within Buildings.Media.Examples.BaseClasses;
partial model PartialProperties
  "Partial model that contains common parameters of the fluid properties"

  replaceable package Medium = Modelica.Media.Interfaces.PartialMedium;

  parameter Modelica.Units.SI.Temperature TMin
    "Minimum temperature for the simulation";
  parameter Modelica.Units.SI.Temperature TMax
    "Maximum temperature for the simulation";
  parameter Modelica.Units.SI.Pressure p=Medium.p_default "Pressure";
  parameter Modelica.Units.SI.MassFraction X[Medium.nX]=Medium.X_default
    "Mass fraction";
  parameter Real errAbs=1E-8 "Absolute error used in the check of the state calculations";
  Medium.Temperature T "Temperature";
  Modelica.Units.NonSI.Temperature_degC T_degC "Celsius temperature";

  Medium.ThermodynamicState state_pTX "Medium state";

  Modelica.Units.SI.Density d "Density";
  Modelica.Units.SI.DynamicViscosity eta "Dynamic viscosity";
  Modelica.Units.SI.SpecificEnthalpy h "Specific enthalpy";
  Modelica.Units.SI.SpecificInternalEnergy u "Specific internal energy";
  Modelica.Units.SI.SpecificEntropy s "Specific entropy";
  Modelica.Units.SI.SpecificEnergy g "Specific Gibbs energy";
  Modelica.Units.SI.SpecificEnergy f "Specific Helmholtz energy";

  Modelica.Units.SI.SpecificEnthalpy hIse "Isentropic enthalpy";

  Modelica.Media.Interfaces.Types.IsobaricExpansionCoefficient beta
    "Isobaric expansion coefficient";
  Modelica.Units.SI.IsothermalCompressibility kappa
    "Isothermal compressibility";

  Modelica.Units.SI.SpecificHeatCapacity cp "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cv "Specific heat capacity";
  Modelica.Units.SI.ThermalConductivity lambda "Thermal conductivity";

  Modelica.Units.SI.AbsolutePressure pMed "Pressure";
  Medium.Temperature TMed "Temperature";
  Modelica.Units.SI.MolarMass MM "Mixture molar mass";

  Medium.BaseProperties basPro "Medium base properties";
protected
  constant Real conv(unit="1/s") = 1 "Conversion factor to satisfy unit check";

  function checkState "This function checks the absolute error in the state calculations"
    extends Modelica.Icons.Function;
    input Medium.ThermodynamicState state1 "Medium state";
    input Medium.ThermodynamicState state2 "Medium state";
    input Real errAbs "Absolute error threshold";
    input String message "Message for error reporting";

  protected
              Real TErrAbs=abs(Medium.temperature(state1)-Medium.temperature(state2))
      "Absolute error in temperature";
  protected
              Real pErrAbs=abs(Medium.pressure(state1)-Medium.pressure(state2))
      "Absolute error in pressure";
  algorithm
    assert(TErrAbs < errAbs, "Absolute temperature error: " + String(TErrAbs) +
       " K. Error in temperature of " + message);
    assert(pErrAbs < errAbs, "Absolute pressure error: " + String(pErrAbs) +
       " Pa. Error in pressure of " + message);
  end checkState;

equation
    // Compute temperatures that are used as input to the functions
    T = TMin + conv*time * (TMax-TMin);
    T_degC =Modelica.Units.Conversions.to_degC(T);

    // Check the implementation of the functions
    d = Medium.density(state_pTX);
    eta = Medium.dynamicViscosity(state_pTX);
    h = Medium.specificEnthalpy(state_pTX);

    u = Medium.specificInternalEnergy(state_pTX);
    s = Medium.specificEntropy(state_pTX);
    g = Medium.specificGibbsEnergy(state_pTX);
    f = Medium.specificHelmholtzEnergy(state_pTX);
    hIse = Medium.isentropicEnthalpy(p, state_pTX);
    beta = Medium.isobaricExpansionCoefficient(state_pTX);
    kappa = Medium.isothermalCompressibility(state_pTX);

    cp = Medium.specificHeatCapacityCp(state_pTX);
    cv = Medium.specificHeatCapacityCv(state_pTX);
    lambda = Medium.thermalConductivity(state_pTX);
    pMed = Medium.pressure(state_pTX);
    assert(abs(p-pMed) < errAbs, "Error in pressure computation.");
    TMed = Medium.temperature(state_pTX);
    assert(abs(T-TMed) < errAbs, "Error in temperature computation.");
    MM = Medium.molarMass(state_pTX);
    // Check the implementation of the base properties
    assert(abs(h-basPro.h) < errAbs, "Error in enthalpy computation in BaseProperties.");
    assert(abs(u-basPro.u) < errAbs, "Error in internal energy computation in BaseProperties.");
end PartialProperties;


within Buildings.Media.Examples.BaseClasses;
partial model TestTemperatureEnthalpyInversion
  "Model to check computation of h(T) and its inverse with a controlleable tolerance"
   replaceable package Medium =
        Modelica.Media.Interfaces.PartialMedium;
  parameter Modelica.Units.SI.Temperature T0=273.15 + 20 "Temperature";
     parameter Real tol = 1E-8 "Numerical tolerance";
  Modelica.Units.SI.Temperature T "Temperature";
  Modelica.Units.SI.SpecificEnthalpy h "Enthalpy";
     Medium.MassFraction Xi[:] = Medium.reference_X "Mass fraction";
equation
    h = Medium.specificEnthalpy_pTX(p=101325, T=T0, X=Xi);
    T = Medium.temperature_phX(p=101325, h=h,  X=Xi);
    if (time>=0.1) then
    assert(abs(T-T0)<tol, "Error in implementation of functions.\n"
       + "   T0 = " + String(T0) + "\n"
       + "   T  = " + String(T) + "\n"
       + "   Absolute error: " + String(abs(T-T0)) + " K");
    end if;
end TestTemperatureEnthalpyInversion;


within Buildings.Media;
package Refrigerants "Package with functions for refrigerant properties"
  extends Modelica.Icons.Package;
end Refrigerants;


Refrigerant R410A

within Buildings.Media.Refrigerants;
package R410A "Refrigerant R410A"
  extends Modelica.Icons.VariantsPackage;

final constant Modelica.Units.SI.SpecificEntropy R=114.55
  "Gas constant for use in Martin-Hou equation of state";

final constant Modelica.Units.SI.Temperature TCri=345.25 "Critical temperature";

final constant Modelica.Units.SI.Temperature T_min=173.15
  "Minimum temperature for correlated properties";

final constant Modelica.Units.SI.AbsolutePressure pCri=4926.1e3
  "Critical pressure";

protected
  final constant Real A[:] = {-1.721781e2, 2.381558e-1, -4.329207e-4, -6.241072e-7}
    "Coefficients A for Martin-Hou equation of state";

  final constant Real B[:] = {1.646288e-1, -1.462803e-5, 0, 1.380469e-9}
    "Coefficients B for Martin-Hou equation of state";

  final constant Real C[:] = {-6.293665e3, 1.532461e1, 0, 1.604125e-4}
    "Coefficients C for Martin-Hou equation of state";

  final constant Real b = 4.355134e-4
    "Coefficient b for Martin-Hou equation of state";

  final constant Real k = 5.75
    "Coefficient K for Martin-Hou equation of state";

end R410A;


within Buildings.Media.Refrigerants;
package Validation "Collection of models that validate the implementation of the
  refrigerants"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Validation of the derivatives of the specific volume with regards to p and T. Validation case for evaluation of derivatives of the Martin-Hou equation of
state with regards to pressure and temperature.

within Buildings.Media.Refrigerants.Validation;
model R410A_dSpecificVolumeVap_pT
  "Validation of the derivatives of the specific volume with regards to p and T"
  extends Modelica.Icons.Example;

  parameter Modelica.Units.SI.AbsolutePressure p=400e3
    "Pressure of refrigerant vapor";

  parameter Modelica.Units.SI.Temperature T=273.15 "Temperature of refrigerant";

  parameter Real dp(final unit="Pa") = 1.0
    "Delta of pressure of refrigerant vapor";

  parameter Real dT(final unit="K") = 0.01
    "Delta of temperature of refrigerant";

  Real dvdp(
    final unit="m3/(kg.Pa)")
     "Derivative of specific volume with regards to pressure";

  Real dvdT(
    final unit="m3/(kg.K)")
     "Derivative of specific volume with regards to temperature";

  Real dvdp_num(
    final unit="m3/(kg.Pa)")
     "Numerical derivative ofspecific volume with regards to pressure";

  Real dvdT_num(
    final unit="m3/(kg.K)")
     "Numerical derivative of specific volume with regards to temperature";

protected
  Real dv_p(
    final unit="m3/(kg)")
    "Delta of specific volume of refrigerant with regards to pressure";

  Real dv_T(
    final unit="m3/(kg)")
    "Delta of specific volume of refrigerant with regards to temperature";

  Real dv_p_num(
    final unit="m3/(kg)")
    "Numerical delta of specific volume of refrigerant with regards to
    pressure";

  Real dv_T_num(
    final unit="m3/(kg)")
    "Numerical delta of specific volume of refrigerant with regards to
    temperature";

  constant Modelica.Units.SI.Time oneSec=1.0
    "Unit time variable for unit conversion of time derivatives";

equation

  // Analytical derivatives
  dv_p = Buildings.Media.Refrigerants.R410A.dSpecificVolumeVap_pT(
    p, T, dp/oneSec, 0.0)*oneSec;

  dv_T = Buildings.Media.Refrigerants.R410A.dSpecificVolumeVap_pT(
    p, T, 0.0, dT/oneSec)*oneSec;

  dvdp = dv_p / dp;

  dvdT = dv_T / dT;

  // Numerical derivatives
  dv_p_num = Buildings.Media.Refrigerants.R410A.specificVolumeVap_pT(p+0.5*dp, T)
    - Buildings.Media.Refrigerants.R410A.specificVolumeVap_pT(p-0.5*dp, T);

  dv_T_num = Buildings.Media.Refrigerants.R410A.specificVolumeVap_pT(p, T+0.5*dT)
    - Buildings.Media.Refrigerants.R410A.specificVolumeVap_pT(p, T-0.5*dT);

  dvdp_num = dv_p / dp;

  dvdT_num = dv_T / dT;
end R410A_dSpecificVolumeVap_pT;


within Buildings.Media;
package Specialized "Package with specialized media implementations"
  extends Modelica.Icons.Package;
end Specialized;


Specialized implementation of air

within Buildings.Media.Specialized;
package Air "Specialized implementation of air"
  extends Modelica.Icons.Package;
end Air;


Model for air as a perfect gas

