Modelica - Is it possible to set name of a variable as the value of another variable? - modelica

I’m quite noob in Modelica language and I’d appreciate any help about this simple issue.
I’d like to know if it’s possible to write a variable name as a function of other variable in order to shorten the general code.
Here there is an example about what I’d like to do.
Thanks in advance!
model example
Real variable1;
Real variable2;
Real variable3;
equation
for i in 1:3 loop
variable(i)= […]
end for;
end example;

You probably want to use arrays in some way. This is similar to the code above, but perhaps you only need the array and not variable1 … variable3.
Real variable1;
Real variable2;
Real variable3;
Real variables[3] = {variable1,variable2,variable3};
equation
for i in 1:3 loop
variables[i] = /* … */;
end for;

Related

Discrete iteration, how can I make this possible?

I want to decompose a part like this, into an array of x rows and y columns, and then do the operations. Mainly use the loop statement (for). Do you guys have a similar example? thank you all very much.
just be like:
equation
for i in 1:n-1 loop
for j in 1:m-1 loop
//equations
T[i+1,j] = T[i,j]+something+...;
T[i,j+1] = ...;
end for;
end for;
The best example I could find is the following: Modelica.Electrical.Analog.Basic.M_Transformer, although the loop is "only" in the initial equation section.
What is more common, is to use loops in connect statements, like in Modelica.Electrical.Batteries.BaseClasses.BaseStackWithSensors. But that will likely not be a good fit for your task.
Some general advise:
A good read to start with the topic is: https://mbe.modelica.university/behavior/arrays/looping/
For complex for/if-statements it is often simpler to formulate them in an algorithm section. Those can be placed in a function and "ease" some of the pretty strict requirements of the equation section, like allowing a multiple assignments for a single variable. It will be more like a coding in a procedural programming language.
If you prefer to write the statements in the equation section (which can make sense performance-wise) you need to make sure, that every unknown needs exactly one equation to compute it.

Loop and vary the name of a list by concatenation on matlab [duplicate]

Let's assume that I want to create 10 variables which would look like this:
x1 = 1;
x2 = 2;
x3 = 3;
x4 = 4;
.
.
xi = i;
This is a simplified version of what I'm intending to do. Basically I just want so save code lines by creating these variables in an automated way. Is there the possibility to construct a variable name in Matlab? The pattern in my example would be ["x", num2str(i)]. But I cant find a way to create a variable with that name.
You can do it with eval but you really should not
eval(['x', num2str(i), ' = ', num2str(i)]); %//Not recommended
Rather use a cell array:
x{i} = i
I also strongly advise using a cell array or a struct for such cases. I think it will even give you some performance boost.
If you really need to do so Dan told how to. But I would also like to point to the genvarname function. It will make sure your string is a valid variable name.
EDIT: genvarname is part of core matlab and not of the statistics toolbox
for k=1:10
assignin('base', ['x' num2str(k)], k)
end
Although it is long overdue, i justed wanted to add another answer.
the function genvarname is exactly for these cases
and if you use it with a tmp structure array you do not need the eval cmd
the example 4 from this link is how to do it http://www.mathworks.co.uk/help/matlab/ref/genvarname.html
for k = 1:5
t = clock;
pause(uint8(rand * 10));
v = genvarname('time_elapsed', who);
eval([v ' = etime(clock,t)'])
end
all the best
eyal
If anyone else is interested, the correct syntax from Dan's answer would be:
eval(['x', num2str(i), ' = ', num2str(i)]);
My question already contained the wrong syntax, so it's my fault.
I needed something like this since you cannot reference structs (or cell arrays I presume) from workspace in Simulink blocks if you want to be able to change them during the simulation.
Anyway, for me this worked best
assignin('base',['string' 'parts'],values);

Evaluating variables at a specific time in Modelica

