Skip to content

solution.Solution

Bases: object

An aqueous solution.

Notes

See phreeqpython.add_solution() for details on creating a solution.

Methods:

  • __add__ –

    Add two solutions.

  • __div__ –

    Set devision factor.

  • __init__ –

    Returns an empty solution.

  • __mul__ –

    Set multiplication factor.

  • __str__ –

    Returns solution and number.

  • __truediv__ –

    Python 3 support.

  • activity –

    Returns the activity of a species in the solution.

  • add –

    Add a species to the solution.

  • chain –

    CHECK

  • change –

    Change the solution by adding or removing species.

  • change_ph –

    Change the pH of the solution.

  • change_temperature –

    Change the temperature of the solution.

  • copy –

    Returns an independent copy of the solution.

  • desaturate –

    Desaturate a solution from a pure phase via precipitation or vaporization.

  • end –

    CHECK

  • equalize –

    Equalize the solution with one or more pure phases.

  • forget –

    Remove this solution from the PhreeQC simulation.

  • interact –

    Equilibrate the solution with a multicomponent gas or solid phase.

  • kinetics –

    CHECK

  • molality –

    Returns the molality of a species in the solution.

  • moles –

    Returns the amount of a species in the solution.

  • remove –

    Remove a species from the solution.

  • remove_fraction –

    Remove a fraction of the species from the solution.

  • saturate –

    Saturate the solution with a pure phase.

  • si –

    Returns the saturation index (SI) of a phase in the solution.

  • sr –

    Returns the saturation ratio (SR) of a phase in the solution.

  • total –

    Returns the amount of a species in the solution.

  • total_activity –

    Returns the total of the activities of all species of the element in the solution.

  • total_element –

    Returns the total amount of an element in the solution.

Attributes:

  • I –

    Returns the ionic strength of the solution.

  • density –

    Returns the density of the solution.

  • elements –

    Returns all elements in the solution and their amount.

  • extraneous –
  • factor –
  • mass –

    Returns the mass of water in the solution.

  • masters_species –

    Returns all master species in the solution and their species.

  • mu –

    Returns the ionic strength of the solution.

  • number –
  • pH –

    Returns the pH of the solution.

  • pe –

    REturns the electron activity of the solution.

  • phases –

    Returns all phases in the solution and their saturation index (SI).

  • pp –
  • sc –

    Returns the specific conductance of the solution.

  • species –

    Returns all species in the solution and their amount.

  • species_activities –

    Returns all species in the solution and their activities.

  • species_molalities –

    Returns all species in the solution and their concentration.

  • species_moles –

    Returns all species in the solution and their amount.

  • temperature –

    Returns the temperature of the solution.

  • volume –

    Returns the volume of the solution.

Attributes

I property

Returns the ionic strength of the solution.

Returns:

  • float –

    The ionic strength (mol/L).

density property

Returns the density of the solution.

Returns:

  • float –

    The density (kg/L).

(kg/L).

elements property

Returns all elements in the solution and their amount.

Returns:

  • dict –

    With phase (str) and amount (float) pairs, amount in mol.

Examples:

>>> sol.elements
{   'C(4)': 0.50,
    'Ca': 0.20,
    ... 
}

extraneous = {} if extraneous is None else extraneous instance-attribute

factor = 1 instance-attribute

mass property

Returns the mass of water in the solution.

Returns:

  • float –

    The mass of water (kg).

Warning

not very intuitive, one would expect this to return the solution mass, not the water part.
I did a few checks with high salt concentrations:
sol.volume * sol.density always accurately returns the solution mass.

Proposal:
sol.mass = sol.volume * sol.density
sol.mass_water = the water mass

masters_species property

Returns all master species in the solution and their species.

Returns:

  • dict –

    with master_species (str) and species (lst[str]) pairs.

Examples:

>>> sol.masters_species        
{   'C(4)': ['CO2', 'CO3-2', 'CaCO3', 'HCO3-'],
    'Ca': ['Ca+2', 'CaCO3', 'CaHCO3+', 'CaOH+'],
    'Cl': ['Cl-'],
    ...
}
Warning

shouldn't this be: master_species ?

mu property

Returns the ionic strength of the solution.

Returns:

  • float –

    The ionic strength (mol/L).

number = number instance-attribute

pH property

Returns the pH of the solution.

Returns:

  • float –

    The pH (-).

pe property

REturns the electron activity of the solution.

Returns:

  • float –

    The electron activity (-).

