Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/time_integration/methods_2N.jl
2055 views
1
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).
2
# Since these FMAs can increase the performance of many numerical algorithms,
3
# we need to opt-in explicitly.
4
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.
5
@muladd begin
6
#! format: noindent
7
8
# Abstract base type for time integration schemes of storage class `2N`
9
abstract type SimpleAlgorithm2N <: AbstractTimeIntegrationAlgorithm end
10
11
"""
12
CarpenterKennedy2N54()
13
14
The following structures and methods provide a minimal implementation of
15
the low-storage explicit Runge-Kutta method of
16
17
- Carpenter, Kennedy (1994)
18
Fourth-order 2N-storage Runge-Kutta schemes (Solution 3)
19
URL: https://ntrs.nasa.gov/citations/19940028444
20
File: https://ntrs.nasa.gov/api/citations/19940028444/downloads/19940028444.pdf
21
22
using the same interface as OrdinaryDiffEq.jl.
23
"""
24
struct CarpenterKennedy2N54 <: SimpleAlgorithm2N
25
a::SVector{5, Float64}
26
b::SVector{5, Float64}
27
c::SVector{5, Float64}
28
29
function CarpenterKennedy2N54()
30
a = SVector(0.0,
31
567301805773.0 / 1357537059087.0,
32
2404267990393.0 / 2016746695238.0,
33
3550918686646.0 / 2091501179385.0,
34
1275806237668.0 / 842570457699.0)
35
b = SVector(1432997174477.0 / 9575080441755.0,
36
5161836677717.0 / 13612068292357.0,
37
1720146321549.0 / 2090206949498.0,
38
3134564353537.0 / 4481467310338.0,
39
2277821191437.0 / 14882151754819.0)
40
c = SVector(0.0,
41
1432997174477.0 / 9575080441755.0,
42
2526269341429.0 / 6820363962896.0,
43
2006345519317.0 / 3224310063776.0,
44
2802321613138.0 / 2924317926251.0)
45
46
new(a, b, c)
47
end
48
end
49
50
"""
51
CarpenterKennedy2N43()
52
53
The following structures and methods provide a minimal implementation of
54
the low-storage explicit Runge-Kutta method of
55
56
- Carpenter, Kennedy (1994)
57
Third-order 2N-storage Runge-Kutta schemes with error control
58
URL: https://ntrs.nasa.gov/citations/19940028444
59
File: https://ntrs.nasa.gov/api/citations/19940028444/downloads/19940028444.pdf
60
61
using the same interface as OrdinaryDiffEq.jl.
62
"""
63
struct CarpenterKennedy2N43 <: SimpleAlgorithm2N
64
a::SVector{4, Float64}
65
b::SVector{4, Float64}
66
c::SVector{4, Float64}
67
68
function CarpenterKennedy2N43()
69
a = SVector(0, 756391 / 934407, 36441873 / 15625000, 1953125 / 1085297)
70
b = SVector(8 / 141, 6627 / 2000, 609375 / 1085297, 198961 / 526383)
71
c = SVector(0, 8 / 141, 86 / 125, 1)
72
73
new(a, b, c)
74
end
75
end
76
77
# This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L1
78
mutable struct SimpleIntegratorOptions{Callback}
79
callback::Callback # callbacks; used in Trixi.jl
80
adaptive::Bool # whether the algorithm is adaptive; ignored
81
dtmax::Float64 # ignored
82
maxiters::Int # maximal number of time steps
83
tstops::Vector{Float64} # tstops from https://diffeq.sciml.ai/v6.8/basics/common_solver_opts/#Output-Control-1; ignored
84
end
85
86
function SimpleIntegratorOptions(callback, tspan; maxiters = typemax(Int), kwargs...)
87
SimpleIntegratorOptions{typeof(callback)}(callback, false, Inf, maxiters,
88
[last(tspan)])
89
end
90
91
# This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L77
92
# This implements the interface components described at
93
# https://diffeq.sciml.ai/v6.8/basics/integrator/#Handing-Integrators-1
94
# which are used in Trixi.jl.
95
mutable struct SimpleIntegrator2N{RealT <: Real, uType <: AbstractVector,
96
Params, Sol, F, Alg,
97
SimpleIntegratorOptions} <: AbstractTimeIntegrator
98
u::uType
99
du::uType
100
u_tmp::uType
101
t::RealT
102
dt::RealT # current time step
103
dtcache::RealT # ignored
104
iter::Int # current number of time steps (iteration)
105
p::Params # will be the semidiscretization from Trixi.jl
106
sol::Sol # faked
107
f::F # `rhs!` of the semidiscretization
108
alg::Alg # SimpleAlgorithm2N
109
opts::SimpleIntegratorOptions
110
finalstep::Bool # added for convenience
111
end
112
113
function init(ode::ODEProblem, alg::SimpleAlgorithm2N;
114
dt, callback::Union{CallbackSet, Nothing} = nothing, kwargs...)
115
u = copy(ode.u0)
116
du = similar(u)
117
u_tmp = similar(u)
118
t = first(ode.tspan)
119
iter = 0
120
integrator = SimpleIntegrator2N(u, du, u_tmp, t, dt, zero(dt), iter, ode.p,
121
(prob = ode,), ode.f, alg,
122
SimpleIntegratorOptions(callback, ode.tspan;
123
kwargs...), false)
124
125
initialize_callbacks!(callback, integrator)
126
127
return integrator
128
end
129
130
function step!(integrator::SimpleIntegrator2N)
131
@unpack prob = integrator.sol
132
@unpack alg = integrator
133
t_end = last(prob.tspan)
134
callbacks = integrator.opts.callback
135
136
@assert !integrator.finalstep
137
if isnan(integrator.dt)
138
error("time step size `dt` is NaN")
139
end
140
141
limit_dt!(integrator, t_end)
142
143
# one time step
144
integrator.u_tmp .= 0
145
for stage in eachindex(alg.c)
146
t_stage = integrator.t + integrator.dt * alg.c[stage]
147
integrator.f(integrator.du, integrator.u, prob.p, t_stage)
148
149
a_stage = alg.a[stage]
150
b_stage_dt = alg.b[stage] * integrator.dt
151
@trixi_timeit timer() "Runge-Kutta step" begin
152
@threaded for i in eachindex(integrator.u)
153
integrator.u_tmp[i] = integrator.du[i] -
154
integrator.u_tmp[i] * a_stage
155
integrator.u[i] += integrator.u_tmp[i] * b_stage_dt
156
end
157
end
158
end
159
integrator.iter += 1
160
integrator.t += integrator.dt
161
162
@trixi_timeit timer() "Step-Callbacks" handle_callbacks!(callbacks, integrator)
163
164
check_max_iter!(integrator)
165
166
return nothing
167
end
168
169
# get a cache where the RHS can be stored
170
get_tmp_cache(integrator::SimpleIntegrator2N) = (integrator.u_tmp,)
171
172
# some algorithms from DiffEq like FSAL-ones need to be informed when a callback has modified u
173
u_modified!(integrator::SimpleIntegrator2N, ::Bool) = false
174
175
# stop the time integration
176
function terminate!(integrator::SimpleIntegrator2N)
177
integrator.finalstep = true
178
empty!(integrator.opts.tstops)
179
180
return nothing
181
end
182
183
# used for AMR
184
function Base.resize!(integrator::SimpleIntegrator2N, new_size)
185
resize!(integrator.u, new_size)
186
resize!(integrator.du, new_size)
187
resize!(integrator.u_tmp, new_size)
188
189
return nothing
190
end
191
end # @muladd
192
193