within Buildings.Media.Specialized.Air;
package PerfectGas "Model for air as a perfect gas"
  extends Modelica.Media.Interfaces.PartialCondensingGases(
     mediumName="Moist air unsaturated perfect gas",
     substanceNames={"water", "air"},
     final reducedX=true,
     final singleState=false,
     reference_X={0.01,0.99},
     reference_T=273.15,
     reference_p=101325,
     fluidConstants = {Modelica.Media.IdealGases.Common.FluidData.H2O,
                       Modelica.Media.IdealGases.Common.FluidData.N2},
     AbsolutePressure(start=p_default),
     Temperature(start=T_default));

  extends Modelica.Icons.Package;

  constant Integer Water=1
    "Index of water (in substanceNames, massFractions X, etc.)";
  constant Integer Air=2
    "Index of air (in substanceNames, massFractions X, etc.)";

  redeclare record extends ThermodynamicState(
    p(start=p_default),
    T(start=T_default),
    X(start=X_default)) "ThermodynamicState record for moist air"
  end ThermodynamicState;

  redeclare replaceable model extends BaseProperties(
    p(stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default),
    Xi(
      nominal={0.01},
      each stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default),
    final standardOrderComponents=true)

    /* p, T, X = X[Water] are used as preferred states, since only then all
     other quantities can be computed in a recursive sequence.
     If other variables are selected as states, static state selection
     is no longer possible and non-linear algebraic equations occur.
      */
  protected
    constant Modelica.Units.SI.MolarMass[2] MMX={steam.MM,dryair.MM}
      "Molar masses of components";

    MassFraction X_steam "Mass fraction of steam water";
    MassFraction X_air "Mass fraction of air";
  equation
    assert(T >= 200.0, "
In "   + getInstanceName() + ": Temperature T exceeded its minimum allowed value of -73.15 degC (200 Kelvin)
as required from medium model \"" + mediumName + "\".");
    assert(T <= 423.15, "
In "   + getInstanceName() + ": Temperature T exceeded its maximum allowed value of 150 degC (423.15 Kelvin)
as required from medium model \"" + mediumName + "\".");

    MM = 1/(Xi[Water]/MMX[Water]+(1.0-Xi[Water])/MMX[Air]);

    X_steam  = Xi[Water];
    X_air    = 1-Xi[Water];

    h = (T - reference_T)*dryair.cp * (1 - Xi[Water]) +
        ((T-reference_T) * steam.cp + h_fg) * Xi[Water];

    R_s = dryair.R*(1 - X_steam) + steam.R*X_steam;
    //
    u =h - R_s*T;
    d =p/(R_s*T);
    /* Note, u and d are computed under the assumption that the volume of the liquid
         water is negligible with respect to the volume of air and of steam
      */
    state.p = p;
    state.T = T;
    state.X = X;
  end BaseProperties;

  function Xsaturation = Modelica.Media.Air.MoistAir.Xsaturation
    "Steam water mass fraction of saturation boundary in kg_water/kg_moistair"
  redeclare function setState_pTX
    "Thermodynamic state as function of p, T and composition X"
      extends Modelica.Media.Air.MoistAir.setState_pTX;
  end setState_pTX;

  redeclare function setState_phX
    "Thermodynamic state as function of p, h and composition X"
  extends Modelica.Icons.Function;
  input AbsolutePressure p "Pressure";
  input SpecificEnthalpy h "Specific enthalpy";
  input MassFraction X[:] "Mass fractions";
  output ThermodynamicState state;
  algorithm
  state := if size(X,1) == nX then
         ThermodynamicState(p=p,T=temperature_phX(p,h,X),X=X) else
        ThermodynamicState(p=p,T=temperature_phX(p,h,X), X=cat(1,X,{1-sum(X)}));
  end setState_phX;

  redeclare function setState_dTX
    "Thermodynamic state as function of d, T and composition X"
  extends Modelica.Icons.Function;
  input Density d "Density";
  input Temperature T "Temperature";
  input MassFraction X[:]=reference_X "Mass fractions";
  output ThermodynamicState state "Thermodynamic state";
  algorithm
  state := if size(X, 1) == nX then ThermodynamicState(
        p=d*({steam.R,dryair.R}*X)*T,
        T=T,
        X=X) else ThermodynamicState(
        p=d*({steam.R,dryair.R}*cat(
          1,
          X,
          {1 - sum(X)}))*T,
        T=T,
        X=cat(
          1,
          X,
          {1 - sum(X)}));
  end setState_dTX;

redeclare function extends gasConstant "Gas constant"
algorithm
    R_s := dryair.R*(1 - state.X[Water]) + steam.R*state.X[Water];
end gasConstant;

function saturationPressureLiquid
    "Return saturation pressure of water as a function of temperature T in the range of 273.16 to 373.16 K"

  extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature Tsat "saturation temperature";
    output Modelica.Units.SI.AbsolutePressure psat "saturation pressure";
  // This function is declared here explicitly, instead of referencing the function in its
  // base class, since otherwise Dymola 7.3 does not find the derivative for the model
  // Buildings.Fluid.Sensors.Examples.MassFraction
algorithm
  psat := 611.657*Modelica.Math.exp(17.2799 - 4102.99/(Tsat - 35.719));
end saturationPressureLiquid;

function saturationPressureLiquid_der
    "Time derivative of saturationPressureLiquid"

  extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature Tsat "Saturation temperature";
  input Real dTsat(unit="K/s") "Saturation temperature derivative";
  output Real psat_der(unit="Pa/s") "Saturation pressure";

algorithm
  psat_der:=611.657*Modelica.Math.exp(17.2799 - 4102.99/(Tsat - 35.719))*4102.99*dTsat/(Tsat - 35.719)/(Tsat - 35.719);
end saturationPressureLiquid_der;

  function sublimationPressureIce =
      Modelica.Media.Air.MoistAir.sublimationPressureIce
    "Saturation curve valid for 223.16 <= T <= 273.16. Outside of these limits a (less accurate) result is returned"
  function sublimationPressureIce_der =
      Modelica.Media.Air.MoistAir.sublimationPressureIce_der
    "Derivative function for 'sublimationPressureIce'"
redeclare function extends saturationPressure
    "Saturation curve valid for 223.16 <= T <= 373.16 (and slightly outside with less accuracy)"

algorithm
  psat := Buildings.Utilities.Math.Functions.regStep(
            y1=saturationPressureLiquid(Tsat),
            y2=sublimationPressureIce(Tsat),
            x=Tsat-273.16,
            x_small=1.0);
end saturationPressure;

 redeclare function extends pressure "Gas pressure"
 algorithm
  p := state.p;
 end pressure;

 redeclare function extends temperature "Gas temperature"
 algorithm
  T := state.T;
 end temperature;

 redeclare function extends density "Gas density"
 algorithm
  d := state.p/(gasConstant(state)*state.T);
 end density;

 redeclare function extends specificEntropy
    "Specific entropy (liquid part neglected, mixing entropy included)"
 algorithm
  s := s_pTX(
        state.p,
        state.T,
        state.X);
 end specificEntropy;

 redeclare function extends enthalpyOfVaporization
    "Enthalpy of vaporization of water"
 algorithm
  r0 := h_fg;
 end enthalpyOfVaporization;

function HeatCapacityOfWater
    "Specific heat capacity of water (liquid only) which is constant"
    extends Modelica.Icons.Function;
    input Temperature T;
    output SpecificHeatCapacity cp_fl;
algorithm
    cp_fl := cpWatLiq;
end HeatCapacityOfWater;

redeclare replaceable function extends enthalpyOfLiquid
    "Enthalpy of liquid (per unit mass of liquid) which is linear in the temperature"

algorithm
  h := (T - reference_T)*cpWatLiq;
end enthalpyOfLiquid;

replaceable function der_enthalpyOfLiquid
    "Temperature derivative of enthalpy of liquid per unit mass of liquid"
  extends Modelica.Icons.Function;
  input Temperature T "temperature";
  input Real der_T "temperature derivative";
  output Real der_h "derivative of liquid enthalpy";
algorithm
  der_h := cpWatLiq*der_T;
end der_enthalpyOfLiquid;

redeclare function enthalpyOfCondensingGas
    "Enthalpy of steam per unit mass of steam"
  extends Modelica.Icons.Function;

  input Temperature T "temperature";
  output SpecificEnthalpy h "steam enthalpy";
algorithm
  h := (T-reference_T) * steam.cp + enthalpyOfVaporization(T);
end enthalpyOfCondensingGas;

replaceable function der_enthalpyOfCondensingGas
    "Derivative of enthalpy of steam per unit mass of steam"
  extends Modelica.Icons.Function;
  input Temperature T "temperature";
  input Real der_T "temperature derivative";
  output Real der_h "derivative of steam enthalpy";
algorithm
  der_h := steam.cp*der_T;
end der_enthalpyOfCondensingGas;

redeclare function enthalpyOfNonCondensingGas
    "Enthalpy of non-condensing gas per unit mass of steam"
  extends Modelica.Icons.Function;

  input Temperature T "temperature";
  output SpecificEnthalpy h "enthalpy";
algorithm
  h := enthalpyOfDryAir(T);
end enthalpyOfNonCondensingGas;

replaceable function der_enthalpyOfNonCondensingGas
    "Derivative of enthalpy of non-condensing gas per unit mass of steam"
  extends Modelica.Icons.Function;
  input Temperature T "temperature";
  input Real der_T "temperature derivative";
  output Real der_h "derivative of steam enthalpy";
algorithm
  der_h := der_enthalpyOfDryAir(T, der_T);
end der_enthalpyOfNonCondensingGas;

redeclare replaceable function extends enthalpyOfGas
    "Enthalpy of gas mixture per unit mass of gas mixture"
algorithm
  h := enthalpyOfCondensingGas(T)*X[Water]
       + enthalpyOfDryAir(T)*(1.0-X[Water]);
end enthalpyOfGas;

replaceable function enthalpyOfDryAir
    "Enthalpy of dry air per unit mass of dry air"
  extends Modelica.Icons.Function;

  input Temperature T "temperature";
  output SpecificEnthalpy h "dry air enthalpy";
algorithm
  h := (T - reference_T)*dryair.cp;
end enthalpyOfDryAir;

replaceable function der_enthalpyOfDryAir
    "Derivative of enthalpy of dry air per unit mass of dry air"
  extends Modelica.Icons.Function;
  input Temperature T "temperature";
  input Real der_T "temperature derivative";
  output Real der_h "derivative of dry air enthalpy";
algorithm
  der_h := dryair.cp*der_T;
end der_enthalpyOfDryAir;

redeclare replaceable function extends specificHeatCapacityCp
    "Specific heat capacity of gas mixture at constant pressure"
algorithm
  cp := dryair.cp*(1-state.X[Water]) +steam.cp*state.X[Water];
end specificHeatCapacityCp;

replaceable function der_specificHeatCapacityCp
    "Derivative of specific heat capacity of gas mixture at constant pressure"
    input ThermodynamicState state;
    input ThermodynamicState der_state;
    output Real der_cp(unit="J/(kg.K.s)");
algorithm
  der_cp := (steam.cp-dryair.cp)*der_state.X[Water];
end der_specificHeatCapacityCp;

redeclare replaceable function extends specificHeatCapacityCv
    "Specific heat capacity of gas mixture at constant volume"
algorithm
  cv:= dryair.cv*(1-state.X[Water]) +steam.cv*state.X[Water];
end specificHeatCapacityCv;

replaceable function der_specificHeatCapacityCv
    "Derivative of specific heat capacity of gas mixture at constant volume"
    input ThermodynamicState state;
    input ThermodynamicState der_state;
    output Real der_cv(unit="J/(kg.K.s)");
algorithm
  der_cv := (steam.cv-dryair.cv)*der_state.X[Water];
end der_specificHeatCapacityCv;

redeclare function extends dynamicViscosity "dynamic viscosity of dry air"
algorithm
  eta := 1.85E-5;
end dynamicViscosity;

redeclare function extends thermalConductivity
    "Thermal conductivity of dry air as a polynomial in the temperature"
algorithm
  lambda :=Modelica.Math.Polynomials.evaluate({(-4.8737307422969E-008),
      7.67803133753502E-005,0.0241814385504202},
      Modelica.Units.Conversions.to_degC(state.T));
end thermalConductivity;

redeclare function extends specificEnthalpy "Specific enthalpy"
algorithm
  h := specificEnthalpy_pTX(state.p, state.T, state.X);
end specificEnthalpy;

