matrix singular under determined linear system not solvable - modelica

Following this question, I modified my code to:
model test
// types
type Mass = Real(unit = "Kg", min = 0);
type Length = Real(unit = "m");
type Area = Real(unit = "m2", min = 0);
type Force = Real(unit = "Kg.m/s2");
type Pressure = Real(unit = "Kg/m/s2");
type Torque = Real(unit = "Kg.m2/s2");
type Velocity = Real(unit = "m/s");
type Time = Real(unit = "s");
// constants
constant Real pi = 2 * Modelica.Math.asin(1.0);
parameter Mass Mp = 0.01;
parameter Length r1 = 0.010;
parameter Length r3 = 0.004;
parameter Integer n = 3;
parameter Area A = 0.020 * 0.015;
parameter Time Stepping = 1.0;
parameter Real DutyCycle = 1.0;
parameter Pressure Pin = 500000;
parameter Real Js = 1;
//parameter Real Muk = 0.0;
parameter Real Muk = 0.158;
// variables
Length x[n];
Velocity vx[n];
Real theta;
Real vt;
Pressure P[n];
Force Fnsp[n];
Torque Tfsc;
initial equation
theta = 0;
vt = 0;
algorithm
for i in 1:n loop
if noEvent((i - 1) * Stepping < mod(time, n * Stepping)) and noEvent(mod(time, n * Stepping) < Stepping * ((i - 1) + DutyCycle)) then
P[i] := Pin;
else
P[i] := 0;
end if;
end for;
Tfsc := -r3 * Muk * sign(vt) * abs(sum(Fnsp));
equation
vx = der(x);
vt = der(theta);
x = r1 * {sin(theta + (i - 1) * 2 * pi / n) for i in 1:n};
Mp * der(vx) + P * A = Fnsp;
Js * der(theta) = Tfsc - r1 * Fnsp * {cos(theta + (i - 1) * 2 * pi / n) for i in 1:n};
// Js * der(theta) = - r1 * Fnsp * {cos(theta + (i - 1) * 2 * pi / n) for i in 1:n};
annotation(
experiment(StartTime = 0, StopTime = 30, Tolerance = 1e-06, Interval = 0.03),
__OpenModelica_simulationFlags(lv = "LOG_STATS", outputFormat = "mat", s = "dassl"));
end test;
However, I get the preprocessing warning of
[1] .... Translation Warning
Iteration variables with default zero start attribute in torn nonlinear equation system:
Fnsp[3]:VARIABLE(unit = "Kg.m/s2" ) type: Real [3]
Fnsp[2]:VARIABLE(unit = "Kg.m/s2" ) type: Real [3]
Fnsp[1]:VARIABLE(unit = "Kg.m/s2" ) type: Real [3]
$DER.vt:VARIABLE() type: Real
which doesn't make sense but I assume I can safely ignore, and the compiling error of:
Matrix singular!
under-determined linear system not solvable
which had also been previously reported here. if I remove the lines
Torque Tfsc;
and
Tfsc := -r3 * Muk * sign(vt) * abs(sum(Fnsp));
and changing
Js * der(theta) = - r1 * Fnsp * {cos(theta + (i - 1) * 2 * pi / n) for i in 1:n};
works perfectly fine. However, setting Muk to zero, which theoretically the same thing leads to the same error as above! I would appreciate if you could help me know what is the problem and how I can resolve it.
P.S.1. On the demo version of Dymola the simulation test finishes with no errors, only the warning:
Some variables are iteration variables of the initialization problem:
but they are not given any explicit start values. Zero will be used.
Iteration variables:
der(theta, 2)
P[1]
P[2]
P[3]
P.S.2. Using JModelica, removing the noEvent and using the python code:
model_name = 'test'
mo_file = 'test.mo'
from pymodelica import compile_fmu
from pyfmi import load_fmu
my_fmu = compile_fmu(model_name, mo_file)
myModel = load_fmu('test.fmu')
res = myModel.simulate(final_time=30)
theta = res['theta']
t = res['time']
import matplotlib.pyplot as plt
plt.plot(t, theta)
plt.show()
it solves the model blazingly fast for small values (e.g. 0.1) of Muk. But again it gets stuck for bigger values. The only warnings are:
Warning at line 30, column 3, in file 'test.mo':
Iteration variable "Fnsp[2]" is missing start value!
Warning at line 30, column 3, in file 'test.mo':
Iteration variable "Fnsp[3]" is missing start value!
Warning in flattened model:
Iteration variable "der(_der_theta)" is missing start value!

