Cantera  2.5.1
ThermoFactory.cpp
Go to the documentation of this file.
1 /**
2  * @file ThermoFactory.cpp
3  * Definitions for the factory class that can create known ThermoPhase objects
4  * (see \ref thermoprops and class \link Cantera::ThermoFactory ThermoFactory\endlink).
5  */
6 
7 // This file is part of Cantera. See License.txt in the top-level directory or
8 // at https://cantera.org/license.txt for license and copyright information.
9 
11 
12 #include "cantera/thermo/Species.h"
18 
34 #include "cantera/thermo/HMWSoln.h"
41 
42 using namespace std;
43 
44 namespace Cantera
45 {
46 
47 ThermoFactory* ThermoFactory::s_factory = 0;
48 std::mutex ThermoFactory::thermo_mutex;
49 
50 ThermoFactory::ThermoFactory()
51 {
52  reg("ideal-gas", []() { return new IdealGasPhase(); });
53  addAlias("ideal-gas", "IdealGas");
54  reg("constant-density", []() { return new ConstDensityThermo(); });
55  addAlias("constant-density", "Incompressible");
56  reg("ideal-surface", []() { return new SurfPhase(); });
57  addAlias("ideal-surface", "Surface");
58  reg("edge", []() { return new EdgePhase(); });
59  addAlias("edge", "Edge");
60  reg("electron-cloud", []() { return new MetalPhase(); });
61  addAlias("electron-cloud", "Metal");
62  reg("fixed-stoichiometry", []() { return new StoichSubstance(); });
63  addAlias("fixed-stoichiometry", "StoichSubstance");
64  reg("pure-fluid", []() { return new PureFluidPhase(); });
65  addAlias("pure-fluid", "PureFluid");
66  reg("compound-lattice", []() { return new LatticeSolidPhase(); });
67  addAlias("compound-lattice", "LatticeSolid");
68  reg("lattice", []() { return new LatticePhase(); });
69  addAlias("lattice", "Lattice");
70  reg("HMW-electrolyte", []() { return new HMWSoln(); });
71  addAlias("HMW-electrolyte", "HMW");
72  reg("ideal-condensed", []() { return new IdealSolidSolnPhase(); });
73  addAlias("ideal-condensed", "IdealSolidSolution");
74  reg("Debye-Huckel", []() { return new DebyeHuckel(); });
75  addAlias("Debye-Huckel", "DebyeHuckel");
76  reg("ideal-molal-solution", []() { return new IdealMolalSoln(); });
77  addAlias("ideal-molal-solution", "IdealMolalSolution");
78  reg("ideal-solution-VPSS", []() { return new IdealSolnGasVPSS(); });
79  reg("ideal-gas-VPSS", []() { return new IdealSolnGasVPSS(); });
80  addAlias("ideal-solution-VPSS", "IdealSolnVPSS");
81  addAlias("ideal-gas-VPSS", "IdealGasVPSS");
82  reg("Margules", []() { return new MargulesVPSSTP(); });
83  reg("ions-from-neutral-molecule", []() { return new IonsFromNeutralVPSSTP(); });
84  addAlias("ions-from-neutral-molecule", "IonsFromNeutralMolecule");
85  reg("fixed-chemical-potential", []() { return new FixedChemPotSSTP(); });
86  addAlias("fixed-chemical-potential", "FixedChemPot");
87  reg("Redlich-Kister", []() { return new RedlichKisterVPSSTP(); });
88  reg("Redlich-Kwong", []() { return new RedlichKwongMFTP(); });
89  addAlias("Redlich-Kwong", "RedlichKwongMFTP");
90  addAlias("Redlich-Kwong", "RedlichKwong");
91  reg("Maskell-solid-solution", []() { return new MaskellSolidSolnPhase(); });
92  addAlias("Maskell-solid-solution", "MaskellSolidSolnPhase");
93  reg("liquid-water-IAPWS95", []() { return new WaterSSTP(); });
94  addAlias("liquid-water-IAPWS95", "PureLiquidWater");
95  reg("binary-solution-tabulated", []() { return new BinarySolutionTabulatedThermo(); });
96  addAlias("binary-solution-tabulated", "BinarySolutionTabulatedThermo");
97 }
98 
99 ThermoPhase* ThermoFactory::newThermoPhase(const std::string& model)
100 {
101  return create(model);
102 }
103 
105 {
106  string model = xmlphase.child("thermo")["model"];
107  unique_ptr<ThermoPhase> t(newThermoPhase(model));
108  importPhase(xmlphase, t.get());
109  return t.release();
110 }
111 
112 unique_ptr<ThermoPhase> newPhase(AnyMap& phaseNode, const AnyMap& rootNode)
113 {
114  unique_ptr<ThermoPhase> t(newThermoPhase(phaseNode["thermo"].asString()));
115  setupPhase(*t, phaseNode, rootNode);
116  return t;
117 }
118 
119 ThermoPhase* newPhase(const std::string& infile, std::string id)
120 {
121  size_t dot = infile.find_last_of(".");
122  string extension;
123  if (dot != npos) {
124  extension = toLowerCopy(infile.substr(dot+1));
125  }
126  if (id == "-") {
127  id = "";
128  }
129 
130  if (extension == "yml" || extension == "yaml") {
131  AnyMap root = AnyMap::fromYamlFile(infile);
132  AnyMap& phase = root["phases"].getMapWhere("name", id);
133  unique_ptr<ThermoPhase> t(newThermoPhase(phase["thermo"].asString()));
134  setupPhase(*t, phase, root);
135  return t.release();
136  } else {
137  XML_Node* root = get_XML_File(infile);
138  XML_Node* xphase = get_XML_NameID("phase", "#"+id, root);
139  if (!xphase) {
140  throw CanteraError("newPhase",
141  "Couldn't find phase named \"" + id + "\" in file, " + infile);
142  }
143  return newPhase(*xphase);
144  }
145 }
146 
147 //! Gather a vector of pointers to XML_Nodes for a phase
148 /*!
149  * @param spDataNodeList Output vector of pointer to XML_Nodes which contain
150  * the species XML_Nodes for the species in the current phase.
151  * @param spNamesList Output Vector of strings, which contain the names
152  * of the species in the phase
153  * @param spRuleList Output Vector of ints, which contain the value of
154  * sprule for each species in the phase
155  * @param spArray_names Vector of pointers to the XML_Nodes which contains
156  * the names of the species in the phase
157  * @param spArray_dbases Input vector of pointers to species data bases. We
158  * search each data base for the required species
159  * names
160  * @param sprule Input vector of sprule values
161  */
162 static void formSpeciesXMLNodeList(std::vector<XML_Node*> &spDataNodeList,
163  std::vector<std::string> &spNamesList,
164  vector_int &spRuleList,
165  const std::vector<XML_Node*> spArray_names,
166  const std::vector<XML_Node*> spArray_dbases,
167  const vector_int sprule)
168 {
169  // used to check that each species is declared only once
170  std::map<std::string, bool> declared;
171 
172  for (size_t jsp = 0; jsp < spArray_dbases.size(); jsp++) {
173  const XML_Node& speciesArray = *spArray_names[jsp];
174 
175  // Get the top XML for the database
176  const XML_Node* db = spArray_dbases[jsp];
177 
178  // Get the array of species name strings and then count them
179  std::vector<std::string> spnames;
180  getStringArray(speciesArray, spnames);
181  size_t nsp = spnames.size();
182 
183  // if 'all' is specified as the one and only species in the
184  // spArray_names field, then add all species defined in the
185  // corresponding database to the phase
186  if (nsp == 1 && spnames[0] == "all") {
187  std::vector<XML_Node*> allsp = db->getChildren("species");
188  nsp = allsp.size();
189  spnames.resize(nsp);
190  for (size_t nn = 0; nn < nsp; nn++) {
191  string stemp = (*allsp[nn])["name"];
192  if (!declared[stemp] || sprule[jsp] < 10) {
193  declared[stemp] = true;
194  spNamesList.push_back(stemp);
195  spDataNodeList.push_back(allsp[nn]);
196  spRuleList.push_back(sprule[jsp]);
197  }
198  }
199  } else if (nsp == 1 && spnames[0] == "unique") {
200  std::vector<XML_Node*> allsp = db->getChildren("species");
201  nsp = allsp.size();
202  spnames.resize(nsp);
203  for (size_t nn = 0; nn < nsp; nn++) {
204  string stemp = (*allsp[nn])["name"];
205  if (!declared[stemp]) {
206  declared[stemp] = true;
207  spNamesList.push_back(stemp);
208  spDataNodeList.push_back(allsp[nn]);
209  spRuleList.push_back(sprule[jsp]);
210  }
211  }
212  } else {
213  std::map<std::string, XML_Node*> speciesNodes;
214  for (size_t k = 0; k < db->nChildren(); k++) {
215  XML_Node& child = db->child(k);
216  speciesNodes[child["name"]] = &child;
217  }
218  for (size_t k = 0; k < nsp; k++) {
219  string stemp = spnames[k];
220  if (!declared[stemp] || sprule[jsp] < 10) {
221  declared[stemp] = true;
222  // Find the species in the database by name.
223  auto iter = speciesNodes.find(stemp);
224  if (iter == speciesNodes.end()) {
225  throw CanteraError("formSpeciesXMLNodeList",
226  "no data for species, \"{}\"", stemp);
227  }
228  spNamesList.push_back(stemp);
229  spDataNodeList.push_back(iter->second);
230  spRuleList.push_back(sprule[jsp]);
231  }
232  }
233  }
234  }
235 }
236 
238 {
239  // Check the the supplied XML node in fact represents a phase.
240  if (phase.name() != "phase") {
241  throw CanteraError("importPhase",
242  "Current const XML_Node named, " + phase.name() +
243  ", is not a phase element.");
244  }
245 
246  // In this section of code, we get the reference to the phase XML tree
247  // within the ThermoPhase object. Then, we clear it and fill it with the
248  // current information that we are about to use to construct the object. We
249  // will then be able to resurrect the information later by calling xml().
250  th->setXMLdata(phase);
251 
252  // set the id attribute of the phase to the 'id' attribute in the XML tree.
253  th->setName(phase.id());
254 
255  // Number of spatial dimensions. Defaults to 3 (bulk phase)
256  if (phase.hasAttrib("dim")) {
257  int idim = intValue(phase["dim"]);
258  if (idim < 1 || idim > 3) {
259  throw CanteraError("importPhase",
260  "phase, " + th->name() +
261  ", has unphysical number of dimensions: " + phase["dim"]);
262  }
263  th->setNDim(idim);
264  } else {
265  th->setNDim(3); // default
266  }
267 
268  // Set equation of state parameters. The parameters are specific to each
269  // subclass of ThermoPhase, so this is done by method setParametersFromXML
270  // in each subclass.
271  const XML_Node& eos = phase.child("thermo");
272  if (phase.hasChild("thermo")) {
273  th->setParametersFromXML(eos);
274  } else {
275  throw CanteraError("importPhase",
276  " phase, " + th->name() +
277  ", XML_Node does not have a \"thermo\" XML_Node");
278  }
279 
280  VPStandardStateTP* vpss_ptr = 0;
281  int ssConvention = th->standardStateConvention();
282  if (ssConvention == cSS_CONVENTION_VPSS) {
283  vpss_ptr = dynamic_cast <VPStandardStateTP*>(th);
284  if (vpss_ptr == 0) {
285  throw CanteraError("importPhase",
286  "phase, " + th->name() + ", was VPSS, but dynamic cast failed");
287  }
288  }
289 
290  // Add the elements.
291  if (ssConvention != cSS_CONVENTION_SLAVE) {
292  installElements(*th, phase);
293  }
294 
295  // Add the species.
296  //
297  // Species definitions may be imported from multiple sources. For each one,
298  // a speciesArray element must be present.
299  vector<XML_Node*> sparrays = phase.getChildren("speciesArray");
300  if (ssConvention != cSS_CONVENTION_SLAVE && sparrays.empty()) {
301  throw CanteraError("importPhase",
302  "phase, " + th->name() + ", has zero \"speciesArray\" XML nodes.\n"
303  + " There must be at least one speciesArray nodes "
304  "with one or more species");
305  }
306  vector<XML_Node*> dbases;
307  vector_int sprule(sparrays.size(),0);
308 
309  // Default behavior when importing from CTI/XML is for undefined elements to
310  // be treated as an error
312 
313  // loop over the speciesArray elements
314  for (size_t jsp = 0; jsp < sparrays.size(); jsp++) {
315  const XML_Node& speciesArray = *sparrays[jsp];
316 
317  // If the speciesArray element has a child element
318  //
319  // <skip element="undeclared">
320  //
321  // then set sprule[jsp] to 1, so that any species with an undeclared
322  // element will be quietly skipped when importing species. Additionally,
323  // if the skip node has the following attribute:
324  //
325  // <skip species="duplicate">
326  //
327  // then duplicate species names will not cause Cantera to throw an
328  // exception. Instead, the duplicate entry will be discarded.
329  if (speciesArray.hasChild("skip")) {
330  const XML_Node& sk = speciesArray.child("skip");
331  string eskip = sk["element"];
332  if (eskip == "undeclared") {
333  sprule[jsp] = 1;
334  }
335  string dskip = sk["species"];
336  if (dskip == "duplicate") {
337  sprule[jsp] += 10;
338  }
339  }
340 
341  // Get a pointer to the node containing the species definitions for the
342  // species declared in this speciesArray element. This may be in the
343  // local file containing the phase element, or may be in another file.
344  XML_Node* db = get_XML_Node(speciesArray["datasrc"], &phase.root());
345  if (db == 0) {
346  throw CanteraError("importPhase",
347  "Can not find XML node for species database: {}",
348  speciesArray["datasrc"]);
349  }
350 
351  // add this node to the list of species database nodes.
352  dbases.push_back(db);
353  }
354 
355  // Now, collect all the species names and all the XML_Node * pointers for
356  // those species in a single vector. This is where we decide what species
357  // are to be included in the phase. The logic is complicated enough that we
358  // put it in a separate routine.
359  std::vector<XML_Node*> spDataNodeList;
360  std::vector<std::string> spNamesList;
361  vector_int spRuleList;
362  formSpeciesXMLNodeList(spDataNodeList, spNamesList, spRuleList,
363  sparrays, dbases, sprule);
364 
365  size_t nsp = spDataNodeList.size();
366  if (ssConvention == cSS_CONVENTION_SLAVE && nsp > 0) {
367  throw CanteraError("importPhase", "For Slave standard states, "
368  "number of species must be zero: {}", nsp);
369  }
370  for (size_t k = 0; k < nsp; k++) {
371  XML_Node* s = spDataNodeList[k];
372  AssertTrace(s != 0);
373  if (spRuleList[k]) {
375  }
376  th->addSpecies(newSpecies(*s));
377  if (vpss_ptr) {
378  const XML_Node* const ss = s->findByName("standardState");
379  std::string ss_model = (ss) ? ss->attrib("model") : "ideal-gas";
380  unique_ptr<PDSS> kPDSS(newPDSS(ss_model));
381  kPDSS->setParametersFromXML(*s);
382  vpss_ptr->installPDSS(k, std::move(kPDSS));
383  }
384  th->saveSpeciesData(k, s);
385  }
386 
387  // Done adding species. Perform any required subclass-specific
388  // initialization.
389  th->initThermo();
390 
391  // Perform any required subclass-specific initialization that requires the
392  // XML phase object
393  std::string id = "";
394  th->initThermoXML(phase, id);
395 }
396 
397 void addDefaultElements(ThermoPhase& thermo, const vector<string>& element_names) {
398  for (const auto& symbol : element_names) {
399  thermo.addElement(symbol);
400  }
401 }
402 
403 void addElements(ThermoPhase& thermo, const vector<string>& element_names,
404  const AnyValue& elements, bool allow_default)
405 {
406  const auto& local_elements = elements.asMap("symbol");
407  for (const auto& symbol : element_names) {
408  if (local_elements.count(symbol)) {
409  auto& element = *local_elements.at(symbol);
410  double weight = element["atomic-weight"].asDouble();
411  long int number = element.getInt("atomic-number", 0);
412  double e298 = element.getDouble("entropy298", ENTROPY298_UNKNOWN);
413  thermo.addElement(symbol, weight, number, e298);
414  } else if (allow_default) {
415  thermo.addElement(symbol);
416  } else {
417  throw InputFileError("addElements", elements,
418  "Element '{}' not found", symbol);
419  }
420  }
421 }
422 
423 void addSpecies(ThermoPhase& thermo, const AnyValue& names, const AnyValue& species)
424 {
425  if (names.is<vector<string>>()) {
426  // 'names' is a list of species names which should be found in 'species'
427  const auto& species_nodes = species.asMap("name");
428  for (const auto& name : names.asVector<string>()) {
429  if (species_nodes.count(name)) {
430  thermo.addSpecies(newSpecies(*species_nodes.at(name)));
431  } else {
432  throw InputFileError("addSpecies", names, species,
433  "Could not find a species named '{}'.", name);
434  }
435  }
436  } else if (names == "all") {
437  // The keyword 'all' means to add all species from this source
438  for (const auto& item : species.asVector<AnyMap>()) {
439  thermo.addSpecies(newSpecies(item));
440  }
441  } else {
442  throw InputFileError("addSpecies", names,
443  "Could not parse species declaration of type '{}'", names.type_str());
444  }
445 }
446 
447 void setupPhase(ThermoPhase& thermo, AnyMap& phaseNode, const AnyMap& rootNode)
448 {
449  thermo.setName(phaseNode["name"].asString());
450  if (rootNode.hasKey("__file__")) {
451  phaseNode["__file__"] = rootNode["__file__"];
452  }
453 
454  if (phaseNode.hasKey("deprecated")) {
455  string msg = phaseNode["deprecated"].asString();
456  string filename = phaseNode.getString("__file__", "unknown file");
457  string method = fmt::format("{}/{}", filename, phaseNode["name"].asString());
458  warn_deprecated(method, msg);
459  }
460 
461  // Add elements
462  if (phaseNode.hasKey("elements")) {
463  if (phaseNode.getBool("skip-undeclared-elements", false)) {
464  thermo.ignoreUndefinedElements();
465  } else {
466  thermo.throwUndefinedElements();
467  }
468 
469  if (phaseNode["elements"].is<vector<string>>()) {
470  // 'elements' is a list of element symbols
471  if (rootNode.hasKey("elements")) {
472  addElements(thermo, phaseNode["elements"].asVector<string>(),
473  rootNode["elements"], true);
474  } else {
475  addDefaultElements(thermo, phaseNode["elements"].asVector<string>());
476  }
477  } else if (phaseNode["elements"].is<vector<AnyMap>>()) {
478  // Each item in 'elements' is a map with one item, where the key is
479  // a section in this file or another YAML file, and the value is a
480  // list of element symbols to read from that section
481  for (const auto& elemNode : phaseNode["elements"].asVector<AnyMap>()) {
482  const string& source = elemNode.begin()->first;
483  const auto& names = elemNode.begin()->second.asVector<string>();
484  const auto& slash = boost::ifind_last(source, "/");
485  if (slash) {
486  std::string fileName(source.begin(), slash.begin());
487  std::string node(slash.end(), source.end());
488  const AnyMap elements = AnyMap::fromYamlFile(fileName,
489  rootNode.getString("__file__", ""));
490  addElements(thermo, names, elements.at(node), false);
491  } else if (rootNode.hasKey(source)) {
492  addElements(thermo, names, rootNode.at(source), false);
493  } else if (source == "default") {
494  addDefaultElements(thermo, names);
495  } else {
496  throw InputFileError("setupPhase", elemNode,
497  "Could not find elements section named '{}'", source);
498  }
499  }
500  } else {
501  throw InputFileError("setupPhase", phaseNode["elements"],
502  "Could not parse elements declaration of type '{}'",
503  phaseNode["elements"].type_str());
504  }
505  } else {
506  // If no elements list is provided, just add elements as-needed from the
507  // default list.
508  thermo.addUndefinedElements();
509  }
510 
511  // Add species
512  if (phaseNode.hasKey("species")) {
513  if (phaseNode["species"].is<vector<string>>()) {
514  // 'species' is a list of species names to be added from the current
515  // file's 'species' section
516  addSpecies(thermo, phaseNode["species"], rootNode["species"]);
517  } else if (phaseNode["species"].is<string>()) {
518  // 'species' is a keyword applicable to the current file's 'species'
519  // section
520  addSpecies(thermo, phaseNode["species"], rootNode["species"]);
521  } else if (phaseNode["species"].is<vector<AnyMap>>()) {
522  // Each item in 'species' is a map with one item, where the key is
523  // a section in this file or another YAML file, and the value is a
524  // list of species names to read from that section
525  for (const auto& speciesNode : phaseNode["species"].asVector<AnyMap>()) {
526  const string& source = speciesNode.begin()->first;
527  const auto& names = speciesNode.begin()->second;
528  const auto& slash = boost::ifind_last(source, "/");
529  if (slash) {
530  // source is a different input file
531  std::string fileName(source.begin(), slash.begin());
532  std::string node(slash.end(), source.end());
533  AnyMap species = AnyMap::fromYamlFile(fileName,
534  rootNode.getString("__file__", ""));
535  addSpecies(thermo, names, species[node]);
536  } else if (rootNode.hasKey(source)) {
537  // source is in the current file
538  addSpecies(thermo, names, rootNode[source]);
539  } else {
540  throw InputFileError("setupPhase", speciesNode,
541  "Could not find species section named '{}'", source);
542  }
543  }
544  } else {
545  throw InputFileError("setupPhase", phaseNode["species"],
546  "Could not parse species declaration of type '{}'",
547  phaseNode["species"].type_str());
548  }
549  } else if (rootNode.hasKey("species")) {
550  // By default, add all species from the 'species' section
551  addSpecies(thermo, AnyValue("all"), rootNode["species"]);
552  }
553 
554  auto* vpssThermo = dynamic_cast<VPStandardStateTP*>(&thermo);
555  if (vpssThermo) {
556  for (size_t k = 0; k < thermo.nSpecies(); k++) {
557  unique_ptr<PDSS> pdss;
558  if (thermo.species(k)->input.hasKey("equation-of-state")) {
559  // Use the first node which specifies a valid PDSS model
560  auto& eos = thermo.species(k)->input["equation-of-state"];
561  bool found = false;
562  for (auto& node : eos.asVector<AnyMap>()) {
563  string model = node["model"].asString();
564  if (PDSSFactory::factory()->exists(model)) {
565  pdss.reset(newPDSS(model));
566  pdss->setParameters(node);
567  found = true;
568  break;
569  }
570  }
571  if (!found) {
572  throw InputFileError("setupPhase", eos,
573  "Could not find an equation-of-state specification "
574  "which defines a known PDSS model.");
575  }
576  } else {
577  pdss.reset(newPDSS("ideal-gas"));
578  }
579  vpssThermo->installPDSS(k, std::move(pdss));
580  }
581  }
582 
583  thermo.setParameters(phaseNode, rootNode);
584  thermo.initThermo();
585 
586  if (phaseNode.hasKey("state")) {
587  auto node = phaseNode["state"].as<AnyMap>();
588  thermo.setState(node);
589  } else {
590  thermo.setState_TP(298.15, OneAtm);
591  }
592 }
593 
594 void installElements(Phase& th, const XML_Node& phaseNode)
595 {
596  // get the declared element names
597  if (!phaseNode.hasChild("elementArray")) {
598  throw CanteraError("installElements",
599  "phase XML node doesn't have \"elementArray\" XML Node");
600  }
601  XML_Node& elements = phaseNode.child("elementArray");
602  vector<string> enames;
603  getStringArray(elements, enames);
604 
605  // // element database defaults to elements.xml
606  string element_database = "elements.xml";
607  if (elements.hasAttrib("datasrc")) {
608  element_database = elements["datasrc"];
609  }
610 
611  XML_Node* doc = get_XML_File(element_database);
612  XML_Node* dbe = &doc->child("elementData");
613 
614  XML_Node& root = phaseNode.root();
615  XML_Node* local_db = 0;
616  if (root.hasChild("elementData")) {
617  local_db = &root.child("elementData");
618  }
619 
620  for (size_t i = 0; i < enames.size(); i++) {
621  // Find the element data
622  XML_Node* e = 0;
623  if (local_db) {
624  e = local_db->findByAttr("name",enames[i]);
625  }
626  if (!e) {
627  e = dbe->findByAttr("name",enames[i]);
628  }
629  if (!e) {
630  throw CanteraError("installElements", "no data for element '{}'",
631  enames[i]);
632  }
633 
634  // Add the element
635  doublereal weight = 0.0;
636  if (e->hasAttrib("atomicWt")) {
637  weight = fpValue(e->attrib("atomicWt"));
638  }
639  int anum = 0;
640  if (e->hasAttrib("atomicNumber")) {
641  anum = intValue(e->attrib("atomicNumber"));
642  }
643  string symbol = e->attrib("name");
644  doublereal entropy298 = ENTROPY298_UNKNOWN;
645  if (e->hasChild("entropy298")) {
646  XML_Node& e298Node = e->child("entropy298");
647  if (e298Node.hasAttrib("value")) {
648  entropy298 = fpValueCheck(e298Node["value"]);
649  }
650  }
651  th.addElement(symbol, weight, anum, entropy298);
652  }
653 }
654 
655 const XML_Node* speciesXML_Node(const std::string& kname,
656  const XML_Node* phaseSpeciesData)
657 {
658  if (!phaseSpeciesData) {
659  return 0;
660  }
661  string jname = phaseSpeciesData->name();
662  if (jname != "speciesData") {
663  throw CanteraError("speciesXML_Node",
664  "Unexpected phaseSpeciesData name: " + jname);
665  }
666  vector<XML_Node*> xspecies = phaseSpeciesData->getChildren("species");
667  for (size_t j = 0; j < xspecies.size(); j++) {
668  const XML_Node& sp = *xspecies[j];
669  jname = sp["name"];
670  if (jname == kname) {
671  return &sp;
672  }
673  }
674  return 0;
675 }
676 
677 }
Cantera::ThermoPhase::initThermoXML
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object using an XML tree.
Definition: ThermoPhase.cpp:1089
Cantera::AnyValue
A wrapper for a variable whose type is determined at runtime.
Definition: AnyMap.h:76
Cantera::XML_Node::hasAttrib
bool hasAttrib(const std::string &a) const
Tests whether the current node has an attribute with a particular name.
Definition: xml.cpp:533
IonsFromNeutralVPSSTP.h
Cantera::ThermoPhase::setParametersFromXML
virtual void setParametersFromXML(const XML_Node &eosdata)
Set equation of state parameter values from XML entries.
Definition: ThermoPhase.h:1728
Cantera::get_XML_File
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:110
MargulesVPSSTP.h
PureFluidPhase.h
Cantera::Phase::setNDim
void setNDim(size_t ndim)
Set the number of spatial dimensions (1, 2, or 3).
Definition: Phase.h:658
Cantera::LatticePhase
A simple thermodynamic model for a bulk phase, assuming a lattice of solid atoms.
Definition: LatticePhase.h:230
Cantera::BinarySolutionTabulatedThermo
Overloads the virtual methods of class IdealSolidSolnPhase to implement tabulated standard state ther...
Definition: BinarySolutionTabulatedThermo.h:113
Cantera::warn_deprecated
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:54
StoichSubstance.h
MetalPhase.h
Cantera::XML_Node::id
std::string id() const
Return the id attribute, if present.
Definition: xml.cpp:538
Cantera::XML_Node::hasChild
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:528
Cantera::AnyMap::hasKey
bool hasKey(const std::string &key) const
Returns true if the map contains an item named key.
Definition: AnyMap.cpp:984
Cantera::IdealGasPhase
Class IdealGasPhase represents low-density gases that obey the ideal gas equation of state.
Definition: IdealGasPhase.h:287
RedlichKwongMFTP.h
Cantera::XML_Node::attrib
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
Definition: xml.cpp:492
Cantera::Phase::addElement
size_t addElement(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.
Definition: Phase.cpp:765
Cantera::AnyMap::at
const AnyValue & at(const std::string &key) const
Get the value of the item stored in key.
Definition: AnyMap.cpp:974
Cantera::ThermoPhase::setState_TP
virtual void setState_TP(doublereal t, doublereal p)
Set the temperature (K) and pressure (Pa)
Definition: ThermoPhase.cpp:136
Cantera::XML_Node::root
XML_Node & root() const
Return the root of the current XML_Node tree.
Definition: xml.cpp:749
Cantera::Phase::addUndefinedElements
void addUndefinedElements()
Set behavior when adding a species containing undefined elements to add those elements to the phase.
Definition: Phase.cpp:1001
ThermoFactory.h
Cantera::FixedChemPotSSTP
Class FixedChemPotSSTP represents a stoichiometric (fixed composition) incompressible substance.
Definition: FixedChemPotSSTP.h:150
Cantera::MetalPhase
Definition: MetalPhase.h:22
Cantera::ThermoPhase::standardStateConvention
virtual int standardStateConvention() const
This method returns the convention used in specification of the standard state, of which there are cu...
Definition: ThermoPhase.cpp:59
Cantera::Phase::name
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:84
Cantera::ThermoPhase::setState
virtual void setState(const AnyMap &state)
Set the state using an AnyMap containing any combination of properties supported by the thermodynamic...
Definition: ThermoPhase.cpp:208
FixedChemPotSSTP.h
AssertTrace
#define AssertTrace(expr)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:234
Cantera::newThermoPhase
ThermoPhase * newThermoPhase(const std::string &model)
Create a new thermo manager instance.
Definition: ThermoFactory.h:100
speciesThermoTypes.h
Cantera::newSpecies
shared_ptr< Species > newSpecies(const XML_Node &species_node)
Create a new Species object from a 'species' XML_Node.
Definition: Species.cpp:36
Cantera::speciesXML_Node
const XML_Node * speciesXML_Node(const std::string &kname, const XML_Node *phaseSpeciesData)
Search an XML tree for species data.
Definition: ThermoFactory.cpp:655
DebyeHuckel.h
LatticePhase.h
Cantera::Phase::setXMLdata
void setXMLdata(XML_Node &xmlPhase)
Stores the XML tree information for the current phase.
Definition: Phase.cpp:50
Cantera::MaskellSolidSolnPhase
Class MaskellSolidSolnPhase represents a condensed phase non-ideal solution with 2 species following ...
Definition: MaskellSolidSolnPhase.h:27
Cantera::ThermoPhase::addSpecies
virtual bool addSpecies(shared_ptr< Species > spec)
Definition: ThermoPhase.cpp:1134
SpeciesThermoFactory.h
Cantera::IonsFromNeutralVPSSTP
Definition: IonsFromNeutralVPSSTP.h:67
EdgePhase.h
ENTROPY298_UNKNOWN
#define ENTROPY298_UNKNOWN
Number indicating we don't know the entropy of the element in its most stable state at 298....
Definition: Elements.h:87
Cantera::LatticeSolidPhase
A phase that is comprised of a fixed additive combination of other lattice phases.
Definition: LatticeSolidPhase.h:104
MaskellSolidSolnPhase.h
Cantera::VPStandardStateTP::installPDSS
void installPDSS(size_t k, std::unique_ptr< PDSS > &&pdss)
Install a PDSS object for species k
Definition: VPStandardStateTP.cpp:228
MultiSpeciesThermo.h
Cantera::XML_Node::name
std::string name() const
Returns the name of the XML node.
Definition: xml.h:372
IdealSolidSolnPhase.h
Cantera::ThermoPhase::setParameters
virtual void setParameters(int n, doublereal *const c)
Set the equation of state parameters.
Definition: ThermoPhase.h:1691
Cantera::setupPhase
void setupPhase(ThermoPhase &thermo, AnyMap &phaseNode, const AnyMap &rootNode)
Initialize a ThermoPhase object.
Definition: ThermoFactory.cpp:447
Cantera::XML_Node::getChildren
std::vector< XML_Node * > getChildren(const std::string &name) const
Get a vector of pointers to XML_Node containing all of the children of the current node which match t...
Definition: xml.cpp:711
Cantera::XML_Node::nChildren
size_t nChildren(bool discardComments=false) const
Return the number of children.
Definition: xml.cpp:556
Cantera::installElements
void installElements(Phase &th, const XML_Node &phaseNode)
Add the elements given in an XML_Node tree to the specified phase.
Definition: ThermoFactory.cpp:594
Cantera::InputFileError
Error thrown for problems processing information contained in an AnyMap or AnyValue.
Definition: AnyMap.h:538
Cantera::XML_Node::findByAttr
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:661
Species.h
Cantera::XML_Node
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:103
SurfPhase.h
Cantera::get_XML_NameID
XML_Node * get_XML_NameID(const std::string &nameTarget, const std::string &file_ID, XML_Node *root)
This routine will locate an XML node in either the input XML tree or in another input file specified ...
Definition: global.cpp:232
BinarySolutionTabulatedThermo.h
Cantera::OneAtm
const double OneAtm
One atmosphere [Pa].
Definition: ct_defs.h:78
LatticeSolidPhase.h
Cantera::ThermoPhase
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:101
stringUtils.h
Cantera::intValue
int intValue(const std::string &val)
Translate a string into one integer value.
Definition: stringUtils.cpp:124
Cantera::AnyMap::getBool
bool getBool(const std::string &key, bool default_) const
If key exists, return it as a bool, otherwise return default_.
Definition: AnyMap.cpp:1034
Cantera::ThermoPhase::saveSpeciesData
void saveSpeciesData(const size_t k, const XML_Node *const data)
Store a reference pointer to the XML tree containing the species data for this phase.
Definition: ThermoPhase.cpp:1164
Cantera::dot
doublereal dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
Definition: utilities.h:112
Cantera::getStringArray
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:427
PDSSFactory.h
Cantera::Phase::nSpecies
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:285
IdealMolalSoln.h
Cantera::cSS_CONVENTION_VPSS
const int cSS_CONVENTION_VPSS
Standard state uses the molality convention.
Definition: ThermoPhase.h:38
Cantera::SurfPhase
A simple thermodynamic model for a surface phase, assuming an ideal solution model.
Definition: SurfPhase.h:142
ConstDensityThermo.h
Cantera::MargulesVPSSTP
MargulesVPSSTP is a derived class of GibbsExcessVPSSTP that employs the Margules approximation for th...
Definition: MargulesVPSSTP.h:214
Cantera::Phase
Class Phase is the base class for phases of matter, managing the species and elements in a phase,...
Definition: Phase.h:100
Cantera::IdealMolalSoln
This phase is based upon the mixing-rule assumption that all molality-based activity coefficients are...
Definition: IdealMolalSoln.h:78
Cantera::ConstDensityThermo
Overloads the virtual methods of class ThermoPhase to implement the incompressible equation of state.
Definition: ConstDensityThermo.h:32
Cantera::get_XML_Node
XML_Node * get_XML_Node(const std::string &file_ID, XML_Node *root)
This routine will locate an XML node in either the input XML tree or in another input file specified ...
Definition: global.cpp:194
RedlichKisterVPSSTP.h
Cantera::formSpeciesXMLNodeList
static void formSpeciesXMLNodeList(std::vector< XML_Node * > &spDataNodeList, std::vector< std::string > &spNamesList, vector_int &spRuleList, const std::vector< XML_Node * > spArray_names, const std::vector< XML_Node * > spArray_dbases, const vector_int sprule)
Gather a vector of pointers to XML_Nodes for a phase.
Definition: ThermoFactory.cpp:162
Cantera::HMWSoln
Class HMWSoln represents a dilute or concentrated liquid electrolyte phase which obeys the Pitzer for...
Definition: HMWSoln.h:1038
Cantera::AnyMap
A map of string keys to values whose type can vary at runtime.
Definition: AnyMap.h:359
IdealSolnGasVPSS.h
Cantera::IdealSolidSolnPhase
Class IdealSolidSolnPhase represents a condensed phase ideal solution compound.
Definition: IdealSolidSolnPhase.h:39
Cantera::RedlichKisterVPSSTP
RedlichKisterVPSSTP is a derived class of GibbsExcessVPSSTP that employs the Redlich-Kister approxima...
Definition: RedlichKisterVPSSTP.h:216
Cantera::Phase::setName
void setName(const std::string &nm)
Sets the string name for the phase.
Definition: Phase.cpp:89
Cantera::PureFluidPhase
This phase object consists of a single component that can be a gas, a liquid, a mixed gas-liquid flui...
Definition: PureFluidPhase.h:30
Cantera::vector_int
std::vector< int > vector_int
Vector of ints.
Definition: ct_defs.h:182
Cantera::toLowerCopy
std::string toLowerCopy(const std::string &input)
Convert to lower case.
Definition: stringUtils.cpp:264
Cantera::CanteraError
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:60
Cantera::importPhase
void importPhase(XML_Node &phase, ThermoPhase *th)
Import a phase information into an empty ThermoPhase object.
Definition: ThermoFactory.cpp:237
Cantera::fpValueCheck
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
Definition: stringUtils.cpp:138
Cantera::DebyeHuckel
Definition: DebyeHuckel.h:558
Cantera::npos
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:188
Cantera::newPhase
ThermoPhase * newPhase(const std::string &infile, std::string id)
Create and Initialize a ThermoPhase object from an input file.
Definition: ThermoFactory.cpp:119
Cantera::ThermoPhase::initThermo
virtual void initThermo()
Initialize the ThermoPhase object after all species have been set up.
Definition: ThermoPhase.cpp:1096
Cantera::cSS_CONVENTION_SLAVE
const int cSS_CONVENTION_SLAVE
Standard state thermodynamics is obtained from slave ThermoPhase objects.
Definition: ThermoPhase.h:40
Cantera::IdealSolnGasVPSS
Definition: IdealSolnGasVPSS.h:30
Cantera::XML_Node::findByName
const XML_Node * findByName(const std::string &nm, int depth=100000) const
This routine carries out a recursive search for an XML node based on the name of the node.
Definition: xml.cpp:679
Cantera::EdgePhase
A thermodynamic phase representing a one dimensional edge between two surfaces.
Definition: EdgePhase.h:30
Cantera::Phase::species
shared_ptr< Species > species(const std::string &name) const
Return the Species object for the named species.
Definition: Phase.cpp:980
Cantera::WaterSSTP
Class for single-component water.
Definition: WaterSSTP.h:119
Cantera
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:263
Cantera::Phase::throwUndefinedElements
void throwUndefinedElements()
Set the behavior when adding a species containing undefined elements to throw an exception.
Definition: Phase.cpp:1005
HMWSoln.h
Cantera::fpValue
doublereal fpValue(const std::string &val)
Translate a string into one doublereal value.
Definition: stringUtils.cpp:129
Cantera::Phase::ignoreUndefinedElements
void ignoreUndefinedElements()
Set behavior when adding a species containing undefined elements to just skip the species.
Definition: Phase.cpp:997
IdealGasPhase.h
Cantera::XML_Node::child
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:546
Cantera::VPStandardStateTP
Definition: VPStandardStateTP.h:41
WaterSSTP.h
Cantera::AnyMap::getString
const std::string & getString(const std::string &key, const std::string &default_) const
If key exists, return it as a string, otherwise return default_.
Definition: AnyMap.cpp:1049
Cantera::RedlichKwongMFTP
Implementation of a multi-species Redlich-Kwong equation of state.
Definition: RedlichKwongMFTP.h:19
Cantera::StoichSubstance
Class StoichSubstance represents a stoichiometric (fixed composition) incompressible substance.
Definition: StoichSubstance.h:149