redeclare replaceable function specificEnthalpy_pTX "Specific enthalpy"
  extends Modelica.Icons.Function;
    input Modelica.Units.SI.Pressure p "Pressure";
    input Modelica.Units.SI.Temperature T "Temperature";
    input Modelica.Units.SI.MassFraction X[:] "Mass fractions of moist air";
    output Modelica.Units.SI.SpecificEnthalpy h "Specific enthalpy at p, T, X";

  protected
    Modelica.Units.SI.SpecificEnthalpy hDryAir "Enthalpy of dry air";
algorithm
  hDryAir := (T - reference_T)*dryair.cp;
  h := hDryAir * (1 - X[Water]) +
       ((T-reference_T) * steam.cp + h_fg) * X[Water];
end specificEnthalpy_pTX;

redeclare function extends specificInternalEnergy "Specific internal energy"
  extends Modelica.Icons.Function;
algorithm
  u := specificEnthalpy_pTX(state.p,state.T,state.X) - gasConstant(state)*state.T;
end specificInternalEnergy;

redeclare function extends specificGibbsEnergy "Specific Gibbs energy"
  extends Modelica.Icons.Function;
algorithm
  g := specificEnthalpy_pTX(state.p,state.T,state.X) - state.T*specificEntropy(state);
end specificGibbsEnergy;

redeclare function extends specificHelmholtzEnergy "Specific Helmholtz energy"
  extends Modelica.Icons.Function;
algorithm
  f := specificEnthalpy_pTX(state.p,state.T,state.X) - gasConstant(state)*state.T - state.T*specificEntropy(state);
end specificHelmholtzEnergy;

redeclare replaceable function temperature_phX
    "Compute temperature from specific enthalpy and mass fraction"
    extends Modelica.Icons.Function;
  input AbsolutePressure p "Pressure";
  input SpecificEnthalpy h "specific enthalpy";
  input MassFraction[:] X "mass fractions of composition";
  output Temperature T "temperature";
algorithm
  T := reference_T + (h - h_fg * X[Water])
       /((1 - X[Water])*dryair.cp + X[Water] * steam.cp);
end temperature_phX;
//////////////////////////////////////////////////////////////////////
// Protected classes.
// These classes are only of use within this medium model.
// Equipment models generally have no need to access them.
// Therefore, they are made protected. This also allows to redeclare the
// medium model with another medium model that does not provide an
// implementation of these classes.
protected
  record GasProperties
    "Coefficient data record for properties of perfect gases"
    extends Modelica.Icons.Record;

    Modelica.Units.SI.MolarMass MM "Molar mass";
    Modelica.Units.SI.SpecificHeatCapacity R "Gas constant";
    Modelica.Units.SI.SpecificHeatCapacity cp
      "Specific heat capacity at constant pressure";
    Modelica.Units.SI.SpecificHeatCapacity cv=cp - R
      "Specific heat capacity at constant volume";
  end GasProperties;
  // In the assignments below, we compute cv as OpenModelica
  // cannot evaluate cv=cp-R as defined in GasProperties.
  constant GasProperties dryair(
    R=Modelica.Media.IdealGases.Common.SingleGasesData.Air.R_s,
    MM=Modelica.Media.IdealGases.Common.SingleGasesData.Air.MM,
    cp=Buildings.Utilities.Psychrometrics.Constants.cpAir,
    cv=Buildings.Utilities.Psychrometrics.Constants.cpAir - Modelica.Media.IdealGases.Common.SingleGasesData.Air.R_s)
    "Dry air properties";
  constant GasProperties steam(
    R=Modelica.Media.IdealGases.Common.SingleGasesData.H2O.R_s,
    MM=Modelica.Media.IdealGases.Common.SingleGasesData.H2O.MM,
    cp=Buildings.Utilities.Psychrometrics.Constants.cpSte,
    cv=Buildings.Utilities.Psychrometrics.Constants.cpSte - Modelica.Media.IdealGases.Common.SingleGasesData.H2O.R_s)
    "Steam properties";

  constant Real k_mair =  steam.MM/dryair.MM "Ratio of molar weights";

  constant Modelica.Units.SI.SpecificEnergy h_fg=Buildings.Utilities.Psychrometrics.Constants.h_fg
    "Latent heat of evaporation of water";

  constant Modelica.Units.SI.SpecificHeatCapacity cpWatLiq=Buildings.Utilities.Psychrometrics.Constants.cpWatLiq
    "Specific heat capacity of liquid water";

  function s_pTX = Modelica.Media.Air.MoistAir.s_pTX
    "Return specific entropy of moist air as a function of pressure p, temperature T and composition X (only valid for phi<1)";
  function s_pTX_der = Modelica.Media.Air.MoistAir.s_pTX_der
    "Return specific entropy of moist air as a function of pressure p, temperature T and composition X (only valid for phi<1)";
end PerfectGas;


within Buildings.Media.Specialized.Air;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Temperature

within Buildings.Media.Specialized.Air.Examples;
model PerfectGasDerivativeCheck
  extends Modelica.Icons.Example;

   package Medium = Buildings.Media.Specialized.Air.PerfectGas;

  Modelica.Units.SI.Temperature T "Temperature";
  Modelica.Units.SI.SpecificEnthalpy hLiqSym "Liquid phase enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hLiqCod "Liquid phase enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hSteSym "Water vapor enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hSteCod "Water vapor enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hAirSym "Dry air enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hAirCod "Dry air enthalpy";
    constant Real convT(unit="K/s3") = 270
    "Conversion factor to satisfy unit check";
initial equation
     hLiqSym = hLiqCod;
     hSteSym = hSteCod;
     hAirSym = hAirCod;
equation
    T = 273.15+convT*time^3;

    hLiqCod=Medium.enthalpyOfLiquid(T);
    der(hLiqCod)=der(hLiqSym);
    assert(abs(hLiqCod-hLiqSym) < 1E-2, "Model has an error");

    hSteCod=Medium.enthalpyOfCondensingGas(T);
    der(hSteCod)=der(hSteSym);
    assert(abs(hSteCod-hSteSym) < 1E-2, "Model has an error");

    hAirCod=Medium.enthalpyOfDryAir(T);
    der(hAirCod)=der(hAirSym);
    assert(abs(hAirCod-hAirSym) < 1E-2, "Model has an error");
end PerfectGasDerivativeCheck;


within Buildings.Media.Specialized.Air.Examples;
model PerfectGasTemperatureEnthalpyInversion
  "Model to check computation of h(T) and its inverse"
  extends Modelica.Icons.Example;
  extends Buildings.Media.Examples.BaseClasses.TestTemperatureEnthalpyInversion(
    redeclare package Medium = Buildings.Media.Specialized.Air.PerfectGas);
end PerfectGasTemperatureEnthalpyInversion;


Specialized implementation of water

within Buildings.Media.Specialized;
package Water "Specialized implementation of water"
  extends Modelica.Icons.Package;
end Water;


within Buildings.Media.Specialized.Water;
package TemperatureDependentDensity
  "Package with model for liquid water with temperature-dependent density"
   extends Modelica.Media.Interfaces.PartialPureSubstance(
     mediumName="WaterDetailed",
     p_default=300000,
     reference_p=300000,
     reference_T=273.15,
     reference_X={1},
     final singleState=true,
     ThermoStates=Modelica.Media.Interfaces.Choices.IndependentVariables.T,
     AbsolutePressure(start=p_default),
     Temperature(start=T_default));
   extends Modelica.Icons.Package;

  redeclare record FluidConstants =
    Modelica.Media.Interfaces.Types.Basic.FluidConstants (
    each chemicalFormula="H2O",
    each structureFormula="H2O",
    each casRegistryNumber="7732-18-5",
    each iupacName="oxidane",
    each molarMass=MM_const);
  redeclare record extends ThermodynamicState "Thermodynamic state variables"
    Temperature T(start=T_default) "Temperature of medium";
    AbsolutePressure p(start=p_default) "Pressure of medium";
  end ThermodynamicState;
  constant Modelica.Units.SI.SpecificHeatCapacity cp_const=4184
    "Specific heat capacity at constant pressure";

  redeclare model extends BaseProperties(
     preferredMediumStates=true) "Base properties"
  equation
    h = (T - reference_T)*cp_const;
    u = h-reference_p/d;
    d = density(state);
    state.T = T;
    state.p = p;
    R_s = 0;
    MM=MM_const;
  end BaseProperties;

redeclare function extends density "Return the density"
algorithm
  d := smooth(1,
    if state.T < 278.15 then
      -0.042860825*state.T + 1011.9695761
    elseif state.T < 373.15 then
      0.000015009*state.T^3 - 0.01813488505*state.T^2 + 6.5619527954075*state.T
      + 254.900074971947
    else
     -0.7025109*state.T + 1220.35045233);
end density;

redeclare function extends dynamicViscosity "Return the dynamic viscosity"
algorithm
  eta := density(state)*kinematicViscosity(state.T);
end dynamicViscosity;

redeclare function extends specificEnthalpy "Return the specific enthalpy"
algorithm
  h := (state.T - reference_T)*cp_const;
end specificEnthalpy;

function enthalpyOfLiquid "Return the specific enthalpy of liquid"
  extends Modelica.Icons.Function;
    input Modelica.Units.SI.Temperature T "Temperature";
    output Modelica.Units.SI.SpecificEnthalpy h "Specific enthalpy";
algorithm
  h := (T - reference_T)*cp_const;
end enthalpyOfLiquid;

redeclare function extends specificInternalEnergy
    "Return the specific enthalpy"
algorithm
  u := specificEnthalpy(state) - reference_p/density(state);
end specificInternalEnergy;

redeclare function extends specificEntropy "Return the specific entropy"
  extends Modelica.Icons.Function;
algorithm
  s := cv_const*Modelica.Math.log(state.T/reference_T);
end specificEntropy;

redeclare function extends specificGibbsEnergy
    "Return the specific Gibbs energy"
  extends Modelica.Icons.Function;
algorithm
  g := specificEnthalpy(state) - state.T*specificEntropy(state);
end specificGibbsEnergy;

redeclare function extends specificHelmholtzEnergy
    "Return the specific Helmholtz energy"
  extends Modelica.Icons.Function;
algorithm
  f := specificInternalEnergy(state) - state.T*specificEntropy(state);
end specificHelmholtzEnergy;

redeclare function extends isentropicEnthalpy "Return the isentropic enthalpy"
algorithm
  h_is := specificEnthalpy(setState_psX(
            p=p_downstream,
            s=specificEntropy(refState),
            X={1}));
end isentropicEnthalpy;

redeclare function extends isobaricExpansionCoefficient
    "Return the isobaric expansion coefficient"
algorithm
    beta := -smooth(0,
    if state.T < 278.15 then
      0.042860825*(0.042860825*state.T - 1011.9695761)/(-0.042860825*state.T +
      1011.9695761)^2
    elseif state.T < 373.15 then
      (4.5027e-5*state.T^2 - 0.0362697701*state.T + 6.5619527954075)/
        (1.5009e-5*state.T^3 - 0.01813488505*state.T^2 + 6.5619527954075*state.T + 254.900074971947)
    else
       0.7025109*(0.7025109*state.T - 1220.35045233)/(-0.7025109*state.T +
       1220.35045233)^2);
        // Symbolic conversion of degC to Kelvin
//        ((4.5027e-05)*T_degC^2 - 0.01167152*state.T +
//               3.202446788)/((1.5009e-05)*T_degC^3 - 0.00583576*T_degC^2 +
//               0.0143711*state.T + 996.194534035)
end isobaricExpansionCoefficient;

redeclare function extends isothermalCompressibility
    "Return the isothermal compressibility factor"
algorithm
  kappa := 0;
end isothermalCompressibility;

