within AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses;
model GasolineEngineChp
  "Thermal and mechanical model of an internal combustion engine with consideration of the individual mass flows"

  replaceable package Medium_Fuel =
      DataBase.CHP.ModularCHPEngineMedia.LiquidFuel_LPG             constrainedby DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa
    "Fuel medium model used in the CHP plant"
  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
    DataBase.CHP.ModularCHPEngineData.CHPEngDataBaseRecord
    CHPEngineModel=AixLib.DataBase.CHP.ModularCHPEngineData.CHP_ECPowerXRGI15()
    "CHP engine data for calculations"
  parameter Data.ModularCHP.EngineMaterialData EngMat=
      AixLib.Fluid.BoilerCHP.Data.ModularCHP.EngineMaterial_CastIron()
    "Thermal engine material data for calculations"
  parameter Modelica.Units.SI.Temperature T_amb=298.15
    "Default ambient temperature"
  parameter Modelica.Units.SI.Mass mEng=CHPEngineModel.mEng
    "Total engine mass for heat capacity calculation"
  parameter Modelica.Units.SI.Thickness dInn=0.005
    "Typical value for the thickness of the cylinder wall (between combustion chamber and cooling circle)"
  parameter Modelica.Units.SI.ThermalConductance GEngToAmb=0.23
    "Thermal conductance from engine housing to the surrounding air"

  AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.BaseClassComponents.GasolineEngineChp_EngineModel
    cHPCombustionEngine(
    redeclare package Medium1 = Medium_Fuel,
    redeclare package Medium2 = Medium_Air,
    redeclare package Medium3 = Medium_Exhaust,
    T_Amb=T_amb,
    CHPEngData=CHPEngineModel,
    inertia(phi(fixed=false), w(fixed=false, displayUnit="rad/s")),
    T_logEngCool=T_logEngCoo,
    T_ExhCHPOut=T_ExhCHPOut,
    modFac=modFac,
    SwitchOnOff=cHPEngBus.isOn)
    "Mean value combustion engine model with mechanical and fluid ports"
  AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.BaseClassComponents.GasolineEngineChp_EngineHousing
    engineToCoolant(
    z=CHPEngineModel.z,
    eps=CHPEngineModel.eps,
    m_Exh=cHPCombustionEngine.m_flow_Exh,
    T_Amb=T_amb,
    redeclare package Medium3 = Medium_Exhaust,
    dCyl=CHPEngineModel.dCyl,
    hStr=CHPEngineModel.hStr,
    meanCpExh=cHPCombustionEngine.meanCpExh,
    cylToInnerWall(maximumEngineHeat(y=cHPCombustionEngine.Q_therm),
        heatLimit(strict=true)),
    T_Com=cHPCombustionEngine.T_Com,
    nEng=cHPCombustionEngine.nEng,
    lambda=EngMat.lambda,
    rhoEngWall=EngMat.rhoEngWall,
    c=EngMat.c,
    EngMatData=EngMat,
    mEng=mEng,
    dInn=dInn,
    T_ExhPowUniOut=T_ExhCHPOut,
    GEngToAmb=GEngToAmb)
    "A physikal model for calculating the thermal, mass and mechanical output of an ice powered CHP"
  Modelica.Mechanics.Rotational.Interfaces.Flange_a flange_eng
    "Mechanical port of the engines output drive"
  Modelica.Fluid.Interfaces.FluidPort_b port_exh(redeclare package Medium =
        Medium_Exhaust)
    "Fluid port of the exhaust gas comming from the combustion engine"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_amb
    "Heat port to ambient"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_cooCir
    "Heat port to cooling circuit"
  AixLib.Controls.Interfaces.CHPControlBus cHPEngBus
    "Signal bus of the combustion engine model"

protected
  Real modFac=cHPEngBus.modFac
    "Modulation factor for energy outuput control of the Chp unit  "
  Modelica.Units.SI.Temperature T_logEngCoo=(cHPEngBus.meaTemInEng + cHPEngBus.meaTemOutEng)
      /2 "Logarithmic mean temperature of coolant inside the engine"
  Modelica.Units.SI.Temperature T_ExhCHPOut=cHPEngBus.meaTemExhHexOut
    "Exhaust gas outlet temperature of CHP unit"
  Modelica.Units.SI.Temperature T_Exh=engineToCoolant.T_Exh
    "Calculated mean temperature of the exhaust gas inside the cylinders"

equation
  connect(port_exh, cHPCombustionEngine.port_exh)
  connect(port_amb, engineToCoolant.port_amb)
  connect(port_cooCir, engineToCoolant.port_coo)
  connect(engineToCoolant.exhaustGasTemperature, cHPCombustionEngine.exhaustGasTemperature)
  connect(cHPCombustionEngine.flange_a, flange_eng)
  connect(cHPEngBus, cHPCombustionEngine.cHPEngineBus)
end GasolineEngineChp;


Model of modular CHP power unit

within AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses;
model ModularCHP_PowerUnit "Model of modular CHP power unit"
  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"

  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=298.15
    "Default ambient temperature"
  parameter Modelica.Units.SI.AbsolutePressure p_amb=101325
    "Default ambient pressure"
 /* Modelica.SIunits.Temperature T_CoolRet=exhaustHeatExchanger_Experimental_New.senTCooCold.T
    "Coolant return temperature";
  Modelica.SIunits.Temperature T_CooSup=submodel_CoolingEASY_New.senTCooEngOut.T
    "Coolant supply temperature";*/
  parameter Real s_til=abs((inductionMachine.s_nominal*(inductionMachine.M_til/
      inductionMachine.M_nominal) + inductionMachine.s_nominal*sqrt(abs(((
      inductionMachine.M_til/inductionMachine.M_nominal)^2) - 1 + 2*
      inductionMachine.s_nominal*((inductionMachine.M_til/inductionMachine.M_nominal)
       - 1))))/(1 - 2*inductionMachine.s_nominal*((inductionMachine.M_til/
      inductionMachine.M_nominal) - 1))) "Tilting slip of electric machine"
  parameter Real calFac=1
    "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 exhaust heat exchanger to cooling circuit"
  parameter Modelica.Units.SI.Mass mEng=CHPEngineModel.mEng
    "Total engine mass for heat capacity calculation"
  parameter Modelica.Units.SI.HeatCapacity CExhHex=50000
    "Heat capacity of exhaust heat exchanger(default= 4000 J/K)"
  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=0.23
    "Thermal conductance from engine housing to the surrounding air"
  parameter Modelica.Units.SI.ThermalConductance GAmb=5
    "Constant thermal conductance of material"
  parameter Modelica.Units.SI.Area A_surExhHea=50
    "Surface for exhaust heat transfer"
  parameter Modelica.Units.SI.MassFlowRate m_flow=
      CHPEngineModel.m_floCooNominal
    "Nominal mass flow rate of coolant inside the engine cooling circle"
  parameter Boolean ConTec=false
    "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.0001
    "Small exhaust mass flow rate for regularization of zero flow"
  parameter Modelica.Units.SI.MassFlowRate
    mCool_flow_small=0.0001
    "Small coolant mass flow rate for regularization of zero flow"

  Modelica.Units.SI.Power Q_Therm=if (submodelCooling.heatPort_outside.Q_flow
       + exhaustHeatExchanger.pipeCoolant.heatPort_outside.Q_flow) > 10 then
      submodelCooling.heatPort_outside.Q_flow + exhaustHeatExchanger.pipeCoolant.heatPort_outside.Q_flow
       else 1 "Thermal power output of the CHP unit";
  Modelica.Units.SI.Power P_Mech=gasolineEngineChp.cHPCombustionEngine.P_eff
    "Mechanical power output of the CHP unit";
  Modelica.Units.SI.Power P_El=-inductionMachine.P_E
    "Electrical power output of the CHP unit";
  Modelica.Units.SI.Power P_Fuel=if (gasolineEngineChp.cHPEngBus.isOn) then
      m_flow_Fue*Medium_Fuel.H_U else 0 "CHP fuel expenses";
  Modelica.Units.SI.Power Q_TotUnused=gasolineEngineChp.cHPCombustionEngine.Q_therm
       - gasolineEngineChp.engineToCoolant.actualHeatFlowEngine.Q_flow +
      exhaustHeatExchanger.volExhaust.heatPort.Q_flow
    "Total heat error of the CHP unit";
  Modelica.Units.SI.MassFlowRate m_flow_CO2=gasolineEngineChp.cHPCombustionEngine.m_flow_CO2Exh
    "CO2 emission output rate";
  Modelica.Units.SI.MassFlowRate m_flow_Fue=if (gasolineEngineChp.cHPCombustionEngine.m_flow_Fue)
       > 0.0001 then gasolineEngineChp.cHPCombustionEngine.m_flow_Fue else
      0.0001 "Fuel consumption rate of CHP unit";
  type SpecificEmission=Real(final unit="g/(kW.h)", min=0.0001);
  SpecificEmission b_CO2=if noEvent(abs(Q_Therm + P_El) > 0) then 3600000000.0 *
      m_flow_CO2/(Q_Therm + P_El) else 0
    "Specific CO2 emissions per kWh (heat and power)";
  SpecificEmission b_e=if noEvent(abs(Q_Therm + P_El) > 0) then 3600000000.0 *
      m_flow_Fue/(Q_Therm + P_El) else 0
    "Specific fuel consumption per kWh (heat and power)";
  Real FueUtiRate=(Q_Therm + P_El)/(m_flow_Fue*Medium_Fuel.H_U)
    "Fuel utilization rate of the CHP unit";
  Real PowHeatRatio = P_El/Q_Therm "Power to heat ration of the CHP unit";
  Real eta_Therm=Q_Therm/(m_flow_Fue*Medium_Fuel.H_U)
    "Thermal efficiency of the CHP unit";
  Real eta_Mech=P_Mech/(m_flow_Fue*Medium_Fuel.H_U)
    "Mechanical efficiency of the CHP unit";
  Real eta_El=P_El/(m_flow_Fue*Medium_Fuel.H_U)
    "Mechanical efficiency of the CHP unit";

  inner Modelica.Fluid.System system(p_ambient=p_amb, T_ambient=T_amb)
  Modelica.Fluid.Sources.FixedBoundary outletExhaustGas(
    redeclare package Medium = Medium_Exhaust,
    p=p_amb,
    nPorts=1)
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature ambientTemperature(T=
       T_amb) "Ambient temperature for thermal loss calculation"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heatFlowSensor
  AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.ExhaustHeatExchanger
    exhaustHeatExchanger(
    pipeCoolant(
      p_a_start=system.p_start,
      p_b_start=system.p_start,
      use_HeatTransferConvective=false,
      isEmbedded=true,
      diameter=CHPEngineModel.dCoo,
      allowFlowReversal=allowFlowReversalCoolant),
    T_Amb=T_amb,
    p_Amb=p_amb,
    redeclare package Medium3 = Medium_Exhaust,
    redeclare package Medium4 = Medium_Coolant,
    d_iExh=CHPEngineModel.dExh,
    dp_CooExhHex=CHPEngineModel.dp_Coo,
    heatConvExhaustPipeInside(length=exhaustHeatExchanger.l_ExhHex),
    CHPEngData=CHPEngineModel,
    M_Exh=gasolineEngineChp.cHPCombustionEngine.MM_Exh,
    allowFlowReversal1=allowFlowReversalExhaust,
    allowFlowReversal2=allowFlowReversalCoolant,
    m1_flow_small=mExh_flow_small,
    m2_flow_small=mCool_flow_small,
    ConTec=ConTec,
    A_surExhHea=A_surExhHea,
    m2_flow_nominal=m_flow,
    CExhHex=CExhHex,
    GCoo=GCooExhHex,
    GAmb=GAmb) "Exhaust gas heat exchanger of a CHP power unit"
  AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.CHP_ElectricMachine
    inductionMachine(
    CHPEngData=CHPEngineModel,
    useHeat=useGenHea,
    calFac=calFac,
    s_til=s_til)
    "Induction machine working as a starter motor and generator inside the CHP power unit"
  Modelica.Fluid.Interfaces.FluidPort_a port_retCoo(redeclare package Medium =
        Medium_Coolant)
    "Fluid port for the return flow side of the cooling circuit"
  Modelica.Fluid.Interfaces.FluidPort_b port_supCoo(redeclare package Medium =
        Medium_Coolant)
    "Fluid port for the supply flow side of the cooling circuit"
  AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.GasolineEngineChp
    gasolineEngineChp(
    redeclare package Medium_Fuel = Medium_Fuel,
    redeclare package Medium_Air = Medium_Air,
    redeclare package Medium_Exhaust = Medium_Exhaust,
    CHPEngineModel=CHPEngineModel,
    EngMat=EngMat,
    T_amb=T_amb,
    mEng=mEng,
    dInn=dInn,
    GEngToAmb=GEngToAmb)
    "Combustion engine with thermal and mechanical power output"
  AixLib.Controls.Interfaces.CHPControlBus     sigBusCHP
    "Signal bus connector for the CHP power unit"
  AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.SubmodelCooling submodelCooling(
    redeclare package Medium_Coolant = Medium_Coolant,
    CHPEngineModel=CHPEngineModel,
    m_flow=m_flow,
    GEngToCoo=GEngToCoo,
    allowFlowReversalCoolant=allowFlowReversalCoolant,
    mCool_flow_small=mCool_flow_small)
    "Model of the main fluid components inside the cooling circuit of a CHP power unit"
  Modelica.Blocks.Sources.RealExpression specificFuelUse(y=b_e)
  Modelica.Blocks.Sources.RealExpression specificCO2(y=b_CO2)
  Modelica.Blocks.Sources.RealExpression thermalPowerCHP(y=Q_Therm)
  Modelica.Blocks.Sources.RealExpression thermalEfficiencyCHP(y=eta_Therm)
  Modelica.Blocks.Sources.RealExpression electricEfficiencyCHP(y=eta_El)
  Modelica.Blocks.Sources.RealExpression fuelUtilizationRate(y=FueUtiRate)

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"

