Validation of model that generates system requests. This example validates

Buildings.Controls.OBC.ASHRAE.G36.TerminalUnits.SeriesFanVVF.Subsequences.SystemRequests
for generating system requests.

within Buildings.Controls.OBC.ASHRAE.G36.TerminalUnits.SeriesFanVVF.Subsequences.Validation;
model SystemRequests
  "Validation of model that generates system requests"

  Buildings.Controls.OBC.ASHRAE.G36.TerminalUnits.SeriesFanVVF.Subsequences.SystemRequests sysReq(
    final floHys=0.01,
    final looHys=0.01,
    final damPosHys=0.01,
    final valPosHys=0.01) "Block outputs system requests"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin sine(
    final freqHz=1/7200,
    final offset=296.15)
    "Generate data for setpoint"
  Buildings.Controls.OBC.CDL.Discrete.UnitDelay TCooSet(
    final samplePeriod=1800) "Cooling setpoint temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin TZon(
    final freqHz=1/7200,
    final amplitude=2,
    final offset=299.15)
    "Zone temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp uCoo(
    final height=-1,
    final duration=2000,
    final offset=1,
    final startTime=1000)
    "Cooling loop signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp disAirSet(
    final height=0.9,
    final duration=7200,
    final offset=0.1) "Discharge airflow rate setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp disAir(
    final duration=7200,
    final offset=0.1,
    final height=0.3) "Discharge airflow rate"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp damPos(
    final duration=3000,
    final height=-0.7,
    final offset=0.7) "Damper position"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul(
    final width=0.1,
    final period=7200)
    "After suppression"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TDis(
    final duration=3600,
    final offset=273.15 + 20,
    final height=-5)
    "Discharge air temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TDisSet(
    final k=273.15 + 30)
    "Discharge airflow temperature setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp valPos(
    final duration=2000,
    final height=-0.7,
    final offset=0.7,
    final startTime=3600) "Valve position"
  Buildings.Controls.OBC.CDL.Logical.Not not1
    "Logical not"
equation
  connect(sine.y, TCooSet.u)
  connect(TCooSet.y, sysReq.TCooSet)
  connect(TZon.y, sysReq.TZon)
  connect(uCoo.y, sysReq.uCoo)
  connect(disAirSet.y, sysReq.VSet_flow)
  connect(disAir.y,sysReq.VPri_flow)
  connect(damPos.y, sysReq.uDam)
  connect(TDisSet.y, sysReq.TDisSet)
  connect(TDis.y, sysReq.TDis)
  connect(valPos.y, sysReq.uVal)
  connect(booPul.y, not1.u)
  connect(not1.y, sysReq.uAftSup)
end SystemRequests;


Validation of model that controls series-fan powered unit with variable volume fan. This example validates

Buildings.Controls.OBC.ASHRAE.G36.TerminalUnits.SeriesFanVVF.Controller.

within Buildings.Controls.OBC.ASHRAE.G36.TerminalUnits.SeriesFanVVF.Validation;
model Controller
  "Validation of model that controls series-fan powered unit with variable volume fan"

  Buildings.Controls.OBC.ASHRAE.G36.TerminalUnits.SeriesFanVVF.Controller serFanCon(
    final venStd=Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1,
    final VAreBreZon_flow=0.006,
    final VPopBreZon_flow=0.005,
    final VMin_flow=0.5,
    final VCooMax_flow=1.5,
    final maxRat=2,
    final controllerTypeVal=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    final staPreMul=1,
    final hotWatRes=1,
    final floHys=0.01,
    final looHys=0.01,
    final damPosHys=0.01,
    final valPosHys=0.01,
    final VOccMin_flow=0,
    final VAreMin_flow=0)
    "Series-fan powered unit controller"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin TZon(
    final freqHz=1/86400,
    final amplitude=4,
    final offset=299.15)
    "Zone temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp disAirTem(
    final height=2,
    final duration=43200,
    final offset=273.15 + 15,
    final startTime=28800)
    "Discharge airflow temperture"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse winSta(
    final width=0.05,
    final period=43200,
    final shift=43200)
    "Window opening status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant cooSet(
    final k=273.15 + 24)
    "Zone cooling setpoint temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant heaSet(
    final k=273.15 + 20)
    "Zone heating setpoint temperature"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse occ(
    final width=0.75,
    final period=43200,
    final shift=28800) "Occupancy status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp opeMod(
    final offset=1,
    final height=2,
    final duration=28800,
    final startTime=28800)
    "Operation mode"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2
    "Convert real to integer"
  Buildings.Controls.OBC.CDL.Reals.Round round2(
    final n=0)
    "Round real number to given digits"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin CO2(
    final amplitude=400,
    final freqHz=1/28800,
    final offset=600) "CO2 concentration"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin parFanFlo(
    final offset=1.2,
    final amplitude=0.6,
    final freqHz=1/28800) "Parallel fan flow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp oveFlo(
    final height=2,
    final duration=10000,
    final startTime=35000)
    "Override flow setpoint"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1
    "Convert real to integer"
  Buildings.Controls.OBC.CDL.Reals.Round round1(
    final n=0)
    "Round real number to given digits"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp oveDam(
    final height=2,
    final duration=5000,
    startTime=60000) "Override damper position"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt3
    "Convert real to integer"
  Buildings.Controls.OBC.CDL.Reals.Round round3(
    final n=0)
    "Round real number to given digits"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp oveTerFan(
    final height=2,
    final duration=5000,
    final startTime=60000) "Override terminal fan control"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt4
    "Convert real to integer"
  Buildings.Controls.OBC.CDL.Reals.Round round4(
    final n=0)
    "Round real number to given digits"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin TSup(
    final offset=273.15 + 13,
    final amplitude=1,
    final freqHz=1/28800) "Supply air temperature from air handling unit"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse heaOff(
    final width=0.75,
    final period=3600)
    "Close heating valve"
  Buildings.Controls.OBC.CDL.Logical.Not not1
    "Logical not"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant terFan(
    final k=true)
    "Terminal fan status"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse hotPla(
    final width=0.9,
    final period=7500)
    "Hot water plant status"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse supFan(
    final width=0.75,
    final period=7500)
    "AHU supply fan status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TSupSet(
    final k=273.15 + 13)
    "AHU supply air temperature setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin disFlo(
    final offset=1.3,
    final amplitude=0.6,
    final freqHz=1/28800) "Discharge airflow rate"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant CO2Set(final k=894)
    "CO2 concentration setpoint"
  Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not"
equation
  connect(TZon.y,serFanCon. TZon)
  connect(cooSet.y,serFanCon. TCooSet)
  connect(heaSet.y,serFanCon. THeaSet)
  connect(occ.y, serFanCon.u1Occ)
  connect(opeMod.y,round2. u)
  connect(round2.y,reaToInt2. u)
  connect(reaToInt2.y,serFanCon. uOpeMod)
  connect(CO2.y,serFanCon. ppmCO2)
  connect(oveFlo.y,round1. u)
  connect(round1.y,reaToInt1. u)
  connect(oveDam.y, round3.u)
  connect(round3.y,reaToInt3. u)
  connect(reaToInt1.y,serFanCon. oveFloSet)
  connect(oveTerFan.y, round4.u)
  connect(round4.y,reaToInt4. u)
  connect(disAirTem.y,serFanCon. TDis)
  connect(reaToInt3.y,serFanCon. oveDamPos)
  connect(reaToInt4.y,serFanCon. oveFan)
  connect(heaOff.y, not1.u)
  connect(not1.y,serFanCon. uHeaOff)
  connect(supFan.y, serFanCon.u1Fan)
  connect(terFan.y, serFanCon.u1TerFan)
  connect(hotPla.y, serFanCon.u1HotPla)
  connect(TSupSet.y,serFanCon. TSupSet)
  connect(TSup.y,serFanCon. TSup)
  connect(disFlo.y,serFanCon.VPri_flow)
  connect(CO2Set.y, serFanCon.ppmCO2Set)
  connect(winSta.y, not2.u)
  connect(not2.y, serFanCon.u1Win)
end Controller;


Collection of validation models

within Buildings.Controls.OBC.ASHRAE.G36.TerminalUnits.SeriesFanVVF;
package Validation "Collection of validation models"
end Validation;


Zone level alarms. This block outputs zone alarms. The implementation is according to the ASHRAE
Guideline 36, Section 5.3.6.

