https://mooseframework.inl.gov
AqueousReactionsEquilibriumPhysics.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 "ReactionNetworkUtils.h"
12 
13 // Register the actions for the objects actually used
14 registerMooseAction("ChemicalReactionsApp", AqueousReactionsEquilibriumPhysics, "add_kernel");
15 registerMooseAction("ChemicalReactionsApp", AqueousReactionsEquilibriumPhysics, "add_aux_kernel");
17 
20 {
22  params.addClassDescription("Forms the equations for the chemical reaction networks in a fluid"
23  " medium using a continuous Galerkin finite element discretization.");
24 
25  // Rename parameters to match the previously existing actions for AqueousEquilibrium
26  // ReactionNetwork
27  params.renameParam("solver_variables", "primary_species", "The list of primary species to add");
28  params.renameParam(
29  "auxiliary_variables", "secondary_species", "The list of secondary species to add");
30  params.renameParam(
31  "variable_order", "order", "Order of both the primary and secondary species variables");
32  params.renameParam("equation_scaling", "scaling", "");
33  params.setDocString("reactions", "The list of equilibrium reactions occuring in the fluid");
34 
35  // To preserve the legacy option to perform Darcy-advection with AqueousEquilibrium
36  // ReactionNetwork
37  params.addParam<bool>("add_darcy_advection_term",
38  false,
39  "Whether to add an advection term using the Darcy equation to compute the "
40  "advecting velocity");
41  params.addParam<std::vector<VariableName>>(
42  "pressure", {}, "Pressure variable (for Darcy advection)");
43  params.addParam<RealVectorValue>(
44  "gravity", RealVectorValue(0, 0, -9.81), "Gravity vector (for Darcy advection)");
45 
46  return params;
47 }
48 
50  const InputParameters & parameters)
51  : ReactionNetworkPhysicsBase(parameters),
52  _sto_u(_num_solver_species),
53  _sto_v(_num_solver_species),
54  _weights(_num_solver_species),
55  _primary_participation(_num_solver_species),
56  _coupled_v(_num_solver_species),
57  _pressure_var(getParam<std::vector<VariableName>>("pressure"))
58 {
59  // Further parse the reactions
60  // Keeping the data in these vectors of vectors as an intermediate processing step
61  for (const auto i : index_range(_reactions))
62  {
63  const auto & reaction = _reactions[i];
64  _solver_species_involved.push_back(reaction.getReactantSpecies());
65  _stos.push_back(reaction.getStoichiometricCoefficients());
66 
67  // There are only one equilibrium species. We look at the output species
68  const auto & products = reaction.getProductSpecies();
69  if (products.size() != 1)
70  mooseError("Reaction:\n" + _reactions_input[i] +
71  "\n has more than one product species (on the RHS). This Physics only supports "
72  "one product species per reaction");
73  _eq_species.push_back(products[0]);
74 
75  // If user passed log_K use that, else use K
76  if (reaction.hasMetaData<Real>("log10_K"))
77  _log_eq_const.push_back(std::stod(reaction.getMetaData("log10_K")));
78  else if (reaction.hasMetaData<Real>("K"))
79  _log_eq_const.push_back(std::log10(std::stod(reaction.getMetaData("K"))));
80  else if (reaction.hasMetaData("K") || reaction.hasMetaData("log10_K"))
81  paramError("reactions",
82  "Equilibrium constant species in square brackets must be specified as a float, "
83  "not a name");
84  else
85  paramError("reactions",
86  "Reaction: '" + _reactions_input[i] +
87  "'\n is missing an equilibrium constant [K=] or its logarithm [log10_K=] in "
88  "its metadata");
89  }
90 
91  // For each primary/solver species, we examine the reactions to get the coefficients
92  // and various constants
93  for (unsigned int i = 0; i < _solver_species.size(); ++i)
94  {
95  _sto_u[i].resize(_num_reactions, 0.0);
96  _sto_v[i].resize(_num_reactions);
97  _coupled_v[i].resize(_num_reactions);
98  _weights[i].resize(_num_reactions, 0.0);
99 
100  _primary_participation[i].resize(_num_reactions, false);
101  for (unsigned int j = 0; j < _num_reactions; ++j)
102  {
103  // Set the booleans for involvement in a reaction
104  for (unsigned int k = 0; k < _solver_species_involved[j].size(); ++k)
106  _primary_participation[i][j] = true;
107 
108  if (_primary_participation[i][j])
109  {
110  for (unsigned int k = 0; k < _solver_species_involved[j].size(); ++k)
111  {
112  // Re-sort the coefficients into a more convenient format
114  {
115  _sto_u[i][j] = _stos[j][k];
116  _weights[i][j] = _stos[j][k];
117  }
118  else
119  {
120  _sto_v[i][j].push_back(_stos[j][k]);
121  _coupled_v[i][j].push_back(_solver_species_involved[j][k]);
122  }
123  }
124  }
125  }
126  }
127 
128  // Parameter checks
129  checkSecondParamSetOnlyIfFirstOneTrue("add_darcy_advection_term", "pressure");
130  checkSecondParamSetOnlyIfFirstOneTrue("add_darcy_advection_term", "gravity");
131 }
132 
133 void
135 {
136  // Add Kernels for each primary species
137  // Note that the equations are on a per-species basis!
138  // So equations are organized differently than reactions
139  for (const auto i : index_range(_solver_species))
140  {
141  for (const auto j : make_range(_num_reactions))
142  {
143  if (_primary_participation[i][j])
144  {
145  {
146  InputParameters params_sub = _factory.getValidParams("CoupledBEEquilibriumSub");
147  assignBlocks(params_sub, _blocks);
148  params_sub.set<NonlinearVariableName>("variable") = _solver_species[i];
149  params_sub.set<Real>("weight") = _weights[i][j];
150  params_sub.defaultCoupledValue("log_k", _log_eq_const[j]);
151  params_sub.set<Real>("sto_u") = _sto_u[i][j];
152  params_sub.set<std::vector<Real>>("sto_v") = _sto_v[i][j];
153  params_sub.set<std::vector<VariableName>>("v") = _coupled_v[i][j];
154  _problem->addKernel("CoupledBEEquilibriumSub",
155  _solver_species[i] + "_" + _eq_species[j] + "_sub",
156  params_sub);
157  }
158 
159  {
160  InputParameters params_cd = _factory.getValidParams("CoupledDiffusionReactionSub");
161  assignBlocks(params_cd, _blocks);
162  params_cd.set<NonlinearVariableName>("variable") = _solver_species[i];
163  params_cd.set<Real>("weight") = _weights[i][j];
164  params_cd.defaultCoupledValue("log_k", _log_eq_const[j]);
165  params_cd.set<Real>("sto_u") = _sto_u[i][j];
166  params_cd.set<std::vector<Real>>("sto_v") = _sto_v[i][j];
167  params_cd.set<std::vector<VariableName>>("v") = _coupled_v[i][j];
168  _problem->addKernel("CoupledDiffusionReactionSub",
169  _solver_species[i] + "_" + _eq_species[j] + "_cd",
170  params_cd);
171  }
172 
173  // If pressure is coupled, add a CoupledConvectionReactionSub Kernel as well
174  if (getParam<bool>("add_darcy_advection_term") && isParamValid("pressure"))
175  {
176  InputParameters params_conv = _factory.getValidParams("CoupledConvectionReactionSub");
177  assignBlocks(params_conv, _blocks);
178  params_conv.set<NonlinearVariableName>("variable") = _solver_species[i];
179  params_conv.set<Real>("weight") = _weights[i][j];
180  params_conv.defaultCoupledValue("log_k", _log_eq_const[j]);
181  params_conv.set<Real>("sto_u") = _sto_u[i][j];
182  params_conv.set<std::vector<Real>>("sto_v") = _sto_v[i][j];
183  params_conv.set<std::vector<VariableName>>("v") = _coupled_v[i][j];
184  params_conv.set<std::vector<VariableName>>("p") = _pressure_var;
185  params_conv.set<RealVectorValue>("gravity") = getParam<RealVectorValue>("gravity");
186  _problem->addKernel("CoupledConvectionReactionSub",
187  _solver_species[i] + "_" + _eq_species[j] + "_conv",
188  params_conv);
189  }
190  }
191  }
192  }
193 }
194 
195 void
197 {
198  // Add AqueousEquilibriumRxnAux AuxKernels for equilibrium species
199  for (const auto j : make_range(_num_reactions))
200  {
201  // Add these aux-kernels only for the aux species involved in the reaction
202  // we should not be adding them twice, since only 1 eq_species per reaction
203  if (std::find(_aux_species.begin(), _aux_species.end(), _eq_species[j]) != _aux_species.end())
204  {
205  InputParameters params_eq = _factory.getValidParams("AqueousEquilibriumRxnAux");
206  assignBlocks(params_eq, _blocks);
207  params_eq.set<AuxVariableName>("variable") = _eq_species[j];
208  params_eq.defaultCoupledValue("log_k", _log_eq_const[j]);
209  mooseAssert(_stos[j].size() >= _solver_species_involved[j].size(),
210  "Coefs are for solver + auxiliary");
211  std::vector<Real> stos_primary(_stos[j].begin(),
212  _stos[j].begin() + _solver_species_involved[j].size());
213  params_eq.set<std::vector<Real>>("sto_v") = stos_primary;
214  params_eq.set<std::vector<VariableName>>("v") = _solver_species_involved[j];
215  getProblem().addAuxKernel("AqueousEquilibriumRxnAux", "aux_" + _eq_species[j], params_eq);
216  }
217  }
218 }
void renameParam(const std::string &old_name, const std::string &new_name, const std::string &new_docstring)
void assignBlocks(InputParameters &params, const std::vector< SubdomainName > &blocks) const
AqueousReactionsEquilibriumPhysics(const InputParameters &parameters)
const std::vector< ReactionNetworkUtils::Reaction > _reactions
Reaction network after being parsed in initializePhysics()
std::vector< std::vector< Real > > _stos
Stoichiometric coefficients for each primary species (outer indexing) in each reaction.
std::string reaction(const DenseMatrix< Real > &stoi, unsigned row, const std::vector< std::string > &names, Real stoi_tol=1.0E-6, int precision=4)
Returns a nicely formatted string corresponding to the reaction defined by the given row of the stoic...
void paramError(const std::string &param, Args... args) const
std::vector< std::string > _reactions_input
Reaction network as a vector of lines for pretty output.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void setDocString(const std::string &name, const std::string &doc)
const unsigned int _num_reactions
Number of reactions involved in the network.
Factory & _factory
T & set(const std::string &name, bool quiet_mode=false)
registerReactionNetworkPhysicsBaseTasks("ChemicalReactionsApp", AqueousReactionsEquilibriumPhysics)
InputParameters getValidParams(const std::string &name) const
const std::vector< VariableName > & _solver_species
Name of the species variables to solve for in the reaction network.
std::vector< std::vector< VariableName > > _solver_species_involved
Primary species involved in the ith equilibrium reaction (outer indexing)
virtual void addAuxKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
static InputParameters validParams()
std::vector< SubdomainName > _blocks
virtual FEProblemBase & getProblem()
Base class to host all common parameters and attributes of Physics actions to solve equations for mul...
const std::vector< AuxVariableName > & _aux_species
Name of the species variables that can be computed without additional solves, simply auxkernels...
Real defaultCoupledValue(const std::string &coupling_name, unsigned int i=0) const
std::vector< std::vector< std::vector< Real > > > _sto_v
Stoichiometric coefficients of coupled primary variables (outer indexing) in each reaction...
Creates all the objects needed to solve a reaction network of chemical reactions at equilibrium in an...
std::vector< std::vector< std::vector< VariableName > > > _coupled_v
Coupled primary species for each reaction (outer indexing is primary species, then reactions then inn...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< std::vector< bool > > _primary_participation
Vector of vectors, indexed by (i, j), of whether primary solver species &#39;i&#39; is present in reaction &#39;j...
registerMooseAction("ChemicalReactionsApp", AqueousReactionsEquilibriumPhysics, "add_kernel")
std::vector< std::vector< Real > > _sto_u
Stoichiometric coefficients of primary/solver variables (outer indexing) in each reaction.
std::vector< Real > _log_eq_const
log10(Equilibrium constants) for each reaction
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
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")
std::vector< std::vector< Real > > _weights
Weight of each primary species (outer indexing) in each reaction.
bool isParamValid(const std::string &name) const
const std::vector< VariableName > & _pressure_var
Name of the pressure variable.
void checkSecondParamSetOnlyIfFirstOneTrue(const std::string &param1, const std::string &param2) const
static const std::string k
Definition: NS.h:134
auto index_range(const T &sizable)
std::vector< VariableName > _eq_species
Equilibrium species: only one per reaction. This is a restriction of this implementation.