within Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses;
block ASHRAESolarGain
  "Calculate the solar heat gain of a solar collector per ASHRAE Standard 93"
  extends Modelica.Blocks.Icons.Block;
  extends Buildings.Obsolete.BaseClasses.ObsoleteModel;
  extends SolarCollectors.BaseClasses.PartialParameters;

  replaceable package Medium = Modelica.Media.Interfaces.PartialMedium
    "Medium in the system";

  parameter Real B0 "1st incident angle modifer coefficient";
  parameter Real B1 "2nd incident angle modifer coefficient";
  parameter Boolean use_shaCoe_in = false "Enable input connector for shaCoe"

  parameter Real shaCoe(
    min=0.0,
    max=1.0) = 0 "Shading coefficient 0.0: no shading, 1.0: full shading"

  parameter Modelica.Units.SI.Angle til "Surface tilt";

  Modelica.Blocks.Interfaces.RealInput shaCoe_in if use_shaCoe_in
    "Shading coefficient"
   Modelica.Blocks.Interfaces.RealInput TFlu[nSeg](
   each unit = "K",
   each displayUnit="degC",
   each quantity="ThermodynamicTemperature")
   Modelica.Blocks.Interfaces.RealInput HSkyDifTil(
     unit="W/m2", quantity="RadiantEnergyFluenceRate")
    "Diffuse solar irradiation on a tilted surfce from the sky"
  Modelica.Blocks.Interfaces.RealInput HGroDifTil(
    unit="W/m2", quantity="RadiantEnergyFluenceRate")
    "Diffuse solar irradiation on a tilted surfce from the ground"
  Modelica.Blocks.Interfaces.RealInput incAng(
    quantity="Angle",
    unit="rad",
    displayUnit="deg") "Incidence angle of the sun beam on a tilted surface"
  Modelica.Blocks.Interfaces.RealInput HDirTil(
    unit="W/m2", quantity="RadiantEnergyFluenceRate")
    "Direct solar irradiation on a tilted surfce"
  Modelica.Blocks.Interfaces.RealOutput QSol_flow[nSeg](each final unit="W")
    "Solar heat gain"

protected
  constant Modelica.Units.SI.TemperatureDifference dTMax=1
    "Safety temperature difference to prevent TFlu > Medium.T_max";
  final parameter Modelica.Units.SI.Temperature TMedMax=Medium.T_max - dTMax
    "Fluid temperature above which there will be no heat gain computed to prevent TFlu > Medium.T_max";
  final parameter Modelica.Units.SI.Temperature TMedMax2=TMedMax - dTMax
    "Fluid temperature below which there will be no heat loss computed to prevent TFlu < Medium.T_min";

  final parameter Real iamSky(fixed = false)
    "Incident angle modifier for diffuse solar radiation from the sky";
  final parameter Real iamGro(fixed = false)
    "Incident angle modifier for diffuse solar radiation from the ground";
  final parameter Modelica.Units.SI.Angle incAngSky(fixed=false)
    "Incident angle of diffuse radiation from the sky";
  final parameter Modelica.Units.SI.Angle incAngGro(fixed=false)
    "Incident angle of diffuse radiation from the ground";
  final parameter Real tilDeg(
    unit = "deg") = Modelica.Units.Conversions.to_deg(  til)
    "Surface tilt angle in degrees";
  final parameter Modelica.Units.SI.HeatFlux HTotMin=1
    "Minimum HTot to avoid div/0";
  final parameter Real HMinDel = 0.001
    "Delta of the smoothing function for HTot";

  Real iamBea "Incident angle modifier for direct solar radiation";
  Real iam "Weighted incident angle modifier";

  Modelica.Blocks.Interfaces.RealInput shaCoe_internal
    "Internally used shading coefficient";

initial equation
  // E+ Equ (557)
  incAngSky =Modelica.Units.Conversions.from_deg(59.68 - 0.1388*(tilDeg) +
    0.001497*(tilDeg)^2);
  // Diffuse radiation from the sky
  // E+ Equ (555)
  iamSky = SolarCollectors.BaseClasses.IAM(incAngSky, B0, B1);
  // E+ Equ (558)
  incAngGro =Modelica.Units.Conversions.from_deg(90 - 0.5788*(tilDeg) +
    0.002693*(tilDeg)^2);
  // Diffuse radiation from the ground
  // E+ Equ (555)
  iamGro = SolarCollectors.BaseClasses.IAM(
    incAngGro,
    B0,
    B1);

equation

  connect(shaCoe_internal, shaCoe_in);

  if not use_shaCoe_in then
    shaCoe_internal = shaCoe;
  end if;

  // E+ Equ (555)
  iamBea = SolarCollectors.BaseClasses.IAM(incAng, B0, B1);
  // E+ Equ (556)
  iam = (HDirTil*iamBea + HSkyDifTil*iamSky + HGroDifTil*iamGro)/
      Buildings.Utilities.Math.Functions.smoothMax((
        HDirTil + HSkyDifTil + HGroDifTil), HTotMin, HMinDel);
  // Modified from EnergyPlus Equ (559) by applying shade effect for
  //direct solar radiation
  // Only solar heat gain is considered here
  for i in 1 : nSeg loop
    QSol_flow[i] = A_c/nSeg*(y_intercept*iam*
      (HDirTil*(1.0 - shaCoe_internal) + HSkyDifTil + HGroDifTil))*
      smooth(1, if TFlu[i] < TMedMax2
        then 1
        else Buildings.Utilities.Math.Functions.smoothHeaviside(TMedMax-TFlu[i], dTMax));
  end for;
end ASHRAESolarGain;


Calculate the heat loss of a solar collector per EN12975. This component computes the heat loss from the solar thermal collector
to the environment. It is designed anticipating ratings data collected in
accordance with EN12975. A negative heat loss indicates that heat
is being lost to the environment.

within Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses;
block EN12975HeatLoss "Calculate the heat loss of a solar collector per EN12975"
  extends Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses.PartialHeatLoss(
    final QLos_nominal = -A_c * (C1 * dT_nominal - C2 * dT_nominal^2)
      "Heat loss at nominal condition, for reporting only",
    QLos_internal = A_c/nSeg * {dT[i] * (C1 - C2 * dT[i]) for i in 1:nSeg});

  parameter Modelica.Units.SI.CoefficientOfHeatTransfer C1(final min=0)
    "C1 from ratings data";

  parameter Real C2(final unit = "W/(m2.K2)", final min=0)
    "C2 from ratings data";
end EN12975HeatLoss;


within Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses;
model EN12975SolarGain "Model calculating solar gains per the EN12975 standard"
  extends Modelica.Blocks.Icons.Block;
  extends Buildings.Obsolete.BaseClasses.ObsoleteModel;
  extends SolarCollectors.BaseClasses.PartialParameters;

  replaceable package Medium = Modelica.Media.Interfaces.PartialMedium
    "Medium in the system";

  parameter Real B0 "1st incident angle modifer coefficient";
  parameter Real B1 "2nd incident angle modifer coefficient";
  parameter Boolean use_shaCoe_in = false
    "Enables an input connector for shaCoe"
  parameter Real shaCoe(
    min=0.0,
    max=1.0) = 0 "Shading coefficient 0.0: no shading, 1.0: full shading"

  parameter Real iamDiff "Incidence angle modifier for diffuse radiation";

  Modelica.Blocks.Interfaces.RealInput shaCoe_in if use_shaCoe_in
    "Time varying input for the shading coefficient"

  Modelica.Blocks.Interfaces.RealInput HSkyDifTil(
    unit="W/m2",
    quantity="RadiantEnergyFluenceRate")
    "Diffuse solar irradiation on a tilted surfce from the sky"
  Modelica.Blocks.Interfaces.RealInput incAng(
    quantity="Angle",
    unit="rad",
    displayUnit="deg") "Incidence angle of the sun beam on a tilted surface"
  Modelica.Blocks.Interfaces.RealInput HDirTil(
    unit="W/m2",
    quantity="RadiantEnergyFluenceRate")
    "Direct solar irradiation on a tilted surfce"
  Modelica.Blocks.Interfaces.RealOutput QSol_flow[nSeg](each final unit="W")
    "Solar heat gain"
  Modelica.Blocks.Interfaces.RealInput TFlu[nSeg](
     each final unit="K",
     each displayUnit="degC",
     each final quantity="ThermodynamicTemperature")

protected
  constant Modelica.Units.SI.TemperatureDifference dTMax=1
    "Safety temperature difference to prevent TFlu > Medium.T_max";
  final parameter Modelica.Units.SI.Temperature TMedMax=Medium.T_max - dTMax
    "Fluid temperature above which there will be no heat gain computed to prevent TFlu > Medium.T_max";
  final parameter Modelica.Units.SI.Temperature TMedMax2=TMedMax - dTMax
    "Fluid temperature below which there will be no heat loss computed to prevent TFlu < Medium.T_min";
  Real iamBea "Incidence angle modifier for director solar radiation";
  Modelica.Blocks.Interfaces.RealInput shaCoe_internal "Internally used shaCoe";

equation
  connect(shaCoe_internal, shaCoe_in);

  // E+ Equ (555)
  iamBea = SolarCollectors.BaseClasses.IAM(incAng, B0, B1);

  // Modified from EnergyPlus Equ (559) by applying shade effect for direct solar radiation
  // Only solar heat gain is considered here
  if not use_shaCoe_in then
    shaCoe_internal = shaCoe;
  end if;

  for i in 1 : nSeg loop
  QSol_flow[i] = A_c/nSeg*(y_intercept*(iamBea*HDirTil*(1.0 - shaCoe_internal) + iamDiff *
  HSkyDifTil))*
      smooth(1, if TFlu[i] < TMedMax2
        then 1
        else Buildings.Utilities.Math.Functions.smoothHeaviside(TMedMax-TFlu[i], dTMax));
  end for;
end EN12975SolarGain;


Function for incident angle modifer.

within Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses;
function IAM "Function for incident angle modifer"

  input Modelica.Units.SI.Angle incAng "Incident angle";
  input Real B0 "1st incident angle modifer coefficient";
  input Real B1 "2nd incident angle modifer coefficient";
  output Real incAngMod "Incident angle modifier coefficient";
protected
  constant Modelica.Units.SI.Angle incAngMin=Modelica.Constants.pi/2 - 0.1
    "Minimum incidence angle to avoid division by zero";
  constant Real delta = 0.0001 "Width of the smoothing function";
  constant Real cosIncAngMin = Modelica.Math.cos(incAngMin) "Cosine of minimum incidence angle";
  Real k = 1/Buildings.Utilities.Math.Functions.smoothMax(Modelica.Math.cos(incAng),
         cosIncAngMin, delta) - 1
         "Term 1/cos(theta)-1 with regularization to avoid division by zero";
algorithm
  // E+ Equ (555), except that we do no longer set incAngMod to zero
  // at incidence angle larger than 60, see
  // https://github.com/lbl-srg/modelica-buildings/issues/785

  incAngMod :=
  Buildings.Utilities.Math.Functions.smoothLimit(
    x = (1 + B0*k + B1*k^2),
    l = 0,
    u = 1,
    deltaX = delta);
end IAM;


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


within Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses;
block PartialHeatLoss
  "Partial heat loss model on which ASHRAEHeatLoss and EN12975HeatLoss are based"
  extends Modelica.Blocks.Icons.Block;
  extends Buildings.Obsolete.BaseClasses.ObsoleteModel;
  extends SolarCollectors.BaseClasses.PartialParameters;

  replaceable package Medium = Modelica.Media.Interfaces.PartialMedium
    "Medium in the component";

  parameter Modelica.Units.SI.Irradiance G_nominal
    "Irradiance at nominal conditions"
  parameter Modelica.Units.SI.TemperatureDifference dT_nominal
    "Ambient temperature minus fluid temperature at nominal conditions"
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal
    "Fluid flow rate at nominal conditions"

  parameter Modelica.Units.SI.SpecificHeatCapacity cp_default
    "Specific heat capacity of the fluid at the default temperature";

  parameter Modelica.Units.SI.HeatFlowRate QLos_nominal
    "Heat loss at nominal conditions, negative if heat flows from collector to environment";

  Modelica.Blocks.Interfaces.RealInput TEnv(
    quantity="ThermodynamicTemperature",
    unit="K",
    displayUnit="degC") "Temperature of surrounding environment"

  Modelica.Blocks.Interfaces.RealInput TFlu[nSeg](
    each quantity="ThermodynamicTemperature",
    each unit = "K",
    each displayUnit="degC") "Temperature of the heat transfer fluid"
  Modelica.Blocks.Interfaces.RealOutput QLos[nSeg](
    each quantity="HeatFlowRate",
    each unit="W",
    each displayUnit="W") = {QLos_internal[i] *
      smooth(1, if TFlu[i] > TMedMin2
        then 1
        else Buildings.Utilities.Math.Functions.smoothHeaviside(TFlu[i]-TMedMin, dTMin))
      for i in 1:nSeg}
    "Limited heat loss rate at current conditions"

