MATLAB want to convert explicit euler algorithm to implicit euler algorithm for SYSTEM of 1st order ODEs - matlab

Before anything, I can't use ANY built-in ODE solvers for this. I coded this system of ODEs with explicit euler's method but I need to instead rewrite it with implicit euler's. If I just switch the "i" to "i+1" (ex "y(1,i)" to "y(1,i+1)") then the answer comes out obscenely wrong.
A_init= 4;
B_init= 1.1;
C_init= 4;
y0 = [A_init; B_init; C_init];
h = 20/100;
n = 100;
t0 = 0;
tf = 20;
t = linspace(t0,tf,n);
y = zeros(numel(y0) , n);
y(:, 1) = y0(:);
dAdt= #(a,b) 7.27*(b-a*b+ a-(8.375*10^-5)*a^3);
dBdt= #(b,a,c)(-b-a*b+c)/77.27;
dCdt= #(c,a) 0.4*(a-c);
for i = 1:n-1
y(1,i+1) = y(1,i) +h*feval(dAdt,y(1,i),y(2,i));
y(3,i+1) = y(3,i) +h*feval(dCdt,y(3,i),y(1,i));
y(2,i+1) = y(2,i) +h*feval(dBdt,y(2,i),y(1,i),y(3,i));
end

Your idea is correct, but remember that if you change the i on the right-hand side to i+1, you will have y(1,i+1), y(2,i+1), y(3,i+1) appearing on both sides of the equation. This means that you actually have to solve for y(1,i+1), y(2,i+1) and y(3,i+1) at each step. Since your three equations are coupled, you have to solve a nonlinear system of equations at each time-step, using fsolve or fzero.
Read the answer to this question, which shows how to do this for the single equation case.

Related

Double integral expressed by a second variable

I'm having trouble with implementing double integral in Matlab.
Unlike other double integrals, I need the result of the first (inside) integral to be an expression of the second variable, before going through the second (outside) integral, as it must be powered by k.
For example:
In the example above, I need the result of the inside integral to be expressed as 2y, so that I can calculate (2y)^k, before doing the second (outside) integral.
Does anyone know how to do this in Matlab?
I don't like doing things symbolically, because 99.9% of all problems don't have a closed form solution at all. For 99.9% of the problems that do have a closed-form solution, that solution is unwieldy and hardly useful at all. That may be because of my specific discipline, but I'm going to assume that your problem falls in one of those 99.9% sets, so I'll present the most obvious numerical way to do this.
And that is, integrate a function which calls integral itself:
function dbl_int()
f = #(x,y) 2.*x.*y + 1;
k = 1;
x_limits = [0 1];
y_limits = [1 2];
val = integral(#(y) integrand(f, y, k, x_limits), ...
y_limits(1), y_limits(2));
end
function val = integrand(f, y, k, x_limits)
val = zeros(size(y));
for ii = 1:numel(y)
val(ii) = integral(#(x) f(x,y(ii)), ...
x_limits(1), x_limits(2));
end
val = val.^k;
end

Matlab optimiziation where objective is implicitly given by a fixed point equation

I have the following problem:
max CEQ(w) s.t. w in (0,1) and I don't know anything about CEQ(w) except that is given by a fixed point equation of the form CEQ(w) = F(CEQ(w)). If I fix a w, I can solve the fixed point equation using the fzero function and obtain a value for CEQ. If I choose a different w, I get another value for CEQ. Thus, I could loop over all possible values of w and then choose the one that gives the highest CEQ. This seems bad programming though and I was wondering whether I can do this more efficient in MATLAB: I want to model the solution to my fixed point equation as a function of w but I don't know how to implement it.
To be more precise, here is a sample code:
clear all
clc
NoDraws = 1000000;
T_hat = 12;
mu = 0.0058;
variance = 0.0017;
rf = 0.0036;
sim_returns(:,T_hat/12) = T_hat*mu + sqrt(T_hat*variance)*randn(NoDraws,1);
A = 5;
kappa=1;
l=0;
theta = 1 - l*(kappa^(1-A) - 1) *(kappa>1);
CEQ_DA_0 = 1.1;
CEQ_opt = -1000;
w_opt = 0;
W_T = #(w) (1-w)*exp(rf*T_hat) + w*exp(rf*T_hat + sim_returns(:,T_hat/12));
for w=0.01:0.01:0.99
W=W_T(w);
fp = #(CEQ) theta*CEQ^(1-A)/(1-A) - mean( W.^(1-A)/(1-A)) + l*mean( ((kappa*CEQ)^(1-A)/(1-A) - W.^(1-A)/(1-A)) .* (W < kappa*CEQ));
CEQ_DA = fzero(fp,CEQ_DA_0);
if CEQ_DA > CEQ_opt
CEQ_opt = CEQ_DA;
w_opt = w;
end
end
That is, in the loop, I fix a w, solve the fixed point equation and store the value for CEQ. If some other w gives a bigger value for CEQ, the current optimal w gets replaced by that new w. what I would like to have (instead of the loop part) is something like this:
fp = #(CEQ,w) theta*CEQ^(1-A)/(1-A) - mean( W_T(w).^(1-A)/(1-A)) + l*mean( ((kappa*CEQ)^(1-A)/(1-A) - W_T(w).^(1-A)/(1-A)) .* (W_T(w) < kappa*CEQ));
CEQ_DA = #(w) fzero(fp,CEQ_DA_0);
[w_opt, fval]=fminbnd(CEQ_DA,0,1);
Your proposed solution is very close. In words, you're defining fp as a function of two arguments, and would like CEQ_DA to be a function of w, which solves fp for CEQ, with that given w. The only issue is that fzero doesn't know which parameter of fp to solve over, because it can't match anonymous function parameters and fp parameters by name.
The answer is yet one more anonymous function inside the fzero, to turn fp(CEP,w) into fp_w(CEP), which will be solveable for CEQ
CEQ_DA = #(w) fzero(#(CEQ) fp(CEQ, w),CEQ_DA_0);

