13 #include "libmesh/utility.h" 27 Reactions <- (_ Reaction _ Newline?)* _ 28 Reaction <- TermList _ '->' _ TermList _ Metadata? 29 TermList <- Term (_ Term)* 30 Term <- Coefficient? Species 32 Float <- [+-]? (_)? ([0-9]+)? ('.' [0-9]+)? 33 Species <- BaseSpecies State? Charge? 34 BaseSpecies <- [a-zA-Z][a-zA-Z0-9_]* 35 State <- '(' [a-z]{1,3} ')' 36 Charge <- ('^'? [0-9]* [+-]) 37 Metadata <- '[' _ Pair (_ ',' _ Pair)* _ ']' 38 Pair <- Key _ '=' _ Value 39 Key <- [A-Za-z_][A-Za-z0-9_]* 40 Value <- [A-Za-z0-9_.-]+ 44 mooseAssert(parser, "Failed to build parser");
47 parser[
"Reactions"] = [](
const SemanticValues & vs)
49 std::vector<Reaction> reactions;
50 for (
const auto &
v : vs)
54 reactions.push_back(std::any_cast<Reaction>(
v));
60 parser[
"Float"] = [](
const SemanticValues & vs)
63 std::string vs_str = std::string(std::any_cast<std::string_view>(vs.token()));
64 vs_str.erase(std::remove(vs_str.begin(), vs_str.end(),
' '), vs_str.end());
67 else if (vs_str ==
"+" || vs_str ==
"")
70 return std::stod(std::string(vs_str));
73 parser[
"Coefficient"] = [](
const SemanticValues & vs) {
return std::any_cast<
double>(vs[0]); };
75 parser[
"BaseSpecies"] = [](
const SemanticValues & vs) {
return vs.token(); };
77 parser[
"State"] = [](
const SemanticValues & vs) {
return vs.token(); };
79 parser[
"Charge"] = [](
const SemanticValues & vs) {
return vs.token(); };
81 parser[
"Species"] = [](
const SemanticValues & vs)
83 std::string base = std::string(std::any_cast<std::string_view>(vs[0]));
84 std::optional<std::string> state;
85 std::optional<std::string> charge;
90 for (
size_t i = 1; i < vs.size(); ++i)
91 if (vs[i].type() ==
typeid(std::string_view))
93 std::string val = std::string(std::any_cast<std::string_view>(vs[i]));
94 if (val.front() ==
'(' && val.back() ==
')')
101 return Term{1.0, base, state, charge};
104 parser[
"Term"] = [](
const SemanticValues & vs)
106 mooseAssert(vs.size() <= 2,
"Should only have a coefficient and a species");
109 double coeff = std::any_cast<
double>(vs[0]);
110 Term term = std::any_cast<
Term>(vs[1]);
115 return std::any_cast<
Term>(vs[0]);
118 parser[
"TermList"] = [](
const SemanticValues & vs)
121 for (
const auto &
v : vs)
124 if (
v.type() ==
typeid(
Term))
125 terms.push_back(std::any_cast<Term>(
v));
127 else if (
v.type() ==
typeid(std::vector<Term>))
129 const auto & more = std::any_cast<std::vector<Term>>(
v);
130 terms.insert(terms.end(), more.begin(), more.end());
137 parser[
"Key"] = [](
const SemanticValues & vs) {
return vs.token(); };
139 parser[
"Value"] = [](
const SemanticValues & vs) {
return vs.token(); };
141 parser[
"Pair"] = [](
const SemanticValues & vs)
143 mooseAssert(vs.size() == 2,
"Metadata entry should have exactly one key and one value");
144 return std::make_pair(std::string(std::any_cast<std::string_view>(vs[0])),
145 std::string(std::any_cast<std::string_view>(vs[1])));
148 parser[
"Metadata"] = [](
const SemanticValues & vs)
151 for (
const auto &
v : vs)
153 if (
v.type() ==
typeid(std::pair<std::string, std::string>))
155 const auto & [
k, val] = std::any_cast<std::pair<std::string, std::string>>(
v);
158 else if (
v.type() ==
typeid(std::vector<std::pair<std::string, std::string>>))
160 const auto & pairs = std::any_cast<std::vector<std::pair<std::string, std::string>>>(
v);
161 for (
const auto & [
k, val] : pairs)
168 parser[
"Reaction"] = [](
const SemanticValues & vs)
171 if (vs.size() != 2 && vs.size() != 3)
172 mooseError(
"Reaction failed to read as 'reactors -> products [metadata]");
176 r.
metadata = std::any_cast<Metadata>(vs[2]);
180 parser.enable_packrat_parsing();
182 std::vector<Reaction> reactions;
183 if (!parser.parse(reaction_network_string, reactions))
189 for (
size_t i = 0; i < reactions.size(); ++i)
191 const auto & r = reactions[i];
192 Moose::out <<
"Reaction " << i + 1 <<
":\n";
200 std::vector<VariableName>
203 std::vector<VariableName> species;
205 species.push_back(term.species + term.state.value_or(
"") + term.charge.value_or(
""));
207 species.push_back(term.species + term.state.value_or(
"") + term.charge.value_or(
""));
211 std::vector<VariableName>
214 std::vector<VariableName> species;
215 std::set<Term> terms_gathered;
217 if (terms_gathered.find(term) == terms_gathered.end())
219 species.push_back(term.species + term.state.value_or(
"") + term.charge.value_or(
""));
220 terms_gathered.insert(term);
223 if (terms_gathered.find(term) == terms_gathered.end())
225 species.push_back(term.species + term.state.value_or(
"") + term.charge.value_or(
""));
226 terms_gathered.insert(term);
234 std::vector<Real> coeffs;
236 coeffs.push_back(term.coefficient);
238 coeffs.push_back(term.coefficient);
242 std::map<VariableName, Real>
245 std::map<VariableName, Real> terms_gathered;
248 const auto term_str = term.species + term.state.value_or(
"") + term.charge.value_or(
"");
249 terms_gathered[term_str] -= term.coefficient;
253 const auto term_str = term.species + term.state.value_or(
"") + term.charge.value_or(
"");
254 terms_gathered[term_str] += term.coefficient;
256 return terms_gathered;
259 std::vector<VariableName>
262 std::vector<VariableName> species;
264 species.push_back(term.species + term.state.value_or(
"") + term.charge.value_or(
""));
268 std::vector<VariableName>
271 std::vector<VariableName> species;
272 std::set<Term> terms_gathered;
274 if (terms_gathered.find(term) == terms_gathered.end())
276 species.push_back(term.species + term.state.value_or(
"") + term.charge.value_or(
""));
277 terms_gathered.insert(term);
282 std::vector<std::string>
285 std::vector<std::string> species;
287 species.push_back(term.species + term.state.value_or(
"") + term.charge.value_or(
""));
291 std::vector<std::string>
294 std::vector<std::string> species;
295 std::set<Term> terms_gathered;
297 if (terms_gathered.find(term) == terms_gathered.end())
299 species.push_back(term.species + term.state.value_or(
"") + term.charge.value_or(
""));
300 terms_gathered.insert(term);
307 Reaction::hasMetaData<Real>(
const std::string & key)
const 309 return metadata.count(key) && MooseUtils::isFloat(libmesh_map_find(metadata, key));
312 template <
typename T>
316 mooseError(
"Has metadata not implemented for type " + MooseUtils::prettyCppType<T>());
331 return libmesh_map_find(
metadata, key);
333 mooseError(
"MetaData item '" + key +
"' was not found in reaction:\n" +
345 std::string str_out =
" Reactants:\n";
348 str_out +=
" " + std::to_string(t.coefficient) +
" " + t.species;
350 str_out += t.charge.value();
352 str_out +=
" (" + t.state.value() +
")";
355 str_out +=
" Products:\n";
358 str_out +=
" " + std::to_string(t.coefficient) +
" " + t.species;
360 str_out += t.charge.value();
362 str_out +=
" (" + t.state.value() +
")";
367 str_out +=
" Metadata:\n";
369 str_out +=
" " +
k +
" = " +
v +
"\n";
std::vector< Term > TermList
std::map< std::string, std::string > Metadata
void mooseError(Args &&... args)
std::vector< std::string > getProductSpecies() const
Get all product species involved in the reaction (on RHS)
const std::string & getMetaData(const std::string &key) const
Get the metadata from the reaction.
std::vector< VariableName > getReactantSpecies() const
Get all reactant species involved in the reaction (on LHS)
std::vector< Real > getStoichiometricCoefficients() const
Get the stoeichiometric coefficients for each species in the reaction The sign used matches the sign ...
std::vector< VariableName > getSpecies() const
Get all species involved in the reaction.
std::string stringify(const T &t)
std::vector< std::string > getUniqueProductSpecies() const
Get all unique product species involved in the reaction (on RHS)
std::map< VariableName, Real > getUniqueStoichiometricCoefficients() const
Get the stoeichiometric coefficients for each unique species in the reaction Note: if a species is bo...
std::vector< Reaction > parseReactionNetwork(const std::string &reaction_network_string, bool output_to_cout)
Parses the reaction network from a string form to a vector a Reaction.
std::vector< VariableName > getUniqueSpecies() const
Get all unique species involved in the reaction Note: a species will only appear once even if both a ...
std::vector< VariableName > getUniqueReactantSpecies() const
Get all unique reactant species involved in the reaction (on LHS)
std::string stringify(const ReactionNetworkUtils::Reaction &t)
static const std::string k
bool hasMetaData(const std::string &key) const
Whether the reaction has the metadata with the given type.