00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef WIN32
00022 #pragma warning(disable:4786)
00023 #endif
00024
00025 #include "Elements.h"
00026 #include "xml.h"
00027 #include "ctml.h"
00028 #include "ctexceptions.h"
00029 #include "stringUtils.h"
00030
00031 using namespace ctml;
00032 using namespace std;
00033
00034 #ifdef USE_DGG_CODE
00035 #include <map>
00036 #endif
00037 #include <cstdlib>
00038
00039 namespace Cantera {
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 struct awData {
00059 char name[4];
00060 double atomicWeight;
00061 };
00062
00063
00064
00065
00066
00067
00068
00069 static struct awData aWTable[] = {
00070 {"H", 1.00794},
00071 {"D", 2.0 },
00072 {"Tr", 3.0 },
00073 {"He", 4.002602},
00074 {"Li", 6.941 },
00075 {"Be", 9.012182},
00076 {"B", 10.811 },
00077 {"C", 12.011 },
00078 {"N", 14.00674},
00079 {"O", 15.9994 },
00080 {"F", 18.9984032},
00081 {"Ne", 20.1797 },
00082 {"Na", 22.98977},
00083 {"Mg", 24.3050 },
00084 {"Al", 26.98154},
00085 {"Si", 28.0855 },
00086 {"P", 30.97376},
00087 {"S", 32.066 },
00088 {"Cl", 35.4527 },
00089 {"Ar", 39.948 },
00090 {"K", 39.0983 },
00091 {"Ca", 40.078 },
00092 {"Sc", 44.95591},
00093 {"Ti", 47.88 },
00094 {"V", 50.9415 },
00095 {"Cr", 51.9961 },
00096 {"Mn", 54.9381 },
00097 {"Fe", 55.847 },
00098 {"Co", 58.9332 },
00099 {"Ni", 58.69 },
00100 {"Cu", 63.546 },
00101 {"Zn", 65.39 },
00102 {"Ga", 69.723 },
00103 {"Ge", 72.61 },
00104 {"As", 74.92159},
00105 {"Se", 78.96 },
00106 {"Br", 79.904 },
00107 {"Kr", 83.80 },
00108 {"Rb", 85.4678 },
00109 {"Sr", 87.62 },
00110 {"Y", 88.90585},
00111 {"Zr", 91.224 },
00112 {"Nb", 92.90638},
00113 {"Mo", 95.94 },
00114 {"Tc", 97.9072 },
00115 {"Ru", 101.07 },
00116 {"Rh", 102.9055 },
00117 {"Pd", 106.42 },
00118 {"Ag", 107.8682 },
00119 {"Cd", 112.411 },
00120 {"In", 114.82 },
00121 {"Sn", 118.710 },
00122 {"Sb", 121.75 },
00123 {"Te", 127.6 },
00124 {"I", 126.90447},
00125 {"Xe", 131.29 },
00126 {"Cs", 132.90543},
00127 {"Ba", 137.327 },
00128 {"La", 138.9055 },
00129 {"Ce", 140.115 },
00130 {"Pr", 140.90765},
00131 {"Nd", 144.24 },
00132 {"Pm", 144.9127 },
00133 {"Sm", 150.36 },
00134 {"Eu", 151.965 },
00135 {"Gd", 157.25 },
00136 {"Tb", 158.92534},
00137 {"Dy", 162.50 },
00138 {"Ho", 164.93032},
00139 {"Er", 167.26 },
00140 {"Tm", 168.93421},
00141 {"Yb", 173.04 },
00142 {"Lu", 174.967 },
00143 {"Hf", 178.49 },
00144 {"Ta", 180.9479 },
00145 {"W", 183.85 },
00146 {"Re", 186.207 },
00147 {"Os", 190.2 },
00148 {"Ir", 192.22 },
00149 {"Pt", 195.08 },
00150 {"Au", 196.96654},
00151 {"Hg", 200.59 },
00152 {"Ti", 204.3833 },
00153 {"Pb", 207.2 },
00154 {"Bi", 208.98037},
00155 {"Po", 208.9824 },
00156 {"At", 209.9871 },
00157 {"Rn", 222.0176 },
00158 {"Fr", 223.0197 },
00159 {"Ra", 226.0254 },
00160 {"Ac", 227.0279 },
00161 {"Th", 232.0381 },
00162 {"Pa", 231.03588},
00163 {"U", 238.0508 },
00164 {"Np", 237.0482 },
00165 {"Pu", 244.0482 }
00166 };
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 doublereal Elements::LookupWtElements(const std::string& ename) {
00190 int num = sizeof(aWTable) / sizeof(struct awData);
00191 string s3 = ename.substr(0,3);
00192 for (int i = 0; i < num; i++) {
00193 if (s3 == aWTable[i].name) {
00194 return (aWTable[i].atomicWeight);
00195 }
00196 }
00197 throw CanteraError("LookupWtElements", "element not found");
00198 return -1.0;
00199 }
00200
00201
00202
00203
00204
00205
00206
00207 class ElementsFrozen : public CanteraError {
00208 public:
00209
00210
00211
00212
00213 ElementsFrozen(string func)
00214 : CanteraError(func,
00215 "elements cannot be added after species.") {}
00216 };
00217
00218
00219
00220
00221
00222 Elements::Elements() :
00223 m_mm(0),
00224 m_elementsFrozen(false),
00225 numSubscribers(0)
00226 {
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236 Elements::~Elements() {
00237 if (numSubscribers != 0) {
00238 throw CanteraError("~Elements", "numSubscribers not zero");
00239 }
00240 }
00241
00242 Elements::Elements(const Elements &right) :
00243 m_mm(0),
00244 m_elementsFrozen(false),
00245 numSubscribers(0)
00246 {
00247 *this = operator=(right);
00248 }
00249
00250 Elements& Elements::operator=(const Elements &right) {
00251 if (&right == this) return *this;
00252
00253 m_mm = right.m_mm;
00254 m_elementsFrozen = right.m_elementsFrozen;
00255 m_atomicWeights = right.m_atomicWeights;
00256 m_atomicNumbers = right.m_atomicNumbers;
00257 m_elementNames = right.m_elementNames;
00258 m_entropy298 = right.m_entropy298;
00259
00260 numSubscribers = 0;
00261
00262 return *this;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 void Elements::freezeElements() {
00274 m_elementsFrozen = true;
00275 }
00276
00277 #ifdef INCL_DEPRECATED_METHODS
00278
00279
00280
00281
00282
00283 ElementData Elements::element(int m) const {
00284 ElementData e;
00285 e.name = m_elementNames[m];
00286 e.atomicWeight = m_atomicWeights[m];
00287 return e;
00288 }
00289 #endif
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 #ifdef USE_DGG_CODE
00301 int Elements::elementIndex(std::string name) const{
00302 map<string, int>::const_iterator it;
00303 it = m_definedElements.find(name);
00304 if (it != m_definedElements.end()) {
00305 return it->second;
00306 }
00307 return -1;
00308 }
00309 #else
00310 int Elements::elementIndex(std::string name) const {
00311 for (int i = 0; i < m_mm; i++) {
00312 if (m_elementNames[i] == name) return i;
00313 }
00314 return -1;
00315 }
00316 #endif
00317
00318
00319
00320
00321
00322
00323 string Elements::elementName(int m) const {
00324 if (m < 0 || m >= nElements()) {
00325 throw ElementRangeError("Elements::elementName", m, nElements());
00326 }
00327 return m_elementNames[m];
00328 }
00329
00330
00331
00332 doublereal Elements::entropyElement298(int m) const {
00333 AssertThrowMsg(m_entropy298[m] != ENTROPY298_UNKNOWN,
00334 "Elements::entropy298",
00335 "Entropy at 298 K of element is unknown");
00336 AssertTrace(m >= 0 && m < m_mm);
00337 return (m_entropy298[m]);
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 void Elements::
00354 addElement(const std::string& symbol, doublereal weight)
00355 {
00356 if (weight == -12345.0) {
00357 weight = LookupWtElements(symbol);
00358 if (weight < 0.0) {
00359 throw ElementsFrozen("addElement");
00360 }
00361 }
00362 if (m_elementsFrozen) {
00363 throw ElementsFrozen("addElement");
00364 return;
00365 }
00366 m_atomicWeights.push_back(weight);
00367 m_elementNames.push_back(symbol);
00368 #ifdef USE_DGG_CODE
00369 m_definedElements[symbol] = nElements() + 1;
00370 #endif
00371 m_mm++;
00372 }
00373
00374 void Elements::
00375 addElement(const XML_Node& e) {
00376 doublereal weight = atof(e["atomicWt"].c_str());
00377 string symbol = e["name"];
00378 addElement(symbol, weight);
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 #ifdef USE_DGG_CODE
00395 void Elements::
00396 addUniqueElement(const std::string& symbol, doublereal weight, int atomicNumber,
00397 doublereal entropy298)
00398 {
00399 if (m_elementsFrozen)
00400 throw ElementsFrozen("addElement");
00401
00402 if (weight == -12345.0) {
00403 weight = LookupWtElements(symbol);
00404 }
00405
00406
00407
00408
00409
00410
00411 int i = m_definedElements[symbol] - 1;
00412 if (i < 0) {
00413 m_atomicWeights.push_back(weight);
00414 m_elementNames.push_back(symbol);
00415 m_atomicNumbers.push_back(atomicNumber);
00416 m_entropy298.push_back(entropy298);
00417 m_mm++;
00418 }
00419 else {
00420 if (m_atomicWeights[i] != weight) {
00421 throw CanteraError("AddUniqueElement",
00422 "Duplicate Elements (" + symbol +
00423 ") have different weights");
00424 }
00425 }
00426 }
00427
00428 #else
00429 void Elements::
00430 addUniqueElement(const std::string& symbol,
00431 doublereal weight, int atomicNumber, doublereal entropy298)
00432 {
00433 if (weight == -12345.0) {
00434 weight = LookupWtElements(symbol);
00435 if (weight < 0.0) {
00436 throw ElementsFrozen("addElement");
00437 }
00438 }
00439
00440
00441
00442
00443
00444 int ifound = 0;
00445 int i = 0;
00446 for (vector<string>::const_iterator it = m_elementNames.begin();
00447 it < m_elementNames.end(); ++it, ++i) {
00448 if (*it == symbol) {
00449 ifound = 1;
00450 break;
00451 }
00452 }
00453 if (!ifound) {
00454 if (m_elementsFrozen) {
00455 throw ElementsFrozen("addElement");
00456 return;
00457 }
00458 m_atomicWeights.push_back(weight);
00459 m_elementNames.push_back(symbol);
00460 m_atomicNumbers.push_back(atomicNumber);
00461 m_entropy298.push_back(entropy298);
00462 m_mm++;
00463 } else {
00464 if (m_atomicWeights[i] != weight) {
00465 throw CanteraError("AddUniqueElement",
00466 "Duplicate Elements (" + symbol +
00467 ") have different weights");
00468 }
00469 }
00470 }
00471 #endif
00472
00473
00474
00475
00476
00477
00478 void Elements::
00479 addUniqueElement(const XML_Node& e) {
00480 doublereal weight = 0.0;
00481 if (e.hasAttrib("atomicWt"))
00482 weight = atof(stripws(e["atomicWt"]).c_str());
00483 int anum = 0;
00484 if (e.hasAttrib("atomicNumber"))
00485 anum = atoi(stripws(e["atomicNumber"]).c_str());
00486 string symbol = e["name"];
00487 doublereal entropy298 = ENTROPY298_UNKNOWN;
00488 if (e.hasChild("entropy298")) {
00489 XML_Node& e298Node = e.child("entropy298");
00490 if (e298Node.hasAttrib("value")) {
00491 entropy298 = atofCheck(stripws(e298Node["value"]).c_str());
00492 }
00493 }
00494 if (weight != 0.0) {
00495 addUniqueElement(symbol, weight, anum, entropy298);
00496 } else {
00497 addUniqueElement(symbol);
00498 }
00499 }
00500
00501
00502
00503
00504
00505
00506 void Elements::clear() {
00507 m_mm = 0;
00508 m_atomicWeights.resize(0);
00509 m_elementNames.resize(0);
00510 m_elementsFrozen = false;
00511 }
00512
00513
00514
00515
00516
00517
00518 bool Elements::ready() const {
00519 return (m_elementsFrozen);
00520 }
00521
00522
00523 void Elements::addElementsFromXML(const XML_Node& phase) {
00524
00525
00526 if (! phase.hasChild("elementArray")) {
00527 throw CanteraError("Elements::addElementsFromXML",
00528 "phase xml node doesn't have \"elementArray\" XML Node");
00529 }
00530 XML_Node& elements = phase.child("elementArray");
00531 vector<string> enames;
00532 getStringArray(elements, enames);
00533
00534
00535 string element_database = "elements.xml";
00536 if (elements.hasAttrib("datasrc"))
00537 element_database = elements["datasrc"];
00538
00539 XML_Node* doc = get_XML_File(element_database);
00540 XML_Node* dbe = &doc->child("ctml/elementData");
00541
00542 XML_Node& root = phase.root();
00543 XML_Node* local_db = 0;
00544 if (root.hasChild("ctml")) {
00545 if (root.child("ctml").hasChild("elementData")) {
00546 local_db = &root.child("ctml/elementData");
00547 }
00548 }
00549
00550 int nel = static_cast<int>(enames.size());
00551 int i;
00552 string enm;
00553 XML_Node* e = 0;
00554 for (i = 0; i < nel; i++) {
00555 e = 0;
00556 if (local_db) {
00557
00558 e = local_db->findByAttr("name",enames[i]);
00559
00560 }
00561 if (!e)
00562 e = dbe->findByAttr("name",enames[i]);
00563 if (e) {
00564 addUniqueElement(*e);
00565 }
00566 else {
00567 throw CanteraError("addElementsFromXML","no data for element "
00568 +enames[i]);
00569 }
00570 }
00571
00572 }
00573
00574
00575
00576
00577
00578
00579
00580 void Elements::subscribe() {
00581 ++numSubscribers;
00582 }
00583 int Elements::unsubscribe() {
00584 --numSubscribers;
00585 return numSubscribers;
00586 }
00587 int Elements::reportSubscriptions() const {
00588 return numSubscribers;
00589 }
00590
00591
00592
00593
00594
00595
00596
00597 vector<Elements *> Elements::Global_Elements_List;
00598
00599 }