Model that checks the correct implementation of the 2nd order derivative of the flow function. This model validates the implementation of

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_dp
and its second order derivative

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_dp_der2.
If the derivative implementation is wrong, the simulation will stop with an error.

within AixLib.Fluid.BaseClasses.FlowModels.Validation;
model BasicFlowFunction_dp_DerivativeCheck2
  "Model that checks the correct implementation of the 2nd order derivative of the flow function"
  extends Modelica.Icons.Example;

  parameter Real k = 0.35 "Flow coefficient";
  parameter Modelica.Units.SI.MassFlowRate m_flow_turbulent=0.36
    "Mass flow rate where transition to turbulent flow occurs";
  Modelica.Units.SI.MassFlowRate m_flow "Mass flow rate";
  Modelica.Units.SI.MassFlowRate m_flow_comp "Comparison value for m_flow";
  Real der_m_flow(unit="kg/s2") "1st order derivative of mass flow rate";
  Real der_m_flow_comp(unit="kg/s2")
    "2nd order derivative of comparison value for m_flow";

  Modelica.Units.SI.PressureDifference dp "Pressure drop";
  Modelica.Units.SI.MassFlowRate err_m_flow "Integration error for m_flow";
  Real err_der_m_flow(unit="kg/s2") "Integration error for der_m_flow";
initial equation
  m_flow = m_flow_comp;
  der_m_flow = der_m_flow_comp;
equation
  // Multiply by 1 to avoid a warning due to unit mismatch,
  // and raise to third power so that dp_der2 has positive and negative sign
  // in AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_dp_der2
  dp = 1*time^3;

  m_flow = AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_dp(
    dp=dp,
    k = k,
    m_flow_turbulent=m_flow_turbulent);

  // Equate first and second order derivatives
  der_m_flow      = der(m_flow);
  der_m_flow_comp = der(m_flow_comp);
  der(der_m_flow) = der(der_m_flow_comp);

  // Error control
  err_m_flow = m_flow-m_flow_comp;
  assert(abs(err_m_flow) < 1E-3, "Error in implementation.");
  err_der_m_flow = der_m_flow-der_m_flow_comp;
  assert(abs(err_der_m_flow) < 1E-3, "Error in implementation.");
end BasicFlowFunction_dp_DerivativeCheck2;


Model that checks the correct implementation of the 1st order derivative of the flow function. This model validates the implementation of

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_m_flow
and its first order derivative

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_m_flow_der.
If the derivative implementation is wrong, the simulation will stop with an error.

within AixLib.Fluid.BaseClasses.FlowModels.Validation;
model BasicFlowFunction_m_flow_DerivativeCheck
  "Model that checks the correct implementation of the 1st order derivative of the flow function"
  extends Modelica.Icons.Example;

  constant Real gain = 0.5 "Gain for computing the mass flow rate";

  parameter Real k = 0.35 "Flow coefficient";
  parameter Modelica.Units.SI.MassFlowRate m_flow_turbulent=0.36
    "Mass flow rate where transition to turbulent flow occurs";
  Modelica.Units.SI.MassFlowRate m_flow "Mass flow rate";
  Modelica.Units.SI.PressureDifference dp "Pressure drop";
  Modelica.Units.SI.PressureDifference dp_comp "Comparison value for dp";
  Modelica.Units.SI.PressureDifference err "Integration error";
initial equation
 dp = dp_comp;
equation
  m_flow = time*gain;
  dp = AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_m_flow(
    m_flow=m_flow,
    k = k,
    m_flow_turbulent=m_flow_turbulent);
  der(dp) = der(dp_comp);
  err = dp-dp_comp;
  assert(abs(err) < 1E-3, "Error in implementation.");
end BasicFlowFunction_m_flow_DerivativeCheck;


Model that checks the correct implementation of the 2nd order derivative of the flow function. This model validates the implementation of

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_m_flow
and its second order derivative

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_m_flow_der2.
If the derivative implementation is wrong, the simulation will stop with an error.

within AixLib.Fluid.BaseClasses.FlowModels.Validation;
model BasicFlowFunction_m_flow_DerivativeCheck2
  "Model that checks the correct implementation of the 2nd order derivative of the flow function"
  extends Modelica.Icons.Example;
  AixLib.Utilities.Diagnostics.CheckEquality cheEqu1(
    threShold=1e-3)
    "Block for checking integration error";
  AixLib.Utilities.Diagnostics.CheckEquality cheEqu2(
    threShold=1e-3)
    "Block for checking integration error";
  parameter Real k = 0.35 "Flow coefficient";
  parameter Modelica.Units.SI.MassFlowRate m_flow_turbulent=0.36
    "Mass flow rate where transition to turbulent flow occurs";
  Modelica.Units.SI.PressureDifference dp "Pressure drop";
  Modelica.Units.SI.PressureDifference dp_comp "Comparison value for dp";
  Real der_dp(unit="Pa/s") "1st order derivative of pressure drop";
  Real der_dp_comp(unit="Pa/s")
    "2nd order derivative of comparison value for pressure drop";

  Modelica.Units.SI.MassFlowRate m_flow "Mass flow rate";

  Modelica.Units.SI.PressureDifference err_dp "Integration error for dp";
  Real err_der_dp(unit="Pa/s") "Integration error for der_dp";
initial equation
  dp = dp_comp;
  der_dp = der_dp_comp;
equation
  // Divide by 8 to avoid a warning due to unit mismatch, and
  // and raise to third power so that m_flow_der2 has positive and negative sign
  // in AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_m_flow_der2
  m_flow = time^3/8;

  dp = AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_m_flow(
    m_flow=m_flow,
    k = k,
    m_flow_turbulent=m_flow_turbulent);

  // Equate first and second order derivatives
  der_dp      = der(dp);
  der_dp_comp = der(dp_comp);
  der(der_dp) = der(der_dp_comp);

  // Error control
  cheEqu1.u1 = dp;
  cheEqu1.u2 = dp_comp;
  err_dp = cheEqu1.y;
  assert(abs(err_dp) < 1E-3, "Error in implementation.");
  cheEqu2.u1 = der_dp;
  cheEqu2.u2 = der_dp_comp;
  err_der_dp = cheEqu2.y;
  assert(abs(err_der_dp) < 1E-3, "Error in implementation.");
end BasicFlowFunction_m_flow_DerivativeCheck2;


Test model for flow function and its inverse. This model tests the inverse formulation of the flow functions.
The pressure difference dp and dpCalc need to
be equal up to the solver tolerance, except for a small neighborhood
around the origin. In this neighborhood around the origin, the functions

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_dp
and

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_m_flow
are not invertible.

within AixLib.Fluid.BaseClasses.FlowModels.Validation;
model InverseFlowFunctions "Test model for flow function and its inverse"
  extends Modelica.Icons.Example;
  Modelica.Units.SI.MassFlowRate m_flow;
  Modelica.Units.SI.PressureDifference dp(displayUnit="Pa")
    "Pressure difference";
  Modelica.Units.SI.PressureDifference dpCalc(displayUnit="Pa")
    "Pressure difference computed by the flow functions";
  Modelica.Units.SI.Pressure deltaDp(displayUnit="Pa")
    "Pressure difference between input and output to the functions";
  Modelica.Units.SI.Time dTime=2;
 parameter Real k = 0.5;
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=1 "Nominal flow rate";
equation
  dp = (time-0.5)/dTime * 20;
  m_flow=FlowModels.basicFlowFunction_dp(dp=dp, k=k, m_flow_turbulent=m_flow_nominal*0.3);
  dpCalc=FlowModels.basicFlowFunction_m_flow(m_flow=m_flow, k=k, m_flow_turbulent=m_flow_nominal*0.3);
  deltaDp = dp - dpCalc;
end InverseFlowFunctions;


Test model that inverts basicFlowFunction_dp. This model tests whether the Modelica translator substitutes the
inverse function for

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_dp.
Specifically, this function declares in its annotation section
that its inverse is provided by

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_m_flow.
Translating this model should therefore give no nonlinear equations
after the symbolic manipulation.

within AixLib.Fluid.BaseClasses.FlowModels.Validation;
model InvertingBasicFlowFunction_dp
  "Test model that inverts basicFlowFunction_dp"
  extends Modelica.Icons.Example;

 parameter Real k = 0.5 "Flow coefficient";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=1.5
    "Nominal mass flow rate";

  Modelica.Units.SI.MassFlowRate m_flow "Mass flow rate";
  Modelica.Units.SI.PressureDifference dp(displayUnit="Pa", start=0)
    "Pressure difference";
equation
  m_flow = 4*(time-0.5);
  m_flow = FlowModels.basicFlowFunction_dp(dp=dp, k=k, m_flow_turbulent=m_flow_nominal*0.3);
end InvertingBasicFlowFunction_dp;


Test model that inverts basicFlowFunction_m_flow. This model tests whether the Modelica translator substitutes the
inverse function for

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_m_flow.
Specifically, this function declares in its annotation section
that its inverse is provided by

AixLib.Fluid.BaseClasses.FlowModels.basicFlowFunction_dp.
Translating this model should therefore give no nonlinear equations
after the symbolic manipulation.

within AixLib.Fluid.BaseClasses.FlowModels.Validation;
model InvertingBasicFlowFunction_m_flow
  "Test model that inverts basicFlowFunction_m_flow"
  extends Modelica.Icons.Example;

 parameter Real k = 0.5 "Flow coefficient";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.5
    "Nominal mass flow rate";

  Modelica.Units.SI.MassFlowRate m_flow(start=0) "Mass flow rate";
  Modelica.Units.SI.PressureDifference dp(displayUnit="Pa")
    "Pressure difference";
equation
  dp = 4*(time-0.5);
  dp = FlowModels.basicFlowFunction_m_flow(m_flow=m_flow, k=k, m_flow_turbulent=m_flow_nominal*0.3);
end InvertingBasicFlowFunction_m_flow;


Collection of validation models

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


Validation model for the actuator filter. This example validates

AixLib.Fluid.BaseClasses.ActuatorFilter.
The validation is done for different settings of u_nominal and for
different start values of the filter output.

within AixLib.Fluid.BaseClasses.Validation;
model ActuatorFilter "Validation model for the actuator filter"
  extends Modelica.Icons.Example;

  parameter Modelica.Units.SI.Time riseTime=10 "Cut-off frequency of filter";
  final parameter Modelica.Units.SI.Frequency fCut=5/(2*Modelica.Constants.pi*
      riseTime) "Cut-off frequency of filter";

  AixLib.Fluid.BaseClasses.ActuatorFilter act_1(f=fCut, initType=Modelica.Blocks.Types.Init.InitialState)
    "Filter with u_nominal not set"
  AixLib.Fluid.BaseClasses.ActuatorFilter act_2(f=fCut, initType=Modelica.Blocks.Types.Init.InitialState)
    "Filter with u_nominal set to 100"
  Modelica.Blocks.Math.Gain gain(k=100) "Gain for input signal"
  Modelica.Blocks.Sources.Step step(startTime=0)
  AixLib.Fluid.BaseClasses.ActuatorFilter act_y_start05(
    f=fCut,
    initType=Modelica.Blocks.Types.Init.InitialOutput,
    y_start=0.5) "Filter with initial start value for output"
  AixLib.Fluid.BaseClasses.ActuatorFilter act_y_start1(
    f=fCut,
    initType=Modelica.Blocks.Types.Init.InitialOutput,
    y_start=1) "Filter with initial start value for output"
equation
  connect(act_2.u, gain.y)
  connect(step.y, act_1.u)
  connect(step.y, gain.u)
  connect(act_y_start05.u, step.y)
  connect(act_y_start1.u, step.y)
end ActuatorFilter;


Example use of MassFlowRateMultiplier

within AixLib.Fluid.BaseClasses.Validation;
model MassFlowRateMultiplier "Example use of MassFlowRateMultiplier"
  extends Modelica.Icons.Example;
  package Medium = AixLib.Media.Water;

  AixLib.Fluid.BaseClasses.MassFlowRateMultiplier
    massFlowRateMultiplier(
      redeclare package Medium = Medium,
      k=5)
      "Mass flow rate multiplier"
  Modelica.Blocks.Sources.Ramp ram_m_flow(
    height=10,
    duration=10,
    offset=0) "Mass flow rate ramp"
  AixLib.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Mass flow source"
  AixLib.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    nPorts=2)
    "Mass flow sink"
  AixLib.Fluid.BaseClasses.MassFlowRateMultiplier
    massFlowRateMultiplier1(
    redeclare package Medium = Medium,
    use_input=true,
    k=5)
      "Mass flow rate multiplier"
  Modelica.Blocks.Sources.Ramp gaiMasFlo(
    height=4.9,
    duration=10,
    offset=0.1) "Mass flow rate multiplier factor"
  AixLib.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Mass flow source"
equation
  connect(ram_m_flow.y, sou.m_flow_in)
  connect(sou.ports[1], massFlowRateMultiplier.port_a)
  connect(massFlowRateMultiplier.port_b, sin.ports[1])
  connect(sou1.ports[1], massFlowRateMultiplier1.port_a)
  connect(massFlowRateMultiplier1.port_b, sin.ports[2])
  connect(gaiMasFlo.y, massFlowRateMultiplier1.u)
  connect(ram_m_flow.y, sou1.m_flow_in)
end MassFlowRateMultiplier;


Collection of validation models

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


Boiler with internal and external control.