equation
  connect(ambientTemperature.port, heatFlowSensor.port_b)
  connect(inductionMachine.flange_genIn, gasolineEngineChp.flange_eng)
  connect(gasolineEngineChp.port_exh, exhaustHeatExchanger.port_a1)
  connect(gasolineEngineChp.port_amb, heatFlowSensor.port_a)
  connect(gasolineEngineChp.port_cooCir, submodelCooling.heatPort_outside)
  connect(exhaustHeatExchanger.port_amb, heatFlowSensor.port_a)
  connect(inductionMachine.cHPGenBus, sigBusCHP)
  connect(exhaustHeatExchanger.cHPExhHexBus, sigBusCHP)
  connect(gasolineEngineChp.cHPEngBus, sigBusCHP)
  connect(port_supCoo, submodelCooling.port_b)
  connect(exhaustHeatExchanger.port_b2, submodelCooling.port_a)
  connect(submodelCooling.sigBus_coo, sigBusCHP)
  connect(port_retCoo, exhaustHeatExchanger.port_a2)
  connect(exhaustHeatExchanger.port_b1, outletExhaustGas.ports[1])
  connect(thermalPowerCHP.y, sigBusCHP.meaThePowChp)
  connect(specificCO2.y, sigBusCHP.calEmiCO2Chp)
  connect(specificFuelUse.y, sigBusCHP.calFueChp)
  connect(thermalEfficiencyCHP.y, sigBusCHP.calEtaTheChp)
  connect(electricEfficiencyCHP.y, sigBusCHP.calEtaElChp)
  connect(fuelUtilizationRate.y, sigBusCHP.calFueUtiChp)
end ModularCHP_PowerUnit;


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


within AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses;
model SubmodelCooling

  replaceable package Medium_Coolant =
      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
    DataBase.CHP.ModularCHPEngineData.CHPEngDataBaseRecord
    CHPEngineModel=DataBase.CHP.ModularCHPEngineData.CHP_ECPowerXRGI15()
    "CHP engine data for calculations"
  parameter Modelica.Units.SI.MassFlowRate m_flow=
      CHPEngineModel.m_floCooNominal
    "Nominal mass flow rate of coolant inside the engine cooling circle"
  parameter Modelica.Units.SI.ThermalConductance GEngToCoo=45
    "Thermal conductance of engine housing from the cylinder wall to the water cooling channels"
  parameter Boolean allowFlowReversalCoolant=true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal for coolant medium"
  parameter Modelica.Units.SI.MassFlowRate
    mCool_flow_small=0.0001
    "Small coolant mass flow rate for regularization of zero flow"

  outer Modelica.Fluid.System system
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort_outside
    "Heat port to engine"
  Modelica.Fluid.Interfaces.FluidPort_a port_a(redeclare package Medium =
        Medium_Coolant)
    "Fluid port for the return flow side of the cooling circuit model"
  Modelica.Fluid.Interfaces.FluidPort_b port_b(redeclare package Medium =
        Medium_Coolant)
    "Fluid port for the supply flow side of the cooling circuit model"
  AixLib.Controls.Interfaces.CHPControlBus sigBus_coo
    "Signal bus of the cooling circuit components"
  Movers.FlowControlled_m_flow                coolantPump(
    m_flow_small=mCool_flow_small,
    redeclare package Medium = Medium_Coolant,
    dp_nominal=CHPEngineModel.dp_Coo,
    allowFlowReversal=allowFlowReversalCoolant,
    addPowerToMedium=false,
    m_flow_nominal=m_flow,
    use_inputFilter=false) "Model of a fluid pump or fan"
  AixLib.Utilities.Logical.SmoothSwitch switch1
  Modelica.Blocks.Sources.RealExpression massFlowPump(y=m_flow)
  Modelica.Blocks.Sources.RealExpression minMassFlowPump(y=mCool_flow_small)
  Modelica.Fluid.Sensors.TemperatureTwoPort senTCooEngIn(
    redeclare package Medium = Medium_Coolant,
    allowFlowReversal=allowFlowReversalCoolant,
    m_flow_nominal=m_flow,
    m_flow_small=mCool_flow_small) "Temperature sensor of engine cooling inlet"
  FixedResistances.Pipe engineHeatTransfer(
    redeclare package Medium = Medium_Coolant,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalLaminarFlow (
          dp_nominal=CHPEngineModel.dp_Coo, m_flow_nominal=m_flow),
    Heat_Loss_To_Ambient=true,
    eps=0,
    isEmbedded=true,
    use_HeatTransferConvective=false,
    p_a_start=system.p_start,
    p_b_start=system.p_start,
    hCon_i=GEngToCoo/(engineHeatTransfer.perimeter*engineHeatTransfer.length),
    diameter=CHPEngineModel.dCoo,
    allowFlowReversal=allowFlowReversalCoolant)
  Modelica.Fluid.Sensors.TemperatureTwoPort senTCooEngOut(
    redeclare package Medium = Medium_Coolant,
    allowFlowReversal=allowFlowReversalCoolant,
    m_flow_nominal=m_flow,
    m_flow_small=mCool_flow_small)
    "Temperature sensor of engine cooling outlet"

equation
  connect(engineHeatTransfer.port_b, senTCooEngOut.port_a)
  connect(heatPort_outside, engineHeatTransfer.heatPort_outside)
  connect(port_a, senTCooEngIn.port_a)
  connect(port_b, senTCooEngOut.port_b)
  connect(senTCooEngIn.port_b, coolantPump.port_a)
  connect(engineHeatTransfer.port_a, coolantPump.port_b)
  connect(switch1.y, coolantPump.m_flow_in)
  connect(sigBus_coo.isOnPump, switch1.u2)
  connect(massFlowPump.y, switch1.u1)
  connect(minMassFlowPump.y, switch1.u3)
  connect(senTCooEngIn.T, sigBus_coo.meaTemInEng)
  connect(senTCooEngOut.T, sigBus_coo.meaTemOutEng)
end SubmodelCooling;


within AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.BaseClassComponents;
class GasolineEngineChp_EngineHousing
  "Engine housing as a simple two layer wall."

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

  parameter Modelica.Units.SI.Thickness dInn=0.005
    "Typical value for the thickness of the cylinder wall (between combustion chamber and cooling circle)"
  parameter AixLib.Fluid.BoilerCHP.Data.ModularCHP.EngineMaterialData
    EngMatData=AixLib.Fluid.BoilerCHP.Data.ModularCHP.EngineMaterial_CastIron()
    "Thermal engine material data for calculations (most common is cast iron)"
  constant Modelica.Units.SI.ThermalConductivity lambda=EngMatData.lambda
    "Thermal conductivity of the engine block material"
  constant Modelica.Units.SI.Density rhoEngWall=EngMatData.rhoEngWall
    "Density of the the engine block material"
  constant Modelica.Units.SI.SpecificHeatCapacity c=EngMatData.c
    "Specific heat capacity of the cylinder wall material"
  constant Real z
    "Number of engine cylinders"
  constant Modelica.Units.SI.Thickness dCyl "Engine cylinder diameter"
  constant Modelica.Units.SI.Thickness hStr "Engine stroke"
  constant Real eps
    "Engine compression ratio"
  parameter Modelica.Units.SI.Mass mEng "Total engine mass"
  parameter Modelica.Units.SI.ThermalConductance GEngToAmb=0.23
    "Thermal conductance from engine housing to the surrounding air"
  parameter Modelica.Units.SI.Temperature T_Amb=298.15 "Ambient temperature"
  Real nEng
    "Current engine speed"
  Modelica.Units.SI.ThermalConductance CalT_Exh
    "Calculation variable for the temperature of the exhaust gas";
  Modelica.Units.SI.Temperature T_Com
    "Calculated maximum combustion temperature inside the engine"
  Modelica.Units.SI.Temperature T_CylWall "Temperature of cylinder wall";
 /* Modelica.SIunits.Temperature T_LogMeanCool
 "Mean logarithmic coolant temperature" */
  Modelica.Units.SI.Temperature T_Exh "Inlet temperature of exhaust gas"
  Modelica.Units.SI.Temperature T_ExhPowUniOut
    "Outlet temperature of exhaust gas"
  type RotationSpeed=Real(final unit="1/s", min=0);
  Modelica.Units.SI.MassFlowRate m_Exh "Mass flow rate of exhaust gas"
  Modelica.Units.SI.SpecificHeatCapacity meanCpExh
    "Mean specific heat capacity of the exhaust gas"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_amb
    "Heat port to ambient"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor innerWall(
    C=CEngWall,
    der_T(fixed=false, start=0),
    T(start=T_Amb,
      fixed=true)) "Thermal capacity model of the cylinder wall"
  Modelica.Blocks.Sources.RealExpression realExpr1(y=innerWall.T)
  Modelica.Blocks.Sources.RealExpression realExpr2(y=T_CylWall)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor innerThermalCond(G=
        GInnWall/2)
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow actualHeatFlowEngine
    "Heat flow from engine combustion"
  AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.BaseClassComponents.GasolineEngineChp_EngineHousing_CylToInnerWall
    cylToInnerWall(
    GInnWall=GInnWall,
    dInn=dInn,
    lambda=lambda,
    A_WInn=A_WInn,
    z=z) "Thermal model of the cylinder wall"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_coo
    "Heat port to cooling circuit"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor engHeatToCoolant
  AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.BaseClassComponents.GasolineEngineChp_EngineHousing_EngineBlock
    engineBlock(
    CEngBlo=CEngBlo,
    GInnWall=GInnWall,
    GEngBlo=GEngBlo,
    dInn=dInn,
    dOut=dOut,
    lambda=lambda,
    rhoEngWall=rhoEngWall,
    c=c,
    A_WInn=A_WInn,
    z=z,
    mEngBlo=mEngBlo,
    mEng=mEng,
    mEngWall=mEngWall,
    GEngToAmb=GEngToAmb,
    outerEngineBlock(T(start=T_Amb))) "Thermal model of the engine block"

  Modelica.Blocks.Sources.RealExpression calculatedExhaustTemp(y=T_Exh)
  Modelica.Blocks.Interfaces.RealOutput exhaustGasTemperature
    "Calculated exhaust gas temperature output to the mechanical engine model"

protected
  constant Modelica.Units.SI.Area A_WInn=z*(Modelica.Constants.pi*dCyl*(dCyl/2
       + hStr*(1 + 1/(eps - 1))))
    "Area of heat transporting surface from cylinder wall to outer engine block"
  parameter Modelica.Units.SI.Mass mEngWall=A_WInn*rhoEngWall*dInn
    "Calculated mass of cylinder wall between combustion chamber and cooling circle"
  parameter Modelica.Units.SI.Mass mEngBlo=mEng - mEngWall
    "Calculated mass of the remaining engine body"
  parameter Modelica.Units.SI.Thickness dOut=mEngBlo/A_WInn/rhoEngWall
    "Thickness of outer wall of the remaining engine body"
  parameter Modelica.Units.SI.HeatCapacity CEngWall=dInn*A_WInn*rhoEngWall*c
    "Heat capacity of cylinder wall between combustion chamber and cooling circle"
  parameter Modelica.Units.SI.HeatCapacity CEngBlo=dOut*A_WInn*rhoEngWall*c
    "Heat capacity of the remaining engine body"
  parameter Modelica.Units.SI.ThermalConductance GInnWall=lambda*A_WInn/dInn
    "Thermal conductance of the inner engine wall"
  parameter Modelica.Units.SI.ThermalConductance GEngBlo=lambda*A_WInn/dOut
    "Thermal conductance of the remaining engine body"

equation

 /* if EngOp and m_Exh>0.001 then
  T_CylWall=0.5*(T_Com+T_Amb)*CalTCyl;
  else
  T_CylWall=T_Amb;
  end if;*/
  CalT_Exh = meanCpExh*m_Exh;

  if noEvent(nEng*60<800) then
  T_CylWall=innerWall.T;
  T_Exh=innerWall.T;
  else
  T_CylWall=T_Amb+0.2929*(T_Com-T_Amb);
  T_Exh=T_ExhPowUniOut + abs((cylToInnerWall.maximumEngineHeat.y-actualHeatFlowEngine.Q_flow)/CalT_Exh);
  end if;

 // T_CylWall=T_Amb+0.2929*(T_Com-T_Amb);
  // T_CylWall=(T_Com-T_Amb)/Modelica.Math.log(T_Com/T_Amb);

 /* if abs(QuoT_SupRet-1)>0.0001 then
  T_LogMeanCool=(T_CoolSup-T_CoolRet)/Modelica.Math.log(QuoT_SupRet);
  else
  T_LogMeanCool=T_CoolRet;
  end if; */

  connect(actualHeatFlowEngine.port,innerWall. port)
  connect(engineBlock.port_a, innerWall.port)
  connect(cylToInnerWall.y, actualHeatFlowEngine.Q_flow)
  connect(cylToInnerWall.T, realExpr2.y)
  connect(realExpr1.y, cylToInnerWall.T1)
  connect(engineBlock.port_a1, port_amb)
  connect(innerThermalCond.port_a, innerWall.port)
  connect(port_coo, engHeatToCoolant.port_b)
  connect(innerThermalCond.port_b, engHeatToCoolant.port_a)
  connect(calculatedExhaustTemp.y, exhaustGasTemperature)
