within Modelica.Fluid.Examples;
package DrumBoiler
  "Drum boiler example, see Franke, Rode, Krüger: On-line Optimization of Drum Boiler Startup, 3rd International Modelica Conference, Linköping, 2003"

  extends Modelica.Icons.ExamplesPackage;
  model DrumBoiler
    "Complete drum boiler model, including evaporator and supplementary components"
    extends Modelica.Icons.Example;

    parameter Boolean use_inputs = false
      "= true, if external inputs are used, otherwise use test data contained internally";

    Modelica.Fluid.Examples.DrumBoiler.BaseClasses.EquilibriumDrumBoiler
      evaporator(
      m_D=300e3,
      cp_D=500,
      V_t=100,
      V_l_start=67,
      redeclare package Medium = Modelica.Media.Water.StandardWater,
      energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
      massDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
      p_start=100000)
    Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow furnace
    Modelica.Fluid.Sources.FixedBoundary sink(nPorts=1, p=Cv.from_bar(0.5),
      redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase,
      T=500)
    Modelica.Fluid.Sensors.MassFlowRate massFlowRate(redeclare
        package Medium =
          Modelica.Media.Water.StandardWater)
    Modelica.Fluid.Sensors.Temperature temperature(redeclare package Medium
        = Modelica.Media.Water.StandardWater)
    Modelica.Fluid.Sensors.Pressure pressure(redeclare package
        Medium =
          Modelica.Media.Water.StandardWater)
    Modelica.Blocks.Continuous.PI controller(T=120, k=10, initType=Modelica.Blocks.Types.Init.InitialState)
    Modelica.Fluid.Sources.MassFlowSource_h pump(nPorts=1,
                                             h=5e5, redeclare package Medium =
          Modelica.Media.Water.StandardWater,
      use_m_flow_in=true)
    Modelica.Blocks.Math.Feedback feedback
    Modelica.Blocks.Sources.Constant levelSetPoint(k=67)
    Modelica.Blocks.Interfaces.RealOutput T_S(final unit="degC") "Steam temperature"
    Modelica.Blocks.Interfaces.RealOutput p_S(final unit="bar") "Steam pressure"
    Modelica.Blocks.Interfaces.RealOutput qm_S(unit="kg/s") "Steam flow rate"
    Modelica.Blocks.Interfaces.RealOutput V_l(unit="m3") "Liquid volume inside drum"
  public
    Modelica.Blocks.Math.Gain MW2W(k=1e6)
    Modelica.Blocks.Math.Gain Pa2bar(k=1e-5)
    Modelica.Thermal.HeatTransfer.Celsius.FromKelvin K2degC
    Modelica.Blocks.Nonlinear.Limiter limiter(uMin=0, uMax=500)
    Modelica.Fluid.Valves.ValveLinear SteamValve(redeclare
        package Medium =
          Modelica.Media.Water.StandardWater,
      dp_nominal=9000000,
      m_flow_nominal=180)

    inner Modelica.Fluid.System system
    Modelica.Blocks.Sources.TimeTable q_F_Tab(table=[0, 0; 3600, 400; 7210,
          400]) if not use_inputs
    Modelica.Blocks.Sources.TimeTable Y_Valve_Tab(table=[0,0; 900,1; 7210,1]) if not use_inputs
    Blocks.Interfaces.RealInput q_F(unit="MW") if
                                       use_inputs "Fuel flow rate"
    Blocks.Interfaces.RealInput Y_Valve if use_inputs "Valve opening"
  equation
    connect(furnace.port, evaporator.heatPort)
    connect(controller.u,feedback.y)
    connect(massFlowRate.m_flow, qm_S)
    connect(evaporator.V, V_l)
    connect(MW2W.y,furnace.Q_flow)
    connect(pressure.p, Pa2bar.u)
    connect(Pa2bar.y, p_S)
    connect(K2degC.Celsius, T_S)
    connect(controller.y, limiter.u)
    connect(limiter.y, pump.m_flow_in)
    connect(temperature.T, K2degC.Kelvin)
    connect(pressure.port, massFlowRate.port_a)
    connect(pump.ports[1], evaporator.port_a)
    connect(massFlowRate.port_b, SteamValve.port_a)
    connect(SteamValve.port_b, sink.ports[1])
    connect(evaporator.port_b, massFlowRate.port_a)
    connect(temperature.port, massFlowRate.port_a)
    connect(q_F_Tab.y, MW2W.u)
    connect(Y_Valve_Tab.y, SteamValve.opening)
    connect(q_F, MW2W.u)
    connect(Y_Valve, SteamValve.opening)
    connect(evaporator.V, feedback.u2)
    connect(levelSetPoint.y, feedback.u1)
  end DrumBoiler;

  package BaseClasses "Additional components for drum boiler example"
    extends Modelica.Icons.BasesPackage;

    model EquilibriumDrumBoiler
      "Simple Evaporator with two states, see Åström, Bell: Drum-boiler dynamics, Automatica 36, 2000, pp.363-378"
      extends Modelica.Fluid.Interfaces.PartialTwoPort(
        final port_a_exposesState=true,
        final port_b_exposesState=true,
        redeclare replaceable package Medium =
            Modelica.Media.Water.StandardWater
            constrainedby Modelica.Media.Interfaces.PartialTwoPhaseMedium);
      import Modelica.Constants;
      import Modelica.Fluid.Types;

      parameter SI.Mass m_D "Mass of surrounding drum metal";
      parameter Medium.SpecificHeatCapacity cp_D
        "Specific heat capacity of drum metal";
      parameter SI.Volume V_t "Total volume inside drum";
      parameter Medium.AbsolutePressure p_start=system.p_start
        "Start value of pressure"
      parameter SI.Volume V_l_start=V_t/2
        "Start value of liquid volumeStart value of volume"

      // Assumptions
      parameter Boolean allowFlowReversal = system.allowFlowReversal
        "= true, if flow reversal is enabled, otherwise restrict flow to design direction (port_a -> port_b)"
      parameter Types.Dynamics energyDynamics=system.energyDynamics
        "Formulation of energy balance"
      parameter Types.Dynamics massDynamics=system.massDynamics
        "Formulation of mass balance"

      Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
      Modelica.Blocks.Interfaces.RealOutput V(unit="m3") "Liquid volume"

      Medium.SaturationProperties sat
        "State vector to compute saturation properties";
      Medium.AbsolutePressure p(start=p_start, stateSelect=StateSelect.prefer)
        "Pressure inside drum boiler";
      Medium.Temperature T "Temperature inside drum boiler";
      SI.Volume V_v "Volume of vapour phase";
      SI.Volume V_l(start=V_l_start, stateSelect=StateSelect.prefer)
        "Volumes of liquid phase";
      Medium.SpecificEnthalpy h_v=Medium.dewEnthalpy(sat)
        "Specific enthalpy of vapour";
      Medium.SpecificEnthalpy h_l=Medium.bubbleEnthalpy(sat)
        "Specific enthalpy of liquid";
      Medium.Density rho_v=Medium.dewDensity(sat) "Density in vapour phase";
      Medium.Density rho_l=Medium.bubbleDensity(sat) "Density in liquid phase";
      SI.Mass m "Total mass of drum boiler";
      SI.Energy U "Internal energy";
      Medium.Temperature T_D=heatPort.T "Temperature of drum";
      SI.HeatFlowRate q_F=heatPort.Q_flow "Heat flow rate from furnace";
      Medium.SpecificEnthalpy h_W=inStream(port_a.h_outflow)
        "Feed water enthalpy (specific enthalpy close to feedwater port when mass flows in to the boiler)";
      Medium.SpecificEnthalpy h_S=inStream(port_b.h_outflow)
        "Steam enthalpy (specific enthalpy close to steam port when mass flows in to the boiler)";
      SI.MassFlowRate qm_W=port_a.m_flow "Feed water mass flow rate";
      SI.MassFlowRate qm_S=port_b.m_flow "Steam mass flow rate";
    /*outer Modelica.Fluid.Components.FluidOptions fluidOptions
    "Global default options";*/
    equation
    // balance equations
      m = rho_v*V_v + rho_l*V_l + m_D "Total mass";
      U = rho_v*V_v*h_v + rho_l*V_l*h_l - p*V_t + m_D*cp_D*T_D "Total energy";
      if massDynamics == Types.Dynamics.SteadyState then
        0 = qm_W + qm_S "Steady state mass balance";
      else
        der(m) = qm_W + qm_S "Dynamic mass balance";
      end if;
      if energyDynamics == Types.Dynamics.SteadyState then
        0 = q_F + port_a.m_flow*actualStream(port_a.h_outflow)
                + port_b.m_flow*actualStream(port_b.h_outflow)
          "Steady state energy balance";
      else
        der(U) = q_F
                + port_a.m_flow*actualStream(port_a.h_outflow)
                + port_b.m_flow*actualStream(port_b.h_outflow)
          "Dynamic energy balance";
      end if;
      V_t = V_l + V_v;

    // Properties of saturated liquid and steam
      sat.psat = p;
      sat.Tsat = T;
      sat.Tsat = Medium.saturationTemperature(p);

    // ideal heat transfer between metal and water
      T_D = T;

    // boundary conditions at the ports
      port_a.p = p;
      port_a.h_outflow = h_l;
      port_b.p = p;
      port_b.h_outflow = h_v;

    // liquid volume
      V = V_l;

    // Check that two-phase equilibrium is actually possible
      assert(p < Medium.fluidConstants[1].criticalPressure - 10000,
        "Evaporator model requires subcritical pressure");
    initial equation
    // Initial conditions
      // Note: p represents the energy as it is constrained by T_sat
      if energyDynamics == Types.Dynamics.FixedInitial then
        p = p_start;
      elseif energyDynamics == Types.Dynamics.SteadyStateInitial then
        der(p) = 0;
      end if;

      if massDynamics == Types.Dynamics.FixedInitial then
        V_l = V_l_start;
      elseif energyDynamics == Types.Dynamics.SteadyStateInitial then
        der(V_l) = 0;
      end if;
    end EquilibriumDrumBoiler;
  end BaseClasses;
end DrumBoiler;


within Modelica.Fluid.Examples;
package Explanatory
  "A set of examples illustrating when special attention has to be paid"
  extends Modelica.Icons.ExamplesPackage;

  model MeasuringTemperature "Differences between using one port with and without explicit junction model and two port sensors for fluid temperature measuring"
     extends Modelica.Icons.Example;
    Modelica.Fluid.Sensors.Temperature T_onePort(redeclare package Medium =
          Modelica.Media.Water.StandardWater)
    Modelica.Fluid.Sensors.TemperatureTwoPort T_twoPort(redeclare package
        Medium =
          Modelica.Media.Water.StandardWater)
    inner Modelica.Fluid.System system(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    Modelica.Fluid.Vessels.OpenTank openTankCold2(nPorts=1,
      redeclare package Medium = Modelica.Media.Water.StandardWater,
      height=2,
      crossArea=2,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.05)},
      level_start=0.975,
      T_start=293.15)
    Modelica.Fluid.Vessels.OpenTank openTankCold1(
      redeclare package Medium = Modelica.Media.Water.StandardWater,
      height=2,
      crossArea=2,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.05)},
      nPorts=1,
      level_start=0.975,
      T_start=293.15)
    Modelica.Fluid.Vessels.OpenTank openTankHot1(nPorts=1,
      level_start=1,
      redeclare package Medium = Modelica.Media.Water.StandardWater,
      height=2,
      crossArea=2,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.05)},
      T_start=353.15)
    Modelica.Fluid.Vessels.OpenTank openTankHot2(nPorts=1,
      level_start=1,
      redeclare package Medium = Modelica.Media.Water.StandardWater,
      height=2,
      crossArea=2,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.05)},
      T_start=353.15)
    Modelica.Fluid.Sources.MassFlowSource_T mFlow1(
      nPorts=1,
      redeclare package Medium = Modelica.Media.Water.StandardWater,
      use_m_flow_in=true,
      use_T_in=false,
      T=323.15)
    Modelica.Fluid.Sources.MassFlowSource_T mFlow2(
      nPorts=1,
      redeclare package Medium = Modelica.Media.Water.StandardWater,
      use_m_flow_in=true,
      T=323.15)
    Modelica.Blocks.Sources.Sine sine(f=1)
    Modelica.Fluid.Sensors.Temperature T_junction(redeclare package Medium =
          Modelica.Media.Water.StandardWater)
    Modelica.Fluid.Vessels.OpenTank openTankCold3(nPorts=1,
      redeclare package Medium = Modelica.Media.Water.StandardWater,
      height=2,
      crossArea=2,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.05)},
      level_start=0.975,
      T_start=293.15)
    Modelica.Fluid.Vessels.OpenTank openTankHot3(nPorts=1,
      level_start=1,
      redeclare package Medium = Modelica.Media.Water.StandardWater,
      height=2,
      crossArea=2,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.05)},
      T_start=353.15)
    Modelica.Fluid.Sources.MassFlowSource_T mFlow3(
      nPorts=1,
      redeclare package Medium = Modelica.Media.Water.StandardWater,
      use_m_flow_in=true,
      T=323.15)
    Modelica.Fluid.Fittings.TeeJunctionIdeal junctionIdeal(
                                                         redeclare package
        Medium =
          Modelica.Media.Water.StandardWater)
  equation
    connect(mFlow2.ports[1], T_twoPort.port_a)
    connect(mFlow1.ports[1], T_onePort.port)
    connect(sine.y, mFlow1.m_flow_in)
    connect(sine.y, mFlow2.m_flow_in)
    connect(mFlow3.ports[1], T_junction.port)
    connect(sine.y, mFlow3.m_flow_in)
    connect(T_junction.port, junctionIdeal.port_1)
    connect(T_twoPort.port_b, openTankCold2.ports[1])
    connect(T_onePort.port, openTankHot1.ports[1])
    connect(T_twoPort.port_b, openTankHot2.ports[1])
    connect(junctionIdeal.port_3, openTankCold3.ports[1])
    connect(junctionIdeal.port_2, openTankHot3.ports[1])
    connect(T_onePort.port, openTankCold1.ports[1])
  end MeasuringTemperature;

  model MomentumBalanceFittings
    "Illustrating a case in which kinetic terms play a major role in the momentum balance"
     extends Modelica.Icons.Example;
    Modelica.Fluid.Sources.Boundary_pT leftBoundary1(
      redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase,
      nPorts=1,
      p=100000)
    Modelica.Fluid.Sources.Boundary_pT rightBoundary1(
      redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase,
      nPorts=1,
      p=110000)
    Modelica.Fluid.Fittings.AbruptAdaptor suddenExpansion1(
      diameter_a=0.1,
      diameter_b=0.2,
      m_flow_start=60,
      redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase,
      show_totalPressures=true,
      show_portVelocities=true)
    Modelica.Fluid.Sources.Boundary_pT leftBoundary2(
      redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase,
      nPorts=1,
      p=100000)
    Modelica.Fluid.Sources.Boundary_pT rightBoundary2(
      redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase,
      nPorts=1,
      p=110000)
    Modelica.Fluid.Fittings.AbruptAdaptor suddenExpansion2(
      diameter_a=0.1,
      diameter_b=0.2,
      redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase,
      show_totalPressures=true,
      show_portVelocities=true)
    Modelica.Fluid.Fittings.AbruptAdaptor leftAdaptor(
      diameter_a=0.1,
      redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase,
      diameter_b=1e60)
    Modelica.Fluid.Fittings.AbruptAdaptor rightAdaptor(
      redeclare package Medium = Modelica.Media.Water.StandardWaterOnePhase,
      diameter_a=0.2,
      diameter_b=1e60)
    inner System system
  equation
    connect(leftBoundary1.ports[1], suddenExpansion1.port_a)
    connect(suddenExpansion1.port_b, rightBoundary1.ports[1])
    connect(leftAdaptor.port_b, leftBoundary2.ports[1])
    connect(leftAdaptor.port_a, suddenExpansion2.port_a)
    connect(suddenExpansion2.port_b,rightAdaptor. port_a)
    connect(rightAdaptor.port_b, rightBoundary2.ports[1])
  end MomentumBalanceFittings;
