I am trying to solve, using MATLAB, the time dependent Harmonic oscillator equation numerically. But I have no idea how to even get started as I have never learned this method in university:
X'' + w(t)^2 X = 0
with boundary conditions X_0 = 1, X_0' = 0 and Y_0 = 0, Y'_0 = 1
ode45 is a good start point.
Basic examples :
clear;close all;clc
tspan=[0 100]; % time
x_init=[5;0]; % known initial conditions
[t,y] = ode45(#vdp1,tspan,x_init);
figure(1)
plot(t,y(:,1),'r',t,y(:,2),'b')
grid on
title('Solution with ODE45');
xlabel('Time t');
ylabel('Solution y');
legend('y_1','y_2')
f=.5
[t,y] = ode45(#(t,y) vdp2(t,y,f),tspan,x_init);
figure(2)
plot(t,y(:,1),'r',t,y(:,2),'b')
grid on
title(['Solution with ODE45 and f = ' num2str(f)]);
xlabel('Time t');
ylabel('Solution y');
legend('y_1','y_2')
support functions:
function dydt = vdp1(t,y)
%
f=.1;
dydt = [y(2); sin(2*pi*f*t)*y(1)];
function dydt = vdp2(t,y,f)
%
dydt = [y(2); sin(2*pi*f*t)*y(1)];
This: https://uk.mathworks.com/matlabcentral/fileexchange/69951-runge-kutta-fixed-step-solvers?s_tid=srchtitle_harmonic%2520oscillator_81 among other examples has example1 solving damped and driven harmonic oscillators
And another harmonic oscillator solution with ODE solver:
https://uk.mathworks.com/matlabcentral/fileexchange/83233-matlab_program_solving_odes_harmonic_oscillators?s_tid=srchtitle_harmonic%20oscillator_9
You can also solve with symbolic expressions, this is Loren's post comparing symbolic and numerical solving
https://blogs.mathworks.com/loren/2010/04/08/odes-from-symbolic-to-numeric-code/?s_tid=srchtitle_harmonic%2520oscillator_105
I find the following concise introduction to ODE solving by Cleve Moler more useful than some full year university modules.
https://blogs.mathworks.com/cleve/2016/11/14/my-favorite-ode/?s_tid=srchtitle_harmonic%2520oscillator_131
When solving oscillators in polar coordinates you may need to have a look at
https://blogs.mathworks.com/cleve/2017/11/06/three-term-recurrence-relations-and-bessel-functions/?s_tid=srchtitle_harmonic%2520oscillator_140
In point 6 there's a wonderful introduction to Bessel functions and their zeros.
Related
I have two differential equations: da/dt=a(.3/a^3+.7)^1/2 and dτ/dt=1/a. The initial conditions are t=0; a=1 and τ=0, respectively. How can I solve the equations in Matlab? I need to calculate different values of a, t and τ also plot τ vs a. Thanks.
That's quite easy.
First write a function to implement your differential equation and save it with a filename corresponding to the function name:
function dy = my_ode(t,y)
dy(1) = y(1)*(0.3/y(1)^3 + 0.)^(1/2); % a
dy(2) = 1/dy(1); % tau
Then in MATLAB, call the ode45 solver with your function
[t,y] = ode45(#my_ode,[0 10],[1; 0]);
This is the result:
Let's suppose that we have the following solver for a system of first-order ODEs:
% func.m
function dydt = func(t,y)
dydt = [y(2); (1-y(1)^2)*y(2)-y(1)];
and the main code:
% solver.m
tspan=0:1:10;
[t,y] = ode45(#func,tspan,[2; 0]);
How to display in real-time the results, y1(t) and y2(t), for each time step t that the ode45 makes (t=0,1,2,...,10), without waiting for the whole code to finish?
The OutputFcn ode solver option should be used. For example, to plot the solution vs time, the built-in output function odeplot can be used:
options= odeset('OutputFcn',#odeplot);
[t,y] = ode45(#func,[0 200],[2; 0],options);
You can use your own output function. Here is an example:
myOutputFcn= #(t,y,flag)fprintf('t= %s y= %s\n',mat2str(t),mat2str(y))*0;
options= odeset('OutputFcn',myOutputFcn);
[t,y] = ode45(#f,0:1:10,[2; 0],options);
I have a question about the use of Matlab to compute solution of stochastic differentials equations. The equations are the 2.2a,b, page 3, in this paper (PDF).
My professor suggested using ode45 with a small time step, but the results do not match with those in the article. In particular the time series and the pdf. I also have a doubt about the definition of the white noise in the function.
Here the code for the integration function:
function dVdt = R_Lang( t,V )
global sigma lambda alpha
W1=sigma*randn(1,1);
W2=sigma*randn(1,1);
dVdt=[alpha*V(1)+lambda*V(1)^3+1/V(1)*0.5*sigma^2+W1;
sigma/V(1)*W2];
end
Main script:
clear variables
close all
global sigma lambda alpha
sigma=sqrt(2*0.0028);
alpha=3.81;
lambda=-5604;
tspan=[0,10];
options = odeset('RelTol',1E-6,'AbsTol',1E-6,'MaxStep',0.05);
A0=random('norm',0,0.5,[2,1]);
[t,L]=ode45(#(t,L) R_Lang(t,L),tspan,A0,options);
If you have any suggestions I'd be grateful.
Here the new code to confront my EM method and 'sde_euler'.
lambda = -5604;
sigma=sqrt(2*0.0028) ;
Rzero = 0.03; % problem parameters
phizero=-1;
dt=1e-5;
T = 0:dt:10;
N=length(T);
Xi1 = sigma*randn(1,N); % Gaussian Noise with variance=sigma^2
Xi2 = sigma*randn(1,N);
alpha=3.81;
Rem = zeros(1,N); % preallocate for efficiency
Rtemp = Rzero;
phiem = zeros(1,N); % preallocate for efficiency
phitemp = phizero;
for j = 1:N
Rtemp = Rtemp + dt*(alpha*Rtemp+lambda*Rtemp^3+sigma^2/(2*Rtemp)) + sigma*Xi1(j);
phitemp=phitemp+sigma/Rtemp*Xi2(j);
phiem(j)=phitemp;
Rem(j) = Rtemp;
end
f = #(t,V)[alpha*V(1)+lambda*V(1)^3+0.5*sigma^2/V(1)/2;
0]; % Drift function
g = #(t,V)[sigma;
sigma/V(1)]; % Diffusion function
A0 = [0.03;0]; % 2-by-1 initial condition
opts = sdeset('RandSeed',1,'SDEType','Ito'); % Set random seed, use Ito formulation
L = sde_euler(f,g,T,A0,opts);
plot(T,Rem,'r')
hold on
plot(T,L(:,1),'b')
Thanks again for the help !
ODEs and SDEs are very different and one should not use tools for ODEs, like ode45, to try to solve SDEs. Looking at the paper you linked to, they used a basic Euler-Maruyama scheme to integrate the system. This a very simple solver to implement yourself.
Before proceeding, you (and your professor!) should take some time to read up on SDEs and how to solve them numerically. I recommend this paper, which includes many Matlab examples:
Desmond J. Higham, 2001, An Algorithmic Introduction to Numerical Simulation of Stochastic Differential Equations, SIAM Rev. (Educ. Sect.), 43 525–46. http://dx.doi.org/10.1137/S0036144500378302
The URL to the Matlab files in the paper won't work; use this one. Note, that as this a 15-year old paper, some of the code related to random number generation is out of date (use rng(1) instead of randn('state',1) to seed the generator).
If you are familiar with ode45 you might look at my SDETools Matlab toolbox on GitHub. It was designed to be fast and has an interface that works very similarly to Matlab's ODE suite. Here is how you might code up your example using the Euler-Maruyma solver:
sigma = 1e-1*sqrt(2*0.0028);
lambda = -5604;
alpha = 3.81;
f = #(t,V)[alpha*V(1)+lambda*V(1)^3+0.5*sigma^2/V(1);
0]; % Drift function
g = #(t,V)[sigma;
sigma/V(1)]; % Diffusion function
dt = 1e-3; % Time step
t = 0:dt:10; % Time vector
A0 = [0.03;-2]; % 2-by-1 initial condition
opts = sdeset('RandSeed',1,'SDEType','Ito'); % Set random seed, use Ito formulation
L = sde_euler(f,g,t,A0,opts); % Integrate
figure;
subplot(211);
plot(t,L(:,2));
ylabel('\phi');
subplot(212);
plot(t,L(:,1));
ylabel('r');
xlabel('t');
I had to reduce the size of sigma or the noise was so large that it could cause the radius variable to go negative. I'm not sure if the paper discusses how they handle this singularity. You can try the 'NonNegative' option within sdeset to try to handle this or you may need to construct your own solver. I also couldn't find what integration time step the paper used. You should also consider contacting the authors of the paper directly.
UPDATE
Here's an Euler-Maruyama implementation that matches the sde_euler code above:
sigma = 1e-1*sqrt(2*0.0028);
lambda = -5604;
alpha = 3.81;
f = #(t,V)[alpha*V(1)+lambda*V(1)^3+0.5*sigma^2/V(1);
0]; % Drift function
g = #(t,V)[sigma;
sigma/V(1)]; % Diffusion function
dt = 1e-3; % Time step
t = 0:dt:10; % Time vector
A0 = [0.03;-2]; % 2-by-1 initial condition
% Create and initialize state vector (L here is transposed relative to sde_euler output)
lt = length(t);
n = length(A0);
L = zeros(n,lt);
L(:,1) = A0;
% Set seed and pre-calculate Wiener increments with order matching sde_euler
rng(1);
r = sqrt(dt)*randn(lt-1,n).';
% General Euler-Maruyama integration loop
for i = 1:lt-1
L(:,i+1) = L(:,i)+f(t(i),L(:,i))*dt+r(:,i).*g(t(i),L(:,i));
end
figure;
subplot(211);
plot(t,L(2,:));
ylabel('\phi');
subplot(212);
plot(t,L(1,:));
ylabel('r');
xlabel('t');
I've got two second order non-linear differential equations which I need to solve in order to model and plot the motion of a mass hanging on a spring which is swinging like a pendulum. They are here:
I'm using odeToVectorField to rewrite them as first order linear ODEs, then I call ode45 to solve the resulting system of equations. But when I plot the results, it gives me strange answers, like negative radius, etc.
Can anyone help me find where I've messed up my code? Thanks a lot!
My code is as follows:
global m R g B k %declare global variables to use them everywhere
m=1.0; %mass of ball [kg]
k=200; % stiffness of the spring [N/m]
R=0.5; % unstretched length of the spring [m]
g=9.81; % acceleration due to the gravity [m/s^2]
B=0; % coefficient of air drag [kg/m]
syms r(t) f(t)
[V] = odeToVectorField(diff(r,2)== r*((diff(f,1))^2) + (g*cos(f))-(k*(r-R))-B*diff(r,1)*sqrt(diff(r,1)^2 +r^2*diff(f,1)^2),...
diff(f,2)== ((g*sin(f)+2*diff(r,1)*diff(f,1))/-r)-B*diff(f,1)*sqrt(diff(r,1)^2 +r^2*diff(f,1)^2));
F = matlabFunction(V,'vars',{'t','Y'});
%define initial conditions:
theta_0=(70*pi/180);
theta_dot_0=0;
r_0= R + (m*g*cos(theta_0))/k ;
r_dot_0=0;
t_start=0; %start time
t_step=.01; % time step
t_final=5; % final time
%Solve that system of ODEs from [V]
[t , X]=ode45(F, t_start:t_step:t_final , [r_0;r_dot_0;theta_0;theta_dot_0]);
figure(1)
subplot(2,1,1)
plot(t,X(:,1),'LineWidth',2)
xlabel('t');ylabel('r','fontsize',12);
hold on
subplot(2,1,2)
plot(t,X(:,2),'LineWidth',2)
xlabel('t');ylabel('r dot','fontsize',12);
hold on
figure(2)
subplot(2,1,1)
plot(t,X(:,3),'LineWidth',2)
xlabel('t');ylabel('theta [rad]','fontsize',12);
hold on
subplot(2,1,2)
plot(t,X(:,4),'LineWidth',2)
xlabel('t');ylabel('theta dot [rad/s]','fontsize',12);
hold on
Dx=y
Dy=-k*y-x^3+9.8*cos(t)
inits=('x(0)=0,y(0)=0')
these are the differential equations that I wanted to plot.
first, I tried to solve the differential equation and then plot the graph.
Dsolve('Dx=y','Dy=-k*y-x^3+9.8*cos(t)', inits)
like this, however, there was no explicit solution for this system.
now i am stuck :(
how can you plot this system without solving the equations?
First define the differential equation you want to solve. It needs to be a function that takes two arguments - the current time t and the current position x, and return a column vector. Instead of x and y, we'll use x(1) and x(2).
k = 1;
f = #(t,x) [x(2); -k * x(2) - x(1)^3 + 9.8 * cos(t)];
Define the timespan you want to solve over, and the initial condition:
tspan = [0, 10];
xinit = [0, 0];
Now solve the equation numerically using ode45:
ode45(f, tspan, xinit)
which results in this plot:
If you want to get the values of the solution at points in time, then just ask for some output arguments:
[t, y] = ode45(f, tspan, xinit);
You can plot the phase portrait x against y by doing
plot(y(:,1), y(:,2)), xlabel('x'), ylabel('y'), grid
which results in the following plot