Generic pipe model for DHC applications

within AixLib.Fluid.DistrictHeatingCooling.Pipes;
model DHCPipe "Generic pipe model for DHC applications"
  extends AixLib.Fluid.Interfaces.PartialTwoPortInterface(show_T=true);

  parameter Boolean use_zeta=false
    "= true HydraulicResistance is implemented, zeta value has to be given next"

  parameter Boolean use_soil=false
    "= true 3 cylindric heat transfers are implemented, representing the soil around the pipe, otherwise direct heat throughzeta value has to be given next"

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

  parameter Modelica.Units.SI.Length dh=sqrt(4*m_flow_nominal/rho_default/
      v_nominal/Modelica.Constants.pi)
    "Hydraulic diameter (assuming a round cross section area)"

  parameter Modelica.Units.SI.Velocity v_nominal=1.5
    "Velocity at m_flow_nominal (used to compute default value for hydraulic diameter dh)"

  parameter Real ReC=4000
    "Reynolds number where transition to turbulent starts";

  parameter Modelica.Units.SI.Height roughness=2.5e-5
    "Average height of surface asperities (default: smooth steel pipe)"

  parameter Modelica.Units.SI.Length length "Pipe length"

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal
    "Nominal mass flow rate"

  parameter Modelica.Units.SI.MassFlowRate m_flow_small=1E-4*abs(m_flow_nominal)
    "Small mass flow rate for regularization of zero flow"

  parameter Modelica.Units.SI.Length dIns
    "Thickness of pipe insulation, used to compute R"

  parameter Modelica.Units.SI.ThermalConductivity kIns
    "Heat conductivity of pipe insulation, used to compute R"

  parameter Modelica.Units.SI.SpecificHeatCapacity cPip=2300
    "Specific heat of pipe wall material. 2300 for PE, 500 for steel"

  parameter Modelica.Units.SI.Density rhoPip(displayUnit="kg/m3") = 930
    "Density of pipe wall material. 930 for PE, 8000 for steel"

  parameter Modelica.Units.SI.Length thickness=0.0035 "Pipe wall thickness"

  parameter Modelica.Units.SI.Temperature T_start_in(start=Medium.T_default)=
    Medium.T_default "Initialization temperature at pipe inlet"
  parameter Modelica.Units.SI.Temperature T_start_out(start=Medium.T_default)=
       T_start_in "Initialization temperature at pipe outlet"
  parameter Boolean initDelay(start=false) = false
    "Initialize delay for a constant mass flow rate if true, otherwise start from 0"
  parameter Modelica.Units.SI.MassFlowRate m_flow_start=0
    "Initial value of mass flow rate through pipe"

  parameter Real R(unit="(m.K)/W")=1/(kIns*2*Modelica.Constants.pi/
    Modelica.Math.log((dh/2 + dIns)/(dh/2)))
    "Thermal resistance per unit length from fluid to boundary temperature"

  parameter Real fac= 1.0
    "Factor to take into account flow resistance of bends etc., fac=dp_nominal/dpStraightPipe_nominal"

  parameter Real sum_zetas=0
    "Sum of all zeta values. Takes into account additional pressure drops due to bends/valves/etc. if use_zeta"

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

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

  //Ground/Soil: values for sandy soil with clay content based on "SIMULATIONSMODELL
  //"ERDWÄRMEKOLLEKTOR" zur wärmetechnischen Beurteilung von Wärmequellen,
  //Wärmesenken und Wärme-/Kältespeichern" by Bernd Glück --> move to docu

  parameter Modelica.Units.SI.Density rho_soi=1630 "Density of material/soil"

  parameter Modelica.Units.SI.SpecificHeatCapacity c=1046
    "Specific heat capacity of material/soil"
  parameter Modelica.Units.SI.Length thickness_soi=0.6
    "thickness of soil layer for heat loss calulcation"

  parameter Modelica.Units.SI.ThermalConductivity lambda=1.5
    "Heat conductivity of material/soil"

  final parameter Modelica.Units.SI.Length d_in=dh + 2*thickness
    "Inner diameter of pipe"

  final parameter Modelica.Units.SI.Temperature T0=289.15 "Initial temperature"

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

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
    "Heat transfer to or from surroundings (heat loss from pipe results in a positive heat flow)"

  replaceable AixLib.Fluid.FixedResistances.BaseClasses.PlugFlowCore pipCor(
    redeclare final package Medium = Medium,
    final dh=dh,
    final v_nominal=v_nominal,
    final length=length,
    final C=C,
    final R=R,
    final m_flow_small=m_flow_small,
    final m_flow_nominal=m_flow_nominal,
    final T_start_in=T_start_in,
    final T_start_out=T_start_out,
    final m_flow_start=m_flow_start,
    final initDelay=initDelay,
    final from_dp=from_dp,
    final fac=if not use_zeta then fac else 1.0,
    final ReC=ReC,
    final thickness=thickness,
    final roughness=roughness,
    final allowFlowReversal=allowFlowReversal,
    final homotopyInitialization=homotopyInitialization,
    final linearized=linearized) constrainedby Interfaces.PartialTwoPort(
    redeclare package Medium = Medium,
    dh=dh,
    v_nominal=v_nominal,
    length=length,
    C=C,
    R=R,
    m_flow_small=m_flow_small,
    m_flow_nominal=m_flow_nominal,
    T_start_in=T_start_in,
    T_start_out=T_start_out,
    m_flow_start=m_flow_start,
    initDelay=initDelay,
    from_dp=from_dp,
    fac=if not use_zeta then fac else 1.0,
    ReC=ReC,
    thickness=thickness,
    roughness=roughness,
    allowFlowReversal=allowFlowReversal,
    homotopyInitialization=homotopyInitialization,
    linearized=linearized) "Describing the pipe behavior"

  // In the volume, below, we scale down V and use
  // mSenFac. Otherwise, for air, we would get very large volumes
  // which affect the delay of water vapor and contaminants.
  // See also AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes.TransportWaterAir
  // for why mSenFac is 10 and not 1000, as this gives more reasonable
  // temperature step response
  AixLib.Fluid.MixingVolumes.MixingVolume vol(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final V=if rho_default > 500 then VEqu else VEqu/1000,
    final nPorts=2,
    final T_start=T_start_out,
    final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    final mSenFac = if rho_default > 500 then 1 else 10)
    "Control volume connected to ports_b. Represents equivalent pipe wall thermal capacity."

  AixLib.Utilities.HeatTransfer.CylindricHeatTransfer cylHeaTra1(
    final energyDynamics=energyDynamics,
    final rho=rho_soi,
    final c=c,
    final d_in=dh + 2*thickness,
    final d_out=d_in + thickness_soi/3,
    final length=length,
    final lambda=lambda,
    T0=283.15) if use_soil

  AixLib.Utilities.HeatTransfer.CylindricHeatTransfer cylHeaTra2(
    final energyDynamics=energyDynamics,
    final rho=rho_soi,
    final c=c,
    final d_in=dh + 2*thickness + thickness_soi/3,
    final d_out=d_in + 2*thickness_soi/3,
    final length=length,
    final lambda=lambda,
    T0=283.15) if use_soil
  AixLib.Utilities.HeatTransfer.CylindricHeatTransfer cylHeaTra3(
    final energyDynamics=energyDynamics,
    final rho=rho_soi,
    final c=c,
    final d_in=dh + 2*thickness + 2*thickness_soi/3,
    final d_out=d_in + thickness_soi,
    final length=length,
    final lambda=lambda,
    T0=283.15) if use_soil

protected
  parameter Modelica.Units.SI.HeatCapacity CPip=length*((dh + 2*thickness)^2 -
      dh^2)*Modelica.Constants.pi/4*cPip*rhoPip "Heat capacity of pipe wall";

  final parameter Modelica.Units.SI.Volume VEqu=CPip/(rho_default*cp_default)
    "Equivalent water volume to represent pipe wall thermal inertia";

  parameter Medium.ThermodynamicState sta_default=Medium.setState_pTX(
      T=Medium.T_default,
      p=Medium.p_default,
      X=Medium.X_default) "Default medium state";

  parameter Modelica.Units.SI.SpecificHeatCapacity cp_default=
      Medium.specificHeatCapacityCp(state=sta_default)
    "Heat capacity of medium";

  parameter Real C(unit="J/(K.m)")=
    rho_default*Modelica.Constants.pi*(dh/2)^2*cp_default
    "Thermal capacity per unit length of water in pipe";

  parameter Modelica.Units.SI.Density rho_default=Medium.density_pTX(
      p=Medium.p_default,
      T=Medium.T_default,
      X=Medium.X_default)
    "Default density (e.g., rho_liquidWater = 995, rho_air = 1.2)"

  Modelica.Units.SI.Velocity v_med "Velocity of the medium in the pipe";

  Modelica.Units.SI.Heat Q_los(start=0.0, fixed=true)
    "Integrated heat loss of the pipe";
  Modelica.Units.SI.Heat Q_gai(start=0.0, fixed=true)
    "Integrated heat gain of the pipe";

public
  FixedResistances.HydraulicResistance hydRes(
    diameter=dh,
    m_flow_nominal=m_flow_nominal,
    redeclare package Medium = Medium,
    zeta=sum_zetas,
    allowFlowReversal=allowFlowReversal,
    from_dp=from_dp,
    homotopyInitialization=homotopyInitialization,
    linearized=linearized,
    m_flow_start=m_flow_start) if use_zeta
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector thePasThr(final m=1)
    if not use_soil "Thermal pass through if there is no soil activated"
  Interfaces.PassThroughMedium pasThrMed(redeclare package Medium = Medium)
                                                 if not use_zeta
equation
  //calculation of the flow velocity of water in the pipes
  v_med = (4 * port_a.m_flow) / (Modelica.Constants.pi * rho_default * dh * dh);

  //calculation of heat losses and heat gains of pipe
  der(Q_los) = min(0, pipCor.heatPort.Q_flow);
  der(Q_gai) = max(0, pipCor.heatPort.Q_flow);

  connect(vol.ports[2], port_b)

  connect(pipCor.port_b, vol.ports[1])
  connect(pipCor.heatPort, cylHeaTra1.port_a)
  connect(cylHeaTra1.port_b, cylHeaTra2.port_a)
  connect(cylHeaTra2.port_b, cylHeaTra3.port_a)
  connect(cylHeaTra3.port_b, heatPort)
  connect(pipCor.heatPort, thePasThr.port_a[1])
  connect(thePasThr.port_b, heatPort)
  connect(port_a, hydRes.port_a)
  connect(hydRes.port_b, pipCor.port_a)
  connect(port_a, port_a)
  connect(port_a, pasThrMed.port_a)
  connect(pasThrMed.port_b, pipCor.port_a)
end DHCPipe;


Models for DHC systems' pipe networks

within AixLib.Fluid.DistrictHeatingCooling;
package Pipes "Models for DHC systems' pipe networks"
end Pipes;