protected
  constant Modelica.Units.SI.Temperature dTMin=1
    "Safety temperature difference to prevent TFlu < Medium.T_min";
  final parameter Modelica.Units.SI.Temperature TMedMin=Medium.T_min + dTMin
    "Fluid temperature below which there will be no heat loss computed to prevent TFlu < Medium.T_min";
  final parameter Modelica.Units.SI.Temperature TMedMin2=TMedMin + dTMin
    "Fluid temperature below which there will be no heat loss computed to prevent TFlu < Medium.T_min";
//  final parameter Modelica.Units.SI.HeatFlowRate QUse_nominal(min=0) = G_nominal * A_c * y_intercept + QLos_nominal
//    "Useful heat gain at nominal conditions";

  input Modelica.Units.SI.HeatFlowRate QLos_internal[nSeg]
    "Heat loss rate at current conditions for each segment";

  Modelica.Units.SI.TemperatureDifference dT[nSeg]={TEnv - TFlu[i] for i in 1:
      nSeg} "Environment minus collector fluid temperature";
end PartialHeatLoss;


Partial model for parameters. Partial parameters used in all solar collector models

within Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses;
block PartialParameters "Partial model for parameters"

  parameter Modelica.Units.SI.Area A_c "Area of the collector";
  parameter Integer nSeg(min=3)=3 "Number of segments";
  parameter Real y_intercept "Y intercept (Maximum efficiency)";
end PartialParameters;


Partial model for solar collectors

within Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses;
model PartialSolarCollector "Partial model for solar collectors"
 extends Buildings.Obsolete.BaseClasses.ObsoleteModel;
 extends Buildings.Fluid.Interfaces.LumpedVolumeDeclarations;
  extends Buildings.Fluid.Interfaces.TwoPortFlowResistanceParameters(
    final dp_nominal = dp_nominal_final,
    final computeFlowResistance=(abs(dp_nominal) > Modelica.Constants.eps));
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
    final m_flow_nominal=m_flow_nominal_final);

  constant Boolean homotopyInitialization = true "= true, use homotopy method"

  parameter Integer nSeg(min=3) = 3
    "Number of segments used to discretize the collector model";

  parameter Modelica.Units.SI.Angle azi(displayUnit="deg")
    "Surface azimuth (0 for south-facing; -90 degree for east-facing; +90 degree for west facing";
  parameter Modelica.Units.SI.Angle til(displayUnit="deg")
    "Surface tilt (0 for horizontally mounted collector)";
  parameter Real rho(
    final min=0,
    final max=1,
    final unit = "1") "Ground reflectance";
  parameter Modelica.Units.SI.HeatCapacity C=385*perPar.mDry
    "Heat capacity of solar collector without fluid (default: cp_copper*mDry*nPanels)";

  parameter Boolean use_shaCoe_in = false
    "Enables an input connector for shaCoe"
  parameter Real shaCoe(
    min=0.0,
    max=1.0) = 0 "Shading coefficient. 0.0: no shading, 1.0: full shading"

  parameter Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection nColType=
  Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number
    "Selection of area specification format"
  parameter Integer nPanels= 0 "Desired number of panels in the simulation"

  parameter Modelica.Units.SI.Area totalArea=0
    "Total area of panels in the simulation"

  parameter Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration sysConfig=
  Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Series
    "Selection of system configuration"

  Modelica.Blocks.Interfaces.RealInput shaCoe_in if use_shaCoe_in
    "Shading coefficient"

  Buildings.BoundaryConditions.WeatherData.Bus weaBus "Weather data bus"
  Buildings.BoundaryConditions.SolarIrradiation.DiffusePerez HDifTilIso(
    final outSkyCon=true,
    final outGroCon=true,
    final til=til,
    final azi=azi,
    final rho=rho) "Diffuse solar irradiation on a tilted surface"

  Buildings.BoundaryConditions.SolarIrradiation.DirectTiltedSurface HDirTil(
    final til=til,
    final azi=azi) "Direct solar irradiation on a tilted surface"

  Buildings.Fluid.Sensors.MassFlowRate senMasFlo(redeclare package Medium =
    Medium, allowFlowReversal=allowFlowReversal) "Mass flow rate sensor"
  Buildings.Fluid.FixedResistances.PressureDrop res(
    redeclare final package Medium = Medium,
    final from_dp=from_dp,
    final show_T=show_T,
    final m_flow_nominal=m_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    final linearized=linearizeFlowResistance,
    final homotopyInitialization=homotopyInitialization,
    deltaM=deltaM,
    final dp_nominal=dp_nominal_final) "Flow resistance"

  // The size of the liquid volume has been increased to also
  // add the heat capacity of the metal. See the info section
  // for an explanation.
  Buildings.Fluid.MixingVolumes.MixingVolume vol[nSeg](
    each nPorts=2,
    redeclare package Medium = Medium,
    each final m_flow_nominal=m_flow_nominal,
    each final energyDynamics=energyDynamics,
    each final p_start=p_start,
    each final T_start=T_start,
    each final m_flow_small=m_flow_small,
    each final V=(perPar.V+C/cp_default/rho_default)*nPanels_internal/nSeg,
    each final massDynamics=massDynamics,
    each final X_start=X_start,
    each final C_start=C_start,
    each final C_nominal=C_nominal,
    each final mSenFac=mSenFac,
    each final allowFlowReversal=allowFlowReversal,
    each final prescribedHeatFlowRate=false)
    "Volume of fluid in one segment of the solar collector"

  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor temSen[nSeg]
    "Temperature sensor"

  Buildings.HeatTransfer.Sources.PrescribedHeatFlow heaGai[nSeg]
    "Rate of solar heat gain"
  Buildings.HeatTransfer.Sources.PrescribedHeatFlow QLos[nSeg]
    "Rate of solar heat gain"

protected
  parameter Buildings.Obsolete.Fluid.SolarCollectors.Data.GenericSolarCollector perPar
    "Partial performance data"

  Modelica.Blocks.Interfaces.RealInput shaCoe_internal
    "Internally used shading coefficient";

  final parameter Modelica.Units.SI.MassFlowRate m_flow_nominal_final(
      displayUnit="kg/s") = if sysConfig == Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Parallel
     then nPanels_internal*perPar.mperA_flow_nominal*perPar.A else perPar.mperA_flow_nominal*perPar.A
    "Nominal mass flow rate through the system of collectors";

  final parameter Modelica.Units.SI.PressureDifference dp_nominal_final(
      displayUnit="Pa") = if sysConfig == Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Series
     then nPanels_internal*perPar.dp_nominal else perPar.dp_nominal
    "Nominal pressure loss across the system of collectors";

  parameter Modelica.Units.SI.Area TotalArea_internal=nPanels_internal*perPar.A
    "Area used in the simulation";

  parameter Real nPanels_internal=
    if nColType == Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number then
      nPanels
    else
      totalArea/perPar.A "Number of panels used in the simulation";

  parameter Medium.ThermodynamicState sta_default = Medium.setState_pTX(
    T=Medium.T_default,
    p=Medium.p_default,
    X=Medium.X_default[1:Medium.nXi]) "Medium state at default properties";
  parameter Modelica.Units.SI.SpecificHeatCapacity cp_default=
      Medium.specificHeatCapacityCp(sta_default)
    "Specific heat capacity of the fluid";
  parameter Modelica.Units.SI.Density rho_default=Medium.density(sta_default)
    "Density, used to compute fluid mass";

initial equation
  assert(homotopyInitialization, "In " + getInstanceName() +
    ": The constant homotopyInitialization has been modified from its default value. This constant will be removed in future releases.",
    level = AssertionLevel.warning);

equation
  connect(shaCoe_internal,shaCoe_in);

  if not use_shaCoe_in then
    shaCoe_internal=shaCoe;
  end if;

  connect(weaBus, HDifTilIso.weaBus)
  connect(weaBus, HDirTil.weaBus)
  connect(port_a, senMasFlo.port_a)
  connect(senMasFlo.port_b, res.port_a)
      connect(vol[nSeg].ports[2], port_b)
  connect(vol[1].ports[1], res.port_b)
      for i in 1:(nSeg - 1) loop
    connect(vol[i].ports[2], vol[i + 1].ports[1]);
  end for;
  connect(vol.heatPort, temSen.port)
  connect(heaGai.port, vol.heatPort)
  connect(QLos.port, vol.heatPort)
end PartialSolarCollector;


within Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses.Examples;
model ASHRAEHeatLoss "Example showing the use of ASHRAEHeatLoss"
  extends Modelica.Icons.Example;
  parameter Buildings.Obsolete.Fluid.SolarCollectors.Data.GenericSolarCollector per=
    Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_SolahartKf()
    "Performance data"
  Modelica.Blocks.Sources.Sine TEnv(
    f=0.01,
    offset=273.15 + 10,
    amplitude=7.5) "Temperature of the surrounding environment"
  Modelica.Blocks.Sources.Sine T1(
    f=0.1,
    amplitude=15,
    offset=273.15 + 10) "Temperature in the first segment"
  Modelica.Blocks.Sources.Sine T2(
    f=0.1,
    amplitude=15,
    offset=273.15 + 15) "Temperature in the second segment"
  Modelica.Blocks.Sources.Sine T3(
    f=0.1,
    amplitude=15,
    offset=273.15 + 20) "Temperature in the third segment"
  Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses.ASHRAEHeatLoss heaLos(
    nSeg=3,
    m_flow_nominal=per.mperA_flow_nominal*per.A,
    redeclare package Medium = Buildings.Media.Water,
    G_nominal=per.G_nominal,
    dT_nominal=per.dT_nominal,
    A_c=per.A,
    y_intercept=per.y_intercept,
    slope=per.slope,
    cp_default=4186) "Heat loss model using ASHRAE93 calculations"
equation
  connect(TEnv.y, heaLos.TEnv)
  connect(T3.y, heaLos.TFlu[3])
  connect(T2.y, heaLos.TFlu[2])
  connect(T1.y, heaLos.TFlu[1])
end ASHRAEHeatLoss;


within Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses.Examples;
model ASHRAESolarGain "Example showing the use of ASHRAESolarGain"
  extends Modelica.Icons.Example;
  parameter Buildings.Obsolete.Fluid.SolarCollectors.Data.GenericSolarCollector per=
    Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_ThermaLiteHS20()
    "Performance data"
  Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses.ASHRAESolarGain   solHeaGai(
    nSeg=3,
    shaCoe=0,
    use_shaCoe_in=true,
    A_c=per.A,
    y_intercept=per.y_intercept,
    B0=per.B0,
    B1=per.B1,
    redeclare package Medium = Buildings.Media.Water,
    til=0.78539816339745) "Solar heat gain model using ASHRAE 93 calculations"
  Modelica.Blocks.Sources.Sine HGroDifTil(
    amplitude=50,
    f=4/86400,
    offset=100) "Diffuse radiation from the ground, tilted surface"
  Modelica.Blocks.Sources.Ramp incAng(duration=86400, height=60*(2*Modelica.Constants.pi
        /360)) "Incidence angle"
  Modelica.Blocks.Sources.Sine HDirTil(
    offset=400,
    amplitude=300,
    f=2/86400) "Direct beam radiation, tilted surface"
  Modelica.Blocks.Sources.Sine HSkyDifTil(
    f=1/86400,
    amplitude=100,
    offset=100) "Diffuse radiation, tilted surface"
  Modelica.Blocks.Sources.Ramp shaCoe(
    height=-1,
    duration=86400,
    offset=1) "Shading coefficient"
  Modelica.Blocks.Sources.Sine T3(
    f=2/86400,
    amplitude=50,
    offset=273.15 + 110)
  Modelica.Blocks.Sources.Sine T2(
    f=2/86400,
    amplitude=50,
    offset=273.15 + 100)
  Modelica.Blocks.Sources.Sine T1(
    f=2/86400,
    amplitude=50,
    offset=273.15 + 90)
equation
  connect(HGroDifTil.y, solHeaGai.HGroDifTil)
  connect(shaCoe.y, solHeaGai.shaCoe_in)
  connect(incAng.y, solHeaGai.incAng)
  connect(HDirTil.y, solHeaGai.HDirTil)
  connect(HSkyDifTil.y, solHeaGai.HSkyDifTil)
  connect(T3.y, solHeaGai.TFlu[3])
  connect(T2.y, solHeaGai.TFlu[2])
  connect(T1.y, solHeaGai.TFlu[1])