You do not need to use algorithm for the assignments of equations (even if they are in a for-loop and an if). I moved them to the equation section and removed your algorithm section completely:
model test
// types
type Mass = Real(unit = "Kg", min = 0);
type Length = Real(unit = "m");
type Area = Real(unit = "m2", min = 0);
type Force = Real(unit = "Kg.m/s2");
type Pressure = Real(unit = "Kg/m/s2");
type Torque = Real(unit = "Kg.m2/s2");
type Velocity = Real(unit = "m/s");
type Time = Real(unit = "s");
// constants
constant Real pi = 2 * Modelica.Math.asin(1.0);
parameter Mass Mp = 0.01;
parameter Length r1 = 0.010;
parameter Length r3 = 0.004;
parameter Integer n = 3;
parameter Area A = 0.020 * 0.015;
parameter Time Stepping = 1.0;
parameter Real DutyCycle = 1.0;
parameter Pressure Pin = 500000;
parameter Real Js = 1;
//parameter Real Muk = 0.0;
parameter Real Muk = 0.158;
// variables
Length x[n];
Velocity vx[n];
Real theta;
Real vt;
Pressure P[n];
Force Fnsp[n];
Torque Tfsc;
initial equation
theta = 0;
vt = 0;
equation
for i in 1:n loop
if noEvent((i - 1) * Stepping < mod(time, n * Stepping)) and noEvent(mod(time, n * Stepping) < Stepping * ((i - 1) + DutyCycle)) then
P[i] = Pin;
else
P[i] = 0;
end if;
end for;
Tfsc = -r3 * Muk * sign(vt) * abs(sum(Fnsp));
vx = der(x);
vt = der(theta);
x = r1 * {sin(theta + (i - 1) * 2 * pi / n) for i in 1:n};
Mp * der(vx) + P * A = Fnsp;
Js * der(theta) = Tfsc - r1 * Fnsp * {cos(theta + (i - 1) * 2 * pi / n) for i in 1:n};
// Js * der(theta) = - r1 * Fnsp * {cos(theta + (i - 1) * 2 * pi / n) for i in 1:n};
end test;
This makes it far easier for the compiler to find a sensible sorting and tearing for the strong components. This still breaks at 19s but before that it may just be what you are looking for. The newton solver diverges after that threshold, since i don't really know what you are doing here i unfortunately cannot provide any analysis of the results.

Also it seems like your event triggered by your if-equation could be cleanly replaced by a Sample operator. You might want to have a look at that.

Related

Failed to solve linear system of equations

