https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | Private Attributes | List of all members
PertinentGeochemicalSystem Class Reference

Constructs and stores a minimal amount of information that is pertinent to the user-defined geochemical system. More...

#include <PertinentGeochemicalSystem.h>

Public Member Functions

 PertinentGeochemicalSystem (const GeochemicalDatabaseReader &db, const std::vector< std::string > &basis_species, const std::vector< std::string > &minerals, const std::vector< std::string > &gases, const std::vector< std::string > &kinetic_minerals, const std::vector< std::string > &kinetic_redox, const std::vector< std::string > &kinetic_surface_species, const std::string &redox_ox, const std::string &redox_e)
 
const ModelGeochemicalDatabasemodelGeochemicalDatabase () const
 Return a reference to the ModelGeochemicalDatabase structure.
 
void addKineticRate (const KineticRateUserDescription &description)
 Adds a rate description for kinetic_species.
 
unsigned getIndexOfOriginalBasisSpecies (const std::string &name) const
 
std::vector< std::string > originalBasisNames () const
 

Private Member Functions

void buildBasis (const std::vector< std::string > &basis_species)
 using the basis_species list, this method builds _basis_index and _basis_info
 
void buildMinerals (const std::vector< std::string > &minerals)
 using the minerals list, this method builds _mineral_index and _mineral_info, unless minerals = {"*"}, in which case buildAllMinerals is used instead
 
void buildAllMinerals (const std::vector< std::string > &minerals)
 If minerals = {"*"} then populate _mineral_index and _mineral_info with all relevant minerals This is called in the constructor after buildSecondarySpecies and buildKineticMinerals because it adds to _mineral_index and _mineral_info all minerals that:
 
void buildGases (const std::vector< std::string > &gases)
 using the gas list, this method builds _gas_index and _gas_info
 
void buildKineticMinerals (const std::vector< std::string > &kinetic_minerals)
 using the kinetic_minerals list, this method builds _kinetic_mineral_index and _kinetic_mineral_info
 
void buildKineticRedox (const std::vector< std::string > &kinetic_redox)
 using the kinetic_redox list, this method builds _kinetic_redox_index and _kinetic_redox_info
 
void buildKineticSurface (const std::vector< std::string > &kinetic_surface)
 using the kinetic_surface list, this method builds _kinetic_surface_index and _kinetic_surface_info
 
void buildSecondarySpecies ()
 Extract all relevant "redox couples" and "secondary species" and "surface species" from the database.
 
bool checkRedoxe ()
 
void checkMinerals (const std::vector< GeochemistryMineralSpecies > &mineral_info) const
 Check that all minerals in mineral_info have reactions that involve only the basis_species or secondary_species.
 
void checkGases () const
 Check that all gases in the "gases" list have reactions that involve only the basis_species or secondary_species.
 
void checkKineticRedox () const
 Check that all kinetic redox species in the _kinetic_redox list have reactions that involve only the basis_species or secondary_species.
 
void checkKineticSurfaceSpecies () const
 Check that all kinetic surface species in the _kinetic_surface_species list have reactions that involve only the basis_species or secondary_species.
 
void createModel ()
 Fully populate the ModelGeochemicalDatabase.
 
void buildRedoxeInfo (std::vector< Real > &redox_e_stoichiometry, std::vector< Real > &redox_e_log10K)
 Extract the stoichiometry and log10K for the _redox_e species.
 

Private Attributes

GeochemicalDatabaseReader _db
 The database.
 
std::unordered_map< std::string, unsigned > _basis_index
 given a species name, return its index in the corresponding "info" std::vector
 
std::vector< GeochemistryBasisSpecies_basis_info
 a vector of all relevant species
 
std::unordered_map< std::string, unsigned > _mineral_index
 given a species name, return its index in the corresponding "info" std::vector
 
std::vector< GeochemistryMineralSpecies_mineral_info
 a vector of all relevant species
 
std::unordered_map< std::string, unsigned > _gas_index
 given a species name, return its index in the corresponding "info" std::vector
 
std::vector< GeochemistryGasSpecies_gas_info
 a vector of all relevant species
 
std::unordered_map< std::string, unsigned > _kinetic_mineral_index
 given a species name, return its index in the corresponding "info" std::vector
 
std::vector< GeochemistryMineralSpecies_kinetic_mineral_info
 a vector of all relevant species
 
std::unordered_map< std::string, unsigned > _kinetic_redox_index
 given a species name, return its index in the corresponding "info" std::vector
 
std::vector< GeochemistryRedoxSpecies_kinetic_redox_info
 a vector of all relevant species
 
std::unordered_map< std::string, unsigned > _kinetic_surface_index
 given a species name, return its index in the corresponding "info" std::vector
 
std::vector< GeochemistrySurfaceSpecies_kinetic_surface_info
 a vector of all relevant species
 
std::unordered_map< std::string, unsigned > _secondary_index
 given a species name, return its index in the corresponding "info" std::vector
 
std::vector< GeochemistryEquilibriumSpecies_secondary_info
 a vector of all relevant species
 
const std::string _redox_ox
 The name of the oxygen in all disequilibrium-redox equations, eg O2(aq), which must be a basis species if disequilibrium redox reactions are to be recorded.
 
const std::string _redox_e
 The name of the free electron involved in redox reactions.
 
ModelGeochemicalDatabase _model
 The important datastructure built by this class.
 

Detailed Description

Constructs and stores a minimal amount of information that is pertinent to the user-defined geochemical system.

Most importantly, all basis species, secondary species, mineral species, etc, that are defined in the geochemical database but are irrelevant to the user-defined system are eliminated from further consideration. This reduces the amount of information considerably. The final result is stored in a ModelGeochemicalDatabase structure. This structure is designed to be computationally efficient. A "getter" that copies this structure is provided as a public method. It is intended that a MOOSE simulation will construct one PertinentGeochemicalSystem object, and then copy the information to the nodes during the initial setup. If different nodes are allowed different swaps (likely to be the case) each node will need a different copy of the ModelGeochemicalDatabase structure.

Definition at line 386 of file PertinentGeochemicalSystem.h.

Constructor & Destructor Documentation

◆ PertinentGeochemicalSystem()

PertinentGeochemicalSystem::PertinentGeochemicalSystem ( const GeochemicalDatabaseReader db,
const std::vector< std::string > &  basis_species,
const std::vector< std::string > &  minerals,
const std::vector< std::string > &  gases,
const std::vector< std::string > &  kinetic_minerals,
const std::vector< std::string > &  kinetic_redox,
const std::vector< std::string > &  kinetic_surface_species,
const std::string &  redox_ox,
const std::string &  redox_e 
)
Parameters
dbthe database reader, which will have parsed the database file
basis_speciesA list of basis components relevant to the aqueous-equilibrium problem. "H2O" must appear first in this list. No element must appear more than once in this list. These components must be chosen from the "basis species" in the database, the sorbing sites (if any) and the decoupled redox states that are in disequilibrium (if any). Any redox pair that is not in this list or the kinetic_redox list, will be assumed to be at equilibrium with the aqueous solution and will be considered a secondary species. All these species, except H2O, may be later swapped out of this list, either by a manual user-prescribed swap (and replaced by a mineral or a gas of fixed fugacity, for instance), or during the numerical solve.
mineralsA list of minerals that are in equilibrium with the aqueous solution. This can only include the "minerals" in the database file. No element can appear more than once in this list. Their equilibrium reaction must consist of only the basis_species, and secondary species and non-kinetically-controlled redox couples that can be expressed in terms of the basis_species. If they are also "sorbing minerals" in the database then their sorption sites must consist of the basis_species only. During simulation, the user can compute the saturation index of these minerals, and these minerals can be "swapped" into the basis if desired (or required during the numerical solve). If the user performs a manual "swap" then an initial condition must be provided for the mineral. The user choose whether these minerals are allowed to precipitate or not - that is, they can be "supressed". This list, along with the kinetic_minerals list, comprises the entire list of minerals in the problem: all others are eliminated from consideration.
gasesA list of gases that are in equilibrium with the aqueous solution and can have their fugacities fixed, at least at some time and spatial location. All members of this list must be a "gas" in the database file. No gas must appear more than once in this list. The equilibrium reaction of each gas must involve only the basis_species, or secondary species or non-kinetically-controlled redox couples that can be expressed in terms of the basis_species.
kinetic_mineralsA list of minerals that whose dynamics are governed by a rate law. These are not in equilibrium with the aqueous solution. This can only include the "minerals" in the database file. No element can appear more than once in this list. Their equilibrium reaction must involve only the basis_species, or secondary species or non-kinetically-controlled redox couples that can be expressed in terms of the basis_species. If they are also "sorbing minerals" in the database then their sorption sites must consist of the basis_speices only. No members of this list must be in the minerals list. They can never be "swapped" into the basis, nor can they be "supressed".
kinetic_redoxA list of redox pairs whose dynamics are governed by a rate law. These are not in equilibrium with the aqueous solution. Each element of this list must appear in the "redox couples" section of the database. No element can appear more than once in this list. Their reaction must involve only the basis_species, or secondary species or non-kinetically-controlled redox couples that can be expressed in terms of the basis_species. No members of this list must be in the basis_species list. They can never be "swapped" into the basis.
kinetic_surface_speciesA list of surface sorbing species whose dynamics are governed by a rate law. These are not in equilibrium with the aqueous solution. All elements of this list must appear as a "surface species" in the database. No member must appear more than twice in this list. Their reaction must involve only the basis_species, or secondary species or non-kinetically-controlled redox couples that can be expressed in terms of the basis_species. They can never be "swapped" into the basis.
redox_oxThe name of the oxygen species, eg O2(aq), that appears in redox reactions. For redox pairs that are in disequilibrium to be correctly recorded, and hence their Nernst potentials to be computed easily, redox_ox must be a basis_species and it must appear in the reaction for each redox pair.
redox_eThe name of the free electron, eg e-. For redox pairs that are in disequilibrium to be correctly recorded, and hence their Nernst potentials to be computed easily, the equilibrium reaction for redox_e must involve redox_ox, and the basis species must be chosen so that redox_e is an equilibrium species according to the database reader

