Set temperature by the user.

within AixLib.Controls.HVACAgentBasedControl.Agents;
model RoomAgent
  extends BaseClasses.PartialAgent(
    name=10001,
    uDPSend_adapted(userBufferSize=100000, autoBufferSize=true),
    uDPReceive_adapted(userBufferSize=100000, autoBufferSize=true));
  parameter Real T_set = 273.15+20 "Set temperature by the user";
  parameter Integer broker = 10003 "Name of the corresponding broker-agent";
  parameter Real startTime = 0 "Time when the agent makes first request";
  parameter Real threshold = 2
    "Temperature threshold difference when agent gets active";
  parameter Real sampleTriggerTime = 60
    "Time difference between two calls for adjustment [s]";
  parameter Real P=50 "Proportional factor for load estimation";
  parameter Real Kd = 30000 "Derivative factor for load estimation";
  parameter Real G=1 "Gain for the load estimation";

  Modelica.Blocks.Interfaces.RealInput T "Room temperature"

  Modelica.Blocks.Math.Add add(k2=-1)
  Modelica.Blocks.Logical.GreaterThreshold T_too_high(threshold=threshold)
  Modelica.Blocks.Math.Add add1(k2=-1)
  Modelica.Blocks.Logical.GreaterThreshold T_too_low(threshold=threshold)
  Modelica.Blocks.Sources.SampleTrigger sampleTrigger(           startTime=
        startTime, period=sampleTriggerTime)
  Modelica.Blocks.Logical.Or or1

  Modelica.Blocks.Logical.And actionTrigger
  Modelica.StateGraph.InitialStep waiting(       nOut=2, nIn=3)
  Modelica.StateGraph.TransitionWithSignal newMessage
  Modelica.Blocks.Math.IntegerChange integerChange
  Modelica.StateGraph.TransitionWithSignal transitionWithSignal
  Modelica.StateGraph.Step composeRequest(nOut=1, nIn=3)
  Modelica.StateGraph.Transition requestNoted(enableTimer=true, waitTime=1)
  Modelica.StateGraph.StepWithSignal sendRequest(nOut=2, nIn=1)
  Modelica.StateGraph.TransitionWithSignal newMessage1 "confirmation"
  Modelica.StateGraph.Transition repeat(enableTimer=true, waitTime=
        100000000)
  Modelica.Blocks.Sources.BooleanExpression booleanExpression1(y=noEvent(
        getperformative.y[1] == 5))
  Modelica.StateGraph.Step state(nIn=1, nOut=2)
  Modelica.StateGraph.TransitionWithSignal rightMessage "confirmation"
  Modelica.StateGraph.Transition repeat1(enableTimer=true, waitTime=
        100000000000.0)
  Modelica.StateGraph.Step composeNotUnderstood(nIn=1, nOut=1)
  Modelica.StateGraph.Transition transition2(enableTimer=true, waitTime=1)
  Modelica.StateGraph.StepWithSignal sendNotUnderstood(nOut=1, nIn=1)
  Modelica.StateGraph.Transition transition4(enableTimer=true, waitTime=1)
  Modelica.Blocks.Logical.Or or2

protected
  Modelica.Blocks.Interfaces.RealOutput T_ref

public
  Modelica.StateGraph.Step composeConfirm(nOut=1, nIn=1)
  Modelica.StateGraph.StepWithSignal sendConfirm(nOut=1, nIn=1)
  Modelica.StateGraph.Transition confirmNoted(enableTimer=true, waitTime=1)
  Modelica.StateGraph.Transition transition1(enableTimer=true, waitTime=1)
  Modelica.Blocks.Logical.Or or3
  Modelica.StateGraph.Step waitForInform(        nIn=1, nOut=2)
  Modelica.StateGraph.TransitionWithSignal rightMessage1 "confirmation"
  Modelica.Blocks.Sources.BooleanExpression booleanExpression2(y=noEvent(
        getperformative.y[1] == 8))
  Modelica.Blocks.Continuous.Derivative derivative
  Modelica.StateGraph.Transition reset(enableTimer=true, waitTime=180)
algorithm
  when noEvent(waiting.active) then
      content.u[1] := 0;
      content.u[2] := 0;
  end when;

  when noEvent(composeRequest.active) then
      content.u[1] := G*(P*add1.y+Kd*derivative.y); //temporary function
      content.u[2] := 0;
      performative.u[1]:= 19;
      sender.u[1]:=name;
      receiver.u[1]:= broker;
      reply_to.u[1] := name;
      ontology.u[1] := 1;
      uDPSend_adapted.receiver := broker;
      messageID.u[1] := name*name + integer(time);
      Modelica.Utilities.Streams.print("RoomAgent "+ String(name)+ " requests " + String(content.u[1]) + " W of heat from Broker "+ String(broker)+".");
  end when;

  // Send out "not understood" message, if message has unknown performative
  when noEvent(composeNotUnderstood.active) then
    content.u[1] := 0;
    content.u[2] := 0;
    performative.u[1] := 11; //"not understood"
    sender.u[1] := name;
    receiver.u[1] := getsender.y[1];
    uDPSend_adapted.receiver :=  getsender.y[1];
    ontology.u[1] := getontology.y[1];
    messageID.u[1] := name*name + integer(time);
  end when;

  // Confirm the information by broker
  when noEvent(composeConfirm.active) then
    content.u[1] := get_content.y[1];
    content.u[2] := get_content.y[2];
    performative.u[1] := 5; //"confirm"
    receiver.u[1] := broker;
    reply_to.u[1] := name;
    ontology.u[1] := 1;
    uDPSend_adapted.receiver := broker;
    messageID.u[1] := name*name + integer(time);
    Modelica.Utilities.Streams.print("RoomAgent "+ String(name)+ " confirms the request of " + String(content.u[2]) + " W of heat " + "for a price of "+String(content.u[1])+".");
  end when;

equation
  T_ref = T_set;

  connect(T, add.u1)
  connect(add.u2, T_ref)
  connect(add.y, T_too_high.u)
  connect(add1.u2, add.u1)
  connect(add1.u1, T_ref)
  connect(T_too_low.u, add1.y)
  connect(T_too_low.y, or1.u2)

  connect(T_too_high.y, or1.u1)

  connect(T_ref, T_ref)
  connect(actionTrigger.u2, sampleTrigger.y)
  connect(integerChange.u, getMessageID.y[1])
  connect(transitionWithSignal.inPort, waiting.outPort[1])
  connect(composeRequest.inPort[1], transitionWithSignal.outPort)
  connect(requestNoted.inPort, composeRequest.outPort[1])
  connect(requestNoted.outPort, sendRequest.inPort[1])
  connect(newMessage1.inPort, sendRequest.outPort[1])
  connect(repeat.outPort, composeRequest.inPort[2])
  connect(repeat.inPort, sendRequest.outPort[2])
  connect(integerChange.y, newMessage1.condition)
  connect(state.inPort[1], newMessage1.outPort)
  connect(repeat1.outPort, composeRequest.inPort[3])

  connect(repeat1.inPort, state.outPort[2])
  connect(rightMessage.inPort, state.outPort[1])
  connect(booleanExpression1.y, rightMessage.condition)

  connect(newMessage.inPort, waiting.outPort[2])
  connect(newMessage.condition, newMessage1.condition)

  connect(composeNotUnderstood.inPort[1], newMessage.outPort)
  connect(composeNotUnderstood.outPort[1], transition2.inPort)
  connect(transition2.outPort, sendNotUnderstood.inPort[1])
  connect(sendNotUnderstood.outPort[1], transition4.inPort)
  connect(transition4.outPort, waiting.inPort[2])
  connect(actionTrigger.y, transitionWithSignal.condition)
  connect(sendRequest.active, or2.u1)
  connect(sendNotUnderstood.active, or2.u2)

  connect(confirmNoted.inPort, composeConfirm.outPort[1])
  connect(confirmNoted.outPort, sendConfirm.inPort[1])
  connect(sendConfirm.outPort[1], transition1.inPort)
  connect(transition1.outPort, waiting.inPort[1])
  connect(or3.u1, sendConfirm.active)
  connect(or2.y, or3.u2)

  connect(or3.y, uDPSend_adapted.trigger)
  connect(waitForInform.outPort[1], rightMessage1.inPort)
  connect(booleanExpression2.y, rightMessage1.condition)
  connect(rightMessage.outPort, waitForInform.inPort[1])
  connect(rightMessage1.outPort, composeConfirm.inPort[1])
  connect(derivative.u, add1.y)
  connect(or1.y, actionTrigger.u1)
  connect(waitForInform.outPort[2], reset.inPort)
  connect(reset.outPort, waiting.inPort[3])
end RoomAgent;


Name of the agent (five-digit number, eg. 10001).

within AixLib.Controls.HVACAgentBasedControl.BaseClasses;
partial model PartialAgent
  parameter Integer name "Name of the agent (five-digit number, eg. 10001)";
  parameter Boolean usePoke=false
    "Use Modelica internal communication for inbox update";
  parameter Real sampleRate=5
    "Sample time for inbox update (used if usePoke=false)";

  outer HVACAgentBasedControl.Agents.MessageNotification messageNotification
 if usePoke;

  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.Packager packager
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.AddReal content(nu=1, n=2)
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.GetReal get_content(nu=
       1, n=2)
  Modelica_DeviceDrivers.Blocks.Communication.UDPReceive
                     uDPReceive_adapted(port_recv=name,
    enableExternalTrigger= if usePoke then true else false,
    sampleTime= if usePoke then 10e20 else sampleRate)
  UDPSend_adapted                                       uDPSend_adapted
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.AddInteger sender(nu=1)
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.AddInteger receiver(nu=
       1)
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.AddInteger reply_to(nu=
       1)
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.AddReal    ontology(nu=1)
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.GetInteger
    getperformative(nu=1)
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.GetInteger getsender(
      nu=1)
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.GetInteger getreceiver(
      nu=1)
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.GetInteger getreply_to(
      nu=1)
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.GetReal    getontology(nu=1)
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.AddInteger performative(nu=1)
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.GetInteger getMessageID
  Modelica_DeviceDrivers.Blocks.Packaging.SerialPackager.AddInteger messageID(nu=1)
  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot
  SendSample                                       sendSample
                                                     if usePoke
  Modelica.Blocks.Interfaces.BooleanOutput sendOut if usePoke
    "Turns true when the sending unit of the agent is active"
equation

  if usePoke then
  connect(messageNotification.y, uDPReceive_adapted.trigger);
  end if;
  connect(sender.pkgOut[1], receiver.pkgIn)
  connect(receiver.pkgOut[1], reply_to.pkgIn)
  connect(reply_to.pkgOut[1], content.pkgIn)
  connect(content.pkgOut[1], ontology.pkgIn)
  connect(getperformative.pkgIn, uDPReceive_adapted.pkgOut)
  connect(getperformative.pkgOut[1], getsender.pkgIn)
  connect(getsender.pkgOut[1], getreceiver.pkgIn)
  connect(getreceiver.pkgOut[1], getreply_to.pkgIn)
  connect(getreply_to.pkgOut[1], get_content.pkgIn)
  connect(get_content.pkgOut[1], getontology.pkgIn)
  connect(performative.pkgIn, packager.pkgOut)
  connect(performative.pkgOut[1], sender.pkgIn)
  connect(getontology.pkgOut[1], getMessageID.pkgIn)
  connect(ontology.pkgOut[1], messageID.pkgIn)
  connect(messageID.pkgOut[1], uDPSend_adapted.pkgIn)
  connect(sendSample.u, uDPSend_adapted.send)
  connect(sendOut, sendSample.y)
end PartialAgent;


Input to connect with ProducerAgent.

within AixLib.Controls.HVACAgentBasedControl.BaseClasses;
partial model PartialCostFunction

  Modelica.Blocks.Interfaces.RealInput capacity
    "Input to connect with ProducerAgent"
  Modelica.Blocks.Interfaces.RealOutput cost
    "Output to connect with ProducerAgent"
equation
end PartialCostFunction;


Input connected to boolean output of UDPSend_adapted.

within AixLib.Controls.HVACAgentBasedControl.BaseClasses;
model SendSample

  Modelica.Blocks.MathBoolean.Or or1(nu=4)
  Modelica.Blocks.MathBoolean.OnDelay onDelay4(delayTime=0.1)
  Modelica.Blocks.MathBoolean.OnDelay onDelay5(delayTime=0.2)
  Modelica.Blocks.MathBoolean.OnDelay onDelay6(delayTime=0.5)
  Modelica.Blocks.MathBoolean.OnDelay onDelay7(delayTime=1)
  Modelica.Blocks.Interfaces.BooleanInput u
    "Input connected to boolean output of UDPSend_adapted"
  Modelica.Blocks.Interfaces.BooleanOutput y
    "Output connected to sendOut of PartialAgent"
  Modelica.Blocks.Logical.Edge edge1
  Modelica.Blocks.Logical.Edge edge2
  Modelica.Blocks.Logical.Edge edge3
  Modelica.Blocks.Logical.Edge edge4
equation
  connect(onDelay4.u, u)
  connect(or1.y, y)
  connect(edge1.u, onDelay4.y)
  connect(onDelay5.y, edge2.u)
  connect(onDelay6.y, edge3.u)
  connect(onDelay7.y, edge4.u)
  connect(onDelay5.u, u)
  connect(onDelay6.u, u)
  connect(onDelay7.u, u)
  connect(edge1.y, or1.u[1])
  connect(edge2.y, or1.u[2])
  connect(edge3.y, or1.u[3])
  connect(edge4.y, or1.u[4])
end SendSample;


A block for sending UDP datagrams.

within AixLib.Controls.HVACAgentBasedControl.BaseClasses;
model UDPSend_adapted "A block for sending UDP datagrams"
  import Modelica_DeviceDrivers;
  extends Modelica_DeviceDrivers.Utilities.Icons.BaseIcon;
  extends Modelica_DeviceDrivers.Utilities.Icons.UDPconnection;
  import Modelica_DeviceDrivers.Packaging.SerialPackager;
  import Modelica_DeviceDrivers.Communication.UDPSocket;

  // Parameter Modelica.SIunits.Period sampleTime=0.01
  //  "Sample time for update";
  parameter Boolean autoBufferSize = true
    "true, buffer size is deduced automatically, otherwise set it manually."
  parameter Integer userBufferSize=16*1024
    "Buffer size of message data in bytes (if not deduced automatically)."
  parameter String IPAddress="127.0.0.1" "IP address of remote UDP server"
  Real port_send "Target port of the receiving UDP server"
  Modelica_DeviceDrivers.Blocks.Interfaces.PackageIn pkgIn
    "Port for the data to send"
