root/branches/maintenance/2.2.2/Modelica/Media/Air.mo

Revision 589, 57.6 kB (checked in by hubertus, 15 months ago)

Fixed a problem with DryAirNasa that Katrin discovered

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1within Modelica.Media;
2package Air "Medium models for air" 
3 
4  package SimpleAir "Air: Simple dry air model (0..100 degC)" 
5   
6    extends Interfaces.PartialSimpleIdealGasMedium(
7       mediumName="SimpleAir",
8       cp_const=1005.45,
9       MM_const=0.0289651159,
10       R_gas=Constants.R/0.0289651159,
11       eta_const=1.82e-5,
12       lambda_const=0.026,
13       T_min=Cv.from_degC(0),
14       T_max=Cv.from_degC(100));
15   
16    import SI = Modelica.SIunits;
17    import Cv = Modelica.SIunits.Conversions;
18    import Modelica.Constants;
19   
20    constant FluidConstants[nS] fluidConstants=
21      FluidConstants(iupacName={"simple air"},
22                     casRegistryNumber={"not a real substance"},
23                     chemicalFormula={"N2, O2"},
24                     structureFormula={"N2, O2"},
25                     molarMass=Modelica.Media.IdealGases.Common.SingleGasesData.N2.MM) 
26      "constant data for the fluid";
27   
28    annotation (Documentation(info="<html>
29                              <h4>Simple Ideal gas air model for low temperatures</h4>
30                              <p>This model demonstrats how to use the PartialSimpleIdealGas base class to build a
31                              simple ideal gas model with a limited temperature validity range.</p>
32                              </html>"));
33  end SimpleAir;
34 
35  package DryAirNasa "Air: Detailed dry air model as ideal gas (200..6000 K)" 
36    extends IdealGases.Common.SingleGasNasa(
37     mediumName="Air",
38     data=IdealGases.Common.SingleGasesData.Air,
39     fluidConstants={IdealGases.Common.FluidData.N2});
40    annotation (preferedView="info", Documentation(info="<HTML>
41      <IMG SRC=\"../Images/Media/IdealGases/SingleGases/Air.png\"></HTML>"));
42   
43    import Cv = Modelica.SIunits.Conversions;
44   
45  redeclare function dynamicViscosity
46      "Simple polynomial for dry air (moisture influence small), valid from 73.15 K to 373.15 K" 
47    extends Modelica.Icons.Function;
48    input ThermodynamicState state "Thermodynamic state record";
49    output DynamicViscosity eta "Dynamic viscosity";
50  algorithm 
51    eta := Incompressible.TableBased.Polynomials_Temp.evaluate({(-4.96717436974791E-011), 5.06626785714286E-008, 1.72937731092437E-005}, Cv.to_degC(state.T));
52      annotation (Documentation(info="<html>
53Dynamic viscosity is computed from temperature using a second order polynomial with a range of validity between 73 and 373 K.
54</html>"));
55  end dynamicViscosity;
56   
57    redeclare function thermalConductivity
58      "Simple polynomial for dry air (moisture influence small), valid from 73.15 K to 373.15 K" 
59      extends Modelica.Icons.Function;
60      input ThermodynamicState state "Thermodynamic state record";
61      input Integer method=1 "Dummy for compatibility reasons";
62      output ThermalConductivity lambda "Thermal conductivity";
63    algorithm 
64      lambda := Incompressible.TableBased.Polynomials_Temp.evaluate({(-4.8737307422969E-008), 7.67803133753502E-005, 0.0241814385504202},Cv.to_degC(state.T));
65     
66      annotation (Documentation(info="<html>
67Thermal conductivity is computed from temperature using a second order polynomial with a range of validity between 73 and 373 K.
68</html>"));
69    end thermalConductivity;
70   
71    annotation (Documentation(info="<html>
72Ideal gas medium model for dry air based on the package <a href=Modelica:Modelica.Media.IdealGases>IdealGases</a> with additional functions for dynamic viscosity and thermal conductivity in a limited temperature range.
73</html>"));
74  end DryAirNasa;
75 
76  package MoistAir "Air: Moist air model (240 ... 400 K)" 
77    extends Interfaces.PartialCondensingGases(
78       mediumName="Moist air",
79       substanceNames={"water", "air"},
80       final reducedX=true,
81       final singleState=false,
82       reference_X={0.01,0.99},
83       fluidConstants = {IdealGases.Common.FluidData.H2O,IdealGases.Common.FluidData.N2});
84   
85    constant Integer Water=1 
86      "Index of water (in substanceNames, massFractions X, etc.)";
87    constant Integer Air=2 
88      "Index of air (in substanceNames, massFractions X, etc.)";
89    //     constant SI.Pressure psat_low=saturationPressureWithoutLimits(200.0);
90    //     constant SI.Pressure psat_high=saturationPressureWithoutLimits(422.16);
91    constant Real k_mair =  steam.MM/dryair.MM "ratio of molar weights";
92   
93    constant IdealGases.Common.DataRecord dryair = IdealGases.Common.SingleGasesData.Air;
94    constant IdealGases.Common.DataRecord steam = IdealGases.Common.SingleGasesData.H2O;
95   
96    import Modelica.Media.Interfaces;
97    import Modelica.Math;
98    import SI = Modelica.SIunits;
99    import Cv = Modelica.SIunits.Conversions;
100    import Modelica.Constants;
101    import Modelica.Media.IdealGases.Common.SingleGasNasa;
102   
103    redeclare replaceable model extends BaseProperties(
104      T(stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default),
105      p(stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default),
106      Xi(stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default)) 
107      "Moist air base properties record" 
108     
109      /* p, T, X = X[Water] are used as preferred states, since only then all
110     other quantities can be computed in a recursive sequence.
111     If other variables are selected as states, static state selection
112     is no longer possible and non-linear algebraic equations occur.
113      */
114      MassFraction x_water "Mass of total water/mass of dry air";
115      Real phi "Relative humidity";
116      annotation(structurallyIncomplete, Documentation(info="<html>
117This model computes thermodynamic properties of moist air from three independent (thermodynamic or/and numerical) state variables. Preferred numerical states are temperature T, pressure p and the reduced composition vector Xi, which contains the water mass fraction only. As an EOS the <b>ideal gas law</b> is used and associated restrictions apply. The model can also be used in the <b>fog region</b>, when moisture is present in its liquid state. However, it is assumed that the liquid water volume is negligible compared to that of the gas phase. Computation of thermal properties is based on property data of <a href=Modelica:Modelica.Media.Air.DryAirNasa> dry air</a> and water (source: VDI-W&auml;rmeatlas), respectively. Besides the standard thermodynamic variables <b>absolute and relative humidity</b>, x_water and phi, respectively, are given by the model. Upper case X denotes absolute humidity with respect to mass of moist air while absolute humidity with respect to mass of dry air only is denoted by a lower case x throughout the model. See <a href=Modelica:Modelica.Media.Air.MoistAir>package description</a> for further information.
118</html>"));
119     
120    protected 
121      constant SI.MolarMass[2] MMX = {steam.MM,dryair.MM} 
122        "Molar masses of components";
123     
124      MassFraction X_liquid "Mass fraction of liquid or solid water";
125      MassFraction X_steam "Mass fraction of steam water";
126      MassFraction X_air "Mass fraction of air";
127      MassFraction X_sat
128        "Steam water mass fraction of saturation boundary in kg_water/kg_moistair";
129      MassFraction x_sat
130        "Steam water mass content of saturation boundary in kg_water/kg_dryair";
131      AbsolutePressure p_steam_sat "Partial saturation pressure of steam";
132    equation 
133      assert(T >= 200.0 and T <= 423.15, "
134Temperature T is not in the allowed range
135200.0 K <= (T =" + String(T) + " K) <= 423.15 K
136required from medium model \""       + mediumName + "\".");
137      MM = 1/(Xi[Water]/MMX[Water]+(1.0-Xi[Water])/MMX[Air]);
138     
139      p_steam_sat = min(saturationPressure(T),0.999*p);
140      X_sat = min(p_steam_sat * k_mair/max(100*Constants.eps, p - p_steam_sat)*(1 - Xi[Water]), 1.0) 
141        "Water content at saturation with respect to actual water content";
142      X_liquid = max(Xi[Water] - X_sat, 0.0);
143      X_steam  = Xi[Water]-X_liquid;
144      X_air    = 1-Xi[Water];
145     
146      h = specificEnthalpy_pTX(p,T,Xi);
147      R = dryair.R*(X_air/(1 - X_liquid)) + steam.R*X_steam/(1 - X_liquid);
148      //               
149      u = h - R*T;
150      d = p/(R*T);
151      /* Note, u and d are computed under the assumption that the volume of the liquid
152         water is neglible with respect to the volume of air and of steam
153      */
154      state.p = p;
155      state.T = T;
156      state.X = X;
157     
158      // these x are per unit mass of DRY air!
159      x_sat    = k_mair*p_steam_sat/max(100*Constants.eps,p - p_steam_sat);
160      x_water = Xi[Water]/max(X_air,100*Constants.eps);
161      phi = p/p_steam_sat*Xi[Water]/(Xi[Water] + k_mair*X_air);
162    end BaseProperties;
163   
164    redeclare function setState_pTX
165      "Return thermodynamic state as function of pressure p, temperature T and composition X" 
166      extends Modelica.Icons.Function;
167      input AbsolutePressure p "Pressure";
168      input Temperature T "Temperature";
169      input MassFraction X[:]=reference_X "Mass fractions";
170      output ThermodynamicState state "Thermodynamic state";
171    algorithm 
172      state := if size(X,1) == nX then ThermodynamicState(p=p,T=T, X=X) else 
173             ThermodynamicState(p=p,T=T, X=cat(1,X,{1-sum(X)}));
174      annotation (Documentation(info="<html>
175The <a href=Modelica:Modelica.Media.Air.MoistAir.ThermodynamicState>thermodynamic state record</a> is computed from pressure p, temperature T and composition X.
176</html>"));
177    end setState_pTX;
178   
179    redeclare function setState_phX
180      "Return thermodynamic state as function of pressure p, specific enthalpy h and composition X" 
181      extends Modelica.Icons.Function;
182      input AbsolutePressure p "Pressure";
183      input SpecificEnthalpy h "Specific enthalpy";
184      input MassFraction X[:]=reference_X "Mass fractions";
185      output ThermodynamicState state "Thermodynamic state";
186    algorithm 
187      state := if size(X,1) == nX then ThermodynamicState(p=p,T=T_phX(p,h,X),X=X) else 
188             ThermodynamicState(p=p,T=T_phX(p,h,X), X=cat(1,X,{1-sum(X)}));
189      annotation (Documentation(info="<html>
190The <a href=Modelica:Modelica.Media.Air.MoistAir.ThermodynamicState>thermodynamic state record</a> is computed from pressure p, specific enthalpy h and composition X.
191</html>"));
192    end setState_phX;
193   
194    redeclare function setState_dTX
195      "Return thermodynamic state as function of density d, temperature T and composition X" 
196      extends Modelica.Icons.Function;
197      input Density d "density";
198      input Temperature T "Temperature";
199      input MassFraction X[:]=reference_X "Mass fractions";
200      output ThermodynamicState state "Thermodynamic state";
201    algorithm 
202      state := if size(X,1) == nX then ThermodynamicState(p=d*({steam.R,dryair.R}*X)*T,T=T,X=X) else 
203             ThermodynamicState(p=d*({steam.R,dryair.R}*cat(1,X,{1-sum(X)}))*T,T=T, X=cat(1,X,{1-sum(X)}));
204      annotation (Documentation(info="<html>
205The <a href=Modelica:Modelica.Media.Air.MoistAir.ThermodynamicState>thermodynamic state record</a> is computed from density d, temperature T and composition X.
206</html>"));
207    end setState_dTX;
208   
209    function Xsaturation
210      "Return absolute humitity per unit mass of moist air at saturation as a function of the thermodynamic state record" 
211      input ThermodynamicState state "Thermodynamic state record";
212      output MassFraction X_sat "Steam mass fraction of sat. boundary";
213    algorithm 
214      X_sat := k_mair/(state.p/min(saturationPressure(state.T),0.999*state.p) - 1 + k_mair);
215      annotation (Documentation(info="<html>
216Absolute humidity per unit mass of moist air at saturation is computed from pressure and temperature in the state record. Note, that unlike X_sat in the BaseProperties model this mass fraction refers to mass of moist air at saturation.
217</html>"));
218    end Xsaturation;
219   
220    function xsaturation
221      "Return absolute humitity per unit mass of dry air at saturation as a function of the thermodynamic state record" 
222      input ThermodynamicState state "Thermodynamic state record";
223      output MassFraction x_sat "Absolute humidity per unit mass of dry air";
224    algorithm 
225      x_sat:=k_mair*saturationPressure(state.T)/max(100*Constants.eps,state.p - saturationPressure(state.T));
226      annotation (Documentation(info="<html>
227Absolute humidity per unit mass of dry air at saturation is computed from pressure and temperature in the thermodynamic state record.
228</html>"));
229    end xsaturation;
230   
231    function xsaturation_pT
232      "Return absolute humitity per unit mass of dry air at saturation as a function of pressure p and temperature T" 
233      input AbsolutePressure p "Pressure";
234      input SI.Temperature T "Temperature";
235      output MassFraction x_sat "Absolute humidity per unit mass of dry air";
236    algorithm 
237      x_sat:=k_mair*saturationPressure(T)/max(100*Constants.eps,p - saturationPressure(T));
238      annotation (Documentation(info="<html>
239Absolute humidity per unit mass of dry air at saturation is computed from pressure and temperature.
240</html>"));
241    end xsaturation_pT;
242   
243    function massFraction_pTphi
244      "Return steam mass fraction as a function of relative humidity phi and temperature T" 
245      input AbsolutePressure p "Pressure";
246      input Temperature T "Temperature";
247      input Real phi "Relative humidity (0 ... 1.0)";
248      output MassFraction X_steam "Absolute humidity, steam mass fraction";
249    protected 
250      constant Real k = 0.621964713077499 "Ratio of molar masses";
251      AbsolutePressure psat = saturationPressure(T) "Saturation pressure";
252    algorithm 
253      X_steam := phi*k/(k*phi+p/psat-phi);
254      annotation (Documentation(info="<html>
255Absolute humidity per unit mass of moist air is computed from temperature, pressure and relative humidity.
256</html>"));
257    end massFraction_pTphi;
258   
259    function relativeHumidity_pTX
260      "Return relative humidity as a function of pressure p, temperature T and composition X" 
261      input SI.Pressure p "Pressure";
262      input SI.Temperature T "Temperature";
263      input SI.MassFraction[:] X "Composition";
264      output Real phi "Relative humidity";
265    protected 
266      SI.Pressure p_steam_sat "Saturation pressure";
267      SI.MassFraction X_air "Dry air mass fraction";
268    algorithm 
269      p_steam_sat :=min(saturationPressure(T), 0.999*p);
270      X_air    :=1 - X[Water];
271      phi :=max(0.0,min(1.0, p/p_steam_sat*X[Water]/(X[Water] + k_mair*X_air)));
272      annotation (Documentation(info="<html>
273Relative humidity is computed from pressure, temperature and composition with 1.0 as the upper limit at saturation. Water mass fraction is the first entry in the composition vector.
274</html>"));
275    end relativeHumidity_pTX;
276   
277    function relativeHumidity
278      "Return relative humidity as a function of the thermodynamic state record" 
279      input ThermodynamicState state "Thermodynamic state";
280      output Real phi "Relative humidity";
281    algorithm 
282      phi:=relativeHumidity_pTX(state.p, state.T, state.X);
283      annotation (Documentation(info="<html>
284Relative humidity is computed from the thermodynamic state record with 1.0 as the upper limit at saturation.
285</html>"));
286    end relativeHumidity;
287   
288    /*   
289    redeclare function setState_psX "Return thermodynamic state as function of p, s and composition X"
290      extends Modelica.Icons.Function;
291      input AbsolutePressure p "Pressure";
292      input SpecificEntropy s "Specific entropy";
293      input MassFraction X[:]=reference_X "Mass fractions";
294      output ThermodynamicState state;
295    algorithm
296      state := if size(X,1) == nX then ThermodynamicState(p=p,T=T_psX(s,p,X),X=X)
297        else ThermodynamicState(p=p,T=T_psX(p,s,X), X=cat(1,X,{1-sum(X)}));       
298    end setState_psX;
299*/
300   
301    redeclare function extends gasConstant
302      "Return ideal gas constant as a function from thermodynamic state, only valid for phi<1" 
303    algorithm 
304      R := dryair.R*(1-state.X[Water]) + steam.R*state.X[Water];
305      annotation (Documentation(info="<html>
306The ideal gas constant for moist air is computed from <a href=Modelica:Modelica.Media.Air.MoistAir.ThermodynamicState>thermodynamic state</a> assuming that all water is in the gas phase.
307</html>"));
308    end gasConstant;
309   
310    function gasConstant_X
311      "Return ideal gas constant as a function from composition X" 
312      input SI.MassFraction X[:] "Gas phase composition";
313      output SI.SpecificHeatCapacity R "Ideal gas constant";
314    algorithm 
315      R := dryair.R*(1-X[Water]) + steam.R*X[Water];
316      annotation (Documentation(info="<html>
317The ideal gas constant for moist air is computed from the gas phase composition. The first entry in composition vector X is the steam mass fraction of the gas phase.
318</html>"));
319    end gasConstant_X;
320   
321    function saturationPressureLiquid
322      "Return saturation pressure of water as a function of temperature T in the range of 273.16 to 373.16 K" 
323     
324      extends Modelica.Icons.Function;
325      input SI.Temperature Tsat "saturation temperature";
326      output SI.AbsolutePressure psat "saturation pressure";
327      annotation(Inline=false,smoothOrder=5,
328        Documentation(derivative=saturationPressureLiquid_der,info="<html>
329Saturation pressure of water above the triple point temperature is computed from temperature. It's range of validity is between
330273.16 and 373.16 K. Outside these limits a less accurate result is returned.
331</html>"));
332    algorithm 
333      psat := 611.657*Math.exp(17.2799 - 4102.99/(Tsat - 35.719));
334    end saturationPressureLiquid;
335   
336    function saturationPressureLiquid_der
337      "Time derivative of saturationPressureLiquid" 
338     
339      extends Modelica.Icons.Function;
340      input SI.Temperature Tsat "Saturation temperature";
341      input Real dTsat(unit="K/s") "Saturation temperature derivative";
342      output Real psat_der(unit="Pa/s") "Saturation pressure";
343      annotation(Inline=false,smoothOrder=5,
344        Documentation(info="<html>
345Derivative function of <a href=Modelica:Modelica.Media.Air.MoistAir.saturationPressureLiquid>saturationPressureLiquid</a>
346</html>"));
347    algorithm 
348    /*psat := 611.657*Math.exp(17.2799 - 4102.99/(Tsat - 35.719));*/
349      psat_der:=611.657*Math.exp(17.2799 - 4102.99/(Tsat - 35.719))*4102.99*dTsat/(Tsat - 35.719)/(Tsat - 35.719);
350     
351    end saturationPressureLiquid_der;
352   
353    function sublimationPressureIce
354      "Return sublimation pressure of water as a function of temperature T between 223.16 and 273.16 K" 
355     
356      extends Modelica.Icons.Function;
357      input SI.Temperature Tsat "sublimation temperature";
358      output SI.AbsolutePressure psat "sublimation pressure";
359      annotation(Inline=false,smoothOrder=5,
360        Documentation(derivative=sublimationPressureIce_der,info="<html>
361Sublimation pressure of water below the triple point temperature is computed from temperature. It's range of validity is between
362 223.16 and 273.16 K. Outside of these limits a less accurate result is returned.
363</html>"));
364    algorithm 
365      psat := 611.657*Math.exp(22.5159*(1.0 - 273.16/Tsat));
366    end sublimationPressureIce;
367   
368    function sublimationPressureIce_der
369      "Derivative function for 'sublimationPressureIce'" 
370     
371      extends Modelica.Icons.Function;
372      input SI.Temperature Tsat "Sublimation temperature";
373      input Real dTsat(unit="K/s") "Time derivative of sublimation temperature";
374      output Real psat_der(unit="Pa/s") "Sublimation pressure";
375      annotation(Inline=false,smoothOrder=5,
376        Documentation(info="<html>
377Derivative function of <a href=Modelica:Modelica.Media.Air.MoistAir.sublimationPressureIce>saturationPressureIce</a>
378</html>"));
379    algorithm 
380      /*psat := 611.657*Math.exp(22.5159*(1.0 - 273.16/Tsat));*/
381      psat_der:=611.657*Math.exp(22.5159*(1.0 - 273.16/Tsat))*22.5159*273.16*dTsat/Tsat/Tsat;
382    end sublimationPressureIce_der;
383   
384    redeclare function extends saturationPressure
385      "Return saturation pressure of water as a function of temperature T between 223.16 and 373.16 K" 
386     
387      annotation(Inline=false,smoothOrder=5,
388        Documentation(derivative=saturationPressure_der,info="<html>
389Saturation pressure of water in the liquid and the solid region is computed using an Antoine-type correlation. It's range of validity is between 223.16 and 373.16 K. Outside of these limits a (less accurate) result is returned. Functions for the
390<a href=Modelica.Media.Air.MoistAir.sublimationPressureIce>solid</a> and the <a href=\"Modelica.Media.MoistAir.saturationPressureLiquid\"> liquid</a> region, respectively, are combined using the first derivative continuous <a href=Modelica.Media.MoistAir.Utilities.spliceFunction>spliceFunction</a>.
391</html>"));
392    algorithm 
393      psat := Utilities.spliceFunction(saturationPressureLiquid(Tsat),sublimationPressureIce(Tsat),Tsat-273.16,1.0);
394    end saturationPressure;
395   
396    function saturationPressure_der
397      "Derivative function for 'saturationPressure'" 
398      input Temperature Tsat "Saturation temperature";
399      input Real dTsat(unit="K/s") "Time derivative of saturation temperature";
400      output Real psat_der(unit="Pa/s") "Saturation pressure";
401      annotation(Inline=false,smoothOrder=5,
402        Documentation(info="<html>
403Derivative function of <a href=Modelica:Modelica.Media.Air.MoistAir.saturationPressure>saturationPressure</a>
404</html>"));
405     
406    algorithm 
407      /*psat := Utilities.spliceFunction(saturationPressureLiquid(Tsat),sublimationPressureIce(Tsat),Tsat-273.16,1.0);*/
408      psat_der := Utilities.spliceFunction_der(
409        saturationPressureLiquid(Tsat),
410        sublimationPressureIce(Tsat),
411        Tsat - 273.16,
412        1.0,
413        saturationPressureLiquid_der(Tsat=Tsat, dTsat=dTsat),
414        sublimationPressureIce_der(Tsat=Tsat, dTsat=dTsat),
415        dTsat,
416        0);
417    end saturationPressure_der;
418   
419    function saturationTemperature
420      "Return saturation temperature of water as a function of (partial) pressure p" 
421     
422      input SI.Pressure p "Pressure";
423      input SI.Temperature T_min=200 "Lower boundary of solution";
424      input SI.Temperature T_max=400 "Upper boundary of solution";
425      output SI.Temperature T "Saturation temperature";
426     
427    protected 
428    package Internal
429       extends Modelica.Media.Common.OneNonLinearEquation;
430       
431     redeclare record extends f_nonlinear_Data
432       // Define data to be passed to user function
433     end f_nonlinear_Data;
434       
435     redeclare function extends f_nonlinear
436     algorithm 
437        y:=saturationPressure(x);
438      // Compute the non-linear equation: y = f(x, Data)
439     end f_nonlinear;
440       
441     // Dummy definition
442     redeclare function extends solve
443     end solve;
444    end Internal;
445    algorithm 
446      T:=Internal.solve(p, T_min, T_max);
447      annotation (Documentation(info="<html>
448 Computes saturation temperature from (partial) pressure via numerical inversion of the function <a href=Modelica:Modelica.Media.Air.MoistAir.saturationPressure>saturationPressure</a>. Therefore additional inputs are required (or the defaults are used) for upper and lower temperature bounds. 
449</html>"));
450    end saturationTemperature;
451   
452   redeclare function extends enthalpyOfVaporization
453      "Return enthalpy of vaporization of water as a function of temperature T, 0 - 130 degC" 
454   algorithm 
455    /*r0 := 1e3*(2501.0145 - (T - 273.15)*(2.3853 + (T - 273.15)*(0.002969 - (T
456      - 273.15)*(7.5293e-5 + (T - 273.15)*4.6084e-7))));*/
457   //katrin: replaced by linear correlation, simpler and more accurate in the entire region
458   //source VDI-Waermeatlas, linear inter- and extrapolation between values for 0.01°C and 40°C.
459   r0:=(2405900-2500500)/(40-0)*(T-273.16)+2500500;
460      annotation (Documentation(info="<html>
461Enthalpy of vaporization of water is computed from temperature in the region of 0 to 130 °C.
462</html>"));
463   end enthalpyOfVaporization;
464   
465    function HeatCapacityOfWater
466      "Return specific heat capacity of water (liquid only) as a function of temperature T" 
467      extends Modelica.Icons.Function;
468      input Temperature T "Temperature";
469      output SpecificHeatCapacity cp_fl "Specific heat capacity of liquid";
470      annotation (Documentation(info="<html>
471The specific heat capacity of water (liquid and solid) is calculated using a
472                 polynomial approach and data from VDI-Waermeatlas 8. Edition (Db1)
473</html>"));
474    algorithm 
475      cp_fl := 1e3*(4.2166 - (T - 273.15)*(0.0033166 + (T - 273.15)*(0.00010295
476         - (T - 273.15)*(1.3819e-6 + (T - 273.15)*7.3221e-9))));
477    end HeatCapacityOfWater;
478   
479   redeclare function extends enthalpyOfLiquid
480      "Return enthalpy of liquid water as a function of temperature T(use enthalpyOfWater instead)" 
481     
482     annotation(Inline=false,smoothOrder=5,
483        Documentation(info="<html>
484Specific enthalpy of liquid water is computed from temperature using a polynomial approach. Kept for compatibility reasons, better use <a href=Modelica:Modelica.Media.Air.MoistAir.enthalpyOfWater>enthalpyOfWater</a> instead.
485</html>"));
486   algorithm 
487     h := (T - 273.15)*1e3*(4.2166 - 0.5*(T - 273.15)*(0.0033166 + 0.333333*(T - 273.15)*(0.00010295
488        - 0.25*(T - 273.15)*(1.3819e-6 + 0.2*(T - 273.15)*7.3221e-9))));
489   end enthalpyOfLiquid;
490   
491   redeclare function extends enthalpyOfGas
492      "Return specific enthalpy of gas (air and steam) as a function of temperature T and composition X" 
493     
494     annotation(Inline=false,smoothOrder=5,
495        Documentation(info="<html>
496Specific enthalpy of moist air is computed from temperature, provided all water is in the gaseous state. The first entry in the composition vector X must be the mass fraction of steam. For a function that also covers the fog region please refer to <a href=Modelica:Modelica.Media.Air.MoistAir.h_pTX>h_pTX</a>.
497</html>"));
498   algorithm 
499     h := SingleGasNasa.h_Tlow(data=steam, T=T, refChoice=3, h_off=46479.819+2501014.5)*X[Water]
500          + SingleGasNasa.h_Tlow(data=dryair, T=T, refChoice=3, h_off=25104.684)*(1.0-X[Water]);
501   end enthalpyOfGas;
502   
503   redeclare function extends enthalpyOfCondensingGas
504      "Return specific enthalpy of steam as a function of temperature T" 
505     annotation(Inline=false,smoothOrder=5,
506        Documentation(info="<html>
507Specific enthalpy of steam is computed from temperature.
508</html>"));
509   algorithm 
510     h := SingleGasNasa.h_Tlow(data=steam, T=T, refChoice=3, h_off=46479.819+2501014.5);
511   end enthalpyOfCondensingGas;
512   
513  function enthalpyOfWater
514      "Computes specific enthalpy of water (solid/liquid) near atmospheric pressure from temperature T" 
515    input SIunits.Temperature T "Temperature";
516    output SIunits.SpecificEnthalpy h "Specific enthalpy of water";
517  annotation (derivative=enthalpyOfWater_der, Documentation(info="<html>
518Specific enthalpy of water (liquid and solid) is computed from temperature using constant properties as follows:<br>
519<ul>
520<li>  heat capacity of liquid water:4200 J/kg
521<li>  heat capacity of solid water: 2050 J/kg
522<li>  enthalpy of fusion (liquid=>solid): 333000 J/kg
523</ul>
524Pressure is assumed to be around 1 bar. This function is usually used to determine the specific enthalpy of the liquid or solid fraction of moist air.
525</html>"));
526  algorithm 
527  /*simple model assuming constant properties:
528  heat capacity of liquid water:4200 J/kg
529  heat capacity of solid water: 2050 J/kg
530  enthalpy of fusion (liquid=>solid): 333000 J/kg*/
531     
532    h:=Utilities.spliceFunction(4200*(T-273.15),2050*(T-273.15)-333000,T-273.16,0.1);
533  end enthalpyOfWater;
534   
535  function enthalpyOfWater_der "Derivative function of enthalpyOfWater" 
536    input SIunits.Temperature T "Temperature";
537    input Real dT(unit="K/s") "Time derivative of temperature";
538    output Real dh(unit="J/(kg.s)") "Time derivative of specific enthalpy";
539  algorithm 
540  /*simple model assuming constant properties:
541  heat capacity of liquid water:4200 J/kg
542  heat capacity of solid water: 2050 J/kg
543  enthalpy of fusion (liquid=>solid): 333000 J/kg*/
544     
545    //h:=Utilities.spliceFunction(4200*(T-273.15),2050*(T-273.15)-333000,T-273.16,0.1);
546    dh:=Utilities.spliceFunction_der(4200*(T-273.15),2050*(T-273.15)-333000,T-273.16,0.1,4200*dT,2050*dT,dT,0);
547      annotation (Documentation(info="<html>
548Derivative function for <a href=Modelica:Modelica.Media.Air.MoistAir.enthalpyOfWater>enthalpyOfWater</a>.
549 
550</html>"));
551  end enthalpyOfWater_der;
552   
553   redeclare function extends pressure
554      "Returns pressure of ideal gas as a function of the thermodynamic state record" 
555   algorithm 
556    p := state.p;
557      annotation (Documentation(info="<html>
558Pressure is returned from the thermodynamic state record input as a simple assignment.
559</html>"));
560   end pressure;
561   
562   redeclare function extends temperature
563      "Return temperature of ideal gas as a function of the thermodynamic state record" 
564   algorithm 
565     T := state.T;
566      annotation (Documentation(info="<html>
567Temperature is returned from the thermodynamic state record input as a simple assignment.
568</html>"));
569   end temperature;
570   
571  function T_phX
572      "Return temperature as a function of pressure p, specific enthalpy h and composition X" 
573    input AbsolutePressure p "Pressure";
574    input SpecificEnthalpy h "Specific enthalpy";
575    input MassFraction[:] X "Mass fractions of composition";
576    output Temperature T "Temperature";
577     
578    protected 
579  package Internal
580        "Solve h(data,T) for T with given h (use only indirectly via temperature_phX)" 
581    extends Modelica.Media.Common.OneNonLinearEquation;
582    redeclare record extends f_nonlinear_Data
583          "Data to be passed to non-linear function" 
584      extends Modelica.Media.IdealGases.Common.DataRecord;
585    end f_nonlinear_Data;
586       
587    redeclare function extends f_nonlinear
588    algorithm 
589        y := h_pTX(p,x,X);
590    end f_nonlinear;
591       
592    // Dummy definition has to be added for current Dymola
593    redeclare function extends solve
594    end solve;
595  end Internal;
596     
597  algorithm 
598    T := Internal.solve(h, 200, 6000, p, X[1:nXi], steam);
599      annotation (Documentation(info="<html>
600Temperature is computed from pressure, specific enthalpy and composition via numerical inversion of function <a href=Modelica:Modelica.Media.Air.MoistAir.h_pTX>h_pTX</a>.
601</html>"));
602  end T_phX;
603   
604   redeclare function extends density
605      "Returns density of ideal gas as a function of the thermodynamic state record" 
606   algorithm 
607     d := state.p/(gasConstant(state)*state.T);
608      annotation (Documentation(info="<html>
609Density is computed from pressure, temperature and composition in the thermodynamic state record applying the ideal gas law.
610</html>"));
611   end density;
612   
613  redeclare function extends specificEnthalpy
614      "Return specific enthalpy of moist air as a function of the thermodynamic state record" 
615  algorithm 
616    h := h_pTX(state.p, state.T, state.X);
617      annotation (Documentation(info="<html>
618Specific enthalpy of moist air is computed from the thermodynamic state record. The fog region is included for both, ice and liquid fog.
619</html>"));
620  end specificEnthalpy;
621   
622  function h_pTX
623      "Return specific enthalpy of moist air as a function of pressure p, temperature T and composition X" 
624    extends Modelica.Icons.Function;
625    input SI.Pressure p "Pressure";
626    input SI.Temperature T "Temperature";
627    input SI.MassFraction X[:] "Mass fractions of moist air";
628    output SI.SpecificEnthalpy h "Specific enthalpy at p, T, X";
629    annotation(Inline=false,smoothOrder=1,
630        Documentation(derivative=h_pTX_der,info="<html>
631Specific enthalpy of moist air is computed from pressure, temperature and composition with X[1] as the total water mass fraction. The fog region is included for both, ice and liquid fog.
632</html>"));
633    protected 
634    SI.AbsolutePressure p_steam_sat "Partial saturation pressure of steam";
635    SI.MassFraction X_sat "Absolute humidity per unit mass of moist air";
636    SI.MassFraction X_liquid "ma