Path: blob/main/src/callbacks_step/euler_acoustics_coupling.jl
2055 views
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).1# Since these FMAs can increase the performance of many numerical algorithms,2# we need to opt-in explicitly.3# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.4@muladd begin5#! format: noindent67@doc raw"""8EulerAcousticsCouplingCallback910!!! warning "Experimental code"11This callback is experimental and may change in any future release.1213A callback that couples the acoustic perturbation equations and compressible Euler equations. Must14be used in conjunction with [`SemidiscretizationEulerAcoustics`](@ref).15This callback manages the flow solver - which is always one time step ahead of the16acoustics solver - and calculates the acoustic source term after each time step. The linearized17Lamb vector is used as the source term, i.e.18```math19\mathbf{s} = -(\mathbf{\omega'} \times \bar{\mathbf{v}}20+ \bar{\mathbf{\omega}} \times \mathbf{v'}),21```22where ``\mathbf{v}`` denotes the velocity, ``\mathbf{\omega}`` denotes the vorticity, the bar23``\bar{(\cdot)}`` indicates time-averaged quantities (see [`AveragingCallback`](@ref)) and prime24``(\cdot)'`` denotes perturbed quantities defined by ``\phi' = \phi - \bar{\phi}``. Note that25the perturbed quantities here are based entirely on the pure flow solution and should not be26confused with the state variables of the acoustic perturbation equations.2728In addition, this callback manages the time step size for both solvers29and initializes the mean values of the acoustic perturbation equations using results obtained with30the [`AveragingCallback`](@ref).3132- Michael Schlottke-Lakemper (2017)33A direct-hybrid method for aeroacoustic analysis34[DOI: 10.18154/RWTH-2017-04082](https://doi.org/10.18154/RWTH-2017-04082)35"""36mutable struct EulerAcousticsCouplingCallback{RealT <: Real, MeanValues,37IntegratorEuler}38stepsize_callback_acoustics::StepsizeCallback{RealT}39stepsize_callback_euler::StepsizeCallback{RealT}40mean_values::MeanValues41integrator_euler::IntegratorEuler42end4344function Base.show(io::IO,45cb::DiscreteCallback{<:Any, <:EulerAcousticsCouplingCallback})46@nospecialize cb # reduce precompilation time47euler_acoustics_coupling = cb.affect!4849print(io, "EulerAcousticsCouplingCallback(")50print(io, euler_acoustics_coupling.stepsize_callback_acoustics)51print(io, ", ", euler_acoustics_coupling.stepsize_callback_euler, ")")52end5354function Base.show(io::IO, ::MIME"text/plain",55cb::DiscreteCallback{<:Any, <:EulerAcousticsCouplingCallback})56@nospecialize cb # reduce precompilation time57euler_acoustics_coupling = cb.affect!5859summary_header(io, "EulerAcousticsCouplingCallback")60summary_line(io, "acoustics StepsizeCallback",61euler_acoustics_coupling.stepsize_callback_acoustics)62summary_line(io, "Euler StepsizeCallback",63euler_acoustics_coupling.stepsize_callback_euler)64summary_footer(io)65end6667"""68EulerAcousticsCouplingCallback(ode_euler,69averaging_callback::DiscreteCallback{<:Any, <:AveragingCallback},70alg, cfl_acoustics::Real, cfl_euler::Real; kwargs...)7172!!! warning "Experimental code"73This callback is experimental and may change in any future release.7475Creates an [`EulerAcousticsCouplingCallback`](@ref) based on the pure flow `ODEProblem` given by76`ode_euler`. Creates an integrator using the time integration method `alg` and the keyword arguments77to solve `ode_euler` (consult the [OrdinaryDiffEq documentation](https://diffeq.sciml.ai/stable/)78for further information).79Manages the step size for both solvers by using the minimum of the maximum step size obtained with80CFL numbers `cfl_acoustics` for the acoustics solver and `cfl_euler` for and flow solver,81respectively.82The mean values for the acoustic perturbation equations are read from `averaging_callback`83(see [`AveragingCallback`](@ref)).84"""85function EulerAcousticsCouplingCallback(ode_euler,86averaging_callback::DiscreteCallback{<:Any,87<:AveragingCallback},88alg, cfl_acoustics::Real, cfl_euler::Real;89kwargs...)90@unpack mean_values = averaging_callback.affect!9192return EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,93cfl_euler;94kwargs...)95end9697"""98EulerAcousticsCouplingCallback(ode_euler, averaging_file::AbstractString, alg,99cfl_acoustics::Real, cfl_euler::Real; kwargs...)100101!!! warning "Experimental code"102This callback is experimental and may change in any future release.103104Creates an [`EulerAcousticsCouplingCallback`](@ref) based on the pure flow `ODEProblem` given by105`ode_euler`. Creates an integrator using the time integration method `alg` and the keyword arguments106to solve `ode_euler` (consult the [OrdinaryDiffEq documentation](https://diffeq.sciml.ai/stable/)107for further information).108Manages the step size for both solvers by using the minimum of the maximum step size obtained with109CFL numbers `cfl_acoustics` for the acoustics solver and `cfl_euler` for and flow solver,110respectively.111The mean values for the acoustic perturbation equations are read from `averaging_file`112(see [`AveragingCallback`](@ref)).113"""114function EulerAcousticsCouplingCallback(ode_euler, averaging_file::AbstractString, alg,115cfl_acoustics::Real, cfl_euler::Real; kwargs...)116semi_euler = ode_euler.p117mean_values = load_averaging_file(averaging_file, semi_euler)118119return EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,120cfl_euler;121kwargs...)122end123124function EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,125cfl_euler;126kwargs...)127# Set up ODE Integrator for Euler equations128integrator_euler = init(ode_euler, alg, save_everystep = false, dt = 1.0; kwargs...) # dt will be overwritten129130euler_acoustics_coupling = EulerAcousticsCouplingCallback{typeof(cfl_acoustics),131typeof(mean_values),132typeof(integrator_euler)}(StepsizeCallback(cfl_acoustics),133StepsizeCallback(cfl_euler),134mean_values,135integrator_euler)136condition = (u, t, integrator) -> true137138return DiscreteCallback(condition, euler_acoustics_coupling,139save_positions = (false, false),140initialize = initialize!)141end142143# This is called before the main loop and initializes the mean values in u_ode144function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t,145integrator_acoustics) where {Condition,146Affect! <:147EulerAcousticsCouplingCallback}148euler_acoustics_coupling = cb.affect!149semi = integrator_acoustics.p150@unpack semi_acoustics = semi151152# Initialize mean values in u_ode153u_acoustics = wrap_array(u_ode, semi_acoustics)154@unpack mean_values = euler_acoustics_coupling155@views @. u_acoustics[4:5, .., :] = mean_values.v_mean156@views @. u_acoustics[6, .., :] = mean_values.c_mean157@views @. u_acoustics[7, .., :] = mean_values.rho_mean158159# Adjust stepsize, advance the flow solver by one time step160cb.affect!(integrator_acoustics)161162return nothing163end164165# This function is called at the end of every time step and advances the Euler solution by one166# time step, manages the time stepsize for both the acoustics and Euler solvers and calculates the167# acoustic sources for the next acoustics time step168function (euler_acoustics_coupling::EulerAcousticsCouplingCallback)(integrator_acoustics)169@unpack stepsize_callback_acoustics, stepsize_callback_euler, integrator_euler = euler_acoustics_coupling170171@assert integrator_acoustics.t == integrator_euler.t172173# Use the minimum of the acoustics and Euler stepsizes for both solvers174stepsize_callback_acoustics(integrator_acoustics)175stepsize_callback_euler(integrator_euler)176dt = min(get_proposed_dt(integrator_acoustics), get_proposed_dt(integrator_euler))177178set_proposed_dt!(integrator_acoustics, dt)179integrator_acoustics.opts.dtmax = dt180integrator_acoustics.dtcache = dt181182set_proposed_dt!(integrator_euler, dt)183integrator_euler.opts.dtmax = dt184integrator_euler.dtcache = dt185186# Advance the Euler solution by one step and check for errors187if !isfinished(integrator_euler)188@trixi_timeit timer() "Euler solver" step!(integrator_euler)189return_code = check_error(integrator_euler)190if !(SciMLBase.successful_retcode(return_code) ||191return_code != SciMLBase.ReturnCode.Default)192error("Error during compressible Euler time integration. Received return code $(return_code)")193end194end195196# Calculate acoustic sources based on linearized lamb vector197semi = integrator_acoustics.p198semi_euler = integrator_euler.p199u_acoustics = wrap_array(integrator_acoustics.u, semi)200u_euler = wrap_array(integrator_euler.u, semi_euler)201@unpack acoustic_source_terms, coupled_element_ids = semi.cache202@unpack vorticity_mean = euler_acoustics_coupling.mean_values203204@trixi_timeit timer() "calc acoustic source terms" begin205calc_acoustic_sources!(acoustic_source_terms, u_euler, u_acoustics,206vorticity_mean, coupled_element_ids,207mesh_equations_solver_cache(semi_euler)...)208end209210# avoid re-evaluation possible FSAL stages211u_modified!(integrator_acoustics, false)212u_modified!(integrator_euler, false)213214return nothing215end216217include("euler_acoustics_coupling_dg2d.jl")218end # @muladd219220221