within AixLib.Fluid.DistrictHeatingCooling.Pipes;
model PlugFlowPipeEmbedded
  "Embedded pipe model using spatialDistribution for temperature delay"

  extends AixLib.Fluid.Interfaces.PartialTwoPortInterface(show_T=true);

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

  parameter Boolean use_zeta=false
    "= true HydraulicResistance is implemented, zeta value has to be given next"

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

  parameter Modelica.Units.SI.Length dh=sqrt(4*m_flow_nominal/rho_default/
      v_nominal/Modelica.Constants.pi)
    "Hydraulic diameter (assuming a round cross section area)"

  parameter Modelica.Units.SI.Velocity v_nominal=1.5
    "Velocity at m_flow_nominal (used to compute default value for hydraulic diameter dh)"

  parameter Real ReC=4000
    "Reynolds number where transition to turbulent starts";

  parameter Modelica.Units.SI.Height roughness=2.5e-5
    "Average height of surface asperities (default: smooth steel pipe)"

  parameter Modelica.Units.SI.Length length "Pipe length"

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal
    "Nominal mass flow rate"

  parameter Modelica.Units.SI.MassFlowRate m_flow_small=1E-4*abs(m_flow_nominal)
    "Small mass flow rate for regularization of zero flow"

  parameter Modelica.Units.SI.Length dIns
    "Thickness of pipe insulation, used to compute R"

  parameter Modelica.Units.SI.ThermalConductivity kIns
    "Heat conductivity of pipe insulation, used to compute R"

  parameter Modelica.Units.SI.SpecificHeatCapacity cPip=2300
    "Specific heat of pipe wall material. 2300 for PE, 500 for steel"

  parameter Modelica.Units.SI.Density rhoPip(displayUnit="kg/m3") = 930
    "Density of pipe wall material. 930 for PE, 8000 for steel"

  parameter Modelica.Units.SI.Length thickness=0.0035 "Pipe wall thickness"

  parameter Modelica.Units.SI.Temperature T_start_in(start=Medium.T_default)=
    Medium.T_default "Initialization temperature at pipe inlet"
  parameter Modelica.Units.SI.Temperature T_start_out(start=Medium.T_default)=
       T_start_in "Initialization temperature at pipe outlet"
  parameter Boolean initDelay(start=false) = false
    "Initialize delay for a constant mass flow rate if true, otherwise start from 0"
  parameter Modelica.Units.SI.MassFlowRate m_flow_start=0
    "Initial value of mass flow rate through pipe"

  parameter Real R(unit="(m.K)/W")=1/(kIns*2*Modelica.Constants.pi/
    Modelica.Math.log((dh/2 + dIns)/(dh/2)))
    "Thermal resistance per unit length from fluid to boundary temperature"

  parameter Real fac=1
    "Factor to take into account flow resistance of bends etc., fac=dp_nominal/dpStraightPipe_nominal"

  parameter Real sum_zetas=0
    "Sum of all zeta values. Takes into account additional pressure drops due to bends/valves/etc."

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

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

  //Ground/Soil: values for sandy soil with clay content based on "SIMULATIONSMODELL
  //"ERDWÄRMEKOLLEKTOR" zur wärmetechnischen Beurteilung von Wärmequellen,
  //Wärmesenken und Wärme-/Kältespeichern" by Bernd Glück

  parameter Modelica.Units.SI.Density rho_soi=1630 "Density of material/soil"

  parameter Modelica.Units.SI.SpecificHeatCapacity c=1046
    "Specific heat capacity of material/soil"
  parameter Modelica.Units.SI.Length thickness_soi=0.6
    "thickness of soil layer for heat loss calulcation"

  parameter Modelica.Units.SI.ThermalConductivity lambda=1.5
    "Heat conductivity of material/soil"

  final parameter Modelica.Units.SI.Length d_in=dh + 2*thickness
    "Inner diameter of pipe"
  final parameter Integer nParallel = 1 "Number of identical parallel pipes"
  final parameter Modelica.Units.SI.Temperature T0=289.15 "Initial temperature"

  Modelica.Units.SI.Velocity v_med "Velocity of the medium in the pipe";

  AixLib.Fluid.DistrictHeatingCooling.Pipes.PlugFlowPipeZeta plugFlowPipeZeta(
    redeclare final package Medium = Medium,
    final dh=dh,
    final v_nominal=v_nominal,
    final ReC=ReC,
    final roughness=roughness,
    final length=length,
    final m_flow_nominal=m_flow_nominal,
    final dIns=dIns,
    final kIns=kIns,
    final cPip=cPip,
    final rhoPip=rhoPip,
    final thickness=thickness,
    final R=R,
    final fac=fac,
    final sum_zetas=sum_zetas,
    final use_zeta=true)

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
    "Heat transfer to or from surroundings (heat loss from pipe results in a positive heat flow)"

  AixLib.Utilities.HeatTransfer.CylindricHeatTransfer cylindricHeatTransfer_1(
    final energyDynamics=energyDynamics,
    final rho=rho_soi,
    final c=c,
    final d_in=dh + 2*thickness,
    final d_out=d_in + thickness_soi/3,
    final length=length,
    final lambda=lambda,
    T0=283.15)

  AixLib.Utilities.HeatTransfer.CylindricHeatTransfer cylindricHeatTransfer_2(
    final energyDynamics=energyDynamics,
    final rho=rho_soi,
    final c=c,
    final d_in=dh + 2*thickness + thickness_soi/3,
    final d_out=d_in + 2*thickness_soi/3,
    final length=length,
    final lambda=lambda,
    T0=283.15)
  AixLib.Utilities.HeatTransfer.CylindricHeatTransfer cylindricHeatTransfer_3(
    final energyDynamics=energyDynamics,
    final rho=rho_soi,
    final c=c,
    final d_in=dh + 2*thickness + 2*thickness_soi/3,
    final d_out=d_in + thickness_soi,
    final length=length,
    final lambda=lambda,
    T0=283.15)

protected
  parameter Modelica.Units.SI.HeatCapacity CPip=length*((dh + 2*thickness)^2 -
      dh^2)*Modelica.Constants.pi/4*cPip*rhoPip "Heat capacity of pipe wall";

  final parameter Modelica.Units.SI.Volume VEqu=CPip/(rho_default*cp_default)
    "Equivalent medium volume to represent pipe wall thermal inertia";

  parameter Medium.ThermodynamicState sta_default=Medium.setState_pTX(
      T=Medium.T_default,
      p=Medium.p_default,
      X=Medium.X_default) "Default medium state";

  parameter Modelica.Units.SI.SpecificHeatCapacity cp_default=
      Medium.specificHeatCapacityCp(state=sta_default)
    "Heat capacity of medium";

  parameter Real C(unit="J/(K.m)")=
    rho_default*Modelica.Constants.pi*(dh/2)^2*cp_default
    "Thermal capacity per unit length of medium in pipe";

  parameter Modelica.Units.SI.Density rho_default=Medium.density_pTX(
      p=Medium.p_default,
      T=Medium.T_default,
      X=Medium.X_default)
    "Default density (e.g., rho_liquidWater = 995, rho_air = 1.2)"

equation
 //calculation of the flow velocity of medium in the pipes
 v_med = (4 * port_a.m_flow) / (Modelica.Constants.pi * rho_default * dh * dh);

  connect(plugFlowPipeZeta.heatPort, cylindricHeatTransfer_1.port_a)
  connect(cylindricHeatTransfer_1.port_b, cylindricHeatTransfer_2.port_a)
  connect(cylindricHeatTransfer_2.port_b,cylindricHeatTransfer_3. port_a)
  connect(cylindricHeatTransfer_3.port_b, heatPort)
  connect(port_a, plugFlowPipeZeta.port_a)
  connect(plugFlowPipeZeta.port_b, port_b)
end PlugFlowPipeEmbedded;


within AixLib.Fluid.DistrictHeatingCooling.Pipes;
model PlugFlowPipeZeta
  "Pipe model using spatialDistribution for temperature delay and conditional HydraulicResistance"
  extends AixLib.Fluid.Interfaces.PartialTwoPortInterface(show_T=true);

  parameter Boolean use_zeta=false
    "= true HydraulicResistance is implemented, zeta value has to be given next"

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

  parameter Modelica.Units.SI.Length dh=sqrt(4*m_flow_nominal/rho_default/
      v_nominal/Modelica.Constants.pi)
    "Hydraulic diameter (assuming a round cross section area)"

  parameter Modelica.Units.SI.Velocity v_nominal=1.5
    "Velocity at m_flow_nominal (used to compute default value for hydraulic diameter dh)"

  parameter Real ReC=4000
    "Reynolds number where transition to turbulent starts";

  parameter Modelica.Units.SI.Height roughness=2.5e-5
    "Average height of surface asperities (default: smooth steel pipe)"

  parameter Modelica.Units.SI.Length length "Pipe length"

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal
    "Nominal mass flow rate"

  parameter Modelica.Units.SI.MassFlowRate m_flow_small=1E-4*abs(m_flow_nominal)
    "Small mass flow rate for regularization of zero flow"

  parameter Modelica.Units.SI.Length dIns
    "Thickness of pipe insulation, used to compute R"

  parameter Modelica.Units.SI.ThermalConductivity kIns
    "Heat conductivity of pipe insulation, used to compute R"

  parameter Modelica.Units.SI.SpecificHeatCapacity cPip=2300
    "Specific heat of pipe wall material. 2300 for PE, 500 for steel"

  parameter Modelica.Units.SI.Density rhoPip(displayUnit="kg/m3") = 930
    "Density of pipe wall material. 930 for PE, 8000 for steel"

  parameter Modelica.Units.SI.Length thickness=0.0035 "Pipe wall thickness"

  parameter Modelica.Units.SI.Temperature T_start_in(start=Medium.T_default)=
    Medium.T_default "Initialization temperature at pipe inlet"
  parameter Modelica.Units.SI.Temperature T_start_out(start=Medium.T_default)=
       T_start_in "Initialization temperature at pipe outlet"
  parameter Boolean initDelay(start=false) = false
    "Initialize delay for a constant mass flow rate if true, otherwise start from 0"
  parameter Modelica.Units.SI.MassFlowRate m_flow_start=0
    "Initial value of mass flow rate through pipe"

  parameter Real R(unit="(m.K)/W")=1/(kIns*2*Modelica.Constants.pi/
    Modelica.Math.log((dh/2 + dIns)/(dh/2)))
    "Thermal resistance per unit length from fluid to boundary temperature"

  parameter Real fac= 1.0
    "Factor to take into account flow resistance of bends etc., fac=dp_nominal/dpStraightPipe_nominal"

  parameter Real sum_zetas=0
    "Sum of all zeta values. Takes into account additional pressure drops due to bends/valves/etc."

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

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

  Modelica.Units.SI.Velocity v_med "Velocity of the medium in the pipe";

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
    "Heat transfer to or from surroundings (heat loss from pipe results in a positive heat flow)"

  AixLib.Fluid.FixedResistances.BaseClasses.PlugFlowCore plugFlowCore(
    redeclare final package Medium = Medium,
    final dh=dh,
    final v_nominal=v_nominal,
    final length=length,
    final C=C,
    final R=R,
    final m_flow_small=m_flow_small,
    final m_flow_nominal=m_flow_nominal,
    final T_start_in=T_start_in,
    final T_start_out=T_start_out,
    final m_flow_start=m_flow_start,
    final initDelay=initDelay,
    final from_dp=from_dp,
    final fac=if not use_zeta then fac else 1.0,
    final ReC=ReC,
    final thickness=thickness,
    final roughness=roughness,
    final allowFlowReversal=allowFlowReversal,
    final homotopyInitialization=homotopyInitialization,
    final linearized=linearized) "Describing the pipe behavior"

  // In the volume, below, we scale down V and use
  // mSenFac. Otherwise, for air, we would get very large volumes
  // which affect the delay of water vapor and contaminants.
  // See also AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes.TransportWaterAir
  // for why mSenFac is 10 and not 1000, as this gives more reasonable
  // temperature step response
  Fluid.MixingVolumes.MixingVolume vol(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final V=if rho_default > 500 then VEqu else VEqu/1000,
    final nPorts=2,
    final T_start=T_start_out,
    final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    final mSenFac = if rho_default > 500 then 1 else 10)
    "Control volume connected to ports_b. Represents equivalent pipe wall thermal capacity."

protected
  parameter Modelica.Units.SI.HeatCapacity CPip=length*((dh + 2*thickness)^2 -
      dh^2)*Modelica.Constants.pi/4*cPip*rhoPip "Heat capacity of pipe wall";

  final parameter Modelica.Units.SI.Volume VEqu=CPip/(rho_default*cp_default)
    "Equivalent medium volume to represent pipe wall thermal inertia";

  parameter Medium.ThermodynamicState sta_default=Medium.setState_pTX(
      T=Medium.T_default,
      p=Medium.p_default,
      X=Medium.X_default) "Default medium state";

  parameter Modelica.Units.SI.SpecificHeatCapacity cp_default=
      Medium.specificHeatCapacityCp(state=sta_default)
    "Heat capacity of medium";

  parameter Real C(unit="J/(K.m)")=
    rho_default*Modelica.Constants.pi*(dh/2)^2*cp_default
    "Thermal capacity per unit length of medium in pipe";

  parameter Modelica.Units.SI.Density rho_default=Medium.density_pTX(
      p=Medium.p_default,
      T=Medium.T_default,
      X=Medium.X_default)
    "Default density (e.g., rho_liquidWater = 995, rho_air = 1.2)"

public
  FixedResistances.HydraulicResistance hydraulicResistance(
    diameter=dh,
    m_flow_nominal=m_flow_nominal,
    redeclare package Medium = Medium,
    zeta=sum_zetas,
    allowFlowReversal=allowFlowReversal,
    from_dp=from_dp,
    homotopyInitialization=homotopyInitialization,
    linearized=linearized,
    m_flow_start=m_flow_start) if use_zeta
equation
  //calculation of the flow velocity of medium in the pipes
  v_med = (4 * port_a.m_flow) / (Modelica.Constants.pi * rho_default * dh * dh);

  connect(vol.ports[2], port_b)
  connect(plugFlowCore.heatPort, heatPort)

  connect(plugFlowCore.port_b, vol.ports[1])
  if use_zeta then
  connect(hydraulicResistance.port_b, plugFlowCore.port_a)
  connect(hydraulicResistance.port_a, port_a)
  else
  connect(port_a, plugFlowCore.port_a)
  end if;
end PlugFlowPipeZeta;


