Testmodel for VentilationHeat. This example shows the application of VentilationHeat. For solar
  radiation, the example relies on the standard weather file in AixLib.

within AixLib.ThermalZones.ReducedOrder.Windows.Examples;
model VentilationHeat "Testmodel for VentilationHeat"
  extends Modelica.Icons.Example;

  AixLib.ThermalZones.ReducedOrder.Windows.BaseClasses.VentilationHeat ventilationHeat(
    d=0.1,
    screen=true,
    x_f=0.8,
    tau_e=0.1,
    rho_e=0.7125,
    til=1.5707963267949)
    "Heat input due to ventilation with closed sunblind"
  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 for Chicago"
  AixLib.BoundaryConditions.SolarIrradiation.DiffusePerez HDifTil(azi=0, til=
        1.5707963267949) "Diffuse irradiation on the window"
  AixLib.BoundaryConditions.SolarIrradiation.DirectTiltedSurface HDirTil(azi=0,
      til=1.5707963267949) "Direct solar irradiation on the window"
  AixLib.ThermalZones.ReducedOrder.Windows.BaseClasses.Sunblind sunblind(lim=200) "Sunblind of the window"
  AixLib.BoundaryConditions.SolarGeometry.BaseClasses.AltitudeAngle altAng
    "Solar altitude angle"
  AixLib.BoundaryConditions.SolarGeometry.ZenithAngle zen "Solar zenith angle"
  AixLib.BoundaryConditions.WeatherData.Bus weaBus "Weather bus"
  AixLib.ThermalZones.ReducedOrder.Windows.Window window(
    n=1,
    UWin=1.4,
    g={0.64},
    g_TotDir={0.08},
    g_TotDif={0.27},
    tau_vis={0.72},
    tau_visTotDir={0.08},
    tau_visTotDif={0.32},
    lim=200,
    azi={0},
    lat=0.86393797973719,
    til={1.5707963267949}) "Window facing south"
  Modelica.Blocks.Math.Add add
    "Total solar energy entering the room through the window"
equation
  connect(altAng.zen, zen.y)
  connect(altAng.alt, ventilationHeat.alt)
  connect(HDifTil.H, ventilationHeat.HDifTil)
  connect(weaDat.weaBus, HDifTil.weaBus)
  connect(HDirTil.H, ventilationHeat.HDirTil)
  connect(HDifTil.H, sunblind.HDifTil)
  connect(HDirTil.H, sunblind.HDirTil)
  connect(sunblind.sunscreen, ventilationHeat.sunscreen)
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.HDifHor, ventilationHeat.HDifHor)
  connect(weaBus.HDirNor, ventilationHeat.HDirNor)
  connect(weaDat.weaBus, HDirTil.weaBus)
  connect(weaDat.weaBus, zen.weaBus)
  connect(weaDat.weaBus, window.weaBus)
  connect(ventilationHeat.HVen, add.u1)
  connect(window.HWin[1], add.u2)
end VentilationHeat;


Testmodel for Window. This example shows the application of Window. For
  solar radiation, the example relies on the standard weather file in
  AixLib.

within AixLib.ThermalZones.ReducedOrder.Windows.Examples;
model Window "Testmodel for Window"
    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"))
    "Weather data for Chicago"
  AixLib.ThermalZones.ReducedOrder.Windows.Window window(
    n=2,
    UWin=1.4,
    g={0.64,0.64},
    g_TotDir={0.08,0.08},
    g_TotDif={0.27,0.27},
    tau_vis={0.72,0.72},
    tau_visTotDir={0.08,0.08},
    tau_visTotDif={0.32,0.32},
    lim=200,
    lat=0.86393797973719,
    til={1.5707963267949,1.5707963267949},
    azi={0,1.5707963267949})
    "Two windows: One facing south, one facing west"
equation
  connect(weaDat.weaBus, window.weaBus)
end Window;


Package with type definitions

within AixLib;
package Types "Package with type definitions"
  extends Modelica.Icons.TypesPackage;

  type Reset = enumeration(
    Disabled   "Disabled",
    Parameter   "Use parameter value",
    Input   "Use input signal")
    "Options for integrator reset"
end Types;


within AixLib.Types;
package Azimuth "List of possible constant values for surface azimuth"
   extends Modelica.Icons.TypesPackage;

constant Modelica.Units.SI.Angle S=0
  "Azimuth for an exterior wall whose outer surface faces south";
constant Modelica.Units.SI.Angle SW=+Modelica.Constants.pi/4
  "Azimuth for an exterior wall whose outer surface faces south-west";
constant Modelica.Units.SI.Angle W=+Modelica.Constants.pi/2
  "Azimuth for an exterior wall whose outer surface faces west";
constant Modelica.Units.SI.Angle NW=+Modelica.Constants.pi*3/4
  "Azimuth for an exterior wall whose outer surface faces north-west";
constant Modelica.Units.SI.Angle N=Modelica.Constants.pi
  "Azimuth for an exterior wall whose outer surface faces north";
constant Modelica.Units.SI.Angle NE=-Modelica.Constants.pi*3/4
  "Azimuth for an exterior wall whose outer surface faces north-east";
constant Modelica.Units.SI.Angle E=-Modelica.Constants.pi/2
  "Azimuth for an exterior wall whose outer surface faces east";
constant Modelica.Units.SI.Angle SE=-Modelica.Constants.pi/4
  "Azimuth for an exterior wall whose outer surface faces south-east";
end Azimuth;


within AixLib.Types;
package Tilt "List of possible constant values for surface tilt"
  extends Modelica.Icons.TypesPackage;

constant Modelica.Units.SI.Angle Ceiling=0 "Tilt for ceiling";
constant Modelica.Units.SI.Angle Floor=Modelica.Constants.pi "Tilt for floor";
constant Modelica.Units.SI.Angle Wall=Modelica.Constants.pi/2 "Tilt for wall";
end Tilt;


within AixLib;
package Utilities "Package with utility functions such as for I/O"
  extends Modelica.Icons.Package;
end Utilities;


Asserts Real input value while passing it through to Real output. Asserts Real input value while passing it through to Real output.

within AixLib.Utilities.Assertions;
model RealPassThroughWithAssertion
  "Asserts Real input value while passing it through to Real output"

  extends Modelica.Blocks.Routing.RealPassThrough;

  parameter Real minBound "Minimal value for the assertion boundary";
  parameter Real maxBound "Maximal value for the assertion boundary";
  parameter Modelica.Units.SI.Time startTime=-Modelica.Constants.inf
    "Time after which assert statement is applied";
  parameter AssertionLevel assertLevel=AssertionLevel.error "Level of assertion (built-in enumerator)";

initial equation
  assert(maxBound >= minBound, "Assertion block: Limits must be consistent. However, uMax (=" + String(maxBound) +
                     ") < uMin (=" + String(minBound) + ")");

equation
  if time > startTime then
    assert(u>=minBound and u<=maxBound,
      "In component " + getInstanceName() + " the variable value is not between bounds (min: " + String(minBound) + ", max: " + String(maxBound) + ")",
        assertLevel);
  end if;
end RealPassThroughWithAssertion;


Package with clustering functions

within AixLib.Utilities;
package Clustering "Package with clustering functions"
  extends Modelica.Icons.VariantsPackage;
end Clustering;


Model that verifies the k-means clustering function for 1d data. This example tests the k-means clustering algorithm on 1d data.

within AixLib.Utilities.Clustering.Validation;
model KMeans_1d "Model that verifies the k-means clustering function for 1d data"
  extends Modelica.Icons.Example;

  parameter Integer n_clusters = 3 "Number of clusters to be generated";
  parameter Real data[:,:] = [1;2;2;3;4] "Test data to be clustered";

  parameter Integer nDat = size(data,1) "Number of samples";
  parameter Integer nDim = size(data,2) "Number of features";
  parameter Real[n_clusters,nDim] centroids(each fixed=false)
    "Centroids of the clusters";
  parameter Integer[nDat] labels(each fixed=false)
    "Cluster label associated with each data point";
  parameter Integer[n_clusters] cluster_size(each fixed=false)
    "Size of the clusters";

  parameter Integer labelsExp[nDat]=
    {2,2,2,1,3}
    "Expected cluster labels";

  // Comparison result
  Boolean cmp "Comparison result";

initial equation
  (centroids, labels, cluster_size) = AixLib.Utilities.Clustering.KMeans(
    data, n_clusters, nDat, nDim);

equation
  cmp = Modelica.Math.Vectors.isEqual(labels, labelsExp);
end KMeans_1d;


Model that verifies the k-means clustering function for 2d data. This example tests the k-means clustering algorithm on 2d data.

within AixLib.Utilities.Clustering.Validation;
model KMeans_2d "Model that verifies the k-means clustering function for 2d data"
  extends Modelica.Icons.Example;

  parameter Integer n_clusters = 3 "Number of clusters to be generated";
  parameter Real data[:,:]=
    [ 1, 1;
      1, 2;
      2, 1;
      2, 1.2;
      3, 0;
      4, 0]
     "Test data to be clustered";

  parameter Integer nDat = size(data,1) "Number of samples";
  parameter Integer nDim = size(data,2) "Number of features";
  parameter Real[n_clusters,nDim] centroids(each fixed=false)
    "Centroids of the clusters";
  parameter Integer[nDat] labels(each fixed=false)
    "Cluster label associated with each data point";
  parameter Integer[n_clusters] cluster_size(each fixed=false)
    "Size of the clusters";

  parameter Integer labelsExp[nDat]=
    {2,2,1,2,1,3}
    "Expected cluster labels";

  // Comparison result
  Boolean cmp "Comparison result";

initial equation
  (centroids, labels, cluster_size) = AixLib.Utilities.Clustering.KMeans(
    data, n_clusters, nDat, nDim);

equation
  cmp = Modelica.Math.Vectors.isEqual(labels, labelsExp);
end KMeans_2d;


within AixLib.Utilities.Clustering;
package Validation "Validation models for clustering functions."
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Models for Co-Simulation communication

within AixLib.Utilities;
package Communication "Models for Co-Simulation communication "
end Communication;


within AixLib.Utilities.Communication;
package SocketCommunication "Package for socket communication in Modelica"
extends Modelica.Icons.Package;
end SocketCommunication;


Example model to show TCP communication with simple server.

within AixLib.Utilities.Communication.SocketCommunication.Components;
model TCPCommunicatorExample
  "Example model to show TCP communication with simple server"
  extends BaseClasses.PartialTCPCommunicator(
          final nin = nSend,
          final nout = nRecv,
          final samplePeriod = samplePeriodExample,
          final startTime=startTimeExample,
          final IP_Address=IP_AddressExample,
          final port=portExample); //Extends basic TCP communication model

  /**************** necessary Input ****************************/
  parameter Modelica.Units.SI.Time samplePeriodExample=1
    "Sample period how often a telegram is send";
  parameter Modelica.Units.SI.Time startTimeExample=0
    "Start time when sampling starts";
  parameter String IP_AddressExample = "127.0.0.1"
    "IP address or name of Server";
  parameter Integer portExample=27015 "Port on server";
  parameter Integer nSend = 1 "Number of data points to be written";
  parameter Integer nRecv = 1 "Number of data points to be read";
  parameter Modelica_DeviceDrivers.Utilities.Types.ByteOrder byteOrder = Modelica_DeviceDrivers.Utilities.Types.ByteOrder.LE "Byte order";
protected
  Integer stateExample "Dummy variable to check state of TCP send function, 0 == OK, 1 == error";
  Modelica_DeviceDrivers.Packaging.SerialPackager pkgSend = Modelica_DeviceDrivers.Packaging.SerialPackager(8*nSend) "Package for the message to be send";
  Modelica_DeviceDrivers.Packaging.SerialPackager pkgRecv = Modelica_DeviceDrivers.Packaging.SerialPackager(8*nRecv) "Package to host the received message";

algorithm
  when {sampleTrigger} then
    if isConnected then
      Modelica_DeviceDrivers.Packaging.SerialPackager_.addReal(pkgSend, u, byteOrder);
      stateExample := Modelica_DeviceDrivers.Communication.TCPIPSocketClient_.sendTo(socketHandle, pkgSend, 8*nSend);    // send message
      Modelica_DeviceDrivers.Packaging.SerialPackager_.resetPointer(pkgSend);

/************************* In between for explanation ******************************/
      Modelica.Utilities.Streams.print("SocketSend(): Send message to IP " + IP_Address + " at port " + String(port) + ": " + String(u[1]));
/************************* In between for explanation ******************************/

      Modelica_DeviceDrivers.Communication.TCPIPSocketClient_.read(socketHandle, pkgRecv, 8*nRecv);   // receive message

      y := Modelica_DeviceDrivers.Packaging.SerialPackager_.getReal(pkgRecv, nRecv, byteOrder);
      Modelica_DeviceDrivers.Packaging.SerialPackager_.resetPointer(pkgRecv);

/************************* In between for explanation ******************************/
      Modelica.Utilities.Streams.print("SocketReceive(): Message received from IP " + IP_Address + " at port " + String(port) + ": " + String(y[1]));
/************************* In between for explanation ******************************/
    end if;
  end when;
end TCPCommunicatorExample;


Modelica.Icons.BasesPackage

within AixLib.Utilities.Communication.SocketCommunication.Components;
package BaseClasses "Modelica.Icons.BasesPackage"
  extends Modelica.Icons.BasesPackage;

