Commit 4aa04a40 authored by Henning Francke's avatar Henning Francke
Browse files

VBA: Added Henry sheet and exported VBA code

parent 8d53a8ee
This diff is collapsed.
......@@ -2,157 +2,269 @@ Attribute VB_Name = "Brine_gas"
' Properties of gas mixture (density, viscosity, specific heat capacity, specific enthalpy)
' by Henning Francke francke@gfz-potsdam.de
' 2014 GFZ Potsdam
' 2020 GFZ Potsdam
Option Explicit
Option Base 1
Public Const nX_gas = 3
Public Const nX = nX_gas + 1
Public Const ignoreLimitN2_T = True
Const R = 8.314472
Const nM_CO2 = 1 'number of ions per molecule
Const nM_N2 = 1 'number of ions per molecule
Const nM_CH4 = 1 'number of ions per molecule
Const nX = nX_gas + 1
Public GasDataSet As Boolean
Function MM_vec()
'generates double vector of molar masses
Dim V(1 To nX_gas + 1) As Double
V(1) = M_CO2
V(2) = M_N2
V(3) = M_CH4
V(4) = M_H2O
If Not GasDataSet Then
DefineGasData
End If
If i_CO2 > 0 Then
V(i_CO2 - nX_salt) = CO2.MM
End If
If i_N2 > 0 Then
V(i_N2 - nX_salt) = N2.MM
End If
If i_CH4 > 0 Then
V(i_CH4 - nX_salt) = CH4.MM
End If
If i_H2 > 0 Then
V(i_H2 - nX_salt) = H2.MM
End If
If H2O.MM = 0 Then
DefineWater
End If
V(nX_gas + 1) = H2O.MM
MM_vec = V
End Function
Function nM_vec() As Double()
'generates double vector of molar masses
'generates double vector of molar numbers
Dim V(1 To nX_gas + 1) As Double
V(1) = CO2.nM
V(2) = N2.nM
V(3) = CH4.nM
V(4) = H2O.nM
' V(4) = nM_H2
If i_CO2 > 0 Then
V(i_CO2 - nX_salt) = CO2.nM
End If
If i_N2 > 0 Then
V(i_N2 - nX_salt) = N2.nM
End If
If i_CH4 > 0 Then
V(i_CH4 - nX_salt) = CH4.nM
End If
If i_H2 > 0 Then
V(i_H2 - nX_salt) = H2.nM
End If
V(nX_gas + 1) = H2O.nM
nM_vec = V
End Function
Function R_gas(Xi)
Dim X_
X_ = CheckMassVector(Xi, nX)
' end of gas definition
Function specificEnthalpy(p As Double, T As Double, Xin)
'calculation of specific enthalpy of gas mixture
Dim X_: X_ = CheckMassVector(Xin, nX)
If VarType(X_) = vbString Then
R_gas = X_
specificEnthalpy = X_ & " (Brine_gas.specificEnthalpy)"
Exit Function
End If
R_gas = ScalProd(X_, Array(CO2.R, N2.R, CH4.R, H2O.R))
End Function
'ABOVE SPECIFIC TO GAS COMPOSITION
'BELOW GENERIC PART
' Dim h_H2O_sat As Double, h_H2O As Double, h_CO2 As Double, h_N2 As Double, h_CH4 As Double
' h_H2O_sat = Waterh_satv_p(p) 'Modelica.Media.Water.IF97_Utilities.BaseIF97.Regions.hv_p(p)
Dim h_vec(nX_gas + 1), h_tmp As Double
' h_vec() = Array( _
' SingleGasNasa_h_T(CO2, T), _
' SingleGasNasa_h_T(N2, T), _
' SingleGasNasa_h_T(CH4, T), _
' Application.Max(h_H2O_sat, SpecificEnthalpy_pT(p, T)) _
' ) 'to make sure it is gaseous TODO:Take regions directly
Private Function MM_gas(X_) As Double
MM_gas = CheckMassVector(X_)
If VarType(MM_gas) <> vbBoolean Then
' For i = 1 To nX_gas
If i_CO2 > 0 Then
h_tmp = SingleGasNasa_h_T(CO2, T)
If Not VarType(h_tmp) = vbDouble Then
specificEnthalpy = X_ & "Error in cp calculation for " & CO2.name & " (Brine_gas.specificEnthalpy)"
Exit Function
End If
MM_gas = ScalProd(X_, MM_vec)
h_vec(i_CO2 - nX_salt) = h_tmp
End If
If i_N2 > 0 Then
h_tmp = SingleGasNasa_h_T(N2, T)
If Not VarType(h_tmp) = vbDouble Then
specificEnthalpy = X_ & "Error in cp calculation for " & N2.name & " (Brine_gas.specificEnthalpy"
Exit Function
End If
h_vec(i_N2 - nX_salt) = h_tmp
End If
If i_CH4 > 0 Then
h_tmp = SingleGasNasa_h_T(CH4, T)
If Not VarType(h_tmp) = vbDouble Then
specificEnthalpy = X_ & "Error in cp calculation for " & CH4.name & " (Brine_gas.specificEnthalpy)"
Exit Function
End If
h_vec(i_CH4 - nX_salt) = h_tmp
End If
If i_H2 > 0 Then
h_tmp = SingleGasNasa_h_T(H2, T)
If Not VarType(h_tmp) = vbDouble Then
specificEnthalpy = X_ & "Error in cp calculation for " & H2.name & " (Brine_gas.specificEnthalpy)"
Exit Function
End If
h_vec(i_H2 - nX_salt) = h_tmp
End If
h_tmp = Waterh_satv_p(p)
If Not VarType(h_tmp) = vbDouble Then
specificEnthalpy = X_ & "Error in cp calculation for " & H2.name & " (Brine_gas.specificEnthalpy)"
Exit Function
End If
h_vec(nX_gas + 1) = Application.Max(h_tmp, SpecificEnthalpy_pT(p, T))
If DebugMode Then
Debug.Print "Running BrineGas.SpecificEnthalpy(" & p / 10 ^ 5 & " bar," & T - 273.15 & " C, X=" & Vector2String(X_) & ")"
' Debug.Print "No gas composition, assuming water vapour.(Brine_gas.SpecificHeatCapacity_pTX)"
End If
specificEnthalpy = ScalProd(h_vec, X_) 'mass weighted average
End Function
Function density(p As Double, T As Double, Xin)
'Density of an ideal mixture of ideal gases
Function specificHeatCapacityCp(p As Double, T As Double, Xin) 'calculation of specific enthalpy of gas mixture
'Argument X is either X or XI (mass vector with or without water)
If DebugMode Then
Debug.Print "Running BrineGas.Density(" & p / 10 ^ 5 & " bar," & T - 273.15 & " C"
Debug.Print "Running specificHeatCapacityCp_gas(" & p / 10 ^ 5 & " bar," & T - 273.15 & " C)"
End If
Dim X_
X_ = CheckMassVector(Xin, nX)
If VarType(X_) = vbString Then
density = X_ & " (Brine_gas.density)"
specificHeatCapacityCp = X_ & " (Brine_gas.specificHeatCapacityCp)"
Exit Function
End If
density = p / (T * R_gas(X_))
Debug.Assert density > 0
End Function
Dim cp_H2O_sat As Double ', cp_H2O As Double, cp_CO2 As Double, cp_N2 As Double, cp_CH4 As Double
Dim cp_vec(nX_gas + 1) As Double, cp_tmp
' cp_vec() = Array(cp_CO2, cp_N2, cp_CH4, cp_H2O)
Private Function SingleGasNasa_h_T(data As DataRecord, T As Double, Optional exclEnthForm As Boolean = True, Optional ZeroAt0K As Boolean = True, Optional h_off As Double = 0) As Double
SingleGasNasa_h_T = _
IIf(T < data.Tlimit, data.R * ((-data.alow(1) + T * (data.blow(1) + data.alow(2) * Math.Log(T) + T * (1# * data.alow(3) + T * (0.5 * data.alow(4) + T * (1 / 3 * data.alow(5) + T * (0.25 * data.alow(6) + 0.2 * data.alow(7) * T)))))) / T) _
, data.R * ((-data.ahigh(1) + T * (data.bhigh(1) + data.ahigh(2) * Math.Log(T) + T * (1# * data.ahigh(3) + T * (0.5 * data.ahigh(4) + T * (1 / 3 * data.ahigh(5) + T * (0.25 * data.ahigh(6) + 0.2 * data.ahigh(7) * T)))))) / T)) _
+ IIf(exclEnthForm, -data.Hf, 0#) + IIf(ZeroAt0K, data.h0, 0#) + h_off
End Function
If i_CO2 > 0 Then
cp_tmp = SingleGasNasa_cp_T(CO2, T)
If Not VarType(cp_tmp) = vbDouble Then
specificHeatCapacityCp = cp_tmp & "Error in cp calculation for " & CO2.name & " (Brine_gas.specificHeatCapacityCp)"
Exit Function
End If
cp_vec(i_CO2 - nX_salt) = cp_tmp
End If
Function specificEnthalpy(p As Double, T As Double, Xin)
'calculation of specific enthalpy of gas mixture
If i_N2 > 0 Then
'cp_N2 = SingleGasNasa_cp_T(N2, T)
cp_tmp = SingleGasNasa_cp_T(N2, T)
If Not VarType(cp_tmp) = vbDouble Then
specificHeatCapacityCp = X_ & "Error in cp calculation for " & N2.name & " (Brine_gas.specificHeatCapacityCp)"
Exit Function
End If
cp_vec(i_N2 - nX_salt) = cp_tmp
End If
Dim X_
X_ = CheckMassVector(Xin, nX)
If VarType(X_) = vbString Then
specificEnthalpy = X_ & " (Brine_gas.specificEnthalpy)"
If i_H2 > 0 Then
If Not VarType(cp_tmp) = vbDouble Then
specificHeatCapacityCp = X_ & "Error in cp calculation for " & H2.name & " (Brine_gas.specificHeatCapacityCp)"
Exit Function
End If
cp_vec(i_H2 - nX_salt) = cp_tmp
End If
If i_CH4 > 0 Then
' cp_CH4 = SingleGasNasa_cp_T(CH4, T)
cp_tmp = SingleGasNasa_cp_T(CH4, T)
If Not VarType(cp_tmp) = vbDouble Then
specificHeatCapacityCp = X_ & "Error in cp calculation for " & CH4.name & " (Brine_gas.specificHeatCapacityCp)"
Exit Function
End If
cp_vec(i_CH4 - nX_salt) = cp_tmp
End If
Dim h_H2O_sat As Double, h_H2O As Double, h_CO2 As Double, h_N2 As Double, h_CH4 As Double
h_H2O_sat = Waterh_satv_p(p) 'Modelica.Media.Water.IF97_Utilities.BaseIF97.Regions.hv_p(p)
Dim h_vec()
h_vec() = Array( _
SingleGasNasa_h_T(CO2, T), _
SingleGasNasa_h_T(N2, T), _
SingleGasNasa_h_T(CH4, T), _
Application.Max(h_H2O_sat, SpecificEnthalpy_pT(p, T)) _
) 'to make sure it is gaseous TODO:Take regions directly
'cp_H2O = SingleGasNasa_cp_T(H2O, T)
cp_tmp = IAPWS.SpecificHeatCapacityCp_pT(Application.Min(p, IAPWS.Waterpsat_T(T) - 1), T)
If Not VarType(cp_tmp) = vbDouble Then
specificHeatCapacityCp = X_ & "Error in cp calculation for " & H2O.name & " (Brine_gas.specificHeatCapacityCp)"
Exit Function
End If
cp_vec(nX_gas + 1) = cp_tmp
If DebugMode Then
Debug.Print "Running BrineGas.SpecificEnthalpy(" & p / 10 ^ 5 & " bar," & T - 273.15 & " C, X=" & Vector2String(X_) & ")"
Debug.Print String2Vector(cp_vec)
End If
'If Not Application.Min(X) > 0 Then
' Debug.Print "No gas composition, assuming water vapour.(Brine_gas.SpecificHeatCapacity_pTX)"
'End If
specificHeatCapacityCp = ScalProd(cp_vec, X_) 'mass weighted average
End Function
specificEnthalpy = ScalProd(h_vec, X_) 'mass weighted average
'ABOVE SPECIFIC TO GAS COMPOSITION
'BELOW GENERIC PART
Function R_gas(Xi)
Dim X_: X_ = CheckMassVector(Xi, nX)
If VarType(X_) = vbString Then
R_gas = X_
Exit Function
End If
' R_gas = ScalProd(X_, Array(CO2.R_s, N2.R_s, CH4.R_s, H2O.R_s))
' R_gas = ScalProd(X_, Array(CO2.R, R / M_H2, CH4.R, H2O.R))
R_gas = ScalProd(X_, VecDiv(R, MM_vec))
End Function
Private Function SingleGasNasa_cp_T(data As DataRecord, T As Double, Optional exclEnthForm As Boolean = True, Optional ZeroAt0K As Boolean = True, Optional h_off As Double = 0) As Double
SingleGasNasa_cp_T = _
IIf(T < data.Tlimit, _
data.R * (1 / (T * T) * (data.alow(1) + T * (data.alow(2) + T * (1# * data.alow(3) + T * (data.alow(4) + T * (data.alow(5) + T * (data.alow(6) + data.alow(7) * T))))))) _
, data.R * (1 / (T * T) * (data.ahigh(1) + T * (data.ahigh(2) + T * (1# * data.ahigh(3) + T * (data.ahigh(4) + T * (data.ahigh(5) + T * (data.ahigh(6) + data.ahigh(7) * T))))))) _
)
Private Function MM_gas(X_) As Double
MM_gas = CheckMassVector(X_)
If VarType(MM_gas) <> vbBoolean Then
Exit Function
End If
MM_gas = ScalProd(X_, MM_vec)
End Function
Function specificHeatCapacityCp(p As Double, T As Double, Xin) 'calculation of specific enthalpy of gas mixture
'Argument X is either X or XI (mass vector with or without water)
Function density(p As Double, T As Double, Xin)
'Density of an ideal mixture of ideal gases
If DebugMode Then
Debug.Print "Running specificHeatCapacityCp_gas(" & p / 10 ^ 5 & " bar," & T - 273.15 & " C)"
Debug.Print "Running BrineGas.Density(" & p / 10 ^ 5 & " bar," & T - 273.15 & " C"
End If
Dim X_
X_ = CheckMassVector(Xin, nX)
If VarType(X_) = vbString Then
specificHeatCapacityCp = X_ & " (Brine_gas.specificHeatCapacityCp)"
density = X_ & " (Brine_gas.density)"
Exit Function
End If
Dim cp_H2O_sat As Double, cp_H2O As Double, cp_CO2 As Double, cp_N2 As Double, cp_CH4 As Double
cp_CO2 = SingleGasNasa_cp_T(CO2, T)
cp_N2 = SingleGasNasa_cp_T(N2, T)
cp_CH4 = SingleGasNasa_cp_T(CH4, T)
'cp_H2O = SingleGasNasa_cp_T(H2O, T)
cp_H2O = IAPWS.SpecificHeatCapacityCp_pT(Application.Min(p, IAPWS.Waterpsat_T(T) - 1), T)
Dim cp_vec()
cp_vec() = Array(cp_CO2, cp_N2, cp_CH4, cp_H2O)
density = p / (T * R_gas(X_))
Debug.Assert density > 0
End Function
If DebugMode Then
Debug.Print "cp_CO2: " & cp_CO2
Debug.Print "cp_N2: " & cp_N2
Debug.Print "cp_CH4: " & cp_CH4
Debug.Print "cp_H2O: " & cp_H2O
End If
Private Function SingleGasNasa_h_T(data As GasDataRecord, T As Double, Optional exclEnthForm As Boolean = True, Optional ZeroAt0K As Boolean = True, Optional h_off As Double = 0) As Double
With data
SingleGasNasa_h_T = _
IIf(T < .Tlimit, .R_s * ((-.alow(1) + T * (.blow(1) + .alow(2) * Math.Log(T) + T * (1# * .alow(3) + T * (0.5 * .alow(4) + T * (1 / 3 * .alow(5) + T * (0.25 * .alow(6) + 0.2 * .alow(7) * T)))))) / T) _
, .R_s * ((-.ahigh(1) + T * (.bhigh(1) + .ahigh(2) * Math.Log(T) + T * (1# * .ahigh(3) + T * (0.5 * .ahigh(4) + T * (1 / 3 * .ahigh(5) + T * (0.25 * .ahigh(6) + 0.2 * .ahigh(7) * T)))))) / T)) _
+ IIf(exclEnthForm, -.Hf, 0#) + IIf(ZeroAt0K, .h0, 0#) + h_off
End With
End Function
specificHeatCapacityCp = ScalProd(cp_vec, X_) 'mass weighted average
Private Function SingleGasNasa_cp_T(data As GasDataRecord, T As Double, Optional exclEnthForm As Boolean = True, Optional ZeroAt0K As Boolean = True, Optional h_off As Double = 0) As Double
With data
SingleGasNasa_cp_T = _
IIf(T < .Tlimit, _
.R_s * (1 / (T * T) * (.alow(1) + T * (.alow(2) + T * (1# * .alow(3) + T * (.alow(4) + T * (.alow(5) + T * (.alow(6) + .alow(7) * T))))))) _
, .R_s * (1 / (T * T) * (.ahigh(1) + T * (.ahigh(2) + T * (1# * .ahigh(3) + T * (.ahigh(4) + T * (.ahigh(5) + T * (.ahigh(6) + .ahigh(7) * T))))))) _
)
End With
End Function
Function dynamicViscosity(p As Double, T As Double, Optional X_)
dynamicViscosity = GasData.MoistAirDynamicViscosity(T)
dynamicViscosity = GasProps.MoistAirDynamicViscosity(T)
End Function
This diff is collapsed.
Attribute VB_Name = "Constants"
' Public Const R = 8.314472
Public Const R = 8.3144598 ' Modelica.Constants.R
Public Const R = 8.31446261815324 ' Modelica.Constants.R
Sub DefineWater()
With H2O
.name = "H2O"
.MM = 0.018015268 '[kg/mol] from Modelica.Media.Water.waterConstants
.Hf = -13423382.8172529
.h0 = 549760.647628014
.Tlimit = 1000
.alow = Array(-39479.6083, 575.573102, 0.931782653, 0.00722271286, -0.00000734255737, 4.95504349E-09, -1.336933246E-12)
.blow = Array(-33039.7431, 17.24205775)
.ahigh = Array(1034972.096, -2412.698562, 4.64611078, 0.002291998307, -0.000000683683048, 9.42646893E-11, -4.82238053E-15)
.bhigh = Array(-13842.86509, -7.97814851)
.R_s = R / .MM '461.523329085088
.nM = 1
End With
End Sub
This diff is collapsed.
Attribute VB_Name = "H2solubility_Chabab"
' by Henning Francke francke@gfz-potsdam.de
' 2021 GFZ Potsdam
' Chabab, S., Thveneau, P., Coquelet, C., Corvisier, J. & Paricaud, P. Measurements and predictive models of high-pressure H2 solubility in brine (H2O+NaCl) for underground hydrogen storage application. Int. J. Hydrogen Energy 45, 3220632220 (2020).
' For H2 solubility in pure water (Eq. (13)): 273.15 < T (K) < 373.15; 1 < P (bar) < 203
' For H2 solubility in NaCl-brine (Eq. (12)): 323.15 < T (K) < 373.15; 10 < P (bar) < 230; 0 < molality (mol/kgw) < 5
Option Explicit
Option Base 1
'Const ignoreLimitH2_T = False
'Const ignoreLimitH2_p = False
'Const ignoreLimitH2_b = False
'Public Const M_H2 = 1.008 * 2 / 1000 '[kg/mol]
'Function MM_H2() As Double
' MM_H2 = M_H2
'End Function
Function solubility_H2_pTX_Chabab2020(p As Double, T As Double, Xin, p_gas)
' converts from molaltity to mass fraction
Dim x: x = CheckMassVector(Xin, Brine.nX)
If VarType(x) = vbString Then
solubility_H2_pTX_Chabab2020 = x
Exit Function
End If
Dim solu: solu = solubility_H2_pTX_Chabab2020_molality(p, T, x, p_gas) ' mol/kg_H2O
If VarType(solu) = vbString Then
solubility_H2_pTX_Chabab2020 = solu
Exit Function
End If
Dim X_H2O As Double: X_H2O = x(Brine.nX) ' to be used in solubility_H2_pTX_Li2018
solubility_H2_pTX_Chabab2020 = solu * H2.MM * X_H2O 'molality->mass fraction
End Function
Function solubility_H2_pTX_Chabab2020_molality(p As Double, T As Double, Xin, p_gas)
' passes on p_gas + p_H2O as absolute pressure to correlation function
' returns mass fraction
Dim x: x = CheckMassVector(Xin, Brine.nX)
If VarType(x) = vbString Then
solubility_H2_pTX_Chabab2020_molality = x
Exit Function
End If
Dim molalities
molalities = ToDouble(massFractionsToMolalities(x, Brine.MM_vec))
If VarType(molalities) = vbString Then
solubility_H2_pTX_Chabab2020_molality = molalities
Exit Function
End If
Dim m_Cl As Double, m_Na As Double, m_K As Double, m_Ca As Double, m_Mg As Double, m_SO4 As Double
m_Cl = molalities(i_NaCl) + molalities(i_KCl) + 2 * molalities(i_CaCl2) ' + 2 * molalities(i_MgCl2)
m_Na = molalities(i_NaCl)
m_K = molalities(i_KCl)
m_Ca = molalities(i_CaCl2)
m_Mg = 0 ' molalities(i_MgCl2)
m_SO4 = 0 ' molalities(i_MgCl2)
Dim b_NaCl As Double: b_NaCl = m_Na + m_K + 2 * m_Ca + 2 * m_Mg
' Debug.Print "b_NaCl: "; b_NaCl
Dim p_H2O: p_H2O = IAPWS.Waterpsat_T(T)
Dim solu: solu = solubility_H2_pTb_Chabab2020_molality(p_gas + p_H2O, T, b_NaCl) ' mol/kg_H2O
If VarType(solu) = vbString Then
solubility_H2_pTX_Chabab2020_molality = solu
Exit Function
End If
solubility_H2_pTX_Chabab2020_molality = solu
End Function
Function solubility_H2_pTb_Chabab2020_molality(p As Double, T As Double, b_NaCl As Double) ' conversion mole fraction to molality
Dim y_H2: y_H2 = solubility_H2_pTb_Chabab2020_y(p, T, b_NaCl) ' mole fraction b_H2 / b/H2O
If VarType(y_H2) = vbString Then
solubility_H2_pTb_Chabab2020_molality = y_H2
Else
solubility_H2_pTb_Chabab2020_molality = y_H2 / (1 - y_H2) / H2O.MM ' mol/kg_H2O
End If
End Function
' equations from article
Function solubility_H2_pTb_Chabab2020_y(p As Double, T As Double, b_NaCl As Double) ' mole fraction b_H2 / b/H2O
' p is absolute pressure, here p_H2 + p_H2O
' Debug.Print "p="; p / 100000#; " bar, b_NaCl="; b_NaCl
Dim T_min As Double: T_min = IIf(b_NaCl > 0, 323.15, 273.15)
Dim T_max As Double: T_max = 373.15
Dim p_min As Double: p_min = IIf(b_NaCl > 0, 10 ^ 5, 10 ^ 6)
Dim p_max As Double: p_max = 23000000#
Dim b_max As Double: b_max = 5
Dim msg As String
msg = RangeCheck_pTb(p, T, b_NaCl, ignoreLimitH2_p, ignoreLimitH2_T, ignoreLimitH2_b, p_min, p_max, T_min, T_max, b_max, "solubility_H2_pTb_Chabab2020_molality")
If Len(msg) > 0 Then
solubility_H2_pTb_Chabab2020_y = msg
Exit Function
End If
' If Not (ignoreLimitH2_T Or (T_min <= T And T <= T_max)) Then
' solubility_H2_pTb_Chabab2020_molality = "# T=" & T - 273.15 & "C out of range (GasData.VirialEquation)"
' Exit Function
' End If
' If Not (ignoreLimitH2_p Or (p_min <= p And p <= p_max)) Then
' solubility_H2_pTb_Chabab2020_molality = "# p=" & p / 100000# & " out of range {" & p_min / 100000# & "..." & p_max / 100000# & " bar} (solubility_H2_pTb_Chabab2020_molality)"
' Exit Function
' End If
Dim x_H2_0 As Double: x_H2_0 = solubility_H2_pT_Chabab2020_y(p, T)
Dim a1 As Double: a1 = 0.018519
Dim a2 As Double: a2 = -0.30185103
'Dim x_H2 As Double: x_H2
solubility_H2_pTb_Chabab2020_y = x_H2_0 * Exp(a1 * b_NaCl ^ 2 + a2 * b_NaCl) 'equ. 12 (mol H2 per kg H2O)
End Function
Private Function solubility_H2_pT_Chabab2020_y(p As Double, T As Double)
' returns salt-free mole fraction
Dim p_bar As Double: p_bar = p / 100000#
If Not p > 0 Then ' = 0
solubility_H2_pT_Chabab2020_y = 0
Exit Function
ElseIf p < 0 Then
solubility_H2_pT_Chabab2020_y = "#p_gas negative! (GasData.solubility_H2_pT_Chabab2020_molality)"
Exit Function
End If
Dim b1 As Double: b1 = 0.0000003338844
Dim b2 As Double: b2 = 0.0363161
Dim b3 As Double: b3 = -0.00020734
Dim b4 As Double: b4 = -2.1301815E-09
solubility_H2_pT_Chabab2020_y = b1 * p_bar * T + b2 * p_bar / T + b3 * p_bar + b4 * p_bar ^ 2 'equ. 13
End Function
Attribute VB_Name = "H2solubility_Li"
' by Henning Francke francke@gfz-potsdam.de
' 2021 GFZ Potsdam
'Li, D., Beyer, C., & Bauer, S. (2018). A unified phase equilibrium model for hydrogen solubility and solution density. International Journal of Hydrogen Energy, 43(1), 512529. https://doi.org/10.1016/j.ijhydene.2017.07.228
' NOT USED
Option Explicit
Option Base 1
Const ignoreLimitH2_T = False
Const ignoreLimitH2_p = False
Const ignoreLimitH2_b = False
'Const M_H2 = 1.00784 * 2 * 0.001
Public Type VirialCoeffs
'Public name As String 'Name of ideal gas
a As Double
b As Double
c As Double
d As Double
e As Double
f As Double
p_min As Double
p_max As Double
T_min As Double
T_max As Double
End Type
' Public Const nX_salt = 3
' Public Const nX_gas = 3
Function solubility_H2_pTX_Li2018(p As Double, T As Double, Xin, p_gas)
Dim solu ' mol/kg_H2O
Dim X_H2O As Double
solu = solubility_H2_pTX_Li2018_molality(p, T, Xin, p_gas, X_H2O)
If VarType(solu) = vbString Then
solubility_H2_pTX_Li2018 = solu
Exit Function
End If
solubility_H2_pTX_Li2018 = solu * H2.MM * X_H2O 'molality->mass fraction
End Function
Function solubility_H2_pTX_Li2018_molality(p As Double, T As Double, Xin, p_gas, Optional ByRef X_H2O As Double) 'solubility calculation of N2 in seawater Mao&Duan(2006)
'Li, D., Beyer, C., & Bauer, S. (2018). A unified phase equilibrium model for hydrogen solubility and solution density. International Journal of Hydrogen Energy, 43(1), 512529. https://doi.org/10.1016/j.ijhydene.2017.07.228
' 273-373 K, 1-50 MPa and 0-5 mol/kg NaCl
'Calculates solubility for y_H2 = p_gas/p
Dim T_min As Double: T_min = 0 + 273.15
Dim T_max As Double: T_max = 100 + 273.15
Dim p_min As Double: p_min = 1 * 10 ^ 6
Dim p_max As Double: p_max = 50 * 10 ^ 6
Dim b_max As Double: b_max = 5
If Not p_gas > 0 Then ' = 0
solubility_H2_pTX_Li2018_molality = 0
Exit Function
ElseIf p_gas < 0 Then
solubility_H2_pTX_Li2018_molality = "#p_gas negative! (GasData.solubility_H2_pTX_Li2018_molality)"
Exit Function
ElseIf p_gas > p Then
solubility_H2_pTX_Li2018_molality = "#p_gas > p ! (GasData.solubility_H2_pTX_Li2018_molality)"
Exit Function
End If
If p < 0 Then
solubility_H2_pTX_Li2018_molality = "#p negative! (GasData.solubility_H2_pTX_Li2018_molality)"
Exit Function
End If
' p is not used other than in the checks! The total pressure for equation 16 is calculated as p = p_gas + p_H2O
Dim x: x = CheckMassVector(Xin, Brine.nX)
If VarType(x) = vbString Then
solubility_H2_pTX_Li2018_molality = x
Exit Function
End If
X_H2O = x(Brine.nX) ' to be used in solubility_H2_pTX_Li2018 avoiding double calculation
Dim molalities
molalities = ToDouble(massFractionsToMolalities(x, Brine.MM_vec))
If VarType(molalities) = vbString Then
solubility_H2_pTX_Li2018_molality = molalities
Exit Function
End If
Dim m_Cl As Double, m_Na As Double, m_K As Double, m_Ca As Double, m_Mg As Double, m_SO4 As Double
m_Cl = molalities(i_NaCl) + molalities(i_KCl) + 2 * molalities(i_CaCl2) ' + 2 * molalities(i_MgCl2)
m_Na = molalities(i_NaCl)
m_K = molalities(i_KCl)
m_Ca = molalities(i_CaCl2)
m_Mg = 0 ' molalities(i_MgCl2)
m_SO4 = 0 ' molalities(i_MgCl2)
Dim b_NaCl As Double: b_NaCl = m_Na + m_K + 2 * m_Ca + 2 * m_Mg
' Debug.Print "b_NaCl: "; b_NaCl
Dim p_H2O As Double: p_H2O = IAPWS.Waterpsat_T(T)
If VarType(p_H2O) = vbString Then 'if error
solubility_H2_pTX_Li2018_molality = p_H2O & "(GasData.solubility_H2_pTX_Li2018_molality)"
Exit Function
End If
Dim p_MPa As Double, T_C As Double
p_MPa = (p_gas + p_H2O) / 10 ^ 6 'assumption made for multi-gas
T_C = T - 273.15
If p_gas + p_H2O > p Then
solubility_H2_pTX_Li2018_molality = "#p_gas + p_H2O > p! (GasData.solubility_H2_pTX_Li2018_molality)"
Exit Function
End If
If Not p_gas > 0 Then
solubility_H2_pTX_Li2018_molality = 0
Exit Function
End If
Dim msg As String
msg = RangeCheck_pTb(p, T, b_NaCl, ignoreLimitH2_p, ignoreLimitH2_T, ignoreLimitH2_b, p_min, p_max, T_min, T_max, b_max, "solubility_H2_pTX_Li2018_molality")
If Len(msg) > 0 Then
solubility_H2_pTX_Li2018_molality = msg
Exit Function
End If
' Dim msg As String
' If outOfRangeMode > 0 Then
' If Not ignoreLim