Index increase in inner function - matlab

I have a main Matlab code which I use in order to calculate ode.
The main code contains many lines but I will explain only the ones needed.
The code looks as following (short version):
global array
t0=0
x0=[5,5]
dt=0.01
tfinal=10
[tout,xout]=rk4('equation',t0,x0,dt,tfinal) % the functions use the function 'equation' and calculates its values at every time from 0 to 20
Where 'equation' is another function from the following type:
global array
Dydx = equation(t,x)
Dydx=[x(1)
x(2)+array(j)]
j=j+1
However, as can be seen, inside the function "equation" there is a variable j which I want to increase every t iteration of rk4.
Which means that while I calculate the ode for time t, the rk4 should use function 'equation' and increase the j by one and so on.
The problem I get is that if I try to make 'equation' gives output of j like [Dydx,j] =equation(t,x) I recieve an error because of rk4.
How can I increase j in the inner function while the outside functions also get the value?(tried global but it kept showing j as [] in the work space).
I have tried to make it global as following but it didnt work:
global array jcount
t0=0
x0=[5,5]
dt=0.01
tfinal=10
jcount = 1;
[tout,xout]=rk4('equation',t0,x0,dt,tfinal)
global array jcount
Dydx = equation(t,x)
Dydx=[x(1)
x(2)+array(jcount)]
jcount=jcount+1
Thank you.
.

Related

Using parfor with temporary variable

I want to calculate count of outside points which are not in the circle. But I got this problem. My circle is unit circle.My Error is this : The temporary variable outside will be cleared at the beginning of each iteration
of the parfor loop.
function [ ] = girkoson( N,n )
%UNTÄ°TLED Summary of this function goes here
% Detailed explanation goes here
hold on
outside = 0;
parfor i=0:N
E=ones(N,n);
karekok = sqrt(n);
E = [E, eig(randn(n))/karekok];
a=real(E);
b= imag(E);
plot(a,b,'.r');
if (a>= -1) | (a<=1) | (b>=-1) | (b<=1)
outside = outside +1;
fprintf('%f',outside);
end
end
derece=0:0.01:2*pi;
xp=1*cos(derece);
yp=1*sin(derece);
x=0;y=0;
plot(x+xp,y+yp,'-b');
hold off
end
It looks like you're trying to treat outside as a parfor reduction variable. You cannot access the intermediate values of reduction variables during the loop - you can only perform the reductions. In other words, the line fprintf('%f', outside) is causing the problem, you must remove this for the parfor loop to work.
Also note that workers operating on the body of your parfor loop cannot display graphics to your desktop, so your plot calls will not show anything on-screen. (You can use print to emit graphics to a file if you wish).

Looping a Function in Matlab

total newbie here. I'm having problems looping a function that I've created. I'm having some problems copying the code over but I'll give a general idea of it:
function[X]=Test(A,B,C,D)
other parts of the code
.
.
.
X = linsolve(K,L)
end
where K,L are other matrices I derived from the 4 variables A,B,C,D
The problem is whenever I execute the function Test(1,2,3,4), I can only get one answer out. I'm trying to loop this process for one variable, keep the other 3 variables constant.
For example, I want to get answers for A = 1:10, while B = 2, C = 3, D = 4
I've tried the following method and they did not work:
Function[X] = Test(A,B,C,D)
for A = 1:10
other parts of the code...
X=linsolve(K,L)
end
Whenever I keyed in the command Test(1,2,3,4), it only gave me the output of Test(10,2,3,4)
Then I read somewhere that you have to call the function from somewhere else, so I edited the Test function to be Function[X] = Test(B,C,D) and left A out where it can be assigned in another script eg:
global A
for A = 1:10
Test(A,2,3,4)
end
But this gives an error as well, as Test function requires A to be defined. As such I'm a little lost and can't seem to find any information on how can this be done. Would appreciate all the help I can get.
Cheers guys
I think this is what you're looking for:
A=1:10; B=2; C=3; D=4;
%Do pre-allocation for X according to the dimensions of your output
for iter = 1:length(A)
X(:,:,iter)= Test(A(iter),B,C,D);
end
X
where
function [X]=Test(A,B,C,D)
%other parts of the code
X = linsolve(K,L)
end
Try this:
function X = Test(A,B,C,D)
% allocate output (it is faster than changing the size in every loop)
X = {};
% loop for each position in A
for i = 1:numel(A);
%in the other parts you have to use A(i) instead of just A
... other parts of code
%overwrite the value in X at position i
X{i} = linsolve(K,L);
end
end
and run it with Test(1:10,2,3,4)
To answer what went wrong before:
When you loop with 'for A=1:10' you overwrite the A that was passed to the function (so the function will ignore the A that you passed it) and in each loop you overwrite the X calculated in the previous loop (that is why you can only see the answer for A=10).
The second try should work if you have created a file named Test.m with the function X = (A,B,C,D) as the first code in the file. Although the global assignment is unnecessary. In fact I would strongly recommend you not to use global variables as it gets very messy very fast.

