Test model for declination. This model validates the computation of the solar declination, which is the angle between the equatorial plane and the solar beam. The time table solDecNOAA outputs the solar declination according to the computation of the National Oceanic and Atmospheric Administration (NOAA), using their yearly calculator from http://www.esrl.noaa.gov/gmd/grad/solcalc/calcdetails.html. The values differ slightly because the equation in AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Declination is an approximation.

within AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Examples;
model Declination "Test model for declination"
  extends Modelica.Icons.Example;
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Declination decAng
    "Declination angle"
  AixLib.Utilities.Time.ModelTime modTim "Model time"

  Modelica.Blocks.Sources.TimeTable solDecNOAA(table=[
       0, -0.4007544;
 2678400, -0.2960882;
 5097600, -0.1292836;
 7776000,  0.0824143;
10368000,  0.2656267;
13046400,  0.3860123;
15638400,  0.4027150;
18316800,  0.3123199;
20995200,  0.1414929;
23587200, -0.0587907;
26265600, -0.2544026;
28857600, -0.3817216;
28944000, -0.3843185;
31536000, -0.4010977], y(unit="rad")) "Solar declination according to NOAA"
equation
  connect(modTim.y, decAng.nDay)
end Declination;


Test model for incidence angle. This example computes the solar incidence angle on a tilted surface.
This model is also part of more extensive tests that run the
model for different orientations. These tests are at

AixLib.BoundaryConditions.SolarGeometry.Examples.IncidenceAngle.

within AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Examples;
model IncidenceAngle "Test model for incidence angle"
  extends Modelica.Icons.Example;
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Declination decAng
    "Declination angle"
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.SolarHourAngle
    solHouAng "Solar hour angle"
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.IncidenceAngle incAng(
    azi=AixLib.Types.Azimuth.S,
    til=AixLib.Types.Tilt.Wall)
    "Incidence angle"
  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data"
  AixLib.BoundaryConditions.WeatherData.Bus weaBus "Weather bus"
equation
  connect(decAng.decAng, incAng.decAng)
  connect(solHouAng.solHouAng, incAng.solHouAng)
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.cloTim, decAng.nDay)
  connect(weaBus.solTim, solHouAng.solTim)
  connect(weaBus.lat, incAng.lat)
end IncidenceAngle;


within AixLib.BoundaryConditions.SolarGeometry.BaseClasses;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Test model for zenith angle. This example computes the solar azimuth angle.

within AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Examples;
model SolarAzimuth "Test model for zenith angle"
  extends Modelica.Icons.Example;

  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.SolarHourAngle
    solHouAng "Solar hour angle"
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.ZenithAngle zen
    "Zenith angle"
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Declination decAng
    "Declination angle"
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.SolarAzimuth solAzi
    "Solar azimuth"
  WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data"
  WeatherData.Bus weaBus "Weather bus"
equation
  connect(zen.zen, solAzi.zen)
  connect(solHouAng.solHouAng, zen.solHouAng)
  connect(decAng.decAng, solAzi.decAng)
  connect(decAng.decAng, zen.decAng)
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.cloTim, decAng.nDay)
  connect(weaBus.solTim, solHouAng.solTim)
  connect(weaBus.solTim, solAzi.solTim)
  connect(zen.lat, weaBus.lat)
  connect(solAzi.lat, weaBus.lat)
end SolarAzimuth;


Test model for solar hour angle. This example computes the solar hour angle,
which is defined as the angle between the circle
that passes through an observer, the north pole and the south pole,
and the circle that passes through the sun, the north and the south pole.

within AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Examples;
model SolarHourAngle "Test model for solar hour angle"
  extends Modelica.Icons.Example;
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.SolarHourAngle
    solHouAng "Solar hour Angle"
  WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data"
  WeatherData.Bus weaBus "Weather bus"
equation
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.solTim, solHouAng.solTim)
end SolarHourAngle;


Test model for wall solar azimuth angle. This example calculates the wall solar azimuth angle.

within AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Examples;
model WallSolarAzimuth "Test model for wall solar azimuth angle"
extends Modelica.Icons.Example;
  AixLib.BoundaryConditions.SolarGeometry.IncidenceAngle incAng(
    azi=0,
    til=1.5707963267949) "solar incidence angle"
  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data"
  AixLib.BoundaryConditions.WeatherData.Bus weaBus "Weather bus"
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.WallSolarAzimuth
    walSolAzi "Vertical wall solar azimuth angle"
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.AltitudeAngle altAng
    "Altitude angle"
  parameter Modelica.Units.SI.Angle lat=41.98*Modelica.Constants.pi/180
    "Latitude";
equation
  connect(weaDat.weaBus, weaBus)
  connect(weaDat.weaBus, incAng.weaBus)
  connect(incAng.y, walSolAzi.incAng)
  connect(altAng.alt, walSolAzi.alt)
  connect(weaBus.solZen, altAng.zen)
end WallSolarAzimuth;


Test model for zenith angle. This example computes the zenith angle,
which is the angle between the earth surface normal and the sun's beam.

within AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Examples;
model ZenithAngle "Test model for zenith angle"
  extends Modelica.Icons.Example;
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.ZenithAngle zen
    "Zenith angle"
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.Declination decAng
    "Declination angle"
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.SolarHourAngle
    solHouAng "Solar hour angle"
  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data"
  AixLib.BoundaryConditions.WeatherData.Bus weaBus "Weather bus"
equation
  connect(decAng.decAng, zen.decAng)
  connect(solHouAng.solHouAng, zen.solHouAng)
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.cloTim, decAng.nDay)
  connect(weaBus.solTim, solHouAng.solTim)
  connect(weaBus.lat, zen.lat)
end ZenithAngle;


Test model for solar incidence angle. This example computes the solar incidence angle on tilted surfaces.
There are fives surfaces, a horizontal surface and a surface
that faces Norths, East, South and West.

within AixLib.BoundaryConditions.SolarGeometry.Examples;
model IncidenceAngle "Test model for solar incidence angle"
  extends Modelica.Icons.Example;
  AixLib.BoundaryConditions.SolarGeometry.IncidenceAngle incAngHor(
    til=AixLib.Types.Tilt.Ceiling, azi=0.3)
    "Incidence angle on horizontal surface"
  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data (Chicago)"
  AixLib.BoundaryConditions.SolarGeometry.IncidenceAngle incAngNor(
    azi=AixLib.Types.Azimuth.N,
    til=AixLib.Types.Tilt.Wall) "Incidence angle on North-facing surface"
  AixLib.BoundaryConditions.SolarGeometry.IncidenceAngle incAngWes(
    azi=AixLib.Types.Azimuth.W,
    til=AixLib.Types.Tilt.Wall) "Incidence angle on West-facing surface"
  AixLib.BoundaryConditions.SolarGeometry.IncidenceAngle incAngSou(
    azi=AixLib.Types.Azimuth.S,
    til=AixLib.Types.Tilt.Wall) "Incidence angle on South-facing surface"
  AixLib.BoundaryConditions.SolarGeometry.IncidenceAngle incAngEas(
    azi=AixLib.Types.Azimuth.E,
    til=AixLib.Types.Tilt.Wall) "Incidence angle on East-facing surface"
equation
  connect(weaDat.weaBus, incAngHor.weaBus)
  connect(incAngNor.weaBus, weaDat.weaBus)
  connect(incAngWes.weaBus, weaDat.weaBus)
  connect(incAngSou.weaBus, weaDat.weaBus)
  connect(incAngEas.weaBus, weaDat.weaBus)
end IncidenceAngle;


within AixLib.BoundaryConditions.SolarGeometry;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Test model for zenith angle. This example computes the zenith angle,
which is the angle between the earth surface normal and the sun beam.

within AixLib.BoundaryConditions.SolarGeometry.Examples;
model ZenithAngle "Test model for zenith angle"
  extends Modelica.Icons.Example;
  AixLib.BoundaryConditions.SolarGeometry.ZenithAngle zen
    "Zenith angle"
  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
equation
  connect(weaDat.weaBus, zen.weaBus)
end ZenithAngle;


Diffuse solar irradiation on a tilted surface with an isotropic sky model. This component computes the hemispherical diffuse irradiation
on a tilted surface using an isotropic model.
The irradiation is a sum composed of diffuse solar irradiation and
radiation reflected by the ground.
For a definition of the parameters, see the
User's Guide.

within AixLib.BoundaryConditions.SolarIrradiation;
block DiffuseIsotropic
  "Diffuse solar irradiation on a tilted surface with an isotropic sky model"
  extends
    AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.PartialSolarIrradiation;
  parameter Real rho(min=0, max=1, final unit="1")=0.2 "Ground reflectance";
  parameter Boolean outSkyCon=false
    "Output contribution of diffuse irradiation from sky";
  parameter Boolean outGroCon=false
    "Output contribution of diffuse irradiation from ground";

  Modelica.Blocks.Math.Add add "Block to add radiation"

  Modelica.Blocks.Interfaces.RealOutput HSkyDifTil if outSkyCon
    "Diffuse solar irradiation on a tilted surface from the sky"
  Modelica.Blocks.Interfaces.RealOutput HGroDifTil if outGroCon
    "Diffuse solar irradiation on a tilted surface from the ground"
protected
  AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.DiffuseIsotropic
    HDifTilIso(til=til, rho=rho) "Diffuse isotropic irradiation on tilted surface"

equation
  connect(weaBus.HGloHor, HDifTilIso.HGloHor)
  connect(weaBus.HDifHor, HDifTilIso.HDifHor)

  connect(HDifTilIso.HSkyDifTil, add.u1)
  connect(HDifTilIso.HGroDifTil, add.u2)
  connect(add.y, H)

  connect(HDifTilIso.HSkyDifTil, HSkyDifTil)
  connect(HDifTilIso.HGroDifTil, HGroDifTil)
end DiffuseIsotropic;


Hemispherical diffuse irradiation on a tilted surface using Perez's anisotropic sky model. This component computes the hemispherical diffuse irradiation on a tilted surface using an anisotropic
sky model proposed by Perez.
For a definition of the parameters, see the
User's Guide.

within AixLib.BoundaryConditions.SolarIrradiation;
block DiffusePerez
  "Hemispherical diffuse irradiation on a tilted surface using Perez's anisotropic sky model"
  extends
    AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.PartialSolarIrradiation;

  parameter Real rho(min=0, max=1, final unit="1")=0.2 "Ground reflectance";
  parameter Modelica.Units.SI.Angle azi "Surface azimuth";
  parameter Boolean outSkyCon=false
    "Output contribution of diffuse irradiation from sky";
  parameter Boolean outGroCon=false
    "Output contribution of diffuse irradiation from ground";

  Modelica.Blocks.Interfaces.RealOutput HSkyDifTil if outSkyCon
    "Hemispherical diffuse solar irradiation on a tilted surface from the sky"
  Modelica.Blocks.Interfaces.RealOutput HGroDifTil if outGroCon
    "Hemispherical diffuse solar irradiation on a tilted surface from the ground"

protected
  BaseClasses.DiffusePerez HDifTil(
    final til=til,
    final rho=rho) "Diffuse irradiation on tilted surface"
  BaseClasses.SkyClearness skyCle "Sky clearness"
  BaseClasses.BrighteningCoefficient briCoe "Brightening coefficient"
  BaseClasses.RelativeAirMass relAirMas "Relative air mass"
  BaseClasses.SkyBrightness skyBri "Sky brightness"
  SolarGeometry.IncidenceAngle incAng(
    final azi=azi,
    final til=til) "Incidence angle"
  Modelica.Blocks.Math.Add add "Block to add radiations"
equation
  connect(relAirMas.relAirMas, skyBri.relAirMas)
  connect(skyBri.skyBri, briCoe.skyBri)
  connect(skyCle.skyCle, briCoe.skyCle)
  connect(incAng.y, HDifTil.incAng)
  connect(weaBus.solZen, skyCle.zen)
  connect(weaBus.solZen, relAirMas.zen)
  connect(weaBus.solZen, briCoe.zen)
  connect(weaBus.HDirNor, skyCle.HDirNor)
  connect(weaBus.HDifHor, skyCle.HDifHor)
  connect(weaBus.HDifHor, skyBri.HDifHor)
  connect(weaBus.HGloHor, HDifTil.HGloHor)
  connect(weaBus.HDifHor, HDifTil.HDifHor)

  connect(briCoe.F2, HDifTil.briCof2)
  connect(briCoe.F1, HDifTil.briCof1)
  connect(weaBus, incAng.weaBus)
  connect(weaBus.solZen, HDifTil.zen)
  connect(HDifTil.HSkyDifTil, add.u1)
  connect(HDifTil.HGroDifTil, add.u2)
  connect(add.y, H)

  connect(HDifTil.HSkyDifTil, HSkyDifTil)
  connect(HDifTil.HGroDifTil, HGroDifTil)
  connect(weaBus.solTim, skyBri.solTim)
  connect(weaBus.alt, relAirMas.alt)