end Explanatory;


Demo of a heat exchanger model

within Modelica.Fluid.Examples;
package HeatExchanger "Demo of a heat exchanger model"
  extends Modelica.Icons.ExamplesPackage;

  model HeatExchangerSimulation "Simulation for the heat exchanger model"

  extends Modelica.Icons.Example;

  //replaceable package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater;
  replaceable package Medium = Modelica.Media.Water.StandardWaterOnePhase;
  //package Medium = Modelica.Media.Incompressible.Examples.Essotherm650;
    Modelica.Fluid.Examples.HeatExchanger.BaseClasses.BasicHX HEX(
      c_wall=500,
      use_T_start=true,
      nNodes=20,
      m_flow_start_1=0.2,
      m_flow_start_2=0.2,
      k_wall=100,
      s_wall=0.005,
      crossArea_1=4.5e-4,
      crossArea_2=4.5e-4,
      perimeter_1=0.075,
      perimeter_2=0.075,
      rho_wall=900,
      redeclare package Medium_1 =
          Medium,
      redeclare package Medium_2 =
          Medium,
      modelStructure_1=Modelica.Fluid.Types.ModelStructure.av_b,
      modelStructure_2=Modelica.Fluid.Types.ModelStructure.a_vb,
      redeclare model HeatTransfer_1 =
          Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.LocalPipeFlowHeatTransfer
          (alpha0=1000),
      length=20,
      area_h_1=0.075*20,
      area_h_2=0.075*20,
      redeclare model HeatTransfer_2 =
          Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.ConstantFlowHeatTransfer
          (alpha0=2000),
      Twall_start=300,
      dT=1,
      T_start_1=304,
      T_start_2=300)

    Modelica.Fluid.Sources.Boundary_pT ambient2(nPorts=1,
      p=1e5,
      T=280,
      redeclare package Medium = Medium)
    Modelica.Fluid.Sources.Boundary_pT ambient1(nPorts=1,
      p=1e5,
      T=300,
      redeclare package Medium = Medium)
    Modelica.Fluid.Sources.MassFlowSource_T massFlowRate2(nPorts=1,
      m_flow=0.2,
      T=360,
      redeclare package Medium = Medium,
      use_m_flow_in=true,
      use_T_in=false,
      use_X_in=false)
    Modelica.Fluid.Sources.MassFlowSource_T massFlowRate1(nPorts=1,
      redeclare package Medium = Medium,
      m_flow=0.2,
      T=300)
    Modelica.Blocks.Sources.Ramp Ramp1(
      startTime=50,
      duration=5,
      height=0.4,
      offset=-0.2)
    inner Modelica.Fluid.System system(energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial,
        use_eps_Re=true)
  equation
    connect(massFlowRate1.ports[1], HEX.port_a1)
    connect(HEX.port_b1, ambient1.ports[1])
    connect(Ramp1.y, massFlowRate2.m_flow_in)
    connect(massFlowRate2.ports[1], HEX.port_b2)
    connect(HEX.port_a2, ambient2.ports[1])
  end HeatExchangerSimulation;

  package BaseClasses "Additional models for heat exchangers"
    extends Modelica.Icons.BasesPackage;

    model BasicHX "Simple heat exchanger model"
      outer Modelica.Fluid.System system "System properties";
      //General
      parameter SI.Length length(min=0) "Length of flow path for both fluids";
      parameter Integer nNodes(min=1) = 2 "Spatial segmentation";
      parameter Modelica.Fluid.Types.ModelStructure modelStructure_1=Types.ModelStructure.av_vb
        "Determines whether flow or volume models are present at the ports"
      parameter Modelica.Fluid.Types.ModelStructure modelStructure_2=Types.ModelStructure.av_vb
        "Determines whether flow or volume models are present at the ports"
      replaceable package Medium_1 = Modelica.Media.Water.StandardWater constrainedby
        Modelica.Media.Interfaces.PartialMedium "Fluid 1"
      replaceable package Medium_2 = Modelica.Media.Water.StandardWater constrainedby
        Modelica.Media.Interfaces.PartialMedium "Fluid 2"
      parameter SI.Area crossArea_1 "Cross sectional area"
      parameter SI.Area crossArea_2 "Cross sectional area"
      parameter SI.Length perimeter_1 "Flow channel perimeter"
      parameter SI.Length perimeter_2 "Flow channel perimeter"
      final parameter Boolean use_HeatTransfer = true
        "= true to use the HeatTransfer_1/_2 model";

      // Heat transfer
      replaceable model HeatTransfer_1 =
          Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer
        constrainedby
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.PartialFlowHeatTransfer
        "Heat transfer model"

      replaceable model HeatTransfer_2 =
          Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer
        constrainedby
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.PartialFlowHeatTransfer
        "Heat transfer model"

      parameter SI.Area area_h_1 "Heat transfer area"
      parameter SI.Area area_h_2 "Heat transfer area"
     //Wall
      parameter SI.Length s_wall(min=0) "Wall thickness"
      parameter SI.ThermalConductivity k_wall
        "Thermal conductivity of wall material"
      parameter SI.SpecificHeatCapacity c_wall
        "Specific heat capacity of wall material"
      parameter SI.Density rho_wall "Density of wall material"
      final parameter SI.Area area_h=(area_h_1 + area_h_2)/2
        "Heat transfer area";
      final parameter SI.Mass m_wall=rho_wall*area_h*s_wall "Wall mass";

      // Assumptions
      parameter Boolean allowFlowReversal = system.allowFlowReversal
        "Allow flow reversal, false restricts to design direction (port_a -> port_b)"
      parameter Modelica.Fluid.Types.Dynamics energyDynamics=system.energyDynamics
        "Formulation of energy balance"
      parameter Modelica.Fluid.Types.Dynamics massDynamics=system.massDynamics
        "Formulation of mass balance"
      parameter Modelica.Fluid.Types.Dynamics momentumDynamics=system.momentumDynamics
        "Formulation of momentum balance, if pressureLoss options available"

      //Initialization pipe 1
      parameter SI.Temperature Twall_start "Start value of wall temperature"
      parameter SI.TemperatureDifference dT "Start value for pipe_1.T - pipe_2.T"
      parameter Boolean use_T_start=true
        "Use T_start if true, otherwise h_start"
      parameter Medium_1.AbsolutePressure p_a_start1=Medium_1.p_default
        "Start value of pressure"
      parameter Medium_1.AbsolutePressure p_b_start1=Medium_1.p_default
        "Start value of pressure"
      parameter Medium_1.Temperature T_start_1=if use_T_start then Medium_1.
          T_default else Medium_1.temperature_phX(
            (p_a_start1 + p_b_start1)/2,
            h_start_1,
            X_start_1) "Start value of temperature"
      parameter Medium_1.SpecificEnthalpy h_start_1=if use_T_start then Medium_1.specificEnthalpy_pTX(
            (p_a_start1 + p_b_start1)/2,
            T_start_1,
            X_start_1) else Medium_1.h_default
        "Start value of specific enthalpy"
      parameter Medium_1.MassFraction X_start_1[Medium_1.nX]=Medium_1.X_default
        "Start value of mass fractions m_i/m"
      parameter Medium_1.MassFlowRate m_flow_start_1 = system.m_flow_start
        "Start value of mass flow rate"
      //Initialization pipe 2

      parameter Medium_2.AbsolutePressure p_a_start2=Medium_2.p_default
        "Start value of pressure"
      parameter Medium_2.AbsolutePressure p_b_start2=Medium_2.p_default
        "Start value of pressure"
      parameter Medium_2.Temperature T_start_2=if use_T_start then Medium_2.
          T_default else Medium_2.temperature_phX(
            (p_a_start2 + p_b_start2)/2,
            h_start_2,
            X_start_2) "Start value of temperature"
      parameter Medium_2.SpecificEnthalpy h_start_2=if use_T_start then Medium_2.specificEnthalpy_pTX(
            (p_a_start2 + p_b_start2)/2,
            T_start_2,
            X_start_2) else Medium_2.h_default
        "Start value of specific enthalpy"
      parameter Medium_2.MassFraction X_start_2[Medium_2.nX]=Medium_2.X_default
        "Start value of mass fractions m_i/m"
      parameter Medium_2.MassFlowRate m_flow_start_2 = system.m_flow_start
        "Start value of mass flow rate"

      //Pressure drop and heat transfer
      replaceable model FlowModel_1 =
          Modelica.Fluid.Pipes.BaseClasses.FlowModels.DetailedPipeFlow
        constrainedby
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.PartialStaggeredFlowModel
        "Characteristic of wall friction"
      replaceable model FlowModel_2 =
          Modelica.Fluid.Pipes.BaseClasses.FlowModels.DetailedPipeFlow
        constrainedby
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.PartialStaggeredFlowModel
        "Characteristic of wall friction"
      parameter Modelica.Fluid.Types.Roughness roughness_1=2.5e-5
        "Absolute roughness of pipe (default = smooth steel pipe)"
      parameter Modelica.Fluid.Types.Roughness roughness_2=2.5e-5
        "Absolute roughness of pipe (default = smooth steel pipe)"

      //Display variables
      SI.HeatFlowRate Q_flow_1 "Total heat flow rate of pipe 1";
      SI.HeatFlowRate Q_flow_2 "Total heat flow rate of pipe 2";

      BaseClasses.WallConstProps wall(
        rho_wall=rho_wall,
        c_wall=c_wall,
        T_start=Twall_start,
        k_wall=k_wall,
        dT=dT,
        s=s_wall,
        energyDynamics=energyDynamics,
        n=nNodes,
        area_h=area_h)

      Pipes.DynamicPipe pipe_1(
        redeclare package Medium = Medium_1,
        final isCircular=false,
        final diameter=0,
        final nNodes=nNodes,
        final allowFlowReversal=allowFlowReversal,
        final energyDynamics=energyDynamics,
        final massDynamics=massDynamics,
        final momentumDynamics=momentumDynamics,
        final length=length,
        final use_HeatTransfer=use_HeatTransfer,
        redeclare model HeatTransfer = HeatTransfer_1,
        final use_T_start=use_T_start,
        final T_start=T_start_1,
        final h_start=h_start_1,
        final X_start=X_start_1,
        final m_flow_start=m_flow_start_1,
        final perimeter=perimeter_1,
        final crossArea=crossArea_1,
        final p_a_start=p_a_start1,
        final p_b_start=p_b_start1,
        final roughness=roughness_1,
        redeclare model FlowModel = FlowModel_1,
        final modelStructure=modelStructure_1)

      Pipes.DynamicPipe pipe_2(
        redeclare package Medium = Medium_2,
        final nNodes=nNodes,
        final allowFlowReversal=allowFlowReversal,
        final energyDynamics=energyDynamics,
        final massDynamics=massDynamics,
        final momentumDynamics=momentumDynamics,
        final length=length,
        final isCircular=false,
        final diameter=0,
        final use_HeatTransfer=use_HeatTransfer,
        redeclare model HeatTransfer = HeatTransfer_2,
        final use_T_start=use_T_start,
        final T_start=T_start_2,
        final h_start=h_start_2,
        final X_start=X_start_2,
        final m_flow_start=m_flow_start_2,
        final perimeter=perimeter_2,
        final crossArea=crossArea_2,
        final p_a_start=p_a_start2,
        final p_b_start=p_b_start2,
        final roughness=roughness_2,
        redeclare model FlowModel = FlowModel_2,
        final modelStructure=modelStructure_2)

      Modelica.Fluid.Interfaces.FluidPort_b port_b1(redeclare package
          Medium =
            Medium_1)
      Modelica.Fluid.Interfaces.FluidPort_a port_a1(redeclare package
          Medium =
            Medium_1)
      Modelica.Fluid.Interfaces.FluidPort_b port_b2(redeclare package
          Medium =
            Medium_2)
      Modelica.Fluid.Interfaces.FluidPort_a port_a2(redeclare package
          Medium =
            Medium_2)

    equation
      Q_flow_1 = sum(pipe_1.heatTransfer.Q_flows);
      Q_flow_2 = sum(pipe_2.heatTransfer.Q_flows);
      connect(pipe_2.port_b, port_b2)
      connect(pipe_1.port_b, port_b1)
      connect(pipe_1.port_a, port_a1)
      connect(pipe_2.port_a, port_a2)
      connect(wall.heatPort_b, pipe_1.heatPorts)
      connect(pipe_2.heatPorts[nNodes:-1:1], wall.heatPort_a[1:nNodes])
    end BasicHX;

    model WallConstProps
      "Pipe wall with capacitance, assuming 1D heat conduction and constant material properties"
      parameter Integer n(min=1)=1
        "Segmentation perpendicular to heat conduction";
    //Geometry
      parameter SI.Length s "Wall thickness";
      parameter SI.Area area_h "Heat transfer area";
    //Material properties
      parameter SI.Density rho_wall "Density of wall material";
      parameter SI.SpecificHeatCapacity c_wall
        "Specific heat capacity of wall material";
      parameter SI.ThermalConductivity k_wall
        "Thermal conductivity of wall material";
      parameter SI.Mass[n] m=fill(rho_wall*area_h*s/n,n)
        "Distribution of wall mass";
    //Initialization
      outer Modelica.Fluid.System system;
      parameter Modelica.Fluid.Types.Dynamics energyDynamics=system.energyDynamics
        "Formulation of energy balance"
      parameter SI.Temperature T_start "Wall temperature start value";
      parameter SI.TemperatureDifference dT "Start value for port_b.T - port_a.T";
    //Temperatures
      SI.Temperature[n] Tb(each start=T_start+0.5*dT);
      SI.Temperature[n] Ta(each start=T_start-0.5*dT);
      SI.Temperature[n] T(start=ones(n)*T_start, each stateSelect=StateSelect.prefer)
        "Wall temperature";
      Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a[n] heatPort_a
        "Thermal port"
      Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a[n] heatPort_b
        "Thermal port"

    initial equation
      if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyStateInitial then
        der(T) = zeros(n);
      elseif energyDynamics == Modelica.Fluid.Types.Dynamics.FixedInitial then
        T = ones(n)*T_start;
      end if;
    equation
      for i in 1:n loop
       assert(m[i]>0, "Wall has negative dimensions");
       if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState then
         0 = heatPort_a[i].Q_flow + heatPort_b[i].Q_flow;
       else
         c_wall*m[i]*der(T[i]) = heatPort_a[i].Q_flow + heatPort_b[i].Q_flow;
       end if;
       heatPort_a[i].Q_flow=2*k_wall/s*(Ta[i]-T[i])*area_h/n;
       heatPort_b[i].Q_flow=2*k_wall/s*(Tb[i]-T[i])*area_h/n;
      end for;
      Ta=heatPort_a.T;
      Tb=heatPort_b.T;
    end WallConstProps;
  end BaseClasses;
