Time varying input ODE solving - matlab

I'm trying to solve a set of ODE equations using ode45. A number of my parameters are already a function of time but I keep getting errors.
function odo
dx(1,1) = (vl+vr)/2*cos(x(3));
dx(2,1) = (vl+vr)/2*sin(x(3));
dx(3,1) = obz
where obz, vr and vl are each vectors e.g:
obz = sin(t), t = 0:dt:tf;
I use the following syntax:
[t, x1] = ode45(#(t,x) odo(t,x,b,obz,vr,vl), 0:dt:tf, [0;0;0]);
with R15 but keep getting the error:
Assignment has more non-singleton rhs dimensions than non-singleton subscripts
How to solve this issue?

You have some syntax errors here. First You can't just type function odo and let the MATLAB guess what it should do here. The second, you call t and x twice in your solver expressions. Be consistent, call function in ode solver this way:
t_span=1:1:12;
b=0.2;
[t, x] = ode45(#odo, t_span, [0;0;0], b);
You don't need to pass t and x manually, solver do it itself. Only the additional parameter b (however it is not in use, in your example). Also in declaration of function do as follow:
function dx = odo(t,x,b)
vr=sin(t); %Non-OD equations here
vl=cos(t);
obz=0.05*sin(t);
n=numel(x); %this generate a holder for results
dx=zeros(n,1);
dx(1) = (vl+vr)/2*cos(x(3)); %All ODEs formatted like this
dx(2) = (vl+vr)/2*sin(x(3));
dx(3) = obz;
As you can see, vr, vl, and obz are time-depended values, so need to be re-calculated in every step of solver. You have to place it in your solver function.

Related

Computing the Jacobian of an anonymous function - MATLAB

I'm trying to solve a system of non linear odes in Matlab as follows.
editparams %parameters
Tend = 50;
Nt = 100;
% Define RHS functions
RHS = #(t,x) ModelRHS(t,x,param); %anonymous function defining the set of equations
%Execution-----------------------------------------------------------------
x0 =[0.04;0.75;0.85]; %Initial condition
t = linspace(0,Tend,Nt); %TSPAN
[t x] = ode45(RHS, t, x0);
Now, I need to find the steady state of the system and I'm trying to create a function for this. I thought I'd calculate the steady state using the Jacobian. My equations are in an anonymous function which is defined as f in the code below. However, I realised that jacobian does not work for anonymous functions (or may be there is a way to do with anonymous functions) . so I thought I would convert the anonymous function to a symbolic function and try it. But
i still have a difficulty in getting that done. So any help is really appreciated!
function SS = SteadyState(param, E)
f = #(t,x)ModelRHS(t,x,param,E); %set of odes
SymbolicSystem = sym(f); %trying to make the anonymous function symbolic
SymbolicJacobian = jacobian(SymbolicSystem',x); %jacobian
Jacob = matlabFunction(SymbolicJacobian,x);
end
Also if there is any other way apart from finding the Jacobian, kindly let me know about that too.
I tried using 'fsolve' to calculate the steady-state as follows:
f = #(t,x)ModelRHS(t,x,param);
x0 =[0.04;0.75;0.85]';
options = optimoptions('fsolve','Display','iter'); % Option to display output
SS = fsolve(f,x0,options); % Call solver
but it returned an error
Not enough input arguments.
Error in #(t,x)ModelRHS(t,x,param)
Error in fsolve (line 242)
fuser = feval(funfcn{3},x,varargin{:});
Caused by:
Failure in initial objective function evaluation. FSOLVE cannot continue.

Solve a matrix valued differential equation in Matlab

I am trying to solve a particular system of ODE's dF/dt = A*F, F_initial = eye(9). Being a Matlab novice, I am trying to somehow use the implemented ode45 function, and I found useful advises online. However, all of them assume A to be constant, while in my case the matrix A is a function of t, in other words, A changes with each time step.
I have solved A separately and stored it in a 9x9xN array (because my grid is t = 0:dt:2, N=2/dt is the number of time-steps, and A(:,:,i) corresponds to it's value at the i-th time step). But I can't implement this array in ode45 to eventually solve my ODE.
Any help is welcomed, and please tell me if I have missed anything important while explaining my problem. Thank you
First of all, F must be a column vector when using ode45. You won't ever get a result by setting F_initial = eye(9), you'd need F = ones(9,1).
Also, ode45 (documentation here, check tspan section) doesn't necessarily evaluate your function at the timesteps that you give it, so you can't pre-compute the A matrix. Here I'm going to assume that F is a column vector and A is a matrix which acts on it, which can be computed each timestep. If this is the case, then we can just include A in the function passed to ode45, like so:
F_initial = ones(9,1);
dt = 0.01;
tspan = 0:2/dt:2;
[t, F] = ode45(#(t,F) foo(t, F, Ainput), tspan, F_initial);
function f = foo(t, F, Ainput)
A = calculate_A(t, Ainput);
f = A*F;
end
function A = calculate_A(t, Ainput)
%some logic, calculate A based on inputs and timestep
A = ones(9,9)*sqrt(t)*Ainput;
end
The #(x) f(x,y) basically creates a new anonymous function which allows you to treat y as a constant in the calculation.
Hope this is helpful, let me know if I've misunderstood something or if you have other questions.

Numeric solution to ODE with square-rooted coefficient

I'm trying to use MATLAB's ODE23 to solve the following equation:
u"(t) = -u'(t) - u(t)^0.5
I've created an auxiliary file for a function I simply called myfun2 as such:
function F2 = myfun2(t,x)
F2 = [-x(1) - power(x(2),0.5); x(1)];
Then I am calling ODE23 as:
[t,x] = ode23(#myfun2, [0:0.1:(7*pi())], [0, 1/0.6671])
The problem is that the solver is outputting a bunch of imaginary values for both t and u which doesn't make sense for u and absolutely none for t since t is supposed to be defined in a 0 to 7PI range at steps of 0.1, as far as I understand...

Solving an ODE when the function is given as discrete values -matlab-

I have the following ODE:
x_dot = 3*x.^0.5-2*x.^1.5 % (Equation 1)
I am using ode45 to solve it. My solution is given as a vector of dim(k x 1) (usually k = 41, which is given by the tspan).
On the other hand, I have made a model that approximates the model from (1), but in order to compare how accurate this second model is, I want to solve it (solve the second ODE) by means of ode45. My problem is that this second ode is given discrete:
x_dot = f(x) % (Equation 2)
f is discrete and not a continuous function like in (1). The values I have for f are:
0.5644
0.6473
0.7258
0.7999
0.8697
0.9353
0.9967
1.0540
1.1072
1.1564
1.2016
1.2429
1.2803
1.3138
1.3435
1.3695
1.3917
1.4102
1.4250
1.4362
1.4438
1.4477
1.4482
1.4450
1.4384
1.4283
1.4147
1.3977
1.3773
1.3535
1.3263
1.2957
1.2618
1.2246
1.1841
1.1403
1.0932
1.0429
0.9893
0.9325
0.8725
What I want now is to solve this second ode using ode45. Hopefully I will get a solution very similar that the one from (1). How can I solve a discrete ode applying ode45? Is it possible to use ode45? Otherwise I can use Runge-Kutta but I want to be fair comparing the two methods, which means that I have to solve them by the same way.
You can use interp1 to create an interpolated lookup table function:
fx = [0.5644 0.6473 0.7258 0.7999 0.8697 0.9353 0.9967 1.0540 1.1072 1.1564 ...
1.2016 1.2429 1.2803 1.3138 1.3435 1.3695 1.3917 1.4102 1.4250 1.4362 ...
1.4438 1.4477 1.4482 1.4450 1.4384 1.4283 1.4147 1.3977 1.3773 1.3535 ...
1.3263 1.2957 1.2618 1.2246 1.1841 1.1403 1.0932 1.0429 0.9893 0.9325 0.8725];
x = 0:0.25:10
f = #(xq)interp1(x,fx,xq);
Then you should be able to use ode45 as normal:
tspan = [0 1];
x0 = 2;
xout = ode45(#(t,x)f(x),tspan,x0);
Note that you did not specify what values of of x your function (fx here) is evaluated over so I chose zero to ten. You'll also not want to use the copy-and-pasted values from the command window of course because they only have four decimal places of accuracy. Also, note that because ode45 required the inputs t and then x, I created a separate anonymous function using f, but f can created with an unused t input if desired.

solving nonlinear equations

I want to solve two nonlinear equations in MATLAB so i did the following:
part of my script
c=[A\u;A\v];
% parts of code are omitted.
x0=[1;1];
sol= fsolve(#myfunc,x0);
the myfunc function is as follows
function F = myfunc(x)
F=[ x(1)*c(1)+x(2)*c(2)+x(1)*x(2)*c(3)+c(4)-ii;
x(1)*c(5)+x(2)*c(6)+x(1)*x(2)*c(7)+c(8)-jj];
end
i have two unknowns x(1) and x(2)
my question is How to pass a values(c,ii,jj) to myfunc in every time i call it?
or how to overcome this error Undefined function or method 'c' for input arguments of type 'double'.
thanks
Edit: The previous answer was bogus and not contributing at all. Hence has been deleted. Here is the right way.
In your main code create a vector of the coefficients c,ii,jj and a dummy function handle f_d
coeffs = [c,ii,jj];
f_d = #(x0) myfunc(x0,coeffs); % f_d considers x0 as variables
sol = fsolve(f_d,x0);
Make your function myfunc capable of taking in 2 variables, x0 and coeffs
function F = myfunc(x, coeffs)
c = coeffs(1:end-2);
ii = coeffs(end-1);
jj = coeffs(end);
F(1) = x(1)*c(1)+x(2)*c(2)+x(1)*x(2)*c(3)+c(4)-ii;
F(2) = x(1)*c(5)+x(2)*c(6)+x(1)*x(2)*c(7)+c(8)-jj;
I think that should solve for x0(1) and x0(2).
Edit: Thank you Eitan_T. Changes have been made above.
There is an alternative option, that I prefer, if a function handle is not what you are looking for.
Say I have this function:
function y = i_have_a_root( x, a )
y = a*x^2;
end
You can pass in your initial guess for x and a value for a by just calling fsolve like so:
a = 5;
x0 = 0;
root = fsolve('i_have_a_root',x0,[],a);
Note: The [] is reserved for fsolve options, which you probably want to use. See the second call to fsolve in the documentation here for information on the options argument.