OGS
ChemistryLib::PhreeqcKernelData::PhreeqcKernel Class Referencefinal

Detailed Description

Definition at line 25 of file PhreeqcKernel.h.

#include <PhreeqcKernel.h>

Inheritance diagram for ChemistryLib::PhreeqcKernelData::PhreeqcKernel:
[legend]
Collaboration diagram for ChemistryLib::PhreeqcKernelData::PhreeqcKernel:
[legend]

Public Member Functions

 PhreeqcKernel (MeshLib::Mesh const &mesh, GlobalLinearSolver &linear_solver, std::size_t const num_chemical_systems, std::vector< std::pair< int, std::string > > const &process_id_to_component_name_map, std::string const &database, AqueousSolution aqueous_solution, std::unique_ptr< EquilibriumReactants > &&equilibrium_reactants, std::unique_ptr< Kinetics > &&kinetic_reactants, std::vector< ReactionRate > &&reaction_rates)
void executeSpeciationCalculation (double const dt) override
void setAqueousSolutions (std::vector< GlobalVector * > const &process_solutions)
void callPhreeqc (std::vector< GlobalVector * > &process_solutions)
void updateNodalProcessSolutions (std::vector< GlobalVector * > const &process_solutions, std::size_t const node_id)
Public Member Functions inherited from ChemistryLib::ChemicalSolverInterface
 ChemicalSolverInterface (MeshLib::Mesh const &mesh, GlobalLinearSolver &linear_solver_)
std::vector< std::size_t > const & activeElementIDs () const
virtual void initialize ()
virtual void initializeChemicalSystemConcrete (std::vector< double > const &, GlobalIndexType const &, MaterialPropertyLib::Medium const &, ParameterLib::SpatialPosition const &, double const)
virtual void setChemicalSystemConcrete (std::vector< double > const &, GlobalIndexType const &, MaterialPropertyLib::Medium const *, MaterialPropertyLib::VariableArray const &, ParameterLib::SpatialPosition const &, double const, double const)
virtual void setAqueousSolutionsPrevFromDumpFile ()
virtual double getConcentration (int const, GlobalIndexType const) const
virtual std::vector< std::string > const getComponentList () const
virtual Eigen::SparseMatrix< double > const * getStoichiometricMatrix () const
virtual double getKineticPrefactor (std::size_t reaction_id) const
virtual void updateVolumeFractionPostReaction (GlobalIndexType const &, MaterialPropertyLib::Medium const &, ParameterLib::SpatialPosition const &, double const, double const, double const)
virtual void updatePorosityPostReaction (GlobalIndexType const &, MaterialPropertyLib::Medium const &, double &)
virtual void computeSecondaryVariable (std::size_t const, std::vector< GlobalIndexType > const &)
virtual ~ChemicalSolverInterface ()=default

Private Member Functions

void initializePhreeqcGeneralSettings ()
void tidyEquilibriumReactants (EquilibriumReactants const &equilibrium_reactants)
void loadDatabase (std::string const &database)
void reinitializeRates ()
void setConvergenceTolerance ()
void configureOutputSettings ()
cxxISolution * getOrCreateInitialAqueousSolution (cxxSolution &aqueous_solution)
void setTimeStepSize (double const dt)
void reset (std::size_t const chemical_system_id)

Private Attributes

std::map< int, struct master * > _process_id_to_master_map
std::unique_ptr< cxxISolution const > _initial_aqueous_solution
std::unique_ptr< cxxSolution const > _aqueous_solution
std::vector< ReactionRate > const _reaction_rates

Additional Inherited Members

Public Attributes inherited from ChemistryLib::ChemicalSolverInterface
std::vector< GlobalIndexTypechemical_system_index_map
MeshLib::Mesh const & _mesh
GlobalLinearSolverlinear_solver

Constructor & Destructor Documentation

◆ PhreeqcKernel()

ChemistryLib::PhreeqcKernelData::PhreeqcKernel::PhreeqcKernel ( MeshLib::Mesh const & mesh,
GlobalLinearSolver & linear_solver,
std::size_t const num_chemical_systems,
std::vector< std::pair< int, std::string > > const & process_id_to_component_name_map,
std::string const & database,
AqueousSolution aqueous_solution,
std::unique_ptr< EquilibriumReactants > && equilibrium_reactants,
std::unique_ptr< Kinetics > && kinetic_reactants,
std::vector< ReactionRate > && reaction_rates )