within Buildings.Controls.OBC.ASHRAE.G36.ThermalZones;
block Alarms "Zone level alarms"

  parameter Real timChe(
    final unit="s",
    final quantity="Time")=600
    "Threshold time to check temperature difference"
  parameter Boolean have_CO2Sen=false
    "True: the zone has CO2 sensor"
  parameter Real modChe(
    final unit="s",
    final quantity="Time")=7200
    "Threshold time to check unoccupied time"
  parameter Real CO2Set=894
    "CO2 setpoint in ppm"
  parameter Real dTHys(
    final unit="K",
    final quantity="TemperatureDifference")=0.25
    "Delta between the temperature hysteresis high and low limit"
  parameter Real ppmHys(
    final unit="1")=25
    "Hysteresis to check CO2 concentration"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TZon(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Measured zone temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TCooSet(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Zone cooling setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaSet(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Zone heating setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1ResSet
    "True: zone setpoint temperature is being resetted"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod
    "AHU operation mode status signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput ppmCO2(
    final unit="1") if have_CO2Sen
    "Measured CO2 concentration"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yTemAla
    "Zone temperature alarm"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yCO2Ala if have_CO2Sen
    "CO2 concentration alarm"

  Buildings.Controls.OBC.CDL.Reals.Subtract lowTem
    "Zone temperature below the heating setpoint"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold twoDegLow(
    final t=2,
    final h=dTHys)
    "Check if the zone temperature is 2 degC lower than the heating setpoint"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold thrDegLow(
    final t=3,
    final h=dTHys)
    "Check if the zone temperature is 3 degC lower than the heating setpoint"
  Buildings.Controls.OBC.CDL.Reals.Subtract higTem
    "Zone temperature above the cooling setpoint"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold twoDegHig(
    final t=2,
    final h=dTHys)
    "Check if the zone temperature is 2 degC higher than the cooling setpoint"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold thrDegHig(
    final t=3,
    final h=dTHys)
    "Check if the zone temperature is 3 degC higher than the cooling setpoint"
  Buildings.Controls.OBC.CDL.Utilities.Assert higTemAla3(
    final message="Warning: zone temperature is 2 degC higher than the cooling setpoint")
    "Level 3 high temperature alarm"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not"
  Buildings.Controls.OBC.CDL.Logical.Not notSupTemAla
    "Do not suppress temperature alarms"
  Buildings.Controls.OBC.CDL.Logical.And and2
    "Check if alarms should be generated"
  Buildings.Controls.OBC.CDL.Logical.And and1
    "Check if alarms should be generated"
  Buildings.Controls.OBC.CDL.Logical.And and3
    "Check if alarms should be generated"
  Buildings.Controls.OBC.CDL.Logical.And and4
    "Check if alarms should be generated"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt(
    final integerTrue=3)
    "Level 3 high temperature alarm"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt2(
    final integerTrue=3)
    "Level 3 low temperature alarm"
  Buildings.Controls.OBC.CDL.Integers.Equal levThrHig
    "Check if generating level 3 high temperature alarm"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant levTwo(
    final k=2) "Level 2 alarm"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant levThr(
    final k=3) "Level 3 alarm"
  Buildings.Controls.OBC.CDL.Utilities.Assert higTemAla2(
    final message="Warning: zone temperature is 3 degC higher than the cooling setpoint")
    "Level 2 high temperature alarm"
  Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not"
  Buildings.Controls.OBC.CDL.Integers.Equal levTwoHig
    "Check if generating level 2 high temperature alarm"
  Buildings.Controls.OBC.CDL.Utilities.Assert lowTemAla3(
    final message="Warning: zone temperature is 2 degC lower than the heating setpoint")
    "Level 3 low temperature alarm"
  Buildings.Controls.OBC.CDL.Logical.Not not3 "Logical not"
  Buildings.Controls.OBC.CDL.Integers.Equal levThrLow
    "Check if generating level 3 low temperature alarm"
  Buildings.Controls.OBC.CDL.Utilities.Assert lowTemAla2(
    final message="Warning: zone temperature is 3 degC lower than the heating setpoint")
    "Level 2 low temperature alarm"
  Buildings.Controls.OBC.CDL.Logical.Not not4 "Logical not"
  Buildings.Controls.OBC.CDL.Integers.Equal levTwoLow
    "Check if generating level 2 low temperature alarm"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lesThr(
    final t=300,
    final h=ppmHys) if have_CO2Sen
    "Check if the CO2 concentration is less than threshold"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(
    final t=600,
    final h=ppmHys) if have_CO2Sen
    "Check if the CO2 concentration is greater than threshold"
  Buildings.Controls.OBC.CDL.Logical.And and5 if have_CO2Sen
    "Check if it has been in unoccupied mode for long time and CO2 concentration exceeds threshold"
  Buildings.Controls.OBC.CDL.Utilities.Assert lowTemAla4(
    final message="Warning: the zone CO2 concentration exceeds 600 ppm in unoccupied mode. The CO2 sensor may be out of calibration.")
    if have_CO2Sen "Level 3 CO2 alarm"
  Buildings.Controls.OBC.CDL.Logical.Not not5 if have_CO2Sen "Logical not"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr1(
    final t=1.1*CO2Set,
    final h=ppmHys) if have_CO2Sen
    "Check if the CO2 concentration exceeds setpoint plus 10%"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt4(
    final integerTrue=3) if have_CO2Sen
    "Level 3 CO2 concentration alarm"
  Buildings.Controls.OBC.CDL.Logical.Not not6 if have_CO2Sen "Logical not"
  Buildings.Controls.OBC.CDL.Logical.And and6 if have_CO2Sen
    "Check if it has been in unoccupied mode for long time and CO2 concentration exceeds threshold"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt5(
    final integerTrue=2) if have_CO2Sen
    "Level 2 CO2 concentration alarm"
  Buildings.Controls.OBC.CDL.Utilities.Assert lowTemAla5(
    final message="Warning: the zone CO2 concentration exceeds setpoint plus 10%.")
    if have_CO2Sen "Level 2 CO2 alarm"
  Buildings.Controls.OBC.CDL.Integers.Add temAla
    "Zone temperature alarm"
  Buildings.Controls.OBC.CDL.Integers.Add co2Ala if have_CO2Sen
    "CO2 concentration alarm"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay tenMinDur(
    final delayTime=timChe)
    "Check if it has been over threshold time"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay tenMinDur1(
    final delayTime=timChe)
    "Check if it has been over threshold time"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay tenMinDur2(
    final delayTime=timChe)
    "Check if it has been over threshold time"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay tenMinDur3(
    final delayTime=timChe)
    "Check if it has been over threshold time"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant cooDowMod(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.coolDown)
    "Cool down mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant warUpMod(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.warmUp)
    "Warm-up mode"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu3
    "Check if current operation mode is setback mode"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu4
    "Check if current operation mode is warmup mode"
  Buildings.Controls.OBC.CDL.Logical.Or or2
    "Cooldown or warm-up mode"
  Buildings.Controls.OBC.CDL.Logical.Or or1
    "Check if the zone temperature alarms should be suppressed"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu1 if have_CO2Sen
    "Check if current operation mode is warmup mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant unoMod(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.unoccupied)
    if have_CO2Sen "Unoccupied mode"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay twoHou(
    final delayTime=modChe) if have_CO2Sen
    "Check if it has been in unoccupied mode by threshold time"
  Buildings.Controls.OBC.CDL.Logical.Or or3 if have_CO2Sen
    "Check if should generate level 3 alarm"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay tenMinDur4(
    final delayTime=timChe) if have_CO2Sen
    "Check if it has been over threshold time"
  Buildings.Controls.OBC.CDL.Integers.Switch higTemAla
    "High temperature alarms"
  Buildings.Controls.OBC.CDL.Integers.Switch lowTemAla
    "Low temperature alarms"

equation
  connect(lowTem.y, twoDegLow.u)
  connect(lowTem.y, thrDegLow.u)
  connect(higTem.y, twoDegHig.u)
  connect(higTem.y, thrDegHig.u)
  connect(TZon, higTem.u1)
  connect(TCooSet, higTem.u2)
  connect(THeaSet, lowTem.u1)
  connect(cooDowMod.y, intEqu3.u1)
  connect(warUpMod.y, intEqu4.u1)
  connect(uOpeMod, intEqu3.u2)
  connect(uOpeMod, intEqu4.u2)
  connect(intEqu3.y, or2.u1)
  connect(intEqu4.y, or2.u2)
  connect(u1ResSet, or1.u1)
  connect(or2.y, or1.u2)
  connect(or1.y, notSupTemAla.u)
  connect(twoDegHig.y, and2.u1)
  connect(thrDegHig.y, and1.u1)
  connect(twoDegLow.y, and3.u1)
  connect(thrDegLow.y, and4.u1)
  connect(and2.y, tenMinDur2.u)
  connect(and1.y, tenMinDur3.u)
  connect(and3.y, tenMinDur.u)
  connect(and4.y, tenMinDur1.u)
  connect(not1.y, higTemAla3.u)
  connect(tenMinDur2.y, booToInt.u)
  connect(tenMinDur.y, booToInt2.u)
  connect(notSupTemAla.y, and2.u2)
  connect(notSupTemAla.y, and1.u2)
  connect(notSupTemAla.y, and3.u2)
  connect(notSupTemAla.y, and4.u2)
  connect(not2.y, higTemAla2.u)
  connect(not3.y, lowTemAla3.u)
  connect(not4.y, lowTemAla2.u)
  connect(levThrHig.y, not1.u)
  connect(levTwoHig.y, not2.u)
  connect(levThrLow.y, not3.u)
  connect(levTwoLow.y, not4.u)
  connect(levThr.y, levThrHig.u2)
  connect(levThr.y, levThrLow.u2)
  connect(levTwo.y, levTwoHig.u2)
  connect(levTwo.y, levTwoLow.u2)
  connect(unoMod.y, intEqu1.u1)
  connect(uOpeMod, intEqu1.u2)
  connect(ppmCO2, greThr.u)
  connect(intEqu1.y, twoHou.u)
  connect(twoHou.y, and5.u1)
  connect(greThr.y, and5.u2)
  connect(ppmCO2, lesThr.u)
  connect(and5.y, or3.u1)
  connect(lesThr.y, or3.u2)
  connect(not5.y, lowTemAla4.u)
  connect(greThr1.y, tenMinDur4.u)
  connect(ppmCO2, greThr1.u)
  connect(or3.y, and6.u1)
  connect(tenMinDur4.y, not6.u)
  connect(not6.y, and6.u2)
  connect(and6.y, not5.u)
  connect(and6.y, booToInt4.u)
  connect(tenMinDur4.y, booToInt5.u)
  connect(not6.y, lowTemAla5.u)
  connect(booToInt4.y, co2Ala.u1)
  connect(booToInt5.y, co2Ala.u2)
  connect(temAla.y, yTemAla)
  connect(co2Ala.y, yCO2Ala)
  connect(TZon, lowTem.u2)
  connect(tenMinDur3.y, higTemAla.u2)
  connect(tenMinDur1.y, lowTemAla.u2)
  connect(levTwo.y, higTemAla.u1)
  connect(levTwo.y, lowTemAla.u1)
  connect(booToInt.y, higTemAla.u3)
  connect(booToInt2.y, lowTemAla.u3)
  connect(higTemAla.y, levTwoHig.u1)
  connect(higTemAla.y, levThrHig.u1)
  connect(higTemAla.y, temAla.u1)
  connect(lowTemAla.y, levTwoLow.u1)
  connect(lowTemAla.y, levThrLow.u1)
  connect(lowTemAla.y, temAla.u2)
end Alarms;


Heating and cooling control loops. This block outputs the heating and cooling control loop signal. The implementation
is according to the ASHRAE Guideline 36, Section 5.3.4.

within Buildings.Controls.OBC.ASHRAE.G36.ThermalZones;
block ControlLoops "Heating and cooling control loops"

  parameter Real kCooCon=0.1
    "Gain of controller for cooling control loop"
  parameter Real TiCooCon(unit="s")=900
    "Time constant of integrator block for cooling control loop"
  parameter Real kHeaCon=0.1
    "Gain of controller for heating control loop"
  parameter Real TiHeaCon(unit="s")=900
    "Time constant of integrator block for heating control loop"
  parameter Real timChe(unit="s")=30
    "Threshold time to check the zone temperature status"
  parameter Real dTHys(unit="K")=0.25
    "Delta between the temperature hysteresis high and low limit"
  parameter Real looHys(unit="1")=0.01
    "Threshold value to check if the controller output is near zero"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TCooSet(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Zone cooling setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TZon(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Measured zone temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaSet(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Zone heating setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yCoo(
    final min=0,
    final max=1,
    final unit="1") "Cooling control signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHea(
    final min=0,
    final max=1,
    final unit="1") "Heating control signal"
  Buildings.Controls.OBC.CDL.Reals.PIDWithReset conCoo(
    final controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    final k=kCooCon,
    final Ti=TiCooCon,
    final reverseActing=false)
    "Cooling controller"
  Buildings.Controls.OBC.CDL.Reals.PIDWithReset conHea(
    final controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    final k=kHeaCon,
    final Ti=TiHeaCon)
    "Heating controller"

protected
  Buildings.Controls.OBC.CDL.Reals.Less enaHeaLoo(
    final h=dTHys)
    "Check if heating control loop should be enabled"
  Buildings.Controls.OBC.CDL.Reals.Less enaCooLoo(
    final h=dTHys)
    "Check if cooling control loop should be enabled"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay disCoo(
    final delayTime=timChe)
    "Check if the controller output has been near zero for a threshold time"
  Buildings.Controls.OBC.CDL.Logical.Not colZon
    "Check if the zone temperature is lower than the cooling setpoint"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal zerCoo(
    final realTrue=0,
    final realFalse=1)
    "Output zero control signal when the cooling loop should be disabled"
  Buildings.Controls.OBC.CDL.Reals.Multiply cooConSig
    "Cooling control loop signal"
  Buildings.Controls.OBC.CDL.Logical.Not holZon
    "Check if the zone temperature is higher than the heating setpoint"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay disHea(
    final delayTime=timChe)
    "Check if the controller output has been near zero for a threshold time"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal zerHea(
    final realTrue=0,
    final realFalse=1)
    "Output zero control signal when the heating loop should be disabled"
  Buildings.Controls.OBC.CDL.Reals.Multiply heaConSig
    "Heating control loop signal"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold zerCon(
    final t=looHys, final h=0.8*looHys)
    "Check if the controller output is near zero"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold zerCon1(
    final t=looHys, final h=0.8*looHys)
    "Check if the controller output is near zero"
  Buildings.Controls.OBC.CDL.Logical.And disCooCon
    "Check if disable cooling control loop"
  Buildings.Controls.OBC.CDL.Logical.And disHeaCon
    "Check if disable heating control loop"

equation
  connect(TZon, enaHeaLoo.u1)
  connect(THeaSet, enaHeaLoo.u2)
  connect(TZon, enaCooLoo.u2)
  connect(TCooSet, enaCooLoo.u1)
  connect(TCooSet,conCoo. u_s)
  connect(TZon,conCoo. u_m)
  connect(enaCooLoo.y,conCoo. trigger)
  connect(enaCooLoo.y, colZon.u)
  connect(conCoo.y, cooConSig.u1)
  connect(THeaSet,conHea. u_s)
  connect(TZon,conHea. u_m)
  connect(enaHeaLoo.y, holZon.u)
  connect(enaHeaLoo.y,conHea. trigger)
  connect(conHea.y, heaConSig.u1)
  connect(zerCon.y, disCoo.u)
  connect(conCoo.y, zerCon.u)
  connect(conHea.y, zerCon1.u)
  connect(zerCon1.y, disHea.u)
  connect(disCoo.y, disCooCon.u1)
  connect(disCooCon.y, zerCoo.u)
  connect(colZon.y, disCooCon.u2)
  connect(zerCoo.y, cooConSig.u2)
  connect(disHea.y, disHeaCon.u1)
  connect(holZon.y, disHeaCon.u2)
  connect(disHeaCon.y, zerHea.u)
  connect(zerHea.y, heaConSig.u2)
  connect(cooConSig.y, yCoo)
  connect(heaConSig.y, yHea)
end ControlLoops;


within Buildings.Controls.OBC.ASHRAE.G36;
package ThermalZones "Package of sequences for calculating temperature setpoint"
end ThermalZones;


Block outputs thermal zone cooling and heating active setpoint. This sequence sets the thermal zone cooling and heating active setpoints. The implementation
is according to the ASHRAE Guideline 36, Section 5.3.2. The calculation is done
following the steps below.

within Buildings.Controls.OBC.ASHRAE.G36.ThermalZones;
block Setpoints
  "Block outputs thermal zone cooling and heating active setpoint"

  parameter Boolean have_occSen "Check if the zone has occupancy sensor"
  parameter Boolean have_winSen
    "Check if the zone has window status sensor"
  parameter Boolean have_locAdj=true
    "True: the zone has local setpoint adjustment knob"
  parameter Boolean sepAdj=true
    "True: cooling and heating setpoint can be adjusted separately"
  parameter Boolean ignDemLim = true
    "True: exempt the individual zone from demand limit setpoint adjustment"
  parameter Real TActCoo_max(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=300.15
    "Maximum active cooling setpoint"
  parameter Real TActCoo_min(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=295.15
    "Minimum active cooling setpoint"
  parameter Real TActHea_max(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=295.15
    "Maximum active heating setpoint"
  parameter Real TActHea_min(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=291.15
    "Minimum active heating setpoint"
  parameter Real TWinOpeCooSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=322.15
    "Cooling setpoint when window is open"
  parameter Real TWinOpeHeaSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=277.15
    "Heating setpoint when window is open"
  parameter Real incTSetDem_1(unit="K")=0.5
    "Cooling setpoint increase value (degC) when cooling demand limit level 1 is imposed"
  parameter Real incTSetDem_2(unit="K")=1
    "Cooling setpoint increase value (degC) when cooling demand limit level 2 is imposed"
  parameter Real incTSetDem_3(unit="K")=2
    "Cooling setpoint increase value (degC) when cooling demand limit level 3 is imposed"
  parameter Real decTSetDem_1(unit="K")=0.5
    "Heating setpoint decrease value (degC) when heating demand limit level 1 is imposed"
  parameter Real decTSetDem_2(unit="K")=1
    "Heating setpoint decrease value (degC) when heating demand limit level 2 is imposed"
  parameter Real decTSetDem_3(unit="K")=2
    "Heating setpoint decrease value (degC) when heating demand limit level 3 is imposed"

  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod
    "AHU operation mode status signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOccCooSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Occupied zone cooling setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TUnoCooSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Unoccupied zone cooling setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOccHeaSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Occupied zone heating setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TUnoHeaSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Unoccupied zone heating setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput setAdj(
    final unit="K",
    final quantity="TemperatureDifference")
    if have_locAdj and not sepAdj
    "The adjustment value for both heating and cooling setpoints if it allows only single setpoint adjustment"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput cooSetAdj(
    final unit="K",
    final quantity="TemperatureDifference")
    if have_locAdj and sepAdj
    "Cooling setpoint adjustment value"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput heaSetAdj(
    final unit="K",
    final quantity="TemperatureDifference")
    if have_locAdj and sepAdj
    "Heating setpoint adjustment value"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uCooDemLimLev
    "Cooling demand limit level"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uHeaDemLimLev
    "Heating demand limit level"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Occ if have_occSen
    "Occupancy sensor (occupied=true, unoccupied=false)"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Win if have_winSen
    "Window status, normally closed (true), when windows open, it becomes false"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TCooSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Cooling setpoint temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput THeaSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Heating setpoint temperature"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yAla "Alarm level"

protected
  Buildings.Controls.OBC.CDL.Logical.Or or2
    "Check if there is cooling/heating demand limit being imposed"
  Buildings.Controls.OBC.CDL.Logical.Edge edg "If demand limit is imposed"
  Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler cooSetFre
    "Freeze current cooling setpoint when demand limit is imposed"
  Buildings.Controls.OBC.CDL.Logical.Not not3 "Logical not"
  Buildings.Controls.OBC.CDL.Logical.Or or5
    "Check if demand limit should be ignored or if there is no demand limit"
  Buildings.Controls.OBC.CDL.Logical.Or or1
    "Check if cooling demand limit level is imposed"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Logic not"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar3(
    final p=incTSetDem_3)
    "Increase cooling setpoint when at demand limit level 3"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar1(
    final p=incTSetDem_2)
    "Increase cooling setpoint when at demand limit level 2"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar2(
    final p=incTSetDem_1)
    "Increase cooling setpoint when at demand limit level 1"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro6
    "Output product of the two inputs"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro
    "Output product of the two inputs"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro1
    "Output product of the two inputs"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro2
    "Output product of the two inputs"
  Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler heaSetFre
    "Freeze current heating setpoint when demand limit is imposed"
  Buildings.Controls.OBC.CDL.Logical.Or or4
    "Check if heating demand limit level is imposed"
  Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro7
    "Output product of the two inputs"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar6(
    final p=-decTSetDem_1)
    "Decrease heating setpoint when at demand limit level 1"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar5(
    final p=-decTSetDem_2)
    "Decrease heating setpoint when at demand limit level 2"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar4(
    final p=-decTSetDem_3)
    "Decrease heating setpoint when at demand limit level 3"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro5
    "Output product of the two inputs"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro4
    "Output product of the two inputs"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro3
    "Output product of the two inputs"
  Buildings.Controls.OBC.CDL.Logical.Timer tim(
    final t=300)
    "Check whether the zone has been unpopulated for 5 minutes continuously during occupied mode"
  Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truHol(
    final falseHoldDuration=0,
    final trueHoldDuration=60)
    "When the zone is unpopulated by more than threshold time and then becomes populated, hold the change by short period"
  Buildings.Controls.OBC.CDL.Logical.Edge edg1
    "Instant when the zone becomes more than 5 minutes"
  Buildings.Controls.OBC.CDL.Reals.AddParameter heaSetDec(
    final p=-0.5)
    "Heating setpoint decrease due to continuously unpopulated under occupied mode"
  Buildings.Controls.OBC.CDL.Reals.AddParameter cooSetInc(
    final p=0.5)
    "Cooling setpoint increase due to continuously unpopulated under occupied mode"
  Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler cooSetSam
    "Sample current cooling setpoint when zone becomes unpopulated by 5 minutes"
  Buildings.Controls.OBC.CDL.Discrete.TriggeredSampler heaSetSam
    "Sample current heating setpoint when zone becomes unpopulated by 5 minutes"
  Buildings.Controls.OBC.CDL.Reals.Add add1 "Adjusted heating setpoint"
  Buildings.Controls.OBC.CDL.Reals.Add add2 "Adjusted cooling setpoint"
  Buildings.Controls.OBC.CDL.Reals.Limiter cooSetLim(
    final uMax=TActCoo_max,
    final uMin=TActCoo_min)
    "Limit occupied zone cooling setpoint"
  Buildings.Controls.OBC.CDL.Reals.Limiter heaSetLim(
    final uMax=TActHea_max,
    final uMin=TActHea_min)
    "Limit occupied zone heating setpoint"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar(
    final p=-0.5)
    "Cooling setpoint minus the minimum difference between cooling and heating setpoints"
  Buildings.Controls.OBC.CDL.Logical.Or or6
    "Current operation mode is occupied, warm-up, or cooldown mode"
  Buildings.Controls.OBC.CDL.Logical.Or or7
    "Check if cooling demand limit level is imposed"
  Buildings.Controls.OBC.CDL.Logical.Or or8
    "Check if heating demand limit level is imposed"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu
    "Check if current operation mode is warm-up mode"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu1
    "Check if current operation mode is cool-down mode"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu2
    "Check if current operation mode is occupied mode"
  Buildings.Controls.OBC.CDL.Logical.Or or9
    "Current operation mode is occupied, warm-up, or cooldown mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.warmUp)
    "Warm-up mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.coolDown)
    "Cooldown mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied)
    "Occupied mode"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant cooSetAdjCon(
    final k=have_locAdj)
    "Cooling setpoint adjustable"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(
    final k=0) "Zero adjustment"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con3(
    final k=0) if not have_locAdj
    "Zero adjustment"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con4(
    final k=0) if not have_locAdj
    "Zero adjustment"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant heaSetAdjCon(
    final k=have_locAdj)
    "Heating setpoint adjustable"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1(
    final k=0) "Zero adjustment"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant con2(
    final k=ignDemLim)
    "Check whether the zone should exempt from setpoint adjustment due to the demand limit"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant conTru(
    final k=true) if not have_occSen
    "Constant true"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant conFal(
    final k=false) if not have_winSen
    "Constant false"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant winSenCon(
    final k=have_winSen)
    "Check if there is window status sensor"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant have_occSenCon(
    final k=have_occSen)
    "Check if there is occupancy sensor"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant cooSetWinOpe(
    final k=TWinOpeCooSet)
    "Cooling setpoint when window is open"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant heaSetWinOpe(
    final k=TWinOpeHeaSet)
    "Heating setpoint when window is open"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant alaZer(
    final k=-0.2)
    "Alarm level 0"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant alaFou(
    final k=3.8)
    "Alarm level 4"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt
    "Convert real input to integer output"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea
    "Convert boolean to real value"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1
    "Convert boolean to real value"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea6
    "Convert boolean to real value"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea2
    "Convert boolean to real value"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea3
    "Convert boolean to real value"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea4
    "Convert boolean to real value"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea5
    "Convert boolean to real value"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea7
    "Convert boolean to real value"
  Buildings.Controls.OBC.CDL.Logical.And and11
    "Check if window is open during operation modes other than occupied"
  Buildings.Controls.OBC.CDL.Logical.Not not5  "Other than occupied mode"
  Buildings.Controls.OBC.CDL.Reals.Less les
    "Check if occupied cooling setpoint is less than unoccupied one"
  Buildings.Controls.OBC.CDL.Reals.Greater gre
    "Check if occupied heating setpoint is greater than unoccupied one"
  Buildings.Controls.OBC.CDL.Reals.Greater gre2
    "Check if the difference between cooling and heating setpoints is less than the minimum value"
  Buildings.Controls.OBC.CDL.Reals.Switch swi
    "Switch between occupied and unoccupied cooling setpoint"
  Buildings.Controls.OBC.CDL.Reals.Switch swi1
    "Switch between occupied and unoccupied heating setpoint"
  Buildings.Controls.OBC.CDL.Reals.Switch swi2
    "Adjustment shall only affect occupied set point"
  Buildings.Controls.OBC.CDL.Reals.Switch swi3
    "Setpoint can only be adjusted in occupied mode"
  Buildings.Controls.OBC.CDL.Reals.Switch swi4
    "If there is no cooling adjustment, zero adjust"
  Buildings.Controls.OBC.CDL.Reals.Switch swi6
    "If there is no heating adjustment, zero adjust"
  Buildings.Controls.OBC.CDL.Reals.Switch swi7
    "Ensure heating setpoint being not higher than cooling setpoint minus 0.5 degC"
  Buildings.Controls.OBC.CDL.Reals.Switch swi8
    "Ensure unoccupied heating setppint being lower than occupied one"
  Buildings.Controls.OBC.CDL.Reals.Switch swi9
    "Ensure unoccupied cooling setppint being higher than occupied one"
  Buildings.Controls.OBC.CDL.Reals.Switch swi10
    "Switch between occupied and unoccupied cooling setpoint"
  Buildings.Controls.OBC.CDL.Reals.Switch swi11
    "Switch between occupied and unoccupied cooling setpoint"
  Buildings.Controls.OBC.CDL.Reals.Switch swi12
    "Increase cooling setpoint when the zone is continuously unpopulated"
  Buildings.Controls.OBC.CDL.Reals.Switch swi13
    "Decrease heating setpoint when the zone is continuously unpopulated"
  Buildings.Controls.OBC.CDL.Reals.Switch swi14
    "Switch to TWinOpeCooSet when window is open"
  Buildings.Controls.OBC.CDL.Reals.Switch swi15
    "Switch to TWinOpeHeaSet when window is open"
  Buildings.Controls.OBC.CDL.Reals.Switch swi16
    "Generate level 4 alarm when window is open during modes other than occupied"
  Buildings.Controls.OBC.CDL.Reals.Switch swi17
    "If it is occupied mode, cooling setpoint should be limited"
  Buildings.Controls.OBC.CDL.Reals.Switch swi18
    "If it is occupied mode, heating setpoint should be limited"
  Buildings.Controls.OBC.CDL.Reals.Switch swi19
    "If there is occupancy sensor, update heating setpoint according to the occupancy"
  Buildings.Controls.OBC.CDL.Reals.Switch swi20
    "If there is occupancy sensor, update cooling setpoint according to the occupancy"
  Buildings.Controls.OBC.CDL.Reals.Switch swi21
    "If there is window status sensor, update heating setpoint according to the window status"
  Buildings.Controls.OBC.CDL.Reals.Switch swi22
    "If there is window status sensor, update cooling setpoint according to the window status"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu7
    "Check if the heating demand limit level is level 2"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt8(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.DemandLimitLevels.heating3)
    "Heat demand limit level 3"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu8
    "Check if the heating demand limit level is level 3"
  Buildings.Controls.OBC.CDL.Logical.Not not4 "Logical not"
  Buildings.Controls.OBC.CDL.Logical.And and10
    "Check if the zone becomes unpopulated during occupied mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt6(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.DemandLimitLevels.heating1)
    "Heat demand limit level 1"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu6
    "Check if the heating demand limit level is level 1"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt7(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.DemandLimitLevels.heating2)
    "Heat demand limit level 2"
  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr
    "Check if cooling demand limit level is higher than level zero"
  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr1
    "Check if heating demand limit level is higher than level zero"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt3(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.DemandLimitLevels.cooling1)
    "Cool demand limit level 1"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu3
    "Check if the cooling demand limit level is level 1"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt4(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.DemandLimitLevels.cooling2)
    "Cool demand limit level 2"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu4
    "Check if the cooling demand limit level is level 2"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt5(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.DemandLimitLevels.cooling3)
    "Cool demand limit level 3"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu5
    "Check if the cooling demand limit level is level 3"
  Buildings.Controls.OBC.CDL.Reals.Add add3 "Add real inputs"
  Buildings.Controls.OBC.CDL.Reals.Add add4 "Add real inputs"
  Buildings.Controls.OBC.CDL.Reals.Add add5 "Add real inputs"
  Buildings.Controls.OBC.CDL.Reals.Add add6 "Add real inputs"
  Buildings.Controls.OBC.CDL.Reals.Add add7 "Add real inputs"
  Buildings.Controls.OBC.CDL.Reals.Add add8 "Add real inputs"
  Buildings.Controls.OBC.CDL.Logical.Not winOpe if have_winSen "Window is open"
equation
  connect(uOpeMod, intEqu.u1)
  connect(uOpeMod, intEqu1.u1)
  connect(uOpeMod, intEqu2.u1)
  connect(conInt.y, intEqu.u2)
  connect(conInt1.y, intEqu1.u2)
  connect(conInt2.y, intEqu2.u2)
  connect(TOccCooSet, swi.u1)
  connect(TUnoCooSet, swi.u3)
  connect(TOccHeaSet, swi1.u1)
  connect(TUnoHeaSet, swi1.u3)
  connect(or9.y, swi.u2)
  connect(or9.y, swi1.u2)
  connect(cooSetAdjCon.y, swi4.u2)
  connect(setAdj, swi4.u1)
  connect(con3.y, swi4.u1)
  connect(con.y, swi4.u3)
  connect(swi4.y, add2.u2)
  connect(swi.y, add2.u1)
  connect(add2.y, swi2.u1)
  connect(swi.y, swi2.u3)
  connect(swi6.y, add1.u2)
  connect(add1.y, swi3.u1)
  connect(swi1.y, add1.u1)
  connect(swi1.y, swi3.u3)
  connect(intEqu2.y, swi3.u2)
  connect(uCooDemLimLev, intGreThr.u)
  connect(uHeaDemLimLev, intGreThr1.u)
  connect(intGreThr1.y, or2.u2)
  connect(intGreThr.y, or2.u1)
  connect(or2.y, edg.u)
  connect(intEqu3.y, booToRea.u)
  connect(intEqu4.y, booToRea1.u)
  connect(intEqu5.y, booToRea2.u)
  connect(uCooDemLimLev, intEqu3.u1)
  connect(uCooDemLimLev, intEqu4.u1)
  connect(uCooDemLimLev, intEqu5.u1)
  connect(conInt3.y, intEqu3.u2)
  connect(conInt4.y, intEqu4.u2)
  connect(conInt5.y, intEqu5.u2)
  connect(intEqu3.y, or1.u1)
  connect(intEqu4.y, or1.u2)
  connect(not1.y, booToRea6.u)
  connect(booToRea.y, pro.u2)
  connect(cooSetFre.y, addPar2.u)
  connect(cooSetFre.y, addPar1.u)
  connect(cooSetFre.y, addPar3.u)
  connect(booToRea1.y, pro1.u2)
  connect(booToRea2.y, pro2.u2)
  connect(addPar2.y, pro.u1)
  connect(cooSetFre.y, pro6.u2)
  connect(booToRea6.y, pro6.u1)
  connect(addPar1.y, pro1.u1)
  connect(addPar3.y, pro2.u1)
  connect(or2.y, not3.u)
  connect(con2.y, or5.u1)
  connect(not3.y, or5.u2)
  connect(uHeaDemLimLev, intEqu6.u1)
  connect(uHeaDemLimLev, intEqu7.u1)
  connect(uHeaDemLimLev, intEqu8.u1)
  connect(conInt6.y, intEqu6.u2)
  connect(conInt7.y, intEqu7.u2)
  connect(conInt8.y, intEqu8.u2)
  connect(intEqu6.y, booToRea3.u)
  connect(intEqu7.y, booToRea4.u)
  connect(intEqu8.y, booToRea5.u)
  connect(intEqu6.y, or4.u1)
  connect(intEqu7.y, or4.u2)
  connect(not2.y, booToRea7.u)
  connect(booToRea7.y, pro7.u1)
  connect(heaSetFre.y, pro7.u2)
  connect(heaSetFre.y, addPar6.u)
  connect(heaSetFre.y, addPar5.u)
  connect(heaSetFre.y, addPar4.u)
  connect(addPar6.y, pro3.u1)
  connect(addPar5.y, pro4.u1)
  connect(addPar4.y, pro5.u1)
  connect(booToRea3.y, pro3.u2)
  connect(booToRea4.y, pro4.u2)
  connect(booToRea5.y, pro5.u2)
  connect(edg.y, cooSetFre.trigger)
  connect(edg.y, heaSetFre.trigger)
  connect(or5.y, swi10.u2)
  connect(or5.y, swi11.u2)
  connect(swi2.y, cooSetFre.u)
  connect(swi2.y, swi10.u1)
  connect(swi3.y, heaSetFre.u)
  connect(swi3.y, swi11.u1)
  connect(u1Occ, not4.u)
  connect(conTru.y, not4.u)
  connect(and10.y, tim.u)
  connect(truHol.y, edg1.u)
  connect(edg1.y, cooSetSam.trigger)
  connect(edg1.y, heaSetSam.trigger)
  connect(cooSetSam.y, cooSetInc.u)
  connect(heaSetSam.y, heaSetDec.u)
  connect(cooSetInc.y, swi12.u1)
  connect(heaSetDec.y, swi13.u1)
  connect(truHol.y, swi12.u2)
  connect(truHol.y, swi13.u2)
  connect(swi11.y, swi13.u3)
  connect(swi10.y, swi12.u3)
  connect(intEqu2.y, and10.u1)
  connect(not4.y, and10.u2)
  connect(swi11.y, heaSetSam.u)
  connect(swi10.y, cooSetSam.u)
  connect(have_occSenCon.y, swi20.u2)
  connect(have_occSenCon.y, swi19.u2)
  connect(swi12.y, swi20.u1)
  connect(swi13.y, swi19.u1)
  connect(swi10.y, swi20.u3)
  connect(swi11.y, swi19.u3)
  connect(intEqu2.y, not5.u)
  connect(not5.y, and11.u1)
  connect(and11.y, swi16.u2)
  connect(alaFou.y, swi16.u1)
  connect(alaZer.y, swi16.u3)
  connect(swi16.y, reaToInt.u)
  connect(cooSetWinOpe.y, swi14.u1)
  connect(heaSetWinOpe.y, swi15.u1)
  connect(winSenCon.y, swi22.u2)
  connect(winSenCon.y, swi21.u2)
  connect(swi19.y, swi15.u3)
  connect(swi19.y, swi21.u3)
  connect(swi20.y, swi14.u3)
  connect(swi20.y, swi22.u3)
  connect(swi14.y, swi22.u1)
  connect(swi15.y, swi21.u1)
  connect(conFal.y, and11.u2)
  connect(conFal.y, swi14.u2)
  connect(conFal.y, swi15.u2)
  connect(swi22.y, cooSetLim.u)
  connect(swi21.y, heaSetLim.u)
  connect(cooSetLim.y, swi17.u1)
  connect(heaSetLim.y, swi18.u1)
  connect(swi22.y, swi17.u3)
  connect(swi21.y, swi18.u3)
  connect(intEqu2.y, swi17.u2)
  connect(intEqu2.y, swi18.u2)
  connect(swi17.y, les.u1)
  connect(les.y, swi9.u2)
  connect(swi18.y, gre.u1)
  connect(gre.y, swi8.u2)
  connect(swi17.y, swi9.u1)
  connect(swi18.y, swi8.u1)
  connect(TUnoCooSet, les.u2)
  connect(TUnoCooSet, swi9.u3)
  connect(TUnoHeaSet, gre.u2)
  connect(TUnoHeaSet, swi8.u3)
  connect(swi9.y, addPar.u)
  connect(gre2.y, swi7.u2)
  connect(swi8.y, gre2.u1)
  connect(addPar.y, gre2.u2)
  connect(swi8.y, swi7.u3)
  connect(addPar.y, swi7.u1)
  connect(swi7.y, THeaSet)
  connect(swi9.y, TCooSet)
  connect(reaToInt.y, yAla)
  connect(pro6.y, add3.u1)
  connect(pro.y, add3.u2)
  connect(pro1.y, add4.u1)
  connect(pro2.y, add4.u2)
  connect(add3.y, add5.u1)
  connect(add4.y, add5.u2)
  connect(add5.y, swi10.u3)
  connect(pro7.y, add6.u1)
  connect(pro3.y, add6.u2)
  connect(pro4.y, add7.u1)
  connect(pro5.y, add7.u2)
  connect(add6.y, add8.u1)
  connect(add7.y, add8.u2)
  connect(add8.y, swi11.u3)
  connect(or9.y, swi2.u2)
  connect(tim.passed, truHol.u)
  connect(cooSetAdj, swi4.u1)
  connect(heaSetAdjCon.y, swi6.u2)
  connect(heaSetAdj, swi6.u1)
  connect(con1.y, swi6.u3)
  connect(setAdj, swi6.u1)
  connect(con4.y, swi6.u1)
  connect(u1Win, winOpe.u)
  connect(winOpe.y, and11.u2)
  connect(winOpe.y, swi14.u2)
  connect(winOpe.y, swi15.u2)
  connect(intEqu.y, or6.u1)
  connect(intEqu1.y, or6.u2)
  connect(or6.y,or9. u1)
  connect(intEqu2.y,or9. u2)
  connect(intEqu5.y, or7.u2)
  connect(or1.y, or7.u1)
  connect(not2.u, or8.y)
  connect(or7.y, not1.u)
  connect(or4.y, or8.u1)
  connect(intEqu8.y, or8.u2)</li>
<li>As a default, the active occupied heating setpoint shall be limited between
18 °C (65 °F) and 22 °C (72 °F);</li>
</ol>
</li>
<li>The active heating and cooling setpoint shall be independently adjustable,
respecting the limits and anti-overlap logic described above. If zone thermostat
provides only a single setpoint adjustment, then the adjustment shall move both
the same amount, within the limits described above.</li>
<li>The adjustment shall only affect occupied setpoints in occupied mode, warm-up mode
and cool-down mode and shall have no impact on setpoints in all other modes.</li>
<li>At the onset of demand limiting, the local setpoint adjustment value shall
be frozen. Further adjustment of the setpoint by local controls shall be suspended
for the duration of the demand limit event.</li>
</ul>
</li>
<li>Cooling demand limit setpoint adjustment.
The active cooling setpoints for all zones shall be increased when a demand limit
is imposed on the associated zone group. The operator shall have the ability
to exempt individual zones from this adjustment through the normal
Building Automation System (BAS) user interface. Changes due to demand limits
are not cumulative.
<ul>
<li>At Demand Limit Level 1, increase setpoint by 0.5 °C (1 °F).</li>
<li>At Demand Limit Level 2, increase setpoint by 1 °C (2 °F).</li>
<li>At Demand Limit Level 3, increase setpoint by 2 °C (4 °F).</li>
</ul>
</li>
<li>Heating demand limit setpoint adjustment.
The active heating setpoints for all zones shall be decreased when a demand limit
is imposed on the associated zone group. The operator shall have the ability
to exempt individual zones from this adjustment through the normal BAS user
interface. Changes due to demand limits are not cumulative.
<ul>
<li>At Demand Limit Level 1, decrease setpoint by 0.5 °C (1 °F).</li>
<li>At Demand Limit Level 2, decrease setpoint by 1 °C (2 °F).</li>
<li>At Demand Limit Level 3, decrease setpoint by 2 °C (4 °F).</li>
</ul>
</li>
<li>Window switches.
For zones that have operable windows with indicator switches, when the window
switch indicates the window is open, the heating setpoint shall be temporarily
set to 4 °C (40 °F) and the cooling setpoint shall be temporarily
set to 49 °C (120 °F). When the window switch indicates the window is
open during other than Occupied Mode, a Level 4 alarm shall be generated.
</li>
<li>Occupancy sensor
<ul>
<li>When the switch indicates the space has been unpopulated for 5 minutes
continuously during the Occupied Mode, the active heating setpoint shall be
decreased by 0.5 °C (1 °F) and the cooling setpoint shall be increased
by 0.5 °C (1 °F).</li>
<li>When the switch indicated that the space has been populated for 1 minute
continuously, the active heating and cooling setpoints shall be restored to
their previously values.</li>
</ul>
</li>
<li>Hierarchy of setpoint adjustments: the following adjustment restrictions
shall prevail in order from highest to lowest priority.
<ol type=\"i\">
<li>Setpoint overlap restriction</li>
<li>Absolute limits on local setpoint adjustment</li>
<li>Window swtiches</li>
<li>Demand limit (a. Occupancy sensors; b. Local setpoint adjustment)</li>
<li>Scheduled setpoints based on zone group mode</li>
</ol>
</li>
</ol>
</html>", revisions="<html>
<ul>
<li>
June 3, 2020, by Jianjun Hu:<br/>
Upgraded according to G36 official release.
</li>
<li>
October 11, 2017, by Michael Wetter:<br/>
Removed wrong conditional on <code>yAla</code>.
</li>
<li>
August 17, 2017, by Jianjun Hu:<br/>
First implementation.
</li>
</ul>
</html>"));
end Setpoints;


Select the zone state. Block that outputs the zone state. It first checks if the zone is in heating state;
if not, it checks if the zone is in cooling state; otherwise it is in deadband state.

within Buildings.Controls.OBC.ASHRAE.G36.ThermalZones;
block ZoneStates "Select the zone state"

  parameter Real uLow(
    final unit = "1") = 0.01
    "Hysteresis parameter uLow for heating and cooling control signals to avoid chattering"
  parameter Real uHigh(
    final unit = "1") = 0.05
    "Hysteresis parameter uHigh for heating and cooling control signals to avoid chattering"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput uHea "Heating control signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uCoo "Cooling control signal"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yZonSta "Zone state"

protected
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToIntHea(
    final integerFalse=0,
    final integerTrue=Buildings.Controls.OBC.ASHRAE.G36.Types.ZoneStates.heating)
    "Convert Boolean to Integer number"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToIntCoo(
    final integerFalse=0,
    final integerTrue=Buildings.Controls.OBC.ASHRAE.G36.Types.ZoneStates.cooling)
    "Convert Boolean to Integer number"
  Buildings.Controls.OBC.CDL.Logical.Nor isDea "In deadband state"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToIntDea(
    final integerFalse=0,
    final integerTrue=Buildings.Controls.OBC.ASHRAE.G36.Types.ZoneStates.deadband)
    "Convert Boolean to Integer number"
  Buildings.Controls.OBC.CDL.Logical.And isHea "In heating state if both conditions are true"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysUHea(
    final uLow=uLow,
    final uHigh=uHigh)
    "Check if it is in heating state"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysUCoo(
    final uLow=uLow,
    final uHigh=uHigh)
    "Check if it is in cooling state"
  Buildings.Controls.OBC.CDL.Reals.Subtract uHeaMinUCoo
    "Difference between uHea and uCoo"
  Buildings.Controls.OBC.CDL.Logical.And isCoo "In cooling state if both inputs are true"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysU(
    final uLow=-uLow,
    final uHigh=uLow)
    "Check if heating control signal is bigger than cooling control signal"
  Buildings.Controls.OBC.CDL.Logical.Not notHea "Not in heating state"
  Buildings.Controls.OBC.CDL.Integers.Add addInt "Add two integer inputs"
  Buildings.Controls.OBC.CDL.Integers.Add addInt1 "Add two integer inputs"

equation
  connect(isDea.y, booToIntDea.u)
  connect(hysUHea.y, isHea.u1)
  connect(uHea, hysUHea.u)
  connect(uCoo,hysUCoo. u)
  connect(uCoo, uHeaMinUCoo.u2)
  connect(uHea, uHeaMinUCoo.u1)
  connect(isCoo.y, booToIntCoo.u)
  connect(hysUCoo.y, isCoo.u2)
  connect(uHeaMinUCoo.y, hysU.u)
  connect(isHea.y, booToIntHea.u)
  connect(isHea.y, notHea.u)
  connect(hysU.y, isHea.u2)
  connect(notHea.y, isCoo.u1)
  connect(isCoo.y, isDea.u2)
  connect(isHea.y, isDea.u1)
  connect(booToIntHea.y, addInt.u1)
  connect(booToIntCoo.y, addInt.u2)
  connect(addInt.y, addInt1.u1)
  connect(booToIntDea.y, addInt1.u2)
  connect(addInt1.y, yZonSta)
end ZoneStates;


Validate block for generating alarms. This example validates

Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.Alarms
for generating alarms.

within Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.Validation;
model Alarms "Validate block for generating alarms"

  Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.Alarms zonAla(
    final have_CO2Sen=true) "Block that generates alarms"

  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram(
    final duration=7200) "Generate ramp output"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(t=0.75)
    "Check if input is greater than 0.75"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt(
    final integerTrue=1,
    final integerFalse=2)
    "Convert boolean input to integer output"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TZonCooSetOcc(
    final k=295.15)
    "Occupied cooling setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TZonHeaSetOcc(
    final k=293.15)
    "Occupied heating setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin zonTem(
    final amplitude=8,
    final freqHz=1/7200,
    final offset=273.15 + 15) "Zone temperature"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse occSta(
    final period=7200,
    final width=0.05)
    "Generate signal indicating suppressing status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin CO2(
    final amplitude=500,
    final freqHz=1/7200,
    final offset=600) "CO2 concentration"

equation
  connect(ram.y, greThr.u)
  connect(greThr.y, not1.u)
  connect(not1.y, booToInt.u)
  connect(booToInt.y, zonAla.uOpeMod)
  connect(zonTem.y, zonAla.TZon)
  connect(TZonCooSetOcc.y, zonAla.TCooSet)
  connect(TZonHeaSetOcc.y, zonAla.THeaSet)
  connect(occSta.y, zonAla.u1ResSet)
  connect(CO2.y, zonAla.ppmCO2)
end Alarms;


Validation models of determining heating and coooling loop signal. This example validates

Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.ControlLoops.

within Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.Validation;
model ControlLoops
  "Validation models of determining heating and coooling loop signal"
  Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.ControlLoops conLoo
    "Heating and cooling loop"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TZonCooSetOcc(
    final k=297.15)
    "Occupied cooling setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TZonHeaSetOcc(
    final k=293.15)
    "Occupied heating setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin zonTem(
    final amplitude=8,
    final freqHz=1/7200,
    final offset=273.15 + 18) "Zone temperature"

equation
  connect(TZonCooSetOcc.y, conLoo.TCooSet)
  connect(TZonHeaSetOcc.y, conLoo.THeaSet)
  connect(zonTem.y, conLoo.TZon)
end ControlLoops;


Collection of validation models

within Buildings.Controls.OBC.ASHRAE.G36.ThermalZones;
package Validation "Collection of validation models"
end Validation;


Validate block for zone set point. This example validates

Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.Setpoints
for a change of zone setpoint temperature.

within Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.Validation;
model Setpoints "Validate block for zone set point"

  Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.Setpoints TZonSet(
    final have_occSen=true,
    final have_winSen=true) "Block that determines the thermal zone setpoints"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TZonCooSetOcc(
    final k=297.15)
    "Occupied cooling setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TZonHeaSetOcc(
    final k=293.15)
    "Occupied heating setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TZonCooSetUno(
    final k=303.15)
    "Unoccupied cooling setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TZonHeaSetUno(
    final k=287.15)
    "Unoccupied heating setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin cooSetAdj(
    final freqHz=1/28800) "Cooling setpoint adjustment"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin heaSetAdj(
    final freqHz=1/28800,
    final amplitude=0.5)
    "Heating setpoint adjustment"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant cooDemLimLev(
    final k=0)
    "Cooling demand limit level"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant heaDemLimLev(
    final k=0)
    "Heating demand limit level"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram(
    final duration=28800)
    "Generate ramp output"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(t=0.75)
    "Check if input is greater than 0.75"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt(
    final integerTrue=1,
    final integerFalse=7)
    "Convert boolean input to integer output"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse winSta(
    final period=14400, final shift=1200)
    "Generate signal indicating window status"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse occSta(
    final period=14400,
    final width=0.95)
    "Generate signal indicating occupancy status"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zerAdj(
    final k=0) "Zero adjustment"
  Buildings.Controls.OBC.CDL.Reals.Switch swi1
    "Switch to zero adjustment when window is open"
  Buildings.Controls.OBC.CDL.Reals.Switch swi2
    "Switch to zero adjustment when window is open"
  Buildings.Controls.OBC.CDL.Logical.Not not2
    "Logical not"
