Skip to content

Commit 4ac990c

Browse files
prelim adaptivity
1 parent 733bfa5 commit 4ac990c

File tree

6 files changed

+214
-76
lines changed

6 files changed

+214
-76
lines changed

lib/OrdinaryDiffEqFIRK/src/algorithms.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,13 @@ struct AdaptiveRadau{CS, AD, F, P, FDT, ST, CJ, Tol, C1, C2, StepLimiter} <:
163163
new_W_γdt_cutoff::C2
164164
controller::Symbol
165165
step_limiter!::StepLimiter
166-
num_stages::Int
166+
min_num_stages::Int
167+
max_num_stages::Int
167168
end
168169

169170
function AdaptiveRadau(; chunk_size = Val{0}(), autodiff = Val{true}(),
170171
standardtag = Val{true}(), concrete_jac = nothing,
171-
diff_type = Val{:forward}, num_stages = 3,
172+
diff_type = Val{:forward}, min_num_stages = 3, max_num_stages = 3,
172173
linsolve = nothing, precs = DEFAULT_PRECS,
173174
extrapolant = :dense, fast_convergence_cutoff = 1 // 5,
174175
new_W_γdt_cutoff = 1 // 5,
@@ -186,6 +187,6 @@ function AdaptiveRadau(; chunk_size = Val{0}(), autodiff = Val{true}(),
186187
fast_convergence_cutoff,
187188
new_W_γdt_cutoff,
188189
controller,
189-
step_limiter!, num_stages)
190+
step_limiter!, min_num_stages, max_num_stages)
190191
end
191192

lib/OrdinaryDiffEqFIRK/src/controllers.jl

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@
2424
q
2525
end
2626

27-
function step_accept_controller!(integrator, controller::PredictiveController, alg, q)
27+
function step_accept_controller!(integrator, controller::PredictiveController, alg::Union{RadauIIA3, RadauIIA5, RadauIIA9}, q)
2828
@unpack qmin, qmax, gamma, qsteady_min, qsteady_max = integrator.opts
29+
2930
EEst = DiffEqBase.value(integrator.EEst)
3031

3132
if integrator.success_iter > 0
@@ -42,6 +43,43 @@ function step_accept_controller!(integrator, controller::PredictiveController, a
4243
end
4344
integrator.dtacc = integrator.dt
4445
integrator.erracc = max(1e-2, EEst)
46+
47+
return integrator.dt / qacc
48+
end
49+
50+
51+
function step_accept_controller!(integrator, controller::PredictiveController, alg::AdaptiveRadau, q)
52+
@unpack qmin, qmax, gamma, qsteady_min, qsteady_max = integrator.opts
53+
@unpack cache = integrator
54+
@unpack num_stages, step, θ, θprev, orders = cache
55+
56+
EEst = DiffEqBase.value(integrator.EEst)
57+
58+
if integrator.success_iter > 0
59+
expo = 1 / (get_current_adaptive_order(alg, integrator.cache) + 1)
60+
qgus = (integrator.dtacc / integrator.dt) *
61+
DiffEqBase.fastpow((EEst^2) / integrator.erracc, expo)
62+
qgus = max(inv(qmax), min(inv(qmin), qgus / gamma))
63+
qacc = max(q, qgus)
64+
else
65+
qacc = q
66+
end
67+
if qsteady_min <= qacc <= qsteady_max
68+
qacc = one(qacc)
69+
end
70+
integrator.dtacc = integrator.dt
71+
integrator.erracc = max(1e-2, EEst)
72+
73+
cache.step = step + 1
74+
if (step > 10)
75+
Ψ = θ * θprev
76+
if<= 0.002 && num_stages < alg.max_num_stages)
77+
cache.num_stages += 2
78+
elseif ((Ψ >= 0.8 || cache.status == VerySlowConvergence || cache.status == Divergence) && num_stages > alg.min_num_stages)
79+
cache.num_stages -= 2
80+
cache.step = 1
81+
end
82+
end
4583
return integrator.dt / qacc
4684
end
4785

lib/OrdinaryDiffEqFIRK/src/firk_caches.jl

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ end
477477
mutable struct AdaptiveRadauConstantCache{F, Tab, Tol, Dt, U, JType} <:
478478
OrdinaryDiffEqConstantCache
479479
uf::F
480-
tab::Tab
480+
tabs::Vector{Tab}
481481
κ::Tol
482482
ηold::Tol
483483
iter::Int
@@ -486,6 +486,11 @@ mutable struct AdaptiveRadauConstantCache{F, Tab, Tol, Dt, U, JType} <:
486486
W_γdt::Dt
487487
status::NLStatus
488488
J::JType
489+
num_stages::Int
490+
step::Int
491+
θ::BigFloat
492+
θprev::BigFloat
493+
orders::Vector{Int}
489494
end
490495