Definition at line 19 of file PhreeqcKernel.cpp.

31 _initial_aqueous_solution(aqueous_solution.getInitialAqueousSolution()),
32 _aqueous_solution(aqueous_solution.castToBaseClassNoninitialized()),
33 _reaction_rates(std::move(reaction_rates))
34{
36
37 loadDatabase(database);
38
39 // solution
40 for (std::size_t chemical_system_id = 0;
41 chemical_system_id < num_chemical_systems;
42 ++chemical_system_id)
43 {
44 aqueous_solution.setChemicalSystemID(chemical_system_id);
45 Rxn_solution_map.emplace(chemical_system_id,
46 *aqueous_solution.castToBaseClass());
47 }
48 use.Set_solution_in(true);
49
50 // equilibrium reactants
51 if (equilibrium_reactants)
52 {
53 tidyEquilibriumReactants(*equilibrium_reactants);
54
55 for (std::size_t chemical_system_id = 0;
56 chemical_system_id < num_chemical_systems;
57 ++chemical_system_id)
58 {
59 equilibrium_reactants->setChemicalSystemID(chemical_system_id);
60 Rxn_pp_assemblage_map.emplace(
61 chemical_system_id, *equilibrium_reactants->castToBaseClass());
62 }
63 // explicitly release and delete equilibrium_reactants
64 equilibrium_reactants.reset(nullptr);
65
66 use.Set_pp_assemblage_in(true);
67 }
68
69 // kinetic reactants
70 if (kinetic_reactants)
71 {
72 for (std::size_t chemical_system_id = 0;
73 chemical_system_id < num_chemical_systems;
74 ++chemical_system_id)
75 {
76 kinetic_reactants->setChemicalSystemID(chemical_system_id);
77 Rxn_kinetics_map.emplace(chemical_system_id,
78 *kinetic_reactants->castToBaseClass());
79 }
80 // explicitly release and delete kinetic_reactants
81 kinetic_reactants.reset(nullptr);
82
83 use.Set_kinetics_in(true);
84 }
85
86 // rates
88
90
92
93 for (auto const& map_pair : process_id_to_component_name_map)
94 {
95 auto const transport_process_id = map_pair.first;
96 auto const& transport_process_variable = map_pair.second;
97
98 auto master_species =
99 master_bsearch(transport_process_variable.c_str());
100
101 _process_id_to_master_map[transport_process_id] = master_species;
102 }
103}
ChemicalSolverInterface(MeshLib::Mesh const &mesh, GlobalLinearSolver &linear_solver_)
std::vector< ReactionRate > const _reaction_rates
std::map< int, struct master * > _process_id_to_master_map
void tidyEquilibriumReactants(EquilibriumReactants const &equilibrium_reactants)
void loadDatabase(std::string const &database)
std::unique_ptr< cxxSolution const > _aqueous_solution
std::unique_ptr< cxxISolution const > _initial_aqueous_solution

References ChemistryLib::ChemicalSolverInterface::ChemicalSolverInterface(), _aqueous_solution, _initial_aqueous_solution, _process_id_to_master_map, _reaction_rates, ChemistryLib::PhreeqcKernelData::AqueousSolution::castToBaseClass(), configureOutputSettings(), initializePhreeqcGeneralSettings(), ChemistryLib::ChemicalSolverInterface::linear_solver, loadDatabase(), reinitializeRates(), ChemistryLib::PhreeqcKernelData::AqueousSolution::setChemicalSystemID(), setConvergenceTolerance(), and tidyEquilibriumReactants().

Member Function Documentation

◆ callPhreeqc()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::callPhreeqc ( std::vector< GlobalVector * > & process_solutions)

Definition at line 257 of file PhreeqcKernel.cpp.