equation
  connect(ram.y, greThr.u)
  connect(greThr.y, not1.u)
  connect(not1.y, booToInt.u)
  connect(TZonCooSetOcc.y, TZonSet.TOccCooSet)
  connect(TZonHeaSetOcc.y, TZonSet.TOccHeaSet)
  connect(TZonCooSetUno.y, TZonSet.TUnoCooSet)
  connect(TZonHeaSetUno.y, TZonSet.TUnoHeaSet)
  connect(cooDemLimLev.y, TZonSet.uCooDemLimLev)
  connect(heaDemLimLev.y, TZonSet.uHeaDemLimLev)
  connect(booToInt.y, TZonSet.uOpeMod)
  connect(zerAdj.y, swi2.u1)
  connect(zerAdj.y, swi1.u1)
  connect(cooSetAdj.y, swi2.u3)
  connect(heaSetAdj.y, swi1.u3)
  connect(swi1.y, TZonSet.heaSetAdj)
  connect(occSta.y, TZonSet.u1Occ)
  connect(swi2.y, TZonSet.cooSetAdj)
  connect(winSta.y, not2.u)
  connect(not2.y, swi1.u2)
  connect(not2.y, swi2.u2)
  connect(not2.y, TZonSet.u1Win)
end Setpoints;


Validation models of determining zone state. This example validates

Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.ZoneStates.

within Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.Validation;
model ZoneStates "Validation models of determining zone state"
  Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.ZoneStates zonSta "Zone state"
  Buildings.Controls.OBC.CDL.Reals.Sources.Pulse uCoo(
    final period=2,
    final shift=1,
    final offset=0,
    final amplitude=1) "Cooling control signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Pulse uHea(
    final period=2,
    final shift=2,
    final offset=0,
    final amplitude=1) "Heating control signal"

equation
  connect(uHea.y, zonSta.uHea)
  connect(uCoo.y, zonSta.uCoo)
end ZoneStates;


within Buildings.Controls.OBC.ASHRAE.G36;
package Types "Package with type definitions for control sequences"
end Types;


Demand limit levels

within Buildings.Controls.OBC.ASHRAE.G36.Types;
package DemandLimitLevels "Demand limit levels"
  constant Integer cooling0 = 0 "Cooling demand limit level 0";
  constant Integer cooling1 = 1 "Cooling demand limit level 1";
  constant Integer cooling2 = 2 "Cooling demand limit level 2";
  constant Integer cooling3 = 3 "Cooling demand limit level 3";
  constant Integer heating0 = 0 "Heating demand limit level 0";
  constant Integer heating1 = 1 "Heating demand limit level 1";
  constant Integer heating2 = 2 "Heating demand limit level 2";
  constant Integer heating3 = 3 "Heating demand limit level 3";