redeclare function extends density_derp_T
    "Return the partial derivative of density with respect to pressure at constant temperature"
algorithm
  ddpT := 0;
end density_derp_T;

redeclare function extends density_derT_p
    "Return the partial derivative of density with respect to temperature at constant pressure"
algorithm
  ddTp := if state.T < 278.15 then
            -0.042860825
          elseif state.T < 373.15 then
            (0.0000450270000000000*state.T^2 - 0.0362697701000000*state.T +
            6.56195279540750)
          else
           -0.7025109;
end density_derT_p;

redeclare function extends density_derX
    "Return the partial derivative of density with respect to mass fractions at constant pressure and temperature"
algorithm
  dddX := fill(0, nX);
end density_derX;

redeclare replaceable function extends specificHeatCapacityCp
    "Return the specific heat capacity at constant pressure"
algorithm
  cp := cp_const;
end specificHeatCapacityCp;

redeclare replaceable function extends specificHeatCapacityCv
    "Return the specific heat capacity at constant volume"
algorithm
  cv := cv_const;
end specificHeatCapacityCv;

redeclare function extends thermalConductivity
    "Return the thermal conductivity"
algorithm
  lambda :=0.6065*(-1.48445 + 4.12292*(state.T/298.15) - 1.63866*(state.T/298.15)^2);
end thermalConductivity;

redeclare function extends pressure "Return the pressure"
algorithm
    p := state.p;
end pressure;

redeclare function extends temperature "Return the temperature"
algorithm
    T := state.T;
end temperature;

redeclare function extends molarMass "Return the molar mass"
algorithm
    MM := MM_const;
end molarMass;

redeclare function setState_dTX
    "Return thermodynamic state from d, T, and X or Xi"
    extends Modelica.Icons.Function;
    input Density d "Density";
    input Temperature T "Temperature";
    input MassFraction X[:]=reference_X "Mass fractions";
    output ThermodynamicState state "Thermodynamic state record";
algorithm
    assert(false,
      "Pressure can not be computed from temperature and density for an incompressible fluid!");
end setState_dTX;

redeclare function extends setState_phX
    "Return the thermodynamic state as function of pressure p, specific enthalpy h and composition X or Xi"
algorithm
  state := ThermodynamicState(p=p, T=reference_T + h/cp_const);
end setState_phX;

redeclare function extends setState_pTX
    "Return the thermodynamic state as function of p, T and composition X or Xi"
algorithm
    state := ThermodynamicState(p=p, T=T);
end setState_pTX;

redeclare function extends setState_psX
    "Return the thermodynamic state as function of p, s and composition X or Xi"
algorithm
  // The temperature is obtained from symbolic solving the
  // specificEntropy function for T, i.e.,
  // s := cv_const*Modelica.Math.log(state.T/reference_T)
  state := ThermodynamicState(p=p, T=reference_T * Modelica.Math.exp(s/cv_const));
end setState_psX;
//////////////////////////////////////////////////////////////////////
// Protected classes.
// These classes are only of use within this medium model.
// Equipment models generally have no need to access them.
// Therefore, they are made protected. This also allows to redeclare the
// medium model with another medium model that does not provide an
// implementation of these classes.
protected
  final constant Modelica.Units.SI.SpecificHeatCapacity cv_const=cp_const
    "Specific heat capacity at constant volume";

  constant Modelica.Units.SI.VelocityOfSound a_const=1484
    "Constant velocity of sound";
  constant Modelica.Units.SI.MolarMass MM_const=0.018015268 "Molar mass";

replaceable function der_specificHeatCapacityCp
    "Return the derivative of the specific heat capacity at constant pressure"
  extends Modelica.Icons.Function;
  input ThermodynamicState state "Thermodynamic state";
  input ThermodynamicState der_state "Derivative of thermodynamic state";
  output Real der_cp(unit="J/(kg.K.s)") "Derivative of specific heat capacity";
algorithm
  der_cp := 0;
end der_specificHeatCapacityCp;

replaceable function der_enthalpyOfLiquid
    "Temperature derivative of enthalpy of liquid per unit mass of liquid"
  extends Modelica.Icons.Function;
  input Temperature T "Temperature";
  input Real der_T "Temperature derivative";
  output Real der_h "Derivative of liquid enthalpy";
algorithm
  der_h := cp_const*der_T;
end der_enthalpyOfLiquid;

function kinematicViscosity "Return the kinematic viscosity"
  extends Modelica.Icons.Function;

    input Modelica.Units.SI.Temperature T "Temperature";
    output Modelica.Units.SI.KinematicViscosity kinVis "Kinematic viscosity";
algorithm
  kinVis := smooth(1,
  if T < 278.15 then
    -(4.63023776563e-08)*T + 1.44011135763e-05
  else
    1.0e-6*Modelica.Math.exp(
      -(7.22111000000000e-7)*T^3 + 0.000809102858950000*T^2
      - 0.312920238272193*T + 40.4003044106506));

This has been converted to Kelvin, which resulted in the above expression.
In addition, at 5 °C the kinematic viscosity is linearly extrapolated
to avoid a large gradient at very low temperatures.
We selected the same point for the linearization as we used for the density,
as the density and the kinematic viscosity are combined in

Buildings.Media.Specialized.Water.TemperatureDependentDensity.dynamicViscosity.

",
revisions="

April 11, 2016 by Michael Wetter:

Corrected wrong hyperlink in documentation for
issue 450.

December 18, 2013, by Michael Wetter:

First implementation, based on the IDA implementation in therpro.nmf,
but converted from Celsius to Kelvin.

"));
end kinematicViscosity;
end TemperatureDependentDensity;


within Buildings.Media.Specialized.Water;
package ConstantProperties_pT "Package with model for liquid water with constant properties at user-provided nominal conditions"

  extends Buildings.Media.Water(
    mediumName="ConstantPropertyWater(p="+String(p_nominal)+",T="+String(T_nominal)+")",
    p_default=p_nominal,
    reference_p=p_nominal,
    cp_const=cp_nominal,
    d_const=d_nominal,
    eta_const=eta_nominal,
    lambda_const=lambda_nominal,
    a_const=a_nominal,
    T_max=T_max_nominal);

constant Modelica.Units.SI.Temperature T_max_nominal=
    Modelica.Media.Water.IF97_Utilities.BaseIF97.Basic.tsat(p_nominal)
  "Maximum temperature valid for medium model";

constant Modelica.Units.SI.Temperature T_nominal=273.15 + 20
  "Nominal temperature for calculation of water properties";

constant Modelica.Units.SI.VelocityOfSound a_nominal=
    Modelica.Media.Water.IF97_Utilities.velocityOfSound_pT(p_nominal, T_nominal)
  "Constant velocity of sound";

constant Modelica.Units.SI.SpecificHeatCapacity cp_nominal=
    Modelica.Media.Water.IF97_Utilities.cp_pT(p_nominal, T_nominal)
  "Specific heat capacity at nominal water conditions";

constant Modelica.Units.SI.Density d_nominal=
    Modelica.Media.Water.IF97_Utilities.rho_pT(p_nominal, T_nominal)
  "Density at nominal water conditions";

constant Modelica.Units.SI.DynamicViscosity eta_nominal=
    Modelica.Media.Water.IF97_Utilities.dynamicViscosity(
    d_nominal,
    T_nominal,
    p_nominal) "Constant dynamic viscosity";

constant Modelica.Units.SI.ThermalConductivity lambda_nominal=
    Modelica.Media.Water.IF97_Utilities.thermalConductivity(
    d_nominal,
    T_nominal,
    p_nominal) "Constant thermal conductivity";

constant Modelica.Units.SI.AbsolutePressure p_nominal=101325
  "Nominal pressure for calculation of water properties";

", revisions="

September 20, 2016, by Michael Wetter:

Reordered constants to conform with the order in package.order.

This is for
issue 518.

September 14, 2016, by Michael Wetter:

Revised implementation.

September 8, 2016, by Marcus Fuchs:

First implementation.

"),
    Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}),
        graphics={
        Polygon(
          points={{16,-28},{32,-42},{26,-48},{10,-36},{16,-28}},
          lineColor={95,95,95},
          fillPattern=FillPattern.Sphere,
          fillColor={95,95,95}),
        Polygon(
          points={{10,34},{26,44},{30,36},{14,26},{10,34}},
          lineColor={95,95,95},
          fillPattern=FillPattern.Sphere,
          fillColor={95,95,95}),
        Ellipse(
          extent={{-82,52},{24,-54}},
          lineColor={95,95,95},
          fillPattern=FillPattern.Sphere,
          fillColor={0,0,0}),
        Ellipse(
          extent={{22,82},{80,24}},
          lineColor={0,0,0},
          fillPattern=FillPattern.Sphere,
          fillColor={95,95,95}),
        Ellipse(
          extent={{20,-30},{78,-88}},
          lineColor={0,0,0},
          fillPattern=FillPattern.Sphere,
          fillColor={95,95,95}),
        Text(
          extent={{-110,40},{50,-36}},
          textColor={238,46,47},
          textString="pT")}));
end ConstantProperties_pT;


within Buildings.Media.Specialized.Water;
package Examples "Collection of models that test the water models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within Buildings.Media.Specialized.Water.Examples;
model TemperatureDependentDensityDerivativeCheck
  "Model that tests the derivative implementation"
  extends Modelica.Icons.Example;

   package Medium =
      Buildings.Media.Specialized.Water.TemperatureDependentDensity
    "Medium model";

  Modelica.Units.SI.Temperature T "Temperature";
  Modelica.Units.SI.SpecificEnthalpy hLiqSym "Liquid phase enthalpy";
  Modelica.Units.SI.SpecificEnthalpy hLiqCod "Liquid phase enthalpy";
  Modelica.Units.SI.SpecificHeatCapacity cpSym "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cpCod "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cvSym "Specific heat capacity";
  Modelica.Units.SI.SpecificHeatCapacity cvCod "Specific heat capacity";
    constant Real convT(unit="K/s3") = 270
    "Conversion factor to satisfy unit check";
initial equation
     hLiqSym = hLiqCod;
     cpSym   = cpCod;
     cvSym   = cvCod;
equation
    T = 273.15+convT*time^3;

    hLiqCod=Medium.enthalpyOfLiquid(T);
    der(hLiqCod)=der(hLiqSym);
    assert(abs(hLiqCod-hLiqSym) < 1E-2, "Model has an error");

    cpCod=Medium.specificHeatCapacityCp(
      Medium.setState_pTX(
         p=1e5,
         T=T,
         X=Medium.X_default));
    der(cpCod)=der(cpSym);
    assert(abs(cpCod-cpSym) < 1E-2, "Model has an error");

     cvCod=Medium.specificHeatCapacityCv(
      Medium.setState_pTX(
         p=1e5,
         T=T,
         X=Medium.X_default));
    der(cvCod)=der(cvSym);
    assert(abs(cvCod-cvSym) < 1E-2, "Model has an error");
end TemperatureDependentDensityDerivativeCheck;


within Buildings.Media.Specialized.Water.Examples;
model TemperatureDependentDensityProperties
  "Model that tests the implementation of the fluid properties"
  extends Modelica.Icons.Example;
  extends Buildings.Media.Examples.BaseClasses.FluidProperties(
    redeclare package Medium =
        Buildings.Media.Specialized.Water.TemperatureDependentDensity,
    TMin=273.15,
    TMax=373.15);
equation
  // Check the implementation of the base properties
  basPro.state.p=p;
  basPro.state.T=T;
end TemperatureDependentDensityProperties;


