Skip to content

Calliope.solubility

solubility

Solubility(composition)

Solubility base class.

Pressures are in bar; subclasses return dissolved concentration in ppmw (parts-per-million by weight in the silicate melt).

Source code in src/calliope/solubility.py
44
45
def __init__(self, composition):
    self.callmodel = getattr(self, composition)

SolubilityCH4(composition='basalt_ardia')

Bases: Solubility

CH4 solubility models

Source code in src/calliope/solubility.py
195
196
def __init__(self, composition='basalt_ardia'):
    super().__init__(composition)

basalt_ardia(p, p_total)

Ardia 2013

Source code in src/calliope/solubility.py
198
199
200
201
202
203
def basalt_ardia(self, p, p_total):
    """Ardia 2013"""
    p_total *= 1e-4  # Convert to GPa
    p *= 1e-4  # Convert to GPa
    ppmw = p * np.exp(4.93 - (1.93 * p_total))
    return ppmw

SolubilityCO(composition='mafic_armstrong')

Bases: Solubility

CO solubility models

Source code in src/calliope/solubility.py
209
210
def __init__(self, composition='mafic_armstrong'):
    super().__init__(composition)

mafic_armstrong(p, p_total)

Armstrong 2015

Source code in src/calliope/solubility.py
212
213
214
215
def mafic_armstrong(self, p, p_total):
    """Armstrong 2015"""
    ppmw = 10 ** (-0.738 + 0.876 * np.log10(p) - 5.44e-5 * p_total)
    return ppmw

SolubilityCO2(composition='basalt_dixon')

Bases: Solubility

CO2 solubility models

Source code in src/calliope/solubility.py
126
127
def __init__(self, composition='basalt_dixon'):
    super().__init__(composition)

basalt_dixon(p, temp)

Dixon et al. (1995)

Source code in src/calliope/solubility.py
129
130
131
132
133
def basalt_dixon(self, p, temp):
    """Dixon et al. (1995)"""
    ppmw = (3.8e-7) * p * np.exp(-23 * (p - 1) / (83.15 * temp))
    ppmw = 1.0e4 * (4400 * ppmw) / (36.6 - 44 * ppmw)
    return ppmw

SolubilityH2O(composition='peridotite')

Bases: Solubility

H2O solubility models

Source code in src/calliope/solubility.py
59
60
def __init__(self, composition='peridotite'):
    super().__init__(composition)

anorthite_diopside(p)

Newcombe et al. (2017)

Source code in src/calliope/solubility.py
62
63
64
def anorthite_diopside(self, p):
    """Newcombe et al. (2017)"""
    return self.power_law(p, 727, 0.5)

basalt_dixon(p)

Dixon et al. (1995) refit by Paolo Sossi

Source code in src/calliope/solubility.py
70
71
72
def basalt_dixon(self, p):
    """Dixon et al. (1995) refit by Paolo Sossi"""
    return self.power_law(p, 965, 0.5)

basalt_wilson(p)

Hamilton (1964) and Wilson and Head (1981)

Source code in src/calliope/solubility.py
74
75
76
def basalt_wilson(self, p):
    """Hamilton (1964) and Wilson and Head (1981)"""
    return self.power_law(p, 215, 0.7)

lunar_glass(p)

Newcombe et al. (2017)

Source code in src/calliope/solubility.py
78
79
80
def lunar_glass(self, p):
    """Newcombe et al. (2017)"""
    return self.power_law(p, 683, 0.5)

peridotite(p)

Sossi et al. (2023)

Source code in src/calliope/solubility.py
66
67
68
def peridotite(self, p):
    """Sossi et al. (2023)"""
    return self.power_law(p, 524, 0.5)

SolubilityN2(composition='libourel', x_SiO2=0.56, x_Al2O3=0.11, x_TiO2=0.01)

Bases: Solubility

N2 solubility models.

Parameters:

