Cantera  3.0.0
Loading...
Searching...
No Matches
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
10
11#define CT_SKIP_DEPRECATION_WARNINGS
12#include "cantera/kinetics/GasKinetics.h" // @todo Remove after Cantera 3.0
13
19
20#include <boost/algorithm/string.hpp>
21
22namespace Cantera
23{
24
25KineticsFactory* KineticsFactory::s_factory = 0;
26std::mutex KineticsFactory::kinetics_mutex;
27
28KineticsFactory::KineticsFactory() {
29 reg("none", []() { return new Kinetics(); });
30 addDeprecatedAlias("none", "Kinetics");
31 addDeprecatedAlias("none", "None");
32 reg("bulk", []() { return new BulkKinetics(); });
33 // @todo After Cantera 3.0, "gas" should be an alias for "bulk"
34 reg("gas", []() { return new GasKinetics(); });
35 addDeprecatedAlias("gas", "gaskinetics");
36 addDeprecatedAlias("gas", "Gas");
37 reg("surface", []() { return new InterfaceKinetics(); });
38 addAlias("surface", "interface");
39 addDeprecatedAlias("surface", "Surf");
40 addDeprecatedAlias("surface", "surf");
41 reg("edge", []() { return new EdgeKinetics(); });
42 addDeprecatedAlias("edge", "Edge");
43}
44
45KineticsFactory* KineticsFactory::factory() {
46 std::unique_lock<std::mutex> lock(kinetics_mutex);
47 if (!s_factory) {
48 s_factory = new KineticsFactory;
49 }
50 return s_factory;
51}
52
54 std::unique_lock<std::mutex> lock(kinetics_mutex);
55 delete s_factory;
56 s_factory = 0;
57}
58
60{
61 return create(toLowerCopy(model));
62}
63
64Kinetics* newKineticsMgr(const string& model)
65{
66 warn_deprecated("newKineticsMgr",
67 "To be removed after Cantera 3.0; superseded by newKinetics.");
68 return KineticsFactory::factory()->newKinetics(model);
69}
70
71shared_ptr<Kinetics> newKinetics(const string& model)
72{
73 shared_ptr<Kinetics> kin(KineticsFactory::factory()->newKinetics(model));
74 return kin;
75}
76
77shared_ptr<Kinetics> newKinetics(const vector<shared_ptr<ThermoPhase>>& phases,
78 const AnyMap& phaseNode,
79 const AnyMap& rootNode,
80 shared_ptr<Solution> soln)
81{
82 string kinType = phaseNode.getString("kinetics", "none");
83 kinType = KineticsFactory::factory()->canonicalize(kinType);
84 if (kinType == "none") {
85 // determine phase with minimum number of dimensions
86 size_t nDim = 3;
87 for (auto& phase : phases) {
88 nDim = std::min(phase->nDim(), nDim);
89 }
90 // change kinetics type as necessary
91 if (nDim == 2) {
92 kinType = "surface";
93 } else if (nDim == 1) {
94 kinType = "edge";
95 }
96 }
97
98 shared_ptr<Kinetics> kin(KineticsFactory::factory()->newKinetics(kinType));
99 if (soln) {
100 soln->setKinetics(kin);
101 }
102 for (auto& phase : phases) {
103 kin->addThermo(phase);
104 }
105 kin->init();
106 addReactions(*kin, phaseNode, rootNode);
107 return kin;
108}
109
110unique_ptr<Kinetics> newKinetics(const vector<ThermoPhase*>& phases,
111 const AnyMap& phaseNode,
112 const AnyMap& rootNode)
113{
114 warn_deprecated("newKinetics(vector<ThermoPhase*>&, AnyMap&, AnyMap&)",
115 "To be removed after Cantera 3.0; superseded by\nnewKinetics"
116 "(const vector<shared_ptr<ThermoPhase>>&, const AnyMap&, const AnyMap&).");
117 string kinType = phaseNode.getString("kinetics", "none");
118 kinType = KineticsFactory::factory()->canonicalize(kinType);
119 if (kinType == "none") {
120 // determine phase with minimum number of dimensions
121 size_t nDim = 3;
122 for (auto& phase : phases) {
123 nDim = std::min(phase->nDim(), nDim);
124 }
125 // change kinetics type as necessary
126 if (nDim == 2) {
127 kinType = "surface";
128 } else if (nDim == 1) {
129 kinType = "edge";
130 }
131 }
132
133 unique_ptr<Kinetics> kin(KineticsFactory::factory()->newKinetics(kinType));
134 for (auto& phase : phases) {
135 kin->addPhase(*phase);
136 }
137 kin->init();
138 addReactions(*kin, phaseNode, rootNode);
139 return kin;
140}
141
142shared_ptr<Kinetics> newKinetics(const vector<shared_ptr<ThermoPhase>>& phases,
143 const string& filename,
144 const string& phase_name)
145{
146 if (phase_name != "") {
147 warn_deprecated("newKinetics", "After Cantera 3.0, the 'phase_name' argument "
148 "will be removed and an exception will be thrown if the reacting phase is "
149 "not the first phase in the 'phases' vector.");
150 }
151 string reaction_phase = (phase_name.empty()) ? phases.at(0)->name() : phase_name;
152 AnyMap root = AnyMap::fromYamlFile(filename);
153 AnyMap& phaseNode = root["phases"].getMapWhere("name", reaction_phase);
154 return newKinetics(phases, phaseNode, root);
155}
156
157unique_ptr<Kinetics> newKinetics(const vector<ThermoPhase*>& phases,
158 const string& filename, const string& phase_name)
159{
160 warn_deprecated("newKinetics(vector<ThermoPhase*>&, const string&, const string&)",
161 "To be removed after Cantera 3.0; superseded by\nnewKinetics"
162 "(const vector<shared_ptr<ThermoPhase>>&, const string&, const string&).");
163 AnyMap root = AnyMap::fromYamlFile(filename);
164 AnyMap& phaseNode = root["phases"].getMapWhere("name", phase_name);
165 return newKinetics(phases, phaseNode, root);
166}
167
168void addReactions(Kinetics& kin, const AnyMap& phaseNode, const AnyMap& rootNode)
169{
171 phaseNode.getBool("skip-undeclared-third-bodies", false));
172
173 loadExtensions(rootNode);
174
175 // Find sections containing reactions to add
176 vector<string> sections, rules;
177
178 if (phaseNode.hasKey("reactions")) {
179 const auto& reactionsNode = phaseNode.at("reactions");
180 if (reactionsNode.is<string>()) {
181 if (rootNode.hasKey("reactions")) {
182 // Specification of the rule for adding species from the default
183 // 'reactions' section, if it exists
184 sections.push_back("reactions");
185 rules.push_back(reactionsNode.asString());
186 } else if (reactionsNode.asString() != "none") {
187 throw InputFileError("addReactions", reactionsNode,
188 "Phase entry implies existence of 'reactions' section "
189 "which does not exist in the current input file.");
190 }
191 } else if (reactionsNode.is<vector<string>>()) {
192 // List of sections from which all species should be added
193 for (const auto& item : reactionsNode.as<vector<string>>()) {
194 sections.push_back(item);
195 rules.push_back("all");
196 }
197 } else if (reactionsNode.is<vector<AnyMap>>()) {
198 // Mapping of rules to apply for each specified section containing
199 // reactions
200 for (const auto& item : reactionsNode.as<vector<AnyMap>>()) {
201 sections.push_back(item.begin()->first);
202 rules.push_back(item.begin()->second.asString());
203 }
204 }
205 } else if (kin.kineticsType() != "none") {
206 if (!phaseNode.hasKey("kinetics")) {
207 // Do nothing - default surface or edge kinetics require separate detection
208 // while not adding reactions
209 } else if (rootNode.hasKey("reactions")) {
210 // Default behavior is to add all reactions from the 'reactions'
211 // section, if a 'kinetics' model has been specified
212 sections.push_back("reactions");
213 rules.push_back("all");
214 } else {
215 throw InputFileError("addReactions", phaseNode,
216 "Phase entry implies existence of 'reactions' section which "
217 "does not exist in the current input file. Add the field "
218 "'reactions: none' to the phase entry to specify a kinetics "
219 "model with no reactions.");
220 }
221 }
222
223 // Add reactions from each section
224 fmt::memory_buffer add_rxn_err;
225 for (size_t i = 0; i < sections.size(); i++) {
226 if (rules[i] == "all") {
227 kin.skipUndeclaredSpecies(false);
228 } else if (rules[i] == "declared-species") {
229 kin.skipUndeclaredSpecies(true);
230 } else if (rules[i] == "none") {
231 continue;
232 } else {
233 throw InputFileError("addReactions", phaseNode.at("reactions"),
234 "Unknown rule '{}' for adding species from the '{}' section.",
235 rules[i], sections[i]);
236 }
237 const auto& slash = boost::ifind_last(sections[i], "/");
238 if (slash) {
239 // specified section is in a different file
240 string fileName (sections[i].begin(), slash.begin());
241 string node(slash.end(), sections[i].end());
242 AnyMap reactions = AnyMap::fromYamlFile(fileName,
243 rootNode.getString("__file__", ""));
244 loadExtensions(reactions);
245 for (const auto& R : reactions[node].asVector<AnyMap>()) {
246 #ifdef NDEBUG
247 try {
248 kin.addReaction(newReaction(R, kin), false);
249 } catch (CanteraError& err) {
250 fmt_append(add_rxn_err, "{}", err.what());
251 }
252 #else
253 kin.addReaction(newReaction(R, kin), false);
254 #endif
255 }
256 } else {
257 // specified section is in the current file
258 for (const auto& R : rootNode.at(sections[i]).asVector<AnyMap>()) {
259 #ifdef NDEBUG
260 try {
261 kin.addReaction(newReaction(R, kin), false);
262 } catch (CanteraError& err) {
263 fmt_append(add_rxn_err, "{}", err.what());
264 }
265 #else
266 kin.addReaction(newReaction(R, kin), false);
267 #endif
268 }
269 }
270 }
271
272 if (add_rxn_err.size()) {
273 throw CanteraError("addReactions", to_string(add_rxn_err));
274 }
275 kin.checkDuplicates();
276 kin.resizeReactions();
277}
278
279}
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:427
bool hasKey(const string &key) const
Returns true if the map contains an item named key.
Definition AnyMap.cpp:1423
bool getBool(const string &key, bool default_) const
If key exists, return it as a bool, otherwise return default_.
Definition AnyMap.cpp:1515
const string & getString(const string &key, const string &default_) const
If key exists, return it as a string, otherwise return default_.
Definition AnyMap.cpp:1530
static AnyMap fromYamlFile(const string &name, const string &parent_name="")
Create an AnyMap from a YAML file.
Definition AnyMap.cpp:1771
const AnyValue & at(const string &key) const
Get the value of the item stored in key.
Definition AnyMap.cpp:1408
const 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:109
Base class for exceptions thrown by Cantera classes.
const char * what() const override
Get a description of the error.
Kinetics * create(const string &name, Args... args)
Create an object using the object construction function corresponding to "name" and the provided cons...
Definition FactoryBase.h:75
void reg(const string &name, function< Kinetics *(Args...)> f)
Register a new object construction function.
Definition FactoryBase.h:80
void addAlias(const string &original, const string &alias)
Add an alias for an existing registered type.
Definition FactoryBase.h:85
void addDeprecatedAlias(const string &original, const string &alias)
Add a deprecated alias for an existing registered type.
Error thrown for problems processing information contained in an AnyMap or AnyValue.
Definition AnyMap.h:738
void deleteFactory() override
Virtual abstract function that deletes the factory.
Kinetics * newKinetics(const string &model)
Return a new, empty kinetics manager.
Public interface for kinetics managers.
Definition Kinetics.h:126
virtual void resizeReactions()
Finalize Kinetics object and associated objects.
Definition Kinetics.cpp:35
virtual string kineticsType() const
Identifies the Kinetics manager type.
Definition Kinetics.h:145
virtual pair< size_t, size_t > checkDuplicates(bool throw_err=true) const
Check for unmarked duplicate reactions and unmatched marked duplicates.
Definition Kinetics.cpp:107
virtual bool addReaction(shared_ptr< Reaction > r, bool resize=true)
Add a single reaction to the mechanism.
Definition Kinetics.cpp:665
void skipUndeclaredSpecies(bool skip)
Determine behavior when adding a new reaction that contains species not defined in any of the phases ...
Definition Kinetics.h:1400
void skipUndeclaredThirdBodies(bool skip)
Determine behavior when adding a new reaction that contains third-body efficiencies for species not d...
Definition Kinetics.h:1412
void fmt_append(fmt::memory_buffer &b, Args... args)
Versions 6.2.0 and 6.2.1 of fmtlib do not include this define before they include windows....
Definition fmt.h:29
string toLowerCopy(const string &input)
Convert to lower case.
Kinetics * newKineticsMgr(const string &model)
Create a new kinetics manager.
shared_ptr< Kinetics > newKinetics(const string &model)
Create a new Kinetics instance.
void addReactions(Kinetics &kin, const AnyMap &phaseNode, const AnyMap &rootNode)
Add reactions to a Kinetics object.
Namespace for the Cantera kernel.
Definition AnyMap.cpp:564
void loadExtensions(const AnyMap &node)
Load extensions providing user-defined models from the extensions section of the given node.
Definition global.cpp:179
void warn_deprecated(const string &source, const AnyBase &node, const string &message)
A deprecation warning for syntax in an input file.
Definition AnyMap.cpp:1926
unique_ptr< Reaction > newReaction(const string &type)
Create a new empty Reaction object.
Definition Reaction.cpp:912
Contains declarations for string manipulation functions within Cantera.