end ASHRAESolarGain;


within Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses.Examples;
model EN12975HeatLoss "Example showing the use of EN12975HeatLoss"
  extends Modelica.Icons.Example;
  parameter Buildings.Obsolete.Fluid.SolarCollectors.Data.GenericSolarCollector per=
    Buildings.Obsolete.Fluid.SolarCollectors.Data.Concentrating.C_VerificationModel()
    "Performance data"
  Modelica.Blocks.Sources.Sine TEnv(
    f=0.01,
    offset=273.15 + 10,
    amplitude=15) "Temperature of the surrounding environment"
  Modelica.Blocks.Sources.Sine T1(
    amplitude=15,
    f=0.1,
    offset=273.15 + 10) "Temperature of the first segment"
  Modelica.Blocks.Sources.Sine T2(
    f=0.1,
    amplitude=15,
    offset=273.15 + 15) "Temperature of the second segment"
  Modelica.Blocks.Sources.Sine T3(
    f=0.1,
    amplitude=15,
    offset=273.15 + 20) "Temperature of the third segment"
  Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses.EN12975HeatLoss heaLos(
    nSeg=3,
    redeclare package Medium = Buildings.Media.Water,
    C1=per.C1,
    C2=per.C2,
    m_flow_nominal=per.mperA_flow_nominal*per.A,
    G_nominal=per.G_nominal,
    dT_nominal=per.dT_nominal,
    A_c=per.A,
    y_intercept=per.y_intercept,
    cp_default=4186) "Heat loss model using EN12975 calculations"
equation
  connect(TEnv.y, heaLos.TEnv)
  connect(T3.y, heaLos.TFlu[3])
  connect(T2.y, heaLos.TFlu[2])
  connect(T1.y, heaLos.TFlu[1])
end EN12975HeatLoss;


within Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses.Examples;
model EN12975SolarGain "Example showing the use of EN12975SolarGain"
  extends Modelica.Icons.Example;
  parameter Buildings.Obsolete.Fluid.SolarCollectors.Data.GenericSolarCollector per=
    Buildings.Obsolete.Fluid.SolarCollectors.Data.Concentrating.C_VerificationModel()
    "Performance data"
  Buildings.Obsolete.Fluid.SolarCollectors.BaseClasses.EN12975SolarGain solHeaGai(
    B0=per.B0,
    B1=per.B1,
    y_intercept=per.y_intercept,
    nSeg=3,
    A_c=per.A,
    iamDiff=per.IAMDiff,
    shaCoe=0,
    use_shaCoe_in=true,
    redeclare package Medium = Buildings.Media.Water)
    "Solar heat gain model using EN12975 calculations"
  Modelica.Blocks.Sources.Ramp incAng(duration=86400,
    height=60*(2*Modelica.Constants.pi/360)) "Incidence angle"
  Modelica.Blocks.Sources.Sine HDirTil(
    offset=400,
    amplitude=300,
    f=2/86400) "Direct beam radiation, tilted surface"
  Modelica.Blocks.Sources.Sine HDifTil(
    amplitude=200,
    f=1/86400,
    offset=300) "Diffuse radiation, tilted surface"
  Modelica.Blocks.Sources.Ramp shaCoe(
    duration=86400,
    offset=1,
    height=-1) "Shading coefficient"
  Modelica.Blocks.Sources.Sine T3(
    f=2/86400,
    amplitude=50,
    offset=273.15 + 110)
  Modelica.Blocks.Sources.Sine T2(
    f=2/86400,
    amplitude=50,
    offset=273.15 + 100)
  Modelica.Blocks.Sources.Sine T1(
    f=2/86400,
    amplitude=50,
    offset=273.15 + 90)
equation
  connect(incAng.y, solHeaGai.incAng)
  connect(shaCoe.y, solHeaGai.shaCoe_in)
  connect(HDirTil.y, solHeaGai.HDirTil)
  connect(HDifTil.y, solHeaGai.HSkyDifTil)
  connect(T3.y, solHeaGai.TFlu[3])
  connect(T2.y, solHeaGai.TFlu[2])
  connect(T1.y, solHeaGai.TFlu[1])
end EN12975SolarGain;


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


Controller which activates a circulation pump when solar radiation is above a critical level. Pump on/off controller for a solar thermal system.

within Buildings.Obsolete.Fluid.SolarCollectors.Controls;
model CollectorPump
  "Controller which activates a circulation pump when solar radiation is above a critical level"
  extends Modelica.Blocks.Icons.Block;
  extends Buildings.Obsolete.BaseClasses.ObsoleteModel;

  parameter Modelica.Units.SI.HeatFlowRate delQ_flow(min=1)=10
    "Required estimated heat gain per unit area of collector to switch system on";
  parameter Modelica.Units.SI.Angle azi(displayUnit="deg")
    "Surface azimuth (0 for south-facing; -90 degree for east-facing; +90 degree for west facing";
  parameter Modelica.Units.SI.Angle til(displayUnit="deg")
    "Surface tilt (0 for horizontally mounted collector)";
  parameter Real rho(
    final min=0,
    final max=1,
    final unit = "1") = 0.2 "Ground reflectance";

  parameter Buildings.Obsolete.Fluid.SolarCollectors.Data.GenericSolarCollector per
    "Performance data"

  Modelica.Blocks.Interfaces.RealInput TIn(
    final unit = "K",
    final displayUnit = "degC",
    quantity = "ThermodynamicTemperature")
    "Fluid temperature entering the collector"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput on
    "Ouputs true if collector pump should be on"

  Buildings.BoundaryConditions.WeatherData.Bus weaBus "Weather data input"

  Buildings.Obsolete.Fluid.SolarCollectors.Controls.BaseClasses.GCritCalc criSol(
    final slope=per.slope,
    final y_intercept=per.y_intercept)
    "Calculates the critical insolation based on collector design and current weather conditions"
  BoundaryConditions.SolarIrradiation.DiffusePerez HDifTilIso(
    final til=til,
    final azi=azi,
    final rho=rho) "Diffuse solar irradiation on a tilted surface"
  BoundaryConditions.SolarIrradiation.DirectTiltedSurface HDirTil(
    final til=til,
    final azi=azi)
      "Direct solar irradiation on a tilted surface"
  Buildings.Controls.OBC.CDL.Reals.Add HTotTil(
    u1(final unit="W/m2"),
    u2(final unit="W/m2"),
    y(final unit="W/m2"))
    "Total irradiation on tilted surface"

  Buildings.Controls.OBC.CDL.Reals.Hysteresis hys(
      final uLow=0,
      final uHigh=delQ_flow)
protected
  Buildings.Controls.OBC.CDL.Reals.Subtract sub
    "Difference between incident solar and required incident to compensate thermal losses"
equation
  connect(TIn, criSol.TIn)
  connect(weaBus.TDryBul, criSol.TEnv)
  connect(HDirTil.weaBus, weaBus)
  connect(HDifTilIso.weaBus, weaBus)
  connect(HDifTilIso.H, HTotTil.u1)
  connect(HDirTil.H, HTotTil.u2)
  connect(HTotTil.y, sub.u1)
  connect(criSol.G_TC, sub.u2)
  connect(hys.u, sub.y)
  connect(on, hys.y)
end CollectorPump;


within Buildings.Obsolete.Fluid.SolarCollectors;
package Controls "Package for solar thermal collector controllers"
  extends Modelica.Icons.Package;
end Controls;


Controller which activates a circulation pump when solar radiation is above a critical level.

within Buildings.Obsolete.Fluid.SolarCollectors.Controls;
model SolarPumpController
  "Controller which activates a circulation pump when solar radiation is above a critical level"
  extends Modelica.Blocks.Icons.Block;
  extends Buildings.Obsolete.BaseClasses.ObsoleteModel;

  parameter Real delY(final unit = "W/m2") = 0.01
    "Width of the smoothHeaviside function";
  parameter Buildings.Obsolete.Fluid.SolarCollectors.Data.GenericSolarCollector per
    "Performance data"

  Modelica.Blocks.Interfaces.RealInput TIn(final unit = "K",
  final displayUnit = "degC", quantity = "ThermodynamicTemperature")
    "Fluid temperature entering the collector"
  Modelica.Blocks.Interfaces.RealOutput y(min=0, max=1, unit="1")
    "On/off control signal for the pump"
  Buildings.BoundaryConditions.WeatherData.Bus weaBus "Weather data input"

  Buildings.Obsolete.Fluid.SolarCollectors.Controls.BaseClasses.GCritCalc criSol(final
      slope=per.slope, final y_intercept=per.y_intercept)
    "Calculates the critical insolation based on collector design and current weather conditions"
  Modelica.Blocks.Math.Add add(final k2=-1)
    "Compares the current insolation to the critical insolation"
protected
  Buildings.Utilities.Math.SmoothHeaviside smoHea(final delta=delY)
    "Creates a smooth 1/0 output"

equation
  connect(TIn, criSol.TIn)
  connect(weaBus.TDryBul, criSol.TEnv)
  connect(weaBus.HDirNor, add.u1)
  connect(smoHea.y, y)
  connect(add.y, smoHea.u)
  connect(criSol.G_TC, add.u2)
end SolarPumpController;


Model calculating the critical insolation level. This component calculates the solar radiation necessary for the fluid
      in the collector to gain heat. It is used in the model

      Buildings.Obsolete.Fluid.SolarCollectors.Controls.CollectorPump.

within Buildings.Obsolete.Fluid.SolarCollectors.Controls.BaseClasses;
model GCritCalc "Model calculating the critical insolation level"
  extends Buildings.Obsolete.BaseClasses.ObsoleteModel;
  extends Modelica.Blocks.Icons.Block;

  parameter Real slope(unit="W/(m2.K)") "Slope from ratings data";
  parameter Real y_intercept "y_intercept from ratings data";

  Modelica.Blocks.Interfaces.RealInput TIn(unit="K",
  displayUnit = "degC", quantity = "ThermodynamicTemperature")
    "Temperature of water entering the collector"
  Modelica.Blocks.Interfaces.RealOutput G_TC(unit="W/m2",
  quantity = "RadiantEnergyFluenceRate") "Critical radiation level"
  Modelica.Blocks.Interfaces.RealInput TEnv(unit="K",
  displayUnit = "degC", quantity = "ThermodynamicTemperature")
    "Ambient temperature at the collector"

equation
  G_TC = -slope * (TIn - TEnv) / y_intercept;
end GCritCalc;


within Buildings.Obsolete.Fluid.SolarCollectors.Controls;
package BaseClasses "Package of BaseClass models used to create the models in the Controls package"
extends Modelica.Icons.Package;
end BaseClasses;


Example showing the use of GCritCalc. This model provides an example of how to use the

      Buildings.Obsolete.Fluid.SolarCollectors.Controls.BaseClasses.GCritCalc model.

within Buildings.Obsolete.Fluid.SolarCollectors.Controls.BaseClasses.Examples;
model GCritCalc "Example showing the use of GCritCalc"
  extends Modelica.Icons.Example;
  Buildings.Obsolete.Fluid.SolarCollectors.Controls.BaseClasses.GCritCalc criSol(slope=-3.764,
      y_intercept=0.602)
    "Calculates the critical insolation based on collector design and current weather conditions"
  Modelica.Blocks.Sources.Sine TEnv(
    amplitude=10,
    f=0.1,
    offset=10)
  Modelica.Blocks.Sources.Sine TIn(
    amplitude=10,
    f=0.01,
    offset=30)
equation
  connect(TEnv.y, criSol.TEnv)
  connect(TIn.y, criSol.TIn)
end GCritCalc;


within Buildings.Obsolete.Fluid.SolarCollectors.Controls.BaseClasses;
package Examples "Package containing examples demonstrating the use of Controls.BaseClasses models"

  extends Modelica.Icons.ExamplesPackage;
end Examples;


within Buildings.Obsolete.Fluid.SolarCollectors.Controls;
package Examples "Examples for solar thermal collector controller models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Example for the solar pump controller. This model illustrates the use of the

        Buildings.Obsolete.Fluid.SolarCollectors.Controls.SolarPumpController model.
        Based on weather data and inlet temperature, the controller switches the pump on
        and off.

within Buildings.Obsolete.Fluid.SolarCollectors.Controls.Examples;
model SolarPumpController "Example for the solar pump controller"
  extends Modelica.Icons.Example;
  Buildings.Obsolete.Fluid.SolarCollectors.Controls.SolarPumpController
        pumCon(per=
        Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_ThermaLiteHS20())
    "Model controlling the on/off status of the pump"
  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
     filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
    "Weather data input file"
  Modelica.Blocks.Sources.Sine sine(
    amplitude=20,
    f=0.0001,
    offset=273.15 + 40) "Water inlet temperature"
