LCOV - code coverage report
Current view: top level - src/utils - GeochemicalDatabaseReader.C (source / functions) Hit Total Coverage
Test: idaholab/moose geochemistry: 602416 Lines: 375 380 98.7 %
Date: 2025-07-18 11:37:48 Functions: 44 44 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "GeochemicalDatabaseReader.h"
      11             : #include "GeochemicalDatabaseValidator.h"
      12             : 
      13             : #include "MooseUtils.h"
      14             : #include "Conversion.h"
      15             : #include "string"
      16             : #include <fstream>
      17             : 
      18         949 : GeochemicalDatabaseReader::GeochemicalDatabaseReader(
      19             :     const FileName filename,
      20             :     const bool reexpress_free_electron,
      21             :     const bool use_piecewise_interpolation,
      22         949 :     const bool remove_all_extrapolated_secondary_species)
      23         949 :   : _filename(filename)
      24             : {
      25        1898 :   read(_filename);
      26         949 :   validate(_filename, _root);
      27             : 
      28         948 :   if (reexpress_free_electron)
      29         946 :     reexpressFreeElectron();
      30             : 
      31         948 :   if (use_piecewise_interpolation && _root["Header"].contains("logk model"))
      32         903 :     _root["Header"]["logk model"] = "piecewise-linear";
      33             : 
      34         948 :   if (remove_all_extrapolated_secondary_species)
      35           9 :     removeExtrapolatedSecondarySpecies();
      36             : 
      37         948 :   setTemperatures();
      38         948 :   setDebyeHuckel();
      39         948 :   setNeutralSpeciesActivity();
      40         952 : }
      41             : 
      42             : void
      43         949 : GeochemicalDatabaseReader::read(const FileName filename)
      44             : {
      45         949 :   MooseUtils::checkFileReadable(filename);
      46             : 
      47             :   // Read the JSON database
      48         949 :   std::ifstream jsondata(filename);
      49         949 :   jsondata >> _root;
      50         949 : }
      51             : 
      52             : void
      53         949 : GeochemicalDatabaseReader::validate(const FileName filename, const nlohmann::json & db)
      54             : {
      55             :   // Validate the JSON database so that we don't have to check array sizes,
      56             :   // check for conversion issues, etc when extracting data using get methods
      57         949 :   GeochemicalDatabaseValidator dbv(filename, db);
      58         949 :   dbv.validate();
      59         948 : }
      60             : 
      61             : void
      62         946 : GeochemicalDatabaseReader::reexpressFreeElectron()
      63             : {
      64        1717 :   if (!_root.contains("free electron") || !_root["free electron"].contains("e-") ||
      65         771 :       !_root["free electron"]["e-"]["species"].contains("O2(g)"))
      66         186 :     return;
      67         769 :   if (!_root.contains("basis species") || !_root["basis species"].contains("O2(aq)"))
      68           8 :     return;
      69        2281 :   if (!_root.contains("gas species") || !_root["gas species"].contains("O2(g)") ||
      70        1521 :       !_root["gas species"]["O2(g)"]["species"].contains("O2(aq)") ||
      71         760 :       (_root["gas species"]["O2(g)"]["species"].size() != 1))
      72           1 :     return;
      73             : 
      74             :   // remove O2(g) in the "e-" and replace with O2(aq)
      75             :   const std::string stoi_o2g =
      76         760 :       nlohmann::to_string(_root["free electron"]["e-"]["species"]["O2(g)"]);
      77         760 :   _root["free electron"]["e-"]["species"].erase("O2(g)");
      78         760 :   _root["free electron"]["e-"]["species"]["O2(aq)"] = stoi_o2g;
      79         760 :   const Real stoi = getReal(stoi_o2g);
      80             : 
      81             :   // alter equilibrium constants
      82         760 :   if (!_root["Header"].contains("temperatures"))
      83             :     return;
      84        6840 :   for (unsigned i = 0; i < _root["Header"]["temperatures"].size(); ++i)
      85             :   {
      86        6080 :     const Real logk_e = getReal(_root["free electron"]["e-"]["logk"][i]);
      87        6080 :     const Real logk_o2 = getReal(_root["gas species"]["O2(g)"]["logk"][i]);
      88        6080 :     const Real newk = logk_e + stoi * logk_o2;
      89       12160 :     _root["free electron"]["e-"]["logk"][i] = std::to_string(newk);
      90             :   }
      91             : }
      92             : 
      93             : void
      94           9 : GeochemicalDatabaseReader::removeExtrapolatedSecondarySpecies()
      95             : {
      96           9 :   if (_root.contains("secondary species"))
      97             :   {
      98             :     std::set<std::string> remove; // items to remove
      99        4433 :     for (const auto & item : _root["secondary species"].items())
     100        4415 :       if (item.value().contains("note"))
     101        2385 :         remove.insert(item.key());
     102             : 
     103        2394 :     for (const auto & name : remove)
     104        2385 :       _root["secondary species"].erase(name);
     105             :   }
     106           9 : }
     107             : 
     108             : std::string
     109        2161 : GeochemicalDatabaseReader::getActivityModel() const
     110             : {
     111        2161 :   return _root["Header"]["activity model"];
     112             : }
     113             : 
     114             : std::string
     115           1 : GeochemicalDatabaseReader::getFugacityModel() const
     116             : {
     117           1 :   return _root["Header"]["fugacity model"];
     118             : }
     119             : 
     120             : std::string
     121       17834 : GeochemicalDatabaseReader::getLogKModel() const
     122             : {
     123       17834 :   return _root["Header"]["logk model"];
     124             : }
     125             : 
     126             : void
     127         948 : GeochemicalDatabaseReader::setTemperatures()
     128             : {
     129         948 :   if (_root["Header"].contains("temperatures"))
     130             :   {
     131         948 :     auto temperatures = _root["Header"]["temperatures"];
     132         948 :     _temperature_points.resize(temperatures.size());
     133        8532 :     for (unsigned int i = 0; i < temperatures.size(); ++i)
     134        7584 :       _temperature_points[i] = getReal(temperatures[i]);
     135             :   }
     136         948 : }
     137             : 
     138             : const std::vector<Real> &
     139       21461 : GeochemicalDatabaseReader::getTemperatures() const
     140             : {
     141       21461 :   return _temperature_points;
     142             : }
     143             : 
     144             : std::vector<Real>
     145           1 : GeochemicalDatabaseReader::getPressures()
     146             : {
     147             :   // Read pressure points
     148           1 :   if (_root["Header"].contains("pressures"))
     149             :   {
     150           1 :     auto pressures = _root["Header"]["pressures"];
     151           1 :     _pressure_points.resize(pressures.size());
     152           9 :     for (unsigned int i = 0; i < pressures.size(); ++i)
     153           8 :       _pressure_points[i] = getReal(pressures[i]);
     154             :   }
     155             : 
     156           1 :   return _pressure_points;
     157             : }
     158             : 
     159             : void
     160         948 : GeochemicalDatabaseReader::setDebyeHuckel()
     161             : {
     162        1896 :   if (getActivityModel() == "debye-huckel")
     163             :   {
     164         947 :     if (_root["Header"].contains("adh"))
     165             :     {
     166         947 :       std::vector<Real> adhvals(_root["Header"]["adh"].size());
     167        8523 :       for (unsigned int i = 0; i < _root["Header"]["adh"].size(); ++i)
     168        7576 :         adhvals[i] = getReal(_root["Header"]["adh"][i]);
     169         947 :       _debye_huckel.adh = adhvals;
     170             :     }
     171             : 
     172         947 :     if (_root["Header"].contains("bdh"))
     173             :     {
     174         947 :       std::vector<Real> bdhvals(_root["Header"]["bdh"].size());
     175        8523 :       for (unsigned int i = 0; i < _root["Header"]["bdh"].size(); ++i)
     176        7576 :         bdhvals[i] = getReal(_root["Header"]["bdh"][i]);
     177         947 :       _debye_huckel.bdh = bdhvals;
     178             :     }
     179             : 
     180         947 :     if (_root["Header"].contains("bdot"))
     181             :     {
     182         947 :       std::vector<Real> bdotvals(_root["Header"]["bdot"].size());
     183        8523 :       for (unsigned int i = 0; i < _root["Header"]["bdot"].size(); ++i)
     184        7576 :         bdotvals[i] = getReal(_root["Header"]["bdot"][i]);
     185         947 :       _debye_huckel.bdot = bdotvals;
     186             :     }
     187             :   }
     188         948 : }
     189             : 
     190             : const GeochemistryDebyeHuckel &
     191        1211 : GeochemicalDatabaseReader::getDebyeHuckel() const
     192             : {
     193        2422 :   if (getActivityModel() != "debye-huckel")
     194           1 :     mooseError("Attempted to get Debye-Huckel activity parameters but the activity model is ",
     195           1 :                getActivityModel());
     196        1210 :   return _debye_huckel;
     197             : }
     198             : 
     199             : std::map<std::string, GeochemistryElements>
     200           1 : GeochemicalDatabaseReader::getElements()
     201             : {
     202           1 :   if (_root.contains("elements"))
     203             :   {
     204           4 :     for (auto & el : _root["elements"].items())
     205             :     {
     206           6 :       _elements[el.key()].name = el.value()["name"];
     207           2 :       _elements[el.key()].molecular_weight = getReal(el.value()["molecular weight"]);
     208             :     }
     209             :   }
     210             : 
     211           1 :   return _elements;
     212             : }
     213             : 
     214             : std::map<std::string, GeochemistryBasisSpecies>
     215        6278 : GeochemicalDatabaseReader::getBasisSpecies(const std::vector<std::string> & names)
     216             : {
     217             :   // Parse the basis species specified in names
     218       12557 :   for (const auto & species : names)
     219        6280 :     if (_root["basis species"].contains(species))
     220             :     {
     221             :       GeochemistryBasisSpecies dbs;
     222             : 
     223       12558 :       auto basis_species = _root["basis species"][species];
     224             :       dbs.name = species;
     225        6279 :       dbs.radius = getReal(basis_species["radius"]);
     226        6279 :       dbs.charge = getReal(basis_species["charge"]);
     227        6279 :       dbs.molecular_weight = getReal(basis_species["molecular weight"]);
     228             : 
     229             :       std::map<std::string, Real> elements;
     230       22281 :       for (auto & el : basis_species["elements"].items())
     231        9723 :         elements[el.key()] = getReal(el.value());
     232             : 
     233             :       dbs.elements = elements;
     234             : 
     235        6279 :       _basis_species[species] = dbs;
     236        6279 :     }
     237             :     else
     238           1 :       mooseError(species + " does not exist in database " + _filename);
     239             : 
     240        6277 :   return _basis_species;
     241             : }
     242             : 
     243             : std::map<std::string, GeochemistryEquilibriumSpecies>
     244      299007 : GeochemicalDatabaseReader::getEquilibriumSpecies(const std::vector<std::string> & names)
     245             : {
     246             :   // Parse the secondary species specified in names
     247      598017 :   for (const auto & species : names)
     248      299011 :     if (_root["secondary species"].contains(species) or _root["free electron"].contains(species))
     249             :     {
     250             :       GeochemistryEquilibriumSpecies dbs;
     251             : 
     252      299010 :       auto sec_species = _root["secondary species"].contains(species)
     253      597349 :                              ? _root["secondary species"][species]
     254      598020 :                              : _root["free electron"][species];
     255             :       dbs.name = species;
     256      299010 :       dbs.radius = getReal(sec_species["radius"]);
     257      299010 :       dbs.charge = getReal(sec_species["charge"]);
     258      299010 :       dbs.molecular_weight = getReal(sec_species["molecular weight"]);
     259             : 
     260      299010 :       std::vector<Real> eq_const(sec_species["logk"].size());
     261     2691090 :       for (unsigned int i = 0; i < sec_species["logk"].size(); ++i)
     262     2392080 :         eq_const[i] = getReal(sec_species["logk"][i]);
     263             : 
     264      299010 :       dbs.equilibrium_const = eq_const;
     265             : 
     266             :       std::map<std::string, Real> basis_species;
     267     1351822 :       for (auto & bs : sec_species["species"].items())
     268      753802 :         basis_species[bs.key()] = getReal(bs.value());
     269             : 
     270             :       dbs.basis_species = basis_species;
     271             : 
     272      299010 :       _equilibrium_species[species] = dbs;
     273      299010 :     }
     274             :     else
     275           1 :       mooseError(species + " does not exist in database " + _filename);
     276             : 
     277      299006 :   return _equilibrium_species;
     278             : }
     279             : 
     280             : std::map<std::string, GeochemistryMineralSpecies>
     281        1900 : GeochemicalDatabaseReader::getMineralSpecies(const std::vector<std::string> & names)
     282             : {
     283             :   // Parse the mineral species specified in names
     284        3803 :   for (const auto & species : names)
     285        1906 :     if (_root["mineral species"].contains(species))
     286             :     {
     287             :       GeochemistryMineralSpecies dbs;
     288             : 
     289        3806 :       auto mineral_species = _root["mineral species"][species];
     290             :       dbs.name = species;
     291        1903 :       dbs.molecular_weight = getReal(mineral_species["molecular weight"]);
     292        1903 :       dbs.molecular_volume = getReal(mineral_species["molar volume"]);
     293             : 
     294        1903 :       std::vector<Real> eq_const(mineral_species["logk"].size());
     295       17127 :       for (unsigned int i = 0; i < mineral_species["logk"].size(); ++i)
     296       15224 :         eq_const[i] = getReal(mineral_species["logk"][i]);
     297             : 
     298        1903 :       dbs.equilibrium_const = eq_const;
     299             : 
     300             :       std::map<std::string, Real> basis_species;
     301       10292 :       for (auto & bs : mineral_species["species"].items())
     302        6486 :         basis_species[bs.key()] = getReal(bs.value());
     303             : 
     304             :       dbs.basis_species = basis_species;
     305             : 
     306             :       // recover sorption information, if any
     307             :       std::map<std::string, Real> species_and_sorbing_density;
     308        1903 :       dbs.surface_area = 0.0;
     309        1903 :       if (_root["sorbing minerals"].contains(species))
     310             :       {
     311         113 :         auto sorbing_mineral = _root["sorbing minerals"][species];
     312         113 :         dbs.surface_area = getReal(sorbing_mineral["surface area"]);
     313             : 
     314         452 :         for (auto & site : sorbing_mineral["sorbing sites"].items())
     315         226 :           species_and_sorbing_density[site.key()] = getReal(site.value());
     316             :       }
     317             :       dbs.sorption_sites = species_and_sorbing_density;
     318             : 
     319        1903 :       _mineral_species[species] = dbs;
     320        1903 :     }
     321             :     else
     322           3 :       mooseError(species + " does not exist in database " + _filename);
     323             : 
     324        1897 :   return _mineral_species;
     325             : }
     326             : 
     327             : std::map<std::string, GeochemistryGasSpecies>
     328         344 : GeochemicalDatabaseReader::getGasSpecies(const std::vector<std::string> & names)
     329             : {
     330             :   // Parse the gas species specified in names
     331         687 :   for (const auto & species : names)
     332         345 :     if (_root["gas species"].contains(species))
     333             :     {
     334             :       GeochemistryGasSpecies dbs;
     335             : 
     336         686 :       auto gas_species = _root["gas species"][species];
     337             :       dbs.name = species;
     338         343 :       dbs.molecular_weight = getReal(gas_species["molecular weight"]);
     339             : 
     340         343 :       std::vector<Real> eq_const(gas_species["logk"].size());
     341        3087 :       for (unsigned int i = 0; i < gas_species["logk"].size(); ++i)
     342        2744 :         eq_const[i] = getReal(gas_species["logk"][i]);
     343             : 
     344         343 :       dbs.equilibrium_const = eq_const;
     345             : 
     346             :       std::map<std::string, Real> basis_species;
     347        1389 :       for (auto & bs : gas_species["species"].items())
     348         703 :         basis_species[bs.key()] = getReal(bs.value());
     349             : 
     350             :       dbs.basis_species = basis_species;
     351             : 
     352             :       // Optional fugacity coefficients
     353         343 :       if (gas_species.contains("chi"))
     354             :       {
     355         186 :         std::vector<Real> chi(gas_species["chi"].size());
     356        1302 :         for (unsigned int i = 0; i < gas_species["chi"].size(); ++i)
     357        1116 :           chi[i] = getReal(gas_species["chi"][i]);
     358             : 
     359         186 :         dbs.chi = chi;
     360             :       }
     361             : 
     362         343 :       if (gas_species.contains("Pcrit"))
     363         343 :         dbs.Pcrit = getReal(gas_species["Pcrit"]);
     364             : 
     365         343 :       if (gas_species.contains("Tcrit"))
     366         343 :         dbs.Tcrit = getReal(gas_species["Tcrit"]);
     367             : 
     368         343 :       if (gas_species.contains("omega"))
     369         343 :         dbs.omega = getReal(gas_species["omega"]);
     370             : 
     371         343 :       _gas_species[species] = dbs;
     372         343 :     }
     373             :     else
     374           2 :       mooseError(species + " does not exist in database " + _filename);
     375             : 
     376         342 :   return _gas_species;
     377             : }
     378             : 
     379             : std::map<std::string, GeochemistryRedoxSpecies>
     380       29730 : GeochemicalDatabaseReader::getRedoxSpecies(const std::vector<std::string> & names)
     381             : {
     382             :   // Parse the redox species specified in names
     383       59458 :   for (const auto & species : names)
     384       29730 :     if (_root["redox couples"].contains(species))
     385             :     {
     386             :       GeochemistryRedoxSpecies dbs;
     387             : 
     388       59456 :       auto redox_species = _root["redox couples"][species];
     389             :       dbs.name = species;
     390       29728 :       dbs.radius = getReal(redox_species["radius"]);
     391       29728 :       dbs.charge = getReal(redox_species["charge"]);
     392       29728 :       dbs.molecular_weight = getReal(redox_species["molecular weight"]);
     393             : 
     394       29728 :       std::vector<Real> eq_const(redox_species["logk"].size());
     395      267552 :       for (unsigned int i = 0; i < redox_species["logk"].size(); ++i)
     396      237824 :         eq_const[i] = getReal(redox_species["logk"][i]);
     397             : 
     398       29728 :       dbs.equilibrium_const = eq_const;
     399             : 
     400             :       std::map<std::string, Real> basis_species;
     401      171844 :       for (auto & bs : redox_species["species"].items())
     402      112388 :         basis_species[bs.key()] = getReal(bs.value());
     403             : 
     404             :       dbs.basis_species = basis_species;
     405             : 
     406       29728 :       _redox_species[species] = dbs;
     407       29728 :     }
     408             :     else
     409           2 :       mooseError(species + " does not exist in database " + _filename);
     410             : 
     411       29728 :   return _redox_species;
     412             : }
     413             : 
     414             : std::map<std::string, GeochemistryOxideSpecies>
     415           2 : GeochemicalDatabaseReader::getOxideSpecies(const std::vector<std::string> & names)
     416             : {
     417             :   // Parse the oxide species specified in names
     418           3 :   for (auto & species : names)
     419           2 :     if (_root["oxides"].contains(species))
     420             :     {
     421             :       GeochemistryOxideSpecies dbs;
     422             : 
     423           2 :       auto oxide_species = _root["oxides"][species];
     424             :       dbs.name = species;
     425           1 :       dbs.molecular_weight = getReal(oxide_species["molecular weight"]);
     426             : 
     427             :       std::map<std::string, Real> basis_species;
     428           5 :       for (auto & bs : oxide_species["species"].items())
     429           3 :         basis_species[bs.key()] = getReal(bs.value());
     430             : 
     431             :       dbs.basis_species = basis_species;
     432             : 
     433           1 :       _oxide_species[species] = dbs;
     434           1 :     }
     435             :     else
     436           1 :       mooseError(species + " does not exist in database " + _filename);
     437             : 
     438           1 :   return _oxide_species;
     439             : }
     440             : 
     441             : std::map<std::string, GeochemistrySurfaceSpecies>
     442       10927 : GeochemicalDatabaseReader::getSurfaceSpecies(const std::vector<std::string> & names)
     443             : {
     444             :   // Parse the secondary species specified in names
     445       21852 :   for (const auto & species : names)
     446       10927 :     if (_root["surface species"].contains(species))
     447             :     {
     448             :       GeochemistrySurfaceSpecies dbs;
     449             : 
     450       21850 :       auto surface_species = _root["surface species"][species];
     451             :       dbs.name = species;
     452       10925 :       dbs.charge = getReal(surface_species["charge"]);
     453       10925 :       dbs.molecular_weight = getReal(surface_species["molecular weight"]);
     454       10925 :       dbs.log10K = getReal(surface_species["log K"]);
     455       10925 :       dbs.dlog10KdT = getReal(surface_species["dlogK/dT"]);
     456             : 
     457             :       std::map<std::string, Real> basis_species;
     458       54006 :       for (auto & bs : surface_species["species"].items())
     459       32156 :         basis_species[bs.key()] = getReal(bs.value());
     460             : 
     461             :       dbs.basis_species = basis_species;
     462             : 
     463       10925 :       _surface_species[species] = dbs;
     464       10925 :     }
     465             :     else
     466           2 :       mooseError(species + " does not exist in database " + _filename);
     467             : 
     468       10925 :   return _surface_species;
     469             : }
     470             : 
     471             : void
     472         948 : GeochemicalDatabaseReader::setNeutralSpeciesActivity()
     473             : {
     474         948 :   if (_root["Header"].contains("neutral species"))
     475             :   {
     476         947 :     auto neutral_species = _root["Header"]["neutral species"];
     477        3787 :     for (auto & ns : neutral_species.items())
     478             :     {
     479             :       std::vector<std::vector<Real>> coeffs;
     480             : 
     481       11884 :       for (auto & nsac : ns.value().items())
     482             :       {
     483       16196 :         if (nsac.key() == "note")
     484         767 :           continue;
     485        7331 :         std::vector<Real> coeffvec(nsac.value().size());
     486             : 
     487       65979 :         for (unsigned int i = 0; i < coeffvec.size(); ++i)
     488       58648 :           coeffvec[i] = getReal(nsac.value()[i]);
     489             : 
     490        7331 :         coeffs.push_back(coeffvec);
     491             :       }
     492             : 
     493             :       // GeochemistryNeutralSpeciesActivity expects four vectos, so
     494             :       // add empty vectors if coeffs.size() != 4
     495        1893 :       coeffs.resize(4, {});
     496             : 
     497        1893 :       GeochemistryNeutralSpeciesActivity nsa(coeffs);
     498             : 
     499        1893 :       _neutral_species_activity[ns.key()] = nsa;
     500        1893 :     }
     501             :   }
     502         948 : }
     503             : 
     504             : const std::map<std::string, GeochemistryNeutralSpeciesActivity> &
     505        4836 : GeochemicalDatabaseReader::getNeutralSpeciesActivity() const
     506             : {
     507        4836 :   if (!_root["Header"].contains("neutral species"))
     508           1 :     mooseError("No neutral species activity coefficients in database");
     509        4835 :   return _neutral_species_activity;
     510             : }
     511             : 
     512             : std::vector<std::string>
     513           2 : GeochemicalDatabaseReader::equilibriumReactions(const std::vector<std::string> & names) const
     514             : {
     515           2 :   std::vector<std::map<std::string, Real>> basis_species(names.size());
     516             : 
     517           7 :   for (unsigned int i = 0; i < names.size(); ++i)
     518             :   {
     519           6 :     auto species = names[i];
     520             : 
     521           6 :     if (_root["secondary species"].contains(species))
     522             :     {
     523           5 :       auto sec_species = _root["secondary species"][species];
     524             : 
     525             :       // The basis species in this reaction
     526             :       std::map<std::string, Real> this_basis_species;
     527          23 :       for (auto & bs : sec_species["species"].items())
     528          13 :         this_basis_species[bs.key()] = getReal(bs.value());
     529             : 
     530             :       basis_species[i] = this_basis_species;
     531             :     }
     532             :     else
     533           2 :       mooseError(species + " does not exist in database " + _filename);
     534             :   }
     535             : 
     536           1 :   auto reactions = printReactions(names, basis_species);
     537             : 
     538           1 :   return reactions;
     539           2 : }
     540             : 
     541             : std::vector<std::string>
     542           2 : GeochemicalDatabaseReader::mineralReactions(const std::vector<std::string> & names) const
     543             : {
     544           2 :   std::vector<std::map<std::string, Real>> basis_species(names.size());
     545             : 
     546           3 :   for (unsigned int i = 0; i < names.size(); ++i)
     547             :   {
     548           2 :     const auto species = names[i];
     549             : 
     550           2 :     if (_root["mineral species"].contains(species))
     551             :     {
     552           1 :       auto min_species = _root["mineral species"][species];
     553             : 
     554             :       // The basis species in this reaction
     555             :       std::map<std::string, Real> this_basis_species;
     556           5 :       for (auto & bs : min_species["species"].items())
     557           3 :         this_basis_species[bs.key()] = getReal(bs.value());
     558             : 
     559             :       basis_species[i] = this_basis_species;
     560             :     }
     561             :     else
     562           2 :       mooseError(species + " does not exist in database " + _filename);
     563             :   }
     564             : 
     565           1 :   auto reactions = printReactions(names, basis_species);
     566             : 
     567           1 :   return reactions;
     568           2 : }
     569             : 
     570             : std::vector<std::string>
     571           2 : GeochemicalDatabaseReader::gasReactions(const std::vector<std::string> & names) const
     572             : {
     573           2 :   std::vector<std::map<std::string, Real>> basis_species(names.size());
     574             : 
     575           4 :   for (unsigned int i = 0; i < names.size(); ++i)
     576             :   {
     577           3 :     const auto species = names[i];
     578             : 
     579           3 :     if (_root["gas species"].contains(species))
     580             :     {
     581           2 :       auto gas_species = _root["gas species"][species];
     582             : 
     583             :       // The basis species in this reaction
     584             :       std::map<std::string, Real> this_basis_species;
     585           6 :       for (auto & bs : gas_species["species"].items())
     586           2 :         this_basis_species[bs.key()] = getReal(bs.value());
     587             : 
     588             :       basis_species[i] = this_basis_species;
     589             :     }
     590             :     else
     591           2 :       mooseError(species + " does not exist in database " + _filename);
     592             :   }
     593             : 
     594           1 :   auto reactions = printReactions(names, basis_species);
     595             : 
     596           1 :   return reactions;
     597           2 : }
     598             : 
     599             : std::vector<std::string>
     600           2 : GeochemicalDatabaseReader::redoxReactions(const std::vector<std::string> & names) const
     601             : {
     602           2 :   std::vector<std::map<std::string, Real>> basis_species(names.size());
     603             : 
     604           4 :   for (unsigned int i = 0; i < names.size(); ++i)
     605             :   {
     606           3 :     const auto species = names[i];
     607             : 
     608           3 :     if (_root["redox couples"].contains(species))
     609             :     {
     610           2 :       auto redox_species = _root["redox couples"][species];
     611             : 
     612             :       // The basis species in this reaction
     613             :       std::map<std::string, Real> this_basis_species;
     614          12 :       for (auto & bs : redox_species["species"].items())
     615           8 :         this_basis_species[bs.key()] = getReal(bs.value());
     616             : 
     617             :       basis_species[i] = this_basis_species;
     618             :     }
     619             :     else
     620           2 :       mooseError(species + " does not exist in database " + _filename);
     621             :   }
     622             : 
     623           1 :   auto reactions = printReactions(names, basis_species);
     624             : 
     625           1 :   return reactions;
     626           2 : }
     627             : 
     628             : std::vector<std::string>
     629           2 : GeochemicalDatabaseReader::oxideReactions(const std::vector<std::string> & names) const
     630             : {
     631           2 :   std::vector<std::map<std::string, Real>> basis_species(names.size());
     632             : 
     633           3 :   for (unsigned int i = 0; i < names.size(); ++i)
     634             :   {
     635           2 :     const auto species = names[i];
     636             : 
     637           2 :     if (_root["oxides"].contains(species))
     638             :     {
     639           1 :       auto oxide_species = _root["oxides"][species];
     640             : 
     641             :       // The basis species in this reaction
     642             :       std::map<std::string, Real> this_basis_species;
     643           5 :       for (auto & bs : oxide_species["species"].items())
     644           3 :         this_basis_species[bs.key()] = getReal(bs.value());
     645             : 
     646             :       basis_species[i] = this_basis_species;
     647             :     }
     648             :     else
     649           2 :       mooseError(species + " does not exist in database " + _filename);
     650             :   }
     651             : 
     652           1 :   auto reactions = printReactions(names, basis_species);
     653             : 
     654           1 :   return reactions;
     655           2 : }
     656             : 
     657             : std::vector<std::string>
     658           5 : GeochemicalDatabaseReader::printReactions(
     659             :     const std::vector<std::string> & names,
     660             :     const std::vector<std::map<std::string, Real>> & basis_species) const
     661             : {
     662             :   std::vector<std::string> reactions;
     663             : 
     664          16 :   for (unsigned int i = 0; i < names.size(); ++i)
     665             :   {
     666          11 :     std::string reaction = "";
     667          40 :     for (auto & bs : basis_species[i])
     668             :     {
     669          29 :       if (bs.second < 0.0)
     670             :       {
     671          10 :         if (bs.second == -1.0)
     672          12 :           reaction += " - " + bs.first;
     673             :         else
     674           8 :           reaction += " " + Moose::stringify(bs.second) + bs.first;
     675             :       }
     676             :       else
     677             :       {
     678          19 :         if (bs.second == 1.0)
     679          30 :           reaction += " + " + bs.first;
     680             :         else
     681           8 :           reaction += " + " + Moose::stringify(bs.second) + bs.first;
     682             :       }
     683             :     }
     684             : 
     685             :     // Trim off leading +
     686          11 :     if (reaction.size() > 1 && reaction[1] == '+')
     687           9 :       reaction.erase(1, 2);
     688             : 
     689          22 :     reactions.push_back(names[i] + " =" + reaction);
     690             :   }
     691             : 
     692           5 :   return reactions;
     693           0 : }
     694             : 
     695             : std::vector<std::string>
     696           2 : GeochemicalDatabaseReader::mineralSpeciesNames() const
     697             : {
     698             :   std::vector<std::string> names;
     699           2 :   if (_root.contains("mineral species"))
     700          17 :     for (auto & item : _root["mineral species"].items())
     701          13 :       names.push_back(item.key());
     702           2 :   return names;
     703           0 : }
     704             : 
     705             : std::vector<std::string>
     706        1833 : GeochemicalDatabaseReader::secondarySpeciesNames() const
     707             : {
     708             :   std::vector<std::string> names;
     709        1833 :   if (_root.contains("secondary species"))
     710      479654 :     for (auto & item : _root["secondary species"].items())
     711      475990 :       names.push_back(item.key());
     712             : 
     713        1833 :   if (_root.contains("free electron"))
     714        4977 :     for (const auto & nm : _root["free electron"].items())
     715        1659 :       names.push_back(nm.key());
     716        1833 :   return names;
     717           0 : }
     718             : 
     719             : std::vector<std::string>
     720        1164 : GeochemicalDatabaseReader::redoxCoupleNames() const
     721             : {
     722             :   std::vector<std::string> names;
     723        1164 :   if (_root.contains("redox couples"))
     724       31532 :     for (const auto & item : _root["redox couples"].items())
     725       29204 :       names.push_back(item.key());
     726        1164 :   return names;
     727           0 : }
     728             : 
     729             : std::vector<std::string>
     730        1164 : GeochemicalDatabaseReader::surfaceSpeciesNames() const
     731             : {
     732             :   std::vector<std::string> names;
     733        1164 :   if (_root.contains("surface species"))
     734       12160 :     for (const auto & item : _root["surface species"].items())
     735       10922 :       names.push_back(item.key());
     736        1164 :   return names;
     737           0 : }
     738             : 
     739             : const FileName &
     740           2 : GeochemicalDatabaseReader::filename() const
     741             : {
     742           2 :   return _filename;
     743             : }
     744             : 
     745             : bool
     746        6984 : GeochemicalDatabaseReader::isBasisSpecies(const std::string & name) const
     747             : {
     748        6984 :   return _root["basis species"].contains(name);
     749             : }
     750             : 
     751             : bool
     752        3796 : GeochemicalDatabaseReader::isRedoxSpecies(const std::string & name) const
     753             : {
     754        3796 :   return _root["redox couples"].contains(name);
     755             : }
     756             : 
     757             : bool
     758          13 : GeochemicalDatabaseReader::isSorbingMineral(const std::string & name) const
     759             : {
     760          13 :   return _root["sorbing minerals"].contains(name);
     761             : }
     762             : 
     763             : bool
     764          28 : GeochemicalDatabaseReader::isSecondarySpecies(const std::string & name) const
     765             : {
     766          28 :   return _root["secondary species"].contains(name) || _root["free electron"].contains(name);
     767             : }
     768             : 
     769             : bool
     770          13 : GeochemicalDatabaseReader::isGasSpecies(const std::string & name) const
     771             : {
     772          13 :   return _root["gas species"].contains(name);
     773             : }
     774             : 
     775             : bool
     776          13 : GeochemicalDatabaseReader::isMineralSpecies(const std::string & name) const
     777             : {
     778          13 :   return _root["mineral species"].contains(name);
     779             : }
     780             : 
     781             : bool
     782          13 : GeochemicalDatabaseReader::isOxideSpecies(const std::string & name) const
     783             : {
     784          13 :   return _root["oxides"].contains(name);
     785             : }
     786             : 
     787             : bool
     788          13 : GeochemicalDatabaseReader::isSurfaceSpecies(const std::string & name) const
     789             : {
     790          13 :   return _root["surface species"].contains(name);
     791             : }
     792             : 
     793             : std::string
     794           2 : GeochemicalDatabaseReader::getSpeciesData(const std::string name) const
     795             : {
     796             :   std::string output;
     797          26 :   for (auto & item : _root.items())
     798          22 :     if (_root[item.key()].contains(name))
     799             :     {
     800           1 :       std::ostringstream os;
     801           2 :       os << item.value()[name].dump(4);
     802           1 :       output = os.str();
     803           1 :     }
     804             : 
     805           2 :   if (output.empty())
     806           1 :     mooseError(name + " is not a species in the database");
     807             : 
     808           3 :   return name + ":\n" + output;
     809             : }
     810             : 
     811             : Real
     812     4720437 : GeochemicalDatabaseReader::getReal(const nlohmann::json & node)
     813             : {
     814     4720437 :   if (node.is_string())
     815      263510 :     return MooseUtils::convert<Real>(node);
     816     4588682 :   return node;
     817             : }

Generated by: LCOV version 1.14