3

I am having some difficulty in finding exactly the best way to write the energy balance of a simple lumped volume, say a pipe, with fluid flow and a heat flow output. I basically just want to add a Q_loss term in the energy balance to reduce the temperature of any fluid flowing through, but keep the overall model super simple (no friction, pressure, convection losses etc).

I tried to write a simple model but I am getting stuck having one less equation than I need. Is there a way to do this without fixing the pressure?

My code (the medium is not standard and may need to be redeclared):

model IdealLossPipe
   extends SolarTherm.Interfaces.Models.Pipe;
  Medium.BaseProperties medium;
  replaceable package Medium = SolarTherm.Media.MoltenSalt.MoltenSalt_base
    constrainedby Modelica.Media.Interfaces.PartialMedium
  Modelica.Fluid.Interfaces.FluidPort_a fluid_a(redeclare package Medium =
        Medium);
  Modelica.Fluid.Interfaces.FluidPort_b fluid_b(redeclare package Medium =
        Medium) annotation (Placement(transformation(extent={{110,-10},{90,10}}, rotation=0),
        iconTransformation(extent={{110,-10},{90,10}})));
    parameter Real Q_loss_spec(unit="W/m") = 284 "Heat loss per m of piping";
    SI.HeatFlowRate Q_loss;
    parameter SI.Length length = 13.1 annotation(Dialog(group="Length"));
    parameter SI.Length diameter = 0.052;

    SI.Energy U;
    SI.Mass m;
    SI.Volume V;

equation 
  V = length*(diameter/2)^2*Modelica.Constants.pi;
  m=V*medium.d;
  U=m*medium.u;
  fluid_a.p=medium.p;
  fluid_b.p=medium.p;
  (instream(fluid_a.h_outflow)+fluid_b.h_outflow)/2=medium.h;
  fluid_a.h_outflow=0;
  Q_loss=-length*Q_loss_spec;

  //Mass Balance
  fluid_a.m_flow+fluid_b.m_flow=der(m);

  //Energy Balance
  der(U)= fluid_a.m_flow*inStream(fluid_a.h_outflow) + fluid_b.m_flow*fluid_b.h_outflow + Q_loss;

end IdealLossPipe;

Thank you in advance for helping me out!!

EDIT: removed unecessary heatPort in my model

1 Answers1

1

I edited your model (see below). Some additions included initialization of medium which is required if using that approach for base properties. It would be helpful to take a close look at existing open-source fluid libraries (e.g., Modelica Standard Library, TRANSFORM, or ThermoPower) to see how they do things or use their components.

model IdealLossPipe
  import SI = Modelica.SIunits;

  replaceable package Medium = Modelica.Media.Water.StandardWater
    constrainedby Modelica.Media.Interfaces.PartialMedium annotation (
      choicesAllMatching=true);

  Medium.BaseProperties medium(
    each preferredMediumStates=true,
    p(start=p_start),
    T(start=T_start),
    h(start=Medium.specificEnthalpy(Medium.setState_pT(p_start, T_start))),
    d(start=Medium.density(Medium.setState_pT(p_start, T_start))),
    u(start=Medium.specificInternalEnergy(Medium.setState_pT(p_start, T_start))),
    Xi(start=X_start[1:Medium.nXi]),
    X(start=X_start));

  Modelica.Fluid.Interfaces.FluidPort_a fluid_a(redeclare package Medium =
        Medium) annotation (Placement(transformation(extent={{-90,-10},{-110,10}},
          rotation=0), iconTransformation(extent={{-90,-10},{-110,10}})));
  Modelica.Fluid.Interfaces.FluidPort_b fluid_b(redeclare package Medium =
        Medium) annotation (Placement(transformation(extent={{110,-10},{90,10}},
          rotation=0), iconTransformation(extent={{110,-10},{90,10}})));

  parameter Real Q_loss_spec(unit="W/m") = 284 "Heat loss per m of piping";
  parameter SI.Length length=13.1 annotation (Dialog(group="Length"));
  parameter SI.Length diameter=0.052;

  // Initialization
  parameter SI.Pressure p_start=1e5;
  parameter SI.Temperature T_start=293.15;
  parameter SI.MassFraction X_start[Medium.nX]=Medium.X_default "Mass fraction";

  SI.HeatFlowRate Q_loss;
  SI.Energy U;
  SI.Mass m;
  SI.Volume V;

equation 

  V = length*(diameter/2)^2*Modelica.Constants.pi;
  m = V*medium.d;
  U = m*medium.u;

  Q_loss = -length*Q_loss_spec;

  //Mass Balance
  fluid_a.m_flow + fluid_b.m_flow = der(m);

  //Energy Balance
  der(U) = fluid_a.m_flow*inStream(fluid_a.h_outflow) + fluid_b.m_flow*inStream(
     fluid_b.h_outflow) + Q_loss;

  // Port definitions
  fluid_a.h_outflow = medium.h;
  fluid_b.h_outflow = medium.h;
  fluid_a.p = medium.p;
  fluid_b.p = medium.p;
  fluid_a.Xi_outflow = medium.Xi;
  fluid_b.Xi_outflow = medium.Xi;
  fluid_a.C_outflow = inStream(fluid_b.C_outflow);
  fluid_b.C_outflow = inStream(fluid_a.C_outflow);