258{
259 if (process_solutions.empty())
260 {
261 OGS_FATAL("About to access an empty process solutions vector.");
262 }
263 std::size_t const num_chemical_systems = process_solutions[0]->size();
264 for (std::size_t chemical_system_id = 0;
265 chemical_system_id < num_chemical_systems;
266 ++chemical_system_id)
267 {
268 Rxn_new_solution.insert(chemical_system_id);
269 new_solution = 1;
270 use.Set_n_solution_user(chemical_system_id);
271
272 if (!Rxn_pp_assemblage_map.empty())
273 {
274 Rxn_new_pp_assemblage.insert(chemical_system_id);
275 use.Set_pp_assemblage_in(true);
276 use.Set_n_pp_assemblage_user(chemical_system_id);
277 }
278
279 if (!Rxn_kinetics_map.empty())
280 {
281 use.Set_kinetics_in(true);
282 use.Set_n_kinetics_user(chemical_system_id);
283 }
284
285 initial_solutions(false);
286
287 reactions();
288
289 updateNodalProcessSolutions(process_solutions, chemical_system_id);
290
291 reset(chemical_system_id);
292 }
293}
#define OGS_FATAL(...)
Definition Error.h:19
void updateNodalProcessSolutions(std::vector< GlobalVector * > const &process_solutions, std::size_t const node_id)
void reset(std::size_t const chemical_system_id)

References OGS_FATAL, reset(), and updateNodalProcessSolutions().

Referenced by executeSpeciationCalculation().

◆ configureOutputSettings()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::configureOutputSettings ( )
inlineprivate

Definition at line 60 of file PhreeqcKernel.h.

60{ pr.all = false; }

Referenced by PhreeqcKernel().

◆ executeSpeciationCalculation()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::executeSpeciationCalculation ( double const dt)
overridevirtual

Run PHREEQC for all local chemical systems for the current timestep.

Uses the state previously provided by initializeChemicalSystemConcrete() / setChemicalSystemConcrete() for each chemical_system_id. Each local system is advanced as an isolated batch reactor over \(\Delta t\): no mass is exchanged between different systems inside PHREEQC.

PHREEQC returns, for each system:

  • updated aqueous composition,
  • reaction / source terms \(R_{\alpha}\) for each transported component,
  • updated mineral amounts and saturation state.

After this call completes, these reacted values are available for porosity update and for assembling the reaction/source term in the transport equation.

Parameters
dtTimestep size \(\Delta t\) used for kinetic reactions.

Reimplemented from ChemistryLib::ChemicalSolverInterface.

Definition at line 167 of file PhreeqcKernel.cpp.

168{
169 std::vector<GlobalVector*> process_solutions;
170
171 setAqueousSolutions(process_solutions);
172
173 setTimeStepSize(dt);
174
175 callPhreeqc(process_solutions);
176}
void setAqueousSolutions(std::vector< GlobalVector * > const &process_solutions)
void callPhreeqc(std::vector< GlobalVector * > &process_solutions)

References callPhreeqc(), setAqueousSolutions(), and setTimeStepSize().

◆ getOrCreateInitialAqueousSolution()

cxxISolution * ChemistryLib::PhreeqcKernelData::PhreeqcKernel::getOrCreateInitialAqueousSolution ( cxxSolution & aqueous_solution)
private

Definition at line 235 of file PhreeqcKernel.cpp.

237{
238 if (!aqueous_solution.Get_initial_data())
239 {
240 aqueous_solution.Set_initial_data(_initial_aqueous_solution.get());
241 aqueous_solution.Set_new_def(true);
242 }
243
244 return aqueous_solution.Get_initial_data();
245}

References _initial_aqueous_solution.

Referenced by setAqueousSolutions().

◆ initializePhreeqcGeneralSettings()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::initializePhreeqcGeneralSettings ( )
inlineprivate

Definition at line 49 of file PhreeqcKernel.h.

49{ do_initialize(); }

Referenced by PhreeqcKernel().

◆ loadDatabase()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::loadDatabase ( std::string const & database)
private

Definition at line 126 of file PhreeqcKernel.cpp.

127{
128 std::ifstream in(database);
129 if (!in)
130 {
131 OGS_FATAL("Unable to open database file '{:s}'.", database);
132 }
133 assert(phrq_io->get_istream() == nullptr);
134 phrq_io->push_istream(&in, false);
135 read_database();
136}

References OGS_FATAL.

Referenced by PhreeqcKernel().

◆ reinitializeRates()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::reinitializeRates ( )
private

Definition at line 138 of file PhreeqcKernel.cpp.

139{
140 std::vector<struct rate> rates(_reaction_rates.size());
141 int rate_id = 0;
142 for (auto const& reaction_rate : _reaction_rates)
143 {
144 rates[rate_id].name = reaction_rate.kinetic_reactant.data();
145
146 // Commands' strings are freed by Phreeqc dtor.
147 rates[rate_id].commands = static_cast<char*>(
148 malloc(sizeof(char) * reaction_rate.commands().size() + 1));
149 if (rates[rate_id].commands == nullptr)
150 {
151 OGS_FATAL("Could not allocate memory for rate[{:d}] commands.",
152 rate_id);
153 }
154 reaction_rate.commands().copy(rates[rate_id].commands,
155 std::string::npos);
156 rates[rate_id].commands[reaction_rate.commands().size()] = '\0';
157
158 rates[rate_id].new_def = 1;
159 rates[rate_id].linebase = nullptr;
160 rates[rate_id].varbase = nullptr;
161 rates[rate_id].loopbase = nullptr;
162
163 ++rate_id;
164 };
165}

References _reaction_rates, and OGS_FATAL.

Referenced by PhreeqcKernel().

◆ reset()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::reset ( std::size_t const chemical_system_id)
private

Definition at line 295 of file PhreeqcKernel.cpp.

296{
297 // Clean up
298 Rxn_new_solution.clear();
299
300 // Solution
301 {
302 Rxn_solution_map[chemical_system_id] = *_aqueous_solution;
303 Rxn_solution_map[chemical_system_id].Set_n_user_both(
304 chemical_system_id);
305 Rxn_solution_map[chemical_system_id].Set_pe(-s_eminus->la);
306 }
307
308 // Equilibrium reactants
309 if (!Rxn_pp_assemblage_map.empty())
310 {
311 Rxn_new_pp_assemblage.clear();
312 for (int j = 0; j < count_unknowns; j++)
313 {
314 if (x == nullptr || x[j]->type != PP)
315 continue;
316
317 auto& phase_components = Rxn_pp_assemblage_map[chemical_system_id]
318 .Get_pp_assemblage_comps();
319 phase_components[x[j]->pp_assemblage_comp_name].Set_moles(
320 x[j]->moles);
321 }
322 }
323
324 // Kinetics
325 if (!Rxn_kinetics_map.empty())
326 {
327 Rxn_kinetics_map[chemical_system_id].Get_steps().clear();
328 }
329}

References _aqueous_solution.

Referenced by callPhreeqc().

◆ setAqueousSolutions()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::setAqueousSolutions ( std::vector< GlobalVector * > const & process_solutions)

Definition at line 183 of file PhreeqcKernel.cpp.

185{
186 assert(!process_solutions.empty());
187 // Loop over chemical systems
188 std::size_t const num_chemical_systems = process_solutions[0]->size();
189 for (std::size_t chemical_system_id = 0;
190 chemical_system_id < num_chemical_systems;
191 ++chemical_system_id)
192 {
193 auto& aqueous_solution = Rxn_solution_map[chemical_system_id];
194
195 auto initial_aqueous_solution =
196 getOrCreateInitialAqueousSolution(aqueous_solution);
197
198 auto& components = initial_aqueous_solution->Get_comps();
199 // Loop over transport process id map to retrieve component
200 // concentrations from process solutions
201 for (auto const& map_pair : _process_id_to_master_map)
202 {
203 auto const transport_process_id = map_pair.first;
204 auto const& master_species = map_pair.second;
205
206 auto& transport_process_solution =
207 process_solutions[transport_process_id];
208
209 char const* const element_name = master_species->elt->name;
210 auto const concentration =
211 transport_process_solution->get(chemical_system_id);
212 if (isHydrogen(element_name))
213 {
214 // Set pH value by hydrogen concentration.
215 double const pH = -std::log10(concentration);
216 aqueous_solution.Set_ph(pH);
217
218 {
219 auto hydrogen = components.find("H(1)");
220 if (hydrogen != components.end())
221 {
222 hydrogen->second.Set_input_conc(pH);
223 }
224 }
225 }
226 else
227 {
228 // Set component concentrations.
229 components[element_name].Set_input_conc(concentration);
230 }
231 }
232 }
233}
cxxISolution * getOrCreateInitialAqueousSolution(cxxSolution &aqueous_solution)
static bool isHydrogen(std::string_view const element)
@ concentration
used to specify decay rate of a substance.

References _process_id_to_master_map, getOrCreateInitialAqueousSolution(), ChemistryLib::PhreeqcKernelData::isHydrogen(), and ChemistryLib::pH.

Referenced by executeSpeciationCalculation().

◆ setConvergenceTolerance()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::setConvergenceTolerance ( )
inlineprivate