end DiffusePerez;


Direct solar irradiation on a tilted surface. This component computes the direct solar irradiation on a tilted surface.
For a definition of the parameters, see the
User's Guide.

within AixLib.BoundaryConditions.SolarIrradiation;
block DirectTiltedSurface "Direct solar irradiation on a tilted surface"
  extends
    AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.PartialSolarIrradiation;

  parameter Modelica.Units.SI.Angle azi "Surface azimuth";

  Modelica.Blocks.Interfaces.RealOutput inc(
    final quantity="Angle",
    final unit="rad",
    displayUnit="deg") "Incidence angle"

protected
  SolarGeometry.IncidenceAngle incAng(
    final azi=azi,
    final til=til) "Incidence angle"
  AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.DirectTiltedSurface
    HDirTil "Direct irradition on tilted surface"

equation
  connect(incAng.y, HDirTil.incAng)

  connect(weaBus.HDirNor, HDirTil.HDirNor)
  connect(incAng.y, inc)
  connect(HDirTil.HDirTil, H)

  connect(weaBus, incAng.weaBus)
end DirectTiltedSurface;


Global solar irradiation on a tilted surface with diffuse irradiation calculation following Perez. This component computes the hemispherical direct and diffuse irradiation on a tilted surface
and outputs the global irradiation.

within AixLib.BoundaryConditions.SolarIrradiation;
block GlobalPerezTiltedSurface
  "Global solar irradiation on a tilted surface with diffuse irradiation calculation following Perez"
  extends
    AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.PartialSolarIrradiation;
  parameter Modelica.Units.SI.Angle azi "Surface azimuth";
  parameter Real rho=0.2 "Ground reflectance";
  parameter Boolean outSkyCon=false
    "Output contribution of diffuse irradiation from sky";
  parameter Boolean outGroCon=false
    "Output contribution of diffuse irradiation from ground";
  DiffusePerez HDifTil(
    final til=til,
    final rho=rho,
    final azi=azi,
    final outSkyCon=outSkyCon,
    final outGroCon=outGroCon)
    "Diffuse irradiation on tilted surface"
  DirectTiltedSurface HDirTil(
    final til=til,
    final azi=azi)
    "Direct irradiation on tilted surface"
  Modelica.Blocks.Math.Add HGloTil(
      final k1=1,
      final k2=1)
    "Global irradiation on tilted surface"

equation
  connect(weaBus, HDifTil.weaBus)
  connect(weaBus, HDirTil.weaBus)
  connect(HDifTil.H, HGloTil.u1)
  connect(HDirTil.H, HGloTil.u2)
  connect(HGloTil.y, H)
end GlobalPerezTiltedSurface;


within AixLib.BoundaryConditions;
package SolarIrradiation "Package with models to compute solar irradition"
  extends Modelica.Icons.VariantsPackage;
end SolarIrradiation;


Circumsolar and horizon brightening coefficients. This component computes the circumsolar and horizon brightening coefficients.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses;
block BrighteningCoefficient "Circumsolar and horizon brightening coefficients"
  extends Modelica.Blocks.Icons.Block;
  import H = AixLib.Utilities.Math.Functions.regStep;
  Modelica.Blocks.Interfaces.RealInput zen(
    quantity="Angle",
    unit="rad",
    displayUnit="deg") "Zenith angle of the sun beam"
  Modelica.Blocks.Interfaces.RealInput skyCle
    "Sky clearness. skyCle=1: overcast sky; skyCle=8 clear sky"
  Modelica.Blocks.Interfaces.RealInput skyBri "Sky brightness [0,1]"
  Modelica.Blocks.Interfaces.RealOutput F1
    "Circumsolar brightening coefficient"
  Modelica.Blocks.Interfaces.RealOutput F2 "Horizon brightening coefficient"
protected
  Real F11;
  Real F12;
  Real F13;
  Real F21;
  Real F22;
  Real F23;
  Real d=0.01;
  Real a1;
  Real a2;
  Real a3;
  Real a4;
  Real a5;
  Real a6;
  Real a7;
  Real a8;
  Real b1;
  Real b2;
  Real b3;
  Real b4;
  Real b5;
  Real b6;
  Real b7;
  Real b8;
equation
  b1 = H(
    y1=1,
    y2=0,
    x=1.065 - skyCle,
    x_small=d);
  b2 = H(
    y1=1,
    y2=0,
    x=1.23 - skyCle,
    x_small=d);
  b3 = H(
    y1=1,
    y2=0,
    x=1.50 - skyCle,
    x_small=d);
  b4 = H(
    y1=1,
    y2=0,
    x=1.95 - skyCle,
    x_small=d);
  b5 = H(
    y1=1,
    y2=0,
    x=2.80 - skyCle,
    x_small=d);

  b6 = H(
    y1=1,
    y2=0,
    x=4.50 - skyCle,
    x_small=d);
  b7 = H(
    y1=1,
    y2=0,
    x=6.20 - skyCle,
    x_small=d);
  b8 = H(
    y1=1,
    y2=0,
    x=skyCle - 6.20,
    x_small=d);

  a1 = b1;
  a2 = b2 - b1;
  a3 = b3 - b2;
  a4 = b4 - b3;
  a5 = b5 - b4;
  a6 = b6 - b5;
  a7 = b7 - b6;
  a8 = b8;

  F11 = -0.0083117*a1 + 0.1299457*a2 + 0.3296958*a3 + 0.5682053*a4 + 0.8730280*
    a5 + 1.1326077*a6 + 1.0601591*a7 + 0.6777470*a8;
  F12 = 0.5877285*a1 + 0.6825954*a2 + 0.4868735*a3 + 0.1874525*a4 - 0.3920403*
    a5 - 1.2367284*a6 - 1.5999137*a7 - 0.3272588*a8;
  F13 = -0.0620636*a1 - 0.1513725*a2 - 0.2210958*a3 - 0.2951290*a4 - 0.3616149*
    a5 - 0.4118494*a6 - 0.3589221*a7 - 0.2504286*a8;
  F21 = -0.0596012*a1 - 0.0189325*a2 + 0.0554140*a3 + 0.1088631*a4 + 0.2255647*
    a5 + 0.2877813*a6 + 0.2642124*a7 + 0.1561313*a8;
  F22 = 0.0721249*a1 + 0.0659650*a2 - 0.0639588*a3 - 0.1519229*a4 - 0.4620442*
    a5 - 0.8230357*a6 - 1.1272340*a7 - 1.3765031*a8;
  F23 = -0.0220216*a1 - 0.0288748*a2 - 0.0260542*a3 - 0.0139754*a4 + 0.0012448*
    a5 + 0.0558651*a6 + 0.1310694*a7 + 0.2506212*a8;
  F1 = AixLib.Utilities.Math.Functions.smoothMax(
    0,
    F11 + F12*skyBri + F13*zen,
    0.01);
  F2 = F21 + F22*skyBri + F23*zen;
end BrighteningCoefficient;


Diffuse solar irradiation on a tilted surface with an isotropic model. This component computes the hemispherical diffuse irradiation on a tilted surface.
The irradiation is composed of the diffuse horizontal solar irradiation and the irradiation
that has been reflected by the ground. Both components are adjusted to take into account
the tilt of the receiving surface.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses;
block DiffuseIsotropic
  "Diffuse solar irradiation on a tilted surface with an isotropic model"
  extends Modelica.Blocks.Icons.Block;
  parameter Real rho=0.2 "Ground reflectance";
  parameter Modelica.Units.SI.Angle til(displayUnit="deg") "Surface tilt angle";

  Modelica.Blocks.Interfaces.RealInput HDifHor(quantity=
        "RadiantEnergyFluenceRate", unit="W/m2")
    "Horizontal diffuse solar radiation"
  Modelica.Blocks.Interfaces.RealInput HGloHor(quantity=
        "RadiantEnergyFluenceRate", unit="W/m2") "Horizontal global radiation"

  Modelica.Blocks.Interfaces.RealOutput HGroDifTil(final quantity="RadiantEnergyFluenceRate",
      final unit="W/m2")
    "Diffuse solar irradiation on a tilted surface from the ground"
  Modelica.Blocks.Interfaces.RealOutput HSkyDifTil(final quantity="RadiantEnergyFluenceRate",
      final unit="W/m2")
    "Diffuse solar irradiation on a tilted surface from the sky"
protected
  Real til_c "Cosine of tilt angle";
equation
  til_c = Modelica.Math.cos(til);
  HSkyDifTil = 0.5*HDifHor*(1 + til_c);
  HGroDifTil = 0.5*HGloHor*rho*(1 - til_c);
end DiffuseIsotropic;


Hemispherical diffuse irradiation on a tilted surface with Perez's anisotropic model. This component computes the hemispherical diffuse irradiation on a tilted surface by using an anisotropic model proposed by Perez.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses;
block DiffusePerez
  "Hemispherical diffuse irradiation on a tilted surface with Perez's anisotropic model"
  extends Modelica.Blocks.Icons.Block;
  parameter Real rho=0.2 "Ground reflectance";
  parameter Modelica.Units.SI.Angle til(displayUnit="deg") "Surface tilt angle";
  Modelica.Blocks.Interfaces.RealInput briCof1 "Brightening Coeffcient F1"
  Modelica.Blocks.Interfaces.RealInput briCof2 "Brightening Coeffcient F2"
  Modelica.Blocks.Interfaces.RealInput HDifHor(quantity=
        "RadiantEnergyFluenceRate", unit="W/m2")
    "Diffuse horizontal solar radiation"
  Modelica.Blocks.Interfaces.RealInput HGloHor(quantity=
        "RadiantEnergyFluenceRate", unit="W/m2") "Global horizontal radiation"

  Modelica.Blocks.Interfaces.RealInput zen(
    quantity="Angle",
    unit="rad",
    displayUnit="deg") "Zenith angle of the sun beam"
  Modelica.Blocks.Interfaces.RealInput incAng(
    quantity="Angle",
    unit="rad",
    displayUnit="deg") "Solar incidence angle on the surface"

  Modelica.Blocks.Interfaces.RealOutput HGroDifTil(final quantity=
        "RadiantEnergyFluenceRate", final unit="W/m2")
    "Hemispherical diffuse solar irradiation on a tilted surface from the ground"
  Modelica.Blocks.Interfaces.RealOutput HSkyDifTil(final quantity=
        "RadiantEnergyFluenceRate", final unit="W/m2")
    "Hemispherical diffuse solar irradiation on a tilted surface from the sky"
protected
  Real a;
  Real b;
  constant Real bMin=Modelica.Math.cos(Modelica.Constants.pi*85/180)
    "Lower bound for b";
equation
  a = AixLib.Utilities.Math.Functions.smoothMax(
    0,
    Modelica.Math.cos(incAng),
    0.01);
  b = AixLib.Utilities.Math.Functions.smoothMax(
    bMin,
    Modelica.Math.cos(zen),
    0.01);
  HSkyDifTil = HDifHor*(0.5*(1 - briCof1)*(1 + Modelica.Math.cos(til)) +
    briCof1*a/b + briCof2*Modelica.Math.sin(til));
  HGroDifTil = HGloHor*0.5*rho*(1 - Modelica.Math.cos(til));
end DiffusePerez;


Direct solar irradiation on a tilted surface. This component computes the direct solar irradiation on a tilted surface.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses;
block DirectTiltedSurface "Direct solar irradiation on a tilted surface"
  extends Modelica.Blocks.Icons.Block;
  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 HDirNor(quantity=
        "RadiantEnergyFluenceRate", unit="W/m2") "Direct normal radiation"
  Modelica.Blocks.Interfaces.RealOutput HDirTil(final quantity=
        "RadiantEnergyFluenceRate", final unit="W/m2")
    "Direct solar irradiation on a tilted surface"

equation
  HDirTil =  max(0, Modelica.Math.cos(incAng)*HDirNor);
end DirectTiltedSurface;


within AixLib.BoundaryConditions.SolarIrradiation;
package BaseClasses "Package with base classes for AixLib.BoundaryConditions.SolarIrradiation"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial model that is used to compute the direct and diffuse solar irradiation. This is a partial model that is used to implement the direct and diffuse irradiation.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses;
partial block PartialSolarIrradiation
  "Partial model that is used to compute the direct and diffuse solar irradiation"
  extends Modelica.Blocks.Icons.Block;
  parameter Modelica.Units.SI.Angle til(displayUnit="deg") "Surface tilt";
  Modelica.Blocks.Interfaces.RealOutput H(
     final quantity="RadiantEnergyFluenceRate",
     final unit="W/m2") "Radiation per unit area"

  WeatherData.Bus weaBus "Bus with weather data"
