Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/callbacks_step/averaging.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
AveragingCallback(semi::SemidiscretizationHyperbolic, tspan; output_directory="out",
10
filename="averaging.h5")
11
12
!!! warning "Experimental code"
13
This callback is experimental and may change in any future release.
14
15
A callback that averages the flow field described by `semi` which must be a semidiscretization of
16
the compressible Euler equations in two dimensions. The callback records the mean velocity,
17
mean speed of sound, mean density, and mean vorticity for each node over the time interval given by
18
`tspan` and stores the results in an HDF5 file `filename` in the directory `output_directory`. Note
19
that this callback does not support adaptive mesh refinement ([`AMRCallback`](@ref)).
20
"""
21
struct AveragingCallback{TSpan, MeanValues, Cache}
22
tspan::TSpan
23
mean_values::MeanValues
24
cache::Cache
25
output_directory::String
26
filename::String
27
end
28
29
function Base.show(io::IO, cb::DiscreteCallback{<:Any, <:AveragingCallback})
30
@nospecialize cb # reduce precompilation time
31
averaging_callback = cb.affect!
32
@unpack tspan = averaging_callback
33
34
print(io, "AveragingCallback(tspan=", tspan, ")")
35
end
36
37
function Base.show(io::IO, ::MIME"text/plain",
38
cb::DiscreteCallback{<:Any, <:AveragingCallback})
39
@nospecialize cb # reduce precompilation time
40
41
if get(io, :compact, false)
42
show(io, cb)
43
else
44
averaging_callback = cb.affect!
45
46
setup = [
47
"Start time" => first(averaging_callback.tspan),
48
"Final time" => last(averaging_callback.tspan)
49
]
50
summary_box(io, "AveragingCallback", setup)
51
end
52
end
53
54
function AveragingCallback(semi::SemidiscretizationHyperbolic{<:Any,
55
<:CompressibleEulerEquations2D},
56
tspan; output_directory = "out", filename = "averaging.h5")
57
mesh, equations, solver, cache = mesh_equations_solver_cache(semi)
58
mean_values = initialize_mean_values(mesh, equations, solver, cache)
59
cache = create_cache(AveragingCallback, mesh, equations, solver, cache)
60
61
averaging_callback = AveragingCallback(tspan, mean_values, cache, output_directory,
62
filename)
63
condition = (u, t, integrator) -> first(tspan) <= t <= last(tspan)
64
65
return DiscreteCallback(condition, averaging_callback,
66
save_positions = (false, false),
67
initialize = initialize!)
68
end
69
70
function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t,
71
integrator) where {Condition, Affect! <: AveragingCallback}
72
averaging_callback = cb.affect!
73
semi = integrator.p
74
mesh, equations, solver, cache = mesh_equations_solver_cache(semi)
75
u = wrap_array(u_ode, mesh, equations, solver, cache)
76
77
@trixi_timeit timer() "averaging" initialize_cache!(averaging_callback.cache, u,
78
mesh, equations, solver, cache)
79
80
# avoid re-evaluating possible FSAL stages
81
u_modified!(integrator, false)
82
return nothing
83
end
84
85
# This function is called during time integration and updates the mean values according to the
86
# trapezoidal rule
87
function (averaging_callback::AveragingCallback)(integrator)
88
@unpack mean_values = averaging_callback
89
90
u_ode = integrator.u
91
u_prev_ode = integrator.uprev
92
semi = integrator.p
93
mesh, equations, solver, cache = mesh_equations_solver_cache(semi)
94
u = wrap_array(u_ode, mesh, equations, solver, cache)
95
u_prev = wrap_array(u_prev_ode, mesh, equations, solver, cache)
96
97
dt = integrator.t - integrator.tprev
98
tspan = averaging_callback.tspan
99
100
integration_constant = 0.5 * dt / (tspan[2] - tspan[1]) # .5 due to trapezoidal rule
101
102
@trixi_timeit timer() "averaging" calc_mean_values!(mean_values,
103
averaging_callback.cache,
104
u, u_prev, integration_constant,
105
mesh, equations, solver, cache)
106
107
# Store mean values in a file if this is the last time step
108
if isfinished(integrator)
109
save_averaging_file(averaging_callback, semi)
110
end
111
112
# avoid re-evaluating possible FSAL stages
113
u_modified!(integrator, false)
114
115
return nothing
116
end
117
118
function save_averaging_file(averaging_callback, semi::AbstractSemidiscretization)
119
# Create output directory if it doesn't exist
120
mkpath(averaging_callback.output_directory)
121
122
save_averaging_file(averaging_callback, mesh_equations_solver_cache(semi)...)
123
end
124
125
function load_averaging_file(averaging_file, semi::AbstractSemidiscretization)
126
load_averaging_file(averaging_file, mesh_equations_solver_cache(semi)...)
127
end
128
129
include("averaging_dg.jl")
130
include("averaging_dg2d.jl")
131
end # @muladd
132
133