Path: blob/main/src/callbacks_step/euler_acoustics_coupling.jl
5586 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, RealT}39stepsize_callback_euler::StepsizeCallback{RealT, 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, ")")52return nothing53end5455function Base.show(io::IO, ::MIME"text/plain",56cb::DiscreteCallback{<:Any, <:EulerAcousticsCouplingCallback})57@nospecialize cb # reduce precompilation time58euler_acoustics_coupling = cb.affect!5960summary_header(io, "EulerAcousticsCouplingCallback")61summary_line(io, "acoustics StepsizeCallback",62euler_acoustics_coupling.stepsize_callback_acoustics)63summary_line(io, "Euler StepsizeCallback",64euler_acoustics_coupling.stepsize_callback_euler)65summary_footer(io)66return nothing67end6869"""70EulerAcousticsCouplingCallback(ode_euler,71averaging_callback::DiscreteCallback{<:Any, <:AveragingCallback},72alg, cfl_acoustics::Real, cfl_euler::Real; kwargs...)7374!!! warning "Experimental code"75This callback is experimental and may change in any future release.7677Creates an [`EulerAcousticsCouplingCallback`](@ref) based on the pure flow `ODEProblem` given by78`ode_euler`. Creates an integrator using the time integration method `alg` and the keyword arguments79to solve `ode_euler` (consult the [OrdinaryDiffEq documentation](https://diffeq.sciml.ai/stable/)80for further information).81Manages the step size for both solvers by using the minimum of the maximum step size obtained with82CFL numbers `cfl_acoustics` for the acoustics solver and `cfl_euler` for and flow solver,83respectively.84The mean values for the acoustic perturbation equations are read from `averaging_callback`85(see [`AveragingCallback`](@ref)).86"""87function EulerAcousticsCouplingCallback(ode_euler,88averaging_callback::DiscreteCallback{<:Any,89<:AveragingCallback},90alg, cfl_acoustics::Real, cfl_euler::Real;91kwargs...)92@unpack mean_values = averaging_callback.affect!9394return EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,95cfl_euler;96kwargs...)97end9899"""100EulerAcousticsCouplingCallback(ode_euler, averaging_file::AbstractString, alg,101cfl_acoustics::Real, cfl_euler::Real; kwargs...)102103!!! warning "Experimental code"104This callback is experimental and may change in any future release.105106Creates an [`EulerAcousticsCouplingCallback`](@ref) based on the pure flow `ODEProblem` given by107`ode_euler`. Creates an integrator using the time integration method `alg` and the keyword arguments108to solve `ode_euler` (consult the [OrdinaryDiffEq documentation](https://diffeq.sciml.ai/stable/)109for further information).110Manages the step size for both solvers by using the minimum of the maximum step size obtained with111CFL numbers `cfl_acoustics` for the acoustics solver and `cfl_euler` for and flow solver,112respectively.113The mean values for the acoustic perturbation equations are read from `averaging_file`114(see [`AveragingCallback`](@ref)).115"""116function EulerAcousticsCouplingCallback(ode_euler, averaging_file::AbstractString, alg,117cfl_acoustics::Real, cfl_euler::Real; kwargs...)118semi_euler = ode_euler.p119mean_values = load_averaging_file(averaging_file, semi_euler)120121return EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,122cfl_euler;123kwargs...)124end125126function EulerAcousticsCouplingCallback(ode_euler, mean_values, alg, cfl_acoustics,127cfl_euler;128kwargs...)129# Set up ODE Integrator for Euler equations130integrator_euler = init(ode_euler, alg, save_everystep = false, dt = 1.0; kwargs...) # dt will be overwritten131132euler_acoustics_coupling = EulerAcousticsCouplingCallback{typeof(cfl_acoustics),133typeof(mean_values),134typeof(integrator_euler)}(StepsizeCallback(cfl_acoustics),135StepsizeCallback(cfl_euler),136mean_values,137integrator_euler)138condition = (u, t, integrator) -> true139140return DiscreteCallback(condition, euler_acoustics_coupling,141save_positions = (false, false),142initialize = initialize!)143end144145# This is called before the main loop and initializes the mean values in u_ode146function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t,147integrator_acoustics) where {Condition,148Affect! <:149EulerAcousticsCouplingCallback}150euler_acoustics_coupling = cb.affect!151semi = integrator_acoustics.p152@unpack semi_acoustics = semi153154# Initialize mean values in u_ode155u_acoustics = wrap_array(u_ode, semi_acoustics)156@unpack mean_values = euler_acoustics_coupling157@views @. u_acoustics[4:5, .., :] = mean_values.v_mean158@views @. u_acoustics[6, .., :] = mean_values.c_mean159@views @. u_acoustics[7, .., :] = mean_values.rho_mean160161# Adjust stepsize, advance the flow solver by one time step162cb.affect!(integrator_acoustics)163164return nothing165end166167# This function is called at the end of every time step and advances the Euler solution by one168# time step, manages the time stepsize for both the acoustics and Euler solvers and calculates the169# acoustic sources for the next acoustics time step170function (euler_acoustics_coupling::EulerAcousticsCouplingCallback)(integrator_acoustics)171@unpack stepsize_callback_acoustics, stepsize_callback_euler, integrator_euler = euler_acoustics_coupling172173@assert integrator_acoustics.t == integrator_euler.t174175# Use the minimum of the acoustics and Euler stepsizes for both solvers176stepsize_callback_acoustics(integrator_acoustics)177stepsize_callback_euler(integrator_euler)178dt = min(get_proposed_dt(integrator_acoustics), get_proposed_dt(integrator_euler))179180set_proposed_dt!(integrator_acoustics, dt)181integrator_acoustics.opts.dtmax = dt182integrator_acoustics.dtcache = dt183184set_proposed_dt!(integrator_euler, dt)185integrator_euler.opts.dtmax = dt186integrator_euler.dtcache = dt187188# Advance the Euler solution by one step and check for errors189if !isfinished(integrator_euler)190@trixi_timeit timer() "Euler solver" step!(integrator_euler)191return_code = check_error(integrator_euler)192if !(SciMLBase.successful_retcode(return_code) ||193return_code != SciMLBase.ReturnCode.Default)194error("Error during compressible Euler time integration. Received return code $(return_code)")195end196end197198# Calculate acoustic sources based on linearized lamb vector199semi = integrator_acoustics.p200semi_euler = integrator_euler.p201u_acoustics = wrap_array(integrator_acoustics.u, semi)202u_euler = wrap_array(integrator_euler.u, semi_euler)203@unpack acoustic_source_terms, coupled_element_ids = semi.cache204@unpack vorticity_mean = euler_acoustics_coupling.mean_values205206@trixi_timeit timer() "calc acoustic source terms" begin207calc_acoustic_sources!(acoustic_source_terms, u_euler, u_acoustics,208vorticity_mean, coupled_element_ids,209mesh_equations_solver_cache(semi_euler)...)210end211212# avoid re-evaluation possible FSAL stages213u_modified!(integrator_acoustics, false)214u_modified!(integrator_euler, false)215216return nothing217end218219include("euler_acoustics_coupling_dg2d.jl")220end # @muladd221222223