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
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
@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}
40
stepsize_callback_euler::StepsizeCallback{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
end
54
55
function Base.show(io::IO, ::MIME"text/plain",
56
cb::DiscreteCallback{<:Any, <:EulerAcousticsCouplingCallback})
57
@nospecialize cb # reduce precompilation time
58
euler_acoustics_coupling = cb.affect!
59
60
summary_header(io, "EulerAcousticsCouplingCallback")
61
summary_line(io, "acoustics StepsizeCallback",
62
euler_acoustics_coupling.stepsize_callback_acoustics)
63
summary_line(io, "Euler StepsizeCallback",
64
euler_acoustics_coupling.stepsize_callback_euler)
65
summary_footer(io)
66
end
67
68
"""
69
EulerAcousticsCouplingCallback(ode_euler,
70
averaging_callback::DiscreteCallback{<:Any, <:AveragingCallback},
71
alg, cfl_acoustics::Real, cfl_euler::Real; kwargs...)
72
73
!!! warning "Experimental code"
74
This callback is experimental and may change in any future release.
75
76
Creates an [`EulerAcousticsCouplingCallback`](@ref) based on the pure flow `ODEProblem` given by
77
`ode_euler`. Creates an integrator using the time integration method `alg` and the keyword arguments
78
to solve `ode_euler` (consult the [OrdinaryDiffEq documentation](https://diffeq.sciml.ai/stable/)
79
for further information).
80
Manages the step size for both solvers by using the minimum of the maximum step size obtained with
81
CFL numbers `cfl_acoustics` for the acoustics solver and `cfl_euler` for and flow solver,
82
respectively.
83
The mean values for the acoustic perturbation equations are read from `averaging_callback`
84
(see [`AveragingCallback`](@ref)).
85
"""
86
function EulerAcousticsCouplingCallback(ode_euler,
87
averaging_callback::DiscreteCallback{<:Any,
88
<:AveragingCallback},
89
alg, cfl_acoustics::Real, cfl_euler::Real;
90
kwargs...)
91
@unpack mean_values = averaging_callback.affect!
92
93
return EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,
94
cfl_euler;
95
kwargs...)
96
end
97
98
"""
99
EulerAcousticsCouplingCallback(ode_euler, averaging_file::AbstractString, alg,
100
cfl_acoustics::Real, cfl_euler::Real; kwargs...)
101
102
!!! warning "Experimental code"
103
This callback is experimental and may change in any future release.
104
105
Creates an [`EulerAcousticsCouplingCallback`](@ref) based on the pure flow `ODEProblem` given by
106
`ode_euler`. Creates an integrator using the time integration method `alg` and the keyword arguments
107
to solve `ode_euler` (consult the [OrdinaryDiffEq documentation](https://diffeq.sciml.ai/stable/)
108
for further information).
109
Manages the step size for both solvers by using the minimum of the maximum step size obtained with
110
CFL numbers `cfl_acoustics` for the acoustics solver and `cfl_euler` for and flow solver,
111
respectively.
112
The mean values for the acoustic perturbation equations are read from `averaging_file`
113
(see [`AveragingCallback`](@ref)).
114
"""
115
function EulerAcousticsCouplingCallback(ode_euler, averaging_file::AbstractString, alg,
116
cfl_acoustics::Real, cfl_euler::Real; kwargs...)
117
semi_euler = ode_euler.p
118
mean_values = load_averaging_file(averaging_file, semi_euler)
119
120
return EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,
121
cfl_euler;
122
kwargs...)
123
end
124
125
function EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,
126
cfl_euler;
127
kwargs...)
128
# Set up ODE Integrator for Euler equations
129
integrator_euler = init(ode_euler, alg, save_everystep = false, dt = 1.0; kwargs...) # dt will be overwritten
130
131
euler_acoustics_coupling = EulerAcousticsCouplingCallback{typeof(cfl_acoustics),
132
typeof(mean_values),
133
typeof(integrator_euler)}(StepsizeCallback(cfl_acoustics),
134
StepsizeCallback(cfl_euler),
135
mean_values,
136
integrator_euler)
137
condition = (u, t, integrator) -> true
138
139
return DiscreteCallback(condition, euler_acoustics_coupling,
140
save_positions = (false, false),
141
initialize = initialize!)
142
end
143
144
# This is called before the main loop and initializes the mean values in u_ode
145
function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t,
146
integrator_acoustics) where {Condition,
147
Affect! <:
148
EulerAcousticsCouplingCallback}
149
euler_acoustics_coupling = cb.affect!
150
semi = integrator_acoustics.p
151
@unpack semi_acoustics = semi
152
153
# Initialize mean values in u_ode
154
u_acoustics = wrap_array(u_ode, semi_acoustics)
155
@unpack mean_values = euler_acoustics_coupling
156
@views @. u_acoustics[4:5, .., :] = mean_values.v_mean
157
@views @. u_acoustics[6, .., :] = mean_values.c_mean
158
@views @. u_acoustics[7, .., :] = mean_values.rho_mean
159
160
# Adjust stepsize, advance the flow solver by one time step
161
cb.affect!(integrator_acoustics)
162
163
return nothing
164
end
165
166
# This function is called at the end of every time step and advances the Euler solution by one
167
# time step, manages the time stepsize for both the acoustics and Euler solvers and calculates the
168
# acoustic sources for the next acoustics time step
169
function (euler_acoustics_coupling::EulerAcousticsCouplingCallback)(integrator_acoustics)
170
@unpack stepsize_callback_acoustics, stepsize_callback_euler, integrator_euler = euler_acoustics_coupling
171
172
@assert integrator_acoustics.t == integrator_euler.t
173
174
# Use the minimum of the acoustics and Euler stepsizes for both solvers
175
stepsize_callback_acoustics(integrator_acoustics)
176
stepsize_callback_euler(integrator_euler)
177
dt = min(get_proposed_dt(integrator_acoustics), get_proposed_dt(integrator_euler))
178
179
set_proposed_dt!(integrator_acoustics, dt)
180
integrator_acoustics.opts.dtmax = dt
181
integrator_acoustics.dtcache = dt
182
183
set_proposed_dt!(integrator_euler, dt)
184
integrator_euler.opts.dtmax = dt
185
integrator_euler.dtcache = dt
186
187
# Advance the Euler solution by one step and check for errors
188
if !isfinished(integrator_euler)
189
@trixi_timeit timer() "Euler solver" step!(integrator_euler)
190
return_code = check_error(integrator_euler)
191
if !(SciMLBase.successful_retcode(return_code) ||
192
return_code != SciMLBase.ReturnCode.Default)
193
error("Error during compressible Euler time integration. Received return code $(return_code)")
194
end
195
end
196
197
# Calculate acoustic sources based on linearized lamb vector
198
semi = integrator_acoustics.p
199
semi_euler = integrator_euler.p
200
u_acoustics = wrap_array(integrator_acoustics.u, semi)
201
u_euler = wrap_array(integrator_euler.u, semi_euler)
202
@unpack acoustic_source_terms, coupled_element_ids = semi.cache
203
@unpack vorticity_mean = euler_acoustics_coupling.mean_values
204
205
@trixi_timeit timer() "calc acoustic source terms" begin
206
calc_acoustic_sources!(acoustic_source_terms, u_euler, u_acoustics,
207
vorticity_mean, coupled_element_ids,
208
mesh_equations_solver_cache(semi_euler)...)
209
end
210
211
# avoid re-evaluation possible FSAL stages
212
u_modified!(integrator_acoustics, false)
213
u_modified!(integrator_euler, false)
214
215
return nothing
216
end
217
218
include("euler_acoustics_coupling_dg2d.jl")
219
end # @muladd
220
221