3

I'm trying to implement a really simple 4th order Runge-Kutta Method, for solving the ODE y'=f(x,y).

I've implemented the algorithm in both R and MATLAB (see below), but for some reason it takes a few minutes to run in MATLAB and a few milliseconds to run in R.

My question is WHY?

It appears that the only difference is the initialization, and playing around with that doesn't seem to make a difference.


R Script:

# Initialise Variables ----------------------------------------------------

L  = 1 #Domain of solution function
h  = 0.01#step size
x0 = 0
y0 = 0
x  = x0
y  = y0

# Define Forcing Function -------------------------------------------------

force = function(x,y){
  -16*y + 15*exp(-x)
}


# Compute Algorithm -------------------------------------------------------

for(i in 0:(L/h)){

  k1 = h*force(x,y[i])
  k2 = h*force(x + h/2, y[i] + k1 /2)
  k3 = h*force(x + h/2, y[i] + k2 /2)
  k4 = h*force(x + h  , y[i] + k3   )

  temp=y[i] + (1/6)*(k1 + 2*k2 + 2*k3 + k4)

  y = c(y,temp)
  x = x + h
  i = i+1  
}

t <- seq(from=0, to=L, by=h)
plot(t,y,type="l")

MATLAB Script:

%% Initialise Variables
y0 = 0;
x0 = 0;
L  = 1; %Length of Domain of function (here y)
N  = 100; %Number of steps to break the domain into
h  = L/N; %Step Size

yi = y0; %intermediate value of y
xi = x0; %intermediate value of x to be ticked in algo

y = zeros(N,1); %store y values as components
x = 0:h:L; %just for plot later

%% Define Forcing Function
syms f(A,B)
f(A,B) = 15*exp(-A) - 16*B;

%% Execute Algorithm
for n = 1:1:N;
    xi= h*(n-1);

    k1= h*f(xi,yi);    
    k2= h*f(xi + h/2 , yi + k1/2);
    k3= h*f(xi + h/2 , yi + k2/2);
    k4= h*f(xi + h   , yi + k3  );

    yi= yi + (1/6)*(k1 + 2*k2 + 2*k3 + k4);
    y(n,1)=yi;
end

%plot(x,y)
Dev-iL
  • 23,742
  • 7
  • 57
  • 99
Hafez
  • 33
  • 2

1 Answers1

9

The reason you have this problem is because you're using symbolic variables to do a computation that should be purely numerical.

If you define f as follows:

f = @(A,B)15*exp(-A) - 16*B;

The loop finishes almost instantly. Few more notes:

  • The syntax above is used to define a function handle to an anonymous function.
  • The resulting x and y vectors have a different length, so you wouldn't be able to plot them afterwards.
  • In the future you should profile your code to find performance bottlenecks.

P.S.
The MATLAB equivalent of the function definition you had in R would be quite similar:

function out = force(x)
  out = 15*exp( -x(1) ) - 16*x(2);
end

or

function out = force(x,y)
  out = 15*exp(-x) - 16*y;
end

... depending on whether the input comes as a vector or not.

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
  • Thank you very much, really appreciate your answer and your corrections to my question formatting. This was my first question on the site so yeah was just kind of winging it. – Hafez Aug 08 '18 at 15:15
  • You're welcome! I didn't see it immediately, I just ran the code. I'd advise you to use [`linspace(start, stop, nPoints)`](https://www.mathworks.com/help/matlab/ref/linspace.html) to avoid such problems. – Dev-iL Aug 08 '18 at 15:18
  • Cheers my man :) Forgot about linspace aha. I'm picking up my coding properly now after having kind of neglected it over the first two years of uni physics – Hafez Aug 08 '18 at 15:50