How does function work regarding to the memory usage?

When you are using function in MATLAB you have just the output of the function in the work space and all the other variables that maybe created or used in the body of that function are not shown. I am wondering how does function work? Does it clear all other variables from memory and just save the output?
function acts like a small, isolated programming environment. At the front end you insert your input (e.g. variables, strings, name-value pairs etc). After the function has finished, only the output is available, discarding all temporarily created variables.
function [SUM] = MySum(A)
for ii = 1:length(A)-1
SUM(ii) = A(ii)+A(ii+1);
kk(ii) = ii;
end
end
>> A=1:10
>> MySum(A)
This code just adds two consecutive values for the input array A. Note that the iteration number, stored in kk, is not output and is thus discarded after the function has completed. In MATLAB kk(ii) = ii; will be underlined orange, since it 'might be unused'.
Say you want to also retain kk, just add it to the function outputs:
function [SUM,kk] = MySum(A)
and keep the rest the same.
If you have large variables that you only use up to a certain point and wish them not clogging up your memory whilst the function is running, use clear for that:
function [SUM] = MySum(A)
for ii = 1:length(A)-1
SUM(ii) = A(ii)+A(ii+1);
kk(ii) = ii;
end
clear kk
end

MATLAB Return value of first non-empty argument (built-in COALESCE function)

Is there something inbuilt in MATLAB which functions similar to the SQL COALESCE function. I want that function to return the first 'existing' value from all the arguments.
For example,
clear A B; C=10; COALESCE(A,B,C)
should return value of C (because A and B are unassigned/don't exist).
I know it would be very easy to code, and I am just being lazy here. But, I would be surprised if MATLAB doesn't have a similar function.
As far as I know there is no built-in function for that. But you can easily write your own.
Note that it is not possible in Matlab to pass a variable that has not been defined prior of using it. Therefore your proposed call clear A B; C=10; COALESCE(A,B,C) is invalid and will throw an error. Instead we can define an empty variable using var=[].
The following code creates two empty variables A, B and and assigns C=10. Inside the function coalesce we assume at the beginning that all variables are empty. In the for-loop we return the first non-empty variable. In the version without for-loop we get the index of the first non-zero element and then return the corresponding content of the cell if a non-zero element exists.
If you want the function to be accessible from everywhere within Matlab, see the documentation here.
function testcoalesce
A = [];
B = [];
C = 10;
COALESCE(A,B)
COALESCE(A,B,C)
end
% with for-loop (much faster)
function out = COALESCE(varargin)
out = [];
for i = 1:length(varargin)
if ~isempty(varargin{i})
out = varargin{i};
return;
end
end
end
% without for-loop (slower)
function out = COALESCE(varargin)
out = [];
ind = find(cellfun('isempty', varargin)==0, 1);
if ~isempty(ind);
out = varargin{ind};
end
end
The output is as expected:
ans =
[]
ans =
10
Timing the two functions showed, that the first solution using the for-loop is approximately 48% faster than the function without loop.
(10 samples, 1'000'000 iterations, 3 variables & 20 variables)

Using Matlab Parfor with 'Eval'

I am trying to execute a parfor loop within a parent script for Matlab.
I want to calculate the implied volatility of an option price, and then create a new column within a preexisting dataset with the results.
load('/home/arreat/Casino/names.mat')
name = char(names(i))
%Loop over n rows to populate columns in dataset named using variable 'name(i)'
rows = eval(['length(',name,')'])
parfor n=[1:rows]
%Calculate implied volatility using blsimpv(Price, Strike, Rate, Time, Value, Limit,Yield, Tolerance, Class)
BidIV = blsimpv(eval([name,'.UnderlyingPrice(n)']),...
eval([name,'.Strike(n)']),...
RiskFree/100,...
eval([name,'.Lifespan(n)'])/252,...
eval([name,'.Bid(n)'])+.01,...
10,...
0,...
1e-15,...
eval([name,'.Type(n)'])...
)
eval([name,'.BidIV(n,1) = double(BidIV);']);
%Loop and add implied volatility (BidIV) to a column with n number of
%rows.
end
The problem arises with the 'eval()' calculation in the parfor loop. Mathworks suggested that I should turn the whole script into a function, and then call the function within the parfor loop.
While I work on this, any ideas?
Instead of calling eval all the time, you can call it once outside the loop, e.g. data = eval(name), and then use data.Strike etc inside the parfor loop.
To avoid calling eval at all, do the following:
%# load mat-file contents into structure allData, where
%# each variable becomes a field
allData = load('/home/arreat/Casino/names.mat');
data = allData.(name);