end BaseClasses;


Partial Model of TCP-Interface, minimum code which needs additional information. This is a partial model for a model which handles TCP communication.
  It only establishes a connection to a server on a certain port and
  terminates it when the simulation ends.

within AixLib.Utilities.Communication.SocketCommunication.Components.BaseClasses;
partial model PartialTCPCommunicator
  "Partial Model of TCP-Interface, minimum code which needs additional information"

 // Base Class Discrete MIMO from MSL with discrete event mechanism via sampleTrigger
extends Modelica.Blocks.Interfaces.DiscreteMIMO;

/**************** Required input ****************************/
  parameter String IP_Address="127.0.0.1" "IP address or name of server";
  parameter Integer port(min=0)=27015 "Port on server";

 /**************** socket handle ***********************/
protected
  Modelica_DeviceDrivers.Communication.TCPIPSocketClient socketHandle = Modelica_DeviceDrivers.Communication.TCPIPSocketClient() "Socket handle";

  Boolean isConnected(start=false, fixed=true);

equation
  when initial() then
    isConnected = Modelica_DeviceDrivers.Communication.TCPIPSocketClient_.connect_(socketHandle, IP_Address, port);
  end when;
end PartialTCPCommunicator;


Example to include TCP communication to simple test server in the control loop. This is a very simple example to show the TCP communication
  functionality. A feedback control is modeled where a gain controller
  controls a first order system. The signal is send to a server which
  returns the send message unaltered back to the client.

within AixLib.Utilities.Communication.SocketCommunication.Examples;
model ExampleClientLoop
  "Example to include TCP communication to simple test server in the control loop"
extends Modelica.Icons.Example;
  Modelica.Blocks.Continuous.FirstOrder system(
    k=1,
    T=1,
    initType=Modelica.Blocks.Types.Init.InitialOutput,
    y_start=5) "Simple first order system to be controlled"
  Modelica.Blocks.Math.Feedback feedback
  Modelica.Blocks.Nonlinear.Limiter limiter(uMax=100, uMin=-100)
    "limits output of controller"
  Modelica.Blocks.Math.Gain gain(k=10) "Only gain controller"
  Modelica.Blocks.Sources.Pulse pulse(
    amplitude=5,
    period=1,
    offset=5) "Pulse of set point"
  Components.TCPCommunicatorExample tCPCommunicatorExample(portExample=27015,
    samplePeriodExample=0.01,
    IP_AddressExample="127.0.0.1")
    "TCP block which sends values and receives values, has no impact on signal"
equation

  connect(system.y, feedback.u2)
  connect(gain.u, feedback.y)
  connect(gain.y, limiter.u)
  connect(pulse.y, feedback.u1)
  connect(tCPCommunicatorExample.y[1], system.u)
  connect(tCPCommunicatorExample.u[1], limiter.y)
end ExampleClientLoop;


Package with cryptographic functions

within AixLib.Utilities;
package Cryptographics "Package with cryptographic functions"
  extends Modelica.Icons.VariantsPackage;
end Cryptographics;


within AixLib.Utilities.Cryptographics;
package Validation "Validation models for cryptographic functions."
extends Modelica.Icons.ExamplesPackage;
end Validation;


Model that verifies the SHA1 encryption C function. This validation function tests the C implementation of the SHA1 encryption for
the following strings:

within AixLib.Utilities.Cryptographics.Validation;
model SHA1 "Model that verifies the SHA1 encryption C function"
  extends Modelica.Icons.Example;

  //Test strings
  parameter String strIn1 = "abc"
    "First test string";
  parameter String strIn2 = ""
    "Second test string";
  parameter String strIn3 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
    "Third test string";
  parameter String strIn4 = "1.23e+4"
    "Fourth test string";
  parameter String strIn5 = Modelica.Utilities.Strings.repeat(509, string="a")
    "Fifth test string";

  //Expected outputs
  parameter String strEx1=
    "a9993e364706816aba3e25717850c26c9cd0d89d"
    "Encryption result of first string";
  parameter String strEx2=
    "da39a3ee5e6b4b0d3255bfef95601890afd80709"
    "Encryption result of second string";
  parameter String strEx3=
    "84983e441c3bd26ebaae4aa1f95129e5e54670f1"
    "Encryption result of third string";
  parameter String strEx4=
    "bdd220adb45b392f17915af70ed8a006c382b983"
    "Encryption result of fourth string";
  parameter String strEx5=
    "edff7a135c2e06d4c8084e61b4516c901bd5fcd0"
    "Encryption result of fifth string";

  //Comparison results
  Boolean cmp1,cmp2,cmp3,cmp4,cmp5,cmpAll;

equation
  cmp1 = Modelica.Utilities.Strings.isEqual(AixLib.Utilities.Cryptographics.sha(strIn1),strEx1,false);
  cmp2 = Modelica.Utilities.Strings.isEqual(AixLib.Utilities.Cryptographics.sha(strIn2),strEx2,false);
  cmp3 = Modelica.Utilities.Strings.isEqual(AixLib.Utilities.Cryptographics.sha(strIn3),strEx3,false);
  cmp4 = Modelica.Utilities.Strings.isEqual(AixLib.Utilities.Cryptographics.sha(strIn4),strEx4,false);
  cmp5 = Modelica.Utilities.Strings.isEqual(AixLib.Utilities.Cryptographics.sha(strIn5),strEx5,false);
  cmpAll = cmp1 and cmp2 and cmp3 and cmp4 and cmp5;
end SHA1;


Assert when condition is violated. Model that triggers an assert if
|u1-u2| > threShold
and t > t0.

within AixLib.Utilities.Diagnostics;
block AssertEquality "Assert when condition is violated"
  extends BaseClasses.PartialInputCheck(message = "Inputs differ by more than threShold");
equation
  if noEvent(time > t0) then
    assert(noEvent(abs(u1 - u2) < threShold), message + "\n"
      + "  time       = " + String(time) + "\n"
      + "  u1         = " + String(u1) + "\n"
      + "  u2         = " + String(u2) + "\n"
      + "  abs(u1-u2) = " + String(abs(u1-u2)) + "\n"
      + "  threShold  = " + String(threShold));
  end if;
end AssertEquality;


Assert when condition is violated. Model that triggers an assert if
u1 > u2 - threShold
and t > t0.

within AixLib.Utilities.Diagnostics;
block AssertInequality "Assert when condition is violated"
  extends BaseClasses.PartialInputCheck(message = "Inputs differ by more than threShold",
     threShold = 0);
equation
  if noEvent(time > t0) then
    assert(noEvent(u1 > u2 - threShold), message + "\n"
      + "  time       = " + String(time) + "\n"
      + "  u1         = " + String(u1) + "\n"
      + "  u2         = " + String(u2) + "\n"
      + "  abs(u1-u2) = " + String(abs(u1-u2)) + "\n"
      + "  threShold  = " + String(threShold));
  end if;
end AssertInequality;


Check equality between inputs up to a threshold. Block that outputs 0 if the difference
|u1-u2| < threShold,
or else it outputs u2-u1.

within AixLib.Utilities.Diagnostics;
block CheckEquality "Check equality between inputs up to a threshold"
  extends Modelica.Blocks.Icons.Block;

  parameter Real threShold(min=0)=1e-2 "Threshold for equality comparison";

  Modelica.Blocks.Interfaces.RealInput u1 "Value to check"
  Modelica.Blocks.Interfaces.RealInput u2 "Value to check"
  Modelica.Blocks.Interfaces.RealOutput y "Error"

equation
  y = noEvent(if abs(u2-u1)< threShold then 0 else u2-u1);
end CheckEquality;


within AixLib.Utilities;
package Diagnostics "Library with models to diagnose model errors"
  extends Modelica.Icons.VariantsPackage;
end Diagnostics;


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


Assert when condition is violated. Partial model that can be used to check whether its
inputs satisfy a certain condition such as equality within
a prescribed threshold.

within AixLib.Utilities.Diagnostics.BaseClasses;
block PartialInputCheck "Assert when condition is violated"
  extends Modelica.Blocks.Icons.Block;
  parameter Modelica.Units.SI.Time startTime=0
    "Start time for activating the assert";
  parameter Real threShold(min=0)=1E-2 "Threshold for equality comparison";
  parameter String message = "Inputs differ by more than threShold";
  Modelica.Blocks.Interfaces.RealInput u1 "Value to check"
  Modelica.Blocks.Interfaces.RealInput u2 "Value to check"
protected
  parameter Modelica.Units.SI.Time t0(fixed=false) "Simulation start time";
initial equation
  t0 = time + startTime;
end PartialInputCheck;


Validation model for the check equality model. This model validates the use of the

AixLib.Utilities.Diagnostics.CheckEquality.

within AixLib.Utilities.Diagnostics.Validation;
model CheckEquality "Validation model for the check equality model"
  extends Modelica.Icons.Example;

  AixLib.Utilities.Diagnostics.CheckEquality cheEqu
    "Checks for equality of the input"
  Modelica.Blocks.Sources.Constant con(k=0.1) "Input"
  Modelica.Blocks.Sources.Sine sin1(f=1, amplitude=0.03) "Input"
  Modelica.Blocks.Math.Add add "Adder to offset the sin input signal"
equation

  connect(con.y, cheEqu.u1)
  connect(add.u1, con.y)
  connect(sin1.y, add.u2)
  connect(add.y, cheEqu.u2)
end CheckEquality;


within AixLib.Utilities.Diagnostics;
package Validation "Collection of models that validate the diagnostics models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


    April 11, 2013  by Ole Odendahl:

    Formatted documentation appropriately

    October 14, 2012  by Ana Constantin:

    Implemented.

.

within AixLib.Utilities.Examples;
model HeatConv_outside
  extends Modelica.Icons.Example;
  HeatTransfer.HeatConvOutside heatTransfer_Outside(
    calcMethod=3,
    A=16,
    hCon_const=25)
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature Tinside
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature Toutside
  Modelica.Blocks.Sources.RealExpression Windspeed(y = 4)
  Modelica.Blocks.Sources.Constant const(k = 10 + 273.15)
  Modelica.Blocks.Sources.Constant const1(k = 20 + 273.15)
  Modelica.Blocks.Sources.RealExpression HeatFlow(y = heatTransfer_Outside.port_b.Q_flow)
equation
  connect(const.y, Toutside.T)
  connect(const1.y, Tinside.T)
  connect(heatTransfer_Outside.port_a, Toutside.port)
  connect(heatTransfer_Outside.port_b, Tinside.port)
  connect(Windspeed.y, heatTransfer_Outside.WindSpeedPort)
end HeatConv_outside;


Test routine for heat transfer models.

within AixLib.Utilities.Examples;
model HeatTransfer_test "Test routine for heat transfer models"
  extends Modelica.Icons.Example;
  HeatTransfer.HeatConv heatConv(hCon=2, A=16)
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor load(C = 1000 * 1600 * 16 * 0.2)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor heatCond(G = 16 * 2.4 / 0.1)
  HeatTransfer.HeatConvInside heatConv_inside(
    A=16,
    hCon_const=2,
    surfaceOrientation=2,
    calcMethod=1)
  HeatTransfer.HeatConvOutside heatTransfer_Outside(
    calcMethod=1,
    A=16,
    hCon_const=25,
    surfaceType=DataBase.Surfaces.RoughnessForHT.Brick_RoughPlaster())
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor heatTrans(G = 16 * 1.5)
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature TempOutside
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature TempInside
  Modelica.Blocks.Sources.Sine sineWindSpeed(amplitude=10, f=0.5)
  Modelica.Blocks.Interfaces.RealOutput Q_flow[6]
  Modelica.Blocks.Sources.Sine sine(
    amplitude=15,
    f=1/3600/12,
    offset=273.15 + 15)
  Modelica.Blocks.Sources.Constant constTempInside(k=273.15 + 20)
equation
  //Connecting the Heat Flow Output, models as stated below in source code
  Q_flow[1] = heatConv.port_b.Q_flow;
  Q_flow[2] = load.port.Q_flow;
  Q_flow[3] = heatCond.port_b.Q_flow;
  Q_flow[4] = heatConv_inside.port_b.Q_flow;
  Q_flow[5] = heatTransfer_Outside.port_b.Q_flow;
  Q_flow[6] = heatTrans.port_b.Q_flow;
  connect(TempOutside.port, load.port)
  connect(TempOutside.port, heatCond.port_a)
  connect(TempOutside.port, heatConv_inside.port_a)
  connect(heatConv.port_b, TempInside.port)
  connect(heatCond.port_b, TempInside.port)
  connect(heatConv_inside.port_b, TempInside.port)
  connect(sineWindSpeed.y, heatTransfer_Outside.WindSpeedPort)
  connect(TempOutside.port, heatConv.port_a)
  connect(sine.y, TempOutside.T)
  connect(constTempInside.y, TempInside.T)
  connect(TempOutside.port, heatTrans.port_a)
  connect(heatTrans.port_b, TempInside.port)
  connect(heatTransfer_Outside.port_a, TempOutside.port)
  connect(heatTransfer_Outside.port_b, TempInside.port)
end HeatTransfer_test;


Examples for BaseLib Components

within AixLib.Utilities;
package Examples "Examples for BaseLib Components"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Simulation to test the utilities concerning the time.

