Troubleshooting Simple Harmonic Oscillator in MATLAB

Click For Summary

Discussion Overview

The discussion revolves around troubleshooting a MATLAB implementation of a simple harmonic oscillator. Participants explore numerical methods for solving differential equations, specifically focusing on the issues arising from the original code and the effectiveness of different numerical integration techniques.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant shares their MATLAB code for simulating a simple harmonic oscillator but reports nonsensical results.
  • Another participant suggests that the issue lies in the numerical approximation used, recommending more stable methods like Runge-Kutta (RK) for better accuracy.
  • A later reply provides various numerical methods and discusses the stability of different schemes, including Euler's method, which is noted for its instability.
  • One participant successfully implements the RK method and shares their updated code, noting a significant improvement in results.
  • Questions arise about the reasons for the RK method's superior performance and the limitations of the original approach, including concerns about execution time for larger simulations.
  • Some participants express uncertainty about the underlying reasons for the differences in performance between methods.
  • Another participant mentions that MATLAB has built-in ODE solvers that could provide faster solutions compared to manual implementations.

Areas of Agreement / Disagreement

Participants generally agree that the original implementation using Euler's method is unstable and that the RK method yields better results. However, there is no consensus on the specific reasons for the differences in performance or the limits of the RK method's effectiveness over longer periods.

Contextual Notes

Participants note that the execution time of the RK method is longer, which may affect the feasibility of testing larger time spans. There is also mention of MATLAB's performance issues related to dynamic array resizing during loops.

Who May Find This Useful

This discussion may be useful for individuals interested in numerical methods for solving differential equations, particularly in the context of physics simulations using MATLAB.

ShayanJ
Science Advisor
Insights Author
Messages
2,802
Reaction score
605
I'm trying to plot the evolution of a simple harmonic oscillator using MATLAB but I'm getting non-sense result and I have no idea what's wrong!
Here's my code:

Code:
clear
clc
x(1)=0;
v(1)=10;
h=.001;
k=100;
m=.1;
t=[0:h:10];
n=length(t);

for i=2:n

	F(i-1)=-k*x(i-1);
	v(i)=(h/m)*F(i-1)+v(i-1);
	x(i)=h*v(i-1)+x(i-1);

end

plot(t(1:n),x);
And this is what I get:
http://www.cvberry.com/octave/graphs/graph1395294146456.jpg

What's wrong?
Thanks
 
Last edited by a moderator:
Physics news on Phys.org
That's not very surprising.
You have discretized the differential equation.
You might solve the discretized version you got, and see that indeed its solution is what you found.

This means that you need to find a better numerical approximation.
One that is stable, or more stable.
This means an approximation that will be closer to the solution of the DE on a longer time span.

There is of course no approximation that will fit exactly the DE for any time.

There are many methods that improve your integration scheme.
One of the best known is the Runge-Kutta (RG) method.

In my personal toolbox methods are those two that I like to play (RG or other for serious work) with:

- "more precise stepping" (small improvement, less divergent)
v(i)=(h/m)*F(i-1)+v(i-1);
x(i)=F(i-1)/m*h²/2+v(i-1)*h+x(i-1);

- "implicit scheme" (decreasing amplitude)
by solving at each time step the linear system:
F(i)=-k*x(i);
v(i)=(h/m)*F(i)+v(i-1);
x(i)=h*v(i)+x(i-1);
(many variants are possible)

or (if I am not mistaken):

F(i) = -((m*(dt*k*v(i-1) + k*x(i-1)))/(dt**2*k + m))
v(i) = -((-(m*v(i-1)) + dt*k*x(i-1))/(dt**2*k + m))
x(i) = (m*(dt*v(i-1) + x(i-1)))/(dt**2*k + m)

- try RG: http://en.wikipedia.org/wiki/Runge–Kutta_methods

The stability of any numerical scheme can be analyzed.
You can also do numerical experiments, very easily with matlab.
You will see the benefit of renowned methods, like the RG.

- see also:
http://en.wikipedia.org/wiki/Numerical_methods_for_ordinary_differential_equations

