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.
Related
In a MATLAB-function the following code is used:
function stuff()
if a == 2
do1();
else
do2();
end
end
This code is placed inside a simulation-loop and gets called 1000 times or more per second. The if-statement does only matter in the first call of the function, after that either do1 or do2 are used, the variable a will not change any more.
How do I prevent to waste processing time with this if-statement? Basically, how do I tell Matlab, to not check the if-statement any more, and just call the one function, that gets selected in the first call to stuff?
Contrary to your beliefs this is not a problem, the compiler (should) automatically does this optimization for you. See e.g. Loop-invariant code motion.
What you can do to help the compiler is to move the calculation of the check outside as a flag, e.g.
flag = a==2;
for i = 1:100
stuff(flag)
end
Then you only have to do the calculation once and it is clear to the compiler that the value does not change.
NOTE: Obviously, if your check really is a==2, this would not make much of a difference.
EDIT: I have not been able to definitely verify that MATLAB does this automatically. However, this is only the first layer of optimization that is done for you. All modern processors use what is called a Branch predictor, see e.g. this brilliant answer Why is processing a sorted array faster than processing an unsorted array?, or this wiki page. In short, the processor guesses the result of the if-statement, if it is correct, everything goes faster. I think it is fair to say that the processor guesses correctly in all of your cases.
TLDR: Do not wory about it.
Given the comments above, it seems what you are actually looking for is a way to dynamically chose the function to be run in your simulation. This choice should be dynamic (you do not know which function to use at runtime) but the choice should only be done once. This is easily achievable using function handles: https://www.mathworks.com/help/matlab/function-handles.html
Here is an example:
function dynamicSimulation()
if ( rand() > 0.5 ) % determine which function should be called dynamically
sim=#func1;
else
sim=#func2;
end
other_params = [];
for k = 1:5 % run the simulation
sim( k, other_params );
end
end
function func1( index, other_params )
fprintf( 'Index=%d: Simulating using function 1\n', index );
end
function func2( index, other_params )
fprintf( 'Index=%d: Simulating using function 2\n', index );
end
If you run this several times you will notice that the (random) choice of func1 or func2 will mean you do not get the same function being run each time, although the same one is used for the entire simulation.
I reckon you don't waste much time on checking the validity that if statement. However, since you specifically mention it only checks for the first iteration: why not get that out? So instead of:
for ii = 1:10
if ii == 1
k = 1;
else
k = k + 1;
end
end
You could do
k = 1;
for ii = 2:10
k = k + 1;
end
Thus eliminating the check.
NB: this scales badly of course, but as it is only a single iteration here I consider it a good option.
I run a Matlab code with an iteration loop, and during each iteration it sample random numbers and uses the function intlinprog. My issue is that, due to the large amount of data I provide to the intlinprog function and to the stochastic values I assign to part of its variables, some of the iterations take a really long time.
My code is more or less like this:
rounds = 1E3;
Total_PF = zeros(rounds,4893);
for i=1:rounds
i
cT = zeros (4894,1);
cT(4894,1) = 1;
xint = linspace(1,4893,4893);
xint = xint';
AT = rand(4,4894);
beT = ones(4,1);
lb = zeros(4894,1);
ub = ones (4894,1);
ub(4894,1) = Inf;
[x] = intlinprog(cT,xint,AT,beT,[],[],lb,ub);
Total_PF(i,:)= (x(1:length(x)-1)');
end
Now in the minimal working example I provided, all the iterations are quite fast, but in my real code, sometimes intlinprog takes really long time ( I mean hours) to do a single iteration.
Therefore, I was wondering: is there a way to break the intlinprog while the intlinprog line is being executed? I was thinking that it may be done by modifying the matlab function but first of all I do not know if I am allowed to do it, secondly I am afraid that may be very dangerous.
This is very difficult to do effectively.
You could try using a timer object to watch the value. However, since you are using inherent Matlab functions and not executing external functions, you could set a time limit value and utilize tic and toc in a while loop while you execute the intlinprog and checking the value of toc against your time limit and break your code if toc exceeds the limit.
This might seem like a strange thing to do, which it probably is. In my main (or how you call it in matlab) I would like to have all the information needed for the program to run. A change of variables or formulas should only happen in my main.
For example I would like to change the number of iterations and the formula of the hypothese in my main and let other function use these, instead of declaring them within the function themselves and having to edit it all over the place. The problem I face is not knowing how to do this properly for hypothese_formula and wonder if there is a better way of doing this?
function prog1()
iterations = 1;
hypothese_formula = x^2;
doSomethingWithFormulaAndIterations(hypothese_formula, iterations);
end
Practical: I would to do linear regression with a hypothesis of the formula and specific starting values of theta and don't want them to be hidden within a function. I don't know how to declare global formula's.
You can use anonymous functions.
function prog1()
iterations = 1;
hypothese_formula = #(x) x.^2
doSomethingWithFormulaAndIterations(hypothese_formula, iterations);
end
I parallelised the code below but the simulation time is actually 400-500 times longer than the serial code. The only reason i can think of that can cause this is the message 'variable x is indexed but not sliced in parfor loop and 'variable p is indexed but not sliced in parfor loop. Can anyone verify whether this is the reason for the huge increase in simulation time or the way i parallelised the code.
p=(1,i) and x(1,i) are matrix with values set before hand.
nt=1;
nc=32;
time(1,1) = 0.0;
for t=dt:dt:0.1
nt=nt+1;
time(1,nt) = t;
disp(t);
for ii=2:nc
mytemp=zeros(1,ii);
dummy=0.0;
parfor jj=1:nc+1
if ii==jj % skipped
continue;
end
dxx = x(1,jj) - x(1,ii);
rr=abs(dxx);
if rr < re
dummy(jj) = (p(nt-1,jj)-p(nt-1,ii))*kernel(rr,re,ktype)*rr;
mytemp(jj) = kernel(rr,re,ktype)*rr;
%sumw(1,ii) = sumw(1,ii) + kernel(rr,re,1);
end
end
mysum = sum(dummy);
zeta(1,ii)=sum(mytemp);
lapp(1,ii) = 2.0*dim*mysum/zeta(1,ii);
p(nt,ii) = p(nt-1,ii) + dt*lapp(1,ii);
end
% update boundary value
p(nt,1) = function_phi(0,t);
p(nt,nc+1) = function_phi(1,t);
end
Can't be sure that is the reason, but if some parts of the code end up being parallelized while others cannot, it will create a lot of overhead without any speedup. See for example the Q&A here for a more detailed discussion of slicing.
Basically, if you have a parfor with a variable jj, then every statement in which jj is used on the right hand side should also use jj on the left hand side - in that way, the "job" can be divided between different processors, each of which tackles part of the array in parallel. As soon as that doesn't happen, for example in your lines
dxx = x(1,jj) - x(1,ii);
rr=abs(dxx);
you break the paradigm. 400x slower? I don't know about that - but the warning is pretty clear.
The first two lines could be consolidated, by the way, by computing rr(jj) (although you don't need an array):
rr(jj) = abs(x(1,jj) - x(1,ii));
You then use that value rather than rr later in the loop. This is a bit like having a private variable for each copy of the loop (a concept that I don't think Matlab has - but exists in OMP ).
I don't see where p is indexed in the parfor loop … it seems to be update outside of the inner loop, where it ought not to matter.
You might find it helpful to profile your code with the parallel profiler http://www.mathworks.com/help/distcomp/profiling-parallel-code.html - it will be instructive.
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.