equation
  connect(weaDat.weaBus, pumCon.weaBus)
  connect(sine.y, pumCon.TIn)
end SolarPumpController;


Data for solar thermal collectors

within Buildings.Obsolete.Fluid.SolarCollectors;
package Data "Data for solar thermal collectors"
extends Modelica.Icons.MaterialPropertiesPackage;
end Data;


C - All inputs necessary for verification of EN12975 models.

within Buildings.Obsolete.Fluid.SolarCollectors.Data.Concentrating;
record C_VerificationModel =
  SolarCollectors.Data.GenericSolarCollector (
    final ATyp=Types.Area.Aperture,
    final A=4.302,
    final V=4.4/1000,
    final dp_nominal = 100,
    final mperA_flow_nominal=0.0241,
    final y_intercept=0.720,
    final IAMDiff=0.133,
    final C1=2.8312,
    final C2=0.00119,
    final B0=0,
    final B1=0,
    final mDry=484,
    final slope=0,
    final G_nominal = 1000,
    final dT_nominal = 20)
  "C - All inputs necessary for verification of EN12975 models"


within Buildings.Obsolete.Fluid.SolarCollectors.Data;
package Concentrating "Package with SRCC rating information for concentrating solar thermal collectors"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Concentrating;


within Buildings.Obsolete.Fluid.SolarCollectors.Data;
package GlazedFlatPlate "Package with SRCC rating information for glazed flat-plate solar thermal collectors"
extends Modelica.Icons.MaterialPropertiesPackage;
end GlazedFlatPlate;


within Buildings.Obsolete.Fluid.SolarCollectors.Data;
package Tubular "Package with SRCC rating information for tubular solar thermal collectors"
extends Modelica.Icons.MaterialPropertiesPackage;
end Tubular;


within Buildings.Obsolete.Fluid.SolarCollectors.Examples;
model Concentrating "Example showing the use of Concentrating"
  extends Modelica.Icons.Example;
  replaceable package Medium = Buildings.Media.Water "Medium in the system";
  Buildings.Obsolete.Fluid.SolarCollectors.EN12975 solCol(
    redeclare package Medium = Medium,
    shaCoe=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    use_shaCoe_in=false,
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.Concentrating.C_VerificationModel(),
    sysConfig=Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Series,
    rho=0.2,
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    nPanels=5,
    nSeg=9,
    azi=0.3,
    til=0.5) "Concentrating solar collector model"

  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
    "Weather data input file"
  Buildings.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    use_p_in=false,
    p(displayUnit="Pa") = 101325,
    nPorts=1) "Inlet for fluid flow"
  Buildings.Fluid.Sensors.TemperatureTwoPort TOut(
    redeclare package Medium = Medium,
    T_start(displayUnit="K"),
    m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
  Buildings.Fluid.Sensors.TemperatureTwoPort TIn(redeclare package Medium =
    Medium, m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    use_p_in=true,
    p(displayUnit="Pa")) "Inlet for water flow"
  Modelica.Blocks.Sources.Sine sine(
    f=3/86400,
    offset=101325,
    amplitude=-2*solCol.dp_nominal)
equation
  connect(solCol.port_b,TOut. port_a)
  connect(TOut.port_b,sin. ports[1])
  connect(TIn.port_b,solCol. port_a)
  connect(weaDat.weaBus, solCol.weaBus)
  connect(sine.y, sou.p_in)
  connect(sou.ports[1], TIn.port_a)
end Concentrating;


Test model for FlatPlate

within Buildings.Obsolete.Fluid.SolarCollectors.Examples;
model FlatPlate "Test model for FlatPlate"
  extends Modelica.Icons.Example;
  replaceable package Medium = Modelica.Media.Incompressible.Examples.Glycol47
    "Medium in the system";

  Buildings.Obsolete.Fluid.SolarCollectors.ASHRAE93 solCol(
    redeclare package Medium = Medium,
    shaCoe=0,
    rho=0.2,
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    sysConfig=Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Series,
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_GuangdongFSPTY95(),
    nPanels=1,
    nSeg=9,
    azi=0.3,
    til=0.5,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    massDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Flat plate solar collector model"

  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
    "Weather data input file"
  Buildings.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    p(displayUnit="bar") = 100000,
    nPorts=1) "Outlet for water flow"
  Buildings.Fluid.Sensors.TemperatureTwoPort TOut(
    redeclare package Medium = Medium,
    T_start(displayUnit="K"),
    m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
  Buildings.Fluid.Sensors.TemperatureTwoPort TIn(redeclare package Medium =
    Medium, m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    use_p_in=true) "Inlet for water flow"
  Modelica.Blocks.Sources.Sine sine(
    f=3/86400,
    amplitude=-solCol.dp_nominal,
    offset=1E5) "Pressure source"
equation
  connect(solCol.port_b, TOut.port_a)
  connect(sou.ports[1], TIn.port_a)
  connect(weaDat.weaBus, solCol.weaBus)
  connect(TIn.port_b, solCol.port_a)
  connect(TOut.port_b, sin.ports[1])
  connect(sine.y, sou.p_in)
end FlatPlate;


within Buildings.Obsolete.Fluid.SolarCollectors.Examples;
model FlatPlateShaCoeTrue "Test model for FlatPlate with use_shaCoe_in = true"
  extends Modelica.Icons.Example;
  replaceable package Medium = Buildings.Media.Water "Medium in the system";
  Buildings.Obsolete.Fluid.SolarCollectors.ASHRAE93          solCol(
    redeclare package Medium = Medium,
    shaCoe=0,
    from_dp=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    use_shaCoe_in=true,
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_GuangdongFSPTY95(),
    rho=0.2,
    azi=0,
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    nPanels=5,
    sysConfig=Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Series,
    nSeg=9,
    til=0.5235987755983) "Flat plate solar collector with 3 segments"

  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
    "Weather data input file"
  Buildings.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    use_p_in=false,
    p(displayUnit="Pa") = 101325,
    nPorts=1) "Outlet for water flow"
  Buildings.Fluid.Sensors.TemperatureTwoPort TOut(
    redeclare package Medium = Medium,
    T_start(displayUnit="K"),
    m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
  Buildings.Fluid.Sensors.TemperatureTwoPort TIn(redeclare package Medium =
    Medium, m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    use_p_in=false,
    nPorts=1,
    T=273.15 + 10,
    p(displayUnit="Pa") = 101325 + 5*solCol.per.dp_nominal)
    "Inlet for water flow"
  Modelica.Blocks.Sources.Ramp shaCoe(
    startTime=34040,
    height=1,
    duration=24193) "Varying shading coefficient"
equation
  connect(solCol.port_b, TOut.port_a)
  connect(TOut.port_b, sin.ports[1])
  connect(TIn.port_b, solCol.port_a)
  connect(sou.ports[1], TIn.port_a)
  connect(shaCoe.y, solCol.shaCoe_in)
  connect(weaDat.weaBus, solCol.weaBus)
end FlatPlateShaCoeTrue;


within Buildings.Obsolete.Fluid.SolarCollectors.Examples;
model FlatPlateTotalArea "Example showing the use of TotalArea and nSeg"
  extends Modelica.Icons.Example;
  replaceable package Medium = Buildings.Media.Water "Medium in the system";

  Buildings.Obsolete.Fluid.SolarCollectors.ASHRAE93          solCol(
    redeclare package Medium = Medium,
    shaCoe=0,
    from_dp=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    rho=0.2,
    sysConfig=Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Series,
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_SolahartKf(),
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    nPanels=10,
    nSeg=9,
    azi=0.3,
    til=0.5) "Flat plate solar collector model"

  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
    "Weather data input file"
  Buildings.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    use_p_in=false,
    p(displayUnit="Pa") = 101325,
    nPorts=2) "Outlet for water flow"
  Buildings.Fluid.Sensors.TemperatureTwoPort TOut(
    redeclare package Medium = Medium,
    T_start(displayUnit="K"),
    m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
  Buildings.Fluid.Sensors.TemperatureTwoPort TIn(redeclare package Medium =
    Medium, m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    use_p_in=false,
    nPorts=2,
    p(displayUnit="Pa") = 101325 + solCol.dp_nominal) "Inlet for water flow"

  Buildings.Obsolete.Fluid.SolarCollectors.ASHRAE93 solCol1(
    redeclare package Medium = Medium,
    shaCoe=0,
    from_dp=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    rho=0.2,
    sysConfig=Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Series,
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_SolahartKf(),
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    nPanels=10,
    nSeg=27,
    azi=0.3,
    til=0.5) "Flat plate solar collector model"
  Buildings.Fluid.Sensors.TemperatureTwoPort TOut1(
    redeclare package Medium = Medium,
    T_start(displayUnit="K"),
    m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
  Buildings.Fluid.Sensors.TemperatureTwoPort TIn1(
    redeclare package Medium =
    Medium, m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
equation
  connect(solCol.port_b, TOut.port_a)
  connect(TOut.port_b, sin.ports[1])
  connect(TIn.port_b, solCol.port_a)
  connect(sou.ports[1], TIn.port_a)
  connect(weaDat.weaBus, solCol.weaBus)
  connect(solCol1.port_b, TOut1.port_a)
  connect(TIn1.port_b, solCol1.port_a)
  connect(weaDat.weaBus, solCol1.weaBus)
  connect(sou.ports[2], TIn1.port_a)
  connect(TOut1.port_b, sin.ports[2])
end FlatPlateTotalArea;


within Buildings.Obsolete.Fluid.SolarCollectors.Examples;
model FlatPlateWithTank
  "Example showing use of the flat plate solar collector in a complete solar thermal system"
  extends Modelica.Icons.Example;
  replaceable package Medium = Buildings.Media.Water
    "Fluid in the storage tank";
  replaceable package Medium_2 = Buildings.Media.Water "Fluid flowing through the collector";

  parameter Modelica.Units.SI.Angle azi=0.3
    "Surface azimuth (0 for south-facing; -90 degree for east-facing; +90 degree for west facing";
  parameter Modelica.Units.SI.Angle til=0.78539816339745
    "Surface tilt (0 for horizontally mounted collector)";
  parameter Real rho=0.2 "Ground reflectance";

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal = solCol.m_flow_nominal
    "Nominal mass flow rate";

  Buildings.Obsolete.Fluid.SolarCollectors.ASHRAE93 solCol(
    redeclare package Medium = Medium_2,
    shaCoe=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    nPanels=5,
    sysConfig=Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Series,
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_SolahartKf(),
    nSeg=9,
    final azi=azi,
    final til=til,
    final rho=rho) "Flat plate solar collector model"

  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"),
    computeWetBulbTemperature=false) "Weather data file reader"
  Buildings.Fluid.Sensors.TemperatureTwoPort TOut(
    T_start(displayUnit="K"),
    m_flow_nominal=m_flow_nominal,
    redeclare package Medium = Medium_2) "Temperature sensor"
  Buildings.Fluid.Sensors.TemperatureTwoPort TIn(m_flow_nominal=m_flow_nominal,
    redeclare package Medium = Medium_2) "Temperature sensor"
  Buildings.Fluid.Storage.StratifiedEnhancedInternalHex
   tan(
    nSeg=4,
    redeclare package Medium = Medium,
    hTan=1.8,
    m_flow_nominal=m_flow_nominal,
    VTan=1.5,
    dIns=0.07,
    redeclare package MediumHex = Medium_2,
    CHex=200,
    dExtHex=0.01905,
    hHex_a=0.9,
    hHex_b=0.65,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    Q_flow_nominal=3000,
    mHex_flow_nominal=3000/20/4200,
    T_start=293.15,
    TTan_nominal=293.15,
    THex_nominal=323.15,
    energyDynamicsHex=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Storage tank model"
  Buildings.Obsolete.Fluid.SolarCollectors.Controls.CollectorPump pumCon(
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_ThermaLiteHS20(),
    final azi=azi,
    final til=til,
    final rho=rho)
    "Pump controller"
  Buildings.HeatTransfer.Sources.FixedTemperature rooT(T=293.15)
    "Room temperature"
  Buildings.Fluid.Sources.Boundary_pT bou(redeclare package Medium =
    Medium, nPorts=1) "Outlet for hot water draw"
  Buildings.Fluid.Sources.MassFlowSource_T bou1(
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    nPorts=1,
    m_flow=0.001,
    T=288.15) "Inlet and flow rate for hot water draw"
  Buildings.Fluid.Movers.FlowControlled_m_flow pum(
    redeclare package Medium = Medium_2,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    nominalValuesDefineDefaultPressureCurve=true)
    "Pump forcing circulation through the system"
  Buildings.Fluid.Storage.ExpansionVessel exp(
    redeclare package Medium = Medium_2, V_start=0.1) "Expansion tank"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor TTan
    "Temperature in the tank water that surrounds the heat exchanger"

  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea(realTrue=
        m_flow_nominal)
equation
  connect(solCol.port_b,TOut. port_a)
  connect(TIn.port_b,solCol. port_a)
  connect(weaDat.weaBus,solCol. weaBus)
  connect(weaDat.weaBus, pumCon.weaBus)
  connect(rooT.port, tan.heaPorTop)
  connect(rooT.port, tan.heaPorSid)
  connect(pum.port_b, TIn.port_a)
  connect(pum.port_a, exp.port_a)
  connect(exp.port_a, tan.portHex_b)
  connect(TOut.port_b, tan.portHex_a)
  connect(bou.ports[1], tan.port_a)
  connect(bou1.ports[1], tan.port_b)
  connect(tan.heaPorVol[3], TTan.port)
  connect(TTan.T, pumCon.TIn)
  connect(pumCon.on, booToRea.u)
  connect(pum.m_flow_in, booToRea.y)
end FlatPlateWithTank;


within Buildings.Obsolete.Fluid.SolarCollectors;
package Examples "Examples demonstrating the use of models in the SolarCollectors package"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Example showing the use of Tubular

within Buildings.Obsolete.Fluid.SolarCollectors.Examples;
model Tubular "Example showing the use of Tubular"
  extends Modelica.Icons.Example;
  replaceable package Medium = Buildings.Media.Water "Medium in the system";
  Buildings.Obsolete.Fluid.SolarCollectors.ASHRAE93 solCol(
    redeclare package Medium = Medium,
    shaCoe=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    use_shaCoe_in=false,
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.Tubular.T_AMKCollectraAGOWR20(),
    nPanels=10,
    sysConfig=Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Parallel,
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    rho=0.2,
    nSeg=9,
    azi=0.3,
    til=0.5) "Tubular solar collector model"

  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
    "Weather data input file"
  Buildings.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    use_p_in=false,
    p(displayUnit="Pa") = 101325,
    nPorts=1) "Inlet for fluid flow"
  Buildings.Fluid.Sensors.TemperatureTwoPort TOut(
    redeclare package Medium = Medium,
    T_start(displayUnit="K"),
    m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
  Buildings.Fluid.Sensors.TemperatureTwoPort TIn(redeclare package Medium =
    Medium, m_flow_nominal=solCol.m_flow_nominal) "Temperature sensor"
  Modelica.Blocks.Sources.Sine sine(
    f=3/86400,
    offset=101325,
    amplitude=-0.1*solCol.dp_nominal)
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    use_p_in=true,
    p(displayUnit="Pa")) "Inlet for water flow"
equation
  connect(solCol.port_b,TOut. port_a)
  connect(TOut.port_b,sin. ports[1])
  connect(TIn.port_b,solCol. port_a)
  connect(weaDat.weaBus, solCol.weaBus)
  connect(sine.y, sou.p_in)
  connect(sou.ports[1], TIn.port_a)
end Tubular;


within Buildings.Obsolete.Fluid.SolarCollectors;
package Types "Package with type definitions used in solar collector data records"
  extends Modelica.Icons.TypesPackage;
end Types;


within Buildings.Obsolete.Fluid.SolarCollectors.Validation;
model EN12975NPanels
  "Validation model for collector according to EN12975 with different settings for nPanel"
  extends Modelica.Icons.Example;
  replaceable package Medium = Buildings.Media.Water "Medium in the system";

  parameter Integer nPanels=10 "Number of panels";

  Buildings.Obsolete.Fluid.SolarCollectors.EN12975 solCol(
    redeclare package Medium = Medium,
    per=datSolCol,
    shaCoe=0,
    azi=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    rho=0.2,
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    nPanels=1,
    nSeg=30,
    til=0.78539816339745)
    "Flat plate solar collector model, has been modified for validation purposes"

  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"),
      computeWetBulbTemperature=false)
    "Weather data file reader"
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    use_p_in=false,
    p(displayUnit="Pa") = 101325,
    nPorts=1) "Outlet for water flow"
  Buildings.Fluid.Sources.MassFlowSource_T bou(
    nPorts=1,
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    use_T_in=false,
    T=303.15) "Inlet for water flow, at a prescribed flow rate and temperature"

  Buildings.Obsolete.Fluid.SolarCollectors.EN12975 solCol1(
    redeclare package Medium = Medium,
    per=datSolCol,
    shaCoe=0,
    azi=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    rho=0.2,
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    nSeg=30,
    til=0.78539816339745,
    nPanels=nPanels)
    "Flat plate solar collector model, has been modified for validation purposes"
  Buildings.Fluid.Sources.Boundary_pT sou1(
    redeclare package Medium = Medium,
    use_p_in=false,
    p(displayUnit="Pa") = 101325,
    nPorts=1) "Outlet for water flow"
  Buildings.Fluid.Sources.MassFlowSource_T bou1(
    nPorts=1,
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    use_T_in=false,
    T=303.15) "Inlet for water flow, at a prescribed flow rate and temperature"
  Modelica.Blocks.Math.Gain gaiNPan(k=nPanels) "Gain for number of panels"
  Modelica.Blocks.Sources.RealExpression difHeaGai(y=solCol.heaGai[30].Q_flow
         - solCol1.heaGai[30].Q_flow/nPanels)
    "Difference in heat gain at last panel between model with 1 and with 30 panels"
  Modelica.Blocks.Sources.RealExpression difHeaLos(y=solCol.QLos[30].Q_flow -
        solCol1.QLos[30].Q_flow/nPanels)
    "Difference in heat loss at last panel between model with 1 and with 30 panels"
  Modelica.Blocks.Sources.Constant m_flow_nominal(k=datSolCol.A*datSolCol.mperA_flow_nominal)
    "Nominal flow rate for one panel"
  parameter Data.Concentrating.C_VerificationModel datSolCol
equation
  connect(weaDat.weaBus, solCol1.weaBus)
  connect(bou1.ports[1], solCol1.port_a)
  connect(sou1.ports[1], solCol1.port_b)
  connect(gaiNPan.y, bou1.m_flow_in)
  connect(solCol.port_a, bou.ports[1])
  connect(solCol.port_b, sou.ports[1])
  connect(solCol.weaBus, weaDat.weaBus)
  connect(m_flow_nominal.y, bou.m_flow_in)
  connect(gaiNPan.u, m_flow_nominal.y)
end EN12975NPanels;


within Buildings.Obsolete.Fluid.SolarCollectors.Validation;
model EN12975_Series
  "Validation model for collector according to EN12975 with different panels in series"
  extends Modelica.Icons.Example;
  replaceable package Medium = Buildings.Media.Water "Medium in the system";

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=solCol.datSolCol.A*
      solCol.datSolCol.mperA_flow_nominal "Nominal mass flow rate";

  model collector
    extends Buildings.Obsolete.Fluid.SolarCollectors.EN12975(
    redeclare final package Medium = Buildings.Media.Water,
    final show_T = true,
    final per=datSolCol,
    final shaCoe=0,
    final azi=0,
    final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    final rho=0.2,
    final nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    nPanels=1,
    final til=0.78539816339745,
    final C=385*perPar.mDry,
    final use_shaCoe_in=false,
    final sysConfig=Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Series);
  parameter SolarCollectors.Data.GenericSolarCollector datSolCol(
    final ATyp=Types.Area.Aperture,
    A=4.302,
    V=4.4/1000,
    final dp_nominal = 100,
    final mperA_flow_nominal=0.0241,
    final y_intercept=0.720,
    final IAMDiff=0.133,
    final C1=2.8312,
    final C2=0.00119,
    final B0=0,
    final B1=0,
    mDry=484,
    final slope=0,
    final G_nominal = 1000,
    final dT_nominal = 20) "Performance data"
  end collector;

  collector solCol(
    nPanels=2,
    nSeg=6)
    "Flat plate solar collector model, has been modified for validation purposes"

  collector solCol1(
    nSeg=3,
    nPanels=1)
    "Flat plate solar collector model, has been modified for validation purposes"

  collector solCol2(
    nSeg=3,
    nPanels=1) "Flat plate solar collector model, has been modified for validation purposes"

  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"),
      computeWetBulbTemperature=false)
    "Weather data file reader"
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    use_p_in=false,
    p(displayUnit="Pa") = 101325,
    nPorts=1) "Outlet for water flow"
  Buildings.Fluid.Sources.MassFlowSource_T bou(
    nPorts=1,
    redeclare package Medium = Medium,
    use_T_in=false,
    m_flow=m_flow_nominal,
    T=303.15) "Inlet for water flow, at a prescribed flow rate and temperature"

  Buildings.Fluid.Sources.Boundary_pT sou1(
    redeclare package Medium = Medium,
    use_p_in=false,
    p(displayUnit="Pa") = 101325,
    nPorts=1) "Outlet for water flow"
  Buildings.Fluid.Sources.MassFlowSource_T bou1(
    nPorts=1,
    redeclare package Medium = Medium,
    use_T_in=false,
    m_flow=m_flow_nominal,
    T=303.15) "Inlet for water flow, at a prescribed flow rate and temperature"

  Buildings.Fluid.Sensors.TemperatureTwoPort senTem(
     redeclare package Medium = Medium,
     tau=0,
     m_flow_nominal=m_flow_nominal)
    "Temperature sensor"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTem1(
    redeclare package Medium = Medium,
    tau=0,
    m_flow_nominal=m_flow_nominal)
    "Temperature sensor"
  Modelica.Blocks.Math.Add dT(final k2=-1) "Temperature difference (must be zero)"