end HeatExchanger;


Simple model of a heating system

within Modelica.Fluid.Examples;
model HeatingSystem "Simple model of a heating system"
  extends Modelica.Icons.Example;
   replaceable package Medium =
      Modelica.Media.CompressibleLiquids.LinearWater_pT_Ambient
     constrainedby Modelica.Media.Interfaces.PartialMedium;

  Modelica.Fluid.Vessels.OpenTank tank(
    redeclare package Medium = Medium,
    crossArea=0.01,
    height=2,
    level_start=1,
    nPorts=2,
    massDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    use_HeatTransfer=true,
    portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=
        0.01),Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=
        0.01)},
    redeclare model HeatTransfer =
        Modelica.Fluid.Vessels.BaseClasses.HeatTransfer.IdealHeatTransfer (k=10),
    ports(each p(start=1.1e5)),
    T_start=Modelica.Units.Conversions.from_degC(20))
  Machines.ControlledPump pump(
    redeclare package Medium = Medium,
    N_nominal=1500,
    use_T_start=true,
    T_start=Modelica.Units.Conversions.from_degC(40),
    m_flow_start=0.01,
    m_flow_nominal=0.01,
    control_m_flow=false,
    allowFlowReversal=false,
    p_a_start=110000,
    p_b_start=130000,
    p_a_nominal=110000,
    p_b_nominal=130000)
  Modelica.Fluid.Valves.ValveIncompressible valve(
    redeclare package Medium = Medium,
    CvData=Modelica.Fluid.Types.CvTypes.OpPoint,
    m_flow_nominal=0.01,
    show_T=true,
    allowFlowReversal=false,
    dp_start=18000,
    dp_nominal=10000)
protected
  Modelica.Blocks.Interfaces.RealOutput m_flow(unit="kg/s")
public
  Sensors.MassFlowRate sensor_m_flow(redeclare package Medium = Medium)
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature T_ambient(T=system.T_ambient)
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor wall(G=1.6e3/20)
  Modelica.Thermal.HeatTransfer.Sources.FixedHeatFlow burner(
                                                     Q_flow=1.6e3,
    T_ref=343.15,
    alpha=-0.5)
  inner Modelica.Fluid.System system(
      m_flow_small=1e-4, energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial)
  Pipes.DynamicPipe heater(
    redeclare package Medium = Medium,
    use_T_start=true,
    T_start=Modelica.Units.Conversions.from_degC(80),
    length=2,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    diameter=0.01,
    nNodes=1,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.DetailedPipeFlow,
    use_HeatTransfer=true,
    modelStructure=Modelica.Fluid.Types.ModelStructure.a_v_b,
    p_a_start=130000)

  Pipes.DynamicPipe radiator(
    use_T_start=true,
    redeclare package Medium = Medium,
    length=10,
    T_start=Modelica.Units.Conversions.from_degC(40),
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    diameter=0.01,
    nNodes=1,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.DetailedPipeFlow,
    use_HeatTransfer=true,
    modelStructure=Modelica.Fluid.Types.ModelStructure.a_v_b,
    p_a_start=110000,
    state_a(p(start=110000)),
    state_b(p(start=110000)))

protected
  Modelica.Blocks.Interfaces.RealOutput T_forward(unit="K")
  Modelica.Blocks.Interfaces.RealOutput T_return(unit="K")
public
  Modelica.Fluid.Sensors.Temperature sensor_T_forward(redeclare package Medium
      = Medium)
  Modelica.Fluid.Sensors.Temperature sensor_T_return(redeclare package Medium
      = Medium)
protected
  Modelica.Blocks.Interfaces.RealOutput tankLevel(unit="m")
public
  Modelica.Blocks.Sources.Step handle(
    startTime=2000,
    height=0.9,
    offset=0.1)
  Pipes.DynamicPipe pipe(
    redeclare package Medium = Medium,
    use_T_start=true,
    T_start=Modelica.Units.Conversions.from_degC(80),
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    diameter=0.01,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.DetailedPipeFlow,
    length=10,
    p_a_start=130000)

equation
tankLevel = tank.level;
  connect(sensor_m_flow.m_flow, m_flow)
  connect(sensor_m_flow.port_b, heater.port_a)
  connect(T_ambient.port, wall.port_a)
  connect(sensor_T_forward.T, T_forward)
  connect(radiator.port_a, valve.port_b)
  connect(sensor_T_return.port, radiator.port_b)
  connect(tank.ports[2], pump.port_a)
  connect(handle.y, valve.opening)
  connect(pump.port_b, sensor_m_flow.port_a)
  connect(sensor_T_return.T, T_return)
  connect(burner.port, heater.heatPorts[1])
  connect(wall.port_b, radiator.heatPorts[1])
  connect(sensor_T_forward.port, heater.port_b)
  connect(heater.port_b, pipe.port_a)
  connect(pipe.port_b, valve.port_a)
  connect(radiator.port_b, tank.ports[1])
end HeatingSystem;


within Modelica.Fluid.Examples;
model IncompressibleFluidNetwork
  "Multi-way connections of pipes and incompressible medium model"
  extends Modelica.Icons.Example;

  parameter Types.ModelStructure pipeModelStructure = Modelica.Fluid.Types.ModelStructure.av_vb "Model structure in distributed pipe model";

  replaceable package Medium =
      Modelica.Media.Incompressible.Examples.Glycol47
    constrainedby Modelica.Media.Interfaces.PartialMedium;

  import Modelica.Fluid.Types.Dynamics;
  parameter Dynamics systemMassDynamics = if Medium.singleState then Dynamics.SteadyState else Dynamics.SteadyStateInitial "Formulation of mass balances";

  Sources.Boundary_pT source(nPorts=1,
    redeclare package Medium = Medium,
    p=5.0e5,
    T=300)
  Pipes.DynamicPipe
       pipe1(
    use_T_start=true,
    length=10,
    diameter=2.5e-2,
    redeclare package Medium = Medium,
    modelStructure=pipeModelStructure,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.TurbulentPipeFlow)

  Pipes.DynamicPipe pipe2(
    use_T_start=true,
    diameter=2.5e-2,
    redeclare package Medium = Medium,
    length=0.5,
    modelStructure=pipeModelStructure,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.TurbulentPipeFlow)

  Pipes.DynamicPipe pipe3(
    use_T_start=true,
    diameter=2.5e-2,
    redeclare package Medium = Medium,
    length=0.5,
    modelStructure=pipeModelStructure,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.TurbulentPipeFlow)
  Pipes.DynamicPipe pipe4(
    use_T_start=true,
    diameter=2.5e-2,
    redeclare package Medium = Medium,
    length=2,
    modelStructure=pipeModelStructure,
    use_HeatTransfer=true,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.TurbulentPipeFlow)
  Pipes.DynamicPipe pipe6(
    use_T_start=true,
    diameter=2.5e-2,
    redeclare package Medium = Medium,
    length=20,
    modelStructure=pipeModelStructure,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.TurbulentPipeFlow)
  Valves.ValveIncompressible valve1(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    rho_nominal=1000,
    CvData=Modelica.Fluid.Types.CvTypes.Av,
    Av=2.5e-2^2/4*Modelica.Constants.pi,
    dp_nominal=30000)
  Valves.ValveIncompressible valve2(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    rho_nominal=1000,
    CvData=Modelica.Fluid.Types.CvTypes.Av,
    Av=2.5e-2^2/4*Modelica.Constants.pi,
    dp_nominal=30000)
  Pipes.DynamicPipe pipe7(
    use_T_start=true,
    length=10,
    diameter=2.5e-2,
    redeclare package Medium = Medium,
    modelStructure=pipeModelStructure,
    use_HeatTransfer=true,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.TurbulentPipeFlow)
  Valves.ValveIncompressible valve3(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    rho_nominal=1000,
    CvData=Modelica.Fluid.Types.CvTypes.Av,
    Av=2.5e-2^2/4*Modelica.Constants.pi,
    dp_nominal=30000)
  Sources.Boundary_pT sink(nPorts=1,
    redeclare package Medium = Medium,
    T=300,
    p=1.0e5)
  inner Modelica.Fluid.System system(
      massDynamics=systemMassDynamics, energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    use_eps_Re=true)
  Modelica.Blocks.Sources.Step valveOpening1(
    offset=1,
    startTime=50,
    height=-1)
  Modelica.Blocks.Sources.Step valveOpening2(
    offset=1,
    height=-0.5,
    startTime=100)
  Modelica.Blocks.Sources.Step valveOpening3(
    offset=1,
    startTime=150,
    height=-0.5)
  Pipes.DynamicPipe pipe8(
    use_T_start=true,
    length=10,
    diameter=2.5e-2,
    redeclare package Medium = Medium,
    modelStructure=pipeModelStructure,
    use_HeatTransfer=true,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.TurbulentPipeFlow)
  Pipes.DynamicPipe pipe9(
    use_T_start=true,
    length=10,
    diameter=2.5e-2,
    redeclare package Medium = Medium,
    modelStructure=pipeModelStructure,
    use_HeatTransfer=true,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.TurbulentPipeFlow)
  Pipes.DynamicPipe pipe10(
    use_T_start=true,
    length=10,
    diameter=2.5e-2,
    redeclare package Medium = Medium,
    modelStructure=pipeModelStructure,
    use_HeatTransfer=true,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.TurbulentPipeFlow)
  Pipes.DynamicPipe pipe5(
    use_T_start=true,
    diameter=2.5e-2,
    redeclare package Medium = Medium,
    length=20,
    modelStructure=pipeModelStructure,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.TurbulentPipeFlow)
  Thermal.HeatTransfer.Sources.FixedHeatFlow[ pipe8.nNodes] heat8(Q_flow=16e3*
        pipe8.dxs)
  Pipes.DynamicPipe pipe11(
    use_T_start=true,
    diameter=2.5e-2,
    redeclare package Medium = Medium,
    modelStructure=pipeModelStructure,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.TurbulentPipeFlow,
    length=0.5)