protected
  UDPSocket socket = UDPSocket(0);
  Integer bufferSize;
  Real dummy;
public
  Modelica.Blocks.Interfaces.BooleanInput trigger
    "Input to start the sending procedure"
  Modelica.Blocks.Interfaces.RealInput receiver
    "Input for receiving agent name"
  Modelica.Blocks.Interfaces.BooleanOutput send
    "Turns true when a message is send"
equation
  port_send = receiver;
  when initial() then
    pkgIn.userPkgBitSize = if autoBufferSize then -1 else userBufferSize*8;
    pkgIn.autoPkgBitSize = 0;
    bufferSize = if autoBufferSize then Modelica_DeviceDrivers.Packaging.SerialPackager_.getBufferSize(pkgIn.pkg) else userBufferSize;
  end when;
  pkgIn.backwardTrigger = trigger;
  // pkgIn.backwardTrigger = noEvent(sample(0, sampleTime));
  when noEvent(trigger) then
    dummy = AixLib.Controls.HVACAgentBasedControl.BaseClasses.Internal.sendToUDP(
      socket,
      IPAddress,
      port_send,
      pkgIn.pkg,
      bufferSize,
      pkgIn.dummy);
  end when;
  connect(trigger, send)
end UDPSend_adapted;


<span style=\

within AixLib.Controls.HVACAgentBasedControl;
package CostFunctions
  extends Modelica.Icons.VariantsPackage;
end CostFunctions;


Price per kWh of fuel. Overview

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.Economic;
model Constant_Economic_Cost
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real p = 0.30 "Price per kWh of fuel";
  parameter Real eta = 0.95 "thermal efficiency of the device";

equation
  cost = (p/eta) * capacity;
end Constant_Economic_Cost;


Price per kWh of fuel. Overview

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.Economic;
model PV_Variable_Economic_Cost
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real p = 0.30 "Price per kWh of fuel";
  parameter Real eta = 0.95 "thermal efficiency of the device";
  parameter Real rad_treshold = 310 "Treshold when electricity is free";

  Modelica.Blocks.Interfaces.RealInput rad "Input for solar radiation"
  Modelica.Blocks.Logical.GreaterEqualThreshold
                                             lessEqualThreshold(threshold=
        rad_treshold)
  Modelica.Clocked.RealSignals.Sampler.SampleClocked sample1
  Modelica.Clocked.ClockSignals.Clocks.PeriodicRealClock periodicClock1(period=
        300)
  Modelica.Clocked.RealSignals.Sampler.Hold hold1(y_start=100)
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Logical.Switch switch1
  Modelica.Blocks.Sources.RealExpression realExpression(y=(p/eta))
  Modelica.Blocks.Sources.RealExpression realExpression1(y=0.0001)
  Modelica.Blocks.Interfaces.BooleanOutput electricity_free
    "Indicator if electricity is considered free"
equation

  connect(sample1.u, rad)
  connect(periodicClock1.y, sample1.clock)
  connect(sample1.y, hold1.u)
  connect(hold1.y, lessEqualThreshold.u)
  connect(capacity, product.u2)
  connect(switch1.u2, lessEqualThreshold.y)
  connect(switch1.y, product.u1)
  connect(product.y, cost)
  connect(lessEqualThreshold.y, electricity_free)
  connect(switch1.u1, realExpression1.y)
  connect(switch1.u3, realExpression.y)
end PV_Variable_Economic_Cost;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.Exergy;
model Boiler_ExergyDestruction
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";
  parameter Real eta = 0.84 "Overall efficiency of the boiler";

  Real m_flow "mass flow";

  Modelica.Blocks.Interfaces.RealInput T_in
  Modelica.Blocks.Interfaces.RealInput T_out

equation
  m_flow = capacity/(4182*(T_out-T_in));
  cost= -capacity - (m_flow*T_0*4182*log(T_in/T_out)) + 0.9257 * capacity/eta;
end Boiler_ExergyDestruction;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.Exergy;
model Boiler_ExergyDestruction_Simplified
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";
  parameter Real eta = 0.84 "Overall efficiency of the boiler";

  Modelica.Blocks.Math.Division division
  Modelica.Blocks.Sources.RealExpression realExpression(y=eta)
  Modelica.Blocks.Math.Division division1
  Modelica.Blocks.Sources.RealExpression realExpression1(y=T_0)
  Modelica.Blocks.Math.Add add(k2=-1)
  Modelica.Blocks.Sources.RealExpression realExpression3(y=1)
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Math.Add add1(k2=-1)
  Modelica.Blocks.Math.Gain gain(k=0.9257)
  Modelica.Blocks.Interfaces.RealInput T_circuit
  Modelica.Blocks.Math.Max min
  Modelica.Blocks.Sources.RealExpression realExpression2(y=274.15)
equation
  connect(division.u2, realExpression.y)
  connect(division1.u1, realExpression1.y)
  connect(division1.y, add.u2)
  connect(add.u1, realExpression3.y)
  connect(add.y, product.u1)
  connect(capacity, product.u2)
  connect(division.u1, product.u2)
  connect(product.y, add1.u2)
  connect(add1.y, cost)
  connect(division.y, gain.u)
  connect(gain.y, add1.u1)
  connect(min.y, division1.u2)
  connect(min.u1, realExpression2.y)
  connect(min.u2, T_circuit)
end Boiler_ExergyDestruction_Simplified;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.Exergy;
model HeatingRod_ExergyDestruction
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";
  parameter Real eta = 0.97 "Overall efficiency of the boiler";

  Real T_in "Inlet temperature";

  Modelica.Blocks.Interfaces.RealInput T_below
    "Temperature of the storage water layer below the heating rod"
  Modelica.Blocks.Interfaces.RealInput m_flow(start=0.5, fixed=true)

equation
  T_in = T_below;

  cost= -(m_flow*T_0*4182*log(T_in/(T_in+capacity/(4182*m_flow))));
end HeatingRod_ExergyDestruction;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.Exergy;
model HeatingRod_ExergyDestruction_Simplified
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";
  parameter Real eta = 1 "Overall efficiency of the boiler";

  Modelica.Blocks.Math.Division division
  Modelica.Blocks.Sources.RealExpression realExpression(y=eta)
  Modelica.Blocks.Math.Division division1
  Modelica.Blocks.Sources.RealExpression realExpression1(y=T_0)
  Modelica.Blocks.Math.Add add(k2=-1)
  Modelica.Blocks.Sources.RealExpression realExpression3(y=1)
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Math.Add add1(k2=-1)
  Modelica.Blocks.Math.Gain gain(k=1)
  Modelica.Blocks.Interfaces.RealInput T_circuit
  Modelica.Blocks.Math.Max min
  Modelica.Blocks.Sources.RealExpression realExpression2(y=274.15)
equation
  connect(division.u2, realExpression.y)
  connect(division1.u1, realExpression1.y)
  connect(division1.y, add.u2)
  connect(add.u1, realExpression3.y)
  connect(add.y, product.u1)
  connect(capacity, product.u2)
  connect(division.u1, product.u2)
  connect(product.y, add1.u2)
  connect(add1.y, cost)
  connect(division.y, gain.u)
  connect(gain.y, add1.u1)
  connect(min.y, division1.u2)
  connect(min.u1, realExpression2.y)
  connect(min.u2, T_circuit)
end HeatingRod_ExergyDestruction_Simplified;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.Exergy;
model HeatPump_ExergyDestruction_Cooling
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";

  parameter Real tablePower[:, :] = fill(0.0, 0, 2)
    "table matrix (grid u1 = first column, grid u2 = first row; e.g., table=[0,0;0,1])";
  parameter Real tableHeatFlowCondenser[:, :] = fill(0.0, 0, 2)
    "table matrix (grid u1 = first column, grid u2 = first row; e.g., table=[0,0;0,1])";

  Real COP "Cooefficient of performance";

  Modelica.Blocks.Sources.RealExpression realExpression(y=1 - (1/COP))
  Modelica.Blocks.Math.Add add1(k2=+1)
  Modelica.Blocks.Math.Add add2(k2=-1)
  Modelica.Blocks.Math.Add add4(k2=-1)
  Modelica.Blocks.Math.Division division1
  Modelica.Blocks.Sources.RealExpression realExpression1(y=T_0)
  Modelica.Blocks.Interfaces.RealInput T_cold
  Modelica.Blocks.Sources.RealExpression realExpression2(y=1)
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Interfaces.RealInput T_hot
  Modelica.Blocks.Math.Division division2
  Modelica.Blocks.Sources.RealExpression realExpression3(y=T_0)
  Modelica.Blocks.Sources.RealExpression realExpression4(y=1)
  Modelica.Blocks.Math.Add add5(k2=-1)
  Modelica.Blocks.Math.Product product1
  Modelica.Blocks.Math.Division division3
  Modelica.Blocks.Sources.RealExpression realExpression5(y=COP)
  Modelica.Blocks.Math.Division division4
  Modelica.Blocks.Math.Add add3(k2=-1)
  Modelica.Blocks.Tables.CombiTable2Ds PowerTable(table=tablePower)
  Modelica.Blocks.Tables.CombiTable2Ds HeatFlowCondenserTable(table=
        tableHeatFlowCondenser)
equation

 COP = HeatFlowCondenserTable.y/PowerTable.y;
  connect(add1.y, add2.u1)
  connect(division1.u1, realExpression1.y)
  connect(division1.u2, T_cold)
  connect(add4.u1, realExpression2.y)
  connect(division1.y, add4.u2)
  connect(add4.y, product.u2)
  connect(realExpression3.y, division2.u1)
  connect(division2.u2, T_hot)
  connect(add5.u2, division2.y)
  connect(add5.y, product1.u2)
  connect(realExpression4.y, add5.u1)
  connect(cost, add2.y)
  connect(product1.y, add1.u1)
  connect(division3.u2, realExpression.y)
  connect(product1.u1, division3.y)
  connect(capacity, division3.u1)
  connect(realExpression5.y, division4.u2)
  connect(division4.u1, division3.y)
  connect(add2.u2, product.y)
  connect(add1.u2, division4.y)
  connect(add3.u2, division4.y)
  connect(add3.u1, division3.u1)
  connect(add3.y, product.u1)
  connect(T_hot, HeatFlowCondenserTable.u1)
  connect(T_hot, PowerTable.u1)
  connect(T_cold, PowerTable.u2)
  connect(HeatFlowCondenserTable.u2, T_cold)
end HeatPump_ExergyDestruction_Cooling;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.Exergy;
model HeatPump_ExergyDestruction_Heating
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";

  parameter Real tablePower[:, :] = fill(0.0, 0, 2)
    "table matrix (grid u1 = first column, grid u2 = first row; e.g., table=[0,0;0,1])";
  parameter Real tableHeatFlowCondenser[:, :] = fill(0.0, 0, 2)
    "table matrix (grid u1 = first column, grid u2 = first row; e.g., table=[0,0;0,1])";

  Real COP "Cooefficient of performance";

  Modelica.Blocks.Sources.RealExpression realExpression(y=COP)
  Modelica.Blocks.Math.Add add1(k2=+1)
  Modelica.Blocks.Math.Add add2(k2=-1)
  Modelica.Blocks.Math.Division division
  Modelica.Blocks.Math.Add add3(k1=-1, k2=+1)
  Modelica.Blocks.Math.Add add4(k2=-1)
  Modelica.Blocks.Math.Division division1
  Modelica.Blocks.Sources.RealExpression realExpression1(y=T_0)
  Modelica.Blocks.Interfaces.RealInput T_cold
  Modelica.Blocks.Sources.RealExpression realExpression2(y=1)
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Interfaces.RealInput T_hot
  Modelica.Blocks.Math.Division division2
  Modelica.Blocks.Sources.RealExpression realExpression3(y=T_0)
  Modelica.Blocks.Sources.RealExpression realExpression4(y=1)
  Modelica.Blocks.Math.Add add5(k2=-1)
  Modelica.Blocks.Math.Product product1
  Modelica.Blocks.Tables.CombiTable2Ds HeatFlowCondenserTable(table=
        tableHeatFlowCondenser)
  Modelica.Blocks.Tables.CombiTable2Ds PowerTable(table=tablePower)
equation
   COP = HeatFlowCondenserTable.y/PowerTable.y;
  connect(add1.y, add2.u1)
  connect(division.u2, realExpression.y)
  connect(division.u1, capacity)
  connect(add3.u2, capacity)
  connect(division.y, add3.u1)
  connect(division1.u1, realExpression1.y)
  connect(division1.u2, T_cold)
  connect(add4.u1, realExpression2.y)
  connect(division1.y, add4.u2)
  connect(add3.y, product.u1)
  connect(add4.y, product.u2)
  connect(add1.u1, division.y)
  connect(add1.u2, product.y)
  connect(realExpression3.y, division2.u1)
  connect(division2.u2, T_hot)
  connect(add5.u2, division2.y)
  connect(add5.y, product1.u2)
  connect(product1.u1, capacity)
  connect(product1.y, add2.u2)
  connect(realExpression4.y, add5.u1)
  connect(add2.y, cost)
  connect(T_hot,HeatFlowCondenserTable. u1)
  connect(T_cold,PowerTable. u2)
  connect(T_hot,PowerTable. u1)
  connect(HeatFlowCondenserTable.u2, T_cold)
end HeatPump_ExergyDestruction_Heating;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.Exergy;
model MixingValveAndHEX_ExergyDestruction
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";
  parameter Real T_circuit_hot = 273.15+80
    "Temperature of the hot water circuit";
  parameter Real m_flow_hot = 0.2 "Mass flow in the hot temperature circuit";

  Real T1(start=271.15+40) "Inlet cold temperature";
  Real T2(start=273.15+40, fixed=true) "Outlet cold temperature";
  Real T3(start=273.15+40) "Inlet hot temperature";
  Real T4(start=273.15+40) "Outlet hot temperature";
  Real m_flow_hot_actual(start=0.2);

  Modelica.Blocks.Interfaces.RealInput T_cold_in
  Modelica.Blocks.Interfaces.RealInput m_flow_cold