within Buildings.Media.Specialized.Water.Examples;
model TemperatureDependentDensityTemperatureEnthalpyInversion
  "Model to check computation of h(T) and its inverse"
  extends Modelica.Icons.Example;
  extends Buildings.Media.Examples.BaseClasses.TestTemperatureEnthalpyInversion(
    redeclare package Medium =
        Buildings.Media.Specialized.Water.TemperatureDependentDensity);
end TemperatureDependentDensityTemperatureEnthalpyInversion;


within Buildings.Media.Specialized.Water.Examples;
model WaterProperties_pT
  "Model that tests the implementation of the fluid properties at nominal conditions"
  extends Modelica.Icons.Example;
  extends Buildings.Media.Examples.BaseClasses.FluidProperties(
    redeclare package Medium =
      Buildings.Media.Specialized.Water.ConstantProperties_pT (
        T_nominal=273.15+100,
        p_nominal=5e5),
    TMin=273.15,
    TMax=273.15+150);
equation
  // Check the implementation of the base properties
  basPro.state.p=p;
  basPro.state.T=T;
end WaterProperties_pT;


within Buildings.Obsolete;
package Air "Package with models that are configured to use with air-based HVAC systems"
  extends Modelica.Icons.Package;
end Air;


within Buildings.Obsolete.Air;
package Systems "Package with pre-configured HVAC systems"
  extends Modelica.Icons.Package;
end Systems;


within Buildings.Obsolete.Air.Systems;
package SingleZone "Package with pre-configured system models that serve a single thermal zone"
  extends Modelica.Icons.Package;
end SingleZone;


VAV system model

within Buildings.Obsolete.Air.Systems.SingleZone;
package VAV "VAV system model"
  extends Modelica.Icons.Package;
end VAV;


Variable air volume flow system with single themal zone and ASHRAE Guideline 36 sequence control. Implementation of
Buildings.Air.Systems.SingleZone.VAV.Examples.BaseClasses.PartialOpenLoop
with ASHRAE Guideline 36 control sequence.

within Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples;
model Guideline36
  "Variable air volume flow system with single themal zone and ASHRAE Guideline 36 sequence control"
  extends Modelica.Icons.Example;
  extends
    Buildings.Air.Systems.SingleZone.VAV.Examples.BaseClasses.PartialOpenLoop(
     hvac(QCoo_flow_nominal=-10000));
  parameter Modelica.Units.SI.Temperature TSupChi_nominal=279.15
    "Design value for chiller leaving water temperature";

  Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.SingleZone.VAV.Controller con(
    have_winSen=true,
    TZonHeaOn=293.15,
    TZonCooOff=303.15,
    kCoo=4,
    kCooCoi=1,
    yHeaMax=0.2,
    AFlo=48,
    VOutMin_flow=0.0144,
    VOutDes_flow=0.025,
    yMin=0.1,
    kHea=4,
    kMod=4,
    have_occSen=false,
    TZonHeaOff=288.15,
    TZonCooOn=298.15,
    TSupSetMax=343.15,
    TSupSetMin=286.15,
    yDam_VOutMin_minSpe=0.2304,
    yDam_VOutMin_maxSpe=0.02304,
    yDam_VOutDes_minSpe=0.4,
    yDam_VOutDes_maxSpe=0.04)
    "VAV controller"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysChiPla(
    uLow=-1,
    uHigh=0)
    "Hysteresis with delay to switch on cooling"
  Modelica.Blocks.Math.Feedback errTRooCoo
    "Control error on room temperature for cooling"
  Buildings.Controls.SetPoints.OccupancySchedule occSch(occupancy=3600*{8,18})
    "Occupancy schedule"
  Modelica.Blocks.Sources.BooleanConstant uWin(k=false) "Window opening signal"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant demLim(final k=0)
    "Cooling and heating demand imit level"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant cooWarTim(final k=0)
    "Cooldown and warm-up time"

protected
  Modelica.Blocks.Sources.Constant TSetSupChiConst(final k=TSupChi_nominal)
    "Set point for chiller temperature"

equation
  connect(con.yFan, hvac.uFan)
  connect(con.yHeaCoi, hvac.uHea)
  connect(con.yOutDamPos, hvac.uEco)
  connect(TSetSupChiConst.y, hvac.TSetChi)
  connect(errTRooCoo.y, hysChiPla.u)
  connect(zon.TRooAir, errTRooCoo.u1)
  connect(hysChiPla.y, hvac.chiOn)
  connect(weaBus.TDryBul, con.TOut)
  connect(zon.TRooAir, con.TZon)
  connect(hvac.TSup, con.TSup)
  connect(hvac.TMix, con.TMix)
  connect(occSch.tNexOcc, con.tNexOcc)
  connect(con.uOcc, occSch.occupied)
  connect(uWin.y, con.uWin)
  connect(con.TZonCooSet, errTRooCoo.u2)
  connect(hvac.TRet, con.TCut)
  connect(demLim.y, con.uCooDemLimLev)
  connect(demLim.y, con.uHeaDemLimLev)
  connect(cooWarTim.y, con.warUpTim)
  connect(cooWarTim.y, con.cooDowTim)
  connect(con.yCooCoi, hvac.uCooVal)
end Guideline36;


within Buildings.Obsolete.Air.Systems.SingleZone.VAV;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Example model using the block OptimalStart with a Guideline36 controller for a single-zone system in spring. This is an example model on how to use the block

Buildings.Controls.OBC.Utilities.OptimalStart
that integrates with a controller based on Guideline36

Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.SingleZone.VAV.Controller,
a single-zone VAV system and a single-zone floor building.
The building, HVAC system and controller model
can be found in the base class

Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart.BaseClasses.ZoneWithAHUG36.

within Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart;
model Guideline36Spring
  "Example model using the block OptimalStart with a Guideline36 controller for a single-zone system in spring"
  extends Modelica.Icons.Example;

  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    computeWetBulbTemperature=false,
    filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data"

  Buildings.Controls.OBC.Utilities.OptimalStart optStaHea(
    computeHeating=true,
    computeCooling=false,
    uLow=0.1,
    thrOptOn(displayUnit="s"))
    "Optimal start for heating"
  Buildings.Controls.SetPoints.OccupancySchedule occSch(occupancy=3600*{8,18})
    "Occupancy schedule"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSetHeaOn(k=20 + 273.15)
    "Zone heating setpoint during occupied period"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSetCooOn(k=24 + 273.15)
    "Zone cooling setpoint during occupied time"
  Buildings.Controls.OBC.Utilities.OptimalStart optStaCoo(
    computeHeating=false,
    computeCooling=true,
    uLow=0.1,
    thrOptOn(displayUnit="s"))
    "Optimal start for cooling"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(k=0)
    "No optimal start"
  Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart.BaseClasses.ZoneWithAHUG36
    zonAHUG36Opt
    "A single zone building with a VAV system and a Guideline36 controller"
  Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart.BaseClasses.ZoneWithAHUG36
    zonAHUG36Con
    "A single zone building with a VAV system and a Guideline36 controller"

equation
  connect(TSetHeaOn.y, optStaHea.TSetZonHea)
  connect(TSetCooOn.y, optStaCoo.TSetZonCoo)
  connect(occSch.tNexOcc, optStaCoo.tNexOcc)
  connect(optStaCoo.TZon, optStaHea.TZon)
  connect(occSch.tNexOcc, zonAHUG36Opt.tNexOcc)
  connect(occSch.occupied, zonAHUG36Opt.uOcc)
  connect(optStaHea.tOpt, zonAHUG36Opt.warUpTim)
  connect(optStaCoo.tOpt, zonAHUG36Opt.cooDowTim)
  connect(zonAHUG36Opt.TZon, optStaHea.TZon)
  connect(con.y, zonAHUG36Con.warUpTim)
  connect(con.y, zonAHUG36Con.cooDowTim)
  connect(occSch.tNexOcc, zonAHUG36Con.tNexOcc)
  connect(occSch.occupied, zonAHUG36Con.uOcc)
  connect(occSch.tNexOcc, optStaHea.tNexOcc)

  connect(weaDat.weaBus, zonAHUG36Opt.weaBus)
  connect(weaDat.weaBus, zonAHUG36Con.weaBus)
end Guideline36Spring;


Example model using the block OptimalStart with a Guideline36 controller for a single-zone system in summer. This is an example model on how to use the block

Buildings.Controls.OBC.Utilities.OptimalStart
that integrates with a controller based on Guideline36

Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.SingleZone.VAV.Controller,
a single-zone VAV system and a single-zone floor building.
The building, HVAC system and controller model
can be found in the base class

Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart.BaseClasses.ZoneWithAHUG36.

within Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart;
model Guideline36Summer
  "Example model using the block OptimalStart with a Guideline36 controller for a single-zone system in summer"
  extends
    Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart.Guideline36Spring;
end Guideline36Summer;


Example model using the block OptimalStart with a Guideline36 controller for a single-zone system in winter. This is an example model on how to use the block

Buildings.Controls.OBC.Utilities.OptimalStart
that integrates with a controller based on Guideline36

Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.SingleZone.VAV.Controller,
a single-zone VAV system and a single-zone floor building.
The building, HVAC system and controller model
can be found in the base class

Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart.BaseClasses.ZoneWithAHUG36.

within Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart;
model Guideline36Winter
  "Example model using the block OptimalStart with a Guideline36 controller for a single-zone system in winter"
  extends
    Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart.Guideline36Spring;
end Guideline36Winter;


within Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples;
package OptimalStart "Example models of the block OptimalStart"
extends Modelica.Icons.ExamplesPackage;
end OptimalStart;


within Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart;
package BaseClasses "Base classes of models in the package OptimalStart"
extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.Obsolete.Air.Systems.SingleZone.VAV.Examples.OptimalStart.BaseClasses;
block ZoneWithAHUG36
  "A single zone building with a VAV system and a Guideline36 controller"

  package MediumA = Buildings.Media.Air(extraPropertiesNames={"CO2"})
    "Buildings library air media package";
  package MediumW = Buildings.Media.Water
    "Buildings library water media package";
  parameter Modelica.Units.SI.Temperature TSupChi_nominal=279.15
    "Design value for chiller leaving water temperature";
  parameter Modelica.Units.SI.Volume VRoo=4555.7 "Space volume of the floor";
  parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal=VRoo*4*1.2/3600
    "Design air flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal=90000
    "Design heating flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QCoo_flow_nominal=-100000
    "Design cooling flow rate";

  Buildings.Controls.OBC.CDL.Interfaces.RealInput warUpTim(
    final unit="s",
    final quantity="Time")
    "Warm-up time retrieved from optimal warm-up block"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput cooDowTim(
    final unit="s",
    final quantity="Time")
    "Cool-down time retrieved from optimal cool-down block"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput tNexOcc(
    final unit="s",
    final quantity="Time")
    "Next occupancy time"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput uOcc
    "Current occupancy period, true if it is in occupant period"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TZon(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Zone air temperature"

  Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.SingleZone.VAV.Controller con(
    have_winSen=false,
    TZonHeaOn=293.15,
    TZonCooOff=303.15,
    kCoo=4,
    kCooCoi=1,
    yHeaMax=0.2,
    AFlo=1663,
    VOutMin_flow=0.5,
    VOutDes_flow=0.71,
    yMin=0.1,
    kHea=4,
    kMod=4,
    have_occSen=false,
    TZonHeaOff=288.15,
    TZonCooOn=297.15,
    TSupSetMax=343.15,
    TSupSetMin=286.15,
    uLow=0,
    uHigh=0.5)
    "VAV controller"
  Buildings.ThermalZones.Detailed.Validation.BaseClasses.SingleZoneFloor sinZonFlo(
    redeclare package Medium = MediumA)
    "Single zone floor"
  Buildings.Air.Systems.SingleZone.VAV.ChillerDXHeatingEconomizer hvac(
    redeclare package MediumA = MediumA,
    redeclare package MediumW = MediumW,
    mAir_flow_nominal=mAir_flow_nominal,
    etaHea_nominal=0.99,
    QHea_flow_nominal=QHea_flow_nominal,
    QCoo_flow_nominal=QCoo_flow_nominal,
    TSupChi_nominal=TSupChi_nominal) "HVAC system"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysChiPla1(uLow=-1, uHigh=0)
    "Hysteresis with delay to switch on cooling"
  Modelica.Blocks.Math.Feedback errTRooCoo1
    "Control error on room temperature for cooling"
  Buildings.BoundaryConditions.WeatherData.Bus weaBus
    "Weather bus"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant demLim(
    final k=0)
    "Cooling and heating demand imit level"

protected
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSetSupChiConst(
    final k=TSupChi_nominal)
    "Set point for chiller temperature"

equation
  connect(con.yFan, hvac.uFan)
  connect(con.yHeaCoi, hvac.uHea)
  connect(con.yOutDamPos, hvac.uEco)
  connect(hvac.TSup, con.TSup)
  connect(hvac.TMix, con.TMix)
  connect(hvac.TRet, con.TCut)
  connect(weaBus, sinZonFlo.weaBus)
  connect(con.yCooCoi, hvac.uCooVal)
  connect(hvac.supplyAir, sinZonFlo.ports[1])
  connect(hvac.returnAir, sinZonFlo.ports[2])
  connect(errTRooCoo1.y,hysChiPla1. u)
  connect(hysChiPla1.y, hvac.chiOn)
  connect(con.TZonCooSet, errTRooCoo1.u2)
  connect(con.TOut, weaBus.TDryBul)
  connect(errTRooCoo1.u1, con.TZon)
  connect(TSetSupChiConst.y, hvac.TSetChi)
  connect(sinZonFlo.TRooAir, con.TZon)
  connect(demLim.y, con.uCooDemLimLev)
  connect(demLim.y, con.uHeaDemLimLev)
  connect(sinZonFlo.TRooAir, TZon)
  connect(tNexOcc, con.tNexOcc)
  connect(uOcc, con.uOcc)
  connect(warUpTim, con.warUpTim)
  connect(cooDowTim, con.cooDowTim)

  connect(hvac.weaBus, weaBus)
end ZoneWithAHUG36;


within Buildings.Obsolete;
package BaseClasses "Package with base classes for Buildings.Obsolete"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.Obsolete;
package Controls "Package with obsolete models for controls"
  extends Modelica.Icons.VariantsPackage;
end Controls;


within Buildings.Obsolete.Controls;
package Continuous "Package with obsolete models for continuous time control"
  extends Modelica.Icons.VariantsPackage;
end Continuous;


PID controller with anti-windup, output limiter and output hysteresis. Block of a controller for set point tracking with a hysteresis element that switches the
controller on and off.

within Buildings.Obsolete.Controls.Continuous;
model PIDHysteresis
  "PID controller with anti-windup, output limiter and output hysteresis"
  extends Modelica.Blocks.Interfaces.SVcontrol;
  extends Buildings.Obsolete.BaseClasses.ObsoleteModel;

  parameter Real eOn = 1
    "if off and control error > eOn, switch to set point tracking"
  parameter Real eOff = -eOn "if on and control error < eOff, set y=0"
  parameter Boolean pre_y_start=false
    "Value of hysteresis output at initial time"

  parameter Modelica.Blocks.Types.SimpleController controllerType=Modelica.Blocks.Types.SimpleController.PI
    "Type of controller"
  parameter Real k=1 "Gain of controller"
  parameter Modelica.Units.SI.Time Ti "Time constant of Integrator block"
  parameter Modelica.Units.SI.Time Td "Time constant of Derivative block"
  parameter Real yMax=1 "Upper limit of output"
  parameter Real yMin=0 "Lower limit of output"
  parameter Real wp=1 "Set-point weight for Proportional block (0..1)"
  parameter Real wd=0 "Set-point weight for Derivative block (0..1)"
  parameter Real Ni=0.9 "Ni*Ti is time constant of anti-windup compensation"
  parameter Real Nd=10 "The higher Nd, the more ideal the derivative block"
  parameter Boolean reverseActing = true
    "Set to true for reverse acting, or false for direct acting control action"

  parameter Modelica.Blocks.Types.Init initType=Modelica.Blocks.Types.Init.InitialState
    "Type of initialization (1: no init, 2: steady state, 3: initial state, 4: initial output)"
  parameter Real xi_start=0
    "Initial or guess value value for integrator output (= integrator state)"
  parameter Real xd_start=0
    "Initial or guess value for state of derivative block"
  parameter Real y_start=0 "Initial value of output"

  parameter Boolean strict=true "= true, if strict limits with noEvent(..)"

  Buildings.Controls.Continuous.LimPID PID(
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti,
    final yMax=yMax,
    final yMin=yMin,
    final wp=wp,
    final wd=wd,
    final Ni=Ni,
    final Nd=Nd,
    final initType=initType,
    final xi_start=xi_start,
    final xd_start=xd_start,
    final y_start=y_start,
    final Td=Td,
    final reverseActing=reverseActing,
    final strict=strict) "Controller for room temperature"
  Modelica.Blocks.Logical.Hysteresis hys(
    final pre_y_start=pre_y_start,
    final uLow=eOff,
    final uHigh=eOn) "Hysteresis element to switch controller on and off"
  Modelica.Blocks.Math.Feedback feeBac
protected
  Modelica.Blocks.Logical.Switch swi
  Modelica.Blocks.Sources.Constant zer(final k=0) "Zero signal"
  Modelica.Blocks.Logical.Switch swi1

equation
  assert(eOff < eOn, "Wrong controller parameters. Require eOff < eOn.");
  connect(zer.y, swi.u3)
  connect(swi.y, y)
  connect(u_m, PID.u_m)
  connect(hys.y, swi.u2)
  connect(PID.y, swi.u1)
  connect(u_s, feeBac.u1)
  connect(u_m, feeBac.u2)
  connect(feeBac.y, hys.u)
  connect(u_s, swi1.u1)
  connect(hys.y, swi1.u2)
  connect(u_m, swi1.u3)
  connect(swi1.y, PID.u_s)
end PIDHysteresis;


PID controller with anti-windup, hysteresis and timer to prevent short cycling. Block of a controller for set point tracking with a hysteresis element that switches the controller on and off, and a timer that prevents the
controller to short cycle.

within Buildings.Obsolete.Controls.Continuous;
model PIDHysteresisTimer
  "PID controller with anti-windup, hysteresis and timer to prevent short cycling"
  extends Modelica.Blocks.Interfaces.SVcontrol;
  extends Buildings.Obsolete.BaseClasses.ObsoleteModel;

  parameter Real minOffTime=600
    "Minimum time that devices needs to be off before it can run again"
  parameter Real eOn = 1
    "if off and control error > eOn, switch to set point tracking"
  parameter Real eOff = -eOn "if on and control error < eOff, set y=0"
  parameter Boolean pre_y_start=false
    "Value of hysteresis output at initial time"

  parameter Modelica.Blocks.Types.SimpleController controllerType=Modelica.Blocks.Types.SimpleController.PI
    "Type of controller"
  parameter Real k=1 "Gain of controller"
  parameter Modelica.Units.SI.Time Ti "Time constant of Integrator block"
  parameter Modelica.Units.SI.Time Td "Time constant of Derivative block"
  parameter Real yMax=1 "Upper limit of modulating output"
  parameter Real yMin=0.3
    "Lower limit of modulating output (before switch to 0)"
  parameter Real wp=1 "Set-point weight for Proportional block (0..1)"
  parameter Real wd=0 "Set-point weight for Derivative block (0..1)"
  parameter Real Ni=0.9 "Ni*Ti is time constant of anti-windup compensation"
  parameter Real Nd=10 "The higher Nd, the more ideal the derivative block"
  parameter Boolean reverseActing = true
    "Set to true for reverse acting, or false for direct acting control action"

  parameter Modelica.Blocks.Types.Init initType=Modelica.Blocks.Types.Init.InitialState
    "Type of initialization (1: no init, 2: steady state, 3: initial state, 4: initial output)"
  parameter Real xi_start=0
    "Initial or guess value value for integrator output (= integrator state)"
  parameter Real xd_start=0
    "Initial or guess value for state of derivative block"
  parameter Real y_start=0 "Initial value of output"

  parameter Boolean strict=true "= true, if strict limits with noEvent(..)"

  Modelica.Blocks.Interfaces.RealOutput tOn "Time since boiler switched on"
  Modelica.Blocks.Interfaces.RealOutput tOff "Time since boiler switched off"

  Buildings.Controls.Continuous.LimPID con(
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti,
    final Td=Td,
    final wp=wp,
    final wd=wd,
    final Ni=Ni,
    final Nd=Nd,
    final initType=initType,
    final xi_start=xi_start,
    final xd_start=xd_start,
    final y_start=y_start,
    final yMin=yMin,
    final yMax=yMax,
    final reverseActing=reverseActing,
    final strict=strict) "Controller to track setpoint"
  Buildings.Controls.Continuous.OffTimer offHys
  Modelica.Blocks.Logical.Timer onTimer
  Modelica.Blocks.Logical.Timer offTimer
         Modelica.Blocks.Interfaces.BooleanOutput on
    "Outputs true if boiler is on"
  Modelica.Blocks.Math.Feedback feeBac
  Modelica.Blocks.Logical.Hysteresis hys(
    final pre_y_start=pre_y_start,
    final uLow=eOff,
    final uHigh=eOn) "Hysteresis element to switch controller on and off"
protected
  Modelica.Blocks.Sources.Constant zer(final k=0) "Zero signal"
  Modelica.Blocks.Logical.Switch switch2
  Modelica.Blocks.Logical.GreaterEqualThreshold greaterEqualThreshold(threshold=
       minOffTime)
  Modelica.Blocks.Logical.And and3
  Modelica.Blocks.Logical.Not not1
  Modelica.Blocks.Logical.Switch switch1
equation
  connect(u_m, con.u_m)
  connect(zer.y,switch2. u3)
  connect(switch2.y, y)
  connect(and3.y,switch2. u2)
  connect(greaterEqualThreshold.y, and3.u1)
  connect(offHys.y, greaterEqualThreshold.u)
  connect(con.y,switch2. u1)
  connect(onTimer.y, tOn)
  connect(offTimer.y, tOff)
  connect(and3.y, on)
  connect(and3.y, onTimer.u)
  connect(and3.y, not1.u)
  connect(not1.y, offTimer.u)
  connect(and3.y, switch1.u2)
  connect(u_s, switch1.u1)
  connect(u_m, switch1.u3)
  connect(switch1.y, con.u_s)
  connect(u_s, feeBac.u1)
  connect(u_m, feeBac.u2)
  connect(feeBac.y, hys.u)
  connect(hys.y, offHys.u)
  connect(hys.y, and3.u2)
end PIDHysteresisTimer;


within Buildings.Obsolete.Controls.Continuous;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Example model for PID controller with hysteresis. Example that demonstrates the use of the PID controller
with hysteresis. The control objective is to keep
the temperature of the energy storage cap
at 40°C.
The controller con is parameterized to
switch on if the control error is bigger than
eon=1.
The output of the controller remains above ymin=0.3 until the control
error is smaller than eoff=-1, at which
time the controller outputs y=0 until the
control error is again bigger than 1.
The figure below shows the control error
con.feeBac.y and the control signal
con.y.

within Buildings.Obsolete.Controls.Continuous.Examples;
model PIDHysteresis "Example model for PID controller with hysteresis"
  extends Modelica.Icons.Example;

  Buildings.Obsolete.Controls.Continuous.PIDHysteresis con(
    pre_y_start=false,
    yMin=0.3,
    Ti=600,
    Td=60)
  Modelica.Blocks.Sources.Constant TSet(k=273.15 + 40, y(unit="K")) "Set point"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor cap(C=1000000, T(start=
         313.15, fixed=true))
  Buildings.HeatTransfer.Sources.PrescribedTemperature TBC
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=20)
  Modelica.Blocks.Math.Gain gain(k=2000)
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temSen
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow Q_flow
  Modelica.Blocks.Sources.Sine sine(
    f=1/86400,
    offset=273.15,
    amplitude=20,
    phase=-1.5707963267949,
    y(unit="K"))
