Line data Source code
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 :
10 : #include "AddGeochemistrySolverAction.h"
11 : #include "GeochemicalModelDefinition.h"
12 : #include "GeochemistryReactorBase.h"
13 : #include "NearestNodeNumber.h"
14 : #include "GeochemistryConsoleOutput.h"
15 : #include "BlockRestrictable.h"
16 : #include "BoundaryRestrictable.h"
17 :
18 : registerMooseAction("GeochemistryApp", AddGeochemistrySolverAction, "add_output");
19 : registerMooseAction("GeochemistryApp", AddGeochemistrySolverAction, "add_user_object");
20 : registerMooseAction("GeochemistryApp",
21 : AddGeochemistrySolverAction,
22 : "add_geochemistry_molality_aux");
23 :
24 : InputParameters
25 623 : AddGeochemistrySolverAction::validParams()
26 : {
27 623 : InputParameters params = Action::validParams();
28 1246 : params.addParam<UserObjectName>(
29 : "geochemistry_reactor_name",
30 : "geochemistry_reactor",
31 : "The name that will be given to the GeochemistryReactor UserObject built by this action");
32 1246 : params.addParam<bool>("include_moose_solve",
33 1246 : false,
34 : "Include a usual MOOSE solve involving Variables and Kernels. In pure "
35 : "reaction systems (without transport) include_moose_solve = false is "
36 : "appropriate, but with transport 'true' must be used");
37 :
38 1246 : params.addRequiredParam<UserObjectName>("model_definition",
39 : "The name of the GeochemicalModelDefinition user object "
40 : "(you must create this UserObject yourself)");
41 623 : params += GeochemistryReactorBase::sharedParams();
42 :
43 623 : params += BlockRestrictable::validParams();
44 623 : params += BoundaryRestrictable::validParams();
45 :
46 1869 : params.addRangeCheckedParam<Real>(
47 : "stoichiometry_tolerance",
48 1246 : 1E-6,
49 : "stoichiometry_tolerance >= 0.0",
50 : "Swapping involves inverting matrices via a singular value decomposition. During this "
51 : "process: (1) if abs(singular value) < stoi_tol * L1norm(singular values), then the "
52 : "matrix is deemed singular (so the basis swap is deemed invalid); (2) if abs(any "
53 : "stoichiometric coefficient) < stoi_tol then it is set to zero.");
54 :
55 : // following are exclusively for the GeochemistryConsoleOutput
56 623 : params += GeochemistryConsoleOutput::sharedParams();
57 623 : ExecFlagEnum exec_enum = MooseUtils::getDefaultExecFlagEnum();
58 2492 : exec_enum = {EXEC_INITIAL, EXEC_FINAL};
59 1246 : params.addParam<ExecFlagEnum>(
60 : "execute_console_output_on", exec_enum, "When to execute the geochemistry console output");
61 623 : params.addParam<Point>("point",
62 623 : Point(0.0, 0.0, 0.0),
63 : "The geochemistry console output will be regarding the aqueous "
64 : "solution at node that is closest to this point");
65 :
66 : // following are the Aux possibilities
67 1246 : params.addParam<bool>(
68 : "add_aux_solvent_kg",
69 1246 : true,
70 : "Add AuxVariable, called kg_solvent_H2O, that records the kg of solvent water");
71 1246 : params.addParam<bool>(
72 1246 : "add_aux_pH", true, "Add AuxVariable, called pH, that records the pH of solvent water");
73 1246 : params.addParam<bool>(
74 : "add_aux_molal",
75 1246 : true,
76 : "Add AuxVariables measured in molal units (ie mol(species)/kg(solvent_water)). These are "
77 : "named molal_name, where 'name' is the species name. AuxVariables are added for all species "
78 : "except minerals");
79 1246 : params.addParam<bool>("add_aux_mg_per_kg",
80 1246 : true,
81 : "Add AuxVariables measured in mg(species)/kg(solvent_water). These are "
82 : "named mg_per_kg_name, where 'name' is the species name. AuxVariables are "
83 : "added for all species except minerals");
84 1246 : params.addParam<bool>("add_aux_free_mg",
85 1246 : true,
86 : "Add AuxVariables for all minerals measured in free mg. These are named "
87 : "free_mg_name, where 'name' is the species name");
88 1246 : params.addParam<bool>("add_aux_free_cm3",
89 1246 : true,
90 : "Add AuxVariables for all minerals measured in free cm^3. These are named "
91 : "free_cm3_name, where 'name' is the species name");
92 1246 : params.addParam<bool>(
93 : "add_aux_activity",
94 1246 : true,
95 : "Add AuxVariables that record the activity for all species (for gas species this equals the "
96 : "gas fugacity). These are called activity_name where 'name' is the species name.");
97 1246 : params.addParam<bool>(
98 : "add_aux_bulk_moles",
99 1246 : true,
100 : "Add AuxVariables that record the number of bulk-composition moles for all species. Note "
101 : "that these will be zero for any species not currently in the basis. These are called "
102 : "bulk_moles_name where 'name' is the species name.");
103 1246 : params.addParam<bool>("add_aux_surface_charge",
104 1246 : true,
105 : "Add AuxVariables, measured in C/m^2, corresponding to specific surface "
106 : "charge for each mineral involved in surface sorption. These are "
107 : "surface_charge_name, where 'name' is the mineral name");
108 1246 : params.addParam<bool>("add_aux_surface_potential",
109 1246 : true,
110 : "Add AuxVariables, measured in V, corresponding to surface potential "
111 : "for each mineral involved in surface sorption. These are "
112 : "surface_potential_name, where 'name' is the mineral name");
113 1246 : params.addParam<bool>("add_aux_temperature",
114 1246 : true,
115 : "Add AuxVariable, called solution_temperature, that records the "
116 : "temperature of the aqueous solution in degC");
117 1246 : params.addParam<bool>(
118 : "add_aux_kinetic_moles",
119 1246 : true,
120 : "Add AuxVariables that record the number of moles for all kinetic species. These are called "
121 : "moles_name where 'name' is the species name.");
122 1246 : params.addParam<bool>("add_aux_kinetic_additions",
123 1246 : true,
124 : "Add AuxVariables that record the rate-of-change (-reaction_rate * dt) for "
125 : "all kinetic species. These are called "
126 : "mol_change_name where 'name' is the species name.");
127 1246 : params.addClassDescription("Base class for an Action that sets up a reaction solver. This class "
128 : "adds a GeochemistryConsoleOutput and AuxVariables corresponding to "
129 : "molalities, etc. Derived classes will create the solver.");
130 :
131 623 : return params;
132 623 : }
133 :
134 623 : AddGeochemistrySolverAction::AddGeochemistrySolverAction(const InputParameters & params)
135 623 : : Action(params)
136 : {
137 623 : }
138 :
139 : void
140 4345 : AddGeochemistrySolverAction::act()
141 : {
142 5591 : if (_current_task == "add_user_object" && isParamValid("execute_console_output_on"))
143 : {
144 431 : const std::string class_name = "NearestNodeNumberUO";
145 431 : auto params = _factory.getValidParams(class_name);
146 862 : params.set<Point>("point") = getParam<Point>("point");
147 862 : if (isParamValid("block"))
148 0 : params.set<std::vector<SubdomainName>>("block") =
149 0 : getParam<std::vector<SubdomainName>>("block");
150 862 : if (isParamValid("boundary"))
151 0 : params.set<std::vector<BoundaryName>>("boundary") =
152 0 : getParam<std::vector<BoundaryName>>("boundary");
153 431 : params.set<ExecFlagEnum>("execute_on") = EXEC_INITIAL; // NOTE: adaptivity not active yet
154 431 : _problem->addUserObject(class_name, "geochemistry_nearest_node_number", params);
155 431 : }
156 5112 : else if (_current_task == "add_output" && isParamValid("execute_console_output_on"))
157 : {
158 407 : const std::string class_name = "GeochemistryConsoleOutput";
159 407 : auto params = _factory.getValidParams(class_name);
160 814 : params.set<UserObjectName>("geochemistry_reactor") =
161 407 : getParam<UserObjectName>("geochemistry_reactor_name");
162 814 : params.set<unsigned>("precision") = getParam<unsigned>("precision");
163 814 : params.set<Real>("mol_cutoff") = getParam<Real>("mol_cutoff");
164 814 : params.set<Real>("stoichiometry_tolerance") = getParam<Real>("stoichiometry_tolerance");
165 814 : params.set<bool>("solver_info") = getParam<bool>("solver_info");
166 814 : params.set<UserObjectName>("nearest_node_number_UO") = "geochemistry_nearest_node_number";
167 1221 : params.set<ExecFlagEnum>("execute_on") = getParam<ExecFlagEnum>("execute_console_output_on");
168 407 : _problem->addOutput(class_name, "geochemistry_console_output", params);
169 407 : }
170 3507 : else if (_current_task == "add_geochemistry_molality_aux")
171 : {
172 599 : const ModelGeochemicalDatabase & mgd = _problem
173 599 : ->getUserObject<GeochemicalModelDefinition>(
174 599 : getParam<UserObjectName>("model_definition"))
175 599 : .getDatabase();
176 : // add temperature aux, if requested
177 1198 : if (getParam<bool>("add_aux_temperature"))
178 1194 : addAuxSpecies("solution_temperature", "H2O", "temperature");
179 : // add water, if requested
180 1198 : if (getParam<bool>("add_aux_solvent_kg"))
181 1194 : addAuxSpecies("kg_solvent_H2O", "H2O", "molal");
182 1198 : if (getParam<bool>("add_aux_activity"))
183 1194 : addAuxSpecies("activity_H2O", "H2O", "activity");
184 1198 : if (getParam<bool>("add_aux_bulk_moles"))
185 1194 : addAuxSpecies("bulk_moles_H2O", "H2O", "bulk_moles");
186 : // add pH, if requested
187 1198 : if (getParam<bool>("add_aux_pH"))
188 1130 : addAuxSpecies("pH", "H+", "neglog10a");
189 :
190 : // add the remaining ones
191 599 : const unsigned num_basis = mgd.basis_species_name.size();
192 3931 : for (unsigned i = 1; i < num_basis; ++i)
193 : {
194 9996 : if (getParam<bool>("add_aux_molal") && !mgd.basis_species_mineral[i])
195 6656 : addAuxSpecies("molal_" + mgd.basis_species_name[i], mgd.basis_species_name[i], "molal");
196 9996 : if (getParam<bool>("add_aux_mg_per_kg") && !mgd.basis_species_mineral[i])
197 9984 : addAuxSpecies(
198 6656 : "mg_per_kg_" + mgd.basis_species_name[i], mgd.basis_species_name[i], "mg_per_kg");
199 9996 : if (getParam<bool>("add_aux_free_cm3") && mgd.basis_species_mineral[i])
200 0 : addAuxSpecies(
201 0 : "free_cm3_" + mgd.basis_species_name[i], mgd.basis_species_name[i], "free_cm3");
202 9996 : if (getParam<bool>("add_aux_free_mg") && mgd.basis_species_mineral[i])
203 0 : addAuxSpecies("free_mg_" + mgd.basis_species_name[i], mgd.basis_species_name[i], "free_mg");
204 6664 : if (getParam<bool>("add_aux_activity"))
205 9984 : addAuxSpecies(
206 6656 : "activity_" + mgd.basis_species_name[i], mgd.basis_species_name[i], "activity");
207 6664 : if (getParam<bool>("add_aux_bulk_moles"))
208 9984 : addAuxSpecies(
209 6656 : "bulk_moles_" + mgd.basis_species_name[i], mgd.basis_species_name[i], "bulk_moles");
210 : }
211 599 : const unsigned num_eqm = mgd.eqm_species_name.size();
212 16237 : for (unsigned j = 0; j < num_eqm; ++j)
213 : {
214 46914 : if (getParam<bool>("add_aux_molal") && !mgd.eqm_species_mineral[j])
215 28996 : addAuxSpecies("molal_" + mgd.eqm_species_name[j], mgd.eqm_species_name[j], "molal");
216 46914 : if (getParam<bool>("add_aux_mg_per_kg") && !mgd.eqm_species_mineral[j])
217 28996 : addAuxSpecies("mg_per_kg_" + mgd.eqm_species_name[j], mgd.eqm_species_name[j], "mg_per_kg");
218 46914 : if (getParam<bool>("add_aux_free_cm3") && mgd.eqm_species_mineral[j])
219 2272 : addAuxSpecies("free_cm3_" + mgd.eqm_species_name[j], mgd.eqm_species_name[j], "free_cm3");
220 46914 : if (getParam<bool>("add_aux_free_mg") && mgd.eqm_species_mineral[j])
221 2272 : addAuxSpecies("free_mg_" + mgd.eqm_species_name[j], mgd.eqm_species_name[j], "free_mg");
222 31276 : if (getParam<bool>("add_aux_activity"))
223 31268 : addAuxSpecies("activity_" + mgd.eqm_species_name[j], mgd.eqm_species_name[j], "activity");
224 31276 : if (getParam<bool>("add_aux_bulk_moles"))
225 46902 : addAuxSpecies(
226 31268 : "bulk_moles_" + mgd.eqm_species_name[j], mgd.eqm_species_name[j], "bulk_moles");
227 : }
228 : // add the kinetic aux variables
229 599 : const unsigned num_kin = mgd.kin_species_name.size();
230 713 : for (unsigned k = 0; k < num_kin; ++k)
231 : {
232 342 : if (getParam<bool>("add_aux_free_cm3") && mgd.kin_species_mineral[k])
233 196 : addAuxSpecies("free_cm3_" + mgd.kin_species_name[k], mgd.kin_species_name[k], "free_cm3");
234 342 : if (getParam<bool>("add_aux_free_mg") && mgd.kin_species_mineral[k])
235 196 : addAuxSpecies("free_mg_" + mgd.kin_species_name[k], mgd.kin_species_name[k], "free_mg");
236 228 : if (getParam<bool>("add_aux_kinetic_moles"))
237 228 : addAuxSpecies("moles_" + mgd.kin_species_name[k], mgd.kin_species_name[k], "kinetic_moles");
238 228 : if (getParam<bool>("add_aux_kinetic_additions"))
239 342 : addAuxSpecies(
240 228 : "mol_change_" + mgd.kin_species_name[k], mgd.kin_species_name[k], "kinetic_additions");
241 : }
242 :
243 : // add surface stuff
244 677 : for (const auto & mineral : mgd.surface_sorption_name)
245 : {
246 156 : if (getParam<bool>("add_aux_surface_charge"))
247 156 : addAuxSpecies("surface_charge_" + mineral, mineral, "surface_charge");
248 156 : if (getParam<bool>("add_aux_surface_potential"))
249 156 : addAuxSpecies("surface_potential_" + mineral, mineral, "surface_potential");
250 : }
251 : }
252 4345 : }
253 :
254 : void
255 79381 : AddGeochemistrySolverAction::addAuxSpecies(const std::string & var_name,
256 : const std::string & species_name,
257 : const std::string & quantity)
258 : {
259 : // add AuxVariable
260 79381 : auto var_params = _factory.getValidParams("MooseVariable");
261 79381 : _problem->addAuxVariable("MooseVariable", var_name, var_params);
262 : // add AuxKernel
263 79381 : const std::string class_name = "GeochemistryQuantityAux";
264 79381 : auto params = _factory.getValidParams(class_name);
265 79381 : params.set<std::string>("species") = species_name;
266 79381 : params.set<MooseEnum>("quantity") = quantity;
267 238143 : params.set<UserObjectName>("reactor") = getParam<UserObjectName>("geochemistry_reactor_name");
268 158762 : params.set<AuxVariableName>("variable") = var_name;
269 79381 : params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_END;
270 79381 : _problem->addAuxKernel(class_name, var_name, params);
271 158762 : }
|