Definition at line 12 of file PertinentGeochemicalSystem.C.

22 : _db(db),
27 _gas_index(),
28 _gas_info(),
37 _redox_ox(redox_ox),
38 _redox_e(redox_e),
39 _model(_db)
40{
41 // Use the constructor info to build the "index" and "info" structures
42 buildBasis(basis_species);
43 buildMinerals(minerals);
44 buildGases(gases);
45 buildKineticMinerals(kinetic_minerals);
46 buildKineticRedox(kinetic_redox);
47 buildKineticSurface(kinetic_surface_species);
48
49 // Pull out all secondary equilibrium species: these are all relevant "redox couples" and
50 // "secondary species" and "surface species"
52
53 // Build minerals in the case that minerals = {"*"}
54 buildAllMinerals(minerals);
55
56 // Check that everything can be expressed in terms of the basis, possibly via redox and secondary
57 // species
59 checkGases();
63
64 // Populate _model
66}
const GeochemicalDatabaseReader db("database/moose_testdb.json", true, true, false)
std::vector< GeochemistryEquilibriumSpecies > _secondary_info
a vector of all relevant species
void buildKineticRedox(const std::vector< std::string > &kinetic_redox)
using the kinetic_redox list, this method builds _kinetic_redox_index and _kinetic_redox_info
void buildGases(const std::vector< std::string > &gases)
using the gas list, this method builds _gas_index and _gas_info
const std::string _redox_ox
The name of the oxygen in all disequilibrium-redox equations, eg O2(aq), which must be a basis specie...
void buildMinerals(const std::vector< std::string > &minerals)
using the minerals list, this method builds _mineral_index and _mineral_info, unless minerals = {"*"}...
std::vector< GeochemistryMineralSpecies > _kinetic_mineral_info
a vector of all relevant species
void buildBasis(const std::vector< std::string > &basis_species)
using the basis_species list, this method builds _basis_index and _basis_info
std::vector< GeochemistryBasisSpecies > _basis_info
a vector of all relevant species
std::unordered_map< std::string, unsigned > _gas_index
given a species name, return its index in the corresponding "info" std::vector
std::unordered_map< std::string, unsigned > _basis_index
given a species name, return its index in the corresponding "info" std::vector
std::vector< GeochemistryRedoxSpecies > _kinetic_redox_info
a vector of all relevant species
ModelGeochemicalDatabase _model
The important datastructure built by this class.
void checkKineticSurfaceSpecies() const
Check that all kinetic surface species in the _kinetic_surface_species list have reactions that invol...
std::unordered_map< std::string, unsigned > _secondary_index
given a species name, return its index in the corresponding "info" std::vector
const std::string _redox_e
The name of the free electron involved in redox reactions.
std::vector< GeochemistryGasSpecies > _gas_info
a vector of all relevant species
void buildKineticMinerals(const std::vector< std::string > &kinetic_minerals)
using the kinetic_minerals list, this method builds _kinetic_mineral_index and _kinetic_mineral_info
void checkGases() const
Check that all gases in the "gases" list have reactions that involve only the basis_species or second...
std::unordered_map< std::string, unsigned > _kinetic_surface_index
given a species name, return its index in the corresponding "info" std::vector
void createModel()
Fully populate the ModelGeochemicalDatabase.
void buildKineticSurface(const std::vector< std::string > &kinetic_surface)
using the kinetic_surface list, this method builds _kinetic_surface_index and _kinetic_surface_info
GeochemicalDatabaseReader _db
The database.
std::unordered_map< std::string, unsigned > _kinetic_redox_index
given a species name, return its index in the corresponding "info" std::vector
void checkMinerals(const std::vector< GeochemistryMineralSpecies > &mineral_info) const
Check that all minerals in mineral_info have reactions that involve only the basis_species or seconda...
void buildAllMinerals(const std::vector< std::string > &minerals)
If minerals = {"*"} then populate _mineral_index and _mineral_info with all relevant minerals This is...
std::unordered_map< std::string, unsigned > _kinetic_mineral_index
given a species name, return its index in the corresponding "info" std::vector
std::vector< GeochemistryMineralSpecies > _mineral_info
a vector of all relevant species
std::vector< GeochemistrySurfaceSpecies > _kinetic_surface_info
a vector of all relevant species
void buildSecondarySpecies()
Extract all relevant "redox couples" and "secondary species" and "surface species" from the database.
std::unordered_map< std::string, unsigned > _mineral_index
given a species name, return its index in the corresponding "info" std::vector
void checkKineticRedox() const
Check that all kinetic redox species in the _kinetic_redox list have reactions that involve only the ...

Member Function Documentation

◆ addKineticRate()

void PertinentGeochemicalSystem::addKineticRate ( const KineticRateUserDescription description)

Adds a rate description for kinetic_species.

Note that a single kinetic species can have multiple rates prescribed to it (by calling this method multiple times): they are added together to give an overall rate.

Definition at line 856 of file PertinentGeochemicalSystem.C.