end DemandLimitLevels;


within Buildings.Controls.OBC.ASHRAE.G36.Types;
package FreezeProtectionStages "Package with constants that indicate the freeze protection stages"
  constant Integer stage0 = 0 "Freeze protection is deactivated";
  constant Integer stage1 = 1 "First stage of freeze protection";
  constant Integer stage2 = 2 "Second stage of freeze protection";
  constant Integer stage3 = 3 "Third stage of freeze protection";
end FreezeProtectionStages;


Zone group operating modes

within Buildings.Controls.OBC.ASHRAE.G36.Types;
package OperationModes "Zone group operating modes"
  constant Integer coolDown = 2 "Cool-down";
  constant Integer freezeProtection = 6 "Freeze protection";
  constant Integer occupied = 1 "Occupied";
  constant Integer setBack = 5 "Set-back";
  constant Integer setUp =  3 "Set-up";
  constant Integer unoccupied = 7 "Unoccupied";
  constant Integer warmUp =  4 "Warm-up";
end OperationModes;


AHU Zone States

within Buildings.Controls.OBC.ASHRAE.G36.Types;
package ZoneStates "AHU Zone States"
  constant Integer cooling = 3 "Output of the space cooling control loop is nonzero";
  constant Integer deadband = 2 "When not in either heating or cooling";
  constant Integer heating = 1 "Output of the space heating control loop is nonzero";
