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
5586 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
return nothing
36
end
37
38
function Base.show(io::IO, ::MIME"text/plain",
39
cb::DiscreteCallback{<:Any, <:AveragingCallback})
40
@nospecialize cb # reduce precompilation time
41
42
if get(io, :compact, false)
43
show(io, cb)
44
else
45
averaging_callback = cb.affect!
46
47
setup = [
48
"Start time" => first(averaging_callback.tspan),
49
"Final time" => last(averaging_callback.tspan)
50
]
51
summary_box(io, "AveragingCallback", setup)
52
end
53
end
54
55
function AveragingCallback(semi::SemidiscretizationHyperbolic{<:Any,
56
<:CompressibleEulerEquations2D},
57
tspan; output_directory = "out", filename = "averaging.h5")
58
mesh, equations, solver, cache = mesh_equations_solver_cache(semi)
59
mean_values = initialize_mean_values(mesh, equations, solver, cache)
60
cache = create_cache(AveragingCallback, mesh, equations, solver, cache)
61
62
averaging_callback = AveragingCallback(tspan, mean_values, cache, output_directory,
63
filename)
64
condition = (u, t, integrator) -> first(tspan) <= t <= last(tspan)
65
66
return DiscreteCallback(condition, averaging_callback,
67
save_positions = (false, false),
68
initialize = initialize!)
69
end
70
71
function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t,
72
integrator) where {Condition, Affect! <: AveragingCallback}
73
averaging_callback = cb.affect!
74
semi = integrator.p
75
mesh, equations, solver, cache = mesh_equations_solver_cache(semi)
76
u = wrap_array(u_ode, mesh, equations, solver, cache)
77
78
@trixi_timeit timer() "averaging" initialize_cache!(averaging_callback.cache, u,
79
mesh, equations, solver, cache)
80
81
# avoid re-evaluating possible FSAL stages
82
u_modified!(integrator, false)
83
return nothing
84
end
85
86
# This function is called during time integration and updates the mean values according to the
87
# trapezoidal rule
88
function (averaging_callback::AveragingCallback)(integrator)
89
@unpack mean_values = averaging_callback
90
91
u_ode = integrator.u
92
u_prev_ode = integrator.uprev
93
semi = integrator.p
94
mesh, equations, solver, cache = mesh_equations_solver_cache(semi)
95
u = wrap_array(u_ode, mesh, equations, solver, cache)
96
u_prev = wrap_array(u_prev_ode, mesh, equations, solver, cache)
97
98
dt = integrator.t - integrator.tprev
99
tspan = averaging_callback.tspan
100
101
integration_constant = 0.5 * dt / (tspan[2] - tspan[1]) # .5 due to trapezoidal rule
102
103
@trixi_timeit timer() "averaging" calc_mean_values!(mean_values,
104
averaging_callback.cache,
105
u, u_prev, integration_constant,
106
mesh, equations, solver, cache)
107
108
# Store mean values in a file if this is the last time step
109
if isfinished(integrator)
110
save_averaging_file(averaging_callback, semi)
111
end
112
113
# avoid re-evaluating possible FSAL stages
114
u_modified!(integrator, false)
115
116
return nothing
117
end
118
119
function save_averaging_file(averaging_callback, semi::AbstractSemidiscretization)
120
# Create output directory if it doesn't exist
121
mkpath(averaging_callback.output_directory)
122
123
return save_averaging_file(averaging_callback, mesh_equations_solver_cache(semi)...)
124
end
125
126
function load_averaging_file(averaging_file, semi::AbstractSemidiscretization)
127
return load_averaging_file(averaging_file, mesh_equations_solver_cache(semi)...)
128
end
129
130
include("averaging_dg.jl")
131
include("averaging_dg2d.jl")
132
end # @muladd
133
134