equation
  connect(weaDat.weaBus, solCol1.weaBus)
  connect(bou1.ports[1], solCol1.port_a)
  connect(solCol.port_a, bou.ports[1])
  connect(solCol.weaBus, weaDat.weaBus)
  connect(solCol2.port_a, solCol1.port_b)
  connect(weaDat.weaBus, solCol2.weaBus)
  connect(solCol.port_b, senTem.port_a)
  connect(senTem.port_b, sou.ports[1])
  connect(sou1.ports[1], senTem1.port_b)
  connect(senTem1.port_a, solCol2.port_b)
  connect(dT.u1, senTem.T)
  connect(senTem1.T, dT.u2)
end EN12975_Series;


within Buildings.Obsolete.Fluid.SolarCollectors.Validation;
model ExtremeAmbientConditions
  "Validation model for to ensure that collectors do not freeze or boil"
  extends Modelica.Icons.Example;

  replaceable package Medium = Buildings.Media.Water(T_min=273.15, T_max=273.15+100)
    "Medium in the system";

  ASHRAE93 solAsh(
    redeclare package Medium = Medium,
    shaCoe=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    rho=0.2,
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    sysConfig=Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Series,
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_GuangdongFSPTY95(),
    nPanels=1,
    azi=0.3,
    til=0.5,
    T_start=313.15) "Flat plate solar collector model using the ASHRAE model"
  EN12975 solEn(
    redeclare package Medium = Medium,
    shaCoe=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    rho=0.2,
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    sysConfig=Buildings.Obsolete.Fluid.SolarCollectors.Types.SystemConfiguration.Series,
    nPanels=1,
    azi=0.3,
    til=0.5,
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.Concentrating.C_VerificationModel(),
    T_start=313.15) "Flat plate solar collector model using the EN 12975 model"

  Buildings.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    nPorts=1,
    m_flow=0) "Inlet boundary conditions"
  Buildings.Fluid.Sources.Boundary_pT sou1(
    redeclare package Medium = Medium,
    p(displayUnit="Pa"),
    use_p_in=false,
    nPorts=2) "Inlet boundary conditions"
  Modelica.Blocks.Sources.Ramp TAmb(
    offset=273.15 + 40,
    height=-100,
    duration=10*3600) "Ambient temperature"
  Modelica.Blocks.Sources.Ramp HSol(
    duration=12*3600,
    height=1000,
    startTime=10*3600) "Solar irradiation"

  Buildings.Fluid.Sources.MassFlowSource_T sou2(
    redeclare package Medium = Medium,
    nPorts=1,
    m_flow=0) "Inlet boundary conditions"
  BoundaryConditions.WeatherData.Bus weaBus
  Modelica.Blocks.Sources.Constant const(k=0) "Constant that outputs zero"
  Modelica.Blocks.Sources.Constant solTim(k=12*3600) "Solar time"
  Modelica.Blocks.Sources.Constant lat(k=0.656593) "Location latitude"
  Modelica.Blocks.Sources.Constant alt(k=2) "Location altitude"
  Modelica.Blocks.Sources.Constant const1(k=0)
                                              "Constant that outputs zero"
