LCOV - code coverage report
Current view: top level - include/utils - GeochemicalSystem.h (source / functions) Hit Total Coverage
Test: idaholab/moose geochemistry: 602416 Lines: 74 74 100.0 %
Date: 2025-07-18 11:37:48 Functions: 3 3 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             : #pragma once
      11             : 
      12             : #include "MultiMooseEnum.h"
      13             : #include "PertinentGeochemicalSystem.h"
      14             : #include "GeochemistrySpeciesSwapper.h"
      15             : #include "GeochemistryActivityCoefficientsDebyeHuckel.h"
      16             : #include "GeochemistryConstants.h"
      17             : #include "GeochemistryUnitConverter.h"
      18             : 
      19             : /**
      20             :  * This class holds information about bulk composition, molalities, activities, activity
      21             :  * coefficients, etc of the user-defined geochemical system in PertinentGeochemicalSystem.  Hence,
      22             :  * it extends the generic information in PertinentGeochemicalSystem to a system that is specific to
      23             :  * one spatio-temporal location.  It offers methods to manipulate these molalities, bulk
      24             :  * compositions, etc, as well as performing basis swaps.
      25             :  *
      26             :  * Related to this, this class also builds the so-called "algebraic system" which is the nonlinear
      27             :  * system of algebraic equations for the unknown basis molalities, surface potentials and mole
      28             :  * number of kinetic species, and computes the residual vector and jacobian of this algebraic
      29             :  * system.  This class initialises the algebraic variables (the unknown molalities, surface
      30             :  * potentials and kinetic moles) to reaponable values, but it does not solve the algebraic system:
      31             :  * instead, it has a "setter" method, setAlgebraicValues that can be used to set the unknowns, hence
      32             :  * another class can use whatever method it desires to solve the system.
      33             :  *
      34             :  * WARNING: because GeochemicalSystem performs swaps, it will change the
      35             :  * ModelGeochemicalDatabase object.
      36             :  * WARNING: because GeochemicalSystem sets internal parameters in the
      37             :  * activity-coefficient object, it will change the GeochemistryActivityCoefficient object.
      38             :  */
      39             : class GeochemicalSystem
      40             : {
      41             : public:
      42             :   /**
      43             :    * Each basis species has one of the following constraints.  During the process of units
      44             :    * conversion (from user-prescribed units to mole-based units) each ConstraintMeaningUserEnum
      45             :    * supplied by the user is translated to the appropriate ConstraintMeaningEnum
      46             :    */
      47             :   enum class ConstraintMeaningEnum
      48             :   {
      49             :     MOLES_BULK_WATER,
      50             :     KG_SOLVENT_WATER,
      51             :     MOLES_BULK_SPECIES,
      52             :     FREE_MOLALITY,
      53             :     FREE_MOLES_MINERAL_SPECIES,
      54             :     FUGACITY,
      55             :     ACTIVITY
      56             :   };
      57             : 
      58             :   /// Each basis species must be provided with a constraint, that is chosen by the user from the following enum
      59             :   enum class ConstraintUserMeaningEnum
      60             :   {
      61             :     KG_SOLVENT_WATER,
      62             :     BULK_COMPOSITION,
      63             :     BULK_COMPOSITION_WITH_KINETIC,
      64             :     FREE_CONCENTRATION,
      65             :     FREE_MINERAL,
      66             :     ACTIVITY,
      67             :     LOG10ACTIVITY,
      68             :     FUGACITY,
      69             :     LOG10FUGACITY
      70             :   };
      71             : 
      72             :   /**
      73             :    * Construct the geochemical system, check consistency of the constructor's arguments,
      74             :   and initialize all internal variables (molalities, bulk compositions, equilibrium constants,
      75             :   activities, activity coefficients, surface potentials and kinetic mole numbers) and set up the
      76             :   algebraic system
      77             :    * @param mgd the model's geochemical database, which is a model-specific version of the full
      78             :   geochemical database.  WARNING: because GeochemicalSystem performs swaps, it will
      79             :   change mgd
      80             :   * @param gac the object that computes activity coefficients.  WARNING: because
      81             :   GeochemicalSystem sets internal parameters in gac, it will change it.
      82             :   * @param is object to compute ionic strengths
      83             :   * @param swapper object to perform swaps on mgd
      84             :    * @param swap_out_of_basis A list of basis species that should be swapped out of the basis and
      85             :   replaced with swap_into_basis, prior to any other computations
      86             :    * @param swap_into_basis A list of equilibrium species that should be swapped into the basis in
      87             :   place of swap_out_of_basis
      88             :    * @param charge_balance_species The charge-balance species, which must be a basis species after
      89             :   the swaps are performed
      90             :    * @param constrained_species A list of the basis species after the swaps have been performed
      91             :    * @param constraint_values Numerical values of the constraints placed on the basis species.  Each
      92             :   basis species must have exactly one constraint
      93             :    * @param constraint_unit Units of the constraint_values.  Each constraint_value must have
      94             :   exactly one constraint_unit.  This is only used during construction, to convert the
      95             :   constraint_values to mole units
      96             :    * @param constraint_user_meaning A list the provides physical meaning to the constraint_values
      97             :    * @param initial_temperature Initial temperature
      98             :    * @param iters_to_make_consistent The initial equilibrium molalities depend on the activity
      99             :   coefficients, which depend on the basis and equilibrium molalities.  This circular dependence
     100             :   means it is usually impossible to define an exactly consistent initial configuration for
     101             :   molalities.  An iterative process is used to approach the consistent initial configuration, using
     102             :   iters_to_make_consistent iterations.  Usually iters_to_make_consistent=0 is reasonable, because
     103             :   there are so many approximations used in the solution process that a slightly inconsistent initial
     104             :   configuration is fine
     105             :    * @param min_initial_molality Minimum value of equilibrium molality used in the initial condition
     106             :    * @param kin_name Names of the kinetic species that are provided with initial conditions in
     107             :   kin_initial_moles.  All kinetic species must be provided with an initial condition
     108             :    * @param kin_initial Values of the initial mole number or mass or volume (depending on
     109             :   kin_unit) for the kinetic species
     110             :    * @param kin_unit The units of the numbers given in kin_initial
     111             :    */
     112             :   GeochemicalSystem(ModelGeochemicalDatabase & mgd,
     113             :                     GeochemistryActivityCoefficients & gac,
     114             :                     GeochemistryIonicStrength & is,
     115             :                     GeochemistrySpeciesSwapper & swapper,
     116             :                     const std::vector<std::string> & swap_out_of_basis,
     117             :                     const std::vector<std::string> & swap_into_basis,
     118             :                     const std::string & charge_balance_species,
     119             :                     const std::vector<std::string> & constrained_species,
     120             :                     const std::vector<Real> & constraint_value,
     121             :                     const MultiMooseEnum & constraint_unit,
     122             :                     const MultiMooseEnum & constraint_user_meaning,
     123             :                     Real initial_temperature,
     124             :                     unsigned iters_to_make_consistent,
     125             :                     Real min_initial_molality,
     126             :                     const std::vector<std::string> & kin_name,
     127             :                     const std::vector<Real> & kin_initial_moles,
     128             :                     const MultiMooseEnum & kin_unit);
     129             : 
     130             :   GeochemicalSystem(
     131             :       ModelGeochemicalDatabase & mgd,
     132             :       GeochemistryActivityCoefficients & gac,
     133             :       GeochemistryIonicStrength & is,
     134             :       GeochemistrySpeciesSwapper & swapper,
     135             :       const std::vector<std::string> & swap_out_of_basis,
     136             :       const std::vector<std::string> & swap_into_basis,
     137             :       const std::string & charge_balance_species,
     138             :       const std::vector<std::string> & constrained_species,
     139             :       const std::vector<Real> & constraint_value,
     140             :       const std::vector<GeochemistryUnitConverter::GeochemistryUnit> & constraint_unit,
     141             :       const std::vector<ConstraintUserMeaningEnum> & constraint_user_meaning,
     142             :       Real initial_temperature,
     143             :       unsigned iters_to_make_consistent,
     144             :       Real min_initial_molality,
     145             :       const std::vector<std::string> & kin_name,
     146             :       const std::vector<Real> & kin_initial,
     147             :       const std::vector<GeochemistryUnitConverter::GeochemistryUnit> & kin_unit);
     148             : 
     149             :   /**
     150             :    * Copy assignment operator.  Almost all of the following is trivial.  The most important
     151             :    * non-trivial feature is copying src._mgd into our _mgd.  Note this method gets called when
     152             :    * dest = src
     153             :    * and dest is already constructed.  (Code such as GeochemicalSystem dest = src uses the copy
     154             :    * constructor which simply sets the _mgd reference in dest equal to the _mgd reference in src,
     155             :    * and does not make a copy of the data within src._mgd)
     156             :    */
     157         863 :   GeochemicalSystem & operator=(const GeochemicalSystem & src)
     158             :   {
     159         863 :     if (this == &src) // trivial a=a situation
     160             :       return *this;
     161             :     // check for bad assignment situations.  Other "const" things that
     162             :     // needn't be the same (but probably actually are) include: _swap_out and _swap_in
     163         862 :     if (_num_basis != src._num_basis || _num_eqm != src._num_eqm || _num_redox != src._num_redox ||
     164        1725 :         _num_surface_pot != src._num_surface_pot || _num_kin != src._num_kin ||
     165         861 :         _original_charge_balance_species != src._original_charge_balance_species)
     166           3 :       mooseError("GeochemicalSystem: copy assigment operator called with inconsistent fundamental "
     167             :                  "properties");
     168             :     // actually do the copying
     169         860 :     _mgd = src._mgd;
     170         860 :     _swapper = src._swapper;
     171             :     _gac = src._gac;
     172         860 :     _is = src._is;
     173         860 :     _charge_balance_species = src._charge_balance_species;
     174         860 :     _charge_balance_basis_index = src._charge_balance_basis_index;
     175         860 :     _constrained_species = src._constrained_species;
     176         860 :     _constraint_value = src._constraint_value;
     177         860 :     _original_constraint_value = src._original_constraint_value;
     178         860 :     _constraint_unit = src._constraint_unit;
     179         860 :     _constraint_user_meaning = src._constraint_user_meaning;
     180         860 :     _constraint_meaning = src._constraint_meaning;
     181         860 :     _eqm_log10K = src._eqm_log10K;
     182         860 :     _redox_log10K = src._redox_log10K;
     183         860 :     _kin_log10K = src._kin_log10K;
     184         860 :     _num_basis_in_algebraic_system = src._num_basis_in_algebraic_system;
     185         860 :     _num_in_algebraic_system = src._num_in_algebraic_system;
     186         860 :     _in_algebraic_system = src._in_algebraic_system;
     187         860 :     _algebraic_index = src._algebraic_index;
     188         860 :     _basis_index = src._basis_index;
     189         860 :     _bulk_moles_old = src._bulk_moles_old;
     190         860 :     _basis_molality = src._basis_molality;
     191         860 :     _basis_activity_known = src._basis_activity_known;
     192         860 :     _basis_activity = src._basis_activity;
     193         860 :     _eqm_molality = src._eqm_molality;
     194         860 :     _basis_activity_coef = src._basis_activity_coef;
     195         860 :     _eqm_activity_coef = src._eqm_activity_coef;
     196         860 :     _eqm_activity = src._eqm_activity;
     197         860 :     _surface_pot_expr = src._surface_pot_expr;
     198         860 :     _sorbing_surface_area = src._sorbing_surface_area;
     199         860 :     _kin_moles = src._kin_moles;
     200         860 :     _kin_moles_old = src._kin_moles_old;
     201         860 :     _iters_to_make_consistent = src._iters_to_make_consistent;
     202         860 :     _temperature = src._temperature;
     203         860 :     _min_initial_molality = src._min_initial_molality;
     204         860 :     _original_redox_lhs = src._original_redox_lhs;
     205         860 :     return *this;
     206             :   };
     207             : 
     208             :   /**
     209             :    * Copy constructor.
     210             :    */
     211        2104 :   GeochemicalSystem(const GeochemicalSystem & src) = default;
     212             : 
     213           2 :   bool operator==(const GeochemicalSystem & rhs) const
     214             :   {
     215           2 :     return (_mgd == rhs._mgd) && (_num_basis == rhs._num_basis) && (_num_eqm == rhs._num_eqm) &&
     216           2 :            (_num_redox == rhs._num_redox) && (_num_surface_pot == rhs._num_surface_pot) &&
     217           2 :            (_num_kin == rhs._num_kin) && (_swapper == rhs._swapper) &&
     218           2 :            (_swap_out == rhs._swap_out) && (_swap_in == rhs._swap_in) && (_gac == rhs._gac) &&
     219           4 :            (_is == rhs._is) && (_charge_balance_species == rhs._charge_balance_species) &&
     220           2 :            (_original_charge_balance_species == rhs._original_charge_balance_species) &&
     221           2 :            (_charge_balance_basis_index == rhs._charge_balance_basis_index) &&
     222           2 :            (_constrained_species == rhs._constrained_species) &&
     223           2 :            (_constraint_value == rhs._constraint_value) &&
     224           2 :            (_original_constraint_value == rhs._original_constraint_value) &&
     225           2 :            (_constraint_unit == rhs._constraint_unit) &&
     226           2 :            (_constraint_user_meaning == rhs._constraint_user_meaning) &&
     227           2 :            (_constraint_meaning == rhs._constraint_meaning) && (_eqm_log10K == rhs._eqm_log10K) &&
     228           2 :            (_redox_log10K == rhs._redox_log10K) && (_kin_log10K == rhs._kin_log10K) &&
     229           2 :            (_num_basis_in_algebraic_system == rhs._num_basis_in_algebraic_system) &&
     230           2 :            (_num_in_algebraic_system == rhs._num_in_algebraic_system) &&
     231           2 :            (_in_algebraic_system == rhs._in_algebraic_system) &&
     232           2 :            (_algebraic_index == rhs._algebraic_index) && (_basis_index == rhs._basis_index) &&
     233           2 :            (_bulk_moles_old == rhs._bulk_moles_old) && (_basis_molality == rhs._basis_molality) &&
     234           2 :            (_basis_activity_known == rhs._basis_activity_known) &&
     235           2 :            (_basis_activity == rhs._basis_activity) && (_eqm_molality == rhs._eqm_molality) &&
     236           2 :            (_basis_activity_coef == rhs._basis_activity_coef) &&
     237           2 :            (_eqm_activity_coef == rhs._eqm_activity_coef) && (_eqm_activity == rhs._eqm_activity) &&
     238           2 :            (_surface_pot_expr == rhs._surface_pot_expr) &&
     239           2 :            (_sorbing_surface_area == rhs._sorbing_surface_area) && (_kin_moles == rhs._kin_moles) &&
     240           2 :            (_kin_moles_old == rhs._kin_moles_old) &&
     241           2 :            (_iters_to_make_consistent == rhs._iters_to_make_consistent) &&
     242           2 :            (_temperature == rhs._temperature) &&
     243           4 :            (_min_initial_molality == rhs._min_initial_molality) &&
     244           2 :            (_original_redox_lhs == rhs._original_redox_lhs);
     245             :   }
     246             : 
     247             :   /// returns the number of species in the basis
     248             :   unsigned getNumInBasis() const;
     249             : 
     250             :   /// returns the number of species in equilibrium with the basis components
     251             :   unsigned getNumInEquilibrium() const;
     252             : 
     253             :   /// returns the number of kinetic species
     254             :   unsigned getNumKinetic() const;
     255             : 
     256             :   /// initialize all variables, ready for a Newton solve of the algebraic system
     257             :   void initialize();
     258             : 
     259             :   /// return the index of the charge-balance species in the basis list
     260             :   unsigned getChargeBalanceBasisIndex() const;
     261             : 
     262             :   /**
     263             :    * If the molality of the charge-balance basis species is less than threshold molality, then
     264             :    * attempt to change the charge-balance species, preferably to another component with opposite
     265             :    * charge and big molality.
     266             :    * @param threshold_molality if the charge-balance basis species has molality greater than this,
     267             :    * this routine does nothing
     268             :    * @return true if the charge-balance species was changed
     269             :    */
     270             :   bool alterChargeBalanceSpecies(Real threshold_molality);
     271             : 
     272             :   /**
     273             :    * @param j the index of the equilibrium species
     274             :    * @return the value of log10(equilibrium constant) for the j^th equilibrium species
     275             :    */
     276             :   Real getLog10K(unsigned j) const;
     277             : 
     278             :   /**
     279             :    * @return the number of redox species in disequibrium
     280             :    */
     281             :   unsigned getNumRedox() const;
     282             : 
     283             :   /**
     284             :    * @param red the index of the redox species in disequilibrium (red < _num_redox)
     285             :    * @return the value of log10(equilibrium constant) for the given disequilibrium-redox species
     286             :    */
     287             :   Real getRedoxLog10K(unsigned red) const;
     288             : 
     289             :   /**
     290             :    * @param red the index of the redox species in disequilibrium (red < _num_redox)
     291             :    * @return the value of log10(activity product) for the given disequilibrium-redox species
     292             :    */
     293             :   Real log10RedoxActivityProduct(unsigned red) const;
     294             : 
     295             :   /**
     296             :    * @param kin the index of the kinetic species (must be < _num_kin)
     297             :    * @return the value of log10(equilibrium constant) for the given kinetic species
     298             :    */
     299             :   Real getKineticLog10K(unsigned kin) const;
     300             : 
     301             :   /**
     302             :    * @return the value of log10(equilibrium constant) for the each kinetic species
     303             :    */
     304             :   const std::vector<Real> & getKineticLog10K() const;
     305             : 
     306             :   /**
     307             :    * @param kin the index of the kinetic species (must be < _num_kin)
     308             :    * @return the value of log10(activity product) for the given kinetic species
     309             :    */
     310             :   Real log10KineticActivityProduct(unsigned kin) const;
     311             : 
     312             :   /**
     313             :    * @param kin the index of the kinetic species (must be < _num_kin)
     314             :    * @return the mole number for the given kinetic species
     315             :    */
     316             :   Real getKineticMoles(unsigned kin) const;
     317             : 
     318             :   /**
     319             :    * Sets the current AND old mole number for a kinetic species.  Note: this does not compute a
     320             :    * consistent configuration (viz, the bulk mole composition is not updated): use
     321             :    * computeConsistentConfiguration if you need to.
     322             :    * @param kin the index of the kinetic species (must be < _num_kin)
     323             :    * @param moles the number of moles
     324             :    */
     325             :   void setKineticMoles(unsigned kin, Real moles);
     326             : 
     327             :   /**
     328             :    * @return the mole number for all kinetic species
     329             :    */
     330             :   const std::vector<Real> & getKineticMoles() const;
     331             : 
     332             :   /**
     333             :    * Usually used at the end of a solve, to provide correct initial conditions to the next
     334             :    * time-step, this method:
     335             :    * - sets kin_moles_old = kin_moles
     336             :    * - updates the constraint_values and bulk_moles_old with mole_additions, for BULK-type species
     337             :    * - ensures charge balance holds if all species are BULK-type species
     338             :    * - computes basis_molality for the BULK-type mineral species
     339             :    * - computes bulk_moles_old from the molalities for non-BULK-type species
     340             :    * Note that it is possible that you would like to enforceChargeBalance() immediately after
     341             :    * calling this method: that is fine, there will be no negative consequences if the system has
     342             :    * been solved
     343             :    * @param mole_additions the increment of mole number of each basis species and kinetic species
     344             :    * since the last timestep.  This must have size _num_basis + _num_kin.  Only the first _num_basis
     345             :    * of these are used.
     346             :    */
     347             :   void updateOldWithCurrent(const DenseVector<Real> & mole_additions);
     348             : 
     349             :   /**
     350             :    * @return the number in the algebraic system (number of basis species in algebraic system +
     351             :    * number of surface potentials + number of kinetic species)
     352             :    */
     353             :   unsigned getNumInAlgebraicSystem() const;
     354             : 
     355             :   /// return the number of basis species in the algebraic system
     356             :   unsigned getNumBasisInAlgebraicSystem() const;
     357             : 
     358             :   /// return the number of surface potentials
     359             :   unsigned getNumSurfacePotentials() const;
     360             : 
     361             :   /**
     362             :    * @return a vector of length _num_basis whose entries determine whether the basis species is in
     363             :    * the algebraic system
     364             :    */
     365             :   const std::vector<bool> & getInAlgebraicSystem() const;
     366             : 
     367             :   /**
     368             :    * @return v, a vector of length _num_basis, where v[i] = the basis index of the i^th species in
     369             :    the algebraic system.  Note that for i > _num_basis_in_algebraic_system, the value of v is
     370             :    undefined.
     371             :    */
     372             :   const std::vector<unsigned> & getBasisIndexOfAlgebraicSystem() const;
     373             : 
     374             :   /**
     375             :    * @return v, a vector of length _num_basis, where v[i] = the algebraic index of the i^th basis
     376             :    * species.  Note that unless the i^th basis species is in the algebraic system, this is
     377             :    * meaningless
     378             :    */
     379             :   const std::vector<unsigned> & getAlgebraicIndexOfBasisSystem() const;
     380             : 
     381             :   /**
     382             :    * @return v, a vector of length getNumInAlgebraicSystem, the elements of which are the current
     383             :    * values of the algebraic variables
     384             :    */
     385             :   std::vector<Real> getAlgebraicVariableValues() const;
     386             : 
     387             :   /**
     388             :    * @return v, a vector of length _num_basis_in_algebraic_system, the elements of which are the
     389             :    * current values of the algebraic variables: molalities only (not surface potentials or kinetic
     390             :    * species)
     391             :    */
     392             :   std::vector<Real> getAlgebraicBasisValues() const;
     393             : 
     394             :   /**
     395             :    * @return v, a DenseVector of length getNumInAlgebraicSystem, the elements of which are the
     396             :    * current values of the algebraic variables
     397             :    */
     398             :   DenseVector<Real> getAlgebraicVariableDenseValues() const;
     399             : 
     400             :   /// Returns the mass of solvent water
     401             :   Real getSolventWaterMass() const;
     402             : 
     403             :   /**
     404             :    * @return the number of bulk-composition moles.  Note this will typically be the "old" number of
     405             :    * bulk moles (from the previous time-step) unless addtoBulkMoles or updateOldWithCurrent or other
     406             :    * similar methods have just been called.  Note that this contains contributions from kinetic
     407             :    * species, in contrast to the Bethke approach.
     408             :    */
     409             :   const std::vector<Real> & getBulkMolesOld() const;
     410             : 
     411             :   /**
     412             :    * @return the number of bulk-composition moles in the original basis.  Note this will typically
     413             :    * be the "old" number of bulk moles (from the previous time-step) unless addtoBulkMoles or
     414             :    * updateOldWithCurrent or other similar methods have just been called.  Note that this contains
     415             :    * contributions from kinetic species, in contrast to the Bethke approach.
     416             :    */
     417             :   DenseVector<Real> getBulkOldInOriginalBasis() const;
     418             : 
     419             :   /**
     420             :    * @return the number of bulk-composition moles that are transported in reactive-transport,
     421             :    * expressed in the original basis.  Note this is computed using the existing molalities, so the
     422             :    * result might be junk if the system is inconsistent, but will be OK if, for instance, a solve
     423             :    * has just converged.  Also note that this does not include contributions from kinetic species
     424             :    */
     425             :   DenseVector<Real> getTransportedBulkInOriginalBasis() const;
     426             : 
     427             :   /**
     428             :    * Computes the value of transported bulk moles for all basis species using the existing
     429             :    * molalities.  Note that this is probably gives rubbish results unless the system is consistent
     430             :    * (eg, the solve has converged).  Also note that this does not include contributions from kinetic
     431             :    * species
     432             :    */
     433             :   void computeTransportedBulkFromMolalities(std::vector<Real> & transported_bulk) const;
     434             : 
     435             :   /**
     436             :    * @return vector v, where v[i] = mass of solvent water (i=0), or v[i] = molality of the basis
     437             :    * aqueous species i, or v[i] = free moles of basis mineral i, whichever is appropriate
     438             :    */
     439             :   const std::vector<Real> & getSolventMassAndFreeMolalityAndMineralMoles() const;
     440             : 
     441             :   /**
     442             :    * @return vector v, where v[i] = true if the activity of basis species i is fixed, either by the
     443             :    * user providing an activity value, or a fugacity value, or because the i^th basis species is a
     444             :    * mineral
     445             :    */
     446             :   const std::vector<bool> & getBasisActivityKnown() const;
     447             : 
     448             :   /**
     449             :    * @return the activity for the i^th basis species
     450             :    */
     451             :   Real getBasisActivity(unsigned i) const;
     452             : 
     453             :   /**
     454             :    * @return the activity for the basis species
     455             :    */
     456             :   const std::vector<Real> & getBasisActivity() const;
     457             : 
     458             :   /**
     459             :    * @return the molality of the j^th equilibrium species.  This is not defined for minerals or
     460             :    * gases
     461             :    */
     462             :   Real getEquilibriumMolality(unsigned j) const;
     463             : 
     464             :   /**
     465             :    * @return the molalities of the equilibrium species.  These are not defined for minerals or
     466             :    * gases
     467             :    */
     468             :   const std::vector<Real> & getEquilibriumMolality() const;
     469             : 
     470             :   /**
     471             :    * @return the activity coefficient for the i^th basis species.  This is not defined for water,
     472             :    * minerals, gases, or aqueous species that have been provided an activity by the user
     473             :    */
     474             :   Real getBasisActivityCoefficient(unsigned i) const;
     475             : 
     476             :   /**
     477             :    * @return the activity coefficients for the basis species.  These are not defined for water,
     478             :    * minerals, gases, or aqueous species that have been provided an activity by the user
     479             :    */
     480             :   const std::vector<Real> & getBasisActivityCoefficient() const;
     481             : 
     482             :   /**
     483             :    * @return the activity coefficient for the j^th equilibrium species.  This is not defined for
     484             :    * minerals
     485             :    */
     486             :   Real getEquilibriumActivityCoefficient(unsigned j) const;
     487             : 
     488             :   /**
     489             :    * @return the activity coefficients for the equilibrium species.  These are not defined for
     490             :    * minerals
     491             :    */
     492             :   const std::vector<Real> & getEquilibriumActivityCoefficient() const;
     493             : 
     494             :   /**
     495             :    * @return the total charge in the system.  Note this is based on the old values of bulk moles and
     496             :    * kinetic moles (ie, from the previous time-step) so to get the current values methods like
     497             :    * addToBulkMoles should be called, or updateOldWithCurrent
     498             :    */
     499             :   Real getTotalChargeOld() const;
     500             : 
     501             :   /**
     502             :    * Return the residual of the algebraic system for the given algebraic index
     503             :    * @param algebraic_ind the algebraic index
     504             :    * @param mole_additions the increment of mole number of each basis species and kinetic species
     505             :    * since the last timestep.  This must have size _num_basis + _num_kin.  For the basis species,
     506             :    * this is the amount of each species being injected into the system over the timestep.  For the
     507             :    * kinetic species, this is -dt*reaction_rate.  Please note: do not decompose the kinetic-species
     508             :    * additions into basis components and add them to the first slots of mole_additions!  This method
     509             :    * does that decomposition automatically.  The first _num_basis slots of mole_additions contain
     510             :    * kinetic-independent additions, while the last _num_kin slots contain kinetic-rate
     511             :    * contributions.
     512             :    */
     513             :   Real getResidualComponent(unsigned algebraic_ind, const DenseVector<Real> & mole_additions) const;
     514             : 
     515             :   /**
     516             :    * @return reference to the underlying ModelGeochemicalDatabase
     517             :    */
     518             :   const ModelGeochemicalDatabase & getModelGeochemicalDatabase() const;
     519             : 
     520             :   /**
     521             :    * Copies a ModelGeochemicalDatabase into our _mgd structure
     522             :    * @param mgd reference to the ModelGeochemicalDatabase that will be copied into _mgd
     523             :    */
     524             :   void setModelGeochemicalDatabase(const ModelGeochemicalDatabase & mgd);
     525             : 
     526             :   /**
     527             :    * Compute the Jacobian for the algebraic system and put it in jac
     528             :    * @param res The residual of the algebraic system.  This is used to speed up computations of the
     529             :    * jacobian
     530             :    * @param jac The jacobian entries are placed here
     531             :    * @param mole_additions The molar additions to the basis species and the kinetic species
     532             :    * @param dmole_additions d(mole_additions)/d(molality or kinetic_moles)
     533             :    */
     534             :   void computeJacobian(const DenseVector<Real> & res,
     535             :                        DenseMatrix<Real> & jac,
     536             :                        const DenseVector<Real> & mole_additions,
     537             :                        const DenseMatrix<Real> & dmole_additions) const;
     538             : 
     539             :   /**
     540             :    * Set the variables in the algebraic system (molalities and potentially the mass of solvent
     541             :    * water, and surface potentials, and kinetic mole numbers if any) to algebraic_var.  All elements
     542             :    * of this vector must be postivie.  This function also calls computeConsistentConfiguration.
     543             :    * @param algebraic_var the values to set the algebraic variables to
     544             :    */
     545             :   void setAlgebraicVariables(const DenseVector<Real> & algebraic_var);
     546             : 
     547             :   /**
     548             :    * Enforces charge balance by altering the constraint_value and bulk_moles_old of the
     549             :    * charge-balance species.  Use with caution, since this overwrites the constraint values provided
     550             :    * in the constructor, and also changes bulk_moles_old which is usually the value of bulk moles
     551             :    * from the previous time-step
     552             :    */
     553             :   void enforceChargeBalance();
     554             : 
     555             :   /**
     556             :    * Changes the charge-balance species to the original that is specified in the constructor (this
     557             :    * might not be possible since the original charge-balance species might have been swapped out)
     558             :    * @return true if the charge-balance species is changed
     559             :    */
     560             :   bool revertToOriginalChargeBalanceSpecies();
     561             : 
     562             :   /**
     563             :    * @return vector v, where v[j] = saturation index of equilibrium species j = log10(activity
     564             :    * product) - log10K.  If the equilibrium species is not a mineral then v[j] = 0
     565             :    */
     566             :   std::vector<Real> getSaturationIndices() const;
     567             : 
     568             :   /**
     569             :    * Perform the basis swap, and ensure that the resulting system is consistent.  Note that this
     570             :    * alters the bulk_moles_old of species.  If you are confident that your configuration is
     571             :    * reasonably correct, you should therefore ensure bulk_moles_old is set to the actual bulk_moles
     572             :    * in your system prior to calling performSwap.  Alternatively, if you are unsure of the
     573             :    * correctness, just let performSwap use bulk_moles_old to set the bulk moles of your new basis.
     574             :    * @param swap_out_of_basis index of basis species to remove from basis
     575             :    * @param swap_into_basis index of equilibrium species to add to basis
     576             :    */
     577             :   void performSwap(unsigned swap_out_of_basis, unsigned swap_into_basis);
     578             : 
     579             :   /// Get the ionic strength
     580             :   Real getIonicStrength() const;
     581             : 
     582             :   /// Get the stoichiometric ionic strength
     583             :   Real getStoichiometricIonicStrength() const;
     584             : 
     585             :   /**
     586             :    * @param sp surface number of interest.  sp < _num_surface_pot
     587             :    * @return the surface potential (units Volts) for the surface number
     588             :    */
     589             :   Real getSurfacePotential(unsigned sp) const;
     590             : 
     591             :   /**
     592             :    * @param sp surface number of interest.  sp < _num_surface_pot
     593             :    * @return the specific charge of the surface (units: Coulombs/m^2) for the surface number
     594             :    */
     595             :   Real getSurfaceCharge(unsigned sp) const;
     596             : 
     597             :   /**
     598             :    * @return the sorbing surface area (units: m^2) for each sorbing surface
     599             :    */
     600             :   const std::vector<Real> & getSorbingSurfaceArea() const;
     601             : 
     602             :   /**
     603             :    * @return the temperature in degC
     604             :    */
     605             :   Real getTemperature() const;
     606             : 
     607             :   /**
     608             :    * Sets the temperature to the given quantity.  This also:
     609             :    * - calculates new values of equilibrium constants for equilibrium, redox and kinetic species
     610             :    * - instructs the activity-coefficient calculator to set its internal temperature and calculate
     611             :    * new values of the Debye-Huckel parameters.
     612             :    * However, it does NOT update activity coefficients, basis molalities for species of known
     613             :    * activities, basis activities, equilibrium molalities, bulk mole number of species with fixed
     614             :    * free molality, free mineral mole numbers, or surface sorbing area.  Hence, the state of the
     615             :    * equilibrium geochemical system will be left inconsistent after a call to setTemperature, and
     616             :    * you should computeConsistentConfiguration() to rectify this, if needed.
     617             :    * @param temperature the temperature in degC
     618             :    */
     619             :   void setTemperature(Real temperature);
     620             : 
     621             :   /**
     622             :    * Sets:
     623             :    * - solvent water mass
     624             :    * - free molality of all basis species and equilibrium species that are not (water or gas or
     625             :    * mineral)
     626             :    * - free number of moles of all minerals (if any)
     627             :    * - surface potential expressions for all surface-sorption sites (if any)
     628             :    * - mole number and old mole number of the kinetic species (if any)
     629             :    * Then computes bulk mole composition, activities, activity coefficients and sorbing surface
     630             :    * areas so that the GeochemicalSystem is kept self-consistent.
     631             :    *
     632             :    * This method is designed to be run at the start of a simulation, or during a "recover" operator.
     633             :    *
     634             :    * @param names the names of all the basis species, equilibrium species, surface-sorption
     635             :    * minerals and kinetic species that are in the system.  Note, there must be exactly num_basis +
     636             :    * num_eqm + num_surface_pot + num_kin of these, ie, all species must be provided with a value
     637             :    * @param values the values of the molalities (or solvent water mass for water, or free number of
     638             :    * moles for minerals/kinetics, or surface_potential_expr for surface-sorption sites).  There must
     639             :    * be an equal number of these as "names".
     640             :    * @param contraints_from_molalities whether the constraints initial provided to the
     641             :    * GeochemicalSystem should be updated by the values provided.  This must have size
     642             :    * num_basis.
     643             :    *
     644             :    * This method is reasonably nontrivial:
     645             :    * - it assumes that temperature-dependent quantities (equilibrium constants, Debye-Huckel
     646             :    * parameters, etc) have been set prior to calling this method, eg in the constructor or
     647             :    * setTemperature()
     648             :    * - it assumes the algebraic info has been built during instantiation, or during swaps, etc
     649             :    * - it does not assume the value provided are "good", although since they most usually come from
     650             :    * a previous solve, they are typically pretty "good".  It does check for non-negativity: molality
     651             :    * for basis gases must be zero; molality for basis minerals must be non-negative; molality for
     652             :    * every other basis species must be positive; molality for equilibrium gases and equilibrium
     653             :    * minerals are set to zero irrespective of values provided; molality of other equilibrium species
     654             :    * must be non-negative; surface_potential_expressions must be positive; mole number of kinetic
     655             :    * species must be positive.  (In the previous sentence, "molality" is molality, kg solvent water,
     656             :    * or free mineral moles, whichever is appropriate.)
     657             :    * - if constraints_from_molalities is false then: if the original constraint was
     658             :    * KG_SOLVENT_WATER, FREE_MOLALITY or FREE_MOLES_MINERAL_SPECIES then the constraint take
     659             :    * precedence over the molality provided to this method, so the molality is ignored and the
     660             :    * constraint value used instead.
     661             :    * - if constraints_from_molalities is true then: if the original constraint was KG_SOLVENT_WATER,
     662             :    * FREE_MOLALITY or FREE_MOLES_MINERAL_SPECIES then the constraint value is set to the value
     663             :    * provided by to this method; if the original constraint was MOLES_BULK_WATER or
     664             :    * MOLES_BULK_SPECIES then the constraint value is set to the value computed from the molalities
     665             :    * provided to this method; if the original constraint was ACTIVITY, then the constraint value is
     666             :    * set to activity_coefficient * molality_provided_to_this_method
     667             :    * - Note the possibilities for ignoring the values provided to this method mentioned in the
     668             :    * preceeding paragraphs (setting to zero for equilibrium minerals and gases, and constraints
     669             :    * overriding the values provided)!
     670             :    */
     671             :   void setSolventMassAndFreeMolalityAndMineralMolesAndSurfacePotsAndKineticMoles(
     672             :       const std::vector<std::string> & names,
     673             :       const std::vector<Real> & values,
     674             :       const std::vector<bool> & constraints_from_molalities);
     675             : 
     676             :   /**
     677             :    * @return a vector of the constraint meanings for the basis species
     678             :    */
     679             :   const std::vector<GeochemicalSystem::ConstraintMeaningEnum> & getConstraintMeaning() const;
     680             : 
     681             :   /**
     682             :    * Changes a KG_SOLVENT_WATER constraint to MOLES_BULK_WATER (if there is such a constraint) and
     683             :    * all FREE_MOLALITY and FREE_MOLES_MINERAL_SPECIES to MOLES_BULK_SPECIES using the current values
     684             :    * of _bulk_moles_old.  If, after performing these changes, all constraints are MOLES_BULK_WATER
     685             :    * or MOLES_BULK_SPECIES then charge-balance is performed by altering the bulk_moles_old for the
     686             :    * charge-balance species.
     687             :    */
     688             :   void closeSystem();
     689             : 
     690             :   /**
     691             :    * Changes the constraint to MOLES_BULK_SPECIES (or MOLES_BULK_WATER if basis_ind = 0) for the
     692             :    * basis index.  The constraint value (the bulk number of moles of the species) is computed from
     693             :    * the current molality values.  Note that if basis_ind corresponds to a gas, then changing the
     694             :    * constraint involves performing a basis swap with a non-gaseous equilibrium species (eg O2(g) is
     695             :    * removed from the basis and O2(aq) enters in its place).  If, after performing the change to
     696             :    * MOLES_BULK_SPECIES, all constraints are MOLES_BULK_WATER or MOLES_BULK_SPECIES then
     697             :    * charge-balance is performed by altering the bulk_moles_old for the charge-balance species.
     698             :    * @param basis_ind the index of the basis species
     699             :    */
     700             :   void changeConstraintToBulk(unsigned basis_ind);
     701             : 
     702             :   /**
     703             :    * Changes the constraint to MOLES_BULK_SPECIES (or MOLES_BULK_WATER if basis_ind = 0) for the
     704             :    * basis index.  The constraint value (the bulk number of moles of the species) is set to value.
     705             :    * It is an error to call this function when basis_ind corresponds to a gas, because changing the
     706             :    * constraint involves performing a basis swap with a non-gaseous equilibrium species (eg O2(g) is
     707             :    * removed from the basis and O2(aq) enters in its place), so the bulk number of moles will be
     708             :    * computed by the swapper: use changeConstraintToBulk(basis_ind) instead.    If, after performing
     709             :    * the change to MOLES_BULK_SPECIES, all constraints are MOLES_BULK_WATER or MOLES_BULK_SPECIES
     710             :    * then charge-balance is performed by altering the bulk_moles_old for the charge-balance species.
     711             :    * @param basis_ind the index of the basis species
     712             :    * @param value the value to set the bulk number of moles to
     713             :    */
     714             :   void changeConstraintToBulk(unsigned basis_ind, Real value);
     715             : 
     716             :   /**
     717             :    * Add to the MOLES_BULK_SPECIES (or MOLES_BULK_WATER if basis_ind = 0) for the basis species.
     718             :    * Note that if the constraint on the basis species is not MOLES_BULK_SPECIES (or
     719             :    * MOLES_BULK_WATER) then this will have no impact.  Note that charge-balance is performed if all
     720             :    * constraints are BULK-type.
     721             :    * @param basis_ind the index of the basis species
     722             :    * @param value the value to add to the bulk number of moles
     723             :    */
     724             :   void addToBulkMoles(unsigned basis_ind, Real value);
     725             : 
     726             :   /**
     727             :    * Set the constraint value for the basis species.  If molalities or activities are changed, this
     728             :    * method uses computeConsistentConfiguration to result in a consistent configuration, while if
     729             :    * bulk composition is altered it uses alterSystemBecauseBulkChanged to result in a consistent
     730             :    * configuration (charge-balance is performed if all constraints are BULK-type)
     731             :    * @param basis_ind the index of the basis species
     732             :    * @param value the value to set the constraint to
     733             :    */
     734             :   void setConstraintValue(unsigned basis_ind, Real value);
     735             : 
     736             :   /**
     737             :    * Compute a reasonably consistent configuration that can be used as an initial condition in a
     738             :    * Newton process to solve the algebraic system.  Note that unless _iters_to_make_consistent is
     739             :    * very large, the resulting configuration will not be completely consistent, but this is
     740             :    * conventional in geochemical modelling: there are so many unknowns and approximations used in
     741             :    * the Newton process, that starting from a completely consistent configuration is unimportant.
     742             :    *
     743             :    * Before entering this method, it is assumed that::
     744             :    * - basis molality has been set for all basis species.  For species where this is unknown (viz,
     745             :    * it will be solved for in the Newton process) a reasonable initial condition should be set.  Use
     746             :    * the initBulkAndFree method.
     747             :    * - basis_activity_known has been set to true for basis species whose activities are specified by
     748             :    * the user, for basis gases and for basis minerals.  Use the buildKnownBasisActivities method.
     749             :    * - basis_activity has been set for basis species with basis_activity_known = true.  Use the
     750             :    * buildKnownBasisActivities method.
     751             :    * - equilibrium molality has been pre-initialised (eg, to zero) for all equilibrium species prior
     752             :    * to entering this method.
     753             :    *
     754             :    * This method computes:
     755             :    * - ionic strength and stoichiometric ionic strength
     756             :    * - basis activity coefficients (not for water, minerals or gases)
     757             :    * - equilibrium activity coefficients (not for minerals or gases)
     758             :    * - basis molality for basis species where the user has specified the activity
     759             :    * - basis molality for mineral basis species
     760             :    * - basis activity for all basis species
     761             :    * - equilibrium molality for all equilibrium species (molality for minerals and gases are set to
     762             :    * zero)
     763             :    * - bulk_moles_old for all basis species (set to the constraint_value for BULK-type constraints,
     764             :    * otherwise computed from the current values of molality)
     765             :    * - sorbing surface area
     766             :    *
     767             :    * It does not compute activity for equilibrium species: use computeAndGetEquilibriumActivity for
     768             :    * that
     769             :    */
     770             :   void computeConsistentConfiguration();
     771             : 
     772             :   /**
     773             :    * @return the original redox left-hand-side after the initial basis swaps
     774             :    */
     775             :   const std::string & getOriginalRedoxLHS() const;
     776             : 
     777             :   /**
     778             :    * Perform the basis swap, and ensure that the resulting system is consistent.  Note: no
     779             :    * sanity-checks regarding swapping out the charge-balance species, etc, are made.
     780             :    * Note that this
     781             :    * alters the bulk_moles_old of species.  If you are confident that your configuration is
     782             :    * reasonably correct, you should therefore ensure bulk_moles_old is set to the actual bulk_moles
     783             :    * in your system prior to calling performSwap.  Alternatively, if you are unsure of the
     784             :    * correctness, just let performSwap use bulk_moles_old to set the bulk moles of your new basis.
     785             :    * @param swap_out_of_basis index of basis species to remove from basis
     786             :    * @param swap_into_basis index of equilibrium species to add to basis
     787             :    */
     788             :   void performSwapNoCheck(unsigned swap_out_of_basis, unsigned swap_into_basis);
     789             : 
     790             :   /**
     791             :    * @return a reference to the swapper used by this object
     792             :    */
     793             :   const GeochemistrySpeciesSwapper & getSwapper() const;
     794             : 
     795             :   /**
     796             :    * Set the free mole number of mineral-related species to the value provided.  This sets the mole
     797             :    * number of basis minerals, the molality of unoccupied sorption sites (whether in the basis or
     798             :    * not), and the molality of sorbed species to the value provided.  It does not set the molality
     799             :    * of equilibrium minerals, which is always zero.
     800             :    * NOTE: calling this method can easily result in a
     801             :    * completely inconsistent GeochemicalSystem because no
     802             :    * computeConsistentConfiguration() is called.  If you need a consistent configuration, please
     803             :    * call that method after calling this one
     804             :    * @param value the mole number (or molality, for sorption-related species)
     805             :    */
     806             :   void setMineralRelatedFreeMoles(Real value);
     807             : 
     808             :   /**
     809             :    * Computes activity for all equilibrium species (_eqm_activity) and returns a reference to the
     810             :    * vector.  The vector _eqm_activity is only used for output purposes (such as recording the
     811             :    * fugacity of equilibrium gases) so it is only computed by this method and not internally during
     812             :    * computeConsistentConfiguration.
     813             :    * @return equilibrium activities
     814             :    */
     815             :   const std::vector<Real> & computeAndGetEquilibriumActivity();
     816             : 
     817             :   /**
     818             :    * Returns the value of activity for the equilibrium species with index eqm_index
     819             :    * @param eqm_index the index in mgd for the equilibrium species of interest
     820             :    */
     821             :   Real getEquilibriumActivity(unsigned eqm_ind) const;
     822             : 
     823             :   /**
     824             :    * Computes the kinetic rates and their derivatives based on the current values of molality, mole
     825             :    * number, etc, and then, using dt, calculates the appropriate mole_additions and dmole_additions.
     826             :    * NOTE: this *adds* the kinetic contributes to mole_additions and dmole_additions.
     827             :    * This method is not const because it modifies _eqm_activity for
     828             :    * equilibrium gases and eqm species H+ and OH- (if there are any).
     829             :    * @param dt time-step size
     830             :    * @param mole_additions The kinetic rates multiplied by dt get placed in the last num_kin slots
     831             :    * @param dmole_additions d(mole_additions)/d(molality or kinetic_moles)
     832             :    */
     833             :   void
     834             :   addKineticRates(Real dt, DenseVector<Real> & mole_additions, DenseMatrix<Real> & dmole_additions);
     835             : 
     836             : private:
     837             :   /// The minimal geochemical database
     838             :   ModelGeochemicalDatabase & _mgd;
     839             :   /// number of basis species
     840             :   const unsigned _num_basis;
     841             :   /// number of equilibrium species
     842             :   const unsigned _num_eqm;
     843             :   /// number of redox species
     844             :   const unsigned _num_redox;
     845             :   /// number of surface potentials
     846             :   const unsigned _num_surface_pot;
     847             :   /// number of kinetic species
     848             :   const unsigned _num_kin;
     849             :   /// swapper that can swap species into and out of the basis
     850             :   GeochemistrySpeciesSwapper & _swapper;
     851             :   /// Species to immediately remove from the basis in favor of _swap_in
     852             :   const std::vector<std::string> _swap_out;
     853             :   /// Species to immediately add to the basis in favor of _swap_out
     854             :   const std::vector<std::string> _swap_in;
     855             :   /// Object to compute the activity coefficients and activity of water
     856             :   GeochemistryActivityCoefficients & _gac;
     857             :   /// Object that provides the ionic strengths
     858             :   GeochemistryIonicStrength & _is;
     859             :   /// The species used to enforce charge balance
     860             :   std::string _charge_balance_species;
     861             :   /// The species used to enforce charge balance, as provided in the constructor
     862             :   const std::string _original_charge_balance_species;
     863             :   /// The index in the list of basis species corresponding to the charge-balance species.  This gets altered as the simulation progresses, due to swaps, and alterChargeBalanceSpecies
     864             :   unsigned _charge_balance_basis_index;
     865             :   /// Names of the species in that have their values fixed to _constraint_value with meanings _constraint_meaning.  In the constructor, this is ordered to have the same ordering as the basis species.
     866             :   std::vector<std::string> _constrained_species;
     867             :   /// Numerical values of the constraints on _constraint_species.  In the constructor, this is ordered to have the same ordering as the basis species.
     868             :   std::vector<Real> _constraint_value;
     869             :   /// Numerical values of the constraints on _constraint_species.  In the constructor, this is ordered to have the same ordering as the basis species.  Since values can change due to charge-balance, this holds the original values set by the user.
     870             :   std::vector<Real> _original_constraint_value;
     871             :   /// Units of the _constraint_value when the GeochemicalSystem is constructed.  This is used during the constructor to convert the constraint_values into mole units
     872             :   std::vector<GeochemistryUnitConverter::GeochemistryUnit> _constraint_unit;
     873             :   /// The user-defined meaning of the values in _constraint_value.  In the constructor, this is ordered to have the same ordering as the basis species.  During the process of unit conversion, from the user-supplied _constraint_unit, to mole-based units, _constraint_user_meaning is used to populate _constraint_meaning, and henceforth usually only _constraint_meaning is used in the code
     874             :   std::vector<ConstraintUserMeaningEnum> _constraint_user_meaning;
     875             :   /// The meaning of the values in _constraint_value.  In the constructor, this is ordered to have the same ordering as the basis species.
     876             :   std::vector<ConstraintMeaningEnum> _constraint_meaning;
     877             :   /// equilibrium constant of the equilibrium species
     878             :   std::vector<Real> _eqm_log10K;
     879             :   /// equilibrium constant of the redox species
     880             :   std::vector<Real> _redox_log10K;
     881             :   /// equilibrium constant of the kinetic species
     882             :   std::vector<Real> _kin_log10K;
     883             :   /// number of unknown molalities in the algebraic system.  Note: surface potentials (if any) are extra quantities in the algebraic system
     884             :   unsigned _num_basis_in_algebraic_system;
     885             :   /// number of unknowns in the algebraic system (includes molalities and surface potentials)
     886             :   unsigned _num_in_algebraic_system;
     887             :   /// if _in_algebraic_system[i] == true then we need to solve for the i^th basis-species molality
     888             :   std::vector<bool> _in_algebraic_system;
     889             :   /// _algebraic_index[i] = index in the algebraic system of the basis species i.  _basis_index[_algebraic_index[i]] = i
     890             :   std::vector<unsigned> _algebraic_index;
     891             :   /// _basis_index[i] = index in the basis of the algebraic system species i, for i<num_basis_in_algebraic_system.  _basis_index[_algebraic_index[i]] == i
     892             :   std::vector<unsigned> _basis_index;
     893             :   /// Number of bulk moles of basis species (this includes contributions from kinetic species, in contrast to Bethke)
     894             :   std::vector<Real> _bulk_moles_old;
     895             :   /**
     896             :    * IMPORTANT: this is
     897             :    * - number of kg of solvent water as the first element
     898             :    * - molality of basis aqueous species, or free moles of basis mineral, whichever is appropriate
     899             :    * - always zero for gases
     900             :    */
     901             :   std::vector<Real> _basis_molality;
     902             :   /// whether basis_activity[i] is fixed by the user
     903             :   std::vector<bool> _basis_activity_known;
     904             :   /// values of activity (for water, minerals and aqueous basis species) or fugacity (for gases)
     905             :   std::vector<Real> _basis_activity;
     906             :   /// molality of equilibrium species
     907             :   std::vector<Real> _eqm_molality;
     908             :   /// basis activity coefficients
     909             :   std::vector<Real> _basis_activity_coef;
     910             :   /// equilibrium activity coefficients
     911             :   std::vector<Real> _eqm_activity_coef;
     912             :   /**
     913             :    * equilibrium activities.  NOTE: for computational efficiency, these are not computed until
     914             :    * computeAndGetEqmActivity is called, and they are currently only ever used for output purposes
     915             :    * and computing kinetic rates
     916             :    */
     917             :   std::vector<Real> _eqm_activity;
     918             :   /**
     919             :    * surface potential expressions.  These are not the surface potentials themselves.  Instead they
     920             :    * are exp(-surface_potential * Faraday / 2 / R / T_k).  Hence _surface_pot_expr >= 0 (like
     921             :    * molalities) and the surface-potential residual is close to linear in _surface_pot_expr if
     922             :    * equilibrium molalities are large
     923             :    */
     924             :   std::vector<Real> _surface_pot_expr;
     925             :   /// surface areas of the sorbing minerals
     926             :   std::vector<Real> _sorbing_surface_area;
     927             :   /// mole number of kinetic species
     928             :   std::vector<Real> _kin_moles;
     929             :   /// old mole number of kinetic species
     930             :   std::vector<Real> _kin_moles_old;
     931             :   /**
     932             :    * Iterations to make the initial configuration consistent.  Note that because equilibrium
     933             :    * molality depends on activity and activity coefficients, and water activity and activity
     934             :    * coefficients depend on molality, it is a nontrivial task to compute all these so that the
     935             :    * algorithm starts with a consistent initial condition from which to solve the algebraic system.
     936             :    * Usually the algorithm doesn't even attempt to make a consistent initial condition (a suitable
     937             :    * default is iters_to_make_consistent=0), because solving the algebraic system includes so many
     938             :    * approximations anyway.
     939             :    */
     940             :   unsigned _iters_to_make_consistent;
     941             :   /// The temperature in degC
     942             :   Real _temperature;
     943             :   /// Minimum molality ever used in an initial guess
     944             :   Real _min_initial_molality;
     945             :   /// The left-hand-side of the redox equations in _mgd after initial swaps
     946             :   std::string _original_redox_lhs;
     947             : 
     948             :   /**
     949             :    * Using the provided value of temperature, build _eqm_log10K for each eqm species and redox
     950             :    * species
     951             :    */
     952             :   void buildTemperatureDependentQuantities(Real temperature);
     953             : 
     954             :   /// Builds in_algebraic_system, algebraic_index and basis_index, and sets num_basis_in_algebraic_system appropriately
     955             :   void buildAlgebraicInfo(std::vector<bool> & in_algebraic_system,
     956             :                           unsigned & num_basis_in_algebraic_system,
     957             :                           unsigned & num_in_algebraic_system,
     958             :                           std::vector<unsigned> & algebraic_index,
     959             :                           std::vector<unsigned> & basis_index) const;
     960             : 
     961             :   /**
     962             :    * based on _constrained_value and _constraint_meaning, populate nw, bulk_moles_old and
     963             :    * basis_molality with reasonable initial conditions that may be used during the Newton solve of
     964             :    * the algebraic system
     965             :    * @param bulk_moles_old bulk composition number of moles of the basis species
     966             :    * @param basis_molality zeroth component is mass of solvent water, other components are either
     967             :    * molality of the basis aqueous species or number of moles of basis mineral, whichever is
     968             :    * appropriate
     969             :    */
     970             :   void initBulkAndFree(std::vector<Real> & bulk_moles_old,
     971             :                        std::vector<Real> & basis_molality) const;
     972             : 
     973             :   /**
     974             :    * Fully populates basis_activity_known, which is true if activity has been set by the user, or
     975             :    * the fugacity has been set by the user, or the basis species is a mineral. Populates only those
     976             :    * slots in basis_activity for which basis_activity_known == true
     977             :    */
     978             :   void buildKnownBasisActivities(std::vector<bool> & basis_activity_known,
     979             :                                  std::vector<Real> & basis_activity) const;
     980             : 
     981             :   /**
     982             :    * Compute the activity of water and put in basis_activity[0], and use the _basis_activity_coef
     983             :    * and _basis_molality to compute the remaining basis activities (for those that are not minerals,
     984             :    * gases or aqueous species provided with an activity)
     985             :    */
     986             :   void computeRemainingBasisActivities(std::vector<Real> & basis_activity) const;
     987             : 
     988             :   /**
     989             :    * For basis aqueous species (not water, minerals or gases) with activity set by the user, set
     990             :    * basis_molality = activity / activity_coefficient
     991             :    */
     992             :   void updateBasisMolalityForKnownActivity(std::vector<Real> & basis_molality) const;
     993             : 
     994             :   /**
     995             :    * @return log10(activity product) for equilibrium species eqm_j
     996             :    */
     997             :   Real log10ActivityProduct(unsigned eqm_j) const;
     998             : 
     999             :   /**
    1000             :    * compute the equilibrium molalities (not for minerals or gases)
    1001             :    */
    1002             :   void computeEqmMolalities(std::vector<Real> & eqm_molality) const;
    1003             : 
    1004             :   /**
    1005             :    * If all non-charged basis species are provided with a bulk number of moles, alter the bulk
    1006             :    * number of moles (old) of the charge_balance_species so that charges are balanced
    1007             :    * @param constraint_value the values of the constraints provided by the user
    1008             :    * @param bulk_moles_old the old values of bulk moles (from previous time-step)
    1009             :    */
    1010             :   void enforceChargeBalanceIfSimple(std::vector<Real> & constraint_value,
    1011             :                                     std::vector<Real> & bulk_moles_old) const;
    1012             : 
    1013             :   /**
    1014             :    * Computes the value of bulk_moles_old for all basis species.  For species with BULK-type
    1015             :    * constraints bulk_moles_old gets set to the constraint value, while for other species
    1016             :    * bulk_moles_old is computed from the molalities, and, in contrast to Bethke, the kinetic species
    1017             :    */
    1018             :   void computeBulk(std::vector<Real> & bulk_moles_old) const;
    1019             : 
    1020             :   /**
    1021             :    * Enforces charge balance by altering the constraint_value and bulk_moles_old of the
    1022             :    * charge-balance species.  Note that this changes the important constraint_value and the old
    1023             :    * bulk_moles_old (usually from the previous time-step) so should be used with caution.
    1024             :    */
    1025             :   void enforceChargeBalance(std::vector<Real> & constraint_value,
    1026             :                             std::vector<Real> & bulk_moles_old) const;
    1027             : 
    1028             :   /**
    1029             :    * Compute the free mineral moles (ie, basis_molality for basis species that are minerals), using
    1030             :    * the bulk_moles_old.  Note that usually computeBulk should have been called immediately
    1031             :    * preceding this in order to correctly set bulk_moles_old.
    1032             :    */
    1033             :   void computeFreeMineralMoles(std::vector<Real> & basis_molality) const;
    1034             : 
    1035             :   /**
    1036             :    * Used during construction: checks for sane inputs and initializes molalities, etc, using the
    1037             :    * initialize() method
    1038             :    * @param kin_name names of kinetic species
    1039             :    * @param kin_initial initial mole numbers (or mass or volume, depending on kin_unit) of the
    1040             :    * species named in kin_name
    1041             :    * @param kin_unit units of the numbers provided in kin_initial
    1042             :    */
    1043             :   void
    1044             :   checkAndInitialize(const std::vector<std::string> & kin_name,
    1045             :                      const std::vector<Real> & kin_initial,
    1046             :                      const std::vector<GeochemistryUnitConverter::GeochemistryUnit> & kin_unit);
    1047             : 
    1048             :   /**
    1049             :    * Set the charge-balance species to the basis index provided.  No checks are made on the
    1050             :    * sanity of the desired change. Before setting, the _constraint_value mole number of the old
    1051             :    * charge-balance species is set to the value provided in the constructor.  Then
    1052             :    * _charge_balance_basis_index and _charge_balance_species is set appropriately
    1053             :    */
    1054             :   void setChargeBalanceSpecies(unsigned new_charge_balance_index);
    1055             : 
    1056             :   /**
    1057             :    * @param eqm_j the index of the equilibrium species
    1058             :    * @return the modifier to the mass-balance equation for equilibrium species j, which is
    1059             :    * exp(-z * psi * F / R / TK), where z is the charge of the equilibrium species j, psi is the
    1060             :    * surface potential relevant to the equilibrium species j, F the Faraday constant, R the gas
    1061             :    * constant, and TK the temperature in Kelvin.  If equilibrium species j has no relevant surface
    1062             :    * potential, unity is returned.  Note that exp(-z * psi * F / R / TK) = (_surface_pot_expr)^(2z)
    1063             :    */
    1064             :   Real surfaceSorptionModifier(unsigned eqm_j) const;
    1065             : 
    1066             :   /**
    1067             :    * @param sp Surface potential number.  sp < _num_surface_pot
    1068             :    * @return (1/2) * A / F * sqrt(R * T_k * eps * eps_0 * rho * I).  This appears in the
    1069             :    * surface-potential equation.
    1070             :    */
    1071             :   Real surfacePotPrefactor(unsigned sp) const;
    1072             : 
    1073             :   /// Compute sorbing_surface_area depending on the current molality of the sorbing minerals
    1074             :   void computeSorbingSurfaceArea(std::vector<Real> & sorbing_surface_area) const;
    1075             : 
    1076             :   /**
    1077             :    * @param basis_ind the index of the basis species in mgd
    1078             :    * @return the number of bulk moles of the species basis_ind.  This depends on the current
    1079             :    * molality of the basis_ind species, as well as the current molalities of the equilibrium species
    1080             :    * that depend on this basis species, and, in contrast to the Bethke approach, the current mole
    1081             :    * number of kinetic species that depend on this basis species.
    1082             :    */
    1083             :   Real computeBulkFromMolalities(unsigned basis_ind) const;
    1084             : 
    1085             :   /**
    1086             :    * Alter the GeochemicalSystem to reflect changes in bulk composition constraints that
    1087             :    * occur through, for instance, setConstraintValue or addToBulkMoles or changeConstraintToBulk
    1088             :    * (the latter because charge neutrality might be easily enforced, changing constraints and hence
    1089             :    * bulk moles). This method enforces charge neutrality if simple (ie, all constraints are
    1090             :    * BULK-type), then sets _bulk_moles_old, and free mineral moles appropriately
    1091             :    */
    1092             :   void alterSystemBecauseBulkChanged();
    1093             : };

Generated by: LCOV version 1.14