I have a selection of variables in my Modelica simulation (using Dymola) which is running good. Now I want to plot the behaviour of certain of these variables, which are numbered (with indices). I do not wish to plot the variables versus time, but versus their index. I'm planning to use the plotArray function, but that's not really what I'm curious about in this post. The problem is, all variables are zero when I call them, which indeed is their initial value, but I want to attain their value when steady state has set in, let's say when time = 5000. Hence I need to evaluate the variables at this specific time.
How do I evaluate a variable at a specific time from the simulation, or at the end of the simulation for that matter?
Edit: After extensive googling I've come over a function called val(), which seems to do what I want, but I can't get it to work with my Dymola software.
Edit 2: I've managed to evaluate my variables as desired, but the approach I used was (in my opinion) beyond tedious. I extracted the .mat-file from the simulation into MATLAB, where I eventually managed to identify the variables of my desire, and then plotted them at the desired time. What really surprised me, however, was the apparent chaos with respect to the variables in the .mat-file. On first glance, there was little agreement between how my variables are ordered in the Modelica model and how they are ordered in the .mat-file, and there was no naming of the variables, leaving me to search for variables solely based on comparing their value with the Dymola simulation. Am I simply completely mistaken here, or is there some easier way to extract variables from the .mat-file?
Maybe I'm misunderstanding your question, but I suspect there is a simple answer here. It sounds like you have an array and you want to populate that array with the values of a specific variable at a specific time and then plot the array. So, for example, let's say you had a variable x and you want to record the time that x crossed certain threshholds. A simple model like this would suffice:
model RecordVariables
Real x;
Real times[10];
initial equation
x = 11;
equation
der(x) = -x;
when x<=10.0 then
times[1] = time;
end when;
when x<=9.0 then
times[2] = time;
end when;
when x<=8.0 then
times[3] = time;
end when;
when x<=7.0 then
times[4] = time;
end when;
when x<=6.0 then
times[5] = time;
end when;
when x<=5.0 then
times[6] = time;
end when;
when x<=4.0 then
times[7] = time;
end when;
when x<=3.0 then
times[8] = time;
end when;
when x<=2.0 then
times[9] = time;
end when;
when x<=1.0 then
times[10] = time;
end when;
end RecordVariables;
Of course, writing out all those when clauses is pretty tedious. So we can actually create a more compact version like this:
model RecordVariables2
Real x;
Real times[5];
Integer i;
Real next_level;
initial equation
next_level = 10.0;
x = 11;
i = 1;
algorithm
der(x) :=-x;
when x<=pre(next_level) then
times[i] :=time;
if i<size(times,1) then
i :=pre(i) + 1;
next_level :=next_level - 1.0;
end if;
end when;
end RecordVariables2;
A few comments about this approach. First, note the use of the pre operator. This is necessary to distinguish between the values of the variables i and next_level both before and after the events generated by the when clause. Second, you will note the if statement within the when clause that prevents the index i from getting large enough to "overflow" the times buffer. This allows you to set times to have whatever size you want and never risk such an overflow. Note, however, that it is entirely possible in this model to make times so large that some values will never be filled in.
I hope this helps.
You can use DymBrowse.m to load variables from the resultfile to Matlab. It should be available in \Program Files\Dymola xx\Mfiles\dymtools.
Add the directory \Mfiles... to your matlab paths.

Calling several of the same component in Modelica

I seem to struggle with a modeling problem in Modelica (using Dymola), and I hereby seek your help. The idea is this:
I have modeled some components (models) that I want to connect together through their ports. The models are working. The thing is I want to connect several of the same unit (called myUnit in the pseudo code below) in a series. If the number of units were, let's say, only 5 then I could easily dragged them out 1-by-1 and connected them in a standard manner, but let's say I want 100 units. Is there an easy and elegant way to do this? I don't believe for loops to be working outside the equation part of the model, and I want an elegant way of naming the units. I'll try to illustrate this by doing a pseudo code below, explaining what I wish to achieve:
model someModel
parameter Integer n = 100 "Length of series";
parameter Real optionValue = 123;
myLibrary.myStartUnit startUnit(someOption = optionValue); // First unit
for i in 2:n-1 loop
myLibrary.myUnit unit_'num2str(i)'(someOption = optionValue); // i'th unit
end for;
myLibrary.myEndUnit endUnit(someOption = optionValue); // Last unit
equation
connect(startUnit.outPort,unit_1.inPort);
for i in 2:n-1 loop
connect(unit_'num2str(i)'.outPort,unit_'num2str(i+1)'.inPort)
end for;
connect(unit_'num2str(n-1)'.outPort,endUnit.inport);
end someModel;
I hope I've managed to explain my problem properly, now.
Any tips for solving this problem? I greatly appreciate both strategic advice as to solve the problem as well as purely syntactic advice.
In advance, thanks for all help. :)
You can use arrays to achieve this. For example, using models of the Modelica standard library:
model ArrayDemo
parameter Integer n = 10 "Number of springs/masses";
Modelica.Mechanics.Translational.Sources.ConstantForce constantForce(f_constant=100);
Modelica.Mechanics.Translational.Components.Spring springs[n];
Modelica.Mechanics.Translational.Components.Mass masses[n];
Modelica.Mechanics.Translational.Components.Fixed fixed;
equation
connect(constantForce.flange, springs[1].flange_a);
for i in 1 : n - 1 loop
connect(springs[i].flange_b, masses[i].flange_a);
connect(masses[i].flange_b, springs[i + 1].flange_a);
end for;
connect(springs[n].flange_b, masses[n].flange_a);
connect(masses[n].flange_b, fixed.flange);
end ArrayDemo;
The idea is to declare the components using arrays and then connect them using for loops.