end ZoneStates;


within Buildings.Controls.OBC.ASHRAE.G36;
package VentilationZones "Package of sequences calculating ventilation airflow"
end VentilationZones;


Sequences complying ASHRAE62.1

within Buildings.Controls.OBC.ASHRAE.G36.VentilationZones;
package ASHRAE62_1 "Sequences complying ASHRAE62.1"
end ASHRAE62_1;


Specify zone minimum outdoor air and minimum airflow set points for compliance with ASHRAE standard 62.1. This sequence sets the zone minimum outdoor air and minimum airflow setpoints, for
compliance with the ventilation rate procedure of ASHRAE Standard 62.1. The
implementation is according to ASHRAE Guideline36, Section 5.2.1.3. The calculation
is done following the steps below.

within Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.ASHRAE62_1;
block Setpoints
    "Specify zone minimum outdoor air and minimum airflow set points for compliance with ASHRAE standard 62.1"

  parameter Boolean have_winSen=false
    "True: the zone has window sensor"
  parameter Boolean have_occSen=false
    "True: the zone has occupancy sensor"
  parameter Boolean have_CO2Sen=false
    "True: the zone has CO2 sensor"
  parameter Boolean have_typTerUni=false
    "True: the zone has typical terminal units and CO2 sensor"
  parameter Boolean have_parFanPowUni=false
    "True: the zone has parallel fan-powered terminal unit and CO2 sensor"
  parameter Boolean have_SZVAV=false
    "True: it is single zone VAV AHU system with CO2 sensor"

  parameter Boolean permit_occStandby=true
    "True: occupied-standby mode is permitted"
  parameter Real VAreBreZon_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s")
    "Design area component of the breathing zone outdoor airflow"
  parameter Real VPopBreZon_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s")
    "Design population component of the breathing zone outdoor airflow"
  parameter Real VMin_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s")
    "Design zone minimum airflow setpoint"
  parameter Real VCooMax_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s")=0.025
    "Design zone cooling maximum airflow rate"
  parameter Real zonDisEff_cool=1.0
    "Zone cooling air distribution effectiveness"
  parameter Real zonDisEff_heat=0.8
    "Zone heating air distribution effectiveness"
  parameter Real dTHys(
    final unit="K",
    final quantity="TemperatureDifference")=0.25
    "Temperature difference hysteresis below which the temperature difference will be seen as zero"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Win if have_winSen
    "Window status, normally closed (true), when windows open, it becomes false"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Occ if have_occSen
    "True: the zone is populated"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod
    "Zone operation mode"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput ppmCO2Set if have_CO2Sen
    "CO2 concentration setpoint, in PPM"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput ppmCO2 if have_CO2Sen
    "Detected CO2 concentration"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uZonSta
    if have_CO2Sen and have_parFanPowUni
    "Zone state"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VParFan_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s")
    if have_CO2Sen and have_parFanPowUni
    "Parallel fan airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TZon(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    final displayUnit="degC")
    "Measured room temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TDis(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    final displayUnit="degC") "Measured discharge air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VAdjPopBreZon_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s")
    "Adjusted population component breathing zone flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VOccZonMin_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s") if not have_SZVAV
    "Occupied minimum airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VAdjAreBreZon_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s")
    "Adjusted area component breathing zone flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VMinOA_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s") "Minimum outdoor airflow setpoint"

protected
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal airDisEff(
    final realTrue=zonDisEff_cool,
    final realFalse=zonDisEff_heat)
    "Air distribution effectiveness"
  Buildings.Controls.OBC.CDL.Reals.Line lin if have_CO2Sen
    "CO2 control loop"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(
    final k=0) if have_CO2Sen "Constant zero"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(
    final k=1) if have_CO2Sen
    "Constant one"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar(
    final p=-200) if have_CO2Sen
    "Lower threshold of CO2 setpoint"
  Buildings.Controls.OBC.CDL.Integers.Equal inOccMod
    "Check if it is in occupied mode"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea if have_CO2Sen
    "Convert boolean to real"
  Buildings.Controls.OBC.CDL.Reals.Multiply co2Con if have_CO2Sen
    "Corrected CO2 control loop output"
  Buildings.Controls.OBC.CDL.Reals.Line occMinAirSet if have_CO2Sen and not have_SZVAV
    "Modified occupied minimum airflow setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zonMinFlo(
    final k=VMin_flow) if not have_SZVAV
    "Zone minimum airflow setpoint Vmin"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zonCooMaxFlo(
    final k=VCooMax_flow) if have_CO2Sen and not have_SZVAV
    "Maximum cooling airflow setpoint"
  Buildings.Controls.OBC.CDL.Reals.Line popBreOutAir if have_CO2Sen
    "Modified population componenet of the required breathing zone outdoor airflow"
  Buildings.Controls.OBC.CDL.Integers.Equal inCooSta if have_CO2Sen and have_parFanPowUni
    "Check if it is in cooling state"
  Buildings.Controls.OBC.CDL.Reals.Switch maxFloCO2 if have_CO2Sen and have_parFanPowUni
    "Maximum airflow set point for CO2"
  Buildings.Controls.OBC.CDL.Reals.Subtract difCooMax if have_CO2Sen and have_parFanPowUni
    "Maximum cooling airflw set point minus parallel fan airflow"
  Buildings.Controls.OBC.CDL.Logical.Or or2
    "Check if it is not in occupied mode or the window is open"
  Buildings.Controls.OBC.CDL.Logical.Not notOccMod "Not in occupied mode"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(
    final k=false) if not have_winSen
    "Constant false"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant perOccSta(
    final k=permit_occStandby) if have_occSen
    "Permit occupied-standby mode"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1(
    final k=0) "Constant zero"
  Buildings.Controls.OBC.CDL.Reals.Switch modPopBreAir
    "Modified popuplation component of the breathing zone airflow"
  Buildings.Controls.OBC.CDL.Reals.Switch modAreBreAir
    "Modified area component of the breathing zone airflow"
  Buildings.Controls.OBC.CDL.Reals.Switch occMinAir if not
    have_SZVAV
    "Occupied minimum airflow setpoint"
  Buildings.Controls.OBC.CDL.Logical.Not notOcc if have_occSen "Not occupied"
  Buildings.Controls.OBC.CDL.Reals.Switch unpPopBreAir
    "Population component of the required breathing zone outdoor airflow when it is unpopulated"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1(
    final realTrue=0,
    final realFalse=1) if have_occSen
    "Convert boolean to real"
  Buildings.Controls.OBC.CDL.Reals.Multiply unPopAreBreAir if have_occSen
    "Area component of the required breathing zone outdoor airflow when it is unpopulated"
  Buildings.Controls.OBC.CDL.Reals.Multiply unpMinZonFlo if have_occSen and not have_SZVAV
    "Minimum zone airflow when it is unpopulated"
  Buildings.Controls.OBC.CDL.Reals.Switch unpAreBreAir
    "Area component of the required breathing zone outdoor airflow when it is unpopulated"
  Buildings.Controls.OBC.CDL.Reals.Switch unpMinZonAir if not have_SZVAV
    "Minimum zone airflow when it is unpopulated"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1(
    final k=false) if not have_occSen
    "Constant false"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai(
    final k=1) if not have_CO2Sen and not have_SZVAV
    "Dummy gain for conditional input"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai1(
    final k=1) if not have_CO2Sen
    "Dummy gain for conditional input"
  Buildings.Controls.OBC.CDL.Reals.Add reqBreAir
    "Required breathing zone outdoor airflow"
  Buildings.Controls.OBC.CDL.Reals.Divide minOA "Minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant occMod(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied)
    "Occupied mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant cooSta(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.ZoneStates.cooling)
    if have_CO2Sen and have_parFanPowUni
    "Cooling state"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer2(
    final k=0) if not have_occSen
    "Constant zero"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer3(
    final k=0) if not have_occSen or have_SZVAV
    "Constant zero"
  Buildings.Controls.OBC.CDL.Reals.Greater cooSup(
    final h=dTHys)
    "Check if it is supplying cooling"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter  gai2(
    final k=1)
    if have_CO2Sen and not have_SZVAV and not have_parFanPowUni
    "Dummy gain for conditional input"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant desAreAir(
    final k=VAreBreZon_flow)
    "Design area component of the breathing zone outdoor airflow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant desPopAir(
    final k=VPopBreZon_flow)
    "Design population component of the breathing zone outdoor airflow"
  CDL.Logical.Not winOpe if have_winSen "Window is open"
