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;
Related
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 want to simulate a controller for a mass-spring model which works based on energy:
model model
//parameters
parameter Real m = 1;
parameter Real k = 1;
parameter Real Fmax = 3;
parameter Real x0 = 1;
parameter Real x1 = 2;
parameter Real t1 = 1;
//variables
Real x, v, a, xy, vm;
initial equation
x = x0;
v = 2;
equation
v = der(x);
a = der(v);
m * a + k * x = F;
algorithm
vm := sign(xy - x)*sqrt(2 * (Fmax * abs(xy - x) + k * (xy^2 - x^2) / 2) / m);
// step signal
if time < t1 then
xy := x0;
else
xy := x1;
end if;
if xy == x then
F := k * x;
else
F := sign(vm - v) * Fmax;
end if;
end model;
But it leads to the error message:
Translation Error
Error occurred while flattening model
I would appreciate it if you could help me know what is the problem and how I can fix it.
P.S.1. SIMULINK is also not able to finish!
P.S.2. New version of the code can be seen here.
P.S.3. According to this discussion on Discord, the algorithm section was not really meant for casual relations. More information about the keyword is here.
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...