1
+ module solver_new
2
+ use tri_body_prob
3
+ implicit none
4
+ real * 16 , parameter :: min_adj_dt = 1.Q-9
5
+ real * 16 , parameter , dimension (6 ) :: rkf_tki = &
6
+ [0.q0 , 1.q0 / 4.q0 , 3.q0 / 8.q0 , 12.q0 / 13.q0 , 1.q0 , 1.q0 / 2.q0 ]
7
+ real * 16 , parameter , dimension (6 , 6 ) :: rkf_yki = transpose ( reshape ( [&
8
+ 0.q0 , 0.q0 , 0.q0 , 0.q0 , 0.q0 , 0.q0 , &
9
+ 1.q0 / 4.q0 , 0.q0 , 0.q0 , 0.q0 , 0.q0 , 0.q0 , &
10
+ 3.q0 / 32.q0 , 9.q0 / 32.q0 , 0.q0 , 0.q0 , 0.q0 , 0.q0 , &
11
+ 1932.q0 / 2197.q0 , - 7200.q0 / 2197.q0 , 7296.q0 / 2197.q0 , 0.q0 , 0.q0 , 0.q0 , &
12
+ 439.q0 / 216.q0 , - 8.q0 , 3680.q0 / 513.q0 , - 845.q0 / 4104.q0 , 0.q0 , 0.q0 , &
13
+ - 8.q0 / 27.q0 , 2.q0 , - 3544.q0 / 2565.q0 , 1859.q0 / 4104.q0 , - 11.q0 / - 40.q0 , 0.q0 &
14
+ ], [6 , 6 ]))
15
+ real * 16 , parameter , dimension (6 ) :: rkf_yk = &
16
+ [25.q0 / 216.q0 , 0.q0 , 1408.q0 / 2565.q0 , 2197.q0 / 4101.q0 , - 1.q0 / 5.q0 , 0.q0 ]
17
+ real * 16 , parameter , dimension (6 ) :: rkf_zk = &
18
+ [16.q0 / 135.q0 , 0.q0 , 6656.q0 / 12825.q0 , 28561.q0 / 56430.q0 , - 9.q0 / 50.q0 , 2.q0 / 55.q0 ]
19
+ contains
20
+ subroutine rk5 (h , w , err )
21
+ real * 16 , intent (in ) :: h
22
+ type (triBody) :: w, yl
23
+ real * 16 :: err
24
+ type (triBody), dimension (6 ) :: k
25
+ integer :: i, j
26
+
27
+ do i= 1 , 6
28
+ k(i) = w
29
+ do j= 1 , i-1
30
+ k(i) = k(i) + rkf_yki(i, j) * h * k(j)
31
+ end do
32
+ k(i) = fdt(rkf_tki(i) * h, k(i))
33
+ ! call k(i)%show_triBody()
34
+ end do
35
+ yl = w
36
+ do i= 1 , 5
37
+ yl = yl + rkf_yk(i) * h * k(i)
38
+ end do
39
+ do i= 1 , 6
40
+ w = w + rkf_zk(i) * h * k(i)
41
+ end do
42
+ err = modulus(w - yl) / modulus(w)
43
+ ! call w%show_triBody()
44
+ ! print *, 'err in rk5', err
45
+ end
46
+ recursive subroutine rkf45 (t , delta_t , state , err , tol )
47
+ real * 16 :: adjusted_dt, err_tmp
48
+ real * 16 , intent (inout ) :: t, err
49
+ real * 16 , intent (in ) :: delta_t, tol
50
+ type (triBody) :: state, test_state
51
+ test_state = state
52
+ call rk5(delta_t, test_state, err_tmp)
53
+ if ((isnan(err_tmp) .eqv. .true. ) .or. (err_tmp < tol)) then
54
+ ! print *, 'passed on first try'
55
+ state = test_state
56
+ t = t + delta_t
57
+ err = err + err_tmp
58
+ else
59
+ ! print *, 'F'
60
+ adjusted_dt = delta_t * 0.84q0 * (tol / err_tmp)** (0.25q0 )
61
+ ! print *, adjusted_dt / delta_t * 100.q0, '%'
62
+ if (adjusted_dt < min_adj_dt) then
63
+ ! print *, 'adjusted length too short'
64
+ call rk5(adjusted_dt, state, err_tmp)
65
+ t = t + adjusted_dt
66
+ err = err + err_tmp
67
+ else
68
+ ! print *, 'L'
69
+ call rkf45(t, adjusted_dt, state, err, tol)
70
+ end if
71
+ if (min_adj_dt > delta_t - adjusted_dt) then
72
+ ! print *, 'length left too short'
73
+ call rk5(delta_t - adjusted_dt, state, err_tmp)
74
+ t = t + delta_t - adjusted_dt
75
+ err = err + err_tmp
76
+ else
77
+ ! print *, 'R'
78
+ call rkf45(t, delta_t - adjusted_dt, state, err, tol)
79
+ end if
80
+ end if
81
+ ! print *, 'EOF'
82
+ end
83
+ subroutine rkf45_loop (t , delta_t , state , err , tol )
84
+ real * 16 :: adjusted_dt, err_tmp, t_f
85
+ real * 16 , intent (inout ) :: t, err
86
+ real * 16 , intent (in ) :: delta_t, tol
87
+ type (triBody) :: state, test_state
88
+ test_state = state
89
+ t_f = t + delta_t
90
+ call rk5(delta_t, test_state, err_tmp)
91
+ if ((isnan(err_tmp) .eqv. .true. ) .or. (err_tmp < tol)) then
92
+ ! print *, 'passed on first try'
93
+ state = test_state
94
+ t = t + delta_t
95
+ err = err + err_tmp
96
+ return
97
+ end if
98
+ adjusted_dt = delta_t * 0.84q0 * (tol / err_tmp)** (0.25q0 )
99
+ do while (t + adjusted_dt < t_f .and. adjusted_dt > min_adj_dt)
100
+ call rk5(adjusted_dt, test_state, err_tmp)
101
+ t = t + adjusted_dt
102
+ err = err + err_tmp
103
+ adjusted_dt = adjusted_dt * 0.84q0 * (tol / err_tmp)** (0.25q0 )
104
+ end do
105
+ call rk5(t_f - t, test_state, err_tmp)
106
+ state = test_state
107
+ err = err + err_tmp
108
+ t = t_f
109
+ end
110
+ subroutine rkf45_iter (t , delta_t , state , err , tol )
111
+ real * 16 :: adjusted_dt
112
+ real * 16 , intent (inout ) :: t, err
113
+ real * 16 , intent (in ) :: delta_t, tol
114
+ type (triBody) :: state, test_state
115
+ test_state = state
116
+ call rk5(delta_t, test_state, err)
117
+ adjusted_dt = delta_t
118
+ do while ((isnan(err) .eqv. .false. ) .and. (err > tol) .and. (adjusted_dt > min_adj_dt))
119
+ ! print *, 'passed on first try'
120
+ call rk5(adjusted_dt, test_state, err)
121
+ adjusted_dt = adjusted_dt * 0.84q0 * (tol / err)** (0.25q0 )
122
+ end do
123
+ state = test_state
124
+ t = t + adjusted_dt
125
+ end
126
+ subroutine rkf45_interpolation (t , delta_t , state , err , tol )
127
+ real * 16 , intent (inout ) :: t, err
128
+ real * 16 , intent (in ) :: delta_t, tol
129
+ real * 16 :: t_r, t_l, err_tmp
130
+ type (triBody) :: state, state_r
131
+ t_l = t
132
+ t_r = t_l
133
+ t = t + delta_t
134
+ state_r = state
135
+ call rkf45_iter(t_r, delta_t, state_r, err, tol)
136
+ do while (t_r < t)
137
+ t_l = t_r
138
+ state = state_r
139
+ call rkf45_iter(t_r, t - t_l, state_r, err_tmp, tol)
140
+ err = err + err_tmp
141
+ end do
142
+ state = state + ((t - t_l) / (t_r - t_l)) * (state_r - state)
143
+ end
144
+ end module solver_new
0 commit comments