Name Type Description Default
composition str

Solubility-law name. 'libourel' selects the linear Henry's-law form of Libourel et al. (2003); 'dasgupta' selects the physical-state-dependent form of Dasgupta et al. (2022).

'libourel'
x_SiO2 float

Melt mole fractions used by the Dasgupta et al. (2022) law to compute the molecular-N2 prefactor dasfac_2. Defaults (0.56, 0.11, 0.01) match the Earth-mantle reference adopted in prior CALLIOPE releases; override for non-Earth compositions. These kwargs have no effect when composition='libourel'.

0.56
x_Al2O3 float

Melt mole fractions used by the Dasgupta et al. (2022) law to compute the molecular-N2 prefactor dasfac_2. Defaults (0.56, 0.11, 0.01) match the Earth-mantle reference adopted in prior CALLIOPE releases; override for non-Earth compositions. These kwargs have no effect when composition='libourel'.

0.56
x_TiO2 float

Melt mole fractions used by the Dasgupta et al. (2022) law to compute the molecular-N2 prefactor dasfac_2. Defaults (0.56, 0.11, 0.01) match the Earth-mantle reference adopted in prior CALLIOPE releases; override for non-Earth compositions. These kwargs have no effect when composition='libourel'.

0.56
Source code in src/calliope/solubility.py
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
def __init__(self, composition='libourel', x_SiO2=0.56, x_Al2O3=0.11, x_TiO2=0.01):
    super().__init__(composition)

    # Stored on the instance so callers can introspect them; defaults
    # match the Earth-mantle reference used by Dasgupta et al. (2022).
    self.x_SiO2 = x_SiO2
    self.x_Al2O3 = x_Al2O3
    self.x_TiO2 = x_TiO2
    # dasfac_2 is only consumed by the dasgupta() path, so skip the
    # exp(...) precompute when libourel is selected. This avoids a
    # spurious RuntimeWarning at construction time when a libourel
    # caller passes extreme composition values that would overflow
    # the exponent (the dasgupta path is the only one that cares).
    if composition == 'dasgupta':
        self.dasfac_2 = np.exp(4.67 + 7.11 * x_SiO2 - 13.06 * x_Al2O3 - 120.67 * x_TiO2)
    else:
        self.dasfac_2 = None

dasgupta(p, ptot, temp, fO2_shift)

Dasgupta et al. (2022)

Source code in src/calliope/solubility.py
176
177
178
179
180
181
182
183
184
185
186
187
188
189
def dasgupta(self, p, ptot, temp, fO2_shift):
    """Dasgupta et al. (2022)"""

    # convert bar to GPa
    pb_N2 = p * 1.0e-4
    pb_tot = ptot * 1.0e-4

    pb_tot = max(pb_tot, 1e-15)

    # calculate N2 concentration in melt
    ppmw = pb_N2**0.5 * np.exp(5908.0 * pb_tot**0.5 / temp - 1.6 * fO2_shift)
    ppmw += pb_N2 * self.dasfac_2

    return ppmw

libourel(p)

Libourel et al. (2003)

Source code in src/calliope/solubility.py
171
172
173
174
def libourel(self, p):
    """Libourel et al. (2003)"""
    ppmw = self.power_law(p, 0.0611, 1.0)
    return ppmw

SolubilityNobleGas(gas)

Bases: Solubility

Noble gas solubility by Henry's law, Jambon et al. (1986).

Each noble gas dissolves in silicate melt in proportion to its partial pressure, ppmw = const * p. What sets it apart from the reactive CHNOS volatiles is the absence of any chemistry: the law carries no melt-composition, temperature, or redox dependence, and the gas couples to no other species through a reaction.

Parameters:

Name Type Description Default
gas str

Noble gas symbol; one of He, Ne, Ar, Kr, Xe.

required
Notes