I'm trying to solve the code
model modelTest
// types
type Mass = Real (unit = "Kg", min = 0);
type Length = Real (unit = "m");
type Area = Real (unit = "m2", min = 0);
type Force = Real (unit = "Kg.m/s2");
type Pressure = Real (unit = "Kg/m/s2");
type Torque = Real (unit = "Kg.m2/s2");
type Velocity = Real (unit = "m/s");
type Time = Real (unit = "s");
// constants
constant Real pi = 2 * Modelica.Math.asin(1.0);
parameter Mass Mp = 0.01;
parameter Length r1 = 0.010;
parameter Integer n = 3;
parameter Area A = 0.020 * 0.015;
parameter Time Stepping = 0.1;
parameter Real DutyCycle = 0.5;
parameter Pressure Pin = 5000;
parameter Real Js = 1;
// variables
Length x[n];
Velocity vx[n];
Real theta;
Real vt;
Pressure P[n];
initial equation
theta = 0;
vt = 0;
algorithm
for i in 1:n loop
if noEvent((i - 1) * Stepping < mod(time, Stepping)) and noEvent(mod(time, Stepping) < (i - 1) * Stepping + Stepping * DutyCycle) then
P[i] := Pin;
else
P[i] := 0;
end if;
end for;
equation
vx = der(x);
vt = der(theta);
x = r1 * {sin(theta + (i -1) * 2 * pi / n) for i in 1:n};
Js * der(theta) = r1 * sum((Mp * der(vx) + P * A) .* {cos(theta + (i -1) * 2 * pi / n) for i in 1:n});
annotation(
experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-6, Interval = 0.01),
__OpenModelica_simulationFlags(lv = "LOG_STATS", outputFormat = "mat", s = "dassl"));
end modelTest;
but the solver never finishes showing the error:
Failed to solve linear system of equations (no. 51) at time ... Residual norm is ...
The default linear solver fails, the fallback solver with total pivoting at time ... that might riase plv LOG_LS.
I would appreciate if you could help me know what is the problem and how I can solve it. Thanks for your support in advance.
P.S.1. I found this similar issue from 15 months ago.
P.S.2. There were several mistakes in the code. A modified version can be found here.

math.acos out of domain error when combined with backlash element

