https://mooseframework.inl.gov
AddCoupledEqSpeciesAction.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 #include "Parser.h"
12 #include "FEProblem.h"
13 #include "Factory.h"
14 #include "MooseError.h"
15 
16 #include "libmesh/string_to_enum.h"
17 
18 // Regular expression includes
19 #include "pcrecpp.h"
20 
21 registerMooseAction("ChemicalReactionsApp", AddCoupledEqSpeciesAction, "add_kernel");
22 
23 registerMooseAction("ChemicalReactionsApp", AddCoupledEqSpeciesAction, "add_aux_kernel");
24 
27 {
29  params.addRequiredParam<std::vector<NonlinearVariableName>>(
30  "primary_species", "The list of primary variables to add");
31  params.addParam<std::vector<AuxVariableName>>(
32  "secondary_species", "The list of aqueous equilibrium species to be output as aux variables");
33  params.addParam<std::string>("reactions", "The list of aqueous equilibrium reactions");
34  params.addParam<std::vector<VariableName>>("pressure", {}, "Pressure variable");
35  RealVectorValue g(0, 0, 0);
36  params.addParam<RealVectorValue>("gravity", g, "Gravity vector (default is (0, 0, 0))");
37  params.addClassDescription("Adds coupled equilibrium Kernels and AuxKernels for primary species");
38  return params;
39 }
40 
42  : Action(params),
43  _primary_species(getParam<std::vector<NonlinearVariableName>>("primary_species")),
44  _secondary_species(getParam<std::vector<AuxVariableName>>("secondary_species")),
45  _weights(_primary_species.size()),
46  _primary_participation(_primary_species.size()),
47  _sto_u(_primary_species.size()),
48  _sto_v(_primary_species.size()),
49  _coupled_v(_primary_species.size()),
50  _input_reactions(getParam<std::string>("reactions")),
51  _pressure_var(getParam<std::vector<VariableName>>("pressure")),
52  _gravity(getParam<RealVectorValue>("gravity"))
53 {
54  // Parse the aqueous equilibrium reactions
55  pcrecpp::RE re_reaction(
56  "(.+?)" // single reaction (any character until the equilibrium coefficient appears)
57  "\\s" // word boundary
58  "(" // start capture
59  "-?" // optional minus sign
60  "\\d+(?:\\.\\d*)?" // digits followed by optional decimal and more digits
61  ")" // end capture
62  "\\b" // word boundary
63  "(?:,?\\s*|$)" // optional comma or end of string
64  ,
65  pcrecpp::RE_Options().set_extended(true));
66 
67  pcrecpp::RE re_terms("(\\S+)");
68  pcrecpp::RE re_coeff_and_species("(?: \\(? (.*?) \\)? )" // match the leading coefficent
69  "([A-Za-z].*)" // match the species
70  ,
71  pcrecpp::RE_Options().set_extended(true));
72 
73  pcrecpp::StringPiece input(_input_reactions);
74 
75  pcrecpp::StringPiece single_reaction, term;
76  std::string single_reaction_str;
77  Real eq_coeff;
78 
79  // Parse reaction network to extract each individual reaction
80  while (re_reaction.FindAndConsume(&input, &single_reaction_str, &eq_coeff))
81  {
82  _reactions.push_back(single_reaction_str);
83  _eq_const.push_back(eq_coeff);
84  }
85 
86  _num_reactions = _reactions.size();
87 
88  if (_num_reactions == 0)
89  mooseError("No equilibrium reaction provided!");
90 
91  if (_pars.isParamValid("secondary_species"))
92  for (unsigned int k = 0; k < _secondary_species.size(); ++k)
94 
95  // Start parsing each reaction
96  for (unsigned int i = 0; i < _num_reactions; ++i)
97  {
98  single_reaction = _reactions[i];
99 
100  // Capture all of the terms
101  std::string species, coeff_str;
102  Real coeff;
103  int sign = 1;
104  bool secondary = false;
105 
106  std::vector<Real> local_stos;
107  std::vector<VariableName> local_species_list;
108 
109  // Find every single term in this reaction (species and operators)
110  while (re_terms.FindAndConsume(&single_reaction, &term))
111  {
112  // Separating the stoichiometric coefficients from species
113  if (re_coeff_and_species.PartialMatch(term, &coeff_str, &species))
114  {
115  if (coeff_str.length())
116  coeff = std::stod(coeff_str);
117  else
118  coeff = 1.0;
119 
120  coeff *= sign;
121 
122  if (secondary)
123  _eq_species.push_back(species);
124  else
125  {
126  local_stos.push_back(coeff);
127  local_species_list.push_back(species);
128  }
129  }
130  // Finding the operators and assign value of -1.0 to "-" sign
131  else if (term == "+" || term == "=" || term == "-")
132  {
133  if (term == "-")
134  {
135  sign = -1;
136  term = "+";
137  }
138  else
139  sign = 1;
140 
141  if (term == "=")
142  secondary = true;
143  }
144  else
145  mooseError("Error parsing term: ", term.as_string());
146  }
147 
148  _stos.push_back(local_stos);
149  _primary_species_involved.push_back(local_species_list);
150  }
151 
152  // Start picking out primary species and coupled primary species and assigning
153  // corresponding stoichiomentric coefficients
154  for (unsigned int i = 0; i < _primary_species.size(); ++i)
155  {
156  _sto_u[i].resize(_num_reactions, 0.0);
157  _sto_v[i].resize(_num_reactions);
158  _coupled_v[i].resize(_num_reactions);
159  _weights[i].resize(_num_reactions, 0.0);
160 
161  _primary_participation[i].resize(_num_reactions, false);
162  for (unsigned int j = 0; j < _num_reactions; ++j)
163  {
164  for (unsigned int k = 0; k < _primary_species_involved[j].size(); ++k)
166  _primary_participation[i][j] = true;
167 
168  if (_primary_participation[i][j])
169  {
170  for (unsigned int k = 0; k < _primary_species_involved[j].size(); ++k)
171  {
173  {
174  _sto_u[i][j] = _stos[j][k];
175  _weights[i][j] = _stos[j][k];
176  }
177  else
178  {
179  _sto_v[i][j].push_back(_stos[j][k]);
180  _coupled_v[i][j].push_back(_primary_species_involved[j][k]);
181  }
182  }
183  }
184  }
185  }
186 
187  // Print out details of the equilibrium reactions to the console
188  _console << "Aqueous equilibrium reactions:\n";
189  for (unsigned int i = 0; i < _num_reactions; ++i)
190  _console << " Reaction " << i + 1 << ": " << _reactions[i] << ", log10(Keq) = " << _eq_const[i]
191  << "\n";
192  _console << std::endl;
193 }
194 
195 void
197 {
198  if (_current_task == "add_kernel")
199  {
200  // Add Kernels for each primary species
201  for (unsigned int i = 0; i < _primary_species.size(); ++i)
202  {
203  for (unsigned int j = 0; j < _num_reactions; ++j)
204  {
205  if (_primary_participation[i][j])
206  {
207  InputParameters params_sub = _factory.getValidParams("CoupledBEEquilibriumSub");
208  params_sub.set<NonlinearVariableName>("variable") = _primary_species[i];
209  params_sub.set<Real>("weight") = _weights[i][j];
210  params_sub.defaultCoupledValue("log_k", _eq_const[j]);
211  params_sub.set<Real>("sto_u") = _sto_u[i][j];
212  params_sub.set<std::vector<Real>>("sto_v") = _sto_v[i][j];
213  params_sub.set<std::vector<VariableName>>("v") = _coupled_v[i][j];
214  _problem->addKernel("CoupledBEEquilibriumSub",
215  _primary_species[i] + "_" + _eq_species[j] + "_sub",
216  params_sub);
217 
218  InputParameters params_cd = _factory.getValidParams("CoupledDiffusionReactionSub");
219  params_cd.set<NonlinearVariableName>("variable") = _primary_species[i];
220  params_cd.set<Real>("weight") = _weights[i][j];
221  params_cd.defaultCoupledValue("log_k", _eq_const[j]);
222  params_cd.set<Real>("sto_u") = _sto_u[i][j];
223  params_cd.set<std::vector<Real>>("sto_v") = _sto_v[i][j];
224  params_cd.set<std::vector<VariableName>>("v") = _coupled_v[i][j];
225  _problem->addKernel("CoupledDiffusionReactionSub",
226  _primary_species[i] + "_" + _eq_species[j] + "_cd",
227  params_cd);
228 
229  // If pressure is coupled, add a CoupledConvectionReactionSub Kernel as well
230  if (_pars.isParamValid("pressure"))
231  {
232  InputParameters params_conv = _factory.getValidParams("CoupledConvectionReactionSub");
233  params_conv.set<NonlinearVariableName>("variable") = _primary_species[i];
234  params_conv.set<Real>("weight") = _weights[i][j];
235  params_conv.defaultCoupledValue("log_k", _eq_const[j]);
236  params_conv.set<Real>("sto_u") = _sto_u[i][j];
237  params_conv.set<std::vector<Real>>("sto_v") = _sto_v[i][j];
238  params_conv.set<std::vector<VariableName>>("v") = _coupled_v[i][j];
239  params_conv.set<std::vector<VariableName>>("p") = _pressure_var;
240  params_conv.set<RealVectorValue>("gravity") = _gravity;
241  _problem->addKernel("CoupledConvectionReactionSub",
242  _primary_species[i] + "_" + _eq_species[j] + "_conv",
243  params_conv);
244  }
245  }
246  }
247  }
248  }
249 
250  if (_current_task == "add_aux_kernel")
251  {
252  // Add AqueousEquilibriumRxnAux AuxKernels for equilibrium species
253  for (unsigned int j = 0; j < _num_reactions; ++j)
254  {
255  if (_aux_species.find(_eq_species[j]) != _aux_species.end())
256  {
257  InputParameters params_eq = _factory.getValidParams("AqueousEquilibriumRxnAux");
258  params_eq.set<AuxVariableName>("variable") = _eq_species[j];
259  params_eq.defaultCoupledValue("log_k", _eq_const[j]);
260  params_eq.set<std::vector<Real>>("sto_v") = _stos[j];
261  params_eq.set<std::vector<VariableName>>("v") = _primary_species_involved[j];
262  _problem->addAuxKernel("AqueousEquilibriumRxnAux", "aux_" + _eq_species[j], params_eq);
263  }
264  }
265  }
266 }
AddCoupledEqSpeciesAction(const InputParameters &params)
std::vector< Real > _eq_const
Equilibrium constants for each reaction.
const std::vector< AuxVariableName > _secondary_species
Secondary species added as AuxVariables.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
std::vector< VariableName > _eq_species
Equilibrium species.
InputParameters getValidParams(const std::string &name) const
std::vector< std::vector< bool > > _primary_participation
Participation of primary species in each reaction.
void addRequiredParam(const std::string &name, const std::string &doc_string)
std::vector< std::string > _reactions
Vector of parsed reactions.
Factory & _factory
std::vector< std::vector< Real > > _sto_u
Stoichiometric coefficients of primary variables in each reaction.
static InputParameters validParams()
Real defaultCoupledValue(const std::string &coupling_name, unsigned int i=0) const
T sign(T x)
const std::string & _current_task
const RealVectorValue _gravity
Gravity (default is (0, 0, 0))
static InputParameters validParams()
std::set< std::string > _aux_species
Set of auxillary species.
std::vector< std::vector< Real > > _weights
Weight of each primary species in each reaction.
std::vector< std::vector< std::vector< Real > > > _sto_v
Stoichiometric coefficients of coupled primary variables in each reaction.
std::string _input_reactions
Reaction network read from input file.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::vector< NonlinearVariableName > _primary_species
Basis set of primary species.
std::vector< std::vector< Real > > _stos
Stoichiometric coefficients for each primary species in each reaction.
registerMooseAction("ChemicalReactionsApp", AddCoupledEqSpeciesAction, "add_kernel")
void mooseError(Args &&... args) const
const InputParameters & _pars
void addClassDescription(const std::string &doc_string)
std::shared_ptr< FEProblemBase > & _problem
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _num_reactions
Number of reactions.
const ConsoleStream _console
std::vector< std::vector< std::vector< VariableName > > > _coupled_v
Coupled primary species for each reaction.
static const std::string k
Definition: NS.h:130
std::vector< std::vector< VariableName > > _primary_species_involved
Primary species involved in the ith equilibrium reaction.
const std::vector< VariableName > _pressure_var
Pressure variable.
bool isParamValid(const std::string &name) const