The calibration is tholeiitic basalt at 1 bar and 1250-1600 C. Applying it at the high surface pressures of a noble-gas-rich atmosphere is an extrapolation of a 1-bar, linear Henry law with no saturation term.

Source code in src/calliope/solubility.py
274
275
276
277
278
279
280
281
282
def __init__(self, gas: str):
    if gas not in noble_gases:
        raise ValueError(
            f"SolubilityNobleGas: '{gas}' is not a noble gas. "
            f'Expected one of {noble_gases}.'
        )
    self.gas = gas
    self.const = jambon86_ppmw_per_bar(gas)
    super().__init__('jambon86')

jambon86(p)

Jambon et al. (1986) linear Henry's law: ppmw = const * p.

Source code in src/calliope/solubility.py
284
285
286
def jambon86(self, p):
    """Jambon et al. (1986) linear Henry's law: `ppmw = const * p`."""
    return self.power_law(p, self.const, 1.0)

SolubilityS2(composition='gaillard', x_FeO=10.0)

Bases: Solubility

S2 solubility models.

Parameters:

Name Type Description Default
composition str

Solubility-law name (currently only 'gaillard' is implemented).

'gaillard'
x_FeO float

Melt FeO content [wt%] used by the Gaillard et al. (2022) law. The default value matches the Earth-mantle reference adopted in prior CALLIOPE releases; override for non-Earth bulk compositions.

10.0
Source code in src/calliope/solubility.py
 97
 98
 99
100
def __init__(self, composition='gaillard', x_FeO=10.0):
    self.fO2_model = OxygenFugacity()
    self.x_FeO = x_FeO
    super().__init__(composition)

jambon86_ppmw_per_bar(gas)

Henry's-law solubility constant for a noble gas [ppmw / bar].

Converts the Jambon et al. (1986) STP-volume Henry constant for gas into parts-per-million by weight of dissolved gas per bar of partial pressure, using the melt-independent chain

const [ppmw/bar] = (k_STP / V_STP) [mol/g/bar]
                   * M [g/mol]
                   * 1e6 [ppmw per mass fraction]

where k_STP is the tabulated constant in cm3 STP/g/bar, V_STP is the molar volume of an ideal gas at STP, and M is the molar mass. The result is the linear coefficient of the ppmw = const * p Henry law.

Parameters:

Name Type Description Default
gas str

Noble gas symbol; one of He, Ne, Ar, Kr, Xe.

required

Returns:

Type Description
float

Solubility constant in ppmw per bar.

Raises:

Type Description
KeyError

If gas is not a Jambon et al. (1986) noble gas.

Source code in src/calliope/solubility.py
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
def jambon86_ppmw_per_bar(gas: str) -> float:
    """Henry's-law solubility constant for a noble gas [ppmw / bar].

    Converts the Jambon et al. (1986) STP-volume Henry constant for `gas`
    into parts-per-million by weight of dissolved gas per bar of partial
    pressure, using the melt-independent chain

        const [ppmw/bar] = (k_STP / V_STP) [mol/g/bar]
                           * M [g/mol]
                           * 1e6 [ppmw per mass fraction]

    where `k_STP` is the tabulated constant in cm3 STP/g/bar, `V_STP` is the
    molar volume of an ideal gas at STP, and `M` is the molar mass. The
    result is the linear coefficient of the `ppmw = const * p` Henry law.

    Parameters
    ----------
    gas : str
        Noble gas symbol; one of `He`, `Ne`, `Ar`, `Kr`, `Xe`.

    Returns
    -------
    float
        Solubility constant in ppmw per bar.

    Raises
    ------
    KeyError
        If `gas` is not a Jambon et al. (1986) noble gas.
    """
    k_stp = JAMBON86_STP_HENRY[gas]
    molar_mass_g = molar_mass[gas] * 1.0e3  # kg/mol -> g/mol
    return (k_stp / STP_MOLAR_VOLUME_CM3) * molar_mass_g * 1.0e6