Using coupled system of PDEs in modelica

Just few questions, i hope someone will find time to answer :).
What if we have COUPLED model example: system of n indepedent variables X and n nonlinear partial differential equations PDEf(X,PDEf(X)) with respect to TIME that depends of X,PDEf(X)(partial differential equation depending of variables X ). Can you give some advice? Here is one example:
Let’s say that c is output, or desired variable. Let’s say that r is independent variable.Partial differential equation looks like:
∂c/∂t=D*1/r+∂c/∂r+2(D* (∂^2 c)/(∂r^2 ))
D=constant
r=0:0.1:Rp- Matlab syntaxis, how to represent same in Modelica (I use integrator,but didn't work)?
Here is a code (does not work):
model PDEtest
/* Boundary conditions
1. delta(c)/delta(r)=0 for r=0
2. delta(c)/delta(r)=-j*d for r=Rp*/
parameter Real Rp=88*1e-3; // length
parameter Real initialConc=1000;
parameter Real Dp=1e-14;
parameter Integer np=10; // num. of points
Real cp[np](start=fill(initialConc,np));
Modelica.Blocks.Continuous.Integrator r(k=1); // independent x1
Real j;
protected
parameter Real dr=Rp/np;
parameter Real ts= 0.01; // for using when loop (sample(0,ts) )
algorithm
j:=sin(time); // this should be indepedent variable like x2
r.u:=dr;
while r.y<=Rp loop
for i in 2:np-1 loop
der(cp[i]):=2*Dp/r.y+(cp[i]-cp[i-1])/dr+2*(Dp*(cp[i+1]-2*cp[i]+cp[i-1])/dr^2);
end for;
if r.y==Rp then
cp[np]:=-j*Dp;
end if;
cp[1]:=if time >=0 then initialConc else initialConc;
end while;
annotation (uses(Modelica(version="3.2")));
end PDEtest;
Here are more questions:
This code don’t work in OpenModelica 1.8.1, also don’t work in Dymola 2013demo. How can we have continuos function of variable c, not array of functions ?
Can we place values of array cp in combiTable? And how?
If instead “algorithm” stay “equation” code can’t be succesfull checked.Why? In OpenModelica, error is :could not flattening model :S.
Is there any simplified way to use a set of equation (PDE’s) that are coupled? I know for PDEs library in Modelica, but I think they are complicated. I want to write a function for solving PDE and call these function in “main model”, so that output of function be continuos function of “c”.I don’t know what for doing with array of functions.
Can you give me advice how to understand Modelica language, if we “speak” like in Matlab? For example: Values of independent variable r,we can specife in Matlab, like r=0:TimeStep:Rp…How to do same in Modelica? And please explain me how section “equation” works, is there similarity with Matlab, and is there necessary sequancial approach?
Cheers :)
It's hard to answer your question, since you assuming that Modelica ~ Matlab, but that's not the case. So I won't comment your code, since it's really wrong. Let me give you an example model to the burger equation. Maybe you could use it as starting point.
model burgereqn
Real u[N+2](start=u0);
parameter Real h = 1/(N+1);
parameter Integer N = 10;
parameter Real v = 234;
parameter Real Pi = 3.14159265358979;
parameter Real u0[N+2]={((sin(2*Pi*x[i]))+0.5*sin(Pi*x[i])) for i in 1:N+2};
parameter Real x[N+2] = { h*i for i in 1:N+2};
equation
der(u[1]) = 0;
for i in 2:N+1 loop
der(u[i]) = - ((u[i+1]^2-u[i-1]^2)/(4*(x[i+1]-x[i-1])))
+ (v/(x[i+1]-x[i-1])^2)*(u[i+1]-2*u[i]+u[i+1]);
end for;
der(u[N+2]) = 0;
end burgereqn;
Your further questions:
cp is an continuous variable and the array is representing
every discretization point.
Why you should want to do that, as far as I understand cp is
your desired solution variable.
You should try to use almost always equation section
algorithm sections are usually used in functions. I'm pretty
sure you can represent your desire behaviour with equations.
I don't know that library, but the hard thing on a pde is the
discretization and the solving it self. You may run into issues
while solving the pde with a modelica tool, since usually
a Modelica tool has no specialized solving algorithm for pdes.
Please consider for that question further references. You could
start with Modelica.org.