I have an external function that I require to call at most twice during the simulation. It has a large output of size Real[n][m][k] where n, m, and ks product is a relatively large integer. I call the function inside a when statement. The issue I have is that the output of the function is copied over and over in .mat file for each iteration and causes it to be really large even though I use the output infrequently. I wonder if there is a way to store the output only once and avoid storing the copies of the output in the results file for each time step.
P.s. If that is not possible I might try to store the results of the function in another file, but need to use them in the simulation. So as an alternative is there also a way to make the simulation ignore storing a variable in the results file.
I don't think there is a way to store a subset of variables only at certain points in time.
Select variables
What can be done is using HideResult to avoid storing them in the result file. They can still be used in the simulation though. As an example:
model HideRes
Real y1 annotation(HideResult=true);
Integer y2;
parameter Real x1 = 1;
parameter Real x2 = 2 annotation(HideResult=true);
equation
when time > 0.1 then
y1 = sin(x1);
elsewhen time > 0.2 then
y1 = sin(x2);
end when;
y2 = 10*integer(y1);
end HideRes;
In the above code, y1 and x2 will not be shown in the result file.
Protect variables
As an alternative to the above (thanks Hans O. for pointing at this) it is also possible to use protected variables. By default, they will not be stored in the result file. Additionally, they will not be accessible from higher levels of hierarchy in the model itself. Also parameters will not show up in the parameter dialog.
Below is the same example with protected applied (the parameter x2 cannot be modified from the outside).
model HideRes
Integer y2;
parameter Real x1 = 1;
protected
Real y1;
parameter Real x2 = 2;
equation
when time > 0.1 then
y1 = sin(x1);
elsewhen time > 0.2 then
y1 = sin(x2);
end when;
y2 = 10*integer(y1);
end HideRes;
Chose timing
Some simulators also offer the possibility to store only at defined events. For Dymola, this would e.g. be:
when x > 0 then
Dymola.Simulation.TriggerResultSnapshot();
end when;
Note: it stores all variables, not just a subset.
Related
I have a differential equation: dx/dt = a * x. Using Matlab Simulink, I need to solve this equation and output it using Scope block.
The problem is, I don't know how to specify an initial condition value t = 0.
So far I have managed to create a solution that looks like this:
I know that inside integrator, there is a possiblity to set "Initial condition" but I can't figure out how that affects the final result. How can I simply set the value of x at t = 0; e.i. x(0) = 6?
Let's work this problem through analytically first so we know if the model is correct.
dx/dt = a*x % Seperable differential equation
=> (1/x) dx = a dt % Now we can integrate
=> ln(x) = a*t + c % We can determine c using the initial condition x(0)
=> ln(x0) = a*0 + c
=> ln(x0) = c
=> x = exp(a*t + ln(x0)) % Subbing into 3rd line and taking exp of both sides
=> x = x0 * exp(a*t)
So now we have an idea. Let's look at this for t = 0 .. 1, x0 = 6, a = 5:
% Plot x vs t using plain MATLAB
x0 = 6; a = 5;
t = 0:1e-2:1; x = x0*exp(a*t);
plot(t,x)
Now let's make a Simulink model which acts as a numerical integrator. We don't actually need the Integrator block for this application, we simply want to add the change at each time step!
To run this, we must first set a couple of things up. In Simulation > Model Configuration Parameters, we must set the time step to match the time step we've used to switch between dx/dt and dx (2nd Gain block).
Lastly, we must set the initial condition for x0, this can be done in the Memory block
Setting the end time to 1s and running the model, we see the expected result in the Scope. Because it matches our analytical solution, we know it is correct.
Now we understand what's going on, we can re-introduce the integration block to make the model more flexible. Using the integrator means that dt is automatically calculated, and we don't need to micro-manage the Gain block, in fact we can get rid of it. We still need a Memory block though. We now also need intial conditions in both the integrator, and the memory block. Put scopes in different locations and just complete the first few time steps to work out why!
Note that the initial conditions are less clear when using the integrator block.
The way to think about the integrator blocks is either completely in the Laplace picture, or as representing the equivalent integral equation for the IVP
y'(t)=f(t,y(t)), y(0) = y_0
is equivalent to
y(t) = y_0 + int(s=0 to t) f(s,y(s)) ds
The feed-back loop in the block diagram realizes almost literally this fixed-point equation for the solution function.
So there is no need for complicated constructions and extra blocks.
I have a code in which I create a large number of the same variable and I would like to store all of its values. Normally I would use for loops for this and store all of them, but due to some complications it is not possible at the moment.
I have to calculate the variable x, store it as x1. Calcute the x with different conditions and store it as x2 etc. The problem I have that I would have to manually change all the x's in my code to x2, x3, x4 etc. And there are a lot of them. Is there a way to it more efficiently?
To better illustrate:
x1 = 5*y(1);
%some calculations with y
x2 = 5*y(2);
% some claculations with y
x3=5*y(3);
If you are really desperate you could use eval and loop through all of your variable names, assuming they are numbered 1 through n.
count = 1;
while exist(['x',num2str(count)],'var')
eval(['x(count)=x',num2str(count),';'])
count = count + 1;
end
This code assumes everything is numbered x1, x2, x3, etc. It will continue looping until the next "sequential" x no longer exists. This would go at the end of whatever script or function you are running after all the declarations have happened.
Just note that storing everything the way you did initially is very frowned upon. It makes code hard to read and cumbersome, and it not very dynamic.
Either way, the code above should do the trick.
You could also write a regular expression to replace all xn and whatever instances to x(n).
Just run the following lines of code, giving it the file name you want to convert, and boom it will handle all of the replacement for you
fileName = 'findReplace.m';
replaced = regexprep(fileread(fileName),'x([0-9]+)','x($1)');
fh = fopen(fileName,'w');
fprintf(fh,replaced);
fclose(fh);
I am trying to create a function that stores a very large variable for use each time the function is called. I have a function myfun(x,y) where y is very large, and therefore slow to execute because MATLAB is pass-by-value. However, I only pass the variable y once during execution of a program, creating a closure that is then passed off to another function to call repeatedly:
Y = create_big_matrix();
newfun = #(x) myfun(x,Y);
some_other_fun(newfun); % This calls newfun several times
I assume that each time newfun is called, it copies the stored value of Y to myfun. This seems very inefficient. Is there a better way to implement newfun so that Y is only copied once, when the newfun is created (and maybe when it's passed to some_other_fun)?
MATLAB has copy-on-write mechanisms that prevent a copy of Y when myfun(x,Y) is called, unless it modifies the input. I do not think you need to worry about performance issues in this case, but I would have to see the code for myfun and run tests to verify.
Quoting this post on a MathWorks blog:
Some users think that because MATLAB behaves as if data are passed by value (as opposed to by reference), that MATLAB always makes copies of the inputs when calling a function. This is not necessarily true.
The article goes on to describe that MATLAB has limited abilities to recognize when a variable is modified by a function and avoids copies when possible. See also this SO answer summarizing the "under the hood" operations during copy-on-write as described in an old newsreader post.
To investigate whether a copy is taking place, use format debug to check the data pointer address pr for Y in the calling function, and again inside myfun. If it is the same, no copy is taking place. Set a breakpoint to step through and examine this pointer.
Since Y is not a parameter of the function handle, it is only passed to the function handle once, namely at the time of it's execution - including all fancy copy-on-write optimizations there might be.
So the function_handle gets its own version of Y right at the time of its definition.
During execution of the function_handle Y is not passed to the function_handle at all.
You can visualize that with a easy example:
>> r = rand();
% at this point the function_handle gets lazy copy of r, stored in its own workspace
>> f = #() r;
>> r
r =
0.6423
% what happens to the original r, doesn't matter to the function-handle:
>> clear r
>> f()
ans =
0.6423
An actual copy should only be made if the original Y gets modified / deleted (where it's really copied on delete might be another question).
You can check whether or not Y gets really copied into the function_handle workspace using functions, with the above example (only with a different value for r):
r =
Structure address = c601538
m = 1
n = 1
pr = 4c834a60
pi = 0
0.4464
>> fcn = functions(f);
>> fcn.workspace{1}.r
ans =
Structure address = c6010c0
m = 1
n = 1
pr = 4c834a60
pi = 0
0.4464
You can see that, as discussed in chappjc's answer, the parameter is only lazily copied at this time - so no full copy is created.
I have a class with properties in it (let say the name of the class file is inputvar),
I use it as the input argument for two different functions, which have an exactly the same calculation, but a little bit different code, which I'll explain later.
For the first function (let say the name is myfun1), I wrote the input argument like this:
f = myfun1 (inputvar)
So every time I want to use variables from the class inside the function, I'll have to call inputvar.var1, inputvar.var2, and etc.
For the second function (myfun2), I wrote each variables from the class in the input argument, so it looks like this:
f = myfun2 (inputvar.var1, inputvar.var2, ... etc )
Inside the function, I just have to use var1, var2, and etc, without having to include the name of the class.
After running both functions, I found that myfun2 runs a lot faster than myfun1, about 60% (I used tic-toc).
Can someone explain to me exactly why is that ?
with the reference:
MATLAB uses a system commonly called "copy-on-write" to avoid making a
copy of the input argument inside the function workspace until or
unless you modify the input argument. If you do not modify the input
argument, MATLAB will avoid making a copy. For instance, in this code:
function y = functionOfLargeMatrix(x) y = x(1); MATLAB will not make a
copy of the input in the workspace of functionOfLargeMatrix, as x is
not being changed in that function. If on the other hand, you called
this function:
function y = functionOfLargeMatrix2(x) x(2) = 2; y = x(1);
then x is being modified inside the workspace of functionOfLargeMatrix2, and so a copy must be made.
According to the statement above, when you directly pass a class object and you change any member of this object, a whole copy operation for the class is applied.
On the other side, with giving the class members as separate arguments, copy operation is applied only for the related members modified in the function, resulting in a faster execution.
I found that accessing properties is very slow in Matlab. I have not found a way around it, but some basic ideas are found here: http://blogs.mathworks.com/loren/2012/03/26/considering-performance-in-object-oriented-matlab-code/
But this article talks only about avoiding horrible, abysmal performance. Even with the simplest properties, performance is mediocre at best.
Take the example class from the Mathworks article. I did small test script:
clear all
clc
n = 1e5;
%% OOP way - abysimal
result = zeros(1, n);
tic
for i = 1:n
cyl = SimpleCylinder();
cyl.R = i;
cyl.Height = 10;
result(i) = cyl.volume();
end
toc
%% OOP Vectorized - fair
clear result
tic
cyl = SimpleCylinder();
cyl.R = 1:n;
cyl.Height = 10;
result = cyl.volume();
toc
%% for loop without objects - good
result = zeros(1, n);
tic
for i = 1:n
result(i) = pi .* i.^2 .* 10;
end
toc
%% Vectorized without objects - excellent
clear result
tic
R = 1:n;
result = pi .* R.^2 .* 10;
toc
With these results:
Elapsed time is 6.141445 seconds.
Elapsed time is 0.006245 seconds.
Elapsed time is 0.002116 seconds.
Elapsed time is 0.000478 seconds.
As you can see, every property access is slowing down. Try to vectorize (as always) but even the simple for-loop outperforms the vectorized OOP solution for small n. (On my PC, they break even at 1e7)
Essential message: OOP in Matlab is slow! You pay the price for every property access.
To your question: When you call
myfun2 (inputvar.var1, inputvar.var2, ... etc )
the values are copied. Within the function, you are no longer dealing with classes. Access to variables is fast. However, if you pass the whole class, every access to a property is slow. You can circumvent this by caching all properties in local variables and use these.
If you modify the class to inherit from handle everything gets a bit faster, but the difference is negligible.
I am implementing the adaptive Simpsons method in Matlab recursively. I wish to store all of the points where function evaluations take place to generate a histogram after integrating. I currently have:
function [S, points] = adsimp(f, a, b, fv, tol, level, points)
...
d = (a+b)*0.25;
e = (a+b)*0.75;
points = [points, d, e];
...
Thus, for every function call, I am increasing the length of points by two. My understanding of Matlab's function input/output scheme is poor. I'd like to know:
1) When the input and output share a variable name, does this use a single variable, or is a local copy made and then returned?
2) If it is a copy, is there a way to pass points by reference and preallocate sufficient memory?
To answer your first question, see here. Most MATLAB variables are passed by value (matrices, etc.) unless it is a handle object (function handle, axis handle etc.) A local copy of an input variable is made only if that variable is altered in the function. ie.
function y = doTheFunc1(x)
x(2) = 17;
y = x;
a copy must be made. As opposed to:
function y = doTheFunc2(x)
y = x(1);
where no copy need be made inside the function. In other words, MATLAB is a "copy on write" language. I am almost certain this is true regardless what your output variable output name is (ie. this holds even if your output and input are both named x).
To answer your second question, look at the first answer here. Consider using a nested function or a handle object.