Go to the documentation of this file.
47 ThermoFactory* ThermoFactory::s_factory = 0;
48 std::mutex ThermoFactory::thermo_mutex;
50 ThermoFactory::ThermoFactory()
53 addAlias(
"ideal-gas",
"IdealGas");
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");
63 addAlias(
"fixed-stoichiometry",
"StoichSubstance");
65 addAlias(
"pure-fluid",
"PureFluid");
67 addAlias(
"compound-lattice",
"LatticeSolid");
69 addAlias(
"lattice",
"Lattice");
70 reg(
"HMW-electrolyte", []() {
return new HMWSoln(); });
71 addAlias(
"HMW-electrolyte",
"HMW");
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");
80 addAlias(
"ideal-solution-VPSS",
"IdealSolnVPSS");
81 addAlias(
"ideal-gas-VPSS",
"IdealGasVPSS");
84 addAlias(
"ions-from-neutral-molecule",
"IonsFromNeutralMolecule");
86 addAlias(
"fixed-chemical-potential",
"FixedChemPot");
89 addAlias(
"Redlich-Kwong",
"RedlichKwongMFTP");
90 addAlias(
"Redlich-Kwong",
"RedlichKwong");
92 addAlias(
"Maskell-solid-solution",
"MaskellSolidSolnPhase");
93 reg(
"liquid-water-IAPWS95", []() {
return new WaterSSTP(); });
94 addAlias(
"liquid-water-IAPWS95",
"PureLiquidWater");
96 addAlias(
"binary-solution-tabulated",
"BinarySolutionTabulatedThermo");
101 return create(model);
106 string model = xmlphase.
child(
"thermo")[
"model"];
114 unique_ptr<ThermoPhase> t(
newThermoPhase(phaseNode[
"thermo"].asString()));
121 size_t dot = infile.find_last_of(
".");
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()));
141 "Couldn't find phase named \"" +
id +
"\" in file, " + infile);
163 std::vector<std::string> &spNamesList,
165 const std::vector<XML_Node*> spArray_names,
166 const std::vector<XML_Node*> spArray_dbases,
170 std::map<std::string, bool> declared;
172 for (
size_t jsp = 0; jsp < spArray_dbases.size(); jsp++) {
173 const XML_Node& speciesArray = *spArray_names[jsp];
176 const XML_Node* db = spArray_dbases[jsp];
179 std::vector<std::string> spnames;
181 size_t nsp = spnames.size();
186 if (nsp == 1 && spnames[0] ==
"all") {
187 std::vector<XML_Node*> allsp = db->
getChildren(
"species");
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]);
199 }
else if (nsp == 1 && spnames[0] ==
"unique") {
200 std::vector<XML_Node*> allsp = db->
getChildren(
"species");
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]);
213 std::map<std::string, XML_Node*> speciesNodes;
214 for (
size_t k = 0; k < db->
nChildren(); k++) {
216 speciesNodes[child[
"name"]] = &child;
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;
223 auto iter = speciesNodes.find(stemp);
224 if (iter == speciesNodes.end()) {
226 "no data for species, \"{}\"", stemp);
228 spNamesList.push_back(stemp);
229 spDataNodeList.push_back(iter->second);
230 spRuleList.push_back(sprule[jsp]);
240 if (phase.
name() !=
"phase") {
242 "Current const XML_Node named, " + phase.
name() +
243 ", is not a phase element.");
258 if (idim < 1 || idim > 3) {
260 "phase, " + th->
name() +
261 ", has unphysical number of dimensions: " + phase[
"dim"]);
276 " phase, " + th->
name() +
277 ", XML_Node does not have a \"thermo\" XML_Node");
286 "phase, " + th->
name() +
", was VPSS, but dynamic cast failed");
299 vector<XML_Node*> sparrays = phase.
getChildren(
"speciesArray");
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");
306 vector<XML_Node*> dbases;
314 for (
size_t jsp = 0; jsp < sparrays.size(); jsp++) {
315 const XML_Node& speciesArray = *sparrays[jsp];
329 if (speciesArray.
hasChild(
"skip")) {
331 string eskip = sk[
"element"];
332 if (eskip ==
"undeclared") {
335 string dskip = sk[
"species"];
336 if (dskip ==
"duplicate") {
347 "Can not find XML node for species database: {}",
348 speciesArray[
"datasrc"]);
352 dbases.push_back(db);
359 std::vector<XML_Node*> spDataNodeList;
360 std::vector<std::string> spNamesList;
363 sparrays, dbases, sprule);
365 size_t nsp = spDataNodeList.size();
367 throw CanteraError(
"importPhase",
"For Slave standard states, "
368 "number of species must be zero: {}", nsp);
370 for (
size_t k = 0; k < nsp; k++) {
379 std::string ss_model = (ss) ? ss->
attrib(
"model") :
"ideal-gas";
380 unique_ptr<PDSS> kPDSS(newPDSS(ss_model));
381 kPDSS->setParametersFromXML(*s);
397 void addDefaultElements(ThermoPhase& thermo,
const vector<string>& element_names) {
398 for (
const auto& symbol : element_names) {
399 thermo.addElement(symbol);
403 void addElements(ThermoPhase& thermo,
const vector<string>& element_names,
404 const AnyValue& elements,
bool allow_default)
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);
413 thermo.addElement(symbol, weight, number, e298);
414 }
else if (allow_default) {
415 thermo.addElement(symbol);
417 throw InputFileError(
"addElements", elements,
418 "Element '{}' not found", symbol);
423 void addSpecies(ThermoPhase& thermo,
const AnyValue& names,
const AnyValue& species)
425 if (names.is<vector<string>>()) {
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)));
432 throw InputFileError(
"addSpecies", names, species,
433 "Could not find a species named '{}'.", name);
436 }
else if (names ==
"all") {
438 for (
const auto& item : species.asVector<AnyMap>()) {
442 throw InputFileError(
"addSpecies", names,
443 "Could not parse species declaration of type '{}'", names.type_str());
449 thermo.
setName(phaseNode[
"name"].asString());
450 if (rootNode.
hasKey(
"__file__")) {
451 phaseNode[
"__file__"] = rootNode[
"__file__"];
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());
462 if (phaseNode.
hasKey(
"elements")) {
463 if (phaseNode.
getBool(
"skip-undeclared-elements",
false)) {
469 if (phaseNode[
"elements"].is<vector<string>>()) {
471 if (rootNode.
hasKey(
"elements")) {
472 addElements(thermo, phaseNode[
"elements"].asVector<string>(),
473 rootNode[
"elements"],
true);
475 addDefaultElements(thermo, phaseNode[
"elements"].asVector<string>());
477 }
else if (phaseNode[
"elements"].is<vector<AnyMap>>()) {
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,
"/");
486 std::string fileName(source.begin(), slash.begin());
487 std::string node(slash.end(), source.end());
488 const AnyMap elements = AnyMap::fromYamlFile(fileName,
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);
497 "Could not find elements section named '{}'", source);
502 "Could not parse elements declaration of type '{}'",
503 phaseNode[
"elements"].type_str());
512 if (phaseNode.
hasKey(
"species")) {
513 if (phaseNode[
"species"].is<vector<string>>()) {
516 addSpecies(thermo, phaseNode[
"species"], rootNode[
"species"]);
517 }
else if (phaseNode[
"species"].is<string>()) {
520 addSpecies(thermo, phaseNode[
"species"], rootNode[
"species"]);
521 }
else if (phaseNode[
"species"].is<vector<AnyMap>>()) {
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,
"/");
531 std::string fileName(source.begin(), slash.begin());
532 std::string node(slash.end(), source.end());
533 AnyMap species = AnyMap::fromYamlFile(fileName,
535 addSpecies(thermo, names, species[node]);
536 }
else if (rootNode.
hasKey(source)) {
538 addSpecies(thermo, names, rootNode[source]);
541 "Could not find species section named '{}'", source);
546 "Could not parse species declaration of type '{}'",
547 phaseNode[
"species"].type_str());
549 }
else if (rootNode.
hasKey(
"species")) {
551 addSpecies(thermo,
AnyValue(
"all"), rootNode[
"species"]);
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")) {
560 auto& eos = thermo.
species(k)->input[
"equation-of-state"];
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);
573 "Could not find an equation-of-state specification "
574 "which defines a known PDSS model.");
577 pdss.reset(newPDSS(
"ideal-gas"));
579 vpssThermo->installPDSS(k, std::move(pdss));
586 if (phaseNode.
hasKey(
"state")) {
587 auto node = phaseNode[
"state"].as<
AnyMap>();
597 if (!phaseNode.
hasChild(
"elementArray")) {
599 "phase XML node doesn't have \"elementArray\" XML Node");
602 vector<string> enames;
606 string element_database =
"elements.xml";
608 element_database = elements[
"datasrc"];
617 local_db = &root.
child(
"elementData");
620 for (
size_t i = 0; i < enames.size(); i++) {
630 throw CanteraError(
"installElements",
"no data for element '{}'",
635 doublereal weight = 0.0;
643 string symbol = e->
attrib(
"name");
651 th.
addElement(symbol, weight, anum, entropy298);
658 if (!phaseSpeciesData) {
661 string jname = phaseSpeciesData->
name();
662 if (jname !=
"speciesData") {
664 "Unexpected phaseSpeciesData name: " + jname);
666 vector<XML_Node*> xspecies = phaseSpeciesData->
getChildren(
"species");
667 for (
size_t j = 0; j < xspecies.size(); j++) {
670 if (jname == kname) {
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object using an XML tree.
A wrapper for a variable whose type is determined at runtime.
bool hasAttrib(const std::string &a) const
Tests whether the current node has an attribute with a particular name.
virtual void setParametersFromXML(const XML_Node &eosdata)
Set equation of state parameter values from XML entries.
void setNDim(size_t ndim)
Set the number of spatial dimensions (1, 2, or 3).
A simple thermodynamic model for a bulk phase, assuming a lattice of solid atoms.
Overloads the virtual methods of class IdealSolidSolnPhase to implement tabulated standard state ther...
std::string id() const
Return the id attribute, if present.
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
bool hasKey(const std::string &key) const
Returns true if the map contains an item named key.
Class IdealGasPhase represents low-density gases that obey the ideal gas equation of state.
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
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.
const AnyValue & at(const std::string &key) const
Get the value of the item stored in key.
virtual void setState_TP(doublereal t, doublereal p)
Set the temperature (K) and pressure (Pa)
XML_Node & root() const
Return the root of the current XML_Node tree.
void addUndefinedElements()
Set behavior when adding a species containing undefined elements to add those elements to the phase.
Class FixedChemPotSSTP represents a stoichiometric (fixed composition) incompressible substance.
virtual int standardStateConvention() const
This method returns the convention used in specification of the standard state, of which there are cu...
std::string name() const
Return the name of the phase.
virtual void setState(const AnyMap &state)
Set the state using an AnyMap containing any combination of properties supported by the thermodynamic...
#define AssertTrace(expr)
Assertion must be true or an error is thrown.
ThermoPhase * newThermoPhase(const std::string &model)
Create a new thermo manager instance.
shared_ptr< Species > newSpecies(const XML_Node &species_node)
Create a new Species object from a 'species' XML_Node.
const XML_Node * speciesXML_Node(const std::string &kname, const XML_Node *phaseSpeciesData)
Search an XML tree for species data.
void setXMLdata(XML_Node &xmlPhase)
Stores the XML tree information for the current phase.
Class MaskellSolidSolnPhase represents a condensed phase non-ideal solution with 2 species following ...
virtual bool addSpecies(shared_ptr< Species > spec)
#define ENTROPY298_UNKNOWN
Number indicating we don't know the entropy of the element in its most stable state at 298....
A phase that is comprised of a fixed additive combination of other lattice phases.
void installPDSS(size_t k, std::unique_ptr< PDSS > &&pdss)
Install a PDSS object for species k
std::string name() const
Returns the name of the XML node.
virtual void setParameters(int n, doublereal *const c)
Set the equation of state parameters.
void setupPhase(ThermoPhase &thermo, AnyMap &phaseNode, const AnyMap &rootNode)
Initialize a ThermoPhase object.
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...
size_t nChildren(bool discardComments=false) const
Return the number of children.
void installElements(Phase &th, const XML_Node &phaseNode)
Add the elements given in an XML_Node tree to the specified phase.
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.
Class XML_Node is a tree-based representation of the contents of an XML file.
const double OneAtm
One atmosphere [Pa].
Base class for a phase with thermodynamic properties.
int intValue(const std::string &val)
Translate a string into one integer value.
bool getBool(const std::string &key, bool default_) const
If key exists, return it as a bool, otherwise return default_.
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.
doublereal dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
void getStringArray(const XML_Node &node, std::vector< std::string > &v)
This function interprets the value portion of an XML element as a string.
size_t nSpecies() const
Returns the number of species in the phase.
const int cSS_CONVENTION_VPSS
Standard state uses the molality convention.
A simple thermodynamic model for a surface phase, assuming an ideal solution model.
MargulesVPSSTP is a derived class of GibbsExcessVPSSTP that employs the Margules approximation for th...
Class Phase is the base class for phases of matter, managing the species and elements in a phase,...
This phase is based upon the mixing-rule assumption that all molality-based activity coefficients are...
Overloads the virtual methods of class ThermoPhase to implement the incompressible equation of state.
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.
Class HMWSoln represents a dilute or concentrated liquid electrolyte phase which obeys the Pitzer for...
A map of string keys to values whose type can vary at runtime.
Class IdealSolidSolnPhase represents a condensed phase ideal solution compound.
RedlichKisterVPSSTP is a derived class of GibbsExcessVPSSTP that employs the Redlich-Kister approxima...
void setName(const std::string &nm)
Sets the string name for the phase.
This phase object consists of a single component that can be a gas, a liquid, a mixed gas-liquid flui...
std::vector< int > vector_int
Vector of ints.
std::string toLowerCopy(const std::string &input)
Convert to lower case.
Base class for exceptions thrown by Cantera classes.
void importPhase(XML_Node &phase, ThermoPhase *th)
Import a phase information into an empty ThermoPhase object.
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
const size_t npos
index returned by functions to indicate "no position"
ThermoPhase * newPhase(const std::string &infile, std::string id)
Create and Initialize a ThermoPhase object from an input file.
virtual void initThermo()
Initialize the ThermoPhase object after all species have been set up.
const int cSS_CONVENTION_SLAVE
Standard state thermodynamics is obtained from slave ThermoPhase objects.
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.
A thermodynamic phase representing a one dimensional edge between two surfaces.
shared_ptr< Species > species(const std::string &name) const
Return the Species object for the named species.
Namespace for the Cantera kernel.
void throwUndefinedElements()
Set the behavior when adding a species containing undefined elements to throw an exception.
doublereal fpValue(const std::string &val)
Translate a string into one doublereal value.
void ignoreUndefinedElements()
Set behavior when adding a species containing undefined elements to just skip the species.
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
const std::string & getString(const std::string &key, const std::string &default_) const
If key exists, return it as a string, otherwise return default_.
Implementation of a multi-species Redlich-Kwong equation of state.
Class StoichSubstance represents a stoichiometric (fixed composition) incompressible substance.