end GasolineEngineChp_EngineHousing;


Thermal conductance of the inner engine wall.

within AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.BaseClassComponents;
model GasolineEngineChp_EngineHousing_CylToInnerWall

  parameter Modelica.Units.SI.ThermalConductance GInnWall=lambda*A_WInn/dInn
    "Thermal conductance of the inner engine wall"
  parameter Modelica.Units.SI.Thickness dInn=0.005
    "Typical value for the thickness of the cylinder wall (between combustion chamber and cooling circle)"
  parameter Modelica.Units.SI.ThermalConductivity lambda=44.5
    "Thermal conductivity of the engine block material"
  parameter Modelica.Units.SI.Area A_WInn
    "Area of heat transporting surface from cylinder wall to outer engine block"
  parameter Real z=4

  Modelica.Blocks.Interfaces.RealOutput y
  Modelica.Blocks.Interfaces.RealInput T(unit="K")
  Modelica.Blocks.Interfaces.RealInput T1(unit="K")
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature meanTempCylWall
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor
    innerThermalConductor1(G=GInnWall/2)
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heatFlowEngine
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature tempInnerWall
  Modelica.Blocks.Nonlinear.VariableLimiter heatLimit(strict=true)
  Modelica.Blocks.Sources.RealExpression maximumEngineHeat
  Modelica.Blocks.Sources.Constant const(k=0)

equation
  connect(heatFlowEngine.Q_flow,heatLimit. u)
  connect(innerThermalConductor1.port_b,heatFlowEngine. port_a)
  connect(heatFlowEngine.port_b, tempInnerWall.port)
  connect(T, meanTempCylWall.T)
  connect(heatLimit.y, y)
  connect(meanTempCylWall.port, innerThermalConductor1.port_a)
  connect(tempInnerWall.T, T1)
  connect(maximumEngineHeat.y, heatLimit.limit1)
  connect(const.y, heatLimit.limit2)
end GasolineEngineChp_EngineHousing_CylToInnerWall;


Heat capacity of the remaining engine body.

within AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.BaseClassComponents;
model GasolineEngineChp_EngineHousing_EngineBlock

  parameter Modelica.Units.SI.HeatCapacity CEngBlo=dOut*A_WInn*rhoEngWall*c
    "Heat capacity of the remaining engine body"
  parameter Modelica.Units.SI.ThermalConductance GEngToAmb=0.23
    "Thermal conductance from the engine block to the ambient"
  parameter Modelica.Units.SI.ThermalConductance GInnWall=lambda*A_WInn/dInn
    "Thermal conductance of the inner engine wall"
  parameter Modelica.Units.SI.ThermalConductance GEngBlo=lambda*A_WInn/dOut
    "Thermal conductance of the outer engine wall"
  parameter Modelica.Units.SI.Temperature T_Amb=298.15 "Ambient temperature"
  parameter Modelica.Units.SI.Thickness dInn=0.005
    "Typical value for the thickness of the cylinder wall (between combustion chamber and cooling circle)"
  parameter Modelica.Units.SI.Thickness dOut=mEngBlo/A_WInn/rhoEngWall
    "Thickness of outer wall of the remaining engine body"
  parameter Modelica.Units.SI.ThermalConductivity lambda=44.5
    "Thermal conductivity of the engine block material"
  parameter Modelica.Units.SI.Density rhoEngWall=72000
    "Density of the the engine block material"
  parameter Modelica.Units.SI.SpecificHeatCapacity c=535
    "Specific heat capacity of the cylinder wall material"
  parameter Modelica.Units.SI.Area A_WInn
    "Area of heat transporting surface from cylinder wall to outer engine block"
  parameter Real z
  parameter Modelica.Units.SI.Mass mEngBlo=mEng - mEngWall
  parameter Modelica.Units.SI.Mass mEng
  parameter Modelica.Units.SI.Mass mEngWall=A_WInn*rhoEngWall*dInn
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a
    "Heat port to engine block"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a1
    "Heat port to ambient"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor innerThermalCond2(G=
        GInnWall/2)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor outerThermalCond(
      G=GEngBlo/2)
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor outerEngineBlock(
    der_T(fixed=false, start=0),
    C=CEngBlo,
    T(start=T_Amb,
      fixed=true)) "Thermal capacity of the engine block"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor outerThermalCond2(
     G=GEngBlo/2)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor toAmbient(G=GEngToAmb)

equation
  connect(outerThermalCond.port_b,outerEngineBlock. port)
  connect(outerThermalCond.port_a, innerThermalCond2.port_b)
  connect(outerEngineBlock.port,outerThermalCond2. port_a)
  connect(port_a, innerThermalCond2.port_a)
  connect(port_a1, toAmbient.port_a)
  connect(outerThermalCond2.port_b, toAmbient.port_b)
end GasolineEngineChp_EngineHousing_EngineBlock;


within AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses.BaseClassComponents;
model GasolineEngineChp_EngineModel
  "Internal combustion engine model for CHP-applications."
  import AixLib;

  replaceable package Medium1 =
      DataBase.CHP.ModularCHPEngineMedia.NaturalGasMixture_TypeAachen
                                                                constrainedby DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa
    "Fuel medium model used in the CHP plant"
  replaceable package Medium2 =
      AixLib.DataBase.CHP.ModularCHPEngineMedia.EngineCombustionAir
                                                            constrainedby DataBase.CHP.ModularCHPEngineMedia.EngineCombustionAir
    "Air medium model used in the CHP plant"
  replaceable package Medium3 =
      DataBase.CHP.ModularCHPEngineMedia.CHPFlueGasLambdaOnePlus constrainedby DataBase.CHP.ModularCHPEngineMedia.CHPCombustionMixtureGasNasa
    "Exhaust gas medium model used in the CHP plant"
  parameter
    AixLib.DataBase.CHP.ModularCHPEngineData.CHPEngDataBaseRecord
    CHPEngData=DataBase.CHP.ModularCHPEngineData.CHP_SenerTecDachsG5_5()
    "Needed engine data for calculations"
  constant Modelica.Units.SI.Volume VCyl=CHPEngData.VEng/CHPEngData.z
    "Cylinder displacement";
  type RotationSpeed=Real(final unit="1/s", min=0);
  constant RotationSpeed nEngNominal = 25.583 "Nominal engine speed at operating point";
  constant Modelica.Units.SI.Power P_mecNominal=CHPEngData.P_mecNominal
    "Mecanical power output at nominal operating point";
  parameter Modelica.Units.SI.Temperature T_Amb=298.15
    "Ambient temperature (matches to fuel and combustion air temperature)";
  type GasConstant=Real(final unit="J/(mol.K)");
  constant GasConstant R = 8.31446 "Gasconstant for calculation purposes";
  constant Real QuoDCyl = CHPEngData.QuoDCyl;
  constant Boolean FuelType = Medium1.isGas "True = Gasoline fuel, False = Liquid fuel";
  constant Modelica.Units.SI.MassFlowRate m_MaxExh=CHPEngData.P_FueNominal/H_U*
      (1 + Lambda*L_St)
    "Maximal exhaust gas flow based on the fuel and combustion properties";
  constant Modelica.Units.SI.Mass m_FueEngRot=CHPEngData.P_FueNominal*60/(H_U*
      CHPEngData.nEngMax*CHPEngData.i)
    "Injected fuel mass per engine rotation(presumed as constant)";
  constant Modelica.Units.SI.Pressure p_Amb=101325 "Ambient pressure";
  constant Modelica.Units.SI.Pressure p_mi=p_mfNominal + p_meNominal
    "Constant indicated mean effective cylinder pressure";
  constant Modelica.Units.SI.Pressure p_meNominal=CHPEngData.p_meNominal
    "Nominal mean effective cylinder pressure";
  constant Modelica.Units.SI.Pressure ref_p_mfNominal=CHPEngData.ref_p_mfNominal
    "Friction mean pressure of reference engine for calculation(dCyl=91mm & nEng=3000rpm & TEng=90°C)";
  constant Modelica.Units.SI.Pressure p_mfNominal=ref_p_mfNominal*QuoDCyl^(-0.3)
    "Nominal friction mean pressure";
  constant Modelica.Units.SI.Temperature T_ExhOut=CHPEngData.T_ExhPowUniOut
    "Assumed exhaust gas outlet temperature of the CHP unit for heat calculations";
  constant Modelica.Units.SI.SpecificEnergy H_U=Medium1.H_U
    "Specific calorific value of the fuel";
  constant Real Lambda=CHPEngData.Lambda "Combustion air ratio";
  constant Real L_St = Medium1.L_st "Stoichiometric air consumption per mass fuel";
  constant Real l_Min = L_St*MM_Fuel/MM_Air "Minimum molar air consumption per mole fuel";
  constant Modelica.Units.SI.MolarMass MM_Fuel=Medium1.MM
    "Molar mass of the fuel";
  constant Modelica.Units.SI.MolarMass MM_Air=Medium2.MM
    "Molar mass of the combustion air";
  constant Modelica.Units.SI.MolarMass MM_ComExh[:]=Medium3.data[:].MM
    "Molar masses of the combustion products: N2, O2, H2O, CO2";
  constant Real expFacCpComExh[:] = {0.11, 0.15, 0.20, 0.30} "Exponential factor for calculating the specific heat capacity of N2, O2, H2O, CO2";
  constant Modelica.Units.SI.SpecificHeatCapacity cpRefComExh[:]={1000,900,1750,
      840}
    "Specific heat capacities of the combustion products at reference state at 0°C";
  constant Modelica.Units.SI.Temperature RefT_Com=1473.15
    "Reference combustion temperature for calculation purposes";

  // Exhaust composition for gasoline fuels

  constant Real n_N2Exh = if FuelType then Medium1.moleFractions_Gas[1] + Lambda*l_Min*Medium2.moleFractions_Air[1]
  else Lambda*l_Min*Medium2.moleFractions_Air[1] "Exhaust: Number of molecules Nitrogen per mole of fuel";
  constant Real n_O2Exh = (Lambda-1)*l_Min*Medium2.moleFractions_Air[2] "Exhaust: Number of molecules Oxygen per mole of fuel";
  constant Real n_H2OExh = if FuelType then 0.5*sum(Medium1.moleFractions_Gas[i]*Medium1.Fuel.nue_H[i] for i in 1:size(Medium1.Fuel.nue_H, 1))
  else 0.5*(Medium1.Fuel.Xi_liq[2]*Medium1.MM/Medium1.Fuel.MMi_liq[2]) "Exhaust: Number of molecules H20 per mole of fuel";
  constant Real n_CO2Exh = if FuelType then sum(Medium1.moleFractions_Gas[i]*Medium1.Fuel.nue_C[i] for i in 1:size(Medium1.Fuel.nue_C, 1))
  else Medium1.Fuel.Xi_liq[1]*Medium1.MM/Medium1.Fuel.MMi_liq[1] "Exhaust: Number of molecules CO2 per mole of fuel";
  constant Real n_ComExh[:] = {n_N2Exh, n_O2Exh, n_H2OExh, n_CO2Exh};
  constant Real n_Exh = sum(n_ComExh[j] for j in 1:size(n_ComExh, 1)) "Number of exhaust gas molecules per mole of fuel";
  constant Modelica.Units.SI.MolarMass MM_Exh=sum(n_ComExh[i]*MM_ComExh[i] for
      i in 1:size(n_ComExh, 1))/sum(n_ComExh[i] for i in 1:size(n_ComExh, 1))
    "Molar mass of the exhaust gas";
  constant Modelica.Units.SI.MassFraction X_N2Exh=MM_ComExh[1]*n_ComExh[1]/(
      MM_Exh*n_Exh) "Mass fraction of N2 in the exhaust gas";
  constant Modelica.Units.SI.MassFraction X_O2Exh=MM_ComExh[2]*n_ComExh[2]/(
      MM_Exh*n_Exh) "Mass fraction of O2 in the exhaust gas";
  constant Modelica.Units.SI.MassFraction X_H2OExh=MM_ComExh[3]*n_ComExh[3]/(
      MM_Exh*n_Exh) "Mass fraction of H2O in the exhaust gas";
  constant Modelica.Units.SI.MassFraction X_CO2Exh=MM_ComExh[4]*n_ComExh[4]/(
      MM_Exh*n_Exh) "Mass fraction of CO2 in the exhaust gas";
  constant Modelica.Units.SI.MassFraction Xi_Exh[size(n_ComExh, 1)]={X_N2Exh,
      X_O2Exh,X_H2OExh,X_CO2Exh};

  Boolean SwitchOnOff=true
     "Operation switch of the CHP unit (true=On, false=Off)"
  RotationSpeed nEng(min=0) "Current engine speed";
  Modelica.Units.SI.MassFlowRate m_flow_Exh "Mass flow rate of exhaust gas";
  Modelica.Units.SI.MassFlowRate m_flow_CO2Exh
    "Mass flow rate of CO2 in the exhaust gas";
  Modelica.Units.SI.MassFlowRate m_flow_Fue(min=0) "Mass flow rate of fuel";
  Modelica.Units.SI.MassFlowRate m_flow_Air(min=0)
    "Mass flow rate of combustion air";
  Modelica.Units.SI.SpecificHeatCapacity meanCpComExh[size(n_ComExh, 1)]
    "Calculated specific heat capacities of the exhaust gas components for the calculated combustion temperature";
  Modelica.Units.SI.SpecificHeatCapacity meanCpExh
    "Calculated specific heat capacity of the exhaust gas for the calculated combustion temperature";
  Modelica.Units.SI.SpecificEnergy h_Exh=1000*(-286 + 1.011*T_ExhCHPOut - 27.29
      *Lambda + 0.000136*T_ExhCHPOut^2 - 0.0255*T_ExhCHPOut*Lambda + 6.425*
      Lambda^2) "Specific enthalpy of the exhaust gas";
  Modelica.Units.SI.Power P_eff "Effective(mechanical) engine power";
  Modelica.Units.SI.Power P_Fue(min=0) = m_flow_Fue*H_U
    "Fuel expenses at operating point";
  Modelica.Units.SI.Power H_Exh "Enthalpy stream of the exhaust gas";
  Modelica.Units.SI.Power CalQ_therm "Calculated heat from engine combustion";
  Modelica.Units.SI.Power Q_therm(min=0) "Total heat from engine combustion";
  Modelica.Units.SI.Torque Mmot "Calculated engine torque";
  Modelica.Units.SI.Temperature T_logEngCool=356.15
    "Logarithmic mean temperature of coolant inside the engine"
  Modelica.Units.SI.Temperature T_Com(start=T_Amb)
    "Temperature of the combustion gases";
  Modelica.Units.SI.Temperature T_ExhCHPOut=383.15
    "Exhaust gas outlet temperature of CHP unit"
  Real modFac=1 "Modulation factor for energy outuput control of the Chp unit"

  // Dynamic engine friction calculation model for the mechanical power and heat output of the combustion engine

  Real A0 = 1.0895-1.079*10^(-2)*(T_logEngCool-273.15)+5.525*10^(-5)*(T_logEngCool-273.15)^2;
  Real A1 = 4.68*10^(-4)-5.904*10^(-6)*(T_logEngCool-273.15)+1.88*10^(-8)*(T_logEngCool-273.15)^2;
  Real A2 = -4.35*10^(-8)+1.12*10^(-9)*(T_logEngCool-273.15)-4.79*10^(-12)*(T_logEngCool-273.15)^2;
  Real B0 = -2.625*10^(-3)+3.75*10^(-7)*(nEng*60)+1.75*10^(-5)*(T_logEngCool-273.15)+2.5*10^(-9)*(T_logEngCool-273.15)*(nEng*60);
  Real B1 = 8.95*10^(-3)+1.5*10^(-7)*(nEng*60)+7*10^(-6)*(T_logEngCool-273.15)-10^(-9)*(T_logEngCool-273.15)*(nEng*60);
  Modelica.Units.SI.Pressure p_mf=p_mfNominal*((A0 + A1*(nEng*60) + A2*(nEng*60)
      ^2) + (B0 + B1*(p_meNominal/100000)))
    "Current friction mean pressure at operating point";
  Modelica.Units.SI.Pressure p_me=(modFac*p_mi) - p_mf
    "Current mean effective pressure at operating point";
  Real etaMec = p_me/p_mi "Current percentage of usable mechanical power compared to inner cylinder power from combustion";

  Modelica.Fluid.Interfaces.FluidPort_b port_exh(redeclare package Medium =
        Medium3)
  Modelica.Fluid.Sources.MassFlowSource_T exhaustFlow(
    use_m_flow_in=true,
    use_T_in=true,
    redeclare package Medium = Medium3,
    X=Xi_Exh,
    use_X_in=false,
    nPorts=1) "Flow source of the exhaust gas from the engine combustion"
  Modelica.Blocks.Sources.RealExpression massFlowExhaust(y=m_flow_Exh)
  Modelica.Blocks.Sources.RealExpression effectiveMechanicalTorque(y=Mmot)
  Modelica.Mechanics.Rotational.Interfaces.Flange_a flange_a
    "Mechanical port of the engines output drive"
  Modelica.Mechanics.Rotational.Sources.Torque engineTorque
    "Calculated engine torque"
  Modelica.Mechanics.Rotational.Components.Inertia inertia(J=0.5*CHPEngData.z/4)
    "Inertia model of the engine"

  Modelica.Blocks.Interfaces.RealInput exhaustGasTemperature
    "Exhaust gas temperature calculated in the thermal engine model"
  AixLib.Controls.Interfaces.CHPControlBus cHPEngineBus
    "Signal bus of the mechanical combustion engine model"
  Modelica.Blocks.Sources.RealExpression engineSpeed(y=nEng)
  Modelica.Blocks.Sources.RealExpression fuelPower(y=P_Fue)
  Modelica.Blocks.Sources.RealExpression thermalPower(y=Q_therm)
  Modelica.Blocks.Sources.RealExpression outputTorque(y=Mmot)
  Modelica.Blocks.Sources.RealExpression airFlow(y=m_flow_Fue)
  Modelica.Blocks.Sources.RealExpression carbondioxideFlow(y=m_flow_CO2Exh)
  Modelica.Blocks.Sources.RealExpression SpecificHeatCapExhGas(y=meanCpExh)
  Modelica.Blocks.Sources.RealExpression fuelFlow(y=m_flow_Air)