857{
858 const std::string kinetic_species = description.kinetic_species_name;
859 if (_model.kin_species_index.count(kinetic_species) == 0)
860 mooseError("Cannot prescribe a kinetic rate to species ",
861 kinetic_species,
862 " since it is not a kinetic species");
863 const unsigned kinetic_species_index = _model.kin_species_index.at(kinetic_species);
864
865 // build the promoting index list
866 const unsigned num_pro = description.promoting_species.size();
867 const unsigned num_basis = _model.basis_species_name.size();
868 const unsigned num_eqm = _model.eqm_species_name.size();
869 std::vector<Real> promoting_ind(num_basis + num_eqm, 0.0);
870 std::vector<Real> promoting_m_ind(num_basis + num_eqm, 0.0);
871 std::vector<Real> promoting_k(num_basis + num_eqm, 0.0);
872 for (unsigned i = 0; i < num_pro; ++i)
873 {
874 unsigned index = 0;
875 const std::string promoting_species = description.promoting_species[i];
876 if (_model.basis_species_index.count(promoting_species) == 1)
877 index = _model.basis_species_index.at(promoting_species);
878 else if (_model.eqm_species_index.count(promoting_species) == 1)
879 index = num_basis + _model.eqm_species_index.at(promoting_species);
880 else
882 "Promoting species ", promoting_species, " must be a basis or a secondary species");
883 promoting_ind[index] = description.promoting_indices[i];
884 promoting_m_ind[index] = description.promoting_monod_indices[i];
885 promoting_k[index] = description.promoting_half_saturation[i];
886 }
887 unsigned progeny_num = 0;
888 if (_model.basis_species_index.count(description.progeny) == 1)
889 progeny_num = _model.basis_species_index.at(description.progeny);
890 else if (_model.eqm_species_index.count(description.progeny) == 1)
891 progeny_num = num_basis + _model.eqm_species_index.at(description.progeny);
892 else
893 mooseError("Progeny ", description.progeny, " must be a basis or a secondary species");
894
895 // append the result to kin_rate
896 _model.kin_rate.push_back(KineticRateDefinition(kinetic_species_index,
897 promoting_ind,
898 promoting_m_ind,
899 promoting_k,
900 progeny_num,
901 description));
902}
void mooseError(Args &&... args)
A single rate expression for the kinetic species with index kinetic_species_index.
std::vector< KineticRateDefinition > kin_rate
rates given to kinetic species.
std::unordered_map< std::string, unsigned > eqm_species_index
eqm_species_index[name] = index of the equilibrium species (secondary aqueous species,...
std::vector< std::string > basis_species_name
basis_species_name[j] = name of the j^th basis species
std::unordered_map< std::string, unsigned > basis_species_index
basis_species_index[name] = index of the basis species, within all ModelGeochemicalDatabase internal ...
std::unordered_map< std::string, unsigned > kin_species_index
kin_species_index[name] = index of the kinetic species, within all ModelGeochemicalDatabase internal ...
std::vector< std::string > eqm_species_name
eqm_species_name[i] = name of the i^th eqm species

Referenced by GeochemicalModelDefinition::GeochemicalModelDefinition(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), and TEST().

◆ buildAllMinerals()

void PertinentGeochemicalSystem::buildAllMinerals ( const std::vector< std::string > &  minerals)
private

If minerals = {"*"} then populate _mineral_index and _mineral_info with all relevant minerals This is called in the constructor after buildSecondarySpecies and buildKineticMinerals because it adds to _mineral_index and _mineral_info all minerals that:

  • are not kinetic minerals (these have been identified by buildKineticMinerals) and
  • whose stoichiometry depends on the basis species specified in the constructor or on secondary species (which are redox couples, secondary species and surface species) that depend on these basis species. These secondary species have already been identified by buildSecondarySpecies.

Definition at line 300 of file PertinentGeochemicalSystem.C.

301{
302 if (!(minerals.size() == 1 && minerals[0] == "*"))
303 return; // buildMinerals has done its job of building _mineral_info and _mineral_index
304 unsigned ind = 0;
305 for (const auto & name_ms : _db.getMineralSpecies(_db.mineralSpeciesNames()))
306 {
307 if (_kinetic_mineral_index.count(name_ms.first) == 1)
308 continue;
309 bool known_basis_only = true;
310 for (const auto & basis_stoi : name_ms.second.basis_species)
311 {
312 if (_basis_index.count(basis_stoi.first) == 0 &&
313 _secondary_index.count(basis_stoi.first) == 0)
314 {
315 known_basis_only = false;
316 break;
317 }
318 }
319 if (known_basis_only)
320 {
321 _mineral_index.emplace(name_ms.first, ind);
322 ind += 1;
323 _mineral_info.push_back(name_ms.second);
324 }
325 }
326}

Referenced by PertinentGeochemicalSystem().

◆ buildBasis()

void PertinentGeochemicalSystem::buildBasis ( const std::vector< std::string > &  basis_species)
private

using the basis_species list, this method builds _basis_index and _basis_info

Definition at line 95 of file PertinentGeochemicalSystem.C.

96{
97 unsigned ind = 0;
98 for (const auto & name : basis_species)
99 {
100 if (ind == 0 and name != "H2O")
101 mooseError("First member of basis species list must be H2O");
102 if (_basis_index.count(name) == 1)
103 mooseError(name, " exists more than once in the basis species list");
104 _basis_index.emplace(name, ind);
105 ind += 1;
107 _basis_info.push_back(_db.getBasisSpecies({name})[name]);
108 else if (_db.isRedoxSpecies(name))
109 {
112 bs.name = rs.name;
113 bs.radius = rs.radius;
114 bs.charge = rs.charge;
116 _basis_info.push_back(bs);
117 }
118 else
119 mooseError(name + " does not exist in the basis species or redox species in " +
120 _db.filename());
121 }
122}
const std::string name
Definition Setup.h:21
bool isBasisSpecies(const std::string &name) const
Checks if species is of given type.
std::map< std::string, GeochemistryRedoxSpecies > getRedoxSpecies(const std::vector< std::string > &names)
Get the redox species (couples) information.
std::map< std::string, GeochemistryBasisSpecies > getBasisSpecies(const std::vector< std::string > &names)
Get the basis (primary) species information.
bool isRedoxSpecies(const std::string &name) const
const FileName & filename() const
Filename of database.
Data structure for basis (primary) species.
Data structure for redox species.

Referenced by PertinentGeochemicalSystem().

◆ buildGases()

void PertinentGeochemicalSystem::buildGases ( const std::vector< std::string > &  gases)
private

using the gas list, this method builds _gas_index and _gas_info

Definition at line 141 of file PertinentGeochemicalSystem.C.

142{
143 unsigned ind = 0;
144 for (const auto & name : gases)
145 {
146 if (_gas_index.count(name) == 1)
147 mooseError(name + " exists more than once in the gases list");
148 _gas_index.emplace(name, ind);
149 ind += 1;
151 _gas_info.push_back(gas);
152 }
153}
std::map< std::string, GeochemistryGasSpecies > getGasSpecies(const std::vector< std::string > &names)
Get the gas species information.
Data structure for mineral species.

Referenced by PertinentGeochemicalSystem().

◆ buildKineticMinerals()

void PertinentGeochemicalSystem::buildKineticMinerals ( const std::vector< std::string > &  kinetic_minerals)
private

using the kinetic_minerals list, this method builds _kinetic_mineral_index and _kinetic_mineral_info

Definition at line 156 of file PertinentGeochemicalSystem.C.

157{
158 unsigned ind = 0;
159 for (const auto & name : kinetic_minerals)
160 {
161 if (_kinetic_mineral_index.count(name) == 1)
162 mooseError(name + " exists more than once in the kinetic_minerals list");
163 if (_mineral_index.count(name) == 1)
164 mooseError(name + " exists in both the minerals and kinetic_minerals lists");
165 _kinetic_mineral_index.emplace(name, ind);
166 ind += 1;
168 }
169}
std::map< std::string, GeochemistryMineralSpecies > getMineralSpecies(const std::vector< std::string > &names)
Get the mineral species information.

Referenced by PertinentGeochemicalSystem().

◆ buildKineticRedox()

void PertinentGeochemicalSystem::buildKineticRedox ( const std::vector< std::string > &  kinetic_redox)
private

using the kinetic_redox list, this method builds _kinetic_redox_index and _kinetic_redox_info

Definition at line 172 of file PertinentGeochemicalSystem.C.

173{
174 unsigned ind = 0;
175 for (const auto & name : kinetic_redox)
176 {
177 if (_kinetic_redox_index.count(name) == 1)
178 mooseError(name + " exists more than once in the kinetic_redox list");
179 if (_basis_index.count(name) == 1)
180 mooseError(name + " exists in both the basis_species and kinetic_redox lists");
181 _kinetic_redox_index.emplace(name, ind);
182 ind += 1;
183 _kinetic_redox_info.push_back(_db.getRedoxSpecies({name})[name]);
184 }
185}

Referenced by PertinentGeochemicalSystem().

◆ buildKineticSurface()

void PertinentGeochemicalSystem::buildKineticSurface ( const std::vector< std::string > &  kinetic_surface)
private

using the kinetic_surface list, this method builds _kinetic_surface_index and _kinetic_surface_info

Definition at line 188 of file PertinentGeochemicalSystem.C.

190{
191 unsigned ind = 0;
192 for (const auto & name : kinetic_surface_species)
193 {
194 if (_kinetic_surface_index.count(name) == 1)
195 mooseError(name + " exists more than once in the kinetic_surface_species list");
196 _kinetic_surface_index.emplace(name, ind);
197 ind += 1;
199 }
200}
std::map< std::string, GeochemistrySurfaceSpecies > getSurfaceSpecies(const std::vector< std::string > &names)
Get the surface sorbing species information.

Referenced by PertinentGeochemicalSystem().

◆ buildMinerals()

void PertinentGeochemicalSystem::buildMinerals ( const std::vector< std::string > &  minerals)
private

using the minerals list, this method builds _mineral_index and _mineral_info, unless minerals = {"*"}, in which case buildAllMinerals is used instead

Definition at line 125 of file PertinentGeochemicalSystem.C.

126{
127 unsigned ind = 0;
128 if (minerals.size() == 1 && minerals[0] == "*")
129 return; // buildAllMinerals is called later
130 for (const auto & name : minerals)
131 {
132 if (_mineral_index.count(name) == 1)
133 mooseError(name + " exists more than once in the minerals list");
134 _mineral_index.emplace(name, ind);
135 ind += 1;
136 _mineral_info.push_back(_db.getMineralSpecies({name})[name]);
137 }
138}

Referenced by PertinentGeochemicalSystem().

◆ buildRedoxeInfo()

void PertinentGeochemicalSystem::buildRedoxeInfo ( std::vector< Real > &  redox_e_stoichiometry,
std::vector< Real > &  redox_e_log10K 
)
private

Extract the stoichiometry and log10K for the _redox_e species.

This is called during createModel()

Parameters
redox_e_stoichiometryupon exit will contain the stoichiometry for the _redox_e species
redox_e_log10Kupon exit will contain the log10K info for the _redox_e species

Definition at line 345 of file PertinentGeochemicalSystem.C.

347{
348 const unsigned num_basis = _basis_info.size();
349 const unsigned numT = _db.getTemperatures().size();
350 redox_e_stoichiometry.assign(num_basis, 0.0);
351 redox_e_log10K.assign(numT, 0.0);
352 for (const auto & name : _db.secondarySpeciesNames())
353 if (name == _redox_e)
354 {
356 for (unsigned i = 0; i < numT; ++i)
357 redox_e_log10K[i] = ss.equilibrium_const[i];
358 for (const auto & react : ss.basis_species)
359 {
360 const Real stoi_coeff = react.second;
361 if (_model.basis_species_index.count(react.first) == 1)
362 {
363 const unsigned col = _model.basis_species_index[react.first];
364 redox_e_stoichiometry[col] += react.second;
365 }
366 else if (_secondary_index.count(react.first) == 1)
367 {
368 // reaction species is not a basis component, but a secondary component.
369 // So express stoichiometry in terms of the secondary component's reaction
370 const unsigned sec_row = _model.eqm_species_index[react.first];
371 for (unsigned i = 0; i < numT; ++i)
372 redox_e_log10K[i] += stoi_coeff * _model.eqm_log10K(sec_row, i);
373 for (unsigned col = 0; col < num_basis; ++col)
374 redox_e_stoichiometry[col] += stoi_coeff * _model.eqm_stoichiometry(sec_row, col);
375 }
376 }
377 }
378}
std::map< std::string, GeochemistryEquilibriumSpecies > getEquilibriumSpecies(const std::vector< std::string > &names)
Get the secondary equilibrium species information.
const std::vector< Real > & getTemperatures() const
Get the temperature points that the equilibrium constant is defined at.
if(subdm)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Data structure for secondary equilibrium species.
DenseMatrix< Real > eqm_stoichiometry
eqm_stoichiometry(i, j) = stoichiometric coefficient for equilibrium species "i" in terms of the basi...
DenseMatrix< Real > eqm_log10K
eqm_log10K(i, j) = log10(equilibrium constant) for i^th equilibrium species at the j^th temperature p...

Referenced by createModel().

◆ buildSecondarySpecies()

void PertinentGeochemicalSystem::buildSecondarySpecies ( )
private

Extract all relevant "redox couples" and "secondary species" and "surface species" from the database.

These are all species whose reaction involves only the basis_species and are not kinetically controlled or already in the basis_species list.

Definition at line 203 of file PertinentGeochemicalSystem.C.

204{
205 // run through all redox couples, including them if:
206 // - they are not part of the kinetic_redox list
207 // - they are not part of the basis_species list
208 // - their reaction involves only basis_species or secondary species already encountered
209 unsigned ind = 0;
210 for (const auto & name : _db.redoxCoupleNames())
211 {
212 if (_kinetic_redox_index.count(name) == 0 && _basis_index.count(name) == 0)
213 {
215 // check all reaction species are in the basis
216 bool all_species_in_basis_or_sec = true;
217 for (const auto & element : rs.basis_species)
218 if (_basis_index.count(element.first) == 0 && _secondary_index.count(element.first) == 0)
219 {
220 all_species_in_basis_or_sec = false;
221 break;
222 }
223 if (all_species_in_basis_or_sec)
224 {
225 _secondary_index.emplace(name, ind);
226 ind += 1;
228 ss.name = rs.name;
231 ss.radius = rs.radius;
232 ss.charge = rs.charge;
234 _secondary_info.push_back(ss);
235 }
236 }
237 }
238
239 // run through all secondary species, including them if:
240 // - their reaction involves only basis_species, or secondary species already encountered
241 // - the name is not _redox_e (which is usually "e-" the free electron)
242 for (const auto & name : _db.secondarySpeciesNames())
243 {
244 if (name == _redox_e)
245 continue;
247 // check all reaction species are in the basis
248 bool all_species_in_basis_or_sec = true;
249 for (const auto & element : ss.basis_species)
250 if (_basis_index.count(element.first) == 0 && _secondary_index.count(element.first) == 0)
251 {
252 all_species_in_basis_or_sec = false;
253 break;
254 }
255 if (all_species_in_basis_or_sec)
256 {
257 _secondary_index.emplace(name, ind);
258 ind += 1;
259 _secondary_info.push_back(ss);
260 }
261 }
262
263 // run through all surface species, including them if:
264 // - their reaction involves only basis_species or secondary species encountered so far
265 // - they are not in the kinetic_surface_species list
266 for (const auto & name : _db.surfaceSpeciesNames())
267 {
268 if (_kinetic_surface_index.count(name) == 0)
269 {
271 // check all reaction species are in the basis
272 bool all_species_in_basis_or_sec = true;
273 for (const auto & element : ss.basis_species)
274 if (_basis_index.count(element.first) == 0 && _secondary_index.count(element.first) == 0)
275 {
276 all_species_in_basis_or_sec = false;
277 break;
278 }
279 if (all_species_in_basis_or_sec)
280 {
282 to_sec.name = ss.name;
283 to_sec.basis_species = ss.basis_species;
284 to_sec.radius = -1.5; // flag to activity calculators that activity coefficient = 1
285 to_sec.charge = ss.charge;
287 const Real T0 = _db.getTemperatures()[0];
288 for (const auto & temp : _db.getTemperatures())
289 to_sec.equilibrium_const.push_back(ss.log10K + ss.dlog10KdT * (temp - T0));
290
291 _secondary_index.emplace(name, ind);
292 ind += 1;
293 _secondary_info.push_back(to_sec);
294 }
295 }
296 }
297}
unsigned int count
std::map< std::string, Real > basis_species
std::map< std::string, Real > basis_species
Data structure for sorbing surface species.
std::map< std::string, Real > basis_species

Referenced by PertinentGeochemicalSystem().

◆ checkGases()

void PertinentGeochemicalSystem::checkGases ( ) const
private

Check that all gases in the "gases" list have reactions that involve only the basis_species or secondary_species.

Definition at line 398 of file PertinentGeochemicalSystem.C.

399{
400 for (const auto & gas : _gas_info)
401 for (const auto & element : gas.basis_species)
402 if (_basis_index.count(element.first) == 0 && _secondary_index.count(element.first) == 0)
403 mooseError("The reaction for " + gas.name + " depends on " + element.first +
404 " which is not reducable to a set of basis species");
405}
for(PetscInt i=0;i< nvars;++i)

Referenced by PertinentGeochemicalSystem().

◆ checkKineticRedox()

void PertinentGeochemicalSystem::checkKineticRedox ( ) const
private

Check that all kinetic redox species in the _kinetic_redox list have reactions that involve only the basis_species or secondary_species.

Definition at line 408 of file PertinentGeochemicalSystem.C.

409{
410 for (const auto & kr : _kinetic_redox_info)
411 for (const auto & element : kr.basis_species)
412 if (_basis_index.count(element.first) == 0 && _secondary_index.count(element.first) == 0)
413 mooseError("The reaction for " + kr.name + " depends on " + element.first +
414 " which is not reducable to a set of basis species");
415}

Referenced by PertinentGeochemicalSystem().

◆ checkKineticSurfaceSpecies()

void PertinentGeochemicalSystem::checkKineticSurfaceSpecies ( ) const
private

Check that all kinetic surface species in the _kinetic_surface_species list have reactions that involve only the basis_species or secondary_species.

Definition at line 418 of file PertinentGeochemicalSystem.C.

419{
420 for (const auto & kr : _kinetic_surface_info)
421 for (const auto & element : kr.basis_species)
422 if (_basis_index.count(element.first) == 0 && _secondary_index.count(element.first) == 0)
423 mooseError("The reaction for " + kr.name + " depends on " + element.first +
424 " which is not reducable to a set of basis species");
425}

Referenced by PertinentGeochemicalSystem().

◆ checkMinerals()

void PertinentGeochemicalSystem::checkMinerals ( const std::vector< GeochemistryMineralSpecies > &  mineral_info) const
private

Check that all minerals in mineral_info have reactions that involve only the basis_species or secondary_species.

Check that if a mineral in this list is also a "sorbing mineral", its sorbing sites are present in the basis_species list

Definition at line 381 of file PertinentGeochemicalSystem.C.

383{
384 for (const auto & mineral : mineral_info)
385 {
386 for (const auto & element : mineral.basis_species)
387 if (_basis_index.count(element.first) == 0 && _secondary_index.count(element.first) == 0)
388 mooseError("The reaction for " + mineral.name + " depends on " + element.first +
389 " which is not reducable to a set of basis species");
390 for (const auto & element : mineral.sorption_sites)
391 if (_basis_index.count(element.first) == 0)
392 mooseError("The sorbing sites for " + mineral.name + " include " + element.first +
393 " which is not in the basis_species list");
394 }
395}

Referenced by PertinentGeochemicalSystem().

◆ checkRedoxe()

bool PertinentGeochemicalSystem::checkRedoxe ( )
private
Returns
true if _redox_e appears as a secondary species in the database and that its stoichiometry can be expressed in terms of basis species

Definition at line 329 of file PertinentGeochemicalSystem.C.

330{
331 bool found = false;
332 for (const auto & name : _db.secondarySpeciesNames())
333 if (name == _redox_e)
334 {
335 found = true;
337 for (const auto & element : ss.basis_species)
338 if (_basis_index.count(element.first) == 0 && _secondary_index.count(element.first) == 0)
339 return false;
340 }
341 return found;
342}

Referenced by createModel().

◆ createModel()

void PertinentGeochemicalSystem::createModel ( )
private

Fully populate the ModelGeochemicalDatabase.

Definition at line 428 of file PertinentGeochemicalSystem.C.

429{
430 const unsigned num_rows = _secondary_info.size() + _mineral_info.size() + _gas_info.size();
431 const unsigned num_cols = _basis_info.size();
432 const unsigned num_temperatures = _db.getTemperatures().size();
433 unsigned ind = 0;
434
435 // create basis_species_index map
437
438 // extract the names
439 _model.basis_species_name = std::vector<std::string>(num_cols);
440 for (const auto & species : _basis_info)
441 _model.basis_species_name[_model.basis_species_index[species.name]] = species.name;
442
443 // initially no basis species are minerals
444 _model.basis_species_mineral = std::vector<bool>(num_cols, false);
445
446 // initially no basis species are gases
447 _model.basis_species_gas = std::vector<bool>(num_cols, false);
448
449 // initially all basis species are involved in transport (this gets modified for surface species
450 // below)
451 _model.basis_species_transported = std::vector<bool>(num_cols, true);
452
453 // record the charge
454 _model.basis_species_charge = std::vector<Real>(num_cols, 0.0);
455 for (const auto & species : _basis_info)
456 _model.basis_species_charge[_model.basis_species_index[species.name]] = species.charge;
457
458 // record the ionic radius
459 _model.basis_species_radius = std::vector<Real>(num_cols, 0.0);
460 for (const auto & species : _basis_info)
461 _model.basis_species_radius[_model.basis_species_index[species.name]] = species.radius;
462
463 // record the molecular weight
464 _model.basis_species_molecular_weight = std::vector<Real>(num_cols, 0.0);
465 for (const auto & species : _basis_info)
466 _model.basis_species_molecular_weight[_model.basis_species_index[species.name]] =
467 species.molecular_weight;
468
469 // record the molecular weight (zero for all species except minerals)
470 _model.basis_species_molecular_volume = std::vector<Real>(num_cols, 0.0);
471
472 // the "eqm_species" stuff is rather long-winded because of the different data structures used
473 // to hold secondary, mineral and gas info. There is a bit of an overlap, however, so let's
474 // create a new data structure that contains that overlapping info
475
476 std::vector<GeochemistryEquilibriumSpecies> overlap(_secondary_info);
477 for (const auto & species : _mineral_info)
478 {
480 es.name = species.name;
481 es.molecular_weight = species.molecular_weight;
482 es.equilibrium_const = species.equilibrium_const;
483 es.basis_species = species.basis_species;
484 overlap.push_back(es);
485 }
486 for (const auto & species : _gas_info)
487 {
489 es.name = species.name;
490 es.molecular_weight = species.molecular_weight;
491 es.equilibrium_const = species.equilibrium_const;
492 es.basis_species = species.basis_species;
493 overlap.push_back(es);
494 }
495
496 // create the eqm_species_index map
497 ind = 0;
498 for (const auto & species : overlap)
499 _model.eqm_species_index[species.name] = ind++;
500
501 // extract the names
502 _model.eqm_species_name = std::vector<std::string>(num_rows);
503 for (const auto & species : _model.eqm_species_index)
504 _model.eqm_species_name[species.second] = species.first;
505
506 // create the eqm_species_mineral vector
507 _model.eqm_species_mineral = std::vector<bool>(num_rows, false);
508 for (const auto & species : _mineral_info)
509 _model.eqm_species_mineral[_model.eqm_species_index[species.name]] = true;
510 for (const auto & species : _gas_info)
511 _model.eqm_species_mineral[_model.eqm_species_index[species.name]] = false;
512
513 // create the eqm_species_gas vector
514 _model.eqm_species_gas = std::vector<bool>(num_rows, false);
515 for (const auto & species : _mineral_info)
516 _model.eqm_species_gas[_model.eqm_species_index[species.name]] = false;
517 for (const auto & species : _gas_info)
518 _model.eqm_species_gas[_model.eqm_species_index[species.name]] = true;
519
520 // create the eqm_species_transported vector (true for non-minerals) - gets modified below for
521 // surface species
522 _model.eqm_species_transported = std::vector<bool>(num_rows, true);
523 for (const auto & species : _mineral_info)
524 _model.eqm_species_transported[_model.eqm_species_index.at(species.name)] = false;
525
526 // record the charge
528 std::vector<Real>(num_rows, 0.0); // charge of gases and minerals is zero
529 for (const auto & species : _secondary_info)
530 _model.eqm_species_charge[_model.eqm_species_index[species.name]] = species.charge;
531
532 // record the radius
534 std::vector<Real>(num_rows, 0.0); // ionic radius of gases and minerals is zero
535 for (const auto & species : _secondary_info)
536 _model.eqm_species_radius[_model.eqm_species_index[species.name]] = species.radius;
537
538 // record the molecular weight
539 _model.eqm_species_molecular_weight = std::vector<Real>(num_rows, 0.0);
540 for (const auto & species : overlap)
541 _model.eqm_species_molecular_weight[_model.eqm_species_index[species.name]] =
542 species.molecular_weight;
543
544 // record the molecular volume (zero for all species except minerals)
545 _model.eqm_species_molecular_volume = std::vector<Real>(num_rows, 0.0);
546 for (const auto & species : _mineral_info)
547 _model.eqm_species_molecular_volume[_model.eqm_species_index[species.name]] =
548 species.molecular_volume;
549
550 // record surface-complexation info
551 for (const auto & species : _mineral_info)
552 if (species.surface_area != 0.0)
553 {
555 sci.surface_area = species.surface_area;
556 sci.sorption_sites = species.sorption_sites;
557 _model.surface_complexation_info[species.name] = sci;
558 }
559 for (const auto & species : _kinetic_mineral_info)
560 if (species.surface_area != 0.0)
561 {
563 sci.surface_area = species.surface_area;
564 sci.sorption_sites = species.sorption_sites;
565 _model.surface_complexation_info[species.name] = sci;
566 }
567
568 // record gas fugacity info
569 for (const auto & species : _gas_info)
570 _model.gas_chi[species.name] = species.chi;
571
572 // create the stoichiometry matrix
573 _model.eqm_stoichiometry.resize(num_rows, num_cols);
574 _model.eqm_log10K.resize(num_rows, num_temperatures);
575
576 // populate the stoichiometry
577 for (const auto & species : overlap)
578 {
579 const unsigned row = _model.eqm_species_index[species.name];
580 for (unsigned i = 0; i < num_temperatures; ++i)
581 _model.eqm_log10K(row, i) = species.equilibrium_const[i];
582 for (const auto & react : species.basis_species)
583 {
584 const Real stoi_coeff = react.second;
585 if (_model.basis_species_index.count(react.first) == 1)
586 {
587 const unsigned col = _model.basis_species_index[react.first];
588 _model.eqm_stoichiometry(row, col) += react.second;
589 }
590 else if (_secondary_index.count(react.first) == 1)
591 {
592 // reaction species is not a basis component, but a secondary component.
593 // So express stoichiometry in terms of the secondary component's reaction
594 const unsigned sec_row = _model.eqm_species_index[react.first];
595 for (unsigned i = 0; i < num_temperatures; ++i)
596 _model.eqm_log10K(row, i) += stoi_coeff * _model.eqm_log10K(sec_row, i);
597 for (unsigned col = 0; col < num_cols; ++col)
598 _model.eqm_stoichiometry(row, col) += stoi_coeff * _model.eqm_stoichiometry(sec_row, col);
599 }
600 else
601 mooseError("Species " + species.name + " includes " + react.first +
602 ", which cannot be expressed in terms of the basis. Previous checks must be "
603 "erroneous!");
604 }
605 }
606
607 // Build the redox information, if any. Here we express any O2(aq) in the redox equations in
608 // terms of redox_e (which is usually e-)
610 std::vector<Real> redox_e_stoichiometry(num_cols, 0.0);
611 std::vector<Real> redox_e_log10K(num_temperatures, 0.0);
612 std::vector<Real> redox_stoi;
613 std::vector<Real> redox_log10K;
614 if ((_model.basis_species_index.count(_redox_ox) == 1) && checkRedoxe())
615 {
616 // construct the stoichiometry and log10K for _redox_e and put it
617 buildRedoxeInfo(redox_e_stoichiometry, redox_e_log10K);
618 redox_stoi.insert(redox_stoi.end(), redox_e_stoichiometry.begin(), redox_e_stoichiometry.end());
619 redox_log10K.insert(redox_log10K.end(), redox_e_log10K.begin(), redox_e_log10K.end());
620 // the electron reaction is
621 // e- = nuw_i * basis_i + beta * O2(aq), where we've pulled out the O2(aq) because it's
622 // special
623 const unsigned o2_index = _model.basis_species_index.at(_redox_ox);
624 const Real beta = redox_e_stoichiometry[o2_index];
625 if (beta != 0.0)
626 {
627 for (const auto & bs : _model.basis_species_index)
628 if (_db.isRedoxSpecies(bs.first))
629 {
630 // this basis species is a redox couple in disequilibrium
631 const GeochemistryRedoxSpecies rs = _db.getRedoxSpecies({bs.first})[bs.first];
632 // check that its reaction involves only basis species, and record the stoichiometry in
633 // the current basis
634 std::vector<Real> stoi(num_cols, 0.0);
635 bool only_involves_basis_species = true;
636 for (const auto & name_stoi : rs.basis_species)
637 {
638 if (_model.basis_species_index.count(name_stoi.first) == 1)
639 stoi[_model.basis_species_index.at(name_stoi.first)] = name_stoi.second;
640 else
641 {
642 only_involves_basis_species = false;
643 break;
644 }
645 }
646 if (!only_involves_basis_species)
647 continue;
648 // Reaction is now
649 // redox = nu_i * basis_i + alpha * O2(aq), where we've pulled the O2(aq) out because
650 // it's special. Now pull the redox couple to the RHS of the reaction, so we have 0 =
651 // -redox + nu_i * basis_i + alpha * O2(aq)
652 stoi[bs.second] = -1.0;
653 // check that the stoichiometry involves O2(aq)
654 const Real alpha = stoi[o2_index];
655 if (alpha == 0.0)
656 continue;
657 // multiply equation -beta/alpha so it reads
658 // 0 = -beta/alpha * (-redox + nu_i * basis_i) - beta * O2(aq)
659 for (unsigned basis_i = 0; basis_i < num_cols; ++basis_i)
660 stoi[basis_i] *= -beta / alpha;
661 // add the equation to e- = nuw_i * basis_i + beta * O2(aq)
662 for (unsigned basis_i = 0; basis_i < num_cols; ++basis_i)
663 stoi[basis_i] += redox_e_stoichiometry[basis_i];
664 // now the reation is e- = nuw_i * basis_i - beta/alpha * (-redox + nu_i * basis_i)
665 redox_stoi.insert(redox_stoi.end(), stoi.begin(), stoi.end());
666
667 // record the equilibrium constants
668 for (unsigned temp = 0; temp < num_temperatures; ++temp)
669 redox_log10K.push_back((-beta / alpha) * rs.equilibrium_const[temp] +
670 redox_e_log10K[temp]);
671 }
672 }
673 }
674 // record the above in the model.redox_stoichiometry and model.redox_log10K DenseMatrices
675 const unsigned num_redox = redox_stoi.size() / num_cols;
676 _model.redox_stoichiometry.resize(num_redox, num_cols);
677 for (unsigned red = 0; red < num_redox; ++red)
678 for (unsigned basis_i = 0; basis_i < num_cols; ++basis_i)
679 _model.redox_stoichiometry(red, basis_i) = redox_stoi[red * num_cols + basis_i];
680 _model.redox_log10K.resize(num_redox, num_temperatures);
681 for (unsigned red = 0; red < num_redox; ++red)
682 for (unsigned temp = 0; temp < num_temperatures; ++temp)
683 _model.redox_log10K(red, temp) = redox_log10K[red * num_temperatures + temp];
684
685 // To build the kin_species_index, kin_species_name, etc, let's build an "overlap", similar to
686 // above
687 std::vector<GeochemistryMineralSpecies> overlap_kin(_kinetic_mineral_info);
688 for (const auto & species : _kinetic_redox_info)
689 {
691 ms.name = species.name;
692 ms.molecular_volume = 0.0;
693 ms.basis_species = species.basis_species;
694 ms.molecular_weight = species.molecular_weight;
695 ms.equilibrium_const = species.equilibrium_const;
696 overlap_kin.push_back(ms);
697 }
698 for (const auto & species : _kinetic_surface_info)
699 {
701 ms.name = species.name;
702 ms.molecular_volume = 0.0;
703 ms.basis_species = species.basis_species;
704 ms.molecular_weight = species.molecular_weight;
705 const Real T0 = _db.getTemperatures()[0];
706 for (const auto & temp : _db.getTemperatures())
707 ms.equilibrium_const.push_back(species.log10K + species.dlog10KdT * (temp - T0));
708 overlap_kin.push_back(ms);
709 }
710 const unsigned num_kin = overlap_kin.size();
711
712 // create the kin_species_index map
713 ind = 0;
714 for (const auto & species : overlap_kin)
715 _model.kin_species_index[species.name] = ind++;
716
717 // extract the names
718 _model.kin_species_name = std::vector<std::string>(num_kin);
719 for (const auto & species : _model.kin_species_index)
720 _model.kin_species_name[species.second] = species.first;
721
722 // build the kin_species_mineral info
723 _model.kin_species_mineral = std::vector<bool>(num_kin, true);
724 for (const auto & species : _kinetic_redox_info)
725 _model.kin_species_mineral[_model.kin_species_index[species.name]] = false;
726 for (const auto & species : _kinetic_surface_info)
727 _model.kin_species_mineral[_model.kin_species_index[species.name]] = false;
728
729 // create the kin_species_transported vector (false for minerals and surface species)
730 _model.kin_species_transported = std::vector<bool>(num_kin, true);
731 for (const auto & species : _kinetic_mineral_info)
732 _model.kin_species_transported[_model.kin_species_index.at(species.name)] = false;
733 for (const auto & species : _kinetic_surface_info)
734 _model.kin_species_transported[_model.kin_species_index.at(species.name)] = false;
735
736 // build the kin_species_charge info
737 _model.kin_species_charge = std::vector<Real>(num_kin, 0.0);
738 for (const auto & species : _kinetic_redox_info)
739 _model.kin_species_charge[_model.kin_species_index[species.name]] = species.charge;
740 for (const auto & species : _kinetic_surface_info)
741 _model.kin_species_charge[_model.kin_species_index[species.name]] = species.charge;
742
743 // extract the molecular weight
744 _model.kin_species_molecular_weight = std::vector<Real>(num_kin, 0.0);
745 for (const auto & species : overlap_kin)
746 _model.kin_species_molecular_weight[_model.kin_species_index[species.name]] =
747 species.molecular_weight;
748
749 // extract the molecular volume
750 _model.kin_species_molecular_volume = std::vector<Real>(num_kin, 0.0);
751 for (const auto & species : overlap_kin)
752 _model.kin_species_molecular_volume[_model.kin_species_index[species.name]] =
753 species.molecular_volume;
754
755 // extract the stoichiometry
756 _model.kin_stoichiometry.resize(num_kin, num_cols);
757 _model.kin_log10K.resize(num_kin, num_temperatures);
758
759 // populate the stoichiometry
760 for (const auto & species : overlap_kin)
761 {
762 const unsigned row = _model.kin_species_index[species.name];
763 for (unsigned i = 0; i < num_temperatures; ++i)
764 _model.kin_log10K(row, i) = species.equilibrium_const[i];
765 for (const auto & react : species.basis_species)
766 {
767 const Real stoi_coeff = react.second;
768 if (_model.basis_species_index.count(react.first) == 1)
769 {
770 const unsigned col = _model.basis_species_index[react.first];
771 _model.kin_stoichiometry(row, col) += react.second;
772 }
773 else if (_model.eqm_species_index.count(react.first) == 1)
774 {
775 // reaction species is not a basis component, but a secondary component.
776 // So express stoichiometry in terms of the secondary component's reaction
777 const unsigned sec_row = _model.eqm_species_index[react.first];
778 for (unsigned i = 0; i < num_temperatures; ++i)
779 _model.kin_log10K(row, i) += stoi_coeff * _model.eqm_log10K(sec_row, i);
780 for (unsigned col = 0; col < num_cols; ++col)
781 _model.kin_stoichiometry(row, col) += stoi_coeff * _model.eqm_stoichiometry(sec_row, col);
782 }
783 else
784 mooseError("Kinetic species " + species.name + " includes " + react.first +
785 ", which cannot be expressed in terms of the basis. Previous checks must be "
786 "erroneous!");
787 }
788 }
789
790 // check that there are no repeated sorbing sites in the SurfaceComplexationInfo
791 std::vector<std::string> all_sorbing_sites;
792 for (const auto & name_info : _model.surface_complexation_info)
793 for (const auto & name_frac : name_info.second.sorption_sites)
794 if (std::find(all_sorbing_sites.begin(), all_sorbing_sites.end(), name_frac.first) !=
795 all_sorbing_sites.end())
797 "The sorbing site ", name_frac.first, " appears in more than one sorbing mineral");
798 else
799 all_sorbing_sites.push_back(name_frac.first);
800
801 // build the information related to surface sorption, and modify the species_transported vectors
802 _model.surface_sorption_related.assign(num_rows, false);
803 _model.surface_sorption_number.assign(num_rows, 99);
804 for (const auto & name_info :
805 _model.surface_complexation_info) // all minerals involved in surface complexation
806 {
807 for (const auto & name_frac :
808 name_info.second.sorption_sites) // all sorption sites on the given mineral
809 {
810 const unsigned basis_index_of_sorption_site = _model.basis_species_index.at(name_frac.first);
811 _model.basis_species_transported[basis_index_of_sorption_site] = false;
812 }
813 bool mineral_involved_in_eqm = false;
814 for (const auto & name_frac :
815 name_info.second.sorption_sites) // all sorption sites on the given mineral
816 {
817 const unsigned basis_index_of_sorption_site = _model.basis_species_index.at(name_frac.first);
818 for (unsigned j = 0; j < num_rows; ++j) // all equilibrium species
819 if (_model.eqm_stoichiometry(j, basis_index_of_sorption_site) != 0.0)
820 {
821 mineral_involved_in_eqm = true;
822 break;
823 }
824 }
825 if (!mineral_involved_in_eqm)
826 continue;
827 const unsigned num_surface_sorption = _model.surface_sorption_name.size();
828 _model.surface_sorption_name.push_back(name_info.first);
829 _model.surface_sorption_area.push_back(name_info.second.surface_area);
830 for (const auto & name_frac :
831 name_info.second.sorption_sites) // all sorption sites on the given mineral
832 {
833 const unsigned basis_index_of_sorption_site = _model.basis_species_index.at(name_frac.first);
834 for (unsigned j = 0; j < num_rows; ++j) // all equilibrium species
835 if (_model.eqm_stoichiometry(j, basis_index_of_sorption_site) != 0.0)
836 {
838 mooseError("It is an error for any equilibrium species (such as ",
840 ") to have a reaction involving more than one sorbing site");
842 _model.surface_sorption_number[j] = num_surface_sorption;
844 }
845 }
846 }
847}
void buildRedoxeInfo(std::vector< Real > &redox_e_stoichiometry, std::vector< Real > &redox_e_log10K)
Extract the stoichiometry and log10K for the _redox_e species.
void resize(const unsigned int new_m, const unsigned int new_n)
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Data structure for mineral species.
std::map< std::string, Real > basis_species
std::vector< bool > eqm_species_mineral
eqm_species_mineral[i] = true iff the i^th equilibrium species is a mineral
std::vector< Real > eqm_species_radius
all quantities have an ionic radius (Angstrom) for computing activity (mineral radius = 0,...
std::vector< Real > basis_species_molecular_weight
all quantities have a molecular weight (g)
DenseMatrix< Real > kin_stoichiometry
kin_stoichiometry(i, j) = stoichiometric coefficient for kinetic species "i" in terms of the basis sp...
std::vector< Real > basis_species_radius
all quantities have an ionic radius (Angstrom) for computing activity (mineral radius = 0,...
std::vector< Real > basis_species_charge
all quantities have a charge (mineral charge = 0, gas charge = 0, oxide charge = 0)
std::vector< Real > eqm_species_molecular_volume
all quantities have a molecular volume (cm^3) (only nonzero for minerals, however)
std::string redox_lhs
the name of the species on the left-hand side of the redox equations.
std::vector< bool > kin_species_mineral
kin_species_mineral[j] = true iff the j^th kinetic species is a mineral
std::vector< Real > eqm_species_molecular_weight
all quantities have a molecular weight (g)
std::vector< unsigned > surface_sorption_number
surface_sorption_number[j] = the index of the surface potential that should be used to modify the equ...
std::vector< bool > basis_species_transported
basis_species_transported[j] = true iff the j^th basis species is transported in reactive-transport s...
std::vector< std::string > kin_species_name
kin_species_name[j] = name of the j^th kinetic species
DenseMatrix< Real > redox_stoichiometry
redox_stoichiometry(i, j) = stoichiometric coefficients for i^th redox species that is in disequilibr...
std::vector< Real > surface_sorption_area
surface_sorption_area[k] = specific surface area [m^2/g] for the k^th mineral involved in surface sor...
std::vector< bool > basis_species_mineral
basis_species_mineral[j] = true iff the j^th basis species is a mineral
std::vector< Real > kin_species_molecular_volume
all quantities have a molecular volume (cm^3/mol) (only nonzero for minerals, however)
DenseMatrix< Real > redox_log10K
redox_log10K(i, j) = log10(equilibrium constant) for i^th redox species at the j^th temperature point
DenseMatrix< Real > kin_log10K
kin_log10K(i, j) = log10(equilibrium constant for the i^th kinetic species at the j^th temperature po...
std::unordered_map< std::string, SurfaceComplexationInfo > surface_complexation_info
Holds info on surface complexation, if any, in the model.
std::vector< bool > surface_sorption_related
surface_sorption_related[j] = true iff the j^th equilibrium species is involved in surface sorption
std::vector< Real > basis_species_molecular_volume
all quantities have a molecular volume (cm^3) (only nonzero for minerals, however)
std::vector< bool > kin_species_transported
kin_species_transported[j] = true iff the j^th kinetic species is transported in reactive-transport s...
std::vector< Real > kin_species_charge
all kinetic quantities have a charge (mineral charge = 0)
std::vector< std::string > surface_sorption_name
surface_sorption_name[k] = name of the mineral involved in surface sorption.
std::vector< bool > basis_species_gas
basis_species_gas[j] = true iff the j^th basis species is a gas
std::vector< Real > eqm_species_charge
all quantities have a charge (mineral charge = 0, gas charge = 0, oxide charge = 0)
std::vector< bool > eqm_species_gas
eqm_species_gas[i] = true iff the i^th equilibrium species is a gas
std::vector< Real > kin_species_molecular_weight
all quantities have a molecular weight (g/mol)
std::vector< bool > eqm_species_transported
eqm_species_transported[i] = true iff the i^th eqm species is transported in reactive-transport sims
Data structure designed to hold information related to sorption via surface complexation.
std::map< std::string, Real > sorption_sites
const Real radius

Referenced by PertinentGeochemicalSystem().

◆ getIndexOfOriginalBasisSpecies()

unsigned PertinentGeochemicalSystem::getIndexOfOriginalBasisSpecies ( const std::string &  name) const
Parameters
namespecies name
Returns
the index of the species in the original basis

Definition at line 69 of file PertinentGeochemicalSystem.C.

70{
71 try
72 {
73 return _basis_index.at(name);
74 }
75 catch (const std::out_of_range &)
76 {
77 mooseError("species ", name, " is not in the original basis");
78 }
79 catch (...)
80 {
81 throw;
82 }
83}

Referenced by GeochemistryQuantityAux::computeValue(), GeochemistryQuantityAux::GeochemistryQuantityAux(), and TEST().

◆ modelGeochemicalDatabase()

const ModelGeochemicalDatabase & PertinentGeochemicalSystem::modelGeochemicalDatabase ( ) const

◆ originalBasisNames()

std::vector< std::string > PertinentGeochemicalSystem::originalBasisNames ( ) const
Returns
a vector of names of the original basis species

Definition at line 86 of file PertinentGeochemicalSystem.C.

87{
88 std::vector<std::string> names(_basis_info.size());
89 for (const auto & name_ind : _basis_index)
90 names[name_ind.second] = name_ind.first;
91 return names;
92}

Referenced by GeochemistryConsoleOutput::output(), TEST(), and TEST_F().

Member Data Documentation

◆ _basis_index

std::unordered_map<std::string, unsigned> PertinentGeochemicalSystem::_basis_index
private

◆ _basis_info

std::vector<GeochemistryBasisSpecies> PertinentGeochemicalSystem::_basis_info
private

a vector of all relevant species

Definition at line 493 of file PertinentGeochemicalSystem.h.

Referenced by buildBasis(), buildRedoxeInfo(), createModel(), and originalBasisNames().

◆ _db

GeochemicalDatabaseReader PertinentGeochemicalSystem::_db
private

◆ _gas_index

std::unordered_map<std::string, unsigned> PertinentGeochemicalSystem::_gas_index
private

given a species name, return its index in the corresponding "info" std::vector

Definition at line 502 of file PertinentGeochemicalSystem.h.

Referenced by buildGases().

◆ _gas_info

std::vector<GeochemistryGasSpecies> PertinentGeochemicalSystem::_gas_info
private

a vector of all relevant species

Definition at line 505 of file PertinentGeochemicalSystem.h.

Referenced by buildGases(), checkGases(), and createModel().

◆ _kinetic_mineral_index

std::unordered_map<std::string, unsigned> PertinentGeochemicalSystem::_kinetic_mineral_index
private

given a species name, return its index in the corresponding "info" std::vector

Definition at line 508 of file PertinentGeochemicalSystem.h.

Referenced by buildAllMinerals(), and buildKineticMinerals().

◆ _kinetic_mineral_info

std::vector<GeochemistryMineralSpecies> PertinentGeochemicalSystem::_kinetic_mineral_info
private

a vector of all relevant species

Definition at line 511 of file PertinentGeochemicalSystem.h.

Referenced by buildKineticMinerals(), createModel(), and PertinentGeochemicalSystem().

◆ _kinetic_redox_index

std::unordered_map<std::string, unsigned> PertinentGeochemicalSystem::_kinetic_redox_index
private

given a species name, return its index in the corresponding "info" std::vector

Definition at line 514 of file PertinentGeochemicalSystem.h.

Referenced by buildKineticRedox(), and buildSecondarySpecies().

◆ _kinetic_redox_info

std::vector<GeochemistryRedoxSpecies> PertinentGeochemicalSystem::_kinetic_redox_info
private

a vector of all relevant species

Definition at line 517 of file PertinentGeochemicalSystem.h.

Referenced by buildKineticRedox(), checkKineticRedox(), and createModel().

◆ _kinetic_surface_index

std::unordered_map<std::string, unsigned> PertinentGeochemicalSystem::_kinetic_surface_index
private

given a species name, return its index in the corresponding "info" std::vector

Definition at line 520 of file PertinentGeochemicalSystem.h.

Referenced by buildKineticSurface(), and buildSecondarySpecies().

◆ _kinetic_surface_info

std::vector<GeochemistrySurfaceSpecies> PertinentGeochemicalSystem::_kinetic_surface_info
private

a vector of all relevant species

Definition at line 523 of file PertinentGeochemicalSystem.h.

Referenced by buildKineticSurface(), checkKineticSurfaceSpecies(), and createModel().

◆ _mineral_index

std::unordered_map<std::string, unsigned> PertinentGeochemicalSystem::_mineral_index
private

given a species name, return its index in the corresponding "info" std::vector

Definition at line 496 of file PertinentGeochemicalSystem.h.

Referenced by buildAllMinerals(), buildKineticMinerals(), and buildMinerals().

◆ _mineral_info

std::vector<GeochemistryMineralSpecies> PertinentGeochemicalSystem::_mineral_info
private

a vector of all relevant species

Definition at line 499 of file PertinentGeochemicalSystem.h.

Referenced by buildAllMinerals(), buildMinerals(), createModel(), and PertinentGeochemicalSystem().

◆ _model

ModelGeochemicalDatabase PertinentGeochemicalSystem::_model
private

The important datastructure built by this class.

Definition at line 541 of file PertinentGeochemicalSystem.h.

Referenced by addKineticRate(), buildRedoxeInfo(), createModel(), and modelGeochemicalDatabase().

◆ _redox_e

const std::string PertinentGeochemicalSystem::_redox_e
private

The name of the free electron involved in redox reactions.

Definition at line 538 of file PertinentGeochemicalSystem.h.

Referenced by buildRedoxeInfo(), buildSecondarySpecies(), checkRedoxe(), and createModel().

◆ _redox_ox

const std::string PertinentGeochemicalSystem::_redox_ox
private

The name of the oxygen in all disequilibrium-redox equations, eg O2(aq), which must be a basis species if disequilibrium redox reactions are to be recorded.

Definition at line 535 of file PertinentGeochemicalSystem.h.

Referenced by createModel().

◆ _secondary_index

std::unordered_map<std::string, unsigned> PertinentGeochemicalSystem::_secondary_index
private

given a species name, return its index in the corresponding "info" std::vector

Definition at line 526 of file PertinentGeochemicalSystem.h.

Referenced by buildAllMinerals(), buildRedoxeInfo(), buildSecondarySpecies(), checkGases(), checkKineticRedox(), checkKineticSurfaceSpecies(), checkMinerals(), checkRedoxe(), and createModel().

◆ _secondary_info

std::vector<GeochemistryEquilibriumSpecies> PertinentGeochemicalSystem::_secondary_info
private

a vector of all relevant species

Definition at line 529 of file PertinentGeochemicalSystem.h.

Referenced by buildSecondarySpecies(), and createModel().


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