within AixLib.Utilities.Examples;
model TimeUtilities_test "Simulation to test the utilities concerning the time"
  import Utilities;
  extends Modelica.Icons.Example;
  Sources.NightMode nightMode(dayStart = 8, dayEnd = 20)
  Sources.HourOfDay hourOfDay
  Modelica.Blocks.Interfaces.BooleanOutput boolNightMode
  Modelica.Blocks.Interfaces.RealOutput realSamples[1]
equation
  //Connections for real outputs
  realSamples[1] = hourOfDay.HOD;
  //Connection for night mode output
  boolNightMode = nightMode.IsNight.y;
  connect(boolNightMode, boolNightMode)
end TimeUtilities_test;


Calculate Q_flow from m_flow, deltaT and specific heat capacity.

within AixLib.Utilities.HeatTransfer;
block CalcQFlow
  "Calculate Q_flow from m_flow, deltaT and specific heat capacity"
  extends Modelica.Blocks.Icons.Block;
  parameter Modelica.Units.SI.SpecificHeatCapacity cp
    "Gain with specific heat capacity"

  Modelica.Blocks.Interfaces.RealInput m_flow(quantity="MassFlowRate", unit="kg/s")
    "Mass flow rate"
  Modelica.Blocks.Interfaces.RealInput T_a(quantity="ThermodynamicTemperature",
    unit="K",
    displayUnit="degC") "Temperature (minuend in substraction)"
  Modelica.Blocks.Interfaces.RealInput T_b(
    quantity="ThermodynamicTemperature",
    unit="K",
    displayUnit="degC") "Temperature (subtrahend in substraction)"

  Modelica.Blocks.Math.Add deltaT(k2=-1)
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Math.Gain specHeaCap(final k=cp)

  Modelica.Blocks.Interfaces.RealOutput Q_flow(final quantity="HeatFlowRate",
      final unit="W") "Q_flow calculated from m_flow, deltaT and cp"
equation
  connect(deltaT.y, product.u2)
  connect(product.y, specHeaCap.u)
  connect(specHeaCap.y, Q_flow)
  connect(T_a, deltaT.u1)
  connect(T_b, deltaT.u2)
  connect(product.u1, m_flow)
end CalcQFlow;


Heat conduction through cylindric material.

within AixLib.Utilities.HeatTransfer;
model CylindricHeatConduction "Heat conduction through cylindric material"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b port_b
  parameter Modelica.Units.SI.Length d_out(min=0) "outer diameter of pipe";
  parameter Modelica.Units.SI.ThermalConductivity lambda=373
    "Heat conductivity of pipe";
  parameter Modelica.Units.SI.Length d_in(min=0) "inner diameter of pipe";
  parameter Modelica.Units.SI.Length length(min=0) " Length of pipe";
  parameter Integer nParallel = 1 "Number of identical parallel pipes";

equation
  port_a.Q_flow + port_b.Q_flow = 0;
  port_a.Q_flow = (2*lambda*length*Modelica.Constants.pi/(log(d_out/d_in)))*(port_a.T - port_b.T)*nParallel;
end CylindricHeatConduction;


Model for cylindric heat transfer.

within AixLib.Utilities.HeatTransfer;
model CylindricHeatTransfer "Model for cylindric heat transfer"
  // Assumptions
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"

  parameter Modelica.Units.SI.Density rho=1600 "Density of material";
  parameter Modelica.Units.SI.SpecificHeatCapacity c=1000
    "Specific heat capacity of material";
  parameter Modelica.Units.SI.Length d_out(min=0) "Outer diameter of pipe";
  parameter Modelica.Units.SI.Length d_in(min=0) "Inner diameter of pipe";
  parameter Modelica.Units.SI.Length length(min=0) " Length of pipe";
  parameter Modelica.Units.SI.ThermalConductivity lambda=373
    "Heat conductivity of pipe";
  parameter Modelica.Units.SI.Temperature T0=289.15 "Initial temperature";
  parameter Integer nParallel = 1 "Number of identical parallel pipes";

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b port_b
  AixLib.Utilities.HeatTransfer.CylindricHeatConduction CylindricHeatConductionOut(
    length=length,
    lambda=lambda,
    d_in=(d_out + d_in)/2,
    d_out=d_out,
    nParallel=nParallel) "Outer heat conduction"
  AixLib.Utilities.HeatTransfer.CylindricLoad CylindricLoad1(
    final energyDynamics=energyDynamics,
    rho=rho,
    c=c,
    d_in=d_in,
    d_out=d_out,
    length=length,
    T0=T0,
    nParallel=nParallel) "Heat capacity"
  AixLib.Utilities.HeatTransfer.CylindricHeatConduction CylindricHeatConductionIn(
    length=length,
    lambda=lambda,
    d_out=(d_out + d_in)/2,
    d_in=d_in,
    nParallel=nParallel) "Inner heat conduction"
equation
  connect(CylindricHeatConductionOut.port_b, port_b)
  connect(CylindricHeatConductionIn.port_b, CylindricLoad1.port)
  connect(port_a, CylindricHeatConductionIn.port_a)
  connect(CylindricHeatConductionOut.port_a, CylindricLoad1.port)
end CylindricHeatTransfer;


Model for a cylindric heat capacity.

within AixLib.Utilities.HeatTransfer;
class CylindricLoad "Model for a cylindric heat capacity"
  // Assumptions
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"

  parameter Modelica.Units.SI.Density rho=1600 "Density of material";
  parameter Modelica.Units.SI.SpecificHeatCapacity c=1000
    "Specific heat capacity of material";
  parameter Modelica.Units.SI.Length d_out(min=0) "outer diameter of pipe";
  parameter Modelica.Units.SI.Length d_in(min=0) "inner diameter of pipe";
  parameter Modelica.Units.SI.Length length(min=0) " Length of pipe";
  parameter Modelica.Units.SI.Temperature T0=289.15 "initial temperature";
  parameter Integer nParallel = 1 "Number of identical parallel pipes";
  final parameter Modelica.Units.SI.Mass m=nParallel*rho*length*Modelica.Constants.pi
      *(d_out*d_out - d_in*d_in)/4 "Mass of material";

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heatCapacitor(
    final C=m*c,
    final T(
      stateSelect=StateSelect.always,
      fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.FixedInitial),
      start=T0),
    final der_T(
      fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyStateInitial),
      start=0)) if not (energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState)

equation
  connect(heatCapacitor.port, port)
end CylindricLoad;


Convection heat transfer coeffient.

within AixLib.Utilities.HeatTransfer;
model HeatConv
  extends Modelica.Thermal.HeatTransfer.Interfaces.Element1D;
  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hCon
    "Convection heat transfer coeffient";
  parameter Modelica.Units.SI.Area A(min=0);
equation
  // no storage of heat
  port_a.Q_flow =hCon*A*(port_a.T - port_b.T);
end HeatConv;


Natural convection computation according to B. Glueck or EN ISO 6946, with choice between several types of surface orientation, according to ASHRAE140-2017 or a constant convective heat transfer coefficient. Overview

within AixLib.Utilities.HeatTransfer;
model HeatConvInside
  "Natural convection computation according to B. Glueck or EN ISO 6946, with choice between several types of surface orientation, according to ASHRAE140-2017 or a constant convective heat transfer coefficient"
  /* calculation of natural convection in the inside of a building according to B.Glueck, ASHRAE140-2017, EN ISO 6946 or using a constant convective heat transfer coefficient hCon_const
  */
  extends Modelica.Thermal.HeatTransfer.Interfaces.Element1D;

  parameter AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransferInsideSurface calcMethod=AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransferInsideSurface.Bernd_Glueck "Calculation method for convective heat transfer coefficient"

  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hCon_const=2.5
    "Custom convective heat transfer coefficient"

  parameter Modelica.Units.SI.TemperatureDifference dT_small=0.1
    "Linearized function around dT = 0 K +/-"

  // which orientation of surface?
  parameter AixLib.ThermalZones.HighOrder.Components.Types.InsideSurfaceOrientation surfaceOrientation=AixLib.ThermalZones.HighOrder.Components.Types.InsideSurfaceOrientation.vertical_wall "Surface orientation"
  parameter Modelica.Units.SI.Area A(min=Modelica.Constants.eps)
    "Area of surface";
  Modelica.Units.SI.CoefficientOfHeatTransfer hCon
    "variable heat transfer coefficient";

protected
  Modelica.Units.NonSI.Temperature_degC posDiff=noEvent(abs(port_b.T - port_a.T))
    "Positive temperature difference";
equation

  /*
        port_b -> wall
        port_a -> air
  */

  // ++++++++++++++++EN ISO 6946 Appendix A >>Flat Surfaces<<++++++++++++++++
  // upward heat flow: hCon = 5, downward heat flow: hCon = 0.7, horizontal heat flow: hCon = 2.5
  if calcMethod == AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransferInsideSurface.EN_ISO_6946_Appendix_A then

    // floor (horizontal facing up)
    if surfaceOrientation == AixLib.ThermalZones.HighOrder.Components.Types.InsideSurfaceOrientation.floor then
      hCon = Modelica.Fluid.Utilities.regStep(
        x=port_b.T - port_a.T,
        y1=5,
        y2=0.7,
        x_small=dT_small);

    // ceiling (horizontal facing down)
    elseif surfaceOrientation == AixLib.ThermalZones.HighOrder.Components.Types.InsideSurfaceOrientation.ceiling then
      hCon = Modelica.Fluid.Utilities.regStep(
        x=port_b.T - port_a.T,
        y1=0.7,
        y2=5,
        x_small=dT_small);

    // vertical
    else
      hCon = 2.5;
    end if;

  // ++++++++++++++++Bernd Glueck++++++++++++++++
  // (Bernd Glueck: Heizen und Kuehlen mit Niedrigexergie - Innovative Waermeuebertragung und Waermespeicherung (LowEx) 2008)
  // upward heat flow: hCon = 2*(posDiff^0.31)          - equation 1.27, page 26
  // downward heat flow: hCon = 0.54*(posDiff^0.31)     - equation 1.28, page 26
  // horizontal heat flow: hCon = 0.1.6*(posDiff^0.31)  - equation 1.26, page 26
  elseif calcMethod == AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransferInsideSurface.Bernd_Glueck then

    // floor (horizontal facing up)

    if surfaceOrientation == AixLib.ThermalZones.HighOrder.Components.Types.InsideSurfaceOrientation.floor then
      hCon = Modelica.Fluid.Utilities.regStep(
        x=port_b.T - port_a.T,
        y1=2*AixLib.Utilities.Math.Functions.regNonZeroPower(posDiff, 0.31, dT_small),
        y2=0.54*AixLib.Utilities.Math.Functions.regNonZeroPower(posDiff, 0.31, dT_small),
        x_small=dT_small);

    // ceiling (horizontal facing down)
    elseif surfaceOrientation == AixLib.ThermalZones.HighOrder.Components.Types.InsideSurfaceOrientation.ceiling then
       hCon = Modelica.Fluid.Utilities.regStep(
        x=port_b.T - port_a.T,
        y1=0.54*AixLib.Utilities.Math.Functions.regNonZeroPower(posDiff, 0.31, dT_small),
        y2=2*AixLib.Utilities.Math.Functions.regNonZeroPower(posDiff, 0.31, dT_small),
        x_small=dT_small);

    // vertical plate
    else
      hCon = 1.6*AixLib.Utilities.Math.Functions.regNonZeroPower(posDiff, 0.31, dT_small);
    end if;

    // ++++++++++++++++hCon_const++++++++++++++++

  elseif calcMethod == AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransferInsideSurface.Custom_hCon then
    hCon = hCon_const;

    // ++++++++++++++++ASHRAE140-2017++++++++++++++++
    // upward heat flow: hCon = 4.13, downward heat flow: hCon = 1, horizontal heat flow: hCon = 3.16
   elseif calcMethod == AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransferInsideSurface.ASHRAE140_2017 then

    // floor (horizontal facing up)
    if surfaceOrientation == AixLib.ThermalZones.HighOrder.Components.Types.InsideSurfaceOrientation.floor then
      hCon = Modelica.Fluid.Utilities.regStep(
        x=port_b.T - port_a.T,
        y1=4.13,
        y2=1,
        x_small=dT_small);

      // ceiling (horizontal facing down)
    elseif surfaceOrientation == AixLib.ThermalZones.HighOrder.Components.Types.InsideSurfaceOrientation.ceiling then
      hCon = Modelica.Fluid.Utilities.regStep(
        x=port_b.T - port_a.T,
        y1=1,
        y2=4.13,
        x_small=dT_small);

      // vertical
    else
      hCon = 3.16;
    end if;

  else
    hCon = Modelica.Constants.eps;
    assert(0>1, "Choose another value for calcMethod. In component " + getInstanceName() + " the value is calcMethod = " + String(calcMethod) + ".", AssertionLevel.error);

  end if;

  port_a.Q_flow = hCon*A*(port_a.T - port_b.T);
end HeatConvInside;


Model for heat transfer at outside surfaces. Choice between multiple models. Overview