equation

for i in 1:size(n_ComExh, 1) loop
  meanCpComExh[i] = cpRefComExh[i]/(expFacCpComExh[i] + 1)/(T_Com/273.15 - 1)*(-1 + (T_Com/273.15)^(expFacCpComExh[i] + 1));
  end for;
  meanCpExh = sum(meanCpComExh[i]*Xi_Exh[i] for i in 1:size(n_ComExh, 1));
  m_flow_Fue = modFac*m_FueEngRot*nEng*CHPEngData.i/60;
  m_flow_Air = m_flow_Fue*Lambda*L_St;
 // m_Exh = m_Fue + m_Air;
  m_flow_CO2Exh = m_flow_Fue*(1 + Lambda*L_St)*X_CO2Exh;
  H_Exh =h_Exh*m_flow_Fue*(1 + Lambda*L_St);
  if inertia.w>=80 and SwitchOnOff then
  Mmot = CHPEngData.i*p_me*CHPEngData.VEng/(2*Modelica.Constants.pi);
  nEng = inertia.w/(2*Modelica.Constants.pi);
    m_flow_Exh = m_flow_Fue + m_flow_Air;
  elseif inertia.w>=80 and not
                              (SwitchOnOff) then
  Mmot = -CHPEngData.i*p_mf*CHPEngData.VEng/(2*Modelica.Constants.pi);
  nEng = inertia.w/(2*Modelica.Constants.pi);
    m_flow_Exh = m_flow_Fue + m_flow_Air + 0.0001;
  elseif inertia.w<80 and noEvent(inertia.w>0.1) then
  Mmot = -CHPEngData.i*p_mf*CHPEngData.VEng/(2*Modelica.Constants.pi);
  nEng = inertia.w/(2*Modelica.Constants.pi);
    m_flow_Exh = m_flow_Fue + m_flow_Air + 0.0001;
  else
  Mmot = 0;
  nEng = 0;
    m_flow_Exh = 0.001;
  end if;
  CalQ_therm = P_Fue - P_eff - H_Exh;
  Q_therm = if (nEng>1) and (CalQ_therm>=10) then CalQ_therm else 0;
  T_Com = (H_U-(60*p_me*CHPEngData.VEng)/m_FueEngRot)/((1 + Lambda*L_St)*meanCpExh) + T_Amb;
  P_eff = CHPEngData.i*nEng*p_me*CHPEngData.VEng;

 /* if m_Fue>0 then
  T_Com = (P_Fue - P_eff)/(m_Fue*(1 + Lambda*L_St)*meanCpExh) + T_Amb;
  else
  T_Com = T_Amb;
  end if;  */

  connect(exhaustFlow.m_flow_in, massFlowExhaust.y)
  connect(exhaustFlow.ports[1], port_exh)
  connect(inertia.flange_b, flange_a)
  connect(inertia.flange_a, engineTorque.flange)
  connect(exhaustFlow.T_in, exhaustGasTemperature)
  connect(engineTorque.tau, effectiveMechanicalTorque.y)
  connect(engineSpeed.y, cHPEngineBus.meaRotEng)
  connect(fuelPower.y, cHPEngineBus.meaFuePowEng)
  connect(thermalPower.y, cHPEngineBus.meaThePowEng)
  connect(SpecificHeatCapExhGas.y, cHPEngineBus.calMeaCpExh)
  connect(carbondioxideFlow.y, cHPEngineBus.meaMasFloCO2Eng)
  connect(airFlow.y, cHPEngineBus.meaMasFloAirEng)
  connect(outputTorque.y, cHPEngineBus.meaTorEng)
  connect(fuelFlow.y, cHPEngineBus.meaMasFloFueEng)
end GasolineEngineChp_EngineModel;


within AixLib.Fluid.BoilerCHP.ModularCHP.BaseClasses;
package BaseClassComponents "Package with base classe components for AixLib.Fluid.BoilerCHP.ModularCHP"
  extends Modelica.Icons.BasesPackage
end BaseClassComponents;


Chiller with prescribed evaporator leaving temperature and performance curve adjusted based on Carnot efficiency. This is a model of a chiller whose coefficient of performance COP changes
with temperatures in the same way as the Carnot efficiency changes.
The control input is the setpoint of the evaporator leaving temperature, which
is met exactly at steady state if the chiller has sufficient capacity.

within AixLib.Fluid.Chillers;
model Carnot_TEva
  "Chiller with prescribed evaporator leaving temperature and performance curve adjusted based on Carnot efficiency"
 extends AixLib.Fluid.Chillers.BaseClasses.PartialCarnot_T(
   final COP_is_for_cooling = true,
   final QCon_flow_nominal = -QEva_flow_nominal*(1 + COP_nominal)/COP_nominal,
   PEle(y=-QEva_flow/COP),
   redeclare HeatExchangers.HeaterCooler_u con(
    final from_dp=from_dp1,
    final dp_nominal=dp1_nominal,
    final linearizeFlowResistance=linearizeFlowResistance1,
    final deltaM=deltaM1,
    final tau=tau1,
    final T_start=T1_start,
    final energyDynamics=energyDynamics,
    final homotopyInitialization=homotopyInitialization,
    final Q_flow_nominal=QCon_flow_nominal),
   redeclare HeatExchangers.SensibleCooler_T eva(
    final from_dp=from_dp2,
    final dp_nominal=dp2_nominal,
    final linearizeFlowResistance=linearizeFlowResistance2,
    final deltaM=deltaM2,
    final QMin_flow=QEva_flow_min,
    final tau=tau2,
    final T_start=T2_start,
    final energyDynamics=energyDynamics,
    final homotopyInitialization=homotopyInitialization));

  parameter Modelica.Units.SI.HeatFlowRate QEva_flow_min(max=0) = -Modelica.Constants.inf
    "Maximum heat flow rate for cooling (negative)";

  Modelica.Blocks.Interfaces.RealInput TSet(unit="K")
    "Evaporator leaving water temperature"

protected
  Modelica.Blocks.Math.Gain yCon(final k=1/QCon_flow_nominal)
    "Normalized condenser heat flow rate"
  Modelica.Blocks.Math.Add QCon_flow_internal(final k1=-1)
    "Heat added to condenser"
initial equation
  assert(QEva_flow_nominal < 0, "Parameter QEva_flow_nominal must be negative.");

equation
  connect(TSet, eva.TSet)
  connect(eva.Q_flow, QEva_flow)
  connect(QCon_flow_internal.y, yCon.u)
  connect(yCon.y, con.u)
  connect(QCon_flow_internal.y, QCon_flow)
  connect(QCon_flow_internal.u1, eva.Q_flow)
  connect(QCon_flow_internal.u2, PEle.y)
end Carnot_TEva;


Chiller with performance curve adjusted based on Carnot efficiency. This is a model of a chiller whose coefficient of performance COP changes
with temperatures in the same way as the Carnot efficiency changes.
The input signal <i>y</i> is the control signal for the compressor.

within AixLib.Fluid.Chillers;
model Carnot_y
  "Chiller with performance curve adjusted based on Carnot efficiency"
  extends AixLib.Fluid.Chillers.BaseClasses.PartialCarnot_y(
    final COP_is_for_cooling = true);
end Carnot_y;


Package with chiller models

within AixLib.Fluid;
package Chillers "Package with chiller models"
  extends Modelica.Icons.VariantsPackage;
end Chillers;


= true, use homotopy method

