首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用OpenModelica组件构建PlugFlowPipe库

使用OpenModelica组件构建PlugFlowPipe库
EN

Stack Overflow用户
提问于 2022-01-31 07:21:29
回答 1查看 105关注 0票数 2

这个问题是问题的延续:OpenModelica: How to model plug flow for multi substance fluid medium?

在默认情况下,modelica不包括支持多种物质和痕量物质的介质模型。因此,我把一个介质模型和基本的Modelica流体组件(源、开罐、静态管道)结合在一起。然而,建筑物库的组件Buildings.Fluid.FixedResistances.PlugFlowPipe似乎是有问题的,我不知道为什么?我在OpenModelica方面的经验非常有限,如果有人能帮我指出理由,我会很感激的。

由于我还没有在其他库中找到任何其他组件来建模管道中的塞流和传输延迟,所以我最终来到了Building库。

下面是用于测试的介质模型和仿真模型。

使用的介质模型:

代码语言:javascript
复制
// file: SimpleMachineStockMedium_400_v1.mo 
package SimpleMachineStockMedium_400_v1

  import Modelica = Modelica;


  // EXTENDING FROM A CLASS
  // **************************


  extends Modelica.Media.Interfaces.PartialMedium(
      final ThermoStates = Modelica.Media.Interfaces.Choices.IndependentVariables.pTX, 
      final singleState = true, 
      final reducedX = true, 
      final fixedX = false, 
      reference_X=fill(1/nX,nX),
      mediumName="SimpleMachineStockMedium_400_v1",
      substanceNames={"water","fiber","filler"},
      extraPropertiesNames=fill("", 0)
      
      //extraPropertiesNames={"reta"}
      );

  // SPECIFY CONSTANTS
  // *********************************

  constant SpecificHeatCapacity cp_const=4184  "Constant specific heat capacity at constant pressure";
  constant SpecificHeatCapacity cv_const=4184  "Constant specific heat capacity at constant volume";
  constant Density d_const=995.586 "Constant density";
  constant DynamicViscosity eta_const=1.e-3 "Constant dynamic viscosity";
  constant ThermalConductivity lambda_const=0.598 "Constant thermal conductivity";
  constant VelocityOfSound a_const=1484 "Constant velocity of sound";
  constant Temperature T_min=273 "Minimum temperature valid for medium model";
  constant Temperature T_max=373 "Maximum temperature valid for medium model";
  constant Temperature T0=273.15 "Zero enthalpy temperature";




  // defining fluid constants for substances
  import Modelica.Media.Water.ConstantPropertyLiquidWater.simpleWaterConstants;

  constant Modelica.Media.Interfaces.Types.Basic.FluidConstants[3]
    simpleWaterConstants(
    each chemicalFormula="H2O",
    each structureFormula="H2O",
    each casRegistryNumber="7732-18-5",
    each iupacName="oxidane",
    each molarMass=0.018015268);



  //constant MolarMass MM_const "Molar mass";
  // Molarmasses are defined for substances, just giving same values for all
  constant Real MM_const_fiber = 0.018015268;
  constant Real MM_const_filler = 0.018015268;
  constant Real MM_const_water = 0.018015268;

  constant MolarMass[nX] MMX ={MM_const_fiber, MM_const_filler, MM_const_water} "Molar mass";


  // THERMODYNAMIC STATE
  // **********************


  redeclare record extends ThermodynamicState "Thermodynamic state"
    AbsolutePressure p "Absolute pressure of medium";
    Temperature T "Temperature of medium";

    // bring in the substances
    MassFraction[nX] X(start=reference_X) "Mass fractions (= (component mass)/total mass  m_i/m)";  

  end ThermodynamicState;



  // MODEL BaseProperties
  // ********************

  redeclare replaceable model extends BaseProperties(
    T(stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default),
    p(stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default), 
    Xi(each stateSelect = if preferredMediumStates then StateSelect.prefer else StateSelect.default),
    final standardOrderComponents = true) "Base properties"

  equation
    assert(T >= T_min and T <= T_max, "
      Temperature T (= " + String(T) + " K) is not
      in the allowed range (" + String(T_min) + " K <= T <= " + String(T_max) + " K)
      required from medium model \"" + mediumName + "\".
      ");

    // h = cp_const*(T-T0);
    h = specificEnthalpy_pTX(
            p,
            T,
            X);
    u = cv_const*(T - T0);
    d = d_const;
    R_s = 0;
    //MM = MM_const;
    MM = molarMass(state);
    state.T = T;
    state.p = p;
    state.X = if fixedX then reference_X else X;

    annotation (Documentation(info="<html>
    <p>
    This is the most simple incompressible medium model, where
    specific enthalpy h and specific internal energy u are only
    a function of temperature T and all other provided medium
    quantities are assumed to be constant.
    Note that the (small) influence of the pressure term p/d is neglected.
    </p>
    </html>"));
    end BaseProperties;

  // DECLARE FUNCTIONS
  // *******************


  //-------------------
  redeclare function setState_pTX
    "Return thermodynamic state from p, T, and X or Xi"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input Temperature T "Temperature";
    input MassFraction X[:]=reference_X "Mass fractions";
    output ThermodynamicState state "Thermodynamic state record";
  algorithm
    //state := ThermodynamicState(p=p, T=T);

    // take into account substances
    state := if size(X,1) == 0 then ThermodynamicState(p=p,T=T,X=reference_X) 
        else if size(X,1) == nX then ThermodynamicState(p=p,T=T, X=X) 
        else ThermodynamicState(p=p,T=T, X=cat(1,X,{1-sum(X)}));   // when reduceX = true

  end setState_pTX;

  //-------------------
  redeclare function setState_phX
    "Return thermodynamic state from p, h, and X or Xi"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input SpecificEnthalpy h "Specific enthalpy";
    input MassFraction X[:]=reference_X "Mass fractions";
    output ThermodynamicState state "Thermodynamic state record";
  
  algorithm

    state := if size(X,1) == 0 then ThermodynamicState(p = p, T = T0 + h / cp_const, X=X)
         else if size(X,1) == nX then ThermodynamicState(p = p, T = T0 + h / cp_const, X=X)
         else ThermodynamicState(p = p, T = T0 + h / cp_const, X=cat(1,X,{1-sum(X)}));

  end setState_phX;

  //-------------------
  redeclare replaceable function setState_psX
    "Return thermodynamic state from p, s, and X or Xi"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input SpecificEntropy s "Specific entropy";
    input MassFraction X[:]=reference_X "Mass fractions";
    output ThermodynamicState state "Thermodynamic state record";
  algorithm
    //state := ThermodynamicState(p=p, T=Modelica.Math.exp(s/cp_const +
    //  Modelica.Math.log(reference_T)))
    //  "Here the incompressible limit is used, with cp as heat capacity";

    // take into account substances
    state := if size(X,1) == 0 then ThermodynamicState(p = p, T = Modelica.Math.exp(s / cp_const + Modelica.Math.log(reference_T)), X=X)
             else if size(X,1) == nX then ThermodynamicState(p = p, T = Modelica.Math.exp(s / cp_const + Modelica.Math.log(reference_T)), X=X)
             else ThermodynamicState(p = p, T = Modelica.Math.exp(s / cp_const + Modelica.Math.log(reference_T)), X=cat(1,X,{1-sum(X)}));
  end setState_psX;

  //-------------------
  redeclare function setState_dTX
    "Return thermodynamic state from d, T, and X or Xi"
    extends Modelica.Icons.Function;
    input Density d "Density";
    input Temperature T "Temperature";
    input MassFraction X[:]=reference_X "Mass fractions";
    output ThermodynamicState state "Thermodynamic state record";
  algorithm
    assert(false,
      "Pressure can not be computed from temperature and density for an incompressible fluid!");
  end setState_dTX;

  //-------------------
  redeclare function extends setSmoothState
    "Return thermodynamic state so that it smoothly approximates: if x > 0 then state_a else state_b"
  algorithm
    state := ThermodynamicState(p=Media.Common.smoothStep(
            x,
            state_a.p,
            state_b.p,
            x_small), T=Media.Common.smoothStep(
            x,
            state_a.T,
            state_b.T,
            x_small));
  end setSmoothState;

  //-------------------
  redeclare function extends dynamicViscosity "Return dynamic viscosity"

  algorithm
    eta := eta_const;
  end dynamicViscosity;

  //-------------------
  redeclare function extends thermalConductivity
    "Return thermal conductivity"

  algorithm
    lambda := lambda_const;
  end thermalConductivity;

  //-------------------
  redeclare function extends pressure "Return pressure"

  algorithm
    p := state.p;
  end pressure;

  //-------------------
  redeclare function extends temperature "Return temperature"

  algorithm
    T := state.T;
  end temperature;

  //-------------------
  redeclare function extends density "Return density"

  algorithm
    d := d_const;
  end density;

  //-------------------
  redeclare function extends specificEnthalpy "Return specific enthalpy"

  algorithm
    h := cp_const*(state.T - T0);
  end specificEnthalpy;

  //-------------------
  redeclare function extends specificHeatCapacityCp
    "Return specific heat capacity at constant pressure"

  algorithm
    cp := cp_const;
  end specificHeatCapacityCp;

  //-------------------
  redeclare function extends specificHeatCapacityCv
    "Return specific heat capacity at constant volume"

  algorithm
    cv := cv_const;
  end specificHeatCapacityCv;

  //-------------------
  redeclare function extends isentropicExponent "Return isentropic exponent"

  algorithm
    gamma := cp_const/cv_const;
  end isentropicExponent;

  //-------------------
  redeclare function extends velocityOfSound "Return velocity of sound"

  algorithm
    a := a_const;
  end velocityOfSound;

  //-------------------
  redeclare function specificEnthalpy_pTX
    "Return specific enthalpy from p, T, and X or Xi"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input Temperature T "Temperature";
    input MassFraction X[nX] "Mass fractions";
    output SpecificEnthalpy h "Specific enthalpy";
  algorithm
    h := cp_const*(T - T0);
    annotation (Documentation(info="<html>
    <p>
    This function computes the specific enthalpy of the fluid, but neglects the (small) influence of the pressure term p/d.
    </p>
    </html>"));
  end specificEnthalpy_pTX;

  //-------------------
  redeclare function temperature_phX
    "Return temperature from p, h, and X or Xi"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input SpecificEnthalpy h "Specific enthalpy";
    input MassFraction X[nX] "Mass fractions";
    output Temperature T "Temperature";
  algorithm
    T := T0 + h/cp_const;
  end temperature_phX;

  //-------------------
  redeclare function density_phX "Return density from p, h, and X or Xi"
    extends Modelica.Icons.Function;
    input AbsolutePressure p "Pressure";
    input SpecificEnthalpy h "Specific enthalpy";
    input MassFraction X[nX] "Mass fractions";
    output Density d "Density";
  algorithm
    d := density(setState_phX(
            p,
            h,
            X));
  end density_phX;

  //-------------------
  redeclare function extends specificInternalEnergy
    "Return specific internal energy"
    extends Modelica.Icons.Function;
  algorithm
    //  u := cv_const*(state.T - T0) - reference_p/d_const;
    u := cv_const*(state.T - T0);
    annotation (Documentation(info="<html>
    <p>
    This function computes the specific internal energy of the fluid, but neglects the (small) influence of the pressure term p/d.
    </p>
    </html>"));
  end specificInternalEnergy;

  //-------------------
  redeclare function extends specificEntropy "Return specific entropy"
    extends Modelica.Icons.Function;
  algorithm
    s := cv_const*Modelica.Math.log(state.T/T0);
  end specificEntropy;

  //-------------------
  redeclare function extends specificGibbsEnergy
    "Return specific Gibbs energy"
    extends Modelica.Icons.Function;
  algorithm
    g := specificEnthalpy(state) - state.T*specificEntropy(state);
  end specificGibbsEnergy;

  //-------------------
  redeclare function extends specificHelmholtzEnergy
    "Return specific Helmholtz energy"
    extends Modelica.Icons.Function;
  algorithm
    f := specificInternalEnergy(state) - state.T*specificEntropy(state);
  end specificHelmholtzEnergy;

  //-------------------
  redeclare function extends isentropicEnthalpy "Return isentropic enthalpy"
  algorithm
    h_is := cp_const*(temperature(refState) - T0);
  end isentropicEnthalpy;

  //-------------------
  redeclare function extends isobaricExpansionCoefficient
    "Returns overall the isobaric expansion coefficient beta"
  algorithm
    beta := 0.0;
  end isobaricExpansionCoefficient;

  //-------------------
  redeclare function extends isothermalCompressibility
    "Returns overall the isothermal compressibility factor"
  algorithm
    kappa := 0;
  end isothermalCompressibility;

  //-------------------
  redeclare function extends density_derp_T
    "Returns the partial derivative of density with respect to pressure at constant temperature"
  algorithm
    ddpT := 0;
  end density_derp_T;

  //-------------------
  redeclare function extends density_derT_p
    "Returns the partial derivative of density with respect to temperature at constant pressure"
  algorithm
    ddTp := 0;
  end density_derT_p;

  //-------------------
  redeclare function extends density_derX
    "Returns the partial derivative of density with respect to mass fractions at constant pressure and temperature"
  algorithm
    dddX := fill(0, nX);
  end density_derX;

  //-------------------
  redeclare function extends molarMass "Return the molar mass of the medium"
  algorithm
    //MM := MM_const;
    MM := 1/sum(state.X[j]/MMX[j] for j in 1:size(state.X,1));
  end molarMass;



  // functions that have been adopted from class PARTIALMIXTUREMEDIUM
 
  // -----------------
  replaceable function gasConstant
    "Return the gas constant of the mixture (also for liquids)"
    extends Modelica.Icons.Function;
    input ThermodynamicState state "Thermodynamic state";
    output SI.SpecificHeatCapacity R_s "Mixture gas constant";
    
  algorithm
    R_s := 0;
  end gasConstant;

  // -----------------
  function moleToMassFractions "Return mass fractions X from mole fractions"
    extends Modelica.Icons.Function;
    input SI.MoleFraction moleFractions[:] "Mole fractions of mixture";
    input MolarMass[:] MMX "Molar masses of components";
    output SI.MassFraction X[size(moleFractions, 1)]
      "Mass fractions of gas mixture";
  protected
    MolarMass Mmix=moleFractions*MMX "Molar mass of mixture";
  algorithm
    for i in 1:size(moleFractions, 1) loop
      X[i] := moleFractions[i]*MMX[i]/Mmix;
    end for;
    annotation (smoothOrder=5);
  end moleToMassFractions;

  // -----------------
  function massToMoleFractions "Return mole fractions from mass fractions X"
    extends Modelica.Icons.Function;
    input SI.MassFraction X[:] "Mass fractions of mixture";
    input SI.MolarMass[:] MMX "Molar masses of components";
    output SI.MoleFraction moleFractions[size(X, 1)]
      "Mole fractions of gas mixture";
  protected
    Real invMMX[size(X, 1)] "Inverses of molar weights";
    SI.MolarMass Mmix "Molar mass of mixture";
  algorithm
    for i in 1:size(X, 1) loop
      invMMX[i] := 1/MMX[i];
    end for;
    Mmix := 1/(X*invMMX);
    for i in 1:size(X, 1) loop
      moleFractions[i] := Mmix*X[i]/MMX[i];
    end for;
    annotation (smoothOrder=5);
  end massToMoleFractions;


end SimpleMachineStockMedium_400_v1;

从该示例导出的PlugFlowPipe模型:

代码语言:javascript
复制
model testing_PlugFlowPipe_example_ver01 "Simple example of plug flow pipe"

  // Modifications to the example
  import Buildings = Buildings;
  import Sources = Buildings.Fluid.Sources;
  import Sensors = Buildings.Fluid.Sensors;
  //replaceable package Medium = Buildings.Media.Water;
  replaceable package Medium = SimpleMachineStockMedium_400_v1;
  
  // End of modifications
  
  
  final parameter Modelica.Units.SI.MassFlowRate m_flow_nominal = 3 "Mass flow rate";
  Modelica.Blocks.Sources.Ramp Tin(height = 20, duration = 0, offset = 273.15 + 50, startTime = 100) "Ramp pressure signal" annotation(
    Placement(transformation(extent = {{-100, -10}, {-80, 10}})));
  Sources.Boundary_pT sin(redeclare package Medium = Medium, T = 273.15 + 10, nPorts = 2, p(displayUnit = "Pa") = 101325) "Pressure boundary condition" annotation(
    Placement(transformation(extent = {{100, -10}, {80, 10}})));
  Buildings.Fluid.FixedResistances.PlugFlowPipe pip(redeclare package Medium = Medium, dh = 0.1, length = 100, dIns = 0.05, kIns = 0.028, m_flow_nominal = m_flow_nominal, cPip = 500, thickness = 0.0032, initDelay = true, m_flow_start = m_flow_nominal, rhoPip = 8000, T_start_in = 323.15, T_start_out = 323.15) "Pipe" annotation(
    Placement(transformation(extent = {{0, 10}, {20, 30}})));
  Buildings.HeatTransfer.Sources.FixedTemperature bou[2](each T = 283.15) "Boundary temperature" annotation(
    Placement(transformation(extent = {{-40, 60}, {-20, 80}})));
  Buildings.Fluid.Sources.MassFlowSource_T sou(redeclare package Medium = Medium, use_T_in = true, m_flow = m_flow_nominal, nPorts = 1) "Flow source" annotation(
    Placement(transformation(extent = {{-60, 10}, {-40, 30}})));
  Buildings.Fluid.Sensors.TemperatureTwoPort senTemOut(redeclare package Medium = Medium, m_flow_nominal = m_flow_nominal, tau = 0, T_start = 323.15) "Temperature sensor" annotation(
    Placement(transformation(extent = {{40, 10}, {60, 30}})));
  Buildings.Fluid.Sensors.TemperatureTwoPort senTemIn(redeclare package Medium = Medium, m_flow_nominal = m_flow_nominal, tau = 0, T_start = 323.15) "Temperature sensor" annotation(
    Placement(transformation(extent = {{-30, 10}, {-10, 30}})));
  Sensors.TemperatureTwoPort senTemInNoMix(redeclare package Medium = Medium, m_flow_nominal = m_flow_nominal, tau = 0, T_start = 323.15) "Temperature sensor" annotation(
    Placement(transformation(extent = {{-30, -30}, {-10, -10}})));
  Buildings.Fluid.FixedResistances.PlugFlowPipe pipNoMix(have_pipCap = false, redeclare package Medium = Medium, dh = 0.1, length = 100, dIns = 0.05, kIns = 0.028, m_flow_nominal = m_flow_nominal, cPip = 500, thickness = 0.0032, initDelay = true, m_flow_start = m_flow_nominal, rhoPip = 8000, T_start_in = 323.15, T_start_out = 323.15) "Pipe" annotation(
    Placement(transformation(extent = {{0, -30}, {20, -10}})));
  Sensors.TemperatureTwoPort senTemOutNoMix(redeclare package Medium = Medium, m_flow_nominal = m_flow_nominal, tau = 0, T_start = 323.15) "Temperature sensor" annotation(
    Placement(transformation(extent = {{40, -30}, {60, -10}})));
  Sources.MassFlowSource_T souNoMix(redeclare package Medium = Medium, use_T_in = true, m_flow = m_flow_nominal, nPorts = 1) "Flow source" annotation(
    Placement(transformation(extent = {{-60, -30}, {-40, -10}})));
equation
  connect(Tin.y, sou.T_in) annotation(
    Line(points = {{-79, 0}, {-68, 0}, {-68, 24}, {-62, 24}}, color = {0, 0, 127}));
  connect(pip.port_b, senTemOut.port_a) annotation(
    Line(points = {{20, 20}, {40, 20}}, color = {0, 127, 255}));
  connect(senTemOut.port_b, sin.ports[1]) annotation(
    Line(points = {{60, 20}, {76, 20}, {76, -1}, {80, -1}}, color = {0, 127, 255}));
  connect(senTemIn.port_b, pip.port_a) annotation(
    Line(points = {{-10, 20}, {0, 20}}, color = {0, 127, 255}));
  connect(senTemInNoMix.port_b, pipNoMix.port_a) annotation(
    Line(points = {{-10, -20}, {0, -20}}, color = {0, 127, 255}));
  connect(pipNoMix.port_b, senTemOutNoMix.port_a) annotation(
    Line(points = {{20, -20}, {40, -20}}, color = {0, 127, 255}));
  connect(senTemOutNoMix.port_b, sin.ports[2]) annotation(
    Line(points = {{60, -20}, {76, -20}, {76, 1}, {80, 1}}, color = {0, 127, 255}));
  connect(bou[1].port, pip.heatPort) annotation(
    Line(points = {{-20, 70}, {-4, 70}, {-4, 40}, {10, 40}, {10, 30}}, color = {191, 0, 0}));
  connect(bou[2].port, pipNoMix.heatPort) annotation(
    Line(points = {{-20, 70}, {-4, 70}, {-4, 0}, {10, 0}, {10, -10}}, color = {191, 0, 0}));
  connect(sou.ports[1], senTemIn.port_a) annotation(
    Line(points = {{-40, 20}, {-30, 20}}, color = {0, 127, 255}));
  connect(souNoMix.ports[1], senTemInNoMix.port_a) annotation(
    Line(points = {{-40, -20}, {-30, -20}}, color = {0, 127, 255}));
  connect(Tin.y, souNoMix.T_in) annotation(
    Line(points = {{-79, 0}, {-68, 0}, {-68, -16}, {-62, -16}}, color = {0, 0, 127}));
  annotation(
    __Dymola_Commands(file = "modelica://Buildings/Resources/Scripts/Dymola/Fluid/FixedResistances/Examples/PlugFlowPipe.mos" "Simulate and Plot"),
    experiment(StopTime = 1000, Tolerance = 1e-006),
    Documentation(info = "<html>
<p>Basic test of model
<a href=\"modelica://Buildings.Fluid.FixedResistances.PlugFlowPipe\">
Buildings.Fluid.FixedResistances.PlugFlowPipe</a> with and without outlet mixing volume.
This test includes an inlet temperature step under a constant mass flow rate.
</p>
</html>", revisions = "<html>
<ul>
<li>July 27, 2021 by Baptiste Ravache<br/>Add case without mixing volume</li>
</ul>
<ul>
<li>September 8, 2017 by Bram van der Heijde<br/>First implementation</li>
</ul>
</html>"),
    Diagram(coordinateSystem(extent = {{-120, -100}, {120, 100}})),
    Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}})));
end testing_PlugFlowPipe_example_ver01;

编辑:版本信息: MSL 4.0.0

建筑物图书馆:

  • I被告知使用9.0.0版本。存储库https://github.com/lbl-srg/modelica-buildings没有任何特定的标签。我使用了存储库的主分支,文件“modelica-Buildings/Buildings/pacage.mo”给出了版本信息9.0.0 (克隆27.1.2022)。

通过OMEdit从建筑物图书馆获取信息

错误信息(Intergrator方法dassl):

来自转换调试器的最新调试消息

使用rungekutta积分器时出现的错误消息:

EN

回答 1

Stack Overflow用户

发布于 2022-02-01 11:53:47

您需要建筑物的最新开发版本(主分支,而不是任何发布版本),因为have_pipCap只是在https://github.com/lbl-srg/modelica-buildings/commit/89bf74035bdea926701edef2c3dbf35f48b32680中引入的。

如果没有这个建筑物版本,您将得到以下信息:

错误:未在类PlugFlowPipe中找到已修改的元素have_pipCap。

建议让Modelica工具在代码上使用注释,这样就可以使用相同的版本进行测试。我认为这就是问题所在,因为问题中没有列出所使用的建筑物的版本或你收到的错误信息。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70922397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档