The impact of CO fugacity on the solubility of calcite

Section 14.3 of Bethke (2007) and involves studying the solubility of calcite in the presence of a progressively changing CO gas buffer.

Assume that:

  • the bulk composition of Na is 10mmolal;

  • the bulk composition of Cl is 10mmolal;

  • the mineral calcite is used in place of Ca in the basis, and that initially it has a free mole number of 0.01354mol, corresponding to a volume of cm;

  • CO(g) is used in place of H in the basis, and that its fugacity is initially ;

  • charge balance is maintained on HCO.

Then the fugacity of CO(g) is changed from to 1, and the dissolution of calcite, the pH, and species concentrations are all recorded as a function of time.

MOOSE input file

The MOOSE input file includes the GeochemicalModelDefinition which defines the basis species, the equilibrium minerals and equilibrium gases in this case. The piecewise_linear_interpolation flag is set true so that the equilibrium constants and Debye-Huckel parameters are evaluated at the 25C value provided in the database file without any least-squares best-fit smoothing.

[UserObjects<<<{"href": "../../../syntax/UserObjects/index.html"}>>>]
  [definition]
    type = GeochemicalModelDefinition<<<{"description": "User object that parses a geochemical database file, and only retains information relevant to the current geochemical model", "href": "../../../source/userobjects/GeochemicalModelDefinition.html"}>>>
    database_file<<<{"description": "The name of the geochemical database file"}>>> = "../../../database/moose_geochemdb.json"
    basis_species<<<{"description": "A list of basis components relevant to the aqueous-equilibrium problem. H2O must appear first in this list.  These components must be chosen from the 'basis species' in the database, the sorbing sites (if any) and the decoupled redox states that are in disequilibrium (if any)."}>>> = "H2O H+ Na+ Cl- Ca++ HCO3-"
    equilibrium_minerals<<<{"description": "A list of minerals that are in equilibrium with the aqueous solution.  All members of this list must be in the 'minerals' section of the database file"}>>> = "Calcite"
    equilibrium_gases<<<{"description": "A list of gases that are in equilibrium with the aqueous solution and can have their fugacities fixed, at least for some time and spatial location.  All members of this list must be in the 'gas' section of the database file"}>>> = "CO2(g)"
    piecewise_linear_interpolation<<<{"description": "If true then use a piecewise-linear interpolation of logK and Debye-Huckel parameters, regardless of the interpolation type specified in the database file.  This can be useful for comparing with results using other geochemistry software"}>>> = true # for comparison with GWB
  []
[]
(modules/geochemistry/test/tests/time_dependent_reactions/changing_fugacity_calcite.i)

The TimeDependentReactionSolver specifies

  • the swaps used

  • the initial free molality of Calcite, the initial fugacity of CO(g) and the bulk mole number for the other species

  • the system is closed at by default, meaning that the external agent cannot add or remove Calcite in order to maintain the free mole number of 0.01354 (ie, Calcite can precipitate or dissolve freely)

  • that the activity (fugacity) of CO(g) is controlled by the fug_co2 AuxVariable