Simulating nonlinear differential quation in MATLAB?

I was assigned a program where I have to create a MATLAB model for the equation and figure as follows-- http://i.stack.imgur.com/wV0ro.png. Unfortunately, I've been stuck for quite a while.
or dh/dt = (-r^2*sqrt(2*g*h))/(0.5r+htan(phi))^2
where
g=386.4 in/s^2
h = 2+(34/64) in
r = 1/10 in
angle=30.519612098961595 degrees
I calculated for dh/dt, which is -0.185963075319895 in/s and time to empty t=13.611573134321043 s, which I did by t=h/-c1_solution.
My x and y range are:
t1_span = [0 t]
y1_span = [0 ; h]
My function is like this so far:
function hvt1 = leak(r,h,angle, g)
c1_solution_1 = (-(r(y1_span))^2 * sqrt(2*g*h(y1_span))) ;
c1_solution_2 = (0.5*r(t1_span)+h(t1_span)*tand(angle))^2 ;
c1_solution = c1_solution_1(1)/c1_solution_2(1) ;
hvt1 = c1_solution ;
So, this definitely needs work. I'm very inexperienced with this type of thing. I'm wondering how I can model how the container drains as a function of time. I'm guessing I'll have to use ode45. I know how to format ode45 in my program, but I'm having trouble with creating the functions.
Thanks in advance. :)
There is nothing mysterious or unclear about the documentation of ode45. As I said in comment, it's unclear what you are asking, and you should rewrite the differential equation in your post instead of linking to an external image...
In this example, you can replace solver by any matlab solver. r,g,phi are the constants defined by your problem, h0 is your initial state and tspan is the timespan in which you are considering your solution. Some solvers allow you to specify a timestep, others choose it dynamically.
[t,h] = solver( #dh_dt, tspan, h0 );
function dh = dh_dt(t,h)
dh = - r*r*sqrt(2*g*h);
dh = dh / (.5*r + h*tan(phi))^2;
end

Matlab: finding coefficients of ODE system

I have all the data and an ODE system of three equations which has 9 unknown coefficients (a1, a2,..., a9).
dS/dt = a1*S+a2*D+a3*F
dD/dt = a4*S+a5*D+a6*F
dF/dt = a7*S+a8*D+a9*F
t = [1 2 3 4 5]
S = [17710 18445 20298 22369 24221]
D = [1357.33 1431.92 1448.94 1388.33 1468.95]
F = [104188 104792 112097 123492 140051]
How to find these coefficients (a1,..., a9) of an ODE using Matlab?
I can't spend too much time on this, but basically you need to use math to reduce the equation to something more meaningful:
your equation is of the order
dx/dt = A*x
ergo the solution is
x(t-t0) = exp(A*(t-t0)) * x(t0)
Thus
exp(A*(t-t0)) = x(t-t0) * Pseudo(x(t0))
Pseudo is the Moore-Penrose Pseudo-Inverse.
EDIT: Had a second look at my solution, and I didn't calculate the pseudo-inverse properly.
Basically, Pseudo(x(t0)) = x(t0)'*inv(x(t0)*x(t0)'), as x(t0) * Pseudo(x(t0)) equals the identity matrix
Now what you need to do is assume each time step (1 to 2, 2 to 3, 3 to 4) is an experiment (therefore t-t0=1), so the solution would be to:
1- Build your pseudo inverse:
xt = [S;D;F];
xt0 = xt(:,1:4);
xInv = xt0'*inv(xt0*xt0');
2- Get exponential result
xt1 = xt(:,2:5);
expA = xt1 * xInv;
3- Get the logarithm of the matrix:
A = logm(expA);
And since t-t0= 1, A is our solution.
And a simple proof to check
[t, y] = ode45(#(t,x) A*x,[1 5], xt(1:3,1));
plot (t,y,1:5, xt,'x')
You have a linear, coupled system of ordinary differential equations,
y' = Ay with y = [S(t); D(t); F(t)]
and you're trying to solve the inverse problem,
A = unknown
Interesting!
First line of attack
For given A, it is possible to solve such systems analytically (read the wiki for example).
The general solution for 3x3 design matrices A take the form
[S(t) D(t) T(t)].' = c1*V1*exp(r1*t) + c2*V2*exp(r2*t) + c3*V3*exp(r3*t)
with V and r the eigenvectors and eigenvalues of A, respectively, and c scalars that are usually determined by the problem's initial values.
Therefore, there would seem to be two steps to solve this problem:
Find vectors c*V and scalars r that best-fit your data
reconstruct A from the eigenvalues and eigenvectors.
However, going down this road is treaturous. You'd have to solve the non-linear least-squares problem for the sum-of-exponentials equation you have (using lsqcurvefit, for example). That would give you vectors c*V and scalars r. You'd then have to unravel the constants c somehow, and reconstruct the matrix A with V and r.
So, you'd have to solve for c (3 values), V (9 values), and r (3 values) to build the 3x3 matrix A (9 values) -- that seems too complicated to me.
Simpler method
There is a simpler way; use brute-force:
function test
% find
[A, fval] = fminsearch(#objFcn, 10*randn(3))
end
function objVal = objFcn(A)
% time span to be integrated over
tspan = [1 2 3 4 5];
% your desired data
S = [17710 18445 20298 22369 24221 ];
D = [1357.33 1431.92 1448.94 1388.33 1468.95 ];
F = [104188 104792 112097 123492 140051 ];
y_desired = [S; D; F].';
% solve the ODE
y0 = y_desired(1,:);
[~,y_real] = ode45(#(~,y) A*y, tspan, y0);
% objective function value: sum of squared quotients
objVal = sum((1 - y_real(:)./y_desired(:)).^2);
end
So far so good.
However, I tried both the complicated way and the brute-force approach above, but I found it very difficult to get the squared error anywhere near satisfyingly small.
The best solution I could find, after numerous attempts:
A =
1.216731997197118e+000 2.298119167536851e-001 -2.050312097914556e-001
-1.357306715497143e-001 -1.395572220988427e-001 2.607184719979916e-002
5.837808840775175e+000 -2.885686207763313e+001 -6.048741083713445e-001
fval =
3.868360951628554e-004
Which isn't bad at all :) But I would've liked a solution that was less difficult to find...

How to use MATLAB to numerically solve equation with unknown embedded in integral?

I've been trying to use MATLAB to solve equations like this:
B = alpha*Y0*sqrt(epsilon)/(pi*ln(b/a)*sqrt(epsilon_t))*integral from
0 to pi of
(2*sinint(k0*sqrt(epsilon*(a^2+b^2-2abcos(theta))-sinint(2*k0*sqrt(epsilon)*a*sin(theta/2))-sinint(2*k0*sqrt(epsilon)*b*sin(theta/2)))
with regard to theta
Where epsilon is the unknown.
I know how to symbolically solve equations with unknown embedded in an integral by using int() and solve(), but using the symbolic integrator int() takes too long for equations this complicated. When I try to use quad(), quadl() and quadgk(), I have trouble dealing with how the unknown is embedded in the integral.
This sort of thing gets complicated real fast. Although it is possible to do it all in a single inline equation, I would advise you to split it up into multiple nested functions, if only for readability.
The best example of why readability is important: you have a bracketing problem in the eqution you posted; there's not enough closing brackets, so I can't be entirely sure what the equation looks like in mathematical notation :)
Anyway, here's one way to do it with the version I --think-- you meant:
function test
% some random values for testing
Y0 = rand;
b = rand;
a = rand;
k0 = rand;
alpha = rand;
epsilon_t = rand;
% D is your B
D = -0.015;
% define SIMPLE anonymous function
Bb = #(ep) F(ep).*main_integral(ep) - D;
% aaaand...solve it!
sol = fsolve(Bb, 1)
% The anonymous function above is only simple, because of these:
% the main integral
function val = main_integral(epsilon)
% we need for loop through epsilon, due to how quad(gk) solves things
val = zeros(size(epsilon));
for ii = 1:numel(epsilon)
ep = epsilon(ii);
% NOTE how the sinint's all have a different function as argument:
val(ii) = quadgk(#(th)...
2*sinint(A(ep,th)) - sinint(B(ep,th)) - sinint(C(ep,th)), ...
0, pi);
end
end
% factor in front of integral
function f = F(epsilon)
f = alpha*Y0*sqrt(epsilon)./(pi*log(b/a)*sqrt(epsilon_t)); end
% first sinint argument
function val = A(epsilon, theta)
val = k0*sqrt(epsilon*(a^2+b^2-2*a*b*cos(theta))); end
% second sinint argument
function val = B(epsilon, theta)
val = 2*k0*sqrt(epsilon)*a*sin(theta/2); end
% third sinint argument
function val = C(epsilon, theta)
val = 2*k0*sqrt(epsilon)*b*sin(theta/2); end
end
The solution above will still be quite slow, but I think that's pretty normal for integrals this complicated.
I don't think implementing your own sinint will help much, as most of the speed loss is due to the for loops with non-builtin functions...If it's speed you want, I'd go for a MEX implementation with your own Gauss-Kronrod adaptive quadrature routine.