end PartialSolarIrradiation;


Relative air mass. This component computes the relative air mass for sky brightness.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses;
block RelativeAirMass "Relative air mass"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput alt(
    quantity="Length",
    unit="m") "location altitude"
  Modelica.Blocks.Interfaces.RealInput zen(
    quantity="Angle",
    unit="rad",
    displayUnit="deg") "Zenith angle of the sun beam"
  Modelica.Blocks.Interfaces.RealOutput relAirMas "Relative air mass"
protected
  Real zenLim "Zenith angle bounded from above by 90 degree";
  Real zenDeg "Zenith angle in degree";
equation
  zenLim = AixLib.Utilities.Math.Functions.smoothMin(
    zen,
    Modelica.Constants.pi/2,
    0.01);
  zenDeg = zenLim*180/Modelica.Constants.pi;
  relAirMas = exp(-0.0001184*alt)/(Modelica.Math.cos(zenLim) + 0.15*(93.9 - zenDeg)^(-1.253));
end RelativeAirMass;


Sky brightness. This component computes the sky brightness.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses;
block SkyBrightness "Sky brightness"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput relAirMas "Relative air mass"
  Modelica.Blocks.Interfaces.RealInput HDifHor(quantity=
        "RadiantEnergyFluenceRate", unit="W/m2")
    "Horizontal diffuse solar radiation"
  Modelica.Blocks.Interfaces.RealInput solTim(quantity="Time", unit="s")
    "Solar time"
  Modelica.Blocks.Interfaces.RealOutput skyBri "Sky brightness"

  Real extRadCor "Correction for extraterrestrial radiation";
equation
  extRadCor =1 + 0.033*cos(2*Modelica.Constants.pi*(solTim/86400 + 1)/365);
  skyBri = AixLib.Utilities.Math.Functions.smoothMin(
    HDifHor*relAirMas/(1366.1*extRadCor),
    1,
    0.025);
end SkyBrightness;


Sky clearness. This component computes the sky clearness.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses;
block SkyClearness "Sky clearness"
  extends Modelica.Blocks.Icons.Block;

  Modelica.Blocks.Interfaces.RealInput zen(
    quantity="Angle",
    unit="rad",
    displayUnit="deg") "Zenith angle of the sun beam"
  Modelica.Blocks.Interfaces.RealInput HDifHor(quantity=
        "RadiantEnergyFluenceRate", unit="W/m2")
    "Horizontal diffuse solar radiation"
  Modelica.Blocks.Interfaces.RealInput HDirNor(quantity=
        "RadiantEnergyFluenceRate", unit="W/m2")
    "Horizontal global solar radiation"
  Modelica.Blocks.Interfaces.RealOutput skyCle
    "Sky clearness. skyCle=1: overast sky; skyCle=8: clear sky"
  // Set hSmall so that hSmall + deltaX < 1E-4. See info section.
protected
  constant Modelica.Units.SI.Irradiance hSmall=0.5e-4
    "Small radiation for regularization";
  constant Modelica.Units.SI.Irradiance deltaX=hSmall/2
    "Small radiation for regularization";
  constant Real k = 5.534e-6*(180/Modelica.Constants.pi)^3 "Constant factor";
  Real tmp1 "Intermediate variable";
  Modelica.Units.SI.Irradiance HDifHorBou
    "Diffuse horizontal irradiation, bounded away from zero";
equation
  tmp1 =  k*zen^3;
  HDifHorBou = AixLib.Utilities.Math.Functions.smoothMax(
                 x1 = HDifHor,
                 x2 = hSmall,
                 deltaX = deltaX);
  // In the Buildings library, HDirNor is always larger than 1E-4
  // (minus some small undershoot due to regularization. Hence,
  // it makes no sense to simplify the equation for
  // HDirNor < Modelica.Constants.small.
  skyCle = AixLib.Utilities.Math.Functions.smoothLimit(
        x = ((HDirNor+HDifHorBou)/HDifHorBou + tmp1)/(1 + tmp1),
        l = 1,
        u = 8,
        deltaX = 0.01);
end SkyClearness;


Test model for brightening coeffcients. This example computes the circumsolar and horizon brightening coefficients.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.Examples;
model BrighteningCoefficient "Test model for brightening coeffcients"
  extends Modelica.Icons.Example;
  AixLib.BoundaryConditions.SolarGeometry.ZenithAngle zen
  AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.SkyClearness skyCle
  AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.BrighteningCoefficient
    briCoe
  AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.RelativeAirMass
    relAirMas
  AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.SkyBrightness
    skyBri
  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
  AixLib.BoundaryConditions.WeatherData.Bus weaBus
equation
  connect(zen.y, skyCle.zen)
  connect(relAirMas.relAirMas, skyBri.relAirMas)
  connect(zen.y, relAirMas.zen)
  connect(skyBri.skyBri, briCoe.skyBri)
  connect(skyCle.skyCle, briCoe.skyCle)
  connect(zen.y, briCoe.zen)
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.HDifHor, skyCle.HDifHor)
  connect(weaBus.HDifHor, skyBri.HDifHor)
  connect(weaBus, zen.weaBus)
  connect(weaBus.solTim, skyBri.solTim)
  connect(weaBus.HDirNor, skyCle.HDirNor)
  connect(weaBus.alt, relAirMas.alt)
end BrighteningCoefficient;


Test model for diffuse solar irradiation on a tilted surface by using isotropic model. This example computes the hemispherical diffuse irradiation on a tilted surface.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.Examples;
model DiffuseIsotropic
  "Test model for diffuse solar irradiation on a tilted surface by using isotropic model"
  extends Modelica.Icons.Example;
  AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.DiffuseIsotropic
    HDifTilIso(til=1.5707963267949)
  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
  AixLib.BoundaryConditions.WeatherData.Bus weaBus
equation
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.HGloHor, HDifTilIso.HGloHor)
  connect(weaBus.HDifHor, HDifTilIso.HDifHor)
end DiffuseIsotropic;


within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Test model for relative air mass. This example computes the relative air mass for sky brightness.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.Examples;
model RelativeAirMass "Test model for relative air mass"
  extends Modelica.Icons.Example;
  AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.RelativeAirMass
    relAirMas
  AixLib.BoundaryConditions.SolarGeometry.ZenithAngle zen
  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
  WeatherData.Bus weaBus
equation
  connect(zen.y, relAirMas.zen)
  connect(weaDat.weaBus, zen.weaBus)
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.alt, relAirMas.alt)
end RelativeAirMass;


Test model for sky brightness. This example computes the sky brightness.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.Examples;
model SkyBrightness "Test model for sky brightness"
  extends Modelica.Icons.Example;
  AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.RelativeAirMass relAirMas
    "Relative air mass"
  AixLib.BoundaryConditions.SolarGeometry.ZenithAngle zen
    "Zenith angle"
  AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.SkyBrightness skyBri
    "Sky brightness"
  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
    "Weather data"
  AixLib.BoundaryConditions.WeatherData.Bus weaBus "Weather data bus"
equation
  connect(zen.y, relAirMas.zen)
  connect(relAirMas.relAirMas, skyBri.relAirMas)
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.HDifHor, skyBri.HDifHor)
  connect(zen.weaBus, weaBus)
  connect(weaBus.solTim, skyBri.solTim)
  connect(weaBus.alt, relAirMas.alt)
end SkyBrightness;


Test model for sky clearness. This example computes the sky clearness.

within AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.Examples;
model SkyClearness "Test model for sky clearness"
  extends Modelica.Icons.Example;

  AixLib.BoundaryConditions.SolarGeometry.ZenithAngle zen
  AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.SkyClearness skyCle

  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
  AixLib.BoundaryConditions.WeatherData.Bus weaBus
equation
  connect(zen.y, skyCle.zen)

  connect(weaDat.weaBus, weaBus)
  connect(weaBus.HDirNor, skyCle.HDirNor)
  connect(weaBus.HDifHor, skyCle.HDifHor)

  connect(weaBus, zen.weaBus)
end SkyClearness;


Test model for diffuse solar irradiation on a tilted surface using the isotropic model. This example computes the hemispherical diffuse irradiation
on a roof, wall and a floor, using an isotropic sky model.
Since the floor only sees the ground,
it receives the lowest amount of diffuse solar irradiation.

within AixLib.BoundaryConditions.SolarIrradiation.Examples;
model DiffuseIsotropic
  "Test model for diffuse solar irradiation on a tilted surface using the isotropic model"
  extends Modelica.Icons.Example;
  parameter Real rho=0.2 "Ground reflectance";

  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
  AixLib.BoundaryConditions.WeatherData.Bus weaBus "Weather data bus"
  AixLib.BoundaryConditions.SolarIrradiation.DiffuseIsotropic
        HDifRoo(til=AixLib.Types.Tilt.Ceiling,
                rho=rho) "Diffuse irradiation on roof"
  AixLib.BoundaryConditions.SolarIrradiation.DiffuseIsotropic
        HDifFlo(til=AixLib.Types.Tilt.Floor,
                rho=rho) "Diffuse irradiation on floor"
  AixLib.BoundaryConditions.SolarIrradiation.DiffuseIsotropic
        HDifWal(
        til=AixLib.Types.Tilt.Wall,
        rho=rho) "Diffuse irradiation on wall"

equation
  connect(weaDat.weaBus, weaBus)

  connect(weaBus,HDifRoo. weaBus)
  connect(HDifWal.weaBus, weaBus)
  connect(HDifFlo.weaBus, weaBus)
end DiffuseIsotropic;


Test model for diffuse solar irradiation on a tilted surface using the Perez model. This model tests the implementation of Perez' model for diffuse solar radiation.
The three instances of Perez' model compute the diffuse solar
irradiation on a roof, a wall and a floor.
Since the floor only sees the ground but not the radiative heat flow that is
scattered in the atmosphere, it receives the lowest amount of
diffuse solar irradiation.

within AixLib.BoundaryConditions.SolarIrradiation.Examples;
model DiffusePerez
  "Test model for diffuse solar irradiation on a tilted surface using the Perez model"
  extends Modelica.Icons.Example;
  parameter Modelica.Units.SI.Angle azi=0.3 "Azi angle";
  parameter Modelica.Units.SI.Angle til=0.5 "Tilted angle";
  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
  AixLib.BoundaryConditions.WeatherData.Bus weaBus
    "Weather data bus"
  AixLib.BoundaryConditions.SolarIrradiation.DiffusePerez HDifRoo(
    til=AixLib.Types.Tilt.Ceiling,
    azi=0.78539816339745)
    "Diffuse irradiation on roof"
  AixLib.BoundaryConditions.SolarIrradiation.DiffusePerez HDifFlo(
    til=AixLib.Types.Tilt.Floor,
    azi=0.78539816339745)
    "Diffuse irradiation on floor"
  AixLib.BoundaryConditions.SolarIrradiation.DiffusePerez HDifWal(
    til=AixLib.Types.Tilt.Wall,
    azi=0.78539816339745)
    "Diffuse irradiation on wall"
equation
  connect(weaDat.weaBus, weaBus)
  connect(weaBus,HDifRoo. weaBus)

  connect(weaBus, HDifFlo.weaBus)
  connect(weaBus, HDifWal.weaBus)
end DiffusePerez;


Test model for direct solar irradiation on a tilted surface. This model tests the direct solar irradiation received on a ceiling, a wall and a floor.
The assert statement will stop the simulation if the floor receives
any direct solar irradiation.

within AixLib.BoundaryConditions.SolarIrradiation.Examples;
model DirectTiltedSurface
  "Test model for direct solar irradiation on a tilted surface"
  extends Modelica.Icons.Example;

  AixLib.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
  AixLib.BoundaryConditions.SolarIrradiation.DirectTiltedSurface HDirRoo(
    til=AixLib.Types.Tilt.Ceiling,
    azi=0.78539816339745)
    "Direct irradiation on roof"
  AixLib.BoundaryConditions.SolarIrradiation.DirectTiltedSurface HDirFlo(
    til=AixLib.Types.Tilt.Floor,
    azi=0.78539816339745)
    "Direct irradiation on floor"
  AixLib.BoundaryConditions.SolarIrradiation.DirectTiltedSurface HDirWal(
    til=AixLib.Types.Tilt.Wall,
    azi=0.78539816339745)
    "Direct irradiation on wall"
  AixLib.Utilities.Diagnostics.AssertEquality assEqu
    "Assert to ensure that direct radiation received by floor construction is zero"
  Modelica.Blocks.Sources.Constant const(k=0) "Block that outputs zero"
