Path: blob/main/src/callbacks_step/averaging.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"""8AveragingCallback(semi::SemidiscretizationHyperbolic, tspan; output_directory="out",9filename="averaging.h5")1011!!! warning "Experimental code"12This callback is experimental and may change in any future release.1314A callback that averages the flow field described by `semi` which must be a semidiscretization of15the compressible Euler equations in two dimensions. The callback records the mean velocity,16mean speed of sound, mean density, and mean vorticity for each node over the time interval given by17`tspan` and stores the results in an HDF5 file `filename` in the directory `output_directory`. Note18that this callback does not support adaptive mesh refinement ([`AMRCallback`](@ref)).19"""20struct AveragingCallback{TSpan, MeanValues, Cache}21tspan::TSpan22mean_values::MeanValues23cache::Cache24output_directory::String25filename::String26end2728function Base.show(io::IO, cb::DiscreteCallback{<:Any, <:AveragingCallback})29@nospecialize cb # reduce precompilation time30averaging_callback = cb.affect!31@unpack tspan = averaging_callback3233print(io, "AveragingCallback(tspan=", tspan, ")")34end3536function Base.show(io::IO, ::MIME"text/plain",37cb::DiscreteCallback{<:Any, <:AveragingCallback})38@nospecialize cb # reduce precompilation time3940if get(io, :compact, false)41show(io, cb)42else43averaging_callback = cb.affect!4445setup = [46"Start time" => first(averaging_callback.tspan),47"Final time" => last(averaging_callback.tspan)48]49summary_box(io, "AveragingCallback", setup)50end51end5253function AveragingCallback(semi::SemidiscretizationHyperbolic{<:Any,54<:CompressibleEulerEquations2D},55tspan; output_directory = "out", filename = "averaging.h5")56mesh, equations, solver, cache = mesh_equations_solver_cache(semi)57mean_values = initialize_mean_values(mesh, equations, solver, cache)58cache = create_cache(AveragingCallback, mesh, equations, solver, cache)5960averaging_callback = AveragingCallback(tspan, mean_values, cache, output_directory,61filename)62condition = (u, t, integrator) -> first(tspan) <= t <= last(tspan)6364return DiscreteCallback(condition, averaging_callback,65save_positions = (false, false),66initialize = initialize!)67end6869function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t,70integrator) where {Condition, Affect! <: AveragingCallback}71averaging_callback = cb.affect!72semi = integrator.p73mesh, equations, solver, cache = mesh_equations_solver_cache(semi)74u = wrap_array(u_ode, mesh, equations, solver, cache)7576@trixi_timeit timer() "averaging" initialize_cache!(averaging_callback.cache, u,77mesh, equations, solver, cache)7879# avoid re-evaluating possible FSAL stages80u_modified!(integrator, false)81return nothing82end8384# This function is called during time integration and updates the mean values according to the85# trapezoidal rule86function (averaging_callback::AveragingCallback)(integrator)87@unpack mean_values = averaging_callback8889u_ode = integrator.u90u_prev_ode = integrator.uprev91semi = integrator.p92mesh, equations, solver, cache = mesh_equations_solver_cache(semi)93u = wrap_array(u_ode, mesh, equations, solver, cache)94u_prev = wrap_array(u_prev_ode, mesh, equations, solver, cache)9596dt = integrator.t - integrator.tprev97tspan = averaging_callback.tspan9899integration_constant = 0.5 * dt / (tspan[2] - tspan[1]) # .5 due to trapezoidal rule100101@trixi_timeit timer() "averaging" calc_mean_values!(mean_values,102averaging_callback.cache,103u, u_prev, integration_constant,104mesh, equations, solver, cache)105106# Store mean values in a file if this is the last time step107if isfinished(integrator)108save_averaging_file(averaging_callback, semi)109end110111# avoid re-evaluating possible FSAL stages112u_modified!(integrator, false)113114return nothing115end116117function save_averaging_file(averaging_callback, semi::AbstractSemidiscretization)118# Create output directory if it doesn't exist119mkpath(averaging_callback.output_directory)120121save_averaging_file(averaging_callback, mesh_equations_solver_cache(semi)...)122end123124function load_averaging_file(averaging_file, semi::AbstractSemidiscretization)125load_averaging_file(averaging_file, mesh_equations_solver_cache(semi)...)126end127128include("averaging_dg.jl")129include("averaging_dg2d.jl")130end # @muladd131132133