11include (" integration.jl" )
22
3- using NonlinearSolve, ODEProblemLibrary, LinearAlgebra
3+ using NonlinearSolve, ODEProblemLibrary, LinearAlgebra, LinearRegression
4+ using OrdinaryDiffEq, OrdinaryDiffEqRosenbrock
45
56# a simple fixed time-step driver for rapid algorithm prototyping
67function integrate (prob, solver; h)
@@ -46,18 +47,19 @@ struct MuTaylorExtrapolation{P, T1, T2, T3, T4}
4647end
4748
4849function prepare (prob, solver:: MuTaylorExtrapolation{P, T1, T2, T3, T4} ) where {P, T1, T2, T3, T4}
49- propagator_all, _ = build_propagator (prob. f, prob. p, ntuple (_ -> 1.0 , solver. order), length (prob. u0))
50+ propagator_all, d_propagator_all = build_propagator (prob. f, prob. p, ntuple (_ -> 1.0 , solver. order), length (prob. u0))
5051 propagator, _ = propagator_all
51- return (; propagator)
52+ d_propagator, _ = d_propagator_all
53+ return (; propagator, d_propagator)
5254end
5355
5456function update! (u, prob, solver:: MuTaylorExtrapolation{P, T1, T2, T3, T4} , cache, t, h) where {T1, T2, T3, T4, P}
5557 (; μ1, c1, μ2, c2) = solver
5658 (; propagator) = cache
5759 tm1 = t + μ1 * h
5860 tm2 = t + μ2 * h
59- nlf = (u_next, u_curr) -> propagator (u_next, tm1, - μ1 * h) - u_curr
60- nlprob1 = NonlinearProblem (nlf , copy (u), u)
61+ nlf1 = (u_next, u_curr) -> propagator (u_next, tm1, - μ1 * h) - u_curr
62+ nlprob1 = NonlinearProblem (nlf1 , copy (u), u)
6163 sol1 = solve (nlprob1)
6264 u_trial1 = real (propagator (sol1. u, tm1, (1 - μ1) * h))
6365 nlf2 = (u_next, u_curr) -> propagator (u_next, tm2, - μ2 * h) - u_curr
@@ -67,27 +69,22 @@ function update!(u, prob, solver::MuTaylorExtrapolation{P, T1, T2, T3, T4}, cach
6769 return u .= (c1 * u_trial1 + c2 * u_trial2)
6870end
6971
70- function estimate_order (solver, prob; dt1 = 1 / 12 , dt2 = 1 / 16 )
71- ref = prob. f. analytic (prob. u0, prob. p, prob. tspan[2 ])
72- println (" Reference: " , ref)
73- u1 = integrate (prob, solver; h = dt1)
74- println (" u1: " , u1)
75- u2 = integrate (prob, solver; h = dt2)
76- println (" u2: " , u2)
77- err1 = norm (u1 - ref)
78- err2 = norm (u2 - ref)
79- order = log (err1 / err2) / log (dt1 / dt2)
80- return order
81- end
72+ prob = ODEProblemLibrary. prob_ode_lotkavolterra
73+ refsol = solve (prob, Tsit5 (); reltol = 1e-14 , abstol = 1e-14 )
8274
83- u0 = rand (2 )
84- linear_f = ODEFunction (
85- ODEProblemLibrary. f_2dlinear, analytic = ODEProblemLibrary. f_2dlinear_analytic
86- )
87- prob = ODEProblem (linear_f, u0, (0.0 , 1.0 ), 1.01 )
88- prob_complex = ODEProblem (
89- linear_f, complex (u0), (0.0 , 1.0 ), 1.01
90- )
75+ function estimate_order (solver, prob; dts = 2. .^ (- 10 : - 4 ))
76+ println (" Reference: " , refsol. u[end ])
77+ errs = Float64[]
78+ for dt in dts
79+ u = integrate (prob, solver; h = dt)
80+ err = norm (u - refsol. u[end ])
81+ push! (errs, err)
82+ end
83+ logdts = log .(dts)
84+ logerrs = log .(errs)
85+ lr = linregress (logdts, logerrs)
86+ return LinearRegression. slope (lr)
87+ end
9188
9289ImplicitTaylor = MuTaylor (Val (1 ), 1.0 )
9390ImplicitTaylorMidpoint = MuTaylor (Val (1 ), 0.5 )
@@ -119,9 +116,9 @@ function normalized_pade(p::Int, q::Int)
119116 RI = Rational{BigInt}
120117 N = p + q
121118 c = Vector {RI} (undef, N + 1 )
122- c[1 ] = big ( 1 ) // big ( 1 )
119+ c[1 ] = 1 // 1
123120 for k in 1 : N
124- c[k + 1 ] = c[k] // big (k)
121+ c[k + 1 ] = c[k] // k
125122 end
126123 if q == 0
127124 dres = RI[]
@@ -133,7 +130,7 @@ function normalized_pade(p::Int, q::Int)
133130 rhs[i] = - c[k + 1 ] # -c_k
134131 for j in 1 : q
135132 idx = k - j # 0-indexed Taylor index
136- A[i, j] = idx >= 0 ? c[idx + 1 ] : big ( 0 ) // big ( 1 )
133+ A[i, j] = idx >= 0 ? c[idx + 1 ] : 0 // 1
137134 end
138135 end
139136 dres = A \ rhs # Rational 精确求解
@@ -145,7 +142,7 @@ function normalized_pade(p::Int, q::Int)
145142 n[k + 1 ] += dres[j] * c[k - j + 1 ]
146143 end
147144 end
148- d = vcat (big ( 1 ) // big ( 1 ) , dres)
145+ d = vcat (1 // 1 , dres)
149146 normalized_n = [x * factorial (k - 1 ) for (k, x) in enumerate (n)]
150147 normalized_d = [x * factorial (k - 1 ) for (k, x) in enumerate (d)]
151148 return normalized_n, normalized_d
@@ -159,22 +156,25 @@ end
159156
160157function prepare (prob, solver:: TaylorPade{P, Q} ) where {P, Q}
161158 polynomial_p, polynomial_q = normalized_pade (P, Q)
162- tuple_p = Base. tail (tuple (map (Float64, polynomial_p)... ))
163- tuple_q = Base. tail (tuple (map (Float64, polynomial_q)... ))
164- println (" Pade coefficients (numerator): " , tuple_p)
165- println (" Pade coefficients (denominator): " , tuple_q)
166- propagator_p_all, _ = build_propagator (prob. f, prob. p, tuple_p, length (prob. u0))
167- propagator_q_all, _ = build_propagator (prob. f, prob. p, tuple_q, length (prob. u0))
159+ println (" Pade coefficients: P = $polynomial_p , Q = $polynomial_q " )
160+ tuple_p = tuple (map (Float64, polynomial_p)... )
161+ tuple_q = tuple (map (Float64, polynomial_q)... )
162+ propagator_p_all, d_propagator_p_all = build_propagator (prob. f, prob. p, tuple_p, length (prob. u0))
163+ propagator_q_all, d_propagator_q_all = build_propagator (prob. f, prob. p, tuple_q, length (prob. u0))
168164 propagator_p, _ = propagator_p_all
169165 propagator_q, _ = propagator_q_all
170- return (; propagator_p, propagator_q)
166+ d_propagator_p, _ = d_propagator_p_all
167+ d_propagator_q, _ = d_propagator_q_all
168+ return (; propagator_p, propagator_q, d_propagator_p, d_propagator_q)
171169end
172170
173171function update! (u, prob, solver:: TaylorPade{P, Q} , cache, t, h) where {P, Q}
174- (; propagator_p, propagator_q) = cache
172+ (; propagator_p, propagator_q, d_propagator_p, d_propagator_q ) = cache
175173 rhs = propagator_p (u, t, h)
176174 nlf = (u_next, rhs) -> propagator_q (u_next, t + h, h) .- rhs
177- nlprob = NonlinearProblem (nlf, copy (u), rhs)
175+ jac = (u_next, rhs) -> d_propagator_q (u_next, t + h, h)
176+ nlf_wrapped = NonlinearFunction (nlf; jac)
177+ nlprob = NonlinearProblem (nlf_wrapped, copy (u), rhs)
178178 sol = solve (nlprob)
179179 return u .= sol. u
180180end
0 commit comments