equation

  connect(TSet.y, con.u_s)
  connect(TBC.port, theCon.port_a)
  connect(theCon.port_b, cap.port)
  connect(con.y, gain.u)
  connect(cap.port, temSen.port)
  connect(temSen.T, con.u_m)
  connect(gain.y, Q_flow.Q_flow)
  connect(Q_flow.port, cap.port)
  connect(sine.y, TBC.T)
end PIDHysteresis;


Example model for PID controller with hysteresis and timer. Example that demonstrates the use of the PID controller
with hysteresis and off timer.
The example is identical to

Buildings.Obsolete.Controls.Continuous.Examples.PIDHysteresis,
except that the controller also has an off timer.
This timer keeps the control signal at y=0
for a period of minOffTime=1000 seconds.
This may be used to avoid short-cycling if the load is small
and the system has little heat capacity.

within Buildings.Obsolete.Controls.Continuous.Examples;
model PIDHysteresisTimer
  "Example model for PID controller with hysteresis and timer"
  extends Modelica.Icons.Example;

  Buildings.Obsolete.Controls.Continuous.PIDHysteresisTimer con(
    yMin=0.3,
    minOffTime=10000,
    Ti=60,
    Td=10)
  Modelica.Blocks.Sources.Constant TSet(k=273.15 + 40, y(unit="K")) "Set point"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor cap(C=100000, T(start=
          293.15, fixed=true))
  Buildings.HeatTransfer.Sources.PrescribedTemperature TBC
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=10)
  Modelica.Blocks.Math.Gain gain(k=800)
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temSen
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow Q_flow
  Modelica.Blocks.Sources.Sine sine(
    f=1/86400,
    offset=273.15,
    amplitude=20,
    phase=-1.5707963267949)
equation

  connect(TSet.y, con.u_s)
  connect(TBC.port, theCon.port_a)
  connect(theCon.port_b, cap.port)
  connect(con.y, gain.u)
  connect(cap.port, temSen.port)
  connect(temSen.T, con.u_m)
  connect(gain.y, Q_flow.Q_flow)
  connect(Q_flow.port, cap.port)
  connect(sine.y, TBC.T)
end PIDHysteresisTimer;


within Buildings.Obsolete.Controls;
package OBC "Package with obsolete blocks and control sequences"
  extends Modelica.Icons.VariantsPackage;
end OBC;


within Buildings.Obsolete.Controls.OBC;
package ASHRAE "Package with control sequences from ASHRAE projects"
end ASHRAE;


within Buildings.Obsolete.Controls.OBC.ASHRAE;
package G36_PR1 "Package with control sequences from ASHRAE Guideline 36"
end G36_PR1;


within Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1;
package AHUs "AHU Sequences as defined in guideline G36"
end AHUs;


Sequences for multi zone AHU control

within Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs;
package MultiZone "Sequences for multi zone AHU control"
end MultiZone;


Multizone AHU controller that composes subsequences for controlling fan speed, dampers, and supply air temperature. Block that is applied for multizone VAV AHU control. It outputs the supply fan status
and the operation speed, outdoor and return air damper position, supply air
temperature setpoint and the valve position of the cooling and heating coils.
It is implemented according to the ASHRAE Guideline 36, PART 5.N.

within Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.MultiZone.VAV;
block Controller
  "Multizone AHU controller that composes subsequences for controlling fan speed, dampers, and supply air temperature"

  parameter Real samplePeriod(
    final unit="s",
    final quantity="Time")=120
    "Sample period of component, set to the same value to the trim and respond sequence";

  parameter Boolean have_perZonRehBox=true
    "Check if there is any VAV-reheat boxes on perimeter zones"

  parameter Boolean have_duaDucBox=false
    "Check if the AHU serves dual duct boxes"

  parameter Boolean have_airFloMeaSta=false
    "Check if the AHU has AFMS (Airflow measurement station)"

  // ----------- Parameters for economizer control -----------
  parameter Boolean use_enthalpy=false
    "Set to true if enthalpy measurement is used in addition to temperature measurement"

  parameter Real delta(
    final unit="s",
    final quantity="Time")=5
    "Time horizon over which the outdoor air flow measurment is averaged"

  parameter Real delTOutHis(
    final unit="K",
    final displayUnit="K",
    final quantity="TemperatureDifference")=1
    "Delta between the temperature hysteresis high and low limit"

  parameter Real delEntHis(
    final unit="J/kg",
    final quantity="SpecificEnergy")=1000
    "Delta between the enthalpy hysteresis high and low limits"

  parameter Real retDamPhyPosMax(
    final min=0,
    final max=1,
    final unit="1") = 1.0
    "Physically fixed maximum position of the return air damper"

  parameter Real retDamPhyPosMin(
    final min=0,
    final max=1,
    final unit="1") = 0.0
    "Physically fixed minimum position of the return air damper"

  parameter Real outDamPhyPosMax(
    final min=0,
    final max=1,
    final unit="1") = 1.0
    "Physically fixed maximum position of the outdoor air damper"

  parameter Real outDamPhyPosMin(
    final min=0,
    final max=1,
    final unit="1") = 0.0
    "Physically fixed minimum position of the outdoor air damper"

  parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerTypeMinOut=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller"

  parameter Real kMinOut(final unit="1")=0.05
    "Gain of controller for minimum outdoor air intake"

  parameter Real TiMinOut(
    final unit="s",
    final quantity="Time")=120
    "Time constant of controller for minimum outdoor air intake"

  parameter Real TdMinOut(
    final unit="s",
    final quantity="Time")=0.1
    "Time constant of derivative block for minimum outdoor air intake"

  parameter Boolean use_TMix=true
    "Set to true if mixed air temperature measurement is enabled"

  parameter Boolean use_G36FrePro=false
    "Set to true to use G36 freeze protection"

  parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerTypeFre=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller"

  parameter Real kFre(final unit="1/K") = 0.05
    "Gain for mixed air temperature tracking for freeze protection, used if use_TMix=true"

  parameter Real TiFre(
    final unit="s",
    final quantity="Time",
    final max=TiMinOut)=120
    "Time constant of controller for mixed air temperature tracking for freeze protection. Require TiFre <= TiMinOut"

  parameter Real TdFre(
    final unit="s",
    final quantity="Time")=0.1
    "Time constant of derivative block for freeze protection"

  parameter Real TFreSet(
     final unit="K",
     final displayUnit="degC",
     final quantity="ThermodynamicTemperature")= 279.15
    "Lower limit for mixed air temperature for freeze protection, used if use_TMix=true"

  parameter Real retDamFulOpeTim(
    final unit="s",
    final quantity="Time")=180
    "Time period to keep RA damper fully open before releasing it for minimum outdoor airflow control
    at disable to avoid pressure fluctuations"

  parameter Real disDel(
    final unit="s",
    final quantity="Time")=15
    "Short time delay before closing the OA damper at disable to avoid pressure fluctuations"

  // ----------- parameters for fan speed control  -----------
  parameter Real pIniSet(
    final unit="Pa",
    final displayUnit="Pa",
    final quantity="PressureDifference")=60
    "Initial pressure setpoint for fan speed control"

  parameter Real pMinSet(
    final unit="Pa",
    final displayUnit="Pa",
    final quantity="PressureDifference")=25
    "Minimum pressure setpoint for fan speed control"

  parameter Real pMaxSet(
    final unit="Pa",
    final displayUnit="Pa",
    final quantity="PressureDifference")=400
    "Maximum pressure setpoint for fan speed control"

  parameter Real pDelTim(
    final unit="s",
    final quantity="Time")=600
    "Delay time after which trim and respond is activated"

  parameter Integer pNumIgnReq=2
    "Number of ignored requests for fan speed control"

  parameter Real pTriAmo(
    final unit="Pa",
    final displayUnit="Pa",
    final quantity="PressureDifference")=-12.0
    "Trim amount for fan speed control"

  parameter Real pResAmo(
    final unit="Pa",
    final displayUnit="Pa",
    final quantity="PressureDifference")=15
    "Respond amount (must be opposite in to triAmo) for fan speed control"

  parameter Real pMaxRes(
    final unit="Pa",
    final displayUnit="Pa",
    final quantity="PressureDifference")=32
    "Maximum response per time interval (same sign as resAmo) for fan speed control"

  parameter Buildings.Controls.OBC.CDL.Types.SimpleController
    controllerTypeFanSpe=Buildings.Controls.OBC.CDL.Types.SimpleController.PI "Type of controller"

  parameter Real kFanSpe(final unit="1")=0.1
    "Gain of fan fan speed controller, normalized using pMaxSet"

  parameter Real TiFanSpe(
    final unit="s",
    final quantity="Time")=60
    "Time constant of integrator block for fan speed"

  parameter Real TdFanSpe(
    final unit="s",
    final quantity="Time")=0.1
    "Time constant of derivative block for fan speed"

  parameter Real yFanMax=1 "Maximum allowed fan speed"

  parameter Real yFanMin=0.1 "Lowest allowed fan speed if fan is on"

  // ----------- parameters for minimum outdoor airflow setting  -----------
  parameter Real VPriSysMax_flow(
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "Maximum expected system primary airflow at design stage"

  parameter Real peaSysPop "Peak system population"

  // ----------- parameters for supply air temperature control  -----------
  parameter Real TSupSetDes(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")=285.15
    "Design coil leaving air temperature"

  parameter Real TSupSetMin(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")=285.15
    "Lowest cooling supply air temperature setpoint when the outdoor air temperature is at the
    higher value of the reset range and above. This should not be lower than the design coil leaving air temperature"

  parameter Real TSupSetMax(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")=291.15
    "Highest cooling supply air temperature setpoint. It is typically 18 degC (65 degF) in mild and dry climates, 16 degC (60 degF) or lower in humid climates"

  parameter Real TOutMin(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")=289.15
    "Lower value of the outdoor air temperature reset range. Typically value is 16 degC (60 degF)"

  parameter Real TOutMax(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")=294.15
    "Higher value of the outdoor air temperature reset range. Typically value is 21 degC (70 degF)"

  parameter Real TSupWarUpSetBac(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")=308.15
    "Supply temperature in warm up and set back mode"

  parameter Real delTimSupTem(
    final unit="s",
    final quantity="Time")=600
    "Delay timer for supply temperature control"

  parameter Integer numIgnReqSupTem=2
    "Number of ignorable requests for supply temperature control"

  parameter Real triAmoSupTem(
    final unit="K",
    final displayUnit="K",
    final quantity="TemperatureDifference")=0.1
    "Trim amount for supply temperature control"

  parameter Real resAmoSupTem(
    final unit="K",
    final displayUnit="K",
    final quantity="TemperatureDifference")=-0.2
    "Response amount for supply temperature control"

  parameter Real maxResSupTem(
    final unit="K",
    final displayUnit="K",
    final quantity="TemperatureDifference")=-0.6
    "Maximum response per time interval for supply temperature control"

  parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerTypeTSup=
      Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller for supply air temperature signal"

  parameter Real kTSup(final unit="1/K")=0.05
    "Gain of controller for supply air temperature signal"

  parameter Real TiTSup(
    final unit="s",
    final quantity="Time")=600
    "Time constant of integrator block for supply air temperature control signal"

  parameter Real TdTSup(
    final unit="s",
    final quantity="Time")=0.1
    "Time constant of integrator block for supply air temperature control signal"

  parameter Real uHeaMax(min=-0.9)=-0.25
    "Upper limit of controller signal when heating coil is off. Require -1 < uHeaMax < uCooMin < 1."

  parameter Real uCooMin(max=0.9)=0.25
    "Lower limit of controller signal when cooling coil is off. Require -1 < uHeaMax < uCooMin < 1."

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TZonHeaSet(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Zone air temperature heating setpoint"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TZonCooSet(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Zone air temperature cooling setpoint"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Outdoor air temperature"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput ducStaPre(
    final unit="Pa",
    final displayUnit="Pa")
    "Measured duct static pressure"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput sumDesZonPop(
    final min=0,
    final unit="1")
    "Sum of the design population of the zones in the group"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput VSumDesPopBreZon_flow(
    final min=0,
    final unit = "m3/s",
    final quantity = "VolumeFlowRate")
    "Sum of the population component design breathing zone flow rate"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput VSumDesAreBreZon_flow(
    final min=0,
    final unit = "m3/s",
    final quantity = "VolumeFlowRate")
    "Sum of the area component design breathing zone flow rate"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput uDesSysVenEff(
    final min=0,
    final unit = "1")
    "Design system ventilation efficiency, equals to the minimum of all zones ventilation efficiency"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput VSumUncOutAir_flow(
    final min=0,
    final unit = "m3/s",
    final quantity = "VolumeFlowRate")
    "Sum of all zones required uncorrected outdoor airflow rate"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput VSumSysPriAir_flow(
    final min=0,
    final unit = "m3/s",
    final quantity = "VolumeFlowRate")
    "System primary airflow rate, equals to the sum of the measured discharged flow rate of all terminal units"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput uOutAirFra_max(
    final min=0,
    final unit = "1")
    "Maximum zone outdoor air fraction, equals to the maximum of primary outdoor air fraction of all zones"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TSup(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Measured supply air temperature"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOutCut(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "OA temperature high limit cutoff. For differential dry bulb temeprature condition use return air temperature measurement"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput hOut(
    final unit="J/kg",
    final quantity="SpecificEnergy") if use_enthalpy "Outdoor air enthalpy"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput hOutCut(
    final unit="J/kg",
    final quantity="SpecificEnergy") if use_enthalpy
    "OA enthalpy high limit cutoff. For differential enthalpy use return air enthalpy measurement"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput VOut_flow(
    final min=0,
    final unit = "m3/s",
    final quantity = "VolumeFlowRate")
    "Measured outdoor volumetric airflow rate"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TMix(
    final unit="K",
    final displayUnit="degC",
    final quantity = "ThermodynamicTemperature") if use_TMix
    "Measured mixed air temperature, used for freeze protection if use_TMix=true"

  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod
    "AHU operation mode status signal"

  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uZonTemResReq
    "Zone cooling supply air temperature reset request"

  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uZonPreResReq
    "Zone static pressure reset requests"

  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uFreProSta
   if use_G36FrePro
   "Freeze protection status, used if use_G36FrePro=true"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput ySupFan
    "Supply fan status, true if fan should be on"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySupFanSpe(
    final min=0,
    final max=1,
    final unit="1") "Supply fan speed"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TSupSet(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Setpoint for supply air temperature"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VDesUncOutAir_flow(
    final min=0,
    final unit = "m3/s",
    final quantity = "VolumeFlowRate")
    "Design uncorrected minimum outdoor airflow rate"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yAveOutAirFraPlu(
    final min=0,
    final unit = "1")
    "Average outdoor air flow fraction plus 1"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VEffOutAir_flow(
    final min=0,
    final unit = "m3/s",
    final quantity = "VolumeFlowRate")
    "Effective minimum outdoor airflow setpoint"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yReqOutAir
    "True if the AHU supply fan is on and the zone is in occupied mode"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHea(
    final min=0,
    final max=1,
    final unit="1")
    "Control signal for heating"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yCoo(
    final min=0,
    final max=1,
    final unit="1") "Control signal for cooling"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDamPos(
    final min=0,
    final max=1,
    final unit="1") "Return air damper position"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOutDamPos(
    final min=0,
    final max=1,
    final unit="1") "Outdoor air damper position"

  Buildings.Controls.OBC.CDL.Reals.Average TZonSetPoiAve
    "Average of all zone set points"

  Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.MultiZone.VAV.SetPoints.SupplyFan
    supFan(
    final samplePeriod=samplePeriod,
    final have_perZonRehBox=have_perZonRehBox,
    final have_duaDucBox=have_duaDucBox,
    final have_airFloMeaSta=have_airFloMeaSta,
    final iniSet=pIniSet,
    final minSet=pMinSet,
    final maxSet=pMaxSet,
    final delTim=pDelTim,
    final numIgnReq=pNumIgnReq,
    final triAmo=pTriAmo,
    final resAmo=pResAmo,
    final maxRes=pMaxRes,
    final controllerType=controllerTypeFanSpe,
    final k=kFanSpe,
    final Ti=TiFanSpe,
    final Td=TdFanSpe,
    final yFanMax=yFanMax,
    final yFanMin=yFanMin) "Supply fan controller"

  Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.MultiZone.VAV.SetPoints.SupplyTemperature
    supTemSetPoi(
    final TSupWarUpSetBac=TSupWarUpSetBac,
    final samplePeriod=samplePeriod,
    final TSupSetMin=TSupSetMin,
    final TSupSetMax=TSupSetMax,
    final TSupSetDes=TSupSetDes,
    final TOutMin=TOutMin,
    final TOutMax=TOutMax,
    final delTim=delTimSupTem,
    final numIgnReq=numIgnReqSupTem,
    final triAmo=triAmoSupTem,
    final resAmo=resAmoSupTem,
    final maxRes=maxResSupTem) "Setpoint for supply temperature"

  Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.AHU
    sysOutAirSet(final VPriSysMax_flow=VPriSysMax_flow, final peaSysPop=
        peaSysPop) "Minimum outdoor airflow setpoint"

  Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.MultiZone.VAV.Economizers.Controller
    eco(
    final use_enthalpy=use_enthalpy,
    final delTOutHis=delTOutHis,
    final delEntHis=delEntHis,
    final retDamFulOpeTim=retDamFulOpeTim,
    final disDel=disDel,
    final controllerTypeMinOut=controllerTypeMinOut,
    final kMinOut=kMinOut,
    final TiMinOut=TiMinOut,
    final TdMinOut=TdMinOut,
    final retDamPhyPosMax=retDamPhyPosMax,
    final retDamPhyPosMin=retDamPhyPosMin,
    final outDamPhyPosMax=outDamPhyPosMax,
    final outDamPhyPosMin=outDamPhyPosMin,
    final uHeaMax=uHeaMax,
    final uCooMin=uCooMin,
    final uOutDamMax=(uHeaMax + uCooMin)/2,
    final uRetDamMin=(uHeaMax + uCooMin)/2,
    final TFreSet=TFreSet,
    final controllerTypeFre=controllerTypeFre,
    final kFre=kFre,
    final TiFre=TiFre,
    final TdFre=TdFre,
    final delta=delta,
    final use_TMix=use_TMix,
    final use_G36FrePro=use_G36FrePro) "Economizer controller"

  Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.MultiZone.VAV.SetPoints.SupplySignals
    val(
    final controllerType=controllerTypeTSup,
    final kTSup=kTSup,
    final TiTSup=TiTSup,
    final TdTSup=TdTSup,
    final uHeaMax=uHeaMax,
    final uCooMin=uCooMin) "AHU coil valve control"

protected
  Buildings.Controls.OBC.CDL.Reals.Divide VOut_flow_normalized(
    u1(final unit="m3/s"),
    u2(final unit="m3/s"),
    y(final unit="1"))
    "Normalization of outdoor air flow intake by design minimum outdoor air intake"

equation
  connect(eco.yRetDamPos, yRetDamPos)
  connect(eco.yOutDamPos, yOutDamPos)
  connect(eco.uSupFan, supFan.ySupFan)
  connect(supFan.ySupFanSpe, ySupFanSpe)
  connect(TOut, eco.TOut)
  connect(eco.TOutCut, TOutCut)
  connect(eco.hOut, hOut)
  connect(eco.hOutCut, hOutCut)
  connect(eco.uOpeMod, uOpeMod)
  connect(supTemSetPoi.TSupSet, TSupSet)
  connect(supTemSetPoi.TOut, TOut)
  connect(supTemSetPoi.uSupFan, supFan.ySupFan)
  connect(supTemSetPoi.uZonTemResReq, uZonTemResReq)
  connect(supTemSetPoi.uOpeMod, uOpeMod)
  connect(supFan.uOpeMod, uOpeMod)
  connect(supFan.uZonPreResReq, uZonPreResReq)
  connect(supFan.ducStaPre, ducStaPre)
  connect(supTemSetPoi.TZonSetAve, TZonSetPoiAve.y)
  connect(supFan.ySupFan, ySupFan)
  connect(TZonSetPoiAve.u2, TZonCooSet)
  connect(eco.TMix, TMix)
  connect(TSup, val.TSup)
  connect(supFan.ySupFan, val.uSupFan)
  connect(val.uTSup, eco.uTSup)
  connect(val.yHea, yHea)
  connect(val.yCoo, yCoo)
  connect(supTemSetPoi.TSupSet, val.TSupSet)
  connect(TZonHeaSet, TZonSetPoiAve.u1)
  connect(eco.uFreProSta, uFreProSta)
  connect(eco.VOut_flow_normalized, VOut_flow_normalized.y)
  connect(VOut_flow_normalized.u1, VOut_flow)
  connect(sysOutAirSet.VDesUncOutAir_flow, VDesUncOutAir_flow)
  connect(sysOutAirSet.VDesOutAir_flow, VOut_flow_normalized.u2)
  connect(sysOutAirSet.effOutAir_normalized, eco.VOutMinSet_flow_normalized)
  connect(supFan.ySupFan, sysOutAirSet.uSupFan)
  connect(uOpeMod, sysOutAirSet.uOpeMod)
  connect(sysOutAirSet.yAveOutAirFraPlu, yAveOutAirFraPlu)
  connect(sysOutAirSet.VEffOutAir_flow, VEffOutAir_flow)
  connect(sysOutAirSet.yReqOutAir, yReqOutAir)
  connect(sysOutAirSet.sumDesZonPop, sumDesZonPop)
  connect(sysOutAirSet.VSumDesPopBreZon_flow, VSumDesPopBreZon_flow)
  connect(sysOutAirSet.VSumDesAreBreZon_flow, VSumDesAreBreZon_flow)
  connect(sysOutAirSet.uDesSysVenEff, uDesSysVenEff)
  connect(sysOutAirSet.VSumUncOutAir_flow, VSumUncOutAir_flow)
  connect(sysOutAirSet.VSumSysPriAir_flow, VSumSysPriAir_flow)
  connect(uOutAirFra_max, sysOutAirSet.uOutAirFra_max)
end Controller;


within Buildings.Obsolete.Controls.OBC.ASHRAE.G36_PR1.AHUs.MultiZone;
package VAV "Sequences for multi zone VAV AHU control"
end VAV;