within AixLib.Utilities.HeatTransfer;
model HeatConvOutside "Model for heat transfer at outside surfaces. Choice between multiple models"
  extends Modelica.Thermal.HeatTransfer.Interfaces.Element1D;
  parameter AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransfer calcMethod=AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransfer.ASHRAE_Fundamentals "Calculation method for convective heat transfer coefficient"
  parameter Modelica.Units.SI.Area A(min=0) "Area of surface"
  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hCon_const=25
    "Custom convective heat transfer coeffient"
  parameter
    DataBase.Surfaces.RoughnessForHT.PolynomialCoefficients_ASHRAEHandbook         surfaceType = DataBase.Surfaces.RoughnessForHT.Brick_RoughPlaster()
    "Surface type"
  // Variables
  Modelica.Units.SI.CoefficientOfHeatTransfer hCon
    "Convection heat transfer coeffient";
  Modelica.Blocks.Interfaces.RealInput WindSpeedPort if calcMethod == AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransfer.DIN_6946 or calcMethod == AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransfer.ASHRAE_Fundamentals

protected
  Modelica.Blocks.Interfaces.RealInput WindSpeed_internal(unit="m/s");
equation
  // Main equation of heat transfer
  port_a.Q_flow =hCon*A*(port_a.T - port_b.T);

  //Determine convection heat transfer coefficient hCon
  if calcMethod == AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransfer.DIN_6946 then
    hCon = (4 + 4*WindSpeed_internal);
  elseif calcMethod == AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodConvectiveHeatTransfer.ASHRAE_Fundamentals then
    hCon = surfaceType.D + surfaceType.E*WindSpeed_internal + surfaceType.F*(WindSpeed_internal^2);
  else
    hCon = hCon_const;
    WindSpeed_internal = 0;
  end if;

  connect(WindSpeedPort, WindSpeed_internal);
end HeatConvOutside;


Dynamic model for Heat Transfer through convection inside a pipe, based on Nussel Correlations.

within AixLib.Utilities.HeatTransfer;
model HeatConvPipeInsideDynamic
  "Dynamic model for Heat Transfer through convection inside a pipe, based on Nussel Correlations"
  extends Modelica.Thermal.HeatTransfer.Interfaces.Element1D;
  parameter Modelica.Units.SI.Length length=1 "Length of total pipe";
  parameter Modelica.Units.SI.Length d_i=0.02 "Inner diameter of exhaust pipe";
  parameter Modelica.Units.SI.Area A_sur=2 "Surface for heat transfer";
  parameter Boolean calculateHConv=true
    "Use calculated value for inside heat coefficient";
  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hConvInsideFix=30
  input Modelica.Units.SI.MassFlowRate m_flow "Mass flow rate of gas";
  input Modelica.Units.SI.SpecificHeatCapacity c
    "Heat capacity of considered medium"
  input Modelica.Units.SI.Density rho "Density of considered medium"
  input Modelica.Units.SI.ThermalConductivity lambda
    "Thermal conductivity of considered medium"
  input Modelica.Units.SI.DynamicViscosity eta
    "Dynamic viscosity of considered medium"
  Modelica.Units.SI.ReynoldsNumber Re;
  Modelica.Units.SI.Velocity v;
  Modelica.Units.SI.NusseltNumber Nu;
  Modelica.Units.SI.NusseltNumber Nu_lam_1;
  Modelica.Units.SI.NusseltNumber Nu_lam_2;
  Modelica.Units.SI.NusseltNumber Nu_lam;
  Modelica.Units.SI.NusseltNumber Nu_tur;
  Modelica.Units.SI.PrandtlNumber Pr;
  Modelica.Units.SI.CoefficientOfHeatTransfer alpha;
  Real zeta "pressure loss coefficient";

equation
  if calculateHConv then
    v      =        4*m_flow/(Modelica.Constants.pi * d_i^2 * rho);
    Re     =    Modelica.Fluid.Pipes.BaseClasses.CharacteristicNumbers.ReynoldsNumber(
      v,rho,eta, d_i)              "Reynolds numbers";
    Pr     =        eta *c /lambda;
    zeta   =        (1.8*log10(max(1e-10,Re))-1.5)^(-2);
    Nu_lam_1 =      3.66;
    Nu_lam_2 =      1.615 * (Re*Pr*d_i/length)^(1/3);
    Nu_lam   =      (Nu_lam_1^3 + 0.7^3 + (Nu_lam_2 - 0.7)^3)^(1/3);
    Nu_tur   =      (zeta/8*Re*Pr)/(1+12.7*(zeta/8)^0.5*(Pr^(2/3)-1))*(1+(d_i/length)^(2/3));
    Nu       =      smooth(0,if Re<=2300 then Nu_lam else Nu_tur);
  else
    //prevent solver from solving the equations if they are not used
    v=0;
    Re=0;
    Pr=0;
    zeta=0;
    Nu_lam_1=0;
    Nu_lam_2=0;
    Nu_lam=0;
    Nu_tur=0;
    Nu=0;
    end if;
  alpha    =      if calculateHConv then Nu  * lambda /d_i else hConvInsideFix;
  port_a.Q_flow = alpha * A_sur * (port_a.T - port_b.T);
end HeatConvPipeInsideDynamic;


Adaptor for approximative longwave radiation exchange with variable surface Area. Overview

within AixLib.Utilities.HeatTransfer;
model HeatToRad "Adaptor for approximative longwave radiation exchange with variable surface Area"
  parameter Modelica.Units.SI.Emissivity eps=0.95 "Emissivity";
  parameter Modelica.Units.SI.Temperature T_ref=
      Modelica.Units.Conversions.from_degC(16)
    "Reference temperature for optional linearization"
  parameter Boolean use_A_in = false
    "Get the area from the input connector"
  parameter Modelica.Units.SI.Area A=-1 "Fixed value of prescribed area"
  parameter AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodRadiativeHeatTransfer radCalcMethod=AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodRadiativeHeatTransfer.No_approx "Calculation method for radiation heat transfer"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a convPort
    "Heat port for convective or conductive heat flow"
  Modelica.Blocks.Interfaces.RealInput A_in(final unit="m2") if use_A_in
    "Area of radiation exchange connector"
  AixLib.Utilities.Interfaces.RadPort radPort
    "Heat port for longwave radiative heat flow"
protected
  Modelica.Blocks.Interfaces.RealInput A_in_internal(final unit="m2")
    "Needed to connect to conditional connector";
initial equation
  if not use_A_in then
    assert(A > 0, "The area for heattransfer must be positive");
  end if;
equation
 convPort.Q_flow + radPort.Q_flow = 0;
  // To prevent negative solutions for T, the max() expression is used.
  // Negative solutions also occur when using max(T,0), therefore, 1 K is used.
  if radCalcMethod == AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodRadiativeHeatTransfer.No_approx then
    convPort.Q_flow = Modelica.Constants.sigma*eps*A_in_internal*(max(convPort.T, 1)*max(convPort.T, 1)*max(convPort.T, 1)*max(convPort.T, 1) - max(radPort.T, 1)*max(radPort.T, 1)*max(radPort.T, 1)*max(radPort.T, 1));
  elseif radCalcMethod == AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodRadiativeHeatTransfer.Linear_wall_temp then
    convPort.Q_flow = Modelica.Constants.sigma*eps*A_in_internal*4*convPort.T*convPort.T*convPort.T*(convPort.T - radPort.T);
  elseif radCalcMethod == AixLib.ThermalZones.HighOrder.Components.Types.CalcMethodRadiativeHeatTransfer.Linear_rad_temp then
    convPort.Q_flow = Modelica.Constants.sigma*eps*A_in_internal*4*radPort.T*radPort.T*radPort.T*(convPort.T - radPort.T);
  else
    convPort.Q_flow =Modelica.Constants.sigma*eps*A_in_internal*4*T_ref*T_ref*T_ref*(convPort.T - radPort.T);
  end if;
  if not use_A_in then
    A_in_internal =A;
  end if;

  connect(A_in, A_in_internal);
end HeatToRad;


within AixLib.Utilities;
package HeatTransfer "Models for different types of heat transfer"
  extends Modelica.Icons.Package;
end HeatTransfer;


Model to distribute short wave radiation transmitted through a window to all areas in the room using shape factors. This model distributes the incoming short wave radtion onto different
  areas of the room according to the approach in the ASHREA Standard,
  Annex B7 \"Detailed calculation of solar fractions\". The ASHREA makes
  some assumptions to estimate the sight factors of each element. For
  more details on the assumptions, we refer to the ASHREA standard. In
  order to ease the usage of this model, we made additional
  assumptions.

within AixLib.Utilities.HeatTransfer;
model SolarRadInRoom
  "Model to distribute short wave radiation transmitted through a window to all areas in the room using shape factors"

  parameter Boolean use_dynamicMethod=true "True = dynamic as holistic approach, false = static approach to obtain the same values as provided in tables of the ASHREA"

  parameter Integer nWin=1
    "Number of windows in room transmitting shortwave radiation"
  parameter Integer nWalls=4 "Number of walls in room - For static calculation, the only option is nWalls=4! The order is: East, South, West, North"
  parameter Integer nFloors=1 "Number of floors in room"
  parameter Integer nCei=1 "Number of ceilings in room"
  parameter Modelica.Units.SI.Length floor_length=0
    "Total length of floors (not levels). Multiple floor parts are modeled as one area. For this equivelant area, you have to specify the length and width of the total floor"
  parameter Modelica.Units.SI.Length floor_width=0
    "Total width of floors (not levels). Multiple floor parts are modeled as one area. For this equivelant area, you have to specify the length and width of the total floor"

  replaceable parameter
    ThermalZones.HighOrder.Components.Types.PartialCoeffTable staticCoeffTable
    constrainedby AixLib.ThermalZones.HighOrder.Components.Types.PartialCoeffTable
    "Record holding the values to reproduce the tables"

  Interfaces.ShortRadSurf win_in[nWin] "Windows input"
  Interfaces.ShortRadSurf walls[nWalls] "Output to the walls"
  Interfaces.ShortRadSurf floors[nFloors] "Output to the floor(s)"
  Interfaces.ShortRadSurf ceilings[nCei] "Output to the ceiling(s)"
  Interfaces.ShortRadSurf win_out[nWin] "Output to the ceiling(s)"

  Real solar_frac_win_abs[nWin]=if use_dynamicMethod then fill(solar_frac_win_abs_int/nWin, nWin) else fill(staticCoeffTable.coeffWinAbs/nWin, nWin) "Solar fractions for windows, absorbed";
  Real solar_frac_win_lost[nWin]=if use_dynamicMethod then fill(solar_frac_win_lost_int/nWin, nWin) else fill(staticCoeffTable.coeffWinLost/nWin, nWin) "Solar fractions for windows, lost cause of transmitvity";
  Real solar_frac_cei[nCei]=if use_dynamicMethod then bounce_1_cei .+ bounce_2_floor_cei .+ bounce_3_rem_cei .+ bounce_R_rem_cei else fill(staticCoeffTable.coeffCeiling/nCei, nCei) "Solar fractions for ceilings";
  Real solar_frac_flo[nFloors]=if use_dynamicMethod then fill(solar_frac_flo_int/nFloors, nFloors) else fill(staticCoeffTable.coeffFloor/nFloors, nFloors) "Solar fractions for floors";
  Real solar_frac_wall[nWalls]=if use_dynamicMethod then bounce_1_wall .+ bounce_2_floor_wall .+ bounce_3_rem_wall .+ bounce_R_rem_wall else {staticCoeffTable.coeffOWEast,staticCoeffTable.coeffOWSouth,staticCoeffTable.coeffOWWest,staticCoeffTable.coeffOWNorth} "Solar fractions for walls";

