Piwi447
Piwi447

Reputation: 31

Modelica fluid mixing simulation

I am newbie to modelica.

I am searching for people having experience with (open)modelica regarding fluid and media library.

My goal is to simulate pressure of a volume related to injection flows of N2 and H2 and controlled outlet valve but also time varying mass fraction ( due to very large volume compared to flow injection / outlet capacity ) Thanks for any feedback. I have a more detailed explanation of my project that I can can share in private.

Up to now I only tried to create a new medium for HNx ( H2N2) from media library using idealgases NasaGasMixture

My main problem is that modelica unit for flow is Kg/s and our industrial practice is Nm3/h ( same for H2 contraction ( molar fraction) related to mass fraction I found molartomassfraction function in the library but do not see how to use this properly to modify the interface using our usual units( for display of measurement, setpoint, but also curves )

Upvotes: 1

Views: 508

Answers (1)

Rene Just Nielsen
Rene Just Nielsen

Reputation: 3413

The equations in Modelica.Fluid are all formulated with masses so you will have to do the conversion to and from chemical units (normal flow and molar fractions) "outside" the Modelica.Fluid components.

I have provided an example where you can vary normal flow and molar fractions of a mixture of N2/H2. Diagram, selected results and code is provided below. All the conversion blocks to the left can, of course, be written in code and/or wrapped nicely in a submodel.

Diagram Diagram view

Selected results Selected results

Medium model

package MixtureGas "Mixture gas"
  extends Modelica.Media.IdealGases.Common.MixtureGasNasa(
    mediumName="MixtureGas",
    data={Modelica.Media.IdealGases.Common.SingleGasesData.N2,Modelica.Media.IdealGases.Common.SingleGasesData.H2},
    fluidConstants={Modelica.Media.IdealGases.Common.FluidData.N2,Modelica.Media.IdealGases.Common.FluidData.H2},
    substanceNames={"N2","H2"},
    reference_X={0.4,0.6});
end MixtureGas;

Simulation Model

model Mixing "Molar fractions and normal flow as independent inputs"
  extends Modelica.Icons.Example;
  package Medium = MixtureGas;

  parameter Medium.AbsolutePressure p_normal=Medium.p_default "Normal pressure";
  parameter Medium.Temperature T_normal=273.15 "Normal temperature";
  Medium.Density rho_normal=Medium.density_pTX(
      p_normal,
      T_normal,
      X) "Normal density of mixture";

  // Conversion from mole to mass fractions 
  Real X[Medium.nX]=Medium.moleToMassFractions(moleFractions=moleFractions.y,
      MMX=Medium.data.MM) "Mass fraction vector {N2, H2}";

  Modelica.Fluid.Sources.MassFlowSource_T source(
    use_m_flow_in=true,
    use_X_in=true,
    redeclare package Medium = Medium,
    nPorts=1)
    annotation (Placement(transformation(extent={{-60,-10},{-40,10}})));
  Modelica.Fluid.Sources.Boundary_pT boundary1(nPorts=1, redeclare package
      Medium = Medium)
    annotation (Placement(transformation(extent={{140,-10},{120,10}})));
  Modelica.Fluid.Vessels.ClosedVolume volume(
    use_portsData=false,
    V=0.1,
    redeclare package Medium = Medium,
    nPorts=2) annotation (Placement(transformation(
        extent={{-10,-10},{10,10}},
        rotation=0,
        origin={-10,20})));
  inner Modelica.Fluid.System system(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    annotation (Placement(transformation(extent={{-140,80},{-120,100}})));
  Modelica.Fluid.Sensors.MassFractionsTwoPort massFraction_H2(redeclare package
      Medium = Medium, substanceName="H2")
    annotation (Placement(transformation(extent={{10,-10},{30,10}})));
  Modelica.Fluid.Sensors.MassFractionsTwoPort massFraction_N2(redeclare package
      Medium = Medium, substanceName="N2")
    annotation (Placement(transformation(extent={{50,-10},{70,10}})));
  Modelica.Blocks.Sources.Ramp Nm3PerHour(
    height=10,
    duration=10,
    startTime=10)
    annotation (Placement(transformation(extent={{-140,-2},{-120,18}})));
  Modelica.Blocks.Sources.Constant const(k=1)
    annotation (Placement(transformation(extent={{70,20},{90,40}})));
  Modelica.Fluid.Valves.ValveLinear valve(
    dp_nominal=100000,
    m_flow_nominal=0.03,
    redeclare package Medium = Medium)
    annotation (Placement(transformation(extent={{90,-10},{110,10}})));
  Modelica.Blocks.Math.Product toMassFlowRate
    annotation (Placement(transformation(extent={{-100,4},{-80,24}})));
  Modelica.Blocks.Sources.RealExpression density(y=rho_normal/3600)
    annotation (Placement(transformation(extent={{-140,30},{-120,50}})));
  Modelica.Blocks.Sources.Ramp molarFractionH2(duration=60, startTime=60)
    annotation (Placement(transformation(extent={{-140,-80},{-120,-60}})));
  Modelica.Blocks.Sources.Constant one(k=1)
    annotation (Placement(transformation(extent={{-140,-50},{-120,-30}})));
  Modelica.Blocks.Math.Feedback molarFractionN2 "fractions must sum to one"
    annotation (Placement(transformation(extent={{-110,-50},{-90,-30}})));
  Modelica.Blocks.Routing.Multiplex2 moleFractions
    annotation (Placement(transformation(extent={{-70,-56},{-50,-36}})));
  Modelica.Blocks.Sources.RealExpression massFractions[Medium.nX](y=X)
    annotation (Placement(transformation(extent={{-100,0},{-80,-20}})));
equation 
  connect(massFraction_H2.port_b, massFraction_N2.port_a)
    annotation (Line(points={{30,0},{50,0}}, color={0,127,255}));
  connect(massFraction_N2.port_b, valve.port_a)
    annotation (Line(points={{70,0},{90,0}}, color={0,127,255}));
  connect(valve.port_b, boundary1.ports[1])
    annotation (Line(points={{110,0},{120,0}}, color={0,127,255}));
  connect(const.y, valve.opening)
    annotation (Line(points={{91,30},{100,30},{100,8}}, color={0,0,127}));
  connect(source.ports[1], volume.ports[1])
    annotation (Line(points={{-40,0},{-11,0},{-11,10}}, color={0,127,255}));
  connect(massFraction_H2.port_a, volume.ports[2])
    annotation (Line(points={{10,0},{-9,0},{-9,10}}, color={0,127,255}));
  connect(Nm3PerHour.y, toMassFlowRate.u2)
    annotation (Line(points={{-119,8},{-102,8}}, color={0,0,127}));
  connect(toMassFlowRate.y, source.m_flow_in) annotation (Line(points={{-79,14},
          {-70,14},{-70,8},{-60,8}}, color={0,0,127}));
  connect(density.y, toMassFlowRate.u1) annotation (Line(points={{-119,40},{-108,
          40},{-108,20},{-102,20}}, color={0,0,127}));
  connect(one.y, molarFractionN2.u1)
    annotation (Line(points={{-119,-40},{-108,-40}}, color={0,0,127}));
  connect(molarFractionH2.y, molarFractionN2.u2) annotation (Line(points={{-119,
          -70},{-100,-70},{-100,-48}}, color={0,0,127}));
  connect(molarFractionN2.y, moleFractions.u1[1])
    annotation (Line(points={{-91,-40},{-72,-40}}, color={0,0,127}));
  connect(molarFractionH2.y, moleFractions.u2[1]) annotation (Line(points={{-119,
          -70},{-86,-70},{-86,-52},{-72,-52}}, color={0,0,127}));
  connect(massFractions.y, source.X_in) annotation (Line(points={{-79,-10},{-70,
          -10},{-70,-4},{-62,-4}}, color={0,0,127}));
  annotation (Diagram(coordinateSystem(extent={{-140,-100},{140,100}}),
        graphics={Line(
          points={{-46,-46},{-34,-46},{-34,-24},{-114,-24},{-114,-10},{-104,-10}},

          color={255,0,0},
          arrow={Arrow.None,Arrow.Filled},
          pattern=LinePattern.Dash)}), experiment(StopTime=500));
end Mixing;

Edit after comment

It is also possible to separate N2/H2 into two separate sources. A code example and diagram is given below

enter image description here

model Mixing_separateSources
  extends Modelica.Icons.Example;
  package Medium = MixtureGas;

  parameter Medium.AbsolutePressure p_normal=Medium.p_default "Normal pressure";
  parameter Medium.Temperature T_normal=273.15 "Normal temperature";
  parameter Medium.Density rho_normal_N2=Medium.density_pTX(
      p_normal,
      T_normal,
      {1,0}) "Normal density of N2";
  parameter Medium.Density rho_normal_H2=Medium.density_pTX(
      p_normal,
      T_normal,
      {0,1}) "Normal density of H2";

  Modelica.Fluid.Sources.MassFlowSource_T N2(
    use_m_flow_in=true,
    X={1,0},
    redeclare package Medium = Medium,
    nPorts=1)
    annotation (Placement(transformation(extent={{-60,-10},{-40,10}})));
  Modelica.Fluid.Sources.Boundary_pT boundary1(nPorts=1, redeclare package
      Medium = Medium)
    annotation (Placement(transformation(extent={{140,-10},{120,10}})));
  Modelica.Fluid.Sources.MassFlowSource_T H2(
    use_m_flow_in=true,
    X={0,1},
    redeclare package Medium = Medium,
    nPorts=1)
    annotation (Placement(transformation(extent={{-60,-50},{-40,-30}})));
  inner Modelica.Fluid.System system(energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    annotation (Placement(transformation(extent={{-140,40},{-120,60}})));
  Modelica.Fluid.Sensors.MassFractionsTwoPort massFraction_H2(redeclare package
      Medium = Medium, substanceName="H2")
    annotation (Placement(transformation(extent={{10,-10},{30,10}})));
  Modelica.Fluid.Sensors.MassFractionsTwoPort massFraction_N2(redeclare package
      Medium = Medium, substanceName="N2")
    annotation (Placement(transformation(extent={{50,-10},{70,10}})));
  Modelica.Blocks.Math.Gain toMassFlowRate_N2(k=rho_normal_N2/3600)
    annotation (Placement(transformation(extent={{-100,-2},{-80,18}})));
  Modelica.Blocks.Math.Gain toMassFlowRate_H2(k=rho_normal_H2/3600)
    annotation (Placement(transformation(extent={{-100,-42},{-80,-22}})));
  Modelica.Blocks.Sources.Ramp N2_Nm3PerHour(
    height=10,
    duration=10,
    startTime=10)
    annotation (Placement(transformation(extent={{-140,-2},{-120,18}})));
  Modelica.Blocks.Sources.Ramp H2_Nm3PerHour(
    height=-10,
    duration=10,
    offset=10,
    startTime=10)
    annotation (Placement(transformation(extent={{-140,-42},{-120,-22}})));
  Modelica.Blocks.Sources.Constant const(k=1)
    annotation (Placement(transformation(extent={{70,20},{90,40}})));
  Modelica.Fluid.Valves.ValveLinear valve(
    dp_nominal=100000,
    m_flow_nominal=0.03,
    redeclare package Medium = Medium)
    annotation (Placement(transformation(extent={{90,-10},{110,10}})));
  Modelica.Fluid.Vessels.ClosedVolume volume(
    use_portsData=false,
    V=0.1,
    redeclare package Medium = Medium,
    nPorts=3) annotation (Placement(transformation(
        extent={{-10,-10},{10,10}},
        rotation=0,
        origin={-10,20})));
equation 
  connect(massFraction_H2.port_b, massFraction_N2.port_a)
    annotation (Line(points={{30,0},{50,0}}, color={0,127,255}));
  connect(toMassFlowRate_N2.y, N2.m_flow_in)
    annotation (Line(points={{-79,8},{-60,8}}, color={0,0,127}));
  connect(toMassFlowRate_H2.y, H2.m_flow_in)
    annotation (Line(points={{-79,-32},{-60,-32}}, color={0,0,127}));
  connect(H2_Nm3PerHour.y, toMassFlowRate_H2.u)
    annotation (Line(points={{-119,-32},{-102,-32}}, color={0,0,127}));
  connect(N2_Nm3PerHour.y, toMassFlowRate_N2.u)
    annotation (Line(points={{-119,8},{-102,8}}, color={0,0,127}));
  connect(massFraction_N2.port_b, valve.port_a)
    annotation (Line(points={{70,0},{90,0}}, color={0,127,255}));
  connect(valve.port_b, boundary1.ports[1])
    annotation (Line(points={{110,0},{120,0}}, color={0,127,255}));
  connect(const.y, valve.opening)
    annotation (Line(points={{91,30},{100,30},{100,8}}, color={0,0,127}));
  connect(N2.ports[1], volume.ports[1]) annotation (Line(points={{-40,0},{-11.3333,
          0},{-11.3333,10}}, color={0,127,255}));
  connect(H2.ports[1], volume.ports[2]) annotation (Line(points={{-40,-40},{-10,
          -40},{-10,10}}, color={0,127,255}));
  connect(massFraction_H2.port_a, volume.ports[3]) annotation (Line(points={{10,
          0},{-8.66667,0},{-8.66667,10}}, color={0,127,255}));
  annotation (Diagram(coordinateSystem(extent={{-140,-100},{140,100}})),
      experiment(StopTime=500, __Dymola_Algorithm="Dassl"));
end Mixing_separateSources;

Upvotes: 1

Related Questions