Path: blob/main/src/callbacks_step/visualization.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: noindent67struct VisualizationCallback{PlotDataCreator, SolutionVariables, VariableNames,8PlotCreator}9plot_data_creator::PlotDataCreator10interval::Int11solution_variables::SolutionVariables12variable_names::VariableNames13show_mesh::Bool14plot_creator::PlotCreator15plot_arguments::Dict{Symbol, Any}16end1718function Base.show(io::IO,19cb::DiscreteCallback{Condition, Affect!}) where {Condition,20Affect! <:21VisualizationCallback22}23visualization_callback = cb.affect!24@unpack plot_data_creator, interval, plot_arguments, solution_variables, variable_names, show_mesh, plot_creator = visualization_callback25print(io, "VisualizationCallback(",26"plot_data_creator=", plot_data_creator, ", ",27"interval=", interval, ", ",28"solution_variables=", solution_variables, ", ",29"variable_names=", variable_names, ", ",30"show_mesh=", show_mesh, ", ",31"plot_creator=", plot_creator, ", ",32"plot_arguments=", plot_arguments, ")")33return nothing34end3536function Base.show(io::IO, ::MIME"text/plain",37cb::DiscreteCallback{Condition, Affect!}) where {Condition,38Affect! <:39VisualizationCallback40}41if get(io, :compact, false)42show(io, cb)43else44visualization_callback = cb.affect!4546setup = [47"plot data creator" => visualization_callback.plot_data_creator,48"interval" => visualization_callback.interval,49"plot arguments" => visualization_callback.plot_arguments,50"solution variables" => visualization_callback.solution_variables,51"variable names" => visualization_callback.variable_names,52"show mesh" => visualization_callback.show_mesh,53"plot creator" => visualization_callback.plot_creator54]55summary_box(io, "VisualizationCallback", setup)56end57end5859"""60VisualizationCallback(semi, plot_data_creator = nothing;61interval=0,62solution_variables=cons2prim,63variable_names=[],64show_mesh=false,65plot_creator=show_plot,66plot_arguments...)6768Create a callback that visualizes results during a simulation, also known as *in-situ69visualization*.7071To customize the generated figure, `plot_data_creator` allows to use different plot data types.72Currently provided are [`PlotData1D`](@ref) and [`PlotData2D`](@ref), while the latter is used for both 2D and 3D.7374The `interval` specifies the number of time step iterations after which a new plot is generated. The75available variables to plot are configured with the `solution_variables` parameter, which acts the76same way as for the [`SaveSolutionCallback`](@ref). The variables to be actually plotted can be77selected by providing a single string or a list of strings to `variable_names`, and if `show_mesh`78is `true`, an additional plot with the mesh will be generated.7980With `plot_creator` you can further specify an own function to visualize results, which must support the81same interface as the default implementation [`show_plot`](@ref). All remaining82keyword arguments are collected and passed as additional arguments to the plotting command.83"""84function VisualizationCallback(semi, plot_data_creator = nothing;85interval = 0,86solution_variables = cons2prim,87variable_names = [],88show_mesh = false,89plot_creator = show_plot,90plot_arguments...)91mpi_isparallel() && error("this callback does not work in parallel yet")9293if variable_names isa String94variable_names = String[variable_names]95end9697if plot_data_creator === nothing # No custom plot data type provided98if ndims(semi) == 199plot_data_creator = PlotData1D100else # 2D or 3D101plot_data_creator = PlotData2D102end103end104105visualization_callback = VisualizationCallback(plot_data_creator,106interval,107solution_variables, variable_names,108show_mesh,109plot_creator,110Dict{Symbol, Any}(plot_arguments))111112return DiscreteCallback(visualization_callback, visualization_callback, # the first one is the condition, the second the affect!113save_positions = (false, false),114initialize = initialize!)115end116117function initialize!(cb::DiscreteCallback{Condition, Affect!}, u, t,118integrator) where {Condition, Affect! <: VisualizationCallback}119visualization_callback = cb.affect!120121visualization_callback(integrator)122123return nothing124end125126# this method is called to determine whether the callback should be activated127function (visualization_callback::VisualizationCallback)(u, t, integrator)128@unpack interval = visualization_callback129130# With error-based step size control, some steps can be rejected. Thus,131# `integrator.iter >= integrator.stats.naccept`132# (total #steps) (#accepted steps)133# We need to check the number of accepted steps since callbacks are not134# activated after a rejected step.135return interval > 0 && (integrator.stats.naccept % interval == 0 ||136isfinished(integrator))137end138139# this method is called when the callback is activated140function (visualization_callback::VisualizationCallback)(integrator)141u_ode = integrator.u142semi = integrator.p143@unpack plot_data_creator, plot_arguments, solution_variables, variable_names, show_mesh, plot_creator = visualization_callback144145# Extract plot data146plot_data = plot_data_creator(u_ode, semi, solution_variables = solution_variables)147148# If variable names were not specified, plot everything149if isempty(variable_names)150variable_names = String[keys(plot_data)...]151end152153# Create plot154plot_creator(plot_data, variable_names;155show_mesh = show_mesh, plot_arguments = plot_arguments,156time = integrator.t, timestep = integrator.stats.naccept)157158# avoid re-evaluating possible FSAL stages159u_modified!(integrator, false)160return nothing161end162163"""164show_plot(plot_data, variable_names;165show_mesh=true, plot_arguments=Dict{Symbol,Any}(),166time=nothing, timestep=nothing)167168Visualize the plot data object provided in `plot_data` and display result, plotting only the169variables in `variable_names` and, optionally, the mesh (if `show_mesh` is `true`). Additionally,170`plot_arguments` will be unpacked and passed as keyword arguments to the `Plots.plot` command.171172This function is the default `plot_creator` argument for the [`VisualizationCallback`](@ref).173`time` and `timestep` are currently unused by this function.174175!!! note176This requires loading [Plots.jl](https://github.com/JuliaPlots/Plots.jl), e.g., via `using Plots`.177178See also: [`VisualizationCallback`](@ref), [`save_plot`](@ref)179"""180function show_plot end181182"""183save_plot(plot_data, variable_names;184show_mesh=true, plot_arguments=Dict{Symbol,Any}(),185time=nothing, timestep=nothing)186187Visualize the plot data object provided in `plot_data` and save result as a PNG file in the `out`188directory, plotting only the variables in `variable_names` and, optionally, the mesh (if `show_mesh`189is `true`). Additionally, `plot_arguments` will be unpacked and passed as keyword arguments to the190`Plots.plot` command.191192The `timestep` is used in the filename. `time` is currently unused by this function.193194!!! note195This requires loading [Plots.jl](https://github.com/JuliaPlots/Plots.jl), e.g., via `using Plots`.196197See also: [`VisualizationCallback`](@ref), [`show_plot`](@ref)198"""199function save_plot end200end # @muladd201202203