within AixLib.Fluid.DistrictHeatingCooling.Pipes;
model StaticPipe
  "Static Pipe model using conditional HydraulicResistance"
  extends AixLib.Fluid.Interfaces.PartialTwoPortInterface(show_T=true);

  parameter Boolean use_zeta=false
    "= true HydraulicResistance is implemented, zeta value has to be given next"

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

  parameter Modelica.Units.SI.Length dh=sqrt(4*m_flow_nominal/rho_default/
      v_nominal/Modelica.Constants.pi)
    "Hydraulic diameter (assuming a round cross section area)"

  parameter Modelica.Units.SI.Velocity v_nominal=1.5
    "Velocity at m_flow_nominal (used to compute default value for hydraulic diameter dh)"

  parameter Real ReC=4000
    "Reynolds number where transition to turbulent starts";

  parameter Modelica.Units.SI.Height roughness=2.5e-5
    "Average height of surface asperities (default: smooth steel pipe)"

  parameter Modelica.Units.SI.Length length "Pipe length"

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal
    "Nominal mass flow rate"

  parameter Modelica.Units.SI.MassFlowRate m_flow_small=1E-4*abs(m_flow_nominal)
    "Small mass flow rate for regularization of zero flow"

  parameter Modelica.Units.SI.Length dIns
    "Thickness of pipe insulation, used to compute R"

  parameter Modelica.Units.SI.ThermalConductivity kIns
    "Heat conductivity of pipe insulation, used to compute R"

  parameter Modelica.Units.SI.SpecificHeatCapacity cPip=2300
    "Specific heat of pipe wall material. 2300 for PE, 500 for steel"

  parameter Modelica.Units.SI.Density rhoPip(displayUnit="kg/m3") = 930
    "Density of pipe wall material. 930 for PE, 8000 for steel"

  parameter Modelica.Units.SI.Length thickness=0.0035 "Pipe wall thickness"

  parameter Modelica.Units.SI.Temperature T_start_in(start=Medium.T_default)=
    Medium.T_default "Initialization temperature at pipe inlet"
  parameter Modelica.Units.SI.Temperature T_start_out(start=Medium.T_default)=
       T_start_in "Initialization temperature at pipe outlet"
  parameter Boolean initDelay(start=false) = false
    "Initialize delay for a constant mass flow rate if true, otherwise start from 0"
  parameter Modelica.Units.SI.MassFlowRate m_flow_start=0
    "Initial value of mass flow rate through pipe"

  parameter Real R(unit="(m.K)/W")=1/(kIns*2*Modelica.Constants.pi/
    Modelica.Math.log((dh/2 + dIns)/(dh/2)))
    "Thermal resistance per unit length from fluid to boundary temperature"

  parameter Real fac=1
    "Factor to take into account flow resistance of bends etc., fac=dp_nominal/dpStraightPipe_nominal"

  parameter Real sum_zetas=0
    "Sum of all zeta values. Takes into account additional pressure drops due to bends/valves/etc."

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

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

  Modelica.Units.SI.Velocity v_med "Velocity of the medium in the pipe";

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
    "Heat transfer to or from surroundings (heat loss from pipe results in a positive heat flow)"

  AixLib.Fluid.DistrictHeatingCooling.Pipes.BaseClassesStatic.StaticCore staticCore(
    redeclare final package Medium = Medium,
    final dh=dh,
    final v_nominal=v_nominal,
    final length=length,
    final C=C,
    final R=R,
    final m_flow_small=m_flow_small,
    final m_flow_nominal=m_flow_nominal,
    final T_start_in=T_start_in,
    final T_start_out=T_start_out,
    final m_flow_start=m_flow_start,
    final initDelay=initDelay,
    final from_dp=from_dp,
    final fac=fac,
    final ReC=ReC,
    final thickness=thickness,
    final roughness=roughness,
    final allowFlowReversal=allowFlowReversal,
    final homotopyInitialization=homotopyInitialization,
    final linearized=linearized) "Describing the pipe behavior"

  // In the volume, below, we scale down V and use
  // mSenFac. Otherwise, for air, we would get very large volumes
  // which affect the delay of water vapor and contaminants.
  // See also AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes.TransportWaterAir
  // for why mSenFac is 10 and not 1000, as this gives more reasonable
  // temperature step response
  Fluid.MixingVolumes.MixingVolume vol(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final V=if rho_default > 500 then VEqu else VEqu/1000,
    final nPorts=2,
    final T_start=T_start_out,
    final energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    final mSenFac = if rho_default > 500 then 1 else 10)
    "Control volume connected to ports_b. Represents equivalent pipe wall thermal capacity."

protected
  parameter Modelica.Units.SI.HeatCapacity CPip=length*((dh + 2*thickness)^2 -
      dh^2)*Modelica.Constants.pi/4*cPip*rhoPip "Heat capacity of pipe wall";

  final parameter Modelica.Units.SI.Volume VEqu=CPip/(rho_default*cp_default)
    "Equivalent medium volume to represent pipe wall thermal inertia";

  parameter Medium.ThermodynamicState sta_default=Medium.setState_pTX(
      T=Medium.T_default,
      p=Medium.p_default,
      X=Medium.X_default) "Default medium state";

  parameter Modelica.Units.SI.SpecificHeatCapacity cp_default=
      Medium.specificHeatCapacityCp(state=sta_default)
    "Heat capacity of medium";

  parameter Real C(unit="J/(K.m)")=
    rho_default*Modelica.Constants.pi*(dh/2)^2*cp_default
    "Thermal capacity per unit length of medium in pipe";

  parameter Modelica.Units.SI.Density rho_default=Medium.density_pTX(
      p=Medium.p_default,
      T=Medium.T_default,
      X=Medium.X_default)
    "Default density (e.g., rho_liquidWater = 995, rho_air = 1.2)"

public
  FixedResistances.HydraulicResistance hydraulicResistance(
    diameter=dh,
    m_flow_nominal=m_flow_nominal,
    redeclare package Medium = Medium,
    zeta=sum_zetas,
    allowFlowReversal=allowFlowReversal,
    from_dp=from_dp,
    homotopyInitialization=homotopyInitialization,
    linearized=linearized,
    m_flow_start=m_flow_start) if use_zeta
equation
  //calculation of the flow velocity of medium in the pipes
 v_med = (4 * port_a.m_flow) / (Modelica.Constants.pi * rho_default * dh * dh);

  connect(vol.ports[2], port_b)
  connect(staticCore.heatPort, heatPort)

  connect(staticCore.port_b, vol.ports[1])
  //Connect hydraulicResistance
  if use_zeta then
  connect(hydraulicResistance.port_b, staticCore.port_a)
  connect(hydraulicResistance.port_a, port_a)
  else
  connect(port_a, staticCore.port_a)
  end if;
end StaticPipe;


Base classes for static pipe

within AixLib.Fluid.DistrictHeatingCooling.Pipes;
package BaseClassesStatic "Base classes for static pipe"
extends Modelica.Icons.BasesPackage;

end BaseClassesStatic;


Pipe model using static conditions

within AixLib.Fluid.DistrictHeatingCooling.Pipes.BaseClassesStatic;
model StaticCore
  "Pipe model using static conditions"
  extends AixLib.Fluid.Interfaces.PartialTwoPort;

  parameter Modelica.Units.SI.Length dh
    "Hydraulic diameter (assuming a round cross section area)";

  parameter Modelica.Units.SI.Velocity v_nominal
    "Velocity at m_flow_nominal (used to compute default value for hydraulic diameter dh)"

  parameter Modelica.Units.SI.Length length(min=0) "Pipe length";

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal(min=0)
    "Nominal mass flow rate"

  parameter Modelica.Units.SI.MassFlowRate m_flow_small(min=0) = 1E-4*abs(
    m_flow_nominal) "Small mass flow rate for regularization of zero flow"

  parameter Modelica.Units.SI.Height roughness=2.5e-5
    "Average height of surface asperities (default: smooth steel pipe)"

  parameter Real R(unit="(m.K)/W")
    "Thermal resistance per unit length from fluid to boundary temperature";

  parameter Real C(unit="J/(K.m)")
    "Thermal capacity per unit length of pipe";

  parameter Real fac=1
    "Factor to take into account flow resistance of bends etc., fac=dp_nominal/dpStraightPipe_nominal";

  parameter Boolean from_dp=false
    "= true, use m_flow = f(dp) else dp = f(m_flow)"
  parameter Modelica.Units.SI.Length thickness(min=0) "Pipe wall thickness";

  parameter Modelica.Units.SI.Temperature T_start_in=Medium.T_default
    "Initialization temperature at pipe inlet"
  parameter Modelica.Units.SI.Temperature T_start_out=Medium.T_default
    "Initialization temperature at pipe outlet"
  parameter Boolean initDelay=false
    "Initialize delay for a constant mass flow rate if true, otherwise start from 0"
  parameter Modelica.Units.SI.MassFlowRate m_flow_start=0

  parameter Real ReC=4000
    "Reynolds number where transition to turbulent starts";

  constant Boolean homotopyInitialization = true "= true, use homotopy method"
  parameter Boolean linearized = false
    "= true, use linear relation between m_flow and dp for any flow rate"

  AixLib.Fluid.FixedResistances.HydraulicDiameter res(
    redeclare final package Medium = Medium,
    final dh=dh,
    final m_flow_nominal=m_flow_nominal,
    final from_dp=from_dp,
    final length=length,
    final roughness=roughness,
    final fac=fac,
    final ReC=ReC,
    final v_nominal=v_nominal,
    final allowFlowReversal=allowFlowReversal,
    final show_T=false,
    final homotopyInitialization=homotopyInitialization,
    final linearized=linearized,
    dp(nominal=fac*200*length))
                 "Pressure drop calculation for this pipe"

  AixLib.Fluid.FixedResistances.BaseClasses.PlugFlowHeatLoss heaLos_a(
    redeclare final package Medium = Medium,
    final C=C,
    final R=R,
    final m_flow_small=m_flow_small,
    final T_start=T_start_in,
    final m_flow_nominal=m_flow_nominal,
    final m_flow_start=m_flow_start,
    final show_T=false,
    final show_V_flow=false) "Heat loss for flow from port_b to port_a"

  AixLib.Fluid.FixedResistances.BaseClasses.PlugFlowHeatLoss heaLos_b(
    redeclare final package Medium = Medium,
    final C=C,
    final R=R,
    final m_flow_small=m_flow_small,
    final T_start=T_start_out,
    final m_flow_nominal=m_flow_nominal,
    final m_flow_start=m_flow_start,
    final show_T=false,
    final show_V_flow=false) "Heat loss for flow from port_a to port_b"
  AixLib.Fluid.Sensors.MassFlowRate senMasFlo(
    redeclare final package Medium = Medium) "Mass flow sensor"
  StaticTransportDelay                                             timDel(
    final length=length,
    final dh=dh,
    final rho=rho_default,
    final initDelay=initDelay,
    final m_flow_nominal=m_flow_nominal,
    final m_flow_start=m_flow_start) "Time delay"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
    "Heat port to connect environment (positive heat flow for heat loss to surroundings)"

protected
  parameter Modelica.Units.SI.Density rho_default=Medium.density_pTX(
      p=Medium.p_default,
      T=Medium.T_default,
      X=Medium.X_default)
    "Default density (e.g., rho_liquidWater = 995, rho_air = 1.2)"

equation
  connect(senMasFlo.m_flow, timDel.m_flow)
  connect(heaLos_a.heatPort, heatPort)
  connect(heaLos_b.heatPort, heatPort)

  connect(timDel.tauRev, heaLos_a.tau)
  connect(timDel.tau, heaLos_b.tau)

  connect(port_a, heaLos_a.port_b)
  connect(heaLos_a.port_a, senMasFlo.port_a)
  connect(heaLos_b.port_b, port_b)
  connect(senMasFlo.port_b, res.port_a)
  connect(res.port_b, heaLos_b.port_a)
end StaticCore;


Delay time for given current velocity. This is a copy of the PlugFlowTransportDelay modified to react
  directly on the current velocity. This gives a static behavior
  similar to quasi-static DHC models for comparison. Note that this is
  only included for some legacy testing.

within AixLib.Fluid.DistrictHeatingCooling.Pipes.BaseClassesStatic;
model StaticTransportDelay "Delay time for given current velocity"

  parameter Modelica.Units.SI.Length length "Pipe length";
  parameter Modelica.Units.SI.Length dh
    "Hydraulic diameter (assuming a round cross section area)";
  parameter Modelica.Units.SI.Density rho "Standard density of fluid";
  parameter Boolean initDelay=false
    "Initialize delay for a constant m_flow_start if true, otherwise start from 0"
  parameter Modelica.Units.SI.MassFlowRate m_flow_start=0
    "Initialization of mass flow rate to calculate initial time delay"

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal(min=0)
    "Nominal mass flow rate"

  final parameter Modelica.Units.SI.Time t_in_start=if initDelay and (abs(
      m_flow_start) > 1E-10*m_flow_nominal) then min(length/m_flow_start*(rho*
      dh^2/4*Modelica.Constants.pi), 0) else 0
    "Initial value of input time at inlet";
  final parameter Modelica.Units.SI.Time t_out_start=if initDelay and (abs(
      m_flow_start) > 1E-10*m_flow_nominal) then min(-length/m_flow_start*(rho*
      dh^2/4*Modelica.Constants.pi), 0) else 0
    "Initial value of input time at outlet";

  Modelica.Units.SI.Velocity velocity "Flow velocity within pipe";

  Modelica.Blocks.Interfaces.RealInput m_flow "Mass flow of fluid"

  Modelica.Blocks.Interfaces.RealOutput tau
    "Time delay for design flow direction"
  Modelica.Blocks.Interfaces.RealOutput tauRev "Time delay for reverse flow"

equation
  velocity = abs(m_flow)/(rho*(dh^2)/4*Modelica.Constants.pi);

  tau = length*(
    AixLib.Utilities.Math.Functions.inverseXRegularized(
       x=velocity,
       delta=0.0001));
  tauRev = tau;
end StaticTransportDelay;


