这个问题是问题的延续:OpenModelica: How to model plug flow for multi substance fluid medium?
在默认情况下,modelica不包括支持多种物质和痕量物质的介质模型。因此,我把一个介质模型和基本的Modelica流体组件(源、开罐、静态管道)结合在一起。然而,建筑物库的组件Buildings.Fluid.FixedResistances.PlugFlowPipe似乎是有问题的,我不知道为什么?我在OpenModelica方面的经验非常有限,如果有人能帮我指出理由,我会很感激的。
由于我还没有在其他库中找到任何其他组件来建模管道中的塞流和传输延迟,所以我最终来到了Building库。
下面是用于测试的介质模型和仿真模型。
使用的介质模型:
// 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模型:
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
建筑物图书馆:
通过OMEdit从建筑物图书馆获取信息

错误信息(Intergrator方法dassl):

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

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

发布于 2022-02-01 11:53:47
您需要建筑物的最新开发版本(主分支,而不是任何发布版本),因为have_pipCap只是在https://github.com/lbl-srg/modelica-buildings/commit/89bf74035bdea926701edef2c3dbf35f48b32680中引入的。
如果没有这个建筑物版本,您将得到以下信息:
错误:未在类PlugFlowPipe中找到已修改的元素have_pipCap。
建议让Modelica工具在代码上使用注释,这样就可以使用相同的版本进行测试。我认为这就是问题所在,因为问题中没有列出所使用的建筑物的版本或你收到的错误信息。
https://stackoverflow.com/questions/70922397
复制相似问题