within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses;
model InternalHEXTwoUTube
  "Internal heat exchanger of a borehole for a double U-tube configuration. In loop 1, fluid 1 streams from a1 to b1 and comes back from a2 to b2. In loop 2: fluid 2 streams from a3 to b3 and comes back from a4 to b4."

  extends
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.PartialInternalHEX;
  extends AixLib.Fluid.Interfaces.EightPortHeatMassExchanger(
    redeclare final package Medium1 = Medium,
    redeclare final package Medium2 = Medium,
    redeclare final package Medium3 = Medium,
    redeclare final package Medium4 = Medium,
    T1_start=TFlu_start,
    T2_start=TFlu_start,
    T3_start=TFlu_start,
    T4_start=TFlu_start,
    final tau1=VTubSeg*rho1_nominal/m1_flow_nominal,
    final tau2=VTubSeg*rho2_nominal/m2_flow_nominal,
    final tau3=VTubSeg*rho3_nominal/m3_flow_nominal,
    final tau4=VTubSeg*rho4_nominal/m4_flow_nominal,
    vol1(
      final energyDynamics=energyDynamics,
      final massDynamics=energyDynamics,
      final prescribedHeatFlowRate=false,
      final allowFlowReversal=allowFlowReversal1,
      final m_flow_small=m1_flow_small,
      final V=VTubSeg,
      final mSenFac=mSenFac),
    vol2(
      final energyDynamics=energyDynamics,
      final massDynamics=energyDynamics,
      final prescribedHeatFlowRate=false,
      final m_flow_small=m2_flow_small,
      final V=VTubSeg,
      final mSenFac=mSenFac),
    vol3(
      final energyDynamics=energyDynamics,
      final massDynamics=energyDynamics,
      final prescribedHeatFlowRate=false,
      final allowFlowReversal=allowFlowReversal3,
      final m_flow_small=m3_flow_small,
      final V=VTubSeg,
      final mSenFac=mSenFac),
    vol4(
      final energyDynamics=energyDynamics,
      final massDynamics=energyDynamics,
      final prescribedHeatFlowRate=false,
      final m_flow_small=m4_flow_small,
      final V=VTubSeg,
      final mSenFac=mSenFac));

  Modelica.Blocks.Sources.RealExpression RVol1(y=
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.convectionResistanceCircularPipe(
      hSeg=hSeg,
      rTub=borFieDat.conDat.rTub,
      eTub=borFieDat.conDat.eTub,
      kMed=kMed,
      muMed=muMed,
      cpMed=cpMed,
      m_flow=m1_flow,
      m_flow_nominal=m1_flow_nominal))
    "Convective and thermal resistance at fluid 1"
  Modelica.Blocks.Sources.RealExpression RVol2(y=
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.convectionResistanceCircularPipe(
      hSeg=hSeg,
      rTub=borFieDat.conDat.rTub,
      eTub=borFieDat.conDat.eTub,
      kMed=kMed,
      muMed=muMed,
      cpMed=cpMed,
      m_flow=m2_flow,
      m_flow_nominal=m2_flow_nominal))
    "Convective and thermal resistance at fluid 2"
  Modelica.Blocks.Sources.RealExpression RVol3(y=
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.convectionResistanceCircularPipe(
      hSeg=hSeg,
      rTub=borFieDat.conDat.rTub,
      eTub=borFieDat.conDat.eTub,
      kMed=kMed,
      muMed=muMed,
      cpMed=cpMed,
      m_flow=m3_flow,
      m_flow_nominal=m3_flow_nominal))
    "Convective and thermal resistance at fluid 1"

  Modelica.Blocks.Sources.RealExpression RVol4(y=
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.convectionResistanceCircularPipe(
      hSeg=hSeg,
      rTub=borFieDat.conDat.rTub,
      eTub=borFieDat.conDat.eTub,
      kMed=kMed,
      muMed=muMed,
      cpMed=cpMed,
      m_flow=m1_flow,
      m_flow_nominal=m4_flow_nominal))
    "Convective and thermal resistance at fluid 1"
  AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.InternalResistancesTwoUTube intRes2UTub(
    hSeg=hSeg,
    borFieDat=borFieDat,
    Rgb_val=Rgb_val,
    Rgg1_val=Rgg1_val,
    Rgg2_val=Rgg2_val,
    RCondGro_val=RCondGro_val,
    energyDynamics=energyDynamics,
    T_start=TGro_start)
                   "Internal resistances for a double U-tube configuration"
  Modelica.Thermal.HeatTransfer.Components.ConvectiveResistor RConv1
    "Pipe convective resistance"

  Modelica.Thermal.HeatTransfer.Components.ConvectiveResistor RConv2
    "Pipe convective resistance"
  Modelica.Thermal.HeatTransfer.Components.ConvectiveResistor RConv3
    "Pipe convective resistance"
  Modelica.Thermal.HeatTransfer.Components.ConvectiveResistor RConv4
    "Pipe convective resistance"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_wall

protected
  parameter Real Rgg1_val(fixed=false);
  parameter Real Rgg2_val(fixed=false);

initial equation
  (x,Rgb_val,Rgg1_val,Rgg2_val,RCondGro_val) =
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.internalResistancesTwoUTube(
      hSeg=hSeg,
      rBor=borFieDat.conDat.rBor,
      rTub=borFieDat.conDat.rTub,
      eTub=borFieDat.conDat.eTub,
      sha=borFieDat.conDat.xC,
      kFil=borFieDat.filDat.kFil,
      kSoi=borFieDat.soiDat.kSoi,
      kTub=borFieDat.conDat.kTub,
      use_Rb=borFieDat.conDat.use_Rb,
      Rb=borFieDat.conDat.Rb,
      kMed=kMed,
      muMed=muMed,
      cpMed=cpMed,
      m_flow_nominal=m1_flow_nominal,
      instanceName=getInstanceName());