equation
  connect(addPar.y, lin.x1)
  connect(zer.y, lin.f1)
  connect(ppmCO2, lin.u)
  connect(one.y, lin.f2)
  connect(uOpeMod, inOccMod.u1)
  connect(occMod.y, inOccMod.u2)
  connect(inOccMod.y, booToRea.u)
  connect(zer.y, occMinAirSet.x1)
  connect(zonMinFlo.y, occMinAirSet.f1)
  connect(one.y, occMinAirSet.x2)
  connect(co2Con.y, occMinAirSet.u)
  connect(zer.y, popBreOutAir.x1)
  connect(zer.y, popBreOutAir.f1)
  connect(one.y, popBreOutAir.x2)
  connect(co2Con.y, popBreOutAir.u)
  connect(uZonSta, inCooSta.u1)
  connect(cooSta.y, inCooSta.u2)
  connect(inCooSta.y, maxFloCO2.u2)
  connect(zonCooMaxFlo.y, maxFloCO2.u1)
  connect(zonCooMaxFlo.y, difCooMax.u1)
  connect(difCooMax.y, maxFloCO2.u3)
  connect(maxFloCO2.y, occMinAirSet.f2)
  connect(lin.y, co2Con.u2)
  connect(booToRea.y, co2Con.u1)
  connect(inOccMod.y, notOccMod.u)
  connect(notOccMod.y, or2.u2)
  connect(con.y, or2.u1)
  connect(zer1.y, modPopBreAir.u1)
  connect(or2.y, modPopBreAir.u2)
  connect(or2.y, modAreBreAir.u2)
  connect(zer1.y, modAreBreAir.u1)
  connect(or2.y, occMinAir.u2)
  connect(zer1.y, occMinAir.u1)
  connect(u1Occ, notOcc.u)
  connect(perOccSta.y, booToRea1.u)
  connect(booToRea1.y, unPopAreBreAir.u2)
  connect(booToRea1.y, unpMinZonFlo.u1)
  connect(zonMinFlo.y, unpMinZonFlo.u2)
  connect(notOcc.y, unpPopBreAir.u2)
  connect(zer1.y, unpPopBreAir.u1)
  connect(notOcc.y, unpAreBreAir.u2)
  connect(unPopAreBreAir.y, unpAreBreAir.u1)
  connect(notOcc.y, unpMinZonAir.u2)
  connect(unpMinZonFlo.y, unpMinZonAir.u1)
  connect(unpPopBreAir.y, modPopBreAir.u3)
  connect(unpAreBreAir.y, modAreBreAir.u3)
  connect(unpMinZonAir.y, occMinAir.u3)
  connect(occMinAirSet.y, unpMinZonAir.u3)
  connect(popBreOutAir.y, unpPopBreAir.u3)
  connect(con1.y, unpPopBreAir.u2)
  connect(con1.y, unpAreBreAir.u2)
  connect(con1.y, unpMinZonAir.u2)
  connect(zonMinFlo.y, gai.u)
  connect(gai.y, unpMinZonAir.u3)
  connect(gai1.y, unpPopBreAir.u3)
  connect(modAreBreAir.y, reqBreAir.u2)
  connect(modPopBreAir.y, reqBreAir.u1)
  connect(reqBreAir.y, minOA.u1)
  connect(airDisEff.y, minOA.u2)
  connect(occMinAir.y, VOccZonMin_flow)
  connect(minOA.y, VMinOA_flow)
  connect(zer2.y, unpAreBreAir.u1)
  connect(zer3.y, unpMinZonAir.u1)
  connect(TZon, cooSup.u1)
  connect(TDis, cooSup.u2)
  connect(cooSup.y, airDisEff.u)
  connect(VParFan_flow, difCooMax.u2)
  connect(zonCooMaxFlo.y, gai2.u)
  connect(gai2.y, occMinAirSet.f2)
  connect(ppmCO2Set, addPar.u)
  connect(ppmCO2Set, lin.x2)
  connect(modAreBreAir.y, VAdjAreBreZon_flow)
  connect(modPopBreAir.y, VAdjPopBreZon_flow)
  connect(desAreAir.y, unpAreBreAir.u3)
  connect(desAreAir.y, unPopAreBreAir.u1)
  connect(desPopAir.y, gai1.u)
  connect(desPopAir.y, popBreOutAir.f2)
  connect(u1Win, winOpe.u)
  connect(winOpe.y, or2.u1)
end Setpoints;


Collection of validation models

within Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.ASHRAE62_1;
package Validation "Collection of validation models"
end Validation;


Validate the outdoor airflow setpoint according to the ASHRAE 62.1. This example validates

Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.ASHRAE62_1.Setpoints.

within Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.ASHRAE62_1.Validation;
model Setpoints "Validate the outdoor airflow setpoint according to the ASHRAE 62.1"

  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.ASHRAE62_1.Setpoints
    noSenZon(
    final VAreBreZon_flow=0.009,
    final VPopBreZon_flow=0.005,
    final VMin_flow=0.018) "Setpoints of zone without any sensors"
  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.ASHRAE62_1.Setpoints
    winSenZon(
    final have_winSen=true,
    final VAreBreZon_flow=0.009,
    final VPopBreZon_flow=0.005,
    final VMin_flow=0.018) "Setpoints of a zone with window sensor"
  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.ASHRAE62_1.Setpoints
    occSenZon(
    final have_occSen=true,
    final VAreBreZon_flow=0.009,
    final VPopBreZon_flow=0.005,
    final VMin_flow=0.018) "Setpoints of a zone with occupancy sensor"
  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.ASHRAE62_1.Setpoints
    co2SenZon(
    final have_CO2Sen=true,
    have_typTerUni=true,
    final VAreBreZon_flow=0.009,
    final VPopBreZon_flow=0.005,
    final VMin_flow=0.018)
    "Setpoints of a zone with  CO2 sensor and typical terminal unit"
  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.ASHRAE62_1.Setpoints
    co2SenZonParFan(
    final have_CO2Sen=true,
    have_parFanPowUni=true,
    final VAreBreZon_flow=0.009,
    final VPopBreZon_flow=0.005,
    final VMin_flow=0.018)
    "Setpoints of a zone with  CO2 sensor and parallel fan-powered terminal unit"
  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.ASHRAE62_1.Setpoints
    co2SenSZVAV(
    final have_CO2Sen=true,
    have_SZVAV=true,
    final VAreBreZon_flow=0.009,
    final VPopBreZon_flow=0.005,
    final VMin_flow=0.018)
    "Setpoints of a zone with  CO2 sensor and single zone VAV AHU"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram(
    final duration=7200)
    "Generate ramp output"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(
    final t=0.75)
    "Check if input is greater than 0.75"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt(
    final integerTrue=1,
    final integerFalse=2)
    "Convert boolean input to integer output"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin zonTem(
    final amplitude=8,
    final freqHz=1/7200,
    final offset=273.15 + 15) "Zone temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin disTem(
    final amplitude=-5,
    final freqHz=1/7200,
    final offset=273.15 + 20) "Discharge air temperature"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse winSta(
    final period=7200,
    final width=0.2) "Window operating status"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse occSta(
    final period=7200,
    final width=0.8)
    "Occupancy status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp co2Con(
    final height=300,
    final duration=7200,
    offset=800) "CO2 concentration"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram1(
    final height=2.6,
    final duration=7200,
    offset=0.6) "Generate ramp output"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt
    "Convert real input to integer output"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin parFanFlo(
    final amplitude=0.01,
    final freqHz=1/7200,
    final offset=0.008) "Parallel fan flow rate"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant CO2Set(
    final k=894)
    "CO2 concentration setpoint"
  Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not"
equation
  connect(ram.y, greThr.u)
  connect(greThr.y, not1.u)
  connect(not1.y, booToInt.u)
  connect(booToInt.y, noSenZon.uOpeMod)
  connect(zonTem.y, noSenZon.TZon)
  connect(disTem.y, noSenZon.TDis)
  connect(booToInt.y, winSenZon.uOpeMod)
  connect(zonTem.y, winSenZon.TZon)
  connect(disTem.y, winSenZon.TDis)
  connect(booToInt.y, occSenZon.uOpeMod)
  connect(zonTem.y, occSenZon.TZon)
  connect(disTem.y, occSenZon.TDis)
  connect(occSta.y, occSenZon.u1Occ)
  connect(booToInt.y, co2SenZon.uOpeMod)
  connect(zonTem.y, co2SenZon.TZon)
  connect(disTem.y, co2SenZon.TDis)
  connect(co2Con.y, co2SenZon.ppmCO2)
  connect(booToInt.y, co2SenZonParFan.uOpeMod)
  connect(ram1.y, reaToInt.u)
  connect(reaToInt.y, co2SenZonParFan.uZonSta)
  connect(co2Con.y, co2SenZonParFan.ppmCO2)
  connect(parFanFlo.y, co2SenZonParFan.VParFan_flow)
  connect(zonTem.y, co2SenZonParFan.TZon)
  connect(disTem.y, co2SenZonParFan.TDis)
  connect(booToInt.y, co2SenSZVAV.uOpeMod)
  connect(co2Con.y, co2SenSZVAV.ppmCO2)
  connect(zonTem.y, co2SenSZVAV.TZon)
  connect(disTem.y, co2SenSZVAV.TDis)
  connect(CO2Set.y, co2SenZonParFan.ppmCO2Set)
  connect(CO2Set.y, co2SenSZVAV.ppmCO2Set)
  connect(CO2Set.y, co2SenZon.ppmCO2Set)
  connect(winSta.y, not2.u)
  connect(not2.y, winSenZon.u1Win)
end Setpoints;


Sequences complying California Title 24

within Buildings.Controls.OBC.ASHRAE.G36.VentilationZones;
package Title24 "Sequences complying California Title 24"
end Title24;


Specify zone minimum outdoor air and minimum airflow set points for compliance with California Title 24. This sequence sets the zone minimum outdoor air and minimum airflow setpoints, for
compliance with the ventilation rate procedure of California Title 24. The
implementation is according to Section 5.2.1.4 of ASHRAE Guideline36, May 2020. The calculation
is done following the steps below.

within Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.Title24;
block Setpoints
  "Specify zone minimum outdoor air and minimum airflow set points for compliance with California Title 24"

  parameter Boolean have_winSen=false
    "True: the zone has window sensor"
  parameter Boolean have_occSen=false
    "True: the zone has occupancy sensor"
  parameter Boolean have_CO2Sen=false
    "True: the zone has CO2 sensor"
  parameter Boolean have_typTerUni=false
    "True: the zone has typical terminal units and CO2 sensor"
  parameter Boolean have_parFanPowUni=false
    "True: the zone has parallel fan-powered terminal unit and CO2 sensor"
  parameter Boolean have_SZVAV=false
    "True: it is single zone VAV AHU system with CO2 sensor"
  parameter Real VOccMin_flow(unit="m3/s")
    "Zone minimum outdoor airflow for occupants"
  parameter Real VAreMin_flow(unit="m3/s")
    "Zone minimum outdoor airflow for building area"
  parameter Real VMin_flow(unit="m3/s")
    "Design zone minimum airflow setpoint"
  parameter Real VCooMax_flow(unit="m3/s")=0.025
    "Design zone cooling maximum airflow rate"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Win if have_winSen
    "Window status, normally closed (true), when windows open, it becomes false"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Occ if have_occSen
    "True: the zone is populated"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod if have_CO2Sen
    "Zone operation mode"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput ppmCO2Set if have_CO2Sen
    "CO2 concentration setpoint, in PPM"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput ppmCO2 if have_CO2Sen
    "Detected CO2 concentration"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uZonSta
    if have_CO2Sen and have_parFanPowUni
    "Zone state"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VParFan_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s") if have_CO2Sen and have_parFanPowUni
    "Parallel fan airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VZonAbsMin_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s")
    "Zone absolute minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VZonDesMin_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s") "Zone design minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VOccZonMin_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s") if not have_SZVAV
    "Occupied zone minimum airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yCO2(
     final unit="1")
    "CO2 control loop signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VMinOA_flow(
    final quantity="VolumeFlowRate",
    final unit="m3/s") if have_SZVAV
    "Zone minimum outdoor airflow setpoint"