end IdealLossPipe;

One thing to keep in mind is the "flow vs volume" or "non-state (flow) vs state (non-flow/volume)" representation of models. A port which exposes a state sets the value of the state variables of the connectors (i.e., pressure for fluid) while a non-state port sets the flow variables of the connector (i.e., mass flow rate for fluid). So for fluids, you want to make sure you do not connect ports that each set the pressure (state variable). Similar with mass flow rate but that tends to be more forgiving by the solver.

For reference, your model sets the state variable (fluid_a.p = medium.p, fluid_b.p = medium.p). A simple model example would want to connect each port with a model that sets the mass flow rate such as a mass flow source on fluid_a and a resistance element followed by a pressure boundary on fluid_b.

model Example
  Unnamed pipe(redeclare package Medium = Modelica.Media.Water.StandardWater,
      Q_loss_spec=10000)
    annotation (Placement(transformation(extent={{-68,4},{-48,24}})));
  Modelica.Fluid.Sources.Boundary_pT boundary(
    nPorts=1,
    redeclare package Medium = Modelica.Media.Water.StandardWater,
    p=100000,
    T=293.15) annotation (Placement(transformation(extent={{34,2},{14,22}})));
  Modelica.Fluid.Sources.MassFlowSource_T boundary1(
    nPorts=1,
    redeclare package Medium = Modelica.Media.Water.StandardWater,
    m_flow=1,
    T=293.15)
    annotation (Placement(transformation(extent={{-124,2},{-104,22}})));
  Modelica.Fluid.Valves.ValveLinear valveLinear(
    redeclare package Medium = Modelica.Media.Water.StandardWater,
    dp_nominal=100000,
    m_flow_nominal=1)
    annotation (Placement(transformation(extent={{-30,4},{-10,24}})));
  Modelica.Blocks.Sources.Constant const(k=1)
    annotation (Placement(transformation(extent={{-52,30},{-32,50}})));
equation 
  connect(boundary1.ports[1], pipe.fluid_a) annotation (Line(points={{-104,12},{
          -86,12},{-86,14},{-68,14}}, color={0,127,255}));
  connect(pipe.fluid_b, valveLinear.port_a)
    annotation (Line(points={{-48,14},{-30,14}}, color={0,127,255}));
  connect(valveLinear.port_b, boundary.ports[1]) annotation (Line(points={{-10,14},
          {2,14},{2,12},{14,12}}, color={0,127,255}));
  connect(const.y, valveLinear.opening)
    annotation (Line(points={{-31,40},{-20,40},{-20,22}}, color={0,0,127}));

end Example;
Scott G
  • 2,194
  • 1
  • 14
  • 24
  • 1
    Thank you very much for your help! My other question is - How does this work in a closed loop system? In the literature it says that a pump (for example) is required to act as a free pressure source. Is this also the case for the mass flow? What sort of component would you leave the mass flow undefined? Also, in a closed loop system, is it possible to have two volumes open to the ambient (ie the pressure in each volume is fixed to the ambient pressure), but each volume connected with a pump circulating fluid? In this case with two fixed pressures does that mean you need two free pressures? – Darcy Corbett Feb 19 '18 at 18:06
  • 1
    In a closed system the pump may act as a free pressure source (i.e., it let's its outlet pressure float according to the set flow rate). There are nuances to that statement though but for simplicity I'll say that's true. In that case the pump sets the flow rate (or deltaP) of the model. Can you have multiple open to ambient volumes?.. of course! it just depends on the model though on how it all looks. So with multiple pumps each pump mass flow rate (deltap) will depend on from where and to what it is pumping. – Scott G Feb 19 '18 at 20:00
  • 1
    So it is possible to have just one pump and several tanks set to the ambient pressure in a closed loop system? I have been finding I am getting errors/overdetermined systems when I try this. Are valves necessary or will pipes usually work to fulfil the flow/volume requirement? – Darcy Corbett Feb 19 '18 at 23:52
  • Short answer yes. An example I can think of is you want to pump water up a hill from one tank to a tank at a higher elevation. The water leaves the higher tank via a pipe to the lower tank via gravity drain. The process repeats. Modeling it though comes to components being used and how well they work, as you are learning. Valves are just flow elements (set mass flow rate/dp) so anything that does similar could work such as a simple flow resistance. – Scott G Feb 20 '18 at 18:12
  • @DarcyCorbett. Please mark the answer as accepted if the original question was answered. Thanks :) – Scott G Feb 20 '18 at 21:07