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

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.

Respuestas (2)

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.

6 comentarios

out of curiosity, I tested it. And it works.
Well if I understand it good.. in the executioned file I should type first paragraph where I define some vector with 15000*1.1 column/rows and this vector is then read one after one in called function.
But if I do that, Matlab reports following problem:
Attempted to access rand_gen(1501,1); index out of bounds because size(rand_gen)=[1500,1].
For example just in this function, where Matlab makes about 1000 computations.
nH=1000*1.5;
global rand_gen count;
rand_gen=rand(nH,1);
count=1;
[t,y]=ode45(@diff_equations,[0:0.01:10],[0.01*0 0.002*0 -0.2*0 0.1*0]);
Matlab function diff_equations:
function dy=diff_equations(t,y)
%%INPUTS
m1=3000;
m2=13100;
b1=40000*0.25;
b2=100000*0.25;
k1=3331500;
k2=1610000;
%Forces
F10=1000;
F20=100;
omega1=50;
omega2=6.5414;
fi1=pi/8;
fi2=-pi/4;
F1=F10*sin(omega1*t+fi1);
F2=F20*sin(omega2*t+fi2);
global rand_gen count;
H=rand_gen(count,1);
count=count+1;
%Kinematical input
v1=1*H+1;
v2=10*H+1;
v=10;
h01=0.005;
h02=0.01*v1;
LB1=0.75;
LB2=0.1*v2;
omega1h=2*pi*v/LB1;
omega2h=2*pi*v/LB2;
fih1=pi/16;
fih2=pi/2;
h1=h01*sin(omega1h*t+fih1);
h2=h02*sin(omega2h*t+fih2);
dh1=omega1h*h01*cos(omega1h*t+fih1);
dh2=omega2h*h02*cos(omega2h*t+fih2);
h=h1+h2;
dh=dh1+dh2;
%COMPUTATION
dy=zeros(4,1);
y1=y(1);
y2=y(2);
y3=y(3);
y4=y(4);
dy(1)=y3;
dy(2)=y4;
dy(3)=-1/m1*((b1+b2)*y3+(k1+k2)*y1-b2*y4-k2*y2-b1*dh-k1*h+F1);
dy(4)=-1/m2*(-b2*y3-k2*y1+b2*y4+k2*y2+F2);
Where H value is located in part called %Kinematical input. Any ideas?
You set nH = 1000*1.5. Please make nH a big number like 15000*1.1.
The error you're getting is simple because matlab's must have called the function more time than 1000*1.5.
Also, make sure to reset count = 1 before every run. IF you still get error, type count in the command window and see what's its value it.
Still the same problem..
Attempted to access rand_gen(25001,1); index out of bounds because size(rand_gen)=[25000,1].
Error in soustava2 (line 23)
H=rand_gen(count,1);
Error in ode45 (line 265)
f(:,5) = feval(odeFcn,t+hA(4),y+f*hB(:,4),odeArgs{:});
Error in kmitani2 (line 8)
[t,y]=ode45(@soustava2,[0:0.01:10],[0.01*0 0.002*0 -0.2*0 0.1*0]);
It doesn't matter if I set nH 1000 or 1 000 000. Matlab can't do it.
clear all
clc
nH=15000;
global rand_gen count;
rand_gen=rand(nH,1);
count=1;
[t,y]=ode45(@soustava2,[0:0.01:10],[0.01*0 0.002*0 -0.2*0 0.1*0]);
Amit
Amit el 23 de En. de 2014
Editada: Amit el 23 de En. de 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.
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?

Iniciar sesión para comentar.

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
load('myfile.mat')
% check for A in the work space
whos A
% now we see A again
Name Size Bytes Class Attributes
A 1x1 8 double

3 comentarios

He is using ode45 to integrate the function. The issue is that the function have a variable that changes randomly everytime it gets called. So even if he used save or assignin, the variable (lets say A) will be overwritten from the previous one.
He need, for some purpose, every of those random values utilized during the integration.
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
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)

Iniciar sesión para comentar.

Categorías

Más información sobre System Commands en Centro de ayuda y File Exchange.

Preguntada:

el 22 de En. de 2014

Editada:

el 23 de En. de 2014

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by