Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/callbacks_step/euler_acoustics_coupling.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
@doc raw"""
9
EulerAcousticsCouplingCallback
10
11
!!! warning "Experimental code"
12
This callback is experimental and may change in any future release.
13
14
A callback that couples the acoustic perturbation equations and compressible Euler equations. Must
15
be used in conjunction with [`SemidiscretizationEulerAcoustics`](@ref).
16
This callback manages the flow solver - which is always one time step ahead of the
17
acoustics solver - and calculates the acoustic source term after each time step. The linearized
18
Lamb vector is used as the source term, i.e.
19
```math
20
\mathbf{s} = -(\mathbf{\omega'} \times \bar{\mathbf{v}}
21
+ \bar{\mathbf{\omega}} \times \mathbf{v'}),
22
```
23
where ``\mathbf{v}`` denotes the velocity, ``\mathbf{\omega}`` denotes the vorticity, the bar
24
``\bar{(\cdot)}`` indicates time-averaged quantities (see [`AveragingCallback`](@ref)) and prime
25
``(\cdot)'`` denotes perturbed quantities defined by ``\phi' = \phi - \bar{\phi}``. Note that
26
the perturbed quantities here are based entirely on the pure flow solution and should not be
27
confused with the state variables of the acoustic perturbation equations.
28
29
In addition, this callback manages the time step size for both solvers
30
and initializes the mean values of the acoustic perturbation equations using results obtained with
31
the [`AveragingCallback`](@ref).
32
33
- Michael Schlottke-Lakemper (2017)
34
A direct-hybrid method for aeroacoustic analysis
35
[DOI: 10.18154/RWTH-2017-04082](https://doi.org/10.18154/RWTH-2017-04082)
36
"""
37
mutable struct EulerAcousticsCouplingCallback{RealT <: Real, MeanValues,
38
IntegratorEuler}
39
stepsize_callback_acoustics::StepsizeCallback{RealT, RealT}
40
stepsize_callback_euler::StepsizeCallback{RealT, RealT}
41
mean_values::MeanValues
42
integrator_euler::IntegratorEuler
43
end
44
45
function Base.show(io::IO,
46
cb::DiscreteCallback{<:Any, <:EulerAcousticsCouplingCallback})
47
@nospecialize cb # reduce precompilation time
48
euler_acoustics_coupling = cb.affect!
49
50
print(io, "EulerAcousticsCouplingCallback(")
51
print(io, euler_acoustics_coupling.stepsize_callback_acoustics)
52
print(io, ", ", euler_acoustics_coupling.stepsize_callback_euler, ")")
53
return nothing
54
end
55
56
function Base.show(io::IO, ::MIME"text/plain",
57
cb::DiscreteCallback{<:Any, <:EulerAcousticsCouplingCallback})
58
@nospecialize cb # reduce precompilation time
59
euler_acoustics_coupling = cb.affect!
60
61
summary_header(io, "EulerAcousticsCouplingCallback")
62
summary_line(io, "acoustics StepsizeCallback",
63
euler_acoustics_coupling.stepsize_callback_acoustics)
64
summary_line(io, "Euler StepsizeCallback",
65
euler_acoustics_coupling.stepsize_callback_euler)
66
summary_footer(io)
67
return nothing
68
end
69
70
"""
71
EulerAcousticsCouplingCallback(ode_euler,
72
averaging_callback::DiscreteCallback{<:Any, <:AveragingCallback},
73
alg, cfl_acoustics::Real, cfl_euler::Real; kwargs...)
74
75
!!! warning "Experimental code"
76
This callback is experimental and may change in any future release.
77
78
Creates an [`EulerAcousticsCouplingCallback`](@ref) based on the pure flow `ODEProblem` given by
79
`ode_euler`. Creates an integrator using the time integration method `alg` and the keyword arguments
80
to solve `ode_euler` (consult the [OrdinaryDiffEq documentation](https://diffeq.sciml.ai/stable/)
81
for further information).
82
Manages the step size for both solvers by using the minimum of the maximum step size obtained with
83
CFL numbers `cfl_acoustics` for the acoustics solver and `cfl_euler` for and flow solver,
84
respectively.
85
The mean values for the acoustic perturbation equations are read from `averaging_callback`
86
(see [`AveragingCallback`](@ref)).
87
"""
88
function EulerAcousticsCouplingCallback(ode_euler,
89
averaging_callback::DiscreteCallback{<:Any,
90
<:AveragingCallback},
91
alg, cfl_acoustics::Real, cfl_euler::Real;
92
kwargs...)
93
@unpack mean_values = averaging_callback.affect!
94
95
return EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,
96
cfl_euler;
97
kwargs...)
98
end
99
100
"""
101
EulerAcousticsCouplingCallback(ode_euler, averaging_file::AbstractString, alg,
102
cfl_acoustics::Real, cfl_euler::Real; kwargs...)
103
104
!!! warning "Experimental code"
105
This callback is experimental and may change in any future release.
106
107
Creates an [`EulerAcousticsCouplingCallback`](@ref) based on the pure flow `ODEProblem` given by
108
`ode_euler`. Creates an integrator using the time integration method `alg` and the keyword arguments
109
to solve `ode_euler` (consult the [OrdinaryDiffEq documentation](https://diffeq.sciml.ai/stable/)
110
for further information).
111
Manages the step size for both solvers by using the minimum of the maximum step size obtained with
112
CFL numbers `cfl_acoustics` for the acoustics solver and `cfl_euler` for and flow solver,
113
respectively.
114
The mean values for the acoustic perturbation equations are read from `averaging_file`
115
(see [`AveragingCallback`](@ref)).
116
"""
117
function EulerAcousticsCouplingCallback(ode_euler, averaging_file::AbstractString, alg,
118
cfl_acoustics::Real, cfl_euler::Real; kwargs...)
119
semi_euler = ode_euler.p
120
mean_values = load_averaging_file(averaging_file, semi_euler)
121
122
return EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,
123
cfl_euler;
124
kwargs...)
125
end
126
127
function EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,
128
cfl_euler;
129
kwargs...)
130
# Set up ODE Integrator for Euler equations
131
integrator_euler = init(ode_euler, alg, save_everystep = false, dt = 1.0; kwargs...) # dt will be overwritten
132
133
euler_acoustics_coupling = EulerAcousticsCouplingCallback{typeof(cfl_acoustics),
134
typeof(mean_values),
135
typeof(integrator_euler)}(StepsizeCallback(cfl_acoustics),
136
StepsizeCallback(cfl_euler),
137
mean_values,
138
integrator_euler)
139
condition = (u, t, integrator) -> true
140
141
return DiscreteCallback(condition, euler_acoustics_coupling,
142
save_positions = (false, false),
143
initialize = initialize!)
144
end
145
146
# This is called before the main loop and initializes the mean values in u_ode
147
function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t,
148
integrator_acoustics) where {Condition,
149
Affect! <:
150
EulerAcousticsCouplingCallback}
151
euler_acoustics_coupling = cb.affect!
152
semi = integrator_acoustics.p
153
@unpack semi_acoustics = semi
154
155
# Initialize mean values in u_ode
156
u_acoustics = wrap_array(u_ode, semi_acoustics)
157
@unpack mean_values = euler_acoustics_coupling
158
@views @. u_acoustics[4:5, .., :] = mean_values.v_mean
159
@views @. u_acoustics[6, .., :] = mean_values.c_mean
160
@views @. u_acoustics[7, .., :] = mean_values.rho_mean
161
162
# Adjust stepsize, advance the flow solver by one time step
163
cb.affect!(integrator_acoustics)
164
165
return nothing
166
end
167
168
# This function is called at the end of every time step and advances the Euler solution by one
169
# time step, manages the time stepsize for both the acoustics and Euler solvers and calculates the
170
# acoustic sources for the next acoustics time step
171
function (euler_acoustics_coupling::EulerAcousticsCouplingCallback)(integrator_acoustics)
172
@unpack stepsize_callback_acoustics, stepsize_callback_euler, integrator_euler = euler_acoustics_coupling
173
174
@assert integrator_acoustics.t == integrator_euler.t
175
176
# Use the minimum of the acoustics and Euler stepsizes for both solvers
177
stepsize_callback_acoustics(integrator_acoustics)
178
stepsize_callback_euler(integrator_euler)
179
dt = min(get_proposed_dt(integrator_acoustics), get_proposed_dt(integrator_euler))
180
181
set_proposed_dt!(integrator_acoustics, dt)
182
integrator_acoustics.opts.dtmax = dt
183
integrator_acoustics.dtcache = dt
184
185
set_proposed_dt!(integrator_euler, dt)
186
integrator_euler.opts.dtmax = dt
187
integrator_euler.dtcache = dt
188
189
# Advance the Euler solution by one step and check for errors
190
if !isfinished(integrator_euler)
191
@trixi_timeit timer() "Euler solver" step!(integrator_euler)
192
return_code = check_error(integrator_euler)
193
if !(SciMLBase.successful_retcode(return_code) ||
194
return_code != SciMLBase.ReturnCode.Default)
195
error("Error during compressible Euler time integration. Received return code $(return_code)")
196
end
197
end
198
199
# Calculate acoustic sources based on linearized lamb vector
200
semi = integrator_acoustics.p
201
semi_euler = integrator_euler.p
202
u_acoustics = wrap_array(integrator_acoustics.u, semi)
203
u_euler = wrap_array(integrator_euler.u, semi_euler)
204
@unpack acoustic_source_terms, coupled_element_ids = semi.cache
205
@unpack vorticity_mean = euler_acoustics_coupling.mean_values
206
207
@trixi_timeit timer() "calc acoustic source terms" begin
208
calc_acoustic_sources!(acoustic_source_terms, u_euler, u_acoustics,
209
vorticity_mean, coupled_element_ids,
210
mesh_equations_solver_cache(semi_euler)...)
211
end
212
213
# avoid re-evaluation possible FSAL stages
214
u_modified!(integrator_acoustics, false)
215
u_modified!(integrator_euler, false)
216
217
return nothing
218
end
219
220
include("euler_acoustics_coupling_dg2d.jl")
221
end # @muladd
222
223