protected
  function sight_fac_parallel "Calculate sight factor based on B7-2 in ASHRAE Appendix for parallel areas"
    input Real x "Length of floor / ceiling";
    input Real y "Depth of floor / ceiling";
    input Real D "Height of wall";
    output Real sight_factor;
  protected
    Real X = x / D;
    Real Y = y / D;
  algorithm
    sight_factor := 2 / (Modelica.Constants.pi * Y * X) *(Modelica.Math.log((1 + Y*Y)*(
      1 + X*X)/(1 + Y*Y + X*X))^0.5 + X*(1 + Y*Y)^0.5*Modelica.Math.atan(X/(1 +
      Y*Y)^0.5) + Y*(1 + X*X)^0.5*Modelica.Math.atan(Y/(1 + X*X)^0.5) - X*
      Modelica.Math.atan(X) - Y*Modelica.Math.atan(Y));
  end sight_fac_parallel;

  function sight_fac_orthogonal "Calculate sight factor based on B7-1 in ASHRAE Appendix for orthogonal areas"
    input Real x "Length of floor / wall";
    input Real y "Depth of floor";
    input Real z "Height of wall";
    output Real sight_factor;
  protected
    Real Y = y / x;
    Real Z = y / x;
  algorithm
    sight_factor := 1 / (Modelica.Constants.pi * Y) *( Y * Modelica.Math.atan(1 / Y) + Z * Modelica.Math.atan(1 / Z) - (Z*Z + Y*Y)^0.5*
      Modelica.Math.atan(1/(Z*Z + Y*Y)^0.5) + 0.25*Modelica.Math.log((1 + Y*Y)*(
      1 + Z*Z)/(1 + Y*Y + Z*Z)*((Y*Y*((1 + Y*Y + Z*Z))/((1 + Y*Y)*(Y*Y + Z*Z)))^(
      Y^2))*((Z*Z*((1 + Y*Y + Z*Z))/((1 + Y*Y)*(Y*Y + Z*Z)))^(Z^2))));
  end sight_fac_orthogonal;

  Modelica.Units.SI.Length floor_length_int=if nFloors > 1 then floor_length
       else floors[1].length "Total length of floors";
  Modelica.Units.SI.Height floor_height_int=if nFloors > 1 then floor_width
       else floors[1].height "Total height of floors";

  // Floors and windows have a special rule. As ASHRAE assumes one window and one floor,
  // possible different material properties have to be averaged in order for the approach to work.
  // Internal values for windows and floors:
  Real solar_frac_win_abs_int = bounce_1_win_abs + bounce_2_floor_win_abs + bounce_3_rem_win_abs + bounce_R_rem_win_abs "Solar fractions for windows";
  Real solar_frac_win_lost_int = bounce_1_win_lost + bounce_2_floor_win_lost + bounce_3_rem_win_lost + bounce_R_rem_win_lost "Solar fractions for windows";
  Real solar_frac_flo_int = bounce_1_floor + bounce_2_floor_floor + bounce_3_rem_floor + bounce_R_rem_floor "Solar fractions for floors";
  Real alpha_flo_int=sum(floors.solar_absorptance)/nFloors;
  Real alpha_win_int=sum(win_in.solar_absorptance)/nWin;
  Real rho_win_int=sum(win_in.solar_reflectance)/nWin;
  Modelica.Units.SI.Area A_floor=sum(floors.length .* floors.height);
  Modelica.Units.SI.Area A_win=sum(win_in.length .* win_in.height);
  Modelica.Units.SI.Area A_walls[nWalls]=walls.length .* walls.height;
  Modelica.Units.SI.Area A_ceil[nCei]=ceilings.length .* ceilings.height;
  Modelica.Units.SI.Area area_total=A_floor + sum(A_ceil) + sum(A_walls) +
      A_win "Total area of all surfaces, used for bounce";

  // Define first bounce values:
  Real bounce_1_win_abs = 0;
  Real bounce_1_win_lost = 0;
  Real bounce_1_cei[nCei] = fill(0, nCei);
  Real bounce_1_floor = alpha_flo_int;
  Real bounce_1_wall[nWalls] = fill(0, nWalls);
  Real sum_bounce_1 = alpha_flo_int "Just used to make the concept of bounce 3 more clear";

  // Define second bounce values:
  Real bounce_2_floor_floor = 0;
  Real bounce_2_floor_cei[nCei]=(1 - alpha_flo_int) .* sight_fac_floor_cei .*
      ceilings.solar_absorptance;
  Real bounce_2_floor_wall[nWalls]=(1 - alpha_flo_int) .* sight_fac_floor_wall .*
      walls.solar_absorptance;
  Real bounce_2_floor_win_lost = (1-alpha_flo_int) * sight_fac_floor_win * (1-(rho_win_int + alpha_win_int/2));
  Real bounce_2_floor_win_abs = (1-alpha_flo_int) * sight_fac_floor_win * alpha_win_int/2;
  Real sum_bounce_2 = sum(bounce_2_floor_cei) + sum(bounce_2_floor_wall) + bounce_2_floor_win_lost + bounce_2_floor_win_abs;

  // Define third bounce values. Info: rem means remaining, non absorbed heat:
  Real bounce_3_rem_cei[nCei]=(1 - sum_bounce_1 - sum_bounce_2) .* A_ceil .*
      ceilings.solar_absorptance/area_total;
  Real bounce_3_rem_wall[nWalls]=(1 - sum_bounce_1 - sum_bounce_2) .* A_walls .*
      walls.solar_absorptance/area_total;
  Real bounce_3_rem_floor = (1 - sum_bounce_1 - sum_bounce_2) *  A_floor / area_total * alpha_flo_int;
  Real bounce_3_rem_win_lost = (1 - sum_bounce_1 - sum_bounce_2) *  A_win / area_total * (1-(rho_win_int + alpha_win_int/2));
  Real bounce_3_rem_win_abs = (1 - sum_bounce_1 - sum_bounce_2) *  A_win / area_total * alpha_win_int;
  Real sum_bounce_3 = sum(bounce_3_rem_cei) + sum(bounce_3_rem_wall) + bounce_3_rem_floor + bounce_3_rem_win_abs + bounce_3_rem_win_lost;

  // Define fourth/last or 'Remaining for R' bounce values:
  Real bounce_R_rem_cei[nCei] = (1 - sum_bounce_1 - sum_bounce_2 - sum_bounce_3) * (bounce_3_rem_cei / sum_bounce_3);
  Real bounce_R_rem_wall[nWalls] = (1 - sum_bounce_1 - sum_bounce_2 - sum_bounce_3) * (bounce_3_rem_wall / sum_bounce_3);
  Real bounce_R_rem_floor = (1 - sum_bounce_1 - sum_bounce_2 - sum_bounce_3) * (bounce_3_rem_floor / sum_bounce_3);
  Real bounce_R_rem_win_lost = (1 - sum_bounce_1 - sum_bounce_2 - sum_bounce_3) * (bounce_3_rem_win_lost / sum_bounce_3);
  Real bounce_R_rem_win_abs = (1 - sum_bounce_1 - sum_bounce_2 - sum_bounce_3) * (bounce_3_rem_win_abs / sum_bounce_3);

  // Define sight factors used in bounce 2:
  // Assumption: All walls have the same heigh + ceiling and floor have the same area.
  // Equally split the sight factor onto possible multiple ceilings
  Real sight_fac_floor_cei[nCei]=fill(sight_fac_parallel(
      x=floor_length_int,
      y=floor_height_int,
      D=walls[1].height)/nCei, nCei);

  Real sight_fac_floor_win = A_win / (A_win + sum(A_walls)) * (1 - sum(sight_fac_floor_cei));
  Real sight_fac_floor_wall[nWalls] = A_walls / (A_win + sum(A_walls)) * (1 - sum(sight_fac_floor_cei));

  // Define connectors:
  Real Q_flow_in=sum(win_in.Q_flow_ShoRadFroSur)
    "Sum of all windows directly goes to floor";
  Modelica.Blocks.Sources.RealExpression QRadWalls_out[nWalls](y={Q_flow_in * solar_frac_wall[n] for n in 1:nWalls});
  Modelica.Blocks.Sources.RealExpression QRadCei_out[nCei](y={Q_flow_in * solar_frac_cei[n] for n in 1:nCei});
  Modelica.Blocks.Sources.RealExpression QRadFloors_out[nFloors](y={Q_flow_in * solar_frac_flo[n] for n in 1:nFloors});
  Modelica.Blocks.Sources.RealExpression QRadWin_out[nWin](y={Q_flow_in*
        solar_frac_win_abs[n] for n in 1:nWin});

initial equation
  // Asssert energy balance matches
  assert(abs(sum(cat(1, solar_frac_cei, solar_frac_flo, solar_frac_wall, solar_frac_win_lost, solar_frac_win_abs)) - 1) < Modelica.Constants.eps, "Sum of solar fractions is not equal to 1", AssertionLevel.error);
  // Assert all walls have the same height:
  assert(((sum(walls.height) / size(walls, 1)) - walls[1].height) <  Modelica.Constants.eps, "Not all walls have the same height", AssertionLevel.error);
  assert(sum(A_ceil) - A_floor < Modelica.Constants.eps, "Ceiling and floor have mismatching areas", AssertionLevel.error);
  // Check correct user input if multiple floors are selected
  assert(A_floor - floor_height_int*floor_length_int < Modelica.Constants.eps, "Total floor area mismatches area specified by user", AssertionLevel.error);
  // Check number of walls for static method
  if not use_dynamicMethod then
    assert(nWalls==4, "For static calcuation, the number of floor needs to be equal to 4.", AssertionLevel.error);
  end if;
equation

  for n in 1:nWalls loop
    connect(walls[n].Q_flow_ShoRadOnSur, QRadWalls_out[n].y);
  end for;

  for n in 1:nWin loop
    connect(win_out[n].Q_flow_ShoRadOnSur, QRadWin_out[n].y);
  end for;

  for n in 1:nCei loop
    connect(ceilings[n].Q_flow_ShoRadOnSur, QRadCei_out[n].y);
  end for;

  for n in 1:nFloors loop
    connect(floors[n].Q_flow_ShoRadOnSur, QRadFloors_out[n].y);
  end for;
end SolarRadInRoom;


Compute the heat flow caused by radiation on a surface.

within AixLib.Utilities.HeatTransfer;
model SolarRadToHeat "Compute the heat flow caused by radiation on a surface"
  parameter Real coeff = 0.6 "Weight coefficient";
  // parameter Modelica.SIunits.Area A=6 "Area of surface";
  parameter Real A(min=0) "Area of surface";
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
  AixLib.Utilities.Interfaces.SolarRad_in solarRad_in
equation
  heatPort.Q_flow = -solarRad_in.I * A * coeff;
end SolarRadToHeat;


within AixLib.Utilities;
package Interfaces "Interfaces that are not defined in MSL or Annex60-Library"
  extends Modelica.Icons.InterfacesPackage;
end Interfaces;


Expandable connector for short wave radiation for a surface inside a room. This connector holds variables used to calculate the short wave
  radiation in a room. As you may notice, some of the variables are
  actually parameters. We chose this approach to pass parameters from
  e.g. a wall model directly to the model which calculates the
  radiation exchange (e.g. SolarRadInRoom).

within AixLib.Utilities.Interfaces;
expandable connector ShortRadSurf
  "Expandable connector for short wave radiation for a surface inside a room"
  // Note: For this bus, the naming convention was not considered on purpose, as the convention is mainly for bus connectors used in controls.
  Modelica.Units.SI.Power Q_flow_ShoRadOnSur
    "Short waved radiation from the room on to the inner surfaces";
  Modelica.Units.SI.Power Q_flow_ShoRadFroSur
    "Short waved radiation from the inner surfaces to the room";

  Modelica.Units.SI.Length length "Length of surface"
  Modelica.Units.SI.Height height "Height of surface"
  Real solar_reflectance "Reflectivity of inner surface"
  Real g "Transmissivity of inner surface"
  Real solar_absorptance "Absorptivity of inner surface, equal to eps or 1-rho-tau"
end ShortRadSurf;


<span style=\.

within AixLib.Utilities.Interfaces.Adaptors;
model ConvRadToCombPort
  AixLib.Utilities.Interfaces.ConvRadComb portConvRadComb
  AixLib.Utilities.Interfaces.RadPort portRad
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a portConv
equation
  connect(portConvRadComb.rad, portRad);
  connect(portConvRadComb.conv, portConv);
end ConvRadToCombPort;


Input and output

within AixLib.Utilities;
package IO "Input and output"
  extends Modelica.Icons.Package;
end IO;


Model for writing results to a format that is readable by the model CombiTimeTable. This model samples the model inputs u and saves them to a .csv file,
which can be read by a

Modelica.Blocks.Sources.CombiTimeTable.
The
Modelica.Blocks.Sources.CombiTimeTable
must then have tableName=\"csv\", as illustrated in the example

AixLib.Utilities.IO.Files.Examples.CSVReader.

within AixLib.Utilities.IO.Files;
model CombiTimeTableWriter
  "Model for writing results to a format that is readable by the model CombiTimeTable"
  extends AixLib.Utilities.IO.Files.BaseClasses.FileWriter(
    final delimiter="\t",
    final isCombiTimeTable=true);

initial algorithm
  if writeHeader then
    str :="# time" + delimiter;
    for i in 1:nin-1 loop
      str :=str + headerNames[i] + delimiter;
      if mod(i+1,10)==0 then // write out buffer every 10 entries to avoid overflow
        writeLine(filWri, str, 1);
        str:="";
      end if;
    end for;
    str :=str + headerNames[nin] + "\n";
    writeLine(filWri, str, 1);
  end if;
end CombiTimeTableWriter;


Model for writing results to a .csv file. This model samples the model inputs u and saves them to a .csv file,
which can be read using e.g. Excel or Python.

within AixLib.Utilities.IO.Files;
model CSVWriter
  "Model for writing results to a .csv file"
  extends AixLib.Utilities.IO.Files.BaseClasses.FileWriter(
    final isCombiTimeTable=false);

initial algorithm
  if writeHeader then
    str := str + "time" + delimiter;
    for i in 1:nin-1 loop
      str := str + headerNames[i] + delimiter;
      if mod(i+1,10)==0 then // write out buffer every 10 entries to avoid overflow
        writeLine(filWri, str, 1);
        str:="";
      end if;
    end for;
    str := str + headerNames[nin] + "\n";
    writeLine(filWri, str, 1);
  end if;
end CSVWriter;


Model for writing results to a json file. This model samples the model inputs u and saves them to a json file.

within AixLib.Utilities.IO.Files;
model JSONWriter "Model for writing results to a json file"
  extends Modelica.Blocks.Icons.DiscreteBlock;
  parameter Integer nin
    "Number of inputs"
  parameter String fileName = getInstanceName() + ".json"
    "File name, including extension";
  parameter String[nin] varKeys = {"key" + String(i) for i in 1:nin}
    "Key names, indices by default";
  parameter AixLib.Utilities.IO.Files.BaseClasses.OutputTime outputTime=
    AixLib.Utilities.IO.Files.BaseClasses.OutputTime.Terminal
    "Time when results are written to file"
  parameter Modelica.Units.SI.Time customTime=0
    "Custom time when results are stored, used if outputTime=Custom only"

  Modelica.Blocks.Interfaces.RealVectorInput[nin] u "Variables that are saved"