equation
  connect(source.ports[1], pipe1.port_a)
  connect(pipe1.port_b, pipe3.port_a)
  connect(pipe1.port_b, pipe2.port_a)
  connect(pipe2.port_b, valve1.port_a)
  connect(valve2.port_b, pipe4.port_a)
  connect(pipe3.port_b, valve2.port_a)
  connect(valve1.port_b, pipe7.port_a)
  connect(valve3.port_b, sink.ports[1])
  connect(valveOpening1.y, valve1.opening)
  connect(valveOpening2.y, valve2.opening)
  connect(valveOpening3.y, valve3.opening)
  connect(pipe7.port_b, pipe9.port_a)
  connect(pipe7.port_b, pipe8.port_a)
  connect(pipe8.port_b, pipe10.port_a)
  connect(pipe4.port_b, pipe6.port_a)
  connect(pipe8.port_b, pipe4.port_b)
  connect(pipe5.port_a, pipe4.port_b)
  connect(heat8.port, pipe8.heatPorts)
  connect(pipe5.port_b, pipe6.port_b)
  connect(pipe6.port_b, pipe10.port_b)
  connect(pipe11.port_b, valve3.port_a)
  connect(pipe9.port_b, pipe11.port_a)
  connect(pipe10.port_b, pipe11.port_a)
end IncompressibleFluidNetwork;


within Modelica.Fluid.Examples;
model InverseParameterization
  "Demonstrates the parameterization of a pump and a pipe for given nominal values"
  extends Modelica.Icons.Example;

  replaceable package Medium = Modelica.Media.Water.StandardWater;
  //replaceable package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater;

  //parameter Real eps_m_flow_turbulent = 0.0 "Turbulent flow |m_flow| >= eps_m_flow_nominal*m_flow_nominal";
  parameter Real eps_m_flow_turbulent = 0.1
    "Turbulent flow |m_flow| >= eps_m_flow_nominal*m_flow_nominal";
  //parameter Real eps_m_flow_turbulent = 1 "Turbulent flow |m_flow| >= eps_m_flow_nominal*m_flow_nominal";

  Modelica.Fluid.Sources.Boundary_pT source(
    redeclare package Medium = Medium,
    nPorts=1,
    use_p_in=false,
    p=100000)
  Modelica.Fluid.Machines.ControlledPump pump(
    m_flow_nominal=1,
    control_m_flow=false,
    use_p_set=true,
    redeclare package Medium = Medium,
    p_a_nominal=100000,
    p_b_nominal=200000)
  Modelica.Fluid.Fittings.SimpleGenericOrifice orifice(
    redeclare package Medium = Medium,
    diameter=2.54e-2,
    use_zeta=false,
    zeta=0,
    dp_nominal=100000,
    m_flow_nominal=1)

  Modelica.Fluid.Sources.Boundary_pT sink(nPorts=1,redeclare package Medium = Medium, p=
        100000)

  inner Modelica.Fluid.System system(m_flow_start = 0.4)
  Modelica.Fluid.Pipes.StaticPipe pipe1(
    redeclare package Medium = Medium,
    diameter=2.54e-2,
    length=0,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
        show_Res=true,
        m_flow_nominal=1,
        m_flow_turbulent=eps_m_flow_turbulent*1,
        dp_nominal=100000))
  Modelica.Fluid.Sources.Boundary_pT sink1(nPorts=1,
    redeclare package Medium = Medium, p=200000)
  Modelica.Blocks.Sources.Ramp p_set(
    height=0.2e5,
    offset=1.9e5,
    duration=8,
    startTime=1)
  Modelica.Fluid.Pipes.StaticPipe pipe2(
    redeclare package Medium = Medium,
    diameter=2.54e-2,
    length=1000,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalLaminarFlow (
        show_Res=true,
        dp_nominal=100000,
        m_flow_nominal=1))
  Modelica.Fluid.Sources.Boundary_pT sink2(nPorts=1,
    redeclare package Medium = Medium, p=200000)
equation
  connect(orifice.port_b, sink.ports[1])
  connect(source.ports[1], pump.port_a)
  connect(pump.port_b, orifice.port_a)
  connect(pipe1.port_b, sink1.ports[1])
  connect(pipe1.port_a, pump.port_b)
  connect(p_set.y, pump.p_set)
  connect(pipe2.port_b, sink2.ports[1])

  connect(pump.port_b, pipe2.port_a)
end InverseParameterization;