within AixLib.Fluid.Chillers.BaseClasses;
partial model Carnot
  extends AixLib.Fluid.Interfaces.PartialFourPortInterface(
    m1_flow_nominal = QCon_flow_nominal/cp1_default/dTCon_nominal,
    m2_flow_nominal = QEva_flow_nominal/cp2_default/dTEva_nominal);

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

  parameter Modelica.Units.SI.HeatFlowRate QEva_flow_nominal(max=0)
    "Nominal cooling heat flow rate (QEva_flow_nominal < 0)"
  parameter Modelica.Units.SI.HeatFlowRate QCon_flow_nominal(min=0)
    "Nominal heating flow rate"

  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal(final max=0)
     = -10 "Temperature difference evaporator outlet-inlet"
  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal(final min=0)
     = 10 "Temperature difference condenser outlet-inlet"

  // Efficiency
  parameter Boolean use_eta_Carnot_nominal = true
    "Set to true to use Carnot effectiveness etaCarnot_nominal rather than COP_nominal"
  parameter Real etaCarnot_nominal(unit="1") = 0.3
    "Carnot effectiveness (=COP/COP_Carnot) used during simulation if use_eta_Carnot_nominal = true"

  parameter Real COP_nominal(unit="1") = etaCarnot_nominal*TUseAct_nominal/
    (TCon_nominal+TAppCon_nominal - (TEva_nominal-TAppEva_nominal))
    "Coefficient of performance at TEva_nominal and TCon_nominal, used during simulation if use_eta_Carnot_nominal = false"

  parameter Modelica.Units.SI.Temperature TCon_nominal=303.15
    "Condenser temperature used to compute COP_nominal if use_eta_Carnot_nominal=false"
  parameter Modelica.Units.SI.Temperature TEva_nominal=278.15
    "Evaporator temperature used to compute COP_nominal if use_eta_Carnot_nominal=false"

  parameter Real a[:] = {1}
    "Coefficients for efficiency curve (need p(a=a, yPL=1)=1)"

  parameter Modelica.Units.SI.Pressure dp1_nominal(displayUnit="Pa")
    "Pressure difference over condenser"
  parameter Modelica.Units.SI.Pressure dp2_nominal(displayUnit="Pa")
    "Pressure difference over evaporator"

  parameter Modelica.Units.SI.TemperatureDifference TAppCon_nominal(min=0) =
    if cp1_default < 1500 then 5 else 2
    "Temperature difference between refrigerant and working fluid outlet in condenser"

  parameter Modelica.Units.SI.TemperatureDifference TAppEva_nominal(min=0) =
    if cp2_default < 1500 then 5 else 2
    "Temperature difference between refrigerant and working fluid outlet in evaporator"

  parameter Boolean from_dp1=false
    "= true, use m_flow = f(dp) else dp = f(m_flow)"
  parameter Boolean from_dp2=false
    "= true, use m_flow = f(dp) else dp = f(m_flow)"

  parameter Boolean linearizeFlowResistance1=false
    "= true, use linear relation between m_flow and dp for any flow rate"
  parameter Boolean linearizeFlowResistance2=false
    "= true, use linear relation between m_flow and dp for any flow rate"

  parameter Real deltaM1(final unit="1")=0.1
    "Fraction of nominal flow rate where flow transitions to laminar"
  parameter Real deltaM2(final unit="1")=0.1
    "Fraction of nominal flow rate where flow transitions to laminar"

  parameter Modelica.Units.SI.Time tau1=60
    "Time constant at nominal flow rate (used if energyDynamics1 <> Modelica.Fluid.Types.Dynamics.SteadyState)"
  parameter Modelica.Units.SI.Time tau2=60
    "Time constant at nominal flow rate (used if energyDynamics2 <> Modelica.Fluid.Types.Dynamics.SteadyState)"

  parameter Modelica.Units.SI.Temperature T1_start=Medium1.T_default
    "Initial or guess value of set point"
  parameter Modelica.Units.SI.Temperature T2_start=Medium2.T_default
    "Initial or guess value of set point"

  parameter Modelica.Fluid.Types.Dynamics energyDynamics=
    Modelica.Fluid.Types.Dynamics.SteadyState "Type of energy balance: dynamic (3 initialization options) or steady state"

  Modelica.Blocks.Interfaces.RealOutput QCon_flow(
    final quantity="HeatFlowRate",
    final unit="W") "Actual heating heat flow rate added to fluid 1"

  Modelica.Blocks.Interfaces.RealOutput P(
    final quantity="Power",
    final unit="W") "Electric power consumed by compressor"

  Modelica.Blocks.Interfaces.RealOutput QEva_flow(
    final quantity="HeatFlowRate",
    final unit="W") "Actual cooling heat flow rate removed from fluid 2"

  Real yPL(final unit="1", min=0) = if COP_is_for_cooling
     then QEva_flow/QEva_flow_nominal
     else QCon_flow/QCon_flow_nominal "Part load ratio";

  Real etaPL(final unit = "1")=
    if evaluate_etaPL
      then AixLib.Utilities.Math.Functions.polynomial(a=a, x=yPL)
      else 1
    "Efficiency due to part load (etaPL(yPL=1)=1)";

  Real COP(min=0, final unit="1") = etaCarnot_nominal_internal * COPCar * etaPL
    "Coefficient of performance";

  Real COPCar(min=0) = TUseAct/AixLib.Utilities.Math.Functions.smoothMax(
    x1=1,
    x2=TConAct - TEvaAct,
    deltaX=0.25) "Carnot efficiency";

  Modelica.Units.SI.Temperature TConAct(start=TCon_nominal + TAppCon_nominal)
     = Medium1.temperature(staB1) + QCon_flow/QCon_flow_nominal*TAppCon_nominal
    "Condenser temperature used to compute efficiency, taking into account pinch temperature between fluid and refrigerant";

  Modelica.Units.SI.Temperature TEvaAct(start=TEva_nominal - TAppEva_nominal)
     = Medium2.temperature(staB2) - QEva_flow/QEva_flow_nominal*TAppEva_nominal
    "Evaporator temperature used to compute efficiency, taking into account pinch temperature between fluid and refrigerant";

protected
  constant Boolean COP_is_for_cooling
    "Set to true if the specified COP is for cooling";

  parameter Real etaCarnot_nominal_internal(unit="1")=
    if use_eta_Carnot_nominal
      then etaCarnot_nominal
      else COP_nominal/
           (TUseAct_nominal / (TCon_nominal + TAppCon_nominal - (TEva_nominal - TAppEva_nominal)))
    "Carnot effectiveness (=COP/COP_Carnot) used to compute COP";

  // For Carnot_y, computing etaPL = f(yPL) introduces a nonlinear equation.
  // The parameter below avoids this if a = {1}.
  final parameter Boolean evaluate_etaPL=
    not ((size(a, 1) == 1 and abs(a[1] - 1)  < Modelica.Constants.eps))
    "Flag, true if etaPL should be computed as it depends on yPL"

  final parameter Modelica.Units.SI.Temperature TUseAct_nominal=if
      COP_is_for_cooling then TEva_nominal - TAppEva_nominal else TCon_nominal
       + TAppCon_nominal
    "Nominal evaporator temperature for chiller or condenser temperature for heat pump, taking into account pinch temperature between fluid and refrigerant";
  Modelica.Units.SI.Temperature TUseAct=if COP_is_for_cooling then TEvaAct
       else TConAct
    "Temperature of useful heat (evaporator for chiller, condenser for heat pump), taking into account pinch temperature between fluid and refrigerant";

  final parameter Modelica.Units.SI.SpecificHeatCapacity cp1_default=
      Medium1.specificHeatCapacityCp(Medium1.setState_pTX(
      p=Medium1.p_default,
      T=Medium1.T_default,
      X=Medium1.X_default))
    "Specific heat capacity of medium 1 at default medium state";

  final parameter Modelica.Units.SI.SpecificHeatCapacity cp2_default=
      Medium2.specificHeatCapacityCp(Medium2.setState_pTX(
      p=Medium2.p_default,
      T=Medium2.T_default,
      X=Medium2.X_default))
    "Specific heat capacity of medium 2 at default medium state";

  Medium1.ThermodynamicState staA1 = Medium1.setState_phX(
    port_a1.p,
    inStream(port_a1.h_outflow),
    inStream(port_a1.Xi_outflow)) "Medium properties in port_a1";
  Medium1.ThermodynamicState staB1 = Medium1.setState_phX(
    port_b1.p,
    port_b1.h_outflow,
    port_b1.Xi_outflow) "Medium properties in port_b1";
  Medium2.ThermodynamicState staA2 = Medium2.setState_phX(
    port_a2.p,
    inStream(port_a2.h_outflow),
    inStream(port_a2.Xi_outflow)) "Medium properties in port_a2";
  Medium2.ThermodynamicState staB2 = Medium2.setState_phX(
    port_b2.p,
    port_b2.h_outflow,
    port_b2.Xi_outflow) "Medium properties in port_b2";

  replaceable Interfaces.PartialTwoPortInterface con
    constrainedby Interfaces.PartialTwoPortInterface(
      redeclare final package Medium = Medium1,
      final allowFlowReversal=allowFlowReversal1,
      final m_flow_nominal=m1_flow_nominal,
      final m_flow_small=m1_flow_small,
      final show_T=false) "Condenser"

  replaceable Interfaces.PartialTwoPortInterface eva
    constrainedby Interfaces.PartialTwoPortInterface(
      redeclare final package Medium = Medium2,
      final allowFlowReversal=allowFlowReversal2,
      final m_flow_nominal=m2_flow_nominal,
      final m_flow_small=m2_flow_small,
      final show_T=false) "Evaporator"

initial equation
  assert(dTEva_nominal < 0,
    "Parameter dTEva_nominal must be negative.");
  assert(dTCon_nominal > 0,
    "Parameter dTCon_nominal must be positive.");

  assert(abs(AixLib.Utilities.Math.Functions.polynomial(
         a=a, x=1)-1) < 0.01, "Efficiency curve is wrong. Need etaPL(y=1)=1.");
  assert(etaCarnot_nominal_internal < 1,   "Parameters lead to etaCarnot_nominal > 1. Check parameters.");

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

equation
  connect(port_a2, eva.port_a)
  connect(eva.port_b, port_b2)
  connect(port_a1, con.port_a)
  connect(con.port_b, port_b1)
end Carnot;


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


Partial model for chiller with performance curve adjusted based on Carnot efficiency. This is a partial model of a chiller whose coefficient of performance (COP) changes
with temperatures in the same way as the Carnot efficiency changes.
This base class is used for the Carnot chiller and Carnot heat pump
that uses the compressor part load ratio as the control signal.

within AixLib.Fluid.Chillers.BaseClasses;
partial model PartialCarnot_T
  "Partial model for chiller with performance curve adjusted based on Carnot efficiency"
  extends AixLib.Fluid.Chillers.BaseClasses.Carnot;

protected
  Modelica.Blocks.Sources.RealExpression PEle "Electrical power consumption"

equation
  connect(PEle.y, P)
end PartialCarnot_T;


Partial chiller model with performance curve adjusted based on Carnot efficiency. This is a partial model of a chiller whose coefficient of performance (COP) changes
with temperatures in the same way as the Carnot efficiency changes.
This base class is used for the Carnot chiller and Carnot heat pump
that uses the leaving fluid temperature as the control signal.

within AixLib.Fluid.Chillers.BaseClasses;
partial model PartialCarnot_y
  "Partial chiller model with performance curve adjusted based on Carnot efficiency"
  extends Carnot(
    final QCon_flow_nominal= P_nominal - QEva_flow_nominal,
    final QEva_flow_nominal = if COP_is_for_cooling
                              then -P_nominal * COP_nominal
                              else -P_nominal * (COP_nominal-1),
    redeclare HeatExchangers.HeaterCooler_u con(
      final from_dp=from_dp1,
      final dp_nominal=dp1_nominal,
      final linearizeFlowResistance=linearizeFlowResistance1,
      final deltaM=deltaM1,
      final tau=tau1,
      final T_start=T1_start,
      final energyDynamics=energyDynamics,
      final homotopyInitialization=homotopyInitialization,
      final Q_flow_nominal=QCon_flow_nominal),
      redeclare HeatExchangers.HeaterCooler_u eva(
      final from_dp=from_dp2,
      final dp_nominal=dp2_nominal,
      final linearizeFlowResistance=linearizeFlowResistance2,
      final deltaM=deltaM2,
      final tau=tau2,
      final T_start=T2_start,
      final energyDynamics=energyDynamics,
      final homotopyInitialization=homotopyInitialization,
      final Q_flow_nominal=QEva_flow_nominal));

  parameter Modelica.Units.SI.Power P_nominal(min=0)
    "Nominal compressor power (at y=1)"

  Modelica.Blocks.Interfaces.RealInput y(min=0, max=1, unit="1")
    "Part load ratio of compressor"

protected
  Modelica.Units.SI.HeatFlowRate QCon_flow_internal(start=QCon_flow_nominal) =
    P - QEva_flow_internal "Condenser heat input";
  Modelica.Units.SI.HeatFlowRate QEva_flow_internal(start=QEva_flow_nominal) =
    if COP_is_for_cooling then -COP*P else (1 - COP)*P "Evaporator heat input";

  Modelica.Blocks.Sources.RealExpression yEva_flow_in(
    y=QEva_flow_internal/QEva_flow_nominal)
    "Normalized evaporator heat flow rate"
  Modelica.Blocks.Sources.RealExpression yCon_flow_in(
    y=QCon_flow_internal/QCon_flow_nominal)
    "Normalized condenser heat flow rate"

  Modelica.Blocks.Math.Gain PEle(final k=P_nominal)
    "Electrical power consumption"
equation

  connect(PEle.y, P)
  connect(PEle.u, y)
  connect(yEva_flow_in.y, eva.u)
  connect(yCon_flow_in.y, con.u)
  connect(con.Q_flow, QCon_flow)
  connect(eva.Q_flow, QEva_flow)
end PartialCarnot_y;