protected
  parameter String insNam = getInstanceName() "Instance name";
  AixLib.Utilities.IO.Files.BaseClasses.JSONWriterObject jsonWri=
      AixLib.Utilities.IO.Files.BaseClasses.JSONWriterObject(
        insNam,
        fileName,
        outputTime==AixLib.Utilities.IO.Files.BaseClasses.OutputTime.Terminal,
        varKeys)
    "File writer object";
equation
  if outputTime==AixLib.Utilities.IO.Files.BaseClasses.OutputTime.Terminal then
    AixLib.Utilities.IO.Files.BaseClasses.cacheVals(jsonWri, u);
  end if;

  if outputTime==AixLib.Utilities.IO.Files.BaseClasses.OutputTime.Initial then
    when initial() then
      AixLib.Utilities.IO.Files.BaseClasses.writeJSON(jsonWri, u);
    end when;
  end if;

  if outputTime==AixLib.Utilities.IO.Files.BaseClasses.OutputTime.Custom then
    when time>=customTime then
      AixLib.Utilities.IO.Files.BaseClasses.writeJSON(jsonWri, u);
    end when;
  end if;
end JSONWriter;


Reports package

within AixLib.Utilities.IO;
package Files "Reports package"
  extends Modelica.Icons.Package;
end Files;


Weekly schedule. This model interprets a schedule file and performs a weekly, cyclic extrapolation on the source data.
An example for a schedule entry is

within AixLib.Utilities.IO.Files;
model WeeklySchedule "Weekly schedule"
  extends Modelica.Blocks.Icons.DiscreteBlock;
  parameter Integer[:] columns = {2}
    "Columns of the schedule to be produced at the output y. First column is time, hence value must be 2 or larger";
  parameter Boolean tableOnFile=false
    "= true, if table is defined on file; false if defined through parameter data"
  parameter String fileName = ""
    "Filename"
  parameter String data = "double tab1(3,2)
# For week-day, output 1 between 7:00 and 19:00, and 0 otherwise
mon,tue,wed,thu,fri:7:00:00  1
mon,tue,wed,thu,fri:19:00:00  0
# For week-end, output always 0. Note that this line is redundant in this example.
sat,sun:0:00:00 0"
    "String data with weekly schedule"
  parameter Modelica.Units.SI.Time t_offset=0
    "Timestamp that corresponds to midnight from Sunday to Monday";

  Modelica.Blocks.Interfaces.RealOutput[n_columns] y=
    {getCalendarValue(cal, iCol-1, time) for iCol in columns} "Schedule values"

protected
  AixLib.Utilities.IO.Files.BaseClasses.WeeklyScheduleObject cal=
      AixLib.Utilities.IO.Files.BaseClasses.WeeklyScheduleObject(tableOnFile, sourceName, t_offset, data)
    "Schedule object";

  final parameter Integer n_columns = size(columns,1) "Number of columns";
  parameter String sourceName = if tableOnFile then fileName else getInstanceName() +".data";

  pure function getCalendarValue
    "Returns the interpolated (zero order hold) value"
    extends Modelica.Icons.Function;
    input AixLib.Utilities.IO.Files.BaseClasses.WeeklyScheduleObject ID "Pointer to file writer object";
    input Integer iCol "Column index";
    input Real timeIn "Time for look-up";
    output Real y "Schedule value";
    external "C" y=getScheduleValue(ID, iCol, timeIn)
  end getCalendarValue;
end WeeklySchedule;


Partial model for writing results to a .csv file. Base class for a file writer.
See extending classes.

within AixLib.Utilities.IO.Files.BaseClasses;
model FileWriter "Partial model for writing results to a .csv file"
  extends Modelica.Blocks.Icons.DiscreteBlock;

  parameter Integer nin
    "Number of inputs"
  parameter String fileName = getInstanceName() + ".csv"
    "File name, including extension";
  parameter Modelica.Units.SI.Time samplePeriod
    "Sample period: equidistant interval for which the inputs are saved";
  parameter String delimiter = "\t"
    "Delimiter for csv file"
  parameter Boolean writeHeader = true
    "=true, to write header with variable names, otherwise no header will be written"
  parameter String[nin] headerNames = {"col"+String(i) for i in 1:nin}
    "Header names, indices by default"
  parameter Integer significantDigits(min=1,max=15) = 6
    "Number of significant digits that are used for converting inputs into string format"

  Modelica.Blocks.Interfaces.RealVectorInput[nin] u "Variables that are saved"

protected
  parameter Boolean isCombiTimeTable = false
    "=true, if CombiTimeTable header should be prepended upon destruction"
  parameter Modelica.Units.SI.Time t0(fixed=false) "First sample time instant";
  parameter String insNam = getInstanceName() "Instance name";
  AixLib.Utilities.IO.Files.BaseClasses.FileWriterObject filWri=
      AixLib.Utilities.IO.Files.BaseClasses.FileWriterObject(
        insNam,
        fileName,
        nin+1,
        isCombiTimeTable)
    "File writer object";

  discrete String str "Intermediate variable for constructing a single line";
  output Boolean sampleTrigger "True, if sample time instant";

  function writeLine
    "Prepend a string to an existing text file"
    extends Modelica.Icons.Function;
    input AixLib.Utilities.IO.Files.BaseClasses.FileWriterObject id "ID of the file writer";
    input String string "Written string";
    input Integer isMetaData "=1, if line should not be included for row count of combiTimeTable";
    external"C" writeLine(id, string, isMetaData)
  end writeLine;

initial equation
  t0 = time;

equation
  sampleTrigger = sample(t0, samplePeriod);

algorithm
  when sampleTrigger then
    str :=String(time,significantDigits=significantDigits) + delimiter;
    for i in 1:nin-1 loop
      str :=str + String(u[i],significantDigits=significantDigits) + delimiter;
      if mod(i+1,10)==0 then // write out buffer every 10 entries to avoid overflow
        writeLine(filWri, str, 1); // not adding this one to row count
        str:="";
      end if;
    end for;
    str :=str + String(u[nin],significantDigits=significantDigits) + "\n";
    writeLine(filWri, str, 0);
  end when;
end FileWriter;


within AixLib.Utilities.IO.Files;
package BaseClasses "Package with base classes for AixLib.Utilities.IO.Files"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Reader for csv files generated by CSVWriter. This model demonstrates how a CombiTimeTable can be used
to read a text file that contains a table. The text file is stored in
AixLib//Resources/Data/Utilities/IO/Files/Examples/CSVReader/Data.txt.
It has the format of a file that can be generated by

AixLib.Utilities.IO.Files.Examples.CSVWriter.

within AixLib.Utilities.IO.Files.Examples;
model CSVReader "Reader for csv files generated by CSVWriter"
  extends AixLib.Utilities.IO.Files.Examples.BaseClasses.PartialCSV;
  Modelica.Blocks.Sources.CombiTimeTable combiTimeTable(
    tableOnFile=true,
    fileName=Modelica.Utilities.Files.loadResource("modelica://AixLib//Resources/Data/Utilities/IO/Files/Examples/CSVReader/Data.txt"),
    columns={2,3},
    tableName="tab") "Reader for test.csv"
end CSVReader;


Example of csv writer use. This model demonstrates the use of the csv file writer.

within AixLib.Utilities.IO.Files.Examples;
model CSVWriter "Example of csv writer use"
  extends AixLib.Utilities.IO.Files.Examples.BaseClasses.PartialCSV;
  CombiTimeTableWriter combiTimeTableWriter(
    nin=2,
    samplePeriod=0.3,
    fileName="test.csv",
    significantDigits=10)
    "Model that writes two inputs to csv file in a format that can be read by a combiTimeTable"
  AixLib.Utilities.IO.Files.CSVWriter csvWriter(
    writeHeader=false,
    nin=2,
    samplePeriod=0.3)
    "Duplicate to test for conflicts when instantiating multiple file writers"

equation
  connect(cos.y, combiTimeTableWriter.u[1])
  connect(step.y, combiTimeTableWriter.u[2])
  connect(csvWriter.u[1], cos.y)
  connect(csvWriter.u[2], step.y)
end CSVWriter;


Example use of the JSON writer. This model generates four json files,
using a single or multiple inputs and at different points in time.

within AixLib.Utilities.IO.Files.Examples;
model JSONWriter "Example use of the JSON writer"
  extends Modelica.Icons.Example;
  AixLib.Utilities.IO.Files.JSONWriter jsonWriterInitial(
    nin=3,
    fileName="InitialOutputs.json",
    outputTime=AixLib.Utilities.IO.Files.BaseClasses.OutputTime.Initial)
    "Outputs at initial time"
  AixLib.Utilities.IO.Files.JSONWriter jsonWriterCustom(
    nin=3,
    outputTime=AixLib.Utilities.IO.Files.BaseClasses.OutputTime.Custom,
    customTime=0.5,
    fileName="CustomOutputs.json",
    varKeys={"Output1","Key2","Name3"}) "Outputs at custom time"
  AixLib.Utilities.IO.Files.JSONWriter jsonWriterTerminal(
    nin=3,
    outputTime=AixLib.Utilities.IO.Files.BaseClasses.OutputTime.Terminal,
    fileName="TerminalOutputs.json") "Outputs at terminal time"
  Modelica.Blocks.Sources.Ramp ramp(
    height=1,
    duration=1,
    offset=1) "Ramp signal"
  Modelica.Blocks.Sources.Constant const(k=2) "Constant signal"
  Modelica.Blocks.Sources.Cosine cosine(amplitude=1, f=12) "Cosine signal"
  AixLib.Utilities.IO.Files.JSONWriter jsonWriterOneVar(nin=1, fileName="TerminalOutput.json")
    "Single variable output"
equation
  connect(ramp.y, jsonWriterInitial.u[1])
  connect(const.y, jsonWriterInitial.u[2])
  connect(cosine.y, jsonWriterInitial.u[3])
  connect(ramp.y, jsonWriterCustom.u[1])
  connect(ramp.y, jsonWriterTerminal.u[1])
  connect(const.y, jsonWriterCustom.u[2])
  connect(const.y, jsonWriterTerminal.u[2])
  connect(cosine.y, jsonWriterCustom.u[3])
  connect(cosine.y, jsonWriterTerminal.u[3])
  connect(const.y, jsonWriterOneVar.u[1])
end JSONWriter;


Examples package

within AixLib.Utilities.IO.Files;
package Examples "Examples package"
extends Modelica.Icons.ExamplesPackage;
end Examples;


Weekly schedule example. Example and consistency test for a weekly schedule.

within AixLib.Utilities.IO.Files.Examples;
model WeeklySchedule "Weekly schedule example"
  extends Modelica.Icons.Example;
  parameter String data = "#test:
mon:0:0:10          -  3   1  -
tue,thu:20:30:59  123  -  45  -
wed                12  1   4  -" "Contents of schedule.txt";
  AixLib.Utilities.IO.Files.WeeklySchedule weeSchFil(
    columns={2,3,4,5},
    tableOnFile=true,
    fileName=Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/Data/schedule.txt"),
    t_offset=1e6) "Weekly schedule example using file data source"

  AixLib.Utilities.IO.Files.WeeklySchedule weeSchStri(
    columns={2,3,4,5},
    data=data,
    t_offset=1e6) "Weekly schedule example using parameter data source"
  Diagnostics.AssertEquality assEqu[4](
    each startTime=-10000,
    each threShold=Modelica.Constants.small)
    "Trigger an assertion if the outputs differ"
equation
  connect(weeSchFil.y, assEqu.u1)
  connect(weeSchStri.y, assEqu.u2)
end WeeklySchedule;


Weekly schedule example that outputs 1 from 7:00 to 19:00 on week-days, and 0 otherwise. Example of a weekly schedule that outputs 1 from 7:00 to 19:00 on week-days, and 0 otherwise

within AixLib.Utilities.IO.Files.Examples;
model WeeklySchedule7to19
  "Weekly schedule example that outputs 1 from 7:00 to 19:00 on week-days, and 0 otherwise"
  extends Modelica.Icons.Example;

  AixLib.Utilities.IO.Files.WeeklySchedule sch
end WeeklySchedule7to19;


within AixLib.Utilities.IO.Files.Examples;
package BaseClasses "Package with base classes for AixLib.Utilities.IO.Files.Examples"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Base model for CSV reader and writer example. Partial model that contains a step function and cosine signal.

within AixLib.Utilities.IO.Files.Examples.BaseClasses;
model PartialCSV "Base model for CSV reader and writer example"
  extends Modelica.Icons.Example;
  Modelica.Blocks.Sources.Cosine cos(f=0.345) "Cosine"
  Modelica.Blocks.Sources.Step step(startTime=5) "Step function"
end PartialCSV;


within AixLib.Utilities.IO.Files;
package Validation "Collection of models that validate the models that access files"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Weekly schedule example. Example for a weekly schedule that reads the schedule data from a file.
There are two file readers, one reading a file with Windows line endings and the other with Linux line endings.

within AixLib.Utilities.IO.Files.Validation;
model WeeklyScheduleWindowsLineEndings "Weekly schedule example"
  extends Modelica.Icons.Example;
  parameter String data = "double tab1(3,5) #test:
