Commit 0aa80ed8 authored by Henning Francke's avatar Henning Francke
Browse files

Merge branch 'master' of git@git.gfz-potsdam.de:francke/BrineProp.git

# Conflicts:
#	BrineProp/Brine3salts3gas/package.mo
#	BrineProp/PartialBrineMultiSaltMultiGasTwoPhase/package.mo
parents b0e6de82 4d617fe6
......@@ -21,9 +21,10 @@ package Brine3salts3gas "Two-phase aqueous solution of NaCl, KCl, CaCl2, N2, CO2
iCO2=4,
iN2=5,
iCH4=6,
final gasNames = {"carbondioxide","nitrogen","methane"},
final MM_gas = {M_CO2,M_N2,M_CH4},
final nM_gas = {nM_CO2,nM_N2,nM_CH4}); //iGas not final, because reassigned in Brine5salts3gas
gasNames = {"carbondioxide","nitrogen","methane"},
MM_gas = {M_CO2,M_N2,M_CH4},
nM_gas = {nM_CO2,nM_N2,nM_CH4}); //iGas not final, because reassigned in Brine5salts3gas
//order of gases must be consistent with Brine3Gas TODO: pass order or copy enthalpy/density/cp here
redeclare function extends setState_pTX "to avoid check error"
end setState_pTX;
......@@ -31,40 +32,44 @@ package Brine3salts3gas "Two-phase aqueous solution of NaCl, KCl, CaCl2, N2, CO2
redeclare function extends setState_phX "to avoid check error"
end setState_phX;
redeclare function extends solubilities_pTX
"solubility calculation of CO2 in seawater Duan, Sun(2003), returns gas concentration in kg/kg H2O"
redeclare replaceable function extends solubilities_pTX
"solubility calculation, returns gas concentration in kg/kg H2O"
algorithm
// print("p_gas={"+String(p_gas[1])+", "+String(p_gas[2])+", "+String(p_gas[3])+"} (solubilities_pTX)");
if debugmode then
print("Running solubilities_pTX("+String(p/1e5)+" bar,"+String(T-273.15)+" C, ignoreTlimit="+String(ignoreTlimit)+", X="+Modelica.Math.Matrices.toString(transpose([X]))+") ("+getInstanceName()+")");
print("k={"+String(solu[1]/p_gas[1])+", "+String(solu[2]/p_gas[2])+", "+String(solu[3]/p_gas[3])+"}(solubilities_pTX)");
print("solu={"+String(solu[1])+", "+String(solu[2])+", "+String(solu[3])+"}(solubilities_pTX)");
print(Modelica.Math.Matrices.toString({MM_vec}));
print("Running solubilities_pTX("+String(p/1e5)+" bar,"+String(T-273.15)+" C, ignoreTlimit="+String(ignoreTlimit)+", X="+Modelica.Math.Matrices.toString(transpose([X]))+")");
end if;
solu[1] := if X[nX_salt+1]>0 then solubility_CO2_pTX_Duan2006(p,T,X_l,MM_vec,p_gas[1],ignoreTlimit) else -1
solu[iCO2-nX_salt] := if X[iCO2]>0 then solubility_CO2_pTX_Duan2006(p,T,X_l,MM_vec,p_gas[iCO2-nX_salt],ignoreTlimit) else -1
"aus GasData, mol/kg_H2O -> kg_CO2/kg_H2O";
solu[2] :=if X[nX_salt + 2] > 0 then solubility_N2_pTX_Mao2006(p,T,X_l,MM_vec,p_gas[2],ignoreTlimit) else -1
solu[iN2-nX_salt] :=if X[iN2] > 0 then solubility_N2_pTX_Mao2006(p,T,X_l,MM_vec,p_gas[iN2-nX_salt],ignoreTlimit) else -1
"aus GasData, mol/kg_H2O -> kg_N2/kg_H2O";
// solu[2] := if X[nX_salt+2]>0 then solubility_N2_pTX_Harting(p,T,X_l,MM_vec,p_gas[2]) else -1
solu[3] := if X[nX_salt+3]>0 then solubility_CH4_pTX_Duan2006(p,T,X_l,MM_vec,p_gas[3],ignoreTlimit) else -1
solu[iCH4-nX_salt] := if X[iCH4]>0 then solubility_CH4_pTX_Duan2006(p,T,X_l,MM_vec,p_gas[iCH4-nX_salt],ignoreTlimit) else -1
"aus GasData, mol/kg_H2O -> kg_CH4/kg_H2O";
// solu[3] := if X[nX_salt+3]>0 then solubility_CH4_pTX_Harting(p,T,X_l,MM_vec,p_gas[3]) else -1
// print("k={"+String(solu[1]/p_gas[1])+", "+String(solu[2]/p_gas[2])+", "+String(solu[3]/p_gas[3])+"}(solubilities_pTX)");
// print("solu={"+String(solu[1])+", "+String(solu[2])+", "+String(solu[3])+"}(solubilities_pTX)");
// print(Modelica.Math.Matrices.toString({MM_vec}));
end solubilities_pTX;
redeclare function extends density_liq_pTX
// extends density_Duan2008_pTX(MM_vec=cat(1,MM_salt, {M_H2O}));
//TODO should take MM_vec;
protected
constant Integer[:] liqIndex=cat(1,1:nX_salt,{nX});
Real X_[:] = cat(1, X[1:nX_salt], {1-sum(X[1:nX_salt])}); //recalculate water mass fraction when gases are omitted (which they are in the density function)
algorithm
d := density_Duan2008_pTX(p,T,X_,MM[liqIndex],
saltConstants);
// print("density_liquid_pTX: "+String(p*1e-5)+" bar,"+String(T)+" K->"+String(d)+"kg/m^3");
end density_liq_pTX;
/*function extends density_Duan2008_pTX(nX_salt_=nX_salt, ignoreLimitSalt_p_=ignoreLimitSalt_p_global)
"just to set the flags"
end density_Duan2008_pTX;*/
redeclare replaceable function extends density_gas_pTX
algorithm
d := BrineGas3Gas.density_pTX(p,T,X,MM);
// print("density_liquid_pTX: "+String(p*1e-5)+" bar,"+String(T)+" K->"+String(d)+"kg/m^3");
end density_gas_pTX;
redeclare function extends specificEnthalpy_liq_pTX
// Partial_Units.Molality molalities = massFractionsToMoleFractions(X, MM_vec);
......@@ -78,13 +83,10 @@ protected
// print(String(p*1e-5)+" bar,"+String(T)+" K->"+String(h)+" J/kg (Brine_Duan_Multi_TwoPhase_ngas_3.specificEnthalpy_liq_pTX)");
end specificEnthalpy_liq_pTX;
redeclare function extends specificEnthalpy_gas_pTX
redeclare replaceable function extends specificEnthalpy_gas_pTX
algorithm
h :=BrineGas3Gas.specificEnthalpy_pTX(
p,
T,
X);
h :=BrineGas3Gas.specificEnthalpy_pTX(p,T,X); //,MM
end specificEnthalpy_gas_pTX;
redeclare function extends dynamicViscosity_liq
......@@ -127,14 +129,15 @@ protected
algorithm
// if gasname =="carbondioxide" then
p_sat[1] := if X[nX_salt+1]>0 then degassingPressure_CO2_Duan2006(p,T,X,MM_vec) else 0
p_sat[iCO2-nX_salt] := if X[iCO2]>0 then degassingPressure_CO2_Duan2006(p,T,X,MM_vec) else 0
"aus GasData TODO: use numeral";
// elseif gasname =="nitrogen" then
p_sat[2] :=if X[nX_salt + 2] > 0 then GasData.degassingPressure_N2_Mao2006(p,T,X,MM_vec) else 0
p_sat[iN2-nX_salt] :=if X[iN2] > 0 then GasData.degassingPressure_N2_Mao2006(p,T,X,MM_vec) else 0
"aus GasData";
// elseif gasname =="methane" then
p_sat[3] := if X[nX_salt+3]>0 then degassingPressure_CH4_Duan2006(p,T,X,MM_vec) else 0
p_sat[iCH4-nX_salt] := if X[iCH4]>0 then degassingPressure_CH4_Duan2006(p,T,X,MM_vec) else 0
"aus GasData";
// end if;
if debugmode then
print("saturationPressures("+String(p)+","+String(T)+")={"+Modelica.Math.Matrices.toString({p_sat})+"}");
......
......@@ -3,6 +3,7 @@ setState_pTX
setState_phX
solubilities_pTX
density_liq_pTX
density_gas_pTX
specificEnthalpy_liq_pTX
specificEnthalpy_gas_pTX
dynamicViscosity_liq
......
within BrineProp;
package Brine3salts4gas
"Two-phase aqueous solution of NaCl, KCl, CaCl2, N2, CO2, CH4, H2"
extends Brine3salts3gas(
iH2=7,
final gasNames = {"carbondioxide","nitrogen","methane","hydrogen"},
final MM_gas = {M_CO2,M_N2,M_CH4,M_H2},
final nM_gas = {nM_CO2,nM_N2,nM_CH4,nM_H2}); //iGas not final, because reassigned in Brine5salts3gas
//order of gases must be consistent with Brine3Gas TODO: pass order or copy enthalpy/density/cp here
redeclare function solubilities_pTX
"solubility calculation"
// extends PartialBrineMultiSaltMultiGasTwoPhase.solubilities_pTX;
// TODO: avoid repeating the declarations below (extending Brine3salts3gas doesn't work [multiple algorithms]
input SI.Pressure p;
input SI.Temp_K T;
input SI.MassFraction X_l[nX] "mass fractions m_x/m_Sol";
input SI.MassFraction X[nX] "mass fractions m_x/m_Sol";
input SI.Pressure[nX_gas] p_gas;
input Boolean ignoreTlimit=false "activated by temperature_phX";
// input SI.MolarMass MM[:] "=fill(0,nX)molar masses of components";
// output Molality[nX_gas] solu;
output MassFraction solu[nX_gas] "gas concentration in kg_gas/kg_fluid";
algorithm
if debugmode then
//print("\nRunning setState_pTX("+String(p/1e5)+" bar,"+String(min(1000,T)-273.15)+" degC, ignoreTlimit="+String(ignoreTlimit)+", X="+Modelica.Math.Matrices.toString(transpose([X]))+")");
print("\nRunning setState_pTX(p_gas={"+String(p_gas[1])+", "+String(p_gas[2])+", "+String(p_gas[3])+"}) (solubilities_pTX)");
end if;
if debugmode then
print("Running solubilities_pTX("+String(p/1e5)+" bar,"+String(T-273.15)+" C, ignoreTlimit="+String(ignoreTlimit)+", X="+Modelica.Math.Matrices.toString(transpose([X]))+")");
end if;
solu[iCO2-nX_salt] := if X[iCO2]>0 then solubility_CO2_pTX_Duan2006(p,T,X_l,MM_vec,p_gas[iCO2-nX_salt],ignoreTlimit) else -1
"aus GasData, mol/kg_H2O -> kg_CO2/kg_H2O";
solu[iN2-nX_salt] :=if X[iN2] > 0 then solubility_N2_pTX_Mao2006(p,T,X_l,MM_vec,p_gas[iN2-nX_salt],ignoreTlimit) else -1
"aus GasData, mol/kg_H2O -> kg_N2/kg_H2O";
solu[iCH4-nX_salt] := if X[iCH4]>0 then solubility_CH4_pTX_Duan2006(p,T,X_l,MM_vec,p_gas[iCH4-nX_salt],ignoreTlimit) else -1
"aus GasData, mol/kg_H2O -> kg_CH4/kg_H2O";
solu[iH2-nX_salt] := if X[iH2]>0 then solubility_H2_pTX_Chabab2020(p,T,X_l,MM_vec,p_gas[iH2-nX_salt],ignoreTlimit) else -1
"aus GasData, mol/kg_H2O -> kg_CH4/kg_H2O";
// print("k={"+String(solu[1]/p_gas[1])+", "+String(solu[2]/p_gas[2])+", "+String(solu[3]/p_gas[3])+"}(solubilities_pTX)");
// print("solu={"+String(solu[1])+", "+String(solu[2])+", "+String(solu[3])+"}(solubilities_pTX)");
// print(Modelica.Math.Matrices.toString({MM_vec}));
end solubilities_pTX;
redeclare function extends dynamicViscosity_gas
algorithm
eta :=BrineGas3Gas.dynamicViscosity(BrineGas3Gas.ThermodynamicState(
state.p,
state.T,
state.X_g));
assert(eta>0,"Error in gas viscosity calculation.");
end dynamicViscosity_gas;
redeclare function extends saturationPressures
algorithm
// if gasname =="carbondioxide" then
p_sat[iCO2-nX_salt] := if X[iCO2]>0 then degassingPressure_CO2_Duan2006(p,T,X,MM_vec) else 0
"aus GasData TODO: use numeral";
// elseif gasname =="nitrogen" then
p_sat[iN2-nX_salt] :=if X[iN2] > 0 then GasData.degassingPressure_N2_Mao2006(p,T,X,MM_vec) else 0
"aus GasData";
// elseif gasname =="methane" then
p_sat[iCH4-nX_salt] := if X[iCH4]>0 then degassingPressure_CH4_Duan2006(p,T,X,MM_vec) else 0
"aus GasData";
// end if;
if debugmode then
print("saturationPressures("+String(p)+","+String(T)+")={"+Modelica.Math.Matrices.toString({p_sat})+"}");
end if;
end saturationPressures;
redeclare function extends specificHeatCapacityCp_gas
"calculation of gas specific heat capacity"
import SG = Modelica.Media.IdealGases.SingleGases;
algorithm
if state.x>0 then
cp :=BrineGas3Gas.specificHeatCapacityCp_pTX(
p=state.p,
T=state.T,
X=X_g[end - nX_gas:end]);
else
cp:=-1;
end if;
annotation (Documentation(info="<html>
<p>In the two phase region this function returns the interpolated heat capacity between the
liquid and vapour state heat capacities.</p>
</html>"));
end specificHeatCapacityCp_gas;
redeclare function density_gas_pTX
extends PartialBrineMultiSaltMultiGasTwoPhase.density_gas_pTX;
/* input SI.Pressure p;
input SI.Temp_K T;
input MassFraction X[:] "nX_gas mass fraction";
input SI.MolarMass MM[:] "=MM_vec =fill(0,nX) molar masses of components";
output SI.Density d;*/
algorithm
d := BrineGas4Gas.density_pTX(p,T,X,MM);
// print("density_liquid_pTX: "+String(p*1e-5)+" bar,"+String(T)+" K->"+String(d)+"kg/m^3");
end density_gas_pTX;
redeclare function specificEnthalpy_gas_pTX
extends PartialBrineMultiSaltMultiGasTwoPhase.specificEnthalpy_gas_pTX;
algorithm
h :=BrineGas4Gas.specificEnthalpy_pTX(p,T,X); //,MM
end specificEnthalpy_gas_pTX;
end Brine3salts4gas;
within BrineProp;
package BrineGas3Gas "Gas mixture of CO2+N2+CH4+H2O"
extends PartialBrineGas(
final substanceNames={"carbondioxide","nitrogen","methane","water"},
final MM_vec = {M_CO2,M_N2,M_CH4,M_H2O},
final nM_vec = {nM_CO2,nM_N2,nM_CH4,nM_CH4});
substanceNames={"carbondioxide","nitrogen","methane","water"},
iCO2=1,
iN2=2,
iCH4=3,
MM_vec = {M_CO2,M_N2,M_CH4,M_H2O},
nM_vec = {nM_CO2,nM_N2,nM_CH4,nM_H2O});
extends PartialFlags;
redeclare model extends BaseProperties
//Dummy for OM
end BaseProperties;
/* redeclare record extends ThermodynamicState
//Dummy for OM
end ThermodynamicState;
*/
constant Boolean waterSaturated=false "activates water saturation";
replaceable function waterSaturatedComposition_pTX
"calculates the water saturated mass vector for a given Temperature"
//saturates the mixture with water
......@@ -51,7 +50,6 @@ protected
end waterSaturatedComposition_pTX;
redeclare function extends density "water-saturated density from state"
algorithm
......@@ -66,40 +64,45 @@ protected
// assert(lambda>0,"lambda="+String(lambda));
end density;
replaceable function extends specificHeatCapacityCp_pTX
"calculation of specific heat capacities of gas mixture"
import Modelica.Media.IdealGases.Common.SingleGasNasa;
import Modelica.Media.IdealGases.SingleGases;
import Modelica.Media.Water;
protected
SingleGases.H2O.ThermodynamicState state=SingleGases.H2O.ThermodynamicState(p=0,T=T);
SI.SpecificHeatCapacity cp_CO2=SingleGases.CO2.specificHeatCapacityCp(state);
SI.SpecificHeatCapacity cp_N2=SingleGases.N2.specificHeatCapacityCp(state);
SI.SpecificHeatCapacity cp_CH4=SingleGases.CH4.specificHeatCapacityCp(state);
SI.SpecificHeatCapacity cp_H2O=Water.IF97_Utilities.cp_pT(min(p,Water.IF97_Utilities.BaseIF97.Basic.psat(T)-1),T=T)
"below psat -> gaseous";
SI.SpecificHeatCapacity cp_vec[:]={cp_CO2,cp_N2,cp_CH4,cp_H2O}; //the two-phase models rely on this order!
redeclare function extends density_pTX
"Density of an ideal mixture of ideal gases"
// SpecificHeatCapacity R_gas; //= sum(Modelica.Constants.R*X ./ MM_vec);
// MassFraction[:] X_=cat(1,fill(nX-1,0),{1});
// MassFraction[size(X,1)] X_=cat(1,fill(size(X,1),0),{1});
algorithm
/* if not R_gas >0 then
print("R_gas="+String(R_gas)+", (MM="+Modelica.Math.Matrices.toString({MM_vec})+", X="+Modelica.Math.Matrices.toString({X})+")");
end if;*/
// print("size(X_,1)="+String(size(X_,1))+",size(X,1)="+String(size(X,1)));
if debugmode then
print("Running density_pTX("+String(p/1e5)+" bar,"+String(T-273.15)+" degC, X="+Modelica.Math.Matrices.toString(transpose([X]))+")");
print("Running specificHeatCapacityCp_pTX("+String(p/1e5)+" bar,"+String(T-273.15)+" degC, X="+Modelica.Math.Matrices.toString(transpose([X]))+")");
end if;
// assert(min(X)>0,"Cannot calculate with empty composition.");
if not min(X)>0 and not ignoreNoCompositionInBrineGas then
print("No gas composition, assuming water vapour.(BrineProp.BrineGas_3Gas.density_pTX)");
if not ignoreNoCompositionInBrineGas and not min(X)>0 then
print("No gas composition, assuming water vapour.(BrineProp.BrineGas_3Gas.specificHeatCapacityCp_pTX)");
end if;
R_gas :=Modelica.Constants.R*sum(cat(1,X[1:end-1],{(if min(X)>0 then X[end] else 1)})./ MM_vec);
/* if waterSaturated then
R_gas :=sum(Modelica.Constants.R*waterSaturatedComposition_pTX(
p,
T,
X[end - nX + 1:end]) ./ MM_vec);
d :=p/(T*R_gas);
else*/
d :=p/(T*R_gas);
cp := cp_vec * waterSaturatedComposition_pTX(p,T,X[end - nX+1:end]);
else */
// cp := cp_vec * X[end - nX+1:end];
cp := cp_vec * cat(1,X[1:end-1],{if min(X)>0 then X[end] else 1});
// end if;
// print("d="+String(d)+" kg/m^3");
end density_pTX;
/* print("cp_CO2: "+String(cp_vec[1])+" J/kg");
print("cp_N2: "+String(cp_vec[2])+" J/kg");
print("cp_CH4: "+String(cp_vec[3])+" J/kg");
print("cp_H2O: "+String(cp_vec[4])+" J/kg"); */
end specificHeatCapacityCp_pTX;
redeclare function extends dynamicViscosity
"water-saturated thermal conductivity of water"
......@@ -115,7 +118,6 @@ protected
// assert(lambda>0,"lambda="+String(lambda));
end dynamicViscosity;
redeclare function extends dynamicViscosity_pTX
"calculation of gas dynamic Viscosity"
/* import NG = Modelica.Media.IdealGases.Common.SingleGasNasa;
......@@ -131,7 +133,6 @@ protected
X={0,0}));
end dynamicViscosity_pTX;
redeclare function extends thermalConductivity
"water-saturated thermal conductivity of water"
//very little influence of salinity
......@@ -150,7 +151,6 @@ protected
end thermalConductivity;
redeclare function extends thermalConductivity_pTX
"calculation of gas thermal conductivity"
/* import NG = Modelica.Media.IdealGases.Common.SingleGasNasa;
......@@ -163,8 +163,7 @@ protected
Modelica.Media.Air.MoistAir.ThermodynamicState(p=0,T=T,X={0,0}));
end thermalConductivity_pTX;
redeclare function specificEnthalpy_pTX
redeclare replaceable function specificEnthalpy_pTX
"calculation of specific enthalpy of gas mixture"
// import Modelica.Media.IdealGases.Common.SingleGasNasa;
import Modelica.Media.IdealGases.SingleGases;
......@@ -183,7 +182,7 @@ protected
SI.SpecificEnthalpy h_N2=SingleGases.N2.specificEnthalpy(state);
SI.SpecificEnthalpy h_CH4=SingleGases.CH4.specificEnthalpy(state);
SI.SpecificEnthalpy[:] h_vec={h_CO2,h_N2,h_CH4,h_H2O};
SI.SpecificEnthalpy[:] h_vec={h_CO2,h_N2,h_CH4,h_H2O}; //the two-phase models rely on this order!
SI.MassFraction X_[size(X,1)] "OM workaround for cat";
algorithm
X_[1:end-1]:=X[1:end-1] "OM workaround for cat";
......@@ -208,7 +207,6 @@ protected
*/
end specificEnthalpy_pTX;
redeclare function extends specificEnthalpy
"water-saturated specific enthalpy of gas phase"
algorithm
......@@ -222,7 +220,6 @@ protected
end specificEnthalpy;
annotation (Documentation(info="<html>
<p><b>BrineGas_3Gas</b> is a medium package that, based on Brine.PartialBrineGas, defines a brine with 3 gases (CO<sub>2</sub>, N<sub>2</sub>, CH<sub>4</sub>), which are the main gases in the geofluid in Gross Schoenebeck, Germany.</p>
<h4>Usage</h4>
......
......@@ -2,7 +2,6 @@ BaseProperties
waterSaturated
waterSaturatedComposition_pTX
density
density_pTX
specificHeatCapacityCp
specificHeatCapacityCp_pTX
dynamicViscosity
......
within BrineProp;
package BrineGas4Gas "\"Gas mixture of CO2+N2+CH4+H2+H2O\""
extends BrineGas3Gas(
final substanceNames={"carbondioxide","nitrogen","methane","hydrogen", "water"},
iH2=4,
final MM_vec = {M_CO2,M_N2,M_CH4,M_H2,M_H2O},
final nM_vec = {nM_CO2,nM_N2,nM_CH4,nM_H2,nM_H2O});
redeclare function specificEnthalpy_pTX
"calculation of specific enthalpy of gas mixture"
// import Modelica.Media.IdealGases.Common.SingleGasNasa;
import Modelica.Media.IdealGases.SingleGases;
extends Modelica.Icons.Function;
input AbsolutePressure p "Pressure";
input Temperature T "Temperature";
input MassFraction X[:]=reference_X "Mass fractions";
output SpecificEnthalpy h "Specific enthalpy";
protected
SI.SpecificEnthalpy h_H2O_sat=Modelica.Media.Water.IF97_Utilities.BaseIF97.Regions.hv_p(p);
SI.SpecificEnthalpy h_H2O=max(h_H2O_sat, Modelica.Media.Water.WaterIF97_pT.specificEnthalpy_pT(p,T))
"to make sure it is gaseous";
SingleGases.H2O.ThermodynamicState state=SingleGases.H2O.ThermodynamicState(p=0,T=T);
SI.SpecificEnthalpy h_CO2=SingleGases.CO2.specificEnthalpy(state);
SI.SpecificEnthalpy h_N2=SingleGases.N2.specificEnthalpy(state);
SI.SpecificEnthalpy h_CH4=SingleGases.CH4.specificEnthalpy(state);
SI.SpecificEnthalpy h_H2=SingleGases.H2.specificEnthalpy(state);
// SI.SpecificEnthalpy[:] h_vec={h_CO2,h_N2,h_CH4,h_H2,h_H2O}; //the two-phase models rely on this order!
SI.SpecificEnthalpy[nX] h_vec;
SI.MassFraction X_[size(X,1)] "OM workaround for cat";
algorithm
h_vec[iCO2]:=h_CO2;
h_vec[iN2]:=h_N2;
h_vec[iCH4]:=h_CH4;
h_vec[iH2]:=h_H2;
h_vec[end]:=h_H2O;
X_[1:end-1]:=X[1:end-1] "OM workaround for cat";
X_[end]:=if min(X)>0 then X[end] else 1 "OM workaround for cat";
if debugmode then
print("Running specificEnthalpy_pTX("+String(p/1e5)+" bar,"+String(T-273.15)+" degC, X="+Modelica.Math.Matrices.toString(transpose([X]))+")");
end if;
if not min(X)>0 and not ignoreNoCompositionInBrineGas then
print("No gas composition, assuming water vapour.(BrineProp.BrineGas_3Gas.specificEnthalpy_pTX)");
end if;
h := h_vec*X_ "mass weighted average, OM workaround for cat";
//h := h_vec * cat(1,X[1:end-1], {if min(X)>0 then X[end] else 1}) "Doesn't work in function in OM";
/* print("h_CO2: "+String(h_CO2)+" J/kg");
print("h_N2: "+String(h_N2)+" J/kg");
print("h_CH4: "+String(h_CH4)+" J/kg");
print("h_H2O: "+String(h_H2O)+" J/kg");
print("T: "+String(state.T)+" K");
*/
end specificEnthalpy_pTX;
end BrineGas4Gas;
specificHeatCapacityCp_pTX
specificEnthalpy_pTX
within BrineProp.BrineGas3Gas;
within BrineProp.BrineGas4Gas;
function extends specificHeatCapacityCp_pTX
"calculation of specific heat capacities of gas mixture"
import Modelica.Media.IdealGases.Common.SingleGasNasa;
......@@ -11,18 +11,19 @@ protected
SI.SpecificHeatCapacity cp_CO2=SingleGases.CO2.specificHeatCapacityCp(state);
SI.SpecificHeatCapacity cp_N2=SingleGases.N2.specificHeatCapacityCp(state);
SI.SpecificHeatCapacity cp_CH4=SingleGases.CH4.specificHeatCapacityCp(state);
SI.SpecificHeatCapacity cp_H2=SingleGases.H2.specificHeatCapacityCp(state);
SI.SpecificHeatCapacity cp_H2O=Water.IF97_Utilities.cp_pT(min(p,Water.IF97_Utilities.BaseIF97.Basic.psat(T)-1),T=T)
"below psat -> gaseous";
SI.SpecificHeatCapacity cp_vec[:]={cp_CO2,cp_N2,cp_CH4,cp_H2O};
SI.SpecificHeatCapacity cp_vec[nX]; //={cp_CO2,cp_N2,cp_CH4,cp_H2,cp_H2O};
/* SI.SpecificHeatCapacity cp_vec[:]={
SingleGasNasa.cp_T(data=SingleGasesData.CO2,T=T),
SingleGasNasa.cp_T(data=SingleGasesData.N2,T=T),
SingleGasNasa.cp_T(data=SingleGasesData.CH4,T=T),
Water.IF97_Utilities.cp_pT(min(p,Water.IF97_Utilities.BaseIF97.Basic.psat(T)-1),T=T)}
*/
algorithm
cp_vec[iCO2]:=cp_CO2;
cp_vec[iN2]:=cp_N2;
cp_vec[iCH4]:=cp_CH4;
cp_vec[iH2]:=cp_H2;
cp_vec[iCO2]:=cp_H2O; //the two-phase models rely on this order!
if debugmode then
print("Running specificHeatCapacityCp_pTX("+String(p/1e5)+" bar,"+String(T-273.15)+" degC, X="+Modelica.Math.Matrices.toString(transpose([X]))+")");
end if;
......
......@@ -9,4 +9,5 @@ package ComponentsOrder "to be defined in actual Medium package"
constant Integer iN2;
constant Integer iCO2;
constant Integer iCH4;
constant Integer iH2;
end ComponentsOrder;
......@@ -96,8 +96,8 @@ algorithm
end if;
// print("nX_salts="+String(nX_salt)+", veclength="+String(size(ignoreLimitSalt_p,1)) + ", ignoreLimitSalt_p="+String(ignoreLimitSalt_p[1]));
assert(size(ignoreLimitSalt_p,1)==nX_salt,"Wrong length of ignoreLimitSalt_T ("+String(size(ignoreLimitSalt_p,1))+")"); //needed here, because flag vector with fewer than nX_salts elements causes "out of bounds" and is not caught elsewere
assert(size(ignoreLimitSalt_T,1)==nX_salt,"Wrong length of ignoreLimitSalt_p ("+String(size(ignoreLimitSalt_T,1))+")"); //should be in PartialFlags, but asserts can't be in packages
assert(size(ignoreLimitSalt_p,1)==nX_salt,"Wrong length of ignoreLimitSalt_p ("+String(size(ignoreLimitSalt_p,1))+")"); //needed here, because flag vector with fewer than nX_salts elements causes "out of bounds" and is not caught elsewere
assert(size(ignoreLimitSalt_T,1)==nX_salt,"Wrong length of ignoreLimitSalt_T ("+String(size(ignoreLimitSalt_T,1))+")"); //should be in PartialFlags, but asserts can't be in packages
assert(size(ignoreLimitSalt_b,1)==nX_salt,"Wrong length of ignoreLimitSalt_b ("+String(size(ignoreLimitSalt_b,1))+")");
rho_H2O := Modelica.Media.Water.WaterIF97_pT.density_pT(max(p, p_sat + 1), T)*1e-3
......
within BrineProp.Examples.Gas;
model Brine3Gas_Minimal
package Medium = BrineProp.BrineGas3Gas (ignoreNoCompositionInBrineGas=true);
Medium.BaseProperties props;
equation
props.p = 10*1e5;
props.T = 293.15;
props.Xi={0.1,0.1,0.1};
end Brine3Gas_Minimal;
within BrineProp.Examples.Gas;
model Brine4Gas_Minimal
package Medium = BrineProp.BrineGas4Gas (ignoreNoCompositionInBrineGas=true);
Medium.BaseProperties props;
equation
props.p = 10*1e5;
props.T = 293.15;
props.Xi={0.1,0.1,0.1,0.1};
end Brine4Gas_Minimal;
within BrineProp.Examples;
model BrineGas
within BrineProp.Examples.Gas;
model UnitTestBrine3Gas
package Medium = BrineProp.BrineGas3Gas (ignoreNoCompositionInBrineGas=true);
//package Medium = Modelica.Media.Air.SimpleAir;
//package Medium = PartialBrineGas;
......@@ -58,9 +58,14 @@ equation
// props.Xi={0.8};
props.Xi={0.0892134,0.0051995,0.137699,0,0,0.000639217,7.0356e-6,1.5464e-5};
*/
// assert(abs(props.GVF-0.0497710432105261)<1e6,"GVF differs!");
assert(abs(props.h-2777119.5)<1e6,"h differs!");
assert(abs(props.d-0.007391231)<1e6,"d differs!");
algorithm
// print("rho="+String(d)+" kg/m^3, TDS = " + String(TDS) + " g/l -> "+ String(f*265/TDS));
// print("sum(X_l)="+String(sum(props.state.X_l)-1)+"");
// print("sum(X_sat)="+String(sum(X_sat)));
end BrineGas;
end UnitTestBrine3Gas;
within BrineProp.Examples;
package Gas
end Gas;
Brine3Gas_Minimal
Brine4Gas_Minimal
UnitTestBrine3Gas
within BrineProp.Examples;
within BrineProp.Examples.Liquid;
model BrineProps1PhaseFull
"Example for 1-phase brine property model demonstrating all features"
//needs "Advanced.PedanticModelica:=false" to run
......
within BrineProp.Examples;
within BrineProp.Examples.Liquid;
model BrineProps1PhaseMinimal
"Minimal example for 1-phase brine property model"
//needs "Advanced.PedanticModelica:=false" to run
......
within BrineProp.Examples;
within BrineProp.Examples.Liquid;
model BrineProps1PhasePureNaCl "Pure salt example - only h and cp"
//needs "Advanced.PedanticModelica:=false" to run
// Driesner EOS support also pure NaCl density, but as it is used here only for h and cp only those values can be calculatesd
......
within BrineProp.Examples;
model SalinityFromDensity
"Invert density function to determine NaCl content"
within BrineProp.Examples.Liquid;
model SalinityFromDensity "Invert density function to determine NaCl content"
//needs "Advanced.PedanticModelica:=false" to run
package Medium = Brine3salts "specify medium";
......
within BrineProp.Examples;
within BrineProp.Examples.Liquid;
model SingleSaltBrine
//SPECIFY MEDIUM
// package Medium = BrineProp.BrineDriesner "Driesner EOS for NaCl solution";
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment