-
Notifications
You must be signed in to change notification settings - Fork 1
/
ODE_Solvers.rkt
75 lines (63 loc) · 3.07 KB
/
ODE_Solvers.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#lang racket
(module+ test (require rackunit))
(require "Matrix_List_Helpers.rkt")
(provide forward-euler-step
modified-euler
heun-step
stepper)
;;--Contains a variety of numerical solvers for Ordinary Differential Equations
;;--Note, these are for initial value problems
;;--Both single-step methods and a "stepper" function are included and provided
;;--Derivative Function is: [Number Number -> Number]
;; StepFunction Derivative Number [Listof Number] -> [Listof Number]
;; StepFunction is [Derivative Number Number Number -> Number]
;; Computes list of x's visited while traveling along list of t's
;; starting from initial, using single-step function
(module+ test
(check-equal? (stepper forward-euler-step (λ (t x) 0) 0 '(0 1)) '(0 0))
(check-equal? (stepper forward-euler-step (λ (t x) 3) 1 '(1 2 3)) '(1 4 7)))
(define (stepper single-step deriv x0 lot-all)
(local (;; Number [Listof Number] -> [Listof Number]
;; Uses current list of t's and previous x to make a list of x's
(define (stepper-r x-prev lot)
(cond
[(empty? (rest lot)) '()]
[else (local ((define new-x (single-step deriv
(first lot)
x-prev
(second lot))))
(cons new-x (stepper-r new-x (rest lot))))])))
(cons x0 (stepper-r x0 lot-all))))
;;-----------------------Single Step Functions----------------------------------
;; Derivative Number Number Number -> Number
;; Takes one step along derivative starting at t0,x0 to t1 returns x1
(module+ test
(check-equal? (forward-euler-step (λ (t x) 0) 0 0 1) 0)
(check-equal? (forward-euler-step (λ (t x) 3) 0 2 1) 5)
(check-equal? (forward-euler-step (λ (t x) -5) 1 -5 3) -15))
(define (forward-euler-step deriv t0 x0 t1)
(+ x0 (* (- t1 t0) (deriv t0 x0))))
;; Derivative Number Number Number -> Number
;; Takes half step, then uses that derivative value to get x1
(module+ test
(check-equal? (modified-euler (λ (t x) 0) 0 0 1) 0)
(check-equal? (modified-euler (λ (t x) 3) 0 2 1) 5)
(check-equal? (modified-euler (λ (t x) -5) 1 -5 3) -15))
(define (modified-euler deriv t0 x0 t1)
(local ((define mid-t (/ (+ t0 t1) 2))
(define half-step (forward-euler-step deriv t0 x0 mid-t))
(define new-deriv-val (deriv mid-t half-step)))
(+ x0 (* (- t1 t0) new-deriv-val))))
;; Derivative Number Number Number -> Number
;; Heun's Method, average derivative (using forward euler) at t0,x0 and t1
;; then use to calculate better x1
(module+ test
(check-equal? (heun-step (λ (t x) 0) 0 0 1) 0)
(check-equal? (heun-step (λ (t x) 3) 0 2 1) 5)
(check-equal? (heun-step (λ (t x) -5) 1 -5 3) -15))
(define (heun-step deriv t0 x0 t1)
(local ((define x1-try (forward-euler-step deriv t0 x0 t1))
(define deriv-start (deriv t0 x0))
(define deriv-end (deriv t1 x1-try))
(define better-deriv (/ (+ deriv-start deriv-end) 2)))
(+ x0 (* (- t1 t0) better-deriv))))