protected
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai(
    final k=0.25) "Gain factor"
  Buildings.Controls.OBC.CDL.Reals.Max max1
    "Find the larger input value"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zonOccOAMin(
    final k=VOccMin_flow)
    "Zone minimum outdoor airflow for occupants"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zonAreOAMin(
    final k=VAreMin_flow)
    "Zone minimum outdoor airflow for building area"
  Buildings.Controls.OBC.CDL.Reals.Switch zonAbsMin
    "Zone absolute outdoor air minimum flow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1(
    final k=0)
    "Constant zero"
  Buildings.Controls.OBC.CDL.Logical.Not notOcc
    "Not occupied"
  Buildings.Controls.OBC.CDL.Reals.Switch zonAbsMin1
    "Zone absolute outdoor air minimum flow"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant havCO2Sen(
    final k=have_CO2Sen)
    "Check if the zone has CO2 sensor"
  Buildings.Controls.OBC.CDL.Reals.Switch zonAbsMin2
    "Zone absolute outdoor air minimum flow"
  Buildings.Controls.OBC.CDL.Reals.Switch zonDesMin
    "Zone design outdoor air minimum flow"
  Buildings.Controls.OBC.CDL.Reals.Switch zonDesMin1
    "Zone design outdoor air minimum flow"
  Buildings.Controls.OBC.CDL.Reals.Switch zonOccMin if not have_SZVAV
    "Zone occupied minimum flow"
  Buildings.Controls.OBC.CDL.Reals.Switch zonOccMin1 if not have_SZVAV
    "Zone occupied minimum flow"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant occMod(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied)
    if have_CO2Sen
    "Occupied mode"
  Buildings.Controls.OBC.CDL.Integers.Equal inOccMod if have_CO2Sen
    "Check if it is in occupied mode"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar(final p=-200)
    if have_CO2Sen
    "Lower threshold of CO2 setpoint"
  Buildings.Controls.OBC.CDL.Reals.Line lin if have_CO2Sen
    "CO2 control loop"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0)
    "Constant zero"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(final k=1)
    "Constant one"
  Buildings.Controls.OBC.CDL.Reals.Multiply co2Con if have_CO2Sen
    "Corrected CO2 control loop output"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea if have_CO2Sen
    "Convert boolean to real"
  Buildings.Controls.OBC.CDL.Reals.Line zonOccMin2
    if have_CO2Sen and have_typTerUni
    "Zone occupied minimum flow when the system has typical terminal units"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zonMinFlo(
    final k=VMin_flow)
    "Zone minimum airflow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zonCooMaxFlo(
    final k=VCooMax_flow)
    if have_CO2Sen and (have_typTerUni or have_parFanPowUni)
    "Zone cooling maximum airflow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant hal(
    final k=0.5)
    if have_CO2Sen and (have_typTerUni or have_parFanPowUni) "Constant value"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant cooSta(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.ZoneStates.cooling)
    if have_CO2Sen and have_parFanPowUni
    "Cooling state"
  Buildings.Controls.OBC.CDL.Integers.Equal inCooSta
    if have_CO2Sen and have_parFanPowUni
    "Check if it is in cooling state"
  Buildings.Controls.OBC.CDL.Reals.Subtract difCooMax
    if have_CO2Sen and have_parFanPowUni
    "Maximum cooling airflw set point minus parallel fan airflow"
  Buildings.Controls.OBC.CDL.Reals.Switch maxFloCO2
    if have_CO2Sen and have_parFanPowUni
    "Maximum airflow set point for CO2"
  Buildings.Controls.OBC.CDL.Reals.Line zonOccMin3
    if have_CO2Sen and have_parFanPowUni
    "Zone occupied minimum flow when the system has parallel fan-powered terminal unit"
  Buildings.Controls.OBC.CDL.Reals.Line zonOccMin4 if have_SZVAV
    "Zone minimum outdoor flow when it is the single zone VAV system"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(
    final k=false)
    if not have_winSen
    "Constant false"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant con1(
    final k=true)
    if not have_occSen "Constant true"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai1(
    final k=1)
    if not have_CO2Sen
    "Dummy gain for conditional input"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one2(final k=1)
    if not have_CO2Sen "Constant one"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer3(final k=0)
    if not have_CO2Sen
    "Constant zero"
  Buildings.Controls.OBC.CDL.Logical.Not winOpe if have_winSen "Window is open"
equation
  connect(zer1.y, zonAbsMin.u1)
  connect(u1Occ, notOcc.u)
  connect(notOcc.y, zonAbsMin1.u2)
  connect(zonAreOAMin.y, gai.u)
  connect(gai.y, zonAbsMin1.u1)
  connect(zonAbsMin1.y, zonAbsMin.u3)
  connect(havCO2Sen.y, zonAbsMin2.u2)
  connect(zonAbsMin2.y, zonAbsMin1.u3)
  connect(zer1.y, zonDesMin.u1)
  connect(zonDesMin1.y, zonDesMin.u3)
  connect(notOcc.y, zonDesMin1.u2)
  connect(gai.y, zonDesMin1.u1)
  connect(zonAreOAMin.y, max1.u2)
  connect(zonOccOAMin.y, max1.u1)
  connect(max1.y, zonDesMin1.u3)
  connect(zonDesMin.y, zonAbsMin2.u3)
  connect(zonDesMin.y, VZonDesMin_flow)
  connect(zonAbsMin.y, VZonAbsMin_flow)
  connect(notOcc.y, zonOccMin.u2)
  connect(gai.y, zonOccMin.u1)
  connect(zer1.y, zonOccMin1.u1)
  connect(zonOccMin1.y, zonOccMin.u3)
  connect(uOpeMod, inOccMod.u1)
  connect(occMod.y, inOccMod.u2)
  connect(inOccMod.y, booToRea.u)
  connect(booToRea.y, co2Con.u1)
  connect(ppmCO2Set, addPar.u)
  connect(addPar.y, lin.x1)
  connect(zer.y, lin.f1)
  connect(ppmCO2, lin.u)
  connect(ppmCO2Set, lin.x2)
  connect(one.y, lin.f2)
  connect(lin.y, co2Con.u2)
  connect(co2Con.y, zonOccMin2.u)
  connect(zer.y, zonOccMin2.x1)
  connect(zonMinFlo.y, zonOccMin2.f1)
  connect(hal.y, zonOccMin2.x2)
  connect(uZonSta, inCooSta.u1)
  connect(cooSta.y, inCooSta.u2)
  connect(inCooSta.y, maxFloCO2.u2)
  connect(zonCooMaxFlo.y, zonOccMin2.f2)
  connect(zonCooMaxFlo.y, maxFloCO2.u1)
  connect(difCooMax.y, maxFloCO2.u3)
  connect(zonCooMaxFlo.y, difCooMax.u1)
  connect(VParFan_flow, difCooMax.u2)
  connect(co2Con.y, zonOccMin3.u)
  connect(zer.y, zonOccMin3.x1)
  connect(zonMinFlo.y, zonOccMin3.f1)
  connect(hal.y, zonOccMin3.x2)
  connect(maxFloCO2.y, zonOccMin3.f2)
  connect(co2Con.y, zonOccMin4.u)
  connect(zer.y, zonOccMin4.x1)
  connect(one.y, zonOccMin4.x2)
  connect(zonAbsMin.y, zonOccMin4.f1)
  connect(zonDesMin.y, zonOccMin4.f2)
  connect(zonAreOAMin.y, zonAbsMin2.u1)
  connect(zonOccMin2.y, zonOccMin1.u3)
  connect(zonOccMin3.y, zonOccMin1.u3)
  connect(zonOccMin.y, VOccZonMin_flow)
  connect(con.y, zonAbsMin.u2)
  connect(con.y, zonDesMin.u2)
  connect(con.y, zonOccMin1.u2)
  connect(con1.y, notOcc.u)
  connect(zonMinFlo.y, gai1.u)
  connect(gai1.y, zonOccMin1.u3)
  connect(one2.y, zonOccMin4.u)
  connect(zonOccMin4.y, VMinOA_flow)
  connect(co2Con.y, yCO2)
  connect(zer3.y, yCO2)
  connect(u1Win, winOpe.u)
  connect(winOpe.y, zonAbsMin.u2)
  connect(winOpe.y, zonDesMin.u2)
  connect(winOpe.y, zonOccMin1.u2)
end Setpoints;


Collection of validation models

within Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.Title24;
package Validation "Collection of validation models"
end Validation;


Validate the outdoor airflow setpoint according to the Title 24. This example validates

Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.Title24.Setpoints.

within Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.Title24.Validation;
model Setpoints "Validate the outdoor airflow setpoint according to the Title 24"

  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.Title24.Setpoints
    noSenZon(
    final VOccMin_flow=0.015,
    final VAreMin_flow=0.012,
    final VMin_flow=0.018) "Setpoints of zone without any sensors"
  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.Title24.Setpoints
    winSenZon(
    final VOccMin_flow=0.015,
    final VAreMin_flow=0.012,
    final have_winSen=true,
    final VMin_flow=0.018) "Setpoints of a zone with window sensor"
  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.Title24.Setpoints
    occSenZon(
    final VOccMin_flow=0.015,
    final VAreMin_flow=0.012,
    final have_occSen=true,
    final VMin_flow=0.018) "Setpoints of a zone with occupancy sensor"
  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.Title24.Setpoints
    co2SenZon(
    final VOccMin_flow=0.015,
    final VAreMin_flow=0.012,
    final have_CO2Sen=true,
    final have_typTerUni=true,
    final VMin_flow=0.018)
    "Setpoints of a zone with  CO2 sensor and typical terminal unit"
  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.Title24.Setpoints
    co2SenZonParFan(
    final VOccMin_flow=0.015,
    final VAreMin_flow=0.012,
    final have_CO2Sen=true,
    final have_parFanPowUni=true,
    final VMin_flow=0.018)
    "Setpoints of a zone with  CO2 sensor and parallel fan-powered terminal unit"
  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.Title24.Setpoints
    co2SenSZVAV(
    final VOccMin_flow=0.015,
    final VAreMin_flow=0.012,
    final have_CO2Sen=true,
    final have_SZVAV=true,
    final VMin_flow=0.018)
    "Setpoints of a zone with  CO2 sensor and single zone VAV AHU"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram(
    final duration=7200)
    "Generate ramp output"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(
    final t=0.75)
    "Check if input is greater than 0.75"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt(
    final integerTrue=1,
    final integerFalse=2)
    "Convert boolean input to integer output"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse winSta(
    final period=7200,
    final width=0.2) "Window operating status"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse occSta(
    final period=7200,
    final width=0.8)
    "Occupancy status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp co2Con(
    final height=300,
    final duration=7200,
    offset=800) "CO2 concentration"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram1(
    final height=2.6,
    final duration=7200,
    offset=0.6) "Generate ramp output"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt
    "Convert real input to integer output"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin parFanFlo(
    final amplitude=0.01,
    final freqHz=1/7200,
    final offset=0.008) "Parallel fan flow rate"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant CO2Set(
    final k=894)
    "CO2 concentration setpoint"
  Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not"
equation
  connect(ram.y, greThr.u)
  connect(greThr.y, not1.u)
  connect(not1.y, booToInt.u)
  connect(occSta.y, occSenZon.u1Occ)
  connect(booToInt.y, co2SenZon.uOpeMod)
  connect(co2Con.y, co2SenZon.ppmCO2)
  connect(booToInt.y, co2SenZonParFan.uOpeMod)
  connect(ram1.y, reaToInt.u)
  connect(reaToInt.y, co2SenZonParFan.uZonSta)
  connect(co2Con.y, co2SenZonParFan.ppmCO2)
  connect(parFanFlo.y, co2SenZonParFan.VParFan_flow)
  connect(booToInt.y, co2SenSZVAV.uOpeMod)
  connect(co2Con.y, co2SenSZVAV.ppmCO2)
  connect(CO2Set.y, co2SenZonParFan.ppmCO2Set)
  connect(CO2Set.y, co2SenSZVAV.ppmCO2Set)
  connect(CO2Set.y, co2SenZon.ppmCO2Set)
  connect(winSta.y, not2.u)
  connect(not2.y, winSenZon.u1Win)
end Setpoints;