Cantera  3.2.0a4
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->setParameters(phaseNode);
94 kin->init();
95 addReactions(*kin, phaseNode, rootNode);
96 return kin;
97}
98
99shared_ptr<Kinetics> newKinetics(const vector<shared_ptr<ThermoPhase>>& phases,
100 const string& filename)
101{
102 string reaction_phase = phases.at(0)->name();
103 AnyMap root = AnyMap::fromYamlFile(filename);
104 AnyMap& phaseNode = root["phases"].getMapWhere("name", reaction_phase);
105 return newKinetics(phases, phaseNode, root);
106}
107
108void addReactions(Kinetics& kin, const AnyMap& phaseNode, const AnyMap& rootNode)
109{
110 loadExtensions(rootNode);
111
112 // Find sections containing reactions to add
113 vector<string> sections, rules;
114
115 if (phaseNode.hasKey("reactions")) {
116 const auto& reactionsNode = phaseNode.at("reactions");
117 if (reactionsNode.is<string>()) {
118 if (rootNode.hasKey("reactions")) {
119 // Specification of the rule for adding species from the default
120 // 'reactions' section, if it exists
121 sections.push_back("reactions");
122 rules.push_back(reactionsNode.asString());
123 } else if (reactionsNode.asString() != "none") {
124 throw InputFileError("addReactions", reactionsNode,
125 "Phase entry implies existence of 'reactions' section "
126 "which does not exist in the current input file.");
127 }
128 } else if (reactionsNode.is<vector<string>>()) {
129 // List of sections from which all species should be added
130 for (const auto& item : reactionsNode.as<vector<string>>()) {
131 sections.push_back(item);
132 rules.push_back("all");
133 }
134 } else if (reactionsNode.is<vector<AnyMap>>()) {
135 // Mapping of rules to apply for each specified section containing
136 // reactions
137 for (const auto& item : reactionsNode.as<vector<AnyMap>>()) {
138 sections.push_back(item.begin()->first);
139 rules.push_back(item.begin()->second.asString());
140 }
141 }
142 } else if (kin.kineticsType() != "none") {
143 if (!phaseNode.hasKey("kinetics")) {
144 // Do nothing - default surface or edge kinetics require separate detection
145 // while not adding reactions
146 } else if (rootNode.hasKey("reactions")) {
147 // Default behavior is to add all reactions from the 'reactions'
148 // section, if a 'kinetics' model has been specified
149 sections.push_back("reactions");
150 rules.push_back("all");
151 } else {
152 throw InputFileError("addReactions", phaseNode,
153 "Phase entry implies existence of 'reactions' section which "
154 "does not exist in the current input file. Add the field "
155 "'reactions: none' to the phase entry to specify a kinetics "
156 "model with no reactions.");
157 }
158 }
159
160 // Add reactions from each section
161 fmt::memory_buffer add_rxn_err;
162 for (size_t i = 0; i < sections.size(); i++) {
163 if (rules[i] == "all") {
164 kin.skipUndeclaredSpecies(false);
165 } else if (rules[i] == "declared-species") {
166 kin.skipUndeclaredSpecies(true);
167 } else if (rules[i] == "none") {
168 continue;
169 } else {
170 throw InputFileError("addReactions", phaseNode.at("reactions"),
171 "Unknown rule '{}' for adding species from the '{}' section.",
172 rules[i], sections[i]);
173 }
174 const auto& slash = boost::ifind_last(sections[i], "/");
175 if (slash) {
176 // specified section is in a different file
177 string fileName (sections[i].begin(), slash.begin());
178 string node(slash.end(), sections[i].end());
179 AnyMap reactions = AnyMap::fromYamlFile(fileName,
180 rootNode.getString("__file__", ""));
181 loadExtensions(reactions);
182 for (const auto& R : reactions[node].asVector<AnyMap>()) {
183 #ifdef NDEBUG
184 try {
185 kin.addReaction(newReaction(R, kin), false);
186 } catch (CanteraError& err) {
187 fmt_append(add_rxn_err, "{}", err.what());
188 }
189 #else
190 kin.addReaction(newReaction(R, kin), false);
191 #endif
192 }
193 } else {
194 // specified section is in the current file
195 for (const auto& R : rootNode.at(sections[i]).asVector<AnyMap>()) {
196 #ifdef NDEBUG
197 try {
198 kin.addReaction(newReaction(R, kin), false);
199 } catch (CanteraError& err) {
200 fmt_append(add_rxn_err, "{}", err.what());
201 }
202 #else
203 kin.addReaction(newReaction(R, kin), false);
204 #endif
205 }
206 }
207 }
208
209 if (add_rxn_err.size()) {
210 throw CanteraError("addReactions", to_string(add_rxn_err));
211 }
212 // Hidden flag possibly set by Kinetics::clone
213 bool fixDuplicates = phaseNode.getBool("__fix-duplicate-reactions__", false);
214 kin.checkDuplicates(!fixDuplicates, fixDuplicates);
215 kin.resizeReactions();
216}
217
218}
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:126
virtual void resizeReactions()
Finalize Kinetics object and associated objects.
Definition Kinetics.cpp:49
virtual string kineticsType() const
Identifies the Kinetics manager type.
Definition Kinetics.h:153
virtual pair< size_t, size_t > checkDuplicates(bool throw_err=true, bool fix=false)
Check for unmarked duplicate reactions and unmatched marked duplicates.
Definition Kinetics.cpp:119
virtual bool addReaction(shared_ptr< Reaction > r, bool resize=true)
Add a single reaction to the mechanism.
Definition Kinetics.cpp:675
void skipUndeclaredSpecies(bool skip)
Determine behavior when adding a new reaction that contains species not defined in any of the phases ...
Definition Kinetics.h:1336
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:195
unique_ptr< Reaction > newReaction(const string &type)
Create a new empty Reaction object.
Definition Reaction.cpp:885
Contains declarations for string manipulation functions within Cantera.