Definition at line 58 of file PhreeqcKernel.h.

58{ convergence_tolerance = 1e-12; }

Referenced by PhreeqcKernel().

◆ setTimeStepSize()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::setTimeStepSize ( double const dt)
private

Definition at line 247 of file PhreeqcKernel.cpp.

248{
249 // Loop over rxn kinetics map
250 for (auto& map_pair : Rxn_kinetics_map)
251 {
252 auto& kinetics = map_pair.second;
253 kinetics.Get_steps().push_back(dt);
254 }
255}

Referenced by executeSpeciationCalculation().

◆ tidyEquilibriumReactants()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::tidyEquilibriumReactants ( EquilibriumReactants const & equilibrium_reactants)
private

Definition at line 105 of file PhreeqcKernel.cpp.

107{
108 // extract a part of function body from int
109 // Phreeqc::tidy_pp_assemblage(void)
110 count_elts = 0;
111 double coef = 1.0;
112 for (auto const& phase_component :
113 equilibrium_reactants.getPhaseComponents())
114 {
115 int phase_id;
116 struct phase* phase_component_ptr =
117 phase_bsearch(phase_component.first.c_str(), &phase_id, FALSE);
118 add_elt_list(phase_component_ptr->next_elt, coef);
119 }
120
121 cxxNameDouble nd = elt_list_NameDouble();
122 const_cast<cxxPPassemblage*>(equilibrium_reactants.castToBaseClass())
123 ->Set_eltList(nd);
124}

References ChemistryLib::PhreeqcKernelData::EquilibriumReactants::castToBaseClass(), and ChemistryLib::PhreeqcKernelData::EquilibriumReactants::getPhaseComponents().

Referenced by PhreeqcKernel().

◆ updateNodalProcessSolutions()

void ChemistryLib::PhreeqcKernelData::PhreeqcKernel::updateNodalProcessSolutions ( std::vector< GlobalVector * > const & process_solutions,
std::size_t const node_id )

Definition at line 331 of file PhreeqcKernel.cpp.

334{
335 for (auto const& map_pair : _process_id_to_master_map)
336 {
337 auto const transport_process_id = map_pair.first;
338 auto const& master_species = map_pair.second;
339
340 auto& transport_process_solution =
341 process_solutions[transport_process_id];
342
343 char const* const element_name = master_species->elt->name;
344 if (isHydrogen(element_name))
345 {
346 // Update hydrogen concentration by pH value.
347 auto const hydrogen_concentration = std::pow(10, s_hplus->la);
348 transport_process_solution->set(node_id, hydrogen_concentration);
349 }
350 else
351 {
352 // Update solutions of component transport processes.
353 auto const concentration =
354 master_species->primary
355 ? master_species->total_primary / mass_water_aq_x
356 : master_species->total / mass_water_aq_x;
357 transport_process_solution->set(node_id, concentration);
358 }
359 }
360}

References _process_id_to_master_map, and ChemistryLib::PhreeqcKernelData::isHydrogen().

Referenced by callPhreeqc().

Member Data Documentation

◆ _aqueous_solution

std::unique_ptr<cxxSolution const> ChemistryLib::PhreeqcKernelData::PhreeqcKernel::_aqueous_solution
private

Definition at line 71 of file PhreeqcKernel.h.

Referenced by PhreeqcKernel(), and reset().

◆ _initial_aqueous_solution

std::unique_ptr<cxxISolution const> ChemistryLib::PhreeqcKernelData::PhreeqcKernel::_initial_aqueous_solution
private

Definition at line 70 of file PhreeqcKernel.h.

Referenced by PhreeqcKernel(), and getOrCreateInitialAqueousSolution().

◆ _process_id_to_master_map

std::map<int, struct master*> ChemistryLib::PhreeqcKernelData::PhreeqcKernel::_process_id_to_master_map
private

Definition at line 69 of file PhreeqcKernel.h.

Referenced by PhreeqcKernel(), setAqueousSolutions(), and updateNodalProcessSolutions().

◆ _reaction_rates

std::vector<ReactionRate> const ChemistryLib::PhreeqcKernelData::PhreeqcKernel::_reaction_rates
private

Definition at line 72 of file PhreeqcKernel.h.

Referenced by PhreeqcKernel(), and reinitializeRates().


The documentation for this class was generated from the following files: