Search code examples
pythonrodedifferential-equations

How do I solve a second order differential equation in R?


I am learning R to solve a second order differential equation(probably using deSolve package). Which I have written in python by writing it as two first order differential equations and is given below

import  numpy  as np
import  matplotlib.pyplot  as plt
from  scipy.integrate  import  odeint

def  fun(X, t):
    y , dy , z = X
    M = np.sqrt (1./3. * (1/2. * dy **2 + 1./2.  * y **2))
    dz = (M*z) # dz/dt
    ddy =  -3.* M * dy -  y # ddy/dt

    return [dy ,ddy ,dz]

y0 = 1

dy0 =  -0.1

z0 = 1.

X0 = [y0, dy0, z0]

M0 = np.sqrt (1./3. * (1./2. *  dy0 **2. + 1./2.*  y0 **2)) 

t = np.linspace(0., 100., 10001.) # time spacing

sol = odeint(fun, X0, t)

y = sol[:, 0]

dy = sol[:, 1]

z = sol[:, 2]

M = np.sqrt (1./3. * (1./2. *  dy**2. + 1./2.*  y **2)) 

#Graph plotting
plt.figure()
plt.plot(t, y)
plt.plot(t, z)
plt.plot(t, M)
plt.grid()
plt.show()

Python solve this problem easily, however for another similar but complicated problem python shows error. I have also tried ode(vode/bdf) in python but the problem is still there. Now, I would like to check how R work with the problem. So, I will be much obliged if someone please provide me an example(basically a code translation!) of how to solve this problem in R so that I can try the other one in R and also learn some R(I know that this may not be the ideal way to learn a language).

I understand that this question may have little constructive value, but I am just a novice in R, so please bear with me!


Solution

  • This should be a translation of the Python code to R

    library(deSolve)
    
    deriv <- function(t, state, parameters){
      with(as.list(c(state, parameters)),{
    
        M <- sqrt(1/3 * (1/2 * dy^2 + 1/2 * y^2))
        dz <- M*z # dz/dt
        ddy <-  -3* M * dy -  y # ddy/dt
    
        list(c(dy, ddy, dz))
    
      })
    }
    
    state <- c(y = 1,
               dy = -0.1,
               z = 1)
    
    times <- seq(0, 100, length.out = 10001)
    
    sol <- ode(func = deriv, y = state, times = times, parms = NULL)
    
    y <- sol[, "y"]
    
    dy <- sol[, "dy"]
    
    z <- sol[, "z"]
    
    M <- sqrt(1/3 * (1/2 *  dy^2 + 1/2*  y^2)) 
    
    plot(times, z, col = "red", ylim = c(-1, 18), type = "l")
    lines(times, y, col = "blue")
    lines(times, M, col = "green")
    grid()
    

    There is a faster way to directly calculate M in R with this code:

    library(deSolve)
    
    deriv <- function(t, state, parameters){
      with(as.list(c(state, parameters)),{
    
        M <- sqrt(1/3 * (1/2 * dy^2 + 1/2 * y^2))
        dz <- M*z # dz/dt
        ddy <-  -3* M * dy -  y # ddy/dt
    
        list(c(dy, ddy, dz), M = M)
    
      })
    }
    
    state <- c(y = 1,
               dy = -0.1,
           z = 1)
    
    times <- seq(0, 100, length.out = 10001)
    
    sol <- ode(func = deriv, y = state, times = times, parms = NULL)
    
    ## save to file
    
    write.csv2(sol,file = "path_to_folder/R_ODE.csv")
    
    ## plot
    
    matplot(sol[,"time"], sol[,c("y", "z", "M")], type = "l")
    grid()
    

    enter image description here