mon:0:0:10          -  3   1  -
tue,thu:20:30:59  123  -  45  -
wed                12  1   4  -" "Contents of schedule.txt";
  AixLib.Utilities.IO.Files.WeeklySchedule weeSchLin(
    columns={2,3,4,5},
    tableOnFile=true,
    fileName=Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/Data/schedule.txt"),
    t_offset=1e6) "Weekly schedule example using file data source"

  AixLib.Utilities.IO.Files.WeeklySchedule weeSchWin(
    columns={2,3,4,5},
    tableOnFile=true,
    fileName=Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/Data/scheduleWindows.txt"),
    t_offset=1e6) "Weekly schedule example using parameter data source"
  Diagnostics.AssertEquality assEqu[4](
    each startTime=-10000,
    each threShold=Modelica.Constants.small)
    "Trigger an assertion if the outputs differ"
equation
  connect(weeSchLin.y, assEqu.u1)
  connect(weeSchWin.y, assEqu.u2)
end WeeklyScheduleWindowsLineEndings;


Block that allows a signal to overwritten by an FMU input. This block enables the overwriting of a control signal by an external program,
as well as reading of its meta-data, without the need to explicitly propogate
the external input or activation switch to a top-level model.

within AixLib.Utilities.IO.SignalExchange;
block Overwrite "Block that allows a signal to overwritten by an FMU input"
  extends Modelica.Blocks.Interfaces.SISO;

  parameter String description "Description of the signal being overwritten";

  final parameter Boolean boptestOverwrite = true
    "Parameter that is used by tools to search for overwrite block in models";

  Modelica.Blocks.Logical.Switch swi
    "Switch between external signal and direct feedthrough signal"
  Modelica.Blocks.Sources.RealExpression uExt "External input signal"
  Modelica.Blocks.Sources.BooleanExpression activate
    "Block to activate use of external signal"

equation
  connect(activate.y, swi.u2)
  connect(swi.u3, u)
  connect(uExt.y, swi.u1)
  connect(swi.y, y)
end Overwrite;


External Signal Exchange Package

within AixLib.Utilities.IO;
package SignalExchange "External Signal Exchange Package"
  extends Modelica.Icons.Package;
end SignalExchange;


Block that allows a signal to be read as an FMU output. This block enables the reading of a signal and its meta-data by an external
program without the need to explicitly propogate the signal to a top-level model.

within AixLib.Utilities.IO.SignalExchange;
model Read "Block that allows a signal to be read as an FMU output"
  extends Modelica.Blocks.Routing.RealPassThrough;

  parameter String description "Description of the signal being read";

  parameter SignalTypes.SignalsForKPIs KPIs = SignalTypes.SignalsForKPIs.None
    "Tag with the type of signal for the calculation of the KPIs";

  parameter String zone = "1" if (
    KPIs==AixLib.Utilities.IO.SignalExchange.SignalTypes.SignalsForKPIs.AirZoneTemperature or
    KPIs==AixLib.Utilities.IO.SignalExchange.SignalTypes.SignalsForKPIs.RadiativeZoneTemperature or
    KPIs==AixLib.Utilities.IO.SignalExchange.SignalTypes.SignalsForKPIs.OperativeZoneTemperature or
    KPIs==AixLib.Utilities.IO.SignalExchange.SignalTypes.SignalsForKPIs.RelativeHumidity or
    KPIs==AixLib.Utilities.IO.SignalExchange.SignalTypes.SignalsForKPIs.CO2Concentration)
    "Zone designation, required if KPIs is AirZoneTemperature,
    RadiativeZoneTemperature, OperativeZoneTemperature, RelativeHumidity,
    or CO2Concentration"

  final parameter Boolean boptestRead = true
    "Parameter that is used by tools to search for read block in models";
end Read;


Implements typical weather measurements with signal exchange blocks. This block enables the reading of weather measurements and their meta-data by an external
program without the need to explicitly propagate the signal to a top-level model.
This block utilizes a number of pre-configured instances of

AixLib.Utilities.IO.SignalExchange.Read

within AixLib.Utilities.IO.SignalExchange;
model WeatherStation
  "Implements typical weather measurements with signal exchange blocks"
  AixLib.BoundaryConditions.WeatherData.Bus weaBus "Weather data"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaTDryBul(
    description="Outside drybulb temperature measurement",
    y(final unit="K"))
    "Outside drybulb temperature measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaRelHum(
    description="Outside relative humidity measurement",
    y(final unit="1"))
    "Outside relative humidity measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaWinSpe(
    description="Wind speed measurement",
    y(final unit="m/s"))
    "Wind speed measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaWinDir(
    description="Wind direction measurement",
    y(final unit="rad"))
    "Wind direction measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaHGloHor(
    description="Global horizontal solar irradiation measurement",
    y(final unit="W/m2"))
    "Global horizontal solar irradiation measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaNTot(
    description="Sky cover measurement",
    y(final unit="1"))
    "Sky cover measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaPAtm(
    description="Atmospheric pressure measurement",
    y(final unit="Pa"))
    "Atmospheric pressure measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaHDifHor(
    description="Horizontal diffuse solar radiation measurement",
    y(final unit="W/m2"))
    "Horizontal diffuse solar radiation measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaCeiHei(
    description="Cloud cover ceiling height measurement",
    y(final unit="m"))
    "Cloud cover ceiling height measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaTWetBul(
    description="Wet bulb temperature measurement",
    y(final unit="K"))
    "Wet bulb temperature measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaTDewPoi(
    description="Dew point temperature measurement",
    y(final unit="K"))
    "Dew point temperature measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaTBlaSky(
    description="Black-body sky temperature measurement",
    y(final unit="K"))
    "Black-body sky temperature measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaHHorIR(
    description="Horizontal infrared irradiation measurement",
    y(final unit="W/m2"))
    "Horizontal infrared irradiation measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaHDirNor(
    description="Direct normal radiation measurement",
    y(final unit="W/m2"))
    "Direct normal radiation measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaCloTim(
    description="Day number with units of seconds",
    y(final unit="s"))
    "Day number with units of seconds"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaSolAlt(
    description="Solar altitude angle measurement",
    y(final unit="rad"))
    "Solar altitude angle measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaNOpa(
    description="Opaque sky cover measurement",
    y(final unit="1"))
    "Opaque sky cover measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaLat(
    description="Latitude of the location",
    y(final unit="rad"))
    "Latitude of the location"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaLon(
    description="Longitude of the location",
    y(final unit="rad"))
    "Longitude of the location"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaSolDec(
    description="Solar declination angle measurement",
    y(final unit="rad"))
    "Solar declination angle measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaSolHouAng(
    description="Solar hour angle measurement",
    y(final unit="rad"))
    "Solar hour angle measurement"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaSolTim(
    description="Solar time",
    y(final unit="s"))
    "Solar time"
  AixLib.Utilities.IO.SignalExchange.Read reaWeaSolZen(
    description="Solar zenith angle measurement",
    y(final unit="rad"))
    "Solar zenith angle measurement"
equation
  connect(weaBus.TDryBul, reaWeaTDryBul.u)
  connect(weaBus.relHum, reaWeaRelHum.u)
  connect(weaBus.winSpe, reaWeaWinSpe.u)
  connect(weaBus.winDir, reaWeaWinDir.u)
  connect(weaBus.HGloHor, reaWeaHGloHor.u)
  connect(weaBus.nTot, reaWeaNTot.u)
  connect(weaBus.pAtm, reaWeaPAtm.u)
  connect(weaBus.HDifHor, reaWeaHDifHor.u)
  connect(weaBus.HDirNor, reaWeaHDirNor.u)
  connect(weaBus.HHorIR, reaWeaHHorIR.u)
  connect(weaBus.TBlaSky, reaWeaTBlaSky.u)
  connect(weaBus.TDewPoi, reaWeaTDewPoi.u)
  connect(weaBus.TWetBul, reaWeaTWetBul.u)
  connect(weaBus.ceiHei, reaWeaCeiHei.u)
  connect(weaBus.cloTim, reaWeaCloTim.u)
  connect(weaBus.lat, reaWeaLat.u)
  connect(weaBus.lon, reaWeaLon.u)
  connect(weaBus.nOpa, reaWeaNOpa.u)
  connect(weaBus.solAlt, reaWeaSolAlt.u)
  connect(weaBus.solDec, reaWeaSolDec.u)
  connect(weaBus.solHouAng, reaWeaSolHouAng.u)
  connect(weaBus.solTim, reaWeaSolTim.u)
  connect(weaBus.solZen, reaWeaSolZen.u)
end WeatherStation;


Uses signal exchange block for a first order dynamic system. This example uses the signal exchange blocks in an original model,

AixLib.Utilities.IO.SignalExchange.Examples.BaseClasses.OriginalModel
along with a corresponding model that would result if the original model were
compiled with the BOPTEST parser,
AixLib.Utilities.IO.SignalExchange.Examples.BaseClasses.ExportedModel
to demonstrate the overwriting of either setpoint or actuator control signals
and reading of signals.

within AixLib.Utilities.IO.SignalExchange.Examples;
model FirstOrder
  "Uses signal exchange block for a first order dynamic system"
  extends Modelica.Icons.Example;

  BaseClasses.ExportedModel expMod
  Modelica.Blocks.Sources.Constant uSet(k=2)
  Modelica.Blocks.Sources.BooleanStep actSet(startTime=50)
  Modelica.Blocks.Sources.BooleanStep actAct(startTime=100)
  Modelica.Blocks.Sources.Constant uAct(k=3)

equation
  connect(uSet.y, expMod.oveWriSet_u)
  connect(actSet.y, expMod.oveWriSet_activate)
  connect(actAct.y, expMod.oveWriAct_activate)
  connect(uAct.y, expMod.oveWriAct_u)
end FirstOrder;


within AixLib.Utilities.IO.SignalExchange;
package Examples "This package contains examples for the signal exchange block"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Example use of WeatherStation. This example uses the weather station signal exchange block,

AixLib.Utilities.IO.SignalExchange.WeatherStation
along with a TMY weather data reader.

within AixLib.Utilities.IO.SignalExchange.Examples;
model WeatherStation "Example use of WeatherStation"
  extends Modelica.Icons.Example;
  AixLib.Utilities.IO.SignalExchange.WeatherStation weaSta "Weather station"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data reader"
equation

  connect(weaDat.weaBus, weaSta.weaBus)
end WeatherStation;


Model to be exported as an FMU. This is an example of a model that would be compiled in BOPTEST if the
original model were using the signal exchange blocks. Note that inputs
are added to activate and set values of control signals that can be overwritten
and outputs are added to read signals from the read blocks.

within AixLib.Utilities.IO.SignalExchange.Examples.BaseClasses;
model ExportedModel "Model to be exported as an FMU"
  extends Modelica.Blocks.Icons.Block;

  Modelica.Blocks.Interfaces.RealInput oveWriSet_u "Signal for overwrite block for set point"
  Modelica.Blocks.Interfaces.BooleanInput oveWriSet_activate "Activation for overwrite block for set point"
  Modelica.Blocks.Interfaces.RealInput oveWriAct_u "Signal for overwrite block for actuator signal"
  Modelica.Blocks.Interfaces.BooleanInput oveWriAct_activate "Activation for overwrite block for actuator signal"

  Modelica.Blocks.Interfaces.RealOutput rea = mod.rea.y
    "Measured state variable"

  BaseClasses.OriginalModel mod(
      oveWriSet(
        uExt(
          y=oveWriSet_u),
        activate(
          y=oveWriSet_activate)),
      oveWriAct(
        uExt(
          y=oveWriAct_u),
        activate(
          y=oveWriAct_activate))) "Original model"
end ExportedModel;


Original model. This is a model of a first order dynamic system with feedback control.
Signal exchange blocks are implemented to overwrite either the setpoint or
actuator control signals as well as read the output of the first order
system.

within AixLib.Utilities.IO.SignalExchange.Examples.BaseClasses;
model OriginalModel "Original model"
  extends Modelica.Blocks.Icons.Block;

  Modelica.Blocks.Sources.Constant TSet(k=1) "Set point"

  Modelica.Blocks.Continuous.LimPID conPI(
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    yMax=10) "Controller"

  Modelica.Blocks.Continuous.FirstOrder firOrd(
    T=1,
    initType=Modelica.Blocks.Types.Init.InitialOutput)
    "First order element"

  Overwrite oveWriSet(
    description="First order system control setpoint",
    u(min=-10,
      max=10,
      unit="1")) "Overwrite block for setpoint"

  Overwrite oveWriAct(description="First order system input",
    u(min=-10,
      max=10,
      unit="1")) "Overwrite block for actuator signal"

  Read rea(
    description="First order system output",
    KPIs=AixLib.Utilities.IO.SignalExchange.SignalTypes.SignalsForKPIs.None)
    "Measured state variable"

equation
  connect(TSet.y, oveWriSet.u)
  connect(oveWriSet.y, conPI.u_s)
  connect(conPI.y, oveWriAct.u)
  connect(oveWriAct.y, firOrd.u)
  connect(firOrd.y, rea.u)
  connect(rea.y, conPI.u_m)
end OriginalModel;