equation

  m_flow_hot_actual = (capacity/4000)*m_flow_hot;
  T1 = T_cold_in;
  T2 = T1 + capacity/(m_flow_cold*4182);
  T3 = T_circuit_hot;
  T4 = T3 - capacity/(m_flow_hot*4182);

  cost = - (m_flow_cold * T_0 * 4182 * log( T1/T2)) - (m_flow_hot_actual * T_0 * 4182 * log(T3/T4));
end MixingValveAndHEX_ExergyDestruction;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.Exergy;
model MixingValveAndHEX_ExergyDestruction_Simplified
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";
  Real T_hot(start=273.15+90) "Hot temperature";
  Real T_cold(start=273.15+50) "Cold temperature";

  Modelica.Blocks.Interfaces.RealInput T_cold_in
  Modelica.Blocks.Interfaces.RealInput T_hot_in
  Modelica.Blocks.Interfaces.RealInput T_cold_out
  Modelica.Blocks.Interfaces.RealInput T_hot_out
equation

  T_hot= (T_hot_in+T_hot_out)/2;
  T_cold= (T_cold_in+T_cold_out)/2;
  cost = capacity*(1-T_0/T_hot)-capacity*(1-T_0/T_cold);
end MixingValveAndHEX_ExergyDestruction_Simplified;


<span style=\

within AixLib.Controls.HVACAgentBasedControl.CostFunctions;
package Exergy
  extends Modelica.Icons.VariantsPackage;
end Exergy;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.PrimaryExergy;
model Boiler_PrimaryExergyDestruction_Simplified
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";
  parameter Real eta = 0.84 "Overall efficiency of the boiler";
  parameter Real PEF = 1.1 "Primary energy factor of the fuel";

  Modelica.Blocks.Math.Division division
  Modelica.Blocks.Sources.RealExpression realExpression(y=eta)
  Modelica.Blocks.Math.Division division1
  Modelica.Blocks.Sources.RealExpression realExpression1(y=T_0)
  Modelica.Blocks.Math.Add add(k2=-1)
  Modelica.Blocks.Sources.RealExpression realExpression3(y=1)
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Math.Add add1(k2=-1)
  Modelica.Blocks.Math.Gain gain(k=PEF*0.9257)
  Modelica.Blocks.Interfaces.RealInput T_circuit
  Modelica.Blocks.Math.Max min
  Modelica.Blocks.Sources.RealExpression realExpression2(y=274.15)
equation
  connect(division.u2, realExpression.y)
  connect(division1.u1, realExpression1.y)
  connect(division1.y, add.u2)
  connect(add.u1, realExpression3.y)
  connect(add.y, product.u1)
  connect(capacity, product.u2)
  connect(division.u1, product.u2)
  connect(product.y, add1.u2)
  connect(add1.y, cost)
  connect(division.y, gain.u)
  connect(gain.y, add1.u1)
  connect(min.y, division1.u2)
  connect(min.u1, realExpression2.y)
  connect(min.u2, T_circuit)
end Boiler_PrimaryExergyDestruction_Simplified;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.PrimaryExergy;
model HeatingRod_PrimaryExergyDestruction_Simplified
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";
  parameter Real eta = 1 "Overall efficiency of the boiler";
  parameter Real PEF = 1.8 "Primary energy factor of the fuel";

  Modelica.Blocks.Math.Division division
  Modelica.Blocks.Sources.RealExpression realExpression(y=eta)
  Modelica.Blocks.Math.Division division1
  Modelica.Blocks.Sources.RealExpression realExpression1(y=T_0)
  Modelica.Blocks.Math.Add add(k2=-1)
  Modelica.Blocks.Sources.RealExpression realExpression3(y=1)
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Math.Add add1(k2=-1)
  Modelica.Blocks.Math.Gain gain(k=PEF)
  Modelica.Blocks.Interfaces.RealInput T_circuit
  Modelica.Blocks.Math.Max min
  Modelica.Blocks.Sources.RealExpression realExpression2(y=274.15)
equation
  connect(division.u2, realExpression.y)
  connect(division1.u1, realExpression1.y)
  connect(division1.y, add.u2)
  connect(add.u1, realExpression3.y)
  connect(add.y, product.u1)
  connect(capacity, product.u2)
  connect(division.u1, product.u2)
  connect(product.y, add1.u2)
  connect(add1.y, cost)
  connect(division.y, gain.u)
  connect(gain.y, add1.u1)
  connect(min.y, division1.u2)
  connect(min.u1, realExpression2.y)
  connect(min.u2, T_circuit)
end HeatingRod_PrimaryExergyDestruction_Simplified;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.PrimaryExergy;
model HeatPump_PrimaryExergyDestruction_Cooling
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";

  parameter Real tablePower[:, :] = fill(0.0, 0, 2)
    "table matrix (grid u1 = first column, grid u2 = first row; e.g., table=[0,0;0,1])";
  parameter Real tableHeatFlowCondenser[:, :] = fill(0.0, 0, 2)
    "table matrix (grid u1 = first column, grid u2 = first row; e.g., table=[0,0;0,1])";
  parameter Real PEF = 1.8 "Primary energy factor of the fuel";

  Real COP "Cooefficient of performance";

  Modelica.Blocks.Sources.RealExpression realExpression(y=1 - (1/COP))
  Modelica.Blocks.Math.Add add1(k2=+1)
  Modelica.Blocks.Math.Add add2(k2=-1)
  Modelica.Blocks.Math.Add add4(k2=-1)
  Modelica.Blocks.Math.Division division1
  Modelica.Blocks.Sources.RealExpression realExpression1(y=T_0)
  Modelica.Blocks.Interfaces.RealInput T_cold
  Modelica.Blocks.Sources.RealExpression realExpression2(y=1)
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Interfaces.RealInput T_hot
  Modelica.Blocks.Math.Division division2
  Modelica.Blocks.Sources.RealExpression realExpression3(y=T_0)
  Modelica.Blocks.Sources.RealExpression realExpression4(y=1)
  Modelica.Blocks.Math.Add add5(k2=-1)
  Modelica.Blocks.Math.Product product1
  Modelica.Blocks.Math.Division division3
  Modelica.Blocks.Sources.RealExpression realExpression5(y=COP)
  Modelica.Blocks.Math.Division division4
  Modelica.Blocks.Math.Add add3(k2=-1)
  Modelica.Blocks.Tables.CombiTable2Ds PowerTable(table=tablePower)
  Modelica.Blocks.Tables.CombiTable2Ds HeatFlowCondenserTable(table=
        tableHeatFlowCondenser)
  Modelica.Blocks.Math.Gain gain(k=PEF)
equation

 COP = HeatFlowCondenserTable.y/PowerTable.y;
  connect(add1.y, add2.u1)
  connect(division1.u1, realExpression1.y)
  connect(division1.u2, T_cold)
  connect(add4.u1, realExpression2.y)
  connect(division1.y, add4.u2)
  connect(add4.y, product.u2)
  connect(realExpression3.y, division2.u1)
  connect(division2.u2, T_hot)
  connect(add5.u2, division2.y)
  connect(add5.y, product1.u2)
  connect(realExpression4.y, add5.u1)
  connect(cost, add2.y)
  connect(product1.y, add1.u1)
  connect(division3.u2, realExpression.y)
  connect(product1.u1, division3.y)
  connect(capacity, division3.u1)
  connect(realExpression5.y, division4.u2)
  connect(division4.u1, division3.y)
  connect(add2.u2, product.y)
  connect(add3.u2, division4.y)
  connect(add3.u1, division3.u1)
  connect(add3.y, product.u1)
  connect(T_hot, HeatFlowCondenserTable.u1)
  connect(T_hot, PowerTable.u1)
  connect(T_cold, PowerTable.u2)
  connect(HeatFlowCondenserTable.u2, T_cold)
  connect(gain.y, add1.u2)
  connect(gain.u, division4.y)
end HeatPump_PrimaryExergyDestruction_Cooling;


Exergy reference temperature.

within AixLib.Controls.HVACAgentBasedControl.CostFunctions.PrimaryExergy;
model HeatPump_PrimaryExergyDestruction_Heating
  extends HVACAgentBasedControl.BaseClasses.PartialCostFunction;
  parameter Real T_0 = 298.15 "Exergy reference temperature";

  parameter Real tablePower[:, :] = fill(0.0, 0, 2)
    "table matrix (grid u1 = first column, grid u2 = first row; e.g., table=[0,0;0,1])";
  parameter Real tableHeatFlowCondenser[:, :] = fill(0.0, 0, 2)
    "table matrix (grid u1 = first column, grid u2 = first row; e.g., table=[0,0;0,1])";
  parameter Real PEF = 1.8 "Primary energy factor of the fuel";

  Real COP "Cooefficient of performance";

  Modelica.Blocks.Sources.RealExpression realExpression(y=COP)
  Modelica.Blocks.Math.Add add1(k2=+1)
  Modelica.Blocks.Math.Add add2(k2=-1)
  Modelica.Blocks.Math.Division division
  Modelica.Blocks.Math.Add add3(k1=-1, k2=+1)
  Modelica.Blocks.Math.Add add4(k2=-1)
  Modelica.Blocks.Math.Division division1
  Modelica.Blocks.Sources.RealExpression realExpression1(y=T_0)
  Modelica.Blocks.Interfaces.RealInput T_cold
  Modelica.Blocks.Sources.RealExpression realExpression2(y=1)
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Interfaces.RealInput T_hot
  Modelica.Blocks.Math.Division division2
  Modelica.Blocks.Sources.RealExpression realExpression3(y=T_0)
  Modelica.Blocks.Sources.RealExpression realExpression4(y=1)
  Modelica.Blocks.Math.Add add5(k2=-1)
  Modelica.Blocks.Math.Product product1
  Modelica.Blocks.Tables.CombiTable2Ds HeatFlowCondenserTable(table=
        tableHeatFlowCondenser)
  Modelica.Blocks.Tables.CombiTable2Ds PowerTable(table=tablePower)
  Modelica.Blocks.Math.Gain gain(k=PEF)
equation
   COP = HeatFlowCondenserTable.y/PowerTable.y;
  connect(add1.y, add2.u1)
  connect(division.u2, realExpression.y)
  connect(division.u1, capacity)
  connect(add3.u2, capacity)
  connect(division.y, add3.u1)
  connect(division1.u1, realExpression1.y)
  connect(division1.u2, T_cold)
  connect(add4.u1, realExpression2.y)
  connect(division1.y, add4.u2)
  connect(add3.y, product.u1)
  connect(add4.y, product.u2)
  connect(add1.u2, product.y)
  connect(realExpression3.y, division2.u1)
  connect(division2.u2, T_hot)
  connect(add5.u2, division2.y)
  connect(add5.y, product1.u2)
  connect(product1.u1, capacity)
  connect(product1.y, add2.u2)
  connect(realExpression4.y, add5.u1)
  connect(add2.y, cost)
  connect(T_hot,HeatFlowCondenserTable. u1)
  connect(T_cold,PowerTable. u2)
  connect(T_hot,PowerTable. u1)
  connect(HeatFlowCondenserTable.u2, T_cold)
  connect(gain.u, division.y)
  connect(gain.y, add1.u1)
end HeatPump_PrimaryExergyDestruction_Heating;


<span style=\

within AixLib.Controls.HVACAgentBasedControl.CostFunctions;
package PrimaryExergy
  extends Modelica.Icons.VariantsPackage;
end PrimaryExergy;


within AixLib.Controls.HVACAgentBasedControl;
package Examples "This package contains Examples that show how the agent-based control library can be implemented."
  extends Modelica.Icons.ExamplesPackage;

end Examples;


List of known BookSellerAgents (their adresses).