i've run into a problem with out of domain error involving modelica trigonometric functions and i just dont know what i could do.
My model is that of a nonlinear rotational spring (torque dependant on geometric relations) + a hard stop (using standard backlash element).
Model schematic with elastogap - doesnt work
The error i get in OpenModelica is:
acos(variable) outside domain -1.0 <= -1 <= +1.0
That means the error appears to be in my custom spring model.
Now, the ordinary solution i thought should work is to limit the variable so acos stays in domain using if-conditions. I also followed the advice given here about the noEvent() operator. This did not work however. I even went overboard with the "safekeeping", to no avail.
For completions sake, this is the geometric relation of the spring. I'm positive that it is correct.
I use an input ramp from phi= -2° to 108°. The elastogap allows force-free movement from phi = 0° to 106°.
Without the backlash element my spring works as i expect . No issues with out of domain. Together with this backlash i get the domain issue, even though i added "domain-limits" before every trigonometric function in my custom spring model.
Does anyone have an idea what the issue could be/ what i could try?
I noticed that if i change the range of the backlash to have different limits (for example b=105.9*pi/180 ; phi_rel0=-52.95*pi/180) it also works without domain error, but i would like to get to the bottom of this issue.
The model (with the error):
package test
model LD_Abwickel_ZF_VAL
Modelica.Blocks.Sources.Ramp ramp2(duration = 1.24, height = 122, offset = -2);
Modelica.Mechanics.Rotational.Components.ElastoBacklash2 elastoBacklash(b = 1.85005, c = 1e4, d = 1e2, phi_rel0 = -0.925025);
Modelica.Mechanics.Rotational.Components.Fixed fixed2;
Modelica.Mechanics.Rotational.Sources.Position position1(exact = true);
Modelica.Blocks.Math.UnitConversions.From_deg from_deg1;
test.LD_Pendelarm_ZugfederF2 lD_Pendelarm_ZugfederF21;
equation
connect(position1.flange, lD_Pendelarm_ZugfederF21.flange);
connect(elastoBacklash.flange_a, lD_Pendelarm_ZugfederF21.flange);
connect(ramp2.y, from_deg1.u);
connect(from_deg1.y, position1.phi_ref);
connect(elastoBacklash.flange_b, fixed2.flange);
end LD_Abwickel_ZF_VAL;
model LD_Pendelarm_ZugfederF2
Modelica.Mechanics.Rotational.Interfaces.Flange_a flange;
.Modelica.SIunits.Angle phi(displayUnit = "deg");
.Modelica.SIunits.Torque M;
parameter .Modelica.SIunits.Length a(displayUnit = "mm") = 25.49e-3;
parameter .Modelica.SIunits.Length b(displayUnit = "mm") = 23.38e-3;
parameter .Modelica.SIunits.Length d(displayUnit = "mm") = 43.89e-3;
parameter .Modelica.SIunits.Length L0(displayUnit = "mm") = 59.5e-3 "Ungespannte Laenge d. Feder";
parameter .Modelica.SIunits.Length Lk(displayUnit = "mm") = 47.19e-3 "Laenge unbelasteter Federkörper";
parameter .Modelica.SIunits.Force F0 = 4.1 "innere Vorspannkraft Feder";
parameter .Modelica.SIunits.TranslationalSpringConstant R(displayUnit = "N/mm") = 0.868e+3 "Federkonstante";
parameter Integer z = 2 "Anzahl Federn";
.Modelica.SIunits.Length c(displayUnit = "mm");
.Modelica.SIunits.Angle delta(displayUnit = "deg", min = -2 * .Modelica.Constants.pi, max = 2 * .Modelica.Constants.pi, nominal = 0);
.Modelica.SIunits.Angle alpha(displayUnit = "deg", min = -2 * .Modelica.Constants.pi, max = 2 * .Modelica.Constants.pi, nominal = 0.5 * .Modelica.Constants.pi);
.Modelica.SIunits.Angle beta(displayUnit = "deg", min = -4 * .Modelica.Constants.pi, max = 4 * .Modelica.Constants.pi, nominal = .Modelica.Constants.pi);
.Modelica.SIunits.Angle psi(displayUnit = "deg", min = -4 * .Modelica.Constants.pi, max = 4 * .Modelica.Constants.pi, nominal = 0);
.Modelica.SIunits.Length L_gerade(displayUnit = "mm");
.Modelica.SIunits.Length L_bogen(displayUnit = "mm") = 46.1e-3;
.Modelica.SIunits.Length L_c(displayUnit = "mm") "rel. Federlaenge (gesamt)";
.Modelica.SIunits.Force F_c "Summe Federkraft";
Real cosalpha(min = -1, max = 1, nominal = 0);
Real cosdelta(min = -1, max = 1, nominal = 0);
Real cosbeta(min = -1, max = 1, nominal = 0);
equation
flange.phi = phi;
flange.tau = M;
if noEvent(phi <= 0) then
c = a - b;
cosdelta = 1;
delta = 0;
L_gerade = sqrt(c ^ 2 + d ^ 2);
cosalpha = -1;
alpha = .Modelica.Constants.pi;
else
c = sqrt(a ^ 2 + b ^ 2 - 2 * a * b * cos(phi));
cosdelta = (b ^ 2 - a ^ 2 - c ^ 2) / (-2 * a * c);
if noEvent(cosdelta <= 0.999999 and cosdelta >= (-0.999999)) then
cos(delta) = cosdelta;
else
delta = if noEvent(sign(cosdelta) > 0) then 0 else .Modelica.Constants.pi;
end if;
L_gerade = sqrt(c ^ 2 + d ^ 2 - 2 * c * d * cos(delta + .Modelica.Constants.pi * 0.5));
cosalpha = (a ^ 2 - b ^ 2 - c ^ 2) / (-2 * b * c);
if noEvent(cosalpha <= 0.999999 and cosalpha >= (-0.999999)) then
cos(alpha) = cosalpha;
else
alpha = if noEvent(sign(cosalpha) > 0) then 0 else .Modelica.Constants.pi;
end if;
end if;
cosbeta = (d ^ 2 - c ^ 2 - L_gerade ^ 2) / (-2 * c * L_gerade);
if noEvent(cosbeta <= 0.999999 and cosbeta >= (-0.999999)) then
cos(beta) = cosbeta;
else
beta = if noEvent(sign(cosbeta) > 0) then 0 else .Modelica.Constants.pi;
end if;
psi = alpha - beta;
L_c = L_gerade + L_bogen - (L0 - Lk) - Lk;
F_c = z * (R * L_c + F0);
M = F_c * sin(psi);
end LD_Pendelarm_ZugfederF2;
end test;
So of course it works fine on my machine, but from the code I know it is problematic and might fail randomly. The problem is that you have things like cos(beta) = cosbeta which is solved as beta = acos(cosbeta).
But OpenModelica added a bad equation for common subexpression elimination someTmpVar = acos(cosbeta) which always runs regardless of the if-equations you use to guard this. The expansion seems to happen Feels like a bug to report to OpenModelica since it happens during code generation and just produces lD_Pendelarm_ZugfederF21._delta = if noEvent(from_deg1.y <= 0.0) then 0.0 else if noEvent(lD_Pendelarm_ZugfederF21.cosdelta <= 0.999999) and noEvent(lD_Pendelarm_ZugfederF21.cosdelta >= -0.999999) then if noEvent(abs($TMP$VAR$70$0x1$COS - $TMP$VAR$70$0PREX$COS) < abs($TMP$VAR$70$0x2$COS - $TMP$VAR$70$0PREX$COS)) then $TMP$VAR$70$0x1$COS else $TMP$VAR$70$0x2$COS else if noEvent(sign(lD_Pendelarm_ZugfederF21.cosdelta) > 0) then 0.0 else 3.141592653589793, which won't run faster than before and might produce domain errors.
A probable workaround would be to use an algorithm section as it is not manipulated as heavily by OpenModelica.

