Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/callbacks_step/alive.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
"""
9
AliveCallback(analysis_interval=0, alive_interval=analysis_interval÷10)
10
11
Inexpensive callback showing that a simulation is still running by printing
12
some information such as the current time to the screen every `alive_interval`
13
time steps. If `analysis_interval ≂̸ 0`, the output is omitted every
14
`analysis_interval` time steps.
15
"""
16
mutable struct AliveCallback
17
start_time::Float64
18
alive_interval::Int
19
analysis_interval::Int
20
end
21
22
function AliveCallback(; analysis_interval = 0,
23
alive_interval = analysis_interval ÷ 10)
24
alive_callback = AliveCallback(0.0, alive_interval, analysis_interval)
25
26
DiscreteCallback(alive_callback, alive_callback, # the first one is the condition, the second the affect!
27
save_positions = (false, false),
28
initialize = initialize!)
29
end
30
31
function Base.show(io::IO, cb::DiscreteCallback{<:Any, <:AliveCallback})
32
@nospecialize cb # reduce precompilation time
33
34
alive_callback = cb.affect!
35
print(io, "AliveCallback(alive_interval=", alive_callback.alive_interval, ")")
36
end
37
38
function Base.show(io::IO, ::MIME"text/plain",
39
cb::DiscreteCallback{<:Any, <:AliveCallback})
40
@nospecialize cb # reduce precompilation time
41
42
if get(io, :compact, false)
43
show(io, cb)
44
else
45
alive_callback = cb.affect!
46
47
setup = [
48
"interval" => alive_callback.alive_interval
49
]
50
summary_box(io, "AliveCallback", setup)
51
end
52
end
53
54
function initialize!(cb::DiscreteCallback{Condition, Affect!}, u, t,
55
integrator) where {Condition, Affect! <: AliveCallback}
56
alive_callback = cb.affect!
57
alive_callback.start_time = time_ns()
58
return nothing
59
end
60
61
# this method is called to determine whether the callback should be activated
62
function (alive_callback::AliveCallback)(u, t, integrator)
63
@unpack alive_interval, analysis_interval = alive_callback
64
65
# With error-based step size control, some steps can be rejected. Thus,
66
# `integrator.iter >= integrator.stats.naccept`
67
# (total #steps) (#accepted steps)
68
# We need to check the number of accepted steps since callbacks are not
69
# activated after a rejected step.
70
return alive_interval > 0 && ((integrator.stats.naccept % alive_interval == 0 &&
71
(analysis_interval == 0 ||
72
integrator.stats.naccept % analysis_interval != 0)) ||
73
isfinished(integrator))
74
end
75
76
# this method is called when the callback is activated
77
function (alive_callback::AliveCallback)(integrator)
78
# Checking for floating point equality is OK here as `DifferentialEquations.jl`
79
# sets the time exactly to the final time in the last iteration
80
if isfinished(integrator) && mpi_isroot()
81
println("─"^100)
82
println("Trixi.jl simulation finished. Final time: ", integrator.t,
83
" Time steps: ", integrator.stats.naccept, " (accepted), ",
84
integrator.iter, " (total)")
85
println("─"^100)
86
println()
87
elseif mpi_isroot()
88
t = integrator.t
89
t_initial = first(integrator.sol.prob.tspan)
90
t_final = last(integrator.sol.prob.tspan)
91
sim_time_percentage = (t - t_initial) / (t_final - t_initial) * 100
92
runtime_absolute = 1.0e-9 * (time_ns() - alive_callback.start_time)
93
println(rpad(@sprintf("#timesteps: %6d │ Δt: %.4e │ sim. time: %.4e (%5.3f%%)",
94
integrator.stats.naccept, integrator.dt, t,
95
sim_time_percentage), 71) *
96
@sprintf("│ run time: %.4e s", runtime_absolute))
97
end
98
99
# avoid re-evaluating possible FSAL stages
100
u_modified!(integrator, false)
101
return nothing
102
end
103
end # @muladd
104
105