within AixLib.Controls.HVACAgentBasedControl.Examples.BookTrading;
model BookBuyerAgent
  extends BaseClasses.PartialAgent;
  parameter Real[:,1] knownSellers = [30001; 30002; 30003]
    "List of known BookSellerAgents (their adresses)";
  Real[3,2] proposals(start=[9999,9999;9999,9999;9999,9999]);
  parameter Real ISBN = 3551551677.0
    "ISBN number of the book that the agent tries to buy";
  Integer counter( start=1);
  Integer counterProposals( start=1);
  Boolean requestsDone(start=false);
  Real lowestPrice(start=9999999);
  Boolean bookOffered(start=false);
  parameter Integer  sampleTime = 20
    "Period of time between two tries of the agent to buy the book";

  Modelica.StateGraph.InitialStep waiting(nIn=4, nOut=1)
  Modelica.StateGraph.Step composeRequest(nIn=3, nOut=1)
  Modelica.StateGraph.Step collectProposal(nOut=2, nIn=1)
  Modelica.StateGraph.Step composeBuy(nIn=1, nOut=1)
  Modelica.Blocks.Math.IntegerChange integerChange
  Modelica.Blocks.Sources.SampleTrigger sampleTrigger(period=sampleTime,
      startTime=sampleTime)
  Modelica.StateGraph.TransitionWithSignal transitionWithSignal
  Modelica.StateGraph.Transition transition(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.Step check(nOut=2, nIn=1)
  Modelica.StateGraph.TransitionWithSignal newMessage
  Modelica.StateGraph.TransitionWithSignal offer(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.TransitionWithSignal refuse(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.TransitionWithSignal done(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.TransitionWithSignal notDone(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.StepWithSignal sendRequest(nOut=2, nIn=1)
  Modelica.StateGraph.StepWithSignal sendBuy(nOut=2, nIn=1)
  Modelica.StateGraph.Step check1(nOut=2, nIn=1)
  Modelica.StateGraph.TransitionWithSignal confirmation(enableTimer=true,
      waitTime=0.1)
  Modelica.StateGraph.Step setDone(nOut=1, nIn=1)
  Modelica.StateGraph.Transition transition1(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.Transition transition3(enableTimer=true, waitTime=0.1)
  Modelica.Blocks.Interfaces.BooleanOutput bookBought
    "Indicator that turns true if a book was succesfully bought"
  Modelica.StateGraph.TransitionWithSignal newMessage1
  Modelica.Blocks.Logical.Or or1
  Modelica.Blocks.Sources.BooleanExpression booleanExpression(y=(
        getperformative.y[1] == 13) or (requestsDone))
  Modelica.Blocks.Sources.BooleanExpression booleanExpression1(y=
        getperformative.y[1] == 17)
  Modelica.Blocks.Sources.BooleanExpression booleanExpression2(y=requestsDone)
  Modelica.Blocks.Sources.BooleanExpression booleanExpression3(y=not (
        requestsDone))
  Modelica.Blocks.Sources.BooleanExpression booleanExpression4(y=
        getperformative.y[1] == 5)
  Modelica.StateGraph.Transition abort(enableTimer=true, waitTime=30)

  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot
  Modelica.StateGraph.Step stateOfOffers(nOut=2, nIn=1)
  Modelica.StateGraph.TransitionWithSignal transitionWithSignal1
  Modelica.Blocks.Sources.BooleanExpression booleanExpression5(y=bookOffered)
  Modelica.StateGraph.Transition noOffers(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.Transition abortAction(
                                            enableTimer=true, waitTime=15)
  Modelica.StateGraph.Transition abortAction1(
                                            enableTimer=true, waitTime=15)
  Modelica.StateGraph.Step notServed(nIn=2, nOut=1)
  Modelica.StateGraph.Transition transition2(                  waitTime=0.1,
      enableTimer=false)
  Modelica.Blocks.Logical.And and1
  Modelica.Blocks.Sources.BooleanExpression booleanExpression6(y=not (
        bookBought))

algorithm
    when waiting.active then
      counter :=1;
      counterProposals :=1;
      lowestPrice := 9999999;
      bookOffered :=false;
    end when;

    when composeRequest.active then
      content.u[1] := ISBN; //temporary function
      content.u[2] := 0;
      performative.u[1]:= 4;
      sender.u[1]:=name;
      reply_to.u[1] := name;
      ontology.u[1] := 1;
      uDPSend_adapted.receiver := knownSellers[counter,1];
      receiver.u[1]:= integer(knownSellers[counter,1]);
      messageID.u[1] := name*name + integer(time);
      Modelica.Utilities.Streams.print("BookBuyerAgent "+ String(name)+ " calls for proposals for book " + String(ISBN) + " from BookSellerAgent "+ String(knownSellers[counter,1])+".");
    end when;

    when sendRequest.active then
      counter := counter +1;
      if counter > size(knownSellers,1) then
        requestsDone := true;
      end if;
    end when;

    when collectProposal.active then
      if Modelica.Math.isEqual(getperformative.y[1],13) then
        bookOffered :=true;
        Modelica.Utilities.Streams.print("BookBuyerAgent "+ String(name)+ " collects proposal for book " + String(ISBN)+".");
      end if;

      proposals[counterProposals,1] := get_content.y[1];
      proposals[counterProposals,2] := getsender.y[1];
      counterProposals := counterProposals +1;

    end when;

    when composeBuy.active then
     counter := 1;
     lowestPrice := min(proposals[:,1]);
     // loop to find the cheapest producer
     for counter in 1:size(proposals,1) loop
       if Modelica.Math.isEqual(proposals[counter,1],lowestPrice) then
         break;
       end if;
     end for;

     //send out accept proposal to the cheapest producer
     performative.u[1]:=19;
     sender.u[1]:=name;
     receiver.u[1]:= integer(proposals[counter,2]);
     reply_to.u[1] := name;
     content.u[1] := ISBN;
     ontology.u[1] := 1;
     uDPSend_adapted.receiver := proposals[counter,2];
     messageID.u[1] := name*name + integer(time);
     Modelica.Utilities.Streams.print("BookBuyerAgent "+ String(name)+ " buys book " + String(ISBN) + " from BookSellerAgent "+ String(proposals[counter,2])+".");

    end when;

    when setDone.active then
      bookBought := true;
      Modelica.Utilities.Streams.print("BookBuyerAgent "+ String(name)+ " has succesfully bought the book " + String(ISBN) + " for "+ String(proposals[counter,1])+" €.");
    end when;

    when stateOfOffers.active then
      if not
            (bookOffered) then
        Modelica.Utilities.Streams.print("BookBuyerAgent "+ String(name)+ " was not offered the book " + String(ISBN) + ". It goes back to idle.");
      end if;
    end when;

    when notServed.active then
       Modelica.Utilities.Streams.print("BookBuyerAgent "+ String(name)+ " was not served and goes back to idle.");
    end when;

equation
  connect(waiting.outPort[1], transitionWithSignal.inPort)
  connect(transitionWithSignal.outPort, composeRequest.inPort[1])
  connect(transition.inPort, composeRequest.outPort[1])
  connect(newMessage.outPort, check.inPort[1])
  connect(check.outPort[1], offer.inPort)
  connect(offer.outPort, collectProposal.inPort[1])
  connect(refuse.inPort, check.outPort[2])
  connect(refuse.outPort, composeRequest.inPort[2])
  connect(collectProposal.outPort[1], notDone.inPort)
  connect(done.inPort, collectProposal.outPort[2])
  connect(notDone.outPort, composeRequest.inPort[3])

  connect(sendRequest.outPort[1], newMessage.inPort)
  connect(sendRequest.inPort[1], transition.outPort)
  connect(composeBuy.outPort[1], transition1.inPort)
  connect(transition1.outPort, sendBuy.inPort[1])
  connect(confirmation.inPort, check1.outPort[1])
  connect(setDone.inPort[1], confirmation.outPort)
  connect(transition3.inPort, setDone.outPort[1])
  connect(transition3.outPort, waiting.inPort[1])
  connect(newMessage1.inPort, sendBuy.outPort[1])
  connect(newMessage1.outPort, check1.inPort[1])

  connect(or1.y, uDPSend_adapted.trigger)
  connect(or1.u1, sendRequest.active)
  connect(or1.u2, sendBuy.active)
  connect(booleanExpression.y, offer.condition)
  connect(booleanExpression1.y, refuse.condition)
  connect(booleanExpression2.y, done.condition)
  connect(booleanExpression3.y, notDone.condition)
  connect(integerChange.y, newMessage.condition)
  connect(newMessage1.condition, newMessage.condition)
  connect(abort.inPort, check1.outPort[2])
  connect(abort.outPort, waiting.inPort[2])

  connect(booleanExpression4.y, confirmation.condition)
  connect(transitionWithSignal1.outPort, composeBuy.inPort[1])
  connect(transitionWithSignal1.inPort, stateOfOffers.outPort[1])
  connect(stateOfOffers.inPort[1], done.outPort)
  connect(transitionWithSignal1.condition, booleanExpression5.y)
  connect(noOffers.inPort, stateOfOffers.outPort[2])

  connect(noOffers.outPort, waiting.inPort[3])
  connect(abortAction.inPort, sendRequest.outPort[2])
  connect(abortAction1.inPort, sendBuy.outPort[2])
  connect(abortAction.outPort, notServed.inPort[1])
  connect(abortAction1.outPort, notServed.inPort[2])
  connect(notServed.outPort[1], transition2.inPort)
  connect(transition2.outPort, waiting.inPort[4])

  connect(and1.y, transitionWithSignal.condition)
  connect(sampleTrigger.y, and1.u2)
  connect(booleanExpression6.y, and1.u1)
  connect(getMessageID.y[1], integerChange.u)
end BookBuyerAgent;


BookSellerAgent .

within AixLib.Controls.HVACAgentBasedControl.Examples.BookTrading;
model BookSellerAgent
  extends BaseClasses.PartialAgent;
  Real[:,2] bookList( start= [3551551677.0,30; 3551551679.0,20; 3551551616.0, 20]);
  Real searchedBook(start=0);
  Integer counter(start=1);
  Boolean bookInStock(start=false);
  Boolean bookToSell(start=false);
  Real index(start=1);

  //current message
  Integer sender_current(start=0);
  Integer performative_current(start=0);
  Real content_1_current(start=0);
  Real content_2_current(start=0);

  Modelica.Blocks.Math.IntegerChange integerChange
  Modelica.StateGraph.InitialStep waiting(nIn=2, nOut=1)
  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot
  Modelica.StateGraph.TransitionWithSignal newMessage
  Modelica.StateGraph.Step checkPurpose(nOut=2, nIn=1)
  Modelica.StateGraph.TransitionWithSignal OfferRequestsServer(enableTimer=true,
      waitTime=0.1)
  Modelica.StateGraph.TransitionWithSignal PurchaseOrdersServer(enableTimer=true,
      waitTime=0.1)
  Modelica.StateGraph.Step checkLibrary(nIn=1, nOut=1)
  Modelica.StateGraph.Step composeResponse(nIn=1, nOut=1)
  Modelica.StateGraph.StepWithSignal sendResponse(nIn=1, nOut=1)
  Modelica.StateGraph.Step checkLibrary1(nIn=1, nOut=1)
  Modelica.StateGraph.Step composeResponse1(nIn=1, nOut=1)
  Modelica.StateGraph.StepWithSignal sendResponse1(nIn=1, nOut=1)
  Modelica.StateGraph.Transition transition(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.Transition transition1(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.Transition transition2(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.Transition transition3(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.Transition transition4(enableTimer=true, waitTime=0.1)
  Modelica.StateGraph.Transition transition5(enableTimer=true, waitTime=0.1)
  Modelica.Blocks.Logical.Or or1
  Modelica.Blocks.Sources.BooleanExpression booleanExpression1(y=
        performative_current == 4)
  Modelica.Blocks.Sources.BooleanExpression booleanExpression2(y=
        performative_current == 19)

algorithm
  when waiting.active then
    searchedBook := 0;
    counter := 1;
    bookInStock :=false;
    bookToSell :=false;
    index :=1;
  end when;

  when checkPurpose.active then
    sender_current := getsender.y[1];
    performative_current := getperformative.y[1];
    content_1_current := get_content.y[1];
    content_2_current := get_content.y[2];

  end when;

  when checkLibrary.active then

    searchedBook := content_1_current;
    for index in 1:size(bookList,1) loop
      if Modelica.Math.isEqual(bookList[index,1],searchedBook) then
         bookInStock := true;
         counter  := index;
         break;
      end if;
    end for;
  end when;

 when composeResponse.active then

      sender.u[1]:=name;
      reply_to.u[1] := name;
      ontology.u[1] := 1;
      uDPSend_adapted.receiver := sender_current;
      receiver.u[1]:= sender_current;
      messageID.u[1] := name*name + integer(time);

      if bookInStock then
        content.u[1] := bookList[counter,2];
        content.u[2] := bookList[counter,1];
        performative.u[1]:= 13;
        Modelica.Utilities.Streams.print("BookSellerAgent "+ String(name)+ " has found the book " + String(get_content.y[1]) + " and offers it for "+ String(bookList[counter,2])+" €.");
      else
        content.u[1] := 0;
        content.u[2] := 0;
        performative.u[1]:= 17;
        Modelica.Utilities.Streams.print("BookSellerAgent "+ String(name)+ " has not found the book " + String(get_content.y[1]) + " and refuses the proposal.");
      end if;

  end when;

  when checkLibrary1.active then
    searchedBook := content_1_current;
    for index in 1:size(bookList,1) loop
      if Modelica.Math.isEqual(bookList[index,1],searchedBook) then
         bookToSell := true;
         counter := index;
         break;
      end if;
    end for;

  end when;

  when composeResponse1.active then

      sender.u[1]:=name;
      reply_to.u[1] := name;
      ontology.u[1] := 1;
      uDPSend_adapted.receiver := sender_current;
      receiver.u[1]:= sender_current;
      messageID.u[1] := name*name + integer(time);

     if bookToSell then
       Modelica.Utilities.Streams.print("BookSellerAgent "+ String(name)+ " has found the book " + String(get_content.y[1]) + " and and sells it for "+ String(bookList[counter,2])+" € to " + String(getsender.y[1])+".");
       content.u[1] := bookList[counter,2];
       content.u[2] := bookList[counter,1];
       performative.u[1]:= 5;
       bookList[counter,2] := 0;
       bookList[counter,1] := 0;

     else
       content.u[1] := 0;
       content.u[2] := 0;
       performative.u[1]:= 17;
       Modelica.Utilities.Streams.print("BookSellerAgent "+ String(name)+ " has not found the book " + String(get_content.y[1]) + " and and can therefore not sell it.");
     end if;

  end when;

equation
  connect(getMessageID.y[1], integerChange.u)
  connect(waiting.outPort[1], newMessage.inPort)
  connect(newMessage.outPort,checkPurpose. inPort[1])
  connect(checkPurpose.outPort[1], OfferRequestsServer.inPort)
  connect(checkPurpose.outPort[2], PurchaseOrdersServer.inPort)
  connect(OfferRequestsServer.outPort, checkLibrary.inPort[1])
  connect(transition.inPort, checkLibrary.outPort[1])
  connect(transition.outPort, composeResponse.inPort[1])
  connect(composeResponse.outPort[1], transition1.inPort)
  connect(transition1.outPort, sendResponse.inPort[1])
  connect(transition4.outPort, waiting.inPort[1])
  connect(transition5.outPort, waiting.inPort[2])
  connect(sendResponse.outPort[1], transition4.inPort)
  connect(sendResponse1.outPort[1], transition5.inPort)
  connect(PurchaseOrdersServer.outPort, checkLibrary1.inPort[1])
  connect(checkLibrary1.outPort[1], transition2.inPort)
  connect(transition2.outPort, composeResponse1.inPort[1])
  connect(composeResponse1.outPort[1], transition3.inPort)
  connect(transition3.outPort, sendResponse1.inPort[1])
  connect(uDPSend_adapted.trigger, or1.y)
  connect(or1.u1, sendResponse.active)
  connect(sendResponse1.active, or1.u2)
  connect(booleanExpression1.y, OfferRequestsServer.condition)
  connect(booleanExpression2.y, PurchaseOrdersServer.condition)
  connect(integerChange.y, newMessage.condition)
end BookSellerAgent;


<span style=\.

within AixLib.Controls.HVACAgentBasedControl.Examples.BookTrading;
model BookTrading
    extends Modelica.Icons.Example;

  BookBuyerAgent bookBuyerAgent(name=10001, ISBN=0618640150,
    sampleRate=1)
  BookSellerAgent bookSellerAgent(name=30001, bookList(start=[3551555559.0,30;
          3551555577.0,20; 3551555588.0,20]),
    sampleRate=1)
  BookSellerAgent bookSellerAgent1(name=30002, bookList(start=[3551555589.0,
          30; 3551555559.0,40; 3551555556.0,20]),
    sampleRate=1)
  BookSellerAgent bookSellerAgent2(name=30003, bookList(start=[3551555555.0,
          30; 3551555554.0,20; 3551555553.0,20; 3551555580.0,15]),
    sampleRate=1)
  BookBuyerAgent bookBuyerAgent1(
    name=10002,
    ISBN=3551555559.0,
    sampleRate=1,
    sampleTime=40)
  BookBuyerAgent bookBuyerAgent2(
    ISBN=3551555559.0,
    name=10003,
    sampleRate=1,
    sampleTime=55)
  inner Agents.MessageNotification messageNotification
end BookTrading;


within AixLib.Controls.HVACAgentBasedControl.Examples.BookTrading;
model NetworkCommunication1
    extends Modelica.Icons.Example;

  BookSellerAgent bookSellerAgent1(            bookList(start=[3551555589.0,
          30; 3551555559.0,40; 3551555556.0,20]),
    uDPSend_adapted(IPAddress="134.130.49.128"),
    name=10003,
    sampleRate=1)
  Modelica_DeviceDrivers.Blocks.OperatingSystem.SynchronizeRealtime
    synchronizeRealtime(priority="Below normal")
  inner Agents.MessageNotification messageNotification
end NetworkCommunication1;


within AixLib.Controls.HVACAgentBasedControl.Examples.BookTrading;
model NetworkCommunication2
    extends Modelica.Icons.Example;

  BookBuyerAgent bookBuyerAgent1(
    name=10002,
    ISBN=3551555559.0,
    sampleTime=10,
    uDPSend_adapted(IPAddress="134.130.49.160"),
    knownSellers=[10002],
    sampleRate=1)
  Modelica_DeviceDrivers.Blocks.OperatingSystem.SynchronizeRealtime
    synchronizeRealtime(priority="Below normal")
  inner Agents.MessageNotification messageNotification
end NetworkCommunication2;


bar

within AixLib.Controls.HVACAgentBasedControl.Examples.BuildingHeatingSystems;
model BuildingHeating
  extends Modelica.Icons.Example;
  parameter AixLib.DataBase.Weather.TRYWeatherBaseDataDefinition weatherDataDay = AixLib.DataBase.Weather.TRYWinterDay();

  ThermalZones.ReducedOrder.ThermalZone.ThermalZone
    thermalZone(
      redeclare AixLib.DataBase.ThermalZones.OfficePassiveHouse.OPH_1_OfficeNoHeaterCooler zoneParam,
      redeclare package Medium = Modelica.Media.Air.SimpleAir)
  ThermalZones.ReducedOrder.ThermalZone.ThermalZone
              thermalZone1(redeclare package Medium =
        Modelica.Media.Air.SimpleAir,
    redeclare AixLib.DataBase.ThermalZones.OfficePassiveHouse.OPH_1_OfficeNoHeaterCooler zoneParam)
  AixLib.Fluid.Movers.FlowControlled_m_flow fan(redeclare package Medium =
        Modelica.Media.Water.ConstantPropertyLiquidWater, m_flow_nominal=2)
  AixLib.Fluid.HeatExchangers.HeaterCooler_u hea(
    redeclare package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater,
    m_flow_nominal=2,
    dp_nominal(displayUnit="bar") = 5000,
    Q_flow_nominal=1)

  AixLib.Fluid.HeatExchangers.HeaterCooler_u hea1(
    redeclare package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater,
    m_flow_nominal=2,
    dp_nominal(displayUnit="bar") = 5000,
    Q_flow_nominal=1)

  Fluid.Sources.Boundary_pT          bou(nPorts=1, redeclare package Medium =
        Modelica.Media.Water.ConstantPropertyLiquidWater)
  Agents.RoomAgent roomAgent(              startTime=60,
    threshold=0.5,
    broker=10003,
    sampleRate=1,
    sampleTriggerTime=120,
    G=10)
  Agents.RoomAgent roomAgent1(
    name=10002,
    startTime=70,
    threshold=0.5,
    broker=10003,
    sampleRate=1,
    sampleTriggerTime=120,
    G=10)
  Modelica.Blocks.Sources.Constant roomSetPoint(k=273.15 + 22)
  inner Agents.MessageNotification messageNotification(n=5)
  Agents.HeatProducerAgent heatProducerAgent(                  name=30001,
    maxCapacity=3000,
    sampleRate=1,
    setCapacity(start=1),
    currentCapacityDiscrete(start=1))
  Agents.HeatProducerAgent heatProducerAgent1(name=30002,
    maxCapacity=10000,
    sampleRate=1,
    setCapacity(start=1),
    currentCapacityDiscrete(start=1))
  CostFunctions.Economic.Constant_Economic_Cost constantFactor(eta=1)
  CostFunctions.Economic.Constant_Economic_Cost constantFactor1(p=0.60, eta=1)
  Modelica.Blocks.Sources.BooleanExpression booleanExpression(y=true)
  Modelica.Blocks.Sources.Constant massFlowRate(k=5)
  Agents.Broker broker(name=10003, sampleRate=1)
  Modelica.Fluid.Vessels.ClosedVolume volume(
    nPorts=2,
    redeclare package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater,
    use_portsData=false,
    use_HeatTransfer=true,
    V=30*1E-3)

  Modelica.Fluid.Vessels.ClosedVolume volume1(
    nPorts=2,
    redeclare package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater,
    use_portsData=false,
    use_HeatTransfer=true,
    V=30*1E-3)

  Modelica.Thermal.HeatTransfer.Components.ThermalConductor thermalConductor(G=2000)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor thermalConductor1(G=
       2000)
  AixLib.Fluid.Actuators.Valves.TwoWayLinear val1(
    m_flow_nominal=1,
    dpValve_nominal(displayUnit="bar") = 10000,
    redeclare package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater)
  Modelica.Blocks.Continuous.LimPID PID1(
    yMax=1,
    initType=Modelica.Blocks.Types.Init.InitialOutput,
    k=0.1,
    Ti=1,
    Td=0.01,
    y_start=0.3,
    yMin=0.1)
  AixLib.Fluid.Actuators.Valves.TwoWayLinear val(
    m_flow_nominal=1,
    dpValve_nominal(displayUnit="bar") = 10000,
    redeclare package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater)
  Modelica.Blocks.Continuous.LimPID PID2(
    yMax=1,
    initType=Modelica.Blocks.Types.Init.InitialOutput,
    k=0.1,
    Ti=1,
    Td=0.01,
    y_start=0.3,
    yMin=0.1)
  Modelica.Blocks.Sources.Constant internalGains[3](k={0,0,0})
  Modelica.Blocks.Interfaces.RealOutput T_room(unit="K") "Temperature in room"
  Modelica.Blocks.Interfaces.RealOutput T_room1(unit="K") "Temperature in room"
  Modelica.Blocks.Interfaces.RealOutput Cap_device(unit="W")
    "Capacity of heating device"
  Modelica.Blocks.Interfaces.RealOutput Cap_device1(unit="W")
    "Capacity of heating device"
  BoundaryConditions.WeatherData.ReaderTMY3        weaDat(
    calTSky=AixLib.BoundaryConditions.Types.SkyTemperatureCalculation.HorizontalRadiation,
    computeWetBulbTemperature=false,
    filNam=Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
    "Weather data reader"
  inner Modelica.Fluid.System system
  Modelica.Blocks.Sources.CombiTimeTable InternalHeatGain(
    table=[0,0,0.1,0,0; 3540,0,0.1,0,0; 3600,0,0.1,0,0; 7140,0,0.1,0,0; 7200,0,
        0.1,0,0; 10740,0,0.1,0,0; 10800,0,0.1,0,0; 14340,0,0.1,0,0; 14400,0,0.1,
        0,0; 17940,0,0.1,0,0; 18000,0,0.1,0,0; 21540,0,0.1,0,0; 21600,0,0.1,0,0;
        25140,0,0.1,0,0; 25200,0,0.1,0,0; 28740,0,0.1,0,0; 28800,0,0.1,0,0;
        32340,0,0.1,0,0; 32400,0.6,0.6,1,1; 35940,0.6,0.6,1,1; 36000,1,1,1,1;
        39540,1,1,1,1; 39600,0.4,0.4,1,1; 43140,0.4,0.4,1,1; 43200,0,0.1,0,0;
        46740,0,0.1,0,0; 46800,0,0.1,0,0; 50340,0,0.1,0,0; 50400,0.6,0.6,1,1;
        53940,0.6,0.6,1,1; 54000,1,1,1,1; 57540,1,1,1,1; 57600,0.4,0.4,1,1;
        61140,0.4,0.4,1,1; 61200,0,0.1,0,0; 64740,0,0.1,0,0; 64800,0,0.1,0,0;
        68340,0,0.1,0,0; 68400,0,0.1,0,0; 71940,0,0.1,0,0; 72000,0,0.1,0,0;
        75540,0,0.1,0,0; 75600,0,0.1,0,0; 79140,0,0.1,0,0; 79200,0,0.1,0,0;
        82740,0,0.1,0,0; 82800,0,0.1,0,0; 86340,0,0.1,0,0; 86400,0,0.1,0,0;
        89940,0,0.1,0,0; 90000,0,0.1,0,0; 93540,0,0.1,0,0; 93600,0,0.1,0,0;
        97140,0,0.1,0,0; 97200,0,0.1,0,0; 100740,0,0.1,0,0; 100800,0,0.1,0,0;
        104340,0,0.1,0,0; 104400,0,0.1,0,0; 107940,0,0.1,0,0; 108000,0,0.1,0,0;
        111540,0,0.1,0,0; 111600,0,0.1,0,0; 115140,0,0.1,0,0; 115200,0,0.1,0,0;
        118740,0,0.1,0,0; 118800,0.6,0.6,1,1; 122340,0.6,0.6,1,1; 122400,1,1,1,
        1; 125940,1,1,1,1; 126000,0.4,0.4,1,1; 129540,0.4,0.4,1,1; 129600,0,0.1,
        0,0; 133140,0,0.1,0,0; 133200,0,0.1,0,0; 136740,0,0.1,0,0; 136800,0.6,
        0.6,1,1; 140340,0.6,0.6,1,1; 140400,1,1,1,1; 143940,1,1,1,1; 144000,0.4,
        0.4,1,1; 147540,0.4,0.4,1,1; 147600,0,0.1,0,0; 151140,0,0.1,0,0; 151200,
        0,0.1,0,0; 154740,0,0.1,0,0; 154800,0,0.1,0,0; 158340,0,0.1,0,0; 158400,
        0,0.1,0,0; 161940,0,0.1,0,0; 162000,0,0.1,0,0; 165540,0,0.1,0,0; 165600,
        0,0.1,0,0; 169140,0,0.1,0,0; 169200,0,0.1,0,0; 172740,0,0.1,0,0; 172800,
        0,0.1,0,0; 176340,0,0.1,0,0; 176400,0,0.1,0,0; 179940,0,0.1,0,0; 180000,
        0,0.1,0,0; 183540,0,0.1,0,0; 183600,0,0.1,0,0; 187140,0,0.1,0,0; 187200,
        0,0.1,0,0; 190740,0,0.1,0,0; 190800,0,0.1,0,0; 194340,0,0.1,0,0; 194400,
        0,0.1,0,0; 197940,0,0.1,0,0; 198000,0,0.1,0,0; 201540,0,0.1,0,0; 201600,
        0,0.1,0,0; 205140,0,0.1,0,0; 205200,0.6,0.6,1,1; 208740,0.6,0.6,1,1;
        208800,1,1,1,1; 212340,1,1,1,1; 212400,0.4,0.4,1,1; 215940,0.4,0.4,1,1;
        216000,0,0.1,0,0; 219540,0,0.1,0,0; 219600,0,0.1,0,0; 223140,0,0.1,0,0;
        223200,0.6,0.6,1,1; 226740,0.6,0.6,1,1; 226800,1,1,1,1; 230340,1,1,1,1;
        230400,0.4,0.4,1,1; 233940,0.4,0.4,1,1; 234000,0,0.1,0,0; 237540,0,0.1,
        0,0; 237600,0,0.1,0,0; 241140,0,0.1,0,0; 241200,0,0.1,0,0; 244740,0,0.1,
        0,0; 244800,0,0.1,0,0; 248340,0,0.1,0,0; 248400,0,0.1,0,0; 251940,0,0.1,
        0,0; 252000,0,0.1,0,0; 255540,0,0.1,0,0; 255600,0,0.1,0,0; 259140,0,0.1,
        0,0; 259200,0,0.1,0,0; 262740,0,0.1,0,0; 262800,0,0.1,0,0; 266340,0,0.1,
        0,0; 266400,0,0.1,0,0; 269940,0,0.1,0,0; 270000,0,0.1,0,0; 273540,0,0.1,
        0,0; 273600,0,0.1,0,0; 277140,0,0.1,0,0; 277200,0,0.1,0,0; 280740,0,0.1,
        0,0; 280800,0,0.1,0,0; 284340,0,0.1,0,0; 284400,0,0.1,0,0; 287940,0,0.1,
        0,0; 288000,0,0.1,0,0; 291540,0,0.1,0,0; 291600,0.6,0.6,1,1; 295140,0.6,
        0.6,1,1; 295200,1,1,1,1; 298740,1,1,1,1; 298800,0.4,0.4,1,1; 302340,0.4,
        0.4,1,1; 302400,0,0.1,0,0; 305940,0,0.1,0,0; 306000,0,0.1,0,0; 309540,0,
        0.1,0,0; 309600,0.6,0.6,1,1; 313140,0.6,0.6,1,1; 313200,1,1,1,1; 316740,
        1,1,1,1; 316800,0.4,0.4,1,1; 320340,0.4,0.4,1,1; 320400,0,0.1,0,0;
        323940,0,0.1,0,0; 324000,0,0.1,0,0; 327540,0,0.1,0,0; 327600,0,0.1,0,0;
        331140,0,0.1,0,0; 331200,0,0.1,0,0; 334740,0,0.1,0,0; 334800,0,0.1,0,0;
        338340,0,0.1,0,0; 338400,0,0.1,0,0; 341940,0,0.1,0,0; 342000,0,0.1,0,0;
        345540,0,0.1,0,0; 345600,0,0.1,0,0; 349140,0,0.1,0,0; 349200,0,0.1,0,0;
        352740,0,0.1,0,0; 352800,0,0.1,0,0; 356340,0,0.1,0,0; 356400,0,0.1,0,0;
        359940,0,0.1,0,0; 360000,0,0.1,0,0; 363540,0,0.1,0,0; 363600,0,0.1,0,0;
        367140,0,0.1,0,0; 367200,0,0.1,0,0; 370740,0,0.1,0,0; 370800,0,0.1,0,0;
        374340,0,0.1,0,0; 374400,0,0.1,0,0; 377940,0,0.1,0,0; 378000,0.6,0.6,1,
        1; 381540,0.6,0.6,1,1; 381600,1,1,1,1; 385140,1,1,1,1; 385200,0.4,0.4,1,
        1; 388740,0.4,0.4,1,1; 388800,0,0.1,0,0; 392340,0,0.1,0,0; 392400,0,0.1,
        0,0; 395940,0,0.1,0,0; 396000,0.6,0.6,1,1; 399540,0.6,0.6,1,1; 399600,1,
        1,1,1; 403140,1,1,1,1; 403200,0.4,0.4,1,1; 406740,0.4,0.4,1,1; 406800,0,
        0.1,0,0; 410340,0,0.1,0,0; 410400,0,0.1,0,0; 413940,0,0.1,0,0; 414000,0,
        0.1,0,0; 417540,0,0.1,0,0; 417600,0,0.1,0,0; 421140,0,0.1,0,0; 421200,0,
        0.1,0,0; 424740,0,0.1,0,0; 424800,0,0.1,0,0; 428340,0,0.1,0,0; 428400,0,
        0.1,0,0; 431940,0,0.1,0,0; 432000,0,0,0,0; 435540,0,0,0,0; 435600,0,0,0,
        0; 439140,0,0,0,0; 439200,0,0,0,0; 442740,0,0,0,0; 442800,0,0,0,0;
        446340,0,0,0,0; 446400,0,0,0,0; 449940,0,0,0,0; 450000,0,0,0,0; 453540,
        0,0,0,0; 453600,0,0,0,0; 457140,0,0,0,0; 457200,0,0,0,0; 460740,0,0,0,0;
        460800,0,0,0,0; 464340,0,0,0,0; 464400,0,0,0,0; 467940,0,0,0,0; 468000,
        0,0,0,0; 471540,0,0,0,0; 471600,0,0,0,0; 475140,0,0,0,0; 475200,0,0,0,0;
        478740,0,0,0,0; 478800,0,0,0,0; 482340,0,0,0,0; 482400,0,0,0,0; 485940,
        0,0,0,0; 486000,0,0,0,0; 489540,0,0,0,0; 489600,0,0,0,0; 493140,0,0,0,0;
        493200,0,0,0,0; 496740,0,0,0,0; 496800,0,0,0,0; 500340,0,0,0,0; 500400,
        0,0,0,0; 503940,0,0,0,0; 504000,0,0,0,0; 507540,0,0,0,0; 507600,0,0,0,0;
        511140,0,0,0,0; 511200,0,0,0,0; 514740,0,0,0,0; 514800,0,0,0,0; 518340,
        0,0,0,0; 518400,0,0,0,0; 521940,0,0,0,0; 522000,0,0,0,0; 525540,0,0,0,0;
        525600,0,0,0,0; 529140,0,0,0,0; 529200,0,0,0,0; 532740,0,0,0,0; 532800,
        0,0,0,0; 536340,0,0,0,0; 536400,0,0,0,0; 539940,0,0,0,0; 540000,0,0,0,0;
        543540,0,0,0,0; 543600,0,0,0,0; 547140,0,0,0,0; 547200,0,0,0,0; 550740,
        0,0,0,0; 550800,0,0,0,0; 554340,0,0,0,0; 554400,0,0,0,0; 557940,0,0,0,0;
        558000,0,0,0,0; 561540,0,0,0,0; 561600,0,0,0,0; 565140,0,0,0,0; 565200,
        0,0,0,0; 568740,0,0,0,0; 568800,0,0,0,0; 572340,0,0,0,0; 572400,0,0,0,0;
        575940,0,0,0,0; 576000,0,0,0,0; 579540,0,0,0,0; 579600,0,0,0,0; 583140,
        0,0,0,0; 583200,0,0,0,0; 586740,0,0,0,0; 586800,0,0,0,0; 590340,0,0,0,0;
        590400,0,0,0,0; 593940,0,0,0,0; 594000,0,0,0,0; 597540,0,0,0,0; 597600,
        0,0,0,0; 601140,0,0,0,0; 601200,0,0,0,0; 604740,0,0,0,0],
    columns={2,3,4},
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
  Modelica.Blocks.Math.Gain gain[3](k={0.8,0.8,0.8})
  Fluid.FixedResistances.HydraulicResistance hydraulicResistance(
    redeclare package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater,
    m_flow_nominal=0.02,
    zeta=10,
    diameter=0.05)

equation
  connect(hea.port_b, hea1.port_a)
  connect(hea1.port_b, fan.port_a)
  connect(bou.ports[1], fan.port_a)
  connect(heatProducerAgent.calcCapacity, constantFactor.capacity)
  connect(heatProducerAgent.calcCost, constantFactor.cost)
  connect(heatProducerAgent1.calcCapacity, constantFactor1.capacity)
  connect(heatProducerAgent1.calcCost, constantFactor1.cost)
  connect(heatProducerAgent.setCapacityOut, hea.u)
  connect(heatProducerAgent1.setCapacityOut, hea1.u)
  connect(hea1.Q_flow, heatProducerAgent1.currentCapacity)
  connect(hea.Q_flow, heatProducerAgent.currentCapacity)
  connect(booleanExpression.y, heatProducerAgent.OnOff_external)
  connect(booleanExpression.y, heatProducerAgent1.OnOff_external)
  connect(massFlowRate.y, fan.m_flow_in)
  connect(volume.ports[1], hea.port_a)
  connect(volume1.ports[1], hea.port_a)
  connect(volume.heatPort, thermalConductor.port_a)
  connect(thermalConductor1.port_a, volume1.heatPort)
  connect(PID1.y, val1.y)
  connect(val1.port_b, volume1.ports[2])
  connect(val1.port_a, fan.port_b)
  connect(val.port_b, volume.ports[2])
  connect(val.port_a, fan.port_b)
  connect(PID2.y, val.y)
  connect(roomSetPoint.y, PID1.u_s)
  connect(PID2.u_s, PID1.u_s)
  connect(hea.Q_flow, Cap_device)
  connect(hea1.Q_flow, Cap_device1)
  connect(thermalConductor.port_b, thermalZone.intGainsConv)
  connect(thermalZone.intGainsRad, thermalZone.intGainsConv)
  connect(thermalConductor1.port_b, thermalZone1.intGainsConv)
  connect(thermalZone1.intGainsRad, thermalZone1.intGainsConv)
  connect(thermalZone1.intGains, internalGains.y)
  connect(weaDat.weaBus, thermalZone.weaBus)
  connect(weaDat.weaBus, thermalZone1.weaBus)

  connect(thermalZone.TAir, roomAgent.T)
  connect(thermalZone1.TAir, roomAgent1.T)
  connect(thermalZone1.TAir, T_room1)
  connect(thermalZone1.TAir, PID1.u_m)
  connect(PID2.u_m, thermalZone.TAir)
  connect(thermalZone.TAir, T_room)
  connect(InternalHeatGain.y, gain.u)
  connect(gain.y, thermalZone.intGains)
  connect(hydraulicResistance.port_a, fan.port_b)
  connect(hydraulicResistance.port_b, hea.port_a)
end BuildingHeating;


<span style=\.

within AixLib.Controls.HVACAgentBasedControl.Examples.BuildingHeatingSystems;
model BuildingHeating_usePoke
  extends BuildingHeating(
    roomAgent(usePoke=true),
    roomAgent1(usePoke=true),
    broker(usePoke=true),
    messageNotification(usePoke=true, n=5),
    heatProducerAgent(usePoke=true),
    heatProducerAgent1(usePoke=true));
equation
  connect(roomAgent.sendOut, messageNotification.receive[1])
  connect(roomAgent1.sendOut, messageNotification.receive[2])
  connect(heatProducerAgent1.sendOut, messageNotification.receive[3])
  connect(heatProducerAgent.sendOut, messageNotification.receive[4])
  connect(broker.sendOut, messageNotification.receive[5])
end BuildingHeating_usePoke;


bar

within AixLib.Controls.HVACAgentBasedControl.Examples.BuildingHeatingSystems;
model BuildingWithPV
  extends Modelica.Icons.Example;
  package Medium = AixLib.Media.Water;

  AixLib.Fluid.HeatExchangers.HeaterCooler_u hea(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    Q_flow_nominal=1,
    dp_nominal(displayUnit="bar") = 1000)
  AixLib.Fluid.HeatExchangers.HeaterCooler_u hea1(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    dp_nominal(displayUnit="bar") = 1000,
    Q_flow_nominal=1)
  AixLib.Fluid.Movers.FlowControlled_m_flow fan(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    m_flow(start=1),
    addPowerToMedium=false)
  AixLib.Fluid.MixingVolumes.MixingVolume vol(nPorts=2,
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    V=1)
  AixLib.Fluid.MixingVolumes.MixingVolume vol1(nPorts=2,
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    V=1)
  AixLib.Fluid.Actuators.Valves.TwoWayLinear val(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    dpValve_nominal(displayUnit="bar") = 10000)
  AixLib.Fluid.Actuators.Valves.TwoWayLinear val1(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    dpValve_nominal(displayUnit="bar") = 10000)
  HVACAgentBasedControl.Agents.Broker broker(name=20001)
  HVACAgentBasedControl.Agents.HeatProducerAgent heatProducerAgent(
    name=30001,
    costCurrent(start=0),
    setCapacity(start=0),
    currentCapacityDiscrete(start=0),
    maxCapacity=3000)
  AixLib.Controls.HVACAgentBasedControl.CostFunctions.Economic.Constant_Economic_Cost constantFactor(p=0.067)
  AixLib.Controls.HVACAgentBasedControl.CostFunctions.Economic.PV_Variable_Economic_Cost variableFactorPV(
    rad_treshold=310,
    p=0.29,
    eta=1)
  HVACAgentBasedControl.Agents.HeatProducerAgent heatProducerAgent1(
    name=30002,
    costCurrent(start=0),
    setCapacity(start=0),
    currentCapacityDiscrete(start=0),
    maxCapacity=10000)
  Modelica.Blocks.Sources.RealExpression zero(y=0)
  Modelica.Thermal.HeatTransfer.Sources.FixedHeatFlow fixedHeatFlow(Q_flow=0)
  HVACAgentBasedControl.Agents.RoomAgent roomAgent(
    broker=20001,
    threshold=0.5,
    sampleRate=1,
    sampleTriggerTime=120,
    G=2)
  HVACAgentBasedControl.Agents.RoomAgent roomAgent1(
    name=10002,
    broker=20001,
    startTime=5,
    threshold=0.5,
    sampleRate=1,
    sampleTriggerTime=120,
    G=2)
  Modelica.Blocks.Continuous.LimPID PID(
    yMax=1,
    initType=Modelica.Blocks.Types.Init.InitialOutput,
    k=0.1,
    Ti=1,
    Td=0.01,
    yMin=0.2,
    y_start=0.2)
  Modelica.Blocks.Continuous.LimPID PID1(
    yMax=1,
    initType=Modelica.Blocks.Types.Init.InitialOutput,
    k=0.1,
    Ti=1,
    Td=0.01,
    yMin=0.2,
    y_start=0.2)
  Modelica.Blocks.Sources.RealExpression zero1(y=273.15 + 20)
  Modelica.Blocks.Sources.RealExpression zero2(y=1)
  Fluid.Sources.Boundary_pT          bou(nPorts=1, redeclare package Medium =
        Medium)
  inner Modelica.Fluid.System system
  Modelica.Blocks.Interfaces.RealOutput cap1
  Modelica.Blocks.Interfaces.RealOutput cap2
  Modelica.Blocks.Interfaces.RealOutput valve1
  Modelica.Blocks.Interfaces.RealOutput valve2
  Modelica.Blocks.Interfaces.RealOutput T1
  Modelica.Blocks.Interfaces.RealOutput T2
  AixLib.Fluid.Sensors.Temperature senTem(redeclare package Medium = Medium)
  Modelica.Blocks.Interfaces.RealOutput T_return
  Modelica.Blocks.Logical.LessThreshold lessThreshold(threshold=273.15 + 60)
  Modelica.Blocks.Math.UnitConversions.To_degC to_degC
  Modelica.Blocks.Math.UnitConversions.To_degC to_degC1
  Modelica.Blocks.Math.UnitConversions.To_degC to_degC2
  Modelica.Blocks.Interfaces.RealOutput T_air
  Modelica.Blocks.Math.UnitConversions.To_degC to_degC3
  Modelica.Blocks.Interfaces.BooleanOutput electricity_free
  Modelica.Blocks.Logical.And and1
  Modelica.Blocks.Logical.Or or1
  Modelica.Blocks.Logical.GreaterEqualThreshold greaterEqualThreshold(threshold=
       2999)
  inner HVACAgentBasedControl.Agents.MessageNotification messageNotification

  BoundaryConditions.WeatherData.ReaderTMY3        weaDat(
    calTSky=AixLib.BoundaryConditions.Types.SkyTemperatureCalculation.HorizontalRadiation,
    computeWetBulbTemperature=false,
    filNam=Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
    "Weather data reader"
  ThermalZones.ReducedOrder.ThermalZone.ThermalZone
              thermalZone(redeclare package Medium =
        Modelica.Media.Air.SimpleAir,
    redeclare AixLib.DataBase.ThermalZones.OfficePassiveHouse.OPH_1_OfficeNoHeaterCooler zoneParam)
  ThermalZones.ReducedOrder.ThermalZone.ThermalZone
              thermalZone1(redeclare package Medium =
        Modelica.Media.Air.SimpleAir,
        redeclare AixLib.DataBase.ThermalZones.OfficePassiveHouse.OPH_1_OfficeNoHeaterCooler zoneParam)
  BoundaryConditions.WeatherData.Bus        weaBus
    "Weather data bus"
  Modelica.Blocks.Sources.Constant internalGains[3](k={0,0,0})
  Fluid.FixedResistances.HydraulicResistance hydraulicResistance1(
    redeclare package Medium = Medium,
    m_flow_nominal=0.02,
    zeta=10,
    diameter=0.05)
  Fluid.FixedResistances.HydraulicResistance hydraulicResistance(
    redeclare package Medium = Medium,
    m_flow_nominal=0.02,
    zeta=10,
    diameter=0.05)
equation
  connect(fan.port_a, hea1.port_b)
  connect(fan.port_b, val.port_a)
  connect(val.port_b, vol1.ports[1])
  connect(val1.port_b, vol.ports[1])
  connect(fan.port_b, val1.port_a)
  connect(vol.ports[2], hea.port_a)
  connect(vol1.ports[2], hea.port_a)
  connect(heatProducerAgent.calcCapacity, constantFactor.capacity)
  connect(heatProducerAgent.calcCost, constantFactor.cost)
  connect(heatProducerAgent.setCapacityOut, hea.u)
  connect(hea.Q_flow, heatProducerAgent.currentCapacity)
  connect(hea1.u, heatProducerAgent1.setCapacityOut)
  connect(hea1.Q_flow, heatProducerAgent1.currentCapacity)
  connect(heatProducerAgent1.calcCapacity, variableFactorPV.capacity)
  connect(variableFactorPV.cost, heatProducerAgent1.calcCost)

  connect(PID1.u_m, roomAgent1.T)
  connect(PID.u_s, zero1.y)
  connect(PID1.u_s, zero1.y)
  connect(PID.y, val1.y)
  connect(PID1.y, val.y)
  connect(fan.m_flow_in, zero2.y)
  connect(fixedHeatFlow.port, fan.heatPort)
  connect(bou.ports[1], fan.port_a)
  connect(hea1.Q_flow, cap2)
  connect(hea.Q_flow, cap1)
  connect(val.y_actual, valve1)
  connect(valve2, val1.y_actual)
  connect(senTem.port, hea.port_a)
  connect(senTem.T, lessThreshold.u)
  connect(lessThreshold.y, heatProducerAgent.OnOff_external)
  connect(T_return, to_degC.y)
  connect(senTem.T, to_degC.u)
  connect(T2, to_degC1.y)
  connect(T1, to_degC2.y)
  connect(to_degC3.y, T_air)
  connect(variableFactorPV.electricity_free, electricity_free)
  connect(and1.u1, lessThreshold.y)
  connect(electricity_free, and1.u2)
  connect(greaterEqualThreshold.y, or1.u1)
  connect(heatProducerAgent.setCapacityOut, greaterEqualThreshold.u)
  connect(or1.u2, and1.y)
  connect(or1.y, heatProducerAgent1.OnOff_external)
  connect(weaDat.weaBus, thermalZone1.weaBus)
  connect(weaDat.weaBus,thermalZone. weaBus)
  connect(weaDat.weaBus, weaBus)
  connect(variableFactorPV.rad, weaBus.HGloHor)
  connect(vol.heatPort, thermalZone.intGainsConv)
  connect(vol.heatPort, thermalZone.intGainsRad)
  connect(vol1.heatPort, thermalZone1.intGainsConv)
  connect(vol1.heatPort, thermalZone1.intGainsRad)
  connect(thermalZone.intGains, internalGains.y)
  connect(thermalZone1.intGains, internalGains.y)
  connect(roomAgent.T, PID.u_m)
  connect(thermalZone1.TAir, roomAgent1.T)
  connect(thermalZone.TAir, roomAgent.T)
  connect(to_degC3.u, weaBus.TDryBul)
  connect(to_degC1.u, roomAgent.T)
  connect(to_degC2.u, roomAgent1.T)
  connect(fan.port_b, hydraulicResistance1.port_a)
  connect(hydraulicResistance1.port_b, hea.port_a)
  connect(hea.port_b, hydraulicResistance.port_a)
  connect(hydraulicResistance.port_b, hea1.port_a)
end BuildingWithPV;


High Temperature Circuit
. Overview

within AixLib.Controls.HVACAgentBasedControl.Examples.HVACAgentsCommunications;
model SimpleCommunication
  extends Modelica.Icons.Example;

  Agents.ConsumerAgent roomAgent_C(broker=20001, sampleTrigger(period=100))
  Modelica.Blocks.Sources.TimeTable timeTable(table=[0.0,5000; 20,5000; 30,
        5000; 50,5000; 70,5000; 90,5000])
  Agents.Broker broker_LTC(name=20001, startTable=[30001,0,0,0,0,0,0; 30002,0,
        0,0,0,0,0])
  Agents.IntermediateAgent   intermediateAgent_C(name=30001, broker=40001,
    setCapacity(start=3000))
  Agents.Broker broker_HTC(name=40001, startTable=[40002,0,0,0,0,0,0; 40003,0,
        0,0,0,0,0])
  Agents.HeatProducerAgent heatProducerAgent(setCapacity(start=3000), name=40002)
  Agents.HeatProducerAgent heatProducerAgent1(
    name=30002,
    setCapacity(start=1000),
    maxCapacity=2000)
  Agents.HeatProducerAgent heatProducerAgent2(name=40003, setCapacity(start=4000))
  Modelica.Blocks.Sources.BooleanExpression onOff(y=true)
  Modelica.Blocks.Sources.RealExpression cost(y=100)
  Modelica.Blocks.Sources.RealExpression capacity(y=1)
  inner Agents.MessageNotification messageNotification
  AixLib.Controls.HVACAgentBasedControl.CostFunctions.Economic.Constant_Economic_Cost constantFactor(p=1, eta=1)
  AixLib.Controls.HVACAgentBasedControl.CostFunctions.Economic.Constant_Economic_Cost constantFactor1(eta=1, p=2)
  AixLib.Controls.HVACAgentBasedControl.CostFunctions.Economic.Constant_Economic_Cost constantFactor2(eta=1, p=0.5)
equation
  connect(onOff.y, heatProducerAgent.OnOff_external)
  connect(onOff.y, intermediateAgent_C.OnOff_external)
  connect(onOff.y, heatProducerAgent1.OnOff_external)
  connect(cost.y, intermediateAgent_C.calcCost)
  connect(capacity.y, intermediateAgent_C.currentCapacity)
  connect(capacity.y, heatProducerAgent1.currentCapacity)
  connect(capacity.y, heatProducerAgent2.currentCapacity)
  connect(heatProducerAgent.currentCapacity, heatProducerAgent2.currentCapacity)
  connect(timeTable.y, roomAgent_C.demand)
  connect(onOff.y, heatProducerAgent2.OnOff_external)
  connect(heatProducerAgent.calcCapacity, constantFactor.capacity)
  connect(heatProducerAgent.calcCost, constantFactor.cost)
  connect(heatProducerAgent2.calcCapacity, constantFactor1.capacity)
  connect(constantFactor1.cost, heatProducerAgent2.calcCost)
  connect(heatProducerAgent1.calcCapacity, constantFactor2.capacity)
  connect(heatProducerAgent1.calcCost, constantFactor2.cost)
end SimpleCommunication;


within AixLib.Controls;
package Interfaces "Contains interfaces for connection to physical and automation system"
extends Modelica.Icons.InterfacesPackage;
end Interfaces;


Model of a heating curve. Model of a heating curve. Either based on table input data or with a
  function, the set temperature for the heating system is calculated.

within AixLib.Controls.SetPoints;
model HeatingCurve "Model of a heating curve"
  //General
  parameter Boolean use_tableData=true "Choose between tables or function to calculate TSet"
  parameter Modelica.Units.SI.ThermodynamicTemperature TOffset(displayUnit="K")
     = 0 "Offset to heating curve temperature"
  //Function
  replaceable function HeatingCurveFunction =
      AixLib.Controls.SetPoints.Functions.PartialBaseFct                 "Function to calculate set temperature"
  //Table Data
  parameter AixLib.DataBase.Boiler.DayNightMode.HeatingCurvesDayNightBaseDataDefinition heatingCurveRecord
    "Record with information about heating curve data"
  parameter Real declination=1 "Declination of curve"

  //Dynamic room temperature
  parameter Boolean use_dynTRoom=true "If different room temperatures are required, set to true"
  parameter Modelica.Units.SI.ThermodynamicTemperature TRoom_nominal=293.15
    "Constant desired room temperature "
  //Day-Night Mode:
  parameter AixLib.Utilities.Time.Types.ZeroTime zerTim=AixLib.Utilities.Time.Types.ZeroTime.Custom
    "Enumeration for choosing how reference time (time = 0) should be defined"
  parameter Real day_hour=6 "Hour of day at which day mode is enabled"
  parameter Real night_hour=22 "Hour of day at which night mode is enabled"

  Modelica.Blocks.Interfaces.RealInput T_oda(unit="K") "Outdoor air temperature"
  Modelica.Blocks.Interfaces.RealInput TRoom_in(unit="K") if use_dynTRoom
                                                "Desired room temperature"
  Modelica.Blocks.Interfaces.RealOutput TSet(unit="K")
    "Set temperature calculated by heating curve"

protected
  Modelica.Blocks.Tables.CombiTable2Ds tableDay(
    final tableOnFile=false,
    final table=heatingCurveRecord.varFlowTempDay,
    final smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments)
    if use_tableData "Combi Table for day data";

  Modelica.Blocks.Tables.CombiTable2Ds tableNight(
    final tableOnFile=false,
    final table=heatingCurveRecord.varFlowTempNight,
    final smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments)
    if use_tableData "Combi Table for night data";

  Modelica.Blocks.Interfaces.RealOutput TSet_internal "Internal set temperature";
  Modelica.Blocks.Sources.RealExpression TRoomExp(y=TRoom_nominal) "Real expression for room temperature";
  Modelica.Blocks.Sources.Constant dec(k=declination) "Declination constant for connectors";
  AixLib.Utilities.Time.CalendarTime calTime(zerTim = zerTim) "Calendar-time to get current hour";
  Modelica.Blocks.Interfaces.RealInput TRoom_internal "Actual room temperature to calculate with";
  Modelica.Blocks.Math.UnitConversions.To_degC to_degC if use_tableData
                                                                       "Convert Kelvin to degC";
  AixLib.Utilities.Logical.SmoothSwitch dayNightSwitch if use_tableData "Switch between day and night mode";
  Modelica.Blocks.Interfaces.BooleanOutput isDay "Boolean to evaluate whether it is daytime or nighttime";

equation
  //Connect the room temperatures
  if use_dynTRoom then
    connect(TRoom_internal,TRoom_in);
  else
    connect(TRoom_internal,TRoomExp.y);
  end if;
  //Evaluate whether current time is daytime or nighttime
  if calTime.hour >= day_hour and calTime.hour < night_hour then
    isDay = true;
  else
    isDay = false;
  end if;
  //Convert Kelvin to degC for tables and function
  //Connect all models if tables are used, else use the function to calculate the internal set temperature
  if use_tableData then
    connect(T_oda, to_degC.u);
    connect(dec.y, tableDay.u2);
    connect(dec.y, tableNight.u2);
    connect(to_degC.y, tableDay.u1);
    connect(to_degC.y, tableNight.u1);
    connect(tableDay.y, dayNightSwitch.u1);
    connect(isDay, dayNightSwitch.u2);
    connect(tableNight.y, dayNightSwitch.u3);
    connect(dayNightSwitch.y, TSet_internal);
  else
    TSet_internal = HeatingCurveFunction(
      T_oda,
      TRoom_internal,
      isDay);
  end if;
  //Check if current outdoor air temperature is higher than the needed room temperature. If so, no heating is required
  //Else the needed offset is added and the temperature is adjusted according to the wished room temperature
  if T_oda >= TRoom_internal then
    TSet = TRoom_internal;
  else
    TSet =(TSet_internal + TOffset) + 273.15;
  end if;
end HeatingCurve;


Occupancy schedule with look-ahead. This model outputs whether the building is currently occupied,
and how long it will take until the next time when the building
will be occupied or non-occupied.
The latter may be used, for example, to start a ventilation system
half an hour before occupancy starts in order to ventilate the room.

within AixLib.Controls.SetPoints;
block OccupancySchedule "Occupancy schedule with look-ahead"
  extends Modelica.Blocks.Icons.Block;

  parameter Real occupancy[:]=3600*{7, 19}
    "Occupancy table, each entry switching occupancy on or off";
  parameter Boolean firstEntryOccupied = true
    "Set to true if first entry in occupancy denotes a changed from unoccupied to occupied";
  parameter Modelica.Units.SI.Time period=86400 "End time of periodicity";

  Modelica.Blocks.Interfaces.RealOutput tNexNonOcc
    "Time until next non-occupancy"
  Modelica.Blocks.Interfaces.RealOutput tNexOcc "Time until next occupancy"
  Modelica.Blocks.Interfaces.BooleanOutput occupied
    "Outputs true if occupied at current time"

protected
  final parameter Integer nRow = size(occupancy,1)
    "Number of rows in the schedule";

  discrete Modelica.Units.SI.Time tOcc "Time when next occupancy starts";
  discrete Modelica.Units.SI.Time tNonOcc "Time when next non-occupancy starts";
  discrete Modelica.Units.SI.Time tNext "Time of next switch in schedule";

  function getOutput "Get the next occupancy or non-occupancy outputs"
    extends Modelica.Icons.Function;

    input Modelica.Units.SI.Time t "Current model time";
    input Modelica.Units.SI.Time period "Periodicity";
    input Real occupancy[nRow]
      "Occupancy table, each entry switching occupancy on or off";
    input Boolean firstEntryOccupied
      "Set to true if first entry in occupancy denotes a changed from unoccupied to occupied";
    input Integer nRow
      "Number of rows in the schedule";

    output Modelica.Units.SI.Time tOcc "Time when next occupancy starts";
    output Modelica.Units.SI.Time tNonOcc "Time when next non-occupancy starts";
    output Boolean occupied
    "Outputs true if occupied at current time";
    output Modelica.Units.SI.Time tNext "Time of next switch in schedule";

  protected
    Integer iPerSta
      "Counter for the period in which the next occupancy starts";
    Integer iPerSto
      "Counter for the period in which the next occupancy stops";
    Integer nexStaInd "Next index when occupancy starts";
    Integer nexStoInd "Next index when occupancy stops";
  algorithm
    // Initialize variables
    iPerSta := integer(t/period);
    iPerSto := iPerSta;

    // First, assume that the first entry is occupied
    nexStaInd := 1;
    nexStoInd := 2;
    // nRow is an even number
    for
     i in 1:2:nRow-1 loop
   if t >= occupancy[i] + iPerSta*period then
     nexStaInd := i+2;
   end if;
    end for;
    for
     i in 2:2:nRow loop
   if t >= occupancy[i] + iPerSto*period then
     nexStoInd := i+2;
   end if;
    end for;
    if nexStaInd > nRow then
    nexStaInd := 1;
    iPerSta :=iPerSta + 1;
    end if;
    if nexStoInd > nRow then
    nexStoInd := 2;
    iPerSto :=iPerSto + 1;
    end if;
    tOcc := occupancy[nexStaInd] + iPerSta*period;
    tNonOcc := occupancy[nexStoInd] + iPerSto*period;

    occupied := tNonOcc < tOcc;
    // Now, correct if the first entry is vaccant instead of occupied
    if not firstEntryOccupied then
     (nexStaInd, nexStoInd) := switchInteger(nexStaInd, nexStoInd);
     (iPerSta, iPerSto)     := switchInteger(iPerSta,   iPerSto);
     (tOcc, tNonOcc)        := switchReal(tOcc,      tNonOcc);
   occupied := not occupied;
    end if;

   tNext :=min(tOcc, tNonOcc);
  end getOutput;

encapsulated function switchInteger "Switch two Integer arguments"
  import Modelica;
  extends Modelica.Icons.Function;
  input Integer x1 "First argument";
  input Integer x2 "Second argument";
  output Integer y1 "Output = x2";
  output Integer y2 "Output = x1";
algorithm
  y1:=x2;
  y2:=x1;
end switchInteger;

encapsulated function switchReal "Switch two Real arguments"
  import Modelica;
  extends Modelica.Icons.Function;
  input Real x1 "First argument";
  input Real x2 "Second argument";
  output Real y1 "Output = x2";
  output Real y2 "Output = x1";
algorithm
  y1:=x2;
  y2:=x1;
end switchReal;

initial equation
  // Check parameters for correctness
 assert(mod(nRow, 2) < 0.1,
   "The parameter \"occupancy\" must have an even number of elements.\n");
 assert(0 <= occupancy[1],
   "The first element of \"occupancy\" must be bigger than or equal to zero."
   + "\n   Received occupancy[1] = " + String(occupancy[1]));
 assert(period >= occupancy[nRow],
   "The parameter \"period\" must be greater than or equal to the last element of \"occupancy\"."
   + "\n   Received period      = " + String(period)
   + "\n            occupancy[" + String(nRow) +
     "] = " + String(occupancy[nRow]));
  for i in 1:nRow-1 loop
    assert(occupancy[i] < occupancy[i+1],
      "The elements of the parameter \"occupancy\" must be strictly increasing.");
  end for;

  (tOcc, tNonOcc, occupied, tNext) = getOutput(t = time, period = period, occupancy= occupancy, firstEntryOccupied = firstEntryOccupied, nRow=nRow);

equation
  when time >= pre(tNext) then
    (tOcc, tNonOcc, occupied, tNext) = getOutput(t = time, period = period, occupancy= occupancy, firstEntryOccupied = firstEntryOccupied, nRow=nRow);
  end when;

 tNexOcc    =  tOcc-time;
 tNexNonOcc =  tNonOcc-time;
end OccupancySchedule;


within AixLib.Controls;
package SetPoints "Package with models for control set points"
  extends Modelica.Icons.VariantsPackage;
end SetPoints;


Block to compute the supply and return set point. This block computes the set point temperatures for the
supply and return water temperature.
The set point for the room air temperature can either be specified
by a parameter, or it can be an input to the model. The latter allows
to use this model with systems that have night set back.

within AixLib.Controls.SetPoints;
block SupplyReturnTemperatureReset
  "Block to compute the supply and return set point"
  extends Modelica.Blocks.Icons.Block;

  parameter Real m = 1.3 "Exponent for heat transfer";
  parameter Modelica.Units.SI.Temperature TSup_nominal "Supply temperature"
  parameter Modelica.Units.SI.Temperature TRet_nominal "Return temperature"
  parameter Modelica.Units.SI.Temperature TRoo_nominal=293.15
    "Room temperature"
  parameter Modelica.Units.SI.Temperature TOut_nominal "Outside temperature"

  parameter Boolean use_TRoo_in = false
    "Get the room temperature set point from the input connector"
  parameter Modelica.Units.SI.Temperature TRoo=293.15
    "Fixed value of room temperature set point"
  parameter Modelica.Units.SI.TemperatureDifference dTOutHeaBal(displayUnit="K")
     = 8 "Offset for heating curve";
  Modelica.Blocks.Interfaces.RealInput TRoo_in(final quantity="ThermodynamicTemperature",
                                               final unit = "K", displayUnit = "degC", min=0)
       if use_TRoo_in "Room air temperature set point"

  Modelica.Blocks.Interfaces.RealInput TOut(final quantity="ThermodynamicTemperature",
                                            final unit = "K", displayUnit = "degC", min=0)
    "Outside temperature"
  Modelica.Blocks.Interfaces.RealOutput TSup(final quantity="ThermodynamicTemperature",
                                            final unit = "K", displayUnit = "degC", min=0)
    "Setpoint for supply temperature"
  Modelica.Blocks.Interfaces.RealOutput TRet(final quantity="ThermodynamicTemperature",
                                            final unit = "K", displayUnit = "degC", min=0)
    "Setpoint for return temperature"

protected
  Modelica.Blocks.Interfaces.RealInput TRoo_in_internal(final quantity="ThermodynamicTemperature",
                                                        final unit = "K", displayUnit = "degC", min=0)
    "Needed to connect to conditional connector";
  Real qRel "Relative heating load = Q_flow/Q_flow_nominal";
  Modelica.Units.SI.Temperature TOutOffSet
    "Effective outside temperature for heat transfer (takes into account room heat gains)";
  parameter Modelica.Units.SI.Temperature TOutOffSet_nominal=TOut_nominal +
      dTOutHeaBal
    "Effective outside temperature for heat transfer at nominal conditions (takes into account room heat gains)";

equation
  connect(TRoo_in, TRoo_in_internal);
  if not use_TRoo_in then
    TRoo_in_internal = TRoo;
  end if;
 TOutOffSet = TOut + dTOutHeaBal;
 // Relative heating load, compared to nominal conditions
 qRel = max(0, (TRoo_in_internal-TOutOffSet)/(TRoo_nominal-TOutOffSet_nominal));
 TSup = TRoo_in_internal
          + ((TSup_nominal+TRet_nominal)/2-TRoo_nominal) * qRel^(1/m)
          + (TSup_nominal-TRet_nominal)/2 * qRel;
 TRet = TSup - qRel * (TSup_nominal-TRet_nominal);
end SupplyReturnTemperatureReset;


Model for a set point that is interpolated based on a user-specified table. This block can be used to schedule a set-point by using piecewise linear functions.
For example, the instances

within AixLib.Controls.SetPoints;
model Table
  "Model for a set point that is interpolated based on a user-specified table"
  extends Modelica.Blocks.Interfaces.SISO;
  parameter Real table[:,2]=fill(0.0, 1, 2)
    "Table matrix ( e.g., table=[u1, y1; u2, y2; u3, y3])";

  parameter Real offset=0 "Offset of output signal";

  parameter Boolean constantExtrapolation = true
    "If true, then y=y1 for u<u1, and y=yMax for u>uMax";

protected
  final parameter Integer nRow = if constantExtrapolation then
                        size(table,1)+2 else
                        size(table,1) "Number of rows";
  final parameter Real[nRow,2] offsetVector = [zeros(nRow), offset*ones(nRow)]
    "Vector to take offset of output signal into account";
  Modelica.Blocks.Tables.CombiTable1Dv tab(tableOnFile=false, final table=(if
        constantExtrapolation then cat(
        1,
        [table[1, 1] - 1,table[1, 2]],
        table,
        [table[end, 1] + 1,table[end, 2]]) else table) + offsetVector)
    "Table used for interpolation"
equation
  connect(u, tab.u[1])

  connect(tab.y[1], y)
AixLib.Controls.SetPoints.Table tabConExt(constantExtrapolation=true,
                                             table=[20, 0.0;
                                                    22, 0.5;
                                                    25, 0.5;
                                                    26, 1.0]);

will cause the following output:

For the default setting constantExtrapolation=true, the
block outputs
y=y1+offset for u ≤ u1, and
y=yMax+offset for u ≥ uMax.
Otherwise, the table is linearly extrapolated with a constant derivative.

Note that the first column must be strictly increasing.

",
revisions="

August 30, 2016, by Michael Wetter:

Changed protected final parameter nCol to nRow.

This is for
issue 555.

April 5, 2011, by Michael Wetter:

Fixed wrong table declaration.

July 13, 2010, by Michael Wetter:

First implementation.

"),
    Icon(graphics={
    Text(
      extent={{-78,-45},{-40,-56}},
      textColor={0,0,0},
      textString="offset"),
    Line(
      points={{-42,-24},{-42,-74}},
      color={95,95,95},
      thickness=0.25,
      arrow={Arrow.None,Arrow.None}),
    Line(
      points={{-82,-24},{-22,-24},{26,24}},
      color={0,0,255},
      thickness=0.5),
    Line(points={{-82,64},{-82,-84}}, color={95,95,95}),
    Text(
      extent={{-80,88},{-39,68}},
      textColor={0,0,0},
      textString="y"),
    Polygon(
      points={{-82,86},{-88,64},{-76,64},{-82,86}},
      lineColor={95,95,95},
      fillColor={95,95,95},
      fillPattern=FillPattern.Solid),
    Polygon(
      points={{88,-74},{66,-68},{66,-80},{88,-74}},
      lineColor={95,95,95},
      fillColor={95,95,95},
      fillPattern=FillPattern.Solid),
    Line(points={{-92,-74},{80,-74}}, color={95,95,95}),
    Text(
      extent={{68,-84},{92,-95}},
      textColor={0,0,0},
          textString="u"),
    Polygon(
      points={{-42,-24},{-44,-34},{-39,-34},{-42,-24}},
      lineColor={95,95,95},
      fillColor={95,95,95},
      fillPattern=FillPattern.Solid),
    Polygon(
      points={{-42,-74},{-45,-64},{-40,-64},{-42,-74},{-42,-74}},
      lineColor={95,95,95},
      fillColor={95,95,95},
      fillPattern=FillPattern.Solid),
    Line(
      points={{26,24},{77,24}},
      color={0,0,255},
      thickness=0.5)}),
   __Dymola_LockedEditing="Model from IBPSA");
end Table;


Test model for occupancy schedule with look-ahead. Example that demonstrates the use of the occupancy schedule.
The figure below shows how the time until the next occupancy starts or ends
is decreased. The red line hits zero when the schedule indicates an occupied time,
and the blue line hits zero when the schedule indicates a non-occupied time.

within AixLib.Controls.SetPoints.Examples;
model OccupancySchedule "Test model for occupancy schedule with look-ahead"
  extends Modelica.Icons.Example;
  AixLib.Controls.SetPoints.OccupancySchedule occSchDay "Day schedule"
  AixLib.Controls.SetPoints.OccupancySchedule occSchWee(occupancy=3600*{7,19,
        31,43,55,67,79,91,103,115,127,139}, period=7*24*3600) "Week schedule"
end OccupancySchedule;


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


Test model for the heating curve. Example that demonstrates the use of the hot water temperature reset
for a heating system.
The parameters of the block heaCur
are for a heating system with
60°C supply water temperature and
40°C return water temperature at
an outside temperature of
-10°C and a room temperature of
20°C. The offset for the temperature reset is
8 Kelvin, i.e., above
12°C outside temperature, there is no heating load.
The figure below shows the computed supply and return water temperatures.

within AixLib.Controls.SetPoints.Examples;
model SupplyReturnTemperatureReset "Test model for the heating curve"
  extends Modelica.Icons.Example;
  AixLib.Controls.SetPoints.SupplyReturnTemperatureReset heaCur(
    m=1,
    TSup_nominal=333.15,
    TRet_nominal=313.15,
    TOut_nominal=263.15)
    "Temperature reset"
  Modelica.Blocks.Sources.Ramp TOut(
    height=40,
    duration=1,
    offset=263.15)
    "Signal for outside air temperature"
  AixLib.Controls.SetPoints.SupplyReturnTemperatureReset heaCur1(
    m=1,
    use_TRoo_in=true,
    TSup_nominal=333.15,
    TRet_nominal=313.15,
    TOut_nominal=263.15,
    dTOutHeaBal=15)
    "Temperature reset that uses room temperature as input"
  Modelica.Blocks.Sources.Step TRoo(
    offset=273.15 + 20,
    startTime=0.5,
    height=-5) "Night set back from 20 to 15 deg C"
  Modelica.Blocks.Sources.Constant TOut2(k=273.15 - 10)
   "Constant signal for outdoor air temperature"
equation
  connect(TOut.y, heaCur.TOut)
  connect(TOut2.y, heaCur1.TOut)
  connect(TRoo.y, heaCur1.TRoo_in)
end SupplyReturnTemperatureReset;


Test model for table that determines set points. Example that demonstrates the use of the block

AixLib.Controls.SetPoints.Table.

within AixLib.Controls.SetPoints.Examples;
model Table "Test model for table that determines set points"
  extends Modelica.Icons.Example;
  AixLib.Controls.SetPoints.Table tabConExt(table=[20,0; 22,0.5; 25,0.5; 26,1])
  Modelica.Blocks.Sources.Ramp TRoo(
    duration=1,
    offset=15,
    height=15)
  AixLib.Controls.SetPoints.Table tabLinExt(constantExtrapolation=false, table=[
        20,0; 22,0.5; 25,0.5; 26,1])
equation
  connect(TRoo.y, tabLinExt.u)
  connect(TRoo.y, tabConExt.u)
end Table;


within AixLib.Controls.SetPoints;
package Functions "Package with functions for pacakge AixLib.Controls.HeatPump"
end Functions;