Solving ODE with unknown limits - matlab

I'm trying to solve a system of ordinary differential equations from y_1 to y_2, say
G' = D
D' = f(y,G,D)
with the initial conditions
G(y_1) = 0
D(y_1) = 0
My problem is that I do not know y_1 and y_2, to counter for this I of course need two additional equations which is
F_1(y_1,y_2,G(y_2)) = 0
F_2(y_1,y_2,G(y_2)) = 0
So far I have tried to implement it using fsolve (i guess the new name is fzero) to find the zeros, then from the functions F_1 and F_2 i call the ode45 to solve from y_1 to y_2 in order to calculate the functions. However it does not work and I can not seem to find any mistakes. Therefore i looked for new methods/ideas and I found the method bvp4c, but I'm not sure whether i can use it in my case. Does anyone have experience with bvp4c and know whether and how I should use it, or do you have other ideas?
Any help is appreciated.
Code for reference:
function [Fval,sol,t,G] = EntrepreneurialFinanceNondiversifiableRisk
global sigma rf tau b epsilon gamma theta1 theta2 alpha ya K I taug mu eta...
omega
sigma=0.2236; rf=0.03; tau=0.1129; b=0.85; epsilon=0.2; gamma=2;
theta1 = -0.704; alpha = 0.6; theta2=1.704; ya=0.1438; K=27; I = 10;
taug = 0.1; mu = 0.04; eta = 0.4; omega = 0.1;
tau = 0;
option = optimset('Display','iter');
sol = fsolve(#f,[0.1483,2.8],option);
Fval = f(sol);
[t,G] = solvediff(sol(1),sol(2));
function F = f(x)
yd = x(1);
yu = x(2);
global rf tau b theta1 alpha theta2 K I taug
Vstar =# (y) (1-tau+tau*(1-theta1-(1-alpha)*(1-tau)* theta1/tau)^...
(1/theta1))*y/rf;
VstarPrime = (1-tau+tau*(1-theta1-(1-alpha)*(1-tau)...
*theta1/tau)^(1/theta1))*1/rf;
qbar =#(yd,yu) (yd^theta1-yd^theta2)/(yu^theta2*yd^theta1-yu^theta1*...
yd^theta2);
qunderbar =# (yd,yu) (yu^theta2-yu^theta1)/(yu^theta2*yd^theta1-...
yu^theta1*yd^theta2);
A =# (y) (1-tau)*(y/rf);
V = #(y,yd) A(y) + (tau * b)/rf * (1 - (y/yd)^(theta2)) - (1-alpha)*A(yd)*...
(y/yd)^(theta2);
F0 =# (yd,yu) b/rf-(b/rf-alpha*A(yd))*qunderbar(yd,yu)/(1-qbar(yd,yu));
[t,G] = solvediff(yd,yu);
F = zeros(2,1);
F(1) = Vstar(yu)-F0(yd,yu)-K-taug*(Vstar(yu)-K-I)-G(end,2);
F(2) = (1-taug)*VstarPrime-G(end,2);
function [t,G] = solvediff(yd,yu)
[t,G] = ode45(#diff,[yd,yu],[0,0]);

Assuming the domain of definition is big enough and you have good initial values, a Newton implementation with divided differences for the construction of the Jacobian looks like this:
h=1e-5
for k=1:10 do
Fval = F(yd, yu)
dFdyd = (F(yd+h, yu)-F(yd-h, yu))/(2*h)
dFdyu = (F(yd, yu+h)-F(yd, yu-h))/(2*h)
dF = [ dFdyd dFdyu ]
ynext = [ yd; yu ] - dF^(-1)*Fval;
yd = ynext(1); yu = ynext(2);
end

Related

Find roots using fsolve

Basically I would like to use the fsolve command in order to find the roots of an equation.
I think I should create a function handle that evaluates this equation in the form "right hand side - left hand side =0", but I've been struggling to make this work. Does anyone know how to do this?
The equation itself is 1/sqrt(f) = -1.74log((1.254/((1.27310^8)sqrt(f)))+((110^-3)/3.708)). So I would like to find the point of intersection of the left and right side by solving for 1/sqrt(f)+(1.74log((1.254/((1.27310^8)sqrt(f)))+((110^-3)/3.708))) = 0 using fsolve.
Thanks a lot!
The code so far (not working at all)
f = #(x) friction(x,rho,mu,e,D,Q, tol, maxIter) ;
xguess = [0, 1];
sol = fsolve(x, xguess ) ;
function y = friction(x,rho,mu,e,D,Q, tol, maxIter)
D = 0.1;
L = 100
rho = 1000;
mu = 0.001;
e = 0.0001;
Q = 0.01;
U = (4*Q)/(pi*D^2);
Re = (rho*U*D)/mu ;
y = (1/sqrt(x))-(-1.74*log((1.254/(Re*sqrt(x)))+((e/D)/3.708)))
end
Error message:
Error using lsqfcnchk (line 80)
FUN must be a function, a valid character vector expression, or an inline function object.
Error in fsolve (line 238)
funfcn = lsqfcnchk(FUN,'fsolve',length(varargin),funValCheck,gradflag);
Error in Untitled (line 6)
sol = fsolve(x, xguess ) ;
opt = optimset('Display', 'Iter');
sol = fsolve(#(x) friction(x), 1, opt);
function y = friction(x)
D = 0.1;
L = 100; % note -- unused
rho = 1000;
mu = 0.001;
e = 0.0001;
Q = 0.01;
U = (4*Q)/(pi*D^2);
Re = (rho*U*D)/mu ;
y = (1/sqrt(x))-(-1.74*log((1.254/(Re*sqrt(x)))+((e/D)/3.708)));
end
sol = 0.0054
the first argument of fsolve should be the function not variable. Replace:
sol = fsolve(x, xguess );
with
sol = fsolve(f, xguess );
And define Rho, mu, e etc before you define f (not inside the friction function).

How to solve a system of three first-order ODEs in Matlab

I am using Matlab to try and solve a system of three first-order ODEs, but the error message I get is 'syms' requires Symbolic Math Toolbox.
Error in spiders (line 1)
syms f(t) s(t) v(t) r W c h q a k b H K e
On a previous occasion, I received an error saying that this system of ODEs cannot be solved explicitly (i.e. in closed form). I think that numerical integration is the only way. The r,W,c,h, etc are parameters. Could someone please tell me how I can simulate/solve and plot the ODEs below?
syms f(t) s(t) v(t) r W c h q a k b H K e
r = 1;
W = 0.5;
c = 0.4;
h = 0.9;
q = 9;
a = 5;
k = 0.8;
b = 6;
H = 3;
K = 1.3;
e = 2;
ode1 = diff(f) == r*f*(1 - f/W) - c*s*f - h*(1 - q)*f;
ode2 = diff(s) == s*(-a + k*b*v/(H + v) + k*c*f) - h*K*q*s;
ode3 = diff(v) == v*(e - b*s/(H + v)) - h*q*v;
odes=[ode1;ode2;ode3]
S = dsolve(odes)
plot(S);
Looks like you where previously using a different MATLAB license, which included the Symbolic Math Toolbox. I assume you no longer have it available and you are now looking for numeric alternatives.
You have to define functions for the equations you are trying to solve. Then you can call one of the ode solvers. An example from the documentation:
y0 = [1; 0; 0];
tspan = [0 4*logspace(-6,6)];
M = [1 0 0; 0 1 0; 0 0 0];
options = odeset('Mass',M,'RelTol',1e-4,'AbsTol',[1e-6 1e-10 1e-6]);
[t,y] = ode15s(#robertsdae,tspan,y0,options);
Where robertsdae is the equation to solve. The full example including further explanations is available here.

Using the Runge-Kutta integration method in a system

h=0.005;
x = 0:h:40;
y = zeros(1,length(x));
y(1) = 0;
F_xy = ;
for i=1:(length(x)-1)
k_1 = F_xy(x(i),y(i));
k_2 = F_xy(x(i)+0.5*h,y(i)+0.5*h*k_1);
k_3 = F_xy((x(i)+0.5*h),(y(i)+0.5*h*k_2));
k_4 = F_xy((x(i)+h),(y(i)+k_3*h));
y(i+1) = y(i) + (1/6)*(k_1+2*k_2+2*k_3+k_4)*h;
end
I have the following code, I think it's right. I know there's parts missing on the F_xy because this is my follow up question.
I have dx/dt = = −x(2 − y) with t_0 = 0, x(t_0) = 1
and dy/dt = y(1 − 2x) with t_0 = 0, y(t_0) = 2.
My question is that I don't know how to get these equations in to the code. All help appreciated
You are using both t and x as independent variable in an inconsistent manner. Going from the actual differential equations, the independent variable is t, while the dependent variables of the 2-dimensional system are x and y. They can be combined into a state vector u=[x,y] Then one way to encode the system close to what you wrote is
h=0.005;
t = 0:h:40;
u0 = [1, 2]
u = [ u0 ]
function udot = F(t,u)
x = u(1); y = u(2);
udot = [ -x*(2 - y), y*(1 - 2*x) ]
end
for i=1:(length(t)-1)
k_1 = F(t(i) , u(i,:) );
k_2 = F(t(i)+0.5*h, u(i,:)+0.5*h*k_1);
k_3 = F(t(i)+0.5*h, u(i,:)+0.5*h*k_2);
k_4 = F(t(i)+ h, u(i,:)+ h*k_3);
u(i+1,:) = u(i,:) + (h/6)*(k_1+2*k_2+2*k_3+k_4);
end
with a solution output
Is F_xy your derivative function?
If so, simply write it as a helper function or function handle. For example,
F_xy=#(x,y)[-x*(2-y);y*(1-2*x)];
Also note that your k_1, k_2, k_3, k_4, y(i) are all two-dimensional. You need to re-size your y and rewrite the indices in your iterating steps accordingly.

Solving System of Second Order Ordinary Differential Equation in Matlab

Introduction
I am using Matlab to simulate some dynamic systems through numerically solving systems of Second Order Ordinary Differential Equations using ODE45. I found a great tutorial from Mathworks (link for tutorial at end) on how to do this.
In the tutorial the system of equations is explicit in x and y as shown below:
x''=-D(y) * x' * sqrt(x'^2 + y'^2)
y''=-D(y) * y' * sqrt(x'^2 + y'^2) + g(y)
Both equations above have form y'' = f(x, x', y, y')
Question
However, I am coming across systems of equations where the variables can not be solved for explicitly as shown in the example. For example one of the systems has the following set of 3 second order ordinary differential equations:
y double prime equation
y'' - .5*L*(x''*sin(x) + x'^2*cos(x) + (k/m)*y - g = 0
x double prime equation
.33*L^2*x'' - .5*L*y''sin(x) - .33*L^2*C*cos(x) + .5*g*L*sin(x) = 0
A single prime is first derivative
A double prime is second derivative
L, g, m, k, and C are given parameters.
How can Matlab be used to numerically solve a set of second order ordinary differential equations where second order can not be explicitly solved for?
Thanks!
Your second system has the form
a11*x'' + a12*y'' = f1(x,y,x',y')
a21*x'' + a22*y'' = f2(x,y,x',y')
which you can solve as a linear system
[x'', y''] = A\f
or in this case explicitly using Cramer's rule
x'' = ( a22*f1 - a12*f2 ) / (a11*a22 - a12*a21)
y'' accordingly.
I would strongly recommend leaving the intermediate variables in the code to reduce chances for typing errors and avoid multiple computation of the same expressions.
Code could look like this (untested)
function dz = odefunc(t,z)
x=z(1); dx=z(2); y=z(3); dy=z(4);
A = [ [-.5*L*sin(x), 1] ; [.33*L^2, -0.5*L*sin(x)] ]
b = [ [dx^2*cos(x) + (k/m)*y-g]; [-.33*L^2*C*cos(x) + .5*g*L*sin(x)] ]
d2 = A\b
dz = [ dx, d2(1), dy, d2(2) ]
end
Yes your method is correct!
I post the following code below:
%Rotating Pendulum Sym Main
clc
clear all;
%Define parameters
global M K L g C;
M = 1;
K = 25.6;
L = 1;
C = 1;
g = 9.8;
% define initial values for theta, thetad, del, deld
e_0 = 1;
ed_0 = 0;
theta_0 = 0;
thetad_0 = .5;
initialValues = [e_0, ed_0, theta_0, thetad_0];
% Set a timespan
t_initial = 0;
t_final = 36;
dt = .01;
N = (t_final - t_initial)/dt;
timeSpan = linspace(t_final, t_initial, N);
% Run ode45 to get z (theta, thetad, del, deld)
[t, z] = ode45(#RotSpngHndl, timeSpan, initialValues);
%initialize variables
e = zeros(N,1);
ed = zeros(N,1);
theta = zeros(N,1);
thetad = zeros(N,1);
T = zeros(N,1);
V = zeros(N,1);
x = zeros(N,1);
y = zeros(N,1);
for i = 1:N
e(i) = z(i, 1);
ed(i) = z(i, 2);
theta(i) = z(i, 3);
thetad(i) = z(i, 4);
T(i) = .5*M*(ed(i)^2 + (1/3)*L^2*C*sin(theta(i)) + (1/3)*L^2*thetad(i)^2 - L*ed(i)*thetad(i)*sin(theta(i)));
V(i) = -M*g*(e(i) + .5*L*cos(theta(i)));
E(i) = T(i) + V(i);
end
figure(1)
plot(t, T,'r');
hold on;
plot(t, V,'b');
plot(t,E,'y');
title('Energy');
xlabel('time(sec)');
legend('Kinetic Energy', 'Potential Energy', 'Total Energy');
Here is function handle file for ode45:
function dz = RotSpngHndl(~, z)
% Define Global Parameters
global M K L g C
A = [1, -.5*L*sin(z(3));
-.5*L*sin(z(3)), (1/3)*L^2];
b = [.5*L*z(4)^2*cos(z(3)) - (K/M)*z(1) + g;
(1/3)*L^2*C*cos(z(3)) + .5*g*L*sin(z(3))];
X = A\b;
% return column vector [ed; edd; ed; edd]
dz = [z(2);
X(1);
z(4);
X(2)];

Matlab filter simulation error

I made a Wiener filter simulation in matlab but it seem that I made a mistake in the code as the result is incorrect. I would be grateful if somebody glanced at the code and pointed out the error.
Here is the code:
k = 1:100;
sigma = 0.1;
s1 = randn(1,100);
n1 = randn(1,100) * sigma;
Pnum = [1 0.1];
Pdenum = [1 0.9];
Gnum = [1 0.9];
Gdenum = [1 0.1];
n = filter(Pnum, Pdenum, n1);
s = filter(Gnum, Gdenum, s1);
x = n + s;
rxx = xcorr(x);
rxs = xcorr(x,s);
toeplitz_rxx = toeplitz(rxx);
wopt = inv(toeplitz_rxx) * rxs;
wopt = inv(toeplitz_rxx) * transpose(rxs);
s_hat = filter(wopt,1,x);
error = x - s_hat; %this is where the wrong result is being calculated
plot(k,error, 'r',k,s_hat, 'b', k, x, 'g');
The problem is that the error calculated is exactly a mirror image of the s_hat.
Surely this cant be right.
Thanks in advance.
No problem.
I have perfectly a void idea of what you are trying to do. But if what you are trying to do is to get some signal to noise ratio, and trying to mimic those effects through some linear 1st order systems, you should correct your P and G polynomials, which are totally wrong, if that is the case. Type help filter and see the A and B definitions.
This is the correct code:
k = 1:100;
sigma = 0.1;
s1 = randn(1,100);
n1 = randn(1,100) * sigma;
Pnum = [0 0.1];
Pdenum = [1 -0.9];
Gnum = [0 0.9];
Gdenum = [1 -0.1];
n = filter(Pnum, Pdenum, n1);
s = filter(Gnum, Gdenum, s1);
x = n + s;
rxx = xcorr(x);
rxs = xcorr(x,s);
toeplitz_rxx = toeplitz(rxx);
wopt = inv(toeplitz_rxx) * transpose(rxs);
s_hat = filter(wopt,1,x);
error = x - s_hat; %this is where the wrong result is being calculated
plot(k,error, 'r',k,s_hat, 'b', k, x, 'g');
There are still an ill-conditioning on the toeplitz. I leave it that way, for you still have fun for dealing with. This is easy to solve too.
THe guys are true. StackOverflow is NOT for solve your homework, but for helping you in finding the light.