[TimeDependentReactionSolver<<<{"href": "../../../syntax/TimeDependentReactionSolver/index.html"}>>>]
  model_definition<<<{"description": "The name of the GeochemicalModelDefinition user object (you must create this UserObject yourself)"}>>> = definition
  geochemistry_reactor_name<<<{"description": "The name that will be given to the GeochemistryReactor UserObject built by this action"}>>> = reactor
  swap_out_of_basis<<<{"description": "Species that should be removed from the model_definition's basis and be replaced with the swap_into_basis species"}>>> = "Ca++ H+"
  swap_into_basis<<<{"description": "Species that should be removed from the model_definition's equilibrium species list and added to the basis.  There must be the same number of species in swap_out_of_basis and swap_into_basis.  These swaps are performed before any other computations during the initial problem setup. If this list contains more than one species, the swapping is performed one-by-one, starting with the first pair (swap_out_of_basis[0] and swap_into_basis[0]), then the next pair, etc"}>>> = "Calcite CO2(g)"
  charge_balance_species<<<{"description": "Charge balance will be enforced on this basis species.  This means that its bulk mole number may be changed from the initial value you provide in order to ensure charge neutrality.  After the initial swaps have been performed, this must be in the basis, and it must be provided with a bulk_composition constraint_meaning."}>>> = "HCO3-"
  constraint_species<<<{"description": "Names of the species that have their values fixed to constraint_value with meaning constraint_meaning.  All basis species (after swap_into_basis and swap_out_of_basis) must be provided with exactly one constraint.  These constraints are used to compute the configuration during the initial problem setup, and in time-dependent simulations they may be modified as time progresses."}>>> = "H2O              Calcite      CO2(g)        Na+              Cl-              HCO3-"
  constraint_value<<<{"description": "Numerical value of the containts on constraint_species"}>>> = "  1.0              0.01354      -3.5          1E-2             1E-2             0"
  constraint_meaning<<<{"description": "Meanings of the numerical values given in constraint_value.  kg_solvent_water: can only be applied to H2O and units must be kg.  bulk_composition: can be applied to all non-gas species, and represents the total amount of the basis species contained as free species as well as the amount found in secondary species but not in kinetic species, and units must be moles or mass (kg, g, etc).  bulk_composition_with_kinetic: can be applied to all non-gas species, and represents the total amount of the basis species contained as free species as well as the amount found in secondary species and in kinetic species, and units must be moles or mass (kg, g, etc).  free_concentration: can be applied to all basis species that are not gas and not H2O and not mineral, and represents the total amount of the basis species existing freely (not as secondary species) within the solution, and units must be molal or mass_per_kg_solvent.  free_mineral: can be applied to all mineral basis species, and represents the total amount of the mineral existing freely (precipitated) within the solution, and units must be moles, mass or cm3.  activity and log10activity: can be applied to basis species that are not gas and not mineral and not sorbing sites, and represents the activity of the basis species (recall pH = -log10activity), and units must be dimensionless.  fugacity and log10fugacity: can be applied to gases, and units must be dimensionless"}>>> = "kg_solvent_water free_mineral log10fugacity bulk_composition bulk_composition bulk_composition"
  constraint_unit<<<{"description": "Units of the numerical values given in constraint_value.  Dimensionless: should only be used for activity or fugacity constraints.  Moles: mole number.  Molal: moles per kg solvent water.  kg: kilograms.  g: grams.  mg: milligrams.  ug: micrograms.  kg_per_kg_solvent: kilograms per kg solvent water.  g_per_kg_solvent: grams per kg solvent water.  mg_per_kg_solvent: milligrams per kg solvent water.  ug_per_kg_solvent: micrograms per kg solvent water.  cm3: cubic centimeters"}>>> = "   kg               moles        dimensionless moles            moles            moles"
  ramp_max_ionic_strength_initial<<<{"description": "The number of iterations over which to progressively increase the maximum ionic strength (from zero to max_ionic_strength) during the initial equilibration.  Increasing this can help in convergence of the Newton process, at the cost of spending more time finding the aqueous configuration."}>>> = 10
  controlled_activity_name<<<{"description": "The names of the species that have their activity or fugacity constrained.  There should be an equal number of these names as values given in controlled_activity_value.  NOTE: if these species are not in the basis, or they do not have an activity (or fugacity) constraint then their activity cannot be controlled: in this case MOOSE will ignore the value you prescribe in controlled_activity_value."}>>> = 'CO2(g)'
  controlled_activity_value<<<{"description": "Values of the activity or fugacity of the species in controlled_activity_name list.  These should always be positive"}>>> = fug_co2
  stoichiometric_ionic_str_using_Cl_only<<<{"description": "If set to true, the stoichiometric ionic strength will be set equal to Cl- molality (or max_ionic_strength if the Cl- molality is too big).  This flag overrides ionic_str_using_basis_molality_only"}>>> = true # for comparison with GWB
  execute_console_output_on<<<{"description": "When to execute the geochemistry console output"}>>> = '' # only CSV output required for this example
[]
(modules/geochemistry/test/tests/time_dependent_reactions/changing_fugacity_calcite.i)

The fug_co2 fugacity-controller is

[AuxKernels<<<{"href": "../../../syntax/AuxKernels/index.html"}>>>]
  [fug_co2]
    type = FunctionAux<<<{"description": "Auxiliary Kernel that creates and updates a field variable by sampling a function through space and time.", "href": "../../../source/auxkernels/FunctionAux.html"}>>>
    variable<<<{"description": "The name of the variable that this object applies to"}>>> = fug_co2
    function<<<{"description": "The function to use as the value"}>>> = '10^(-3.5*(1 - t))'
    execute_on<<<{"description": "The list of flag(s) indicating when this object should be executed. For a description of each flag, see https://mooseframework.inl.gov/source/interfaces/SetupInterface.html."}>>> = timestep_begin # so the correct value is provided to the reactor
  []