equation
  connect(assEqu.u1, HDirFlo.H)
  connect(const.y, assEqu.u2)
  connect(weaDat.weaBus, HDirRoo.weaBus)
  connect(HDirWal.weaBus, weaDat.weaBus)
  connect(HDirFlo.weaBus, weaDat.weaBus)
end DirectTiltedSurface;


Test model for global solar irradiation on a tilted surface with diffuse
  irradiation calculation based on Perez. This model tests the implementation of global irradiation computation based on Perez' model for diffuse solar radiation.

within AixLib.BoundaryConditions.SolarIrradiation.Examples;
model GlobalPerezTiltedSurface
  "Test model for global solar irradiation on a tilted surface with diffuse
  irradiation calculation based on Perez"
  extends Modelica.Icons.Example;

  parameter Real rho=0.2 "Ground reflectance";

  WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))

  AixLib.BoundaryConditions.SolarIrradiation.GlobalPerezTiltedSurface HGloRoo(
    til=AixLib.Types.Tilt.Ceiling,
    azi=0.78539816339745,
    rho=rho)
    "Diffuse irradiation on roof"
  AixLib.BoundaryConditions.SolarIrradiation.GlobalPerezTiltedSurface HGloFlo(
    til=AixLib.Types.Tilt.Floor,
    azi=0.78539816339745,
    rho=rho)
    "Diffuse irradiation on floor"
  AixLib.BoundaryConditions.SolarIrradiation.GlobalPerezTiltedSurface HGloWal(
    til=AixLib.Types.Tilt.Wall,
    azi=0.78539816339745,
    rho=rho)
    "Diffuse irradiation on wall"
  WeatherData.Bus weaBus
    "Weather data bus"
equation
  connect(weaDat.weaBus,weaBus)
  connect(weaBus,HGloRoo. weaBus)
  connect(weaBus,HGloFlo. weaBus)
  connect(weaBus,HGloWal. weaBus)
end GlobalPerezTiltedSurface;


within AixLib.BoundaryConditions.SolarIrradiation;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Partial model to run BESTEST validation case studies for weather data processing. This model outputs the global radiation with a certain inclination and orientation
using the isotropic sky model and the Perez sky model. The variable H is
the global radiation calculated using the isotropic sky model, while HPer is
the global radiation calculated using the Perez sky model.

within AixLib.BoundaryConditions.Validation;
model IsotropicAndPerezDiffuseRadiation
  "Partial model to run BESTEST validation case studies for weather data processing"
  extends AixLib.BoundaryConditions.SolarIrradiation.BaseClasses.PartialSolarIrradiation;
  Modelica.Blocks.Interfaces.RealOutput HPer(
    final quantity="RadiantEnergyFluenceRate",
    final unit="W/m2")
    "Radiation per unit area using Perez Model"
  parameter Modelica.Units.SI.Angle til(displayUnit="deg") "Surface tilt angle";
  parameter Modelica.Units.SI.Angle azi(displayUnit="deg") "Azimuth angle";
  parameter Real rho=0.2
    "Ground reflectance";
  SolarIrradiation.DirectTiltedSurface HDir(
    til=til,
    azi=azi)
    "Direct Irradiation on tilted surface"
  SolarIrradiation.DiffuseIsotropic HDiffIso(
    til=til,
    rho=rho,
    outSkyCon=true,
    outGroCon=true)
    "Isoentropic diffuse radiation"
  SolarIrradiation.DiffusePerez HDiffPer(
    til=til,
    rho=rho,
    azi=azi,
    outSkyCon=true,
    outGroCon=true)
    "Diffused radiation using Perez"

protected
  Modelica.Blocks.Math.Add addHDirHDiffIso
    "Sum of Direct radiation and Isoentropic radiation"
  Modelica.Blocks.Math.Add addHDirHDiffPer
    "Sum of Direct radiation and Perez radiation"

equation
  connect(weaBus,HDiffIso.weaBus)
  connect(HDir.weaBus,HDiffIso.weaBus)
  connect(HDiffPer.weaBus,HDiffIso.weaBus)
  connect(HDir.H,addHDirHDiffPer.u1)
  connect(HDiffPer.H,addHDirHDiffPer.u2)
  connect(HDiffIso.H,addHDirHDiffIso.u1)
  connect(HDir.H,addHDirHDiffIso.u2)
  connect(addHDirHDiffIso.y,H)
  connect(addHDirHDiffPer.y,HPer)
end IsotropicAndPerezDiffuseRadiation;


within AixLib.BoundaryConditions;
package Validation "Collection of validation models Validation"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


User's Guide

within AixLib.BoundaryConditions.Validation;
package UsersGuide
  "User's Guide"
  extends Modelica.Icons.Information;
end UsersGuide;


within AixLib.BoundaryConditions.Validation;
package BESTEST "Boundary conditions validation according to BESTEST specifications"
  extends Modelica.Icons.ExamplesPackage;
end BESTEST;


Test model for BESTEST weather data: base case.

within AixLib.BoundaryConditions.Validation.BESTEST;
model WD100
  "Test model for BESTEST weather data: base case"
  extends Modelica.Icons.Example;

  parameter Real rho=0
    "Ground reflectance";
  WeatherData.ReaderTMY3 weaDatHHorIR(
    pAtmSou=AixLib.BoundaryConditions.Types.DataSource.File,
    filNam=Modelica.Utilities.Files.loadResource(
      "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD100.mos"),
    calTSky=AixLib.BoundaryConditions.Types.SkyTemperatureCalculation.HorizontalRadiation)
    "Reads all weather data and Tsky using horizontal radiation"
  WeatherData.Bus weaBusHHorIR
    "weather bus to read all weather data and Tsky using horizontal radiation"
  IsotropicAndPerezDiffuseRadiation azi000til00(
    til=AixLib.Types.Tilt.Ceiling,
    azi=AixLib.Types.Azimuth.S,
    rho=rho)
    "Azimuth = Horizontal, Tilt = 0 °"
  IsotropicAndPerezDiffuseRadiation azi000til90(
    til=AixLib.Types.Tilt.Wall,
    azi=AixLib.Types.Azimuth.S,
    rho=rho)
    "Azimuth = South, Tilt = 90 °"
  IsotropicAndPerezDiffuseRadiation azi270til90(
    til=AixLib.Types.Tilt.Wall,
    azi=AixLib.Types.Azimuth.E,
    rho=rho)
    "Azimuth = East, Tilt = 90 °"
  IsotropicAndPerezDiffuseRadiation azi180til90(
    til=AixLib.Types.Tilt.Wall,
    azi=AixLib.Types.Azimuth.N,
    rho=rho)
    "Azimuth = North, Tilt = 90 °"
  IsotropicAndPerezDiffuseRadiation azi090til90(
    til=AixLib.Types.Tilt.Wall,
    azi=AixLib.Types.Azimuth.W,
    rho=rho)
    "Azimuth =  West, Tilt = 90 °"
  IsotropicAndPerezDiffuseRadiation azi315til90(
    til=AixLib.Types.Tilt.Wall,
    azi=AixLib.Types.Azimuth.SE,
    rho=rho)
    "Azimuth = 45 ° SE, Tilt = 0 °"
  IsotropicAndPerezDiffuseRadiation azi045til90(
    til=AixLib.Types.Tilt.Wall,
    azi=AixLib.Types.Azimuth.SW,
    rho=rho)
    "Azimuth = 45 SW, Tilt = 90 °"
  IsotropicAndPerezDiffuseRadiation azi270til30(
    til=0.5235987755983,
    azi=AixLib.Types.Azimuth.E,
    rho=rho)
    "Azimuth = East, Tilt = 30 °"
  IsotropicAndPerezDiffuseRadiation azi000til30(
    til=0.5235987755983,
    azi=AixLib.Types.Azimuth.S,
    rho=rho)
    "Azimuth = South, Tilt = 0 °"
  IsotropicAndPerezDiffuseRadiation azi090til30(
    til=0.5235987755983,
    azi=AixLib.Types.Azimuth.W,
    rho=rho)
    "Azimuth = West, Tilt = 0 °"
  Utilities.Psychrometrics.X_pTphi x_pTphi
  Utilities.Psychrometrics.ToDryAir toDryAir
  WeatherData.ReaderTMY3 weaDatTDryBulTDewPoinOpa(
    pAtmSou=AixLib.BoundaryConditions.Types.DataSource.File,
    filNam=Modelica.Utilities.Files.loadResource(
      "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD100.mos"),
    calTSky=AixLib.BoundaryConditions.Types.SkyTemperatureCalculation.TemperaturesAndSkyCover)
    "Reads all weather data and Tsky using dry bulb temperature, dew point temperature and sky cover"
  WeatherData.Bus weaBusTDryBulTDewPoiOpa
    "Weather bus to read Tsky using dew point temperature and sky cover"

equation
  connect(weaDatHHorIR.weaBus,weaBusHHorIR)
  connect(weaBusHHorIR.pAtm,x_pTphi.p_in)
  connect(weaBusHHorIR.TDryBul,x_pTphi.T)
  connect(weaBusHHorIR.relHum,x_pTphi.phi)
  connect(x_pTphi.X[1],toDryAir.XiTotalAir)
  connect(weaDatTDryBulTDewPoinOpa.weaBus,weaBusTDryBulTDewPoiOpa)
  connect(weaBusHHorIR,azi090til90.weaBus)
  connect(weaBusHHorIR,azi090til30.weaBus)
  connect(weaBusHHorIR,azi000til30.weaBus)
  connect(weaBusHHorIR,azi180til90.weaBus)
  connect(weaBusHHorIR,azi270til30.weaBus)
  connect(weaBusHHorIR,azi270til90.weaBus)
  connect(weaBusHHorIR,azi045til90.weaBus)
  connect(weaBusHHorIR,azi000til90.weaBus)
  connect(weaBusHHorIR,azi315til90.weaBus)
  connect(weaBusHHorIR,azi000til00.weaBus)
end WD100;


Test model for BESTEST weather data: Low Elevation, Hot and Humid Case.

within AixLib.BoundaryConditions.Validation.BESTEST;
model WD200
  "Test model for BESTEST weather data: Low Elevation, Hot and Humid Case"
  extends WD100(
    rho=0,
    weaDatHHorIR(
      filNam=Modelica.Utilities.Files.loadResource(
        "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD200.mos")),
    weaDatTDryBulTDewPoinOpa(
      filNam=Modelica.Utilities.Files.loadResource(
        "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD200.mos")));
end WD200;


Test model for BESTEST weather data: Southern hemisphere case.

within AixLib.BoundaryConditions.Validation.BESTEST;
model WD300
  "Test model for BESTEST weather data: Southern hemisphere case"
  extends WD100(
    rho=0,
    weaDatHHorIR(
      filNam=Modelica.Utilities.Files.loadResource(
        "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD300.mos")),
    weaDatTDryBulTDewPoinOpa(
      filNam=Modelica.Utilities.Files.loadResource(
        "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD300.mos")));
end WD300;


Test model for BESTEST weather data: high latitude case.

within AixLib.BoundaryConditions.Validation.BESTEST;
model WD400
  "Test model for BESTEST weather data: high latitude case"
  extends WD100(
    rho=0,
    weaDatHHorIR(
      filNam=Modelica.Utilities.Files.loadResource(
        "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD400.mos")),
    weaDatTDryBulTDewPoinOpa(
      filNam=Modelica.Utilities.Files.loadResource(
        "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD400.mos")));
end WD400;


Test model for BESTEST weather data: time zone case.

within AixLib.BoundaryConditions.Validation.BESTEST;
model WD500
  "Test model for BESTEST weather data: time zone case"
  extends WD100(
    rho=0,
    weaDatHHorIR(
      filNam=Modelica.Utilities.Files.loadResource(
        "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD500.mos")),
    weaDatTDryBulTDewPoinOpa(
      filNam=Modelica.Utilities.Files.loadResource(
        "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD500.mos")));
end WD500;


Test model for BESTEST weather data: ground reflectance.

within AixLib.BoundaryConditions.Validation.BESTEST;
model WD600
  "Test model for BESTEST weather data: ground reflectance"
  extends WD100(
    rho=0.2,
    weaDatHHorIR(
      filNam=Modelica.Utilities.Files.loadResource(
        "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD600.mos")),
    weaDatTDryBulTDewPoinOpa(
      filNam=Modelica.Utilities.Files.loadResource(
        "modelica://AixLib/Resources/Data/BoundaryConditions/Validation/BESTEST/WD600.mos")));
