/*------------------------------------------------------------------------- | The software accompanies the paper | | | | Classes and Objects of Chemical Thermodynamics in Object-Oriented | | Programming. 2. A Class of Chemical Species | | | | E.B. Rudnyi | | E-mail: rudnyi@comp.chem.msu.su | | Homepages: http://www.chem.msu.su/~rudnyi/welcome.html | | | | presented at Second Electronic Computational Chemistry Conference, | | November 1995, http://hackberry.chem.niu.edu/ECCC2/ | | | | E.B. Rudnyi, Copyright (c) 1995 | | | | Permission to use, copy, modify, distribute and sell this software and | | its documentation for any purpose is hereby granted without fee, | | provided that the above copyright notice with the name of the paper and | | the conference appear in all copies and that both that copyright notice | | and this permission notice appear in supporting documentation. | | E.B. Rudnyi makes no representations about the suitability of this | | software for any purpose. It is provided "as is" without expressed or | | implied warranty. | --------------------------------------------------------------------------*/ #ifndef _SPECIES_H #define _SPECIES_H #ifndef _FUNCTION_H #include "function.h" #endif #ifndef __STRING_H #include #endif const int NELEMENTS = 106; const int BUF_EL = 25; // ########################## class elem ############################## //****************************** Purpose ****************************** // Deals with chemical elements. //****************************** Syntax ******************************* // The name of a chemical element: one or two characters that must comply // with the accepted names of the elements. The name is case-sensitive. // Input opearators skip white spaces from a stream and then try to // match the next two characters with the name of an element. In the // case of success, characters are extracted, otherwise they are left in // the stream. //*************** Relationships with the other classes **************** // Class elem is a building block for class formula (class // formula is a container for keeping several elem objects). class elem { public: //******************************* Data ******************************** enum elements {NEL, e , O , H , D , T , F , Cl, Br, I , At, He, Ne, Ar, Kr, Xe, Rn, S , Se, Te, Po, N , P , As, Sb, Bi, C , Si, Ge, Sn, Pb, B , Al, Ga, In, Tl, Zn, Cd, Hg, Cu, Ag, Au, Fe, Co, Ni, Ru, Rh, Pd, Os, Ir, Pt, Mn, Tc, Re, Cr, Mo, W , V , Nb, Ta, Ti, Zr, Hf, Sc, Y , La, Ce, Pr, Nd, Pm, Sm, Eu, Gd, Tb, Dy, Ho, Er, Tm, Yb, Lu, Ac, Th, Pa, U , Np, Pu, Am, Cm, Bk, Cf, Es, Fm, Md, No, Be, Mg, Ca, Sr, Ba, Ra, Li, Na, K , Rb, Cs, Fr}; // Enumeration that allow to use constants like // elem::Ga. NEL means "not an element". The order of the elements // is taken from the Russian reference books "Thermodynamic // properties of individual substances" and "Thermal constants of // substances". private: elements el; static char el_name[NELEMENTS][2]; static float el_mass[NELEMENTS]; public: //**************************** Operations ***************************** elem() {el = NEL;} // Default constructor. Creates an empty object with the value NEL. elem(elements old) {el = old;} // Construcs the object from a constant of the type elements. // elem t(elem::Kr); elem& operator=(elements old) {el = old; return *this;} // Assigns a constant of the type elements to the object. // t = elem:Cs elem(elem &old) {el = old.el;} // Copy constructor. elem& operator=(elem &old) {el = old.el; return *this;} // Assignment operator. elem(const char *str) {anal(str);} // Constructs the object from a string representation. In the case of // sintactics errors creates an empty object. elem& operator=(const char *str) {anal(str); return *this;} // Assigns a string representation to the object. In the case of // sintactics errors leaves an empty object. const char* anal(const char *in); // Makes the object equal to that given by a string representation. // Returns a pointer to char that was not used by the function. // In the case of sintactics errors leaves an empty object. friend istream& operator>>(istream &in, elem &to); // Skips white spaces from a stream and then tries to // match the next two characters with the name of an element. In the // case of success, characters are extracted, otherwise they are // left in the stream. char* to_str(char *buf) const; // Copies a sting representation of the object to a given string buffer. // Returns a pointer to the given buffer. friend ostream& operator<<(ostream &out, const elem &old); // Writes a string representation of the object to the given stream. int len() const; // Returns a number of characters necessary for string representation // of the object. operator int() const {return el;} // Returns the ordinal number of the element in the list. double mass() {return el_mass[el];} // Returns the mass of the element. For the NEL the result is zero. }; // ###################### end of class elem ########################### // ######################## class formula ############################# //****************************** Purpose ****************************** // Deals with semistructural chemical formulas. Generates and keeps a // formula vector (molecular formula). //****************************** Syntax ******************************* // String representations of a chemical semistructural formula, e.g. // CH3CH2OH, Al2(SO4)3 and so on. No white spaces are allowed, they are // taken as delimiters. Input opearators skip white spaces from a stream // and then try to interpret following characters (as much as possible) as // a chemical formula. In the case of success, characters are extracted, // otherwise they are left in the stream. // // formula // primary // primary formula // formula + // formula - // // primary // elem // elem int // (formula)int // // where elem is a chemical element and int is an integer number. Note // that the electron is considered to be a chemical element. It can be used // for representing multi-charge ions. //*************** Relationships with the other classes **************** // Class formula is a container for keeping several elem objects. // It is a base for class species. class formula { int ne; elem *elems; int *coef; char *frml; void init(); static void sort(int &ne, elem *ele, int *c); static int read(int &i, const char* &in, elem *ele, int *c); public: //**************************** Operations ***************************** formula(); // Default constructor. Creates an empty formula. formula(const formula &old); // Copy constructor. formula& operator=(const formula &old); // Assignment operator. formula(const char *str); // Constructs the object from a string representation. In the case of // sintactics errors creates an empty object. formula& operator=(const char *str); // Assigns a string representation to the object. In the case of // sintactics errors leaves an empty object. ~formula(); // Destructor. void clear(); // Clears the object (result is the empty object). void copy(const formula &old); // Makes the object equal to another object. const char* anal(const char *in); // Makes the object equal to that given by a string representation. // Returns a pointer to char that was not used by the function. // In the case of sintactics errors leaves an empty object. friend istream& operator>>(istream &in, formula &to); // Skip white spaces from a stream and then tries to interpret // following characters (as much as possible) as a chemical formula. // In the case of success, characters are extracted, otherwise they // are left in the stream. char* to_str(char *buf) const; // Copies a sting representation of the object to a given string buffer. // Returns a pointer to the given buffer. friend ostream& operator<<(ostream &out, const formula &old); // Writes a string representation of the object to the given stream. int len() const; // Returns a number of characters necessary for string representation // of the object. operator int() const; // Returns zero if the object is empty and non-zero otherwise. int compare(const formula &second) const; // Compares one formula with another one. The result is -1 for less, // 0 for equal, and 1 for greater. Comparison is performed according // to the formula vector and not by semistructural formula itself. // If the two formula vectors are equivalent, then semistructural // formulas are compared by strcmp. friend int operator<(const formula &first, const formula &second); friend int operator<=(const formula &first, const formula &second); friend int operator==(const formula &first, const formula &second); friend int operator>=(const formula &first, const formula &second); friend int operator>(const formula &first, const formula &second); // Another interface for comparison of two formulas. int nel(); // Returns a total number of distinct elements in the formula. elem el(unsigned int i); // 0 <= i <= nel() // Returns the i-th element in the formula vector. int noa(unsigned int i); // 0 <= i <= nel() // Returns the amount of i-th element in the formula vector. int noa(elem ele); // Returns the amount of a given element in the formula vector. double mass(); // Returns a molecular mass. }; // #################### end of class formula ########################## // ######################### class label ############################## //****************************** Purpose ****************************** // Special string class. //****************************** Syntax ******************************* // Any sequence of characters providing the first is a starting // delimiter and the last is an ending delimiter. Both delimiters are // user defined. Input opearators skip white spaces from a stream and // then compare the first character with the starting delimiter. If they // match, all next characters are read until the ending delimiter (it is // also extracted). If not, the character is left in the stream, and the // label is left empty. // // label // del1 character_string del_2 // // where del1 and del2 are the characters defined as starting and ending // delimiters. Between them there are any characters. //*************** Relationships with the other classes **************** // Class label is a building block for class species (class // species contains two labels). class label { char *str; char del1; char del2; public: //**************************** Operations ***************************** label(char delimiter1, char delimiter2); // Constructor. Creates an empty label but requires to define the // starting and ending delimiters. label(const label &old); // Copy constructor. label& operator=(const label &old); // Assignment operator. label& operator=(const char *str); // Assigns a string representation to the object. ~label(); // Destructor. void clear(); // Clears the object (result is the empty object). Delimiters are // still defined though. void copy(const label &old); // Makes the object equal to another object. const char* anal(const char *in); // Makes the object equal to that given by a string representation. // Returns a pointer to char that was not used by the function. friend istream& operator>>(istream &in, label &to); // Skips white spaces from a stream and then compares the first // character with the starting delimiter. If they match, all next // characters are read until the ending delimiter (it is also extracted). // If not, the character is left in the stream, and the label is left // empty. char* to_str(char *buf) const; // Copies a sting representation of the object to a given string buffer. // Returns a pointer to the given buffer. friend ostream& operator<<(ostream &out, const label &old); // Writes a string representation of the object to the given stream. int len() const; // Returns a number of characters necessary for string representation // of the object. operator int() const; // Returns zero if the object is empty and non-zero otherwise. int compare(const label &second) const; // Compares one label with another one. It is almost the same as // strcmp except the delimiters are not taken into account. friend int operator<(const label &first, const label &second); friend int operator<=(const label &first, const label &second); friend int operator==(const label &first, const label &second); friend int operator>=(const label &first, const label &second); friend int operator>(const label &first, const label &second); // Another interface for comparison of two labels. }; // ##################### end of class label ########################### // ######################## class species ############################# //****************************** Purpose ****************************** // Works with chemical species described as a chemical formula, an // isomer label, an phase label, and a compound function of temperature and // pressure describing the Gibbs energy of the species. //****************************** Syntax ******************************* // A sequence of a chemical formula, two optional labels (for isomer // and phase state information) and a compound function of temperatur and // pressure. The isomer label if present should start with character " // and end with the same character. The phase label if present should start // with character [ and end with character ]. Input opearators read a // stream until the semicolon or the end of file (string). The semicolon is // extracted. // // species // formula "isomer label" [phase label] function ; //*************** Relationships with the other classes **************** // Class species is derived from both function and formula and contains // two label objects. Thus this is an agregate class that inherits all // the base properties. class species: public formula, public function { public: //******************************* Data ******************************** label isomer; // should start with " and end with " label phase; // should start with [ and end with ] // labels to keep text information species(); // Default constructor. Creates an empty species. species(const species &old); // Copy constructor. species& operator=(const species &old); // Assignment operator. species(const function &old); // Constracts a species object from the function object. The formula // and labels are left empty. species& operator=(const function &old); // Assign a new function to the species object. species(const char *str); // Constructs the object from a string representation. In the case of // sintactics errors creates an empty object. species& operator=(const char *str); // Assigns a string representation to the object. In the case of // sintactics errors leaves an empty object. ~species(); // Destructor. void clear(); // Clears the object (result is the empty object). void copy(const species &old); // Makes the object equal to another object. const char* anal(const char *in); // Makes the object equal to that given by a string representation. // Returns a pointer to char that was not used by the function. // In the case of sintactics errors leaves an empty object. friend istream& operator>>(istream &in, species &to); // Reads stream until the semicolon or the end of // file. The semicolon is extracted. char* to_str(char *buf) const; // Copies a sting representation of the object to a given string buffer. // Returns a pointer to the given buffer. friend ostream& operator<<(ostream &out, const species &old); // Writes a string representation of the object to the given stream. int len() const; // Returns a number of characters necessary for string representation // of the object. operator int() const; // Returns zero if the object is empty and non-zero otherwise. int compare(const species &second) const; // Compares one species with another one. First, formulas are // compares. If they are equal, the labels are compared then. The // functions don't take part in comparison. friend int operator<(const species &first, const species &second); friend int operator<=(const species &first, const species &second); friend int operator==(const species &first, const species &second); friend int operator>=(const species &first, const species &second); friend int operator>(const species &first, const species &second); // Another interface for comparison of two species. double mu(const double &T = global::T, const double &p = global::p); // Estimates the Gibbs energy of the species. Another interface to // operator()(). double H(const double &T = global::T, const double &p = global::p); // Estimates enthalpy of the species by // H = G - T (dG/dT) double S(const double &T = global::T, const double &p = global::p); // Estimates entropy of the species by // S = - (dG/dT) double Cp(const double &T = global::T, const double &p = global::p); // Estimates heat capacity of the species by // Cp = -T (d2G/dT2) //************************** Error handling *************************** enum species_err { OKAY, // everything is okay WRLBL, // error in label WRFML, // error in formula WRFNC // error in function }; static species_err errno; // Variable to keep the error code. It may be checked out when // something went wrong. }; // #################### end of class species ########################## inline char* elem::to_str(char *buf) const { buf[0] = el_name[el][0]; if ((buf[1] = el_name[el][1]) != '\0') buf[2] = '\0'; return buf; } inline int elem::len() const { if (!el) return 0; if (el_name[el][1]) return 2; else return 1; } inline ostream& operator<<(ostream &out, const elem &old) { if (!old) return out; out << elem::el_name[old.el][0]; if (elem::el_name[old.el][1]) out << elem::el_name[old.el][1]; return out; } inline formula::formula() { init(); } inline formula::formula(const formula &old) { init(); copy(old); } inline formula& formula::operator=(const formula &old) { if (this == &old) return *this; copy(old); return *this; } inline formula::formula(const char *str) { init(); anal(str); } inline formula& formula::operator=(const char *str) { anal(str); return *this; } inline formula::~formula() { delete [] elems; delete [] coef; delete [] frml; } inline void formula::init() { ne = 0; elems = NULL; coef = NULL; frml = NULL; } inline void formula::clear() { delete [] elems; delete [] coef; delete [] frml; init(); } inline formula::operator int() const { return ne; } inline int operator<(const formula &first, const formula &second) { return (first.compare(second) < 0); } inline int operator<=(const formula &first, const formula &second) { return (first.compare(second) <= 0); } inline int operator==(const formula &first, const formula &second) { return (first.compare(second) == 0); } inline int operator>=(const formula &first, const formula &second) { return (first.compare(second) >= 0); } inline int operator>(const formula &first, const formula &second) { return (first.compare(second) > 0); } inline int formula::nel() { return ne; } inline int formula::noa(unsigned int i) { return (i < ne) ? coef[i] : 0; } inline label::label(char delimiter1, char delimiter2) { str = NULL; del1 = delimiter1; del2 = delimiter2; } inline label::label(const label &old) { str = NULL; copy(old); } inline label& label::operator=(const label &old) { if (this == &old) return *this; copy(old); return *this; } inline label& label::operator=(const char *s) { anal(s); return *this; } inline label::~label() { delete [] str; } inline void label::clear() { delete [] str; str = NULL; } inline void label::copy(const label &old) { clear(); str = new char[strlen(old.str) + 1]; if (str) strcpy(str, old.str); del1 = old.del1; del2 = old.del2; } inline char* label::to_str(char *buf) const { if (str) return buf; char *ptr = buf; *ptr++ = del1; ptr = stpcpy(ptr, str); *ptr++ = del2; *ptr = '\0'; return buf; } inline int label::compare(const label &second) const { return strcmp(str, second.str); } inline int label::len() const { return (str ? strlen(str) + 2 : 0); } inline label::operator int() const { return (str ? 1 : 0); } inline ostream& operator<<(ostream &out, const label &old) { return old.str ? out << old.del1 << old.str << old.del2 : out; } inline int operator<(const label &first, const label &second) { return (strcmp(first.str, second.str) < 0); } inline int operator<=(const label &first, const label &second) { return (strcmp(first.str, second.str) <= 0); } inline int operator==(const label &first, const label &second) { return (strcmp(first.str, second.str) == 0); } inline int operator>=(const label &first, const label &second) { return (strcmp(first.str, second.str) >= 0); } inline int operator>(const label &first, const label &second) { return (strcmp(first.str, second.str) > 0); } inline species::species() : isomer('"', '"'), phase('[', ']') { } inline species::species(const species &old) : isomer('"', '"'), phase('[', ']') { copy(old); } inline species& species::operator=(const species &old) { if (this == &old) return *this; copy(old); return *this; } inline species::species(const function &old) : isomer('"', '"'), phase('[', ']') { function::copy(old); } inline species& species::operator=(const function &old) { function::copy(old); return *this; } inline species::species(const char *str) : isomer('"', '"'), phase('[', ']') { anal(str); } inline species& species::operator=(const char *str) { anal(str); return *this; } inline species::~species() { } inline void species::clear() { formula::clear(); function::clear(); isomer.clear(); phase.clear(); } inline species::operator int() const { return (formula::operator int()); } inline int operator<(const species &first, const species &second) { return (first.compare(second) < 0); } inline int operator<=(const species &first, const species &second) { return (first.compare(second) <= 0); } inline int operator==(const species &first, const species &second) { return (first.compare(second) == 0); } inline int operator>=(const species &first, const species &second) { return (first.compare(second) >= 0); } inline int operator>(const species &first, const species &second) { return (first.compare(second) > 0); } inline double species::mu(const double &T, const double &p) { return est(T, p); } #endif