equation
  connect(sou.ports[1], solAsh.port_a)
  connect(sou2.ports[1], solEn.port_a)
  connect(solAsh.port_b, sou1.ports[1])
  connect(solEn.port_b, sou1.ports[2])
  connect(weaBus, solAsh.weaBus)
  connect(TAmb.y, weaBus.TDryBul)
  connect(HSol.y, weaBus.HDifHor)
  connect(HSol.y, weaBus.HGloHor)
  connect(const.y, weaBus.solZen)
  connect(solTim.y, weaBus.solTim)
  connect(HSol.y, weaBus.HDirNor)
  connect(solEn.weaBus, weaBus)
  connect(lat.y, weaBus.lat)
  connect(alt.y, weaBus.alt)
  connect(const1.y, weaBus.cloTim)
end ExtremeAmbientConditions;


Validation model for FlatPlate

within Buildings.Obsolete.Fluid.SolarCollectors.Validation;
model FlatPlate "Validation model for FlatPlate"
  extends Modelica.Icons.Example;
  replaceable package Medium = Buildings.Media.Water "Medium in the system";
  Buildings.Obsolete.Fluid.SolarCollectors.ASHRAE93
   solCol(
    redeclare package Medium = Medium,
    shaCoe=0,
    azi=0,
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_TRNSYSValidation(),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    rho=0.2,
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    nPanels=1,
    nSeg=30,
    til=0.78539816339745)
    "Flat plate solar collector model, has been modified for validation purposes"

  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"),
      computeWetBulbTemperature=false)
    "Weather data file reader"
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    use_p_in=false,
    p(displayUnit="Pa") = 101325,
    nPorts=1) "Outlet for water flow"
  Buildings.Fluid.Sources.MassFlowSource_T bou(
    nPorts=1,
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    use_T_in=true)
    "Inlet for water flow, at a prescribed flow rate and temperature"
  Modelica.Blocks.Sources.CombiTimeTable datRea(
    tableOnFile=true,
    tableName="TRNSYS",
    columns=2:5,
    fileName=Modelica.Utilities.Files.loadResource(
       "modelica://Buildings/Obsolete/Fluid/SolarCollectors/Examples/ValidationData/TRNSYSAnnualData.txt"),
    smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments)
    "Data reader with inlet conditions from TRNSYS"

  Modelica.Blocks.Math.Add add
    "Converts TRNSYS data from degree Celsius to Kelving"
  Modelica.Blocks.Sources.Constant const(k=273.15)
    "Used to convert TRNSYS data from degree Celsius to Kelving"

equation
  connect(weaDat.weaBus, solCol.weaBus)
  connect(bou.ports[1], solCol.port_a)
  connect(const.y, add.u2)
  connect(add.y, bou.T_in)
  connect(datRea.y[1], add.u1)
  connect(datRea.y[4], bou.m_flow_in)
  connect(sou.ports[1], solCol.port_b)
end FlatPlate;


within Buildings.Obsolete.Fluid.SolarCollectors.Validation;
model FlatPlateNPanels
  "Validation model for flat plate collector with different settings for nPanel"
  extends Buildings.Obsolete.Fluid.SolarCollectors.Validation.FlatPlate;
  parameter Integer nPanels = 10 "Number of panels";
  Buildings.Obsolete.Fluid.SolarCollectors.ASHRAE93
   solCol1(
    redeclare package Medium = Medium,
    shaCoe=0,
    azi=0,
    per=Buildings.Obsolete.Fluid.SolarCollectors.Data.GlazedFlatPlate.FP_TRNSYSValidation(),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    rho=0.2,
    nColType=Buildings.Obsolete.Fluid.SolarCollectors.Types.NumberSelection.Number,
    nSeg=30,
    til=0.78539816339745,
    nPanels=nPanels)
    "Flat plate solar collector model, has been modified for validation purposes"
  Buildings.Fluid.Sources.Boundary_pT sou1(
    redeclare package Medium = Medium,
    use_p_in=false,
    p(displayUnit="Pa") = 101325,
    nPorts=1) "Outlet for water flow"
  Buildings.Fluid.Sources.MassFlowSource_T bou1(
    nPorts=1,
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    use_T_in=true)
    "Inlet for water flow, at a prescribed flow rate and temperature"
  Modelica.Blocks.Math.Gain gaiNPan(k=nPanels) "Gain for number of panels"
  Modelica.Blocks.Sources.RealExpression difHeaGai(
    y=solCol.heaGai[30].Q_flow - solCol1.heaGai[30].Q_flow/nPanels)
    "Difference in heat gain at last panel between model with 1 and with 30 panels"
  Modelica.Blocks.Sources.RealExpression difHeaLos(
    y=solCol.QLos[30].Q_flow - solCol1.QLos[30].Q_flow/nPanels)
    "Difference in heat loss at last panel between model with 1 and with 30 panels"
equation
  connect(weaDat.weaBus, solCol1.weaBus)
  connect(bou1.ports[1], solCol1.port_a)
  connect(add.y, bou1.T_in)
  connect(sou1.ports[1], solCol1.port_b)
  connect(gaiNPan.y, bou1.m_flow_in)
  connect(gaiNPan.u, datRea.y[4])
end FlatPlateNPanels;


Collection of validation models

within Buildings.Obsolete.Fluid.SolarCollectors;
package Validation "Collection of validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Boundary source component. This model defines constant values for boundary conditions:

within Buildings.Obsolete.Fluid.Sources;
model FixedBoundary "Boundary source component"
  extends Buildings.Obsolete.BaseClasses.ObsoleteModel;
  extends Buildings.Fluid.Sources.BaseClasses.PartialSource(final verifyInputs=true);
  parameter Boolean use_p=true "select p or d"
  parameter Medium.AbsolutePressure p=Medium.p_default "Boundary pressure"
  parameter Medium.Density d=Medium.density_pTX(
    p = Medium.p_default,
    T = Medium.T_default,
    X = Medium.X_default) "Boundary density"
  parameter Boolean use_T=true "select T or h"
  parameter Medium.Temperature T=Medium.T_default "Boundary temperature"
  parameter Medium.SpecificEnthalpy h=Medium.h_default
    "Boundary specific enthalpy"
  parameter Medium.MassFraction X[Medium.nX](
    final quantity=Medium.substanceNames) = Medium.X_default
    "Boundary mass fractions m_i/m"

  parameter Medium.ExtraProperty C[Medium.nC](
    final quantity=Medium.extraPropertiesNames)=fill(0, Medium.nC)
    "Boundary trace substances"

protected
  Modelica.Blocks.Interfaces.RealInput T_in_internal(final unit="K",
                                                     displayUnit="degC")
    "Needed to connect to conditional connector";
  Modelica.Blocks.Interfaces.RealInput p_in_internal(final unit="Pa")
    "Needed to connect to conditional connector";
  Modelica.Blocks.Interfaces.RealInput h_in(final unit="J/kg")
    "Needed to connect to conditional connector";

  Modelica.Blocks.Interfaces.RealInput h_in_internal= Medium.specificEnthalpy(Medium.setState_pTX(p_in_internal, T_in_internal, X_in_internal));
  // Modelica.Blocks.Interfaces.RealInput d_in_internal = Medium.density(Medium.setState_pTX(p_in_internal, T_in_internal, X_in_internal));

initial equation
  Modelica.Fluid.Utilities.checkBoundary(Medium.mediumName, Medium.substanceNames,
                                        Medium.singleState, use_p, X,
                                        "FixedBoundary");

equation
  h_in = h;
  if use_p or Medium.singleState then
    p_in_internal = p;
    connect(medium.p, p_in_internal);
  else
    p_in_internal = Medium.p_default;
    connect(medium.p, p_in_internal);
  end if;
  if use_T then
    T_in_internal = T;
    connect(medium.h, h_in_internal);
  else
    T_in_internal = Medium.T_default;
    connect(medium.h, h_in);
  end if;

  X_in_internal = X;
  connect(X_in_internal[1:Medium.nXi], Xi_in_internal);
  connect(medium.Xi, Xi_in_internal);

  ports.C_outflow = fill(C, nPorts);
  C_in_internal = C;

  if not verifyInputs then
    h_in_internal = Medium.h_default;
    p_in_internal = Medium.p_default;
    X_in_internal = Medium.X_default;
    T_in_internal = Medium.T_default;
  end if;

  for i in 1:nPorts loop
     ports[i].p          = p_in_internal;
     ports[i].h_outflow  = h_in_internal;
     ports[i].Xi_outflow = Xi_in_internal;
  end for;
end FixedBoundary;


Package with boundary condition models

within Buildings.Obsolete.Fluid;
package Sources "Package with boundary condition models"
  extends Modelica.Icons.SourcesPackage;
end Sources;


within Buildings.Obsolete;
package Templates "Package with templates for various HVAC systems"
  extends Modelica.Icons.Package;
end Templates;


Central plants

within Buildings.Obsolete.Templates;
package Plants "Central plants"
  extends Modelica.Icons.Package;
end Plants;


Control blocks

within Buildings.Obsolete.Templates.Plants;
package Controls "Control blocks"
end Controls;


Package with utility blocks

within Buildings.Obsolete.Templates.Plants.Controls;
package Utilities "Package with utility blocks"
end Utilities;


Sort elements of input vector in ascending or descending order. Block that sorts the elements of the input signal u.
If the parameter ascending = true, then the output signal y satisfies
yi <= yi+1 for all i ∈ {1, ..., n-1}.
Otherwise, it satisfies
yi >= yi+1 for all i ∈ {1, ..., n-1}.
The output signal yIdx contains the indices of the sorted elements,
with respect to the input vector u.

within Buildings.Obsolete.Templates.Plants.Controls.Utilities;
block SortWithIndices
  "Sort elements of input vector in ascending or descending order"
  extends Modelica.Icons.ObsoleteModel;
  parameter Integer nin(
    final min=0)=0
    "Number of input connections"
  parameter Boolean ascending=true
    "Set to true if ascending order, otherwise order is descending";
  Buildings.Controls.OBC.CDL.Interfaces.RealInput u[nin]
    "Connector of Real input signals"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput y[nin]
    "Sorted vector"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yIdx[nin]
    "Indices of the sorted vector with respect to the original vector"
equation
  (y, yIdx)=Modelica.Math.Vectors.sort(u,
    ascending=ascending);
end SortWithIndices;


Collection of validation models

within Buildings.Obsolete.Templates.Plants.Controls.Utilities;
package Validation "Collection of validation models"
end Validation;


Validation model for the Sort block. Validation model for the block

Buildings.Obsolete.Templates.Plants.Controls.Utilities.SortWithIndices.

within Buildings.Obsolete.Templates.Plants.Controls.Utilities.Validation;
model SortWithIndices
  "Validation model for the Sort block"
  Buildings.Obsolete.Templates.Plants.Controls.Utilities.SortWithIndices sorAsc(
    nin=5)
    "Block that sorts signals in ascending order"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ramp1(
    duration=1,
    offset=-2,
    height=4)
    "Block that generates ramp signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ramp2(
    duration=1,
    offset=-1,
    height=3)
    "Block that generates ramp signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ramp3(
    duration=1,
    offset=2,
    height=-4)
    "Block that generates ramp signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ramp4(
    duration=1,
    offset=3,
    height=-1)
    "Block that generates ramp signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ramp5(
    duration=1,
    offset=0,
    height=4)
    "Block that generates ramp signal"
  Buildings.Obsolete.Templates.Plants.Controls.Utilities.SortWithIndices sorDes(
    nin=5,
    ascending=false)
    "Block that sorts signals in descending order"

equation
  connect(ramp1.y,sorAsc.u[1])
  connect(ramp2.y,sorAsc.u[2])
  connect(ramp3.y,sorAsc.u[3])
  connect(ramp4.y,sorAsc.u[4])
  connect(ramp5.y,sorAsc.u[5])
  connect(ramp1.y,sorDes.u[1])
  connect(ramp2.y,sorDes.u[2])
  connect(ramp3.y,sorDes.u[3])
  connect(ramp4.y,sorDes.u[4])
  connect(ramp5.y,sorDes.u[5])
end SortWithIndices;


within Buildings.Obsolete;
package Utilities "Package with obsolete models for utilities"
  extends Modelica.Icons.Package;
end Utilities;


Package with obsolete models for IO

within Buildings.Obsolete.Utilities;
package IO "Package with obsolete models for IO"
  extends Modelica.Icons.Package;
end IO;


within Buildings;
package Occupants "Package with models to simulate building occupant behaviors"
  extends Modelica.Icons.Package;
end Occupants;


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


