https://mooseframework.inl.gov
GeochemistryActivityCoefficientsDebyeHuckelTest.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "gtest/gtest.h"
11 
14 
15 const GeochemicalDatabaseReader database("database/moose_testdb.json", true, true, false);
16 // The following system has secondary species: (O-phth)--, CO2(aq), CO3--, CaCO3, CaOH+, OH-,
17 // >(s)FeO-, Calcite, seq_radius_neg1
20  {"H2O", "H+", "HCO3-", "O2(aq)", "Ca++", ">(s)FeOH", "radius_neg1", "radius_neg1.5"},
21  {"Calcite"},
22  {},
23  {"Calcite_asdf"},
24  {"CH4(aq)"},
25  {">(s)FeOCa+"},
26  "O2(aq)",
27  "e-");
29 
31 TEST(GeochemistryActivityCoefficientsDebyeHuckelTest, notDH)
32 {
33  const GeochemicalDatabaseReader database_notDH(
34  "database/faultydbs/notDH.json", true, true, false);
35  GeochemistryIonicStrength is(1.0E9, 2.0E9, false, false);
36  try
37  {
38  GeochemistryActivityCoefficientsDebyeHuckel ac_notDH(is, database_notDH);
39  FAIL() << "Missing expected exception.";
40  }
41  catch (const std::exception & e)
42  {
43  std::string msg(e.what());
44  ASSERT_TRUE(msg.find("Attempted to get Debye-Huckel activity parameters but the activity model "
45  "is NOTdebye-huckel") != std::string::npos)
46  << "Failed with unexpected error message: " << msg;
47  }
48 }
49 
51 TEST(GeochemistryActivityCoefficientsDebyeHuckelTest, noNeutral)
52 {
53  const GeochemicalDatabaseReader database_noNeutral(
54  "database/faultydbs/missing_DH.json", true, true, false);
55  GeochemistryIonicStrength is(1.0E9, 2.0E9, false, false);
56  GeochemistryActivityCoefficientsDebyeHuckel ac_noNeutral(is, database_noNeutral);
57  ac_noNeutral.setInternalParameters(
58  25.0, mgd, std::vector<Real>(8, 1.0), std::vector<Real>(9), std::vector<Real>(3));
59  const DebyeHuckelParameters dh = ac_noNeutral.getDebyeHuckel();
60 
61  EXPECT_EQ(dh.A, 0.5555);
62  EXPECT_EQ(dh.B, 0.3333);
63  EXPECT_EQ(dh.Bdot, 0.0444);
64  EXPECT_EQ(dh.a_water, 0.0);
65  EXPECT_EQ(dh.b_water, 0.0);
66  EXPECT_EQ(dh.c_water, 0.0);
67  EXPECT_EQ(dh.d_water, 0.0);
68  EXPECT_EQ(dh.a_neutral, 0.0);
69  EXPECT_EQ(dh.b_neutral, 0.0);
70  EXPECT_EQ(dh.c_neutral, 0.0);
71  EXPECT_EQ(dh.d_neutral, 0.0);
72 }
73 
75 TEST(GeochemistryActivityCoefficientsDebyeHuckelTest, ionicStrengthInterface)
76 {
77  GeochemistryIonicStrength is(1.0E9, 2.0E9, false, false);
79 
80  is.setUseOnlyBasisMolality(true);
81  is.setMaxStoichiometricIonicStrength(2.0E-8);
82 
83  Real gold_ionic_str = 0.0;
84  std::vector<Real> basis_m(8);
85  basis_m[mgd.basis_species_index.at("H2O")] = 1.0;
86  basis_m[mgd.basis_species_index.at("H+")] = 2.0;
87  gold_ionic_str += 2.0;
88  basis_m[mgd.basis_species_index.at("HCO3-")] = 3.0;
89  gold_ionic_str += 3.0;
90  basis_m[mgd.basis_species_index.at("O2(aq)")] = 4.0;
91  basis_m[mgd.basis_species_index.at("Ca++")] = 5.0;
92  gold_ionic_str += 4 * 5.0;
93  basis_m[mgd.basis_species_index.at(">(s)FeOH")] = 6.0;
94  basis_m[mgd.basis_species_index.at("radius_neg1")] = 7.0;
95  basis_m[mgd.basis_species_index.at("radius_neg1.5")] = 8.0;
96 
97  // the equilibrium and kinetic molalities do not make any difference due to ionic strength using
98  // only basis molalities
100  25.0, mgd, basis_m, std::vector<Real>(9, 1.1), std::vector<Real>(3, 2.2));
101 
102  EXPECT_NEAR(ac.getIonicStrength(), 0.5 * gold_ionic_str, 1E-8);
103  EXPECT_EQ(ac.getStoichiometricIonicStrength(), 2.0E-8);
104 }
105 
107 TEST(GeochemistryActivityCoefficientsDebyeHuckelTest, getDebyeHuckel)
108 {
109  GeochemistryIonicStrength is(1.0E9, 2.0E9, false, false);
112  25.0, mgd, std::vector<Real>(8, 1.0), std::vector<Real>(9), std::vector<Real>(3));
113  const DebyeHuckelParameters dh = ac.getDebyeHuckel();
114 
115  EXPECT_EQ(dh.A, 0.5092);
116  EXPECT_EQ(dh.B, 0.3283);
117  EXPECT_EQ(dh.Bdot, 0.041);
118  EXPECT_EQ(dh.a_water, 1.45397);
119  EXPECT_EQ(dh.b_water, 0.022357);
120  EXPECT_EQ(dh.c_water, 0.0093804);
121  EXPECT_EQ(dh.d_water, -0.0005362);
122  EXPECT_EQ(dh.a_neutral, 0.1127);
123  EXPECT_EQ(dh.b_neutral, -0.01049);
124  EXPECT_EQ(dh.c_neutral, 0.001545);
125  EXPECT_EQ(dh.d_neutral, 0.0);
126 }
127 
129 TEST(GeochemistryActivityCoefficientsDebyeHuckelTest, buildActivityCoefficientsDebyeHuckel)
130 {
131  GeochemistryIonicStrength is(1.0E9, 2.0E9, false, false);
134  25.0, mgd, std::vector<Real>(8, 1.0), std::vector<Real>(9), std::vector<Real>(3));
135 
136  const Real ionic_str = ac.getIonicStrength();
137 
138  std::vector<Real> basis_ac;
139  std::vector<Real> eqm_ac;
140  ac.buildActivityCoefficients(mgd, basis_ac, eqm_ac);
141 
142  EXPECT_EQ(basis_ac.size(), (std::size_t)8);
143  EXPECT_EQ(eqm_ac.size(), (std::size_t)9);
144 
145  const DebyeHuckelParameters dh = ac.getDebyeHuckel();
146 
147  // Note that GeochemistryActivity has been tested elsewhere: here we're just checking the slots
148  // get filled correctly
149  for (unsigned i = 1; i < 8; ++i) // don't loop over water
150  {
151  Real gold = 0.0;
152  if (i == 3) // O2(aq)
153  gold = std::pow(10.0,
155  ionic_str, dh.a_neutral, dh.b_neutral, dh.c_neutral, dh.d_neutral));
156  else if (i == 5) // >(s)FeOH
157  gold = 1.0;
158  else if (i == 6) // radius_neg1
159  gold = std::pow(
160  10.0,
162  else if (i == 7) // radius_neg1.5
163  gold = 1.0;
164  else
165  gold =
166  std::pow(10.0,
169  std::sqrt(ionic_str),
170  dh.A,
171  dh.B,
172  dh.Bdot));
173  ASSERT_NEAR(basis_ac[i], gold, 1.0E-8);
174  }
175 
176  for (unsigned j = 0; j < 9; ++j)
177  {
178  Real gold = 0.0;
179  const std::string nm = mgd.eqm_species_name[j];
180  if (nm == "Calcite")
181  continue;
182  else if (nm == "CO2(aq)" || nm == "CaCO3" || nm == ">(s)FeO-")
183  gold = 1.0;
184  else if (nm == "seq_radius_neg1")
185  gold = std::pow(
186  10.0,
188  else
189  gold =
190  std::pow(10.0,
193  std::sqrt(ionic_str),
194  dh.A,
195  dh.B,
196  dh.Bdot));
197  ASSERT_NEAR(eqm_ac[j], gold, 1.0E-8);
198  }
199 }
200 
202 TEST(GeochemistryActivityCoefficientsDebyeHuckelTest, waterActivity)
203 {
204  GeochemistryIonicStrength is(1.0E9, 2.0E9, false, false);
207  25.0, mgd, std::vector<Real>(8, 1.0), std::vector<Real>(9), std::vector<Real>(3));
208 
209  const DebyeHuckelParameters dh = ac.getDebyeHuckel();
210  const Real stoi_ionic_str = ac.getStoichiometricIonicStrength();
211 
212  // note that GeochemistryActivityCalculators::lnActivityDHBdotWater has been tested elsewhere:
213  // this is just testing the information gets passed through to
214  // GeochemistryActivityCoefficientsDebyeHuckel
215  EXPECT_NEAR(ac.waterActivity(),
217  stoi_ionic_str, dh.A, dh.a_water, dh.b_water, dh.c_water, dh.d_water)),
218  1.0E-8);
219 }
TEST(GeochemistryActivityCoefficientsDebyeHuckelTest, notDH)
Test errors when a non-DebyeHuckel database is read.
Real log10ActCoeffDHBdotNeutral(Real ionic_strength, Real a, Real b, Real c, Real d)
log10(activity coefficient) for neutral species according to the Debye-Huckel B-dot model ...
Real getIonicStrength() const
Return the current value of ionic strength.
std::unordered_map< std::string, unsigned > basis_species_index
basis_species_index[name] = index of the basis species, within all ModelGeochemicalDatabase internal ...
const ModelGeochemicalDatabase mgd
Real getStoichiometricIonicStrength() const
Return the current value of stoichiometric ionic strength.
void buildActivityCoefficients(const ModelGeochemicalDatabase &mgd, std::vector< Real > &basis_activity_coef, std::vector< Real > &eqm_activity_coef) const override
Compute the activity coefficients and store them in basis_activity_coef and eqm_activity_coef Note: ...
const GeochemicalDatabaseReader database("database/moose_testdb.json", true, true, false)
Real waterActivity() const override
Computes and returns the activity of water.
Real log10ActCoeffDHBdotAlternative(Real ionic_strength, Real Bdot)
log10(activity coefficient) alternative expression that is sometimes used in conjunction with the Deb...
std::vector< Real > basis_species_radius
all quantities have an ionic radius (Angstrom) for computing activity (mineral radius = 0...
Computes activity coefficients for non-minerals and non-gases (since these species do not have activi...
const ModelGeochemicalDatabase & modelGeochemicalDatabase() const
Return a reference to the ModelGeochemicalDatabase structure.
Constructs and stores a minimal amount of information that is pertinent to the user-defined geochemic...
Calculators to compute ionic strength and stoichiometric ionic strength.
PetscErrorCode PetscInt const PetscInt IS * is
const PertinentGeochemicalSystem model(database, {"H2O", "H+", "HCO3-", "O2(aq)", "Ca++", ">(s)FeOH", "radius_neg1", "radius_neg1.5"}, {"Calcite"}, {}, {"Calcite_asdf"}, {"CH4(aq)"}, {">(s)FeOCa+"}, "O2(aq)", "e-")
std::vector< Real > eqm_species_radius
all quantities have an ionic radius (Angstrom) for computing activity (mineral radius = 0...
Real lnActivityDHBdotWater(Real stoichiometric_ionic_strength, Real A, Real atilde, Real btilde, Real ctilde, Real dtilde)
ln(activity of water) according to the Debye-Huckel B-dot model
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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_charge
all quantities have a charge (mineral charge = 0, gas charge = 0, oxide charge = 0) ...
Data structure to hold all relevant information from the database file.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
Real log10ActCoeffDHBdot(Real charge, Real ion_size, Real sqrt_ionic_strength, Real A, Real B, Real Bdot)
log10(activity coefficient) according to the Debye-Huckel B-dot model
MooseUnits pow(const MooseUnits &, int)
std::vector< std::string > eqm_species_name
eqm_species_name[i] = name of the i^th eqm species
void setInternalParameters(Real temperature, const ModelGeochemicalDatabase &mgd, const std::vector< Real > &basis_species_molality, const std::vector< Real > &eqm_species_molality, const std::vector< Real > &kin_species_molality) override
Sets internal parameters, such as the ionic strength and Debye-Huckel parameters, prior to computing ...
Class for reading geochemical reactions from a MOOSE geochemical database.