OpenModelica Building Libary, using PlugFlowPipe component - modelica

This question is a continuation to the question: OpenModelica: How to model plug flow for multi substance fluid medium?
The modelica does not include by default a medium model supporting multiple substances and trace substances. Therefore, I was putting together a medium model that works fine with basic Modelica fluid components (sources, open tanks, static pipe). However, Buildings library's component Buildings.Fluid.FixedResistances.PlugFlowPipe seems to be problematic and I could not figure out why? I have a very limited experience on OpenModelica and would appreciate if someone could help and point out the reasoning.
I have ended up to the Building library since I haven't found any other component in other libraries that would model the plug flow and transfer delays in pipe lines.
Below are the medium model and Simulation model that has been used for testing.
Medium model used:
// 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 derived from the example :
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;
EDIT:
Version information:
MSL 4.0.0
Buildings library:
I was told to use version 9.0.0. The repository https://github.com/lbl-srg/modelica-buildings did not have any specific label for that. I was using the master branch of the repository and the file "modelica-buildings/Buildings/package.mo" gives the version information 9.0.0 (cloned 27.1.2022).
Information obtained from the Buildings library through OMEdit
Error Message (Intergrator method dassl):
Latest Debug message from Transformational debugger
Error Message when using rungekutta integrator:

You need the latest development version of Buildings (the master branch; not any released version) because have_pipCap was only introduced in https://github.com/lbl-srg/modelica-buildings/commit/89bf74035bdea926701edef2c3dbf35f48b32680
Without this Buildings version, you will get the message:
Error: Modified element have_pipCap not found in class PlugFlowPipe.
It is recommended to let the Modelica tool put the annotation uses on the code so the same version can be used for testing. I am assuming this is the problem because the questions did not list the version of Buildings used or the error-message you got.

Related

Compiling of OpenModelica-Model in Twinbuilder

