Path: blob/main/src/callbacks_step/averaging.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"""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, ")")34return nothing35end3637function Base.show(io::IO, ::MIME"text/plain",38cb::DiscreteCallback{<:Any, <:AveragingCallback})39@nospecialize cb # reduce precompilation time4041if get(io, :compact, false)42show(io, cb)43else44averaging_callback = cb.affect!4546setup = [47"Start time" => first(averaging_callback.tspan),48"Final time" => last(averaging_callback.tspan)49]50summary_box(io, "AveragingCallback", setup)51end52end5354function AveragingCallback(semi::SemidiscretizationHyperbolic{<:Any,55<:CompressibleEulerEquations2D},56tspan; output_directory = "out", filename = "averaging.h5")57mesh, equations, solver, cache = mesh_equations_solver_cache(semi)58mean_values = initialize_mean_values(mesh, equations, solver, cache)59cache = create_cache(AveragingCallback, mesh, equations, solver, cache)6061averaging_callback = AveragingCallback(tspan, mean_values, cache, output_directory,62filename)63condition = (u, t, integrator) -> first(tspan) <= t <= last(tspan)6465return DiscreteCallback(condition, averaging_callback,66save_positions = (false, false),67initialize = initialize!)68end6970function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t,71integrator) where {Condition, Affect! <: AveragingCallback}72averaging_callback = cb.affect!73semi = integrator.p74mesh, equations, solver, cache = mesh_equations_solver_cache(semi)75u = wrap_array(u_ode, mesh, equations, solver, cache)7677@trixi_timeit timer() "averaging" initialize_cache!(averaging_callback.cache, u,78mesh, equations, solver, cache)7980# avoid re-evaluating possible FSAL stages81u_modified!(integrator, false)82return nothing83end8485# This function is called during time integration and updates the mean values according to the86# trapezoidal rule87function (averaging_callback::AveragingCallback)(integrator)88@unpack mean_values = averaging_callback8990u_ode = integrator.u91u_prev_ode = integrator.uprev92semi = integrator.p93mesh, equations, solver, cache = mesh_equations_solver_cache(semi)94u = wrap_array(u_ode, mesh, equations, solver, cache)95u_prev = wrap_array(u_prev_ode, mesh, equations, solver, cache)9697dt = integrator.t - integrator.tprev98tspan = averaging_callback.tspan99100integration_constant = 0.5 * dt / (tspan[2] - tspan[1]) # .5 due to trapezoidal rule101102@trixi_timeit timer() "averaging" calc_mean_values!(mean_values,103averaging_callback.cache,104u, u_prev, integration_constant,105mesh, equations, solver, cache)106107# Store mean values in a file if this is the last time step108if isfinished(integrator)109save_averaging_file(averaging_callback, semi)110end111112# avoid re-evaluating possible FSAL stages113u_modified!(integrator, false)114115return nothing116end117118function save_averaging_file(averaging_callback, semi::AbstractSemidiscretization)119# Create output directory if it doesn't exist120mkpath(averaging_callback.output_directory)121122return save_averaging_file(averaging_callback, mesh_equations_solver_cache(semi)...)123end124125function load_averaging_file(averaging_file, semi::AbstractSemidiscretization)126return load_averaging_file(averaging_file, mesh_equations_solver_cache(semi)...)127end128129include("averaging_dg.jl")130include("averaging_dg2d.jl")131end # @muladd132133134