Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/time_integration/time_integration.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
# Wrapper type for solutions from Trixi.jl's own time integrators, partially mimicking
9
# SciMLBase.ODESolution
10
struct TimeIntegratorSolution{tType, uType, P}
11
t::tType
12
u::uType
13
prob::P
14
end
15
16
# Abstract supertype of Trixi.jl's own time integrators for dispatch
17
abstract type AbstractTimeIntegrator end
18
19
# Abstract supertype for the time integration algorithms of Trixi.jl
20
abstract type AbstractTimeIntegrationAlgorithm end
21
22
# get a cache where the RHS can be stored
23
get_du(integrator::AbstractTimeIntegrator) = integrator.du
24
25
# Forward integrator.stats.naccept to integrator.iter (see GitHub PR#771)
26
function Base.getproperty(integrator::AbstractTimeIntegrator, field::Symbol)
27
if field === :stats
28
return (naccept = getfield(integrator, :iter),)
29
end
30
# general fallback
31
return getfield(integrator, field)
32
end
33
34
# used by adaptive timestepping algorithms in DiffEq
35
@inline function set_proposed_dt!(integrator::AbstractTimeIntegrator, dt)
36
(integrator.dt = dt; integrator.dtcache = dt)
37
38
return nothing
39
end
40
41
# Required e.g. for `glm_speed_callback`
42
@inline function get_proposed_dt(integrator::AbstractTimeIntegrator)
43
return integrator.dt
44
end
45
46
@inline function limit_dt!(integrator::AbstractTimeIntegrator, t_end)
47
# if the next iteration would push the simulation beyond the end time, set dt accordingly
48
if integrator.t + integrator.dt > t_end ||
49
isapprox(integrator.t + integrator.dt, t_end)
50
integrator.dt = t_end - integrator.t
51
terminate!(integrator)
52
end
53
54
return nothing
55
end
56
57
function initialize_callbacks!(callbacks::Union{CallbackSet, Nothing},
58
integrator::AbstractTimeIntegrator)
59
# initialize callbacks
60
if callbacks isa CallbackSet
61
foreach(callbacks.continuous_callbacks) do cb
62
throw(ArgumentError("Continuous callbacks are unsupported."))
63
end
64
foreach(callbacks.discrete_callbacks) do cb
65
cb.initialize(cb, integrator.u, integrator.t, integrator)
66
end
67
end
68
69
return nothing
70
end
71
72
function handle_callbacks!(callbacks::Union{CallbackSet, Nothing},
73
integrator::AbstractTimeIntegrator)
74
# handle callbacks
75
if callbacks isa CallbackSet
76
foreach(callbacks.discrete_callbacks) do cb
77
if cb.condition(integrator.u, integrator.t, integrator)
78
cb.affect!(integrator)
79
end
80
return nothing
81
end
82
end
83
84
return nothing
85
end
86
87
@inline function check_max_iter!(integrator::AbstractTimeIntegrator)
88
# respect maximum number of iterations
89
if integrator.iter >= integrator.opts.maxiters && !integrator.finalstep
90
@warn "Interrupted. Larger maxiters is needed."
91
terminate!(integrator)
92
end
93
94
return nothing
95
end
96
97
"""
98
Trixi.solve(ode::ODEProblem, alg::AbstractTimeIntegrationAlgorithm;
99
dt, callbacks, kwargs...)
100
101
Fakes `solve` from https://diffeq.sciml.ai/v6.8/basics/overview/#Solving-the-Problems-1
102
"""
103
function solve(ode::ODEProblem, alg::AbstractTimeIntegrationAlgorithm;
104
dt, callback = nothing, kwargs...)
105
integrator = init(ode, alg, dt = dt, callback = callback; kwargs...)
106
107
# Start actual solve
108
solve!(integrator)
109
end
110
111
function solve!(integrator::AbstractTimeIntegrator)
112
@unpack prob = integrator.sol
113
114
integrator.finalstep = false
115
116
@trixi_timeit timer() "main loop" while !integrator.finalstep
117
step!(integrator)
118
end
119
120
finalize_callbacks(integrator)
121
122
return TimeIntegratorSolution((first(prob.tspan), integrator.t),
123
(prob.u0, integrator.u), prob)
124
end
125
126
# Interface required by DiffEqCallbacks.jl
127
function DiffEqBase.get_tstops(integrator::AbstractTimeIntegrator)
128
return integrator.opts.tstops
129
end
130
function DiffEqBase.get_tstops_array(integrator::AbstractTimeIntegrator)
131
return get_tstops(integrator).valtree
132
end
133
function DiffEqBase.get_tstops_max(integrator::AbstractTimeIntegrator)
134
return maximum(get_tstops_array(integrator))
135
end
136
137
function finalize_callbacks(integrator::AbstractTimeIntegrator)
138
callbacks = integrator.opts.callback
139
140
if callbacks isa CallbackSet
141
foreach(callbacks.discrete_callbacks) do cb
142
cb.finalize(cb, integrator.u, integrator.t, integrator)
143
end
144
foreach(callbacks.continuous_callbacks) do cb
145
cb.finalize(cb, integrator.u, integrator.t, integrator)
146
end
147
end
148
149
return nothing
150
end
151
152
include("methods_2N.jl")
153
include("methods_3Sstar.jl")
154
include("methods_SSP.jl")
155
include("paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl")
156
include("relaxation_methods/relaxation_methods.jl")
157
end # @muladd
158
159