within AixLib.Fluid.Chillers.Examples;
model Carnot_TEva
  "Test model for chiller based on Carnot efficiency and evaporator outlet temperature control signal"
  extends Modelica.Icons.Example;
 package Medium1 = AixLib.Media.Water "Medium model";
 package Medium2 = AixLib.Media.Water "Medium model";

  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal=-10
    "Temperature difference evaporator outlet-inlet";
  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=10
    "Temperature difference condenser outlet-inlet";
  parameter Real COPc_nominal = 3 "Chiller COP";
  parameter Modelica.Units.SI.HeatFlowRate QEva_flow_nominal=-100E3
    "Evaporator heat flow rate";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal=QEva_flow_nominal/
      dTEva_nominal/4200 "Nominal mass flow rate at chilled water side";

  AixLib.Fluid.Chillers.Carnot_TEva chi(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    dTEva_nominal=dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    m2_flow_nominal=m2_flow_nominal,
    show_T=true,
    QEva_flow_nominal=QEva_flow_nominal,
    allowFlowReversal1=false,
    allowFlowReversal2=false,
    use_eta_Carnot_nominal=true,
    dp1_nominal=6000,
    dp2_nominal=6000) "Chiller model"
  AixLib.Fluid.Sources.MassFlowSource_T sou1(nPorts=1,
    redeclare package Medium = Medium1,
    use_T_in=false,
    use_m_flow_in=true,
    T=298.15)
  AixLib.Fluid.Sources.MassFlowSource_T sou2(nPorts=1,
    redeclare package Medium = Medium2,
    m_flow=m2_flow_nominal,
    use_T_in=false,
    T=295.15)
  AixLib.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium1,
    nPorts=1)
  AixLib.Fluid.Sources.Boundary_pT sin2(nPorts=1,
    redeclare package Medium = Medium2)
  Modelica.Blocks.Sources.Ramp TEvaLvg(
    duration=60,
    startTime=1800,
    offset=273.15 + 6,
    height=10) "Control signal for evaporator leaving temperature"
  Modelica.Blocks.Math.Gain mCon_flow(k=-1/cp1_default/dTEva_nominal)
    "Condenser mass flow rate"
  Modelica.Blocks.Math.Add QCon_flow(k2=-1) "Condenser heat flow rate"

  final parameter Modelica.Units.SI.SpecificHeatCapacity cp1_default=
      Medium1.specificHeatCapacityCp(Medium1.setState_pTX(
      Medium1.p_default,
      Medium1.T_default,
      Medium1.X_default))
    "Specific heat capacity of medium 1 at default medium state";
equation
  connect(sou1.ports[1], chi.port_a1)
  connect(sou2.ports[1], chi.port_a2)
  connect(sin2.ports[1], chi.port_b2)
  connect(TEvaLvg.y, chi.TSet)
  connect(chi.P, QCon_flow.u1)
  connect(chi.QEva_flow, QCon_flow.u2)
  connect(QCon_flow.y, mCon_flow.u)
  connect(mCon_flow.y, sou1.m_flow_in)
  connect(chi.port_b1, sin1.ports[1])
end Carnot_TEva;


within AixLib.Fluid.Chillers.Examples;
model Carnot_y "Test model for chiller based on Carnot_y efficiency"
  extends Modelica.Icons.Example;
 package Medium1 = AixLib.Media.Water "Medium model";
 package Medium2 = AixLib.Media.Water "Medium model";

  parameter Modelica.Units.SI.Power P_nominal=10E3
    "Nominal compressor power (at y=1)";
  parameter Modelica.Units.SI.TemperatureDifference dTEva_nominal=-10
    "Temperature difference evaporator outlet-inlet";
  parameter Modelica.Units.SI.TemperatureDifference dTCon_nominal=10
    "Temperature difference condenser outlet-inlet";
  parameter Real COPc_nominal = 3 "Chiller COP";

  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal=-P_nominal*
      COPc_nominal/dTEva_nominal/4200
    "Nominal mass flow rate at chilled water side";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal=m2_flow_nominal*(
      COPc_nominal + 1)/COPc_nominal
    "Nominal mass flow rate at condenser water wide";

  AixLib.Fluid.Chillers.Carnot_y chi(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    P_nominal=P_nominal,
    dTEva_nominal=dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    use_eta_Carnot_nominal=true,
    dp1_nominal=6000,
    dp2_nominal=6000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    show_T=true,
    T1_start=303.15,
    T2_start=278.15) "Chiller model"
  AixLib.Fluid.Sources.MassFlowSource_T sou1(nPorts=1,
    redeclare package Medium = Medium1,
    use_T_in=true,
    m_flow=m1_flow_nominal,
    T=298.15)
  AixLib.Fluid.Sources.MassFlowSource_T sou2(nPorts=1,
    redeclare package Medium = Medium2,
    use_T_in=true,
    m_flow=m2_flow_nominal,
    T=291.15)
  AixLib.Fluid.Sources.Boundary_pT sin1(
    nPorts=1,
    redeclare package Medium = Medium1)
  AixLib.Fluid.Sources.Boundary_pT sin2(
    nPorts=1,
    redeclare package Medium = Medium2)
  Modelica.Blocks.Sources.Ramp uCom(
    height=-1,
    duration=60,
    offset=1,
    startTime=1800) "Compressor control signal"
  Modelica.Blocks.Sources.Ramp TCon_in(
    height=10,
    duration=60,
    offset=273.15 + 20,
    startTime=60) "Condenser inlet temperature"
  Modelica.Blocks.Sources.Ramp TEva_in(
    height=10,
    duration=60,
    startTime=900,
    offset=273.15 + 15) "Evaporator inlet temperature"
equation
  connect(sou1.ports[1], chi.port_a1)
  connect(sou2.ports[1], chi.port_a2)
  connect(chi.port_b1, sin1.ports[1])
  connect(sin2.ports[1], chi.port_b2)
  connect(TCon_in.y, sou1.T_in)
  connect(TEva_in.y, sou2.T_in)
  connect(uCom.y, chi.y)
end Carnot_y;


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


Reversible chiller using Carnot approach with losses (frost, heat, inertia). Model of a reversible chiller.

within AixLib.Fluid.Chillers.ModularReversible;
model CarnotWithLosses
  "Reversible chiller using Carnot approach with losses (frost, heat, inertia)"
  extends AixLib.Fluid.Chillers.ModularReversible.Modular(
    QHea_flow_nominal=PEle_nominal*refCyc.refCycChiHea.COP_nominal,
    redeclare model RefrigerantCycleChillerHeating =
        AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness
        (
        PEle_nominal=PEle_nominal,
        redeclare
          AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.NoFrosting
          iceFacCal,
        etaCarnot_nominal=etaCarnot_nominal,
        use_constAppTem=true,
        TAppCon_nominal=TAppCon_nominal,
        TAppEva_nominal=TAppEva_nominal),
    redeclare model RefrigerantCycleChillerCooling =
        AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness
        (
        redeclare
          AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.FunctionalIcingFactor
          iceFacCal(redeclare function icingFactor =
              AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.Functions.wetterAfjei1997),
        TAppCon_nominal=TAppCon_nominal,
        TAppEva_nominal=TAppEva_nominal,
        etaCarnot_nominal=etaCarnot_nominal),
    final allowDifferentDeviceIdentifiers=false,
    redeclare model RefrigerantCycleInertia =
        AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.VariableOrder
        (
        final refIneFreConst=1/refIneTimCon,
        final nthOrd=1,
        initType=Modelica.Blocks.Types.Init.InitialOutput));

  parameter Real etaCarnot_nominal=0.3 "Constant Carnot effectiveness";
  parameter Modelica.Units.SI.TemperatureDifference TAppCon_nominal=if
      cpCon < 1500 then 5 else 2
    "Temperature difference between refrigerant and working fluid outlet in condenser"
  parameter Modelica.Units.SI.TemperatureDifference TAppEva_nominal=if
      cpEva < 1500 then 5 else 2
    "Temperature difference between refrigerant and working fluid outlet in evaporator"
  parameter Modelica.Units.SI.Time refIneTimCon = 300
    "Refrigerant cycle inertia time constant for first order delay"
  parameter Integer nthOrd=1 "Order of refrigerant cycle interia"
end CarnotWithLosses;


Large scale water to water chiller

within AixLib.Fluid.Chillers.ModularReversible;
model LargeScaleWaterToWater "Large scale water to water chiller"
  extends Modular(
    dpEva_nominal=datTab.dpEva_nominal*scaFac^2,
    dpCon_nominal=datTab.dpCon_nominal*scaFac^2,
    final dTEva_nominal=-QCoo_flow_nominal/cpEva/mEva_flow_nominal,
    final dTCon_nominal=(PEle_nominal - QCoo_flow_nominal)/cpCon/mCon_flow_nominal,
    redeclare replaceable package MediumCon = AixLib.Media.Water,
    redeclare replaceable package MediumEva = AixLib.Media.Water,
    final GEvaIns=0,
    final GEvaOut=0,
    final CEva=0,
    final use_evaCap=false,
    final GConIns=0,
    final GConOut=0,
    final CCon=0,
    final TConHea_nominal=0,
    final TEvaHea_nominal=0,
    final use_conCap=false,
        redeclare replaceable
    AixLib.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Wuellhorst2021 safCtrPar
      constrainedby
      AixLib.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Generic(
      final tabUppHea=datTab.tabLowBou,
      final tabLowCoo=datTab.tabLowBou,
      final use_TEvaOutCoo=datTab.use_TEvaOutForOpeEnv,
      final use_TConOutCoo=datTab.use_TConOutForOpeEnv),
    redeclare model RefrigerantCycleInertia =
        AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.NoInertia,
    redeclare model RefrigerantCycleChillerHeating =
        AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.NoHeating,
    redeclare model RefrigerantCycleChillerCooling =
        AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.TableData2D (
        redeclare
          AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.NoFrosting
          iceFacCal, datTab=datTab),
    final use_rev=false,
    final QHea_flow_nominal=0,
    final mCon_flow_nominal=autCalMasCon_flow,
    final mEva_flow_nominal=autCalMasEva_flow,
    final tauCon=autCalVCon*rhoCon/autCalMasCon_flow,
    final tauEva=autCalVEva*rhoEva/autCalMasEva_flow);
  final parameter Real scaFac=refCyc.refCycChiCoo.scaFac "Scaling factor of chiller";

  extends AixLib.Fluid.HeatPumps.ModularReversible.BaseClasses.LargeScaleWaterToWaterDeclarations(
    final autCalMasCon_flow=max(5E-5*abs(QCoo_flow_nominal) + 0.3161, autCalMMin_flow),
    final autCalMasEva_flow=max(5E-5*abs(QCoo_flow_nominal) - 0.5662, autCalMMin_flow),
    final autCalVCon=max(2E-7*abs(QCoo_flow_nominal) - 84E-4, autCalVMin),
    final autCalVEva=max(1E-7*abs(QCoo_flow_nominal) - 66E-4, autCalVMin));
  replaceable parameter
    AixLib.Fluid.Chillers.ModularReversible.Data.TableData2D.Generic
    datTab constrainedby Data.TableData2D.Generic "Data Table of Chiller"
end LargeScaleWaterToWater;


Grey-box model for reversible and non-reversible chillers. Model of a reversible, modular chiller.
  This models allows combining any of the available modules
  for refrigerant heating or cooling cycles, inertias,
  heat losses, and safety controls.
  All features are optional.

within AixLib.Fluid.Chillers.ModularReversible;
model Modular
  "Grey-box model for reversible and non-reversible chillers"
  extends
    AixLib.Fluid.HeatPumps.ModularReversible.BaseClasses.PartialReversibleRefrigerantMachine(
    final use_COP=use_rev,
    final use_EER=true,
    con(preDro(m_flow(nominal=-QCoo_flow_nominal/1000/10))),
    eva(preDro(m_flow(nominal=-QCoo_flow_nominal/1000/10))),
    safCtr(redeclare
        AixLib.Fluid.Chillers.ModularReversible.Controls.Safety.OperationalEnvelope
        opeEnv),
    final PEle_nominal=refCyc.refCycChiCoo.PEle_nominal,
    mEva_flow_nominal=-QCoo_flow_nominal/(dTEva_nominal*cpEva),
    mCon_flow_nominal=(PEle_nominal - QCoo_flow_nominal)/(dTCon_nominal*cpCon),
    use_rev=false,
    redeclare final AixLib.Fluid.Chillers.ModularReversible.BaseClasses.RefrigerantCycle refCyc(
      redeclare model RefrigerantCycleChillerCooling = RefrigerantCycleChillerCooling,
      redeclare model RefrigerantCycleChillerHeating = RefrigerantCycleChillerHeating,
      final allowDifferentDeviceIdentifiers=allowDifferentDeviceIdentifiers));
  parameter Modelica.Units.SI.HeatFlowRate QCoo_flow_nominal(max=0)
    "Nominal cooling capcaity"
  parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal=0
    "Nominal heating capacity"

  replaceable model RefrigerantCycleChillerCooling =
      AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle
      (PEle_nominal=0)
    constrainedby
    AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle(
       final useInChi=true,
       final TCon_nominal=TConCoo_nominal,
       final TEva_nominal=TEvaCoo_nominal,
       final QCoo_flow_nominal=QCoo_flow_nominal,
       final cpCon=cpCon,
       final cpEva=cpEva)
  "Refrigerant cycle module for the cooling mode"

  replaceable model RefrigerantCycleChillerHeating =
      AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.NoHeating
      (PEle_nominal=PEle_nominal)
       constrainedby
    AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialHeatPumpCycle(
       final useInHeaPum=false,
       final TCon_nominal=TEvaHea_nominal,
       final TEva_nominal=TConHea_nominal,
       final QHea_flow_nominal=QHea_flow_nominal,
       final cpCon=cpCon,
       final cpEva=cpEva)
  "Refrigerant cycle module for the heating mode"
  parameter Modelica.Units.SI.Temperature TEvaCoo_nominal
    "Nominal temperature of the cooled fluid"
  parameter Modelica.Units.SI.Temperature TConCoo_nominal
    "Nominal temperature of the heated fluid"
  parameter Modelica.Units.SI.Temperature TEvaHea_nominal
    "Nominal temperature of the heated fluid"
  parameter Modelica.Units.SI.Temperature TConHea_nominal
    "Nominal temperature of the cooled fluid"

  Modelica.Blocks.Interfaces.BooleanInput coo if not use_busConOnl and use_rev
    "=true for cooling, =false for heating"
  Modelica.Blocks.Sources.BooleanConstant conCoo(final k=true)
    if not use_busConOnl and not use_rev
    "Locks the device in cooling mode if designated to be not reversible"
  Modelica.Blocks.Logical.Not notCoo "Not cooling is heating"