end WD600;


Weather data reader

within AixLib.BoundaryConditions;
package WeatherData "Weather data reader"
  extends Modelica.Icons.VariantsPackage;
end WeatherData;


Reader for TMY3 weather data

within AixLib.BoundaryConditions.WeatherData;
block ReaderTMY3 "Reader for TMY3 weather data"

  Bus weaBus "Weather data bus"

  //--------------------------------------------------------------
  parameter String filNam="" "Name of weather data file"

  parameter Boolean computeWetBulbTemperature = true
    "If true, then this model computes the wet bulb temperature"

  //--------------------------------------------------------------
  // Atmospheric pressure
  parameter AixLib.BoundaryConditions.Types.DataSource pAtmSou=AixLib.BoundaryConditions.Types.DataSource.Parameter
    "Atmospheric pressure"
  parameter Modelica.Units.SI.Pressure pAtm=101325
    "Atmospheric pressure (used if pAtmSou=Parameter)"
  Modelica.Blocks.Interfaces.RealInput pAtm_in(
    final quantity="Pressure",
    final unit="Pa",
    displayUnit="Pa") if (pAtmSou == AixLib.BoundaryConditions.Types.DataSource.Input)
    "Input pressure"

  //--------------------------------------------------------------
  // Dry bulb temperature
  parameter AixLib.BoundaryConditions.Types.DataSource TDryBulSou=AixLib.BoundaryConditions.Types.DataSource.File
    "Dry bulb temperature"
  parameter Modelica.Units.SI.Temperature TDryBul(displayUnit="degC") = 293.15
    "Dry bulb temperature (used if TDryBul=Parameter)"
  Modelica.Blocks.Interfaces.RealInput TDryBul_in(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") if (TDryBulSou == AixLib.BoundaryConditions.Types.DataSource.Input)
    "Input dry bulb temperature"

  //--------------------------------------------------------------
  // Dew point temperature
  parameter AixLib.BoundaryConditions.Types.DataSource TDewPoiSou=AixLib.BoundaryConditions.Types.DataSource.File
    "Dew point temperature"
  parameter Modelica.Units.SI.Temperature TDewPoi(displayUnit="degC") = 283.15
    "Dew point temperature (used if TDewPoi=Parameter)"
  Modelica.Blocks.Interfaces.RealInput TDewPoi_in(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") if (TDewPoiSou == AixLib.BoundaryConditions.Types.DataSource.Input)
    "Input dew point temperature"

  //--------------------------------------------------------------
  // Black body sky temperature
  parameter AixLib.BoundaryConditions.Types.DataSource TBlaSkySou=AixLib.BoundaryConditions.Types.DataSource.File
    "Black-body sky temperature"
  parameter Modelica.Units.SI.Temperature TBlaSky=273.15
    "Black-body sky temperature (used if TBlaSkySou=Parameter)"
  Modelica.Blocks.Interfaces.RealInput TBlaSky_in(
    final quantity="ThermodynamicTemperature",
    displayUnit="degC",
    final unit="K")
 if (TBlaSkySou == AixLib.BoundaryConditions.Types.DataSource.Input)
    "Black-body sky temperature"
  //--------------------------------------------------------------
  // Relative humidity
  parameter AixLib.BoundaryConditions.Types.DataSource relHumSou=AixLib.BoundaryConditions.Types.DataSource.File
    "Relative humidity"
  parameter Real relHum(
    min=0,
    max=1,
    unit="1") = 0.5 "Relative humidity (used if relHum=Parameter)"
  Modelica.Blocks.Interfaces.RealInput relHum_in(
    min=0,
    max=1,
    unit="1") if (relHumSou == AixLib.BoundaryConditions.Types.DataSource.Input)
    "Input relative humidity"
  //--------------------------------------------------------------
  // Wind speed
  parameter AixLib.BoundaryConditions.Types.DataSource winSpeSou=AixLib.BoundaryConditions.Types.DataSource.File
    "Wind speed"
  parameter Modelica.Units.SI.Velocity winSpe(min=0) = 1
    "Wind speed (used if winSpe=Parameter)"
  Modelica.Blocks.Interfaces.RealInput winSpe_in(
    final quantity="Velocity",
    final unit="m/s",
    min=0) if (winSpeSou == AixLib.BoundaryConditions.Types.DataSource.Input)
    "Input wind speed"
  //--------------------------------------------------------------
  // Wind direction
  parameter AixLib.BoundaryConditions.Types.DataSource winDirSou=AixLib.BoundaryConditions.Types.DataSource.File
    "Wind direction"
  parameter Modelica.Units.SI.Angle winDir=1.0
    "Wind direction (used if winDir=Parameter)"
  Modelica.Blocks.Interfaces.RealInput winDir_in(
    final quantity="Angle",
    final unit="rad",
    displayUnit="deg") if (winDirSou == AixLib.BoundaryConditions.Types.DataSource.Input)
    "Input wind direction"
  //--------------------------------------------------------------
  // Infrared horizontal radiation
  parameter AixLib.BoundaryConditions.Types.DataSource HInfHorSou=AixLib.BoundaryConditions.Types.DataSource.File
    "Infrared horizontal radiation"
  parameter Modelica.Units.SI.HeatFlux HInfHor=0.0
    "Infrared horizontal radiation (used if HInfHorSou=Parameter)"
  Modelica.Blocks.Interfaces.RealInput HInfHor_in(
    final quantity="RadiantEnergyFluenceRate",
    final unit="W/m2") if (HInfHorSou == AixLib.BoundaryConditions.Types.DataSource.Input)
    "Input infrared horizontal radiation"

   parameter AixLib.BoundaryConditions.Types.RadiationDataSource HSou=AixLib.BoundaryConditions.Types.RadiationDataSource.File
    "Global, diffuse, and direct normal radiation"
  //--------------------------------------------------------------
  // Global horizontal radiation
  Modelica.Blocks.Interfaces.RealInput HGloHor_in(
    final quantity="RadiantEnergyFluenceRate",
    final unit="W/m2")
      if (HSou == AixLib.BoundaryConditions.Types.RadiationDataSource.Input_HGloHor_HDifHor or
          HSou == AixLib.BoundaryConditions.Types.RadiationDataSource.Input_HDirNor_HGloHor)
    "Input global horizontal radiation"
  //--------------------------------------------------------------
  // Diffuse horizontal radiation
  Modelica.Blocks.Interfaces.RealInput HDifHor_in(
    final quantity="RadiantEnergyFluenceRate",
    final unit="W/m2")
      if (HSou == AixLib.BoundaryConditions.Types.RadiationDataSource.Input_HGloHor_HDifHor or
          HSou == AixLib.BoundaryConditions.Types.RadiationDataSource.Input_HDirNor_HDifHor)
    "Input diffuse horizontal radiation"
  //--------------------------------------------------------------
  // Direct normal radiation
  Modelica.Blocks.Interfaces.RealInput HDirNor_in(final quantity="RadiantEnergyFluenceRate",
      final unit="W/m2")
      if (HSou == AixLib.BoundaryConditions.Types.RadiationDataSource.Input_HDirNor_HDifHor or
          HSou == AixLib.BoundaryConditions.Types.RadiationDataSource.Input_HDirNor_HGloHor)
    "Input direct normal radiation"

//--------------------------------------------------------------
  // Ceiling height
  parameter AixLib.BoundaryConditions.Types.DataSource ceiHeiSou=AixLib.BoundaryConditions.Types.DataSource.File
    "Ceiling height"
  parameter Real ceiHei(
    final quantity="Height",
    final unit="m",
    displayUnit="m") = 20000 "Ceiling height (used if ceiHei=Parameter)"
  Modelica.Blocks.Interfaces.RealInput ceiHei_in(
    final quantity="Height",
    final unit="m",
    displayUnit="m") if (ceiHeiSou == AixLib.BoundaryConditions.Types.DataSource.Input)
    "Input ceiling height"
  //--------------------------------------------------------------
  // Total sky cover
  parameter AixLib.BoundaryConditions.Types.DataSource totSkyCovSou=AixLib.BoundaryConditions.Types.DataSource.File
    "Total sky cover"
  parameter Real totSkyCov(
    min=0,
    max=1,
    unit="1") = 0.5
    "Total sky cover (used if totSkyCov=Parameter). Use 0 <= totSkyCov <= 1"
  Modelica.Blocks.Interfaces.RealInput totSkyCov_in(
    min=0,
    max=1,
    unit="1") if (totSkyCovSou == AixLib.BoundaryConditions.Types.DataSource.Input)
    "Input total sky cover"
  // Opaque sky cover
  parameter AixLib.BoundaryConditions.Types.DataSource opaSkyCovSou=AixLib.BoundaryConditions.Types.DataSource.File
    "Opaque sky cover"
  parameter Real opaSkyCov(
    min=0,
    max=1,
    unit="1") = 0.5
    "Opaque sky cover (used if opaSkyCov=Parameter). Use 0 <= opaSkyCov <= 1"
  Modelica.Blocks.Interfaces.RealInput opaSkyCov_in(
    min=0,
    max=1,
    unit="1") if (opaSkyCovSou == AixLib.BoundaryConditions.Types.DataSource.Input)
    "Input opaque sky cover"

  parameter AixLib.BoundaryConditions.Types.SkyTemperatureCalculation
    calTSky=AixLib.BoundaryConditions.Types.SkyTemperatureCalculation.TemperaturesAndSkyCover
    "Model choice for black-body sky temperature calculation"

  final parameter Modelica.Units.SI.Angle lon(displayUnit="deg") =
    AixLib.BoundaryConditions.WeatherData.BaseClasses.getLongitudeTMY3(filNam)
    "Longitude";
  final parameter Modelica.Units.SI.Angle lat(displayUnit="deg") =
    AixLib.BoundaryConditions.WeatherData.BaseClasses.getLatitudeTMY3(filNam)
    "Latitude";
  final parameter Modelica.Units.SI.Time timZon(displayUnit="h") =
    AixLib.BoundaryConditions.WeatherData.BaseClasses.getTimeZoneTMY3(filNam)
    "Time zone";
  final parameter Modelica.Units.SI.Length alt(displayUnit="m") =
    AixLib.BoundaryConditions.WeatherData.BaseClasses.getAltitudeLocationTMY3(
    filNam) "Location altitude above sea level";

protected
  final parameter Modelica.Units.SI.Time[2] timeSpan=
      AixLib.BoundaryConditions.WeatherData.BaseClasses.getTimeSpanTMY3(filNam,
      "tab1") "Start time, end time of weather data";

  Modelica.Blocks.Tables.CombiTable1Ds datRea(
    final tableOnFile=true,
    final tableName="tab1",
    final fileName=filNam,
    verboseRead=false,
    final smoothness=Modelica.Blocks.Types.Smoothness.ContinuousDerivative,
    final columns={2,3,4,5,6,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
        28,29,30,8}) "Data reader"

  BaseClasses.SourceSelector pAtmSel(
    final datSou=pAtmSou,
    final p=pAtm) "Source selection for atmospheric pressure"
  BaseClasses.SourceSelector TDewPoiSel(
    final datSou=TDewPoiSou,
    final p=TDewPoi)
    "Source selection for dewpoint temperature pressure"
  BaseClasses.SourceSelector TDryBulSel(
    final datSou=TDryBulSou,
    final p=TDryBul)
    "Source selection for drybulb temperature pressure"
  BaseClasses.SourceSelector TBlaSkySel(
    final datSou=TBlaSkySou,
    final p=TBlaSky)
    "Source selection for sky black body radiation"
  BaseClasses.SourceSelector relHumSel(
    final datSou=relHumSou,
    final p=relHum)
    "Source selection for relative humidity"
  BaseClasses.SourceSelector opaSkyCovSel(
    final datSou=opaSkyCovSou,
    final p=opaSkyCov)
    "Source selection for opaque sky cover"
  BaseClasses.SourceSelector ceiHeiSel(
    final datSou=ceiHeiSou,
    final p=ceiHei)
    "Source selection for ceiling height"
  BaseClasses.SourceSelector totSkyCovSel(
    final datSou=totSkyCovSou,
    final p=totSkyCov)
    "Source selection for total sky cover"
  BaseClasses.SourceSelector winSpeSel(
    final datSou=winSpeSou,
    final p=winSpe)
    "Source selection for wind speed"
  BaseClasses.SourceSelector winDirSel(
    final datSou=winDirSou,
    final p=winDir)
    "Source selection for wind speed"
  BaseClasses.SourceSelector horInfRadSel(
    final datSou=HInfHorSou,
    final p=HInfHor)
    "Source selection for horizontal infrared radiation"
  BaseClasses.SourceSelectorRadiation souSelRad(
    final datSou=HSou)
    "Source selection for solar irradiation"

  BaseClasses.CheckDryBulbTemperature
    cheTemDryBul "Check dry bulb temperature "
  AixLib.BoundaryConditions.WeatherData.BaseClasses.CheckDewPointTemperature
    cheTemDewPoi "Check dew point temperature"
  Modelica.Blocks.Math.Gain conRelHum(final k=0.01)
    if relHumSou == AixLib.BoundaryConditions.Types.DataSource.File
    "Convert the relative humidity from percentage to [0, 1] "
  BaseClasses.CheckPressure chePre "Check the air pressure"
  AixLib.BoundaryConditions.WeatherData.BaseClasses.LimiterRelativeHumidity limRelHum
    "Limiter for relative humidity"
  AixLib.BoundaryConditions.WeatherData.BaseClasses.LimiterTotalSkyCover limTotSkyCov
    "Limits the total sky cover"
  AixLib.BoundaryConditions.WeatherData.BaseClasses.LimiterOpaqueSkyCover limOpaSkyCov
    "Limits the opaque sky cover"
  AixLib.BoundaryConditions.WeatherData.BaseClasses.LimiterCeilingHeight limCeiHei "Limits the ceiling height"
  AixLib.BoundaryConditions.WeatherData.BaseClasses.LimiterWindSpeed limWinSpe "Limits the wind speed"
  AixLib.BoundaryConditions.WeatherData.BaseClasses.LimiterHorizontalInfraredIrradiation limHorInfRad
    "Limits the horizontal infrared irradiation"
  AixLib.BoundaryConditions.WeatherData.BaseClasses.LimiterWindDirection limWinDir
    "Limits the wind direction"
  SkyTemperature.BlackBody TBlaSkyCom(final calTSky=calTSky)
    if TBlaSkySou == AixLib.BoundaryConditions.Types.DataSource.File
    "Computation of the black-body sky temperature"
  AixLib.Utilities.Time.ModelTime modTim "Model time"
  Modelica.Blocks.Math.Add add30Min
    "Add 30 minutes to time to shift weather data reader"
  Modelica.Blocks.Sources.Constant con30Min(final k=1800)
    "Constant used to shift weather data reader"
  AixLib.BoundaryConditions.WeatherData.BaseClasses.LocalCivilTime locTim(
      final lon=lon, final timZon=timZon) "Local civil time"
  Modelica.Blocks.Tables.CombiTable1Ds datRea30Min(
    final tableOnFile=true,
    final tableName="tab1",
    final fileName=filNam,
    verboseRead=false,
    final smoothness=Modelica.Blocks.Types.Smoothness.ContinuousDerivative,
    final columns=9:11) "Data reader with 30 min offset for solar irradiation"
  AixLib.BoundaryConditions.WeatherData.BaseClasses.ConvertTime conTimMin(final
      weaDatStaTim=timeSpan[1], final weaDatEndTim=timeSpan[2])
    "Convert simulation time to calendar time"
  AixLib.BoundaryConditions.WeatherData.BaseClasses.ConvertTime conTim(
    final weaDatStaTim = timeSpan[1],
    final weaDatEndTim = timeSpan[2])
    "Convert simulation time to calendar time"
  BaseClasses.EquationOfTime eqnTim "Equation of time"
  BaseClasses.SolarTime solTim "Solar time"

  Modelica.Blocks.Math.UnitConversions.From_deg conWinDir
    "Convert the wind direction unit from [deg] to [rad]"
  Modelica.Blocks.Math.UnitConversions.From_degC conTDryBul

  Modelica.Blocks.Math.UnitConversions.From_degC conTDewPoi
    "Convert the dew point temperature form [degC] to [K]"
  SolarGeometry.BaseClasses.AltitudeAngle altAng "Solar altitude angle"
   SolarGeometry.BaseClasses.ZenithAngle zenAng
                      "Zenith angle"
   SolarGeometry.BaseClasses.Declination decAng "Declination angle"
   SolarGeometry.BaseClasses.SolarHourAngle
    solHouAng "Solar hour angle"
  Latitude latitude(final latitude=lat) "Latitude"
  Longitude longitude(final longitude=lon) "Longitude"
  Altitude altitude(final Altitude=alt) "Altitude"
  //---------------------------------------------------------------------------
  // Optional instanciation of a block that computes the wet bulb temperature.
  // This block may be needed for evaporative cooling towers.
  // By default, it is enabled. This introduces a nonlinear equation, but
  // we have not observed an increase in computing time because of this equation.
  AixLib.Utilities.Psychrometrics.TWetBul_TDryBulPhi tWetBul_TDryBulXi(
      redeclare package Medium = AixLib.Media.Air,
      TDryBul(displayUnit="degC")) if computeWetBulbTemperature

  //---------------------------------------------------------------------------
  // Conversion blocks for sky cover
  Modelica.Blocks.Math.Gain conTotSkyCov(final k=0.1)
    if totSkyCovSou == AixLib.BoundaryConditions.Types.DataSource.File
    "Convert sky cover from [0...10] to [0...1]"
  Modelica.Blocks.Math.Gain conOpaSkyCov(final k=0.1)
    if opaSkyCovSou == AixLib.BoundaryConditions.Types.DataSource.File
    "Convert sky cover from [0...10] to [0...1]"
  AixLib.BoundaryConditions.WeatherData.BaseClasses.CheckBlackBodySkyTemperature cheTemBlaSky(TMin=0)
    "Check black body sky temperature"

  // Blocks that are added in order to set the name of the output signal,
  // which then is displayed in the GUI of the weather data connector.
  block Latitude "Generate constant signal of type Real"
    extends Modelica.Blocks.Icons.Block;

    parameter Modelica.Units.SI.Angle latitude "Latitude";

    Modelica.Blocks.Interfaces.RealOutput y(
      unit="rad",
      displayUnit="deg") "Latitude of the location"
  equation
    y = latitude;
  end Latitude;

  block Longitude "Generate constant signal of type Real"
    extends Modelica.Blocks.Icons.Block;

    parameter Modelica.Units.SI.Angle longitude "Longitude";

    Modelica.Blocks.Interfaces.RealOutput y(
      unit="rad",
      displayUnit="deg") "Longitude of the location"
  equation
    y = longitude;
  end Longitude;

  block Altitude "Generate constant signal of type Real"
    extends Modelica.Blocks.Icons.Block;

    parameter Modelica.Units.SI.Length Altitude
      "Location altitude above sea level";

    Modelica.Blocks.Interfaces.RealOutput y(
      unit="m") "Location altitude above sea level"
  equation
    y = Altitude;
  end Altitude;

equation

  connect(modTim.y, add30Min.u2)
  connect(con30Min.y, add30Min.u1)
  connect(add30Min.y, conTimMin.modTim)
  connect(conTimMin.calTim, datRea30Min.u)
  connect(modTim.y, locTim.cloTim)
  connect(modTim.y, conTim.modTim)
  connect(conTim.calTim, datRea.u)
  connect(modTim.y, eqnTim.nDay)
  connect(eqnTim.eqnTim, solTim.equTim)
  connect(locTim.locTim, solTim.locTim)
  connect(datRea.y[11], conWinDir.u)
  connect(datRea.y[1], conTDryBul.u)
  connect(datRea.y[2], conTDewPoi.u)
  connect(conRelHum.u, datRea.y[3])

  connect(decAng.decAng, zenAng.decAng)
  connect(solHouAng.solHouAng, zenAng.solHouAng)
  connect(solHouAng.solTim, solTim.solTim)
  connect(decAng.nDay, modTim.y)
  connect(zenAng.zen, altAng.zen)

  connect(limOpaSkyCov.nOpa, TBlaSkyCom.nOpa)
  connect(limRelHum.relHum, tWetBul_TDryBulXi.phi)

  connect(pAtmSel.y, chePre.PIn)
  connect(pAtmSel.uCon, pAtm_in)
  connect(datRea.y[4], pAtmSel.uFil)
  connect(cheTemDewPoi.TIn, TDewPoiSel.y)
  connect(TDewPoiSel.uFil, conTDewPoi.y)
  connect(TDewPoiSel.uCon, TDewPoi_in)
  connect(TDryBulSel.y, cheTemDryBul.TIn)
  connect(TDryBulSel.uFil, conTDryBul.y)
  connect(TDryBulSel.uCon, TDryBul_in)

  connect(TBlaSkySel.y, cheTemBlaSky.TIn)
  connect(TBlaSkyCom.TBlaSky, TBlaSkySel.uFil)
  connect(TBlaSky_in, TBlaSkySel.uCon)
  connect(relHumSel.y, limRelHum.u)
  connect(relHumSel.uFil, conRelHum.y)
  connect(relHum_in, relHumSel.uCon)
  connect(conOpaSkyCov.y, opaSkyCovSel.uFil)
  connect(opaSkyCov_in, opaSkyCovSel.uCon)
  connect(ceiHeiSel.y, limCeiHei.u)
  connect(ceiHeiSel.uFil, datRea.y[16])
  connect(ceiHeiSel.uCon, ceiHei_in)
  connect(totSkyCovSel.uFil, conTotSkyCov.y)
  connect(totSkyCovSel.uCon, totSkyCov_in)
  connect(totSkyCovSel.y, limTotSkyCov.u)
  connect(winSpeSel.y, limWinSpe.u)
  connect(conTotSkyCov.u, datRea.y[13])
  connect(winSpeSel.uFil, datRea.y[12])
  connect(winSpeSel.uCon, winSpe_in)
  connect(winDirSel.y, limWinDir.u)
  connect(conWinDir.y, winDirSel.uFil)
  connect(winDirSel.uCon, winDir_in)
  connect(conOpaSkyCov.u, datRea.y[14])
  connect(horInfRadSel.y, limHorInfRad.u)
  connect(horInfRadSel.uFil, datRea.y[26])
  connect(horInfRadSel.uCon, HInfHor_in)

  connect(souSelRad.HDifHorFil, datRea30Min.y[3])
  connect(souSelRad.HDifHorIn, HDifHor_in)
  connect(souSelRad.HDirNorFil, datRea30Min.y[2])
  connect(souSelRad.HDirNorIn, HDirNor_in)
  connect(souSelRad.HGloHorIn, HGloHor_in)
  connect(souSelRad.zen, zenAng.zen)
  connect(souSelRad.HGloHorFil, datRea30Min.y[1])

  connect(TBlaSkyCom.HHorIR, limHorInfRad.HHorIR)

  connect(opaSkyCovSel.y, limOpaSkyCov.u)
  connect(cheTemDryBul.TDryBul, TBlaSkyCom.TDryBul)
  connect(cheTemDryBul.TDryBul, tWetBul_TDryBulXi.TDryBul)

  connect(chePre.pAtm, tWetBul_TDryBulXi.p)

  connect(cheTemDewPoi.TDewPoi, TBlaSkyCom.TDewPoi)

  // Connections to weather data bus
  connect(cheTemDryBul.TDryBul, weaBus.TDryBul)

  connect(cheTemDewPoi.TDewPoi, weaBus.TDewPoi)
  connect(tWetBul_TDryBulXi.TWetBul, weaBus.TWetBul)

  connect(limRelHum.relHum, weaBus.relHum)

  connect(souSelRad.HDirNor, weaBus.HDirNor)
  connect(souSelRad.HDifHor, weaBus.HDifHor)

  connect(souSelRad.HGloHor, weaBus.HGloHor)

  connect(cheTemBlaSky.TBlaSky, weaBus.TBlaSky)
  connect(limHorInfRad.HHorIR, weaBus.HHorIR)

  connect(limWinSpe.winSpe, weaBus.winSpe)

  connect(limWinDir.winDir, weaBus.winDir)

  connect(limCeiHei.ceiHei, weaBus.ceiHei)

  connect(limTotSkyCov.nTot, weaBus.nTot)
  connect(limOpaSkyCov.nOpa, weaBus.nOpa)

  connect(modTim.y, weaBus.cloTim)

  connect(solTim.solTim, weaBus.solTim)

  connect(altAng.alt, weaBus.solAlt)
  connect(zenAng.zen, weaBus.solZen)
  connect(decAng.decAng, weaBus.solDec)
  connect(solHouAng.solHouAng, weaBus.solHouAng)
  connect(longitude.y, weaBus.lon)
  connect(latitude.y, weaBus.lat)
  connect(altitude.y, weaBus.alt)
  connect(chePre.pAtm, weaBus.pAtm)

  connect(latitude.y, zenAng.lat)</code>.
</li>
<li>
May 30, 2014, by Michael Wetter:<br/>
Removed undesirable annotation <code>Evaluate=true</code>.
</li>
<li>
May 5, 2013, by Thierry S. Nouidui:<br/>
Added the option to use a constant, an input signal or the weather file as the source
for the ceiling height, the total sky cover, the opaque sky cover, the dew point temperature,
and the infrared horizontal radiation <code>HInfHor</code>.
</li>
<li>
October 8, 2013, by Michael Wetter:<br/>
Improved the algorithm that determines the absolute path of the file.
Now weather files are searched in the path specified, and if not found, the urls
<code>file://</code>, <code>modelica://</code> and <code>modelica://AixLib</code>
are added in this order to search for the weather file.
This allows using the data reader without having to specify an absolute path,
as long as the <code>AixLib</code> library
is on the <code>MODELICAPATH</code>.
This change was implemented in
<a href=\"modelica://AixLib.BoundaryConditions.WeatherData.BaseClasses.getAbsolutePath\">
AixLib.BoundaryConditions.WeatherData.BaseClasses.getAbsolutePath</a>
and improves this weather data reader.
</li>
<li>
May 2, 2013, by Michael Wetter:<br/>
Added function call to <code>getAbsolutePath</code>.
</li>
<li>
October 16, 2012, by Michael Wetter:<br/>
Added computation of the wet bulb temperature.
Computing the wet bulb temperature introduces a nonlinear
equation. As we have not observed an increase in computing time
because of computing the wet bulb temperature, it is computed
by default. By setting the parameter
<code>computeWetBulbTemperature=false</code>, the computation of the
wet bulb temperature can be removed.
Revised documentation.
</li>
<li>
August 11, 2012, by Wangda Zuo:<br/>
Renamed <code>radHor</code> to <code>radHorIR</code> and
improved the optional inputs for radiation data.
</li>
<li>
July 24, 2012, by Wangda Zuo:<br/>
Corrected the notes of SI unit requirements for input files.
</li>
<li>
July 13, 2012, by Michael Wetter:<br/>
Removed assignment of <code>HGloHor_in</code> in its declaration,
because this gives an overdetermined system if the input connector
is used.
Removed non-required assignments of attribute <code>displayUnit</code>.
</li>
<li>
February 25, 2012, by Michael Wetter:<br/>
Added subbus for solar position, which is needed by irradition and
shading model.
</li>
<li>
November 29, 2011, by Michael Wetter:<br/>
Fixed wrong display unit for <code>pAtm_in_internal</code> and
made propagation of parameter final.
</li>
<li>
October 27, 2011, by Wangda Zuo:<br/>
<ol>
<li>
Added optional connectors for dry bulb temperature, relative humidity, wind speed, wind direction, global horizontal radiation, diffuse horizontal radiation.<br/>
</li>
<li>
Separate the unit conversion for TMY3 data and data validity check.
</li>
</ol>
</li>
<li>
October 3, 2011, by Michael Wetter:<br/>
Propagated value for sky temperature calculation to make it accessible as a parameter.
</li>
<li>
July 20, 2011, by Michael Wetter:<br/>
Added the option to use a constant, an input signal or the weather file as the source
for the atmospheric pressure.
</li><li>
March 15, 2011, by Wangda Zuo:<br/>
Delete the wet bulb temperature since it may cause numerical problem.
</li>
<li>
March 7, 2011, by Wangda Zuo:<br/>
Added wet bulb temperature. Changed reader to read only needed columns.
Added explanation for 30 minutes shift for radiation data.
</li>
<li>
March 5, 2011, by Michael Wetter:<br/>
Changed implementation to obtain longitude and time zone directly
from weather file.
</li>
<li>
June 25, 2010, by Wangda Zuo:<br/>
First implementation.
</li>
</ul>
</html>"),
    Diagram(coordinateSystem(preserveAspectRatio=false,
     extent={{-200,-300},{300,300}})),
   __Dymola_LockedEditing="Model from IBPSA");
end ReaderTMY3;


Check the validity of the black-body sky temperature data. This component checks the value of the black-body sky temperature.
If the temperature is outside TMin and TMax,
the simulation will stop with an error.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckBlackBodySkyTemperature
  "Check the validity of the black-body sky temperature data"
  extends Modelica.Blocks.Icons.Block;

  parameter Modelica.Units.SI.Temperature TMin(displayUnit="degC") = 203.15
    "Minimum allowed temperature";
  parameter Modelica.Units.SI.Temperature TMax(displayUnit="degC") = 343.15
    "Maximum allowed temperature";

  Modelica.Blocks.Interfaces.RealInput TIn(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Black-body sky temperature"

  Modelica.Blocks.Interfaces.RealOutput TBlaSky(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Black-body sky temperature"

equation
  TBlaSky = TIn;
  assert(noEvent(TIn > TMin and TIn < TMax),
    "In " + getInstanceName() + ": Weather data black-body sky temperature out of bounds.\n" + "   TIn = " +
     String(TIn));
end CheckBlackBodySkyTemperature;


Ensures that the ceiling height is above a lower bound. This component ensures that the ceiling height is at least <i>0</i>
  meters.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckCeilingHeight
  "Ensures that the ceiling height is above a lower bound"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput ceiHeiIn(
    final quantity="Height",
    final unit="m") "Input ceiling height"
  Modelica.Blocks.Interfaces.RealOutput ceiHeiOut(
    final quantity="Height",
    final unit="m") "Ceiling height"
  constant Modelica.Units.SI.Height ceiHeiMin=0
    "Minimum allowed ceiling height";
equation
  ceiHeiOut = AixLib.Utilities.Math.Functions.smoothMax(
    ceiHeiIn,
    ceiHeiMin,
    0.1);
end CheckCeilingHeight;


Check the validity of the dew point temperature data. This component checks the value of temperature.
If the temperature is outside TMin and TMax,
the simulation will stop with an error.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckDewPointTemperature
  "Check the validity of the dew point temperature data"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput TIn(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Input Temperature"
  Modelica.Blocks.Interfaces.RealOutput TDewPoi(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Dew point temperature"

  parameter Modelica.Units.SI.Temperature TMin(displayUnit="degC") = 203.15
    "Minimum allowed temperature";
  parameter Modelica.Units.SI.Temperature TMax(displayUnit="degC") = 343.15
    "Maximum allowed temperature";

equation
  TDewPoi = TIn;
  assert(noEvent(TIn > TMin and TIn < TMax), "In " + getInstanceName() +
     ": Weather data dew point temperature out of bounds.\n" + "   TIn = " + String(
    TIn));
end CheckDewPointTemperature;


Check the validity of the dry bulb temperature data. This component checks the value of the dry bulb temperature.
If the temperature is outside TMin and TMax,
the simulation will stop with an error.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckDryBulbTemperature
  "Check the validity of the dry bulb temperature data"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput TIn(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Input Temperature"
  Modelica.Blocks.Interfaces.RealOutput TDryBul(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Dry bulb temperature"

  parameter Modelica.Units.SI.Temperature TMin(displayUnit="degC") = 203.15
    "Minimum allowed temperature";
  parameter Modelica.Units.SI.Temperature TMax(displayUnit="degC") = 343.15
    "Maximum allowed temperature";

equation
  TDryBul = TIn;
  assert(noEvent(TIn > TMin and TIn < TMax), "In " + getInstanceName() +
     ": Weather data dry bulb temperature out of bounds.\n" + "   TIn = " + String(
    TIn));
end CheckDryBulbTemperature;


Ensure that the radiation is not smaller than 0. This block ensures that the radiation is not smaller than <i>0</i>.
  The Modelica data reader will interpolate data when it reads the data
  from a file. Thus, it is possible to generate negative values due to
  the interpolation.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckIRRadiation "Ensure that the radiation is not smaller than 0"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput HIn(
    final quantity="RadiantEnergyFluenceRate",
    final unit="W/m2") "Input horizontal infrared irradiation"
  Modelica.Blocks.Interfaces.RealOutput HOut(
    final quantity="RadiantEnergyFluenceRate",
    final unit="W/m2") "Horizontal infrared irradiation"

  constant Modelica.Units.SI.RadiantEnergyFluenceRate HMin=0.0001
    "Minimum value for radiation";
equation
  HOut = AixLib.Utilities.Math.Functions.smoothMax(
    x1=HIn,
    x2=HMin,
    deltaX=HMin/10);
end CheckIRRadiation;


Ensures that the interpolated pressure is between prescribed bounds. This component ensures that the interpolated pressure is between 31,000 Pa and 120,000 Pa.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckPressure
  "Ensures that the interpolated pressure is between prescribed bounds"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput PIn(
    final quantity="Pressure",
    final unit="Pa") "Atmospheric pressure"
  Modelica.Blocks.Interfaces.RealOutput pAtm(
    final quantity="Pressure",
    final unit="Pa") "Atmospheric pressure"
  constant Modelica.Units.SI.Pressure PMin=3100 "Minimum allowed pressure";
  constant Modelica.Units.SI.Pressure PMax=120000 "Maximum allowed pressure";
equation
  pAtm = PIn;
  assert(noEvent(PIn > PMin and PIn < PMax), "In " + getInstanceName() +
    ": Weather data atmospheric pressure out of bounds.\n" + "   PIn = " + String(PIn));
end CheckPressure;


within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckRadiation "Ensure that the radiation is not smaller than 0"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput HIn(
    final quantity="RadiantEnergyFluenceRate",
    final unit="W/m2") "Input radiation"
  Modelica.Blocks.Interfaces.RealOutput HOut(
    final quantity="RadiantEnergyFluenceRate",
    final unit="W/m2") "Radiation"

  constant Modelica.Units.SI.RadiantEnergyFluenceRate HMin=0.0001
    "Minimum value for radiation";
equation
  HOut = AixLib.Utilities.Math.Functions.smoothMax(
    x1=HIn,
    x2=HMin,
    deltaX=HMin/10);
end CheckRadiation;


Check the validity of relative humidity. This component constrains the value of relative humidity to a range
  of <i>[0, 1]</i>.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckRelativeHumidity "Check the validity of relative humidity"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput relHumIn(final unit="1")
    "Input relative humidity"
  Modelica.Blocks.Interfaces.RealOutput relHumOut(final unit="1")
    "Relative humidity"
  constant Real delta=0.01 "Smoothing parameter";
protected
  constant Real relHumMin=delta "Lower bound";
  constant Real relHumMax=1 - delta "Upper bound";

equation
  relHumOut = AixLib.Utilities.Math.Functions.smoothLimit(
    relHumIn,
    relHumMin,
    relHumMax,
    delta/10);
end CheckRelativeHumidity;


Constrains the sky cover to [0, 1]. This component constrains the interpolated sky cover between 0
  and 1.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckSkyCover "Constrains the sky cover to [0, 1]"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput nIn(min=0, max=1)
    "Input sky cover [0, 10]"
  Modelica.Blocks.Interfaces.RealOutput nOut(min=0, max=1, unit="1")
    "Sky cover [0, 1]"

  constant Real delta=0.01 "Smoothing parameter";
protected
  constant Real nMin=delta "Lower bound";
  constant Real nMax=10 - delta "Upper bound";
equation
  nOut = AixLib.Utilities.Math.Functions.smoothLimit(
    nIn,
    nMin,
    nMax,
    delta/10);
end CheckSkyCover;


Check the validity of temperature data. This component checks the value of temperature. If the temperature is
  outside TMin and TMax, the simulation will
  stop with an error.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckTemperature "Check the validity of temperature data"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput TIn(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Input Temperature"
  Modelica.Blocks.Interfaces.RealOutput TOut(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Output temperature"

  parameter Modelica.Units.SI.Temperature TMin(displayUnit="degC") = 203.15
    "Minimum allowed temperature";
  parameter Modelica.Units.SI.Temperature TMax(displayUnit="degC") = 343.15
    "Maximum allowed temperature";

equation
  TOut = TIn;
  assert(TOut > TMin, "Temperature out of bounds.\n" + "   TOut = " + String(
    TOut));
  assert(TOut < TMax, "Temperature out of bounds.\n" + "   TOut = " + String(
    TOut));
end CheckTemperature;


Constrains the wind direction to [0, 2*pi] degree. This component constrains the interpolated wind direction between
  0 and 360 degree.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckWindDirection "Constrains the wind direction to [0, 2*pi] degree"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput nIn(
    final quantity="Angle",
    final unit="rad",
    displayUnit="deg") "Input wind direction"
  Modelica.Blocks.Interfaces.RealOutput nOut(
    final quantity="Angle",
    final unit="rad",
    displayUnit="deg") "Wind direction"

  constant Real delta=0.01 "Smoothing parameter";
protected
  constant Real nMin=0 "Lower bound";
  constant Real nMax=2*Modelica.Constants.pi "Upper bound";
equation
  nOut = AixLib.Utilities.Math.Functions.smoothLimit(
    nIn,
    nMin,
    nMax,
    delta/10);
end CheckWindDirection;


Ensures that the wind speed is non-negative. This component ensures that the wind speed is non-negative.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block CheckWindSpeed "Ensures that the wind speed is non-negative"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput winSpeIn(final quantity="Velocity",
      final unit="m/s") "Input wind speed"
  Modelica.Blocks.Interfaces.RealOutput winSpeOut(final quantity="Velocity",
      final unit="m/s") "Wind speed"
  constant Modelica.Units.SI.Velocity winSpeMin=1e-6
    "Minimum allowed wind speed";

equation
  // Modelica Table will interpolate data when it reads the weather data file.
  // It can generate negative values due to the interpolation.
  winSpeOut = AixLib.Utilities.Math.Functions.smoothMax(
    x1=winSpeIn,
    x2=winSpeMin,
    deltaX=winSpeMin/10);
end CheckWindSpeed;


Convert the unit of solar radiation received from the TMY3 data file. The TMY3 data for solar radiation is the radiation accumulated in one
  hour. Thus, it used a unit of Wh/m2. This component
  converts Wh/m2 to W/m2 that is the standard
  unit in Modelica.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block ConvertRadiation
  "Convert the unit of solar radiation received from the TMY3 data file"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput HIn(final unit="W.h/m2")
    "Input radiation"
  Modelica.Blocks.Interfaces.RealOutput HOut(
    final quantity="RadiantEnergyFluenceRate",
    final unit="W/m2") "Radiation"

protected
  constant Modelica.Units.SI.Time Hou=3600 "1 hour";

equation
  HOut =HIn/Modelica.Units.Conversions.to_hour(Hou);
end ConvertRadiation;


Convert the relative humidity from percentage to real. This component converts the relative humidity from percentage to
  real. Input is the relative humidity in percentage, as this is the
  data format that is used in the Typical Meteorological Year weather
  data.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block ConvertRelativeHumidity
  "Convert the relative humidity from percentage to real"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput relHumIn(unit="1")
    "Value of relative humidity in percentage"
  Modelica.Blocks.Interfaces.RealOutput relHumOut(unit="1")
    "Relative humidity between 0 and 1"
equation
  relHumOut = relHumIn/100;
end ConvertRelativeHumidity;


Converts the simulation time to calendar time in scale of 1 year (365 days), or a multiple of a year. This component converts the simulation time to calendar time in a scale of 1 year (365 days),
or a multiple of it, if this is the length of the weather file.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block ConvertTime
  "Converts the simulation time to calendar time in scale of 1 year (365 days), or a multiple of a year"
  extends PartialConvertTime;
  Modelica.Blocks.Interfaces.RealInput modTim(
    final quantity="Time",
    final unit="s") "Simulation time"
  Modelica.Blocks.Interfaces.RealOutput calTim(
    final quantity="Time",
    final unit="s") "Calendar time"

protected
  constant Modelica.Units.SI.Time shiftSolarRad=1800
    "Number of seconds for the shift for solar radiation calculation";

equation
  calTim = calTimAux;
  modTimAux = modTim;
  assert(canRepeatWeatherFile or noEvent((time - weaDatEndTim) < shiftSolarRad),
    "In " + getInstanceName() + ": Insufficient weather data provided for the desired simulation period.
    The simulation time " + String(time) +
    " exceeds the end time " + String(weaDatEndTim) + " of the weather data file.",
    AssertionLevel.error);

  assert(canRepeatWeatherFile or noEvent(time >= weaDatStaTim),
    "In " + getInstanceName() + ": Insufficient weather data provided for the desired simulation period.
    The simulation time " + String(time) +
    " is less than the start time " + String(weaDatStaTim) + " of the weather data file.",
    AssertionLevel.error);
end ConvertTime;


Equation of time. This component computes the difference between solar noon and noon of local civil time.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block EquationOfTime "Equation of time"
  extends PartialConvertTime;
  Modelica.Blocks.Interfaces.RealInput nDay(
    quantity="Time",
    unit="s")
    "Zero-based day number in seconds (January 1=0, January 2=86400)"
  Modelica.Blocks.Interfaces.RealOutput eqnTim(
    final quantity="Time",
    final unit="s",
    displayUnit="min") "Equation of time"
protected
  Real Bt "Intermediate variable";
equation
  modTimAux = nDay;
  Bt = Modelica.Constants.pi*((calTimAux + 86400)/86400 - 81)/182
    "Our unit is s instead of day in (A.4.2b)";
  eqnTim = 60*(9.87*Modelica.Math.sin(2*Bt) - 7.53*Modelica.Math.cos(Bt) - 1.5*
    Modelica.Math.sin(Bt)) "Our unit is s instead of min in (A.4.2a)";
end EquationOfTime;


Block that limits the relative humidity. Block that limits the cloud cover ceiling height to be positive.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block LimiterCeilingHeight "Block that limits the relative humidity"
  extends PartialLimiterMin;

  Modelica.Blocks.Interfaces.RealOutput ceiHei(
    final unit="m") = max(0, u) "Cloud cover ceiling height"
end LimiterCeilingHeight;


Block that limits the horizontal infrared irradiation. Block that limits the horizontal infrared irradiation to be positive.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block LimiterHorizontalInfraredIrradiation
  "Block that limits the horizontal infrared irradiation"
  extends PartialLimiterMin;

  Modelica.Blocks.Interfaces.RealOutput HHorIR(
    final unit="W/m2") = max(0, u) "Horizontal infrared irradiation"
end LimiterHorizontalInfraredIrradiation;


Block that limits the opaque sky cover. Block that limits the opaque sky cover.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block LimiterOpaqueSkyCover "Block that limits the opaque sky cover"
  extends PartialLimiter;

  Modelica.Blocks.Interfaces.RealOutput nOpa(
    final unit="1") "Opaque sky cover"

equation
  nOpa = min(uMax, max(uMin, u));
end LimiterOpaqueSkyCover;


Block that limits the relative humidity. Block that limits the relative humidity.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block LimiterRelativeHumidity "Block that limits the relative humidity"
  extends PartialLimiter;

  Modelica.Blocks.Interfaces.RealOutput relHum(
    final unit="1") "Relative humidity"

equation
  relHum = min(uMax, max(uMin, u));
end LimiterRelativeHumidity;


Block that limits the total sky cover. Block that limits the total sky cover.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block LimiterTotalSkyCover "Block that limits the total sky cover"
  extends PartialLimiter;

  Modelica.Blocks.Interfaces.RealOutput nTot(
    final unit="1") "Total sky cover"

equation
  nTot = min(uMax, max(uMin, u));
end LimiterTotalSkyCover;


Block that limits the wind direction. Block that limits the wind direction.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block LimiterWindDirection "Block that limits the wind direction"
  extends PartialLimiter(
    final uMax=2*Modelica.Constants.pi);

  Modelica.Blocks.Interfaces.RealOutput winDir(
    final unit="rad") "Wind direction"

equation
  winDir = min(uMax, max(uMin, u));
end LimiterWindDirection;


Block that limits the wind speed. Block that limits the wind speed to be positive.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block LimiterWindSpeed "Block that limits the wind speed"
  extends PartialLimiterMin;

  Modelica.Blocks.Interfaces.RealOutput winSpe(
    final unit="m/s") = max(0, u) "Wind speed"
end LimiterWindSpeed;


Converts the clock time to local civil time.. This component converts the clock time to local civil time.
The parameter timZon represents the time zone of the facility  (relative to Greenwich Mean Time or the 0th meridian). Time zones west of GMT (e.g. North America) are represented as negative;
east of GMT as positive. Fraction of hours are represented in decimals (e.g. for 6:30, use 6.5).

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block LocalCivilTime "Converts the clock time to local civil time."
  extends PartialConvertTime;
  Modelica.Blocks.Interfaces.RealInput cloTim(
    final quantity="Time",
    final unit="s") "Clock time"
  parameter Modelica.Units.SI.Time timZon(displayUnit="h") "Time zone";
  parameter Modelica.Units.SI.Angle lon(displayUnit="deg") "Longitude";
  Modelica.Blocks.Interfaces.RealOutput locTim(
    final quantity="Time",
    final unit="s") "Local civil time"
protected
  final parameter Modelica.Units.SI.Time diff=-timZon + lon*43200/Modelica.Constants.pi
    "Difference between local and clock time";
equation
  modTimAux = cloTim;
  locTim = calTimAux + diff;
end LocalCivilTime;


within AixLib.BoundaryConditions.WeatherData;
package BaseClasses "Package with base classes for AixLib.BoundaryConditions.WeatherData"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within AixLib.BoundaryConditions.WeatherData.BaseClasses;
partial block PartialConvertTime
  "Converts the simulation time to calendar time in scale of 1 year (365 days), or a multiple of a year"
  extends Modelica.Blocks.Icons.Block;
  parameter Modelica.Units.SI.Time weaDatStaTim(displayUnit="d") = 0
    "Start time of weather data";
  parameter Modelica.Units.SI.Time weaDatEndTim(displayUnit="d") = 31536000
    "End time of weather data";
  Modelica.Units.SI.Time modTimAux "Model time";
  Modelica.Units.SI.Time calTimAux "Calendar time";

protected
  parameter Modelica.Units.SI.Time lenWea=weaDatEndTim - weaDatStaTim
    "Length of weather data";

  parameter Boolean canRepeatWeatherFile = abs(mod(lenWea, 365*24*3600)) < 1E-2
    "=true, if the weather file can be repeated, since it has the length of a year or a multiple of it";

  discrete Modelica.Units.SI.Time tNext(start=0, fixed=true)
    "Start time of next period";

equation
  when {initial(), canRepeatWeatherFile and modTimAux > pre(tNext)} then
    // simulation time stamp went over the end time of the weather file
    //(last time stamp of the weather file + average increment)
    tNext = if canRepeatWeatherFile then integer(modTimAux/lenWea)*lenWea + lenWea else time;
  end when;
  calTimAux = if canRepeatWeatherFile then modTimAux - tNext + lenWea else modTimAux;
end PartialConvertTime;


Partial block to limit a signal. Block that computes y_internal=min(uMax, max(uMin, u)),
where y_internal is a protected connector.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
partial block PartialLimiter
  "Partial block to limit a signal"
  extends Modelica.Blocks.Icons.Block;

  constant Real uMin = 0 "Minimum value";
  constant Real uMax = 1 "Maximum value";

  Modelica.Blocks.Interfaces.RealInput u "Connector of Real input signal"
end PartialLimiter;


Partial block to limit a signal. Partial block that is used to limit a signal by a minimum value.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
partial block PartialLimiterMin
  "Partial block to limit a signal"
  extends Modelica.Blocks.Icons.Block;

  Modelica.Blocks.Interfaces.RealInput u "Connector of Real input signal"
end PartialLimiterMin;


Solar time. This component computes the local solar time.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block SolarTime "Solar time"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Interfaces.RealInput locTim(quantity="Time", unit="s")
    "Local time"
  Modelica.Blocks.Interfaces.RealInput equTim(quantity="Time", unit="s")
    "Equation of time"
  Modelica.Blocks.Interfaces.RealOutput solTim(
    final quantity="Time",
    final unit="s",
    displayUnit="s") "Solar time"
equation
  solTim = locTim + equTim "Our unit is s in stead of h in (A.4.3)";
end SolarTime;


Block that selects as its output either a parameter value or its input. Block that produces at its output the input value uCon, uFil
or the parameter value p depending on the parameter value
datSou.

within AixLib.BoundaryConditions.WeatherData.BaseClasses;
block SourceSelector
  "Block that selects as its output either a parameter value or its input"
  extends Modelica.Blocks.Interfaces.SO;
  parameter AixLib.BoundaryConditions.Types.DataSource datSou "Data source"
  parameter Real p "Parameter value";
  Modelica.Blocks.Interfaces.RealInput uFil
   if datSou == AixLib.BoundaryConditions.Types.DataSource.File
    "Input signal from file reader"
  Modelica.Blocks.Interfaces.RealInput uCon
  if datSou == AixLib.BoundaryConditions.Types.DataSource.Input
    "Input signal from input connector"
equation
  if datSou == AixLib.BoundaryConditions.Types.DataSource.Parameter then
    y = p;
  end if;
  connect(uCon, y);
  connect(uFil, y);
end SourceSelector;