OpenModelica complains about a negative value which can't be negative

Following this question I have modified the energy based controller which I have described here to avoid negative values inside the sqrt:
model Model
//constants
parameter Real m = 1;
parameter Real k = 2;
parameter Real Fmax = 3;
parameter Real x0 = 1;
parameter Real x1 = 2;
parameter Real t1 = 5;
parameter Real v0 = -2;
//variables
Real x, v, a, xy, F, vm, K;
initial equation
x = x0;
v = v0;
equation
v = der(x);
a = der(v);
m * a + k * x = F;
algorithm
if time < t1 then
xy := x0;
else
xy := x1;
end if;
K := Fmax * abs(xy - x) + k * (xy^2 - x^2) / 2;
if abs(xy - x) < 1e-6 then
F := k * x;
else
if K > 0 then
vm := sign(xy - x) * sqrt(2 * K / m);
F := Fmax * sign(vm - v);
else
F := Fmax * sign(x - xy);
end if;
end if;
annotation(
experiment(StartTime = 0, StopTime = 20, Tolerance = 1e-06, Interval = 0.001),
__OpenModelica_simulationFlags(lv = "LOG_STATS", outputFormat = "mat", s = "euler"));
end Model;
However, it keeps giving me the error:
The following assertion has been violated at time 7.170000
Model error: Argument of sqrt(K / m) was -1.77973e-005 should be >= 0
Integrator attempt to handle a problem with a called assert.
The following assertion has been violated at time 7.169500
Model error: Argument of sqrt(K / m) was -6.5459e-006 should be >= 0
model terminate | Simulation terminated by an assert at the time: 7.1695
STATISTICS 
Simulation process failed. Exited with code -1.
I would appreciate if you could help me know what is the problem and how I can solve it.
The code you created does event localization to find out when the condition in the if-statements becomes true and/or false. During this search it is possible that the expression in the square-root becomes negative although you 'avoided' it with the if-statement.
Try reading this and to apply the solution presented there. Spoiler: It basically comes down to adding a noEvent() statement for you Boolean condition...

OpenModelica solver reaches maximal number of iteration but not able to find root