within AixLib.Fluid.BoilerCHP;
model Boiler "Boiler with internal and external control"
  extends AixLib.Fluid.BoilerCHP.BaseClasses.PartialHeatGenerator(a=paramBoiler.pressureDrop,
                                      vol(energyDynamics=energyDynamics,
                                          V=paramBoiler.volume));

  parameter AixLib.DataBase.Boiler.General.BoilerTwoPointBaseDataDefinition
    paramBoiler
    "Parameters for Boiler"
  parameter
    AixLib.DataBase.Boiler.DayNightMode.HeatingCurvesDayNightBaseDataDefinition
    paramHC
    "Parameters for heating curve"
  parameter Real KR=1
    "Gain of Boiler heater"
  parameter Modelica.Units.SI.Time TN=0.1
    "Time Constant of boiler heater (T>0 required)"
  parameter Modelica.Units.SI.Time riseTime=30
    "Rise/Fall time for step input(T>0 required)"
  parameter Real declination=1.1
    "Declination"
  parameter Modelica.Units.SI.TemperatureDifference Tdelta_Max=2
    "Difference from set flow temperature over which boiler stops"
  parameter Modelica.Units.SI.TemperatureDifference Tdelta_Min=2
    "Difference from set flow temperature under which boiler starts"
  parameter Modelica.Units.SI.Time Fb=3600
    "Period of time for increased set temperature"
  parameter Real FA=0.2 "Increment for increased set temperature"

  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  Modelica.Blocks.Interfaces.BooleanInput isOn
    "Switches Controler on and off"
  Modelica.Blocks.Interfaces.RealInput TAmbient(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Ambient air temperature"
   Modelica.Blocks.Interfaces.BooleanInput switchToNightMode
     "Connector of Boolean input signal"
  replaceable model ExtControl =
    AixLib.Fluid.BoilerCHP.BaseClasses.Controllers.ExternalControlNightDayHC
     constrainedby
    AixLib.Fluid.BoilerCHP.BaseClasses.Controllers.PartialExternalControl
      "External control"
  BaseClasses.Controllers.InternalControl internalControl(
    final paramBoiler=paramBoiler,
    final KR=KR,
    final TN=TN,
    final riseTime=riseTime,
    final energyDynamics=energyDynamics)
    "Internal control"
  ExtControl myExternalControl(
    final paramHC=paramHC,
    final declination=declination,
    final Tdelta_Max=Tdelta_Max,
    final Tdelta_Min=Tdelta_Min,
    final Fb=Fb,
    final FA=FA)
    "External control"

equation
  connect(internalControl.QflowHeater, heater.Q_flow)
  connect(senTCold.T, internalControl.TFlowCold)
  connect(senTHot.T, internalControl.TFlowHot)
  connect(senMasFlo.m_flow, internalControl.mFlow)
  connect(isOn, myExternalControl.isOn)
  connect(senTHot.T, myExternalControl.TFlowIs)
  connect(myExternalControl.isOn_final, internalControl.isOn)
  connect(myExternalControl.TFlowSet, internalControl.Tflow_set)
  connect(TAmbient,myExternalControl.TOutside)
  connect(myExternalControl.switchToNightMode,switchToNightMode)
end Boiler;


Boiler model with physics only.

within AixLib.Fluid.BoilerCHP;
model BoilerNoControl "Boiler model with physics only"
  extends AixLib.Fluid.BoilerCHP.BaseClasses.PartialHeatGenerator(a=paramBoiler.pressureDrop,
                                     vol(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
                                         final V=V));

  parameter AixLib.DataBase.Boiler.General.BoilerTwoPointBaseDataDefinition
    paramBoiler "Parameters for Boiler"
  parameter Modelica.Units.SI.ThermalConductance G=0.003*Q_nom/50
    "Constant thermal conductance to environment(G=Q_loss/dT)";
  parameter Modelica.Units.SI.HeatCapacity C=1.5*Q_nom
    "Heat capacity of metal (J/K)";
  parameter Modelica.Units.SI.Volume V=paramBoiler.volume "Volume";

  parameter Modelica.Units.SI.Power Q_nom=paramBoiler.Q_nom
    "Nominal heating power";

  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor internalCapacity(
      final C=C, T(start=T_start)) "Boiler thermal capacity (dry weight)"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor ConductanceToEnv(
      final G=G) "Thermal resistance of the boiler casing"
  Modelica.Blocks.Math.Product QgasCalculation "Calculate gas usage"
  Modelica.Blocks.Nonlinear.Limiter limiter(final uMax=1, final uMin=0)
    "Limits the rel power between 0 and 1"
  Modelica.Blocks.Sources.RealExpression NominalGasConsumption(final y=Q_nom/
        max(etaLoadBased[:,2]*max(etaTempBased[:,2])))
    "Nominal gas power"
  Modelica.Blocks.Interfaces.RealOutput fuelPower
    "Connector of Real output signal"
  Modelica.Blocks.Interfaces.RealOutput thermalPower "Value of Real output"
  Modelica.Blocks.Interfaces.RealInput u_rel "Relative gas power [0,1]"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b T_amb "Heat port for heat losses to ambient"

  Modelica.Blocks.Tables.CombiTable1Dv efficiencyTableLoadDepending(
    final tableOnFile=false,
    final table=etaLoadBased,
    final columns={2},
    final smoothness=Modelica.Blocks.Types.Smoothness.ContinuousDerivative)
    "Table with efficiency parameters"
  Modelica.Blocks.Math.Product QflowCalculation
    "Calculation of the produced heatflow"

  Modelica.Blocks.Interfaces.RealOutput T_out
    "Outflow temperature of the passing fluid"
  Modelica.Blocks.Interfaces.RealOutput T_in "Inflow temperature of the passing fluid"
  parameter Real etaLoadBased[:,2]=paramBoiler.eta
    "Table matrix for part load based efficiency (e.g. [0,0.99; 0.5, 0.98; 1, 0,97])";
  parameter Real etaTempBased[:,2]=[293.15,1.09; 303.15,1.08; 313.15,1.05; 323.15,1.; 373.15,0.99]
  "Table matrix for temperature based efficiency";
  Modelica.Blocks.Math.Product etaCalculation
    "calculates the efficiency of the boiler"
  Modelica.Blocks.Tables.CombiTable1Dv efficiencyTableLoadDepending1(
    final tableOnFile=false,
    final table=etaTempBased,
    final columns={2},
    final smoothness=Modelica.Blocks.Types.Smoothness.ContinuousDerivative)
    "Table with efficiency parameters"
equation
  connect(vol.heatPort, ConductanceToEnv.port_a)
  connect(vol.heatPort, internalCapacity.port)
  connect(QgasCalculation.y, fuelPower)
  connect(limiter.u, u_rel)
  connect(ConductanceToEnv.port_b, T_amb)
  connect(QgasCalculation.u1, NominalGasConsumption.y)
  connect(limiter.y, QgasCalculation.u2)
  connect(limiter.y, efficiencyTableLoadDepending.u[1])
  connect(QflowCalculation.y, heater.Q_flow)
  connect(QflowCalculation.y, thermalPower)
  connect(QgasCalculation.y, QflowCalculation.u2)
  connect(senTHot.T, T_out)
  connect(senTCold.T, T_in)
  connect(port_b, port_b)
  connect(efficiencyTableLoadDepending.y[1], etaCalculation.u1)
  connect(efficiencyTableLoadDepending1.y[1], etaCalculation.u2)
  connect(senTCold.T, efficiencyTableLoadDepending1.u[1])
  connect(QflowCalculation.u1, etaCalculation.y)
end BoilerNoControl;


Table based CHP model.

within AixLib.Fluid.BoilerCHP;
model CHP "Table based CHP model"
  extends AixLib.Fluid.BoilerCHP.BaseClasses.PartialHeatGenerator(a=1e10,
                  vol(V=param.vol[1]));

  parameter AixLib.DataBase.CHP.CHPDataSimple.CHPBaseDataDefinition param
    "CHP data set"
  parameter Real minCapacity
    "Minimum allowable working capacity in percent"
  parameter Boolean electricityDriven = false
    "If the CHP is controlled by electricity demand (external table required)"
  parameter Boolean TSetIn = true
    "Input temperature setpoint from outside (Otherwise max temp in database)"
  parameter Boolean ctrlStrategy = true
    "True for flow-, false for return- temperature control strategy"
  parameter Modelica.Units.SI.TemperatureDifference minDeltaT=10
    "Minimum flow and return temperature difference"
  parameter Modelica.Units.SI.TemperatureDifference TFlowRange=2
    "Range of allowable flow temperature"
  parameter Modelica.Units.SI.Time delayTime=3600 "Shutdown/Startup delay"
  parameter Real Kc = 1
    "Gain of the controller"
  parameter Modelica.Units.SI.Time Tc=60 "Time Constant (T>0 required)"
  parameter Modelica.Units.SI.Time delayUnit=60
    "Delay measurement of the controller output"
  Modelica.Blocks.Interfaces.RealInput TSet(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") if TSetIn
    "Temperature setpoint"
  Modelica.Blocks.Interfaces.RealInput elSet(
    final quantity="Power",
    final unit="kW") if electricityDriven
    "Electrical power setpoint"
  Modelica.Blocks.Interfaces.BooleanInput on
    "False for shut down"
  Modelica.Blocks.Interfaces.RealOutput TSource(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Combustion temperature"
  Modelica.Blocks.Interfaces.RealOutput electricalPower(
    final quantity="Power",
    final unit="kW")
    "Electrical power"
  Modelica.Blocks.Interfaces.RealOutput thermalPower(
    final unit="kW")
    "Thermal power"
  Modelica.Blocks.Interfaces.RealOutput fuelInput(
    final unit="kW")
    "Fuel input"
  Modelica.Blocks.Interfaces.RealOutput fuelConsumption
    "Fuel consumption"
  BaseClasses.Controllers.DelayedOnOffController delayedOnOffController(
    final maxTReturn=param.maxTReturn,
    final minDeltaT=minDeltaT,
    final TFlowRange=TFlowRange,
    final delayTime=delayTime,
    final delayUnit=delayUnit,
    final minCapacity=minCapacity)
    "OnOff controller to swicht between the modes"
  BaseClasses.Controllers.PIController thControl(
    final Kc=Kc,
    final Tc=Tc,
    final minCapacity=minCapacity)
    "Thermal controller"
  Modelica.Blocks.Math.Min min
    "Determines the min value of both PI controllers"
  Modelica.Blocks.Tables.CombiTable1Ds combiTable1Ds(
    tableName="NoName",
    fileName="NoName",
    final table=param.data_CHP)
    "Time table to read CHP performance data"
  Modelica.Blocks.Continuous.LimPID elControl(
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    yMax=100,
    yMin=0,
    y_start=0,
    final k=Kc,
    final Ti=Tc)
    "Electrical controller"
  Modelica.Blocks.Sources.Constant constSetpoint(
    final k=if ctrlStrategy then (param.maxTFlow) else (param.maxTReturn))
    "Constant setpoint if utilized"
  Modelica.Blocks.Sources.Constant const(final k=minCapacity + 10)
    "Adds safety value on min capacity"
  Modelica.Blocks.Logical.Switch ctrlSwitch
    "Changes the measured temperature source"
  Modelica.Blocks.Sources.BooleanConstant booleanConstant(k=ctrlStrategy)
    "Determines control strategy"
  Modelica.Blocks.Math.Gain gain(final k=1000)
    "Conversion factor"
  Modelica.Blocks.Sources.Constant exothermicTemperature(k=1783.4)
    "Exothermic temperature"

equation
  if electricityDriven then
    connect(elSet, elControl.u_s);
  else
    elControl.u_s = 1e9;
  end if;
  if TSetIn then
    connect(TSet,delayedOnOffController.flowTemp_setpoint);
    connect(TSet,thControl.setpoint);
  else
    connect(constSetpoint.y,delayedOnOffController.flowTemp_setpoint);
    connect(constSetpoint.y,thControl.setpoint);
  end if;

  connect(senTCold.T, ctrlSwitch.u3)
  connect(senTHot.T, ctrlSwitch.u1)
  connect(booleanConstant.y, ctrlSwitch.u2)
  connect(delayedOnOffController.returnTemp, ctrlSwitch.u3)
  connect(delayedOnOffController.flowTemp, ctrlSwitch.u1)
  connect(const.y,delayedOnOffController.minCapacity_in)
  connect(ctrlSwitch.y, thControl.measurement)
  connect(delayedOnOffController.y,thControl.on)
  connect(elControl.y, min.u1)
  connect(thControl.y, min.u2)
  connect(min.y, combiTable1Ds.u)
  connect(min.y,delayedOnOffController.controllerOutput)
  connect(combiTable1Ds.y[1],electricalPower)
  connect(elControl.u_m,electricalPower)
  connect(delayedOnOffController.externalOn,on)
  connect(combiTable1Ds.y[2], gain.u)
  connect(gain.y, heater.Q_flow)
  connect(exothermicTemperature.y,TSource)
  connect(combiTable1Ds.y[2],thermalPower)
  connect(combiTable1Ds.y[3],fuelInput)
  connect(combiTable1Ds.y[4],fuelConsumption)
end CHP;


Table based CHP model without an internal controller. Overview

within AixLib.Fluid.BoilerCHP;
model CHPNoControl
  "Table based CHP model without an internal controller"
  extends AixLib.Fluid.BoilerCHP.BaseClasses.PartialHeatGenerator(a=1e10, vol(
      energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
      massDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial,
                     V=param.vol[1]));

  parameter AixLib.DataBase.CHP.CHPDataSimple.CHPBaseDataDefinition param
    "CHP data set"
  parameter Real minCapacity = 0
    "Minimum allowable working capacity (unit [-])"
  parameter Modelica.Units.SI.ThermalConductance G=0.003*param.data_CHP[end, 3]
      /50 "Constant thermal conductance to environment(G=Q_loss/dT)";
  parameter Modelica.Units.SI.HeatCapacity C=1.5*param.data_CHP[end, 3]
    "Heat capacity of metal (J/K)";

  Modelica.Blocks.Interfaces.RealInput u_rel(
    final unit="1") "Relative"
  Modelica.Blocks.Interfaces.RealOutput electricalPower(
    final quantity="Power", final unit="W")
    "Electrical power"
  Modelica.Blocks.Interfaces.RealOutput thermalPower(final unit="W")
    "Thermal power"
  Modelica.Blocks.Interfaces.RealOutput fuelInput(final unit="W")
    "Fuel input"
  Modelica.Blocks.Interfaces.RealOutput fuelConsumption
    "Fuel consumption"
  Modelica.Blocks.Tables.CombiTable1Ds combiTable1Ds(
    tableName="NoName",
    fileName="NoName",
    final table=param.data_CHP)
    "Time table to read CHP performance data"
  Modelica.Blocks.Math.Gain gain(final k=1000) "Conversion factor"

  Modelica.Blocks.Nonlinear.Limiter limiter(final uMax=1, final uMin=
        minCapacity)
    "Limits the rel power between 0 and 1"
  Modelica.Blocks.Math.Gain gain4(final k=1000)
    "Conversion factor"
  Modelica.Blocks.Math.Gain gain1(final k=1000)
    "Conversion factor"
  Modelica.Blocks.Math.Gain gain2(final k=1000)
    "Conversion factor"
  Modelica.Blocks.Math.Gain gain3(final k=1000)
    "Conversion factor"
  Modelica.Blocks.Interfaces.RealOutput T_out
    "Outflow temperature of the passing fluid"
  Modelica.Blocks.Interfaces.RealOutput T_in "Inflow temperature of the passing fluid"
  Modelica.Blocks.Math.Gain toPercent(final k=100) "Conversion factor"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor internalCapacity(final C=C,
      T(start=T_start))            "Boiler thermal capacity (dry weight)"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor ConductanceToEnv(final G=G)
                 "Thermal resistance of the boiler casing"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b T_amb "Heat port for heat losses to ambient"
equation

  connect(combiTable1Ds.y[2], gain.u)
  connect(gain.y, heater.Q_flow)
  connect(combiTable1Ds.y[4], gain4.u)
  connect(gain4.y, fuelConsumption)
  connect(gain1.u, combiTable1Ds.y[1])
  connect(gain2.u, combiTable1Ds.y[2])
  connect(gain3.u, combiTable1Ds.y[3])
  connect(senTHot.T,T_out)
  connect(senTCold.T,T_in)
  connect(limiter.u, u_rel)
  connect(limiter.y, toPercent.u)
  connect(toPercent.y, combiTable1Ds.u)
  connect(vol.heatPort,internalCapacity. port)
  connect(ConductanceToEnv.port_b,T_amb)
  connect(ConductanceToEnv.port_a, vol.heatPort)
  connect(gain1.y, electricalPower)
  connect(gain2.y, thermalPower)
  connect(gain3.y, fuelInput)
end CHPNoControl;


within AixLib.Fluid.BoilerCHP;
package Data
  "Package with model parameters for combined heat and power systems"
  extends Modelica.Icons.MaterialPropertiesPackage;
  package ModularCHP "Data for the modular CHP model"

    record EngineMaterialData
      extends Modelica.Icons.Record;

      constant Modelica.Units.SI.ThermalConductivity lambda=44.5
        "Thermal conductivity of the engine block material (default value is 44.5)";
      constant Modelica.Units.SI.Density rhoEngWall=7200
        "Density of the the engine block material (default value is 72000)";
      constant Modelica.Units.SI.SpecificHeatCapacity c=535
        "Specific heat capacity of the cylinder wall material (default value is 535)";
    end EngineMaterialData;

    record EngineMaterial_CastIron "Cast iron as engine housing material"
      extends Data.ModularCHP.EngineMaterialData(
                                 lambda=44.5, rhoEngWall=7200, c=535);
    end EngineMaterial_CastIron;

    record EngineMaterial_SpheroidalGraphiteIron
      "Spheroidal graphite iron as engine housing material"
      extends Data.ModularCHP.EngineMaterialData(
                                 lambda=36.2, rhoEngWall=7100, c=515);
    end EngineMaterial_SpheroidalGraphiteIron;

    record EngineMaterial_CastAluminium
      "Cast aluminium as engine housing material"

      extends Data.ModularCHP.EngineMaterialData(
                                 lambda=140, rhoEngWall=2500, c=910);
      //Source: https://www.makeitfrom.com/material-properties/EN-AC-43300-AISi9Mg-Cast-Aluminum
    end EngineMaterial_CastAluminium;
  end ModularCHP;
end Data;


Simple heat generator without control.

within AixLib.Fluid.BoilerCHP;
model HeatGeneratorNoControl "Simple heat generator without control"
  extends AixLib.Fluid.BoilerCHP.BaseClasses.PartialHeatGenerator(
        a=coeffPresLoss, vol(V=V));

  Modelica.Blocks.Interfaces.RealInput Q_flow(final unit="W")
    "Prescribed heat flow"
  Modelica.Blocks.Interfaces.RealOutput TCold(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Temperature of the passing fluid"
  Modelica.Blocks.Interfaces.RealOutput THot(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Temperature of the passing fluid"
  Modelica.Blocks.Interfaces.RealOutput massFlow(quantity="MassFlowRate",
    final unit="kg/s")
    "Mass flow rate from port_a to port_b"
  parameter Modelica.Units.SI.Volume V
    "Volume of the heat exchanger inside the heat generator";
  parameter Real coeffPresLoss
    "Pressure loss coefficient of the heat generator";

equation
  connect(heater.Q_flow, Q_flow)
  connect(senTCold.T,TCold)
  connect(senTHot.T,THot)
  connect(senMasFlo.m_flow, massFlow)
end HeatGeneratorNoControl;


Package with boiler and CHP models

within AixLib.Fluid;
package BoilerCHP "Package with boiler and CHP models"
  extends Modelica.Icons.VariantsPackage;

end BoilerCHP;


Model for temperature depending efficiency of a condensing boiler. This model calculates the efficiency of a condensing boiler and is
  based upon the literature Règles de modélisation
  des systèmes énergétiques dans les bâtiments basse
  consommation

within AixLib.Fluid.BoilerCHP.BaseClasses;
model CondensingBoilerEfficiency
  "Model for temperature depending efficiency of a condensing boiler"
  parameter Real lambda=0.01 "Offset variable of weighting coefficients sigmas";

  parameter Modelica.Units.SI.Temperature T_nom=343.15 "Nominal temperature";
  parameter Modelica.Units.SI.Temperature T_part=308.15
    "Intermediate temperature";
  parameter Modelica.Units.SI.Efficiency eta_nom=1
    "Nominal net heating value efficiency";
  parameter Modelica.Units.SI.Efficiency eta_int=1
    "Intermediate net heating value efficiency";
  parameter Real eta_max=1.11
    "Ratio gross (high) heating value / net (low) heating value defined according to the fuel";

  parameter Real ak=-0.0002 "Sensible temperature depending efficiency decrease per K";
  Real etaSens;
  Real etaCond;
  Real sigmaSens;
  Real sigmaCond;
  Real etaRP;
  Modelica.Units.SI.Temperature Tc(
    start=360,
    max=380,
    min=323,
    nominal=360)
    "Temperature of Sensitive and Latent characteristic intersection";
  //start value is important: equation below has two solutions

  Modelica.Blocks.Interfaces.RealInput T_in(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Ambient air temperature"
  Modelica.Blocks.Interfaces.RealOutput eta "Value of Real output"
algorithm
  //The boiler is launched for partLoadRate (boilerBus.PLR) > PLR_min, if partLoadRate < PLR_min there is no combustion and the efficiency etaRP is zero
  //Determination of the efficiency for the law without condensation
  etaSens := eta_nom + ak*(T_in - T_nom);
  //Determination of the efficiency for the law characterizing the condensation
  etaCond := eta_int + (eta_max - eta_int)*(1 - AixLib.Utilities.Psychrometrics.Functions.saturationPressure(T_in)/AixLib.Utilities.Psychrometrics.Functions.saturationPressure(T_part)*T_part/T_in);
  sigmaCond := 1/(1 + exp(T_in - Tc - lambda));
  sigmaSens := 1 - 1/(1 + exp(T_in - Tc + lambda));
  etaRP := sigmaSens*etaSens + sigmaCond*etaCond;

equation
  //Calculation of Tc
  eta_nom + ak*(Tc - T_nom) = eta_int + (eta_max - eta_int)*(1 - AixLib.Utilities.Psychrometrics.Functions.saturationPressure(Tc)/AixLib.Utilities.Psychrometrics.Functions.saturationPressure(T_part)*
    T_part/Tc);

  eta = etaRP;
end CondensingBoilerEfficiency;


within AixLib.Fluid.BoilerCHP;
package BaseClasses "Package with base classes for Aix.BoilerCHP"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial model for heat generators

within AixLib.Fluid.BoilerCHP.BaseClasses;
partial model PartialHeatGenerator "Partial model for heat generators"
  extends AixLib.Fluid.Interfaces.PartialTwoPortInterface;

  parameter Modelica.Units.SI.Time tau=1
    "Time constant of the temperature sensors at nominal flow rate"
  parameter Modelica.Blocks.Types.Init initType=Modelica.Blocks.Types.Init.InitialState
    "Type of initialization (InitialState and InitialOutput are identical)"
  parameter Modelica.Units.SI.Temperature T_start=Medium.T_default
    "Initial or guess value of output (= state)"
  parameter Boolean transferHeat=false
    "If true, temperature T converges towards TAmb when no flow"
  parameter Modelica.Units.SI.Temperature TAmb=Medium.T_default
    "Fixed ambient temperature for heat transfer"
  parameter Modelica.Units.SI.Time tauHeaTra=1200
    "Time constant for heat transfer, default 20 minutes"
  parameter Modelica.Units.SI.AbsolutePressure dp_start=0
    "Guess value of dp = port_a.p - port_b.p"
  parameter Modelica.Units.SI.MassFlowRate m_flow_start=0
    "Guess value of m_flow = port_a.m_flow"
  parameter Modelica.Units.SI.AbsolutePressure p_start=Medium.p_default
    "Start value of pressure"

  parameter Modelica.Units.SI.PressureDifference dp_nominal=m_flow_nominal^2*a/
      (rho_default^2) "Pressure drop at nominal mass flow rate"
  parameter Boolean from_dp=false
    "= true, use m_flow = f(dp) else dp = f(m_flow)"
  parameter Boolean linearized=false
    "= true, use linear relation between m_flow and dp for any flow rate"
  parameter Real deltaM=0.3
    "Fraction of nominal mass flow rate where transition to turbulent occurs"
  parameter Real a "Coefficient of old approach from model Modelica.Fluid.Fittings.GenericResistances.VolumeFlowRate. Recalculated to dp_nominal based on IBPSA approach."
  Sensors.TemperatureTwoPort senTCold(
    redeclare final package Medium = Medium,
    final tau=tau,
    final m_flow_nominal=m_flow_nominal,
    final initType=initType,
    final T_start=T_start,
    final transferHeat=transferHeat,
    final TAmb=TAmb,
    final tauHeaTra=tauHeaTra,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_small=m_flow_small)
    "Temperature sensor of cold side of heat generator (return)"
  Sensors.TemperatureTwoPort senTHot(
    redeclare final package Medium = Medium,
    final tau=tau,
    final m_flow_nominal=m_flow_nominal,
    final initType=initType,
    final T_start=T_start,
    final transferHeat=transferHeat,
    final TAmb=TAmb,
    final tauHeaTra=tauHeaTra,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_small=m_flow_small)
    "Temperature sensor of hot side of heat generator (supply)"
  Sensors.MassFlowRate senMasFlo(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal)
    "Sensor for mass flwo rate"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow heater
    "Prescribed heat flow"
  MixingVolumes.MixingVolume vol(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final m_flow_small=m_flow_small,
    final allowFlowReversal=allowFlowReversal,
    final nPorts=2,
    final p_start=p_start,
    final T_start=T_start)
    "Fluid volume"
  FixedResistances.PressureDrop                             pressureDrop(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final show_T=false,
    final allowFlowReversal=allowFlowReversal,
    final dp_nominal=dp_nominal)
    "Pressure drop"
  parameter Modelica.Units.SI.Density rho_default=Medium.density_pTX(
      Medium.p_default,
      Medium.T_default,
      Medium.X_default) "Density used for parameterization of pressure curve"

equation
  connect(port_a, senTCold.port_a)
  connect(senTCold.port_b, vol.ports[1])
  connect(vol.ports[2], pressureDrop.port_a)
  connect(senMasFlo.port_b, port_b)
  connect(pressureDrop.port_b, senTHot.port_a)
  connect(senTHot.port_b, senMasFlo.port_a)
  connect(heater.port, vol.heatPort)
end PartialHeatGenerator;


On/Off controller for boiler models.

within AixLib.Fluid.BoilerCHP.BaseClasses.Controllers;
model ControllerOnOff "On/Off controller for boiler models"

  Modelica.Blocks.Interfaces.BooleanInput onOffExtern
    "On/Off signal"
  Modelica.Blocks.Interfaces.BooleanInput THigh
    "Medium temperature is too high"
  Modelica.Blocks.Interfaces.BooleanInput TLow
    "Medium temperature is too low"
  Modelica.Blocks.Interfaces.BooleanOutput onOffFinal
    "Output signal"
  Modelica.Blocks.Logical.And onOff

equation
  connect(onOffExtern,onOff. u1)
  connect(onOff.y,onOffFinal)
algorithm
  if TLow then
    onOff.u2 :=true;
  elseif THigh then
    onOff.u2 :=false;
  end if;
end ControllerOnOff;


CHP engine data for calculations. Model of an easy on-off-controller for the modular CHP model.

within AixLib.Fluid.BoilerCHP.BaseClasses.Controllers;
model ControllerOnOffModularCHP

  parameter
    AixLib.DataBase.CHP.ModularCHPEngineData.CHPEngDataBaseRecord
    CHPEngineModel=DataBase.CHP.ModularCHPEngineData.CHP_ECPowerXRGI15()
    "CHP engine data for calculations"
  parameter Modelica.Units.SI.Time startTimeChp=0
    "Start time for discontinous simulation tests to heat the Chp unit up to the prescribed return temperature";
  parameter Real modTab[:,2]=[0.0,0.8; 7200,0.8; 7200,0.93; 10800,0.93; 10800,
      0.62; 14400,0.62; 14400,0.8; 18000,0.8; 18000,0.0]
    "Table for unit modulation (time = first column; modulation factors = second column)";

  Modelica.Blocks.Logical.Timer timerIsOff
  Modelica.Blocks.Logical.Not not1
  Modelica.Blocks.Logical.LessThreshold declarationTime(threshold=7200)
  Modelica.Blocks.Logical.Or pumpControl
  AixLib.Controls.Interfaces.CHPControlBus modCHPConBus
  Modelica.Blocks.Sources.TimeTable modulationFactorControl(
                          startTime=startTimeChp, table=modTab)
  Modelica.Blocks.Logical.GreaterThreshold greaterThreshold

equation
  connect(timerIsOff.u,not1. y)
  connect(timerIsOff.y,declarationTime. u)
  connect(declarationTime.y,pumpControl. u1)
  connect(pumpControl.y, modCHPConBus.isOnPump)
  connect(modulationFactorControl.y, modCHPConBus.modFac)
  connect(greaterThreshold.y, not1.u)
  connect(pumpControl.u2, not1.u)
  connect(greaterThreshold.y, modCHPConBus.isOn)
  connect(greaterThreshold.u, modulationFactorControl.y)
end ControllerOnOffModularCHP;


CHP On/Off controller.

within AixLib.Fluid.BoilerCHP.BaseClasses.Controllers;
model DelayedOnOffController "CHP On/Off controller"

  parameter Modelica.Units.SI.Temperature maxTReturn
    "Maximum return temperature";
  parameter Modelica.Units.SI.ThermodynamicTemperature minDeltaT
    "Minimum flow and return temperature difference";
  parameter Modelica.Units.SI.ThermodynamicTemperature TFlowRange
    "Range of the flow temperature";
  parameter Modelica.Units.SI.Time delayTime "On/Off delay time";
  parameter Boolean initialOutput=false
    "Initial output";
  parameter Real delayUnit
    "Delay unit";
  parameter Real minCapacity
    "Minimum allowable working capacity in percent";
  Modelica.Blocks.Interfaces.RealInput flowTemp(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Flow temperature"
  Modelica.Blocks.Interfaces.RealInput returnTemp(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Return temperature"
  Modelica.Blocks.Interfaces.BooleanOutput y
    "Signal if controller is on or off"
  Modelica.Blocks.Interfaces.RealInput controllerOutput
    "Controller output"
  Modelica.Blocks.Interfaces.RealInput minCapacity_in
    "Minimal capacity"
  Modelica.Blocks.Interfaces.BooleanInput externalOn
    "False for shut down"
  Modelica.Blocks.Interfaces.RealInput flowTemp_setpoint(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Flow temperature setpoint"
  Modelica.Blocks.Logical.And and1
  Modelica.Blocks.Logical.Pre pre2
  Modelica.Blocks.Logical.OnOffController onOffController(
    final bandwidth=minDeltaT)
    "OnOff controller"
  Modelica.Blocks.Logical.LessThreshold lessThreshold(
    threshold=TFlowRange)
    "Maximum allowable flow temperature variation"
  Modelica.Blocks.Logical.Or or1
  Modelica.Blocks.Logical.GreaterThreshold greaterThreshold(
    threshold=maxTReturn)
    "Max return temperature limit"
  Modelica.Blocks.Discrete.UnitDelay unitDelay(final samplePeriod=delayUnit)
    "Last value"
  Modelica.Blocks.Math.Feedback feedback
  Modelica.Blocks.Logical.Not not1
  Modelica.Blocks.Logical.Not not2
  Modelica.Blocks.Logical.LogicalSwitch logicalSwitch
  Modelica.Blocks.Logical.Not not3
  Modelica.Blocks.Logical.Or or3
  Modelica.Blocks.Logical.LessThreshold lessThreshold1(
    final threshold=minCapacity)
  Modelica.Blocks.Logical.GreaterEqualThreshold greaterEqualThreshold(
    threshold=130 + 273.15)
    "Emergency measure"
  Modelica.Blocks.Logical.Or or4
  Modelica.Blocks.MathBoolean.OnDelay onDelay(
    final delayTime=delayTime)
    "On delay"
  Modelica.Blocks.MathBoolean.OnDelay onDelay1(
    final delayTime=delayTime)
    "On delay"
  Modelica.Blocks.Nonlinear.FixedDelay fixedDelay(
    final delayTime=delayTime)
    "Fixed delay"

initial equation
  pre(y)=initialOutput;

equation
  connect(onOffController.y, pre2.u)
  connect(feedback.u2,flowTemp)
  connect(pre2.y, and1.u2)
  connect(lessThreshold.y, and1.u1)
  connect(feedback.y, lessThreshold.u)
  connect(and1.y, or1.u1)
  connect(onOffController.u,controllerOutput)
  connect(onOffController.reference,minCapacity_in)
  connect(or1.u2, greaterThreshold.y)
  connect(externalOn, not3.u)
  connect(flowTemp_setpoint, feedback.u1)
  connect(or3.u2, or1.y)
  connect(not3.y, or3.u1)
  connect(or3.y, not1.u)
  connect(greaterThreshold.u,returnTemp)
  connect(greaterEqualThreshold.u,flowTemp)
  connect(greaterEqualThreshold.y, or4.u2)
  connect(logicalSwitch.y, or4.u1)
  connect(unitDelay.u,controllerOutput)
  connect(lessThreshold1.y, logicalSwitch.u2)
  connect(onDelay.u, not1.y)
  connect(onDelay.y, not2.u)
  connect(onDelay1.u, or3.y)
  connect(onDelay1.y, logicalSwitch.u1)
  connect(not2.y, logicalSwitch.u3)
  connect(or4.y, y)
  connect(unitDelay.y, fixedDelay.u)
  connect(fixedDelay.y, lessThreshold1.u)
end DelayedOnOffController;


With night and day modes, both with heating curves.

within AixLib.Fluid.BoilerCHP.BaseClasses.Controllers;
model ExternalControlNightDayHC
  "With night and day modes, both with heating curves"
  extends PartialExternalControl;

  parameter
    AixLib.DataBase.Boiler.DayNightMode.HeatingCurvesDayNightBaseDataDefinition
    paramHC
    "Parameters for heating curve"
  parameter Real declination
    "Declination"
  parameter Modelica.Units.SI.TemperatureDifference Tdelta_Max
    "Difference from set flow temperature over which boiler stops"
  parameter Modelica.Units.SI.TemperatureDifference Tdelta_Min
    "Difference from set flow temperature under which boiler starts"
  parameter Modelica.Units.SI.Time Fb
    "Period of time for increased set temperature"
  parameter Real FA
    "Increment for increased set temperature"
  Modelica.Blocks.Logical.Switch switchDayNight
    "Switch"
  ControllerOnOff controlerOnOff
    "On/Off controller"
  Modelica.Blocks.Logical.Timer timer
    "Timer"
  Modelica.Blocks.Logical.LessEqualThreshold lessEqualThreshold(
    final threshold=Fb)
    "Threshold"
  Modelica.Blocks.Logical.And and1
  Modelica.Blocks.Logical.Switch switchIncreasedSetTemp
    "Switch"
  Modelica.Blocks.Math.Gain increase(
    final k=1 + FA)
    "Increase"
  Modelica.Blocks.Math.Gain noIncrease(
    final k=1)
    "No increase"
  Modelica.Blocks.Logical.Not not1
  Modelica.Blocks.Sources.Constant declinationConst(
    k=declination)
    "Declination"

protected
  Modelica.Blocks.Tables.CombiTable2Ds flowTempNight(final table=paramHC.varFlowTempNight)
    "Table for setting the flow temperature during night according to the outside temperature"
  Modelica.Blocks.Tables.CombiTable2Ds flowTempDay(final table=paramHC.varFlowTempDay)
    "Table for setting the flow temperature druing day according to the outside temperature"
  Modelica.Blocks.Math.UnitConversions.To_degC to_degC
  Modelica.Blocks.Math.UnitConversions.From_degC from_degC
  Modelica.Blocks.Logical.GreaterThreshold higher(
    final threshold=Tdelta_Max)
    "Higher"
  Modelica.Blocks.Logical.LessThreshold lower(
    final threshold=-Tdelta_Min)
    "Lower"
  Modelica.Blocks.Math.Feedback difference
    "Difference"

equation
  if cardinality(isOn) < 2 then
    isOn = true;
  end if;

  connect(higher.y, controlerOnOff.THigh)
  connect(lower.y, controlerOnOff.TLow)
  connect(higher.u,difference. y)
  connect(timer.y, lessEqualThreshold.u)
  connect(lessEqualThreshold.y, and1.u2)
  connect(switchDayNight.y,increase. u)
  connect(increase.y, switchIncreasedSetTemp.u1)
  connect(switchDayNight.y,noIncrease. u)
  connect(noIncrease.y, switchIncreasedSetTemp.u3)
  connect(and1.y, switchIncreasedSetTemp.u2)
  connect(switchIncreasedSetTemp.y, from_degC.u)
  connect(not1.y, timer.u)
  connect(not1.y, and1.u1)
  connect(to_degC.y,flowTempNight. u1)
  connect(to_degC.y,flowTempDay. u1)
  connect(declinationConst.y, flowTempNight.u2)
  connect(declinationConst.y, flowTempDay.u2)
  connect(flowTempNight.y, switchDayNight.u1)
  connect(flowTempDay.y, switchDayNight.u3)
  connect(difference.u1, TFlowIs)
  connect(from_degC.y,difference. u2)
  connect(difference.y,lower. u)
  connect(switchToNightMode, not1.u)
  connect(switchToNightMode, switchDayNight.u2)
  connect(TOutside, to_degC.u)
  connect(isOn, controlerOnOff.onOffExtern)
  connect(controlerOnOff.onOffFinal,isOn_final)
  connect(TFlowSet, from_degC.y)
end ExternalControlNightDayHC;


Internal control model for boiler.

within AixLib.Fluid.BoilerCHP.BaseClasses.Controllers;
model InternalControl "Internal control model for boiler"

  parameter AixLib.DataBase.Boiler.General.BoilerTwoPointBaseDataDefinition
    paramBoiler
    "Parameters for boiler"
  parameter Real KR
    "Gain of boiler heater";
  parameter Modelica.Units.SI.Time TN
    "Time constant of boiler heater (T>0 required)";
  parameter Modelica.Units.SI.Time riseTime
    "Rise/fall time for step input(T>0 required)";
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  Real outputPower
    "Output power";
  Modelica.Blocks.Interfaces.BooleanInput isOn
    "On/Off switch for the boiler"
  Modelica.Blocks.Interfaces.RealInput Tflow_set(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Target temperature of the controller"
  Modelica.Blocks.Interfaces.RealInput TFlowHot(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Outgoing temperature"
  Modelica.Blocks.Interfaces.RealOutput QflowHeater(
    final unit="W")
    "Connector of real output signal"
  Modelica.Blocks.Interfaces.RealInput mFlow(
    quantity="MassFlowRate",
    final unit="kg/s")
    "Mass flow through the boiler"
  Modelica.Blocks.Interfaces.RealInput TFlowCold(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Temperature of the cold water"
  Controls.Continuous.PITemp  ControlerHeater(
    final KR=KR,
    final TN=TN,
    final h=paramBoiler.Q_nom,
    final l=paramBoiler.Q_min,
    triggeredTrapezoid(final rising=riseTime, final falling=riseTime),
    final rangeSwitch=false)
    "PI temperature controller"
  Utilities.Sensors.EnergyMeter eEnergyMeter_P(final energyDynamics=
        energyDynamics)
    "For primary energy consumption"
  Utilities.Sensors.EnergyMeter eEnergyMeter_S(final energyDynamics=
        energyDynamics)
    "For secondary energy consumption"
  Modelica.Blocks.Tables.CombiTable1Dv efficiencyTable(
    final tableOnFile=false,
    final table=paramBoiler.eta,
    final columns={2},
    final smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments)
    "Table with efficiency parameters"
  Modelica.Blocks.Math.Gain QNormated(
    final k=1/paramBoiler.Q_nom)
  Modelica.Blocks.Math.Product product
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature
    prescribedTemperature
    "Converts Tflow_hot real input to temperature"

equation

  if cardinality(isOn) < 2 then
    isOn = true;
  end if;

  outputPower =mFlow*4184*(TFlowHot - TFlowCold);
  eEnergyMeter_S.p=outputPower;

  connect(ControlerHeater.y, eEnergyMeter_P.p)
  connect(ControlerHeater.y, QNormated.u)
  connect(QNormated.y,efficiencyTable. u[1])
  connect(ControlerHeater.y, product.u1)
  connect(efficiencyTable.y[1], product.u2)
  connect(product.y, QflowHeater)
  connect(ControlerHeater.setPoint, Tflow_set)
  connect(ControlerHeater.onOff, isOn)
  connect(TFlowHot, prescribedTemperature.T)
  connect(prescribedTemperature.port, ControlerHeater.heatPort)
end InternalControl;


within AixLib.Fluid.BoilerCHP.BaseClasses;
package Controllers "Package with controllers for boiler and CHP models"
  extends Modelica.Icons.VariantsPackage;
end Controllers;


With measurement of primary and secondary energy consumption.

within AixLib.Fluid.BoilerCHP.BaseClasses.Controllers;
partial model PartialExternalControl
  "With measurement of primary and secondary energy consumption"

  Modelica.Blocks.Interfaces.RealInput TOutside(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Outside temperature [K]"
  Modelica.Blocks.Interfaces.BooleanInput isOn
    "On/Off switch for the boiler"
  Modelica.Blocks.Interfaces.BooleanInput switchToNightMode
    "Connector of boolean input signal"
  Modelica.Blocks.Interfaces.BooleanOutput isOn_final
    "On/Off output"
  Modelica.Blocks.Interfaces.RealOutput TFlowSet(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Target temperature of the controller"
  Modelica.Blocks.Interfaces.RealInput TFlowIs(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Actual outgoing temperature"

equation
  if cardinality(isOn) < 2 then
    isOn = true;
  end if;
end PartialExternalControl;


Two coupled PI controllers for CHP control.

within AixLib.Fluid.BoilerCHP.BaseClasses.Controllers;
model PIController "Two coupled PI controllers for CHP control"

  parameter Real Kc
    "Gain of the controller";
  parameter Modelica.Units.SI.Time Tc "Time constant (T>0 required)";
  parameter Real minCapacity
    "Minimum controller output in load operation";

  Modelica.Blocks.Logical.Switch switch1
  Modelica.Blocks.Continuous.LimPID PI(
    final controllerType=Modelica.Blocks.Types.SimpleController.PI,
    yMax=100,
    y_start=0,
    final k=Kc,
    final Ti=Tc,
    final yMin=minCapacity)
    "PI controller"
  Modelica.Blocks.Continuous.LimPID PI1(
    final controllerType=Modelica.Blocks.Types.SimpleController.PI,
    yMax=100,
    yMin=0,
    final k=Kc,
    final Ti=Tc)
    "Limited PI controller"
  Modelica.Blocks.Discrete.TriggeredSampler triggeredSampler(y_start=0)
  Modelica.Blocks.Discrete.TriggeredSampler triggeredSampler2(y_start=0)
  Modelica.Blocks.Logical.TriggeredTrapezoid triggeredTrapezoid(rising=100)
  Modelica.Blocks.Logical.Switch switch3
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Logical.Switch switch2
  Modelica.Blocks.Interfaces.RealOutput y
    "Controller output signal"
  Modelica.Blocks.Interfaces.RealInput setpoint
  Modelica.Blocks.Interfaces.BooleanInput on
    "Connector of boolean input signal"
  Modelica.Blocks.Logical.Not not1
  Modelica.Blocks.Interfaces.RealInput measurement
    "Connector of second real input signal"

equation

  connect(switch1.y, PI.u_m)
  connect(PI1.u_m, PI.u_m)
  connect(triggeredSampler.y, PI1.u_s)
  connect(triggeredSampler2.y, PI.u_s)
  connect(PI.y, switch3.u3)
  connect(PI1.y, switch3.u1)
  connect(product.u1, switch3.y)
  connect(product.u2, triggeredTrapezoid.y)
  connect(product.y, switch2.u3)
  connect(switch2.u1, switch3.y)
  connect(switch2.y, y)
  connect(triggeredSampler2.trigger, triggeredTrapezoid.u)
  connect(switch2.u2, triggeredTrapezoid.u)
  connect(setpoint, triggeredSampler.u)
  connect(triggeredSampler2.u, triggeredSampler.u)
  connect(switch1.u1, triggeredSampler.u)
  connect(switch3.u2, triggeredSampler.trigger)
  connect(on, switch1.u2)
  connect(triggeredSampler.trigger, switch1.u2)
  connect(not1.y, triggeredTrapezoid.u)
  connect(not1.u, switch1.u2)
  connect(switch1.u3, measurement)
end PIController;


within AixLib.Fluid.BoilerCHP.Examples;
model BoilerNoControlSystem
  "Example that illustrates the use of the boiler model without control"
  extends Modelica.Icons.Example;
    package Medium = AixLib.Media.Water

  Modelica.Fluid.Sources.MassFlowSource_T source(
    use_m_flow_in=false,
    redeclare package Medium = Medium,
    use_T_in=true,
    m_flow=0.2,
    T=313.15,
    nPorts=1)
    "Source"
  Modelica.Fluid.Pipes.StaticPipe pipe(
    length=1,
    diameter=0.025,
    redeclare package Medium = Medium)
    "Pressure drop"
  inner Modelica.Fluid.System system(p_start=system.p_ambient,
    p_ambient(displayUnit="Pa"))
    "Pressure drop"
  Modelica.Fluid.Sources.Boundary_pT sink(nPorts=1, redeclare package Medium =
        Medium)
    "Sink"
  Modelica.Blocks.Sources.Ramp ramp(
    height=1,
    duration=360,
    offset=0,
    startTime=120)
    "Ambient air temperature"

  BoilerNoControl boilerNoControl(
    redeclare package Medium = Medium,
    m_flow_nominal=0.2,
    paramBoiler=DataBase.Boiler.General.Boiler_Vitogas200F_18kW())
  Modelica.Blocks.Sources.Ramp ramp1(
    height=60,
    duration=360,
    offset=273.15,
    startTime=520)
    "Ambient air temperature"
equation
  connect(pipe.port_b, sink.ports[1])
  connect(source.ports[1], boilerNoControl.port_a)
  connect(boilerNoControl.port_b, pipe.port_a)
  connect(boilerNoControl.u_rel, ramp.y)
  connect(source.T_in, ramp1.y)
end BoilerNoControlSystem;


within AixLib.Fluid.BoilerCHP.Examples;
model BoilerSystem "Example that illustrates use of boiler model"
  extends Modelica.Icons.Example;

  Modelica.Fluid.Sources.MassFlowSource_T source(
    use_m_flow_in=false,
    nPorts=1,
    redeclare package Medium =
        AixLib.Media.Specialized.Water.TemperatureDependentDensity,
    m_flow=0.05,
    T=293.15)
    "Source"
  Modelica.Fluid.Pipes.StaticPipe pipe(
    length=1,
    diameter=0.025,
    redeclare package Medium =
        AixLib.Media.Specialized.Water.TemperatureDependentDensity)
    "Pressure drop"
  inner Modelica.Fluid.System system(p_start=system.p_ambient,
    p_ambient(displayUnit="Pa"))
    "Pressure drop"
  Boiler boiler(
    redeclare package Medium =
        AixLib.Media.Specialized.Water.TemperatureDependentDensity,
    m_flow_nominal=0.03,
    redeclare model ExtControl =
        BaseClasses.Controllers.ExternalControlNightDayHC,
    declination=1.2,
    FA=0,
    paramHC=DataBase.Boiler.DayNightMode.HeatingCurves_Vitotronic_Day25_Night10(),
    riseTime=0,
    TN=0.05,
    paramBoiler=DataBase.Boiler.General.Boiler_Vitogas200F_11kW())
    "Boiler"
  Modelica.Fluid.Sources.Boundary_pT sink(nPorts=1, redeclare package Medium =
    AixLib.Media.Specialized.Water.TemperatureDependentDensity)
    "Sink"
  Modelica.Blocks.Sources.BooleanConstant on
    "Boiler is always on"
  Modelica.Blocks.Sources.Sine sine(
    amplitude=5,
    f=1/86400,
    phase=4.7123889803847,
    offset=273.15) "Ambient air temperature"
  Modelica.Blocks.Sources.BooleanConstant isNight(k=false)
    "No night-setback"

equation
  connect(source.ports[1], boiler.port_a)
  connect(boiler.port_b, pipe.port_a)
  connect(pipe.port_b, sink.ports[1])
  connect(on.y, boiler.isOn)
  connect(sine.y, boiler.TAmbient)
  connect(isNight.y,boiler.switchToNightMode)
end BoilerSystem;


within AixLib.Fluid.BoilerCHP.Examples;
model CHPSystem "Example that illustrates use of CHP model"
  extends Modelica.Icons.Example;

  AixLib.Fluid.BoilerCHP.CHP combinedHeatPower(
    redeclare package Medium =
        Media.Specialized.Water.TemperatureDependentDensity,
    m_flow_nominal=0.02,
    TSetIn=true,
    minCapacity=20,
    delayTime=300,
    param=DataBase.CHP.CHPDataSimple.CHP_FMB_65_GSK(),
    vol(energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial),
    Kc=0.02,
    Tc=100,
    elControl(initType=Modelica.Blocks.Types.Init.InitialOutput))
                                                       "CHP"
  Modelica.Fluid.Sources.MassFlowSource_T source(
    redeclare package Medium =
        Media.Specialized.Water.TemperatureDependentDensity,
    use_T_in=true,
    nPorts=1,
    m_flow=0.1)
    "Source"
  Modelica.Fluid.Sources.Boundary_pT sink(
    nPorts=1,
    redeclare package Medium =
        Media.Specialized.Water.TemperatureDependentDensity)
    "Sink"
  Modelica.Blocks.Sources.Trapezoid trapezoid(
    rising=7200,
    width=7200,
    falling=7200,
    period=28800,
    offset=313.15,
    amplitude=50,
    startTime=7200)
    "Source temperature"
  Modelica.Blocks.Sources.BooleanConstant on
    "CHP is always on"
  Modelica.Blocks.Sources.Constant TSet(k=80 + 273.15, y(unit="K"))
    "Set temperature"

equation
  connect(source.ports[1],combinedHeatPower. port_a)
  connect(combinedHeatPower.port_b, sink.ports[1])
  connect(trapezoid.y, source.T_in)
  connect(on.y,combinedHeatPower.on)
  connect(TSet.y,combinedHeatPower. TSet)
end CHPSystem;


within AixLib.Fluid.BoilerCHP.Examples;
model CHPSystemNoControl "Example that illustrates use of CHPNoControl model"
  extends Modelica.Icons.Example;
  package Medium = AixLib.Media.Water
  AixLib.Fluid.BoilerCHP.CHPNoControl combinedHeatPower(
    redeclare package Medium = Medium,
    m_flow_nominal=0.02,
    param=DataBase.CHP.CHPDataSimple.CHP_FMB_65_GSK()) "CHP"
  Modelica.Fluid.Sources.MassFlowSource_T source(
    redeclare package Medium = Medium,
    use_T_in=true,
    nPorts=1,
    m_flow=0.5)
    "Source"
  Modelica.Fluid.Sources.Boundary_pT sink(
    nPorts=1, redeclare package Medium = Medium)
    "Sink"
  Modelica.Blocks.Sources.Trapezoid trapezoid(
    rising=7200,
    width=7200,
    falling=7200,
    period=28800,
    offset=313.15,
    amplitude=50,
    startTime=7200)
    "Source temperature"
  Modelica.Blocks.Sources.Ramp     TSet(duration=200, startTime=10)
    "Set temperature"

equation
  connect(source.ports[1],combinedHeatPower. port_a)
  connect(combinedHeatPower.port_b, sink.ports[1])
  connect(trapezoid.y, source.T_in)
  connect(TSet.y, combinedHeatPower.u_rel)
end CHPSystemNoControl;


within AixLib.Fluid.BoilerCHP.Examples;
model HeatGeneratorNoControllSystem "Example that illustrates use of heat generator without control"
  extends Modelica.Icons.Example;

  Modelica.Fluid.Sources.MassFlowSource_T source(
    redeclare package Medium =
        Media.Specialized.Water.TemperatureDependentDensity,
    use_T_in=true,
    nPorts=1,
    m_flow=0.03)
    "Source"
  Modelica.Fluid.Sources.Boundary_pT sink(
    redeclare package Medium =
        Media.Specialized.Water.TemperatureDependentDensity, nPorts=1)
    "Sink"
  HeatGeneratorNoControl heatGeneratorNoControll(
    redeclare package Medium =
        Media.Specialized.Water.TemperatureDependentDensity, m_flow_nominal=
        0.03,
    V=0.002,
    coeffPresLoss=1e10)
    "Heat generator without control"
  Modelica.Blocks.Sources.Trapezoid trapezoid(
    rising=7200,
    width=7200,
    falling=7200,
    period=28800,
    offset=313.15,
    amplitude=50,
    startTime=7200)
    "Source temperature"
  Modelica.Blocks.Sources.Constant const(k=5000)
  "Prescribed heat flow"

equation
  connect(source.ports[1], heatGeneratorNoControll.port_a)
  connect(heatGeneratorNoControll.port_b, sink.ports[1])
  connect(trapezoid.y, source.T_in)
  connect(const.y, heatGeneratorNoControll.Q_flow)
end HeatGeneratorNoControllSystem;


within AixLib.Fluid.BoilerCHP.Examples;
model ModularCHPSystem
  "Example of the modular CHP power unit model inside a heating circuit"
  extends Modelica.Icons.Example;

  replaceable package Medium_Fuel =
      AixLib.DataBase.CHP.ModularCHPEngineMedia.NaturalGasMixture_TypeAachen
                                                                    constrainedby DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa
    "Fuel medium model used in the CHP plant"
  replaceable package Medium_Coolant = Modelica.Media.Air.DryAirNasa
                                                           constrainedby Modelica.Media.Interfaces.PartialMedium
    "Coolant medium model used in the CHP plant"

  replaceable package Medium_HeatingCircuit =
      Modelica.Media.CompressibleLiquids.LinearColdWater   constrainedby Modelica.Media.Interfaces.PartialMedium
    "Heating circuit medium model"

  parameter
    AixLib.DataBase.CHP.ModularCHPEngineData.CHPEngDataBaseRecord
    CHPEngineModel=DataBase.CHP.ModularCHPEngineData.CHP_Kirsch_L4_12()
    "CHP engine data for calculations"
  parameter AixLib.Fluid.BoilerCHP.Data.ModularCHP.EngineMaterialData EngMat=
      AixLib.Fluid.BoilerCHP.Data.ModularCHP.EngineMaterial_CastIron()
    "Thermal engine material data for calculations"
  parameter Modelica.Units.SI.Temperature T_amb=293.15
    "Default ambient temperature"
  parameter Modelica.Units.SI.AbsolutePressure p_amb=101325
    "Default ambient pressure"
  parameter Real s_til=abs((cHP_PowerUnit.cHP_PowerUnit.inductionMachine.s_nominal
      *(cHP_PowerUnit.cHP_PowerUnit.inductionMachine.M_til/cHP_PowerUnit.cHP_PowerUnit.inductionMachine.M_nominal)
       + cHP_PowerUnit.cHP_PowerUnit.inductionMachine.s_nominal*sqrt(abs(((
      cHP_PowerUnit.cHP_PowerUnit.inductionMachine.M_til/cHP_PowerUnit.cHP_PowerUnit.inductionMachine.M_nominal)
      ^2) - 1 + 2*cHP_PowerUnit.cHP_PowerUnit.inductionMachine.s_nominal*((
      cHP_PowerUnit.cHP_PowerUnit.inductionMachine.M_til/cHP_PowerUnit.cHP_PowerUnit.inductionMachine.M_nominal)
       - 1))))/(1 - 2*cHP_PowerUnit.cHP_PowerUnit.inductionMachine.s_nominal*((
      cHP_PowerUnit.cHP_PowerUnit.inductionMachine.M_til/cHP_PowerUnit.cHP_PowerUnit.inductionMachine.M_nominal)
       - 1)))
    "Tilting slip of electric machine"
  parameter Real calFac=0.94
    "Calibration factor for electric power output (default=1)"
  parameter Modelica.Units.SI.ThermalConductance GEngToCoo=33
    "Thermal conductance of engine housing from the cylinder wall to the water cooling channels"
  parameter Modelica.Units.SI.ThermalConductance GCooExhHex=400
    "Thermal conductance of the coolant heat exchanger at nominal flow"
  parameter Modelica.Units.SI.HeatCapacity CExhHex=50000
    "Heat capacity of exhaust heat exchanger(default= 4000 J/K)"
  parameter Modelica.Units.SI.Mass Cal_mEng=0
    "Added engine mass for calibration purposes of the system´s thermal inertia"
  parameter Modelica.Units.SI.Area A_surExhHea=100
    "Surface for exhaust heat transfer"
  parameter Modelica.Units.SI.MassFlowRate m_flow_Coo=0.4
    "Nominal mass flow rate of coolant inside the engine cooling circle"
  parameter Modelica.Units.SI.Thickness dInn=0.01
    "Typical value for the thickness of the cylinder wall (between combustion chamber and cooling circle)"
  parameter Modelica.Units.SI.ThermalConductance GEngToAmb=2
    "Thermal conductance from engine housing to the surrounding air"
  parameter Modelica.Units.SI.ThermalConductance GAmb=10
    "Constant heat transfer coefficient of engine housing to ambient"
  parameter Real modTab[:,2]=[0.0,0.8; 7200,0.8; 7200,0.93; 10800,0.93; 10800,0.62;
      14400,0.62; 14400,0.8; 18000,0.8; 18000,0.0]
    "Table for unit modulation (time = first column; modulation factors = second column)"
  parameter Modelica.Units.SI.Temperature T_HeaRet=303.15
    "Constant heating circuit return temperature"
  parameter Boolean ConTec=true
    "Is condensing technology used and should latent heat be considered?"
  parameter Boolean useGenHea=true
    "Is the thermal loss energy of the elctric machine used?"
  parameter Boolean allowFlowReversalExhaust=true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal for exhaust medium"
  parameter Boolean allowFlowReversalCoolant=true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal for coolant medium"
  parameter Boolean VolCon=true  "Is volume flow rate control used?"
  parameter Modelica.Units.SI.MassFlowRate
    mExh_flow_small=0.001
    "Small exhaust mass flow rate for regularization of zero flow"
  parameter Modelica.Units.SI.MassFlowRate
    mCool_flow_small=0.005
    "Small coolant mass flow rate for regularization of zero flow"
  parameter Modelica.Units.SI.Efficiency eps=0.9 "Heat exchanger effectiveness"

  Modelica.Units.SI.MassFlowRate m_flow_HeaCir=if not VolCon then
      CHPEngineModel.m_floCooNominal else V_flow_HeaCir*senDen.d
    "Nominal mass flow rate inside the heating circuit"
  Modelica.Units.SI.VolumeFlowRate V_flow_HeaCir=0.3/3600
    "Nominal volume flow rate inside the heating circuit"

  Modelica.Fluid.Sources.MassFlowSource_T source(
    use_T_in=true,
    redeclare package Medium = Medium_HeatingCircuit,
    nPorts=1,
    use_m_flow_in=true) "Flow source of heating circuit"
  Modelica.Fluid.Sources.FixedBoundary sink(redeclare package Medium =
        Medium_HeatingCircuit, nPorts=1) "Sink of the heating circuit"

  Modelica.Blocks.Sources.RealExpression tempFlowHeating(y=T_HeaRet)
  AixLib.Fluid.Sensors.DensityTwoPort senDen(
    m_flow_small=mCool_flow_small,
    m_flow_nominal=CHPEngineModel.m_floCooNominal,
    redeclare package Medium = Medium_HeatingCircuit)
    "Density sensor for volume and mass flow calculation"
  Modelica.Blocks.Sources.RealExpression massFlowHeating(y=m_flow_HeaCir)

  AixLib.Fluid.BoilerCHP.ModularCHP.ModularCHPIntegrated cHP_PowerUnit(
    redeclare package Medium_Fuel = Medium_Fuel,
    CHPEngineModel=CHPEngineModel,
    EngMat=EngMat,
    T_amb=T_amb,
    p_amb=p_amb,
    ConTec=ConTec,
    useGenHea=useGenHea,
    allowFlowReversalExhaust=allowFlowReversalExhaust,
    allowFlowReversalCoolant=allowFlowReversalCoolant,
    mExh_flow_small=mExh_flow_small,
    mCool_flow_small=mCool_flow_small,
    A_surExhHea=A_surExhHea,
    redeclare package Medium_Coolant = Medium_Coolant,
    GCooExhHex=GCooExhHex,
    CExhHex=CExhHex,
    dInn=dInn,
    GAmb=GAmb,
    calFac=calFac,
    GEngToCoo=GEngToCoo,
    GEngToAmb=GEngToAmb,
    m_flow_Coo=m_flow_Coo,
    redeclare package Medium_HeatingCircuit = Medium_HeatingCircuit,
    s_til=s_til,
    Cal_mEng=Cal_mEng,
    modTab=modTab,
    cHP_PowerUnit(inductionMachine(s_til=cHP_PowerUnit.cHP_PowerUnit.s_til)),
    coolantHex(eps=eps)) "Model of a CHP unit"

protected
  replaceable package Medium_Air =
      AixLib.DataBase.CHP.ModularCHPEngineMedia.EngineCombustionAir
                                                               constrainedby DataBase.CHP.ModularCHPEngineMedia.EngineCombustionAir
    "Air medium model used in the CHP plant"

  replaceable package Medium_Exhaust =
      DataBase.CHP.ModularCHPEngineMedia.CHPFlueGasLambdaOnePlus  constrainedby DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa
    "Exhaust gas medium model used in the CHP plant"

  parameter Modelica.Units.SI.Mass mEng=CHPEngineModel.mEng + Cal_mEng
    "Total engine mass for heat capacity calculation"

equation
  connect(source.T_in, tempFlowHeating.y)
  connect(source.ports[1], senDen.port_a)
  connect(massFlowHeating.y, source.m_flow_in)
  connect(cHP_PowerUnit.port_supHea, sink.ports[1])
  connect(senDen.port_b,cHP_PowerUnit.port_retHea)
end ModularCHPSystem;


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

end Examples;


within AixLib.Fluid.BoilerCHP.ModularCHP;
model ModularCHPIntegrated
  "Modular combined heat and power system model integrated into a heating circuit"
  import AixLib;

  replaceable package Medium_Fuel =
      AixLib.DataBase.CHP.ModularCHPEngineMedia.NaturalGasMixture_TypeAachen
                                                                    constrainedby DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa
    "Fuel medium model used in the CHP plant"
  replaceable package Medium_Coolant = Modelica.Media.Air.DryAirNasa
                                                           constrainedby Modelica.Media.Interfaces.PartialMedium
    "Coolant medium model used in the CHP plant"

  replaceable package Medium_HeatingCircuit =
      Modelica.Media.CompressibleLiquids.LinearColdWater   constrainedby Modelica.Media.Interfaces.PartialMedium
    "Heating circuit medium model"

  parameter
    AixLib.DataBase.CHP.ModularCHPEngineData.CHPEngDataBaseRecord
    CHPEngineModel=DataBase.CHP.ModularCHPEngineData.CHP_Kirsch_L4_12()
    "CHP engine data for calculations"

  parameter AixLib.Fluid.BoilerCHP.Data.ModularCHP.EngineMaterialData EngMat=
      AixLib.Fluid.BoilerCHP.Data.ModularCHP.EngineMaterial_CastIron()
    "Thermal engine material data for calculations"
  parameter Modelica.Units.SI.Temperature T_amb=293.15
    "Default ambient temperature"
  parameter Modelica.Units.SI.AbsolutePressure p_amb=101325
    "Default ambient pressure"
  parameter Real s_til=abs((cHP_PowerUnit.inductionMachine.s_nominal*(
      cHP_PowerUnit.inductionMachine.M_til/cHP_PowerUnit.inductionMachine.M_nominal)
       + cHP_PowerUnit.inductionMachine.s_nominal*sqrt(abs(((cHP_PowerUnit.inductionMachine.M_til
      /cHP_PowerUnit.inductionMachine.M_nominal)^2) - 1 + 2*cHP_PowerUnit.inductionMachine.s_nominal
      *((cHP_PowerUnit.inductionMachine.M_til/cHP_PowerUnit.inductionMachine.M_nominal)
       - 1))))/(1 - 2*cHP_PowerUnit.inductionMachine.s_nominal*((cHP_PowerUnit.inductionMachine.M_til
      /cHP_PowerUnit.inductionMachine.M_nominal) - 1)))
    "Tilting slip of electric machine"
  parameter Real calFac=0.94
    "Calibration factor for electric power output (default=1)"
  parameter Modelica.Units.SI.ThermalConductance GEngToCoo=33
    "Thermal conductance of engine housing from the cylinder wall to the water cooling channels"
  parameter Modelica.Units.SI.ThermalConductance GCooExhHex=400
    "Thermal conductance of the coolant heat exchanger at nominal flow"
  parameter Modelica.Units.SI.HeatCapacity CExhHex=50000
    "Heat capacity of exhaust heat exchanger(default= 4000 J/K)"
  parameter Modelica.Units.SI.Mass Cal_mEng=0
    "Added engine mass for calibration purposes of the system´s thermal inertia"
  parameter Modelica.Units.SI.Area A_surExhHea=100
    "Surface for exhaust heat transfer"
  parameter Modelica.Units.SI.MassFlowRate m_flow_Coo=0.4
    "Nominal mass flow rate of coolant inside the engine cooling circle"
  parameter Modelica.Units.SI.Thickness dInn=0.01
    "Typical value for the thickness of the cylinder wall (between combustion chamber and cooling circle)"
  parameter Modelica.Units.SI.ThermalConductance GEngToAmb=2
    "Thermal conductance from engine housing to the surrounding air"
  parameter Modelica.Units.SI.ThermalConductance GAmb=10
    "Constant heat transfer coefficient of engine housing to ambient"
  parameter Real modTab[:,2]=[0.0,0.8; 7200,0.8; 7200,0.93; 10800,0.93; 10800,0.62;
      14400,0.62; 14400,0.8; 18000,0.8; 18000,0.0]
    "Table for unit modulation (time = first column; modulation factors = second column)"
  parameter Boolean ConTec=true
    "Is condensing technology used and should latent heat be considered?"
  parameter Boolean useGenHea=true
    "Is the thermal loss energy of the elctric machine used?"
  parameter Boolean allowFlowReversalExhaust=true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal for exhaust medium"
  parameter Boolean allowFlowReversalCoolant=true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal for coolant medium"
  parameter Modelica.Units.SI.MassFlowRate
    mExh_flow_small=0.001
    "Small exhaust mass flow rate for regularization of zero flow"
  parameter Modelica.Units.SI.MassFlowRate
    mCool_flow_small=0.005
    "Small coolant mass flow rate for regularization of zero flow"

  Modelica.Units.SI.Temperature T_Ret=temRetFlo.T "Coolant return temperature";
  Modelica.Units.SI.Temperature T_Sup=temSupFlo.T "Coolant supply temperature";
  Modelica.Units.SI.Power Q_Therm_th=cHP_PowerUnit.Q_Therm
    "Thermal power output of the CHP unit to the coolant media";
  Modelica.Units.SI.Power Q_Therm=coolantHex.Q2_flow
    "Effective thermal power output of the CHP unit to the heating circuit";
  Modelica.Units.SI.Power P_Mech=cHP_PowerUnit.P_Mech
    "Mechanical power output of the CHP unit";
  Modelica.Units.SI.Power P_El=cHP_PowerUnit.P_El
    "Electrical power output of the CHP unit";
  Modelica.Units.SI.Power P_Fuel=cHP_PowerUnit.P_Fuel "CHP fuel expenses";
  Modelica.Units.SI.Power Q_TotUnused=cHP_PowerUnit.Q_TotUnused
    "Total heat error of the CHP unit";
  Modelica.Units.SI.MassFlowRate m_flow_CO2=cHP_PowerUnit.m_flow_CO2
    "CO2 emission output rate";
  Modelica.Units.SI.MassFlowRate m_flow_Fue=cHP_PowerUnit.m_flow_Fue
    "Fuel consumption rate of CHP unit";
  Real FueUtiRate = cHP_PowerUnit.FueUtiRate "Fuel utilization rate of the CHP unit";
  Real PowHeatRatio = cHP_PowerUnit.PowHeatRatio "Power to heat ration of the CHP unit";
  Real eta_Therm = cHP_PowerUnit.eta_Therm "Thermal efficiency of the CHP unit";
  Real eta_Mech = cHP_PowerUnit.eta_Mech "Mechanical efficiency of the CHP unit";
  Real eta_El = cHP_PowerUnit.eta_El "Mechanical efficiency of the CHP unit";

  inner Modelica.Fluid.System system(p_ambient=p_amb, T_ambient=T_amb)
  AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.ModularCHP_PowerUnit
    cHP_PowerUnit(
    redeclare package Medium_Fuel = Medium_Fuel,
    CHPEngineModel=CHPEngineModel,
    EngMat=EngMat,
    T_amb=T_amb,
    p_amb=p_amb,
    m_flow=m_flow_Coo,
    GEngToCoo=GEngToCoo,
    ConTec=ConTec,
    useGenHea=useGenHea,
    allowFlowReversalExhaust=allowFlowReversalExhaust,
    allowFlowReversalCoolant=allowFlowReversalCoolant,
    mExh_flow_small=mExh_flow_small,
    mCool_flow_small=mCool_flow_small,
    A_surExhHea=A_surExhHea,
    mEng=mEng,
    redeclare package Medium_Coolant = Medium_Coolant,
    GCooExhHex=GCooExhHex,
    CExhHex=CExhHex,
    inductionMachine(J_Gen=1),
    dInn=dInn,
    GEngToAmb=GEngToAmb,
    GAmb=GAmb,
    calFac=calFac,
    s_til=s_til)
    "Model of the main heat and power generating components of a CHP unit"
  AixLib.Fluid.HeatExchangers.ConstantEffectiveness coolantHex(
    allowFlowReversal1=allowFlowReversalCoolant,
    allowFlowReversal2=allowFlowReversalCoolant,
    m2_flow_nominal=CHPEngineModel.m_floCooNominal,
    m1_flow_small=mCool_flow_small,
    m2_flow_small=mCool_flow_small,
    redeclare package Medium1 = Medium_Coolant,
    m1_flow_nominal=m_flow_Coo,
    redeclare package Medium2 = Medium_HeatingCircuit,
    dp1_nominal(displayUnit="kPa") = 10000,
    dp2_nominal(displayUnit="kPa") = 10000,
    eps=0.9) "Heat exchanger between inner cooling and outer heating circuit"
  Modelica.Fluid.Sensors.TemperatureTwoPort temRetFlo(
    m_flow_small=mCool_flow_small,
    m_flow_nominal=CHPEngineModel.m_floCooNominal,
    redeclare package Medium = Medium_HeatingCircuit)
    "Heating circuit return flow temperature sensor"
  Modelica.Fluid.Sensors.TemperatureTwoPort temSupFlo(
    m_flow_small=mCool_flow_small,
    m_flow_nominal=CHPEngineModel.m_floCooNominal,
    redeclare package Medium = Medium_HeatingCircuit)
    "Heating circuit supply flow temperature sensor"
  AixLib.Fluid.BoilerCHP.BaseClasses.Controllers.ControllerOnOffModularCHP
    ControllerCHP(
    CHPEngineModel=CHPEngineModel,
    startTimeChp=3600,
    modTab=modTab) "On/Off control with modulation factor setting"
  Modelica.Fluid.Interfaces.FluidPort_a port_retHea(redeclare package Medium =
        Medium_Coolant)
    "Fluid port for the return flow side of the heating circuit"
  Modelica.Fluid.Interfaces.FluidPort_b port_supHea(redeclare package Medium =
        Medium_Coolant)
    "Fluid port for the supply flow side of the heating circuit"

  Modelica.Fluid.Sources.FixedBoundary fixedPressureLevel(
    nPorts=1,
    redeclare package Medium = Medium_Coolant,
    T(displayUnit="K"),
    p=300000)

protected
  replaceable package Medium_Air =
      AixLib.DataBase.CHP.ModularCHPEngineMedia.EngineCombustionAir
                                                               constrainedby DataBase.CHP.ModularCHPEngineMedia.EngineCombustionAir
    "Air medium model used in the CHP plant"

  replaceable package Medium_Exhaust =
      DataBase.CHP.ModularCHPEngineMedia.CHPFlueGasLambdaOnePlus  constrainedby DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa
    "Exhaust gas medium model used in the CHP plant"

  parameter Modelica.Units.SI.Mass mEng=CHPEngineModel.mEng + Cal_mEng
    "Total engine mass for heat capacity calculation"

equation
  connect(coolantHex.port_a2, temRetFlo.port_b)
  connect(coolantHex.port_b2, temSupFlo.port_a)
  connect(ControllerCHP.modCHPConBus, cHP_PowerUnit.sigBusCHP)
  connect(coolantHex.port_b1,cHP_PowerUnit.port_retCoo)
  connect(cHP_PowerUnit.port_supCoo, coolantHex.port_a1)
  connect(temSupFlo.port_b, port_supHea)
  connect(port_retHea, temRetFlo.port_a)
  connect(fixedPressureLevel.ports[1], cHP_PowerUnit.port_retCoo)
end ModularCHPIntegrated;


within AixLib.Fluid.BoilerCHP;
package ModularCHP "Modular and complex CHP model with physical calculation approaches."
end ModularCHP;


Model of a general induction machine working as a starter generator. Model of an electric induction machine that includes the calculation
  of:

within AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses;
model CHP_ElectricMachine
  "Model of a general induction machine working as a starter generator"
  extends Modelica.Electrical.Machines.Icons.TransientMachine;

  parameter
    AixLib.DataBase.CHP.ModularCHPEngineData.CHPEngDataBaseRecord
    CHPEngData=DataBase.CHP.ModularCHPEngineData.CHP_ECPowerXRGI15()
    "Needed engine data for calculations"

  parameter Modelica.Units.SI.Frequency n0=CHPEngData.n0
    "Idling speed of the electric machine"
  parameter Modelica.Units.SI.Frequency n_nominal=CHPEngData.n_nominal
    "Rated rotor speed"
  parameter Modelica.Units.SI.Frequency f_1=CHPEngData.f_1 "Frequency"
  parameter Modelica.Units.SI.Voltage U_1=CHPEngData.U_1 "Rated voltage"
  parameter Modelica.Units.SI.Current I_elNominal=CHPEngData.I_elNominal
    "Rated current"
  parameter Modelica.Units.SI.Current I_1_start=if P_Mec_nominal <= 15000 then
      7.2*I_elNominal else 8*I_elNominal
    "Motor start current (realistic factors used from DIN VDE 2650/2651)"
  parameter Modelica.Units.SI.Power P_elNominal=CHPEngData.P_elNominal
    "Nominal electrical power of electric machine"
  parameter Modelica.Units.SI.Power P_Mec_nominal=P_elNominal*(1 + s_nominal/
      0.22) "Nominal mechanical power of electric machine"
  parameter Modelica.Units.SI.Torque M_nominal=P_Mec_nominal/(2*Modelica.Constants.pi
      *n_nominal) "Nominal torque of electric machine"
  parameter Modelica.Units.SI.Torque M_til=2*M_nominal
    "Tilting torque of electric machine (realistic factor used from DIN VDE 2650/2651)"
  parameter Modelica.Units.SI.Torque M_start=if P_Mec_nominal <= 4000 then 1.6*
      M_nominal elseif P_Mec_nominal >= 22000 then 1*M_nominal else 1.25*
      M_nominal
    "Starting torque of electric machine (realistic factor used from DIN VDE 2650/2651)"
  parameter Modelica.Units.SI.Inertia J_Gen=1
    "Moment of inertia of the electric machine (default=1kg.m2)"
  parameter Boolean useHeat=CHPEngData.useHeat
    "Is the thermal loss energy of the elctric machine used?"
  parameter Real s_nominal=abs(1-n_nominal*p/f_1) "Nominal slip of electric machine"
  parameter Real s_til=abs((s_nominal*(M_til/M_nominal)+s_nominal*sqrt(abs(((M_til/M_nominal)^2)-1+2*s_nominal*((M_til/M_nominal)-1))))/(1-2*s_nominal*((M_til/M_nominal)-1)))
   "Tilting slip of electric machine"
  parameter Real p=CHPEngData.p
                     "Number of pole pairs"
  parameter Real cosPhi=CHPEngData.cosPhi
                            "Power factor of electric machine (default=0.8)"
  parameter Real calFac=1
    "Calibration factor for electric power outuput (default=1)"
  parameter Real gearRatio=CHPEngData.gearRatio
                             "Transmission ratio (engine speed / generator speed)"

  Modelica.Units.SI.Frequency n=inertia.w/(2*Modelica.Constants.pi)
    "Speed of machine rotor [1/s]";
  Modelica.Units.SI.Current I_1 "Electric current of machine stator";
  Modelica.Units.SI.Power P_E "Electrical power at the electric machine";
  Modelica.Units.SI.Power P_Mec "Mechanical power at the electric machine";
  Modelica.Units.SI.Power CalQ_Loss
    "Calculated heat flow from electric machine";
  Modelica.Units.SI.Power Q_Therm=if useHeat then CalQ_Loss else 0
    "Heat flow from electric machine"
  Modelica.Units.SI.Torque M "Torque at electric machine";
  Real s=1-n*p/f_1 "Current slip of electric machine";
  Real eta "Total efficiency of the electric machine (as motor)";
  Real calI_1 = 1/(1+((k-1)/((s_nominal^2)-k))*((s^2)+rho1*abs(s)+rho0));
  Boolean OpMode = (n<=n0) "Operation mode (true=motor, false=generator)";
  Boolean SwitchOnOff=cHPGenBus.isOn
    "Operation of electric machine (true=On, false=Off)";

  Modelica.Mechanics.Rotational.Components.Inertia inertia(       w(fixed=false), J=J_Gen)
    "Inertia model of the electric machine"
  Modelica.Blocks.Sources.RealExpression electricTorque1(y=M)
  Modelica.Mechanics.Rotational.Sources.Torque torque
    "Calculated torque of the electric machine"
  Modelica.Mechanics.Rotational.Interfaces.Flange_a flange_genIn
    "Mechanical port to the output drive"

  Modelica.Mechanics.Rotational.Components.IdealGear gearEngineToGenerator(
      ratio=gearRatio)
    "Model for mapping a possible transmission ratio between engine and generator"
  AixLib.Controls.Interfaces.CHPControlBus cHPGenBus
    "Signal bus of the electric machine"
  Modelica.Blocks.Sources.RealExpression electricCurrent(y=I_1)
  Modelica.Blocks.Sources.RealExpression electricTorque2(y=M)
  Modelica.Blocks.Sources.RealExpression electricPower(y=P_E)
  Modelica.Blocks.Sources.RealExpression generatorHeatLoss(y=Q_Therm)
  Modelica.Blocks.Sources.RealExpression generatorEfficiency(y=eta)

protected
  parameter Real rho0=s_til^2 "Calculation variable for analytical approach (Aree, 2017)"
  parameter Real rho1=(M_start*(1+s_til^2)-2*s_til*M_til)/(M_til-M_start) "Calculation variable for analytical approach (Aree, 2017)"
  parameter Real rho3=(M_til*M_start*(1-s_til)^2)/(M_til-M_start) "Calculation variable for analytical approach (Aree, 2017)"
  parameter Real k=((I_elNominal/I_1_start)^2)*(((s_nominal^2)+rho1*s_nominal+rho0)/(1+rho1+rho0)) "Calculation variable for analytical approach (Aree, 2017)"

equation

if noEvent(SwitchOnOff) then

  I_1=sign(s)*I_1_start*sqrt(abs((1+((k-1)/((s_nominal^2)-k))*(s^2)*(1+rho1+rho0))*calI_1));
  P_E=if noEvent(s>0) then sqrt(3)*I_1*U_1*cosPhi elseif noEvent(s<0) then calFac*(P_Mec+CalQ_Loss) else 1;
 // P_Mec=if noEvent(s>0) then 2*Modelica.Constants.pi*M*n else 2*Modelica.Constants.pi*n*M;
  P_Mec=2*Modelica.Constants.pi*M*n;
  CalQ_Loss= (calFac-1)*P_E + 2*Modelica.Constants.pi*M*(s*n0)/0.22;
  M=sign(s)*(rho3*abs(s))/((s^2)+rho1*abs(s)+rho0);
  eta=if noEvent(s>0) then abs(P_Mec/(P_E+1))
  elseif noEvent(s<0) then abs(P_E/(P_Mec-1)) else 0;

else

  I_1=0;
  P_E=0;
  P_Mec=0;
  CalQ_Loss=0;
  M=if noEvent(s<0) then sign(s)*(rho3*abs(s))/((s^2)+rho1*abs(s)+rho0) else 0;
  eta=0;

  end if;

  connect(electricTorque1.y, torque.tau)
  connect(torque.flange, inertia.flange_a)
  connect(inertia.flange_b, gearEngineToGenerator.flange_b)
  connect(gearEngineToGenerator.flange_a, flange_genIn)
  connect(generatorHeatLoss.y, cHPGenBus.calThePowGen)
  connect(electricPower.y, cHPGenBus.meaElPowGen)
  connect(electricTorque2.y, cHPGenBus.meaTorGen)
  connect(electricCurrent.y, cHPGenBus.meaCurGen)
  connect(generatorEfficiency.y, cHPGenBus.calEtaGen)
end CHP_ElectricMachine;


within AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses;
model ExhaustHeatExchanger
  "Exhaust gas heat exchanger for engine combustion and its heat transfer to a cooling circle"

  extends AixLib.Fluid.Interfaces.PartialFourPortInterface(
    m1_flow_nominal=0.023,
    m2_flow_nominal=0.5556,
    m1_flow_small=0.0001,
    m2_flow_small=0.0001,
    show_T=true,
    redeclare package Medium1 = Medium3,
    redeclare package Medium2 = Medium4);

  replaceable package Medium3 =
      AixLib.DataBase.CHP.ModularCHPEngineMedia.CHPFlueGasLambdaOnePlus
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Exhaust gas medium model used in the CHP plant"
  replaceable package Medium4 =
      DataBase.CHP.ModularCHPEngineMedia.CHPCoolantPropyleneGlycolWater (
                                      property_T=356, X_a=0.50) constrainedby Modelica.Media.Interfaces.PartialMedium
    "Coolant medium model used in the CHP plant"

  parameter
    AixLib.DataBase.CHP.ModularCHPEngineData.CHPEngDataBaseRecord
    CHPEngData=DataBase.CHP.ModularCHPEngineData.CHP_ECPowerXRGI15()
    "Needed engine data for calculations"
  parameter Modelica.Units.SI.Time tau=1
    "Time constant of the temperature sensors at nominal flow rate"
  parameter Modelica.Blocks.Types.Init initType=Modelica.Blocks.Types.Init.InitialState
    "Type of initialization (InitialState and InitialOutput are identical)"
  parameter Modelica.Units.SI.Temperature T1_start=T_Amb
    "Initial or guess value of output (= state)"
  parameter Modelica.Units.SI.Temperature T2_start=T_Amb
    "Initial or guess value of output (= state)"
  parameter Modelica.Media.Interfaces.Types.AbsolutePressure p1_start=p_Amb
    "Start value of pressure"
  parameter Modelica.Media.Interfaces.Types.AbsolutePressure p2_start=p_Amb
    "Start value of pressure"
  parameter Boolean transferHeat=false
    "If true, temperature T converges towards TAmb when no flow"
  parameter Boolean ConTec=false
    "Is condensing technology used and should latent heat be considered?"
  parameter Modelica.Units.SI.Temperature T_Amb=298.15
    "Fixed ambient temperature for heat transfer"
  parameter Modelica.Units.SI.Area A_surExhHea=50
    "Surface for exhaust heat transfer"
  parameter Modelica.Units.SI.Length d_iExh=CHPEngData.dExh
    "Inner diameter of exhaust pipe"
  parameter Modelica.Units.SI.ThermalConductance GAmb=5
    "Constant thermal conductance of material"
  parameter Modelica.Units.SI.ThermalConductance GCoo=850
    "Constant thermal conductance of material"
  parameter Modelica.Units.SI.HeatCapacity CExhHex=4000
    "Heat capacity of exhaust heat exchanger(default= 4000 J/K)"
  parameter Modelica.Media.Interfaces.Types.AbsolutePressure p_Amb=101325
    "Start value of pressure"
  parameter Modelica.Media.Interfaces.Types.AbsolutePressure dp_start=
      CHPEngData.dp_Coo
    "Guess value of dp = port_a.p - port_b.p"
  parameter Modelica.Units.SI.Time tauHeaTra=1200
    "Time constant for heat transfer, default 20 minutes"
  parameter Modelica.Units.SI.MassFlowRate m_flow_start=0
    "Guess value of m_flow = port_a.m_flow"
  constant Modelica.Units.SI.MolarMass M_H2O=0.01802 "Molar mass of water";

    //Antoine-Parameters needed for the calculation of the saturation vapor pressure xSat_H2OExhDry
  constant Real A=11.7621;
  constant Real B=3874.61;
  constant Real C=229.73;

  parameter Modelica.Units.SI.Length l_ExhHex=1
    "Length of the exhaust pipe inside the exhaust heat exchanger"
  parameter Modelica.Units.SI.PressureDifference dp_CooExhHex=CHPEngData.dp_Coo
    "Pressure drop at nominal mass flow rate inside the coolant circle "
  parameter Modelica.Units.SI.MolarMass M_Exh=1200
    "Molar mass of the exhaust gas"

  Real QuoT_ExhInOut=senTExhHot.T/senTExhCold.T
  "Quotient of exhaust gas in and outgoing temperature";

   //Variables for water condensation and its usable latent heat calculation
  Real x_H2OExhDry
    "Water load of the exhaust gas";
  Real xSat_H2OExhDry
    "Saturation water load of the exhaust gas";
  Modelica.Units.SI.MassFlowRate m_H2OExh
    "Mass flow of water in the exhaust gas";
  Modelica.Units.SI.MassFlowRate m_ExhDry "Mass flow of dry exhaust gas";
  Modelica.Units.SI.MassFlowRate m_ConH2OExh "Mass flow of condensing water";
  Modelica.Units.SI.AbsolutePressure pExh
    "Pressure in the exhaust gas stream (assuming ambient conditions)";
  Modelica.Units.SI.AbsolutePressure pSatH2OExh
    "Saturation vapor pressure of the exhaust gas water";
  Modelica.Units.SI.SpecificEnthalpy deltaH_Vap
    "Specific enthalpy of vaporization (empirical formula based on table data)";
  Modelica.Units.SI.SpecificHeatCapacity meanCpExh=cHPExhHexBus.calMeaCpExh
    "Calculated specific heat capacity of the exhaust gas for the calculated combustion temperature"
  Modelica.Units.SI.HeatFlowRate Q_Gen=cHPExhHexBus.calThePowGen
    "Calculated loss heat from the induction machine"
  Modelica.Units.SI.Temperature T_LogMeanExh
    "Mean logarithmic temperature of exhaust gas";

    //Calculation of the thermodynamic state of the exhaust gas inlet used by the convective heat transfer model
  Medium1.ThermodynamicState state1 = Medium1.setState_pTX(senTExhHot.port_b.p,T_LogMeanExh,senTExhHot.port_b.Xi_outflow);
  Modelica.Units.SI.SpecificEnthalpy h1_in=Medium1.specificEnthalpy(state1);
  Modelica.Units.SI.DynamicViscosity eta1_in=Medium1.dynamicViscosity(state1);
  Modelica.Units.SI.Density rho1_in=Medium1.density_phX(
      state1.p,
      h1_in,
      state1.X);
  Modelica.Units.SI.Velocity v1_in=senMasFloExh.m_flow/(Modelica.Constants.pi*
      rho1_in*d_iExh^2/4);
  Modelica.Units.SI.ThermalConductivity lambda1_in=Medium1.thermalConductivity(
      state1);
  Modelica.Units.SI.ReynoldsNumber Re1_in=
      Modelica.Fluid.Pipes.BaseClasses.CharacteristicNumbers.ReynoldsNumber(
      v1_in,
      rho1_in,
      eta1_in,
      d_iExh);

  Modelica.Blocks.Sources.RealExpression machineIsOff(y=0)
    "Calculated heat from generator losses"
  AixLib.Controls.Interfaces.CHPControlBus cHPExhHexBus
    "Signal bus of the exhaust gas heat exchanger"
  AixLib.Utilities.Logical.SmoothSwitch switch2
  Modelica.Blocks.Sources.RealExpression heatToCooling(y=pipeCoolant.heatPort_outside.Q_flow)
  Modelica.Blocks.Sources.RealExpression condensingWater(y=m_ConH2OExh)
  AixLib.Fluid.Sensors.TemperatureTwoPort senTExhHot(
    redeclare final package Medium = Medium1,
    final tau=tau,
    final m_flow_nominal=m1_flow_nominal,
    final initType=initType,
    final T_start=T1_start,
    final transferHeat=transferHeat,
    final TAmb=T_Amb,
    final tauHeaTra=tauHeaTra,
    final allowFlowReversal=allowFlowReversal1,
    final m_flow_small=m1_flow_small)
    "Temperature sensor of hot side of exhaust heat exchanger"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTExhCold(
    redeclare final package Medium = Medium1,
    final tau=tau,
    final m_flow_nominal=m1_flow_nominal,
    final initType=initType,
    final T_start=T1_start,
    final transferHeat=transferHeat,
    final TAmb=T_Amb,
    final tauHeaTra=tauHeaTra,
    final allowFlowReversal=allowFlowReversal1,
    final m_flow_small=m1_flow_small)
    "Temperature sensor of cold side of exhaust heat exchanger"
  AixLib.Fluid.Sensors.MassFlowRate senMasFloExh(redeclare final package Medium =
        Medium1, final allowFlowReversal=allowFlowReversal1)
    "Sensor for mass flwo rate"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTCooCold(
    redeclare final package Medium = Medium2,
    final tau=tau,
    final m_flow_nominal=m2_flow_nominal,
    final initType=initType,
    final T_start=T2_start,
    final transferHeat=transferHeat,
    final TAmb=T_Amb,
    final tauHeaTra=tauHeaTra,
    final allowFlowReversal=allowFlowReversal2,
    final m_flow_small=m2_flow_small)
    "Temperature sensor of coolant cold side of exhaust heat exchanger"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTCooHot(
    redeclare final package Medium = Medium2,
    final tau=tau,
    final m_flow_nominal=m2_flow_nominal,
    final initType=initType,
    final T_start=T2_start,
    final transferHeat=transferHeat,
    final TAmb=T_Amb,
    final tauHeaTra=tauHeaTra,
    final allowFlowReversal=allowFlowReversal2,
    final m_flow_small=m2_flow_small)
    "Temperature sensor of coolant hot side of exhaust heat exchanger"
  AixLib.Fluid.Sensors.MassFlowRate senMasFloCool(redeclare final package Medium =
               Medium2, final allowFlowReversal=allowFlowReversal2)
    "Sensor for mass flwo rate"
  AixLib.Fluid.FixedResistances.Pipe pipeCoolant(
    redeclare package Medium = Medium2,
    isEmbedded=true,
    Heat_Loss_To_Ambient=true,
    withInsulation=false,
    use_HeatTransferConvective=false,
    eps=0,
    hCon_i=GCoo/(pipeCoolant.perimeter*pipeCoolant.length),
    diameter=0.03175,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalLaminarFlow (
          m_flow_nominal=m2_flow_nominal, dp_nominal=10))
    "Pipe model for heat transfer to the cooling circuit"
  Modelica.Fluid.Vessels.ClosedVolume volExhaust(
    redeclare final package Medium = Medium1,
    final m_flow_nominal=m1_flow_nominal,
    final p_start=p1_start,
    final T_start=T1_start,
    use_HeatTransfer=true,
    redeclare model HeatTransfer =
        Modelica.Fluid.Vessels.BaseClasses.HeatTransfer.IdealHeatTransfer,
    use_portsData=false,
    final m_flow_small=m1_flow_small,
    V=VExhHex,
    nPorts=2) "Fluid volume of the exhaust gas inside the heat exchanger"
  AixLib.Fluid.FixedResistances.HydraulicDiameter
                                pressureDropExhaust(
    redeclare final package Medium = Medium1,
    final show_T=false,
    final allowFlowReversal=allowFlowReversal1,
    final m_flow_nominal=m1_flow_nominal,
    dh=d_iExh,
    length=l_ExhHex) "Pressure drop of the exhaust gas"
  AixLib.Utilities.HeatTransfer.HeatConvPipeInsideDynamic
    heatConvExhaustPipeInside(
    d_i=d_iExh,
    A_sur=A_surExhHea,
    rho=rho1_in,
    lambda=lambda1_in,
    eta=eta1_in,
    c=cHPExhHexBus.calMeaCpExh,
    m_flow=cHPExhHexBus.meaMasFloFueEng + cHPExhHexBus.meaMasFloAirEng)
    "Heat transfer model using convection calculation"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow additionalHeat
    "Heat flow from water condensation in the exhaust gas and generator losses"
  Modelica.Blocks.Sources.RealExpression latentAndGeneratorHeat(y=m_ConH2OExh*
        deltaH_Vap + Q_Gen)
    "Calculated latent exhaust heat from water condensation"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor heatCapacitor(C=
        CExhHex, T(start=T_Amb, fixed=true))
    "Thermal capacity of the exhaust gas heat exchanger"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor ambientLoss(G=
        GAmb)
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_amb
    "Heat port to ambient"

protected
  parameter Modelica.Units.SI.Volume VExhHex=l_ExhHex/4*Modelica.Constants.pi*
      d_iExh^2 "Exhaust gas volume inside the exhaust heat exchanger"

equation
//Calculation of water condensation and its usable latent heat
  if ConTec then
  x_H2OExhDry=senTExhHot.port_a.Xi_outflow[3]/(1 - senTExhHot.port_a.Xi_outflow[3]);
  xSat_H2OExhDry=if noEvent(M_H2O*pSatH2OExh/((pExh-pSatH2OExh)*M_Exh)>=0) then M_H2O*pSatH2OExh/((pExh-pSatH2OExh)*M_Exh) else x_H2OExhDry;
  m_H2OExh=senMasFloExh.m_flow*senTExhHot.port_a.Xi_outflow[3];
  m_ExhDry=senMasFloExh.m_flow-m_H2OExh;
  m_ConH2OExh=if (x_H2OExhDry>xSat_H2OExhDry) then m_ExhDry*(x_H2OExhDry-xSat_H2OExhDry) else 0;
  pExh=senTExhHot.port_a.p;
  pSatH2OExh=100000*Modelica.Math.exp(A-B/(senTExhCold.T-273.15+C));
  deltaH_Vap=2697400+446.25*senTExhCold.T-4.357*(senTExhCold.T)^2;
  else
  x_H2OExhDry=0;
  xSat_H2OExhDry=0;
  m_H2OExh=0;
  m_ExhDry=0;
  m_ConH2OExh=0;
  pExh=0;
  pSatH2OExh=0;
  deltaH_Vap=0;
  end if;

  if (QuoT_ExhInOut-1)>0.0001 then
  T_LogMeanExh=(senTExhHot.T-senTExhCold.T)/Modelica.Math.log(QuoT_ExhInOut);
  else
  T_LogMeanExh=senTExhHot.T;
  end if;

  connect(senTExhCold.port_b, senMasFloExh.port_a)
  connect(port_a1, senTExhHot.port_a)
  connect(senMasFloExh.port_b, port_b1)
  connect(port_a2, senTCooCold.port_b)
  connect(senTCooHot.port_a, senMasFloCool.port_a)
  connect(senMasFloCool.port_b, port_b2)
  connect(port_amb, ambientLoss.port_b)
  connect(senTCooCold.port_a, pipeCoolant.port_a)
  connect(senTCooHot.port_b, pipeCoolant.port_b)
  connect(ambientLoss.port_a, heatCapacitor.port)
  connect(heatCapacitor.port, pipeCoolant.heatPort_outside)
  connect(volExhaust.heatPort, heatConvExhaustPipeInside.port_a)
  connect(heatConvExhaustPipeInside.port_b, heatCapacitor.port)
  connect(pressureDropExhaust.port_b, senTExhCold.port_a)
  connect(additionalHeat.port, heatCapacitor.port)
  connect(senTExhHot.port_b, volExhaust.ports[1])
  connect(pressureDropExhaust.port_a, volExhaust.ports[2])
  connect(switch2.y, additionalHeat.Q_flow)
  connect(cHPExhHexBus.isOn, switch2.u2)
  connect(latentAndGeneratorHeat.y, switch2.u1)
  connect(machineIsOff.y, switch2.u3)
  connect(senTCooHot.T, cHPExhHexBus.meaTemOutHex)
  connect(senTCooCold.T, cHPExhHexBus.meaTemInHex)
  connect(senTExhHot.T, cHPExhHexBus.meaTemExhHexIn)
  connect(senTExhCold.T, cHPExhHexBus.meaTemExhHexOut)
  connect(heatToCooling.y, cHPExhHexBus.meaThePowOutHex)
  connect(condensingWater.y, cHPExhHexBus.meaMasFloConHex)
end ExhaustHeatExchanger;