How to resolve the algorithm Runge-Kutta method step by step in the Haskell programming language

Published on 7 June 2024 03:52 AM

How to resolve the algorithm Runge-Kutta method step by step in the Haskell programming language

Table of Contents

Problem Statement

Given the example Differential equation: With initial condition: This equation has an exact solution:

Demonstrate the commonly used explicit   fourth-order Runge–Kutta method   to solve the above differential equation.

Starting with a given

y

n

{\displaystyle y_{n}}

and

t

n

{\displaystyle t_{n}}

calculate: then:

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Runge-Kutta method step by step in the Haskell programming language

Explanation of the First Code:

This code solves an initial value problem using the fourth-order Runge-Kutta method. It calculates the solution of the differential equation y' = sqrt(y) with initial condition y(0) = 1.

  • dv: Computes the derivative of the function y, which is sqrt(y).
  • fy: Defines the function f(x) = 1/16 * (4 + x^2)^2.
  • rk4: Implements the fourth-order Runge-Kutta method to numerically solve the initial value problem.
  • task: Runs the rk4 method for various values of x in steps of 0.1, prints the results, and compares them to the actual solution.

Explanation of the Second Code:

This code also solves the same initial value problem, but it uses a more streamlined implementation.

  • rk4: Implements the fourth-order Runge-Kutta method in a concise manner.
  • actual: Defines the exact solution of the differential equation.
  • step: Defines the step size for the numerical integration.
  • ixs: Generates a list of x values from 0 to 10 with the step size.
  • xys: Computes the numerical solution y for each x value.
  • samples: Extracts data points from the numerical solution at intervals of 10 * step.
  • main: Prints the numerical solution along with the error.

Key Concepts:

  • Initial Value Problem: A mathematical problem where a differential equation is given along with an initial condition.
  • Runge-Kutta Method: A family of numerical methods used to solve initial value problems.
  • Numerical Integration: Approximating the solution of a continuous function by evaluating it at discrete intervals.
  • Error Analysis: Comparing the numerical solution to the exact solution to assess the accuracy of the integration method.

Source code in the haskell programming language

dv
  :: Floating a
  => a -> a -> a
dv = (. sqrt) . (*)

fy t = 1 / 16 * (4 + t ^ 2) ^ 2

rk4
  :: (Enum a, Fractional a)
  => (a -> a -> a) -> a -> a -> a -> [(a, a)]
rk4 fd y0 a h = zip ts $ scanl (flip fc) y0 ts
  where
    ts = [a,h ..]
    fc t y =
      sum . (y :) . zipWith (*) [1 / 6, 1 / 3, 1 / 3, 1 / 6] $
      scanl
        (\k f -> h * fd (t + f * h) (y + f * k))
        (h * fd t y)
        [1 / 2, 1 / 2, 1]

task =
  mapM_
    (print . (\(x, y) -> (truncate x, y, fy x - y)))
    (filter (\(x, _) -> 0 == mod (truncate $ 10 * x) 10) $
     take 101 $ rk4 dv 1.0 0 0.1)


*Main> task
(0,1.0,0.0)
(1,1.5624998542781088,1.4572189122041834e-7)
(2,3.9999990805208006,9.194792029987298e-7)
(3,10.562497090437557,2.909562461184123e-6)
(4,24.999993765090654,6.234909399438493e-6)
(5,52.56248918030265,1.0819697635611192e-5)
(6,99.99998340540378,1.6594596999652822e-5)
(7,175.56247648227165,2.3517730085131916e-5)
(8,288.99996843479926,3.1565204153594095e-5)
(9,451.562459276841,4.0723166534917254e-5)
(10,675.9999490167125,5.098330132113915e-5)


rk4 :: Double -> Double -> Double -> Double
rk4 y x dx =
  let f x y = x * sqrt y
      k1 = dx * f x y
      k2 = dx * f (x + dx / 2.0) (y + k1 / 2.0)
      k3 = dx * f (x + dx / 2.0) (y + k2 / 2.0)
      k4 = dx * f (x + dx) (y + k3)
  in y + (k1 + 2.0 * k2 + 2.0 * k3 + k4) / 6.0
  
actual :: Double -> Double
actual x = (1 / 16) * (x * x + 4) * (x * x + 4)
 
step :: Double
step = 0.1
 
ixs :: [Int]
ixs = [0 .. 100]
 
xys :: [(Double, Double)]
xys =
  scanl
    (\(x, y) _ -> (((x * 10) + (step * 10)) / 10, rk4 y x step))
    (0.0, 1.0)
    ixs
 
samples :: [(Double, Double, Double)]
samples =
  zip ixs xys >>=
  (\(i, (x, y)) ->
      [ (x, y, actual x - y)
      | 0 == mod i 10 ])
 
main :: IO ()
main =
  (putStrLn . unlines) $
  (\(x, y, v) ->
      unwords
        [ "y" ++ justifyRight 3 ' ' ('(' : show (round x)) ++ ") = "
        , justifyLeft 19 ' ' (show y)
        , '±' : show v
        ]) <$>
  samples
  where
    justifyLeft n c s = take n (s ++ replicate n c)
    justifyRight n c s = drop (length s) (replicate n c ++ s)


  

You may also check:How to resolve the algorithm Discordian date step by step in the Julia programming language
You may also check:How to resolve the algorithm LZW compression step by step in the Seed7 programming language
You may also check:How to resolve the algorithm Wilson primes of order n step by step in the Java programming language
You may also check:How to resolve the algorithm Exponentiation operator step by step in the jq programming language
You may also check:How to resolve the algorithm Add a variable to a class instance at runtime step by step in the Smalltalk programming language