Consider the following simple package.
package Test
connector Param
parameter Real k = 1.5;
end Param;
model Component
input Param p;
Real x;
equation
der(x) = p.k;
end Component;
model System
Param p;
Component c;
equation
connect(p, c.p);
end System;
end Test;
This works fine but as soon as I change System.p.k in the simulation, I get the following error:
abs(p.k-c.p.k) <= 0.0
The following error was detected at time: 0
Parameters in connected connectors must be equal
Error: Failed to start model.
Somehow the variables p.k and c.p.k are not aliasing each other. Hence, when I change only p.k, a discrepancy is detected which is not allowed since both have to be equal due to the equations induced by connect(p, c.p).
How can I use parameters as inputs properly and avoid these effects?
Which version of OpenModelica are you using?
For me this doesn't happen.
The simulation works fine:
adrpo#ida-liu050 ~/dev/OpenModelica/build/bin/
$ ./omc TestConnectionParameter.mos
true
""
record SimulationResult
resultFile = "c:/bin/cygwin/home/adrpo/dev/OpenModelica/build/bin/media/TestConnectionParameter.System_res.mat",
simulationOptions = "startTime = 0.0, stopTime = 1.0, numberOfIntervals = 500, tolerance = 1e-006, method = 'dassl', fileNamePrefix = 'TestConnectionParameter.System', options = '', outputFormat = 'mat', variableFilter = '.*', cflags = '', simflags = ''",
messages = "",
timeFrontend = 0.01857038093533281,
timeBackend = 0.009237455657633623,
timeSimCode = 0.002007941686540131,
timeTemplates = 0.06294835594000042,
timeCompile = 2.89228755603547,
timeSimulation = 0.463245543628269,
timeTotal = 3.4489112421252
end SimulationResult;
"Warning: The initial conditions are not fully specified. Use +d=initialization for more information.
"
true
1.5
1.5
1.5
1.5
1.5
1.5
I'm using file: TestConnectionParameter.mo:
package TestConnectionParameter
connector Param
parameter Real k = 1.5;
end Param;
model Component
input Param p;
Real x;
equation
der(x) = p.k;
end Component;
model System
Param p;
Component c;
equation
connect(p, c.p);
end System;
end TestConnectionParameter;
and the script: TestConnectionParameter.mos
loadFile("TestConnectionParameter.mo"); getErrorString();
simulate(TestConnectionParameter.System); getErrorString();
plot({c.x, p.k, c.p.k});
val(p.k, 0);
val(p.k, 0.5);
val(p.k, 1);
val(c.p.k, 0);
val(c.p.k, 0.5);
val(c.p.k, 1);
Getting:
Related
Following this question, I'm trying to generate two time-dependent random functions omega1 and tau using this example. The difference is that I need to have two different sample periods of 0.05 and 0.17 for omega1 and tau respectively. I just duplicated the parts I thought would do the job:
model testData
extends Modelica.Icons.Example;
import Modelica.Math.Random.Generators;
import Modelica.Math.Random.Utilities;
parameter Real k = 50.0;
parameter Real J = 0.001;
Real theta1;
Real theta2;
Real omega2;
parameter Modelica.SIunits.Period samplePeriod1 = 0.05;
parameter Integer globalSeed1 = 30020;
parameter Integer localSeed1 = 614657;
output Real omega1;
parameter Modelica.SIunits.Period samplePeriod2 = 0.17;
parameter Integer globalSeed2 = 30020;
parameter Integer localSeed2 = 614657;
output Real tau;
protected
discrete Integer state1024[33](each start=0, each fixed = true);
algorithm
when initial() then
state1024 := Generators.Xorshift1024star.initialState(localSeed1, globalSeed1);
omega1 := 0;
elsewhen sample(0, samplePeriod1) then
(omega1, state1024) := Generators.Xorshift1024star.random(pre(state1024));
omega1 := (omega1 - 0.5) * 13;
end when;
when initial() then
state1024 := Generators.Xorshift1024star.initialState(localSeed2, globalSeed2);
omega1 := 0;
elsewhen sample(0, samplePeriod2) then
(tau, state1024) := Generators.Xorshift1024star.random(pre(state1024));
tau := (tau - 0.5) * 3;
end when;
public
parameter Integer id1 = Utilities.initializeImpureRandom(globalSeed1);
discrete Real rImpure1;
Integer iImpure1;
parameter Integer id2 = Utilities.initializeImpureRandom(globalSeed2);
discrete Real rImpure2;
Integer iImpure2;
algorithm
when initial() then
rImpure1 := 0;
iImpure1 := 0;
elsewhen sample(0, samplePeriod1) then
rImpure1 := Utilities.impureRandom(id=id1);
iImpure1 := Utilities.impureRandomInteger(
id=id1,
imin=-1234,
imax=2345);
end when;
when initial() then
rImpure2 := 0;
iImpure2 := 0;
elsewhen sample(0, samplePeriod2) then
rImpure2 := Utilities.impureRandom(id=id2);
iImpure2 := Utilities.impureRandomInteger(
id=id2,
imin=-1234,
imax=2345);
end when;
initial equation
theta1 = 0;
theta2 = 0;
der(theta2) = 0;
equation
der(theta1) = omega1;
der(theta2) = omega2;
J * der(omega2) = tau + k * (theta1 - theta2);
annotation(experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-6, Interval = 0.02));
end testData;
however I get the error messages:
Symbolic Error
The given system is mixed-determined. [index > 3]
Please checkout the option "--maxMixedDeterminedIndex".
Translation Error
No system for the symbolic initialization was generated
I would appreciate if you could help me know what is the problem and how I can solve it.
P.S. considering that this code is apparantly compiling fine on Dymola, this could be a problem with OpenModelica. So I'm adding th JModelica tag in the case those guys can help me know if this compiles over there or not.
You have omega1 := 0; in two when initial()statements. Replace it by tau := 0; in the second one and the example will work.
I recommend to cleanup your code a bit. I found various smaller issues and needless code lines.
everything related to the impure random numbers can be removed
localSeed2 and globalSeed2 are useless when they are initialized like the other seed variables
state1024 is initialized at 3 different places (even though it works with OpenModelica): with start values and fixed=true and in two different when initial() statements
omega2 and tau2 don't need to be outputs. The Tool determines by itself what it has to compute.
And finally: Modelica models are a lot easier to debug and understand if existing blocks and physical components are used instead of writing lengthy code in a single class. Your model can also be built graphically with blocks from Modelica.Blocks.Noise and components from Modelica.Mechanics.Rotational.
Below is an updated version of your code with units, only one section for initialization and removed algorithm section (not necessary anymore due to the additional variables rand_omega and rand_tau).
model testData2
extends Modelica.Icons.Example;
import Modelica.Math.Random.Generators;
import Modelica.Math.Random.Utilities;
import SI = Modelica.SIunits;
parameter SI.RotationalSpringConstant k = 50.0;
parameter SI.Inertia J = 0.001;
parameter SI.Period samplePeriod_tau = 0.17;
parameter SI.Period samplePeriod_omega = 0.05;
parameter Integer globalSeed = 30020;
parameter Integer localSeed_tau = 614657;
parameter Integer localSeed_omega = 45613;
SI.Angle theta1, theta2;
SI.AngularVelocity omega1, omega2, rand_omega;
SI.Torque tau, rand_tau;
protected
discrete Integer state1024_tau[33];
discrete Integer state1024_omega[33];
initial equation
state1024_omega = Generators.Xorshift1024star.initialState(localSeed_omega, globalSeed);
state1024_tau = Generators.Xorshift1024star.initialState(localSeed_tau, globalSeed);
theta1 = 0;
theta2 = 0;
der(theta2) = 0;
equation
when sample(0, samplePeriod_omega) then
(rand_omega, state1024_omega) = Generators.Xorshift1024star.random(pre(state1024_omega));
end when;
when sample(0, samplePeriod_tau) then
(rand_tau, state1024_tau) = Generators.Xorshift1024star.random(pre(state1024_tau));
end when;
der(theta1) = omega1;
der(theta2) = omega2;
omega1 = (rand_omega - 0.5) * 13;
tau = (rand_tau - 0.5) * 3;
J * der(omega2) = 0 + k * (theta1 - theta2);
annotation(experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-6, Interval = 0.02));
end testData2;
I'm trying to follow this example to generate a random function of time:
model testData
extends Modelica.Icons.Example;
parameter Real k = 1.0;
Real theta1;
Real theta2;
parameter Real tau = 1.0;
parameter Modelica.SIunits.Period samplePeriod = 0.05;
parameter Integer globalSeed = 30020;
output Real omega1;
algorithm
when initial() then
state1024 := Generators.Xorshift1024star.initialState(localSeed, globalSeed);
omega1 := 0;
elsewhen sample(0,samplePeriod) then
(omega1,state1024) := Generators.Xorshift1024star.random(pre(state1024));
end when;
public
parameter Integer id = Utilities.initializeImpureRandom(globalSeed);
discrete Real rImpure;
Integer iImpure;
algorithm
when initial() then
rImpure := 0;
iImpure := 0;
elsewhen sample(0,samplePeriod) then
rImpure := Utilities.impureRandom(id=id);
iImpure := Utilities.impureRandomInteger(
id=id,
imin=-1234,
imax=2345);
end when;
initial equation
theta1 = 0;
theta2 = 0;
der(theta2) = 0;
equation
der(theta1) = omega1;
der(der(theta2)) = tau + k * (theta1 - theta2);
annotation(experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-6, Interval = 0.02));
end testData;
however, I get the error message:
Translation Error
Class Utilities.initializeImpureRandom not found in scope testData (looking for a function or record).
Translation Error
Error occurred while flattening model testData
I would appreciate if you could help me understand what is the problem and how I can solve it.
You were missing some imports, see below, some variable declarations and you were using der(der(...)) which doesn't work, you need to bind the internal der to a variable. This model below compiles and simulates (I don't know if the results are fine or not).
model testData
extends Modelica.Icons.Example;
import Modelica.Math.Random.Generators;
import Modelica.Math.Random.Utilities;
parameter Real k = 1.0;
Real theta1;
Real theta2;
Real der_theta2;
parameter Real tau = 1.0;
parameter Modelica.SIunits.Period samplePeriod = 0.05;
parameter Integer globalSeed = 30020;
parameter Integer localSeed = 614657;
output Real omega1;
discrete Integer state1024[33](each start=0, each fixed = true);
algorithm
when initial() then
state1024 := Generators.Xorshift1024star.initialState(localSeed, globalSeed);
omega1 := 0;
elsewhen sample(0,samplePeriod) then
(omega1,state1024) := Generators.Xorshift1024star.random(pre(state1024));
end when;
public
parameter Integer id = Utilities.initializeImpureRandom(globalSeed);
discrete Real rImpure;
Integer iImpure;
algorithm
when initial() then
rImpure := 0;
iImpure := 0;
elsewhen sample(0,samplePeriod) then
rImpure := Utilities.impureRandom(id=id);
iImpure := Utilities.impureRandomInteger(
id=id,
imin=-1234,
imax=2345);
end when;
initial equation
theta1 = 0;
theta2 = 0;
der(theta2) = 0;
der_theta2 = 0;
equation
der(theta1) = omega1;
der(theta2) = der_theta2;
der(der_theta2) = tau + k * (theta1 - theta2);
annotation(experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-6, Interval = 0.02));
end testData;
The example Modelica.Math.Random.Examples.GenerateRandomNumbers uses relative class paths.
Utilities.initializeImpureRandom for example points to Modelica.Math.Random.Utilities.initializeImpureRandom, which works due to the package hierarchy
Modelica
|- Math
|- Random
|- Examples
|- Utilities
If you copy the code of the example to a different location, the relative paths will not work anymore.
Dymola updates relative paths when models are duplicated (via New > Duplicate Class). Openmodelica apparently not.
Just add the following two imports to the top of your code and the class paths will work:
import Modelica.Math.Random.Generators;
import Modelica.Math.Random.Utilities;
But your model contains additonal errors:
The declaration of the variables localSeed and state1024 is missing. Just copy them from the original example
der(der(theta2)) is not supported. Create an intermediate variable der_theta2 = der(theta2)
I am trying to prepare a modelica code to understand array and for loop.
When I am compiling the code, I get following error.
The initialization problem is inconsistent due to the following equation: 0 != 1 = 1.0 - I[0]
Error in initialization. Storing results and exiting.
Use -lv=LOG_INIT -w for more information.
Simulation process failed. Exited with code -1.
I have tried to adjust array numbers to see if this solves. Could not trace the reason why the code is failing.
class flu
parameter Real beta = 10.0/(40*8*24);
parameter Real gamma= 3.0/(15*24);
parameter Real dt = 0.1;
parameter Real D = 30;
parameter Integer N_t = integer(D*24/dt);
parameter Integer array = integer(N_t*dt);
//parameter Real time[array];
Real S[array] ;
Real I[array] ;
Real R[array] ;
initial equation
S[0] = 50;
I[0] = 1;
R[0] = 0;
equation
for n in 0:(array-1) loop
S[n+1] = S[n] - dt*beta*S[n]*I[n];
I[n+1] = I[n] + dt*beta*S[n]*I[n] - dt*gamma*I[n];
R[n+1] = R[n] + dt*gamma*I[n];
end for;
annotation(
__OpenModelica_simulationFlags(lv = "LOG_STATS", outputFormat = "mat", s = "dassl"));end flu;
I am expecting to get three curves as a result .
There seems to be a few things wrong here. First of all, it seems OpenModelica does not output the index of the equation so the debugger can be opened.
But more importantly, you are setting
I[0] = 1
I[1] is the first index in Modelica... I don't know why this wouldn't give any warning in OpenModelica. Probably some edge case in an if equation that never triggers and thus no warning/error in this case.
class flu
parameter Real beta = 10.0/(40*8*24);
parameter Real gamma= 3.0/(15*24);
parameter Real dt = 0.1;
parameter Real D = 30;
parameter Integer N_t = integer(D*24/dt);
parameter Integer array = integer(N_t*dt);
//parameter Real time[array];
Real S[array] ;
Real I[array] ;
Real R[array] ;
equation
S[1] = 50;
I[1] = 1;
R[1] = 0;
equation
for n in 1:(array-1) loop
S[n+1] = S[n] - dt*beta*S[n]*I[n];
I[n+1] = I[n] + dt*beta*S[n]*I[n] - dt*gamma*I[n];
R[n+1] = R[n] + dt*gamma*I[n];
end for;
end flu;
class flu
parameter Real beta = 10.0/(40*8*24);
parameter Real gamma= 3.0/(15*24);
Real S(start = 50) ;
Real I(start = 1) ;
Real R(start = 0) ;
equation
der(S)= -beta*S*I;
der(I)=(beta*S*I) - (gamma*I);
der(R)=gamma*I;
annotation(
__OpenModelica_simulationFlags(lv = "LOG_STATS", outputFormat = "mat", s = "dassl"));end flu;
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.
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.