Notes

pe = -log({e-}), with {e-} the electron activity.
pe < 0: high electron activity, reducing environment.
pe > 0: low electron activity, oxidizing environment.

phases property

Returns all phases in the solution and their saturation index (SI).

Returns:

  • dict –

    With phase (str) and SI (float) pairs.

Example

sol.phases { 'Calcite': 0.155, 'CO2(g)': -0.341, ... }

Notes

SI = log10(AIP / Ksp)

pp = phreeqpython instance-attribute

sc property

Returns the specific conductance of the solution.

Returns:

  • float –

    The specific conductance (µS/cm).

Notes

Specific conductance calculated at temperature of the solution.

species property

Returns all species in the solution and their amount.

Returns:

  • dict –

    With species (str) and amount (float) pairs, amount in mmol.

Examples:

>>> sol.species
{   'Ca+2': 0.0036,
    'CO3-2': 2.18e-05,
    ...
}
Warning

units not used, and probably not accessible via a property?
amount is in mol, not mol/L or mol/kgw, can be confusing when sol.mass <> 1.0 kg,
better return a concentration (mol/kgw or mol/kgs)?

species_activities property

Returns all species in the solution and their activities.

Returns:

  • dict –

    With species (str) and activity (float) pairs, activity in mol/kgw.

Examples:

>>> sol.species_activities
{   'Ca+2': 0.045,
    'CO3-2': 3.18e-05,
    ...
}

species_molalities property

Returns all species in the solution and their concentration.

Returns:

  • dict –

    With species (str) and concentration (float) pairs, concentration in mol/kgw.

Examples:

>>> sol.species_molalities
{   'Ca+2': 0.045,
    'CO3-2': 3.18e-05,
    ...
}
Warning

units not used.
this property returns a concentration (mol/kgw), while sol.species returns
absolute amount (mol). Not very intuitive.
Maybe we could define the default units on the simulation level (phreeqpython = pp)?
And have an accessible function to convert if needed (pp.units(...))?

species_moles property

Returns all species in the solution and their amount.

Returns:

  • dict –

    With species (str) and amount (float) pairs, amount in mol.

Warning

calls same function, no difference with property species?
better drop this one?

temperature property

Returns the temperature of the solution.

Returns:

  • float –

    The temperature (°C).

volume property

Returns the volume of the solution.

Returns:

  • float –

    The volume (L).

Methods:

__add__(other)

Add two solutions.

Warning

Remark for creating these:
>>> sol3 = sol1 * 0.2 + sol2 * 0.8
>>> sol3 = sol1 * 0.2
>>> sol3 = sol1 / 4.0

currently, sol.factor is used to track the coefficient in making these mixtures.

But doing this: sol3 = sol1*2 does not increase sol3.mass, it only sets sol3.factor, which is not what the user wants.

Also: sol3 = sol11 + sol12 gives: sol3.mass = 2, not 3, because the second term sets sol1.factor = 2, and then the addition is evaluated

Wouldn't it be easier and more intuitive to do as follows?: sol1*2 calls:
def mul(self, factor):
mixture = self.pp.mix_solutions({self: factor})
return mixture

No need anymore to track the factors, and the resulting solutions always reflect the proper amount. sol3 = sol1 * 0.2 + sol2 * 0.8 will then call mix_solutions 3 times, small price to pay?

__div__(other)

Set devision factor.

__init__(phreeqpython, number, extraneous=None)

Returns an empty solution.

Notes

Use phreeqpython.add_solution() to create a solution.

Warning

the fields: pp, factor, number and extraneous are accessible by the user.
probably not the intention?
Better to make them private?

__mul__(other)

Set multiplication factor.

__str__()

Returns solution and number.

Returns:

  • str –

    A string like:

__truediv__(other)

Python 3 support.

activity(species, units='mmol')

Returns the activity of a species in the solution.

Parameters:

  • element (str) –

    Chemical species.

  • units (str, default: 'mmol' ) –

    Optional, unit of the activity.

Returns:

  • float –

    Activity of the species (mmol/kgw).

Examples:

>>> sol.activity('Ca+2')
>>> sol.activity('NaSO4-', 'mg')        
Warning

this returns a concentration (/kgw), not a total amount.
Confusing with the units shown.

add(element, amount, units='mmol')

Add a species to the solution.

Parameters:

  • element (str) –

    An element or species.

  • amount (float) –

    Amount of the species added.

  • units (str, default: 'mmol' ) –

    Optional, unit of the amount.