Test model for binary variable generation function. This model tests the implementation of

Buildings.Occupants.BaseClasses.binaryVariableGeneration.

within Buildings.Occupants.BaseClasses.Validation;
model BinaryVariableGeneration "Test model for binary variable generation function"
  extends Modelica.Icons.Example;

  parameter Integer seed = 5 "Seed for the random number generator";
  Real p "Time-varying real number as input";
  output Real y "Output";
protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
  Real curSeed "Current value for seed as a real-valued variable";

initial equation
  y = 0;
  t0 = time;
  curSeed = t0*seed;

equation
  p = time;
  when sample(0, 0.1) then
    curSeed = seed*1E6*time;
    if Buildings.Occupants.BaseClasses.binaryVariableGeneration(p, globalSeed=integer(curSeed)) then
      y = 1;
    else
      y = 0;
    end if;
  end when;
end BinaryVariableGeneration;


Test model for exponential variable generation function. This model tests the implementation of

Buildings.Occupants.BaseClasses.exponentialVariableGeneration.

within Buildings.Occupants.BaseClasses.Validation;
model ExponentialVariableGeneration "Test model for exponential variable generation function"
  extends Modelica.Icons.Example;

  parameter Integer seed = 5 "Seed for the random number generator";
  Real mu "Time-varying real number as input";
  output Real y "Output";
protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
  Real curSeed "Current value for seed as a real-valued variable";

initial equation
  y = 0;
  t0 = time;
  curSeed = t0*seed;

equation
  mu = 10*time;
  when sample(0, 0.1) then
    curSeed = seed*1E6*time;
    y = Buildings.Occupants.BaseClasses.exponentialVariableGeneration(mu, globalSeed=integer(curSeed));
  end when;
end ExponentialVariableGeneration;


Test model for 1D binary variable generation function. This model tests the implementation of

Buildings.Occupants.BaseClasses.linear1D.

within Buildings.Occupants.BaseClasses.Validation;
model Linear1D "Test model for 1D binary variable generation function"
  extends Modelica.Icons.Example;

  parameter Integer seed = 5 "Seed for the random number generator";
  parameter Real A = 0.9 "Parameter A";
  parameter Real B = 0 "Parameter B";
  Real x "Time-varying real number as input";
  output Real y "Output";
protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
  Real curSeed "Current value for seed as a real-valued variable";

initial equation
  y = 0;
  t0 = time;
  curSeed = t0*seed;

equation
  x = time;
  when sample(0, 0.1) then
    curSeed = seed*1E6*time;
    if Buildings.Occupants.BaseClasses.linear1D(x,A,B,globalSeed=integer(curSeed)) then
      y = 1;
    else
      y = 0;
    end if;
  end when;
end Linear1D;


Test model for 1D binary variable generation function. This model tests the implementation of

Buildings.Occupants.BaseClasses.logit1D.

within Buildings.Occupants.BaseClasses.Validation;
model Logit1D "Test model for 1D binary variable generation function"
 extends Modelica.Icons.Example;

  parameter Integer seed = 5 "Seed for the random number generator";
  parameter Real A = 0.9 "Parameter A";
  parameter Real B = 0 "Parameter B";
  Real x "Time-varying real number as input";
  output Real y "Output";
protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
  Real curSeed "Current value for seed as a real-valued variable";

initial equation
  y = 0;
  t0 = time;
  curSeed = t0*seed;

equation
  x = time;
  when sample(0, 0.1) then
    curSeed = seed*1E6*time;
    if Buildings.Occupants.BaseClasses.logit1D(x,A,B,globalSeed=integer(curSeed)) then
      y = 1;
    else
      y = 0;
    end if;
  end when;
end Logit1D;


Test model for 1D binary variable generation function. This model tests the implementation of

Buildings.Occupants.BaseClasses.logit1DQuadratic.

within Buildings.Occupants.BaseClasses.Validation;
model Logit1DQuadratic "Test model for 1D binary variable generation function"
 extends Modelica.Icons.Example;

  parameter Integer seed = 5 "Seed for the random number generator";
  parameter Real A = 0.1 "Parameter A";
  parameter Real B = 0.5 "Parameter B";
  parameter Real C = 1.3 "Parameter A";
  parameter Real D = 1.5 "Parameter B";
  Real x "Time-varying real number as input";
  output Real y "Output";
protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
  Real curSeed "Current value for seed as a real-valued variable";

initial equation
  y = 0;
  t0 = time;
  curSeed = t0*seed;

equation
  x = time+1;
  when sample(0, 0.1) then
    curSeed = seed*1E6*time;
    if Buildings.Occupants.BaseClasses.logit1DQuadratic(x,A,B,C,D,globalSeed=integer(curSeed)) then
      y = 1;
    else
      y = 0;
    end if;
  end when;
end Logit1DQuadratic;


Test model for 2D binary variable generation function. This model tests the implementation of

Buildings.Occupants.BaseClasses.logit2D.

within Buildings.Occupants.BaseClasses.Validation;
model Logit2D "Test model for 2D binary variable generation function"
    extends Modelica.Icons.Example;

    parameter Integer seed = 5 "Seed for the random number generator";
    parameter Real A = 0.9 "Parameter A";
    parameter Real B = 1.3 "Parameter B";
    parameter Real C = 0 "Parameter C";
    Real x1 "Time-varying real number as input";
    Real x2 "Time-varying real number as input";
    output Real y "Output";
protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
    Real curSeed "Current value for seed as a real-valued variable";

initial equation
    y = 0;
    t0 = time;
    curSeed = t0*seed;

equation
    x1 = time;
    x2 = 0.7*time;
    when sample(0, 0.1) then
      curSeed = seed*1E6*time;
      if Buildings.Occupants.BaseClasses.logit2D(x1,x2,A,B,C,globalSeed=integer(curSeed)) then
        y = 1;
      else
       y = 0;
      end if;
    end when;
end Logit2D;


within Buildings.Occupants.BaseClasses;
package Validation "Package with examples to validate functions in BaseClasses package"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Test model for 1D binary variable generation function. This model tests the implementation of

Buildings.Occupants.BaseClasses.weibull1DOFF.

within Buildings.Occupants.BaseClasses.Validation;
model Weibull1DOFF "Test model for 1D binary variable generation function"
  extends Modelica.Icons.Example;

  parameter Integer seed = 5 "Seed for the random number generator";
  parameter Real u=1.0 "Parameter defining the Weibull distribution threshold";
  parameter Real L=0.5 "Parameter defining the Weibull distribution normalization factor";
  parameter Real k=1.0 "Parameter defining the Weibull distribution shape factor";
  parameter Real dt=0.2 "Time step length";

  Real x "Time-varying real number as input";
  output Real y "Output";
protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
  Real curSeed "Current value for seed as a real-valued variable";

initial equation
  y = 0;
  t0 = time;
  curSeed = t0*seed;

equation
  x = time;
  when sample(0, 0.1) then
    curSeed = seed*1E6*time;
    if Buildings.Occupants.BaseClasses.weibull1DOFF(x,u,L,k,dt,globalSeed=integer(curSeed)) then
      y = 1;
    else
      y = 0;
    end if;
  end when;
end Weibull1DOFF;


Test model for 1D binary variable generation function. This model tests the implementation of

Buildings.Occupants.BaseClasses.weibull1DON.

within Buildings.Occupants.BaseClasses.Validation;
model Weibull1DON "Test model for 1D binary variable generation function"
    extends Modelica.Icons.Example;

  parameter Integer seed = 5 "Seed for the random number generator";
  parameter Real u=0.2 "Parameter defining the Weibull distribution threshold";
  parameter Real L=0.1 "Parameter defining the Weibull distribution normalization factor";
  parameter Real k=1.0 "Parameter defining the Weibull distribution shape factor";
  parameter Real dt=0.2 "Time step length";

  Real x "Time-varying real number as input";
  output Real y "Output";
protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
  Real curSeed "Current value for seed as a real-valued variable";

initial equation
  y = 0;
  t0 = time;
  curSeed = t0*seed;

equation
  x = time;
  when sample(0, 0.1) then
    curSeed = seed*1E6*time;
    if Buildings.Occupants.BaseClasses.weibull1DON(x,u,L,k,dt,globalSeed=integer(curSeed)) then
      y = 1;
    else
      y = 0;
    end if;
  end when;
end Weibull1DON;


Test model for real variable generation function. This model tests the implementation of

Buildings.Occupants.BaseClasses.weibullVariableGeneration.

within Buildings.Occupants.BaseClasses.Validation;
model WeibullVariableGeneration "Test model for real variable generation function"
  extends Modelica.Icons.Example;

  parameter Integer seed = 5 "Seed for the random number generator";
  parameter Real lambda=10 "Time step length";

  Real k "Time-varying real number as input";

  output Real y "Output";
protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
  Real curSeed "Current value for seed as a real-valued variable";

initial equation
  y = 0;
  t0 = time;
  curSeed = t0*seed;

equation
  k = (time+1);
  when sample(0, 0.1) then
    curSeed = seed*1E6*time;
    y = Buildings.Occupants.BaseClasses.weibullVariableGeneration(lambda,k,globalSeed=integer(curSeed));
  end when;
end WeibullVariableGeneration;


within Buildings.Occupants;
package Office "Package with models to simulate occupant behaviors in office buildings"
    extends Modelica.Icons.Package;
end Office;


A model to predict occupants' blinds behavior with indoor temperature. Model predicting the state of the blinds with the indoor temperature.

within Buildings.Occupants.Office.Blinds;
model Haldi2008BlindsTIn
  "A model to predict occupants' blinds behavior with indoor temperature"
  extends Modelica.Blocks.Icons.DiscreteBlock;
  parameter Real A(final unit="1/K") = 0.425 "Slope of indoor temperature";
  parameter Real B(final unit="1") = -11.37 "Intercept";
  parameter Integer seed = 20 "Seed for the random number generator";
  parameter Modelica.Units.SI.Time samplePeriod=120 "Sample period";

  Modelica.Blocks.Interfaces.RealInput TIn(
    final unit="K",
    displayUnit="degC") "Indoor air temperature"
  Modelica.Blocks.Interfaces.BooleanInput occ
    "Indoor occupancy, true for occupied"
  Modelica.Blocks.Interfaces.RealOutput blindState(
    final min=0,
    final max=1,
    final unit="1")
    "State of blinds, 1 being blinds down"

  Real pDown(
    final unit="1",
    final min=0,
    final max=1) "The probability of lowering the blinds";

protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
  output Boolean sampleTrigger "True, if sample time instant";
  Real curSeed "Current value for seed as a real-valued variable";

initial equation
  t0 = time;
  blindState = 0;
  pDown = 0;
  curSeed = t0*seed;

equation
  sampleTrigger = sample(t0,samplePeriod);
  when sampleTrigger then
    curSeed = seed*time;
    if occ then
      pDown = 1-Modelica.Math.exp(A*(TIn-273.15)+B)/(Modelica.Math.exp(A*(TIn-273.15)+B)+1);
      if Buildings.Occupants.BaseClasses.binaryVariableGeneration(p=pDown, globalSeed=integer(curSeed)) then
        blindState = 0;
      else
        blindState = 1;
      end if;
    else
      pDown = 0;
      blindState = 1;
    end if;
  end when;
end Haldi2008BlindsTIn;


A model to predict occupants' blinds behavior with outdoor temperature. Model predicting the state of the blinds with the outdoor temperature.

within Buildings.Occupants.Office.Blinds;
model Haldi2008BlindsTOut
  "A model to predict occupants' blinds behavior with outdoor temperature"
  extends Modelica.Blocks.Icons.DiscreteBlock;
  parameter Real A(final unit="1/K") = 0.139 "Slope of outdoor temperature";
  parameter Real B(final unit="1") = -3.54 "Intercept";
  parameter Integer seed = 20 "Seed for the random number generator";
  parameter Modelica.Units.SI.Time samplePeriod=120 "Sample period";

  Modelica.Blocks.Interfaces.RealInput TOut(
    final unit="K",
    displayUnit="degC") "Outdoor air temperature"
  Modelica.Blocks.Interfaces.BooleanInput occ
    "Indoor occupancy, true for occupied"
  Modelica.Blocks.Interfaces.RealOutput blindState(
    final min=0,
    final max=1,
    final unit="1")
    "State of blinds, 1 being blinds down"

  Real pDown(
    final unit="1",
    final min=0,
    final max=1) "The probability of lowering the blinds";

protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
  output Boolean sampleTrigger "True, if sample time instant";
  Real curSeed "Current value for seed as a real-valued variable";

initial equation
  t0 = time;
  blindState = 0;
  pDown = 0;
  curSeed = t0*seed;

