# melt_gas.py
import pandas as pd
import math
import warnings as w
# import model_dependent_variables as mdv
import VolFe.model_dependent_variables as mdv
import VolFe.equilibrium_equations as eq
########################################################################################
# Contents #############################################################################
########################################################################################
# Fugacity, mole fraction, partial pressure
# Speciation
# Converting gas and melt compositions
# Volume and density
########################################################################################
# FUGACITY, MOLE FRACTION, PARTIAL PRESSURE ############################################
########################################################################################
[docs]
def f_H2O(PT, melt_wf, models):
"""
Calculates fugacity of water in the vapor from concentration (mole fraction) of
water in the melt.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (e.g., SiO2, TiO2, etc.), particularly H2O.
models: pandas.DataFrame
Model options: minimum requirement is a DataFrame with index of “Hspeciation”
and column label of “option”.
Returns
-------
float
fH2O in bars
See C_H2O for model options for 'Hspeciation'.
"""
Hspeciation = models.loc["Hspeciation", "option"]
# fH2O = xmH2OT^2/CH2O
if Hspeciation in ["none", "none+ideal", "none+regular"]:
value = ((xm_H2OT_so(melt_wf)) ** 2.0) / mdv.C_H2O(PT, melt_wf, models)
return value
# fH2O = xmH2OT/CH2O
elif Hspeciation == "linear":
value = xm_H2OT_so(melt_wf) / mdv.C_H2O(PT, melt_wf, models)
return value
# regular or ideal: fH2O = xmH2Omol/CH2O
else:
value = xm_H2Omol_so(PT, melt_wf, models) / mdv.C_H2O(PT, melt_wf, models)
return value
[docs]
def f_CO2(PT, melt_wf, models):
"""
Calculates fugacity of CO2 in the vapor from concentration (mole fraction) of total
CO2 (i.e., CO2,mol + CO32-) in the melt.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.), in particular CO2.
models: pandas.DataFrame
Model options: minimum requirement is dataframe with index of “carbon dioxide”
and column label of “option”.
Returns
-------
float
fCO2 in bars
See C_CO2 for model options for "carbon dioxide".
"""
CO3model = models.loc["carbon dioxide", "option"]
# wtppm CO2 modified from Shishkina et al. (2014) Chem. Geol. 388:112-129
if CO3model == "Shishkina14":
f = (melt_wf["CO2"] * 1000000.0) / mdv.C_CO3(PT, melt_wf, models)
# fCO2 = xmCO2/C_CO3
else:
f = xm_CO2_so(melt_wf) / mdv.C_CO3(PT, melt_wf, models)
return f
[docs]
def f_S2(PT, melt_wf, models):
"""
Calculates fugacity of S2 in the vapor from concentration (weight fraction) of *S2-
in the melt.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.), in particular *S2-.
models: pandas.DataFrame
Model options.
Returns
-------
float
fS2 in bars
"""
K = mdv.C_S(PT, melt_wf, models) / 1000000.0
return ((melt_wf["S2-"] / K) ** 2.0) * mdv.f_O2(PT, melt_wf, models)
[docs]
def f_H2(PT, melt_wf, models):
"""
Calculates fugacity of H2 in the vapor from fH2O and fO2 based on melt composition.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.)
models: pandas.DataFrame
Model options.
Returns
-------
float
fH2 in bars
"""
K = mdv.KHOg(PT, models)
return f_H2O(PT, melt_wf, models) / (K * mdv.f_O2(PT, melt_wf, models) ** 0.5)
[docs]
def f_CO(PT, melt_wf, models):
"""
Calculates fugacity of CO in the vapor from fCO2 and fO2 based on melt composition.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.)
models: pandas.DataFrame
Model options.
Returns
-------
float
fCO in bars
"""
K = mdv.KCOg(PT, models)
return f_CO2(PT, melt_wf, models) / (K * mdv.f_O2(PT, melt_wf, models) ** 0.5)
[docs]
def f_H2S(PT, melt_wf, models):
"""
Calculates fugacity of H2S in the vapor from fS2, fH2O, and fO2 based on melt
composition.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.)
models: pandas.DataFrame
Model options.
Returns
-------
float
fH2S in bars
"""
K = mdv.KHOSg(PT, models)
return (
K * f_S2(PT, melt_wf, models) ** 0.5 * f_H2O(PT, melt_wf, models)
) / mdv.f_O2(PT, melt_wf, models) ** 0.5
[docs]
def f_SO2(PT, melt_wf, models):
"""
Calculates fugacity of SO2 in the vapor from fS2 and fO2 based on melt composition.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.)
models: pandas.DataFrame
Model options.
Returns
-------
float
fSO2 in bars
"""
K = mdv.KOSg(PT, models)
return K * mdv.f_O2(PT, melt_wf, models) * f_S2(PT, melt_wf, models) ** 0.5
[docs]
def f_SO3(PT, melt_wf, models):
"""
Calculates fugacity of SO3 in the vapor from fS2 and fO2 based on melt composition.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.)
models: pandas.DataFrame
Model options.
Returns
-------
float
fSO2 in bars
"""
K = mdv.KOSg2(PT, models)
return (
K * (mdv.f_O2(PT, melt_wf, models)) ** 1.5 * (f_S2(PT, melt_wf, models)) ** 0.5
)
[docs]
def f_CH4(PT, melt_wf, models):
"""
Calculates fugacity of CH4 in the vapor from fCO2, fH2O, and fO2 based on melt
composition.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.)
models: pandas.DataFrame
Models options.
Returns
-------
float
fCH4 in bars
"""
K = mdv.KCOHg(PT, models)
return (f_CO2(PT, melt_wf, models) * f_H2O(PT, melt_wf, models) ** 2.0) / (
K * mdv.f_O2(PT, melt_wf, models) ** 2.0
)
[docs]
def f_OCS(PT, melt_wf, models):
"""
Calculates fugacity of OCS in the vapor from fCO2, fH2O, and fH2S or fSO2 based on
melt composition.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.)
models: pandas.DataFrame
Model options.
Returns
-------
float
fOCS in bars
"""
OCSmodel = models.loc["carbonylsulfide", "option"]
K = mdv.KOCSg(PT, models)
if OCSmodel == "COHS":
if f_H2O(PT, melt_wf, models) > 0.0:
return (f_CO2(PT, melt_wf, models) * f_H2S(PT, melt_wf, models)) / (
f_H2O(PT, melt_wf, models) * K
)
else:
return 0.0
else:
if f_CO2(PT, melt_wf, models) > 0.0:
return ((f_CO(PT, melt_wf, models) ** 3.0) * f_SO2(PT, melt_wf, models)) / (
(f_CO2(PT, melt_wf, models) ** 2.0) * K
)
else:
return 0.0
[docs]
def f_X(PT, melt_wf, models):
"""
Calculates fugacity of X in the vapor from concentration (weight fraction) of X in
the melt.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.)
models: pandas.DataFrame
Model options.
Returns
-------
float
fX in bars
"""
K = mdv.C_X(PT, melt_wf, models) / 1000000.0
return melt_wf["XT"] / K
#######################
# oxygen fugacity #####
#######################
[docs]
def fO22Dbuffer(PT, fO2, buffer, models):
"""
Converts absolute fO2 to value relative-to-buffer.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
fO2: float
fO2 in bars
buffer: str
Buffer of interest, currently available options are Ni-NiO (NNO) or
Fayalite-Magnetite-Quartz (FMQ).
models: pandas.DataFrame
Models options.
Returns
-------
float
fO2 value relative to buffer
"""
# Ni-NiO
if buffer == "NNO":
return math.log10(fO2) - mdv.NNO(PT, models)
# Fayalite-Magnetite-Quartz
elif buffer == "FMQ":
return math.log10(fO2) - mdv.FMQ(PT, models)
[docs]
def Dbuffer2fO2(PT, D, buffer, model):
"""
Converts value relative-to-buffer to absolute fO2.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
D: float
fO2 value relative to buffer.
buffer: str
Buffer of interest, current options are Ni-NiO (NNO) or
Fayalite-Magnetite-Quartz (FMQ).
models: pandas.DataFrame
Model options.
Returns
-------
float
fO2 in bars
"""
# Ni-NiO
if buffer == "NNO":
return 10.0 ** (D + mdv.NNO(PT, model))
# Fayalite-Magnetite-Quartz
elif buffer == "FMQ":
return 10.0 ** (D + mdv.FMQ(PT, model))
[docs]
def S6S2_2_fO2(S62, melt_wf, PT, models):
"""
Converts S6+/S2- in the melt to fO2.
Parameters
----------
S62: float
S6+/S2- in melt.
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
models: pandas.DataFrame
Model options.
Returns
-------
float
fO2 in bars
"""
def calc_fO2(S62, melt_wf, PT, models):
CSO4 = mdv.C_SO4(PT, melt_wf, models) / 1000000.0
CS = mdv.C_S(PT, melt_wf, models) / 1000000.0
if models.loc["H2S_m", "option"] == "False":
fO2 = ((S62 * CS) / CSO4) ** 0.5
elif models.loc["H2S_m", "option"] == "True":
KHS = mdv.KHOSg(PT, models)
CH2S = (
(mdv.C_H2S(PT, melt_wf, models) / 1000000.0)
/ mdv.species.loc["H2S", "M"]
) * mdv.species.loc["S", "M"]
CH2OT = mdv.C_H2O(PT, melt_wf, models)
xmH2O = xm_H2OT_so(melt_wf)
W = CSO4 / ((KHS * CH2S * (xmH2O**2.0 / CH2OT)) + CS)
fO2 = (S62 / W) ** 0.5
return fO2, xmH2O
melt_wf["Fe3FeT"] = 0.1
fO2, xmH2O = calc_fO2(S62, melt_wf, PT, models)
Fe3FeT = mdv.fO22Fe3FeT(fO2, PT, melt_wf, models)
delta1 = abs(melt_wf["Fe3FeT"] - Fe3FeT)
conc = eq.melt_speciation(PT, melt_wf, models, 1.0, 1.0e-9)
melt_wf["H2OT"] = conc["wm_H2O"]
melt_wf["CO2"] = conc["wm_CO2"]
delta2 = abs(xmH2O - xm_H2OT_so(melt_wf))
while delta1 > 0.0001 or delta2 > 1.0e-9:
melt_wf["Fe3FeT"] = Fe3FeT
fO2, xmH2O = calc_fO2(S62, melt_wf, PT, models)
Fe3FeT = mdv.fO22Fe3FeT(fO2, PT, melt_wf, models)
delta1 = abs(melt_wf["Fe3FeT"] - Fe3FeT)
conc = eq.melt_speciation(PT, melt_wf, models, 1.0, 1.0e-9)
melt_wf["H2OT"] = conc["wm_H2O"]
melt_wf["CO2"] = conc["wm_CO2"]
delta2 = abs(xmH2O - xm_H2OT_so(melt_wf))
else:
fO2, xmH2O = calc_fO2(S62, melt_wf, PT, models)
# S6p = melt_wf["ST"]*(S62/(1.+S62))
# S2mT = melt_wf["ST"] - S6p
# S_H2S_S2m = (mdv.KHOSg(PT,models)*(mdv.C_H2S(PT,melt_wf,models)/1000000.)*
# (xmH2O**2./mdv.C_H2O(PT,melt_wf,models)))/(mdv.C_S(PT,melt_wf,models)/1000000.)
# S_H2S = S2mT*(S_H2S_S2m/(1.+S_H2S_S2m))
# H2S = (S_H2S/mdv.species.loc['S','M'])*mdv.species.loc['H2S','M']
# S2m = S2mT - S_H2S
return fO2
########################
# partial pressure #####
########################
[docs]
def p_H2(PT, melt_wf, models):
"""
Converts fH2 based on melt composition to partial pressure of H2 (pH2).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
pH2 in bars
"""
return f_H2(PT, melt_wf, models) / mdv.y_H2(PT, models)
[docs]
def p_H2O(PT, melt_wf, models):
"""
Converts fH2O based on melt composition to partial pressure of H2O (pH2O).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
pH2O in bars
"""
return f_H2O(PT, melt_wf, models) / mdv.y_H2O(PT, models)
[docs]
def p_O2(PT, melt_wf, models):
"""
Converts fO2 based on melt composition to partial pressure of O2 (pO2).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
pO2 in bars
"""
return mdv.f_O2(PT, melt_wf, models) / mdv.y_O2(PT, models)
[docs]
def p_SO2(PT, melt_wf, models):
"""
Converts fSO2 based on melt composition to partial pressure of SO2 (pSO2).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
pSO2 in bars
"""
return f_SO2(PT, melt_wf, models) / mdv.y_SO2(PT, models)
[docs]
def p_S2(PT, melt_wf, models):
"""
Converts fS2 based on melt composition to partial pressure of S2 (pS2).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.)
models: pandas.DataFrame
Model options.
Returns
-------
float
pS2 in bars
"""
return f_S2(PT, melt_wf, models) / mdv.y_S2(PT, models)
[docs]
def p_H2S(PT, melt_wf, models):
"""
Converts fH2S based on melt composition to partial pressure of H2S (pH2S).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
pH2S in bars
"""
return f_H2S(PT, melt_wf, models) / mdv.y_H2S(PT, models)
[docs]
def p_CO2(PT, melt_wf, models):
"""
Converts fCO2 based on melt composition to partial pressure of CO2 (pCO2).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
pCO2 in bars
"""
return f_CO2(PT, melt_wf, models) / mdv.y_CO2(PT, models)
[docs]
def p_CO(PT, melt_wf, models):
"""
Converts fCO based on melt composition to partial pressure of CO (pCO).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
pCO in bars
"""
return f_CO(PT, melt_wf, models) / mdv.y_CO(PT, models)
[docs]
def p_CH4(PT, melt_wf, models):
"""
Converts fCH4 based on melt composition to partial pressure of CH4 (pCH4).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
pCH4 in bars
"""
return f_CH4(PT, melt_wf, models) / mdv.y_CH4(PT, models)
[docs]
def p_OCS(PT, melt_wf, models):
"""
Converts fOCS based on melt composition to partial pressure of OCS (pOCS).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
pOCS in bars
"""
return f_OCS(PT, melt_wf, models) / mdv.y_OCS(PT, models)
[docs]
def p_X(PT, melt_wf, models):
"""
Converts fX based on melt composition to partial pressure of X (pX).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
pX in bars
"""
return f_X(PT, melt_wf, models) / mdv.y_X(PT, models)
[docs]
def p_tot(PT, melt_wf, models):
"""
Calculate total pressure by summing partial pressures of all vapor species based on
melt composition.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
total P in bars
"""
return (
p_H2(PT, melt_wf, models)
+ p_H2O(PT, melt_wf, models)
+ p_O2(PT, melt_wf, models)
+ p_SO2(PT, melt_wf, models)
+ p_S2(PT, melt_wf, models)
+ p_H2S(PT, melt_wf, models)
+ p_CO2(PT, melt_wf, models)
+ p_CO(PT, melt_wf, models)
+ p_CH4(PT, melt_wf, models)
+ p_OCS(PT, melt_wf, models)
+ p_X(PT, melt_wf, models)
)
############################
# vapor molar fraction #####
############################
[docs]
def xg_H2(PT, melt_wf, models):
"""
Converts pH2 based on melt composition to mole fraction of H2 in the vapor.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of H2 in the vapor
"""
return p_H2(PT, melt_wf, models) / PT["P"]
[docs]
def xg_H2O(PT, melt_wf, models):
"""
Converts pH2O based on melt composition to mole fraction of H2O in the vapor.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of H2O in the vapor
"""
return p_H2O(PT, melt_wf, models) / PT["P"]
[docs]
def xg_O2(PT, melt_wf, models):
"""
Converts pO2 based on melt composition to mole fraction of O2 in the vapor.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of O2 in the vapor
"""
return p_O2(PT, melt_wf, models) / PT["P"]
[docs]
def xg_SO2(PT, melt_wf, models):
"""
Converts pSO2 based on melt composition to mole fraction of SO2 in the vapor.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of SO2 in the vapor
"""
return p_SO2(PT, melt_wf, models) / PT["P"]
[docs]
def xg_S2(PT, melt_wf, models):
"""
Converts pS2 based on melt composition to mole fraction of S2 in the vapor.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of S2 in the vapor
"""
return p_S2(PT, melt_wf, models) / PT["P"]
[docs]
def xg_H2S(PT, melt_wf, models):
"""
Converts pH2S based on melt composition to mole fraction of H2S in the vapor.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of H2S in the vapor
"""
return p_H2S(PT, melt_wf, models) / PT["P"]
[docs]
def xg_CO2(PT, melt_wf, models):
"""
Converts pCO2 based on melt composition to mole fraction of CO2 in the vapor.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of CO2 in the vapor
"""
return p_CO2(PT, melt_wf, models) / PT["P"]
[docs]
def xg_CO(PT, melt_wf, models):
"""
Converts pCO based on melt composition to mole fraction of CO in the vapor.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of CO in the vapor
"""
return p_CO(PT, melt_wf, models) / PT["P"]
[docs]
def xg_CH4(PT, melt_wf, models):
"""
Converts pCH4 based on melt composition to mole fraction of CH4 in the vapor.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of CH4 in the vapor
"""
return p_CH4(PT, melt_wf, models) / PT["P"]
[docs]
def xg_OCS(PT, melt_wf, models):
"""
Converts pOCS based on melt composition to mole fraction of OCS in the vapor.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of OCS in the vapor
"""
return p_OCS(PT, melt_wf, models) / PT["P"]
[docs]
def xg_X(PT, melt_wf, models):
"""
Converts pX based on melt composition to mole fraction of X in the vapor.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of X in the vapor
"""
return p_X(PT, melt_wf, models) / PT["P"]
[docs]
def Xg_tot(PT, melt_wf, models):
"""
Sum over over all vapor species of (mole fraction)*(molecular mass)
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
Sum over over all vapor species of (mole fraction)*(molecular mass)
"""
species_X = models.loc["species X", "option"]
Xg_t = (
xg_CO2(PT, melt_wf, models) * mdv.species.loc["CO2", "M"]
+ xg_CO(PT, melt_wf, models) * mdv.species.loc["CO", "M"]
+ xg_O2(PT, melt_wf, models) * mdv.species.loc["O2", "M"]
+ xg_H2O(PT, melt_wf, models) * mdv.species.loc["H2O", "M"]
+ xg_H2(PT, melt_wf, models) * mdv.species.loc["H2", "M"]
+ xg_CH4(PT, melt_wf, models) * mdv.species.loc["CH4", "M"]
+ xg_SO2(PT, melt_wf, models) * mdv.species.loc["SO2", "M"]
+ xg_S2(PT, melt_wf, models) * mdv.species.loc["S2", "M"]
+ xg_H2S(PT, melt_wf, models) * mdv.species.loc["H2S", "M"]
+ xg_OCS(PT, melt_wf, models) * mdv.species.loc["OCS", "M"]
+ xg_X(PT, melt_wf, models) * mdv.species.loc[species_X, "M"]
)
return Xg_t
##########################
# melt mole fraction #####
##########################
[docs]
def wm_vol(melt_wf):
"""
Calculate wt% of H2OT-eq + CO2-eq in the melt.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
wt% of [H2OT-eq + CO2-eq] in the melt
"""
wm_H2OT = 100.0 * melt_wf["H2OT"]
wm_CO2 = 100.0 * melt_wf["CO2"]
return wm_H2OT + wm_CO2 # + wm_S(wm_ST) + wm_SO3(wm_ST)
[docs]
def wm_nvol(melt_wf):
"""
Calculate wt% of everything except H2OT-eq + CO2-eq in the melt (excluding S and X).
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
wt% of everything except [H2OT-eq + CO2-eq] in the melt
"""
return 100.0 - wm_vol(melt_wf)
[docs]
def M_m_SO(melt_wf):
"""
Calculate molecular mass of the melt on a singular oxygen basis with no volatiles
and all Fe as FeOT.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
molecular mass of melt on singular oxygen basis
"""
# single oxide, no volatiles, all Fe as FeOT
melt_comp = melt_single_O(melt_wf, "no", "no")
M_m = 1.0 / melt_comp["Xmtot"]
return M_m
[docs]
def M_m_ox(melt_wf, models): # no volatiles, all Fe as FeOT
"""
Calculates molecular mass of the melt on an oxide basis with no volatiles and all Fe
as FeOT.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
molecular mass of melt on oxide basis
"""
melt_comp = melt_mole_fraction(melt_wf, models, "no", "no")
M_m = 1.0 / melt_comp["mol_tot"]
return M_m
[docs]
def Xm_H2OT(melt_wf):
"""
Calculates number of moles of H2OT in the melt.
Parameters
----------
melt_wf: dict
H2OT mass concentration in weight fraction
Returns
-------
float
number of moles of H2OT in melt
"""
wm_H2OT = 100.0 * melt_wf["H2OT"]
return wm_H2OT / mdv.species.loc["H2O", "M"]
[docs]
def Xm_CO2(melt_wf):
"""
Calculates number of moles of CO2 in the melt from mass of CO2.
Parameters
----------
melt_wf: dict
CO2 mass concentration in weight fraction
Returns
-------
float
number of moles of CO2 in melt
"""
wm_CO2 = 100.0 * melt_wf["CO2"]
return wm_CO2 / mdv.species.loc["CO2", "M"]
# Mole fraction in the melt based on mixing between volatile-free melt on a singular
# oxygen basis and volatiles
[docs]
def Xm_m_so(melt_wf): # singular oxygen basis
"""
Calculates number of moles of melt in the melt on a singular oxygen basis.
Parameters
----------
melt_wf: dictionary
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
number of moles of melt in melt
"""
return wm_nvol(melt_wf) / M_m_SO(melt_wf)
[docs]
def Xm_tot_so(melt_wf):
"""
Calculates total moles in the melt on a singular oxygen basis including H2OT, CO2,
and melt.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
total moles of melt
"""
return Xm_H2OT(melt_wf) + Xm_CO2(melt_wf) + Xm_m_so(melt_wf)
[docs]
def xm_H2OT_so(melt_wf):
"""
Calculates mole fraction of H2OT in the melt on a singular oxygen basis including
H2OT, CO2, and melt.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
mole fraction of H2OT in the melt
"""
return Xm_H2OT(melt_wf) / Xm_tot_so(melt_wf)
[docs]
def xm_CO2_so(melt_wf):
"""
Calculates mole fraction of CO2 in the melt on a singular oxygen basis including
H2OT, CO2, and melt.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
mole fraction of CO2 in the melt
"""
return Xm_CO2(melt_wf) / Xm_tot_so(melt_wf)
[docs]
def xm_melt_so(melt_wf):
"""
Calculates mole fraction of melt in the melt on a singular oxygen basis including
H2OT, CO2, and melt.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
mole fraction of melt in the melt
"""
return Xm_m_so(melt_wf) / Xm_tot_so(melt_wf)
[docs]
def Xm_t_so(melt_wf):
"""
Calculates total "mass" in the melt on a singular oxygen basis including H2OT, CO2,
and melt from sum of (mole fraction)*(molecular mass).
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
total "mass" in the melt
"""
return (
xm_H2OT_so(melt_wf) * mdv.species.loc["H2O", "M"]
+ xm_CO2_so(melt_wf) * mdv.species.loc["CO2", "M"]
+ xm_melt_so(melt_wf) * M_m_SO(melt_wf)
)
########################################################################################
# SPECIATION ###########################################################################
########################################################################################
[docs]
def ratio2overtotal(x):
"""
Converts ratio of two species (e.g., Fe3+/Fe2+) to ratio of numerator species over
total (e.g., Fe3+/FeT).
Parameters
----------
x: float
Ratio of species 1 over species 2 (i.e., species1/species2).
Returns
-------
float
ratio of species 1 over total of both species (i.e.,
species1/[species1+species2)
"""
return x / x + 1.0
[docs]
def overtotal2ratio(x):
"""
Converts ratio of numerator species over total (e.g., Fe3+/FeT) to ratio of two
species (e.g., Fe3+/Fe2+).
Parameters
----------
x: float
ratio of species 1 over total of both species (i.e.,
species1/[species1+species2])
Returns
-------
float
ratio of species 1 over species 2 (i.e., species1/species2)
"""
return x / (1.0 - x)
###########################
# hydrogen speciation #####
###########################
[docs]
def xm_OH_so(PT, melt_wf, models):
"""
Calculate mole fraction of OH- in the melt on a singular oxygen basis.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of OH- in the melt
See C_H2O for model options for 'Hspeciation'.
"""
Hspeciation = models.loc["Hspeciation", "option"]
Z = xm_H2OT_so(melt_wf)
def f(
A, B, C, Z, x
): # regular solution model rearranged to equal 0 to solve for xm_OH
return (
A
+ B * x
+ C * (Z - 0.5 * x)
+ math.log((x**2.0) / ((Z - 0.5 * x) * (1.0 - Z - 0.5 * x)))
)
def df(B, C, Z, x): # derivative of above
return (
B
- 0.5 * C
- (2.0 / x)
+ (0.5 / (Z - 0.5 * x) + (0.5 / (1.0 - Z - 0.5 * x)))
)
def dx(A, B, C, x):
return abs(0 - f(A, B, C, Z, x))
def nr(A, B, C, x0, e1):
delta1 = dx(A, B, C, x0)
while delta1 > e1:
x0 = x0 - f(A, B, C, Z, x0) / df(B, C, Z, x0)
delta1 = dx(A, B, C, x0)
return x0
if Z == 0.0:
return 0.0
# ideal mixture from Silver & Stolper (1985) J. Geol. 93(2) 161-177
elif Hspeciation in [
"ideal",
"none+ideal",
]:
K = mdv.KHOm(PT, melt_wf, models)
return (0.5 - (0.25 - ((K - 4.0) / K) * (Z - Z**2.0)) ** 0.5) / (
(K - 4.0) / (2.0 * K)
)
# all OH-
elif Hspeciation == "none":
return 0.0
# Regular solution model from Silver & Stolper (1989) J.Pet. 30(3)667-709
elif Hspeciation in [
"regular",
"none+regular",
]:
tol = 0.000001 # tolerance
K = mdv.KHOm(PT, melt_wf, models)
x0 = (0.5 - (0.25 - ((K - 4.0) / K) * (Z - Z**2.0)) ** 0.5) / (
(K - 4.0) / (2.0 * K)
)
A, B, C = mdv.KregH2O(PT, melt_wf, models)
return nr(A, B, C, x0, tol)
[docs]
def xm_H2Omol_so(PT, melt_wf, models):
"""
Calculate mole fraction of H2Omol in the melt on a singular oxygen basis.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
mole fraction of H2Omol in the melt
"""
Z = xm_H2OT_so(melt_wf)
return Z - 0.5 * xm_OH_so(PT, melt_wf, models)
[docs]
def wm_H2Omol_OH(PT, melt_wf, models): # wt fraction
"""
Converts mole fractions of OH- and H2Omol on a singular oxygen basis to weight
fractions of OH- and H2Omol.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
tuple(float,float)
weight fractions in the melt of H2Omol, OH-
"""
H2Omol = xm_H2Omol_so(PT, melt_wf, models) * mdv.species.loc["H2O", "M"]
OH_H2O = xm_OH_so(PT, melt_wf, models) * 0.5 * mdv.species.loc["H2O", "M"]
melt = xm_melt_so(melt_wf) * M_m_SO(melt_wf)
CO2T = xm_CO2_so(melt_wf) * mdv.species.loc["CO2", "M"]
wm_H2Omol = H2Omol / (H2Omol + OH_H2O + melt + CO2T)
wm_OH_H2O = OH_H2O / (H2Omol + OH_H2O + melt + CO2T)
wm_OH = ((wm_OH_H2O / mdv.species.loc["H2O", "M"]) * 2.0) * mdv.species.loc[
"OH", "M"
]
return wm_H2Omol, wm_OH
#########################
# carbon speciation #####
#########################
[docs]
def xm_CO32_CO2mol(PT, melt_wf, models): # mole fraction
"""
Calculate mole fraction of carbonate and CO2,mol in the melt on a singular oxygen
basis.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
tuple(float,float)
mole fraction in the melt of carbonate, CO2mol
See KCOm for model options for 'Cspeccomp'.
"""
xm_CO2T = xm_CO2_so(melt_wf)
xm_H2OT = xm_H2OT_so(melt_wf)
if models.loc["Cspeccomp", "option"] == "Basalt":
xm_CO32 = xm_CO2T
xm_CO2mol = 0.0
elif models.loc["Cspeccomp", "option"] == "Rhyolite":
xm_CO32 = 0.0
xm_CO2mol = xm_CO2T
else:
K = mdv.KCOm(PT, melt_wf, models)
xm_CO32 = (K * xm_CO2T * (1.0 - xm_CO2T - xm_H2OT)) / (
1.0 + K * (1.0 - xm_CO2T - xm_H2OT)
)
xm_CO2mol = xm_CO2T - xm_CO32
return xm_CO32, xm_CO2mol
[docs]
def wm_CO32_CO2mol(PT, melt_wf, models): # wt fraction
"""
Converts mole fractions of carbonate and CO2mol on a singular oxygen basis to weight
fractions of carbonate and CO2mol.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
tuple(float,float)
weight fractions in the melt of carbonate, CO2mol
"""
xm_CO32, xm_CO2mol = xm_CO32_CO2mol(PT, melt_wf, models)
CO2mol = xm_CO2mol * mdv.species.loc["CO2", "M"]
CO2carb = xm_CO32 * mdv.species.loc["CO2", "M"]
melt = xm_melt_so(melt_wf) * M_m_SO(melt_wf)
H2OT = xm_H2OT_so(melt_wf) * mdv.species.loc["H2O", "M"]
wm_CO2mol = CO2mol / (CO2mol + CO2carb + H2OT + melt)
wm_CO2carb = CO2carb / (CO2mol + CO2carb + H2OT + melt)
return wm_CO2carb, wm_CO2mol
##########################
# sulfur speciation ######
##########################
[docs]
def S6S2(PT, melt_wf, models):
"""
Calculates S6+/S2- in the melt (where S2- includes *S2- and H2S).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
S6+/S2- in the melt
"""
model = models.loc["sulfate", "option"]
if model == "Nash19":
A, B = mdv.S_Nash19_terms(PT)
result = 10.0 ** (A * math.log10(Fe3Fe2(melt_wf)) + B)
else:
CSO4 = mdv.C_SO4(PT, melt_wf, models)
CS = mdv.C_S(PT, melt_wf, models)
fO2 = mdv.f_O2(PT, melt_wf, models)
if models.loc["H2S_m", "option"] == "False":
result = (CSO4 / CS) * fO2**2.0
elif models.loc["H2S_m", "option"] == "True":
KHS = mdv.KHOSg(PT, models)
CH2S = mdv.C_H2S(PT, melt_wf, models)
CH2OT = mdv.C_H2O(PT, melt_wf, models)
xmH2O = xm_H2OT_so(melt_wf)
result = (CSO4 / ((KHS * CH2S * (xmH2O**2.0 / CH2OT)) + CS)) * fO2**2.0
return result
[docs]
def S6ST(PT, melt_wf, models):
"""
Calculates S6+/ST in the melt (where ST includes all sulfur species in the melt:
*S2-, H2S, and S6+).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
S6+/ST in the melt
"""
S6S2_ = S6S2(PT, melt_wf, models)
return S6S2_ / (S6S2_ + 1.0)
[docs]
def wm_S(PT, melt_wf, models):
"""
Calculates wt% total S2- as S in the melt (both *S2- and H2S).
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
total S2- as S in wt%
"""
wm_ST = 100.0 * melt_wf["ST"]
S6ST_ = S6ST(PT, melt_wf, models)
return wm_ST * (1.0 - S6ST_)
[docs]
def wm_SO3(PT, melt_wf, models):
"""
Calculates wt% total S6+ in the melt as SO3.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
S6+ as SO3 in wt%
"""
wm_ST = 100.0 * melt_wf["ST"]
S6ST_ = S6ST(PT, melt_wf, models)
return ((wm_ST * S6ST_) / mdv.species.loc["S", "M"]) * mdv.species.loc["SO3", "M"]
#######################
# iron speciation #####
#######################
[docs]
def Fe3Fe2(melt_wf):
"""
Converts Fe3+/FeT to Fe3+/Fe2+ in the melt.
Parameters
----------
melt_wf: dict
Fe3+/FeT as "Fe3FeT"
Returns
-------
float
Fe3+/Fe2+ in the melt
"""
Fe3FeT = melt_wf["Fe3FeT"]
return Fe3FeT / (1.0 - Fe3FeT)
[docs]
def Wm_FeT(melt_wf, molmass="M"):
"""
Calculate weight of total Fe in the melt from FeOT or Fe2O3T or FeO+Fe2O3.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
weight total Fe in the melt
"""
if melt_wf["FeOT"] > 0.0:
return (melt_wf["FeOT"] / mdv.species.loc["FeO", molmass]) * mdv.species.loc[
"Fe", molmass
]
elif melt_wf["Fe2O3T"] > 0.0:
return (
(melt_wf["Fe2O3T"] / mdv.species.loc["Fe2O3", molmass])
* 2.0
* mdv.species.loc["Fe", molmass]
)
else:
return (
(
(melt_wf["FeO"] / mdv.species.loc["FeO", molmass])
+ (melt_wf["Fe2O3"] / mdv.species.loc["Fe2O3", molmass])
)
* 2.0
* mdv.species.loc["Fe", molmass]
)
[docs]
def Wm_FeO(melt_wf, molmass="M"):
"""
Calculate weight of FeO in the melt from total Fe and Fe3+/FeT.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
weight FeO in the melt
"""
Fe3FeT = melt_wf["Fe3FeT"]
return (
(Wm_FeT(melt_wf, molmass=molmass) / mdv.species.loc["Fe", molmass])
* (1.0 - Fe3FeT)
* mdv.species.loc["FeO", molmass]
)
[docs]
def Wm_Fe2O3(melt_wf, molmass="M"):
"""
Calculate weight of Fe2O3 in the melt from total Fe and Fe3+/FeT.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
weight Fe2O3 in the melt
"""
Fe3FeT = melt_wf["Fe3FeT"]
return (
((Wm_FeT(melt_wf, molmass=molmass) / mdv.species.loc["Fe", molmass]) * Fe3FeT)
/ 2.0
) * mdv.species.loc["Fe2O3", molmass]
[docs]
def Wm_FeOT(melt_wf, molmass="M"):
"""
Calculate weight of FeOT in the melt from total Fe.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
weight FeOT in the melt
"""
return (
Wm_FeT(melt_wf, molmass=molmass) / mdv.species.loc["Fe", molmass]
) * mdv.species.loc["FeO", molmass]
[docs]
def wm_Fe_nv(melt_wf): # no volatiles
"""
Calculate weight fraction of total Fe in the melt from all oxides, FeO, Fe2O3 but no
volatiles.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
Returns
-------
float
weight fraction of total Fe in the melt
"""
Wm_tot = (
melt_wf["SiO2"]
+ melt_wf["TiO2"]
+ melt_wf["Al2O3"]
+ melt_wf["MnO"]
+ melt_wf["MgO"]
+ melt_wf["MnO"]
+ melt_wf["CaO"]
+ melt_wf["Na2O"]
+ melt_wf["K2O"]
+ melt_wf["P2O5"]
+ Wm_FeO(melt_wf)
+ Wm_Fe2O3(melt_wf)
)
FeT = mdv.species.loc["Fe", "M"] * (
(2.0 * Wm_Fe2O3(melt_wf) / mdv.species.loc["Fe2O3", "M"])
+ (Wm_FeO(melt_wf) / mdv.species.loc["FeO", "M"])
)
return 100.0 * FeT / Wm_tot
[docs]
def Fe3FeT_i(PT, melt_wf, models):
"""
Calculate initial Fe3+/FeT in the melt based on either: Fe3+/FeT, logfO2, NNO, FMQ,
S6+/ST, or FeO+Fe2O3.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
Fe3+/FeT in the melt
"""
model = models.loc["fO2", "option"]
if model == "buffered":
fO2 = 10 ** (melt_wf["logfO2_i"])
return mdv.fO22Fe3FeT(fO2, PT, melt_wf, models)
else:
if pd.isnull(melt_wf["Fe3FeT_i"]) is False:
if (
pd.isnull(melt_wf["logfO2_i"]) is False
or pd.isnull(melt_wf["DNNO"]) is False
or pd.isnull(melt_wf["DFMQ"]) is False
or pd.isnull(melt_wf["S6ST_i"]) is False
or pd.isnull(melt_wf["Fe2O3"]) is False
or pd.isnull(melt_wf["FeO"]) is False
):
w.warn(
"you entered more than one way to infer iron speciation, note that this calcualtion is only considering the entered Fe3+/FeT" # noqa E501
)
return melt_wf["Fe3FeT_i"]
elif pd.isnull(melt_wf["logfO2_i"]) is False:
if (
pd.isnull(melt_wf["DNNO"]) is False
or pd.isnull(melt_wf["DFMQ"]) is False
or pd.isnull(melt_wf["S6ST_i"]) is False
or pd.isnull(melt_wf["Fe2O3"]) is False
or pd.isnull(melt_wf["FeO"]) is False
):
w.warn(
"you entered more than one way to infer iron speciation, note that this calcualtion is only considering the entered log(fO2)" # noqa E501
)
fO2 = 10.0 ** (melt_wf["logfO2_i"])
return mdv.fO22Fe3FeT(fO2, PT, melt_wf, models)
elif pd.isnull(melt_wf["DNNO"]) is False:
if (
pd.isnull(melt_wf["DFMQ"]) is False
or pd.isnull(melt_wf["S6ST_i"]) is False
or pd.isnull(melt_wf["Fe2O3"]) is False
or pd.isnull(melt_wf["FeO"]) is False
):
w.warn(
"you entered more than one way to infer iron speciation, note that this calcualtion is only considering the entered DNNO" # noqa E501
)
D = melt_wf["DNNO"]
fO2 = Dbuffer2fO2(PT, D, "NNO", models)
return mdv.fO22Fe3FeT(fO2, PT, melt_wf, models)
elif pd.isnull(melt_wf["DFMQ"]) is False:
if (
pd.isnull(melt_wf["S6ST_i"]) is False
or pd.isnull(melt_wf["Fe2O3"]) is False
or pd.isnull(melt_wf["FeO"]) is False
):
w.warn(
"you entered more than one way to infer iron speciation, note that this calcualtion is only considering the entered DFMQ" # noqa E501
)
D = melt_wf["DFMQ"]
fO2 = Dbuffer2fO2(PT, D, "FMQ", models)
return mdv.fO22Fe3FeT(fO2, PT, melt_wf, models)
elif pd.isnull(melt_wf["S6ST_i"]) is False:
if (
pd.isnull(melt_wf["Fe2O3"]) is False
or pd.isnull(melt_wf["FeO"]) is False
):
w.warn(
"you entered more than one way to infer iron speciation, note that this calcualtion is only considering the entered S6+/ST" # noqa E501
)
S6T = melt_wf["S6ST_i"]
S62 = overtotal2ratio(S6T)
fO2 = S6S2_2_fO2(S62, melt_wf, PT, models)
return mdv.fO22Fe3FeT(fO2, PT, melt_wf, models)
else:
return ((2.0 * melt_wf["Fe2O3"]) / mdv.species.loc["Fe2O3", "M"]) / (
((2.0 * melt_wf["Fe2O3"]) / mdv.species.loc["Fe2O3", "M"])
+ (melt_wf["FeO"] / mdv.species.loc["FeO", "M"])
)
########################################################################################
# converting gas and melt compositions #################################################
########################################################################################
# C/S ratio of the vapor
[docs]
def gas_CS(PT, melt_wf, models):
"""
Calculate C/S mole fraction ratio in the vapor including all C and S species based
on the melt composition.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
float
C/S mole fraction ratio in the vapor
"""
S_values = (
(2.0 * xg_S2(PT, melt_wf, models))
+ xg_SO2(PT, melt_wf, models)
+ xg_OCS(PT, melt_wf, models)
+ xg_H2S(PT, melt_wf, models)
)
if S_values > 0:
xgCS = (
xg_CO(PT, melt_wf, models)
+ xg_CO2(PT, melt_wf, models)
+ xg_OCS(PT, melt_wf, models)
+ xg_CH4(PT, melt_wf, models)
) / S_values
else:
xgCS = ""
return xgCS
[docs]
def gas_CS_alt(xg):
"""
Calculate C/S mole fraction ratio in the vapor including all C and S species based
on gas composition.
Parameters
----------
xg: dict
Mole fraction of vapor species.
Returns
-------
float
C/S mole fraction ratio in the vapor
"""
S_values = (2.0 * xg["S2"]) + xg["SO2"] + xg["OCS"] + xg["H2S"]
if S_values > 0:
xgCS = (xg["CO"] + xg["CO2"] + xg["OCS"] + xg["CH4"]) / S_values
else:
xgCS = ""
return xgCS
# all carbon as CO2 and all hydrogen as H2O
[docs]
def melt_H2O_CO2_eq(melt_wf):
"""
Calculate weight fraction of all C as CO2 (CO2-eq) and all H as H2O (H2O-eq) in the
melt.
Parameters
----------
PT: dict
Pressure (bars) as "P" and temperature ('C) as "T".
melt_wf: dict
Melt composition in weight fraction (SiO2, TiO2, etc.).
models: pandas.DataFrame
Model options.
Returns
-------
tuple(float,float)
weight fraction in the melt of CO2-eq, H2O-eq
"""
wmCO2eq = melt_wf["CO2"] + mdv.species.loc["CO2", "M"] * (
(melt_wf["CO"] / mdv.species.loc["CO", "M"])
+ (melt_wf["CH4"] / mdv.species.loc["CH4", "M"])
)
wmH2Oeq = melt_wf["H2OT"] + mdv.species.loc["H2O", "M"] * (
(melt_wf["H2"] / mdv.species.loc["H2", "M"])
+ (2.0 * melt_wf["CH4"] / mdv.species.loc["CH4", "M"])
+ (melt_wf["H2S"] / mdv.species.loc["H2S", "M"])
)
return wmCO2eq, wmH2Oeq
# calculate weight fraction of species in the gas
[docs]
def gas_wf(gas_mf, models):
"""
Convert gas composition from mole fraction to weight fraction.
Parameters
----------
gas_mf: dict
Mole fractions of gas composition and total "mass" of gas.
models: pandas.DataFrame
Model options.
Returns
-------
dict
gas composition in weight fraction
"""
wg_O2 = (mdv.species.loc["O2", "M"] * gas_mf["O2"]) / gas_mf["Xg_t"]
wg_H2 = (mdv.species.loc["H2", "M"] * gas_mf["H2"]) / gas_mf["Xg_t"]
wg_H2O = (mdv.species.loc["H2O", "M"] * gas_mf["H2O"]) / gas_mf["Xg_t"]
wg_H2S = (mdv.species.loc["H2S", "M"] * gas_mf["H2S"]) / gas_mf["Xg_t"]
wg_S2 = (mdv.species.loc["S2", "M"] * gas_mf["S2"]) / gas_mf["Xg_t"]
wg_SO2 = (mdv.species.loc["SO2", "M"] * gas_mf["SO2"]) / gas_mf["Xg_t"]
wg_CO2 = (mdv.species.loc["CO2", "M"] * gas_mf["CO2"]) / gas_mf["Xg_t"]
wg_CO = (mdv.species.loc["CO", "M"] * gas_mf["CO"]) / gas_mf["Xg_t"]
wg_CH4 = (mdv.species.loc["CH4", "M"] * gas_mf["CH4"]) / gas_mf["Xg_t"]
wg_OCS = (mdv.species.loc["OCS", "M"] * gas_mf["OCS"]) / gas_mf["Xg_t"]
species_X = models.loc["species X", "option"]
wg_X = (mdv.species.loc[species_X, "M"] * gas_mf["X"]) / gas_mf["Xg_t"]
result = {
"wg_O2": wg_O2,
"wg_H2": wg_H2,
"wg_H2O": wg_H2O,
"wg_H2S": wg_H2S,
"wg_S2": wg_S2,
"wg_SO2": wg_SO2,
"wg_CO2": wg_CO2,
"wg_CO": wg_CO,
"wg_CH4": wg_CH4,
"wg_OCS": wg_OCS,
"wg_X": wg_X,
}
return result
# calculate weight fraction of species in the gas relative to total system
[docs]
def gas_wft(gas_mf, models):
"""
Calculate gas composition in weight fraction of total system from mole fraction of
gas.
Parameters
----------
gas_mf: dict
Mole fractions of gas composition and total "mass" of gas.
models: pandas.DataFrame
Model options.
Returns
-------
dict
gas composition in weight fraction of total system
"""
gaswf = gas_wf(gas_mf, models)
wgt_O2 = gaswf["wg_O2"] * gas_mf["wt_g"]
wgt_H2 = gaswf["wg_H2"] * gas_mf["wt_g"]
wgt_H2O = gaswf["wg_H2O"] * gas_mf["wt_g"]
wgt_H2S = gaswf["wg_H2S"] * gas_mf["wt_g"]
wgt_S2 = gaswf["wg_S2"] * gas_mf["wt_g"]
wgt_SO2 = gaswf["wg_SO2"] * gas_mf["wt_g"]
wgt_CO2 = gaswf["wg_CO2"] * gas_mf["wt_g"]
wgt_CO = gaswf["wg_CO"] * gas_mf["wt_g"]
wgt_CH4 = gaswf["wg_CH4"] * gas_mf["wt_g"]
wgt_OCS = gaswf["wg_OCS"] * gas_mf["wt_g"]
wgt_X = gaswf["wg_X"] * gas_mf["wt_g"]
result = {
"wgt_O2": wgt_O2,
"wgt_H2": wgt_H2,
"wgt_H2O": wgt_H2O,
"wgt_H2S": wgt_H2S,
"wgt_S2": wgt_S2,
"wgt_SO2": wgt_SO2,
"wgt_CO2": wgt_CO2,
"wgt_CO": wgt_CO,
"wgt_CH4": wgt_CH4,
"wgt_OCS": wgt_OCS,
"wgt_X": wgt_X,
}
return result
[docs]
def gas_weight(gas_mf, bulk_wf):
"""
Calculates mass of each gas species.
Parameters
----------
gas_mf: dict
Mole fractions of gas composition and total "mass" of gas.
bulk_wf: dict
Bulk composition of system in weight fraction.
Returns
-------
dict
mass of each gas species
"""
gaswft_ = gas_wft(gas_mf)
Wg_O2 = gaswft_["wgt_O2"] * bulk_wf["Wt"]
Wg_H2 = gaswft_["wgt_H2"] * bulk_wf["Wt"]
Wg_H2O = gaswft_["wgt_H2O"] * bulk_wf["Wt"]
Wg_H2S = gaswft_["wgt_H2S"] * bulk_wf["Wt"]
Wg_S2 = gaswft_["wgt_S2"] * bulk_wf["Wt"]
Wg_SO2 = gaswft_["wgt_SO2"] * bulk_wf["Wt"]
Wg_CO2 = gaswft_["wgt_CO2"] * bulk_wf["Wt"]
Wg_CO = gaswft_["wgt_CO"] * bulk_wf["Wt"]
Wg_CH4 = gaswft_["wgt_CH4"] * bulk_wf["Wt"]
Wg_OCS = gaswft_["wgt_OCS"] * bulk_wf["Wt"]
Wg_X = gaswft_["wgt_X"] * bulk_wf["Wt"]
Wg_t = gas_mf["wt_g"] * bulk_wf["Wt"]
result = {
"Wg_O2": Wg_O2,
"Wg_H2": Wg_H2,
"Wg_H2O": Wg_H2O,
"Wg_H2S": Wg_H2S,
"Wg_S2": Wg_S2,
"Wg_SO2": Wg_SO2,
"Wg_CO2": Wg_CO2,
"Wg_CO": Wg_CO,
"Wg_CH4": Wg_CH4,
"Wg_OCS": Wg_OCS,
"Wg_X": Wg_X,
"Wg_t": Wg_t,
}
return result
[docs]
def gas_moles(gas_mf, bulk_wf, models):
"""
Calculates moles of each gas species.
Parameters
----------
gas_mf: dict
Mole fractions of gas composition and total "mass" of gas.
bulk_wf: dict
Bulk composition of system in weight fraction.
models: pandas.DataFrame
Model options.
Returns
-------
dict
moles of each gas species
"""
gasw = gas_weight(gas_mf, bulk_wf)
Xg_O2 = gasw["Wg_O2"] / mdv.species.loc["O2", "M"]
Xg_H2O = gasw["Wg_H2O"] / mdv.species.loc["H2O", "M"]
Xg_H2 = gasw["Wg_H2"] / mdv.species.loc["H2", "M"]
Xg_H2S = gasw["Wg_H2S"] / mdv.species.loc["H2S", "M"]
Xg_S2 = gasw["Wg_S2"] / mdv.species.loc["S2", "M"]
Xg_SO2 = gasw["Wg_SO2"] / mdv.species.loc["SO2", "M"]
Xg_CO2 = gasw["Wg_CO2"] / mdv.species.loc["CO2", "M"]
Xg_CO = gasw["Wg_CO"] / mdv.species.loc["CO", "M"]
Xg_CH4 = gasw["Wg_CH4"] / mdv.species.loc["CH4", "M"]
Xg_OCS = gasw["g_OCS"] / mdv.species.loc["OCS", "M"]
species_X = models.loc["species X", "option"]
Xg_X = gasw["Wg_X"] / mdv.species.loc[species_X, "M"]
Xt_g = (
Xg_O2
+ Xg_H2
+ Xg_H2O
+ Xg_H2S
+ Xg_S2
+ Xg_SO2
+ Xg_CO2
+ Xg_CO
+ Xg_CH4
+ Xg_OCS
+ Xg_X
)
result = {
"Xg_O2": Xg_O2,
"Xg_H2": Xg_H2,
"Xg_H2O": Xg_H2O,
"Xg_H2S": Xg_H2S,
"Xg_S2": Xg_S2,
"Xg_SO2": Xg_SO2,
"Xg_CO2": Xg_CO2,
"Xg_CO": Xg_CO,
"Xg_CH4": Xg_CH4,
"Xg_OCS": Xg_OCS,
"Xg_X": Xg_X,
"Xg_t": Xt_g,
}
return result
# calculate weight fraction of elements in the gas
[docs]
def gas_elements(gas_mf, models):
"""
Convert gas composition in mole fraction of each species to weight fraction of each
element.
Parameters
----------
gas_mf: dict
Mole fractions of gas composition and total "mass" of gas.
models: pandas.DataFrame
Model options.
Returns
-------
dict
weight fraction of each element in the gas
"""
gaswf = gas_wf(gas_mf, models)
wg_O = gaswf["wg_O2"] + mdv.species.loc["O", "M"] * (
(gaswf["wg_H2O"] / mdv.species.loc["H2O", "M"])
+ (2.0 * gaswf["wg_SO2"] / mdv.species.loc["SO2", "M"])
+ (2.0 * gaswf["wg_CO2"] / mdv.species.loc["CO2", "M"])
+ (gaswf["wg_CO"] / mdv.species.loc["CO", "M"])
+ (gaswf["wg_OCS"] / mdv.species.loc["OCS", "M"])
)
wg_H = gaswf["wg_H2"] + mdv.species.loc["H", "M"] * (
(2.0 * gaswf["wg_H2O"] / mdv.species.loc["H2O", "M"])
+ (2.0 * gaswf["wg_H2S"] / mdv.species.loc["H2S", "M"])
+ (4.0 * gaswf["wg_CH4"] / mdv.species.loc["CH4", "M"])
)
wg_S = gaswf["wg_S2"] + mdv.species.loc["S", "M"] * (
(gaswf["wg_H2S"] / mdv.species.loc["H2S", "M"])
+ (gaswf["wg_SO2"] / mdv.species.loc["SO2", "M"])
+ (gaswf["wg_OCS"] / mdv.species.loc["OCS", "M"])
)
wg_C = mdv.species.loc["C", "M"] * (
(gaswf["wg_CO2"] / mdv.species.loc["CO2", "M"])
+ (gaswf["wg_CO"] / mdv.species.loc["CO", "M"])
+ (gaswf["wg_OCS"] / mdv.species.loc["OCS", "M"])
+ (gaswf["wg_CH4"] / mdv.species.loc["CH4", "M"])
)
wg_X = gaswf["wg_X"]
result = {"wg_O": wg_O, "wg_H": wg_H, "wg_S": wg_S, "wg_C": wg_C, "wg_X": wg_X}
return result
# calculate weight fraction of elements in the melt
[docs]
def melt_elements(melt_wf, bulk_wf, gas_comp):
"""
Convert melt composition in weight fraction of each species to weight fraction of
each element.
Parameters
----------
melt_wf: dict
Melt composition in weight fraction.
bulk_wf: dict
Bulk composition of system in weight fraction.
gas_comp: dict
Mole fractions of gas composition and total "mass" of gas.
Returns
-------
dict
weight fraction of each element in the melt
"""
wm_C = mdv.species.loc["C", "M"] * (
melt_wf["CO2"] / mdv.species.loc["CO2", "M"]
+ melt_wf["CO"] / mdv.species.loc["CO", "M"]
+ melt_wf["CH4"] / mdv.species.loc["CH4", "M"]
)
wm_H = (
2.0
* mdv.species.loc["H", "M"]
* (
melt_wf["H2OT"] / mdv.species.loc["H2O", "M"]
+ melt_wf["H2"] / mdv.species.loc["H2", "M"]
+ melt_wf["H2S"] / mdv.species.loc["H2S", "M"]
+ (2.0 * melt_wf["CH4"]) / mdv.species.loc["CH4", "M"]
)
)
wm_S = mdv.species.loc["S", "M"] * (
(melt_wf["S2-"] + melt_wf["S6+"]) / mdv.species.loc["S", "M"]
+ (melt_wf["H2S"] / mdv.species.loc["H2S", "M"])
)
wm_Fe = bulk_wf["Fe"] / (1.0 - gas_comp["wt_g"])
Fe32 = overtotal2ratio(melt_wf["Fe3FeT"])
wm_O = mdv.species.loc["O", "M"] * (
(melt_wf["H2OT"] / mdv.species.loc["H2O", "M"])
+ ((2.0 * melt_wf["CO2"]) / mdv.species.loc["CO2", "M"])
+ (3.0 * melt_wf["S6+"] / mdv.species.loc["S", "M"])
+ (melt_wf["CO"] / mdv.species.loc["CO", "M"])
+ (wm_Fe / mdv.species.loc["Fe", "M"]) * ((1.5 * Fe32 + 1.0) / (Fe32 + 1.0))
)
wm_X = melt_wf["XT"]
result = {
"wm_C": wm_C,
"wm_H": wm_H,
"wm_S": wm_S,
"wm_Fe": wm_Fe,
"wm_O": wm_O,
"wm_X": wm_X,
}
return result
########################################################################################
# WORK IN PROGRESS: VOLUME AND DENSITY #################################################
########################################################################################
# molar volume of the gas in J/bar/mol
def Vm_gas(gas_mf, PT, models):
# work in progress
Vm = (
gas_mf["O2"] * mdv.gas_molar_volume("O2", PT, models)
+ gas_mf["H2"] * mdv.gas_molar_volume("H2", PT, models)
+ gas_mf["H2O"] * mdv.gas_molar_volume("H2O", PT, models)
+ gas_mf["CO2"] * mdv.gas_molar_volume("CO2", PT, models)
+ gas_mf["CO"] * mdv.gas_molar_volume("CO", PT, models)
+ gas_mf["CH4"] * mdv.gas_molar_volume("CH4", PT, models)
+ gas_mf["S2"] * mdv.gas_molar_volume("S2", PT, models)
+ gas_mf["H2S"] * mdv.gas_molar_volume("H2S", PT, models)
+ gas_mf["SO2"] * mdv.gas_molar_volume("SO2", PT, models)
+ gas_mf["OCS"] * mdv.gas_molar_volume("OCS", PT, models)
)
return Vm
# volume of the gas in cm3
def gas_volume(PT, gas_mf, bulk_wf, models):
# work in progress
Xg_O2, Xg_H2, Xg_H2O, Xg_H2S, Xg_S2, Xg_SO2, Xg_CO2, Xg_CO, Xg_CH4, Xg_OCS, Xt_g = (
gas_moles(gas_mf, bulk_wf)
)
volume = Xt_g * Vm_gas(gas_mf, PT, models) # in J/bar
volume_cm3 = volume * 10.0
return volume_cm3
# density of the gas in g/cm3
def gas_density(PT, gas_mf, bulk_wf, models):
# work in progress
volume = gas_volume(PT, gas_mf, bulk_wf, models) # cm3
mass = gas_mf["wt_g"] * bulk_wf["Wt"] # g
density = mass / volume
return density
# volume of the melt in cm3
def melt_volume(run, PT, melt_wf, bulk_wf, gas_mf, setup):
# work in progress
density = mdv.melt_density(run, PT, melt_wf, setup)
mass = bulk_wf["Wt"] * (1 - gas_mf["wt_g"])
volume = mass / density
return volume
# volume of the system (melt + gas)
def system_density(run, PT, melt_wf, gas_mf, bulk_wf, setup, models):
# work in progress
wt_g_ = gas_mf["wt_g"]
wt_m_ = 1.0 - wt_g_
density_m = mdv.melt_density(run, PT, melt_wf, setup)
if wt_g_ > 0.0:
density_g = gas_density(PT, gas_mf, bulk_wf, models)
else:
density_g = 0.0
density_sys = density_m * wt_m_ + density_g * wt_g_
return density_sys
########################################################################################
# melt composition #####################################################################
########################################################################################
[docs]
def melt_comp(run, setup):
"""
Convert input DataFrame of melt composition into dictionary.
Parameters
----------
run: float
Index of row of interest.
setup: pandas.DataFrame
Melt composition.
Returns
-------
dict
melt composition and "initial fO2" definer
"""
melt_wf = {}
oxides = setup.columns.tolist()
for x in [
"SiO2",
"TiO2",
"Al2O3",
"MgO",
"MnO",
"CaO",
"Na2O",
"K2O",
"P2O5",
]:
if x in oxides:
value = setup.loc[run, x]
else:
value = 0.0
melt_wf[x] = value
for x in [
"CO2",
"X",
"ST",
]:
if x + "ppm" in oxides:
value = setup.loc[run, x + "ppm"] / 1000000.0
else:
value = 0.0
melt_wf[x] = value
if "H2O" in oxides:
value = setup.loc[run, "H2O"] / 100.0
else:
value = 0.0
melt_wf["H2OT"] = value
for x in ["FeOT", "Fe2O3T", "FeO", "Fe2O3", "DNNO", "DFMQ"]:
if x in oxides:
value = setup.loc[run, x]
else:
value = float("NaN")
melt_wf[x] = value
for x in ["logfO2", "Fe3FeT", "S6ST"]:
if x in oxides:
value = setup.loc[run, x]
else:
value = float("NaN")
melt_wf[x + "_i"] = value
for x in ["sulf_XFe", "sulf_XCu", "sulf_XNi"]:
if x in setup:
melt_wf[x] = setup.loc[run, x]
melt_wf["XT"] = melt_wf["X"]
melt_wf["HT"] = (melt_wf["H2OT"] / mdv.species.loc["H2O", "M"]) * mdv.species.loc[
"H2", "M"
]
melt_wf["CT"] = (melt_wf["CO2"] / mdv.species.loc["CO2", "M"]) * mdv.species.loc[
"C", "M"
]
melt_wf["H2"] = 0.0
return melt_wf
# normalise melt composition in weight fraction
[docs]
def melt_normalise_wf(melt_wf, volatiles, Fe_speciation, molmass="M", majors="majors"):
"""
Normalise melt composition in weight fraction.
Parameters
----------
melt_wf: dict
Weight fraction of melt composition.
volatiles: str
Whether to include volatiles in the normalisation:
"yes" assumes all H is H2O, all C is CO2, all S is S, all X is X;
"water" assumes all H is H2O;
"no" volatiles excluded.
Fe_speciation: str
How iron speciation is treated in the normalisation:
"yes" Fe is split into FeO and Fe2O3;
"no" Fe is treated as FeOT.
Returns
-------
dict
weight fraction of each oxide in the melt
"""
if volatiles == "yes": # assumes all H is H2O, all C is CO2, all S is S, all X is X
H2O = (melt_wf["HT"] / mdv.species.loc["H2", molmass]) * mdv.species.loc[
"H2O", molmass
]
CO2 = (melt_wf["CT"] / mdv.species.loc["C", molmass]) * mdv.species.loc[
"CO2", molmass
]
S = melt_wf["ST"]
X = melt_wf["XT"]
elif volatiles == "water": # assumes all H is H2O
H2O = (melt_wf["HT"] / mdv.species.loc["H2", molmass]) * mdv.species.loc[
"H2O", molmass
]
CO2, S, X = 0.0, 0.0, 0.0
elif volatiles == "no":
H2O, CO2, S, X = 0.0, 0.0, 0.0, 0.0
volatiles = H2O + CO2 + S + X
if Fe_speciation == "no":
Wm_FeOT_ = Wm_FeOT(melt_wf, molmass=molmass)
Wm_FeO_ = 0.0
Wm_Fe2O3_ = 0.0
elif Fe_speciation == "yes":
Wm_FeOT_ = 0.0
Wm_FeO_ = Wm_FeO(melt_wf, molmass=molmass)
Wm_Fe2O3_ = Wm_Fe2O3(melt_wf, molmass=molmass)
if mdv.species.loc["SiO2", majors] == "Y":
Wm_SiO2 = melt_wf["SiO2"]
else:
Wm_SiO2 = 0.0
if mdv.species.loc["TiO2", majors] == "Y":
Wm_TiO2 = melt_wf["TiO2"]
else:
Wm_TiO2 = 0.0
if mdv.species.loc["Al2O3", majors] == "Y":
Wm_Al2O3 = melt_wf["Al2O3"]
else:
Wm_Al2O3 = 0.0
if mdv.species.loc["MgO", majors] == "Y":
Wm_MgO = melt_wf["MgO"]
else:
Wm_MgO = 0.0
if mdv.species.loc["MnO", majors] == "Y":
Wm_MnO = melt_wf["MnO"]
else:
Wm_MnO = 0.0
if mdv.species.loc["CaO", majors] == "Y":
Wm_CaO = melt_wf["CaO"]
else:
Wm_CaO = 0.0
if mdv.species.loc["Na2O", majors] == "Y":
Wm_Na2O = melt_wf["Na2O"]
else:
Wm_Na2O = 0.0
if mdv.species.loc["K2O", majors] == "Y":
Wm_K2O = melt_wf["K2O"]
else:
Wm_K2O = 0.0
if mdv.species.loc["P2O5", majors] == "Y":
Wm_P2O5 = melt_wf["P2O5"]
else:
Wm_P2O5 = 0.0
tot = (
Wm_SiO2
+ Wm_TiO2
+ Wm_Al2O3
+ Wm_FeOT_
+ Wm_FeO_
+ Wm_Fe2O3_
+ Wm_MgO
+ Wm_MnO
+ Wm_CaO
+ Wm_Na2O
+ Wm_K2O
+ Wm_P2O5
)
result = {"SiO2": (Wm_SiO2 / tot) * (1.0 - volatiles)}
result["TiO2"] = (Wm_TiO2 / tot) * (1.0 - volatiles)
result["Al2O3"] = (Wm_Al2O3 / tot) * (1.0 - volatiles)
result["FeOT"] = (Wm_FeOT_ / tot) * (1.0 - volatiles)
result["FeO"] = (Wm_FeO_ / tot) * (1.0 - volatiles)
result["Fe2O3"] = (Wm_Fe2O3_ / tot) * (1.0 - volatiles)
result["MgO"] = (Wm_MgO / tot) * (1.0 - volatiles)
result["MnO"] = (Wm_MnO / tot) * (1.0 - volatiles)
result["CaO"] = (Wm_CaO / tot) * (1.0 - volatiles)
result["Na2O"] = (Wm_Na2O / tot) * (1.0 - volatiles)
result["K2O"] = (Wm_K2O / tot) * (1.0 - volatiles)
result["P2O5"] = (Wm_P2O5 / tot) * (1.0 - volatiles)
result["H2O"] = H2O
result["CO2"] = CO2
result["S"] = S
result["X"] = X
return result
# calculate cation proportions
[docs]
def melt_cation_proportion(
melt_wf, volatiles, Fe_speciation, molmass="M", majors="majors"
):
"""
Calculate cation proportion of melt composition.
Parameters
----------
melt_wf: dict
Weight fraction of melt composition.
volatiles: str
Whether to include volatiles in the normalisation:
"yes" assumes all H is H2O, all C is CO2, all S is S, all X is X;
"water" assumes all H is H2O;
"no" volatiles excluded.
Fe_speciation: str
How iron speciation is treated in the normalisation:
"yes" Fe is split into FeO and Fe2O3;
"no" Fe is treated as FeOT.
Returns
-------
dict
cation mole fraction in the melt
"""
melt_comp = melt_normalise_wf(
melt_wf, volatiles, Fe_speciation, molmass=molmass, majors=majors
)
tot = (
(
(mdv.species.loc["SiO2", "no_cat"] * melt_comp["SiO2"])
/ mdv.species.loc["SiO2", molmass]
)
+ (
(mdv.species.loc["TiO2", "no_cat"] * melt_comp["TiO2"])
/ mdv.species.loc["TiO2", molmass]
)
+ (
(mdv.species.loc["Al2O3", "no_cat"] * melt_comp["Al2O3"])
/ mdv.species.loc["Al2O3", molmass]
)
+ (
(mdv.species.loc["FeO", "no_cat"] * melt_comp["FeOT"])
/ mdv.species.loc["FeO", molmass]
)
+ (
(mdv.species.loc["FeO", "no_cat"] * melt_comp["FeO"])
/ mdv.species.loc["FeO", molmass]
)
+ (
(mdv.species.loc["Fe2O3", "no_cat"] * melt_comp["Fe2O3"])
/ mdv.species.loc["Fe2O3", molmass]
)
+ (
(mdv.species.loc["MgO", "no_cat"] * melt_comp["MgO"])
/ mdv.species.loc["MgO", molmass]
)
+ (
(mdv.species.loc["MnO", "no_cat"] * melt_comp["MnO"])
/ mdv.species.loc["MnO", molmass]
)
+ (
(mdv.species.loc["CaO", "no_cat"] * melt_comp["CaO"])
/ mdv.species.loc["CaO", molmass]
)
+ (
(mdv.species.loc["Na2O", "no_cat"] * melt_comp["Na2O"])
/ mdv.species.loc["Na2O", molmass]
)
+ (
(mdv.species.loc["K2O", "no_cat"] * melt_comp["K2O"])
/ mdv.species.loc["K2O", molmass]
)
+ (
(mdv.species.loc["P2O5", "no_cat"] * melt_comp["P2O5"])
/ mdv.species.loc["P2O5", molmass]
)
+ (
(mdv.species.loc["H2O", "no_cat"] * melt_comp["H2O"])
/ mdv.species.loc["H2O", molmass]
)
+ (
(mdv.species.loc["CO2", "no_cat"] * melt_comp["CO2"])
/ mdv.species.loc["CO2", molmass]
)
)
result = {
"Si": (
(mdv.species.loc["SiO2", "no_cat"] * melt_comp["SiO2"])
/ mdv.species.loc["SiO2", molmass]
)
/ tot
}
result["Ti"] = (
(mdv.species.loc["TiO2", "no_cat"] * melt_comp["TiO2"])
/ mdv.species.loc["TiO2", molmass]
) / tot
result["Al"] = (
(mdv.species.loc["Al2O3", "no_cat"] * melt_comp["Al2O3"])
/ mdv.species.loc["Al2O3", molmass]
) / tot
result["FeT"] = (
(mdv.species.loc["FeO", "no_cat"] * melt_comp["FeOT"])
/ mdv.species.loc["FeO", molmass]
) / tot
result["Fe2"] = (
(mdv.species.loc["FeO", "no_cat"] * melt_comp["FeO"])
/ mdv.species.loc["FeO", molmass]
) / tot
result["Fe3"] = (
(mdv.species.loc["Fe2O3", "no_cat"] * melt_comp["Fe2O3"])
/ mdv.species.loc["Fe2O3", molmass]
) / tot
result["Mg"] = (
(mdv.species.loc["MgO", "no_cat"] * melt_comp["MgO"])
/ mdv.species.loc["MgO", molmass]
) / tot
result["Mn"] = (
(mdv.species.loc["MgO", "no_cat"] * melt_comp["MnO"])
/ mdv.species.loc["MnO", molmass]
) / tot
result["Ca"] = (
(mdv.species.loc["CaO", "no_cat"] * melt_comp["CaO"])
/ mdv.species.loc["CaO", molmass]
) / tot
result["Na"] = (
(mdv.species.loc["Na2O", "no_cat"] * melt_comp["Na2O"])
/ mdv.species.loc["Na2O", molmass]
) / tot
result["K"] = (
(mdv.species.loc["K2O", "no_cat"] * melt_comp["K2O"])
/ mdv.species.loc["K2O", molmass]
) / tot
result["P"] = (
(mdv.species.loc["P2O5", "no_cat"] * melt_comp["P2O5"])
/ mdv.species.loc["P2O5", molmass]
) / tot
result["H"] = (
(mdv.species.loc["H2O", "no_cat"] * melt_comp["H2O"])
/ mdv.species.loc["H2O", molmass]
) / tot
result["C"] = (
(mdv.species.loc["CO2", "no_cat"] * melt_comp["CO2"])
/ mdv.species.loc["CO2", molmass]
) / tot
return result
# calculate mole fractions in the melt
[docs]
def melt_mole_fraction(
melt_wf, models, volatiles, Fe_speciation, molmass="M", majors="majors"
):
"""
Calculate oxide mole fraction of the melt.
Parameters
----------
melt_wf: dict
Weight fraction of melt composition.
models: pandas.DataFrame
Model options.
volatiles: str
Whether to include volatiles in the normalisation:
"yes" assumes all H is H2O, all C is CO2, all S is S, all X is X;
"water" assumes all H is H2O;
"no" volatiles excluded.
Fe_speciation: str
Wow iron speciation is treated in the normalisation:
"yes" Fe is split into FeO and Fe2O3;
"no" Fe is treated as FeOT.
Returns
-------
dict
oxide mole fraction of the melt
"""
melt_comp = melt_normalise_wf(
melt_wf, volatiles, Fe_speciation, molmass=molmass, majors=majors
)
species_X = models.loc["species X", "option"]
mol_tot = (
(melt_comp["SiO2"] / mdv.species.loc["SiO2", molmass])
+ (melt_comp["TiO2"] / mdv.species.loc["TiO2", molmass])
+ (melt_comp["Al2O3"] / mdv.species.loc["Al2O3", molmass])
+ (melt_comp["FeOT"] / mdv.species.loc["FeO", molmass])
+ (melt_comp["FeO"] / mdv.species.loc["FeO", molmass])
+ (melt_comp["Fe2O3"] / mdv.species.loc["Fe2O3", molmass])
+ (melt_comp["MnO"] / mdv.species.loc["MnO", molmass])
+ (melt_comp["MgO"] / mdv.species.loc["MgO", molmass])
+ (melt_comp["CaO"] / mdv.species.loc["CaO", molmass])
+ (melt_comp["Na2O"] / mdv.species.loc["Na2O", molmass])
+ (melt_comp["K2O"] / mdv.species.loc["K2O", molmass])
+ (melt_comp["P2O5"] / mdv.species.loc["P2O5", molmass])
+ (melt_comp["H2O"] / mdv.species.loc["H2O", molmass])
+ (melt_comp["CO2"] / mdv.species.loc["CO2", molmass])
+ (melt_comp["S"] / mdv.species.loc["S", molmass])
+ (melt_comp["X"] / mdv.species.loc[species_X, molmass])
)
result = {"SiO2": (melt_comp["SiO2"] / mdv.species.loc["SiO2", molmass]) / mol_tot}
result["TiO2"] = (melt_comp["TiO2"] / mdv.species.loc["TiO2", molmass]) / mol_tot
result["Al2O3"] = (melt_comp["Al2O3"] / mdv.species.loc["Al2O3", molmass]) / mol_tot
result["FeOT"] = (melt_comp["FeOT"] / mdv.species.loc["FeO", molmass]) / mol_tot
result["FeO"] = (melt_comp["FeO"] / mdv.species.loc["FeO", molmass]) / mol_tot
result["Fe2O3"] = (melt_comp["Fe2O3"] / mdv.species.loc["Fe2O3", molmass]) / mol_tot
result["MnO"] = (melt_comp["MnO"] / mdv.species.loc["MnO", molmass]) / mol_tot
result["MgO"] = (melt_comp["MgO"] / mdv.species.loc["MgO", molmass]) / mol_tot
result["CaO"] = (melt_comp["CaO"] / mdv.species.loc["CaO", molmass]) / mol_tot
result["Na2O"] = (melt_comp["Na2O"] / mdv.species.loc["Na2O", molmass]) / mol_tot
result["K2O"] = (melt_comp["K2O"] / mdv.species.loc["K2O", molmass]) / mol_tot
result["P2O5"] = (melt_comp["P2O5"] / mdv.species.loc["P2O5", molmass]) / mol_tot
result["H2O"] = (melt_comp["H2O"] / mdv.species.loc["H2O", molmass]) / mol_tot
result["CO2"] = (melt_comp["CO2"] / mdv.species.loc["CO2", molmass]) / mol_tot
result["S"] = (melt_comp["S"] / mdv.species.loc["S", molmass]) / mol_tot
result["X"] = (melt_comp["X"] / mdv.species.loc[species_X, molmass]) / mol_tot
result["mol_tot"] = mol_tot
return result
[docs]
def melt_single_O(melt_wf, volatiles, Fe_speciation, molmass="M", majors="majors"):
"""
Calculate oxide mole fraction on a single oxygen basis in the melt.
Parameters
----------
melt_wf: dict
Weight fraction of melt composition.
volatiles: str
Whether to include volatiles in the normalisation:
"yes" assumes all H is H2O, all C is CO2, all S is S, all X is X;
"water" assumes all H is H2O;
"no" volatiles excluded.
Fe_speciation: str
How iron speciation is treated in the normalisation:
"yes" Fe is split into FeO and Fe2O3;
"no" Fe is treated as FeOT.
Returns
-------
dict
oxide mole fraction on a single oxygen basis in the melt
"""
melt_comp = melt_normalise_wf(
melt_wf, volatiles, Fe_speciation, molmass=molmass, majors=majors
)
Xmtot = (
(
melt_comp["SiO2"]
/ (mdv.species.loc["SiO2", molmass] / mdv.species.loc["SiO2", "no_O"])
)
+ (
melt_comp["TiO2"]
/ (mdv.species.loc["TiO2", molmass] / mdv.species.loc["TiO2", "no_O"])
)
+ (
melt_comp["Al2O3"]
/ (mdv.species.loc["Al2O3", molmass] / mdv.species.loc["Al2O3", "no_O"])
)
+ (
melt_comp["MnO"]
/ (mdv.species.loc["MnO", molmass] / mdv.species.loc["MnO", "no_O"])
)
+ (
melt_comp["MgO"]
/ (mdv.species.loc["MgO", molmass] / mdv.species.loc["MgO", "no_O"])
)
+ (
melt_comp["CaO"]
/ (mdv.species.loc["CaO", molmass] / mdv.species.loc["CaO", "no_O"])
)
+ (
melt_comp["Na2O"]
/ (mdv.species.loc["Na2O", molmass] / mdv.species.loc["Na2O", "no_O"])
)
+ (
melt_comp["K2O"]
/ (mdv.species.loc["K2O", molmass] / mdv.species.loc["K2O", "no_O"])
)
+ (
melt_comp["P2O5"]
/ (mdv.species.loc["P2O5", molmass] / mdv.species.loc["P2O5", "no_O"])
)
+ (
melt_comp["FeOT"]
/ (mdv.species.loc["FeO", molmass] / mdv.species.loc["FeO", "no_O"])
)
+ (
melt_comp["FeO"]
/ (mdv.species.loc["FeO", molmass] / mdv.species.loc["FeO", "no_O"])
)
+ (
melt_comp["Fe2O3"]
/ (mdv.species.loc["Fe2O3", molmass] / mdv.species.loc["Fe2O3", "no_O"])
)
+ (
melt_comp["H2O"]
/ (mdv.species.loc["H2O", molmass] / mdv.species.loc["H2O", "no_O"])
)
+ (
melt_comp["CO2"]
/ (mdv.species.loc["CO2", molmass] / mdv.species.loc["CO2", "no_O"])
)
)
result = {
"SiO2": (
melt_comp["SiO2"]
/ (mdv.species.loc["SiO2", molmass] / mdv.species.loc["SiO2", "no_O"])
)
/ Xmtot
}
result["TiO2"] = (
melt_comp["TiO2"]
/ (mdv.species.loc["TiO2", molmass] / mdv.species.loc["TiO2", "no_O"])
) / Xmtot
result["Al2O3"] = (
melt_comp["Al2O3"]
/ (mdv.species.loc["Al2O3", molmass] / mdv.species.loc["Al2O3", "no_O"])
) / Xmtot
result["FeOT"] = (
melt_comp["FeOT"]
/ (mdv.species.loc["FeO", molmass] / mdv.species.loc["FeO", "no_O"])
) / Xmtot
result["FeO"] = (
melt_comp["FeO"]
/ (mdv.species.loc["FeO", molmass] / mdv.species.loc["FeO", "no_O"])
) / Xmtot
result["Fe2O3"] = (
melt_comp["Fe2O3"]
/ (mdv.species.loc["Fe2O3", molmass] / mdv.species.loc["Fe2O3", "no_O"])
) / Xmtot
result["MnO"] = (
melt_comp["MnO"]
/ (mdv.species.loc["MnO", molmass] / mdv.species.loc["MnO", "no_O"])
) / Xmtot
result["MgO"] = (
melt_comp["MgO"]
/ (mdv.species.loc["MgO", molmass] / mdv.species.loc["MgO", "no_O"])
) / Xmtot
result["CaO"] = (
melt_comp["CaO"]
/ (mdv.species.loc["CaO", molmass] / mdv.species.loc["CaO", "no_O"])
) / Xmtot
result["P2O5"] = (
melt_comp["P2O5"]
/ (mdv.species.loc["P2O5", molmass] / mdv.species.loc["P2O5", "no_O"])
) / Xmtot
result["Na2O"] = (
melt_comp["Na2O"]
/ (mdv.species.loc["Na2O", molmass] / mdv.species.loc["Na2O", "no_O"])
) / Xmtot
result["K2O"] = (
melt_comp["K2O"]
/ (mdv.species.loc["K2O", molmass] / mdv.species.loc["K2O", "no_O"])
) / Xmtot
result["H2O"] = (melt_comp["H2O"] / mdv.species.loc["H2O", molmass]) / Xmtot
result["CO2"] = (melt_comp["CO2"] / mdv.species.loc["CO2", molmass]) / Xmtot
result["Xmtot"] = Xmtot
return result
[docs]
def melt_pysulfsat(melt_wf): # output dataframe for pysulfsat
"""
Convert headers to be read by PySulfSat and makes the dictionary a DataFrame.
Parameters
----------
melt_wf: dict
Weight fraction of melt composition.
Returns
-------
pandas.DataFrame
melt composition in weight fraction
"""
comp = {
"SiO2_Liq": [melt_wf["SiO2"]],
"TiO2_Liq": [melt_wf["TiO2"]],
"Al2O3_Liq": [melt_wf["Al2O3"]],
"FeOt_Liq": [Wm_FeOT(melt_wf)],
"MnO_Liq": [melt_wf["MnO"]],
"MgO_Liq": [melt_wf["MgO"]],
"CaO_Liq": [melt_wf["CaO"]],
"Na2O_Liq": [melt_wf["Na2O"]],
"K2O_Liq": [melt_wf["K2O"]],
"P2O5_Liq": [melt_wf["P2O5"]],
}
comp = pd.DataFrame(comp)
return comp