- the DE can also be written as a 2x2 system of 1st order differential equations:

x' = v
v' = F/m = -k x / m

which can be put into matricial for:

transpose({x',v'}) = {{0,1},{-k/m,0}} transpose({x,v})

or: X' = M X where X = transpose({x',v'})

the solution of which is simply X = Exp(M t) Xo

Calculating Exp(M t) is almsot a standard of linear algebra,
and in the case where M is constant, you get an exact solution.
This is of course almost trivial here, as this would be equivalent to an analytical solution.
However, if M is not constant in time, then this integration scheme on a step by step basis is very efficient.
Also, Exp(M t) can also be calculated approximately, and a 1rst order Taylor gives you the method you already used.
Better approximations can for example be based on Padé approximants.At this stage, just try a Runge-Kutta method.
 
Last edited:
  • Like
Likes   Reactions: 1 person
I used RK and it worked,Thanks man!
Here's the new code:
Code:
clear
clc
x(1)=0;
v(1)=10;
h=.001;
k=10;
m=.1;
t=[0:h:10];
n=length(t);

for i=2:n-1

	k1=-((k*h)/m)*x(i-1);
	l1=h*v(i-1);
	k2=-((k*h)/m)*(x(i-1)+l1/2);
	l2=h*(v(i-1)+k1/2);
	k3=-((k*h)/m)*(x(i-1)+l2/2);
	l3=h*(v(i-1)+k3/2);
	k4=-((k*h)/m)*(x(i-1)+l3);
	l4=h*(v(i-1)+k3);
	
	x(i)=x(i-1)+(1/6)*(l1+2*l2+2*l3+l4);
	v(i)=v(i-1)+(1/6)*(k1+2*k2+2*k3+k4);

end

plot(t(1:n-1),x);
And the result:

http://www.cvberry.com/octave/graphs/graph1395303464048.jpg

I should confess I didn't think these methods are that much different!
 
Last edited by a moderator:
Click once on the "Thanks" button, just to increase my poor count a little bit.
Nice that you tried the RK!
But why does it work so better?
And on how many periods would it work so well?
150, 1500, 15000 ?
And why does the "simple" approach work so badly?
Any idea?
 
maajdl said:
Click once on the "Thanks" button, just to increase my poor count a little bit.
Nice that you tried the RK!
But why does it work so better?
And on how many periods would it work so well?
150, 1500, 15000 ?
And why does the "simple" approach work so badly?
Any idea?

I don't know why is that. I'm surprised too.
I plotted it till 500,it was OK.But this new code takes so much longer time to execute that I don't want to try larger values.
I'm just introduced to the numerical computation's world so I don't know enough to talk about it.
 
  • Like
Likes   Reactions: 1 person
To be honest, I don't know either.
 
The scheme you first use is called Euler's method. It is well known to be most often unstable: the inevitable numerical error that is made at each step grows exponentially, except for a small region of parameters.
 
Shyan said:
But this new code takes so much longer time to execute that I don't want to try larger values.
There is a built-in ODE solver in MATLAB that will be much faster. Look up for instance the help page for rk45.

Also, MATLAB is notoriously slow when loops are used, if you are not careful. In your code, for instance, the vectors x and v change size every step of the loop (they increase in length by one). It is best to first initialize them to the right length (n-1, in your case) by using, for instance,
Code:
x = zeros(n-1,1);
v = zeros(n-1,1);
v(1) = 10;
 
  • Like
Likes   Reactions: 1 person

Similar threads

  • · Replies 7 ·
Replies
7
Views
3K
  • · Replies 8 ·
Replies
8
Views
3K
  • · Replies 4 ·
Replies
4
Views
2K
  • · Replies 12 ·
Replies
12
Views
7K
  • · Replies 5 ·
Replies
5
Views
4K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 1 ·
Replies
1
Views
3K
  • · Replies 10 ·
Replies
10
Views
4K
  • · Replies 5 ·
Replies
5
Views
1K
  • · Replies 2 ·
Replies
2
Views
4K