Cantera  3.1.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
16#include <boost/algorithm/string.hpp>
17
18namespace Cantera
19{
20
21KineticsFactory* KineticsFactory::s_factory = 0;
22std::mutex KineticsFactory::kinetics_mutex;
23
24KineticsFactory::KineticsFactory() {
25 reg("none", []() { return new Kinetics(); });
26 addDeprecatedAlias("none", "Kinetics");
27 addDeprecatedAlias("none", "None");
28 reg("bulk", []() { return new BulkKinetics(); });
29 addAlias("bulk", "gas");
30 addDeprecatedAlias("bulk", "gaskinetics");
31 addDeprecatedAlias("bulk", "Gas");
32 reg("surface", []() { return new InterfaceKinetics(); });
33 addAlias("surface", "interface");
34 addDeprecatedAlias("surface", "Surf");
35 addDeprecatedAlias("surface", "surf");
36 reg("edge", []() { return new EdgeKinetics(); });
37 addDeprecatedAlias("edge", "Edge");
38}
39
40KineticsFactory* KineticsFactory::factory() {
41 std::unique_lock<std::mutex> lock(kinetics_mutex);
42 if (!s_factory) {
43 s_factory = new KineticsFactory;
44 }
45 return s_factory;
46}
47
49 std::unique_lock<std::mutex> lock(kinetics_mutex);
50 delete s_factory;
51 s_factory = 0;
52}
53
55{
56 return create(toLowerCopy(model));
57}
58
59shared_ptr<Kinetics> newKinetics(const string& model)
60{
61 shared_ptr<Kinetics> kin(KineticsFactory::factory()->newKinetics(model));
62 return kin;
63}
64
65shared_ptr<Kinetics> newKinetics(const vector<shared_ptr<ThermoPhase>>& phases,
66 const AnyMap& phaseNode,
67 const AnyMap& rootNode,
68 shared_ptr<Solution> soln)
69{
70 string kinType = phaseNode.getString("kinetics", "none");
71 kinType = KineticsFactory::factory()->canonicalize(kinType);
72 if (kinType == "none") {
73 // determine phase with minimum number of dimensions
74 size_t nDim = 3;
75 for (auto& phase : phases) {
76 nDim = std::min(phase->nDim(), nDim);
77 }
78 // change kinetics type as necessary
79 if (nDim == 2) {
80 kinType = "surface";
81 } else if (nDim == 1) {
82 kinType = "edge";
83 }
84 }
85
86 shared_ptr<Kinetics> kin(KineticsFactory::factory()->newKinetics(kinType));
87 if (soln) {
88 soln->setKinetics(kin);
89 }
90 for (auto& phase : phases) {
91 kin->addThermo(phase);
92 }
93 kin->init();
94 addReactions(*kin, phaseNode, rootNode);
95 return kin;
96}
97
98shared_ptr<Kinetics> newKinetics(const vector<shared_ptr<ThermoPhase>>& phases,
99 const string& filename)
100{
101 string reaction_phase = phases.at(0)->name();
102 AnyMap root = AnyMap::fromYamlFile(filename);
103 AnyMap& phaseNode = root["phases"].getMapWhere("name", reaction_phase);
104 return newKinetics(phases, phaseNode, root);
105}
106
107void addReactions(Kinetics& kin, const AnyMap& phaseNode, const AnyMap& rootNode)
108{
110 phaseNode.getBool("skip-undeclared-third-bodies", false));
112 phaseNode.getString("explicit-third-body-duplicates", "warn"));
113
114 loadExtensions(rootNode);
115
116 // Find sections containing reactions to add
117 vector<string> sections, rules;
118
119 if (phaseNode.hasKey("reactions")) {
120 const auto& reactionsNode = phaseNode.at("reactions");
121 if (reactionsNode.is<string>()) {
122 if (rootNode.hasKey("reactions")) {
123 // Specification of the rule for adding species from the default
124 // 'reactions' section, if it exists
125 sections.push_back("reactions");
126 rules.push_back(reactionsNode.asString());
127 } else if (reactionsNode.asString() != "none") {
128 throw InputFileError("addReactions", reactionsNode,
129 "Phase entry implies existence of 'reactions' section "
130 "which does not exist in the current input file.");
131 }
132 } else if (reactionsNode.is<vector<string>>()) {
133 // List of sections from which all species should be added
134 for (const auto& item : reactionsNode.as<vector<string>>()) {
135 sections.push_back(item);
136 rules.push_back("all");
137 }
138 } else if (reactionsNode.is<vector<AnyMap>>()) {
139 // Mapping of rules to apply for each specified section containing
140 // reactions
141 for (const auto& item : reactionsNode.as<vector<AnyMap>>()) {
142 sections.push_back(item.begin()->first);
143 rules.push_back(item.begin()->second.asString());
144 }
145 }
146 } else if (kin.kineticsType() != "none") {
147 if (!phaseNode.hasKey("kinetics")) {
148 // Do nothing - default surface or edge kinetics require separate detection
149 // while not adding reactions
150 } else if (rootNode.hasKey("reactions")) {
151 // Default behavior is to add all reactions from the 'reactions'
152 // section, if a 'kinetics' model has been specified
153 sections.push_back("reactions");
154 rules.push_back("all");
155 } else {
156 throw InputFileError("addReactions", phaseNode,
157 "Phase entry implies existence of 'reactions' section which "
158 "does not exist in the current input file. Add the field "
159 "'reactions: none' to the phase entry to specify a kinetics "
160 "model with no reactions.");
161 }
162 }
163
164 // Add reactions from each section
165 fmt::memory_buffer add_rxn_err;
166 for (size_t i = 0; i < sections.size(); i++) {
167 if (rules[i] == "all") {
168 kin.skipUndeclaredSpecies(false);
169 } else if (rules[i] == "declared-species") {
170 kin.skipUndeclaredSpecies(true);
171 } else if (rules[i] == "none") {
172 continue;
173 } else {
174 throw InputFileError("addReactions", phaseNode.at("reactions"),
175 "Unknown rule '{}' for adding species from the '{}' section.",
176 rules[i], sections[i]);
177 }
178 const auto& slash = boost::ifind_last(sections[i], "/");
179 if (slash) {
180 // specified section is in a different file
181 string fileName (sections[i].begin(), slash.begin());
182 string node(slash.end(), sections[i].end());
183 AnyMap reactions = AnyMap::fromYamlFile(fileName,
184 rootNode.getString("__file__", ""));
185 loadExtensions(reactions);
186 for (const auto& R : reactions[node].asVector<AnyMap>()) {
187 #ifdef NDEBUG
188 try {
189 kin.addReaction(newReaction(R, kin), false);
190 } catch (CanteraError& err) {
191 fmt_append(add_rxn_err, "{}", err.what());
192 }
193 #else
194 kin.addReaction(newReaction(R, kin), false);
195 #endif
196 }
197 } else {
198 // specified section is in the current file
199 for (const auto& R : rootNode.at(sections[i]).asVector<AnyMap>()) {
200 #ifdef NDEBUG
201 try {
202 kin.addReaction(newReaction(R, kin), false);
203 } catch (CanteraError& err) {
204 fmt_append(add_rxn_err, "{}", err.what());
205 }
206 #else
207 kin.addReaction(newReaction(R, kin), false);
208 #endif
209 }
210 }
211 }
212
213 if (add_rxn_err.size()) {
214 throw CanteraError("addReactions", to_string(add_rxn_err));
215 }
216 kin.checkDuplicates();
217 kin.resizeReactions();
218}
219
220}
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:431
bool hasKey(const string &key) const
Returns true if the map contains an item named key.
Definition AnyMap.cpp:1477
bool getBool(const string &key, bool default_) const
If key exists, return it as a bool, otherwise return default_.
Definition AnyMap.cpp:1575
const string & getString(const string &key, const string &default_) const
If key exists, return it as a string, otherwise return default_.
Definition AnyMap.cpp:1590
static AnyMap fromYamlFile(const string &name, const string &parent_name="")
Create an AnyMap from a YAML file.
Definition AnyMap.cpp:1841
const AnyValue & at(const string &key) const
Get the value of the item stored in key.
Definition AnyMap.cpp:1458
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:749
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:125
virtual void resizeReactions()
Finalize Kinetics object and associated objects.
Definition Kinetics.cpp:35
void setExplicitThirdBodyDuplicateHandling(const string &flag)
Specify how to handle duplicate third body reactions where one reaction has an explicit third body an...
Definition Kinetics.cpp:102
virtual string kineticsType() const
Identifies the Kinetics manager type.
Definition Kinetics.h:144
virtual pair< size_t, size_t > checkDuplicates(bool throw_err=true) const
Check for unmarked duplicate reactions and unmatched marked duplicates.
Definition Kinetics.cpp:114
virtual bool addReaction(shared_ptr< Reaction > r, bool resize=true)
Add a single reaction to the mechanism.
Definition Kinetics.cpp:621
void skipUndeclaredSpecies(bool skip)
Determine behavior when adding a new reaction that contains species not defined in any of the phases ...
Definition Kinetics.h:1326
void skipUndeclaredThirdBodies(bool skip)
Determine behavior when adding a new reaction that contains third-body efficiencies for species not d...
Definition Kinetics.h:1338
void fmt_append(fmt::memory_buffer &b, const std::string &tmpl, 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.
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:595
void loadExtensions(const AnyMap &node)
Load extensions providing user-defined models from the extensions section of the given node.
Definition global.cpp:179
unique_ptr< Reaction > newReaction(const string &type)
Create a new empty Reaction object.
Definition Reaction.cpp:846
Contains declarations for string manipulation functions within Cantera.