Input matrix to function file of ode45 - matlab

I have a code(which requires a lot input be given by the user) which will give me a n x n matrix(say A), which I have to use to solve a system of ODEs X'=AX. How do I include this matrix A in the function file(.m file) of ode45. If I include the code in the function file as below:
function xp=g_test(t,x);
k=input('something');
A=some manipulation of inputs;
xp=A*x;
end
Matlab asks for input at each timestep(typically my problem has 30k timesteps). So how do I include/ pass the matrix A to the function?

You can create a function that returns a function handle:
function odeFcn = makeODE(a,b,c)
A = some_function(a, b, c);
odeFcn = #(t,x) A*x;
end
Now you can call ode45 with input matrices a, b, c:
outputVector = ode45(makeODE(a,b,c), [t0, t1], x0);
The inspiration is taken from gnovice's answer here.

Related

ODE solver producing runtime error - not enough input arguments [duplicate]

I have a use case as follows:
Inside F.m I have a function F that takes as its argument a 2 x 1 matrix x. F needs to matrix multiply the matrix kmat by x. kmat is a variable that is generated by a script.
So, what I did was set kmat to be global in the script:
global kmat;
kmat = rand(2);
In F.m:
function result = F(x)
global kmat;
result = kmat*x;
end
Then finally, in the script I have (x_0 has already been defined as an appropriate 2 x 1 matrix, and tstart and tend are positive integers):
xs = ode45(F, [tstart, tend], x_0);
However, this is causing the error:
Error using F (line 3)
Not enough input arguments.
Error in script (line 12)
xs = ode45(F, [tstart, tend], x_0);
What is going on here, and what can I do to fix it? Alternatively, what is the right way to pass kmat to F?
Firstly, the proper way to handle kmat is to make it an input argument to F.m
function result = F(x,kmat)
result = kmat*x;
end
Secondly, the input function to ode45 must be a function with inputs t and x (possibly vectors, t is the dependent variable and x is the dependent). Since your F function doesn't have t as an input argument, and you have an extra parameter kmat, you have to make a small anonymous function when you call ode45
ode45(#(t,x) F(x,kmat),[tstart tend],x_0)
If your derivative function was function result=derivative(t,x), then you simply do ode45(#derivative,[tstart tend],x_0) as Erik said.
I believe F in ode45(F,...) should be a function handle, i.e. #F. Also, you can have a look at this page of the MATLAB documentation for different methods to pass extra parameters to functions.

Use symbolic matlab for flexible number of arguments and functions

I have a function F which takes as an input a vector a. Both the output of the function and a are vectors of length N, where N is arbitrary. Each component Fn is of the form g(a(n),a(n-k)), where g is the same for each component.
I want to implement this function in matlab using its symbolic functionality and calculate its Jacobian (and then store both the function and its jacobian as a regular .m file using matlabFunction). I know how to do this for a function where each input is a scalar that can be handled manually. But here I want a script that is capable of producing these files for any N. Is there a nice way to do this?
One solution I came up with is to generate an array of strings "a0","a1", ..., "aN" and define each component of the output using eval. But this is messy and I was wondering if there is a better way.
Thank you!
[EDIT]
Here is a minimal working example of my current solution:
function F = F_symbolically(N)
%generate symbols
for n = 1:N
syms(['a',num2str(n)]);
end
%define output
F(1) = a1;
for n = 2:N
F(n) = eval(sprintf('a%i + a%i',n,n-1));
end
Try this:
function F = F_symbolically(N)
a = sym('a',[1 N]);
F = a(1);
for i=2:N
F(i) = a(i) + a(i-1);
end
end
Note the use of sym function (not syms) to create an array of symbolic variables.

How to use derive.m function to get central differentioation of f(x)

I've a function that can calculate central difference of f(x) but I'm basic user of matlab and I can't define f(x) for function I've mentioned.
Can any body help me and define f(x) for this function?
INPUTS are a function f; a value
of h; a specific point a; the number of rows n. The input function f(x)
should be defined as an M-file.
My f(x) is : S(x) = 10*x-sin(x) with steps: 0.1
I want to get df(x) near the piont=pi/6
I wrote:
clc
syms x
derive(10*x-sin(x),0.1,pi/6,14)
but I've got this error :
Error using feval
Argument must contain a string or function_handle.
Error in derive (line 7)
D(1,1)=(feval(f,a+h)-feval(f,a-h))/(2*h);
Error in centre(line 2)
========================================
the function derive.m is here:
function derive(f,h,a,n)
% Approximate the derivative of a function at x = a.
disp(' Derivative table')
disp('______________________________________________')
disp(' i h Di,1 Di,2 Di,3 ... ')
disp('______________________________________________')
D(1,1)=(feval(f,a+h)-feval(f,a-h))/(2*h);
fprintf('%2.0f %8.4f %12.4f\n',1,h,D(1,1));
for i=1:n-1
h=h/2;
D(i+1,1)=(feval(f,a+h)-feval(f,a-h))/(2*h);
fprintf('%2.0f %8.4f %12.4f',i+1,h,D(i+1,1));
for k=1:i
D(i+1,k+1)=D(i+1,k)+(D(i+1,k)-D(i,k))/((4^k)-1);
fprintf('%12.4f',D(i+1,k+1));
end
fprintf('\n');
end
feval expects a function handle, that is a MatLab function handle. What you provided (10*x-sin(x)) is a symbolic expression.
You can define a function handle as follows:
f(x) = 10*x-sin(x);
Now f is a MatLab function handle, and you can use it as you wish:
derive(f,0.1,pi/6,14)
EDIT
You can also use an anonymous functions
derive((x)(10*x-sin(x)),0.1,pi/6,14)
END EDIT
Note, you do not need syms x, it defines x as a symbol, but in your function definition you use the parameter x defined in f(x).
EDIT
If you want to use a symbolic function, you can convert it to a MatLab function handle using matlabFunction

optimize the function in MATLAB

I have tried many times taking different initial values of c. I did not get optimum values of c using function fminsearch. I have found more error between simulated and measured values of sigma. Please help me: how can optimize my function?
clc
close all
clear all
syms c sigma est_bio mea_bio
sigma=[-15.1015 -13.7879 -13.0576 -12.7818 -12.3839 -11.7587 -11.1756 -10.6291 -9.9176];
mea_bio=[0.181 0.204 0.529 0.632 1.059 1.533 1.934 1.977 1.861];
%%% create model function q with parameters
q = #(c, mea_bio) ((c(1)/(-2*c(2))).*(1-exp(2*c(2).*mea_bio))+c(3).*exp(2*c(2).*mea_bio))
%// create the desired error-functions for minimization
h = #(c) sum((q(c, mea_bio) - sigma).^2); %// default minimizaton function
c= [-.05 -.0500 -.0500]; % an initial guess
[p_fit_e, r_e] = fminsearch(h, c) % Optimize
est_q = ((c(1)/(-2*c(2))).*(1-exp(2*c(2).*mea_bio))+c(3).*exp(2*c(2).*mea_bio))
err=est_q-sigma
Why do you define c, sigma est_bio and mea_bio as symbolic variables? It doesn't make sense. This is a numerical optimization, no need to involve symbolic computations. Remove that line from your code and it should work:
syms c sigma est_bio mea_bio

using for loop in GA in matlab

I am using GA in Matlab to solve an optimization problem,
my objective function is to minimize cost with variable v,
function b = cost (v)
load ('data.mat');
c1=0;
for i = 1:N
for j=1:1
c1 = c1 + c(i,j)*v(i,j);
end
end
b=c1;
and my constraint is const
function [z] = const(v)
load ('data1.mat');
Z1=1;
for i=1:N
for j=1:1
a(i,j) = (1-v(i,j))*t(i,j);
Z(i,j) = ((a(i,j)+T1)/y(i,j))/(a(i,j)/y(i,j));
end
Z1 = Z1 * Z(i,j);
end
z=[0.7-Z1];
zeq=[];
Using for code for GA
lb=zeros(N,1);
ub=ones(N,1);
IntCon = u;
options = gaoptimset('PlotFcns',{#gaplotbestf,#gaplotmaxconstr},'Display','iter');
[v, fval] = ga(#cost,N,[],[],[],[],lb,ub,#const,IntCon,options);
where u=[1 2 3 4...N]
I have already saved required data in data1.mat file.
I want to make the objective function and constraint both generalized,
otherwise I will have to write R,a and c value for N number of times.
problem is when I run it, it gives a message
%Error using ga (line 342)
%Too many output arguments.
%Caused by:
%Failure in initial user-supplied nonlinear constraint function evaluation.
You need to use varargout which is variable output argument in MATLAB. Simply replace your code's output argument i.e. where you have defined your ga function. Instead of an array, it should be varargout{}. There is an example on Mathworks site about how to do this.
Possibly change your input and output arguments with varargin and varargout respectively. Seems like you will need this throughout.
hope this helps!