[]
(modules/geochemistry/test/tests/time_dependent_reactions/changing_fugacity_calcite.i)

with Executioner defining the notion of time:

[Executioner<<<{"href": "../../../syntax/Executioner/index.html"}>>>]
  type = Transient
  dt = 0.1
  end_time = 1
[]
(modules/geochemistry/test/tests/time_dependent_reactions/changing_fugacity_calcite.i)

The figures below were produced using a time-step size of 0.01 but the regression test uses a bigger dt for efficiency.

A number of Postprocessors capture information from the AuxVariables automatically included by the TimeDependentReactionSolver:

[Postprocessors<<<{"href": "../../../syntax/Postprocessors/index.html"}>>>]
  [cm3_Calcite]
    type = PointValue<<<{"description": "Compute the value of a variable at a specified location", "href": "../../../source/postprocessors/PointValue.html"}>>>
    point<<<{"description": "The physical point where the solution will be evaluated."}>>> = '0 0 0'
    variable<<<{"description": "The name of the variable that this postprocessor operates on."}>>> = 'free_cm3_Calcite'
  []
  [pH]
    type = PointValue<<<{"description": "Compute the value of a variable at a specified location", "href": "../../../source/postprocessors/PointValue.html"}>>>
    point<<<{"description": "The physical point where the solution will be evaluated."}>>> = '0 0 0'
    variable<<<{"description": "The name of the variable that this postprocessor operates on."}>>> = 'pH'
  []
  [molal_CO2aq]
    type = PointValue<<<{"description": "Compute the value of a variable at a specified location", "href": "../../../source/postprocessors/PointValue.html"}>>>
    point<<<{"description": "The physical point where the solution will be evaluated."}>>> = '0 0 0'
    variable<<<{"description": "The name of the variable that this postprocessor operates on."}>>> = 'molal_CO2(aq)'
  []
  [molal_HCO3-]
    type = PointValue<<<{"description": "Compute the value of a variable at a specified location", "href": "../../../source/postprocessors/PointValue.html"}>>>
    point<<<{"description": "The physical point where the solution will be evaluated."}>>> = '0 0 0'
    variable<<<{"description": "The name of the variable that this postprocessor operates on."}>>> = 'molal_HCO3-'
  []
  [molal_Ca++]
    type = PointValue<<<{"description": "Compute the value of a variable at a specified location", "href": "../../../source/postprocessors/PointValue.html"}>>>
    point<<<{"description": "The physical point where the solution will be evaluated."}>>> = '0 0 0'
    variable<<<{"description": "The name of the variable that this postprocessor operates on."}>>> = 'molal_Ca++'
  []
  [fug_co2]
    type = PointValue<<<{"description": "Compute the value of a variable at a specified location", "href": "../../../source/postprocessors/PointValue.html"}>>>
    point<<<{"description": "The physical point where the solution will be evaluated."}>>> = '0 0 0'
    variable<<<{"description": "The name of the variable that this postprocessor operates on."}>>> = 'activity_CO2(g)'
  []
[]
(modules/geochemistry/test/tests/time_dependent_reactions/changing_fugacity_calcite.i)

GWB input file

The equivalent Geochemists Workbench input file is

# React script that is equivalent to changing_fugacity_calcite.i
Na+ = 1e-2 mol
Cl- = 1e-2 mol
balance on HCO3-
swap Calcite for Ca++
Calcite = 0.01354 free mol
swap CO2(g) for H+
log f CO2(g) = -3.5
epsilon = 1e-13
slide f CO2(g) to 1
go
(modules/geochemistry/test/tests/time_dependent_reactions/changing_fugacity_calcite.rea)

Results

Bethke (2007) presents results in Figures 14.6 and 14.7. The Geochemists Workbench and geochemistry module results are shown below.

Figure 1: Calcite volume as CO fugacity is varied. Compare with Bethke's Figure 14.6

Figure 2: pH of a solution containing calcite as CO fugacity is varied. Compare with Bethke's Figure 14.6

Figure 3: Species concentrations as CO fugacity is varied in a solution containing calcite. Compare with Bethke's Figure 14.7

References

  1. Craig M. Bethke. Geochemical and Biogeochemical Reaction Modeling. Cambridge University Press, 2 edition, 2007. doi:10.1017/CBO9780511619670.[BibTeX]