Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Elements.cpp
Go to the documentation of this file.
1 /**
2  * @file Elements.cpp
3  * This file contains a database of atomic weights.
4  */
5 
6 // Copyright 2003 California Institute of Technology
7 
9 #include "cantera/base/ctml.h"
11 
12 using namespace std;
13 
14 namespace Cantera
15 {
16 
17 /*! Database for atomic molecular weights
18  * Values are taken from the 1989 Standard Atomic Weights, CRC
19  *
20  * awTable[] is a static function with scope limited to this file.
21  * It can only be referenced via the LookupWtElements() function.
22  *
23  * units = kg / kg-mol (or equivalently gm / gm-mol)
24  *
25  * This structure was picked because it's simple, compact, and extensible.
26  */
27 struct awData {
28  char name[4]; //!< Null Terminated name, First letter capitalized
29  double atomicWeight; //!< atomic weight in kg / kg-mol
30 };
31 
32 /*!
33  * @var static struct awData aWTable[]
34  * \brief aWTable is a vector containing the atomic weights database.
35  *
36  * The size of the table is given by the initial instantiation.
37  */
38 static struct awData aWTable[] = {
39  {"H", 1.00794},
40  {"D", 2.0 },
41  {"Tr", 3.0 },
42  {"He", 4.002602},
43  {"Li", 6.941 },
44  {"Be", 9.012182},
45  {"B", 10.811 },
46  {"C", 12.011 },
47  {"N", 14.00674},
48  {"O", 15.9994 },
49  {"F", 18.9984032},
50  {"Ne", 20.1797 },
51  {"Na", 22.98977},
52  {"Mg", 24.3050 },
53  {"Al", 26.98154},
54  {"Si", 28.0855 },
55  {"P", 30.97376},
56  {"S", 32.066 },
57  {"Cl", 35.4527 },
58  {"Ar", 39.948 },
59  {"K", 39.0983 },
60  {"Ca", 40.078 },
61  {"Sc", 44.95591},
62  {"Ti", 47.88 },
63  {"V", 50.9415 },
64  {"Cr", 51.9961 },
65  {"Mn", 54.9381 },
66  {"Fe", 55.847 },
67  {"Co", 58.9332 },
68  {"Ni", 58.69 },
69  {"Cu", 63.546 },
70  {"Zn", 65.39 },
71  {"Ga", 69.723 },
72  {"Ge", 72.61 },
73  {"As", 74.92159},
74  {"Se", 78.96 },
75  {"Br", 79.904 },
76  {"Kr", 83.80 },
77  {"Rb", 85.4678 },
78  {"Sr", 87.62 },
79  {"Y", 88.90585},
80  {"Zr", 91.224 },
81  {"Nb", 92.90638},
82  {"Mo", 95.94 },
83  {"Tc", 97.9072 },
84  {"Ru", 101.07 },
85  {"Rh", 102.9055 },
86  {"Pd", 106.42 },
87  {"Ag", 107.8682 },
88  {"Cd", 112.411 },
89  {"In", 114.82 },
90  {"Sn", 118.710 },
91  {"Sb", 121.75 },
92  {"Te", 127.6 },
93  {"I", 126.90447},
94  {"Xe", 131.29 },
95  {"Cs", 132.90543},
96  {"Ba", 137.327 },
97  {"La", 138.9055 },
98  {"Ce", 140.115 },
99  {"Pr", 140.90765},
100  {"Nd", 144.24 },
101  {"Pm", 144.9127 },
102  {"Sm", 150.36 },
103  {"Eu", 151.965 },
104  {"Gd", 157.25 },
105  {"Tb", 158.92534},
106  {"Dy", 162.50 },
107  {"Ho", 164.93032},
108  {"Er", 167.26 },
109  {"Tm", 168.93421},
110  {"Yb", 173.04 },
111  {"Lu", 174.967 },
112  {"Hf", 178.49 },
113  {"Ta", 180.9479 },
114  {"W", 183.85 },
115  {"Re", 186.207 },
116  {"Os", 190.2 },
117  {"Ir", 192.22 },
118  {"Pt", 195.08 },
119  {"Au", 196.96654},
120  {"Hg", 200.59 },
121  {"Ti", 204.3833 },
122  {"Pb", 207.2 },
123  {"Bi", 208.98037},
124  {"Po", 208.9824 },
125  {"At", 209.9871 },
126  {"Rn", 222.0176 },
127  {"Fr", 223.0197 },
128  {"Ra", 226.0254 },
129  {"Ac", 227.0279 },
130  {"Th", 232.0381 },
131  {"Pa", 231.03588},
132  {"U", 238.0508 },
133  {"Np", 237.0482 },
134  {"Pu", 244.0482 }
135 };
136 
137 
138 // Static function to look up an atomic weight
139 /*
140  * This static function looks up the argument string in the
141  * database above and returns the associated molecular weight.
142  * The data are from the periodic table.
143  *
144  * Note: The idea behind this function is to provide a unified
145  * source for the element atomic weights. This helps to
146  * ensure that mass is conserved.
147  *
148  * @param s String, Only the first 3 characters are significant
149  *
150  * @return
151  * Return value contains the atomic weight of the element
152  * If a match for the string is not found, a value of -1.0 is
153  * returned.
154  *
155  * @exception CanteraError
156  * If a match is not found, a CanteraError is thrown as well
157  */
158 doublereal Elements::LookupWtElements(const std::string& ename)
159 {
160  int num = sizeof(aWTable) / sizeof(struct awData);
161  string s3 = ename.substr(0,3);
162  for (int i = 0; i < num; i++) {
163  if (s3 == aWTable[i].name) {
164  return aWTable[i].atomicWeight;
165  }
166  }
167  throw CanteraError("LookupWtElements", "element not found");
168  return -1.0;
169 }
170 
171 doublereal LookupWtElements(const std::string& ename)
172 {
173  int num = sizeof(aWTable) / sizeof(struct awData);
174  string s3 = ename.substr(0,3);
175  for (int i = 0; i < num; i++) {
176  if (s3 == aWTable[i].name) {
177  return aWTable[i].atomicWeight;
178  }
179  }
180  throw CanteraError("LookupWtElements", "element not found");
181  return -1.0;
182 }
183 
184 //! Exception class to indicate a fixed set of elements.
185 /*!
186  * This class is used to warn the user when the number of elements
187  * are changed after at least one species is defined.
188  */
190 {
191 public:
192  //! Constructor for class
193  /*!
194  * @param func Function where the error occurred.
195  */
196  ElementsFrozen(string func)
197  : CanteraError(func,
198  "elements cannot be added after species.") {}
199 };
200 
201 /*
202  * Elements Class Constructor
203  * We initialize all internal variables to zero here.
204  */
205 Elements::Elements() :
206  m_mm(0),
207  m_elementsFrozen(false),
208  m_elem_type(0),
209  numSubscribers(0)
210 {
211  warn_deprecated("class Elements",
212  "Functionality is now part of class Phase. "
213  "To be removed after Cantera 2.2.");
214 }
215 
216 /*
217  * Elements Class Destructor
218  * If the number of subscribers is not zero, through an error.
219  * A logic problem has occurred.
220  *
221  * @exception CanteraError
222  */
224 {
225  if (numSubscribers != 0) {
226  throw CanteraError("~Elements", "numSubscribers not zero");
227  }
228 }
229 
231  m_mm(0),
232  m_elementsFrozen(false),
233  numSubscribers(0)
234 {
235  *this = right;
236 }
237 
239 {
240  if (&right == this) {
241  return *this;
242  }
243 
244  m_mm = right.m_mm;
249  m_entropy298 = right.m_entropy298;
250  m_elem_type = right.m_elem_type;
251  numSubscribers = 0;
252 
253  return *this;
254 }
255 
256 
257 
258 /*
259  * freezeElements():
260  *
261  * Set the freeze flag. This is a prerequesite to other
262  * activivities, i.e., this is done before species are defined.
263  */
265 {
266  m_elementsFrozen = true;
267 }
268 
269 /*
270  * elementIndex():
271  *
272  * Index of element named \c name. The index is an integer
273  * assigned to each element in the order it was added,
274  * beginning with 0 for the first element. If \c name is not
275  * the name of an element in the set, then the value -1 is
276  * returned.
277  *
278  */
279 int Elements::elementIndex(const std::string& name) const
280 {
281  for (int i = 0; i < m_mm; i++) {
282  if (m_elementNames[i] == name) {
283  return i;
284  }
285  }
286  return -1;
287 }
288 
289 /*
290  *
291  * Name of the element with index \c m. @param m Element
292  * index. If m < 0 or m >= nElements() an exception is thrown.
293  */
294 string Elements::elementName(int m) const
295 {
296  if (m < 0 || m >= nElements()) {
297  throw CanteraError("Elements::elementName()", "out of bounds: " + int2str(m) + " " + int2str(nElements()));
298  }
299  return m_elementNames[m];
300 }
301 
302 
303 doublereal Elements::entropyElement298(int m) const
304 {
306  "Elements::entropy298",
307  "Entropy at 298 K of element is unknown");
308  AssertTrace(m >= 0 && m < m_mm);
309  return m_entropy298[m];
310 }
311 //====================================================================================================================
312 //! Return the element constraint type
313 /*!
314  * Possible types include:
315  *
316  * CT_ELEM_TYPE_TURNEDOFF -1
317  * CT_ELEM_TYPE_ABSPOS 0
318  * CT_ELEM_TYPE_ELECTRONCHARGE 1
319  * CT_ELEM_TYPE_CHARGENEUTRALITY 2
320  * CT_ELEM_TYPE_LATTICERATIO 3
321  * CT_ELEM_TYPE_KINETICFROZEN 4
322  * CT_ELEM_TYPE_SURFACECONSTRAINT 5
323  * CT_ELEM_TYPE_OTHERCONSTRAINT 6
324  *
325  * The default is CT_ELEM_TYPE_ABSPOS
326  */
327 int Elements::elementType(int m) const
328 {
329  return m_elem_type[m];
330 }
331 //====================================================================================================================
332 // Change the element type of the mth constraint
333 /*
334  * Reassigns an element type
335  *
336  * @param m Element index
337  * @param elem_type New elem type to be assigned
338  *
339  * @return Returns the old element type
340  */
341 int Elements::changeElementType(int m, int elem_type)
342 {
343  int old = m_elem_type[m];
344  m_elem_type[m] = elem_type;
345  return old;
346 }
347 //====================================================================================================================
348 /*
349  *
350  * Add an element to the current set of elements in the current object.
351  * @param symbol symbol string
352  * @param weight atomic weight in kg/kmol.
353  *
354  * The default weight is a special value, which will cause the
355  * routine to look up the actual weight via a string lookup.
356  *
357  * There are two interfaces to this routine. The XML interface
358  * looks up the required parameters for the regular interface
359  * and then calls the base routine.
360  */
361 void Elements::addElement(const std::string& symbol, doublereal weight)
362 {
363  if (weight == -12345.0) {
364  weight = LookupWtElements(symbol);
365  if (weight < 0.0) {
366  throw ElementsFrozen("addElement");
367  }
368  }
369  if (m_elementsFrozen) {
370  throw ElementsFrozen("addElement");
371  return;
372  }
373  m_atomicWeights.push_back(weight);
374  m_elementNames.push_back(symbol);
375  if (symbol == "E") {
377  } else {
378  m_elem_type.push_back(CT_ELEM_TYPE_ABSPOS);
379  }
380 
381  m_mm++;
382 }
383 //===========================================================================================================
385 {
386  doublereal weight = fpValue(e["atomicWt"]);
387  string symbol = e["name"];
388  addElement(symbol, weight);
389 }
390 //===========================================================================================================
391 /*
392  * addUniqueElement():
393  *
394  * Add a unique element to the set. This routine will not allow
395  * duplicate elements to be input.
396  *
397  * @param symbol symbol string
398  * @param weight atomic weight in kg/kmol.
399  *
400  *
401  * The default weight is a special value, which will cause the
402  * routine to look up the actual weight via a string lookup.
403  */
404 void Elements::addUniqueElement(const std::string& symbol, doublereal weight,
405  int atomicNumber_, doublereal entropy298,
406  int elem_type)
407 {
408  if (weight == -12345.0) {
409  weight = LookupWtElements(symbol);
410  if (weight < 0.0) {
411  throw ElementsFrozen("addElement");
412  }
413  }
414  /*
415  * First decide if this element has been previously added
416  * by conducting a string search. If it unique, add it to
417  * the list.
418  */
419  int ifound = 0;
420  int i = 0;
421  for (vector<string>::const_iterator it = m_elementNames.begin();
422  it < m_elementNames.end(); ++it, ++i) {
423  if (*it == symbol) {
424  ifound = 1;
425  break;
426  }
427  }
428  if (!ifound) {
429  if (m_elementsFrozen) {
430  throw ElementsFrozen("addElement");
431  return;
432  }
433  m_atomicWeights.push_back(weight);
434  m_elementNames.push_back(symbol);
435  m_atomicNumbers.push_back(atomicNumber_);
436  m_entropy298.push_back(entropy298);
437  if (symbol == "E") {
439  } else {
440  m_elem_type.push_back(elem_type);
441  }
442  m_mm++;
443  } else {
444  if (m_atomicWeights[i] != weight) {
445  throw CanteraError("AddUniqueElement",
446  "Duplicate Elements (" + symbol + ") have different weights");
447  }
448  }
449 }
450 
451 /*
452  * @todo call addUniqueElement(symbol, weight) instead of
453  * addElement.
454  */
456 {
457  doublereal weight = 0.0;
458  if (e.hasAttrib("atomicWt")) {
459  weight = fpValue(stripws(e["atomicWt"]));
460  }
461  int anum = 0;
462  if (e.hasAttrib("atomicNumber")) {
463  anum = atoi(stripws(e["atomicNumber"]).c_str());
464  }
465  string symbol = e["name"];
466  doublereal entropy298 = ENTROPY298_UNKNOWN;
467  if (e.hasChild("entropy298")) {
468  XML_Node& e298Node = e.child("entropy298");
469  if (e298Node.hasAttrib("value")) {
470  entropy298 = fpValueCheck(stripws(e298Node["value"]));
471  }
472  }
473  if (weight != 0.0) {
474  addUniqueElement(symbol, weight, anum, entropy298);
475  } else {
476  addUniqueElement(symbol);
477  }
478 }
479 
480 // True if freezeElements has been called.
482 {
483  return m_elementsFrozen;
484 }
485 
486 /*
487  * clear()
488  *
489  * Remove all elements from the structure.
490  */
492 {
493  m_mm = 0;
494  m_atomicWeights.resize(0);
495  m_elementNames.resize(0);
496  m_entropy298.resize(0);
497  m_elem_type.resize(0);
498  m_elementsFrozen = false;
499 }
500 
501 /*
502  * ready():
503  *
504  * True if the elements have been frozen
505  */
506 bool Elements::ready() const
507 {
508  return m_elementsFrozen;
509 }
510 
511 
513 {
514 
515  // get the declared element names
516  if (! phase.hasChild("elementArray")) {
517  throw CanteraError("Elements::addElementsFromXML",
518  "phase XML node doesn't have \"elementArray\" XML Node");
519  }
520  XML_Node& elements = phase.child("elementArray");
521  vector<string> enames;
522  getStringArray(elements, enames);
523 
524  // // element database defaults to elements.xml
525  string element_database = "elements.xml";
526  if (elements.hasAttrib("datasrc")) {
527  element_database = elements["datasrc"];
528  }
529 
530  XML_Node* doc = get_XML_File(element_database);
531  XML_Node* dbe = &doc->child("elementData");
532 
533  XML_Node& root = phase.root();
534  XML_Node* local_db = 0;
535  if (root.hasChild("elementData")) {
536  local_db = &root.child("elementData");
537  }
538 
539  int nel = static_cast<int>(enames.size());
540  int i;
541  string enm;
542  XML_Node* e = 0;
543  for (i = 0; i < nel; i++) {
544  e = 0;
545  if (local_db) {
546  e = local_db->findByAttr("name",enames[i]);
547  }
548  if (!e) {
549  e = dbe->findByAttr("name",enames[i]);
550  }
551  if (e) {
552  addUniqueElement(*e);
553  } else {
554  throw CanteraError("addElementsFromXML","no data for element "
555  +enames[i]);
556  }
557  }
558 
559 }
560 
561 /*
562  * subscribe(), unsubscribe(), and reportSubscriptions():
563  *
564  * Handles setting and reporting the number of subscriptions to this
565  * object.
566  */
568 {
569  ++numSubscribers;
570 }
572 {
573  --numSubscribers;
574  return numSubscribers;
575 }
577 {
578  return numSubscribers;
579 }
580 
581 /********************* GLOBAL STATIC SECTION **************************/
582 /*
583  * We keep track of a vector of pointers to element objects.
584  * Initially there are no Elements objects. Whenever one is created,
585  * the pointer to that object is added onto this list.
586  */
587 vector<Elements*> Elements::Global_Elements_List;
588 /***********************************************************************/
589 }
std::string elementName(int m) const
Name of the element with index m.
Definition: Elements.cpp:294
doublereal fpValue(const std::string &val)
Translate a string into one doublereal value.
XML_Node * findByAttr(const std::string &attr, const std::string &val, int depth=100000) const
This routine carries out a recursive search for an XML node based on an attribute of each XML node...
Definition: xml.cpp:704
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Definition: stringUtils.cpp:39
doublereal LookupWtElements(const std::string &ename)
Function to look up an atomic weight This function looks up the argument string in the database above...
Definition: Elements.cpp:171
void addUniqueElement(const std::string &symbol, doublereal weight=-12345.0, int atomicNumber=0, doublereal entropy298=ENTROPY298_UNKNOWN, int elem_type=CT_ELEM_TYPE_ABSPOS)
Add an element only if the element hasn't been added before.
Definition: Elements.cpp:404
XML_Node * get_XML_File(const std::string &file, int debug)
Return a pointer to the XML tree for a Cantera input file.
Definition: global.cpp:105
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
void clear()
Remove all elements.
Definition: Elements.cpp:491
void addElement(const std::string &symbol, doublereal weight=-12345.0)
Add an element to the current set of elements in the current object.
Definition: Elements.cpp:361
Elements()
Default constructor for the elements class.
Definition: Elements.cpp:205
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:100
Contains the LookupWtElements function and the definitions of element constraint types.
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:78
bool elementsFrozen() const
True if freezeElements has been called.
Definition: Elements.cpp:481
void subscribe()
subscribe to this object
Definition: Elements.cpp:567
#define CT_ELEM_TYPE_ABSPOS
Normal element constraint consisting of positive coefficients for the formula matrix.
Definition: Elements.h:35
vector_int m_elem_type
Vector of element types.
Definition: Elements.h:395
#define CT_ELEM_TYPE_ELECTRONCHARGE
This refers to conservation of electrons.
Definition: Elements.h:41
void freezeElements()
Prohibit addition of more elements, and prepare to add species.
Definition: Elements.cpp:264
int reportSubscriptions() const
report the number of subscriptions
Definition: Elements.cpp:576
#define AssertThrowMsg(expr, procedure, message)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:301
bool ready() const
True if both elements and species have been frozen.
Definition: Elements.cpp:506
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:573
bool m_elementsFrozen
boolean indicating completion of object
Definition: Elements.h:367
std::string stripws(const std::string &s)
Strip the leading and trailing white space from a string.
static struct awData aWTable[]
aWTable is a vector containing the atomic weights database.
Definition: Elements.cpp:38
vector_fp m_atomicWeights
Vector of element atomic weights:
Definition: Elements.h:374
ElementsFrozen(string func)
Constructor for class.
Definition: Elements.cpp:196
Object containing the elements that make up species in a phase.
Definition: Elements.h:116
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
int nElements() const
Inline function that returns the number of elements in the object.
Definition: Elements.h:236
Exception class to indicate a fixed set of elements.
Definition: Elements.cpp:189
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:563
static std::vector< Elements * > Global_Elements_List
Vector of pointers to Elements Objects.
Definition: Elements.h:412
#define ENTROPY298_UNKNOWN
Number indicating we don't know the entropy of the element in its most stable state at 298...
Definition: Elements.h:84
#define AssertTrace(expr)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:270
doublereal entropyElement298(int m) const
Entropy at 298.15 K and 1 bar of stable state of the element.
Definition: Elements.cpp:303
Elements & operator=(const Elements &right)
Assignment operator.
Definition: Elements.cpp:238
double atomicWeight
atomic weight in kg / kg-mol
Definition: Elements.cpp:29
void getStringArray(const XML_Node &node, std::vector< std::string > &v)
This function interprets the value portion of an XML element as a string.
Definition: ctml.cpp:503
std::vector< std::string > m_elementNames
Vector of strings containing the names of the elements.
Definition: Elements.h:386
static double LookupWtElements(const std::string &ename)
Static function to look up an atomic weight.
Definition: Elements.cpp:158
void addElementsFromXML(const XML_Node &phase)
Add multiple elements from a XML_Node phase description.
Definition: Elements.cpp:512
Contains declarations for string manipulation functions within Cantera.
vector_int m_atomicNumbers
Vector of element atomic numbers:
Definition: Elements.h:380
int m_mm
Number of elements.
Definition: Elements.h:359
int changeElementType(int m, int elem_type)
Change the element type of the mth constraint.
Definition: Elements.cpp:341
vector_fp m_entropy298
Entropy at 298.15 K and 1 bar of stable state.
Definition: Elements.h:392
XML_Node & root() const
Return the root of the current XML_Node tree.
Definition: xml.cpp:1095
int elementIndex(const std::string &name) const
Function that returns the index of an element.
Definition: Elements.cpp:279
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
~Elements()
Default destructor for the elements class.
Definition: Elements.cpp:223
int numSubscribers
Number of Constituents Objects that use this object.
Definition: Elements.h:404
bool hasAttrib(const std::string &a) const
Tests whether the current node has an attribute with a particular name.
Definition: xml.cpp:568
int unsubscribe()
unsubscribe to this object
Definition: Elements.cpp:571
int elementType(int m) const
Return the element constraint type.
Definition: Elements.cpp:327