within AixLib.Fluid.DistrictHeatingCooling.Pipes.Examples;
model DHCPipe "Simple example of DHCPipe and its four different modes"
  extends Modelica.Icons.Example;
  replaceable package Medium = AixLib.Media.Water "Medium in the pipe"
  Modelica.Blocks.Sources.Pulse Tin(
    amplitude=20,
    period=20,
    offset=273.15 + 50,
    startTime=100) "Ramp pressure signal"
  Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325) "Pressure boundary condition"
  AixLib.Fluid.DistrictHeatingCooling.Pipes.DHCPipe  pip(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    redeclare BaseClassesStatic.StaticCore pipCor "Static core",
    dh=0.1,
    length=100,
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=1,
    cPip=500,
    thickness=0.0032,
    initDelay=true,
    m_flow_start=1,
    rhoPip=8000,
    use_zeta=false,
    T_start_in=323.15,
    T_start_out=323.15) "Pipe"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature bou(T=283.15)
    "Boundary temperature"
  AixLib.Fluid.Sources.MassFlowSource_T sou(
    nPorts=1,
    redeclare package Medium = Medium,
    use_T_in=true,
    m_flow=1) "Flow source"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTemOut(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTemIn(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
  Modelica.Blocks.Sources.Pulse Tin1(
    amplitude=20,
    period=20,
    offset=273.15 + 50,
    startTime=100) "Ramp pressure signal"
  Sources.Boundary_pT sin1(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325) "Pressure boundary condition"
  AixLib.Fluid.DistrictHeatingCooling.Pipes.DHCPipe pip1(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    redeclare FixedResistances.BaseClasses.PlugFlowCore pipCor "PlugFlow core",
    dh=0.1,
    length=100,
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=1,
    cPip=500,
    thickness=0.0032,
    initDelay=true,
    m_flow_start=1,
    rhoPip=8000,
    use_zeta=false,
    T_start_in=323.15,
    T_start_out=323.15) "Pipe"
  Sources.MassFlowSource_T              sou1(
    nPorts=1,
    redeclare package Medium = Medium,
    use_T_in=true,
    m_flow=1) "Flow source"
  Sensors.TemperatureTwoPort              senTemOut1(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
  Sensors.TemperatureTwoPort              senTemIn1(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
  Modelica.Blocks.Sources.Pulse Tin2(
    amplitude=20,
    period=20,
    offset=273.15 + 50,
    startTime=100) "Ramp pressure signal"
  Sources.Boundary_pT sin2(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325) "Pressure boundary condition"
  AixLib.Fluid.DistrictHeatingCooling.Pipes.DHCPipe pip2(
    redeclare package Medium = Medium,
    use_soil=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    redeclare FixedResistances.BaseClasses.PlugFlowCore pipCor "PlugFlow core",
    dh=0.1,
    length=100,
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=1,
    cPip=500,
    thickness=0.0032,
    initDelay=true,
    m_flow_start=1,
    rhoPip=8000,
    use_zeta=false,
    T_start_in=323.15,
    T_start_out=323.15) "Pipe"
  Sources.MassFlowSource_T              sou2(
    nPorts=1,
    redeclare package Medium = Medium,
    use_T_in=true,
    m_flow=1) "Flow source"
  Sensors.TemperatureTwoPort              senTemOut2(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
  Sensors.TemperatureTwoPort              senTemIn2(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
  Modelica.Blocks.Sources.Pulse Tin3(
    amplitude=20,
    period=20,
    offset=273.15 + 50,
    startTime=100) "Ramp pressure signal"
  Sources.Boundary_pT sin3(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325) "Pressure boundary condition"
  AixLib.Fluid.DistrictHeatingCooling.Pipes.DHCPipe pip3(
    redeclare package Medium = Medium,
    sum_zetas=2.5,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    redeclare FixedResistances.BaseClasses.PlugFlowCore pipCor "PlugFlow core",
    dh=0.1,
    length=100,
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=1,
    cPip=500,
    thickness=0.0032,
    initDelay=true,
    m_flow_start=1,
    rhoPip=8000,
    use_zeta=true,
    T_start_in=323.15,
    T_start_out=323.15) "Pipe"
  Sources.MassFlowSource_T              sou3(
    nPorts=1,
    redeclare package Medium = Medium,
    use_T_in=true,
    m_flow=1) "Flow source"
  Sensors.TemperatureTwoPort              senTemOut3(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
  Sensors.TemperatureTwoPort              senTemIn3(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
equation
  connect(bou.port, pip.heatPort)
  connect(Tin.y, sou.T_in)
  connect(pip.port_b, senTemOut.port_a)
  connect(senTemOut.port_b, sin.ports[1])
  connect(sou.ports[1], senTemIn.port_a)
  connect(senTemIn.port_b, pip.port_a)
  connect(bou.port, pip1.heatPort)
  connect(Tin1.y, sou1.T_in)
  connect(pip1.port_b, senTemOut1.port_a)
  connect(senTemOut1.port_b, sin1.ports[1])
  connect(sou1.ports[1], senTemIn1.port_a)
  connect(senTemIn1.port_b, pip1.port_a)
  connect(bou.port, pip2.heatPort)
  connect(Tin2.y, sou2.T_in)
  connect(pip2.port_b, senTemOut2.port_a)
  connect(senTemOut2.port_b, sin2.ports[1])
  connect(sou2.ports[1], senTemIn2.port_a)
  connect(senTemIn2.port_b, pip2.port_a)
  connect(bou.port, pip3.heatPort)
  connect(Tin3.y, sou3.T_in)
  connect(pip3.port_b, senTemOut3.port_a)
  connect(senTemOut3.port_b, sin3.ports[1])
  connect(sou3.ports[1], senTemIn3.port_a)
  connect(senTemIn3.port_b, pip3.port_a)
end DHCPipe;


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


Simple example of PlugFlowPipeEmbedded

within AixLib.Fluid.DistrictHeatingCooling.Pipes.Examples;
model PlugFlowPipeEmbedded "Simple example of PlugFlowPipeEmbedded"
  extends Modelica.Icons.Example;
  replaceable package Medium = AixLib.Media.Water "Medium in the pipe"
  Modelica.Blocks.Sources.Ramp Tin(
    height=20,
    duration=0,
    offset=273.15 + 50,
    startTime=100) "Ramp pressure signal"
  Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325) "Pressure boundary condition"
  AixLib.Fluid.DistrictHeatingCooling.Pipes.PlugFlowPipeEmbedded
                                             pip(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial,
    dh=0.1,
    length=100,
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=1,
    cPip=500,
    thickness=0.0032,
    initDelay=true,
    m_flow_start=1,
    rhoPip=8000,
    use_zeta=true,
    T_start_in=323.15,
    T_start_out=323.15) "Pipe"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature bou(T=283.15)
    "Boundary temperature"
  AixLib.Fluid.Sources.MassFlowSource_T sou(
    nPorts=1,
    redeclare package Medium = Medium,
    use_T_in=true,
    m_flow=3) "Flow source"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTemOut(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTemIn(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
equation
  connect(bou.port, pip.heatPort)
  connect(Tin.y, sou.T_in)
  connect(pip.port_b, senTemOut.port_a)
  connect(senTemOut.port_b, sin.ports[1])
  connect(sou.ports[1], senTemIn.port_a)
  connect(senTemIn.port_b, pip.port_a)
end PlugFlowPipeEmbedded;


Simple example of PlugFlowPipe

within AixLib.Fluid.DistrictHeatingCooling.Pipes.Examples;
model PlugFlowPipeZeta "Simple example of PlugFlowPipe"
  extends Modelica.Icons.Example;
  replaceable package Medium = AixLib.Media.Water "Medium in the pipe"
  Modelica.Blocks.Sources.Ramp Tin(
    height=20,
    duration=0,
    offset=273.15 + 50,
    startTime=100) "Ramp pressure signal"
  Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325) "Pressure boundary condition"
  AixLib.Fluid.DistrictHeatingCooling.Pipes.PlugFlowPipeZeta pip(
    redeclare package Medium = Medium,
    dh=0.1,
    length=100,
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=1,
    cPip=500,
    thickness=0.0032,
    initDelay=true,
    m_flow_start=1,
    rhoPip=8000,
    use_zeta=true,
    T_start_in=323.15,
    T_start_out=323.15) "Pipe"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature bou(T=283.15)
    "Boundary temperature"
  AixLib.Fluid.Sources.MassFlowSource_T sou(
    nPorts=1,
    redeclare package Medium = Medium,
    use_T_in=true,
    m_flow=3) "Flow source"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTemOut(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTemIn(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
equation
  connect(bou.port, pip.heatPort)
  connect(Tin.y, sou.T_in)
  connect(pip.port_b, senTemOut.port_a)
  connect(senTemOut.port_b, sin.ports[1])
  connect(sou.ports[1], senTemIn.port_a)
  connect(senTemIn.port_b, pip.port_a)
end PlugFlowPipeZeta;


Simple example of StaticPipe

within AixLib.Fluid.DistrictHeatingCooling.Pipes.Examples;
model StaticPipe "Simple example of StaticPipe"
  extends Modelica.Icons.Example;
  replaceable package Medium = AixLib.Media.Water "Medium in the pipe"
  Modelica.Blocks.Sources.Ramp Tin(
    height=20,
    duration=0,
    offset=273.15 + 50,
    startTime=100) "Ramp pressure signal"
  Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325) "Pressure boundary condition"
  AixLib.Fluid.DistrictHeatingCooling.Pipes.StaticPipe pip(
    redeclare package Medium = Medium,
    dh=0.1,
    length=100,
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=1,
    cPip=500,
    thickness=0.0032,
    initDelay=true,
    m_flow_start=1,
    rhoPip=8000,
    use_zeta=true,
    T_start_in=323.15,
    T_start_out=323.15) "Pipe"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature bou(T=283.15)
    "Boundary temperature"
  AixLib.Fluid.Sources.MassFlowSource_T sou(
    nPorts=1,
    redeclare package Medium = Medium,
    use_T_in=true,
    m_flow=3) "Flow source"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTemOut(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTemIn(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
equation
  connect(bou.port, pip.heatPort)
  connect(Tin.y, sou.T_in)
  connect(pip.port_b, senTemOut.port_a)
  connect(senTemOut.port_b, sin.ports[1])
  connect(sou.ports[1], senTemIn.port_a)
  connect(senTemIn.port_b, pip.port_a)
end StaticPipe;


Supply node models

within AixLib.Fluid.DistrictHeatingCooling;
package Supplies "Supply node models"
end Supplies;


within AixLib.Fluid.DistrictHeatingCooling.Supplies.ClosedLoop;
model DHCSupplyHeaterCoolerStorage
  "Supply node model with ideal heater and cooler and storage tank without heat losses for heat and cold supply of bidirectional networks"

      replaceable package Medium = Modelica.Media.Interfaces.PartialMedium "Medium model for water"

  parameter Modelica.Units.SI.Pressure dp_nominal(displayUnit="Pa") = 30000
    "Nominal pressure drop";

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=m_flow_nominal
    "Nominal mass flow rate";

  parameter Modelica.Units.SI.Volume V_Tank "Volume of thermal storage tank";

  Modelica.Fluid.Interfaces.FluidPort_a port_a(redeclare package Medium =
        Medium)
     "Fluid connector for connecting the ideal plant with storage to the cold line of the network"
  Modelica.Fluid.Interfaces.FluidPort_b port_b(redeclare package Medium =
        Medium)
     "Fluid connector for connecting the ideal plant with storage to the warm line of the network"
  AixLib.Fluid.HeatExchangers.PrescribedOutlet coo(
    redeclare package Medium = Medium,
    use_X_wSet=false,
    dp_nominal=dp_nominal,
    use_TSet=true,
    m_flow_nominal=m_flow_nominal)
    "Ideal cooler (only in operation if mass flow direction is from port_b to port_a)"
  AixLib.Fluid.HeatExchangers.PrescribedOutlet hea(
    redeclare package Medium = Medium,
    use_X_wSet=false,
    dp_nominal=dp_nominal,
    m_flow_nominal=m_flow_nominal)
    "Ideal heater (only in operation if mass flow direction is from port_a to port_b)"
  AixLib.Fluid.Sensors.TemperatureTwoPort senT_cooOut(redeclare package Medium =
        Medium, m_flow_nominal=m_flow_nominal)
    "Outlet temperature of ideal cooler if mass flow direcetion is from port_b to port_a"
  Modelica.Blocks.Interfaces.RealInput T_cooSet(unit="K")
    "Maximum supply temperature of the cold line of the bidirectional low-temperature network"
  Modelica.Blocks.Interfaces.RealInput T_heaSet(unit="K")
    "Minimum supply temperature of the hot line of the bidirectional low-temperature network"
  AixLib.Fluid.Storage.Stratified    tan(
    allowFlowReversal=true,
    hTan=4,
    dIns=0.1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial,
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    nSeg=3,
    VTan=V_Tank)
  AixLib.Fluid.Sensors.TemperatureTwoPort senT_heaOut(redeclare package Medium =
        Medium, m_flow_nominal=m_flow_nominal)
    "Outlet temperature of ideal heater if mass flow direcetion is from port_a to port_b"
  AixLib.Fluid.Sensors.TemperatureTwoPort senT_stoHea(redeclare package Medium =
        Medium, m_flow_nominal=m_flow_nominal)
  AixLib.Fluid.Sensors.TemperatureTwoPort senT_stoCoo(redeclare package Medium =
        Medium, m_flow_nominal=m_flow_nominal)
  Modelica.Blocks.Math.Min min "Set temperature of ideal heater"
  Modelica.Blocks.Math.Max max "Set temperature of ideal cooler"
  Sources.Boundary_pT bou(nPorts=1, redeclare package Medium = Medium)
equation
  connect(port_b, senT_heaOut.port_a)
  connect(hea.port_b, senT_heaOut.port_b)
  connect(senT_stoHea.port_a, hea.port_a)
  connect(tan.port_a, senT_stoHea.port_b)
  connect(senT_stoCoo.T, min.u2)
  connect(max.y, hea.TSet)
  connect(senT_stoHea.T, max.u2)
  connect(tan.port_b, senT_stoCoo.port_a)
  connect(senT_stoCoo.port_b, coo.port_a)
  connect(port_a, senT_cooOut.port_b)
  connect(senT_cooOut.port_a, coo.port_b)
  connect(coo.TSet, min.y)
  connect(T_cooSet, min.u1)
  connect(T_heaSet, max.u1)
  connect(bou.ports[1], coo.port_a)
end DHCSupplyHeaterCoolerStorage;


Supply with closed loop design

within AixLib.Fluid.DistrictHeatingCooling.Supplies;
package ClosedLoop "Supply with closed loop design"
end ClosedLoop;


Fluid in the pipes

within AixLib.Fluid.DistrictHeatingCooling.Supplies.Examples;
model DHCSupplyHeaterCoolerStorage
   extends Modelica.Icons.Example;
  package Medium = AixLib.Media.Water "Fluid in the pipes";
  ClosedLoop.DHCSupplyHeaterCoolerStorage DHCSupplyHeaterCoolerStorage(
    redeclare package Medium = Medium,
    m_flow_nominal=5,
    V_Tank=500)
  Demands.ClosedLoop.DHCSubstationHeatPumpDirectCooling substation1(
                                                                   redeclare
      package                                                                        Medium =
                       Medium,
    m_flow_nominal=5,
    heaDem_max=10000,
    deltaT_heaSecSet=278.15,
    T_heaSecSet=328.15,
    T_heaPriSet=295.15,
    T_cooPriSet=289.15)
  Demands.ClosedLoop.DHCSubstationHeatPumpDirectCooling substation2(
                                                                   redeclare
      package                                                                        Medium =
                       Medium,
    m_flow_nominal=5,
    heaDem_max=10000,
    deltaT_heaSecSet=278.15,
    T_heaSecSet=328.15,
    T_heaPriSet=295.15,
    T_cooPriSet=289.15)
  AixLib.Fluid.FixedResistances.PlugFlowPipe plugFlowPipe(
    dh=0.2,
    length=5,
    m_flow_nominal=5,
    dIns=0.001,
    kIns=0.04,
    redeclare package Medium = Medium)
  AixLib.Fluid.FixedResistances.PlugFlowPipe plugFlowPipe1(
    dh=0.2,
    length=5,
    m_flow_nominal=5,
    dIns=0.001,
    kIns=0.04,
    redeclare package Medium = Medium)
  AixLib.Fluid.FixedResistances.PlugFlowPipe plugFlowPipe2(
    dh=0.2,
    length=5,
    m_flow_nominal=5,
    dIns=0.001,
    kIns=0.04,
    redeclare package Medium = Medium)
  AixLib.Fluid.FixedResistances.PlugFlowPipe plugFlowPipe3(
    dh=0.2,
    length=5,
    m_flow_nominal=5,
    dIns=0.001,
    kIns=0.04,
    redeclare package Medium = Medium)
  Modelica.Blocks.Sources.Constant T_HotLineSet(k=16 + 273.15)
  Modelica.Blocks.Sources.Constant T_ColdLineSet(k=22 + 273.15)
  Modelica.Blocks.Sources.Constant heaDem(k=10000)
  Modelica.Blocks.Sources.Step colDem(
    height=10000,
    offset=5000,
    startTime=86400)
equation

  connect(heaDem.y, substation1.heaDem);
  connect(heaDem.y, substation2.heaDem);
  connect(colDem.y, substation1.cooDem);
  connect(colDem.y, substation2.cooDem);

  connect(DHCSupplyHeaterCoolerStorage.port_b, plugFlowPipe.port_a)
  connect(T_ColdLineSet.y, DHCSupplyHeaterCoolerStorage.T_heaSet)
  connect(T_HotLineSet.y, DHCSupplyHeaterCoolerStorage.T_cooSet)
  connect(plugFlowPipe1.port_b, substation2.port_a)
  connect(plugFlowPipe2.port_a, substation2.port_b)
  connect(plugFlowPipe.port_b, plugFlowPipe1.port_a)
  connect(plugFlowPipe.port_b, substation1.port_a)
  connect(plugFlowPipe3.port_a, plugFlowPipe2.port_b)
  connect(substation1.port_b, plugFlowPipe3.port_a)
  connect(DHCSupplyHeaterCoolerStorage.port_a, plugFlowPipe3.port_b)
end DHCSupplyHeaterCoolerStorage;


  This package contains examples for the use of models that can be
  found in <a href=
  \

within AixLib.Fluid.DistrictHeatingCooling.Supplies;
package Examples
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Supplies for open loop model designs

within AixLib.Fluid.DistrictHeatingCooling.Supplies;
package OpenLoop "Supplies for open loop model designs"
end OpenLoop;


within AixLib.Fluid.DistrictHeatingCooling.Supplies.OpenLoop;
model SourceIdeal
  "Simple supply node model with ideal flow source and return port"
  extends BaseClasses.Supplies.OpenLoop.PartialSupply(senT_return(
        allowFlowReversal=true));

  parameter Modelica.Units.SI.AbsolutePressure pReturn "Fixed return pressure";

  parameter Modelica.Units.SI.Temperature TReturn "Fixed return temperature";

  AixLib.Fluid.Sources.Boundary_pT source(          redeclare package Medium =
        Medium,
    nPorts=1,
    use_T_in=true,
    use_p_in=true)
    "Ideal fluid source with prescribed temperature and pressure"

  Sources.Boundary_pT   sink(redeclare package Medium = Medium,
    p=pReturn,
    nPorts=1)
    "Ideal sink for return from the network"
  Modelica.Blocks.Interfaces.RealOutput Q_flow
equation
  Q_flow = (senT_supply.T - senT_return.T) * 4180 * senMasFlo.m_flow;
  connect(source.ports[1], senT_supply.port_a)
  connect(TIn, source.T_in)
  connect(dpIn, source.p_in)
  connect(senT_return.port_a, sink.ports[1])
end SourceIdeal;


within AixLib.Fluid;
package Examples "Example models integrating multiple components"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within AixLib.Fluid.Examples;
model ResistanceVolumeFlowReversal
  "System demonstrating impact of allowFlowReversal on number/size of non-linear systems"
  extends Modelica.Icons.Example;

  package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater;
  parameter Real m_flow_nominal=0.1 "Gain value multiplied with input signal";
  AixLib.Fluid.Sources.Boundary_pT bou(
    redeclare package Medium = Medium,
    nPorts=1) "Boundary for pressure boundary condition"
  Movers.FlowControlled_m_flow pump(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    use_inputFilter=false,
    allowFlowReversal=allowFlowReversal.k,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nominalValuesDefineDefaultPressureCurve=true)
    "Pump model with unidirectional flow"
  AixLib.Fluid.HeatExchangers.Heater_T hea(
    redeclare package Medium = Medium,
    dp_nominal=1000,
    QMax_flow=1000,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    allowFlowReversal=allowFlowReversal.k) "Heater"
  Modelica.Blocks.Sources.Pulse pulse(period=1000) "Pulse input"
  Modelica.Blocks.Math.Gain gain(k=m_flow_nominal) "Gain for m_flow_nominal"
  AixLib.Fluid.Actuators.Valves.ThreeWayLinear val(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    dpValve_nominal=1000,
    l={0.002,0.002},
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Three way valve with constant input"
  Modelica.Blocks.Sources.Constant const(k=0.5) "Constant valve set point"
  Modelica.Blocks.Sources.BooleanConstant allowFlowReversal(k=false)
    "Block for setting allowFlowReversal in components"
  AixLib.Fluid.FixedResistances.PressureDrop[nRes.k] res(
    redeclare package Medium = Medium,
    each allowFlowReversal=allowFlowReversal.k,
    each m_flow_nominal=m_flow_nominal/nRes.k,
    each dp_nominal=1000) "Fluid resistance for splitting flow"
  Modelica.Blocks.Sources.IntegerConstant nRes(k=10)
    "Number of parallel branches"
  Delays.DelayFirstOrder[nRes.k] vol(
    redeclare each package Medium = Medium,
    each m_flow_nominal=m_flow_nominal/nRes.k,
    each nPorts=2,
    each energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    each allowFlowReversal=true) "Mixing volumes for enthalpy circuit"
equation
  connect(bou.ports[1],hea. port_a)
  connect(pulse.y,hea. TSet)
  connect(pump.m_flow_in, gain.y)
  connect(gain.u,pulse. y)
  connect(hea.port_b,val. port_1)
  connect(val.port_2, pump.port_a)
  connect(const.y,val. y)
  connect(val.port_3,hea. port_a)
  for i in 1:nRes.k loop
    connect(pump.port_b, res[i].port_a)
    connect(res[i].port_b, vol[i].ports[1])
    connect(vol[i].ports[2], val.port_3)
  end for;
end ResistanceVolumeFlowReversal;


Example implementation of flow system

within AixLib.Fluid.Examples.FlowSystem;
model Basic "Example implementation of flow system"
  extends Modelica.Icons.Example;
  package Medium = AixLib.Media.Water "Medium model";
  AixLib.Fluid.Movers.FlowControlled_dp pmpSouth(
    redeclare package Medium = Medium,
    redeclare replaceable
      AixLib.Fluid.Movers.Data.Pumps.Wilo.Stratos80slash1to12 per,
    dp_nominal=12*9810,
    m_flow_nominal=27570/3600,
    inputType=AixLib.Fluid.Types.InputType.Stages,
    heads=pmpSouth.dp_nominal*{0,1},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Pump to south of building"
  AixLib.Fluid.FixedResistances.PressureDrop pipSouth1(
    redeclare package Medium = Medium,
    dp_nominal=50000,
    m_flow_nominal=4) "Pipe 1 to south of building"
  AixLib.Fluid.FixedResistances.PressureDrop pipSouth2(
    redeclare package Medium = Medium,
    dp_nominal=50000,
    m_flow_nominal=3) "Pipe 2 to south of building"
  AixLib.Fluid.Movers.FlowControlled_dp pmpNorth(
    redeclare package Medium = Medium,
    redeclare replaceable
      AixLib.Fluid.Movers.Data.Pumps.Wilo.Stratos80slash1to12 per,
    dp_nominal=12*9810,
    m_flow_nominal=24660/3600,
    inputType=AixLib.Fluid.Types.InputType.Stages,
    heads=pmpNorth.dp_nominal*{0,1},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
     "Pump to north of building"
  AixLib.Fluid.FixedResistances.PressureDrop pipNorth2(
    redeclare package Medium = Medium,
    dp_nominal=50000,
    m_flow_nominal=5) "Pipe 2 to north of building"
  AixLib.Fluid.FixedResistances.PressureDrop pipNorth1(
    redeclare package Medium = Medium,
    dp_nominal=50000,
    m_flow_nominal=3) "Pipe 1 to north of building"
  AixLib.Fluid.Actuators.Valves.TwoWayLinear[4] valSouth1(
    each dpFixed_nominal=0,
    each CvData=AixLib.Fluid.Types.CvTypes.OpPoint,
    each dpValve_nominal=8e4,
    redeclare each package Medium = Medium,
    each m_flow_nominal=1) "Valves on souther tabs section 1"
  AixLib.Fluid.Actuators.Valves.TwoWayLinear[8] valSouth2(
    each dpFixed_nominal=0,
    each CvData=AixLib.Fluid.Types.CvTypes.OpPoint,
    each dpValve_nominal=8e4,
    redeclare each package Medium = Medium,
    each m_flow_nominal=1) "Valves on souther tabs section 2"
  AixLib.Fluid.Actuators.Valves.TwoWayLinear[4] valNorth1(
    each dpFixed_nominal=0,
    each CvData=AixLib.Fluid.Types.CvTypes.OpPoint,
    each dpValve_nominal=8e4,
    redeclare each package Medium = Medium,
    each m_flow_nominal=1) "Valves on northern tabs section 1"
  AixLib.Fluid.Actuators.Valves.TwoWayLinear[8] valNorth2(
    each dpFixed_nominal=0,
    each CvData=AixLib.Fluid.Types.CvTypes.OpPoint,
    each dpValve_nominal=8e4,
    redeclare each package Medium = Medium,
    each m_flow_nominal=1) "Valves on northern tabs section 2"
  Modelica.Blocks.Math.BooleanToInteger booleanToInteger(integerTrue=2,
      integerFalse=1) "Boolean to integer conversion block"
  Modelica.Blocks.Sources.BooleanPulse stepPump(startTime=5, period=1000)
    "Step control"
  Modelica.Blocks.Sources.Sine sine(
    amplitude=0.5,
    offset=0.5,
    f=0.001) "Valve control signal"
  AixLib.Fluid.Actuators.Valves.ThreeWayLinear valSouth(
    redeclare package Medium = Medium,
    m_flow_nominal=5,
    dpFixed_nominal={20000,0},
    from_dp=true,
    dpValve_nominal=10000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Three way valve for controlling supply temperature to south of building"
  AixLib.Fluid.Actuators.Valves.ThreeWayLinear valNorth(
    redeclare package Medium = Medium,
    m_flow_nominal=5,
    dpFixed_nominal={20000,0},
    from_dp=true,
    dpValve_nominal=10000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Three way valve for controlling supply temperature to north of building"
  AixLib.Fluid.HeatExchangers.PrescribedOutlet heater(
    m_flow_nominal=10,
    dp_nominal=100,
    redeclare package Medium = Medium,
    use_X_wSet=false)                  "Heating device"
  AixLib.Fluid.Sources.Boundary_pT bou(nPorts=1,
  redeclare package Medium = Medium) "Boundary for setting absolute temperature"
  AixLib.Fluid.FixedResistances.Junction spl(
    m_flow_nominal={10,10,10},
    dp_nominal={1000,10,10},
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter"
  AixLib.Fluid.FixedResistances.Junction spl1(
    m_flow_nominal={10,10,10},
    dp_nominal={10,10,10},
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter"
  AixLib.Fluid.Movers.FlowControlled_m_flow pumpHea(
    m_flow_nominal=10,
    redeclare AixLib.Fluid.Movers.Data.Pumps.Wilo.VeroLine80slash115dash2comma2slash2 per,
    redeclare package Medium = Medium,
    inputType=AixLib.Fluid.Types.InputType.Stages,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Pump for circulating hot water"
  Modelica.Blocks.Sources.Constant Thot(k=273.15 + 50) "Hot water temperature"
  AixLib.Fluid.Actuators.Valves.TwoWayLinear valHea(
    dpFixed_nominal=0,
    CvData=AixLib.Fluid.Types.CvTypes.OpPoint,
    redeclare package Medium = Medium,
    m_flow_nominal=10,
    dpValve_nominal=1e4)
    "Valve for allowing water to be drawn from hot water circuit"
  Modelica.Blocks.Sources.Pulse stepValve(startTime=10, period=500)
    "Set point for valves"
  AixLib.Fluid.Actuators.Valves.TwoWayLinear valCoo(
    dpFixed_nominal=0,
    CvData=AixLib.Fluid.Types.CvTypes.OpPoint,
    redeclare package Medium = Medium,
    m_flow_nominal=10,
    dpValve_nominal=1e4)
    "Valve for allowing water to be drawn from cold water circuit"
  Modelica.Blocks.Sources.RealExpression valCooExp(y=1 - stepValve.y)
    "Cooling valve opens when heating valve is closed"
  AixLib.Fluid.FixedResistances.Junction spl2(
    m_flow_nominal={10,10,10},
    dp_nominal={1000,10,10},
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter"
  AixLib.Fluid.FixedResistances.Junction spl3(
    m_flow_nominal={10,10,10},
    dp_nominal={10,10,10},
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter"
  AixLib.Fluid.Movers.FlowControlled_m_flow pumpCoo(
    m_flow_nominal=10,
    redeclare AixLib.Fluid.Movers.Data.Pumps.Wilo.VeroLine80slash115dash2comma2slash2 per,
    redeclare package Medium = Medium,
    inputType=AixLib.Fluid.Types.InputType.Stages,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Pump for circulating cold water"
  AixLib.Fluid.MixingVolumes.MixingVolume vol(
    nPorts=2,
    redeclare package Medium = Medium,
    m_flow_nominal=10,
    V=1) "Simplified model of cold water source"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature Tcold(T=273.15 + 10)
    "Cold water temperature"
  AixLib.Fluid.FixedResistances.PressureDrop tabsSouth1[4](
    redeclare each package Medium = Medium,
    each dp_nominal=50000,
    m_flow_nominal=valSouth1.m_flow_nominal)
    "Pressure drop of southern tabs sections on collector 1"
  AixLib.Fluid.FixedResistances.PressureDrop tabsSouth2[8](
    redeclare each package Medium = Medium,
    each dp_nominal=50000,
    m_flow_nominal=valSouth2.m_flow_nominal)
    "Pressure drop of southern tabs sections on collector 2"
  AixLib.Fluid.FixedResistances.PressureDrop tabsNorth1[4](
    redeclare each package Medium = Medium,
    each dp_nominal=50000,
    m_flow_nominal=valNorth1.m_flow_nominal)
    "Pressure drop of northern tabs sections on collector 1"
  AixLib.Fluid.FixedResistances.PressureDrop tabsNorth2[8](
    redeclare each package Medium = Medium,
    each dp_nominal=50000,
    m_flow_nominal=valNorth2.m_flow_nominal)
    "Pressure drop of northern tabs sections on collector 2"
equation
  connect(pipSouth2.port_a, pmpSouth.port_b)
  connect(pmpSouth.port_b, pipSouth1.port_a)
  connect(pipNorth1.port_a, pmpNorth.port_b)
  connect(pmpNorth.port_b, pipNorth2.port_a)
  for i in 1:4 loop
      connect(tabsNorth1[i].port_b,valNorth. port_3)
    connect(tabsSouth1[i].port_b, valSouth.port_3)

    connect(valSouth1[i].y, sine.y)

    connect(pipSouth1.port_b, valSouth1[i].port_a)
    connect(pipNorth1.port_b, valNorth1[i].port_a)
   end for;
    for i in 1:8 loop
  connect(tabsNorth2[i].port_b,valNorth. port_3)
    connect(tabsSouth2[i].port_b, valSouth.port_3)

    connect(valSouth2[i].y, sine.y)
    connect(pipSouth2.port_b, valSouth2[i].port_a)
    connect(pipNorth2.port_b, valNorth2[i].port_a)
  end for;

  connect(pmpSouth.stage, pmpNorth.stage)
  connect(booleanToInteger.y, pmpSouth.stage)
  connect(stepPump.y, booleanToInteger.u)
  connect(valSouth1.y, valNorth1.y)
  connect(valSouth2.y,valNorth2. y)

  connect(valSouth.port_2, pmpSouth.port_a)
  connect(valNorth.port_2, pmpNorth.port_a)
  connect(valNorth.y, valSouth.y)
  connect(bou.ports[1], heater.port_a)
  connect(spl1.port_3, spl.port_3)
  connect(heater.port_b, spl.port_1)
  connect(pumpHea.port_a, spl1.port_2)
  connect(pumpHea.port_b, heater.port_a)
  connect(Thot.y, heater.TSet)
  connect(spl1.port_1, valSouth.port_3)
  connect(spl.port_2, valHea.port_a)
  connect(valHea.port_b, valSouth.port_1)
  connect(stepValve.y, valSouth.y)
  connect(stepValve.y, valHea.y)
  connect(valCooExp.y, valCoo.y)
  connect(valCoo.port_b, valSouth.port_1)
  connect(valCoo.port_b,valNorth. port_1)
  connect(spl2.port_2, valCoo.port_a)
  connect(spl3.port_1, spl1.port_1)
  connect(spl3.port_3, spl2.port_3)
  connect(spl3.port_2, pumpCoo.port_a)
  connect(vol.ports[1], pumpCoo.port_b)
  connect(vol.ports[2], spl2.port_1)
  connect(Tcold.port, vol.heatPort)
  connect(pumpHea.stage, pumpCoo.stage)
  connect(pumpHea.stage, booleanToInteger.y)
  connect(valNorth.port_3, spl3.port_1)
  connect(valSouth1.port_b, tabsSouth1.port_a)
  connect(valSouth2.port_b, tabsSouth2.port_a)
  connect(valNorth1.port_b, tabsNorth1.port_a)
  connect(valNorth2.port_b, tabsNorth2.port_a)
end Basic;


<html>
<p>
This package contains fluid flow models that demonstrate
how such models can be simplified to reduce the dimension
of systems of nonlinear equations in order
to reduce computing time.
</p>
</html>

within AixLib.Fluid.Examples;
package FlowSystem
  extends Modelica.Icons.ExamplesPackage;
end FlowSystem;


Aggregated pressure drops. The model is simplified: series pressure drop components are aggregated into the valve model.

within AixLib.Fluid.Examples.FlowSystem;
model Simplified1 "Aggregated pressure drops"
  extends Basic(
    tabsSouth1(each dp_nominal=0),
    tabsSouth2(each dp_nominal=0),
    tabsNorth1(each dp_nominal=0),
    tabsNorth2(each dp_nominal=0),
    valSouth1(each dpFixed_nominal=50000),
    valSouth2(each dpFixed_nominal=50000),
    valNorth1(each dpFixed_nominal=50000),
    valNorth2(each dpFixed_nominal=50000));
end Simplified1;


Using from_dp. The model is simplified: using from_dp to find more efficient tearing variables.

within AixLib.Fluid.Examples.FlowSystem;
model Simplified2 "Using from_dp"
  extends Simplified1(
    valSouth1(each from_dp=true),
    valSouth2(each from_dp=true),
    valNorth1(each from_dp=true),
    valNorth2(each from_dp=true));
end Simplified2;


Neglecting pressure drop in splitters. The model is further simplified by removing some small pressure drops in the bypass.
This allows the solver to identify sub-circuits.

within AixLib.Fluid.Examples.FlowSystem;
model Simplified3 "Neglecting pressure drop in splitters"
  extends Simplified2(
    spl(dp_nominal={1000,0,0}),
    spl1(dp_nominal={0,0,0}),
    spl3(dp_nominal={0,0,0}),
    spl2(dp_nominal={1000,0,0}));
end Simplified3;


Removed valve dynamics. The model is further simplified by removing the valve and pump control dynamics.

within AixLib.Fluid.Examples.FlowSystem;
model Simplified4 "Removed valve dynamics"
  extends Simplified3(
    valNorth(use_inputFilter=false),
    valSouth(use_inputFilter=false),
    pmpNorth(
      energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
      use_inputFilter=false),
    pmpSouth(
      energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
      use_inputFilter=false),
    valSouth1(each use_inputFilter=false),
    valSouth2(each use_inputFilter=false),
    valNorth1(each use_inputFilter=false),
    valNorth2(each use_inputFilter=false),
    pumpHea(use_inputFilter=false),
    pumpCoo(use_inputFilter=false),
    valCoo(use_inputFilter=false),
    valHea(use_inputFilter=false));
end Simplified4;


Removed most mass/energy dynamics. The model is further simplified by setting the mass dynamics and energy dynamics
of most models to be steady state.
Note that by default, the mass dynamics is set to the same configuration
as the energy dynamics.

within AixLib.Fluid.Examples.FlowSystem;
model Simplified5 "Removed most mass/energy dynamics"
  extends Simplified4(
    spl1(energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState),
    spl(energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState),
    spl2(energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState),
    spl3(energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState),
    pumpCoo(energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState),
    pumpHea(energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState),
    heater(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial));
end Simplified5;


Set allowFlowReversal=false. The model is further simplified by setting allowFlowReversal=false.

within AixLib.Fluid.Examples.FlowSystem;
model Simplified6 "Set allowFlowReversal=false"
  extends Simplified5(
    pmpNorth(allowFlowReversal=false),
    pmpSouth(allowFlowReversal=false),
    tabsSouth1(each allowFlowReversal=false),
    tabsSouth2(each allowFlowReversal=false),
    pipSouth1(allowFlowReversal=false),
    pipSouth2(allowFlowReversal=false),
    valSouth2(each allowFlowReversal=false),
    valSouth1(each allowFlowReversal=false),
    tabsNorth1(each allowFlowReversal=false),
    valNorth1(each allowFlowReversal=false),
    pipNorth1(allowFlowReversal=false),
    pipNorth2(allowFlowReversal=false),
    valNorth2(each allowFlowReversal=false),
    tabsNorth2(each allowFlowReversal=false),
    pumpHea(allowFlowReversal=false),
    vol(allowFlowReversal=false),
    heater(allowFlowReversal=false),
    valCoo(allowFlowReversal=false),
    valHea(allowFlowReversal=false));
end Simplified6;


within AixLib.Fluid.Examples.GeothermalHeatPump;
model GeothermalHeatPump "Example of a geothermal heat pump system"

  extends Modelica.Icons.Example;

  extends
    AixLib.Fluid.Examples.GeothermalHeatPump.BaseClasses.GeothermalHeatPumpControlledBase(
    redeclare model PeakLoadDeviceModel =
        AixLib.Fluid.Examples.GeothermalHeatPump.Components.BoilerStandAlone (
          redeclare package Medium = Medium, energyDynamics=energyDynamics));

  Sources.Boundary_pT coldConsumerFlow(redeclare package Medium = Medium,
      nPorts=1)
  Sources.Boundary_pT heatConsumerFlow(redeclare package Medium = Medium,
      nPorts=1) "Sink representing heat consumer"
  Sources.Boundary_pT heatConsumerReturn(redeclare package Medium = Medium,
      nPorts=1,
    T=303.15) "Source representing heat consumer"
  Sources.Boundary_pT coldConsumerReturn(redeclare package Medium = Medium,
      nPorts=1,
    T=287.15) "Source representing cold consumer"
  Modelica.Blocks.Sources.Constant pressureDifference(k=60000)
    "Pressure difference used for all pumps"
  Controls.HeatPump.TwoPointControlledHP
                                      twoPointControlledHP(
    use_secHeaGen=false,
    use_heaLim=false,
    T_heaLim=293.15,
    movAveTime=300,
    bandwidth=2)
    "Controls the temperature in the heat storage by switching the heat pump on or off"
  Modelica.Blocks.Sources.Constant TStorageSet(k=273.15 + 45)
    "Set point of upper heat storage temperature"
  Control.geothermalFieldController     geothermalFieldControllerCold(
      temperature_low=273.15 + 8, temperature_high=273.15 + 10)
    "Controls the heat exchange with the geothermal field and the heat storage"
  Control.geothermalFieldController     geothermalFieldControllerHeat(
      temperature_low=308.15, temperature_high=313.15)
    "Controls the heat exchange with the geothermal field and the heat storage"
  Modelica.Blocks.Sources.BooleanConstant mode "Dummy signal for unit mode, true: heat pump, false: chiller"
equation
  connect(resistanceColdConsumerFlow.port_b,coldConsumerFlow. ports[1])
  connect(pressureDifference.y, pumpColdConsumer.dp_in)
  connect(pressureDifference.y, pumpHeatConsumer.dp_in)
  connect(resistanceColdConsumerReturn.port_a,coldConsumerReturn. ports[1])
  connect(resistanceHeatConsumerReturn.port_a,heatConsumerReturn. ports[1])
  connect(pressureDifference.y, pumpEvaporator.dp_in)
  connect(pressureDifference.y, pumpCondenser.dp_in)
  connect(pumpGeothermalSource.dp_in,pressureDifference. y)
  connect(peaLoaDev.port_b,heatConsumerFlow. ports[1])
  connect(peaLoaDev.chemicalEnergyFlowRate, chemicalEnergyFlowRate)
  connect(getTStorageLower.y,geothermalFieldControllerCold. temperature)
  connect(geothermalFieldControllerCold.valveOpening1, valveColdStorage.y)
  connect(geothermalFieldControllerCold.valveOpening2, valveHeatSource.y)
  connect(getTStorageUpper.y,geothermalFieldControllerHeat. temperature)
  connect(valveHeatSink.y, geothermalFieldControllerHeat.valveOpening1)
  connect(geothermalFieldControllerHeat.valveOpening2, valveHeatStorage.y)
  connect(valveHeatStorage.port_b, heatPump.port_a1)
  connect(TStorageSet.y, twoPointControlledHP.TSet)
  connect(twoPointControlledHP.sigBusHP, heatPumpControlBus)
  connect(getTStorageUpper.y,twoPointControlledHP.TMea)
  connect(mode.y, heatPumpControlBus.hea)
  connect(heatPump.P, heatPumpPower)
  connect(twoPointControlledHP.nOut, heatPumpControlBus.ySet)
  connect(twoPointControlledHP.nOut, heatPumpControlBus.yMea)
end GeothermalHeatPump;


within AixLib.Fluid.Examples;
package GeothermalHeatPump "Contains examples of hydraulic systems based on geothermal heat pumps"
extends Modelica.Icons.ExamplesPackage;
end GeothermalHeatPump;


within AixLib.Fluid.Examples.GeothermalHeatPump.BaseClasses;
partial model GeothermalHeatPumpBase
  "Base class of the geothermal heat pump system"

  replaceable package Medium = AixLib.Media.Water
    "Medium model used for hydronic components";
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal_layer=0.5
    "Nominal mass flow rate in layers of storages";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal_HE=0.5
    "Nominal mass flow rate of heat exchanger layers of storages";
  parameter Modelica.Units.SI.Temperature T_start_cold=300
    "Initial temperature of cold components";

  parameter Modelica.Units.SI.Temperature T_start_hot=300
    "Initial temperature of warm components";

  replaceable model PeakLoadDeviceModel =
      AixLib.Fluid.Interfaces.PartialTwoPortTransport constrainedby
    AixLib.Fluid.Interfaces.PartialTwoPortTransport(redeclare package Medium=Medium)

    PeakLoadDeviceModel peaLoaDev

  Storage.StorageDetailed
                  coldStorage(
    redeclare package Medium = Medium,
    energyDynamics=energyDynamics,
    redeclare package MediumHC1 = Medium,
    redeclare package MediumHC2 = Medium,
    m1_flow_nominal=m_flow_nominal_layer,
    m2_flow_nominal=m_flow_nominal_layer,
    mHC1_flow_nominal=m_flow_nominal_HE,
    useHeatingCoil2=false,
    useHeatingRod=false,
    redeclare DataBase.Storage.Generic_New_2000l data(
      hTank=1.5,
      hUpperPortDemand=1.45,
      hUpperPortSupply=1.45,
      hHC1Up=1.45,
      dTank=1,
      sIns=0.2,
      lambdaIns=0.075,
      hTS2=1.45),
    n=5,
    hConIn=100,
    hConOut=10,
    hConHC1=500,
    upToDownHC1=false)
         "Storage tank for buffering cold demand"
  FixedResistances.PressureDrop                     resistanceColdStorage(
    redeclare package Medium = Medium,
    m_flow_nominal=0.5,
    dp_nominal=15000) "Resistance in evaporator circuit"
  AixLib.Fluid.Sources.Boundary_pT geothFieldSource(
    redeclare package Medium = Medium,
    nPorts=1,
    T=284.15) "Source representing geothermal field"
  FixedResistances.PressureDrop                     resistanceGeothermalSource(
    redeclare package Medium = Medium,
    m_flow_nominal=0.5,
    dp_nominal=15000) "Resistance in geothermal field circuit"
  FixedResistances.PressureDrop                     resistanceColdConsumerFlow(
    redeclare package Medium = Medium,
    m_flow_nominal=0.2,
    dp_nominal=10000) "Resistance in cold consumer flow line"
  Actuators.Valves.TwoWayQuickOpening valveHeatSink(
    redeclare package Medium = Medium,
    m_flow_nominal=0.5,
    dpValve_nominal=5000)
    "Valve connecting geothermal field to the condenser of the heat pump"
  Actuators.Valves.TwoWayQuickOpening
                                 valveHeatSource(redeclare package Medium =
        Medium,
    m_flow_nominal=0.5,
    dpValve_nominal=5000)
    "Valve connecting geothermal field to the evaporator of the heat pump"
  AixLib.Fluid.Storage.StorageDetailed heatStorage(
    redeclare package Medium = Medium,
    energyDynamics=energyDynamics,
    redeclare package MediumHC1 = Medium,
    redeclare package MediumHC2 = Medium,
    m1_flow_nominal=m_flow_nominal_layer,
    m2_flow_nominal=m_flow_nominal_layer,
    mHC1_flow_nominal=m_flow_nominal_HE,
    useHeatingCoil2=false,
    useHeatingRod=false,
    redeclare DataBase.Storage.Generic_New_2000l data(
      hTank=1.5,
      hUpperPortDemand=1.45,
      hUpperPortSupply=1.45,
      hHC1Up=1.45,
      dTank=1,
      sIns=0.2,
      lambdaIns=0.075,
      hTS2=1.45),
    n=5,
    hConIn=100,
    hConOut=10,
    hConHC1=500)         "Storage tank for buffering heat demand"
  AixLib.Fluid.FixedResistances.PressureDrop                     resistanceHeatStorage(
    redeclare package Medium = Medium,
    m_flow_nominal=0.5,
    dp_nominal=15000) "Resistance in condenser circuit"
  AixLib.Fluid.Sources.Boundary_pT geothField_sink1(redeclare package Medium =
        Medium, nPorts=2) "One of two sinks representing geothermal field"
  AixLib.Fluid.FixedResistances.PressureDrop resistanceHeatConsumerFlow(
    redeclare package Medium = Medium,
    m_flow_nominal=0.2,
    dp_nominal=10000) "Resistance in heat consumer flow line"
  AixLib.Fluid.Actuators.Valves.TwoWayQuickOpening valveColdStorage(
    redeclare package Medium = Medium,
    m_flow_nominal=0.5,
    dpValve_nominal=5000)
    "Valve connecting cold storage to the evaporator of the heat pump"
  AixLib.Fluid.Actuators.Valves.TwoWayQuickOpening valveHeatStorage(
    redeclare package Medium = Medium,
    m_flow_nominal=0.5,
    dpValve_nominal=5000)
    "Valve connecting heat storage to the condenser of the heat pump"

  AixLib.Fluid.Movers.FlowControlled_dp pumpColdConsumer(
    energyDynamics=energyDynamics,
    m_flow_nominal=0.05,
    redeclare package Medium = Medium,
    addPowerToMedium=false,
    T_start=T_start_cold)
    "Pump moving fluid from storage tank to cold consumers"
  AixLib.Fluid.Movers.FlowControlled_dp pumpHeatConsumer(
    energyDynamics=energyDynamics,
    m_flow_nominal=0.05,
    redeclare package Medium = Medium,
    addPowerToMedium=false,
    T_start=T_start_hot)
    "Pump moving fluid from storage tank to heat consumers"
  AixLib.Fluid.FixedResistances.PressureDrop resistanceColdConsumerReturn(
    redeclare package Medium = Medium,
    m_flow_nominal=0.2,
    dp_nominal=10000) "Resistance in cold consumer return line"
  AixLib.Fluid.FixedResistances.PressureDrop resistanceHeatConsumerReturn(
    redeclare package Medium = Medium,
    m_flow_nominal=0.2,
    dp_nominal=10000) "Resistance in heat consumer return line"
  AixLib.Fluid.Movers.FlowControlled_dp pumpCondenser(
    energyDynamics=energyDynamics,
    m_flow_nominal=0.05,
    redeclare package Medium = Medium,
    addPowerToMedium=false,
    T_start=T_start_cold)
    "Pump moving fluid from storage tank to condenser of heat pump"
  AixLib.Fluid.Movers.FlowControlled_dp pumpEvaporator(
    energyDynamics=energyDynamics,
    m_flow_nominal=0.05,
    redeclare package Medium = Medium,
    addPowerToMedium=false,
    T_start=T_start_cold)
    "Pump moving fluid from storage tank to evaporator of heat pump"
  AixLib.Fluid.Movers.FlowControlled_dp pumpGeothermalSource(
    energyDynamics=energyDynamics,
    m_flow_nominal=0.05,
    redeclare package Medium = Medium,
    addPowerToMedium=false,
    T_start=T_start_cold)
    "Pump moving fluid from geothermal source into system"
  HeatPumps.ModularReversible.BaseClasses.RefrigerantMachineControlBus
    heatPumpControlBus
  AixLib.Fluid.HeatPumps.ModularReversible.Modular heatPump(
    redeclare package MediumCon = Medium,
    redeclare package MediumEva = Medium,
    use_rev=false,
    tauCon=0.005*heatPump.rhoCon/heatPump.mCon_flow_nominal,
    dTCon_nominal=0,
    tauEva=0.005*heatPump.rhoEva/heatPump.mEva_flow_nominal,
    dpCon_nominal=0,
    use_conCap=false,
    CCon=0,
    GConOut=0,
    GConIns=0,
    dTEva_nominal=0,
    dpEva_nominal=0,
    use_evaCap=false,
    CEva=0,
    GEvaOut=0,
    GEvaIns=0,
    use_intSafCtr=false,
    energyDynamics=energyDynamics,
    QHea_flow_nominal=12740,
    redeclare model RefrigerantCycleHeatPumpHeating =
        AixLib.Fluid.HeatPumps.ModularReversible.RefrigerantCycle.TableData2D (
          redeclare
          AixLib.Fluid.HeatPumps.ModularReversible.Data.TableData2D.EN255.Vitocal350BWH110
          datTab),
    redeclare model RefrigerantCycleHeatPumpCooling =
        AixLib.Fluid.Chillers.ModularReversible.RefrigerantCycle.BaseClasses.NoCooling,
    mCon_flow_nominal=0.5,
    mEva_flow_nominal=0.5,
    TConHea_nominal=318.15,
    TEvaHea_nominal=273.15,
    TConCoo_nominal=273.15,
    TEvaCoo_nominal=273.15,
    use_busConOnl=true)

equation

  connect(resistanceGeothermalSource.port_b, valveHeatSink.port_a)
  connect(valveHeatSource.port_a, valveHeatSink.port_a)

  connect(resistanceColdStorage.port_b, valveColdStorage.port_a)
  connect(resistanceHeatStorage.port_b, valveHeatStorage.port_a)

  connect(pumpColdConsumer.port_b, resistanceColdConsumerFlow.port_a)
  connect(pumpHeatConsumer.port_b, resistanceHeatConsumerFlow.port_a)
  connect(pumpEvaporator.port_b, resistanceColdStorage.port_a)
  connect(pumpCondenser.port_b, resistanceHeatStorage.port_a)
  connect(pumpGeothermalSource.port_b, resistanceGeothermalSource.port_a)
  connect(pumpGeothermalSource.port_a, geothFieldSource.ports[1])
  connect(resistanceHeatConsumerFlow.port_b, peaLoaDev.port_a)
  connect(heatPump.port_b1, geothField_sink1.ports[1])
  connect(valveHeatStorage.port_b, heatPump.port_a1)
  connect(heatPump.port_b2, geothField_sink1.ports[2])
  connect(heatPump.port_a2, valveHeatSource.port_b)
  connect(heatPump.port_a2, valveColdStorage.port_b)
  connect(valveHeatSink.port_b, heatPump.port_a1)
  connect(heatPumpControlBus, heatPump.sigBus)
  connect(coldStorage.fluidportBottom1, pumpColdConsumer.port_a)
  connect(coldStorage.fluidportTop1, resistanceColdConsumerReturn.port_b)
  connect(pumpCondenser.port_a, heatStorage.portHC1Out)
  connect(heatPump.port_b1, heatStorage.portHC1In)
  connect(heatStorage.fluidportTop2, pumpHeatConsumer.port_a)
  connect(resistanceHeatConsumerReturn.port_b, heatStorage.fluidportBottom2)
  connect(pumpEvaporator.port_a, coldStorage.portHC1Out)
  connect(heatPump.port_b2, coldStorage.portHC1In)
end GeothermalHeatPumpBase;


Example of a geothermal heat pump system with controllers. Base class of an example demonstrating the use of a heat pump
  connected to two storages and a geothermal source. A replaceable
  model is connected in the flow line of the heating circuit. A peak
  load device can be added here. This model also includes basic
  controllers.

within AixLib.Fluid.Examples.GeothermalHeatPump.BaseClasses;
partial model GeothermalHeatPumpControlledBase
  "Example of a geothermal heat pump system with controllers"
  extends BaseClasses.GeothermalHeatPumpBase;
  Modelica.Blocks.Sources.RealExpression getTStorageUpper(y=heatStorage.layer[
        heatStorage.n].T) "Gets the temperature of upper heat storage layer"
  Modelica.Blocks.Sources.RealExpression getTStorageLower(y=coldStorage.layer[1].T)
    "Gets the temperature of lower cold storage layer"
  Modelica.Blocks.Interfaces.RealOutput coldStorageTemperature(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC",
    min=0,
    start=T_start_cold) "Temperature in the cold storage"
  Modelica.Blocks.Interfaces.RealOutput heatStorageTemperature(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC",
    min=0,
    start=T_start_hot) "Temperature in the heat storage"
  Modelica.Blocks.Interfaces.RealOutput chemicalEnergyFlowRate(final unit="W")
    "Flow of primary (chemical) energy into boiler "
  Modelica.Blocks.Interfaces.RealOutput heatPumpPower(final unit="W")
    "Electrical power of the heat pump"
  inner Modelica.Fluid.System system
equation
  connect(getTStorageLower.y, coldStorageTemperature)
  connect(getTStorageUpper.y, heatStorageTemperature)
  connect(heatPump.P, heatPumpPower)
end GeothermalHeatPumpControlledBase;


within AixLib.Fluid.Examples.GeothermalHeatPump;
package BaseClasses "Contains base classes required for the examples of geothermal heat pump systems"
extends Modelica.Icons.BasesPackage;
end BaseClasses;


Model containing the simple boiler model and the bus connector for external control. Model containing the simple boiler model AixLib.Fluid.BoilerCHP.Boiler
  and interfaces for external control.

within AixLib.Fluid.Examples.GeothermalHeatPump.Components;
model BoilerExternalControl
  "Model containing the simple boiler model and the bus connector for external control"
  extends BaseClasses.BoilerBase;
  Controls.Interfaces.BoilerControlBus boilerControlBus
equation
  connect(boiler.TAmbient, boilerControlBus.TAmbient)
  connect(boiler.switchToNightMode, boilerControlBus.switchToNightMode)
  connect(boiler.isOn, boilerControlBus.isOn)
  connect(chemicalEnergyFlowRateSource.y, boilerControlBus.chemicalEnergyFlowRate)
end BoilerExternalControl;


Model containing the simple boiler model and all required inputs as dummies. Model containing the simple boiler model AixLib.Fluid.BoilerCHP.Boiler
  and dummy inputs.

within AixLib.Fluid.Examples.GeothermalHeatPump.Components;
model BoilerStandAlone
  "Model containing the simple boiler model and all required inputs as dummies"
  extends BaseClasses.BoilerBase;
  Modelica.Blocks.Sources.BooleanConstant falseSource(k=false)
    "Outputs a false signal"
  Modelica.Blocks.Sources.Constant ambientTemperature(k=273.15 + 10)
    "Dummy for ambient temperature"
  Modelica.Blocks.Sources.BooleanConstant trueSource "Outputs a true signal"
  Modelica.Blocks.Interfaces.RealOutput chemicalEnergyFlowRate(final unit="W")
    "Flow of primary (chemical) energy into boiler "
equation
  connect(ambientTemperature.y, boiler.TAmbient)
  connect(falseSource.y, boiler.switchToNightMode)
  connect(trueSource.y, boiler.isOn)
  connect(chemicalEnergyFlowRateSource.y,chemicalEnergyFlowRate)
end BoilerStandAlone;


within AixLib.Fluid.Examples.GeothermalHeatPump;
package Components "Contains variants of the example with connectors to be used in system models."
extends Modelica.Icons.VariantsPackage;
end Components;


within AixLib.Fluid.Examples.GeothermalHeatPump.Components.BaseClasses;
partial model BoilerBase
  "Base class containing the simple boiler model as peak load device"
  extends Interfaces.PartialTwoPort;
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  BoilerCHP.Boiler boiler(
    redeclare final package Medium = Medium,
    m_flow_nominal=0.5,
    paramHC=AixLib.DataBase.Boiler.DayNightMode.HeatingCurves_Vitotronic_Day23_Night10(),
    paramBoiler=AixLib.DataBase.Boiler.General.Boiler_Vitogas200F_11kW(),
    energyDynamics=energyDynamics)
    "Peak load energy conversion unit"
  Modelica.Blocks.Sources.RealExpression chemicalEnergyFlowRateSource(
    y=boiler.internalControl.ControlerHeater.y)
    "Outputs the chemical energy flow rate of the boiler"

equation
  connect(port_a, boiler.port_a)
  connect(boiler.port_b, port_b)
end BoilerBase;


within AixLib.Fluid.Examples.GeothermalHeatPump.Components;
package BaseClasses "Contains base classes of the component models in this example"
  extends Modelica.Icons.BasesPackage;

end BaseClasses;


Controls the heat exchange with a heat or cold source by setting two valves. This is a model of a controller, which manipulates the opening of two
  valves. If the measured temperature drops below the lower thrshold,
  the first valve is fully closed and the second valve is fully opened.
  The opposite constellation applies if the temperature exceeds the
  higher threshold. To avoid zero mass flow rates, the opening is only
  close 0. Additionally, a delay can be set so that the valves do not
  react simultaneously (opened valve is closed first). It can be used
  in
  AixLib.Fluid.Examples.GeothermalHeatPump.Components.GeothermalHeatPump.

within AixLib.Fluid.Examples.GeothermalHeatPump.Control;
model geothermalFieldController
  "Controls the heat exchange with a heat or cold source by setting two valves"

  parameter Modelica.Units.SI.Temperature temperature_low=273.15 + 40
    "Lower temperature threshold for hysteresis";
  parameter Modelica.Units.SI.Temperature temperature_high=273.15 + 45
    "Upper temperature threshold for hysteresis";
  parameter Boolean warmSide=true
    "true = hysteresis with negation = for warm side";
  parameter Modelica.Units.SI.Time delayTime=10
    "Time delay between opening of valve 1 and 2";

  Modelica.Blocks.Logical.Switch switch
    "Switches between fully opened and fully closed"

  Modelica.Blocks.Nonlinear.FixedDelay fixedDelay(delayTime=delayTime)
    "Delay that prevents that both valves react simultaneously"
  Modelica.Blocks.Math.Add add(k1=-1)
    "If one valve is fully openend, the other one must be fully closed"
  Modelica.Blocks.Logical.Hysteresis hysteresis(uLow=temperature_low, uHigh=
        temperature_high) "Checks if the temperature is too high or too low"
  Modelica.Blocks.Sources.Constant approxFullyClosed(k=0.00001)
    "Used for closing a valve almost fully"
  Modelica.Blocks.Sources.Constant approxFullyOpened(k=0.99999)
    "Used for opening a valve almost fully"
  Modelica.Blocks.Interfaces.RealInput temperature(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC",
    min=0) "Temperature of the controlled flow"
  Modelica.Blocks.Interfaces.RealOutput valveOpening1(min=0, max=1)
    "Actuator position (0: closed, 1: open)"
  Modelica.Blocks.Interfaces.RealOutput valveOpening2(min=0, max=1)
    "Actuator position (0: closed, 1: open)"
  Modelica.Blocks.Logical.Switch switch1
    "Switches between delayed and direct opening"
  Modelica.Blocks.Logical.Switch switch2
    "Switches between delayed and direct opening"
  Modelica.Blocks.Nonlinear.FixedDelay fixedDelay1(
                                                  delayTime=delayTime)
    "Delay that prevents that both valves react simultaneously"
  Modelica.Blocks.Sources.Constant fullOpening(k=1)
    "Used for opening a valve fully"
equation

  connect(approxFullyOpened.y, switch.u1)
  connect(switch.y, add.u1)
  connect(hysteresis.y, switch.u2)
  connect(temperature, hysteresis.u)
  connect(switch1.y, valveOpening1)
  connect(approxFullyClosed.y, switch.u3)
  connect(switch2.y, valveOpening2)
  connect(add.y, fixedDelay.u)
  connect(hysteresis.y, switch1.u2)
  connect(hysteresis.y, switch2.u2)
  connect(fixedDelay.y, switch2.u3)
  connect(add.y, switch2.u1)
  connect(switch1.u1, fixedDelay1.y)
  connect(fixedDelay1.u, switch.y)
  connect(switch1.u3, switch.y)
  connect(fullOpening.y, add.u2)
end geothermalFieldController;


within AixLib.Fluid.Examples.GeothermalHeatPump;
package Control "Contains controllers that are specific for this example"
end Control;


Example 1 model without mixing volume. This model demonstrates the impact of the allowFlowReversal
and from_dp parameters on the sizes of nonlinear algebraic loops.
The user can change the parameter value in the respective
BooleanConstant blocks and rerun the simulation to compare the performance.
The results are also demonstrated below for nRes.k = 20,
the number of parallel branches, which contain one pressure drop element each.

within AixLib.Fluid.Examples.Performance;
model Example1v1 "Example 1 model without mixing volume"
  extends AixLib.Fluid.Examples.Performance.BaseClasses.Example1(
      allowFlowReversal(k=false), from_dp(k=true));

equation
  for i in 1:nRes.k loop
    connect(res[i].port_b, val.port_3)
  end for;

simulateModel(\"AixLib.Fluid.Examples.Performance.Example1v2(from_dp.k=true, allowFlowReversal.k=true)\", stopTime=10000, numberOfIntervals=10, method=\"dassl\", resultFile=\"Example1v2\");

simulateModel(\"AixLib.Fluid.Examples.Performance.Example1v1(allowFlowReversal.k=false, from_dp.k=false)\", stopTime=10000, numberOfIntervals=10, method=\"dassl\", resultFile=\"Example1v1\");

simulateModel(\"AixLib.Fluid.Examples.Performance.Example1v1(allowFlowReversal.k=false, from_dp.k=true)\", stopTime=10000, numberOfIntervals=10, method=\"dassl\", resultFile=\"Example1v1\");

createPlot(id=1, position={15, 10, 592, 421}, range={0.0, 10000.0, -0.01, 0.35}, autoscale=false, grid=true);

plotExpression(apply(Example1v1[end-2].CPUtime), false, \"Default case\", 1);

plotExpression(apply(Example1v2[end].CPUtime), false, \"Adding dummy states\", 1);

plotExpression(apply(Example1v1[end-1].CPUtime), false, \"allowFlowReversal=false\", 1);

plotExpression(apply(Example1v1[end].CPUtime), false, \"allowFlowReversal=false, from_dp=true\", 1);

OutputCPUtime=cpuOld;

Evaluate=evaluateOld;

See Jorissen et al. (2015) for a discussion.

References

Filip Jorissen, Michael Wetter and Lieve Helsen.

Simulation speed analysis and improvements of Modelica
models for building energy simulation.

Submitted: 11th Modelica Conference. Paris, France. Sep. 2015.

", revisions="

July 14, 2015, by Michael Wetter:

Revised documentation.

April 17, 2015, by Filip Jorissen:

First implementation.

"),
    __Dymola_Commands(file="modelica://AixLib/Resources/Scripts/Dymola/Fluid/Examples/Performance/Example1v1.mos"
        "Simulate and plot"),
   __Dymola_LockedEditing="Model from IBPSA");
end Example1v1;