Returns:

  • Solution –

    The altered solution.

Examples:

>>> sol.add('Fe', 5.0)
>>> sol.add('CaCO3', 10.0, 'mg')

chain()

CHECK

Warning

This calls the PhreeQC 'USE SOLUTION' keyword, but not clear when you would need to use this, not intuitive.
What are the use cases?

change(composition, units='mmol')

Change the solution by adding or removing species.

Parameters:

  • composition (dict) –

    A dictionary of (species, amount) pairs.

  • units (str, default: 'mmol' ) –

    Optional, unit of the amounts.

Returns:

  • Solution –

    The altered solution.

Examples:

>>> sol.change({'K': 20.0, 'Na': -10.0})
>>> sol.change({'CaSO4': 5.0}, units='mg')
>>> sol.change({'NaCl': -10.0, 'Fe+2': -5.0})

change_ph(to_pH, with_chemical=None)

Change the pH of the solution.

Parameters:

  • to_pH (float) –

    target pH.

  • with_chemical (str, default: None ) –

    Optional, acid of base to add, default is 'HCl' or 'NaOH'.

Returns:

Examples:

>>> sol.change_ph(4.5)
>>> sol.change_ph(4.5, 'H2SO4')

change_temperature(to_temperature)

Change the temperature of the solution.

Parameters:

  • to_temperature (float) –

    Target temperature.

Returns:

Examples:

>>> sol.change_temperature(50.0)

copy()

Returns an independent copy of the solution.

Examples:

>>> sol2 = sol.copy()

desaturate(phase, to_si=0)

Desaturate a solution from a pure phase via precipitation or vaporization.

Parameters:

  • phase (str) –

    A pure gas or solid phase.

  • to_si (float, default: 0 ) –

    Optional, target saturation index for the phase.

Returns:

  • Solution –

    The solution after equilibration.

Examples:

>>> sol.desaturate('Gypsum')
>>> sol.desaturate('CO2(g)', to_si=-3.5)
Notes

This method will only desaturate, not saturate.

end()

CHECK

Warning

Calls the keyword 'END' on the PhreeQC simulation?
Not better to only define that at the simulation side (pp)?
Its use for a solution is not clear.

equalize(phases, to_si=[0.0], in_phase=[10.0], with_chemical=[None])

Equalize the solution with one or more pure phases.

Parameters:

  • phases (lst[str]) –

    List of one or more pure gas or solid phases.

  • to_si (lst[float], default: [0.0] ) –

    Optional, list of target saturation indices for each phase.

  • in_phase (lst[float], default: [10.0] ) –

    Optional, list of maximum amounts available for each phase, in moles.

  • with_chemical (lst[str], default: [None] ) –

    Optional, list of alternative chemical added for each phase to reach the specified saturation index.

Returns:

  • Solution –

    The solution after equilibration.

Examples:

>>> sol.equalize(phases=['Calcite'])
>>> sol.equalize(phases=['CO2(g)', 'CH4(g)'], to_si=[-0.4, -0.2])
>>> sol.equalize(phases=['Calcite'], with_chemical='HCl')
Notes

saturation index (SI):
for solid phases: SI = log10(IAP / Ksp)
for gases: SI = log10(p_gas), with p_gas the partial pressure.

forget()

Remove this solution from the PhreeQC simulation.

Notes

See also phreeqpython.add_solution() to add solutions to a PhreeQC simulation.

interact(gas_or_phase)

Equilibrate the solution with a multicomponent gas or solid phase.

Parameters:

  • gas_or_phase (Gas | Equilibriumphase) –

    Previously defined multicomponent gas or solid phase.

Returns:

  • Solution –

    The solution after equilibrium with the gas or solid phase.

Examples:

>>> air = pp.add_gas({'O2(g)': 0.2, 'N2(g)': 0.78, 'CO2(g)': 0.000420})
>>> sol.interact(air)

kinetics(element, rate_function, time, m0=0, args=(), units='mmol')

CHECK

Warning

the kinetics examples show different ways of setting up kinetics (with and without this function). Still experimental?
PhreeQC has the kinetics keyword, but would require to parse the rate function(s) into BASIC, hard... but PhreeQC allows kinetics over the whole simulation (e.g. solution, gas, other phases)

Not better to move kinetics functionality to the simulation level (phreeqpython = pp)?

molality(species, units='mmol')

Returns the molality of a species in the solution.

