# How to save multiple varibles from the function into the workspace?

11 views (last 30 days)
Tomas on 22 Jan 2014
Edited: Amit on 23 Jan 2014
Hello,
I have got a Matlab function where I solve a system of differential equations with the ode45 function. Everything works fine, but... there is a variable (we can call it H) which is randomly generated with every calculation step (H=rand(1)). That means H changes its value aprox. 15 000 times during calculation (this number can change). What I want is to save H into the array located in the base workspace of Matlab - to have a matrix (vector) with size 15 000x1 for following use. It's not a problem for me to transfer one variable from the function to the workspace (with assignin or putvar function), but I dont know how to transfer many variables and put them into one array.
I have also an idea to save each of H values to the *.mat file and than load all of them into the workspace. Is this somehow possible?
Thank you.

Amit on 22 Jan 2014
A possible suggestion (Disclaimer: I have never done it)
If you have some estimate how many times the functions gets called in ODE45, then great. Like you mentioned, lets say its ~15000 times. Now,
N = 15000*1.1; % 10% margin
global rand_gen count;
rand_gen = rand(N,1);
count = 1;
In the function you're calling the random number, define
global rand_gen count;
H = rand_gen(count,1);
count = count + 1;
The idea is to make the random stream and a flag for location global. This way the function can access these values and you'll have them stored as well in workspace.
Amit on 23 Jan 2014
Edited: Amit on 23 Jan 2014
Two things: Do you realized the in your initial condition y = [0.01*0 0.002*0 -0.2*0 0.1*0], which is essentially [0 0 0 0]. I am not sure if that is what you're looking for.
I just solved it for [0 1] time space using this method and it solves it. For [0 1] time span, total count it 472778. Imagine this for [0 10].
Now with persistent method, you are adding this in every count time. To do this even for [0 1] time span, it will take dramatic time because everytime the function gets called, you're increasing the size of vector H by 1. MATLAB have to store this to a new location over and over again.
Amit on 23 Jan 2014
Also, this function can not take jumps for integration as in every time step things are changing. So ODE45 will have to call this many many time even for small time range.
I am attaching a result from my integration and you suggest if this is something what you expect?

AJ von Alt on 22 Jan 2014
You can return multiple variables from a function using the function definition syntax:
function [ out1 , out2 , out3 ] = myFunction ( input1 )
out1 = 1;
out2 = 2;
out3 = 3;
You then call the function with the syntax:
[ A, B, C] = myFunction ( input1 )
The outputs out1, out2, and out3 will be stored in A, B, and C respectively.
You can save a single function to a .mat file using the save command followed by the filename and a string containing variable name.
save('myfile.mat','A')
Example:
% save A to myfile.mat
save('myfile.mat','A')
% remove A from the workspace
clear A
% look for A in the work space
whos A
% nothing is returned because A was cleared
% load myfile.mat into the work space
% check for A in the work space
whos A
% now we see A again
Name Size Bytes Class Attributes
A 1x1 8 double
##### 3 CommentsShow 1 older commentHide 1 older comment
AJ von Alt on 22 Jan 2014
In that case a persistent vector is an alternate solution. Make H a persistent vector in the function called by ode45, and append the random number to it in each iteration. The vector can be written to the work space each iteration using assignin or additional code can be written to return it as a second output with a final function call. In either case, the function should be cleared after the call to clear the persistent variable.
Multiple output arguments example:
function [dy Hout] = rigid1(t,y)
persistent H;
if nargout == 2
dy = [];
Hout = H;
clear H;
else
% ode stuff
dy = zeros(3,1); % a column vector
dy(1) = y(2) * y(3);
dy(2) = -y(1) * y(3);
dy(3) = -0.51 * y(1) * y(2);
% store a random number at the end of H
H(end+1) = rand;
end
Command line call:
[T,Y] = ode45(@rigid1,[0 12],[0 1 1]);
[~,Hout] = rigid1([],[]);
clear rigid1
Write H to base workspace every iteration example:
function dy = rigid2(t,y)
persistent H;
% ode stuff
dy = zeros(3,1); % a column vector
dy(1) = y(2) * y(3);
dy(2) = -y(1) * y(3);
dy(3) = -0.51 * y(1) * y(2);
% store a random number at the end of H
H(end+1) = rand;
% write H to the base workspace
assignin('base','Hout',H)
Command line call:
[T,Y] = ode45(@rigid2,[0 12],[0 1 1]);
clear rigid2
Tomas on 23 Jan 2014
Seems like this works. But I have one question - why ode45 procudes vector Y with for example 77 elements and the Hout vector with 153 or 254 elements? (depends how difficult calculation is)
Like in this version of function, where I get 8000 and 13000 elements.
function dy = rigid2(t,y)
persistent H;
% ode stuff
% store a random number at the end of H
H(end+1) = rand;
h=H(end);
dy = zeros(3,1); % a column vector
dy(1) = y(2) * y(3)*h;
dy(2) = -y(1) * y(3)*sin(h);
dy(3) = -0.51 * y(1) * y(2);
% write H to the base workspace
assignin('base','Hout',H)