equation
  sampleTrigger = sample(t0,samplePeriod);
  when sampleTrigger then
    curSeed = time*seed;
    if occ then
      pDown = 1-Modelica.Math.exp(A*(TOut-273.15)+B)/(Modelica.Math.exp(A*(TOut-273.15)+B)+1);
      if Buildings.Occupants.BaseClasses.binaryVariableGeneration(p=pDown, globalSeed=integer(curSeed)) then
        blindState = 0;
      else
        blindState = 1;
      end if;
    else
      pDown = 0;
      blindState = 1;
    end if;
  end when;
end Haldi2008BlindsTOut;


A model to predict occupants' blinds behavior with solar intensity (and self-reported brightness sensitivity). Model predicting the state of the blinds with the solar intensity at the window
and occupancy.

within Buildings.Occupants.Office.Blinds;
model Inkarojrit2008BlindsSolarIntensity
    "A model to predict occupants' blinds behavior with solar intensity (and self-reported brightness sensitivity)"
    extends Modelica.Blocks.Icons.DiscreteBlock;
    parameter Real A1 = 3.22 "Slope of solar intensity at window";
    parameter Real A2 = 1.22 "Slope of Occupants' brightness sensitivity";
    parameter Real B = -8.94 "Intercept";
    parameter Real LSen =  4 "Self-reported sensitivity to brightness,
  seven-point scale, 1 for least sensitive, 7 for most sensitive"
    parameter Integer seed = 10 "Seed for the random number generator";
  parameter Modelica.Units.SI.Time samplePeriod=120 "Sample period";

    Modelica.Blocks.Interfaces.RealInput H(unit="W/m2") "Solar intensity"
    Modelica.Blocks.Interfaces.BooleanInput occ
      "Indoor occupancy, true for occupied"
    Modelica.Blocks.Interfaces.RealOutput blindState(
    final min=0,
    final max=1,
    final unit="1")
      "State of blinds, 1 being blinds down"

    Real p(
      final unit="1",
      final min=0,
      final max=1) "The probability of keeping the blinds on";

protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
    output Boolean sampleTrigger "True, if sample time instant";
    Real curSeed "Current value for seed as a real-valued variable";

initial equation
    t0 = time;
    curSeed = t0*seed;
    blindState = 0;
    p = 0;

equation
    sampleTrigger = sample(t0,samplePeriod);
    when sampleTrigger then
      curSeed = seed*time;
      if occ then
        p = 1 - Modelica.Math.exp(A1*Modelica.Math.log10(H) + A2*LSen + B)/(
          Modelica.Math.exp(A1*Modelica.Math.log10(H) + A2*LSen + B) + 1);
        if Buildings.Occupants.BaseClasses.binaryVariableGeneration(p, globalSeed=integer(curSeed)) then
          blindState = 1;
        else
          blindState = 0;
        end if;
      else
        p = 0;
        blindState = 1;
      end if;
    end when;
end Inkarojrit2008BlindsSolarIntensity;


A model to predict occupants' blinds behavior with solar intensity. Model predicting the state of the blinds with the solar intensity at the window
and occupancy.

within Buildings.Occupants.Office.Blinds;
model Newsham1994BlindsSolarIntensity
    "A model to predict occupants' blinds behavior with solar intensity"
    extends Modelica.Blocks.Icons.DiscreteBlock;
    parameter Real HSet = 233 "Threshold for moving blinds up or down";
  parameter Modelica.Units.SI.Time samplePeriod=120 "Sample period";

    Modelica.Blocks.Interfaces.RealInput H(unit="W/m2") "Solar intensity at the room-side of the window"
    Modelica.Blocks.Interfaces.BooleanInput occ
      "Indoor occupancy, true for occupied"
    Modelica.Blocks.Interfaces.RealOutput blindState(
    final min=0,
    final max=1,
    final unit="1")
    "State of blinds, 1 being blinds down"

protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
    output Boolean sampleTrigger "True, if sample time instant";

initial equation
    t0 = time;
    blindState = 0;

equation
    sampleTrigger = sample(t0,samplePeriod);
    when sampleTrigger then
      if occ then
        if H < HSet then
          blindState = 1;
        else
          blindState = 0;
        end if;
      else
        blindState = 1;
      end if;
    end when;
end Newsham1994BlindsSolarIntensity;


within Buildings.Occupants.Office;
package Blinds "Package with models to simulate blinds behaviors in office buildings"
  extends Modelica.Icons.VariantsPackage;
end Blinds;


A model to predict occupants' blinds behavior with solar altitude. Model predicting the state of the blinds with the solar altitude
and occupancy.

within Buildings.Occupants.Office.Blinds;
model Zhang2012BlindsSolarAltitude
  "A model to predict occupants' blinds behavior with solar altitude"
  extends Modelica.Blocks.Icons.DiscreteBlock;
  parameter Real AUp = 1.089 "Slope of solar altitude for blinds up";
  parameter Real ADown = 1.031 "Slope of solar altitude for blinds down";
  parameter Real BUp = -3.446 "Intercept for blinds up";
  parameter Real BDown = -3.424 "Intercept for blinds down";
  parameter Integer seed = 10 "Seed for the random number generator";
  parameter Modelica.Units.SI.Time samplePeriod=120 "Sample period";

  Modelica.Blocks.Interfaces.RealInput solarAltitude(
    unit="rad") "Solar Altitude"
  Modelica.Blocks.Interfaces.BooleanInput occ
    "Indoor occupancy, true for occupied"
  Modelica.Blocks.Interfaces.RealOutput blindState(
    final min=0,
    final max=1,
    final unit="1")
    "State of blinds, 1 being up, 0 being down"

  Real pUp(
    final unit="1",
    final min=0,
    final max=1) "The probability of blinds up";
  Real pDown(
    final unit="1",
    final min=0,
    final max=1) "The probability of blinds down";

protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
  output Boolean sampleTrigger "True, if sample time instant";
  Boolean isOpen "Blind state as a boolean";
  Real curSeed "Current value for seed as a real-valued variable";

initial equation
  t0 = time;
  curSeed = t0*seed;

  isOpen = false "Initial state of blinds is deployed";
  blindState = if isOpen then 0.0 else 1.0;

  pUp = 0;
  pDown = 0;

equation
  sampleTrigger = sample(t0,samplePeriod);
  when sampleTrigger then
    curSeed = seed*time;
    if occ then
      if not pre(isOpen) then // blindState is either 0 or 1.
        pUp = 0;
        pDown = Modelica.Math.exp(ADown*solarAltitude+BDown)/(Modelica.Math.exp(ADown*solarAltitude+BDown)+1);
        isOpen = Buildings.Occupants.BaseClasses.binaryVariableGeneration(p=pDown,globalSeed=integer(curSeed));
      else
        pUp = Modelica.Math.exp(AUp*solarAltitude+BUp)/(Modelica.Math.exp(AUp*solarAltitude+BUp)+1);
        pDown = 0;
        isOpen = not Buildings.Occupants.BaseClasses.binaryVariableGeneration(p=pUp,globalSeed=integer(curSeed));
      end if;
    else
      pUp = 0;
      pDown = 0;
      isOpen = false;
    end if;
    blindState = if isOpen then 0.0 else 1.0;

  end when;
end Zhang2012BlindsSolarAltitude;


within Buildings.Occupants.Office.Blinds;
model Zhang2012BlindsSolarIntensity
    "A model to predict occupants' blinds behavior with solar intensity"
    extends Modelica.Blocks.Icons.DiscreteBlock;
    parameter Real AUp = 0.003 "Slope of solar intensity for blinds up";
    parameter Real ADown = 0.002 "Slope of solar intensity for blinds down";
    parameter Real BUp = -3.33 "Intercept for blinds up";
    parameter Real BDown = -3.17 "Intercept for blinds down";
    parameter Integer seed = 10 "Seed for the random number generator";
  parameter Modelica.Units.SI.Time samplePeriod=120 "Sample period";

    Modelica.Blocks.Interfaces.RealInput H(
      unit="W/m2") "Solar intensity"
    Modelica.Blocks.Interfaces.BooleanInput occ
      "Indoor occupancy, true for occupied"
    Modelica.Blocks.Interfaces.RealOutput blindState(
    final min=0,
    final max=1,
    final unit="1")
      "State of blinds, 1 being blinds down"

    Real pUp(
      final unit="1",
      final min=0,
      final max=1) "The probability of blinds up";
    Real pDown(
      final unit="1",
      final min=0,
      final max=1) "The probability of blinds down";

protected
  parameter Modelica.Units.SI.Time t0(final fixed=false)
    "First sample time instant";
    output Boolean sampleTrigger "True, if sample time instant";
    Boolean isOpen "Blind state as a boolean";
    Real curSeed "Current value for seed as a real-valued variable";
initial equation
    t0 = time;
    curSeed = t0*seed;

    isOpen = false "Initial state of blinds is deployed";
    blindState = if isOpen then 0.0 else 1.0;

    pUp = 0;
    pDown = 0;

equation
    sampleTrigger = sample(t0,samplePeriod);
    when sampleTrigger then
      curSeed = seed*time;
      if occ then
        if pre(isOpen) == false then
          pUp = 0;
          pDown = Modelica.Math.exp(ADown*H+BDown)/(Modelica.Math.exp(ADown*H+BDown)+1);
          isOpen = Buildings.Occupants.BaseClasses.binaryVariableGeneration(p=pDown,globalSeed=integer(curSeed));
        else
          pUp = Modelica.Math.exp(AUp*H+BUp)/(Modelica.Math.exp(AUp*H+BUp)+1);
          pDown = 0;
          isOpen = not Buildings.Occupants.BaseClasses.binaryVariableGeneration(p=pUp,globalSeed=integer(curSeed));
        end if;
      else
        pUp = 0;
        pDown = 0;
        isOpen = false;
      end if;
      blindState = if isOpen then 0.0 else 1.0;
    end when;
end Zhang2012BlindsSolarIntensity;


Validating the model for blind behaviors. This example validates

Buildings.Occupants.Office.Blinds.Haldi2008BlindsTIn
by examing how the blinds state corresponds
to the indoor temperature.

within Buildings.Occupants.Office.Blinds.Validation;
model Haldi2008BlindsTIn
  "Validating the model for blind behaviors"
  extends Modelica.Icons.Example;

  Modelica.Blocks.Sources.BooleanStep occ(startTime=1800)
    "True for occupied"
  Modelica.Blocks.Sources.Sine TIn(
    amplitude=15,
    offset=293,
    f=0.001,
    y(unit="K", displayUnit="degC")) "Indoor temperature"
  Buildings.Occupants.Office.Blinds.Haldi2008BlindsTIn bli     "Tested blinds model"
equation
  connect(occ.y, bli.occ)
  connect(TIn.y, bli.TIn)
end Haldi2008BlindsTIn;


Validating the model for blind behaviors. This example validates

Buildings.Occupants.Office.Blinds.Haldi2008BlindsTOut
by examing how the blinds state corresponds
to the outdoor temperature.

within Buildings.Occupants.Office.Blinds.Validation;
model Haldi2008BlindsTOut
  "Validating the model for blind behaviors"
  extends Modelica.Icons.Example;

  Modelica.Blocks.Sources.BooleanStep occ(startTime=1800)
    "True for occupied"
  Modelica.Blocks.Sources.Sine TOut(
    amplitude=15,
    offset=293,
    f=0.001,
    y(unit="K", displayUnit="degC")) "Outdoor temperature"
  Buildings.Occupants.Office.Blinds.Haldi2008BlindsTOut bli    "Tested blinds model"
equation
  connect(occ.y, bli.occ)
  connect(TOut.y, bli.TOut)
end Haldi2008BlindsTOut;


Validating the model for blind behaviors. This example validates

Buildings.Occupants.Office.Blinds.Inkarojrit2008BlindsSolarIntensity
by examing how the blinds state corresponds
to the solar intensity.

within Buildings.Occupants.Office.Blinds.Validation;
model Inkarojrit2008BlindsSolarIntensity
    "Validating the model for blind behaviors"
    extends Modelica.Icons.Example;

    Modelica.Blocks.Sources.BooleanStep occ(startTime=1800)
                                            "True for occupied"
  Modelica.Blocks.Sources.Sine H(
    amplitude=250,
    offset=300,
    f=0.001,
    y(unit="W/m2")) "Solar intensity at the window"
    Buildings.Occupants.Office.Blinds.Inkarojrit2008BlindsSolarIntensity bli(LSen= 1)
                               "Tested blinds model"
equation
    connect(occ.y, bli.occ)
    connect(H.y, bli.H)
end Inkarojrit2008BlindsSolarIntensity;