Cantera  3.1.0a1
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));
111
112 loadExtensions(rootNode);
113
114 // Find sections containing reactions to add
115 vector<string> sections, rules;
116
117 if (phaseNode.hasKey("reactions")) {
118 const auto& reactionsNode = phaseNode.at("reactions");
119 if (reactionsNode.is<string>()) {
120 if (rootNode.hasKey("reactions")) {
121 // Specification of the rule for adding species from the default
122 // 'reactions' section, if it exists
123 sections.push_back("reactions");
124 rules.push_back(reactionsNode.asString());
125 } else if (reactionsNode.asString() != "none") {
126 throw InputFileError("addReactions", reactionsNode,
127 "Phase entry implies existence of 'reactions' section "
128 "which does not exist in the current input file.");
129 }
130 } else if (reactionsNode.is<vector<string>>()) {
131 // List of sections from which all species should be added
132 for (const auto& item : reactionsNode.as<vector<string>>()) {
133 sections.push_back(item);
134 rules.push_back("all");
135 }
136 } else if (reactionsNode.is<vector<AnyMap>>()) {
137 // Mapping of rules to apply for each specified section containing
138 // reactions
139 for (const auto& item : reactionsNode.as<vector<AnyMap>>()) {
140 sections.push_back(item.begin()->first);
141 rules.push_back(item.begin()->second.asString());
142 }
143 }
144 } else if (kin.kineticsType() != "none") {
145 if (!phaseNode.hasKey("kinetics")) {
146 // Do nothing - default surface or edge kinetics require separate detection
147 // while not adding reactions
148 } else if (rootNode.hasKey("reactions")) {
149 // Default behavior is to add all reactions from the 'reactions'
150 // section, if a 'kinetics' model has been specified
151 sections.push_back("reactions");
152 rules.push_back("all");
153 } else {
154 throw InputFileError("addReactions", phaseNode,
155 "Phase entry implies existence of 'reactions' section which "
156 "does not exist in the current input file. Add the field "
157 "'reactions: none' to the phase entry to specify a kinetics "
158 "model with no reactions.");
159 }
160 }
161
162 // Add reactions from each section
163 fmt::memory_buffer add_rxn_err;
164 for (size_t i = 0; i < sections.size(); i++) {
165 if (rules[i] == "all") {
166 kin.skipUndeclaredSpecies(false);
167 } else if (rules[i] == "declared-species") {
168 kin.skipUndeclaredSpecies(true);
169 } else if (rules[i] == "none") {
170 continue;
171 } else {
172 throw InputFileError("addReactions", phaseNode.at("reactions"),
173 "Unknown rule '{}' for adding species from the '{}' section.",
174 rules[i], sections[i]);
175 }
176 const auto& slash = boost::ifind_last(sections[i], "/");
177 if (slash) {
178 // specified section is in a different file
179 string fileName (sections[i].begin(), slash.begin());
180 string node(slash.end(), sections[i].end());
181 AnyMap reactions = AnyMap::fromYamlFile(fileName,
182 rootNode.getString("__file__", ""));
183 loadExtensions(reactions);
184 for (const auto& R : reactions[node].asVector<AnyMap>()) {
185 #ifdef NDEBUG
186 try {
187 kin.addReaction(newReaction(R, kin), false);
188 } catch (CanteraError& err) {
189 fmt_append(add_rxn_err, "{}", err.what());
190 }
191 #else
192 kin.addReaction(newReaction(R, kin), false);
193 #endif
194 }
195 } else {
196 // specified section is in the current file
197 for (const auto& R : rootNode.at(sections[i]).asVector<AnyMap>()) {
198 #ifdef NDEBUG
199 try {
200 kin.addReaction(newReaction(R, kin), false);
201 } catch (CanteraError& err) {
202 fmt_append(add_rxn_err, "{}", err.what());
203 }
204 #else
205 kin.addReaction(newReaction(R, kin), false);
206 #endif
207 }
208 }
209 }
210
211 if (add_rxn_err.size()) {
212 throw CanteraError("addReactions", to_string(add_rxn_err));
213 }
214 kin.checkDuplicates();
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: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:125
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: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:102
virtual bool addReaction(shared_ptr< Reaction > r, bool resize=true)
Add a single reaction to the mechanism.
Definition Kinetics.cpp:565
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, 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:564
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:832
Contains declarations for string manipulation functions within Cantera.