equation
  assert(borFieDat.conDat.borCon == AixLib.Fluid.Geothermal.Borefields.Types.BoreholeConfiguration.DoubleUTubeParallel
     or borFieDat.conDat.borCon == AixLib.Fluid.Geothermal.Borefields.Types.BoreholeConfiguration.DoubleUTubeSeries,
    "This model should be used for double U-type borefield, not single U-type.
  Check that the conDat record has been correctly parametrized");
  connect(RVol1.y, RConv1.Rc)

  connect(RConv1.fluid, vol1.heatPort)

  connect(RConv1.solid, intRes2UTub.port_1)
  connect(RConv2.fluid, vol2.heatPort)
  connect(RConv2.solid, intRes2UTub.port_2)
  connect(RConv3.fluid, vol3.heatPort)
  connect(RConv3.solid, intRes2UTub.port_3)
  connect(RConv4.fluid, vol4.heatPort)
  connect(RConv4.solid, intRes2UTub.port_4)
  connect(RVol4.y, RConv4.Rc)
  connect(RVol3.y, RConv3.Rc)
  connect(RVol2.y, RConv2.Rc)
  connect(intRes2UTub.port_wall, port_wall)
end InternalHEXTwoUTube;


Internal resistance model for single U-tube borehole segments.. This model simulates the internal thermal resistance network of a borehole segment in
the case of a single U-tube borehole using the method of Bauer et al. (2011)
and computing explicitely the fluid-to-ground thermal resistance
Rb and the
grout-to-grout resistance
Ra as defined by Claesson and Hellstrom (2011)
using the multipole method.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses;
model InternalResistancesOneUTube
  "Internal resistance model for single U-tube borehole segments."
  extends
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.PartialInternalResistances;

  parameter Modelica.Units.SI.ThermalResistance Rgg_val
    "Thermal resistance between the two grout zones";
  parameter Modelica.Units.SI.HeatCapacity Co_fil=borFieDat.filDat.dFil*
      borFieDat.filDat.cFil*hSeg*Modelica.Constants.pi*(borFieDat.conDat.rBor^2
       - 2*borFieDat.conDat.rTub^2)
    "Heat capacity of the whole filling material";

  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rpg1(R=RCondGro_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgb1(R=Rgb_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor capFil1(
    C=Co_fil/2,
    T(start=T_start, fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.FixedInitial)),
    der_T(fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyStateInitial)))
    if not borFieDat.filDat.steadyState
    "Heat capacity of the filling material"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor capFil2(
    C=Co_fil/2,
    T(start=T_start, fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.FixedInitial)),
    der_T(fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyStateInitial)))
    if not borFieDat.filDat.steadyState
    "Heat capacity of the filling material"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgg(R=Rgg_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rpg2(R=RCondGro_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgb2(R=Rgb_val)
    "Grout thermal resistance"

equation
  connect(port_1, Rpg1.port_a)
  connect(Rpg1.port_b, Rgb1.port_a)
  connect(Rgb1.port_b, port_wall)
  connect(capFil1.port, Rgb1.port_a)
  connect(Rgg.port_a, Rgb1.port_a)
  connect(port_2, Rpg2.port_b)
  connect(Rgg.port_b, Rpg2.port_a)
  connect(Rgb2.port_b, Rpg2.port_a)
  connect(Rgb2.port_a, port_wall)
  connect(capFil2.port, Rgg.port_b)
end InternalResistancesOneUTube;


Internal resistance model for double U-tube borehole segments.. This model simulates the internal thermal resistance network of a borehole segment in
the case of a double U-tube borehole using the method of Bauer et al. (2011)
and computing explicitely the fluid-to-ground thermal resistance
Rb and the
grout-to-grout resistance
Ra as defined by Claesson and Hellstrom (2011)
using the multipole method.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses;
model InternalResistancesTwoUTube
  "Internal resistance model for double U-tube borehole segments."
  extends
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.PartialInternalResistances;

  parameter Modelica.Units.SI.ThermalResistance Rgg1_val
    "Thermal resistance between two neightbouring grout capacities, as defined by Bauer et al (2010)";
  parameter Modelica.Units.SI.ThermalResistance Rgg2_val
    "Thermal resistance between two  grout capacities opposite to each other, as defined by Bauer et al (2010)";
  parameter Modelica.Units.SI.HeatCapacity Co_fil=
     if borFieDat.filDat.steadyState then 0
     else borFieDat.filDat.dFil*borFieDat.filDat.cFil*hSeg*Modelica.Constants.pi*
          (borFieDat.conDat.rBor^2 - 4*borFieDat.conDat.rTub^2)
    "Heat capacity of the whole filling material";

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_3
    "Thermal connection for borehole wall"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_4
    "Thermal connection for borehole wall"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rpg1(R=RCondGro_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgb1(R=Rgb_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgg14(R=Rgg1_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgg21(R=Rgg2_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgg11(R=Rgg1_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rpg2(R=RCondGro_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgg12(R=Rgg1_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgb2(R=Rgb_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgb3(R=Rgb_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgb4(R=Rgb_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rpg4(R=RCondGro_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgg13(R=Rgg2_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rpg3(R=RCondGro_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor Rgg22(R=Rgg1_val)
    "Grout thermal resistance"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor capFil1(T(start=
          T_start, fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.FixedInitial)),
      der_T(fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyStateInitial)),
    C=Co_fil/4)  if not borFieDat.filDat.steadyState "Heat capacity of the filling material"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor capFil2(T(start=
          T_start, fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.FixedInitial)),
      der_T(fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyStateInitial)),
    C=Co_fil/4)  if not borFieDat.filDat.steadyState "Heat capacity of the filling material"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor capFil3(T(start=
          T_start, fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.FixedInitial)),
      der_T(fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyStateInitial)),
    C=Co_fil/4)  if not borFieDat.filDat.steadyState "Heat capacity of the filling material"
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor capFil4(T(start=
          T_start, fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.FixedInitial)),
      der_T(fixed=(energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyStateInitial)),
    C=Co_fil/4)  if not borFieDat.filDat.steadyState "Heat capacity of the filling material"
equation
  connect(Rpg1.port_a, port_1)
  connect(Rpg1.port_b, Rgb1.port_a)
  connect(Rgb1.port_b, port_wall)
  connect(port_wall, Rgb3.port_b)
  connect(Rpg3.port_a, port_3)
  connect(Rpg2.port_a, port_2)
  connect(Rgb2.port_a, Rpg2.port_b)
  connect(port_wall, Rgb2.port_b)
  connect(port_wall, Rgb4.port_b)
  connect(Rgb4.port_a, Rpg4.port_b)
  connect(Rpg4.port_a, port_4)
  connect(Rgg14.port_b, Rpg4.port_b)
  connect(Rgg13.port_a, Rpg4.port_b)
  connect(Rgg13.port_b, Rpg3.port_b)
  connect(Rgg13.port_b, Rgb3.port_a)
  connect(Rgg13.port_b, Rgg11.port_b)
  connect(Rgg13.port_b, Rgg12.port_b)
  connect(Rgb2.port_a, Rgg12.port_a)
  connect(Rgg21.port_a, Rpg2.port_b)
  connect(Rpg1.port_b, Rgg11.port_a)
  connect(Rpg1.port_b, Rgg21.port_b)
  connect(Rgg14.port_a, Rgb1.port_a)
  connect(Rgg22.port_a, Rpg4.port_b)
  connect(Rgg22.port_b, Rpg2.port_b)
  connect(capFil1.port, Rgb1.port_a)
  connect(capFil2.port, Rpg2.port_b)
  connect(capFil3.port, Rpg3.port_b)
  connect(capFil4.port, Rpg4.port_b)
end InternalResistancesTwoUTube;


Base classes for Borehole

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes;
package BaseClasses "Base classes for Borehole"
extends Modelica.Icons.BasesPackage;
end BaseClasses;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses;
partial model PartialBorehole
  "Partial model to implement multi-segment boreholes"
  extends AixLib.Fluid.Interfaces.PartialTwoPortInterface;

  extends AixLib.Fluid.Interfaces.TwoPortFlowResistanceParameters(
    computeFlowResistance=dp_nominal > Modelica.Constants.eps);

  replaceable package Medium =
    Modelica.Media.Interfaces.PartialMedium "Medium in the component"

  constant Real mSenFac(min=1)=1
   "Factor for scaling the sensible thermal mass of the volume";

  parameter Integer nSeg(min=1) = 10
    "Number of segments to use in vertical discretization of the boreholes";
  parameter Modelica.Units.SI.Temperature TGro_start[nSeg]
    "Start value of grout temperature"

  parameter Modelica.Units.SI.Temperature TFlu_start[nSeg]=TGro_start
    "Start value of fluid temperature"

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

  // Initialization
  parameter Medium.AbsolutePressure p_start = Medium.p_default
    "Start value of pressure"

  parameter Data.Borefield.Template borFieDat "Borefield parameters"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_wall[nSeg]
    "Thermal connection for borehole wall"
end PartialBorehole;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses;
partial model PartialInternalHEX
  "Partial model to implement the internal heat exchanger of a borehole segment"
  parameter AixLib.Fluid.Geothermal.Borefields.Data.Borefield.Template
    borFieDat "Borefield parameters"
  replaceable package Medium =
    Modelica.Media.Interfaces.PartialMedium "Medium"
  constant Real mSenFac=1
    "Factor for scaling the sensible thermal mass of the volume";

  parameter Modelica.Units.SI.Length hSeg
    "Length of the internal heat exchanger";
  parameter Modelica.Units.SI.Volume VTubSeg=hSeg*Modelica.Constants.pi*(
      borFieDat.conDat.rTub - borFieDat.conDat.eTub)^2
    "Fluid volume in each tube";
  parameter Modelica.Units.SI.Temperature TFlu_start
    "Start value of fluid temperature"
  parameter Modelica.Units.SI.Temperature TGro_start
    "Start value of grout temperature"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_wall
    "Thermal connection for borehole wall"
protected
  parameter Modelica.Units.SI.SpecificHeatCapacity cpMed=
      Medium.specificHeatCapacityCp(Medium.setState_pTX(
      Medium.p_default,
      Medium.T_default,
      Medium.X_default)) "Specific heat capacity of the fluid";
  parameter Modelica.Units.SI.ThermalConductivity kMed=
      Medium.thermalConductivity(Medium.setState_pTX(
      Medium.p_default,
      Medium.T_default,
      Medium.X_default)) "Thermal conductivity of the fluid";
  parameter Modelica.Units.SI.DynamicViscosity muMed=Medium.dynamicViscosity(
      Medium.setState_pTX(
      Medium.p_default,
      Medium.T_default,
      Medium.X_default)) "Dynamic viscosity of the fluid";
  parameter Real Rgb_val(fixed=false)
    "Thermal resistance between grout zone and borehole wall";
  parameter Real RCondGro_val(fixed=false)
    "Thermal resistance between: pipe wall to capacity in grout";
  parameter Real x(fixed=false) "Capacity location";
initial equation
  assert(borFieDat.conDat.rBor > borFieDat.conDat.xC + borFieDat.conDat.rTub and
         0 < borFieDat.conDat.xC - borFieDat.conDat.rTub,
         "The borehole geometry is not physical. Check the borefield data record
         to ensure that the shank spacing is larger than the outer tube radius
         and that the borehole radius is sufficiently large.");
end PartialInternalHEX;


Partial model to implement borehole segment internal resistance models. Partial model to implement the inner resistance network of a borehole segment.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses;
partial model PartialInternalResistances
  "Partial model to implement borehole segment internal resistance models"
  parameter Modelica.Units.SI.Length hSeg
    "Length of the internal heat exchanger";
  parameter Modelica.Units.SI.Temperature T_start
    "Initial temperature of the filling material";
  parameter Data.Borefield.Template borFieDat "Borefield data"
  parameter Modelica.Units.SI.ThermalResistance Rgb_val
    "Thermal resistance between grout zone and borehole wall";
  parameter Modelica.Units.SI.ThermalResistance RCondGro_val
    "Thermal resistance between: pipe wall to capacity in grout";
  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 port_1
    "Thermal connection for pipe 1"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_wall
    "Thermal connection for pipe 2"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_2
    "Thermal connection for borehole wall"
end PartialInternalResistances;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Examples;
model InternalHEXOneUTube
  "Comparison of the effective borehole thermal resistance  from the thermal network of Bauer et al. with the resistance calculated by singleUTubeResistances (ref)"
  extends Modelica.Icons.Example;

  parameter Integer nSeg(min=1) = 10
    "Number of segments to use in vertical discretization of the boreholes";
  parameter Modelica.Units.SI.Length hSeg=borFieDat.conDat.hBor/nSeg
    "Length of the internal heat exchanger";

  package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater;
  AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.InternalHEXOneUTube
    intHex(
    redeclare package Medium = Medium,
    hSeg=hSeg,
    dp1_nominal=10,
    dp2_nominal=10,
    borFieDat=borFieDat,
    m1_flow_nominal=borFieDat.conDat.mBor_flow_nominal,
    m2_flow_nominal=borFieDat.conDat.mBor_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    TFlu_start=285.15,
    TGro_start=285.15)

  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature fixedTemperature(T=273.15
         + 12)
  AixLib.Fluid.Sources.MassFlowSource_T boundary(nPorts=1,
    redeclare package Medium = Medium,
    m_flow=borFieDat.conDat.mBor_flow_nominal,
    T=293.15)
  AixLib.Fluid.Sources.MassFlowSource_T boundary1(nPorts=1,
    redeclare package Medium = Medium,
    m_flow=borFieDat.conDat.mBor_flow_nominal,
    T=293.15)
  AixLib.Fluid.Sources.Boundary_pT bou(nPorts=2, redeclare package Medium = Medium)
  Real Rb_sim(unit="(m.K)/W") = ((senTem.T + senTem1.T)/2 - intHex.port_wall.T)/max(-intHex.port_wall.Q_flow / hSeg,1);
  AixLib.Fluid.Sensors.TemperatureTwoPort senTem(redeclare package Medium =
        Medium, m_flow_nominal=borFieDat.conDat.mBor_flow_nominal)
  AixLib.Fluid.Sensors.TemperatureTwoPort senTem1(redeclare package Medium =
        Medium, m_flow_nominal=borFieDat.conDat.mBor_flow_nominal)
  Modelica.Blocks.Sources.RealExpression realExpression(y=Rb_sim)
  Modelica.Blocks.Sources.Constant Rb_ref(k=0.082399)
  Modelica.Blocks.Math.Add error(k2=-1)
  parameter AixLib.Fluid.Geothermal.Borefields.Data.Borefield.Example
    borFieDat(conDat=
        AixLib.Fluid.Geothermal.Borefields.Data.Configuration.Example(
        use_Rb=false))
    "Borefield data"
equation

  connect(boundary1.ports[1], intHex.port_a2)
  connect(boundary.ports[1], intHex.port_a1)
  connect(bou.ports[1], senTem.port_b)
  connect(senTem.port_a, intHex.port_b1)
  connect(senTem1.port_a, bou.ports[2])
  connect(senTem1.port_b, intHex.port_b2)
  connect(realExpression.y, error.u1)
  connect(Rb_ref.y, error.u2)
  connect(fixedTemperature.port, intHex.port_wall)
end InternalHEXOneUTube;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Examples;
model InternalHEXTwoUTube
  "Comparison of the effective borehole thermal resistance from the thermal network of Bauer et al. with the resistance calculated by doubleUTubeResistances (ref)"
  extends Modelica.Icons.Example;

  parameter Integer nSeg(min=1) = 10
    "Number of segments to use in vertical discretization of the boreholes";
  parameter Modelica.Units.SI.Length hSeg=borFieDat.conDat.hBor/nSeg
    "Length of the internal heat exchanger";

  package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater;
  AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.InternalHEXTwoUTube
    intHex(
    TFlu_start(displayUnit="K") = 285.15,
    redeclare package Medium = Medium,
    hSeg=hSeg,
    dp1_nominal=10,
    dp2_nominal=10,
    dp3_nominal=10,
    dp4_nominal=10,
    borFieDat=borFieDat,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    TGro_start(displayUnit="K") = 285.15,
    m1_flow_nominal=borFieDat.conDat.mBor_flow_nominal/2,
    m2_flow_nominal=borFieDat.conDat.mBor_flow_nominal/2,
    m3_flow_nominal=borFieDat.conDat.mBor_flow_nominal/2,
    m4_flow_nominal=borFieDat.conDat.mBor_flow_nominal/2)

  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature fixedTemperature(T=273.15
         + 12)
  AixLib.Fluid.Sources.MassFlowSource_T boundary(nPorts=2,
    redeclare package Medium = Medium,
    m_flow=borFieDat.conDat.mBor_flow_nominal,
    T=293.15)
  AixLib.Fluid.Sources.MassFlowSource_T boundary1(nPorts=2,
    redeclare package Medium = Medium,
    m_flow=borFieDat.conDat.mBor_flow_nominal,
    T=288.15)
  AixLib.Fluid.Sources.Boundary_pT bou(nPorts=4, redeclare package Medium = Medium)
  Real Rb_sim(unit="(m.K)/W") = ((senTem.T + senTem1.T + senTem2.T + senTem3.T)/4 - intHex.port_wall.T)/max(-intHex.port_wall.Q_flow / hSeg,1);
  AixLib.Fluid.Sensors.TemperatureTwoPort senTem(redeclare package Medium =
        Medium, m_flow_nominal=borFieDat.conDat.mBor_flow_nominal)
  AixLib.Fluid.Sensors.TemperatureTwoPort senTem1(redeclare package Medium =
        Medium, m_flow_nominal=borFieDat.conDat.mBor_flow_nominal)
  Modelica.Blocks.Sources.RealExpression realExpression(y=Rb_sim)
  Modelica.Blocks.Sources.Constant Rb_ref(k=0.0443802)
  Modelica.Blocks.Math.Add error(k2=-1)
  AixLib.Fluid.Sensors.TemperatureTwoPort senTem2(redeclare package Medium =
        Medium, m_flow_nominal=borFieDat.conDat.mBor_flow_nominal)
  AixLib.Fluid.Sensors.TemperatureTwoPort senTem3(redeclare package Medium =
        Medium, m_flow_nominal=borFieDat.conDat.mBor_flow_nominal)
  parameter AixLib.Fluid.Geothermal.Borefields.Data.Borefield.Example
    borFieDat(conDat=
        AixLib.Fluid.Geothermal.Borefields.Data.Configuration.Example(
        borCon=AixLib.Fluid.Geothermal.Borefields.Types.BoreholeConfiguration.DoubleUTubeParallel,
        use_Rb=false))
    "Borefield data"
equation

  connect(fixedTemperature.port, intHex.port_wall)
  connect(boundary.ports[1], intHex.port_a1)
  connect(bou.ports[1], senTem.port_b)
  connect(senTem.port_a, intHex.port_b1)
  connect(realExpression.y, error.u1)
  connect(Rb_ref.y, error.u2)

  connect(boundary.ports[2], intHex.port_a3)
  connect(boundary1.ports[1], intHex.port_a4)
  connect(boundary1.ports[2], intHex.port_a2)
  connect(intHex.port_b2, senTem1.port_a)
  connect(senTem1.port_b, bou.ports[2])
  connect(intHex.port_b4, senTem2.port_a)
  connect(senTem2.port_b, bou.ports[3])
  connect(intHex.port_b3, senTem3.port_a)
  connect(senTem3.port_b, bou.ports[4])
end InternalHEXTwoUTube;


Validation of InternalResistancesOneUTube.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Examples;
model InternalResistancesOneUTube "Validation of InternalResistancesOneUTube"
  extends Modelica.Icons.Example;

  parameter Integer nSeg(min=1) = 10
    "Number of segments to use in vertical discretization of the boreholes";
  parameter Modelica.Units.SI.Length hSeg=borFieDat.conDat.hBor/nSeg
    "Length of the internal heat exchanger";
  parameter Modelica.Units.SI.ThermalResistance Rgb_val=0.0430511
    "Grout node to borehole wall thermal resistance";
  parameter Modelica.Units.SI.ThermalResistance Rgg_val=0.00605573
    "Grout node to grout node thermal resistance";
  parameter Modelica.Units.SI.ThermalResistance RCondGro_val=0.14285
    "Pipe to grout node thermal resistance";
  parameter Modelica.Units.SI.Temperature T_start=298.15 "Initial temperature";

  AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.InternalResistancesOneUTube
    intRes1UTub(
    hSeg=hSeg,
    T_start=T_start,
    borFieDat=borFieDat,
    Rgb_val=Rgb_val,
    RCondGro_val=RCondGro_val,
    Rgg_val=Rgg_val,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
                     "Thermal resistance and capacitances of the borehole"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TWal(T=T_start)
    "Borehole wall temperature"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TPip2(T=T_start + 15)
    "Wall temperature of pipe 2"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature TPip1
    "Wall temperature of pipe 1"
  Modelica.Blocks.Sources.Ramp T_ramp(
    height=20,
    duration=600,
    offset=T_start)
                   "Temperature ramp of pipe 1"
  parameter AixLib.Fluid.Geothermal.Borefields.Data.Borefield.Example
    borFieDat(conDat=
        AixLib.Fluid.Geothermal.Borefields.Data.Configuration.Example(
        use_Rb=false))
    "Borefield data"
equation

  connect(TWal.port, intRes1UTub.port_wall)
  connect(TPip2.port, intRes1UTub.port_2)
  connect(TPip1.port, intRes1UTub.port_1)
  connect(T_ramp.y, TPip1.T)
end InternalResistancesOneUTube;


Validation of InternalResistancesTwoUTube.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Examples;
model InternalResistancesTwoUTube "Validation of InternalResistancesTwoUTube"
  extends Modelica.Icons.Example;

  parameter Integer nSeg(min=1) = 10
    "Number of segments to use in vertical discretization of the boreholes";
  parameter Modelica.Units.SI.Length hSeg=borFieDat.conDat.hBor/nSeg
    "Length of the internal heat exchanger";
  parameter Modelica.Units.SI.ThermalResistance Rgb_val=0.572601
    "Grout node to borehole wall thermal resistance";
  parameter Modelica.Units.SI.ThermalResistance Rgg1_val=0.0406121
    "Grout node to grout node thermal resistance";
  parameter Modelica.Units.SI.ThermalResistance Rgg2_val=0.216904
    "Thermal resistance between two grout nodes opposite to each other";
  parameter Modelica.Units.SI.ThermalResistance RCondGro_val=0.195099
    "Pipe to grout node thermal resistance";
  parameter Modelica.Units.SI.Temperature T_start=298.15 "Initial temperature";

  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TWal(T=T_start)
    "Borehole wall temperature"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TPip2(T=T_start + 15)
    "Wall temperature of pipe 2"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature TPip1
    "Wall temperature of pipe 1"
  Modelica.Blocks.Sources.Ramp T_ramp(
    height=20,
    duration=600,
    offset=T_start)
                   "Temperature ramp of pipe 1"
  parameter AixLib.Fluid.Geothermal.Borefields.Data.Borefield.Example
    borFieDat(conDat=
        AixLib.Fluid.Geothermal.Borefields.Data.Configuration.Example(
        borCon=AixLib.Fluid.Geothermal.Borefields.Types.BoreholeConfiguration.DoubleUTubeParallel,
        use_Rb=false))
    "Borefield data"
  AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.InternalResistancesTwoUTube
    intRes2UTub(
    hSeg=hSeg,
    T_start=T_start,
    borFieDat=borFieDat,
    Rgb_val=Rgb_val,
    RCondGro_val=RCondGro_val,
    Rgg1_val=Rgg1_val,
    Rgg2_val=Rgg2_val,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
                       "Thermal resistance and capacitances of the borehole"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TPip3(T=T_start + 25)
    "Wall temperature of pipe 2"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TPip4(T=T_start + 10)
    "Wall temperature of pipe 2"
equation

  connect(T_ramp.y,TPip1. T)
  connect(TPip1.port, intRes2UTub.port_1)
  connect(TPip2.port, intRes2UTub.port_2)
  connect(TWal.port, intRes2UTub.port_wall)
  connect(TPip4.port, intRes2UTub.port_4)
  connect(TPip3.port, intRes2UTub.port_3)
end InternalResistancesTwoUTube;


Example models to test base classes

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses;
package Examples "Example models to test base classes"
extends Modelica.Icons.ExamplesPackage;
end Examples;


Thermal resistance from the fluid in pipes and the grout zones (Bauer et al. 2011). This model computes the convection resistance in the pipes of a borehole segment
with heigth hSeg using correlations suggested by Bergman et al. (2011).

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions;
function convectionResistanceCircularPipe
  "Thermal resistance from the fluid in pipes and the grout zones (Bauer et al. 2011)"
  extends Modelica.Icons.Function;

  // Geometry of the borehole
  input Modelica.Units.SI.Height hSeg "Height of the element";
  input Modelica.Units.SI.Radius rTub "Tube radius";
  input Modelica.Units.SI.Length eTub "Tube thickness";
  // thermal properties
  input Modelica.Units.SI.ThermalConductivity kMed
    "Thermal conductivity of the fluid";
  input Modelica.Units.SI.DynamicViscosity muMed
    "Dynamic viscosity of the fluid";
  input Modelica.Units.SI.SpecificHeatCapacity cpMed
    "Specific heat capacity of the fluid";
  input Modelica.Units.SI.MassFlowRate m_flow "Mass flow rate";
  input Modelica.Units.SI.MassFlowRate m_flow_nominal "Nominal mass flow rate";

  // Outputs
  output Modelica.Units.SI.ThermalResistance RFluPip
    "Convection resistance (or conduction in fluid if no mass flow)";

protected
  Modelica.Units.SI.Radius rTub_in=rTub - eTub "Pipe inner radius";
  Modelica.Units.SI.CoefficientOfHeatTransfer h
    "Convective heat transfer coefficient of the fluid";

  Real k(unit="s/kg")
    "Coefficient used in the computation of the convective heat transfer coefficient";
  Modelica.Units.SI.MassFlowRate m_flow_abs=
      AixLib.Utilities.Math.Functions.spliceFunction(
      m_flow,
      -m_flow,
      m_flow,
      m_flow_nominal/30);
  Real Re "Reynolds number";
  Real NuTurb "Nusselt at Re=2400";
  Real Nu "Nusselt";

algorithm
  // Convection resistance and Reynolds number
  k := 2/(muMed*Modelica.Constants.pi*rTub_in);
  Re := m_flow_abs*k;

  if Re>=2400 then
    // Turbulent, fully-developped flow in a smooth circular pipe with the
    // Dittus-Boelter correlation: h = 0.023*k_f*Re*Pr/(2*rTub)
    // Re = rho*v*DTub / mue_f
    //    = m_flow/(pi r^2) * DTub/mue_f = 2*m_flow / ( mue*pi*rTub)
    Nu := 0.023*(cpMed*muMed/kMed)^(0.35)*
      AixLib.Utilities.Math.Functions.regNonZeroPower(
        x=Re,
        n=0.8,
        delta=0.01*m_flow_nominal*k);
  else
    // Laminar, fully-developped flow in a smooth circular pipe with uniform
    // imposed temperature: Nu=3.66 for Re<=2300. For 2300<Re<2400, a smooth
    // transition is created with the splice function.
    NuTurb := 0.023*(cpMed*muMed/kMed)^(0.35)*(2400)^(0.8);
    Nu := AixLib.Utilities.Math.Functions.spliceFunction(NuTurb,3.66,Re-(2300+2400)/2,((2300+2400)/2)-2300);
  end if;
  h := Nu*kMed/(2*rTub_in);

  RFluPip := 1/(2*Modelica.Constants.pi*rTub_in*hSeg*h);
end convectionResistanceCircularPipe;


Thermal resistances for single U-tube, according to Bauer et al. (2011). This model computes the different thermal resistances present in a single-U-tube borehole
using the method of Bauer et al. (2011).
It also computes the fluid-to-ground thermal resistance Rb
and the grout-to-grout thermal resistance Ra
as defined by Claesson and Hellstrom (2011) using the multipole method.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions;
function internalResistancesOneUTube
  "Thermal resistances for single U-tube, according to Bauer et al. (2011)"
  extends
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.partialInternalResistances;

  // Outputs
  output Modelica.Units.SI.ThermalResistance Rgb
    "Thermal resistance between grout zone and borehole wall";
  output Modelica.Units.SI.ThermalResistance Rgg
    "Thermal resistance between the two grout zones";
  output Modelica.Units.SI.ThermalResistance RCondGro
    "Thermal resistance between: pipe wall to capacity in grout";
protected
  Real[2,2] RDelta(each unit="(m.K)/W") "Delta-circuit thermal resistances";
  Real[2,2] R(each unit="(m.K)/W") "Internal thermal resistances";
  Modelica.Units.SI.Position[2] xPip={-sha,sha} "x-Coordinates of pipes";
  Modelica.Units.SI.Position[2] yPip={0.,0.} "y-Coordinates of pipes";
  Modelica.Units.SI.Radius[2] rPip={rTub,rTub} "Outer radius of pipes";
  Real[2] RFluPip(each unit="(m.K)/W") = {RCondPipe+RConv, RCondPipe+RConv} "Fluid to pipe wall thermal resistances";
  Modelica.Units.SI.ThermalResistance Rg
    "Thermal resistance between outer borehole wall and one tube";
  Modelica.Units.SI.ThermalResistance Rar
    "Thermal resistance between the two pipe outer walls";

  Real Ra(unit="(m.K)/W")
    "Grout-to-grout resistance (2D) as defined by Hellstrom. Interaction between the different grout parts";

algorithm
  // Internal thermal resistances
  (RDelta, R) :=
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.multipoleThermalResistances(
      2, 3, xPip, yPip, rBor, rPip, kFil, kSoi, RFluPip);

  // Rb and Ra
  Rb_multipole := 1./(1./RDelta[1,1] + 1./RDelta[2,2]);
  Rb_internal := if use_Rb then Rb else Rb_multipole;
  // The short-circuit resistance in weigthed by the ratio between the used
  // value of Rb and the theoretical value
  Ra := (R[1,1] + R[2,2] - 2*R[1,2])*Rb_internal/Rb_multipole;

  // Conversion of Rb (resp. Ra) to Rg (resp. Rar) of Bauer:
  Rg  :=(2*Rb_internal-RCondPipe-RConv)/hSeg;
  Rar :=(Ra-2*(RCondPipe + RConv))/hSeg;

  // If any of the internal delta-circuit resistances is negative, then
  // the location (x) of the thermal capacity is set to zero to limit
  // instabilities in the calculations. Otherwise, calculations follow the
  // method of Bauer et al. (2011).
  if (RDelta[1,2] < 0) then
    //Thermal resistance between the grout zone and borehole wall
    Rgb := Rg;

    //Conduction resistance in grout from pipe wall to capacity in grout
    RCondGro := RCondPipe/hSeg;

    //Thermal resistance between the two grout zones
    Rgg := 2*Rgb*Rar/(2*Rgb - Rar);

    test := true;
  else
    // ********** Resistances and capacity location according to Bauer **********
    while test == false and i <= 10 loop
      // Capacity location (with correction factor in case that the test is
      // negative)
      x := Modelica.Math.log(sqrt(rBor^2 + 2*rTub^2)/(2*rTub))/
        Modelica.Math.log(rBor/(sqrt(2)*rTub))*((15 - i + 1)/15);

      //Thermal resistance between the grout zone and borehole wall
      Rgb := (1 - x)*Rg;

      //Conduction resistance in grout from pipe wall to capacity in grout
      RCondGro := x*Rg + RCondPipe/hSeg;

      //Thermal resistance between the two grout zones
      Rgg := 2*Rgb*(Rar - 2*x*Rg)/(2*Rgb - Rar + 2*x*Rg);

      // Thermodynamic test to check if negative R values make sense. If not,
      // decrease x-value.
      test := ((1/Rgg + 1/2/Rgb)^(-1) > 0);
      i := i + 1;
    end while;
  end if;
  assert(test, "In " + instanceName + ":\n" +
  "Maximum number of iterations exceeded. Check the borehole geometry.
  The tubes may be too close to the borehole wall.
  Input to the function
  AixLib.Fluid.HeatExchangers.Boreholes.BaseClasses.singleUTubeResistances
  is
           hSeg = " + String(hSeg) + " m
           rBor = " + String(rBor) + " m
           rTub = " + String(rTub) + " m
           eTub = " + String(eTub) + " m
           kSoi = " + String(kSoi) + " W/m/K
           kFil = " + String(kFil) + " W/m/K
           kTub = " + String(kTub) + " W/m/K
           i = "  + String(i) + "
  Computed x    = " + String(x) + " K/W
           Rgb  = " + String(Rgb) + " K/W
           Rgg  = " + String(Rgg) + " K/W");
end internalResistancesOneUTube;


Thermal resistances for double U-tube, according to Bauer et al (2011). This model computes the different thermal resistances present in a double U-tube
borehole using the method of Bauer et al. (2011).
It also computes the fluid-to-ground thermal resistance Rb
and the grout-to-grout thermal resistance Ra
as defined by Claesson and Hellstrom (2011) using the multipole method.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions;
function internalResistancesTwoUTube
  "Thermal resistances for double U-tube, according to Bauer et al (2011)"
  extends
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.partialInternalResistances;

  // Outputs
  output Modelica.Units.SI.ThermalResistance Rgb
    "Thermal resistance between a grout capacity and the borehole wall, as defined by Bauer et al (2010)";
  output Modelica.Units.SI.ThermalResistance Rgg1
    "Thermal resistance between two neightbouring grout capacities, as defined by Bauer et al (2010)";
  output Modelica.Units.SI.ThermalResistance Rgg2
    "Thermal resistance between two  grout capacities opposite to each other, as defined by Bauer et al (2010)";
  output Modelica.Units.SI.ThermalResistance RCondGro
    "Thermal resistance between a pipe wall and the grout capacity, as defined by Bauer et al (2010)";
protected
  Real[4,4] RDelta(each unit="(m.K)/W") "Delta-circuit thermal resistances";
  Real[4,4] R(each unit="(m.K)/W") "Internal thermal resistances";
  Modelica.Units.SI.Position[4] xPip={-sha,sha,0.,0.} "x-Coordinates of pipes";
  Modelica.Units.SI.Position[4] yPip={0.,0.,-sha,sha} "y-Coordinates of pipes";
  Modelica.Units.SI.Radius[4] rPip={rTub,rTub,rTub,rTub}
    "Outer radius of pipes";
  Real[4] RFluPip(each unit="(m.K)/W") = {RCondPipe+RConv, RCondPipe+RConv, RCondPipe+RConv, RCondPipe+RConv} "Fluid to pipe wall thermal resistances";

  Real Ra( unit="(m.K)/W")
    "Grout-to-grout resistance (2D) as defined by Hellstrom. Interaction between the different grout parts";

  Modelica.Units.SI.ThermalResistance Rg
    "Thermal resistance between outer borehole wall and one tube";
  Modelica.Units.SI.ThermalResistance Rar1
    "Thermal resistance between the two closest pipe outer walls";
  Modelica.Units.SI.ThermalResistance Rar2
    "Thermal resistance between the two farthest pipe outer walls";

algorithm
  // Internal thermal resistances
  (RDelta, R) :=
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.multipoleThermalResistances(
      4, 3, xPip, yPip, rBor, rPip, kFil, kSoi, RFluPip);

  // Rb and Ra
  Rb_multipole := 1./(1./RDelta[1,1] + 1./RDelta[2,2] + 1./RDelta[3,3] + 1./RDelta[4,4]);
  Rb_internal := if use_Rb then Rb else Rb_multipole;
  // The short-circuit resistance in weigthed by the ratio between the used
  // value of Rb and the theoretical value
  Ra := (R[1,1] + R[3,3] - 2*R[1,3])*Rb_internal/Rb_multipole;

  // ------ Calculation according to Bauer et al. (2010)
  Rg := (4*Rb_internal - RCondPipe - RConv)/hSeg;
  Rar1 := ((2 + sqrt(2))*Rg*hSeg*(Ra - RCondPipe)/(Rg*hSeg + Ra - RCondPipe))/hSeg;
  Rar2 := sqrt(2)*Rar1;

  // If any of the internal delta-circuit resistances is negative, then
  // the location (x) of the thermal capacity is set to zero to limit
  // instabilities in the calculations. Otherwise, calculations follow the
  // method of Bauer et al. (2011).
  if (RDelta[1,2] < 0) or (RDelta[1,3] < 0) then
    //Thermal resistance between the grout zone and borehole wall
    Rgb := Rg;

    //Conduction resistance in grout from pipe wall to capacity in grout
    RCondGro := RCondPipe/hSeg;

    //Thermal resistance between the two grout zones
    Rgg1 := 2*Rgb*(Rar1)/(2*Rgb - Rar1);
    Rgg2 := 2*Rgb*(Rar2)/(2*Rgb - Rar2);

    test := true;
  else
    // ********** Resistances and capacity location according to Bauer **********
    while test == false and i <= 16 loop
      // Capacity location (with correction factor in case that the test is negative)
      x := Modelica.Math.log(sqrt(rBor^2 + 4*rTub^2)/(2*sqrt(2)*rTub))/
          Modelica.Math.log(rBor/(2*rTub))*((15 - i + 1)/15);

      //Thermal resistance between the grout zone and borehole wall
      Rgb := (1 - x)*Rg;

      //Conduction resistance in grout from pipe wall to capacity in grout
      RCondGro := x*Rg + RCondPipe/hSeg;

      //Thermal resistance between the two grout zones
      Rgg1 := 2*Rgb*(Rar1 - 2*x*Rg)/(2*Rgb - Rar1 + 2*x*Rg);
      Rgg2 := 2*Rgb*(Rar2 - 2*x*Rg)/(2*Rgb - Rar2 + 2*x*Rg);

      // Thermodynamic test to check if negative R values make sense. If not, decrease x-value.
      test := (((1/Rgg1 + 1/2/Rgb)^(-1) > 0) and ((1/Rgg2 + 1/2/Rgb)^(-1) > 0));
      i := i + 1;
    end while;
  end if;
  assert(test, "In " + instanceName + ":\n" +
  "Maximum number of iterations exceeded. Check the borehole geometry.
  The tubes may be too close to the borehole wall.
  Input to the function
  AixLib.Fluid.HeatExchangers.Boreholes.BaseClasses.doubleUTubeResistances
  is
            hSeg = " + String(hSeg) + " m
            rBor = " + String(rBor) + " m
            rTub = " + String(rTub) + " m
            eTub = " + String(eTub) + " m
            sha = " + String(sha) + " m
            kSoi = " + String(kSoi) + " W/m/K
            kFil = " + String(kFil) + " W/m/K
            kTub = " + String(kTub) + " W/m/K
  Computed x    = " + String(x) + " m
            Rgb  = " + String(Rgb) + " K/W
            Rgg1  = " + String(Rgg1) + " K/W
            Rgg2  = " + String(Rgg2) + " K/W");
end internalResistancesTwoUTube;


Fluid temperatures from multipole solution. This model evaluates the fluid temperatures using the multipole method of Claesson and Hellstrom (2011).

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions;
function multipoleFluidTemperature "Fluid temperatures from multipole solution"
  extends Modelica.Icons.Function;

  input Integer nPip "Number of pipes";
  input Integer J "Number of multipoles";
  input Modelica.Units.SI.Position xPip[nPip] "x-Coordinates of pipes";
  input Modelica.Units.SI.Position yPip[nPip] "y-Coordinates of pipes";
  input Real QPip_flow[nPip](each unit="W/m") "Heat flow in pipes";
  input Modelica.Units.SI.Temperature TBor "Average borehole wall temperature";
  input Modelica.Units.SI.Radius rBor "Borehole radius";
  input Modelica.Units.SI.Radius rPip[nPip] "Outter radius of pipes";
  input Modelica.Units.SI.ThermalConductivity kFil
    "Thermal conductivity of grouting material";
  input Modelica.Units.SI.ThermalConductivity kSoi
    "Thermal conductivity of soil material";
  input Real RFluPip[nPip](each unit="(m.K)/W") "Fluid to pipe wall thermal resistances";
  input Real eps=1.0e-5 "Iteration relative accuracy";
  input Integer it_max=100 "Maximum number of iterations";

  output Modelica.Units.SI.Temperature TFlu[nPip] "Fluid temperature in pipes";

protected
  Real pikFil(unit="(m.K)/W")=1/(2*Modelica.Constants.pi*kFil) "Coefficient based on grout thermal conductivity";
  Real sigma=(kFil - kSoi)/(kFil + kSoi) "Thermal conductivity ratio";
  Real betaPip[nPip]=2*Modelica.Constants.pi*kFil*RFluPip "Dimensionless fluid to outter pipe wall thermal resistance";
  Complex zPip_i "Position of pipe i";
  Complex zPip_j "Position of pipe j";
  Complex P_nj "Multipole of order j for pipe n";
  Real PRea[nPip,J] "Matrix of real part of multipoles";
  Real PIma[nPip,J] "Matrix of imaginary part of multipole";
  Complex P_nj_new "New value of multipole of order j for pipe n";
  Real PRea_new[nPip,J] "New value of real part of multipoles";
  Real PIma_new[nPip,J] "New value of imaginary part of multipoles";
  Complex F_mk "Coefficient F of order k of pipe m";
  Real FRea[nPip,J] "Real part of matrix F_mk";
  Real FIma[nPip,J] "Imaginary part of matrix F_mk";
  Real R0[nPip,nPip](each unit="(m.K)/W") "Line source approximation of thermal resistances";
  Complex deltaTFlu "Fluid temperature difference with line source approximation";
  Real rbm "Intermediate coefficient";
  Modelica.Units.SI.Distance dz "Pipe to pipe distance";
  Real coeff[nPip,J] "Coefficient for multiplication with matrix F_mk";
  Real diff "Difference in subsequent multipole evaluations";
  Real diff_max "Maximum difference in subsequent multipole evaluations";
  Real diff_min "Minimum difference in subsequent multipole evaluations";
  Real diff0 "Difference in subsequent multipole evaluations";
  Integer it "Iteration counter";
  Real eps_max "Convergence variable";

algorithm
  // Thermal resistance matrix from 0th order multipole
  for i in 1:nPip loop
    zPip_i := Complex(xPip[i], yPip[i]);
    rbm :=rBor^2/(rBor^2 - Modelica.ComplexMath.abs(zPip_i)^2);
    R0[i, i] := pikFil*(log(rBor/rPip[i]) + betaPip[i] + sigma*log(rbm));
    for j in 1:nPip loop
      zPip_j := Complex(xPip[j], yPip[j]);
      if i <> j then
        dz :=Modelica.ComplexMath.abs(zPip_i - zPip_j);
        rbm :=rBor^2/Modelica.ComplexMath.abs(rBor^2 - zPip_j*
          Modelica.ComplexMath.conj(zPip_i));
        R0[i, j] := pikFil*(log(rBor/dz) + sigma*log(rbm));
      end if;
    end for;
  end for;

  // Initialize maximum error and iteration counter
  eps_max := 1.0e99;
  it := 0;
  // Multipoles
  if J > 0 then
    for m in 1:nPip loop
      for k in 1:J loop
        coeff[m, k] := -(1 - k*betaPip[m])/(1 + k*betaPip[m]);
        PRea[m, k] := 0;
        PIma[m, k] := 0;
      end for;
    end for;
    while eps_max > eps and it < it_max loop
      it := it + 1;
      (FRea, FIma) :=
        AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.multipoleFmk(
        nPip,
        J,
        QPip_flow,
        PRea,
        PIma,
        rBor,
        rPip,
        xPip,
        yPip,
        kFil,
        kSoi);
      for m in 1:nPip loop
        for k in 1:J loop
          F_mk := Complex(FRea[m, k], FIma[m, k]);
          P_nj_new := coeff[m, k]*Modelica.ComplexMath.conj(F_mk);
          PRea_new[m, k] := Modelica.ComplexMath.real(P_nj_new);
          PIma_new[m, k] := Modelica.ComplexMath.imag(P_nj_new);
        end for;
      end for;
      diff_max := 0;
      diff_min := 1e99;
      for m in 1:nPip loop
        for k in 1:J loop
          P_nj := Complex(PRea[m, k], PIma[m, k]);
          P_nj_new := Complex(PRea_new[m, k], PIma_new[m, k]);
          diff_max :=max(diff_max, Modelica.ComplexMath.abs(P_nj_new - P_nj));
          diff_min :=min(diff_min, Modelica.ComplexMath.abs(P_nj_new - P_nj));
        end for;
      end for;
      diff := diff_max - diff_min;
      if it == 1 then
        diff0 :=diff;
      end if;
      eps_max := diff/diff0;
      PRea := PRea_new;
      PIma := PIma_new;
    end while;
  end if;

  // Fluid Temperatures
  TFlu := TBor .+ R0*QPip_flow;
  if J > 0 then
    for m in 1:nPip loop
      zPip_i :=Complex(xPip[m], yPip[m]);
      deltaTFlu := Complex(0, 0);
      for n in 1:nPip loop
        zPip_j :=Complex(xPip[n], yPip[n]);
        for j in 1:J loop
          P_nj := Complex(PRea[n, j], PIma[n, j]);
          if n <> m then
            // Second term
            deltaTFlu := deltaTFlu + P_nj*(rPip[n]/(zPip_i - zPip_j))^j;
          end if;
          // Third term
          deltaTFlu := deltaTFlu + sigma*P_nj*(rPip[n]*
            Modelica.ComplexMath.conj(zPip_i)/(rBor^2 - zPip_j*
            Modelica.ComplexMath.conj(zPip_i)))^j;
        end for;
      end for;
      TFlu[m] := TFlu[m] + Modelica.ComplexMath.real(deltaTFlu);
    end for;
  end if;
end multipoleFluidTemperature;


Complex matrix F_mk from Claesson and Hellstrom (2011). This model evaluates the complex coefficient matrix F_mk from Claesson and Hellstrom (2011).

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions;
function multipoleFmk "Complex matrix F_mk from Claesson and Hellstrom (2011)"
  extends Modelica.Icons.Function;

  input Integer nPip "Number of pipes";
  input Integer J "Number of multipoles";
  input Real QPip_flow[nPip](each unit="W/m") "Heat flow in pipes";
  input Real PRea[nPip,J] "Multipoles (Real part)";
  input Real PIma[nPip,J] "Multipoles (Imaginary part)";
  input Modelica.Units.SI.Radius rBor "Borehole radius";
  input Modelica.Units.SI.Radius rPip[nPip] "Outter radius of pipes";
  input Modelica.Units.SI.Position xPip[nPip] "x-Coordinates of pipes";
  input Modelica.Units.SI.Position yPip[nPip] "y-Coordinates of pipes";
  input Modelica.Units.SI.ThermalConductivity kFil
    "Thermal conductivity of grouting material";
  input Modelica.Units.SI.ThermalConductivity kSoi
    "Thermal conductivity of soil material";

  output Real FRea[nPip,J] "Multipole coefficients";
  output Real FIma[nPip,J] "Multipole coefficients";

protected
  Complex zPip_i "Position of pipe i";
  Complex zPip_j "Position of pipe j";
  Complex P_nj "Multipole of order j for pipe n";
  Real pikFil(unit="(m.K)/W")=1/(2*Modelica.Constants.pi*kFil) "Coefficient based on grout thermal conductivity";
  Real sigma=(kFil - kSoi)/(kFil + kSoi) "Thermal conductivity ratio";
  Complex f "Intermedia value of multipole coefficient";
  Integer j_pend "Maximum loop index in fourth term";

algorithm

  for m in 1:nPip loop
    zPip_i := Complex(xPip[m], yPip[m]);
    for k in 1:J loop
      f := Complex(0, 0);
      for n in 1:nPip loop
        zPip_j := Complex(xPip[n], yPip[n]);
        // First term
        if m <> n then
          f := f + QPip_flow[n]*pikFil/k*(rPip[m]/(zPip_j - zPip_i))^k;
        end if;
        // Second term
        f := f + sigma*QPip_flow[n]*pikFil/k*(rPip[m]*Modelica.ComplexMath.conj(
          zPip_j)/(rBor^2 - zPip_i*Modelica.ComplexMath.conj(zPip_j)))^k;
        for j in 1:J loop
          P_nj := Complex(PRea[n, j], PIma[n, j]);
          // Third term
          if m <> n then
            f := f + P_nj*AixLib.Utilities.Math.Functions.binomial(j + k - 1, j -
              1)*rPip[n]^j*(-rPip[m])^k/(zPip_i - zPip_j)^(j + k);
          end if;
          //Fourth term
          j_pend := min(k, j);
          for jp in 0:j_pend loop
            f := f + sigma*Modelica.ComplexMath.conj(P_nj)*
              AixLib.Utilities.Math.Functions.binomial(j, jp)*
              AixLib.Utilities.Math.Functions.binomial(j + k - jp - 1, j - 1)*
              rPip[n]^j*rPip[m]^k*zPip_i^(j - jp)*Modelica.ComplexMath.conj(
              zPip_j)^(k - jp)/(rBor^2 - zPip_i*Modelica.ComplexMath.conj(
              zPip_j))^(k + j - jp);
          end for;
        end for;
      end for;
      FRea[m, k] := Modelica.ComplexMath.real(f);
      FIma[m, k] := Modelica.ComplexMath.imag(f);
    end for;
  end for;
end multipoleFmk;


Thermal resistances from multipole solution. This model evaluates the delta-circuit borehole thermal resistances using the multipole method of Claesson and Hellstrom (2011).

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions;
function multipoleThermalResistances
  "Thermal resistances from multipole solution"
  extends Modelica.Icons.Function;

  input Integer nPip "Number of pipes";
  input Integer J "Number of multipoles";
  input Modelica.Units.SI.Position xPip[nPip] "x-Coordinates of pipes";
  input Modelica.Units.SI.Position yPip[nPip] "y-Coordinates of pipes";
  input Modelica.Units.SI.Radius rBor "Borehole radius";
  input Modelica.Units.SI.Radius rPip[nPip] "Outter radius of pipes";
  input Modelica.Units.SI.ThermalConductivity kFil
    "Thermal conductivity of grouting material";
  input Modelica.Units.SI.ThermalConductivity kSoi
    "Thermal conductivity of soil material";
  input Real RFluPip[nPip](each unit="(m.K)/W") "Fluid to pipe wall thermal resistances";
  input Modelica.Units.SI.Temperature TBor=0
    "Average borehole wall temperature";

  output Real RDelta[nPip,nPip](each unit="(m.K)/W") "Delta-circuit thermal resistances";
  output Real R[nPip,nPip](each unit="(m.K)/W") "Internal thermal resistances";

protected
  Real QPip_flow[nPip](each unit="W/m") "Pipe heat transfer rates";
  Modelica.Units.SI.Temperature TFlu[nPip] "Fluid temperatures";
  Real K[nPip,nPip](each unit="W/(m.K)") "Internal thermal conductances";

algorithm
  for m in 1:nPip loop
    for n in 1:nPip loop
      if n == m then
        QPip_flow[n] := 1;
      else
        QPip_flow[n] := 0;
      end if;
    end for;
    TFlu :=
      AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.multipoleFluidTemperature(
      nPip,
      J,
      xPip,
      yPip,
      QPip_flow,
      TBor,
      rBor,
      rPip,
      kFil,
      kSoi,
      RFluPip);
    for n in 1:nPip loop
      R[n, m] := TFlu[n];
    end for;
  end for;
  K := -Modelica.Math.Matrices.inv(R);
  for m in 1:nPip loop
    K[m, m] := -K[m, m];
    for n in 1:nPip loop
      if m <> n then
        K[m, m] := K[m, m] - K[m, n];
      end if;
    end for;
  end for;
  for m in 1:nPip loop
    for n in 1:nPip loop
      RDelta[m, n] := 1./K[m, n];
    end for;
  end for;
end multipoleThermalResistances;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses;
package Functions "Package with functions for evaluation of borehole thermal resistances"
extends Modelica.Icons.VariantsPackage;
end Functions;


Partial model for borehole resistance calculation. This partial function defines the common inputs to functions that calculate
the borehole internal resistances.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions;
partial function partialInternalResistances
  "Partial model for borehole resistance calculation"
  extends Modelica.Icons.Function;

  // Geometry of the borehole
  input Boolean use_Rb = false
    "True if the value Rb should be used instead of calculated";
  input Real Rb(unit="(m.K)/W") "Borehole thermal resistance";
  input Modelica.Units.SI.Height hSeg "Height of the element";
  input Modelica.Units.SI.Radius rBor "Radius of the borehole";
  // Geometry of the pipe
  input Modelica.Units.SI.Radius rTub "Radius of the tube";
  input Modelica.Units.SI.Length eTub "Thickness of the tubes";
  input Modelica.Units.SI.Length sha
    "Shank spacing, defined as the distance between the center of a pipe and the center of the borehole";

  // Thermal properties
  input Modelica.Units.SI.ThermalConductivity kFil
    "Thermal conductivity of the grout";
  input Modelica.Units.SI.ThermalConductivity kSoi
    "Thermal conductivity of the soi";
  input Modelica.Units.SI.ThermalConductivity kTub
    "Thermal conductivity of the tube";
  input Modelica.Units.SI.ThermalConductivity kMed
    "Thermal conductivity of the fluid";
  input Modelica.Units.SI.DynamicViscosity muMed
    "Dynamic viscosity of the fluid";
  input Modelica.Units.SI.SpecificHeatCapacity cpMed
    "Specific heat capacity of the fluid";
  input Modelica.Units.SI.MassFlowRate m_flow_nominal "Nominal mass flow rate";
  input String instanceName="undeclared caller"
    "Instance name of the model or block that calls this function";

  // Outputs
  output Real x "Capacity location";

protected
  parameter Real pi = 3.141592653589793 "pi";

  Real rTub_in = rTub-eTub "Inner radius of tube";

  Real RConv(unit="(m.K)/W")=
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.convectionResistanceCircularPipe(
      hSeg=hSeg,
      rTub=rTub,
      eTub=eTub,
      kMed=kMed,
      muMed=muMed,
      cpMed=cpMed,
      m_flow=m_flow_nominal,
      m_flow_nominal=m_flow_nominal)*hSeg;

  Boolean test=false "thermodynamic test for R and x value";

  Real RCondPipe(unit="(m.K)/W") =  Modelica.Math.log((rTub)/rTub_in)/(2*Modelica.Constants.pi*kTub)
    "Thermal resistance of the pipe wall";

  Real Rb_internal(unit="(m.K)/W")
    "Resistance from the fluid in the pipe to the borehole wall";

  Real Rb_multipole(unit="(m.K)/W")
    "Theoretical Fluid-to-borehole-wall resistance evaluated from the multipole method";

  Integer i=1 "Loop counter";
end partialInternalResistances;


Validation of the correlation used to evaluate the convection resistance in circular pipes. This example validates the implementation of

AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.convectionResistanceCircularPipe
for the evaluation of the convection thermal resistance in circular pipes.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.Validation;
model ConvectionResistanceCircularPipe
  "Validation of the correlation used to evaluate the convection resistance in circular pipes"
  extends Modelica.Icons.Example;

  parameter Modelica.Units.SI.Height hSeg=1.0 "Height of the element";
  parameter Modelica.Units.SI.Radius rTub=0.02 "Tube radius";
  parameter Modelica.Units.SI.Length eTub=0.002 "Tube thickness";
  // thermal properties
  parameter Modelica.Units.SI.ThermalConductivity kMed=0.6
    "Thermal conductivity of the fluid";
  parameter Modelica.Units.SI.DynamicViscosity muMed=1.002e-3
    "Dynamic viscosity of the fluid";
  parameter Modelica.Units.SI.SpecificHeatCapacity cpMed=4182
    "Specific heat capacity of the fluid";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=1
    "Nominal mass flow rate";

  Real Re "Reynolds number";
  Real Nu "Reynolds number";
  Modelica.Units.SI.MassFlowRate m_flow "Mass flow rate";
  Modelica.Units.SI.ThermalResistance RConv "Convection resistance";

equation

  Re = time;
  Re = 2*m_flow/(muMed*Modelica.Constants.pi*(rTub-eTub));
  RConv = AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.convectionResistanceCircularPipe(
    hSeg=hSeg,
    rTub=rTub,
    eTub=eTub,
    kMed=kMed,
    muMed=muMed,
    cpMed=cpMed,
    m_flow=m_flow,
    m_flow_nominal=m_flow_nominal);
  Nu = 1/(kMed*Modelica.Constants.pi*hSeg*RConv);
end ConvectionResistanceCircularPipe;


Validation of the thermal resistances using the method of Bauer et al. (2011) for a single U-tube borehole. This example validates the implementation of

AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.internalResistancesOneUTube
for the evaluation of the internal thermal resistances of a single U-tube
borehole.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.Validation;
model InternalResistancesOneUTube
  "Validation of the thermal resistances using the method of Bauer et al. (2011) for a single U-tube borehole"
  extends Modelica.Icons.Example;

  // Geometry of the borehole
  parameter Real Rb(unit="(m.K)/W") = 0.0
    "Borehole thermal resistance (Not used)";
  parameter Modelica.Units.SI.Height hSeg=1.0 "Height of the element";
  parameter Modelica.Units.SI.Radius rBor=0.07 "Radius of the borehole";
  // Geometry of the pipe
  parameter Modelica.Units.SI.Radius rTub=0.02 "Radius of the tube";
  parameter Modelica.Units.SI.Length eTub=0.002 "Thickness of the tubes";
  parameter Modelica.Units.SI.Length sha=0.03
    "Shank spacing, defined as the distance between the center of a pipe and the center of the borehole";

  // Thermal properties (Solids)
  parameter Modelica.Units.SI.ThermalConductivity kFil=1.5
    "Thermal conductivity of the grout";
  parameter Modelica.Units.SI.ThermalConductivity kSoi=2.5
    "Thermal conductivity of the soi";
  parameter Modelica.Units.SI.ThermalConductivity kTub=0.4
    "Thermal conductivity of the tube";

  // Thermal properties (Fluid)
  parameter Modelica.Units.SI.ThermalConductivity kMed=0.6
    "Thermal conductivity of the fluid";
  parameter Modelica.Units.SI.DynamicViscosity muMed=1.0e-3
    "Dynamic viscosity of the fluid";
  parameter Modelica.Units.SI.SpecificHeatCapacity cpMed=4180.0
    "Specific heat capacity of the fluid";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.25
    "Nominal mass flow rate";

  // Outputs
  parameter Real x(fixed=false) "Capacity location";
  parameter Modelica.Units.SI.ThermalResistance Rgb(fixed=false)
    "Thermal resistance between grout zone and borehole wall";
  parameter Modelica.Units.SI.ThermalResistance Rgg(fixed=false)
    "Thermal resistance between the two grout zones";
  parameter Modelica.Units.SI.ThermalResistance RCondGro(fixed=false)
    "Thermal resistance between: pipe wall to capacity in grout";

initial equation
  (x, Rgb, Rgg, RCondGro) =
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.internalResistancesOneUTube(
      hSeg=hSeg,
      rBor=rBor,
      rTub=rTub,
      eTub=eTub,
      sha=sha,
      kFil=kFil,
      kSoi=kSoi,
      kTub=kTub,
      Rb=Rb,
      kMed=kMed,
      muMed=muMed,
      cpMed=cpMed,
      m_flow_nominal=m_flow_nominal,
      instanceName=getInstanceName());
end InternalResistancesOneUTube;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.Validation;
model InternalResistancesOneUTubeNegative
  "Validation of the thermal resistances using the method of Bauer et al. (2011) for a single U-tube borehole"
  extends Modelica.Icons.Example;

  // Geometry of the borehole
  parameter Real Rb(unit="(m.K)/W") = 0.0
    "Borehole thermal resistance (Not used)";
  parameter Modelica.Units.SI.Height hSeg=1.0 "Height of the element";
  parameter Modelica.Units.SI.Radius rBor=0.07 "Radius of the borehole";
  // Geometry of the pipe
  parameter Modelica.Units.SI.Radius rTub=0.02 "Radius of the tube";
  parameter Modelica.Units.SI.Length eTub=0.002 "Thickness of the tubes";
  parameter Modelica.Units.SI.Length sha=0.05
    "Shank spacing, defined as the distance between the center of a pipe and the center of the borehole";

  // Thermal properties (Solids)
  parameter Modelica.Units.SI.ThermalConductivity kFil=1.5
    "Thermal conductivity of the grout";
  parameter Modelica.Units.SI.ThermalConductivity kSoi=2.5
    "Thermal conductivity of the soi";
  parameter Modelica.Units.SI.ThermalConductivity kTub=0.4
    "Thermal conductivity of the tube";

  // Thermal properties (Fluid)
  parameter Modelica.Units.SI.ThermalConductivity kMed=0.6
    "Thermal conductivity of the fluid";
  parameter Modelica.Units.SI.DynamicViscosity muMed=1.0e-3
    "Dynamic viscosity of the fluid";
  parameter Modelica.Units.SI.SpecificHeatCapacity cpMed=4180.0
    "Specific heat capacity of the fluid";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.25
    "Nominal mass flow rate";

  // Outputs
  parameter Real x(fixed=false) "Capacity location";
  parameter Modelica.Units.SI.ThermalResistance Rgb(fixed=false)
    "Thermal resistance between grout zone and borehole wall";
  parameter Modelica.Units.SI.ThermalResistance Rgg(fixed=false)
    "Thermal resistance between the two grout zones";
  parameter Modelica.Units.SI.ThermalResistance RCondGro(fixed=false)
    "Thermal resistance between: pipe wall to capacity in grout";

initial equation
  (x, Rgb, Rgg, RCondGro) =
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.internalResistancesOneUTube(
      hSeg=hSeg,
      rBor=rBor,
      rTub=rTub,
      eTub=eTub,
      sha=sha,
      kFil=kFil,
      kSoi=kSoi,
      kTub=kTub,
      Rb=Rb,
      kMed=kMed,
      muMed=muMed,
      cpMed=cpMed,
      m_flow_nominal=m_flow_nominal,
      instanceName=getInstanceName());
end InternalResistancesOneUTubeNegative;


Validation of the thermal resistances using the method of Bauer et al. (2011) for a double U-tube borehole. This example validates the implementation of

AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.internalResistancesTwoUTube
for the evaluation of the internal thermal resistances of a double U-tube
borehole.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.Validation;
model InternalResistancesTwoUTube
  "Validation of the thermal resistances using the method of Bauer et al. (2011) for a double U-tube borehole"
  extends Modelica.Icons.Example;

  // Geometry of the borehole
  parameter Real Rb(unit="(m.K)/W") = 0.0
    "Borehole thermal resistance (Not used)";
  parameter Modelica.Units.SI.Height hSeg=1.0 "Height of the element";
  parameter Modelica.Units.SI.Radius rBor=0.07 "Radius of the borehole";
  // Geometry of the pipe
  parameter Modelica.Units.SI.Radius rTub=0.02 "Radius of the tube";
  parameter Modelica.Units.SI.Length eTub=0.002 "Thickness of the tubes";
  parameter Modelica.Units.SI.Length sha=0.025
    "Shank spacing, defined as the distance between the center of a pipe and the center of the borehole";

  // Thermal properties (Solids)
  parameter Modelica.Units.SI.ThermalConductivity kFil=0.5
    "Thermal conductivity of the grout";
  parameter Modelica.Units.SI.ThermalConductivity kSoi=2.5
    "Thermal conductivity of the soi";
  parameter Modelica.Units.SI.ThermalConductivity kTub=0.4
    "Thermal conductivity of the tube";

  // Thermal properties (Fluid)
  parameter Modelica.Units.SI.ThermalConductivity kMed=0.6
    "Thermal conductivity of the fluid";
  parameter Modelica.Units.SI.DynamicViscosity muMed=1.0e-3
    "Dynamic viscosity of the fluid";
  parameter Modelica.Units.SI.SpecificHeatCapacity cpMed=4180.0
    "Specific heat capacity of the fluid";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.25
    "Nominal mass flow rate";

  // Outputs
  parameter Real x(fixed=false) "Capacity location";
  parameter Modelica.Units.SI.ThermalResistance Rgb(fixed=false)
    "Thermal resistance between grout zone and borehole wall";
  parameter Modelica.Units.SI.ThermalResistance Rgg1(fixed=false)
    "Thermal resistance between the two adjacent grout zones";
  parameter Modelica.Units.SI.ThermalResistance Rgg2(fixed=false)
    "Thermal resistance between the two opposite grout zones";
  parameter Modelica.Units.SI.ThermalResistance RCondGro(fixed=false)
    "Thermal resistance between: pipe wall to capacity in grout";

initial equation
  (x, Rgb, Rgg1, Rgg2, RCondGro) =
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.internalResistancesTwoUTube(
      hSeg=hSeg,
      rBor=rBor,
      rTub=rTub,
      eTub=eTub,
      sha=sha,
      kFil=kFil,
      kSoi=kSoi,
      kTub=kTub,
      Rb=Rb,
      kMed=kMed,
      muMed=muMed,
      cpMed=cpMed,
      m_flow_nominal=m_flow_nominal,
      instanceName=getInstanceName());
end InternalResistancesTwoUTube;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.Validation;
model InternalResistancesTwoUTubeNegative
  "Validation of the thermal resistances using the method of Bauer et al. (2011) for a double U-tube borehole"
  extends Modelica.Icons.Example;

  // Geometry of the borehole
  parameter Real Rb(unit="(m.K)/W") = 0.0
    "Borehole thermal resistance (Not used)";
  parameter Modelica.Units.SI.Height hSeg=1.0 "Height of the element";
  parameter Modelica.Units.SI.Radius rBor=0.07 "Radius of the borehole";
  // Geometry of the pipe
  parameter Modelica.Units.SI.Radius rTub=0.02 "Radius of the tube";
  parameter Modelica.Units.SI.Length eTub=0.002 "Thickness of the tubes";
  parameter Modelica.Units.SI.Length sha=0.05
    "Shank spacing, defined as the distance between the center of a pipe and the center of the borehole";

  // Thermal properties (Solids)
  parameter Modelica.Units.SI.ThermalConductivity kFil=1.5
    "Thermal conductivity of the grout";
  parameter Modelica.Units.SI.ThermalConductivity kSoi=2.5
    "Thermal conductivity of the soi";
  parameter Modelica.Units.SI.ThermalConductivity kTub=0.4
    "Thermal conductivity of the tube";

  // Thermal properties (Fluid)
  parameter Modelica.Units.SI.ThermalConductivity kMed=0.6
    "Thermal conductivity of the fluid";
  parameter Modelica.Units.SI.DynamicViscosity muMed=1.0e-3
    "Dynamic viscosity of the fluid";
  parameter Modelica.Units.SI.SpecificHeatCapacity cpMed=4180.0
    "Specific heat capacity of the fluid";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.25
    "Nominal mass flow rate";

  // Outputs
  parameter Real x(fixed=false) "Capacity location";
  parameter Modelica.Units.SI.ThermalResistance Rgb(fixed=false)
    "Thermal resistance between grout zone and borehole wall";
  parameter Modelica.Units.SI.ThermalResistance Rgg1(fixed=false)
    "Thermal resistance between the two adjacent grout zones";
  parameter Modelica.Units.SI.ThermalResistance Rgg2(fixed=false)
    "Thermal resistance between the two opposite grout zones";
  parameter Modelica.Units.SI.ThermalResistance RCondGro(fixed=false)
    "Thermal resistance between: pipe wall to capacity in grout";

initial equation
  (x, Rgb, Rgg1, Rgg2, RCondGro) =
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.internalResistancesTwoUTube(
      hSeg=hSeg,
      rBor=rBor,
      rTub=rTub,
      eTub=eTub,
      sha=sha,
      kFil=kFil,
      kSoi=kSoi,
      kTub=kTub,
      Rb=Rb,
      kMed=kMed,
      muMed=muMed,
      cpMed=cpMed,
      m_flow_nominal=m_flow_nominal,
      instanceName=getInstanceName());
end InternalResistancesTwoUTubeNegative;


Validation of the thermal resitances for a single U-tube borehole. This example validates the implementation of

AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.multipoleThermalResistances
for the evaluation of the borehole thermal resistances.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.Validation;
model MultipoleThermalResistances_OneUTube
  "Validation of the thermal resitances for a single U-tube borehole"
  extends Modelica.Icons.Example;

  parameter Integer nPip=2 "Number of pipes";
  parameter Integer J=3 "Number of multipoles";
  parameter Modelica.Units.SI.Position[nPip] xPip={0.03,-0.03}
    "x-Coordinates of pipes";
  parameter Modelica.Units.SI.Position[nPip] yPip={0.00,0.02}
    "y-Coordinates of pipes";
  parameter Modelica.Units.SI.Radius rBor=0.07 "Borehole radius";
  parameter Modelica.Units.SI.Radius[nPip] rPip=fill(0.02, nPip)
    "Outter radius of pipes";
  parameter Modelica.Units.SI.ThermalConductivity kFil=1.5
    "Thermal conductivity of grouting material";
  parameter Modelica.Units.SI.ThermalConductivity kSoi=2.5
    "Thermal conductivity of soil material";
  parameter Real[nPip] RFluPip(each unit="(m.K)/W")=
    fill(1.2/(2*Modelica.Constants.pi*kFil), nPip)
    "Fluid to pipe wall thermal resistances";
  parameter Modelica.Units.SI.Temperature TBor=0
    "Average borehole wall temperature";

  parameter Real[nPip,nPip] RDelta_Ref(each unit="(m.K)/W")=
    {{1/3.680, 1/0.242},{1/0.242, 1/3.724}}
    "Reference delta-circuit thermal resistances";
  parameter Real[nPip,nPip] R_Ref(each unit="(m.K)/W")=
    {{0.25592, 0.01561},{0.01561, 0.25311}}
    "Reference internal thermal resistances";

  Real[nPip,nPip] RDelta(each unit="(m.K)/W")
    "Delta-circuit thermal resistances";
  Real[nPip,nPip] R(each unit="(m.K)/W")
    "Internal thermal resistances";

equation
  (RDelta, R) = AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.multipoleThermalResistances(
    nPip, J, xPip, yPip, rBor, rPip, kFil, kSoi, RFluPip, TBor);
end MultipoleThermalResistances_OneUTube;


Validation of the thermal resitances for a double U-tube borehole. This example validates the implementation of

AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.multipoleThermalResistances
for the evaluation of the borehole thermal resistances.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.Validation;
model MultipoleThermalResistances_TwoUTube
  "Validation of the thermal resitances for a double U-tube borehole"
  extends Modelica.Icons.Example;

  parameter Integer nPip=4 "Number of pipes";
  parameter Integer J=3 "Number of multipoles";
  parameter Modelica.Units.SI.Position[nPip] xPip={0.03,-0.03,-0.03,0.03}
    "x-Coordinates of pipes";
  parameter Modelica.Units.SI.Position[nPip] yPip={0.03,0.03,-0.03,-0.03}
    "y-Coordinates of pipes";
  parameter Modelica.Units.SI.Radius rBor=0.07 "Borehole radius";
  parameter Modelica.Units.SI.Radius[nPip] rPip=fill(0.02, nPip)
    "Outter radius of pipes";
  parameter Modelica.Units.SI.ThermalConductivity kFil=1.5
    "Thermal conductivity of grouting material";
  parameter Modelica.Units.SI.ThermalConductivity kSoi=2.5
    "Thermal conductivity of soil material";
  parameter Real[nPip] RFluPip(each unit="(m.K)/W")=
    fill(1.2/(2*Modelica.Constants.pi*kFil), nPip)
    "Fluid to pipe wall thermal resistances";
  parameter Modelica.Units.SI.Temperature TBor=0
    "Average borehole wall temperature";

  parameter Real[nPip,nPip] RDelta_Ref(each unit="(m.K)/W")=
    {{1/3.61, 1/0.35, -1/0.25, 1/0.35},
     {1/0.35, 1/3.61, 1/0.35, -1/0.25},
     {-1/0.25, 1/0.35, 1/3.61, 1/0.35},
     {1/0.35, -1/0.25, 1/0.35, 1/3.61}}
    "Reference delta-circuit thermal resistances";
  parameter Real[nPip,nPip] R_Ref(each unit="(m.K)/W")=
    {{0.2509, 0.0192, -0.0122, 0.0192},
     {0.0192, 0.2509, 0.0192, -0.0122},
     {-0.0122, 0.0192, 0.2509, 0.0192},
     {0.0192, -0.0122, 0.0192, 0.2509}}
    "Reference internal thermal resistances";

  Real[nPip,nPip] RDelta(each unit="(m.K)/W")
    "Delta-circuit thermal resistances";
  Real[nPip,nPip] R(each unit="(m.K)/W")
    "Internal thermal resistances";

equation
  (RDelta, R) = AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions.multipoleThermalResistances(
    nPip, J, xPip, yPip, rBor, rPip, kFil, kSoi, RFluPip, TBor);
end MultipoleThermalResistances_TwoUTube;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.Functions;
package Validation "Models to validate borehole thermal resistances functions"
extends Modelica.Icons.ExamplesPackage;
end Validation;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.Examples;
model BoreholeDynamics "Example model for different borehole models and dynamics"
  extends Modelica.Icons.Example;
  package Medium = AixLib.Media.Water;

  parameter Integer nSeg(min=1) = 10
    "Number of segments to use in vertical discretization of the boreholes";
  parameter Modelica.Units.SI.Temperature T_start=273.15 + 22
    "Initial soil temperature";

  AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.OneUTube
    borHolOneUTubDyn(
    redeclare package Medium = Medium,
    borFieDat=borFieUTubDat,
    m_flow_nominal=borFieUTubDat.conDat.mBor_flow_nominal,
    dp_nominal=borFieUTubDat.conDat.dp_nominal,
    nSeg=nSeg,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    TGro_start = {T_start for i in 1:nSeg},
    TFlu_start={Medium.T_default for i in 1:nSeg})
    "Borehole with U-Tub configuration and grout dynamics"
  AixLib.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    nPorts=1,
    use_T_in=false,
    m_flow=borFieUTubDat.conDat.mBor_flow_nominal,
    T=303.15) "Source"
  AixLib.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    use_p_in=false,
    use_T_in=false,
    nPorts=1,
    p=101330,
    T=283.15) "Sink"
  parameter
    AixLib.Fluid.Geothermal.Borefields.Data.Borefield.Example
    borFieUTubDat "Borefield parameters with UTube borehole configuration"
  AixLib.Fluid.Sensors.TemperatureTwoPort TBorIn(m_flow_nominal=borFieUTubDat.conDat.mBor_flow_nominal,
    redeclare package Medium = Medium,
    tau=0)
    "Inlet borehole temperature"
  AixLib.Fluid.Sensors.TemperatureTwoPort TBor1UTubDyn(
    m_flow_nominal=borFieUTubDat.conDat.mBor_flow_nominal,
    redeclare package Medium = Medium,
    tau=0)
    "Outlet borehole temperature"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector therCol1(m=nSeg)
   "Thermal collector"
  Modelica.Blocks.Sources.Constant TGroUn(k=T_start)
    "Undisturbed ground temperature"
  AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.OneUTube borHolOneUTubSteSta(
    redeclare package Medium = Medium,
    borFieDat=borFieUTubDatSteSta,
    m_flow_nominal=borFieUTubDatSteSta.conDat.mBor_flow_nominal,
    dp_nominal=borFieUTubDatSteSta.conDat.dp_nominal,
    nSeg=nSeg,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    TGro_start = {T_start for i in 1:nSeg},
    TFlu_start={Medium.T_default for i in 1:nSeg})
    "Borehole with U-Tub configuration and steady state grout"
  AixLib.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium,
    nPorts=1,
    use_T_in=false,
    m_flow=borFieUTubDat.conDat.mBor_flow_nominal,
    T=303.15) "Source"
  AixLib.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium,
    use_p_in=false,
    use_T_in=false,
    nPorts=1,
    p=101330,
    T=283.15) "Sink"
  AixLib.Fluid.Sensors.TemperatureTwoPort TBorIn1(
    m_flow_nominal=borFieUTubDat.conDat.mBor_flow_nominal,
    redeclare package Medium = Medium,
    tau=0) "Inlet borehole temperature"
  AixLib.Fluid.Sensors.TemperatureTwoPort TBor1UTubSteSta(
    m_flow_nominal=borFieUTubDat.conDat.mBor_flow_nominal,
    redeclare package Medium = Medium,
    tau=0) "Outlet borehole temperature"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector therCol2(m=nSeg)
    "Thermal collector"

  AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.TwoUTube borHol2UTubDyn(
    redeclare package Medium = Medium,
    dp_nominal=borFie2UTubDat.conDat.dp_nominal,
    m_flow_nominal=borFie2UTubDat.conDat.mBor_flow_nominal,
    borFieDat=borFie2UTubDat,
    nSeg=nSeg,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    TGro_start = {T_start for i in 1:nSeg},
    TFlu_start={Medium.T_default for i in 1:nSeg})
    "Borehole with 2U-Tub configuration and grout dynamics"
  AixLib.Fluid.Sources.MassFlowSource_T sou2(
    redeclare package Medium = Medium,
    nPorts=1,
    use_T_in=false,
    m_flow=borFie2UTubDat.conDat.mBor_flow_nominal,
    T=303.15) "Source"
  AixLib.Fluid.Sources.Boundary_pT sin2(
    redeclare package Medium = Medium,
    use_p_in=false,
    use_T_in=false,
    nPorts=1,
    p=101330,
    T=283.15) "Sink"
  parameter AixLib.Fluid.Geothermal.Borefields.Data.Borefield.Example borFie2UTubDat(
    conDat=AixLib.Fluid.Geothermal.Borefields.Data.Configuration.Example(
      borCon=AixLib.Fluid.Geothermal.Borefields.Types.BoreholeConfiguration.DoubleUTubeParallel))
    "Borefield parameters with UTube borehole configuration"
  AixLib.Fluid.Sensors.TemperatureTwoPort TBorIn2(redeclare package Medium =
        Medium, m_flow_nominal=borFie2UTubDat.conDat.mBor_flow_nominal,
    tau=0)
    "Inlet borehole temperature"
  AixLib.Fluid.Sensors.TemperatureTwoPort TBor2UTubDyn(redeclare package Medium =
        Medium, m_flow_nominal=borFie2UTubDat.conDat.mBor_flow_nominal,
    tau=0)
    "Outlet borehole temperature"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector therCol3(m=nSeg)
    "Thermal collector"

  AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.TwoUTube borHol2UTubSteSta(
    redeclare package Medium = Medium,
    dp_nominal=borFie2UTubDatSteSta.conDat.dp_nominal,
    m_flow_nominal=borFie2UTubDatSteSta.conDat.mBor_flow_nominal,
    borFieDat=borFie2UTubDatSteSta,
    nSeg=nSeg,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    TGro_start = {T_start for i in 1:nSeg},
    TFlu_start={Medium.T_default for i in 1:nSeg})
    "Borehole with 2U-Tub configuration and steady states grout"
  AixLib.Fluid.Sources.MassFlowSource_T sou3(
    redeclare package Medium = Medium,
    nPorts=1,
    use_T_in=false,
    m_flow=borFie2UTubDat.conDat.mBor_flow_nominal,
    T=303.15) "Source"
  AixLib.Fluid.Sources.Boundary_pT sin3(
    redeclare package Medium = Medium,
    use_p_in=false,
    use_T_in=false,
    nPorts=1,
    p=101330,
    T=283.15) "Sink"
  AixLib.Fluid.Sensors.TemperatureTwoPort TBorIn3(
    redeclare package Medium = Medium,
    m_flow_nominal=borFie2UTubDat.conDat.mBor_flow_nominal,
    tau=0)
    "Inlet borehole temperature"
  AixLib.Fluid.Sensors.TemperatureTwoPort TBor2UTubSteSta(
    redeclare package Medium = Medium,
    m_flow_nominal=borFie2UTubDat.conDat.mBor_flow_nominal,
    tau=0)
    "Outlet borehole temperature"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector therCol4(m=nSeg)
                                    "Thermal collector"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature
    prescribedTemperature
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature
    prescribedTemperature1
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature
    prescribedTemperature2
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature
    prescribedTemperature3
  parameter AixLib.Fluid.Geothermal.Borefields.Data.Borefield.Example borFieUTubDatSteSta(filDat=
        AixLib.Fluid.Geothermal.Borefields.Data.Filling.Bentonite(
        steadyState=true))
    "Borefield parameters with UTube borehole configuration and steady-state filling"
  parameter AixLib.Fluid.Geothermal.Borefields.Data.Borefield.Example borFie2UTubDatSteSta(
    filDat=AixLib.Fluid.Geothermal.Borefields.Data.Filling.Bentonite(
        steadyState=true),
    conDat=AixLib.Fluid.Geothermal.Borefields.Data.Configuration.Example(
        borCon=AixLib.Fluid.Geothermal.Borefields.Types.BoreholeConfiguration.DoubleUTubeParallel))
    "Borefield parameters with UTube borehole configuration and steady-state filling"
equation
  connect(sou.ports[1],TBorIn. port_a)
  connect(TBorIn.port_b, borHolOneUTubDyn.port_a)
  connect(borHolOneUTubDyn.port_b, TBor1UTubDyn.port_a)
  connect(TBor1UTubDyn.port_b, sin.ports[1])
  connect(therCol1.port_a, borHolOneUTubDyn.port_wall)
  connect(sou1.ports[1], TBorIn1.port_a)
  connect(TBorIn1.port_b, borHolOneUTubSteSta.port_a)
  connect(borHolOneUTubSteSta.port_b, TBor1UTubSteSta.port_a)
  connect(TBor1UTubSteSta.port_b, sin1.ports[1])
  connect(therCol2.port_a, borHolOneUTubSteSta.port_wall)
  connect(sou2.ports[1], TBorIn2.port_a)
  connect(TBorIn2.port_b, borHol2UTubDyn.port_a)
  connect(borHol2UTubDyn.port_b, TBor2UTubDyn.port_a)
  connect(TBor2UTubDyn.port_b, sin2.ports[1])
  connect(therCol3.port_a, borHol2UTubDyn.port_wall)
  connect(sou3.ports[1], TBorIn3.port_a)
  connect(TBorIn3.port_b, borHol2UTubSteSta.port_a)
  connect(borHol2UTubSteSta.port_b, TBor2UTubSteSta.port_a)
  connect(TBor2UTubSteSta.port_b, sin3.ports[1])
  connect(therCol4.port_a, borHol2UTubSteSta.port_wall)
  connect(TGroUn.y, prescribedTemperature.T)
  connect(therCol1.port_b, prescribedTemperature.port)
  connect(therCol2.port_b, prescribedTemperature1.port)
  connect(TGroUn.y, prescribedTemperature1.T)
  connect(therCol3.port_b, prescribedTemperature2.port)
  connect(prescribedTemperature2.T, prescribedTemperature1.T)
  connect(therCol4.port_b, prescribedTemperature3.port)
  connect(prescribedTemperature3.T, prescribedTemperature1.T)
end BoreholeDynamics;


Test for the single U-tube borehole model. This example illustrates the use of the

AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.OneUTubes
model. It simulates the behavior of a borehole with a prescribed
borehole wall temperature boundary condition.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.Examples;
model BoreholeOneUTube "Test for the single U-tube borehole model"
  extends Modelica.Icons.Example;
  extends
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.Examples.BaseClasses.PartialBorehole(
      redeclare
      AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.OneUTube
      borHol(
        energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial));
end BoreholeOneUTube;


Test for the double U-tube borehole model. This example illustrates the use of the

AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.TwoUTube
model. It simulates the behavior of a borehole with a prescribed
borehole wall boundary condition.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.Examples;
model BoreholeTwoUTube "Test for the double U-tube borehole model"
  extends Modelica.Icons.Example;
  extends AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.Examples.BaseClasses.PartialBorehole(
      redeclare AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.TwoUTube
        borHol(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial),
      borFieDat(
        conDat=AixLib.Fluid.Geothermal.Borefields.Data.Configuration.Example(
          borCon=AixLib.Fluid.Geothermal.Borefields.Types.BoreholeConfiguration.DoubleUTubeParallel)));
end BoreholeTwoUTube;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes;
package Examples "Example files for borehole heat exchanger"
extends Modelica.Icons.ExamplesPackage;
end Examples;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.Examples;
package BaseClasses "Package with base classes for AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.Examples"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.Examples.BaseClasses;
partial model PartialBorehole "Partial model for borehole example models"
  package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater;

  parameter Integer nSeg(min=1) = 10
    "Number of segments to use in vertical discretization of the boreholes";
  parameter Modelica.Units.SI.Temperature T_start=273.15 + 22
    "Initial soil temperature";

  parameter AixLib.Fluid.Geothermal.Borefields.Data.Borefield.Example
    borFieDat "Borefield parameters"

  replaceable AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.PartialBorehole borHol
    constrainedby
    AixLib.Fluid.Geothermal.Borefields.BaseClasses.Boreholes.BaseClasses.PartialBorehole(
    redeclare package Medium = Medium,
    borFieDat=borFieDat,
    m_flow_nominal=borFieDat.conDat.mBor_flow_nominal,
    dp_nominal=borFieDat.conDat.dp_nominal,
    nSeg=nSeg,
    TGro_start={T_start for i in 1:nSeg},
    TFlu_start={Medium.T_default for i in 1:nSeg})
    "Borehole connected to a discrete ground model"

  AixLib.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    nPorts=1,
    use_T_in=false,
    m_flow=borFieDat.conDat.mBor_flow_nominal,
    T=303.15) "Source"

  AixLib.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    use_p_in=false,
    use_T_in=false,
    nPorts=1,
    p=101330,
    T=283.15) "Sink"

  AixLib.Fluid.Sensors.TemperatureTwoPort TBorIn(m_flow_nominal=borFieDat.conDat.mBor_flow_nominal,
      redeclare package Medium = Medium,
    tau=0) "Inlet borehole temperature"
  AixLib.Fluid.Sensors.TemperatureTwoPort TBorOut(m_flow_nominal=borFieDat.conDat.mBor_flow_nominal,
      redeclare package Medium = Medium,
    tau=0) "Outlet borehole temperature"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature preTem[nSeg](each T=T_start)
    "Prescribed temperature"
equation
  connect(sou.ports[1], TBorIn.port_a)
  connect(TBorIn.port_b, borHol.port_a)
  connect(borHol.port_b, TBorOut.port_a)
  connect(TBorOut.port_b, sin.ports[1])

  connect(borHol.port_wall, preTem.port)
end PartialBorehole;


Heat conduction in a cylinder using the radial discretization as advised by Eskilson. Model for radial heat transfer in a hollow cylinder.

within AixLib.Fluid.Geothermal.Borefields.BaseClasses.HeatTransfer;
model Cylindrical
  "Heat conduction in a cylinder using the radial discretization as advised by Eskilson"

  parameter AixLib.Fluid.Geothermal.Borefields.Data.Soil.Template soiDat
  parameter Modelica.Units.SI.Height h "Height of the cylinder";
  parameter Modelica.Units.SI.Radius r_a "Internal radius";
  parameter Modelica.Units.SI.Radius r_b "External radius";
  parameter Integer nSta(min=1) = 10 "Number of state variables";
  parameter Modelica.Units.SI.Temperature TInt_start
    "Initial temperature at port_a, used if steadyStateInitial = false"
  parameter Modelica.Units.SI.Temperature TExt_start
    "Initial temperature at port_b, used if steadyStateInitial = false"
  parameter Boolean steadyStateInitial=false
    "true initializes dT(0)/dt=0, false initializes T(0) at fixed temperature using T_a_start and T_b_start"

  parameter Real gridFac(min=1) = 2 "Grid factor for spacing";

  parameter Modelica.Units.SI.Radius r[nSta + 1](each fixed=false)
    "Radius to the boundary of the i-th domain";

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a(T(start=TInt_start))
    "Heat port at surface a"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b port_b(T(start=TExt_start))
    "Heat port at surface b"

  Modelica.Units.SI.Temperature T[nSta](start={TInt_start + (TExt_start -
        TInt_start)/Modelica.Math.log(r_b/r_a)*Modelica.Math.log((r_a + (r_b -
        r_a)/(nSta)*(i - 0.5))/r_a) for i in 1:nSta})
    "Temperature of the states";

  Modelica.Units.SI.TemperatureDifference dT "port_a.T - port_b.T";

  Modelica.Units.SI.HeatFlowRate Q_flow[nSta + 1]
    "Heat flow rate from state i to i+1";

protected
  parameter Modelica.Units.SI.Radius rC[nSta](each fixed=false)
    "Radius to the center of the i-th domain";

  final parameter Modelica.Units.SI.SpecificHeatCapacity c=soiDat.cSoi
    "Specific heat capacity";
  final parameter Modelica.Units.SI.ThermalConductivity k=soiDat.kSoi
    "Thermal conductivity of the material";
  final parameter Modelica.Units.SI.Density d=soiDat.dSoi
    "Density of the material";

  parameter Modelica.Units.SI.ThermalConductance G[nSta + 1](each fixed=false)
    "Heat conductance between the temperature nodes";
  parameter Modelica.Units.SI.HeatCapacity C[nSta](each fixed=false)
    "Heat capacity of each state";

  parameter Real gridFac_sum(fixed=false);
  parameter Real gridFac_sum_old(fixed=false);

initial algorithm
  for i in 0:nSta - 3 - 1 loop
    if i == 0 then
      gridFac_sum := gridFac^i;
      gridFac_sum_old := gridFac_sum;
    else
      gridFac_sum := gridFac_sum_old + gridFac^i;
      gridFac_sum_old := gridFac_sum;
    end if;
  end for;

initial equation
  assert(r_a < r_b, "Error: Model requires r_a < r_b.");
  assert(0 < r_a, "Error: Model requires 0 < r_a.");

  // ****************** Comments *********************:
  // The layer is divided into nSta segments. The radius of each segment increase exponentially with base 'griFac':
  // r_b - r_a = sum( a * griFac^k - a , k=2..nSta) => from this we find a = (r_b - r_a)/(griFac^(n+1) - griFac)
  // Using this a, we can now find the r[i]:
  // r[1] := r_a
  // r[i] = r[i-1] + a * griFac^i = r[i-1] + griFac^i * (r_b - r_a) / (griFac^(n+1) - griFac)
  //
  // This can also be writing as:
  // r[i]= r[i-1] + ( r_b - r_a)  * (1-griFac)/(1-griFac^(nSta)) * griFac^(i-2);

  r[1] = r_a;
  r[2] = r_a + sqrt(k/c/d*60) "eskilson minimum length";
  r[3] = r_a + 2*sqrt(k/c/d*60);
  r[4] = r_a + 3*sqrt(k/c/d*60);

  for i in 5:nSta + 1 loop
    r[i] = r[i - 1] + (r_b - r[4])/gridFac_sum*gridFac^(i - 5);
  end for;
  assert(abs(r[nSta + 1] - r_b) < 1E-3,
    "Error: Wrong computation of radius. r[nSta+1]=" + String(r[nSta + 1]));

  // Radii at middle of resistance
  for i in 1:nSta loop
    rC[i] = (r[i] + r[i + 1])/2;
  end for;

  // Conductance between nodes (which are in the center of the domain)
  G[1] = 2*Modelica.Constants.pi*k*h/Modelica.Math.log(rC[1]/r_a);
  G[nSta + 1] = 2*Modelica.Constants.pi*k*h/Modelica.Math.log(r_b/rC[nSta]);
  for i in 2:nSta loop
    G[i] = 2*Modelica.Constants.pi*k*h/Modelica.Math.log(rC[i]/rC[i - 1]);
  end for;

  // Heat capacity of each segment
  for i in 1:nSta loop
    C[i] = (d*Modelica.Constants.pi*c*h*((r[i + 1])^2 - (r[i])^2));
  end for;
  // The initialization is only done for materials that store energy.
  if not soiDat.steadyState then
    if steadyStateInitial then
      der(T) = zeros(nSta);
    else
      for i in 1:nSta loop
        T[i] = TInt_start + (TExt_start - TInt_start)/Modelica.Math.log(r_b/r_a)
          *Modelica.Math.log(rC[i]/r_a);
      end for;
    end if;
  end if;
equation
  dT = port_a.T - port_b.T;
  port_a.Q_flow = +Q_flow[1];
  port_b.Q_flow = -Q_flow[nSta + 1];
  Q_flow[1] = G[1]*(port_a.T - T[1]);
  Q_flow[nSta + 1] = G[nSta + 1]*(T[nSta] - port_b.T);
  for i in 2:nSta loop
    Q_flow[i] = G[i]*(T[i - 1] - T[i]);
    // Q_flow[i] represents the heat flowing between two nodes
  end for;
  if soiDat.steadyState then
    for i in 2:nSta + 1 loop
      Q_flow[i] = Q_flow[1];
    end for;
  else
    for i in 1:nSta loop
      der(T[i]) = (Q_flow[i] - Q_flow[i + 1])/C[i];
    end for;
  end if;
end Cylindrical;