I have a model which is written in Openmodelica. I want to implement this model in Twinbuilder with Modelica. The code of the model is as follows:
model SelfActingValve
extends Modelica.Fluid.Interfaces.PartialTwoPortTransport;
// Import Elements
import Modelica.Constants.pi;
import Modelica.Constants.g_n;
// Thermodynamic states
//Medium.ThermodynamicState port_a_state_inflow "State at port_a if inflowing";
//Medium.ThermodynamicState port_b_state_inflow "State at port_b if inflowing";
// Parameter
parameter Modelica.SIunits.Length dGap=0.0062 "Mean value of outer diameter of the valve and the diameter of the pipe in front of the valve
";
parameter Modelica.SIunits.Angle alpha=pi/2"Angle between the vertical and the bevel edge of the cone valve";
parameter Modelica.SIunits.Length dchamber=0.008"diameter before the valve";
parameter Real gravityAccelerat = g_n;
parameter Real cValve = 100 "spring constant/(N/m)";
parameter Modelica.SIunits.Length spPre = 0.0029 "length of the spring preload";
parameter Modelica.SIunits.Length scaleS = 0.0089 "maximum of possible movement of the sprin";
parameter Modelica.SIunits.Mass mValve = 0.000486 "Mass of the valve body";
parameter Modelica.SIunits.Area surfacePorta=1"Surface of the valve at port_a";
parameter Modelica.SIunits.Area surfacePortb=1"Surface of the valve at port_b";
parameter Modelica.SIunits.Volume volValve= 436e-9 "Volume of the valvebody";
parameter Modelica.SIunits.Length dhydro=1.52e-3"hydraulic eyuivalent diameter of the gap ";
parameter Boolean outletValve = false "= true --> outletValve, false-->inlet valve" annotation(
Dialog(tab = "General"),
Evaluate = true);
parameter Real kgeo=10"geometric constant";
parameter Real zetaOwn=0.7"loss coeffizient of the valve";
// Variables in the equation
//protected
// Real zetaOwn_dummy(start=0.7)"dummy for loss coefficient";
// Real zetaOwn(start=0.7) "loss coefficient";
// Real P_lose(start=0);
Real x(start = 0, min=0, max=scaleS) "Position of the valve";
Real xdot(start = 0) "velocity of the valve";
Real force0(start = 0) " preload of spring";
Real forceSpr(start = 0) "spring force";
Real dummydot(start = 0) "first derrivative dummy";
Real forcePress(start=0);
Real forceGrav(start = 0) "Gravity force of valve";
Real forceDamp(start=0)"Damping force from friction";
Real densiWat(start=998.2)"density of the medium";
Real eta(start=1)"dynamic viscosity";
Real thetaStar(start=0)"damping factor";
Real volumstream(start=0);
// Real reynold(start=10000)"Reynold number of the fluid before the gap";
// Real psi(start=0.4)"coeffizeint to describe the not equal pressure distribution on the valve";
Real reynoldGap(start=1)"Reynold number of the fluid in the gap";
equation
volumstream=m_flow*densiWat;
// outflow equation
m_flow=x*dGap*pi*densiWat*sin(alpha)*(abs((2*dp)/(zetaOwn*densiWat)))^(1/2);
//Ansatz für Lösen der Singularität, aber keine Ergebnisse.
// Isenthalpic state transformation (no storage and no loss of energy)
port_a.h_outflow = inStream(port_b.h_outflow);
port_b.h_outflow = inStream(port_a.h_outflow);
// Fence modelation
if dummydot < 0 and x<0 then
der(xdot) = 0;
der(x) = 0;
elseif dummydot > 0 and x>scaleS then
der(xdot) = 0;
der(x) = 0;
else
if outletValve == true then
der(xdot) = 1 / mValve * ((-force0) - forceGrav - forceSpr + forcePress-forceDamp*xdot);
// der(xdot) = 1 / mValve * ((-force0) - forceGrav - forceSpr + forcePress);
xdot = der(x);
else
der(xdot) = 1 / mValve * ((-force0) + forceGrav - forceSpr+ forcePress-forceDamp*xdot);
// der(xdot) = 1 / mValve * ((-force0) + forceGrav - forceSpr+ forcePress);
xdot = der(x);
end if;
// This If loop is for the direction of the Forces, e.g. Depending if we have a outlet or a inlet valve the pressure force appeals in different directions.
end if;
// This If loop is for modelling of the fences of the valve
when dummydot < 0 and x<0 then
// xdotnew=if edge(impact) then 0 else xdot;
reinit(xdot, 0);
elsewhen dummydot > 0 and x> scaleS then
// xdotnew=if edge(impact) then 0 else xdot;
reinit(xdot, 0);
end when;
// This when loop reinitializes the speed and the accleration of the valve, when it hit the fences.
// equation of motion and force definition
if outletValve == true then
dummydot = 1 / mValve * ((-force0) - forceGrav - forceSpr+ forcePress-forceDamp*xdot );
// dummydot = 1 / mValve * ((-force0) - forceGrav - forceSpr+ forcePress );
else
dummydot = 1 / mValve * ((-force0) + forceGrav - forceSpr + forcePress-forceDamp*xdot);
// dummydot = 1 / mValve * ((-force0) + forceGrav - forceSpr + forcePress);
end if;
// This If loop is for the direction of the Forces, e.g. Depending if we have a outlet or a inlet valve the pressure force appeals in different directions. Dummydot is to calculate the actual acceleration to see, if we get away from the fences.
force0 = spPre * cValve "preload of the spring";
forcePress= port_a.p*surfacePorta-port_b.p*surfacePortb"Force of the pressures acting on the valve";
forceSpr = cValve * x"force of the spring due to movements of the valve";
forceGrav = gravityAccelerat*( mValve -densiWat*volValve) "Gravity of the valve";
forceDamp=thetaStar*eta*dGap/kgeo"damping force";
thetaStar=10*reynoldGap+505"help variable for caculation forceDamp";
// psi=0.82-1.6*x/dGap-0.075*log(abs(reynold));
//zetaOwn=280/reynoldGap+1;
eta = if m_flow > 0 then
Medium.dynamicViscosity(state_a)
else
Medium.dynamicViscosity(state_b);
densiWat=if m_flow>0 then
Medium.density(state_a)
else
Medium.density(state_b);
if x< scaleS/1000 then
reynoldGap=0;
// reynold=1;
else
reynoldGap=4*m_flow/(pi*2*x*sin(alpha)*eta);
// reynold=4*m_flow/(pi*dchamber*eta);
end if;
// if loop: First fix for to big Reynold number in case of nearly closed valve positions
annotation(Icon(coordinateSystem(
preserveAspectRatio=true,
extent={{-100,-100},{100,100}}), graphics={
Line(points={{0,50},{0,0}}),
Rectangle(
extent={{-20,60},{20,50}},
fillPattern=FillPattern.Solid),
Polygon(
points={{-100,50},{100,-50},{100,50},{0,0},{-100,-50},{-100,50}},
fillColor={255,255,255},
fillPattern=FillPattern.Solid),
Polygon(
points=DynamicSelect({{-100,0},{100,-0},{100,0},{0,0},{-100,-0},{-100,
0}}, {{-100,50*opening},{-100,50*opening},{100,-50*opening},{
100,50*opening},{0,0},{-100,-50*opening},{-100,50*opening}}),
fillColor={0,255,0},
lineColor={255,255,255},
fillPattern=FillPattern.Solid),
Polygon(points={{-100,50},{100,-50},{100,50},{0,0},{-100,-50},{-100,
50}})}),Documentation(info="<html>
<p>
This model is build up witht the equations of the doctoral degree thesis ofErwin Thiel at the University Erlangen-Nürnberg with the title 'Kinematik und Druckverlust selbsttätiger Ventile oszillierender Verdrängerpumpen'. GENAUERE BESCHREIBUNG FOLGT
<p>
</html>"),Icon(coordinateSystem(initialScale = 0.1), graphics = {Line(points = {{0, 50}, {0, 0}}), Rectangle(fillPattern = FillPattern.Solid, extent = {{-20, 60}, {20, 50}}), Polygon(fillColor = {255, 255, 255}, fillPattern = FillPattern.Solid, points = {{-100, 50}, {100, -50}, {100, 50}, {0, 0}, {-100, -50}, {-100, 50}}), Polygon(lineColor = {255, 255, 255}, fillColor = {0, 255, 0}, fillPattern = FillPattern.Solid, points = {{-100, 0}, {100, 0}, {100, 0}, {0, 0}, {-100, 0}, {-100, 0}}), Polygon(points = {{-100, 50}, {100, -50}, {100, 50}, {0, 0}, {-100, -50}, {-100, 50}})}),
uses(Modelica(version = "3.2.3")));
end SelfActingValve;
I get the error when compiling this code in TwinBuilder. The error is :
Command GetStaticIconSVG failed with following error:
User error:
ERROR: The annotation for the icon for SelfActingValve is malformed, cannot generate an icon
java exception in java.lang.NullPointerException
Do you know how to handle this error?
I appreciate your help and time you invest to give the advice.
You have two Icon-annotations, at the end of the model, remove one of them.
You can remove the entire annotation if you just want to test it.

Error: Compilation of C code failed - Modelica

when I compile my code in Modelica, I get following error:
Command Compile failed with following error: User error: ERROR: java exception in com.modelon.oct.modelica.api.InternalAPIException with message: Compilation of generated C code failed
I add the code below.
model SimModelcode
Real heatcapacity[n_Kapazitaten];
Real thermalconductance[n_Kapazitaten+1];
Real l_link;
//Real l_oben;
//Real l_Volume[n_Kapazitaten] ;
Real V_alu ;
Real cpm_alu ;
Real m_alu;
Real cpm_links[n_Kapazitaten];
Real y[101,101] ;
Real z;
Real mittellange;
//Real cpm_rechts[n_Kapazitaten] ;
//Real cpm_oben[n_Kapazitaten] ;
//Real cpm_unten[n_Kapazitaten] ;
Real h_aussen[n_Unterteilung];
//Real l_aussen[n_Unterteilung] ;
//Real Flache_oben[n_Unterteilung] ;
Real Flache_link[n_Unterteilung] ;
Real G_links[n_Kapazitaten+1] ;
//Real G_oben[n_Kapazitaten+1] ;
//Real G_rechts[n_Kapazitaten+1] ;
//Real G_unten[n_Kapazitaten+1] ;
Real h_Volume[n_Kapazitaten] ;
Real V_link[n_Kapazitaten] ;
//Real V_oben[n_Kapazitaten] ;
Real m_link[n_Kapazitaten] ;
//Real m_oben[n_Kapazitaten] ;
Real G[n_Kapazitaten+1];
parameter Integer n_Kapazitaten=100 ; //Anzahl der Kapazitäten
parameter Integer n_Unterteilung=2*(n_Kapazitaten+1) ;//Anzahl der Unterteilung
parameter Real l_box=0.3;//die Länge der obigen Kante vom dem Außenrechteck
parameter Real l_Alu=0.05;//die Länge der obigen Kante vom Alublock
parameter Real h_box=0.2;//die Höhe der linken Kante von dem Außenrechteck
parameter Real h_Alu=0.02;//die Höhe der linken Kante von Alublock
parameter Real dicke=0.01;
parameter Integer lambda_Kunststoff=10;
parameter Integer cp_Alu=200;
parameter Integer cp_Kunststoff=10;
parameter Integer rho_Kunststoff=1185;
parameter Integer rho_Alu=2719;
Real cpm[n_Kapazitaten];
Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow PrescribedHeatFlow(Q_flow = 10) annotation(
Placement(visible = true, transformation(origin = {-14, -24}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Thermal.HeatTransfer.Sources.FixedTemperature PrescribedTemperature1(T = 300) annotation(
Placement(visible = true, transformation(origin = {64, 42}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Thermal.HeatTransfer.Sources.FixedTemperature PrescribedTemperature2(T = 300) annotation(
Placement(visible = true, transformation(origin = {64, 42}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Thermal.HeatTransfer.Sources.FixedTemperature PrescribedTemperature3(T = 300) annotation(
Placement(visible = true, transformation(origin = {64, 42}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Thermal.HeatTransfer.Sources.FixedTemperature PrescribedTemperature4(T = 300) annotation(
Placement(visible = true, transformation(origin = {64, 42}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Thermal.HeatTransfer.Components.HeatCapacitor Alu(C = 0.5438) annotation(
Placement(visible = true, transformation(origin = {64, 42}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Thermal.HeatTransfer.Components.HeatCapacitor Capacitors[n_Kapazitaten](C =heatcapacity) annotation(
Placement(visible = true, transformation(origin = {64, 42}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Thermal.HeatTransfer.Components.ThermalConductor Conductors[n_Kapazitaten+1](G=thermalconductance) annotation(
Placement(visible = true, transformation(origin = {64, 42}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
equation
l_link=((l_box-l_Alu)/2) /(n_Kapazitaten+1);// Abstand zwischen zwei Kapazitäten in linkem Block und rechtem Block
//l_oben=((h_box-h_Alu)/2)/(n_Kapazitaten+1);//Abstand zwischen zwei Kapazitäten in obigem Block und unterem Block
V_alu=l_Alu*h_Alu*dicke;
m_alu=V_alu*rho_Alu;
cpm_alu=m_alu*cp_Alu;
for i in 1:n_Unterteilung loop
h_aussen[i]=h_Alu+(i/n_Unterteilung)*(h_box-h_Alu);//Berechnung der Höhe in den linken Trapezflächen
Flache_link[i]=h_aussen[i]*dicke;//Berechnung der Flache in den linken Trapezflächen
//l_aussen[i]=l_Alu+(i/n_Unterteilung)*(l_box-l_Alu);//Berechnung der Länge in den obigen Trapezflächen
//Flache_oben[i]=l_aussen[i]*dicke;//Berechnung der Höhe in den obigen Trapezflächen
end for;
G_links[1:n_Kapazitaten+1]= lambda_Kunststoff*(Flache_link[1:2:n_Unterteilung-1]/l_link);
//G_oben[1:n_Kapazitaten+1]= lambda_Kunststoff*(Flache_oben[1:2:n_Unterteilung-1]/l_oben);
//G_rechts[1:n_Kapazitaten+1]= lambda_Kunststoff*(Flache_link[1:2:n_Unterteilung-1]/l_link);
//G_unten[1:n_Kapazitaten+1]= lambda_Kunststoff*(Flache_oben[1:2:n_Unterteilung-1]/l_oben);
//G =cat(1,G_links,G_oben,G_rechts,G_unten);
G=G_links;
for i in 1:n_Kapazitaten loop
h_Volume[i]=h_Alu+(i/n_Kapazitaten)*(h_box-h_Alu);
//l_Volume[i]=l_Alu+(i/n_Kapazitaten)*(l_box-l_Alu);
V_link[i]=(dicke*(h_Volume[i])*((i/n_Kapazitaten)*(l_box-l_Alu)/2)); //Volumen in linkem und rechtem Block pro Kapazitat
//V_oben[i]=(dicke*(l_Volume[i])*((i/n_Kapazitaten)*(h_box-h_Alu)/2));//Volumen in obigem und unterem Block pro Kapazitat
m_link[i]=rho_Kunststoff*V_link[i];
//m_oben[i]=rho_Kunststoff*V_oben[i];
end for;
cpm_links[1:n_Kapazitaten]=cp_Kunststoff*m_link[1:n_Kapazitaten];
//cpm_oben[1:n_Kapazitaten]=cp_Kunststoff*m_oben[1:n_Kapazitaten];
//cpm_rechts[1:n_Kapazitaten]=cp_Kunststoff*m_link[1:n_Kapazitaten];
//cpm_unten[1:n_Kapazitaten]=cp_Kunststoff*m_oben[1:n_Kapazitaten];
cpm = cpm_links;
for j in 1:101 loop
for i in 1:46 loop
y[i,j]=sqrt(0.09-(i-1)*(((0.09+(j-1)*0.02/100)/45)+((j-1)*0.02/100)))^2+(0.125^2);
end for;
for i in 47:101 loop
y[i,j]=sqrt((i-46)*((0.110-((j-1)*0.02/100))/55)-((j-1)*0.02/100))^2+(0.125^2);
end for;
end for;
z=sum(y);
mittellange=z/10000;
///for i=1:4*n_Kapazitaten
//Capacitors_links=Capacitors[n_Kapazitaten];
//Capacitors_oben=Capacitors[n_Kapazitaten:2*n_Kapazitaten];
//Capacitors_rechts=Capacitors[2*n_Kapazitaten:3*n_Kapazitaten];
//Capacitors_unten=Capacitors[3*n_Kapazitaten:4*n_Kapazitaten]
//end for;
for i in 1:n_Kapazitaten+1 loop
thermalconductance[i]=G[i];
end for;
for i in 1:n_Kapazitaten loop
heatcapacity[i]=cpm[i];
end for;
connect(PrescribedHeatFlow.port, Alu.port);
connect(Conductors[1].port_a,Alu.port );
//connect(Conductors[n_Kapazitaten+2].port_a,Alu.port );
//connect(Conductors[2*(n_Kapazitaten+1)+1].port_a,Alu.port );
//connect(Conductors[3*(n_Kapazitaten+1)+1].port_a,Alu.port );
for i in 1:n_Kapazitaten loop
connect(Conductors[i].port_b,Capacitors[i].port);
connect(Capacitors[i].port,Conductors[i+1].port_a);
end for;
connect(Conductors[n_Kapazitaten+1].port_b,PrescribedTemperature1.port);
//for i in n_Kapazitaten+1:2*n_Kapazitaten loop
//connect(Conductors[i+1].port_b,Capacitors[i].port);
//connect(Capacitors[i].port,Conductors[i+2].port_a);
//end for;
//connect(Conductors[2*n_Kapazitaten+2].port_b,PrescribedTemperature2.port);
//for i in 2*n_Kapazitaten+1:3*n_Kapazitaten loop
//connect(Conductors[i+2].port_b,Capacitors[i].port);
//connect(Capacitors[i].port,Conductors[i+3].port_a);
//end for;
//connect(Conductors[3*n_Kapazitaten+3].port_b,PrescribedTemperature3.port);
//for i in 3*n_Kapazitaten+1:4*n_Kapazitaten loop
//connect(Conductors[i+3].port_b,Capacitors[i].port);
//connect(Capacitors[i].port,Conductors[i+4].port_a);
//end for;
//connect(Conductors[4*n_Kapazitaten+4].port_b,PrescribedTemperature4.port);
end SimModelcode;
Do you know the reason of this error? I appreciate your helps. Thanks in advance!
There are a few variables used as array dimensions that need to be declared as parameter:
parameter Real heatcapacity[n_Kapazitaten];
parameter Real thermalconductance[n_Kapazitaten+1];
And then there are some calls that look like sqrt(...)^2 where ... is negative. If the intent is to make them positive, just call abs(...).
Which is the problem for JModelica, I do not know.

Trapezoidal Integration of nonlinear inductance

I have modeled the nonlinear inductor with Modelica, but the circuit can not be solved by trapezoidal integration, It is appreciated someone can help me to solve the circuit.
model NonlinearInductor
import Modelica.SIunits.MagneticFlux;
extends Modelica.Electrical.Analog.Interfaces.OnePort;
parameter Real T[:,2]=[-1.0015,-1200;-0.0015,-200;0,0;0.0015,200;1.0015,1200]
"piecewiselinear current versus flux relation";
Integer nbPoints = size(T,1) "Number of interpolation points";
Real L; //Slop of line flux-Current; inductance
MagneticFlux flux( start=0);
equation
v = der(flux); // Faraday's Low
algorithm
// Definition of Piecewise nonlinear inductance
if i < T[2,1] then
L := ((T[1,2] - T[2,2]) / (T[1,1] - T[2,1]));
flux := L * (i-T[1,1]) + T[1,2];
elseif i >= T[nbPoints-1,1] then
L := (( T[nbPoints-1,2] - T[nbPoints,2]) / (T[nbPoints-1,1] - T[nbPoints,1]));
flux := L * (i-T[nbPoints-1,1]) + T[nbPoints-1,2];
else
for iter in 2:(nbPoints-2) loop
if i >= T[iter,1] and i <T[iter+1,1] then
L := (( T[iter,2] - T[iter+1,2]) / (T[iter,1] - T[iter+1,1]));
flux := L * (i-T[iter,1]) + T[iter,2];
end if;
end for;
end if;
end NonlinearInductor;
and I have prepared and example as below:
model NonlinearInductorTest
Modelica.Electrical.Analog.Sources.CosineVoltage cosineVoltage1(V = 25e3 * sqrt(2), freqHz = 50,
phase=1.5707963267949) annotation (
Placement(visible = true, transformation(origin = {-80, 20}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
Modelica.Electrical.Analog.Basic.Resistor resistor1(R = 1000e6) annotation (
Placement(visible = true, transformation(origin = {-14, 20}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
Modelica.Electrical.Analog.Basic.Ground ground1 annotation (
Placement(visible = true, transformation(origin = {-80, -12}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Electrical.Analog.Basic.Capacitor capacitor1(C=0.4e-9) annotation (
Placement(visible = true, transformation(origin = {-50, 42}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
NonlinearInductor L annotation(
Placement(visible = true, transformation(origin = {28, 20}, extent = {{-10, -10}, {10, 10}}, rotation = -90)));
equation
connect(L.n, ground1.p) annotation(
Line(points = {{28, 10}, {28, 10}, {28, -2}, {-80, -2}, {-80, -2}}, color = {0, 0, 255}));
connect(L.p, capacitor1.n) annotation(
Line(points = {{28, 30}, {28, 30}, {28, 42}, {-40, 42}, {-40, 42}}, color = {0, 0, 255}));
connect(capacitor1.p, cosineVoltage1.p) annotation(
Line(points = {{-60, 42}, {-80, 42}, {-80, 30}}, color = {0, 0, 255}));
connect(capacitor1.n, resistor1.p) annotation(
Line(points = {{-40, 42}, {-14, 42}, {-14, 30}}, color = {0, 0, 255}));
connect(resistor1.n, ground1.p) annotation(
Line(points = {{-14, 10}, {-14, -2}, {-80, -2}}, color = {0, 0, 255}));
connect(ground1.p, cosineVoltage1.n) annotation(
Line(points = {{-80, -2}, {-80, 10}}, color = {0, 0, 255}));
annotation (
uses(Modelica(version="3.2.2")),
experiment(StartTime = 0, StopTime = 0.1, Tolerance = 1e-6, Interval = 2e-05));
end NonlinearInductorTest;
Please run the example by solver Trapezoidal, StopTime = 0.1, Interval = 2e-05
Your model can be drastically simplified by using the interpolate function of the MSL.
As far as I understood, your code does the same as this function: using linear interpolation inside the defined interval and linear extrapolation outside.
Here is the updated code:
model NonlinearInductor2
extends Modelica.Electrical.Analog.Interfaces.OnePort;
parameter Real T[:,2]=[-1.0015,-1200;
-0.0015,-200;
0,0;
0.0015,200;
1.0015,1200] "piecewiselinear current versus flux relation";
Modelica.SIunits.MagneticFlux flux( start=0);
protected
final parameter Real[:] i_vec = T[:, 1];
final parameter Real[:] flux_vec = T[:, 2];
equation
v = der(flux); // Faraday's Law
flux = Modelica.Math.Vectors.interpolate(i_vec,flux_vec,i);
end NonlinearInductor2;
Apart from making your model much simpler to understand, the usage of the interpolate function brings also these benefits:
The function has the smoothOrder annotation defined, which allows the Modelica translator to differentiate your flux variable analytically .
(With the annotations smooth and smoothOrder you can define up to which order the derivative is continuous)
Instead of the algorithm section we can use a single equation section.
(You should avoid algorithm sections to describe physical behavior, as it limits the Modelica translator in manipulating your equations to create a solvable system. With algorithm sections you force the code to be evaluated exactly how you have written it, which is against the principle of a-causal physical modeling)
Unfortunately, OpenModelica still has some trouble to simulate the new model with your simulation setup (trapezoidal rule, tolerance=1e-6). By reducing the tolerance to 1e-4 the simulation finishes, but still showing the warning
Restart Kinsol: change linear solver to KINDense.
many many times. Maybe an OpenModelica expert can help on that.
Dymola by the way has no troubles with the new code, regardless of the selected solver.

Avoid chattering in a block that finds the index of the highest value in a vector

Modelica Newbie trying to build a block that identifies the highest value of a set of real values (vector).
I tried two versions - one which would just give me the index of the highest value and one which would switch the value of a corresponding boolean vector.
Both failed. For certain high input values the model worked (almost), but most of the time I get an error saying: "Chattering detected around time 0.0277777777839..0.0277777778544 (100 state events in a row with a total time delta less than the step size 0.02). This can be a performance bottleneck. Use -lv LOG_EVENTS for more information. The zero-crossing was: indexMaxBool1.temp > indexMaxBool1.tempMax"
I googled error messages involving chattering and found answers telling to replace the IF-statement by WHEN. I only am affraid, that the latter won't raise the calculation as often as needed (only once??? Does it need a reset?).
I would appreciate getting some hints on how to avoid that chattering.
Here are my models so far:
Block to get the index of the highest value:
block IndexMax
extends Modelica.Blocks.Icons.Block;
parameter Integer nin=1 "Number of inputs";
Modelica.Blocks.Interfaces.RealInput v[nin];
Modelica.Blocks.Interfaces.IntegerOutput index;
protected
Real tempMax;
Real temp;
algorithm
if size(v,1)>1 then
tempMax := v[1];
index := 1;
for i in 2:size(v,1) loop
temp := v[i];
if temp > tempMax then
tempMax := temp;
index := i;
end if;
end for;
else
index :=0;
end if;
end IndexMax;
Block to get a vector of boolean values, with one switched on at the index of the highest input:
block IndexMaxBool
extends Modelica.Blocks.Icons.Block;
parameter Integer nin = 1 "Number of inputs";
Modelica.Blocks.Interfaces.RealInput v[nin];
Modelica.Blocks.Interfaces.BooleanOutput bool[nin];
protected
Real tempMax;
Real temp;
Integer index;
algorithm
if size(v, 1) > 1 then
for i in 1:size(v,1) loop
bool[i] := false;
end for;
tempMax := v[1];
index := 1;
for i in 2:size(v, 1) loop
temp := v[i];
if temp > tempMax then
tempMax := temp;
index := i;
end if;
end for;
else
index := 0;
end if;
if index > 0 then
bool[index]:=true;
end if;
end IndexMaxBool;
The test Models:
model testMax2
Modelica.Blocks.Sources.RealExpression realExpression1(y = 1);
FlowsAndStreams.BDSCalc.IndexMaxBool indexMaxBool1(nin = 3);
Modelica.Blocks.Interfaces.BooleanOutput y;
Modelica.Blocks.Interfaces.BooleanOutput y1;
Modelica.Blocks.Interfaces.BooleanOutput y2;
Modelica.Blocks.Sources.Sine sine1(amplitude = 2, freqHz = 1, phase = 0.785398);
Modelica.Blocks.Sources.Sine sine2(amplitude = 2, freqHz = 3);
equation
connect(sine1.y, indexMaxBool1.v[2]);
connect(sine2.y, indexMaxBool1.v[3]);
connect(indexMaxBool1.bool[3], y2);
connect(indexMaxBool1.bool[1], y);
connect(indexMaxBool1.bool[2], y1);
connect(realExpression1.y, indexMaxBool1.v[1]);
end testMax2;
and:
model testMax
FlowsAndStreams.BDSCalc.IndexMax indexMax1(nin = 3);
Modelica.Blocks.Sources.RealExpression realExpression1(y = 1);
Modelica.Blocks.Sources.RealExpression realExpression2(y = 10);
Modelica.Blocks.Sources.RealExpression realExpression3(y = 3);
Modelica.Blocks.Interfaces.IntegerOutput y;
equation
connect(realExpression3.y, indexMax1.v[3]) annotation(
Line(points = {{-69, -40}, {-8, -40}, {-8, 0}}, color = {0, 0, 127}));
connect(realExpression2.y, indexMax1.v[2]) annotation(
Line(points = {{-69, 0}, {-8, 0}}, color = {0, 0, 127}));
connect(realExpression1.y, indexMax1.v[1]) annotation(
Line(points = {{-69, 30}, {-10, 30}, {-10, 0}, {-8, 0}}, color = {0, 0, 127}));
connect(indexMax1.index, y) annotation(
Line(points = {{10, 0}, {50, 0}}, color = {255, 127, 0}));
end testMax;
I found a solution - but I don't know why it works.
I removed the intermediate variable temp and work instead directly with the v values. Voila!
If v[i]>maxTemp then...
I leave this question here, may it help someone.

Modelica Flow Simulation says divide by zero

I am trying to simulate the flow in a pipe that starts out partially full, and gradually fills up. Once it is full, the flow equation needs to change. I have tried the following code, but I get a divide by zero error once the pipe is full. TestTrap1 is a demo that shows the problem. It seems that some equation is not correct once the pipe is full.
I am using openmodelica to run this.
package FlowPackage
package Interfaces
extends Modelica.Icons.InterfacesPackage;
//Use this for a inlet outlet device
connector Fitting "Inlet port"
flow Modelica.SIunits.MassFlowRate q "Flow rate [Kg/s]";
Modelica.SIunits.Pressure P "Pressure";
annotation(defaultComponentName = "fitting", Icon(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}), graphics = {Rectangle(extent = {{-100, 100}, {100, -100}}, lineColor = {0, 0, 255}, fillColor = {0, 0, 255}, fillPattern = FillPattern.Solid)}), Diagram(coordinateSystem(preserveAspectRatio = true, extent = {{-100, -100}, {100, 100}}), graphics = {Rectangle(extent = {{-40, 40}, {40, -40}}, lineColor = {0, 0, 255}, fillColor = {0, 0, 255}, fillPattern = FillPattern.Solid), Text(extent = {{-160, 110}, {40, 50}}, lineColor = {0, 0, 255}, textString = "%name")}));
end Fitting;
end Interfaces;
model SourceConstant
parameter Modelica.SIunits.MassFlowRate q = 0.015 "Flow rate [Kg/s]";
Interfaces.Fitting fitting annotation(Placement(visible = true, transformation(origin = {100, -6}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, -6}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
-fitting.q = q;
annotation(Icon(graphics = {Rectangle(origin = {-3, 30}, extent = {{-93, 60}, {93, -60}}), Rectangle(origin = {0, 15}, fillColor = {0, 0, 255}, fillPattern = FillPattern.Solid, extent = {{-90, 45}, {90, -45}})}), Diagram);
end SourceConstant;
model ZeroP
parameter Modelica.SIunits.Pressure p = 0.00 "Pressure";
Interfaces.Fitting fitting annotation(Placement(visible = true, transformation(origin = {100, -6}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {100, -6}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
fitting.P = p;
annotation(Icon(graphics = {Rectangle(origin = {-1, 2}, extent = {{-95, 94}, {95, -94}})}), Diagram);
end ZeroP;
model TestTrap1
TrapTemp trap1 ( level(start = 0.0509)) annotation(Placement(visible = true, transformation(origin = {10, 8}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
SourceConstant sourceConstant1(q = 0.03) annotation(Placement(visible = true, transformation(origin = {-50, 26}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
ZeroP zeroP1 (p = 101000) annotation(Placement(visible = true, transformation(origin = {64, 8}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
equation
connect(sourceConstant1.fitting, trap1.fitting_in) annotation(Line(points = {{-40, 26}, {-18, 26}, {-18, 8}, {0, 8}, {0, 8}}, color = {0, 0, 255}));
connect(trap1.fitting_out, zeroP1.fitting) annotation(Line(points = {{20, 8}, {54, 8}, {54, 8}, {54, 8}}, color = {0, 0, 255}));
annotation(Icon, Diagram, experiment(StartTime = 0, StopTime = 1450, Tolerance = 1e-6, Interval = 2.9));
end TestTrap1;
model TrapTemp
//Calculate the velocity for pipe segments
Interfaces.Fitting fitting_in annotation(Placement(visible = true, transformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {-100, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Interfaces.Fitting fitting_out annotation(Placement(visible = true, transformation(origin = {98, -2}, extent = {{-10, -10}, {10, 10}}, rotation = 0), iconTransformation(origin = {98, -2}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
import m = Modelica.Math;
parameter Modelica.SIunits.Length L = 25000 "pipe length (m)";
parameter Modelica.SIunits.Radius R = 0.10194 / 2.0 "pipe inner radius (m)";
parameter Modelica.SIunits.Height roughness = 6.0e-5 "Average height of surface asperities (default: smooth steel pipe)";
/*Values below are liquid at 300K*/
parameter Modelica.SIunits.DynamicViscosity mu = 0.092977 "Dynamic Viscocity (cp)";
parameter Modelica.SIunits.Density row = 501.22 "Density (kg/m^3)";
Modelica.SIunits.Area A;
Modelica.SIunits.Length s(start = 0.158) "wetted perimeter";
Modelica.SIunits.Length rh "hydraulic radius";
Modelica.SIunits.Diameter De(start = 0.1) "eqivalent diameter [m]";
Modelica.SIunits.ReynoldsNumber Re(start = 3000);
Modelica.SIunits.Velocity v(start = 0.0001);
Modelica.SIunits.Length hf "Friction head loss";
Modelica.SIunits.Acceleration g = Modelica.Constants.g_n;
Modelica.SIunits.Acceleration a "Acceleration of flow";
Modelica.SIunits.CoefficientOfFriction f;
Real relative_roughness;
Real percent_full "Fraction of pipe is full [%]";
Modelica.SIunits.Mass mass;
Real percent_full "Fraction of pipe is full [%]";
Modelica.SIunits.Height level "Liquid level (m)";
equation
percent_full = level / R * 100.0;
relative_roughness = roughness / De;
a = der(v);
s = 2 * level + R;
rh = A / s;
De = 4 * rh;
//Protect against negative Re:
Re = De * abs(v) * row / mu;
//Head loss due to friction. Corrected for direction
hf = sign(v) * f * L * v ^ 2 / (2 * De * g);
f = 64 / Re ;
mass = A * row * L;
fitting_in.q + fitting_out.q = der(mass);
fitting_out.q = -v * A * row;
mass * a = A * (fitting_in.P - fitting_out.P - hf * row * g ) ;
A = R * level;
if noEvent(level >= R) then
//full pipe
fitting_in.q = -fitting_out.q;
else
//partially full pipe
fitting_in.P = fitting_out.P;
end if;
annotation(Icon, Diagram);
end TrapTemp;
annotation(Icon, Diagram);
end FlowPackage;
Any suggestions about why this doesn't work, or how to fix it would be greatly appreciated.
firstly, you need to define what is what you want, I mean, if you want to start storing fluid within the pipe before transferring it, you need to define the set of mass and energy equations to store liquid, i.e: if you want to store liquid you cannot calculate Re, because v=0, and once is filled, swap the model as you did with one conditional and define the navier-stokes equations to define the momentum of the fluid.
Anyway, I think you should try connecting one mass flow rate source, one tank, one valve (define the opening law for the valve in function of the level of the tank), one pipe and one sink with the Modelica Standard library components.