I have a MATLAB function, when I try to run it, it does not store the output variables in the workspace. Please let me know the proper solution such that the variables in the function are stored in the workspace.
I have a following code in which I have to store values of variables T and Y in workspace.
function him1
k0 = ones(1,5);
exp=[0.2;0.12;0.24;0.2]; %//experimental data
time=[0;1;2;3]; %//time span
%// initial values of state variables
x01=1;
x02=1;
x03=1;
x04=1;
x0 = [x01,x02,x03,x04];
tspan = [min(time),max(time)];
k_opt = fminsearch(#minimize, k0)
function e = minimize(k0)
[~,y_hat] = ode45(#unit2, tspan, x0,[], k0);
% size(y_hat)
% y_hat = deval(sol, time(end)); % // evaluate solution at given times
e = sum((y_hat(end,:)' - exp).^2) % // compute squarederror '
end
% // plot with optimal parameter
[T,Y] = ode45(#unit2, tspan, [x01,x02,x03,x04], [], k_opt);
figure
subplot(1,2,1)
plot(time(end), exp, '*', 'markersize',15)
hold on
plot(T,Y, 'linewidth', 2)
end
function dx = unit2(t, x, k)
dx = zeros(4,1);
dx(1)=-k(1)*x(1)*7 + k(2)*x(2);
dx(2)=k(1)*x(1)*7 - k(2)*x(2) -k(3)*x(2)*x(2) + k(4)*x(3);
dx(3)=k(3)*x(2)*x(2) - k(4)*x(3)-k(5)*x(4);
dx(4)=k(5)*x(4);
end
It is a characateristic of functions, that only variables which are defined in the declatation are handed over to the workspace. (If you ignore more complex concepts like global variables and assignin)
If your main target is to get the calculation done and the variables in the workspace, than I suggest to convert it to an m-script instead of a function.
See: http://de.mathworks.com/help/matlab/matlab_prog/scripts-and-functions.html
You can try to identify your variables as global.
Related
I have an ODE to be integrated with ode113. Inside the function that describes the derivatives I compute some variables that I would like to "save" (either store into a file or into an array). How can I do that?
Here is an example (adapted from the documentation). Run the following script:
global number_of_calls
number_of_calls = 0;
[t, y] = ode113(#myfunc, [0 10], 0);
plot(t,y,'-o')
fprintf('Number of calls of ''myfunc'': %d\n', number_of_calls)
fprintf('Number of elements of ''t'' : %d\n', length(t))
which calls the function containing the ODE to be integrated:
function dydt = myfunc(t, y)
global number_of_calls
dydt = 2*t;
a = 2*y; % <--- how can I save a?
number_of_calls = number_of_calls + 1;
end
I thought of writing to file the values of a from inside myfunc, but as you can see myfunc is called multiple times before actually storing the current value for the independent variable, t, and in the end I would have two arrays a and t of different size.
Here's one way you can write myfunc to do this. It saves the results to a global vector a, which must be set to [] before each call to ode113. It uses a persistent variable to keep track of the previous time step:
function dydt = myfunc(t, y)
dydt = 2*t;
temp = 2*y; % Extra value to save
global a
persistent tPrevious
if isempty(a) % Initialize
a = temp;
elseif (t > tPrevious) % Moving to a new time step, so add an element
a = [a; temp];
else % Refining time step downwards or recomputing at the same time step
a(end) = temp;
end
tPrevious = t; % Store prior time step
end
And you can check that it's working like so:
global a;
a = [];
[t, y] = ode113(#myfunc, [0 10], 0);
isequal(2.*y, a)
ans =
logical
1 % a exactly equals 2.*y
I am trying to compute the value of this integral using Matlab
Here the other parameters have been defined or computed in the earlier part of the program as follows
N = 2;
sigma = [0.01 0.1];
l = [15];
meu = 4*pi*10^(-7);
f = logspace ( 1, 6, 500);
w=2*pi.*f;
for j = 1 : length(f)
q2(j)= sqrt(sqrt(-1)*2*pi*f(j)*meu*sigma(2));
q1(j)= sqrt(sqrt(-1)*2*pi*f(j)*meu*sigma(1));
C2(j)= 1/(q2(j));
C1(j)= (q1(j)*C2(j) + tanh(q1(j)*l))/(q1(j)*(1+q1(j)*C2(j)*tanh(q1(j)*l)));
Z(j) = sqrt(-1)*2*pi*f(j)*C1(j);
Apprho(j) = meu*(1/(2*pi*f(j))*(abs(Z(j))^2));
Phi(j) = atan(imag(Z(j))/real(Z(j)));
end
%integration part
c1=w./(2*pi);
rho0=1;
fun = #(x) log(Apprho(x)/rho0)/(x.^2-w^2);
c2= integral(fun,0,Inf);
phin=pi/4-c1.*c2;
I am getting an error like this
could anyone help and tell me where i am going wrong.thanks in advance
Define Apprho in a separate *.m function file, instead of storing it in an array:
function [ result ] = Apprho(x)
%
% Calculate f and Z based on input argument x
%
% ...
%
meu = 4*pi*10^(-7);
result = meu*(1/(2*pi*f)*(abs(Z)^2));
end
How you calculate f and Z is up to you.
MATLAB's integral works by calling the function (in this case, Apprho) repeatedly at many different x values. The x values called by integral don't necessarily correspond to the 1: length(f) values used in your original code, which is why you received errors.
I want to fit a Lorentzian to my data, so first I want to test my fitting procedure to simulated data:
X = linspace(0,100,200);
Y = 20./((X-30).^2+20)+0.08*randn(size(X));
starting parameters
a3 = ((max(X)-min(X))/10)^2;
a2 = (max(X)+min(X))/2;
a1 = max(Y)*a3;
a0 = [a1,a2,a3];
find minimum for fit
afinal = fminsearch(#devsum,a0);
afinal is vector with parameters for my fit. If I test my function as follows
d= devsum(a0)
then d= 0, but if I do exactly what's in my function
a=a0;
d = sum((Y - a(1)./((X-a(2)).^2+a(3))).^2)
then d is not equal to zero. How is this possible? My function is super simple so I don't know what's going wrong.
my function:
%devsum.m
function d = devsum(a)
global X Y
d = sum((Y - a(1)./((X-a(2)).^2+a(3))).^2);
end
Basically I'm just implementing stuff I found here
http://www.home.uni-osnabrueck.de/kbetzler/notes/fitp.pdf
page 7
It is usually better to avoid using global variables. The way I usually solve these problems is to first define a function which evaluates the curve you want to fit as a function of x and the parameters:
% lorentz.m
function y = lorentz(param, x)
y = param(1) ./ ((x-param(2)).^2 + param(3))
In this way, you can reuse the function later for plotting the result of the fit.
Then, you define a small anonymous function with the property you want to minimize, with only a single parameter as input, since that is the format that fminsearch needs. Instead of using global variables, the measured X and Y are 'captured' (technical term is doing a closure over these variables) in the definition of the anonymous function:
fit_error = #(param) sum((y_meas - lorentz(param, x_meas)).^2)
And finally you fit your parameters by minimizing the error with fminsearch:
fitted_param = fminsearch(fit_error, starting_param);
Quick demonstration:
% simulate some data
X = linspace(0,100,200);
Y = 20./((X-30).^2+20)+0.08*randn(size(X));
% rough guess of initial parameters
a3 = ((max(X)-min(X))/10)^2;
a2 = (max(X)+min(X))/2;
a1 = max(Y)*a3;
a0 = [a1,a2,a3];
% define lorentz inline, instead of in a separate file
lorentz = #(param, x) param(1) ./ ((x-param(2)).^2 + param(3));
% define objective function, this captures X and Y
fit_error = #(param) sum((Y - lorentz(param, X)).^2);
% do the fit
a_fit = fminsearch(fit_error, a0);
% quick plot
x_grid = linspace(min(X), max(X), 1000); % fine grid for interpolation
plot(X, Y, '.', x_grid, lorentz(a_fit, x_grid), 'r')
legend('Measurement', 'Fit')
title(sprintf('a1_fit = %g, a2_fit = %g, a3_fit = %g', ...
a_fit(1), a_fit(2), a_fit(3)), 'interpreter', 'none')
Result:
I have a set of coupled nonlinear ODE's, i need to solve these ODE's, then estimate and optimize the parameters using genetic algorithm or any function so as to minimize the difference between experimental and simulated data.
i have all the initial values for all state variables and the range(1-10) for the parameters to be estimated. I am new to MATLAB please forgive if i had made any syntax errors.
following is the code:
function dx = reaction( t,x,k )
dx = zeros(6,1);
dx(1)=0;
dx(2)= k(1)*x(1) - k(2)*x(2) - k(3)*x(5) + k(4)*x(6);
dx(3)=0;
dx(4) = -k(2)*x(3)*x(4) + k(3)*x(5);
dx(5) = k(8)*x(3)*x(4) - k(7)*x(5) - k(3)*x(2)*x(5) + k(5)*x(6);
dx(6) = k(6)*x(2)*x(5) - k(3)*x(6) - k(4)*x(2)*x(6);
end
function objective
k01=1:10;
k02=1:10;
k03=1:10;
k04=1:10;
k05=1:10;
k06=1:10;
k07=1:10;
k08=1:10; %//range of parameters to lie in
exp=[8;0;0.8;12;0;0]; %//experimental data
time=[0;5;10;15;20;25]; %//time span
x01=8;
x02=0;
x03=0.8;
x04=12;
x05=0;
x06=0; %// initial values of state variables
tspan = [min(time),max(time)];
k_opt = fminsearch(#minimize, [k1,k2,k3,k4,k5,k6,k7,k8])
function e = minimize(k1,k2,k3,k4,k5,k6,k7,k8)
sol = ode45(#reaction, tspan, [x01,x02,x03,x04,x05,x06],[], [k1,k2,k3,k4,k5,k6,k7,k8]);
y_hat = deval(sol, time); % // evaluate solution at given times
e = sum((y_hat' - exp).^2); % // compute squarederror
end
% // plot with optimal parameter
[T,X] = ode45(#reaction, tspan, [x01,x02,x03,x04,x05,x06], [], k_opt);
figure
plot(time, exp,'ko', 'markersize',10,'markerfacecolor','black')
hold on
plot(T,Y, 'r--', 'linewidth', 2)
end
See this as a start (still needs some work). It is the best that i can come up with.
Your plot plot(time, exp,'ko', 'markersize',10,'markerfacecolor','black') doesn't make sense to me as it plots the data over the time, which (referring to your latest comment) is not what exp should be. Thats why i was asking in the comments
The optimization stops with an error of about 139.3828 for me, also raising some warnings about problems with the numerical integration. The optimal parameterset is
k_opt =
-0.2258 6.2298 -1.2666 3.6352 -1.8671 0.0001 2.5592 -2.2011
Here comes the code:
function main
k0 = ones(1,8);
exp=[8;0;0.8;12;0;0]; %//experimental data
time=[0;5;10;15;20;25]; %//time span
%// initial values of state variables
x01=8;
x02=0;
x03=0.8;
x04=12;
x05=0;
x06=0;
x0 = [x01,x02,x03,x04,x05,x06];
tspan = [min(time),max(time)];
k_opt = fminsearch(#minimize, k0)
function e = minimize(k0)
[t,y_hat] = ode45(#reaction, tspan, x0,[], k0);
% y_hat = deval(sol, time(end)); % // evaluate solution at given times
e = sum((y_hat(end,:)' - exp).^2) % // compute squarederror '
end
% // plot with optimal parameter
[T,Y] = ode45(#reaction, tspan, [x01,x02,x03,x04,x05,x06], [], k_opt);
figure
subplot(1,2,1)
plot(time(end), exp, '*', 'markersize',15)
hold on
plot(T,Y, 'linewidth', 2)
% // Scatter: data vs model
subplot(1,2,2)
scatter(Y(end,:), exp)
hold on
axis equal
grid on
xlabel('model')
ylabel('data')
disp('yay')
end
function dx = reaction(t, x, k)
dx = zeros(6,1);
dx(1)=0;
dx(2)= k(1)*x(1) - k(2)*x(2) - k(3)*x(5) + k(4)*x(6);
dx(3)=0;
dx(4) = -k(2)*x(3)*x(4) + k(3)*x(5);
dx(5) = k(8)*x(3)*x(4) - k(7)*x(5) - k(3)*x(2)*x(5) + k(5)*x(6);
dx(6) = k(6)*x(2)*x(5) - k(3)*x(6) - k(4)*x(2)*x(6);
end
And two plots of the result. Blue and red are fit quite well, however, they do not change while integrating. I do not know about the others i.e. if your equations are correct and actually can reproduce the result.
I have a simple function as below:
function dz = statespace(t,z)
dz = A*z + B*k*z
end
My main script is :
clear all;close all;format short;clc;
% step 1 -- input system parameters
% structure data
M1 = 1; M2= 1; M3= 1; %Lumped Mass(Tons)
M= diag([M1,M2,M3]);
k(1)= 980; k(2)= 980; k(3)= 980; %Stiffness Coefficient(KN/M)
K = zeros(3,3);
for i=1:2
K(i,i)=k(i)+k(i+1);
end
K(3,3)=k(3);
for i=1:2
K(i,i+1)=-k(i+1);
end
for i=2:3
K(i,i-1)=-k(i);
end %Stiffness Matrix(KN/M)
c(1)= 1.407; c(2)= 1.407; c(3)= 1.407; %Damping Coefficient(KN.sec/M)
C = zeros(3,3);
for i=1:2
C(i,i)=c(i)+c(i+1);
end
C(3,3)=c(3);
for i=1:2
C(i,i+1)=-c(i+1);
end
for i=2:3
C(i,i-1)=-c(i);
end %Damping Matrix(KN.sec/M)
A = [zeros(3) eye(3);-inv(M)*K -inv(M)*C]
H = [1;0;0]
B = [0;0;0;inv(M)*H]
k = [-1 -1 -1 -1 -1 -1]
t = 0:0.004:10;
[t,z] = ode45(statespace,t);
When I run my main script it comes with following error:
Undefined function or variable 'A'.
Error in statespace (line 2)
dz = A*z + B*k*z
As you can see I defined A in main script. Why this problem happening?
There multiple things wrong with your code. First, you need to supply the values of A and B to your function but as you are invoking it (incorrectly without the # and additional parameter y0 as I commented below) in the toolbox ode45, you have to keep just two parameters so you cannot supply A and B as additional parameters. If you define A and B within your function or share them via global variables you will get further. However, as noted below the definitions don't seem to be correct as A * z and B * k * z don't have the same dimensions. z is a scalar so B * k needs to be same size and shape as A which currently it is not.
Edit from:
As Jubobs suggested change your function's parameters to include A, B and k. Also you don't need t as it is never used in the function. So:
function dz = statespace(A, B, k, z)
dz = A*z + B*k*z
end
As others have pointed out, A, B and k are not defined in the function workspace, so you either need to define them again (ugly, not recommended), declare them as global variables (slightly better, but still not good practice), or pass them as arguments to your function (the better solution). However, because you then want to use the function with ode45, you need to be a bit careful with how you do it:
function dz = statespace(t,z,A,B,k)
dz = A*z + B*k*z
end
and then the call to ode45 would like this:
[t,z] = ode45(#(t,z)statespace(t,z,A,B,k),[0 Tf],z0); % where Tf is your final time and z0 your initial conditions
See Error using ode45 and deval for a similar problem.