equation
  connect(conCoo.y, sigBus.coo)
  connect(coo, sigBus.coo)
  connect(eff.QUse_flow, refCycIneEva.y)
  connect(eff.hea, notCoo.y)
  connect(notCoo.u, sigBus.coo)
end Modular;


within AixLib.Fluid.Chillers;
package ModularReversible "Package for reversible and non-reversible chillers using a modular model approach"
extends Modelica.Icons.VariantsPackage;
end ModularReversible;


within AixLib.Fluid.Chillers.ModularReversible;
package UsersGuide
  "User's Guide for modular reversible heat pump and chiller models"
  extends Modelica.Icons.Information;
end UsersGuide;


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


Refrigerant cycle model of a chiller. Modular refrigerant cycle model for chiller applications used in
  the model
  AixLib.Fluid.Chillers.ModularReversible.Modular and extending models
  of the modular approach.

within AixLib.Fluid.Chillers.ModularReversible.BaseClasses;
model RefrigerantCycle "Refrigerant cycle model of a chiller"
  extends AixLib.Fluid.HeatPumps.ModularReversible.BaseClasses.PartialModularRefrigerantCycle;

  parameter Boolean allowDifferentDeviceIdentifiers=false
    "if use_rev=true, device data for cooling and heating need to entered. Set allowDifferentDeviceIdentifiers=true to allow different device identifiers devIde"

  replaceable model RefrigerantCycleChillerCooling =
      AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.NoCooling(
        useInChi=true)
    constrainedby
      AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle
    "Replaceable model for refrigerant cycle of a chiller in main operation mode"

  replaceable model RefrigerantCycleChillerHeating =
      AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.NoHeating(
        useInHeaPum=true)
    constrainedby
      AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialHeatPumpCycle
    "Replaceable model for refrigerant cycle of a chiller in reversed operation mode"

  RefrigerantCycleChillerCooling refCycChiCoo
    "Refrigerant cycle instance for cooling"
  RefrigerantCycleChillerHeating refCycChiHea
    "Refrigerant cycle instance for heating"

protected
  parameter String devIde =
    if use_rev then refCycChiHea.devIde else refCycChiCoo.devIde
    "Data source for refrigerant cycle";

initial algorithm
  if not allowDifferentDeviceIdentifiers then
    assert(
      devIde == refCycChiCoo.devIde,
      "In " + getInstanceName() + ": Device identifiers devIde for reversible operation are not equal.
      Cooling device identifier is '" + refCycChiCoo.devIde + "' but heating is '"
      + devIde + "'. To allow this, set 'allowDifferentDeviceIdentifiers=true'.",
      AssertionLevel.error);
  end if;
equation
  connect(pasTrhModSet.u, sigBus.coo);

  connect(sigBus,refCycChiHea.sigBus)
  connect(sigBus,refCycChiCoo.sigBus)

  connect(swiPEle.u2, sigBus.coo)
  connect(swiQEva.u2, sigBus.coo)
  connect(swiQCon.u2, sigBus.coo)
  connect(refCycChiCoo.QEva_flow, swiQEva.u1)
  connect(refCycChiCoo.QCon_flow, swiQCon.u1)
  connect(refCycChiCoo.PEle, swiPEle.u1)
  connect(refCycChiHea.PEle, swiPEle.u3)
  connect(refCycChiHea.QCon_flow, swiQEva.u3)
  connect(refCycChiHea.QEva_flow, swiQCon.u3)
end RefrigerantCycle;


Package of control sequences

within AixLib.Fluid.Chillers.ModularReversible;
package Controls "Package of control sequences"
  extends Modelica.Icons.Package;
end Controls;


Indicates if the chiller operation is within a defined envelope. Model to check if the operating conditions of a chiller are inside
  the given boundaries. If not, the heat pump or chiller will switch off.

within AixLib.Fluid.Chillers.ModularReversible.Controls.Safety;
model OperationalEnvelope
  "Indicates if the chiller operation is within a defined envelope"
  extends
    HeatPumps.ModularReversible.Controls.Safety.BaseClasses.PartialOperationalEnvelope;
  Modelica.Blocks.Logical.Not notCoo "=true for heating"
equation
    if use_TEvaOutHea then
    connect(bouMapHea.TUseSid, sigBus.TEvaOutMea)
  else
    connect(bouMapHea.TUseSid, sigBus.TEvaInMea)
  end if;
  if use_TConOutCoo then
    connect(bouMapCoo.TAmbSid, sigBus.TConOutMea)
  else
    connect(bouMapCoo.TAmbSid, sigBus.TConInMea)
  end if;
  if use_TConOutHea then
    connect(bouMapHea.TAmbSid, sigBus.TConOutMea)
  else
    connect(bouMapHea.TAmbSid, sigBus.TConInMea)
  end if;
  if use_TEvaOutCoo then
    connect(bouMapCoo.TUseSid, sigBus.TEvaOutMea)
  else
    connect(bouMapCoo.TUseSid, sigBus.TEvaInMea)
  end if;
  connect(notCoo.y, swiHeaCoo.u2)
  connect(notCoo.u, sigBus.coo)
end OperationalEnvelope;


within AixLib.Fluid.Chillers.ModularReversible.Controls;
package Safety "Contains typical safety controllers for chillers"
  extends Modelica.Icons.Package;
end Safety;


Package for data records

within AixLib.Fluid.Chillers.ModularReversible;
package Data "Package for data records"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Data;


Package with two-dimensional data

within AixLib.Fluid.Chillers.ModularReversible.Data;
package TableData2D "Package with two-dimensional data"
  extends Modelica.Icons.MaterialPropertiesPackage;
end TableData2D;


Package for EN15411 data records

within AixLib.Fluid.Chillers.ModularReversible.Data.TableData2D;
package EN14511 "Package for EN15411 data records"
end EN14511;


A2W Vitocal 251 by Viessmann. Data from the planning book (Planungshandbuch) from Viessmann.


within AixLib.Fluid.Chillers.ModularReversible.Examples;
model CarnotWithLosses
  "Example for reversible Carnot chiller model"
  extends Modelica.Icons.Example;
  package MediumCon = AixLib.Media.Water "Medium model for condenser";
  package MediumEva = AixLib.Media.Water "Medium model for evaporator";

  AixLib.Fluid.Chillers.ModularReversible.CarnotWithLosses chi(
    redeclare package MediumCon = MediumCon,
    redeclare package MediumEva = MediumEva,
    QCoo_flow_nominal=-30000,
    redeclare
      AixLib.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Wuellhorst2021
      safCtrPar(
      minOffTime=100,
      use_maxCycRat=false,
      tabUppHea=[263.15,313.15; 333.15,313.15],
      tabLowCoo=[263.15,283.15; 333.15,283.15],
      use_TEvaOutCoo=true),
    TConCoo_nominal=313.15,
    dpCon_nominal(displayUnit="Pa") = 6000,
    use_conCap=false,
    CCon=0,
    GConOut=0,
    GConIns=0,
    TEvaCoo_nominal=278.15,
    dTEva_nominal(displayUnit="K") = 10,
    dTCon_nominal(displayUnit="K") = 5,
    dpEva_nominal(displayUnit="Pa") = 6000,
    use_evaCap=false,
    CEva=0,
    GEvaOut=0,
    GEvaIns=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    show_T=true,
    QHea_flow_nominal=40000,
    TConHea_nominal=293.15,
    TEvaHea_nominal=303.15)
                 "Chiller instance with reversbile Carnot approach"
  AixLib.Fluid.Sources.MassFlowSource_T souCon(
    nPorts=1,
    redeclare package Medium = MediumCon,
    use_T_in=true,
    m_flow=chi.mCon_flow_nominal,
    T=298.15) "Condenser source"
  AixLib.Fluid.Sources.MassFlowSource_T souEva(
    nPorts=1,
    redeclare package Medium = MediumEva,
    use_T_in=true,
    m_flow=chi.mEva_flow_nominal,
    T=291.15) "Evaporator source"
  AixLib.Fluid.Sources.Boundary_pT sinCon(nPorts=1, redeclare package Medium =
        MediumCon) "Condenser sink"
  AixLib.Fluid.Sources.Boundary_pT sinEva(nPorts=1, redeclare package Medium =
        MediumEva) "Evaporator sink"
  Modelica.Blocks.Sources.SawTooth ySet(
    amplitude=-1,
    period=500,
    offset=1,
    startTime=500)  "Compressor control signal"
  Modelica.Blocks.Sources.Ramp TConIn(
    height=10,
    duration=60,
    offset=273.15 + 30,
    startTime=60) "Condenser inlet temperature"
  Modelica.Blocks.Sources.Ramp TEvaIn(
    height=10,
    duration=60,
    startTime=900,
    offset=273.15 + 15) "Evaporator inlet temperature"
equation
  connect(souCon.ports[1], chi.port_a1)
  connect(souEva.ports[1], chi.port_a2)
  connect(chi.port_b1, sinCon.ports[1])
  connect(sinEva.ports[1], chi.port_b2)
  connect(TConIn.y, souCon.T_in)
  connect(TEvaIn.y, souEva.T_in)
  connect(ySet.y, chi.ySet)
end CarnotWithLosses;


