Changeset 498

Show
Ignore:
Timestamp:
04/20/2007 01:57:03 PM (21 months ago)
Author:
kproelss
Message:

added documentation to moist air model and example that produces psychrometric data, also simplified some water property functions in the moist air model

Location:
Modelica/trunk/Modelica
Files:
3 added
1 modified

Legend:

Unmodified
Added
Removed
  • Modelica/trunk/Modelica/Media/Air.mo

    r496 r498  
    33  package SimpleAir "Air: Simple dry air model (0..100 degC)"  
    44     
    5     extends Interfaces.PartialSimpleIdealGasMedium 
    6       (mediumName="SimpleAir", 
     5    extends Interfaces.PartialSimpleIdealGasMedium( 
     6       mediumName="SimpleAir", 
    77       cp_const=1005.45, 
    88       MM_const=0.0289651159, 
     
    1717    import Modelica.Constants; 
    1818     
    19     constant FluidConstants[nS] fluidConstants = 
     19    constant FluidConstants[nS] fluidConstants= 
    2020      FluidConstants(iupacName={"simple air"}, 
    2121                     casRegistryNumber={"not a real substance"}, 
    2222                     chemicalFormula={"N2, O2"}, 
    2323                     structureFormula={"N2, O2"}, 
    24                      molarMass=Modelica.Media.IdealGases.Common.SingleGasesData.N2.MM) "constant data for the fluid"; 
    25          
     24                     molarMass=Modelica.Media.IdealGases.Common.SingleGasesData.N2.MM)  
     25      "constant data for the fluid"; 
     26     
    2627    annotation (Documentation(info="<html> 
    27                               <h2>Simple Ideal gas air model for low temperatures<h1> 
     28                              <h2>Simple Ideal gas air model for low temperatures</h2> 
    2829                              <p>This model demonstrats how to use the PartialSimpleIdealGas base class to build a 
    2930                              simple ideal gas model with a limited temperature validity range.</p> 
     
    5960  end DryAirNasa; 
    6061   
    61   package MoistAir "Air: Moist air model (fog but no ice, 0..150 degC)"  
     62  package MoistAir "Air: Moist air model"  
    6263    extends Interfaces.PartialCondensingGases( 
    6364       mediumName="Moist air", 
     
    107108      MassFraction X_steam "mass fraction of steam water"; 
    108109      MassFraction X_air "mass fraction of air"; 
    109       MassFraction X_sat 
     110      MassFraction X_sat  
    110111        "steam water mass fraction of saturation boundary in kg_water/kg_moistair"; 
    111       MassFraction x_sat 
     112      MassFraction x_sat  
    112113        "steam water mass content of saturation boundary in kg_water/kg_dryair"; 
    113114      AbsolutePressure p_steam_sat "Partial saturation pressure of steam"; 
     
    120121       
    121122      p_steam_sat = min(saturationPressure(T),0.999*p); 
    122       X_sat = min(p_steam_sat * k_mair/max(100*Constants.eps, p - p_steam_sat)*(1 - Xi[Water]), 1.0) 
    123                         "Water content at saturation with respect to actual water content"; 
    124       X_liquid = max(Xi[Water] - X_sat, 0.0);  
     123      X_sat = min(p_steam_sat * k_mair/max(100*Constants.eps, p - p_steam_sat)*(1 - Xi[Water]), 1.0)  
     124        "Water content at saturation with respect to actual water content"; 
     125      X_liquid = max(Xi[Water] - X_sat, 0.0); 
    125126      X_steam  = Xi[Water]-X_liquid; 
    126127      X_air    = 1-Xi[Water]; 
     
    138139      state.X = X; 
    139140       
    140       // this x_steam is water load / dry air!!!!!!!!!!! 
     141      // these x are per unit mass of DRY air! 
    141142      x_sat    = k_mair*p_steam_sat/max(100*Constants.eps,p - p_steam_sat); 
    142143      x_water = Xi[Water]/max(X_air,100*Constants.eps); 
    143144      phi = p/p_steam_sat*Xi[Water]/(Xi[Water] + k_mair*X_air); 
    144145    end BaseProperties; 
    145  
    146     function Xsaturation "steam water mass fraction of saturation boundary in kg_water/kg_moistair" 
     146     
     147    function Xsaturation  
     148      "Steam water mass fraction of saturation boundary in kg_water/kg_moistair"  
    147149      input ThermodynamicState state "shermodynamic state"; 
    148150      output MassFraction X_sat "steam mass fraction of sat. boundary"; 
    149       protected 
    150     algorithm 
     151    algorithm  
    151152      X_sat := k_mair/(state.p/min(saturationPressure(state.T),0.999*state.p) - 1 + k_mair); 
    152153    end Xsaturation; 
    153154     
    154     function massFraction_pTphi "compute the steam mass fraction from relative humidity and T" 
     155    function massFraction_pTphi  
     156      "Compute the steam mass fraction from relative humidity and T"  
    155157      input AbsolutePressure p "Pressure"; 
    156158      input Temperature T "Temperature"; 
    157159      input Real phi "relative humidity (0 ... 1.0)"; 
    158160      output MassFraction X_steam "steam Mass fractions"; 
    159     protected 
     161    protected  
    160162      constant Real k = 0.621964713077499 "ratio of molar masses"; 
    161163      AbsolutePressure psat = saturationPressure(T) "saturation pressure"; 
    162     algorithm 
     164    algorithm  
    163165      X_steam := phi*k/(k*phi+p/psat-phi); 
    164166    end massFraction_pTphi; 
    165167     
    166     redeclare function setState_pTX "Return thermodynamic state as function of p, T and composition X"  
     168    redeclare function setState_pTX  
     169      "Return thermodynamic state as function of p, T and composition X"  
    167170      extends Modelica.Icons.Function; 
    168171      input AbsolutePressure p "Pressure"; 
     
    170173      input MassFraction X[:]=reference_X "Mass fractions"; 
    171174      output ThermodynamicState state; 
    172     algorithm 
    173       state := if size(X,1) == nX then ThermodynamicState(p=p,T=T, X=X) 
    174         else ThermodynamicState(p=p,T=T, X=cat(1,X,{1-sum(X)})); 
     175    algorithm  
     176      state := if size(X,1) == nX then ThermodynamicState(p=p,T=T, X=X) else  
     177            ThermodynamicState(p=p,T=T, X=cat(1,X,{1-sum(X)})); 
    175178    end setState_pTX; 
    176179     
    177     redeclare function setState_phX "Return thermodynamic state as function of p, h and composition X"  
     180    redeclare function setState_phX  
     181      "Return thermodynamic state as function of p, h and composition X"  
    178182      extends Modelica.Icons.Function; 
    179183      input AbsolutePressure p "Pressure"; 
     
    181185      input MassFraction X[:]=reference_X "Mass fractions"; 
    182186      output ThermodynamicState state; 
    183     algorithm 
    184       state := if size(X,1) == nX then ThermodynamicState(p=p,T=T_phX(p,h,X),X=X) 
    185         else ThermodynamicState(p=p,T=T_phX(p,h,X), X=cat(1,X,{1-sum(X)})); 
     187    algorithm  
     188      state := if size(X,1) == nX then ThermodynamicState(p=p,T=T_phX(p,h,X),X=X) else  
     189            ThermodynamicState(p=p,T=T_phX(p,h,X), X=cat(1,X,{1-sum(X)})); 
    186190    end setState_phX; 
    187 /*     
     191    /*     
    188192    redeclare function setState_psX "Return thermodynamic state as function of p, s and composition X"  
    189193      extends Modelica.Icons.Function; 
     
    196200        else ThermodynamicState(p=p,T=T_psX(p,s,X), X=cat(1,X,{1-sum(X)}));         
    197201    end setState_psX; 
    198 */     
    199     redeclare function setState_dTX "Return thermodynamic state as function of d, T and composition X"  
     202*/ 
     203    redeclare function setState_dTX  
     204      "Return thermodynamic state as function of d, T and composition X"  
    200205      extends Modelica.Icons.Function; 
    201206      input Density d "density"; 
     
    203208      input MassFraction X[:]=reference_X "Mass fractions"; 
    204209      output ThermodynamicState state; 
    205     algorithm 
    206       state := if size(X,1) == nX then ThermodynamicState(p=d*({steam.R,dryair.R}*X)*T,T=T,X=X) 
    207         else ThermodynamicState(p=d*({steam.R,dryair.R}*cat(1,X,{1-sum(X)}))*T,T=T, X=cat(1,X,{1-sum(X)})); 
     210    algorithm  
     211      state := if size(X,1) == nX then ThermodynamicState(p=d*({steam.R,dryair.R}*X)*T,T=T,X=X) else  
     212            ThermodynamicState(p=d*({steam.R,dryair.R}*cat(1,X,{1-sum(X)}))*T,T=T, X=cat(1,X,{1-sum(X)})); 
    208213    end setState_dTX; 
    209        
    210     redeclare function extends gasConstant "gas constnat: computation neglects liquid fraction" 
     214     
     215    redeclare function extends gasConstant  
     216      "Gas constnat: computation neglects liquid fraction"  
    211217    algorithm  
    212218      R := dryair.R*(1-state.X[Water]) + steam.R*state.X[Water]; 
     
    214220     
    215221    function saturationPressureLiquid  
    216       "saturation curve valid for 273.16 <= T <= 373.16. Outside of these limits a (less accurate) result is returned"  
     222      "Saturation curve valid for 273.16 <= T <= 373.16. Outside of these limits a (less accurate) result is returned"  
    217223      extends Modelica.Icons.Function; 
    218224      input SI.Temperature Tsat "saturation temperature"; 
     
    224230     
    225231    function sublimationPressureIce  
    226       "saturation curve valid for 223.16 <= T <= 273.16. Outside of these limits a (less accurate) result is returned"  
     232      "Saturation curve valid for 223.16 <= T <= 273.16. Outside of these limits a (less accurate) result is returned"  
    227233      extends Modelica.Icons.Function; 
    228234      input SI.Temperature Tsat "sublimation temperature"; 
     
    234240     
    235241    redeclare function extends saturationPressure  
    236       "saturation curve valid for 223.16 <= T <= 373.16 (and slightly outside with less accuracy)"  
     242      "Saturation curve valid for 223.16 <= T <= 373.16 (and slightly outside with less accuracy)"  
    237243       
    238244      annotation(Inline=false,smoothOrder=5); 
     
    241247    end saturationPressure; 
    242248     
     249    function saturationTemperature  
     250      "Computes saturation temperature from (partial) pressure via numerical inversion of the function 'saturationPressure'"  
     251      input SI.Pressure p "pressure"; 
     252      input SI.Temperature T_min=200 "lower boundary of solution"; 
     253      input SI.Temperature T_max=400 "upper boundary of solution"; 
     254      output SI.Temperature T "temperature"; 
     255       
     256    protected  
     257    package Internal  
     258       extends Modelica.Media.Common.OneNonLinearEquation; 
     259         
     260     redeclare record extends f_nonlinear_Data  
     261       // Define data to be passed to user function 
     262     end f_nonlinear_Data; 
     263         
     264     redeclare function extends f_nonlinear  
     265     algorithm  
     266        y:=saturationPressure(x); 
     267      // Compute the non-linear equation: y = f(x, Data) 
     268     end f_nonlinear; 
     269         
     270     // Dummy definition  
     271     redeclare function extends solve  
     272     end solve; 
     273    end Internal; 
     274    algorithm  
     275      T:=Internal.solve(p, T_min, T_max); 
     276    end saturationTemperature; 
     277     
    243278   redeclare function extends enthalpyOfVaporization  
    244       "enthalpy of vaporization of water"  
    245    algorithm  
    246     r0 := 1e3*(2501.0145 - (T - 273.15)*(2.3853 + (T - 273.15)*(0.002969 - (T 
    247          - 273.15)*(7.5293e-5 + (T - 273.15)*4.6084e-7)))); 
     279      "Enthalpy of vaporization of water, 0 - 130 degC"  
     280   algorithm  
     281    /*r0 := 1e3*(2501.0145 - (T - 273.15)*(2.3853 + (T - 273.15)*(0.002969 - (T 
     282      - 273.15)*(7.5293e-5 + (T - 273.15)*4.6084e-7))));*/ 
     283   //katrin: replaced by linear correlation, simpler and more accurate in the entire region 
     284   //source VDI-Waermeatlas, linear inter- and extrapolation between values for 0.01°C and 40°C. 
     285   r0:=(2405900-2500500)/(40-0)*(T-273.16)+2500500; 
    248286   end enthalpyOfVaporization; 
    249287     
    250288    function HeatCapacityOfWater  
    251       "specific heat capacity of water (liquid only)"  
     289      "Specific heat capacity of water (liquid only)"  
    252290      extends Modelica.Icons.Function; 
    253291      input Temperature T; 
     
    261299     
    262300   redeclare function extends enthalpyOfLiquid  
     301      "Computes enthalpy of liquid water from temperature (use enthalpyOfWater instead"  
    263302       
    264303     annotation(Inline=false,smoothOrder=5); 
     
    269308     
    270309   redeclare function extends enthalpyOfGas  
     310      "Computes specific enthalpy of gas (air and steam) from temperature and composition"  
    271311       
    272312     annotation(Inline=false,smoothOrder=5); 
     
    277317     
    278318   redeclare function extends enthalpyOfCondensingGas  
     319      "Computes specific enthalpy of steam from temperature"  
    279320     annotation(Inline=false,smoothOrder=5); 
    280321   algorithm  
     
    282323   end enthalpyOfCondensingGas; 
    283324     
    284    redeclare function extends pressure "return pressure of ideal gas"  
     325  function enthalpyOfWater  
     326      "Computes specific enthalpy of water (solid/liquid) near atmospheric pressure from temperature"  
     327    input SIunits.Temperature T; 
     328    output SIunits.SpecificEnthalpy h; 
     329  annotation (derivative=enthalpyOfWater_der); 
     330  algorithm  
     331  /*simple model assuming constant properties: 
     332  heat capacity of liquid water:4200 J/kg 
     333  heat capacity of solid water: 2050 J/kg 
     334  enthalpy of fusion (liquid=>solid): 333000 J/kg*/ 
     335       
     336    h:=Utilities.spliceFunction(4200*(T-273.15),2050*(T-273.15)-333000,T-273.16,0.1); 
     337  end enthalpyOfWater; 
     338     
     339   redeclare function extends pressure "Returns pressure of ideal gas"  
    285340   algorithm  
    286341    p := state.p; 
    287342   end pressure; 
    288  
    289    redeclare function extends temperature "return temperature of ideal gas"  
     343     
     344   redeclare function extends temperature "Return temperature of ideal gas"  
    290345   algorithm  
    291346     T := state.T; 
    292347   end temperature; 
    293  
    294    redeclare function extends density "return density of ideal gas"  
     348     
     349   redeclare function extends density "Returns density of ideal gas"  
    295350   algorithm  
    296351     d := state.p/(gasConstant(state)*state.T); 
    297352   end density; 
    298  
    299    redeclare function extends specificEntropy 
    300      "return specific entropy (liquid part neglected, mixing entropy included)"  
     353     
     354   redeclare function extends specificEntropy  
     355      "Return specific entropy (liquid part neglected, mixing entropy included)"  
    301356       annotation(Inline=false,smoothOrder=5); 
    302    protected 
    303      MoleFraction[2] Y = massToMoleFractions(state.X,{steam.MM,dryair.MM}) "molar fraction"; 
    304    algorithm 
     357    protected  
     358     MoleFraction[2] Y = massToMoleFractions(state.X,{steam.MM,dryair.MM})  
     359        "molar fraction"; 
     360   algorithm  
    305361     s := SingleGasNasa.s0_Tlow(dryair, state.T)*(1-state.X[Water]) 
    306362       + SingleGasNasa.s0_Tlow(steam, state.T)*state.X[Water] 
     
    309365                   Y[i] for i in 1:size(Y,1)); 
    310366   end specificEntropy; 
    311     
     367     
    312368   redeclare function extends specificHeatCapacityCp  
    313       "Return specific heat capacity at constant pressure"  
     369      "Returns specific heat capacity at constant pressure"  
    314370     annotation(Inline=false,smoothOrder=5); 
    315   algorithm  
     371   algorithm  
    316372     cp:= SingleGasNasa.cp_Tlow(dryair, state.T)*(1-state.X[Water]) 
    317373       + SingleGasNasa.cp_Tlow(steam, state.T)*state.X[Water]; 
    318   end specificHeatCapacityCp; 
     374   end specificHeatCapacityCp; 
    319375     
    320376  redeclare function extends specificHeatCapacityCv  
    321       "Return specific heat capacity at constant volume"  
     377      "Returns specific heat capacity at constant volume"  
    322378     annotation(Inline=false,smoothOrder=5); 
    323379  algorithm  
     
    328384     
    329385  redeclare function extends dynamicViscosity  
    330       "simple polynomial for dry air (moisture influence small), valid from 73.15 K to 373.15 K"  
     386      "Simple polynomial for dry air (moisture influence small), valid from 73.15 K to 373.15 K"  
    331387      import Modelica.Media.Incompressible.TableBased.Polynomials_Temp; 
    332388  algorithm  
     
    336392     
    337393  redeclare function extends thermalConductivity  
    338       "simple polynomial for dry air (moisture influence small), valid from 73.15 K to 373.15 K"  
     394      "Simple polynomial for dry air (moisture influence small), valid from 73.15 K to 373.15 K"  
    339395      import Modelica.Media.Incompressible.TableBased.Polynomials_Temp; 
    340396  algorithm  
     
    344400     
    345401  function h_pTX  
    346     "Compute specific enthalpy from pressure, temperature and mass fraction"  
     402      "Compute specific enthalpy from pressure, temperature and mass fraction"  
    347403    extends Modelica.Icons.Function; 
    348404    input SI.Pressure p "Pressure"; 
     
    351407    output SI.SpecificEnthalpy h "Specific enthalpy at p, T, X"; 
    352408    annotation(Inline=false,smoothOrder=1); 
    353   protected  
     409    protected  
    354410    SI.AbsolutePressure p_steam_sat "Partial saturation pressure of steam"; 
    355411    SI.MassFraction x_sat "steam water mass fraction of saturation boundary"; 
     
    363419    X_steam  :=X[Water] - X_liquid; 
    364420    X_air    :=1 - X[Water]; 
    365     h        := {SingleGasNasa.h_Tlow(data=steam,  T=T, refChoice=3, h_off=46479.819+2501014.5), 
     421   /* h        := {SingleGasNasa.h_Tlow(data=steam,  T=T, refChoice=3, h_off=46479.819+2501014.5), 
     422               SingleGasNasa.h_Tlow(data=dryair, T=T, refChoice=3, h_off=25104.684)}* 
     423    {X_steam, X_air} + enthalpyOfLiquid(T)*X_liquid;*/ 
     424     h        := {SingleGasNasa.h_Tlow(data=steam,  T=T, refChoice=3, h_off=46479.819+2501014.5), 
    366425                 SingleGasNasa.h_Tlow(data=dryair, T=T, refChoice=3, h_off=25104.684)}* 
    367       {X_steam, X_air} + enthalpyOfLiquid(T)*X_liquid; 
     426      {X_steam, X_air} + enthalpyOfWater(T)*X_liquid; 
    368427  end h_pTX; 
    369428     
    370   redeclare function extends specificEnthalpy 
    371       "specific enthalpy" 
    372   algorithm 
    373     h := h_pTX(state.p, state.T, state.X);   
     429  redeclare function extends specificEnthalpy "specific enthalpy"  
     430  algorithm  
     431    h := h_pTX(state.p, state.T, state.X); 
    374432  end specificEnthalpy; 
    375433     
    376   redeclare function extends specificInternalEnergy "Return specific internal energy"  
     434  redeclare function extends specificInternalEnergy  
     435      "Return specific internal energy"  
    377436    extends Modelica.Icons.Function; 
    378437  algorithm  
    379438    u := h_pTX(state.p,state.T,state.X) - gasConstant(state)*state.T; 
    380439  end specificInternalEnergy; 
    381    
     440     
    382441  redeclare function extends specificGibbsEnergy "Return specific Gibbs energy"  
    383442    extends Modelica.Icons.Function; 
     
    385444    g := h_pTX(state.p,state.T,state.X) - state.T*specificEntropy(state); 
    386445  end specificGibbsEnergy; 
    387    
    388   redeclare function extends specificHelmholtzEnergy "Return specific Helmholtz energy"  
     446     
     447  redeclare function extends specificHelmholtzEnergy  
     448      "Return specific Helmholtz energy"  
    389449    extends Modelica.Icons.Function; 
    390450  algorithm  
    391451    f := h_pTX(state.p,state.T,state.X) - gasConstant(state)*state.T - state.T*specificEntropy(state); 
    392452  end specificHelmholtzEnergy; 
    393    
    394   function T_phX  
    395     "Compute temperature from specific enthalpy and mass fraction"  
     453     
     454  function T_phX "Compute temperature from specific enthalpy and mass fraction"  
    396455    input AbsolutePressure p "Pressure"; 
    397456    input SpecificEnthalpy h "specific enthalpy"; 
    398457    input MassFraction[:] X "mass fractions of composition"; 
    399458    output Temperature T "temperature"; 
    400   protected  
     459       
     460    protected  
    401461  package Internal  
    402       "Solve h(data,T) for T with given h (use only indirectly via temperature_phX)"  
     462        "Solve h(data,T) for T with given h (use only indirectly via temperature_phX)"  
    403463    extends Modelica.Media.Common.OneNonLinearEquation; 
    404464    redeclare record extends f_nonlinear_Data  
    405         "Data to be passed to non-linear function"  
     465          "Data to be passed to non-linear function"  
    406466      extends Modelica.Media.IdealGases.Common.DataRecord; 
    407467    end f_nonlinear_Data; 
    408        
     468         
    409469    redeclare function extends f_nonlinear  
    410470    algorithm  
    411471        y := h_pTX(p,x,X); 
    412472    end f_nonlinear; 
    413        
     473         
    414474    // Dummy definition has to be added for current Dymola 
    415475    redeclare function extends solve  
    416476    end solve; 
    417477  end Internal; 
    418      
     478       
    419479  algorithm  
    420480    T := Internal.solve(h, 200, 6000, p, X[1:nXi], steam); 
    421481  end T_phX; 
    422        
     482     
     483  function enthalpyOfWater_der  
     484      "Computes specific enthalpy of water (solid/liquid) near atmospheric pressure from temperature"  
     485    input SIunits.Temperature T; 
     486    input SIunits.Temperature dT; 
     487    output SIunits.SpecificEnthalpy dh; 
     488  algorithm  
     489  /*simple model assuming constant properties: 
     490  heat capacity of liquid water:4200 J/kg 
     491  heat capacity of solid water: 2050 J/kg 
     492  enthalpy of fusion (liquid=>solid): 333000 J/kg*/ 
     493       
     494    //h:=Utilities.spliceFunction(4200*(T-273.15),2050*(T-273.15)-333000,T-273.16,0.1); 
     495    dh:=Utilities.spliceFunction_der(4200*(T-273.15),2050*(T-273.15)-333000,T-273.16,0.1,4200*dT,2050*dT,dT,0); 
     496  end enthalpyOfWater_der; 
     497 
    423498    package Utilities "utility functions"  
    424499      function spliceFunction  
     
    483558     
    484559    annotation (Documentation(info="<html> 
     560  <h3><font color=\"#008000\" size=5>Moist Air Medium Package</font></h3> 
     561<h4><font color=\"#008000\" size=4>Thermodynamic Model</font></h4> 
     562<p>This package provides a full thermodynamic model of moist air including the fog region and temperatures below zero degC. 
     563The governing assumptions in this model are:</p> 
     564<ul> 
     565<li>the perfect gas law applies</li> 
     566<li>water volume other than that of steam is neglected</li></ul> 
     567<p>All extensive properties are expressed in terms of the total mass in order to comply with other media in this libary. However, it is rather common to express the absolute humidity in terms of mass of dry air only, which has advantages when working with charts. Therefore two absolute humidities are computed in the <b>BaseProperties</b> model: <b>X</b> denotes the absolute humidity in terms of the total mass while <b>x</b> denotes the absolute humitity per unit mass of dry air. In addition, the relative humidity <b>phi</b> is also computed.</p> 
     568<p>At the triple point temperature of water of 0.01°C or 273.16 K and a relative humidity greater than 1 fog may be present as liquid and as ice resulting in a specific enthalpy somewhere between those of the two isotherms for solid and liquid fog, respectively. For numerical reasons in this model a coexisting mixture of 50% solid and 50% liquid fog is assumed in the fog region at the triple point. 
     569 
     570<h4><font color=\"#008000\" size=4>Range of validity</font></h4> 
     571<p>From the assumptions mentioned above it follows that the <b>pressure</b> should be in the region around <b>atmospheric</b> conditions or below (a few bars may still be fine though). Additionally a very high water content at low temperatures would yield incorrect densities, because the volume of the liquid or solid phase would not be negligible anymore. The model does not provide any information on limits for water drop size in the fog region or transport information for the actual condensation or evaporation process in combination with surfaces. All excess water which is not in its vapour state is assumed to be still present in the air regarding its energy but not in terms of its spatial extent.<br><br> 
     572The thermodynamic model may be used for <b>temperatures</b> ranging from <b>240 - 400 K</b>. This holds for all functions unless otherwise stated in their description. However, although the model works at temperatures above the saturation temperature it is questionable to use the term \"relative humidity\" in this region.</p> 
     573 
     574<h4><font color=\"#008000\" size=4>Transport Properties</font></h4> 
     575<p>Several additional functions that are not needed to describe the thermodynamic system, but are required to model transport processes, like heat and mass transfer, may be called. They usually neglect the moisture influence unless otherwise stated.</p> 
    485576   
     577<h4><font color=\"#008000\" size=4>Application</font></h4> 
     578<p>The model's main area of application is all processes that involve moist air cooling under near atmospheric pressure with possible moisture condensation. This is the case in all domestic and industrial air conditioning applications. Another large domain of moist air applications covers all processes that deal with the dehydration of bulk material using air as the transport medium. Engineering tasks involving moist air are often performed (or at least visualized) by using charts that contain all relevant thermodynamic data for a moist air system. These so called psychrometric charts can be generated from the medium properties in this package. The model <a href=\"Modelica://Modelica.Media.Air.MoistAir.PsychrometricData\">PsychrometricData</a> may be used for this purpose in order to obtain data for figures like those below (the plotting itself is not part of the model though).</p> 
     579 
     580<p><img src=\"../../Modelica/Images/Media/Air/Mollier.png\"> 
     581<img src=\"../../Modelica/Images/Media/Air/PsycroChart.png\"></p> 
     582<p> 
     583<b>Legend:</b> blue - constant specific enthalpy, red - constant temperature, black - constant relative humidity</p> 
     584 
    486585</html>")); 
     586    model PsychrometricData "produces plot data for psychrometric charts"  
     587      extends Modelica.Icons.Example; 
     588      package Medium = Modelica.Media.Air.MoistAir; 
     589      parameter SIunits.Pressure p_const=1e5 "pressure"; 
     590      parameter Integer n_T=11 "number of isotherms"; 
     591      parameter SIunits.Temperature T_min=253.15 "lowest isotherm"; 
     592      parameter SIunits.Temperature T_step=10  
     593        "temperature step between two isotherms"; 
     594      parameter Integer n_h=16  
     595        "number of lines with constant specific enthalpy"; 
     596      parameter SIunits.SpecificEnthalpy h_min=-20e3  
     597        "lowest line of constant enthalpy"; 
     598      parameter SIunits.SpecificEnthalpy h_step=1e4  
     599        "enthalpy step between two lines of constant enthalpy"; 
     600      parameter Integer n_phi=10  
     601        "number of lines with constant relative humidity"; 
     602      parameter Real phi_min=0.1 "lowest line of constant humidity"; 
     603      parameter Real phi_step=0.1 "step between two lines of constant humidity"; 
     604      parameter SIunits.MassFraction x_min=0.00  
     605        "minimum diagram absolute humidity"; 
     606      parameter SIunits.MassFraction x_max=0.03  
     607        "maximum diagram absolute humidity"; 
     608      parameter SIunits.Time t=1 "simulation time"; 
     609       
     610      final parameter SIunits.Temperature[n_T] T_const={T_min - T_step + i*T_step for i in  
     611              1:n_T}; 
     612      final parameter SIunits.SpecificEnthalpy[n_h] h_const={(i-1)*h_step+h_min for i in 1:n_h}; 
     613      final parameter Real[n_phi] phi_const={(i-1)*phi_step+phi_min for i in 1:n_phi}; 
     614      final parameter Real diagSlope=Medium.enthalpyOfVaporization(273.15)  
     615        "rotation of diagram that zero degrees isotherm becomes horizontal outside the fog region"; 
     616      final parameter SIunits.MassFraction x_start=x_min  
     617        "initial absolute humidity in kg water/kg dry air"; 
     618       
     619      SIunits.MassFraction x(start=x_start)  
     620        "absolute humidity in kg water/kg dry air"; 
     621      SIunits.SpecificEnthalpy[n_T] hx_T "h_1+x for const T"; 
     622      SIunits.SpecificEnthalpy[n_h] hx_h(start=h_const) "const h_1+x"; 
     623      SIunits.SpecificEnthalpy[n_phi] hx_phi "h_1+x for const phi"; 
     624      SIunits.SpecificEnthalpy[n_T] y_T "chart enthalpy for const T"; 
     625      SIunits.SpecificEnthalpy[n_h] y_h "chart enthalpy for const h"; 
     626      SIunits.SpecificEnthalpy[n_phi] y_phi "chart enthalpy for const phi"; 
     627      Medium.BaseProperties[n_T] medium_T "medium properties for const T"; 
     628      Medium.BaseProperties[n_phi] medium_phi "medium properties for const phi"; 
     629       
     630    protected  
     631      SIunits.Pressure[n_phi] ps_phi  
     632        "saturation pressure for constant-phi-lines"; 
     633      SIunits.Temperature[n_phi] T_phi(each start=290); 
     634      Boolean[n_T] fog(start=fill(false, n_T))  
     635        "triggers events at intersection of isotherms with phi=1"; 
     636      SIunits.Pressure[n_T] pd "steam partial pressure along isotherms"; 
     637    initial equation  
     638      x = x_min; 
     639    equation  
     640       
     641      der(x) = (x_max - x_min)/t; 
     642       
     643      for i in 1:n_T loop 
     644        medium_T[i].T=T_const[i]; 
     645        medium_T[i].p=p_const; 
     646        medium_T[i].Xi = {x/(1 + x)}; 
     647        hx_T[i] = medium_T[i].h*(medium_T[i].x_water + 1); 
     648        y_T[i] = hx_T[i] - diagSlope*x; 
     649         
     650        //trigger events 
     651        pd[i] = medium_T[i].Xi[1]*medium_T[i].MM/medium_T[i].MMX[1]*p_const; 
     652        fog[i] = pd[i] >= Medium.saturationPressure(T_const[i]); 
     653      end for; 
     654      for i in 1:n_h loop 
     655        der(hx_h[i]) = 0.0; 
     656        y_h[i] = hx_h[i] - diagSlope*x; 
     657      end for; 
     658      for i in 1:n_phi loop 
     659        medium_phi[i].p=p_const; 
     660        ps_phi[i] = p_const*x/phi_const[i]/(Medium.k_mair + x); 
     661        T_phi[i] = if x < 5e-6 then 200 else Medium.saturationTemperature( 
     662          ps_phi[i]); 
     663        medium_phi[i].T = T_phi[i]; 
     664        medium_phi[i].Xi = {x/(1 + x)}; 
     665        hx_phi[i] = medium_phi[i].h*(medium_phi[i].x_water + 1); 
     666        y_phi[i] = hx_phi[i] - diagSlope*x; 
     667      end for; 
     668        
     669      annotation (experiment(StopTime=1), Documentation(info="<html> 
     670<p>This model produces psychrometric data from the moist air model in this library to be plotted in charts. The two most common chart varieties are the Mollier Diagram and the Psycrometric Chart. The first is widely used in some European countries while the second is more common in the Anglo-American world. Specific enthalpy is plotted over absolute humidity in the Mollier Diagram, it is the other way round in the Psychrometric Chart.<br> 
     671It must be noted that the relationship of both axis variables is not right-angled, the absolute humidity follows a slope which equals the enthalpy of vaporization at 0°C. For better reading and in oder to reduce the fog region the humidity axis is rotated to obtain a right-angled plot. Both charts usually contain additional information as isochores or auxiliary scales for e.g. heat ratios. Those information are omitted in this model and the charts below. Other important features of psychrometric chart data are that all mass specific variables (like absolute humidity, specific enthalpy etc.) are expressed in terms of kg dry air and that their baseline of 0 enthalpy is found at 0°C and zero humidity. </p> 
     672 
     673<p><img src=\"../../Modelica/Images/Media/Air/Mollier.png\"> 
     674<img src=\"../../Modelica/Images/Media/Air/PsycroChart.png\"></p> 
     675<p> 
     676<b>Legend:</b> blue - constant specific enthalpy, red - constant temperature, black - constant relative humidity</p> 
     677 
     678<p>The model provides data for lines of constant specific enthalpy, temperature and relative humidity in a Mollier Diagram or Psychrometric Chart as they were used for the figures above. For limitations and ranges of validity please refer to the MoistAir package description. Absolute humidity <b>x</b> is increased with time in this model. The specific enthalpies adjusted for plotting are then obtained from:</p> 
     679<ul> 
     680<li><b>y_h</b>: constant specific enthalpy</li> 
     681<li><b>y_T</b>: constant temperature</li> 
     682<li><b>y_phi</b>: constant relative humidity</li> 
     683</ul> 
     684</html>")); 
     685    end PsychrometricData;