I am trying to simulate a 1D system of 3 sliding bodies as I have explained here:
and here is the code I have implemented:
model friction
//constants
parameter Real muk = 0.2;
parameter Real mus = 0.3;
parameter Real m1 = 1.0;
parameter Real m2 = 2.0;
parameter Real m3 = 3.0;
parameter Real Fn12 = 3.0;
parameter Real Fn23 = 2.0;
parameter Real absTol = 0.1;
//variables
Real X1, X2, X3, V1, V2, V3, A1, A2, A3, F1, F2, F3, Ff12, Ff23, Fs12, Fs23;
initial equation
X1 = 0;
X2 = 0;
X3 = 0;
V1 = 0;
V2 = 0;
V3 = 0;
equation
F1 = 2 * sin(5 * time);
F2 = 2 * sin(7 * time);
F3 = 3 * sin(11 * time);
V1 = der(X1);
V2 = der(X2);
V3 = der(X3);
A1 = der(V1);
A2 = der(V2);
A3 = der(V3);
m1 * A1 = F1 - Ff12;
m2 * A2 = F2 + Ff12 - Ff23;
m3 * A3 = F3 + Ff23;
Fs12 = (m2 * F1 - m1 * (F2-Ff23)) / (m1 + m2);
Fs23 = (m3 * (F2 + Ff12) - m2 * F3) / (m2 + m3);
if abs(V1 - V2) < absTol and abs(Fs12) < mus * Fn12 then
Ff12 = Fs12;
else
Ff12 = muk * Fn12 * sign(V1 - V2);
end if;
if abs(V3 - V2) < absTol and abs(Fs23) < mus * Fn23 then
Ff23 = Fs23;
else
Ff23 = muk * Fn23 * sign(V2 - V3);
end if;
end friction;
Wolfram SystemModeler is able to run the simulation till t=6sec, but the results are not what I expect as I have explained here. And when I use OpenModelica to solve the simulation I get the error below:
C:/Users/foo/AppData/Local/Temp/OpenModelica/OMEdit/friction.exe -port=64457 -logFormat=xmltcp -override=startTime=0,stopTime=10,stepSize=0.02,tolerance=1e-6,solver=dassl,outputFormat=mat,variableFilter=.* -r=friction_res.mat -jacobian=coloredNumerical -w -lv=LOG_STATS
Warning: maximal number of iteration reached but no root found
Warning: maximal number of iteration reached but no root found
Error solving nonlinear system 42 at time 0.2
Error solving nonlinear system 42 at time 0.2
nonlinear system 42 fails: at t=0.2
Solving non-linear system 42 failed at time=0.2.
For more information please use -lv LOG_NLS.
Simulation process failed. Exited with code -1.
I would appreciate if you could help me know what is the problem and how I can solve it?
You are trying to write your own Friction model.
In Modelica the normal way is to use s-parameterization by e.g. inheriting from: Modelica.Mechanics.Translational.Interfaces.PartialFriction (or using an existing model doing that).
It's documentation is online at:
http://doc.modelica.org/help/Modelica_Mechanics_Rotational_UsersGuide.html#Modelica.Mechanics.Rotational.UsersGuide.ModelingOfFriction
Specifically you have Fs12 and Fs23 that are maximum friction force for adherence, which works if the are constant - but here they depend on Ff12 and Ff23 - and they in turn depend on Fs12 and Fs23; which does not work.
For dry friction modeling I can recommend https://github.com/dzimmer/ZimmersModelicaTutorial/blob/master/Tutorial2015/BaseComponents/Friction/IdealDryFriction.mo which reuses Modelica.Mechanics.Translational.Interfaces.PartialFriction in a simple and clean way.

Model flow from a pipe