within AixLib.Fluid.Chillers.ModularReversible.Examples;
model LargeScaleWaterToWater
  "Example for large scale water to water chiller"
  extends Modelica.Icons.Example;
  package MediumCon = AixLib.Media.Water "Medium model for condenser";
  package MediumEva = AixLib.Media.Water "Medium model for evaporator";

  AixLib.Fluid.Chillers.ModularReversible.LargeScaleWaterToWater chi(
    redeclare
      AixLib.Fluid.Chillers.ModularReversible.Data.TableData2D.EN14511.Carrier30XWP1012_1MW
      datTab,
    redeclare AixLib.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Wuellhorst2021
      safCtrPar,
    redeclare package MediumCon = MediumCon,
    redeclare package MediumEva = MediumEva,
    QCoo_flow_nominal=-1000000,
    TConCoo_nominal=313.15,
    dpCon_nominal(displayUnit="Pa") = 6000,
    TEvaCoo_nominal=278.15,
    dpEva_nominal(displayUnit="Pa") = 6000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Large scale water to water chiller"
  AixLib.Fluid.Sources.MassFlowSource_T souCon(
    nPorts=1,
    redeclare package Medium = MediumCon,
    use_T_in=true,
    m_flow=chi.mCon_flow_nominal,
    T=298.15) "Condenser source"
  AixLib.Fluid.Sources.MassFlowSource_T souEva(
    nPorts=1,
    redeclare package Medium = MediumEva,
    use_T_in=true,
    m_flow=chi.mEva_flow_nominal,
    T=291.15) "Evaporator source"
  AixLib.Fluid.Sources.Boundary_pT sinCon(nPorts=1, redeclare package Medium =
        MediumCon) "Condenser sink"
  AixLib.Fluid.Sources.Boundary_pT sinEva(nPorts=1, redeclare package Medium =
        MediumEva) "Evaporator sink"
  Modelica.Blocks.Sources.Ramp ySet(
    height=-1,
    duration=900,
    offset=1,
    startTime=1800) "Compressor control signal"
  Modelica.Blocks.Sources.Ramp TConIn(
    height=10,
    duration=60,
    offset=273.15 + 30,
    startTime=60) "Condenser inlet temperature"
  Modelica.Blocks.Sources.Ramp TEvaIn(
    height=10,
    duration=60,
    startTime=900,
    offset=273.15 + 15) "Evaporator inlet temperature"
equation
  connect(souCon.ports[1], chi.port_a1)
  connect(souEva.ports[1], chi.port_a2)
  connect(chi.port_b1, sinCon.ports[1])
  connect(sinEva.ports[1], chi.port_b2)
  connect(TConIn.y, souCon.T_in)
  connect(TEvaIn.y, souEva.T_in)
  connect(ySet.y, chi.ySet)
end LargeScaleWaterToWater;


Example for modular reversible chiller

within AixLib.Fluid.Chillers.ModularReversible.Examples;
model Modular
  "Example for modular reversible chiller"
  extends Modelica.Icons.Example;
  package MediumCon = AixLib.Media.Air "Medium model for condenser";
  package MediumEva = AixLib.Media.Water "Medium model for evaporator";

  AixLib.Fluid.Chillers.ModularReversible.Modular chi(
    redeclare package MediumCon = MediumCon,
    redeclare package MediumEva = MediumEva,
    use_rev=true,
    allowDifferentDeviceIdentifiers=true,
    QCoo_flow_nominal=-30000,
    redeclare model RefrigerantCycleInertia =
        AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Inertias.VariableOrder
        (
        refIneFreConst=1/300,
        nthOrd=1,
        initType=Modelica.Blocks.Types.Init.InitialState),
    redeclare
      AixLib.Fluid.HeatPumps.ModularReversible.Controls.Safety.Data.Wuellhorst2021
      safCtrPar(minOffTime=100, use_opeEnv=false),
    TConCoo_nominal=313.15,
    dpCon_nominal(displayUnit="Pa") = 6000,
    use_conCap=false,
    CCon=0,
    GConOut=0,
    GConIns=0,
    TEvaCoo_nominal=278.15,
    dTEva_nominal=5,
    dTCon_nominal=5,
    dpEva_nominal(displayUnit="Pa") = 6000,
    use_evaCap=false,
    CEva=0,
    GEvaOut=0,
    GEvaIns=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    show_T=true,
    QHea_flow_nominal=30000,
    redeclare model RefrigerantCycleChillerCooling =
        AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness
        (etaCarnot_nominal=0.35),
    redeclare model RefrigerantCycleChillerHeating =
        AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.TableData2D (
          redeclare
          AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.NoFrosting
          iceFacCal, datTab=
            AixLib.Fluid.HeatPumps.ModularReversible.Data.TableData2D.EN14511.Vitocal251A08()),
    TEvaHea_nominal=303.15,
    TConHea_nominal=298.15)
                 "Modular reversible chiller instance"
  AixLib.Fluid.Sources.MassFlowSource_T souCon(
    nPorts=1,
    redeclare package Medium = MediumCon,
    use_T_in=true,
    m_flow=chi.mCon_flow_nominal,
    T=298.15) "Condenser source"
  AixLib.Fluid.Sources.MassFlowSource_T souEva(
    nPorts=1,
    redeclare package Medium = MediumEva,
    use_T_in=true,
    m_flow=chi.mEva_flow_nominal,
    T=291.15) "Evaporator source"
  AixLib.Fluid.Sources.Boundary_pT sinCon(nPorts=1, redeclare package Medium =
        MediumCon) "Condenser sink"
  AixLib.Fluid.Sources.Boundary_pT sinEva(nPorts=1, redeclare package Medium =
        MediumEva) "Evaporator sink"
  Modelica.Blocks.Sources.SawTooth ySet(
    amplitude=-1,
    period=500,
    offset=1,
    startTime=500)  "Compressor control signal"
  Modelica.Blocks.Sources.Ramp TConIn(
    height=10,
    duration=60,
    offset=273.15 + 30,
    startTime=60) "Condenser inlet temperature"
  Modelica.Blocks.Sources.Ramp TEvaIn(
    height=10,
    duration=60,
    startTime=900,
    offset=273.15 + 15) "Evaporator inlet temperature"
  Modelica.Blocks.Sources.BooleanStep chiCoo(startTime=2100, startValue=true)
    "Chilling mode on"
equation
  connect(souCon.ports[1], chi.port_a1)
  connect(souEva.ports[1], chi.port_a2)
  connect(chi.port_b1, sinCon.ports[1])
  connect(sinEva.ports[1], chi.port_b2)
  connect(TConIn.y, souCon.T_in)
  connect(TEvaIn.y, souEva.T_in)
  connect(ySet.y, chi.ySet)
  connect(chiCoo.y, chi.coo)
end Modular;


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


Carnot EER with a constant Carnot effectiveness. This model uses a constant Carnot effectiveness approach
  to compute the efficiency of the chiller.

within AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle;
model ConstantCarnotEffectiveness "Carnot EER with a constant Carnot effectiveness"
  extends
    AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle(
      useInChi=true,
      PEle_nominal=-QCoo_flow_nominal/EER_nominal,
      devIde="ConstantCarnotEffectiveness");
  extends
    AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialCarnot(
     TAppCon_nominal=if cpCon < 1500 then 5 else 2,
     TAppEva_nominal=if cpEva < 1500 then 5 else 2,
     final useForChi=true,
     final QEva_flow_nominal=QCoo_flow_nominal,
     final QCon_flow_nominal=PEle_nominal-QCoo_flow_nominal,
     constPEle(final k=PEle_nominal),
    proQUse_flow(nu=4));
  parameter Real EER_nominal(
    min=0,
    final unit="1") = etaCarnot_nominal*(TEva_nominal - TAppEva_nominal)/(
    TCon_nominal + TAppCon_nominal - (TEva_nominal - TAppEva_nominal))
    "Nominal EER";

  Modelica.Blocks.Sources.Constant constNegOne(final k=-1)
    "Negative one to negative evaporator heat flow rate"
equation
  connect(swiQUse.u2, sigBus.onOffMea)
  connect(swiPEle.y, redQCon.u2)
  connect(swiPEle.y, PEle)
  connect(swiPEle.u2, sigBus.onOffMea)
  connect(pasThrYMea.u, sigBus.yMea)
  if useInChi then
    connect(pasThrTCon.u, sigBus.TConOutMea)
    connect(pasThrTEva.u, sigBus.TEvaOutMea)
  else
    connect(pasThrTCon.u, sigBus.TEvaOutMea)
    connect(pasThrTEva.u, sigBus.TConOutMea)
  end if;
  connect(swiQUse.y, proRedQEva.u2)
  connect(constNegOne.y, proQUse_flow.u[4])
end ConstantCarnotEffectiveness;


within AixLib.Fluid.Chillers.ModularReversible;
package RefrigerantCycle "Package for chiller refrigerant cycle modules"
   extends Modelica.Icons.MaterialPropertiesPackage;
end RefrigerantCycle;


Performance data based on condenser outlet and evaporator inlet temperature. This model uses two-dimensional table data typically given
  by manufacturers as required by e.g. European Norm 14511
  or ASHRAE 205 to calculate
  QEva_flow and PEle.

within AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle;
model TableData2D
  "Performance data based on condenser outlet and evaporator inlet temperature"
  extends
    AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.PartialChillerCycle(
    final devIde=datTab.devIde,
    PEle_nominal=Modelica.Blocks.Tables.Internal.getTable2DValueNoDer2(
        tabIdePEle,
        TEva_nominal,
        TCon_nominal) * scaFac);
  extends
    AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialTableData2D(
    final useInRevDev=not useInChi,
    final use_TConOutForTab=datTab.use_TConOutForTab,
    final use_TEvaOutForTab=datTab.use_TEvaOutForTab,
    tabQUse_flow(final table=datTab.tabQEva_flow),
    tabPEle(final table=datTab.tabPEle),
    scaFac=QCoo_flow_nominal/QCooNoSca_flow_nominal,
    mEva_flow_nominal=datTab.mEva_flow_nominal*scaFac,
    mCon_flow_nominal=datTab.mCon_flow_nominal*scaFac,
    final valTabQEva_flow = {{-tabQUse_flow.table[j, i] for i in 2:numCol} for j in 2:numRow},
    final valTabQCon_flow = valTabQEva_flow .+ valTabPEle,
    final mCon_flow_max=max(valTabQCon_flow) * scaFac / cpCon / dTMin,
    final mCon_flow_min=min(valTabQCon_flow) * scaFac / cpCon / dTMax,
    final mEva_flow_min=min(valTabQEva_flow) * scaFac / cpEva / dTMax,
    final mEva_flow_max=max(valTabQEva_flow) * scaFac / cpEva / dTMin);
  parameter Modelica.Units.SI.HeatFlowRate QCooNoSca_flow_nominal=
        Modelica.Blocks.Tables.Internal.getTable2DValueNoDer2(
        tabIdeQUse_flow,
        TEva_nominal,
        TCon_nominal)
    "Unscaled nominal cooling capacity "
  replaceable parameter AixLib.Fluid.Chillers.ModularReversible.Data.TableData2D.Generic datTab
    "Data Table of Chiller"

equation

  connect(scaFacTimPel.y, PEle)
  connect(scaFacTimPel.y, redQCon.u2)
  connect(scaFacTimQUse_flow.y, proRedQEva.u2)
  connect(yMeaTimScaFac.u1, sigBus.yMea)
  connect(reaPasThrTEvaOut.u, sigBus.TEvaOutMea)
  connect(reaPasThrTEvaIn.u, sigBus.TEvaInMea)
  connect(reaPasThrTConIn.u, sigBus.TConInMea)
  connect(reaPasThrTConOut.u, sigBus.TConOutMea)

  if useInChi then
    connect(reaPasThrTConOut.y, tabPEle.u2)
    connect(reaPasThrTConIn.y, tabPEle.u2)
    connect(reaPasThrTConIn.y, tabQUse_flow.u2)
    connect(reaPasThrTConOut.y, tabQUse_flow.u2)
    connect(reaPasThrTEvaOut.y, tabQUse_flow.u1)
    connect(reaPasThrTEvaIn.y, tabQUse_flow.u1)
    connect(reaPasThrTEvaOut.y, tabPEle.u1)
    connect(reaPasThrTEvaIn.y, tabPEle.u1)
  else
    connect(reaPasThrTConOut.y, tabPEle.u1)
    connect(reaPasThrTConOut.y, tabQUse_flow.u1)
    connect(reaPasThrTConIn.y, tabQUse_flow.u1)
    connect(reaPasThrTConIn.y, tabPEle.u1)
    connect(reaPasThrTEvaOut.y, tabPEle.u2)
    connect(reaPasThrTEvaOut.y, tabQUse_flow.u2)
    connect(reaPasThrTEvaIn.y, tabQUse_flow.u2)
    connect(reaPasThrTEvaIn.y, tabPEle.u2)
  end if;
end TableData2D;


Placeholder to disable cooling. Using this model, the chiller will always be off.
  This option is mainly used to avoid warnings about
  partial model which must be replaced.

within AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses;
model NoCooling
  "Placeholder to disable cooling"
  extends PartialChillerCycle(
    TEva_nominal=273.15,
    TCon_nominal=273.15,
    cpEva=4184,
    cpCon=4184,
    PEle_nominal=0,
    redeclare final
      AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.Frosting.NoFrosting
      iceFacCal,
    devIde="NoCooling",
    QCoo_flow_nominal=0);

  Modelica.Blocks.Sources.Constant const(final k=0) "Zero energy flows"
equation
  connect(const.y, redQCon.u2)
  connect(const.y, PEle)
  connect(const.y, proRedQEva.u2)
end NoCooling;


within AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle;
package BaseClasses "Package with partial classes of performance Data"
end BaseClasses;


Partial model of refrigerant cycle used for chiller applications. Partial refrigerant cycle model for chillers.
  It adds the specification for frosting calculation
  and restricts to the intended choices under
  choicesAllMatching.

within AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses;
partial model PartialChillerCycle
  "Partial model of refrigerant cycle used for chiller applications"
  extends
    AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.BaseClasses.PartialRefrigerantCycle;
  parameter Modelica.Units.SI.HeatFlowRate QCoo_flow_nominal
    "Nominal cooling capacity"
  parameter Boolean useInChi
    "=false to indicate that this model is used as a heat pump";
equation
  connect(iceFacCal.iceFac, sigBus.iceFacChiMea)
end PartialChillerCycle;


Example using the Carnot model approach

within AixLib.Fluid.Chillers.ModularReversible.Validation;
model Carnot_y "Example using the Carnot model approach"
  extends AixLib.Fluid.HeatPumps.ModularReversible.Validation.Comparative.BaseClasses.PartialComparison(
    m1_flow_nominal=chi.m1_flow_nominal,
    m2_flow_nominal=chi.m2_flow_nominal,
    sin2(nPorts=1),
    sou2(nPorts=1),
    sin1(nPorts=1),
    sou1(nPorts=1));
  extends Modelica.Icons.Example;
  AixLib.Fluid.Chillers.Carnot_y chi(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    etaCarnot_nominal=etaCarnot_nominal,
    TCon_nominal=TCon_nominal,
    TEva_nominal=TEva_nominal,
    tau1=tau1,
    tau2=tau2,
    P_nominal=QUse_flow_nominal/chi.COP_nominal,
    dTEva_nominal=-dTEva_nominal,
    dTCon_nominal=dTCon_nominal,
    use_eta_Carnot_nominal=false,
    dp1_nominal=dp1_nominal,
    dp2_nominal=dp2_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    show_T=true,
    T1_start=T1_start,
    T2_start=T2_start)
                     "Chiller model"

equation
  connect(sin2.ports[1], chi.port_b2)
  connect(chi.port_a2, sou2.ports[1])
  connect(chi.port_b1, sin1.ports[1])
  connect(chi.port_a1, sou1.ports[1])
  connect(chi.y, uCom.y)
end Carnot_y;


Validation case for modular Carnot approach. Validation case for
AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness.

within AixLib.Fluid.Chillers.ModularReversible.Validation;
model ConstantCarnotEffectiveness
  "Validation case for modular Carnot approach"
  extends BaseClasses.PartialModularComparison(chi(redeclare model
        RefrigerantCycleChillerCooling =
          AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.ConstantCarnotEffectiveness
          (etaCarnot_nominal=etaCarnot_nominal)));
  extends Modelica.Icons.Example;
end ConstantCarnotEffectiveness;


Package for model validation

within AixLib.Fluid.Chillers.ModularReversible;
package Validation "Package for model validation"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Validation case for table data approach. Validation case for
AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.TableData2D.

within AixLib.Fluid.Chillers.ModularReversible.Validation;
model TableData2D "Validation case for table data approach"
  extends BaseClasses.PartialModularComparison(
    TEva_nominal=TEvaIn_nominal,
    TCon_nominal=TConIn_nominal,
    chi(redeclare model RefrigerantCycleChillerCooling =
          AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.TableData2D (
            datTab(
            tabPEle=[0,293.15,303.15; 288.15,14122.8,14122.8; 298.15,14122.8,14122.8],
            mCon_flow_nominal=m1_flow_nominal,
            mEva_flow_nominal=m2_flow_nominal,
            dpCon_nominal=0,
            dpEva_nominal=0,
            devIde="CarnotTableData",
            use_TEvaOutForTab=false,
            use_TConOutForTab=false,
            tabQEva_flow=[0,293.15,303.15; 288.15,-35499.7,-30000; 298.15,0,-36220.8],
            tabLowBou=[273.15,273.15; 273.15,273.15],
            use_TEvaOutForOpeEnv=false,
            use_TConOutForOpeEnv=false))));

  extends Modelica.Icons.Example;
end TableData2D;


Package with partial validation models

within AixLib.Fluid.Chillers.ModularReversible.Validation;
package BaseClasses "Package with partial validation models"
extends Modelica.Icons.BasesPackage;
end BaseClasses;