Cantera 2.6.0

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