I have been trying to model flow through a pipe that can be partially full, or totally full in modelica and running it in OpenModelica. I have finally reduced the example to essentially just use the area of a circle, and to have no outflow until it is full, then complete outflow. But, I am still getting errors. I have tried it a few different ways. The first way gives an error about solving a nonlinear system once the pipe becomes "filled up". Instead I want it to switch over:
model SimplePipe1
Modelica.SIunits.Area A;
Modelica.SIunits.Mass mass;
Modelica.SIunits.Height level(start = 0.5, fixed = true, min = 0.0, max = 2 * R) "Liquid level (m)";
parameter Modelica.SIunits.Radius R = 1.0 "pipe inner radius (m)";
parameter Real flow_in = 1.0;
Real flow_out;
Modelica.SIunits.Angle phi(start = 3.1, min = 0.0, max = 7.2832) "Angle from center to surface level";
Modelica.SIunits.Area A;
Modelica.SIunits.Mass mass;
Modelica.SIunits.Height level(start = 0.5, fixed = true, min = 0.0, max = 2 * R) "Liquid level (m)";
parameter Modelica.SIunits.Radius R = 1.0 "pipe inner radius (m)";
parameter Real flow_in = 1.0;
Real flow_out;
Modelica.SIunits.Angle phi(start = 3.1, min = 0.0, max = 7.2832) "Angle from center to surface level";
equation
mass = A;
//Assume unit length pipe and unit density
flow_in + flow_out = der(mass);
A = 0.5 * R ^ 2 * (phi - sin(phi));
// phi = if noEvent(level <= 0) then 0 elseif noEvent(level >= 2 * R) then 2 * Modelica.Constants.pi else 2 * acos((R - level) / R);
if noEvent(level <= 0) then
phi = 0;
flow_out = 0;
elseif noEvent(level >= 2 * R) then
phi = 2 * Modelica.Constants.pi;
flow_out = -flow_in;
else
flow_out = 0;
//Partially full pipe has no out outflow
phi = 2 * acos((R - level) / R);
end if;
annotation(Icon, Diagram, experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-06, Interval = 0.02));
end SimplePipe1;
This version seems to give results that are closer to what I want, but it still doesn't work. In this case, the problem is that phi is supposed to be limited to 2*pi. Instead it keeps increasing. Meanwhile, I don't actually see flowmode change. I do see the outflow go negative for a single cycle, then it jumps back to zero. I don't understand what is changing the flowmode back from channel to full, since there is no corresponding "when" to change it back.
model SimplePipe2
type modetype = enumeration(empty, full, channel);
modetype flowmode(start = modetype.channel);
Modelica.SIunits.Area A;
Modelica.SIunits.Mass mass;
Modelica.SIunits.Height level(start = 0.5, fixed = true, min = 0.0, max = 2 * R) "Liquid level (m)";
Modelica.SIunits.Height level_limit;
parameter Modelica.SIunits.Radius R = 1.0 "pipe inner radius (m)";
parameter Real flow_in = 1.0;
Real flow_out;
Modelica.SIunits.Angle phi(start = 3.1, min = 0.0, max = 7.2832) "Angle from center to surface level";
Real flow_out;
initial equation
flowmode = modetype.channel;
equation
mass = A;
//Assume unit length pipe and unit density
flow_in + flow_out = der(mass);
A = 0.5 * R ^ 2 * (phi - sin(phi));
cos(phi / 2) = (R - level) / R;
if flowmode == modetype.empty then
flow_out = 0;
elseif flowmode == modetype.full then
flow_out = -flow_in;
else
flow_out = 0;
//Partially full pipe has no out outflow
end if;
when noEvent(phi >= 2 * Modelica.Constants.pi) then
reinit(flow_out, -flow_in);
reinit(level, 2 * R);
flowmode = modetype.full;
end when;
annotation(Icon, Diagram, experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-06, Interval = 0.02));
end SimplePipe2;
This question that I asked is related to solving the same problem, but doesn't have the issue of a circle/cylinder. And, my second example above is based somewhat on this question.
I am using the newest beta of OpenModelica. My complete model will have other feature that are not included in either of these examples. But, hopefully if I can get this simple version working, I can expand from there.
Your code ends up with a non-linear equation for phi (after level_limit and one flow_out was removed from the model).
0 = 0.5 * R ^ 2.0 * (phi - sin(phi)) - mass
OM solves this without adding constraints for the variable phi. The assertion is instead checked after the solution is found. If you use non-linear solver=kinsol in OpenModelica, the constraints are added to the non-linear equation, but it does not help in this case. I am also a bit unsure if when noEvent() would ever trigger.