Parameters:

  • element (str) –

    Chemical species.

  • units (str, default: 'mmol' ) –

    Optional, unit of the amount.

Returns:

  • float –

    Molality of the species (mmol/kgw).

Examples:

>>> sol.molality('Na+')
>>> sol.molality('HCO3-', 'mg')        
Warning

Confusing, units given in 'mmol'... , but returns 'mmol/kgw'?
Checked with {'-water': 2.0, ...} as solution: sol.total() and sol.moles() return 'mmol',
but sol.molality() returns ~half the value, so takes count of the total mass.
Should we show different units?

moles(species, units='mmol')

Returns the amount of a species in the solution.

Parameters:

  • element (str) –

    Chemical species.

  • units (str, default: 'mmol' ) –

    Optional, unit of the amount.

Returns:

  • float –

    Amount of the species (mmol).

Examples:

>>> sol.moles('Na+')
>>> sol.moles('HCO3-', 'mg')        
Warning

Confusing, says moles, but can also return in 'mg'.
Also, seems to always return the same value as sol.total().
Better to remove this method?

remove(element, amount, units='mmol')

Remove a species from the solution.

Parameters:

  • element (str) –

    An element or species.

  • amount (float) –

    Amount of the species removed.

  • units (str, default: 'mmol' ) –

    Optional, unit of the amount.

Returns:

  • Solution –

    The altered solution.

Examples:

>>> sol.remove('Fe', 5.0)
>>> sol.remove('CaCO3', 10.0, 'mg')

remove_fraction(species, fraction)

Remove a fraction of the species from the solution.

Parameters:

  • species (str) –

    An element or species.

  • fraction (float) –

    Fraction of amount to remove.

Returns:

  • Solution –

    The altered solution.

Examples:

>>> sol.remove('K', 0.3)
>>> sol.remove('H2O', 0.9)

saturate(phase, to_si=0, in_phase=10)

Saturate the solution with a pure phase.

Parameters:

  • phase (str) –

    A pure gas or solid phase.

  • to_si (float, default: 0 ) –

    Optional, target saturation index for the phase.

  • in_phase (float, default: 10 ) –

    Optional, maximum amount available of the phase.

Returns:

  • Solution –

    The solution after equilibration.

Examples:

>>> sol.saturate('Calcite')
>>> sol.saturate('CO2(g)', to_si=-3.5)

si(phase)

Returns the saturation index (SI) of a phase in the solution.

Parameters:

  • phase (str) –

    Gas or solid phase.

Returns:

  • float –

    The SI of the phase (-).

Examples:

>>> sol.si('Calcite')
>>> sol.si('CO2(g)')
Notes

Solid phases: SI = log10(IAP / Ksp), with IAP the ion activity product and Ksp the solubility product constant.
Gases: SI = log10(p_gas), with p_gas the partial pressure.

sr(phase)

Returns the saturation ratio (SR) of a phase in the solution.

Parameters:

  • phase (str) –

    Gas or solid phase.

Returns:

  • float –

    The SR of the phase (-).

Examples:

>>> sol.sr('Calcite')
>>> sol.sr('CO2(g)')
Notes

Solid phases: SR = IAP / Ksp, with IAP the ion activity product and Ksp the solubility product constant.
Gases: SR = p_gas, with p_gas the partial pressure.

total(element, units='mmol')

Returns the amount of a species in the solution.

Parameters:

  • element (str) –

    Chemical species.

  • units (str, default: 'mmol' ) –

    Optional, unit of the amount.

Returns:

  • float –

    Amount of the species (mmol).

Examples:

>>> sol.total('Na+')
>>> sol.total('CO2')
>>> sol.total('HCO3-', 'mg')

total_activity(element, units='mmol')

Returns the total of the activities of all species of the element in the solution.

Parameters:

  • element (str) –

    Element (atomic species).

  • units (str, default: 'mmol' ) –

    Optional, unit of the activity.

Returns:

  • float –

    Total activity of the element (mmol/kgw).

Examples:

>>> sol.activity('Ca')
>>> sol.activity('C', 'mg')        
Warning

Slow function!

total_element(element, units='mmol')

Returns the total amount of an element in the solution.

Parameters:

  • element (str) –

    Element (atomic species).

  • units (str, default: 'mmol' ) –

    Optional, unit of the amount.

Returns:

  • float –

    Total amount of the element (mmol).

Examples:

>>> sol.total_element('C')
>>> sol.total_element('S', 'mg')