491496
function alg_cache(alg::AdaptiveRadau, u, rate_prototype, ::Type{uEltypeNoUnits},
@@ -494,8 +499,16 @@ function alg_cache(alg::AdaptiveRadau, u, rate_prototype, ::Type{uEltypeNoUnits}
494499
::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits}
495500
uf = UDerivativeWrapper(f, t, p)
496501
uToltype = constvalue(uBottomEltypeNoUnits)
497-
num_stages = alg.num_stages
498-
502+
num_stages = alg.min_num_stages
503+
max = alg.max_num_stages
504+
tabs = [BigRadauIIA5Tableau(uToltype, constvalue(tTypeNoUnits)), BigRadauIIA9Tableau(uToltype, constvalue(tTypeNoUnits)), BigRadauIIA13Tableau(uToltype, constvalue(tTypeNoUnits))]
505+
506+
i = 9
507+
while i <= alg.max_num_stages
508+
push!(tabs, adaptiveRadauTableau(uToltype, constvalue(tTypeNoUnits), i))
509+
i += 2
510+
end
511+
#=
499512
if (num_stages == 3)
500513
tab = BigRadauIIA5Tableau(uToltype, constvalue(tTypeNoUnits))
501514
elseif (num_stages == 5)
@@ -505,19 +518,19 @@ function alg_cache(alg::AdaptiveRadau, u, rate_prototype, ::Type{uEltypeNoUnits}
505518
elseif iseven(num_stages) || num_stages <3
506519
error("num_stages must be odd and 3 or greater")
507520
else
508-
tab = adaptiveRadauTableau(uToltype, constvalue(tTypeNoUnits), num_stages)
521+
tab = adaptiveRadauTableau(uToltype, constvalue(tTypeNoUnits), min_num_stages)
509522
end
510-
511-
cont = Vector{typeof(u)}(undef, num_stages)
512-
for i in 1: num_stages
523+
=#
524+
cont = Vector{typeof(u)}(undef, max)
525+
for i in 1: max
513526
cont[i] = zero(u)
514527
end
515528

516529
κ = alg.κ !== nothing ? convert(uToltype, alg.κ) : convert(uToltype, 1 // 100)
517530
J = false .* _vec(rate_prototype) .* _vec(rate_prototype)'
518-
519-
AdaptiveRadauConstantCache(uf, tab, κ, one(uToltype), 10000, cont, dt, dt,
520-
Convergence, J)
531+
orders = [0,0,0,0]
532+
AdaptiveRadauConstantCache(uf, tabs, κ, one(uToltype), 10000, cont, dt, dt,
533+
Convergence, J, num_stages, 1, big"1.0", big"1.0", orders)
521534
end
522535

523536
mutable struct AdaptiveRadauCache{uType, cuType, tType, uNoUnitsType, rateType, JType, W1Type, W2Type,
@@ -544,7 +557,7 @@ mutable struct AdaptiveRadauCache{uType, cuType, tType, uNoUnitsType, rateType,
544557
W1::W1Type #real
545558
W2::Vector{W2Type} #complex
546559
uf::UF
547-
tab::Tab
560+
tabs::Vector{Tab}
548561
κ::Tol
549562
ηold::Tol
550563
iter::Int
@@ -559,6 +572,11 @@ mutable struct AdaptiveRadauCache{uType, cuType, tType, uNoUnitsType, rateType,
559572
W_γdt::Dt
560573
status::NLStatus
561574
step_limiter!::StepLimiter
575+
num_stages::Int
576+
step::Int
577+
θ::BigFloat
578+
θprev::BigFloat
579+
orders::Vector{Int}
562580
end
563581

564582
function alg_cache(alg::AdaptiveRadau, u, rate_prototype, ::Type{uEltypeNoUnits},
@@ -567,8 +585,19 @@ function alg_cache(alg::AdaptiveRadau, u, rate_prototype, ::Type{uEltypeNoUnits}
567585
::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits}
568586
uf = UJacobianWrapper(f, t, p)
569587
uToltype = constvalue(uBottomEltypeNoUnits)
570-
num_stages = alg.num_stages
571588

589+
min = alg.min_num_stages
590+
max = alg.max_num_stages
591+
592+
num_stages = min
593+
594+
tabs = [BigRadauIIA5Tableau(uToltype, constvalue(tTypeNoUnits)), BigRadauIIA9Tableau(uToltype, constvalue(tTypeNoUnits)), BigRadauIIA13Tableau(uToltype, constvalue(tTypeNoUnits))]
595+
i = 9
596+
while i <= max
597+
push!(tabs, adaptiveRadauTableau(uToltype, constvalue(tTypeNoUnits), i))
598+
i += 2
599+
end
600+
#=
572601
if (num_stages == 3)
573602
tab = BigRadauIIA5Tableau(uToltype, constvalue(tTypeNoUnits))
574603
elseif (num_stages == 5)
@@ -580,39 +609,40 @@ function alg_cache(alg::AdaptiveRadau, u, rate_prototype, ::Type{uEltypeNoUnits}
580609
else
581610
tab = adaptiveRadauTableau(uToltype, constvalue(tTypeNoUnits), num_stages)
582611
end
612+
=#
583613

584614
κ = alg.κ !== nothing ? convert(uToltype, alg.κ) : convert(uToltype, 1 // 100)
585615

586-
z = Vector{typeof(u)}(undef, num_stages)
587-
w = Vector{typeof(u)}(undef, num_stages)
588-
for i in 1 : num_stages
616+
z = Vector{typeof(u)}(undef, max)
617+
w = Vector{typeof(u)}(undef, max)
618+
for i in 1 : max
589619
z[i] = w[i] = zero(u)
590620
end
591621

592-
c_prime = Vector{typeof(t)}(undef, num_stages) #time stepping
622+
c_prime = Vector{typeof(t)}(undef, max) #time stepping
593623

594624
dw1 = zero(u)
595625
ubuff = zero(u)
596-
dw2 = [similar(u, Complex{eltype(u)}) for _ in 1 : (num_stages - 1) ÷ 2]
626+
dw2 = [similar(u, Complex{eltype(u)}) for _ in 1 : (max - 1) ÷ 2]
597627
recursivefill!.(dw2, false)
598-
cubuff = [similar(u, Complex{eltype(u)}) for _ in 1 : (num_stages - 1) ÷ 2]
628+
cubuff = [similar(u, Complex{eltype(u)}) for _ in 1 : (max - 1) ÷ 2]
599629
recursivefill!.(cubuff, false)
600-
dw = Vector{typeof(u)}(undef, num_stages - 1)
630+
dw = Vector{typeof(u)}(undef, max - 1)
601631

602-
cont = Vector{typeof(u)}(undef, num_stages)
603-
for i in 1 : num_stages
632+
cont = Vector{typeof(u)}(undef, max)
633+
for i in 1 : max
604634
cont[i] = zero(u)
605635
end
606636

607-
derivatives = Matrix{typeof(u)}(undef, num_stages, num_stages)
608-
for i in 1 : num_stages, j in 1 : num_stages
637+
derivatives = Matrix{typeof(u)}(undef, max, max)
638+
for i in 1 : max, j in 1 : max
609639
derivatives[i, j] = zero(u)
610640
end
611641

612642
fsalfirst = zero(rate_prototype)
613-
fw = Vector{typeof(rate_prototype)}(undef, num_stages)
614-
ks = Vector{typeof(rate_prototype)}(undef, num_stages)
615-
for i in 1: num_stages
643+
fw = Vector{typeof(rate_prototype)}(undef, max)
644+
ks = Vector{typeof(rate_prototype)}(undef, max)
645+
for i in 1: max
616646
ks[i] = fw[i] = zero(rate_prototype)
617647
end
618648
k = ks[1]
@@ -622,7 +652,7 @@ function alg_cache(alg::AdaptiveRadau, u, rate_prototype, ::Type{uEltypeNoUnits}
622652
error("Non-concrete Jacobian not yet supported by AdaptiveRadau.")
623653
end
624654

625-
W2 = [similar(J, Complex{eltype(W1)}) for _ in 1 : (num_stages - 1) ÷ 2]
655+
W2 = [similar(J, Complex{eltype(W1)}) for _ in 1 : (max - 1) ÷ 2]
626656
recursivefill!.(W2, false)
627657

628658
du1 = zero(rate_prototype)
@@ -640,7 +670,7 @@ function alg_cache(alg::AdaptiveRadau, u, rate_prototype, ::Type{uEltypeNoUnits}
640670

641671
linsolve2 = [
642672
init(LinearProblem(W2[i], _vec(cubuff[i]); u0 = _vec(dw2[i])), alg.linsolve, alias_A = true, alias_b = true,
643-
assumptions = LinearSolve.OperatorAssumptions(true)) for i in 1 : (num_stages - 1) ÷ 2]
673+
assumptions = LinearSolve.OperatorAssumptions(true)) for i in 1 : (max - 1) ÷ 2]
644674

645675
rtol = reltol isa Number ? reltol : zero(reltol)
646676
atol = reltol isa Number ? reltol : zero(reltol)
@@ -649,9 +679,9 @@ function alg_cache(alg::AdaptiveRadau, u, rate_prototype, ::Type{uEltypeNoUnits}
649679
z, w, c_prime, dw1, ubuff, dw2, cubuff, dw, cont, derivatives,
650680
du1, fsalfirst, ks, k, fw,
651681
J, W1, W2,
652-
uf, tab, κ, one(uToltype), 10000, tmp,
682+
uf, tabs, κ, one(uToltype), 10000, tmp,
653683
atmp, jac_config,
654684
linsolve1, linsolve2, rtol, atol, dt, dt,
655-
Convergence, alg.step_limiter!)
685+
Convergence, alg.step_limiter!, num_stages, 1, big"1.0", big"1.0", [0,0,0,0])
656686
end
657687

0 commit comments

Comments
 (0)