Cantera 2.6.0
KineticsFactory.cpp
Go to the documentation of this file.
1/**
2 * @file KineticsFactory.cpp
3 */
4
5// This file is part of Cantera. See License.txt in the top-level directory or
6// at https://cantera.org/license.txt for license and copyright information.
7
14#include "cantera/base/xml.h"
16
17using namespace std;
18
19namespace Cantera
20{
21
22KineticsFactory* KineticsFactory::s_factory = 0;
23std::mutex KineticsFactory::kinetics_mutex;
24
26 vector<ThermoPhase*> th)
27{
28 // Look for a child of the XML element phase called "kinetics". It has an
29 // attribute name "model". Store the value of that attribute in the variable
30 // kintype
31 string kintype = phaseData.child("kinetics")["model"];
32
33 // Create a kinetics object of the desired type
34 Kinetics* k = newKinetics(kintype);
35 // Now that we have the kinetics manager, we can import the reaction
36 // mechanism into it.
37 importKinetics(phaseData, th, k);
38
39 // Return the pointer to the kinetics manager
40 return k;
41}
42
43KineticsFactory::KineticsFactory() {
44 reg("none", []() { return new Kinetics(); });
45 addAlias("none", "Kinetics");
46 addAlias("none", "None");
47 reg("gas", []() { return new GasKinetics(); });
48 addAlias("gas", "gaskinetics");
49 addAlias("gas", "Gas");
50 reg("surface", []() { return new InterfaceKinetics(); });
51 addAlias("surface", "interface");
52 addAlias("surface", "Surf");
53 addAlias("surface", "surf");
54 reg("edge", []() { return new EdgeKinetics(); });
55 addAlias("edge", "Edge");
56}
57
59{
60 return create(toLowerCopy(model));
61}
62
63unique_ptr<Kinetics> newKinetics(const vector<ThermoPhase*>& phases,
64 const AnyMap& phaseNode,
65 const AnyMap& rootNode)
66{
67 std::string kinType = phaseNode.getString("kinetics", "none");
68 kinType = KineticsFactory::factory()->canonicalize(kinType);
69 if (kinType == "none") {
70 // determine phase with minimum number of dimensions
71 size_t nDim = 3;
72 for (auto& phase : phases) {
73 nDim = std::min(phase->nDim(), nDim);
74 }
75 // change kinetics type as necessary
76 if (nDim == 2) {
77 kinType = "surface";
78 } else if (nDim == 1) {
79 kinType = "edge";
80 }
81 }
82
83 unique_ptr<Kinetics> kin(KineticsFactory::factory()->newKinetics(kinType));
84 for (auto& phase : phases) {
85 kin->addPhase(*phase);
86 }
87 kin->init();
88 addReactions(*kin, phaseNode, rootNode);
89 return kin;
90}
91
92unique_ptr<Kinetics> newKinetics(const std::vector<ThermoPhase*>& phases,
93 const std::string& filename,
94 const std::string& phase_name)
95{
96 size_t dot = filename.find_last_of(".");
97 string extension;
98 if (dot != npos) {
99 extension = toLowerCopy(filename.substr(dot+1));
100 }
101
102 if (extension == "yml" || extension == "yaml") {
103 AnyMap root = AnyMap::fromYamlFile(filename);
104 AnyMap& phaseNode = root["phases"].getMapWhere("name", phase_name);
105 return newKinetics(phases, phaseNode, root);
106 } else {
107 XML_Node* root = get_XML_File(filename);
108 XML_Node* xphase = get_XML_NameID("phase", "#"+phase_name, root);
109 if (!xphase) {
110 throw CanteraError("newKinetics",
111 "Couldn't find phase named '{}' in file '{}'.",
112 phase_name, filename);
113 }
114 return unique_ptr<Kinetics>(newKineticsMgr(*xphase, phases));
115 }
116}
117
118void addReactions(Kinetics& kin, const AnyMap& phaseNode, const AnyMap& rootNode)
119{
121 phaseNode.getBool("skip-undeclared-third-bodies", false));
122
123 // Find sections containing reactions to add
124 vector<string> sections, rules;
125
126 if (phaseNode.hasKey("reactions")) {
127 const auto& reactionsNode = phaseNode.at("reactions");
128 if (reactionsNode.is<string>()) {
129 if (rootNode.hasKey("reactions")) {
130 // Specification of the rule for adding species from the default
131 // 'reactions' section, if it exists
132 sections.push_back("reactions");
133 rules.push_back(reactionsNode.asString());
134 } else if (reactionsNode.asString() != "none") {
135 throw InputFileError("addReactions", reactionsNode,
136 "Phase entry implies existence of 'reactions' section "
137 "which does not exist in the current input file.");
138 }
139 } else if (reactionsNode.is<vector<string>>()) {
140 // List of sections from which all species should be added
141 for (const auto& item : reactionsNode.as<vector<string>>()) {
142 sections.push_back(item);
143 rules.push_back("all");
144 }
145 } else if (reactionsNode.is<vector<AnyMap>>()) {
146 // Mapping of rules to apply for each specified section containing
147 // reactions
148 for (const auto& item : reactionsNode.as<vector<AnyMap>>()) {
149 sections.push_back(item.begin()->first);
150 rules.push_back(item.begin()->second.asString());
151 }
152 }
153 } else if (kin.kineticsType() != "None") {
154 if (!phaseNode.hasKey("kinetics")) {
155 // Do nothing - default surface or edge kinetics require separate detection
156 // while not adding reactions
157 } else if (rootNode.hasKey("reactions")) {
158 // Default behavior is to add all reactions from the 'reactions'
159 // section, if a 'kinetics' model has been specified
160 sections.push_back("reactions");
161 rules.push_back("all");
162 } else {
163 throw InputFileError("addReactions", phaseNode,
164 "Phase entry implies existence of 'reactions' section which "
165 "does not exist in the current input file. Add the field "
166 "'reactions: none' to the phase entry to specify a kinetics "
167 "model with no reactions.");
168 }
169 }
170
171 // Add reactions from each section
172 fmt::memory_buffer add_rxn_err;
173 for (size_t i = 0; i < sections.size(); i++) {
174 if (rules[i] == "all") {
175 kin.skipUndeclaredSpecies(false);
176 } else if (rules[i] == "declared-species") {
177 kin.skipUndeclaredSpecies(true);
178 } else if (rules[i] == "none") {
179 continue;
180 } else {
181 throw InputFileError("addReactions", phaseNode.at("reactions"),
182 "Unknown rule '{}' for adding species from the '{}' section.",
183 rules[i], sections[i]);
184 }
185 const auto& slash = boost::ifind_last(sections[i], "/");
186 if (slash) {
187 // specified section is in a different file
188 string fileName (sections[i].begin(), slash.begin());
189 string node(slash.end(), sections[i].end());
190 AnyMap reactions = AnyMap::fromYamlFile(fileName,
191 rootNode.getString("__file__", ""));
192 for (const auto& R : reactions[node].asVector<AnyMap>()) {
193 try {
194 kin.addReaction(newReaction(R, kin), false);
195 } catch (CanteraError& err) {
196 fmt_append(add_rxn_err, "{}", err.what());
197 }
198 }
199 } else {
200 // specified section is in the current file
201 for (const auto& R : rootNode.at(sections[i]).asVector<AnyMap>()) {
202 #ifdef NDEBUG
203 try {
204 kin.addReaction(newReaction(R, kin), false);
205 } catch (CanteraError& err) {
206 fmt_append(add_rxn_err, "{}", err.what());
207 }
208 #else
209 kin.addReaction(newReaction(R, kin), false);
210 #endif
211 }
212 }
213 }
214
215 kin.checkDuplicates();
216 if (add_rxn_err.size()) {
217 throw CanteraError("addReactions", to_string(add_rxn_err));
218 }
219
220 kin.resizeReactions();
221}
222
223}
Header file for class ThermoPhase, the base class for phases with thermodynamic properties,...
A map of string keys to values whose type can vary at runtime.
Definition: AnyMap.h:399
const AnyValue & at(const std::string &key) const
Get the value of the item stored in key.
Definition: AnyMap.cpp:1391
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
bool getBool(const std::string &key, bool default_) const
If key exists, return it as a bool, otherwise return default_.
Definition: AnyMap.cpp:1487
static AnyMap fromYamlFile(const std::string &name, const std::string &parent_name="")
Create an AnyMap from a YAML file.
Definition: AnyMap.cpp:1743
bool hasKey(const std::string &key) const
Returns true if the map contains an item named key.
Definition: AnyMap.cpp:1406
const std::vector< T > & asVector(size_t nMin=npos, size_t nMax=npos) const
Return the held value, if it is a vector of type T.
Definition: AnyMap.inl.h:72
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:61
const char * what() const
Get a description of the error.
Kinetics * 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
void addAlias(const std::string &original, const std::string &alias)
Add an alias for an existing registered type.
Definition: FactoryBase.h:86
void reg(const std::string &name, std::function< Kinetics *(Args...)> f)
Register a new object construction function.
Definition: FactoryBase.h:81
Error thrown for problems processing information contained in an AnyMap or AnyValue.
Definition: AnyMap.h:702
virtual Kinetics * newKinetics(XML_Node &phase, std::vector< ThermoPhase * > th)
Return a new kinetics manager that implements a reaction mechanism specified in a CTML file.
Public interface for kinetics managers.
Definition: Kinetics.h:114
virtual void resizeReactions()
Finalize Kinetics object and associated objects.
Definition: Kinetics.cpp:48
virtual bool addReaction(shared_ptr< Reaction > r, bool resize=true)
Add a single reaction to the mechanism.
Definition: Kinetics.cpp:660
void skipUndeclaredSpecies(bool skip)
Determine behavior when adding a new reaction that contains species not defined in any of the phases ...
Definition: Kinetics.h:1171
void skipUndeclaredThirdBodies(bool skip)
Determine behavior when adding a new reaction that contains third-body efficiencies for species not d...
Definition: Kinetics.h:1183
virtual std::string kineticsType() const
Identifies the Kinetics manager type.
Definition: Kinetics.h:131
virtual std::pair< size_t, size_t > checkDuplicates(bool throw_err=true) const
Check for unmarked duplicate reactions and unmatched marked duplicates.
Definition: Kinetics.cpp:103
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:103
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
bool importKinetics(const XML_Node &phase, std::vector< ThermoPhase * > th, Kinetics *kin)
Import a reaction mechanism for a phase or an interface.
Definitions of global routines for the importing of data from XML files (see Input File Handling).
Namespace for the Cantera kernel.
Definition: AnyMap.h:29
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:192
XML_Node * get_XML_File(const std::string &file, int debug=0)
Return a pointer to the XML tree for a Cantera input file.
Definition: global.cpp:140
void addReactions(Kinetics &kin, const AnyMap &phaseNode, const AnyMap &rootNode=AnyMap())
doublereal dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
Definition: utilities.h:77
std::string toLowerCopy(const std::string &input)
Convert to lower case.
Kinetics * newKineticsMgr(XML_Node &phase, std::vector< ThermoPhase * > th)
Create a new kinetics manager.
unique_ptr< Reaction > newReaction(const std::string &type)
Create a new empty Reaction object.
Definition: Reaction.cpp:1307
shared_ptr< Kinetics > newKinetics(const std::string &model)
Create a new Kinetics instance.
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
Contains declarations for string manipulation functions within Cantera.
Classes providing support for XML data files.