within Modelica.Fluid.Examples;
model NonCircularPipes "Comparing a circular with a non-circular pipe"
  extends Modelica.Icons.Example;
  replaceable package Medium = Modelica.Media.Water.StandardWater;
  constant Real odim = 0.015;
  constant Real idim = 0.005;
  inner Modelica.Fluid.System system(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
  Modelica.Fluid.Sources.Boundary_pT boundary(
    redeclare package Medium = Medium,
    nPorts = 2,
    p = 10.0e5,
    T = 293.15)
  Modelica.Fluid.Sources.MassFlowSource_T massflowsink1(redeclare package
      Medium =                                                                     Medium, nPorts = 1, m_flow = -0.1, T = 293.15)
  Modelica.Fluid.Sources.MassFlowSource_T massflowsink2(redeclare package
      Medium =                                                                     Medium, nPorts = 1, m_flow = -0.1, T = 293.15)
  Modelica.Fluid.Pipes.DynamicPipe circular_pipe(
    redeclare package Medium = Medium,
    length = 100, diameter = 0.01,
    T_start = 293.15,
    p_a_start = 10.0e5, p_b_start = 10.0e5)
  Modelica.Fluid.Pipes.DynamicPipe annulus_pipe(
    redeclare package Medium = Medium,
    length = 100,
    crossArea = Modelica.Constants.pi * (odim ^ 2 - idim ^ 2) / 4,
    perimeter = Modelica.Constants.pi * (odim + idim),
    isCircular=false,
    diameter=0,
    p_a_start=1000000,
    p_b_start=1000000,
    T_start=293.15)
equation
  connect(boundary.ports[1], circular_pipe.port_a)
  connect(boundary.ports[2], annulus_pipe.port_a)
  connect(circular_pipe.port_b, massflowsink1.ports[1])
  connect(annulus_pipe.port_b, massflowsink2.ports[1])
end NonCircularPipes;


within Modelica.Fluid;
package Examples "Demonstration of the usage of the library"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within Modelica.Fluid.Examples;
model PumpingSystem "Model of a pumping system for drinking water"
  extends Modelica.Icons.Example;

  replaceable package Medium = Modelica.Media.Water.StandardWaterOnePhase
    constrainedby Modelica.Media.Interfaces.PartialMedium;
  //replaceable package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater
  //  constrainedby Modelica.Media.Interfaces.PartialMedium;

  Modelica.Fluid.Sources.FixedBoundary source(
    nPorts = 1,
    use_T=true,
    T=Modelica.Units.Conversions.from_degC(20),
    p=system.p_ambient,
    redeclare package Medium = Medium)

  Modelica.Fluid.Pipes.StaticPipe pipe(
    allowFlowReversal=true,
    length=100,
    height_ab=50,
    diameter=0.3,
    redeclare package Medium = Medium)

  Machines.PrescribedPump pumps(
    checkValve=true,
    checkValveHomotopy = Modelica.Fluid.Types.CheckValveHomotopyType.Closed,
    N_nominal=1200,
    redeclare function flowCharacteristic =
        Modelica.Fluid.Machines.BaseClasses.PumpCharacteristics.quadraticFlow (
          V_flow_nominal={0,0.25,0.5}, head_nominal={100,60,0}),
    use_N_in=true,
    nParallel=1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    V(displayUnit="l") = 0.05,
    massDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    redeclare package Medium = Medium,
    p_b_start=600000,
    T_start=system.T_start)

  Modelica.Fluid.Vessels.OpenTank reservoir(
    T_start=Modelica.Units.Conversions.from_degC(20),
    use_portsData=true,
    crossArea=50,
    level_start=2.2,
    height=3,
    nPorts=3,
    portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.3),
        Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.3),
        Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.01)},
    redeclare package Medium = Medium)

  Modelica.Fluid.Valves.ValveLinear userValve(
    allowFlowReversal=false,
    dp_nominal=200000,
    m_flow_nominal=400,
    redeclare package Medium = Medium)
  Modelica.Fluid.Sources.FixedBoundary sink(
    p=system.p_ambient,
    T=system.T_ambient,
    nPorts=2,
    redeclare package Medium = Medium)
  Modelica.Blocks.Sources.Step valveOpening(startTime=200, offset=1e-6)
  Modelica.Blocks.Sources.Constant RelativePressureSetPoint(k=2e4)
  Modelica.Blocks.Logical.OnOffController controller(bandwidth=4000,
      pre_y_start=false)
  Modelica.Blocks.Logical.TriggeredTrapezoid PumpRPMGenerator(
    rising=3,
    falling=3,
    amplitude=1200,
    offset=0.001)
  Modelica.Fluid.Sensors.RelativePressure reservoirPressure(redeclare package
      Medium = Medium)
  Modelica.Blocks.Continuous.FirstOrder PT1(
    T=2,
    initType=Modelica.Blocks.Types.Init.InitialState,
    y_start=0)

  inner Modelica.Fluid.System system(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
equation
  connect(userValve.port_b, sink.ports[1])
  connect(source.ports[1], pumps.port_a)
  connect(valveOpening.y, userValve.opening)
  connect(RelativePressureSetPoint.y, controller.reference)
  connect(controller.y, PumpRPMGenerator.u)
  connect(reservoirPressure.p_rel, controller.u)
  connect(reservoirPressure.port_b, sink.ports[2])
  connect(PumpRPMGenerator.y, PT1.u)
  connect(PT1.y, pumps.N_in)
  connect(pipe.port_a, pumps.port_b)
  connect(reservoir.ports[1], pipe.port_b)
  connect(reservoir.ports[3], reservoirPressure.port_a)
  connect(reservoir.ports[2], userValve.port_a)
end PumpingSystem;


within Modelica.Fluid.Examples;
package Tanks "Library demonstrating the usage of the tank model"
  extends Modelica.Icons.ExamplesPackage;

  model ThreeTanks "Demonstrating the usage of SimpleTank"
    import Modelica.Fluid;
    extends Modelica.Icons.Example;
     // replaceable package Medium = Modelica.Fluid.Media.Water.ConstantPropertyLiquidWater extends
    // replaceable package Medium = Modelica.Media.Water.StandardWaterOnePhase extends
    // replaceable package Medium = Modelica.Media.Incompressible.Examples.Glycol47 extends
     replaceable package Medium =
        Modelica.Media.Water.ConstantPropertyLiquidWater                           constrainedby
      Modelica.Media.Interfaces.PartialMedium "Medium in the component"

    Modelica.Fluid.Vessels.OpenTank tank1(
      crossArea=1,
      redeclare package Medium = Medium,
      use_portsData=true,
      height=12,
      level_start=8,
      nPorts=1,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=
          0.1)})
    Modelica.Fluid.Vessels.OpenTank tank2(
      crossArea=1,
      redeclare package Medium = Medium,
      use_portsData=true,
      height=12,
      level_start=3,
      nPorts=1,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=
          0.1)})

    inner Modelica.Fluid.System system(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    Modelica.Fluid.Vessels.OpenTank tank3(
      crossArea=1,
      redeclare package Medium = Medium,
      use_portsData=true,
      height=12,
      level_start=3,
      nPorts=1,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=
          0.1)})
    Modelica.Fluid.Pipes.StaticPipe pipe1(                    redeclare package
        Medium =                                                                       Medium,
      allowFlowReversal=true,
      height_ab=2,
      length=2,
      diameter=0.1)
    Modelica.Fluid.Pipes.StaticPipe pipe2(                    redeclare package
        Medium =                                                                       Medium,
      allowFlowReversal=true,
      height_ab=2,
      length=2,
      diameter=0.1)
    Modelica.Fluid.Pipes.StaticPipe pipe3(                    redeclare package
        Medium =                                                                       Medium,
      allowFlowReversal=true,
      height_ab=-1,
      length=2,
      diameter=0.1)
  equation
    connect(pipe1.port_a, pipe2.port_a)
    connect(pipe2.port_a, pipe3.port_a)
    connect(pipe3.port_b, tank3.ports[1])
    connect(pipe1.port_b, tank1.ports[1])
    connect(pipe2.port_b, tank2.ports[1])
  end ThreeTanks;

  model TanksWithOverflow "Two tanks connected with pipes at different heights"
    extends Modelica.Icons.Example;
    import Modelica.Fluid;
    Modelica.Fluid.Vessels.OpenTank upperTank(
      redeclare package Medium =
          Modelica.Media.CompressibleLiquids.LinearColdWater,
      height=20,
      level_start=2,
      crossArea=0.2,
      nPorts=3,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.1),
          Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.1),
          Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.1, height=
           6)})
    Modelica.Fluid.Sources.MassFlowSource_T massFlowRate(nPorts=1,
      redeclare package Medium =
          Modelica.Media.CompressibleLiquids.LinearColdWater,
      m_flow=0.2,
      use_m_flow_in=true)
    inner Modelica.Fluid.System system(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    Modelica.Fluid.Sensors.Pressure pressure(redeclare package Medium =
          Modelica.Media.CompressibleLiquids.LinearColdWater)
    Modelica.Fluid.Pipes.StaticPipe pipe(
      redeclare package Medium =
          Modelica.Media.CompressibleLiquids.LinearColdWater,
      diameter=0.02,
      height_ab=-5,
      length=200)

    Modelica.Fluid.Vessels.OpenTank lowerTank(
      height=20,
      redeclare package Medium =
          Modelica.Media.CompressibleLiquids.LinearColdWater,
      level_start=2,
      crossArea=1,
      nPorts=2,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=
          0.1),Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=0.1,
          height=6)})
    Modelica.Blocks.Logical.Hysteresis hysteresis(
      uLow=1.1e5,
      uHigh=2.5e5,
      pre_y_start=true) "mass flow rate signal by pressure control"
    Modelica.Blocks.Logical.Switch switch1
    Modelica.Blocks.Sources.Constant m_flow_off(k=0)
    Modelica.Blocks.Sources.Constant m_flow_on(k=2)
    Modelica.Fluid.Pipes.StaticPipe overflow(
      redeclare package Medium =
          Modelica.Media.CompressibleLiquids.LinearColdWater,
      diameter=0.02,
      length=200,
      height_ab=-5)
  equation
    connect(massFlowRate.ports[1], upperTank.ports[1])
    connect(pressure.p, hysteresis.u)
    connect(hysteresis.y, switch1.u2)
    connect(m_flow_off.y, switch1.u1)
    connect(m_flow_on.y, switch1.u3)
    connect(switch1.y, massFlowRate.m_flow_in)
    connect(upperTank.ports[2], pipe.port_a)
    connect(pipe.port_a, pressure.port)
    connect(pipe.port_b, lowerTank.ports[1])
    connect(upperTank.ports[3], overflow.port_a)
    connect(overflow.port_b, lowerTank.ports[2])
  end TanksWithOverflow;

  model EmptyTanks "Show the treatment of empty tanks"
    extends Modelica.Icons.Example;
    Modelica.Fluid.Vessels.OpenTank tank1(
      redeclare package Medium =
          Modelica.Media.Water.ConstantPropertyLiquidWater,
      nPorts=1,
      crossArea=1,
      level_start=1,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=
          0.1)},
      height=1.1)

    Modelica.Fluid.Pipes.StaticPipe pipe(
      redeclare package Medium =
          Modelica.Media.Water.ConstantPropertyLiquidWater,
      length=1,
      diameter=0.1,
      height_ab=-1)

    Modelica.Fluid.Vessels.OpenTank tank2(
      crossArea=1,
      redeclare package Medium =
          Modelica.Media.Water.ConstantPropertyLiquidWater,
      nPorts=1,
      height=1.1,
      portsData={Modelica.Fluid.Vessels.BaseClasses.VesselPortsData(diameter=
          0.1, height=0.5)},
      level_start=1.0e-10)
    inner Modelica.Fluid.System system(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
  equation
    connect(tank1.ports[1], pipe.port_a)
    connect(pipe.port_b, tank2.ports[1])
  end EmptyTanks;

end Tanks;


within Modelica.Fluid.Examples;
package TraceSubstances "Library demonstrating the usage of trace substances"
  extends Modelica.Icons.ExamplesPackage;
  model RoomCO2 "Demonstrates a room volume with CO2 accumulation"
    extends Modelica.Icons.Example;
    package Medium=Modelica.Media.Air.MoistAir(extraPropertiesNames={"CO2"},
                                               C_nominal={1.519E-3});
    Modelica.Blocks.Sources.Constant C(k=0.3*1.519E-3)
      "Substance concentration, raising to 1000 PPM CO2"
    Sources.FixedBoundary boundary4(nPorts=1,redeclare package Medium = Medium)
    Sensors.TraceSubstances traceVolume(redeclare package Medium = Medium)
    inner System system(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    Sources.MassFlowSource_T boundary1(
      use_C_in=true,
      m_flow=100/1.2/3600*5,
      redeclare package Medium = Medium,
      nPorts=2,
      X=Medium.X_default)
    Modelica.Fluid.Vessels.ClosedVolume volume(
      C_start={1.519E-3},
      V=100,
      redeclare package Medium = Medium,
      nPorts=2,
      X_start={0.015,0.085},
      massDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
      use_portsData=false)
    Modelica.Fluid.Pipes.StaticPipe pipe(
      redeclare package Medium = Medium,
      length=1,
      diameter=0.15,
      redeclare model FlowModel =
          Modelica.Fluid.Pipes.BaseClasses.FlowModels.DetailedPipeFlow (
           show_Res=true))
    Sensors.TraceSubstances traceSource(redeclare package Medium = Medium)
  equation
    connect(C.y, boundary1.C_in[1])
    connect(pipe.port_b, boundary4.ports[1])
    connect(volume.ports[2], pipe.port_a)
    connect(traceVolume.port, pipe.port_a)
    connect(boundary1.ports[2], volume.ports[1])
    connect(boundary1.ports[1], traceSource.port)
  end RoomCO2;

  model RoomCO2WithControls "Demonstrates a room volume with CO2 controls"
    extends Modelica.Icons.Example;
    package Medium=Modelica.Media.Air.MoistAir(extraPropertiesNames={"CO2"},
                                               C_nominal={1.519E-1});
    Modelica.Blocks.Sources.Constant CAtm(k=0.3*1.519E-3)
      "Atmospheric trace substance concentration, corresponding to 300 PPM CO2"
    Sources.FixedBoundary boundary4(nPorts=1,redeclare package Medium = Medium)
    Sensors.TraceSubstances traceVolume(redeclare package Medium = Medium)
    inner System system(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
      use_eps_Re=true,
      m_flow_nominal=0.1,
      eps_m_flow=1e-2)
    Sources.MassFlowSource_T freshAir(
      use_C_in=true,
      redeclare package Medium = Medium,
      use_m_flow_in=true,
      nPorts=2)
    Modelica.Fluid.Vessels.ClosedVolume volume(
      medium(Xi(each nominal=0.01)),
      C_start={1.519E-3},
      V=100,
      redeclare package Medium = Medium,
      massDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
      use_portsData=false,
      nPorts=4)

    Pipes.DynamicPipe ductOut(
      mCs_scaled(each nominal = 0.01),
      mediums(each Xi(each nominal = 0.01)),
      redeclare package Medium = Medium,
      diameter=0.15,
      redeclare model FlowModel =
          Modelica.Fluid.Pipes.BaseClasses.FlowModels.DetailedPipeFlow (
            show_Res=true),
      modelStructure=Modelica.Fluid.Types.ModelStructure.a_v_b,
      length=5) "Outlet duct"

    Sensors.TraceSubstances traceDuctIn(redeclare package Medium = Medium)
      "Trace substance at duct inlet"
    Sources.MassFlowSource_T peopleSource(
      m_flow=100/1.2/3600*5,
      redeclare package Medium = Medium,
      use_m_flow_in=true,
      use_C_in=false,
      C={100},
      nPorts=1) "CO2 emitted by room occupants."
    Modelica.Blocks.Sources.CombiTimeTable numberOfPeople(
      table=[0,0; 9,10; 11,2; 13,15; 15,5; 18,0; 24,0],
      smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
      timeScale=3600) "Time table for number of people in the room"
    Modelica.Blocks.Math.Gain gain(k=8.18E-6/100)
      "CO2 mass flow rate, released per 100 person (there is another 100 factor in peopleSource)"
    Modelica.Blocks.Math.Gain gain1(k=-100*1.2/3600*5)
      "Nominal fresh air flow rate (for u=1)"
    Modelica.Blocks.Math.Gain gainSensor(k=1/1.519E-3)
      "Gain to normalize CO2 measurement signal. y=1 corresponds to 1000 PPM"
    Modelica.Blocks.Sources.Constant CO2Set(k=1) "Normalized CO2 set point"
    Modelica.Blocks.Continuous.LimPID PID(
      controllerType=Modelica.Blocks.Types.SimpleController.PI,
      yMax=0,
      yMin=-1,
      Ti=10,
      k=10)

    Pipes.DynamicPipe ductIn(
      mCs_scaled(each nominal = 0.01),
      mediums(each Xi(each nominal = 0.01)),
      redeclare package Medium = Medium,
      diameter=0.15,
      redeclare model FlowModel =
          Modelica.Fluid.Pipes.BaseClasses.FlowModels.DetailedPipeFlow (
            show_Res=true),
      modelStructure=Modelica.Fluid.Types.ModelStructure.a_v_b,
      length=5) "Inlet duct"

    Sensors.TraceSubstances traceDuctOut(redeclare package Medium = Medium)
      "Trace substance at duct outlet"
  equation
    connect(CAtm.y, freshAir.C_in[1])
    connect(ductOut.port_b, boundary4.ports[1])
    connect(numberOfPeople.y[1], gain.u)
    connect(gain.y, peopleSource.m_flow_in)
    connect(traceVolume.C, gainSensor.u)
    connect(CO2Set.y, PID.u_s)
    connect(gainSensor.y, PID.u_m)
    connect(PID.y, gain1.u)
    connect(gain1.y, freshAir.m_flow_in)
    connect(ductIn.port_b, volume.ports[1])
    connect(peopleSource.ports[1], volume.ports[2])
    connect(volume.ports[3], ductOut.port_a)
    connect(volume.ports[4], traceVolume.port)
    connect(freshAir.ports[1], traceDuctIn.port)
    connect(ductIn.port_a, freshAir.ports[2])
    connect(traceDuctOut.port, ductIn.port_b)
  end RoomCO2WithControls;
end TraceSubstances;


Library of magnetic models

within Modelica;
package Magnetic "Library of magnetic models"
  extends Modelica.Icons.Package;
  import Modelica.Units.SI;
end Magnetic;


within Modelica.Magnetic;
package FluxTubes "Library for modelling of electromagnetic devices with lumped magnetic networks"

  import Modelica.Constants.pi;
  import Modelica.Constants.mu_0;

  extends Modelica.Icons.Package;
end FluxTubes;


Base class for flux tubes with fixed shape during simulation; linear or non-linear material characteristics. Please refer to the description of  the sub-package Shapes.FixedShape for utilisation of this partial model.

within Modelica.Magnetic.FluxTubes.BaseClasses;
partial model FixedShape "Base class for flux tubes with fixed shape during simulation; linear or non-linear material characteristics"

  extends Interfaces.TwoPort;

  parameter Boolean nonLinearPermeability=true
    "= true, if non-linear rel. permeability is used, otherwise constant rel. permeability"
  parameter SI.RelativePermeability mu_rConst=1
    "Constant relative permeability; used if nonLinearPermeability = false"

  parameter FluxTubes.Material.SoftMagnetic.BaseData material=
      Material.SoftMagnetic.BaseData()
    "Ferromagnetic material characteristics; used if nonLinearPermeability = true"

  SI.Reluctance R_m "Magnetic reluctance";
  SI.Permeance G_m "Magnetic permeance";
  SI.MagneticFluxDensity B "Magnetic flux density";
  SI.CrossSection A "Cross-sectional area penetrated by magnetic flux";
  SI.MagneticFieldStrength H "Magnetic field strength";

  SI.RelativePermeability mu_r "Relative magnetic permeability";

protected
  Real B_N "Absolute value of normalized B";

equation
  B_N = abs(B/material.B_myMax);
  mu_r = if nonLinearPermeability then
    1 + (material.mu_i - 1 + material.c_a*B_N)/(1 + material.c_b*B_N + B_N^material.n) else mu_rConst;

  R_m = 1/G_m;
  V_m = Phi*R_m;
  B = Phi/A;
  H = B/(mu_0*mu_r);
end FixedShape;


Base class for flux tubes with reluctance force generation; constant permeability. Please refer to the description of  the sub-package Shapes.Force for utilisation of this partial model.

within Modelica.Magnetic.FluxTubes.BaseClasses;
partial model Force "Base class for flux tubes with reluctance force generation; constant permeability"

  extends Interfaces.TwoPort;

  parameter Boolean useSupport=false
    "= true, if support flange enabled, otherwise implicitly grounded"

  parameter SI.RelativePermeability mu_r(start=1)
    "Relative magnetic permeability";

  SI.Force F_m "Reluctance force";
  SI.Length s=flange.s - s_support
    "Distance between flange and support";

  SI.Reluctance R_m "Magnetic reluctance";
  SI.Permeance G_m "Magnetic permeance";
  SI.Permeability dGmBydx
    "Derivative of permeance with respect to armature position";
  parameter Integer dlBydx=1
    "Derivative of flux tube's varying dimension with respect to armature position; set to +1 or -1";

  Modelica.Mechanics.Translational.Interfaces.Flange_b flange
    "Generated reluctance force at armature position"
  Modelica.Mechanics.Translational.Interfaces.Support support(s=s_support,
      f=-flange.f) if useSupport "Support/housing of component"

protected
  SI.Length s_support "Absolute position of support flange";

equation
  V_m = Phi*R_m;
  R_m = 1/G_m;
  F_m = 0.5*V_m^2*dGmBydx;

  if not useSupport then
    s_support = 0;
  end if;
  flange.f = -F_m;
end Force;


Partial Tellinen hysteresis model.

within Modelica.Magnetic.FluxTubes.BaseClasses;
partial model Generic "Partial Tellinen hysteresis model"
  extends Interfaces.TwoPort;
  extends Modelica.Magnetic.FluxTubes.Icons.Reluctance;

  // Group Fixed Geometry (Cuboid)
  parameter SI.Length l=0.1 "Length in direction of flux"

  parameter SI.Area A=1e-4 "Area of cross section"
  final parameter SI.Volume V = A * l "Volume of FluxTube";
end Generic;


Partial hysteresis model.

within Modelica.Magnetic.FluxTubes.BaseClasses;
partial model GenericHysteresis "Partial hysteresis model"
  extends BaseClasses.Generic;
  extends Interfaces.ConditionalHeatPort(final T=293.15);

  parameter Boolean includeEddyCurrents = false
    "= true, if eddy current losses are enabled"

  parameter SI.Conductivity sigma=10e6 "Conductivity of core material"
  parameter SI.Length d = 0.5e-3 "Thickness of lamination"

  output SI.MagneticFieldStrength H(start=0) "Magnetic field strength";
  output SI.MagneticFieldStrength Hstat
    "Static (ferromagnetic) portion of the magnetic field strength";
  output SI.MagneticFieldStrength Heddy
    "Dynamic (eddy currents) portion of the magnetic field strength";
  output SI.MagneticFluxDensity B "Magnetic flux density";
  output Real MagRel(final quantity="Relative magnetization", final unit="1", start=0, min=-1, max=1)
    "Relative magnetization at initialization (-1..1)";
  output SI.Power LossPowerStat "Ferromagnetic (static) hysteresis losses";
  output SI.Power LossPowerEddy
    "Eddy current losses (dynamic hysteresis losses)";
  //output SI.Power LossPower "Total power loss of core (ferromagnetic + eddy currents)"; // defined in ConditionalHeatPort
  Real derHstat(start=0, unit="A/(m.s)")=der(Hstat);

protected
  final parameter Real eddyCurrentFactor(final unit="S.m") = (sigma * d^2)/12;

equation
  der(MagRel)=0;

  H = Hstat + Heddy;
  H = V_m/l;
  Phi = B*A;

  Heddy = if includeEddyCurrents then eddyCurrentFactor* der(B)  else 0;

  LossPowerStat = Hstat * der(B) * V;
  LossPowerEddy = Heddy * der(B) * V;
  LossPower = LossPowerStat + LossPowerEddy;
end GenericHysteresis;


Partial Tellinen hysteresis model. A reluctance with the Tellinen hysteresis model. The major hysteresis loop is defined by the hyperbolic tangent function.

within Modelica.Magnetic.FluxTubes.BaseClasses;
partial model GenericHysteresisTellinen "Partial Tellinen hysteresis model"
  extends BaseClasses.GenericHysteresis;

  //Real MagRel(start=0, min=-100, max=100) "Relative magnetization at initialization (-100-100%)";
  output Boolean asc(start=true) "True when der(Hstat)>0";
protected
  SI.MagneticFluxDensity hystR "Rising branch of limiting hysteresis loop";
  SI.MagneticFluxDensity hystF "Falling branch of limiting hysteresis loop";

  SI.MagneticFluxDensity diffHyst
    "Distance between rising and falling limiting hysteresis branch at the current operating point";
  Real dHyst(final quantity="MagneticFluxDensitySlope", final unit="T/s")
    "Slope of the Rising (when der(H)>0) or Falling (when der(H)<0) limiting hysteresis branch at the current operating point";
  Real k;

  parameter Real mu0(final unit="N/A2") = mu_0;

initial equation

  B = (hystR+hystF)/2 + MagRel*diffHyst/2;

equation

  asc = der(Hstat) > 0;

  der(B) = k * dHyst + mu0 * der(Hstat);

  diffHyst = hystF - hystR;

  if initial() then
    k = 0.01;
    dHyst = 0;
  elseif asc then
    dHyst = der(hystR-mu0*Hstat);
    k = max(0.01,(hystF - B)/diffHyst);
  else
    dHyst = der(hystF-mu0*Hstat);
    k = max(0.01, (B - hystR)/diffHyst);
  end if;

if the magnetic field intensity decreases (der(h)<0)

der(b) = dhF/diffHyst * der(hystF);

Fig. 1: Description of the Tellinen hysteresis model.
"));
end GenericHysteresisTellinen;


Base class for leakage flux tubes with position-independent permeance and hence no force generation; mu_r=1. Please refer to the description of  the sub-package Shapes.Leakage for utilisation of this partial model.

within Modelica.Magnetic.FluxTubes.BaseClasses;
partial model Leakage "Base class for leakage flux tubes with position-independent permeance and hence no force generation; mu_r=1"

  extends Interfaces.TwoPort;
  extends Modelica.Magnetic.FluxTubes.Icons.Reluctance;

  SI.Reluctance R_m "Magnetic reluctance";
  SI.Permeance G_m "Magnetic permeance";

equation
  V_m = Phi*R_m;
  R_m = 1/G_m;
end Leakage;


Base classes of flux tube components

within Modelica.Magnetic.FluxTubes;
package BaseClasses "Base classes of flux tube components"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Constant permeance. This constant permeance is provided for test purposes and simple magnetic network models. The permeance is not calculated from geometry and permeability of a flux tube, but is provided as parameter.

within Modelica.Magnetic.FluxTubes.Basic;
model ConstantPermeance "Constant permeance"

  extends Interfaces.TwoPort;
  extends Modelica.Magnetic.FluxTubes.Icons.Reluctance;
  parameter SI.Permeance G_m=1 "Magnetic permeance";

equation
  G_m * V_m = Phi;
end ConstantPermeance;


Constant reluctance. This constant reluctance is provided for test purposes and simple magnetic network models. The reluctance is not calculated from geometry and permeability of a flux tube, but is provided as parameter.

within Modelica.Magnetic.FluxTubes.Basic;
model ConstantReluctance "Constant reluctance"

  extends Interfaces.TwoPort;
  extends Modelica.Magnetic.FluxTubes.Icons.Reluctance;
  parameter SI.Reluctance R_m=1 "Magnetic reluctance";

equation
  V_m = Phi*R_m;
end ConstantReluctance;


Crossing of two branches. This is a simple crossing of two branches. The ports port_p1 and port_p2 are connected, as well as port_n1 and port_n2.

within Modelica.Magnetic.FluxTubes.Basic;
model Crossing "Crossing of two branches"

  FluxTubes.Interfaces.PositiveMagneticPort port_p1
    "Positive port_p1 connected with port_p2"
  FluxTubes.Interfaces.PositiveMagneticPort port_p2
    "Positive port_p2 connected with port_p1"
  FluxTubes.Interfaces.NegativeMagneticPort port_n1
    "Negative port_n1 connected with port_n2"
  FluxTubes.Interfaces.NegativeMagneticPort port_n2
    "Negative port_n2 connected with port_n1"
equation
  connect(port_p1, port_p2)
  connect(port_n1, port_n2)
end Crossing;


For modelling of eddy current in a conductive magnetic flux tube. Eddy currents are induced in a conductive magnetic flux tube when the flux changes with time. This causes a magnetic voltage drop in addition to the voltage drop that is due to the reluctance of this flux tube. The eddy current component can be thought of as a short-circuited secondary winding of a transformer with only one turn. Its resistance is calculated from the geometry and resistivity of the eddy current path.

within Modelica.Magnetic.FluxTubes.Basic;
model EddyCurrent
  "For modelling of eddy current in a conductive magnetic flux tube"

  extends Interfaces.TwoPort;
  extends Modelica.Electrical.Analog.Interfaces.ConditionalHeatPort(
    final T=273.15);

  parameter Boolean useConductance = false
    "Use conductance instead of geometry data and rho"
  parameter SI.Conductance G(min=0) = 1/0.098e-6
    "Equivalent loss conductance G=A/rho/l"
  parameter SI.Resistivity rho=0.098e-6
    "Resistivity of flux tube material (default: Iron at 20degC)"
  parameter SI.Length l=1 "Average length of eddy current path"
  parameter SI.Area A=1 "Cross sectional area of eddy current path"

  final parameter SI.Resistance R=rho*l/A
    "Electrical resistance of eddy current path"

equation
  LossPower = V_m*der(Phi);
  V_m =(if useConductance then G else 1/R) * der(Phi);
  //Magnetic voltage drop in magnetic network due to eddy current
end EddyCurrent;


Ideal electromagnetic energy conversion. The electromagnetic energy conversion is given by Ampere's law and Faraday's law respectively:

within Modelica.Magnetic.FluxTubes.Basic;
model ElectroMagneticConverter "Ideal electromagnetic energy conversion"

  FluxTubes.Interfaces.PositiveMagneticPort port_p "Positive magnetic port"
  FluxTubes.Interfaces.NegativeMagneticPort port_n "Negative magnetic port"
  Modelica.Electrical.Analog.Interfaces.PositivePin p "Positive electrical pin"
  Modelica.Electrical.Analog.Interfaces.NegativePin n "Negative electrical pin"
  SI.Voltage v "Voltage";
  SI.Current i(start=0, stateSelect=StateSelect.prefer) "Current";
  SI.MagneticPotentialDifference V_m "Magnetic potential difference";
  SI.MagneticFlux Phi "Magnetic flux coupled into magnetic circuit";

  parameter Real N=1 "Number of turns";

  // For information only:
  SI.MagneticFlux Psi "Flux linkage";
  SI.Inductance L_stat "Static inductance abs(Psi/i)";

protected
  Real eps=100*Modelica.Constants.eps;
equation
  v = p.v - n.v;
  0 = p.i + n.i;
  i = p.i;

  V_m = port_p.V_m - port_n.V_m;
  0 = port_p.Phi + port_n.Phi;
  Phi = port_p.Phi;

  // Converter equations
  V_m = i*N "Ampere's law";
  N*der(Phi) = -v "Faraday's law";

  // For information only
  Psi = N*Phi;
  // Use of abs() for positive results; due to Modelica sign conventions for flow into connectors
  L_stat = noEvent(if abs(i) > eps then abs(Psi/i) else abs(Psi/eps));
end ElectroMagneticConverter;


Electromagnetic energy conversion with a leakage inductance. Same as ElectroMagneticConverter with an additional leakage path on the magnetic side (leakage inductance, leakage flux). This model may improve stability especially when the magnetic circuit contains more than one electromagnetic converter.

within Modelica.Magnetic.FluxTubes.Basic;
model ElectroMagneticConverterWithLeakageInductance
  "Electromagnetic energy conversion with a leakage inductance"

  Magnetic.FluxTubes.Interfaces.PositiveMagneticPort port_p
    "Positive magnetic port"
  Magnetic.FluxTubes.Interfaces.NegativeMagneticPort port_n
    "Negative magnetic port"
  Modelica.Electrical.Analog.Interfaces.PositivePin p "Positive electrical pin"
  Modelica.Electrical.Analog.Interfaces.NegativePin n "Negative electrical pin"
  SI.Voltage v "Voltage";
  SI.Current i(start=0, stateSelect=StateSelect.prefer) "Current";
  SI.MagneticPotentialDifference V_m "Magnetic potential difference";
  SI.MagneticFlux Phi(stateSelect=StateSelect.never)
    "Total Magnetic flux coupled into magnetic circuit (= Phi_ind + Phi_leak)";
  SI.MagneticFlux Phi_ind(stateSelect=StateSelect.never)
    "Magnetic flux of converter";
  SI.MagneticFlux Phi_leak(stateSelect=StateSelect.never)
    "Magnetic flux of leakage inductance";
  parameter Real N(start=1, min=Modelica.Constants.eps) "Number of turns";

  parameter SI.Length L=10e-3 "Length in direction of flux"
  parameter SI.Area A=10e-6 "Area of cross-section"
  parameter SI.RelativePermeability mu_rel(min=Modelica.Constants.eps) = 1
    "Constant relative permeability of leakage inductance (> 0 required)"
  final parameter SI.Permeance G_m=Modelica.Constants.mu_0*mu_rel*A/L
    "Magnetic permeance of leakage inductance";

  // For information only
  SI.MagneticFlux Psi "Flux linkage";
  SI.Inductance L_stat "Static inductance abs(Psi/i)";

protected
  constant Real eps=100*Modelica.Constants.eps;
equation
  v = p.v - n.v;
  0 = p.i + n.i;
  i = p.i;

  V_m = port_p.V_m - port_n.V_m;
  0 = port_p.Phi + port_n.Phi;
  Phi = port_p.Phi;

  // Converter equations
  V_m = i*N "Ampere's law";
  N*der(Phi_ind) = -v "Faraday's law";

  // Leakage equations
  Phi_leak = G_m*V_m;
  Phi = Phi_ind + Phi_leak;

  // For information only
  Psi = N*Phi_ind;
  //use of abs() for positive results; due to Modelica sign conventions for flow into connectors
  L_stat = noEvent(if abs(i) > eps then abs(Psi/i) else abs(Psi/eps));
end ElectroMagneticConverterWithLeakageInductance;


Zero magnetic potential. The magnetic potential at the magnetic ground node is zero. Every magnetic network model must contain at least one magnetic ground object.

within Modelica.Magnetic.FluxTubes.Basic;
model Ground "Zero magnetic potential"

  FluxTubes.Interfaces.PositiveMagneticPort port
equation
  port.V_m = 0;
end Ground;


Idle running branch. This is a simple idle running branch.

within Modelica.Magnetic.FluxTubes.Basic;
model Idle "Idle running branch"
  extends Interfaces.TwoPort;
equation
  Phi = 0;
end Idle;


Leakage reluctance with respect to the reluctance of a useful flux path (not for dynamic simulation of actuators). Differently from the flux tube elements of package Shapes.Leakage
that are calculated from their geometry, this leakage reluctance is calculated with reference to the total reluctance of a useful flux path. Please refer to the Parameters section for an illustration of the resulting magnetic network. Exploiting Kirchhoff's generalized current law, the leakage reluctance is calculated by means of a coupling coefficient c_usefulFlux.

within Modelica.Magnetic.FluxTubes.Basic;
model LeakageWithCoefficient
  "Leakage reluctance with respect to the reluctance of a useful flux path (not for dynamic simulation of actuators)"
  extends BaseClasses.Leakage;
  import Modelica.Constants.eps;
  parameter SI.CouplingCoefficient c_usefulFlux(final min=eps, final max=1-eps, start=0.7)
    "Ratio useful flux/(leakage flux + useful flux) = useful flux/total flux"
  Blocks.Interfaces.RealInput R_mUsefulTot(quantity="Reluctance", unit="H-1")
equation
  (1 - c_usefulFlux)*R_m = c_usefulFlux*R_mUsefulTot;
  // Generalized Kirchhoff's current law
end LeakageWithCoefficient;


within Modelica.Magnetic.FluxTubes;
package Basic "Basic elements of magnetic network models"
  extends Modelica.Icons.Package;
end Basic;


Short cut branch. This is a simple short cut branch.

within Modelica.Magnetic.FluxTubes.Basic;
model Short "Short cut branch"
  extends Interfaces.TwoPortElementary;

equation
  connect(port_p, port_n)
end Short;


Variable permeance. The permeance of this model is controlled by a real signal input.

within Modelica.Magnetic.FluxTubes.Basic;
model VariablePermeance "Variable permeance"

  extends Interfaces.TwoPort;
  extends Modelica.Magnetic.FluxTubes.Icons.Reluctance;
  Modelica.Blocks.Interfaces.RealInput G_m(quantity="Permeance", unit="H") "Magnetic permeance"

equation
  G_m * V_m = Phi;
end VariablePermeance;


Variable reluctance. The reluctance of this model is controlled by a real signal input.

within Modelica.Magnetic.FluxTubes.Basic;
model VariableReluctance "Variable reluctance"

  extends Interfaces.TwoPort;
  extends Modelica.Magnetic.FluxTubes.Icons.Reluctance;
  Modelica.Blocks.Interfaces.RealInput R_m(quantity="Reluctance", unit="H-1") "Magnetic reluctance"

equation
  V_m = Phi*R_m;
end VariableReluctance;


within Modelica.Magnetic.FluxTubes;
package Examples "Illustration of component usage with simple models of various devices"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Educational examples

within Modelica.Magnetic.FluxTubes.Examples;
package BasicExamples "Educational examples"
extends Modelica.Icons.ExamplesPackage;
end BasicExamples;


Educational example: iron core with airgap. Educational example of a magnetic circuit containing an iron core and an airgap:

within Modelica.Magnetic.FluxTubes.Examples.BasicExamples;
model QuadraticCoreAirgap "Educational example: iron core with airgap"
  extends Modelica.Icons.Example;
  parameter SI.Length l=0.1 "Outer length of iron core";
  parameter SI.Length a=0.01 "Side length of square cross section";
  parameter Real mu_r=1000 "Relative permeability of core";
  parameter SI.Length delta=0.001 "Length of airgap";
  parameter Real sigma=0.1 "Leakage coefficient";
  parameter Integer N=500 "Number of turns of exciting coil";
  parameter SI.Current I=1.5 "Maximum exciting current";
  Basic.ElectroMagneticConverter excitingCoil(N=N)
  Shapes.FixedShape.Cuboid leftLeg(
    nonLinearPermeability=false,
    mu_rConst=mu_r,
    l=l - a,
    a=a,
    b=a)
  Shapes.FixedShape.Cuboid upperYoke(
    nonLinearPermeability=false,
    mu_rConst=mu_r,
    l=l - a,
    a=a,
    b=a)
  Shapes.FixedShape.Cuboid rightLeg(
    nonLinearPermeability=false,
    mu_rConst=mu_r,
    l=l - a - delta,
    a=a,
    b=a)
  Shapes.FixedShape.Cuboid airGap(
    nonLinearPermeability=false,
    mu_rConst=1,
    l=delta,
    a=a,
    b=a)
  Basic.ElectroMagneticConverter measuringCoil(N=1)
  Shapes.FixedShape.Cuboid lowerYoke(
    nonLinearPermeability=false,
    mu_rConst=mu_r,
    l=l - a,
    a=a,
    b=a)
  Basic.Ground magneticGround
  Electrical.Analog.Basic.Ground electricGround1
  Electrical.Analog.Sources.RampCurrent rampCurrent(
    I=I,
    duration=0.015,
    startTime=0.01)
  Sensors.MagneticFluxSensor magFluxSensor
  Electrical.Analog.Basic.Ground electricGround2
  Electrical.Analog.Sensors.VoltageSensor voltageSensor
  Basic.LeakageWithCoefficient leakage(c_usefulFlux=1 - sigma)
  Blocks.Sources.RealExpression usefulReluctance(y=1/airGap.G_m)
equation
  connect(excitingCoil.port_p, leftLeg.port_p)
  connect(leftLeg.port_n, upperYoke.port_p)
  connect(upperYoke.port_n, rightLeg.port_p)
  connect(rightLeg.port_n, measuringCoil.port_p)
  connect(measuringCoil.port_n, airGap.port_p)
  connect(lowerYoke.port_p, airGap.port_n)
  connect(lowerYoke.port_n, magneticGround.port)
  connect(electricGround1.p, excitingCoil.n)
  connect(rampCurrent.p, electricGround1.p)
  connect(rampCurrent.n, excitingCoil.p)
  connect(measuringCoil.n, electricGround2.p)
  connect(measuringCoil.p, voltageSensor.p)
  connect(electricGround2.p, voltageSensor.n)
  connect(excitingCoil.port_n, magFluxSensor.port_n)
  connect(magFluxSensor.port_p, magneticGround.port)
  connect(leakage.port_n, airGap.port_n)
  connect(measuringCoil.port_p, leakage.port_p)
  connect(leakage.R_mUsefulTot, usefulReluctance.y)
end QuadraticCoreAirgap;


Inductor with saturation in the ferromagnetic core. This model demonstrates the effects of non-linear magnetisation characteristics of soft magnetic materials (hysteresis neglected). A sinusoidal voltage is applied to an inductor with a closed ferromagnetic core of rectangular shape. Set the tolerance to 1e-7, simulate for 0.1 s and plot for example:

within Modelica.Magnetic.FluxTubes.Examples.BasicExamples;
model SaturatedInductor "Inductor with saturation in the ferromagnetic core"
  extends Modelica.Icons.Example;

  FluxTubes.Basic.Ground ground_m
  Modelica.Electrical.Analog.Sources.SineVoltage source(
    f=50,
    phase=pi/2,
    V=230*sqrt(2)) "Voltage applied to inductor"
  Modelica.Electrical.Analog.Basic.Resistor r(R=7.5)
    "Inductor coil resistance"
  FluxTubes.Basic.ElectroMagneticConverter coil(N=600, i(fixed=true))
    "Inductor coil"
  Basic.ConstantReluctance r_mLeak(R_m=1.2e6) "Constant leakage reluctance"
  Shapes.FixedShape.Cuboid r_mAirPar(
    a=0.025,
    b=0.025,
    nonLinearPermeability=false,
    mu_rConst=1,
    l=0.0001)
    "Reluctance of small parasitic air gap (ferromagnetic core packeted from single sheets)"
  Shapes.FixedShape.Cuboid r_mFe(
    mu_rConst=1000,
    a=0.025,
    b=0.025,
    nonLinearPermeability=true,
    l=4*0.065,
    material=
        Material.SoftMagnetic.ElectricSheet.M350_50A(),
    B(start=0)) "Reluctance of ferromagnetic inductor core"

  Modelica.Electrical.Analog.Basic.Ground ground

equation
  connect(source.p, r.p)
  connect(r.n, coil.p)
  connect(source.n, coil.n)
  connect(coil.port_p, r_mLeak.port_p)
  connect(r_mLeak.port_p, r_mAirPar.port_p)
  connect(r_mAirPar.port_n, r_mFe.port_p)
  connect(r_mFe.port_n, r_mLeak.port_n)
  connect(r_mFe.port_n, coil.port_n)
  connect(ground.p, source.n)
  connect(ground_m.port, r_mFe.port_n) hysteresis neglected

The magnetisation characteristics of the flux tube element representing the ferromagnetic core can easily be changed from simplified linear behaviour (nonLinearPermeability set to false and R_mFe.mu_rConst set to a positive value, preferably mu_rConst >> 1) to non-linear behaviour (e.g., selection of one of the electric sheets in Material.SoftMagnetic with nonLinearPermeability set to true). This enables for convenient initial design of magnetic circuits with linear material characteristics prior to simulation with non-linear behaviour.

Note

If the supply voltage has a zero-crossing when applied to the inductor at time t=0 (i.e., source.phase set to zero instead of π/2), then the inrush current that is typical for switching of inductive loads can be observed.

"));
end SaturatedInductor;


Educational example: iron core with airgap. Educational example of a magnetic circuit containing a toroidal iron core with circular cross section and an airgap:

within Modelica.Magnetic.FluxTubes.Examples.BasicExamples;
model ToroidalCoreAirgap "Educational example: iron core with airgap"
  extends Modelica.Icons.Example;
  import Modelica.Constants.pi;
  parameter SI.Length r=0.05 "Middle radius of iron core";
  parameter SI.Length d=0.01 "Diameter of cylindrical cross section";
  parameter SI.RelativePermeability mu_r=1000 "Relative permeability of core";
  parameter SI.Length delta=0.001 "Length of airgap";
  parameter SI.Angle alpha=(1 - delta/(2*pi*r))*2*pi "Section angle of toroidal core";
  parameter Integer N=500 "Number of exciting coil turns";
  parameter SI.Current I=1.5 "Maximum exciting current";
  Modelica.Magnetic.FluxTubes.Basic.ElectroMagneticConverter excitingCoil(N=N)
  Shapes.FixedShape.Toroid core(
    nonLinearPermeability=false,
    mu_rConst=mu_r,
    r=r,
    d=d,
    alpha=alpha)
  Shapes.FixedShape.Toroid                             airGap(
    nonLinearPermeability=false,
    mu_rConst=1,
    r=r,
    d=d,
    alpha=2*pi - alpha)
  Modelica.Magnetic.FluxTubes.Basic.ElectroMagneticConverter measuringCoil(N=1)
  Modelica.Magnetic.FluxTubes.Basic.Ground magneticGround
  Modelica.Electrical.Analog.Basic.Ground electricGround1
  Modelica.Electrical.Analog.Sources.RampCurrent rampCurrent(
    I=I,
    duration=0.015,
    startTime=0.01)
  Modelica.Magnetic.FluxTubes.Sensors.MagneticFluxSensor magFluxSensor
  Modelica.Electrical.Analog.Basic.Ground electricGround2
  Modelica.Electrical.Analog.Sensors.VoltageSensor voltageSensor
equation
  connect(core.port_n, measuringCoil.port_p)
  connect(measuringCoil.port_n, airGap.port_p)
  connect(electricGround1.p, excitingCoil.n)
  connect(rampCurrent.p, electricGround1.p)
  connect(rampCurrent.n, excitingCoil.p)
  connect(measuringCoil.n, electricGround2.p)
  connect(measuringCoil.p, voltageSensor.p)
  connect(electricGround2.p, voltageSensor.n)
  connect(excitingCoil.port_n, magFluxSensor.port_n)
  connect(magFluxSensor.port_p, magneticGround.port)
  connect(magneticGround.port, airGap.port_n)
  connect(excitingCoil.port_p, core.port_p)
end ToroidalCoreAirgap;


Educational example: iron core with airgap. Educational example of a magnetic circuit containing a toroidal iron core with rectangular cross section and an airgap:

within Modelica.Magnetic.FluxTubes.Examples.BasicExamples;
model ToroidalCoreQuadraticCrossSection
  "Educational example: iron core with airgap"
  extends Modelica.Icons.Example;
  import Modelica.Constants.pi;
  parameter SI.Length r_o=0.055 "Outer radius of iron core";
  parameter SI.Length r_i=0.045 "Inner radius of iron core";
  parameter SI.Length l=0.01 "Length of rectangular cross section";
  parameter SI.RelativePermeability mu_r=1000 "Relative permeability of core";
  parameter SI.Length delta=0.001 "Length of airgap";
  parameter SI.Angle alpha=(1 - delta/(2*pi*(r_o + r_i)/2))*2*pi "Section angle of toroidal core";
  parameter Integer N=500 "Number of exciting coil turns";
  parameter SI.Current I=1.5 "Maximum exciting current";
  Modelica.Magnetic.FluxTubes.Basic.ElectroMagneticConverter excitingCoil(N=N)
  Shapes.FixedShape.HollowCylinderCircumferentialFlux
                           core(
    nonLinearPermeability=false,
    mu_rConst=mu_r,
    l=l,
    r_i=r_i,
    r_o=r_o,
    alpha=alpha)
  Shapes.FixedShape.HollowCylinderCircumferentialFlux  airGap(
    nonLinearPermeability=false,
    mu_rConst=1,
    l=l,
    r_i=r_i,
    r_o=r_o,
    alpha=2*pi - alpha)
  Modelica.Magnetic.FluxTubes.Basic.ElectroMagneticConverter measuringCoil(N=1)
  Modelica.Magnetic.FluxTubes.Basic.Ground magneticGround
  Modelica.Electrical.Analog.Basic.Ground electricGround1
  Modelica.Electrical.Analog.Sources.RampCurrent rampCurrent(
    I=I,
    duration=0.015,
    startTime=0.01)
  Modelica.Magnetic.FluxTubes.Sensors.MagneticFluxSensor magFluxSensor
  Modelica.Electrical.Analog.Basic.Ground electricGround2
  Modelica.Electrical.Analog.Sensors.VoltageSensor voltageSensor
equation
  connect(core.port_n, measuringCoil.port_p)
  connect(measuringCoil.port_n, airGap.port_p)
  connect(electricGround1.p, excitingCoil.n)
  connect(rampCurrent.p, electricGround1.p)
  connect(rampCurrent.n, excitingCoil.p)
  connect(measuringCoil.n, electricGround2.p)
  connect(measuringCoil.p, voltageSensor.p)
  connect(electricGround2.p, voltageSensor.n)
  connect(excitingCoil.port_n, magFluxSensor.port_n)
  connect(magFluxSensor.port_p, magneticGround.port)
  connect(magneticGround.port, airGap.port_n)
  connect(excitingCoil.port_p, core.port_p)
end ToroidalCoreQuadraticCrossSection;


Comparison of the different hysteresis models. Use the following simulation settings:

within Modelica.Magnetic.FluxTubes.Examples.Hysteresis;
model HysteresisModelComparison
  "Comparison of the different hysteresis models"
  extends Modelica.Icons.Example;
  Modelica.Blocks.Sources.TimeTable timeTable(table=[0.0,0.0; 1,500; 3,-500;
        5,500; 6,-24; 7,24; 8,-24; 9,24; 10,-24; 11,24; 12,-24; 13,24; 14,
        -24; 15,24])
  Basic.ElectroMagneticConverterWithLeakageInductance winding1(i(fixed=true, start=0), N=1) "Winding 1"
  Modelica.Electrical.Analog.Basic.Ground elGnd1
  Basic.Ground magGnd1
  Modelica.Electrical.Analog.Basic.Resistor resistor1(R=1)
  Modelica.Electrical.Analog.Sources.SignalVoltage vSource1
  Basic.ElectroMagneticConverterWithLeakageInductance winding2(i(start=0, fixed=true), N=1) "Winding 2"
  Modelica.Electrical.Analog.Basic.Ground elGnd2
  Shapes.HysteresisAndMagnets.GenericHystTellinenTable tellinenTable(
    includeEddyCurrents=false,
    sigma=1,
    K=100,
    mat=FluxTubes.Material.HysteresisTableData.M330_50A(),
    l=1,
    MagRel(fixed=true, start=0))
  Basic.Ground magGnd2
  Modelica.Electrical.Analog.Basic.Resistor resistor2(R=1)
  Modelica.Electrical.Analog.Sources.SignalVoltage vSource2
  Basic.ElectroMagneticConverterWithLeakageInductance winding3(i(fixed=true, start=0), N=1) "Winding 3"
  Modelica.Electrical.Analog.Basic.Ground elGnd3
  Shapes.HysteresisAndMagnets.GenericHystPreisachEverett preisachEverett(
    includeEddyCurrents=false,
    sigma=1,
    mat=FluxTubes.Material.HysteresisEverettParameter.M330_50A(),
    l=1,
    MagRel(fixed=true, start=0))
  Basic.Ground magGnd3
  Modelica.Electrical.Analog.Basic.Resistor resistor3(R=1)
  Modelica.Electrical.Analog.Sources.SignalVoltage vSource3
  Modelica.Blocks.Math.Gain gain(k=1)
  Shapes.HysteresisAndMagnets.GenericHystTellinenSoft tellinenSoft(
    l=1,
    Js=1.35,
    Br=1.0,
    Hc=40,
    K=100,
    MagRel(fixed=true, start=0))
equation
  connect(winding1.port_n, magGnd1.port)
  connect(resistor1.n, winding1.p)
  connect(winding1.n, elGnd1.p)
  connect(vSource1.p, resistor1.p)
  connect(elGnd1.p, vSource1.n)
  connect(winding2.port_n, magGnd2.port)
  connect(winding2.port_p, tellinenTable.port_p)
  connect(resistor2.n, winding2.p)
  connect(winding2.n, elGnd2.p)
  connect(vSource2.p, resistor2.p)
  connect(elGnd2.p, vSource2.n)
  connect(tellinenTable.port_n, magGnd2.port)
  connect(vSource2.v, vSource1.v)
  connect(winding3.port_n, magGnd3.port)
  connect(winding3.port_p, preisachEverett.port_p)
  connect(resistor3.n, winding3.p)
  connect(winding3.n, elGnd3.p)
  connect(vSource3.p, resistor3.p)
  connect(elGnd3.p, vSource3.n)
  connect(preisachEverett.port_n, magGnd3.port)
  connect(vSource3.v, vSource1.v)
  connect(timeTable.y, gain.u)
  connect(gain.y, vSource1.v)
  connect(winding1.port_p, tellinenSoft.port_p)
  connect(magGnd1.port,tellinenSoft. port_n)
end HysteresisModelComparison;


This is a simple model of an inductor with a ferromagnetic core. The used GenericHystTellinenEverett model considers the ferromagnetic hysteresis, eddy currents and remanence of the core material. For example you can simulate the model for 0.02s and plot Core.B vs. Core.H to visualize the resulting hysteresis loops.

<table border=\. This is a simple model of an inductor with a ferromagnetic core. The used GenericHystTellinenEverett model considers the ferromagnetic hysteresis, eddy currents and remanence of the core material. For example you can simulate the model for 0.02s and plot Core.B vs. Core.H to visualize the resulting hysteresis loops.

within Modelica.Magnetic.FluxTubes.Examples.Hysteresis;
model InductorWithHysteresis
  extends Modelica.Icons.Example;
  Basic.Ground mag_ground
  Basic.ElectroMagneticConverterWithLeakageInductance winding(i(fixed=
          true), N=10)
  Modelica.Electrical.Analog.Basic.Ground el_ground
  Modelica.Electrical.Analog.Basic.Resistor resistor(R=0.1)
  Modelica.Electrical.Analog.Sources.SineVoltage vSource(f=200, V=5)
  Shapes.HysteresisAndMagnets.GenericHystTellinenEverett core(
    mat=FluxTubes.Material.HysteresisEverettParameter.M330_50A(),
    A=4e-4,
    MagRel(fixed=true, start=0),
    includeEddyCurrents=true,
    derHstat(fixed=true),
    l=0.1)
equation
  connect(winding.port_n, mag_ground.port)
  connect(vSource.p, resistor.p)
  connect(vSource.n, el_ground.p)
  connect(winding.n, el_ground.p)
  connect(resistor.n, winding.p)
  connect(winding.port_p,core. port_p)
  connect(mag_ground.port,core. port_n)
end InductorWithHysteresis;


This simple model of an single-phase transformer shows the inrush currents due to the remanence of the core material (M330-50A). For an accurate modelling of the core material the GenericHystTellinenTable hysteresis flux tube element is used. The initial magnetization MagRel of the Core component is set to 80%. Simulation settings:

Stop time: 0.02 s

Number of intervals: 5000

Tolerance: 1e-6

Then plot the flux density of the Core Core.B over the magnetic field strength Core.H and additionally the time course of the primary and secondary current and e.g. the power consumption of the iron core Core.LossPower (see the following figures).

<table border=\. This simple model of an single-phase transformer shows the inrush currents due to the remanence of the core material (M330-50A). For an accurate modelling of the core material the GenericHystTellinenTable hysteresis flux tube element is used. The initial magnetization MagRel of the Core component is set to 80%. Simulation settings:

within Modelica.Magnetic.FluxTubes.Examples.Hysteresis;
model SinglePhaseTransformerWithHysteresis1
  extends Modelica.Icons.Example;
  Basic.Ground mag_ground
  Basic.ElectroMagneticConverterWithLeakageInductance winding1(N=10, i(fixed=true))
  Modelica.Electrical.Analog.Basic.Ground el_ground1
  Modelica.Electrical.Analog.Basic.Resistor resistor1(R=0.05)
  Modelica.Electrical.Analog.Sources.SineVoltage vSource(f=400, V=8)
  Basic.ElectroMagneticConverterWithLeakageInductance winding2(N=10, i(fixed=true))
  Modelica.Electrical.Analog.Basic.Resistor resistor2(R=2)
  Modelica.Electrical.Analog.Basic.Ground el_ground2
  Shapes.HysteresisAndMagnets.GenericHystTellinenTable core(
    asc(fixed=false),
    mat=FluxTubes.Material.HysteresisTableData.M330_50A(),
    includeEddyCurrents=true,
    l=0.2,
    A=5e-4,
    MagRel(start=0.5, fixed=true))
initial equation
  core.derHstat = 0.0;
equation
  connect(winding1.port_n, mag_ground.port)
  connect(vSource.p, resistor1.p)
  connect(vSource.n, el_ground1.p)
  connect(winding1.n, el_ground1.p)
  connect(resistor1.n, winding1.p)
  connect(winding2.port_n, mag_ground.port)
  connect(winding2.p, resistor2.p)
  connect(winding2.n, el_ground2.p)
  connect(resistor2.n, el_ground2.p)
  connect(winding1.port_p, core.port_p)
  connect(core.port_n, winding2.port_p)
end SinglePhaseTransformerWithHysteresis1;


A simple model of an single-phase transformer (similar to <a href=\. A simple model of an single-phase transformer (similar to SinglePhaseTransformerWithHysteresis1 but with separate transformer model: Transformer1PhaseWithHysteresis). Use the simulation settings:

within Modelica.Magnetic.FluxTubes.Examples.Hysteresis;
model SinglePhaseTransformerWithHysteresis2
  extends Modelica.Icons.Example;
  Modelica.Electrical.Analog.Basic.Ground el_ground1
  Modelica.Electrical.Analog.Basic.Resistor resistor1(R=0.05)
  Modelica.Electrical.Analog.Sources.SineVoltage SineVoltage(f=
       400, V=6)
  Modelica.Electrical.Analog.Basic.Resistor resistor2(R=2)
  Modelica.Electrical.Analog.Basic.Ground el_ground2
  Components.Transformer1PhaseWithHysteresis transformer(
    mat=FluxTubes.Material.HysteresisEverettParameter.M330_50A(),
    MagRelFixed=true,
    I1Fixed=true,
    EddyCurrents=false,
    HFixed=false)
initial equation
  transformer.core.derHstat = 0.0;
equation
  connect(SineVoltage.p, resistor1.p)
  connect(SineVoltage.n, el_ground1.p)
  connect(resistor2.n, el_ground2.p)
  connect(resistor1.n, transformer.p1)
  connect(transformer.n1, el_ground1.p)
  connect(transformer.p2, resistor2.p)
  connect(transformer.n2, el_ground2.p)
end SinglePhaseTransformerWithHysteresis2;