14 const std::vector<std::string> & basis_species,
15 const std::vector<std::string> & minerals,
16 const std::vector<std::string> & gases,
17 const std::vector<std::string> & kinetic_minerals,
18 const std::vector<std::string> & kinetic_redox,
19 const std::vector<std::string> & kinetic_surface_species,
20 const std::string & redox_ox,
21 const std::string & redox_e)
29 _kinetic_mineral_index(),
30 _kinetic_mineral_info(),
31 _kinetic_redox_index(),
32 _kinetic_redox_info(),
33 _kinetic_surface_index(),
34 _kinetic_surface_info(),
75 catch (
const std::out_of_range &)
85std::vector<std::string>
90 names[name_ind.second] = name_ind.first;
98 for (
const auto &
name : basis_species)
100 if (ind == 0 and
name !=
"H2O")
101 mooseError(
"First member of basis species list must be H2O");
103 mooseError(
name,
" exists more than once in the basis species list");
119 mooseError(
name +
" does not exist in the basis species or redox species in " +
128 if (minerals.size() == 1 && minerals[0] ==
"*")
130 for (
const auto &
name : minerals)
144 for (
const auto &
name : gases)
159 for (
const auto &
name : kinetic_minerals)
162 mooseError(
name +
" exists more than once in the kinetic_minerals list");
164 mooseError(
name +
" exists in both the minerals and kinetic_minerals lists");
175 for (
const auto &
name : kinetic_redox)
178 mooseError(
name +
" exists more than once in the kinetic_redox list");
180 mooseError(
name +
" exists in both the basis_species and kinetic_redox lists");
189 const std::vector<std::string> & kinetic_surface_species)
192 for (
const auto &
name : kinetic_surface_species)
195 mooseError(
name +
" exists more than once in the kinetic_surface_species list");
216 bool all_species_in_basis_or_sec =
true;
220 all_species_in_basis_or_sec =
false;
223 if (all_species_in_basis_or_sec)
248 bool all_species_in_basis_or_sec =
true;
252 all_species_in_basis_or_sec =
false;
255 if (all_species_in_basis_or_sec)
272 bool all_species_in_basis_or_sec =
true;
276 all_species_in_basis_or_sec =
false;
279 if (all_species_in_basis_or_sec)
302 if (!(minerals.size() == 1 && minerals[0] ==
"*"))
309 bool known_basis_only =
true;
310 for (
const auto & basis_stoi : name_ms.second.basis_species)
315 known_basis_only =
false;
319 if (known_basis_only)
346 std::vector<Real> & redox_e_log10K)
350 redox_e_stoichiometry.assign(num_basis, 0.0);
351 redox_e_log10K.assign(numT, 0.0);
356 for (
unsigned i = 0; i < numT; ++i)
360 const Real stoi_coeff = react.second;
364 redox_e_stoichiometry[col] += react.second;
371 for (
unsigned i = 0; i < numT; ++i)
373 for (
unsigned col = 0; col < num_basis; ++col)
382 const std::vector<GeochemistryMineralSpecies> & mineral_info)
const
384 for (
const auto & mineral : mineral_info)
386 for (
const auto & element : mineral.basis_species)
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)
392 mooseError(
"The sorbing sites for " + mineral.name +
" include " + element.first +
393 " which is not in the basis_species list");
401 for (
const auto & element : gas.basis_species)
403 mooseError(
"The reaction for " + gas.name +
" depends on " + element.first +
404 " which is not reducable to a set of basis species");
411 for (
const auto & element : kr.basis_species)
413 mooseError(
"The reaction for " + kr.name +
" depends on " + element.first +
414 " which is not reducable to a set of basis species");
421 for (
const auto & element : kr.basis_species)
423 mooseError(
"The reaction for " + kr.name +
" depends on " + element.first +
424 " which is not reducable to a set of basis species");
467 species.molecular_weight;
480 es.
name = species.name;
484 overlap.push_back(es);
489 es.
name = species.name;
493 overlap.push_back(es);
498 for (
const auto & species : overlap)
528 std::vector<Real>(num_rows, 0.0);
534 std::vector<Real>(num_rows, 0.0);
540 for (
const auto & species : overlap)
542 species.molecular_weight;
548 species.molecular_volume;
552 if (species.surface_area != 0.0)
560 if (species.surface_area != 0.0)
577 for (
const auto & species : overlap)
580 for (
unsigned i = 0; i < num_temperatures; ++i)
582 for (
const auto & react : species.basis_species)
584 const Real stoi_coeff = react.second;
595 for (
unsigned i = 0; i < num_temperatures; ++i)
597 for (
unsigned col = 0; col < num_cols; ++col)
601 mooseError(
"Species " + species.name +
" includes " + react.first +
602 ", which cannot be expressed in terms of the basis. Previous checks must be "
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;
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());
624 const Real beta = redox_e_stoichiometry[o2_index];
634 std::vector<Real> stoi(num_cols, 0.0);
635 bool only_involves_basis_species =
true;
642 only_involves_basis_species =
false;
646 if (!only_involves_basis_species)
652 stoi[bs.second] = -1.0;
654 const Real alpha = stoi[o2_index];
659 for (
unsigned basis_i = 0; basis_i < num_cols; ++basis_i)
660 stoi[basis_i] *= -beta / alpha;
662 for (
unsigned basis_i = 0; basis_i < num_cols; ++basis_i)
663 stoi[basis_i] += redox_e_stoichiometry[basis_i];
665 redox_stoi.insert(redox_stoi.end(), stoi.begin(), stoi.end());
668 for (
unsigned temp = 0; temp < num_temperatures; ++temp)
670 redox_e_log10K[temp]);
675 const unsigned num_redox = redox_stoi.size() / num_cols;
677 for (
unsigned red = 0; red < num_redox; ++red)
678 for (
unsigned basis_i = 0; basis_i < num_cols; ++basis_i)
681 for (
unsigned red = 0; red < num_redox; ++red)
682 for (
unsigned temp = 0; temp < num_temperatures; ++temp)
691 ms.
name = species.name;
696 overlap_kin.push_back(ms);
701 ms.
name = species.name;
707 ms.
equilibrium_const.push_back(species.log10K + species.dlog10KdT * (temp - T0));
708 overlap_kin.push_back(ms);
710 const unsigned num_kin = overlap_kin.size();
714 for (
const auto & species : overlap_kin)
745 for (
const auto & species : overlap_kin)
747 species.molecular_weight;
751 for (
const auto & species : overlap_kin)
753 species.molecular_volume;
760 for (
const auto & species : overlap_kin)
763 for (
unsigned i = 0; i < num_temperatures; ++i)
765 for (
const auto & react : species.basis_species)
767 const Real stoi_coeff = react.second;
778 for (
unsigned i = 0; i < num_temperatures; ++i)
780 for (
unsigned col = 0; col < num_cols; ++col)
784 mooseError(
"Kinetic species " + species.name +
" includes " + react.first +
785 ", which cannot be expressed in terms of the basis. Previous checks must be "
791 std::vector<std::string> all_sorbing_sites;
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");
799 all_sorbing_sites.push_back(name_frac.first);
804 for (
const auto & name_info :
807 for (
const auto & name_frac :
808 name_info.second.sorption_sites)
813 bool mineral_involved_in_eqm =
false;
814 for (
const auto & name_frac :
815 name_info.second.sorption_sites)
818 for (
unsigned j = 0; j < num_rows; ++j)
821 mineral_involved_in_eqm =
true;
825 if (!mineral_involved_in_eqm)
830 for (
const auto & name_frac :
831 name_info.second.sorption_sites)
834 for (
unsigned j = 0; j < num_rows; ++j)
838 mooseError(
"It is an error for any equilibrium species (such as ",
840 ") to have a reaction involving more than one sorbing site");
860 mooseError(
"Cannot prescribe a kinetic rate to species ",
862 " since it is not a kinetic species");
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)
882 "Promoting species ", promoting_species,
" must be a basis or a secondary species");
887 unsigned progeny_num = 0;
893 mooseError(
"Progeny ", description.
progeny,
" must be a basis or a secondary species");
const GeochemicalDatabaseReader db("database/moose_testdb.json", true, true, false)
void mooseError(Args &&... args)
Class for reading geochemical reactions from a MOOSE geochemical database.
bool isBasisSpecies(const std::string &name) const
Checks if species is of given type.
std::map< std::string, GeochemistryGasSpecies > getGasSpecies(const std::vector< std::string > &names)
Get the gas species information.
std::vector< std::string > secondarySpeciesNames() const
Returns a list of all the names of the "secondary species" and "free electron" in the database.
std::map< std::string, GeochemistryEquilibriumSpecies > getEquilibriumSpecies(const std::vector< std::string > &names)
Get the secondary equilibrium species information.
std::map< std::string, GeochemistryRedoxSpecies > getRedoxSpecies(const std::vector< std::string > &names)
Get the redox species (couples) information.
std::vector< std::string > mineralSpeciesNames() const
Returns a list of all the names of the "mineral species" in the database.
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.
std::vector< std::string > surfaceSpeciesNames() const
Returns a list of all the names of the "surface species" in the database.
const std::vector< Real > & getTemperatures() const
Get the temperature points that the equilibrium constant is defined at.
std::map< std::string, GeochemistrySurfaceSpecies > getSurfaceSpecies(const std::vector< std::string > &names)
Get the surface sorbing species information.
std::vector< std::string > redoxCoupleNames() const
Returns a list of all the names of the "redox couples" in the database.
std::map< std::string, GeochemistryMineralSpecies > getMineralSpecies(const std::vector< std::string > &names)
Get the mineral species information.
std::vector< GeochemistryEquilibriumSpecies > _secondary_info
a vector of all relevant species
unsigned getIndexOfOriginalBasisSpecies(const std::string &name) const
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
const ModelGeochemicalDatabase & modelGeochemicalDatabase() const
Return a reference to the ModelGeochemicalDatabase structure.
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
void buildRedoxeInfo(std::vector< Real > &redox_e_stoichiometry, std::vector< Real > &redox_e_log10K)
Extract the stoichiometry and log10K for the _redox_e species.
const std::string _redox_e
The name of the free electron involved in redox reactions.
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)
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 addKineticRate(const KineticRateUserDescription &description)
Adds a rate description for kinetic_species.
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< std::string > originalBasisNames() const
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 ...
void resize(const unsigned int new_m, const unsigned int new_n)
Data structure for basis (primary) species.
Data structure for secondary equilibrium species.
std::vector< Real > equilibrium_const
std::map< std::string, Real > basis_species
Data structure for mineral species.
Data structure for mineral species.
std::map< std::string, Real > basis_species
std::vector< Real > equilibrium_const
Data structure for redox species.
std::vector< Real > equilibrium_const
std::map< std::string, Real > basis_species
Data structure for sorbing surface species.
std::map< std::string, Real > basis_species
A single rate expression for the kinetic species with index kinetic_species_index.
Holds a user-specified description of a kinetic rate.
std::vector< Real > promoting_indices
std::string kinetic_species_name
std::vector< std::string > promoting_species
std::vector< Real > promoting_monod_indices
std::vector< Real > promoting_half_saturation
Data structure to hold all relevant information from the database file.
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,...
DenseMatrix< Real > eqm_stoichiometry
eqm_stoichiometry(i, j) = stoichiometric coefficient for equilibrium species "i" in terms of the basi...
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< KineticRateDefinition > kin_rate
rates given to kinetic species.
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::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::vector< bool > kin_species_transported
kin_species_transported[j] = true iff the j^th kinetic species is transported in reactive-transport s...
std::unordered_map< std::string, std::vector< Real > > gas_chi
Holds info on gas fugacity "chi" parameters.
std::vector< Real > kin_species_charge
all kinetic quantities have a charge (mineral charge = 0)
std::unordered_map< std::string, unsigned > basis_species_index
basis_species_index[name] = index of the basis species, within all ModelGeochemicalDatabase internal ...
std::vector< std::string > surface_sorption_name
surface_sorption_name[k] = name of the mineral involved in surface sorption.
DenseMatrix< Real > eqm_log10K
eqm_log10K(i, j) = log10(equilibrium constant) for i^th equilibrium species at the j^th temperature p...
std::vector< bool > basis_species_gas
basis_species_gas[j] = true iff the j^th basis species is a gas
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
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