within AixLib.Utilities.IO.SignalExchange.Examples;
package BaseClasses "Contains base classes for signal exchange examples"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Package with signal type definitions

within AixLib.Utilities.IO.SignalExchange;
package SignalTypes "Package with signal type definitions"
 extends Modelica.Icons.TypesPackage;
end SignalTypes;


Transform Real to Boolean signal with Hysteresis. Altered for the use of the AixLib to enable dynamic upper and lower boundaries.. This block transforms a Real input signal into a
  Boolean output signal:

within AixLib.Utilities.Logical;
block DynamicHysteresis
  "Transform Real to Boolean signal with Hysteresis. Altered for the use of the AixLib to enable dynamic upper and lower boundaries."

  extends Modelica.Blocks.Icons.PartialBooleanBlock;
  parameter Boolean pre_y_start=false "Value of pre(y) at initial time";

  Modelica.Blocks.Interfaces.RealInput u
  Modelica.Blocks.Interfaces.BooleanOutput y

  Modelica.Blocks.Interfaces.RealInput uHigh "if y=false and u>=uHigh, switch to y=true"
  Modelica.Blocks.Interfaces.RealInput uLow
    "if y=true and u<=uLow, switch to y=false"
initial equation
  pre(y) = pre_y_start;
equation
  assert(uHigh > uLow,"Hysteresis limits wrong (uHigh = "+String(uHigh)+" <= uLow = "+String(uLow)+")");
  y = not pre(y) and u > uHigh or pre(y) and u >= uLow;
end DynamicHysteresis;


Logicals like switches

within AixLib.Utilities;
package Logical "Logicals like switches"
  extends Modelica.Icons.Package;
end Logical;


Smooth switch between two Real signals.

within AixLib.Utilities.Logical;
block SmoothSwitch "Smooth switch between two Real signals"
  extends Modelica.Blocks.Icons.PartialBooleanBlock;
  Modelica.Blocks.Interfaces.RealInput u1
    "Connector of first Real input signal"
  Modelica.Blocks.Interfaces.BooleanInput u2
    "Connector of Boolean input signal"
  Modelica.Blocks.Interfaces.RealInput u3
    "Connector of second Real input signal"
  Modelica.Blocks.Interfaces.RealOutput y "Connector of Real output signal"
equation
  y = smooth(1, if u2 then u1 else u3);
end SmoothSwitch;


Lumped element for mass convection (m_flow = Gc*dX). This is a model of linear mass convection, e.g., the mass transfer
  between a plate and the surrounding air. It may be used for
  complicated solid geometries and fluid flow over the solid by
  determining the convective mass transfer coefficient Gc by
  measurements. The basic constitutive equation for convection is

within AixLib.Utilities.MassTransfer;
model Convection
  "Lumped element for mass convection (m_flow = Gc*dX)"
  Modelica.Units.SI.MassFlowRate m_flow "Mass flow rate from solid -> fluid";
  Modelica.Units.SI.PartialPressure dp "= solid.p - fluid.p";
  Modelica.Blocks.Interfaces.RealInput Gc(unit="kg/(s.Pa)")
    "Signal representing the convective mass transfer coefficient in [kg/s]"
  MassPort solid
  MassPort fluid
equation
  dp = solid.p - fluid.p;
  solid.m_flow = m_flow;
  fluid.m_flow = -m_flow;
  m_flow = Gc*dp;

  m_flow: Mass flow rate from
  connector 'solid' (e.g., a plate)

  to connector 'fluid' (e.g.,
  the surrounding air)

  Gc = G.signal[1] is an input signal to the component, since Gc is
  nearly never constant in practice. For example, Gc may be a function
  of the speed of a cooling fan. For simple situations, Gc may be
  calculated according to

  Gc = A*h

  A: Convection area (e.g.,
  perimeter*length of a box)

  h: mass transfer
  coefficient

  where the mass transfer coefficient h is calculated from properties
  of the fluid flowing over the solid.

", revisions="

November 20, 2019, by Martin Kremer:

    First Implementation.

"),
       Diagram(coordinateSystem(preserveAspectRatio=true, extent={{-100,-100},
            {100,100}}), graphics={
        Rectangle(
          extent={{-90,80},{-60,-80}},
          fillColor={192,192,192},
          fillPattern=FillPattern.Backward),
        Line(points={{100,0},{100,0}}, color={0,127,255}),
        Line(points={{100,0},{100,0}}, color={0,127,255}),
        Line(points={{100,0},{100,0}}, color={0,127,255}),
        Text(
          extent={{-40,40},{80,20}},
          lineColor={0,140,72},
          textString="m_flow"),
        Line(points={{-60,20},{76,20}}, color={0,140,72}),
        Line(points={{-60,-20},{76,-20}}, color={0,140,72}),
        Line(points={{-34,80},{-34,-80}}, color={0,127,255}),
        Line(points={{6,80},{6,-80}}, color={0,127,255}),
        Line(points={{40,80},{40,-80}}, color={0,127,255}),
        Line(points={{76,80},{76,-80}}, color={0,127,255}),
        Line(points={{-34,-80},{-44,-60}}, color={0,127,255}),
        Line(points={{-34,-80},{-24,-60}}, color={0,127,255}),
        Line(points={{6,-80},{-4,-60}}, color={0,127,255}),
        Line(points={{6,-80},{16,-60}}, color={0,127,255}),
        Line(points={{40,-80},{30,-60}}, color={0,127,255}),
        Line(points={{40,-80},{50,-60}}, color={0,127,255}),
        Line(points={{76,-80},{66,-60}}, color={0,127,255}),
        Line(points={{76,-80},{86,-60}}, color={0,127,255}),
        Line(points={{56,-30},{76,-20}}, color={0,140,72}),
        Line(points={{56,-10},{76,-20}}, color={0,140,72}),
        Line(points={{56,10},{76,20}}, color={0,140,72}),
        Line(points={{56,30},{76,20}}, color={0,140,72})}));
end Convection;


Lumped element transporting mass without storing it. This is a model for transport of mass without storing it; It may be
  used for complicated geometries where the mass diffusion Gd is
  determined by measurements and is assumed to be constant over the
  range of operations. If the component consists mainly of one type of
  material and a regular geometry, it may be calculated, e.g., with one
  of the following equations:

within AixLib.Utilities.MassTransfer;
model MassDiffusion
  "Lumped element transporting mass without storing it"

  Modelica.Units.SI.MassFlowRate m_flow "Mass flow rate from solid -> fluid";
  Modelica.Units.SI.PartialPressure dp "= solid.p - fluid.p";
  Modelica.Blocks.Interfaces.RealInput Gd(unit="m.m.m/(s.Pa)")
    "Signal representing the convective mass transfer coefficient in [m³/(s Pa)]"
  MassPort solid
  MassPort fluid
protected
  constant Modelica.Units.SI.Density rho=1.21 "density of moist air";
equation
  dp = solid.p - fluid.p;
  solid.m_flow = m_flow;
  fluid.m_flow = -m_flow;
  m_flow = -Gd*rho*dp;
end MassDiffusion;


Mass flow rate sensor. This model is capable of monitoring the mass flow rate flowing
  through this component. The sensed value of mass flow rate is the
  amount that passes through this sensor while keeping the partial
  pressure drop across the sensor zero. This is an ideal model so it
  does not absorb any mass and it has no direct effect on the mass
  transfer response of a system it is included in. The output signal is
  positive, if the mass flows from port_a to port_b.

within AixLib.Utilities.MassTransfer;
model MassFlowSensor "Mass flow rate sensor"
  extends Modelica.Icons.RoundSensor;
  Modelica.Blocks.Interfaces.RealOutput m_flow(unit="kg/s")
    "Mass flow from port_a to port_b as output signal"
  MassPort port_a
  MassPort port_b
equation
  port_a.p = port_b.p;
  port_a.m_flow + port_b.m_flow = 0;
  m_flow = port_a.m_flow;
end MassFlowSensor;


package with mass transfer models

within AixLib.Utilities;
package MassTransfer "package with mass transfer models"
end MassTransfer;


Variable partial pressure boundary condition in Pa. This model represents a variable partial pressure boundary condition.
  The partial pressure in [Pa] is given as input signal
  p to the model. The effect is that an instance of
  this model acts as an infinite reservoir able to absorb or generate
  as much mass as required to keep the partial pressure at the
  specified value.

within AixLib.Utilities.MassTransfer;
model PrescribedPartialPressure
  "Variable partial pressure boundary condition in Pa"

  MassPort port
  Modelica.Blocks.Interfaces.RealInput p(unit="Pa")
equation
  port.p = p;
end PrescribedPartialPressure;


Average of a vector. This block outputs the average of the vector.

within AixLib.Utilities.Math;
block Average "Average of a vector"
  extends Modelica.Blocks.Interfaces.MISO;
equation
 y = AixLib.Utilities.Math.Functions.average(u=u, nin=nin);
end Average;


Bessel function of the first kind of order 0, J0. This block computes the bessel function of the first kind of order 0, J0.

within AixLib.Utilities.Math;
block BesselJ0 "Bessel function of the first kind of order 0, J0"
  extends Modelica.Blocks.Interfaces.SISO;
equation
  y = AixLib.Utilities.Math.Functions.besselJ0(x=u);
end BesselJ0;


Bessel function of the first kind of order 1, J1. This block computes the bessel function of the first kind of order 1, J1.

within AixLib.Utilities.Math;
block BesselJ1 "Bessel function of the first kind of order 1, J1"
  extends Modelica.Blocks.Interfaces.SISO;
equation
  y = AixLib.Utilities.Math.Functions.besselJ1(x=u);
end BesselJ1;


Bessel function of the second kind of order 0, Y0. This block computes the bessel function of the second kind of order 0, Y0.

within AixLib.Utilities.Math;
block BesselY0 "Bessel function of the second kind of order 0, Y0"
  extends Modelica.Blocks.Interfaces.SISO;
equation
  y = AixLib.Utilities.Math.Functions.besselY0(x=u);
end BesselY0;


Bessel function of the second kind of order 1, Y1. This block computes the bessel function of the second kind of order 1, Y1.

within AixLib.Utilities.Math;
block BesselY1 "Bessel function of the second kind of order 1, Y1"
  extends Modelica.Blocks.Interfaces.SISO;
equation
  y = AixLib.Utilities.Math.Functions.besselY1(x=u);
end BesselY1;


Bicubic function. This block computes

within AixLib.Utilities.Math;
block Bicubic "Bicubic function"
  extends Modelica.Blocks.Interfaces.SI2SO;
 input Real a[10] "Coefficients";
equation
  y =  AixLib.Utilities.Math.Functions.bicubic(a=a, x1=u1, x2=u2);
end Bicubic;


Binomial function. This block computes the binomial coefficient \"n choose k\".

within AixLib.Utilities.Math;
block Binomial "Binomial function"
  extends Modelica.Blocks.Interfaces.IntegerSO;
  Modelica.Blocks.Interfaces.IntegerInput n "Size of set"
  Modelica.Blocks.Interfaces.IntegerInput k "Size of subsets"
equation
  y = AixLib.Utilities.Math.Functions.binomial(n=n, k=k);
end Binomial;


Biquadratic function. This block computes

within AixLib.Utilities.Math;
block Biquadratic "Biquadratic function"
  extends Modelica.Blocks.Interfaces.SI2SO;
  parameter Real a[6] "Coefficients";
equation
  y =  AixLib.Utilities.Math.Functions.biquadratic(a=a, x1=u1, x2=u2);
end Biquadratic;


Boolean signal replicator. This block replicates the boolean input signal to an array of nout identical output signals.

within AixLib.Utilities.Math;
block BooleanReplicator "Boolean signal replicator"
  extends Modelica.Blocks.Icons.BooleanBlock;
  parameter Integer nout=1 "Number of outputs";
  Modelica.Blocks.Interfaces.BooleanInput u "Connector of boolean input signal"
  Modelica.Blocks.Interfaces.BooleanOutput y[nout]
    "Connector of boolean output signals"
equation
  y = AixLib.Utilities.Math.Functions.booleanReplicator(u=u, nout=nout);
end BooleanReplicator;


Exponential integral function, E1. This block computes the exponential integral, E1.

within AixLib.Utilities.Math;
block ExponentialIntegralE1 "Exponential integral function, E1"
  extends Modelica.Blocks.Interfaces.SISO;
equation
  y = AixLib.Utilities.Math.Functions.exponentialIntegralE1(x=u);
end ExponentialIntegralE1;


Factorial function. This block computes the factorial of the integer input, <i>y=n!</i>.

within AixLib.Utilities.Math;
block Factorial "Factorial function"
  extends Modelica.Blocks.Interfaces.IntegerSO;
  Modelica.Blocks.Interfaces.IntegerInput u "Connector of integer input signal"
equation
  y = AixLib.Utilities.Math.Functions.factorial(n=u);
end Factorial;


Falling factorial function. This block computes the falling factorial, y = nḵ.

within AixLib.Utilities.Math;
block FallingFactorial "Falling factorial function"
  extends Modelica.Blocks.Interfaces.IntegerSO;
  Modelica.Blocks.Interfaces.IntegerInput n "Integer number"
  Modelica.Blocks.Interfaces.IntegerInput k "Falling factorial power"
equation
  y = AixLib.Utilities.Math.Functions.fallingFactorial(n=n, k=k);
end FallingFactorial;