Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ for human readability.
In v0.13, `flux_lax_friedrichs = FluxLaxFriedrichs(max_abs_speed = max_abs_speed)`
instead of the previous default
`FluxLaxFriedrichs(max_abs_speed = max_abs_speed_naive)` ([#2458]).
- The signature of the `VisualizationCallback` constructor changed.
In the new version, it is mandatory to pass the semidiscretization `semi` to
determine the default plotting type (1D for 1D simulations, 2D for 2D and 3D simulations).
This can further be customized via the keyword argument `plot_data_creator`, which had
the default value `plot_data_creator = PlotData2D` before the change ([#2468]).

#### Removed

- Deprecations introduced in earlier versions of Trixi.jl have been removed.

Expand Down
7 changes: 6 additions & 1 deletion examples/tree_1d_dgsem/elixir_advection_extended.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using OrdinaryDiffEqLowStorageRK
using Trixi
using Plots # For visualization callback

###############################################################################
# semidiscretization of the linear advection equation
Expand Down Expand Up @@ -64,10 +65,14 @@ save_solution = SaveSolutionCallback(interval = 100,
# The StepsizeCallback handles the re-calculation of the maximum Δt after each time step
stepsize_callback = StepsizeCallback(cfl = 1.6)

# Enable in-situ visualization with a new plot generated at every time step
visualization = VisualizationCallback(semi; interval = 1)

# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver
callbacks = CallbackSet(summary_callback,
analysis_callback, alive_callback,
save_restart, save_solution,
save_restart,
save_solution, visualization,
stepsize_callback)

###############################################################################
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ save_solution = SaveSolutionCallback(interval = 100,

# Enable in-situ visualization with a new plot generated every 20 time steps
# and additional plotting options passed as keyword arguments
visualization = VisualizationCallback(interval = 20, clims = (0, 1))
visualization = VisualizationCallback(semi; interval = 20, clims = (0, 1))

amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first),
base_level = 3,
Expand Down
58 changes: 30 additions & 28 deletions src/callbacks_step/visualization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
@muladd begin
#! format: noindent

mutable struct VisualizationCallback{SolutionVariables, VariableNames, PlotDataCreator,
mutable struct VisualizationCallback{PlotDataCreator, SolutionVariables, VariableNames,
PlotCreator}
plot_data_creator::PlotDataCreator
interval::Int
solution_variables::SolutionVariables
variable_names::VariableNames
show_mesh::Bool
plot_data_creator::PlotDataCreator
plot_creator::PlotCreator
plot_arguments::Dict{Symbol, Any}
end
Expand All @@ -22,13 +22,13 @@ function Base.show(io::IO,
VisualizationCallback
}
visualization_callback = cb.affect!
@unpack interval, plot_arguments, solution_variables, variable_names, show_mesh, plot_creator, plot_data_creator = visualization_callback
@unpack plot_data_creator, interval, plot_arguments, solution_variables, variable_names, show_mesh, plot_creator = visualization_callback
print(io, "VisualizationCallback(",
"plot_data_creator=", plot_data_creator, ", ",
"interval=", interval, ", ",
"solution_variables=", solution_variables, ", ",
"variable_names=", variable_names, ", ",
"show_mesh=", show_mesh, ", ",
"plot_data_creator=", plot_data_creator, ", ",
"plot_creator=", plot_creator, ", ",
"plot_arguments=", plot_arguments, ")")
end
Expand All @@ -44,49 +44,48 @@ function Base.show(io::IO, ::MIME"text/plain",
visualization_callback = cb.affect!

setup = [
"plot data creator" => visualization_callback.plot_data_creator,
"interval" => visualization_callback.interval,
"plot arguments" => visualization_callback.plot_arguments,
"solution variables" => visualization_callback.solution_variables,
"variable names" => visualization_callback.variable_names,
"show mesh" => visualization_callback.show_mesh,
"plot creator" => visualization_callback.plot_creator,
"plot data creator" => visualization_callback.plot_data_creator
"plot creator" => visualization_callback.plot_creator
]
summary_box(io, "VisualizationCallback", setup)
end
end

"""
VisualizationCallback(; interval=0,
solution_variables=cons2prim,
variable_names=[],
show_mesh=false,
plot_data_creator=PlotData2D,
plot_creator=show_plot,
plot_arguments...)
VisualizationCallback(semi, plot_data_creator = nothing;
interval=0,
solution_variables=cons2prim,
variable_names=[],
show_mesh=false,
plot_creator=show_plot,
plot_arguments...)

Create a callback that visualizes results during a simulation, also known as *in-situ
visualization*.

!!! warning "Experimental implementation"
This is an experimental feature and may change in any future releases.
To customize the generated figure, `plot_data_creator` allows to use different plot data types.
Currently provided are [`PlotData1D`](@ref) and [`PlotData2D`](@ref), while the latter is used for both 2D and 3D.

The `interval` specifies the number of time step iterations after which a new plot is generated. The
available variables to plot are configured with the `solution_variables` parameter, which acts the
same way as for the [`SaveSolutionCallback`](@ref). The variables to be actually plotted can be
selected by providing a single string or a list of strings to `variable_names`, and if `show_mesh`
is `true`, an additional plot with the mesh will be generated.

To customize the generated figure, `plot_data_creator` allows to use different plot data types. With
`plot_creator` you can further specify an own function to visualize results, which must support the
With `plot_creator` you can further specify an own function to visualize results, which must support the
same interface as the default implementation [`show_plot`](@ref). All remaining
keyword arguments are collected and passed as additional arguments to the plotting command.
"""
function VisualizationCallback(; interval = 0,
function VisualizationCallback(semi, plot_data_creator = nothing;
interval = 0,
solution_variables = cons2prim,
variable_names = [],
show_mesh = false,
plot_data_creator = PlotData2D,
plot_creator = show_plot,
plot_arguments...)
mpi_isparallel() && error("this callback does not work in parallel yet")
Expand All @@ -95,10 +94,19 @@ function VisualizationCallback(; interval = 0,
variable_names = String[variable_names]
end

visualization_callback = VisualizationCallback(interval,
if plot_data_creator === nothing # No custom plot data type provided
if ndims(semi) == 1
plot_data_creator = PlotData1D
else # 2D or 3D
plot_data_creator = PlotData2D
end
end

visualization_callback = VisualizationCallback(plot_data_creator,
interval,
solution_variables, variable_names,
show_mesh,
plot_data_creator, plot_creator,
plot_creator,
Dict{Symbol, Any}(plot_arguments))

# Warn users if they create a visualization callback without having loaded the Plots package
Expand Down Expand Up @@ -145,7 +153,7 @@ end
function (visualization_callback::VisualizationCallback)(integrator)
u_ode = integrator.u
semi = integrator.p
@unpack plot_arguments, solution_variables, variable_names, show_mesh, plot_data_creator, plot_creator = visualization_callback
@unpack plot_data_creator, plot_arguments, solution_variables, variable_names, show_mesh, plot_creator = visualization_callback

# Extract plot data
plot_data = plot_data_creator(u_ode, semi, solution_variables = solution_variables)
Expand Down Expand Up @@ -177,9 +185,6 @@ variables in `variable_names` and, optionally, the mesh (if `show_mesh` is `true
This function is the default `plot_creator` argument for the [`VisualizationCallback`](@ref).
`time` and `timestep` are currently unused by this function.

!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.

See also: [`VisualizationCallback`](@ref), [`save_plot`](@ref)
"""
function show_plot(plot_data, variable_names;
Expand Down Expand Up @@ -229,9 +234,6 @@ is `true`). Additionally, `plot_arguments` will be unpacked and passed as keywo

The `timestep` is used in the filename. `time` is currently unused by this function.

!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.

See also: [`VisualizationCallback`](@ref), [`show_plot`](@ref)
"""
function save_plot(plot_data, variable_names;
Expand Down
10 changes: 0 additions & 10 deletions src/visualization/recipes_plots.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
#! format: noindent

# Visualize a single variable in a 2D plot (default: heatmap)
#
# Note: This is an experimental feature and may be changed in future releases without notice.
RecipesBase.@recipe function f(pds::PlotDataSeries{<:AbstractPlotData{2}})
@unpack plot_data, variable_id = pds
@unpack x, y, data, variable_names, orientation_x, orientation_y = plot_data
Expand All @@ -32,8 +30,6 @@ RecipesBase.@recipe function f(pds::PlotDataSeries{<:AbstractPlotData{2}})
end

# Visualize the mesh in a 2D plot
#
# Note: This is an experimental feature and may be changed in future releases without notice.
RecipesBase.@recipe function f(pm::PlotMesh{<:AbstractPlotData{2}})
@unpack plot_data = pm
@unpack x, y, mesh_vertices_x, mesh_vertices_y = plot_data
Expand All @@ -55,8 +51,6 @@ RecipesBase.@recipe function f(pm::PlotMesh{<:AbstractPlotData{2}})
end

# Visualize the mesh in a 2D plot
#
# Note: This is an experimental feature and may be changed in future releases without notice.
RecipesBase.@recipe function f(pm::PlotMesh{<:PlotData2DCartesian{<:Any,
<:AbstractVector{<:AbstractVector}}})
@unpack plot_data = pm
Expand All @@ -79,8 +73,6 @@ RecipesBase.@recipe function f(pm::PlotMesh{<:PlotData2DCartesian{<:Any,
end

# Plot all available variables at once for convenience
#
# Note: This is an experimental feature and may be changed in future releases without notice.
RecipesBase.@recipe function f(pd::AbstractPlotData)
# Create layout that is as square as possible, when there are more than 3 subplots.
# This is done with a preference for more columns than rows if not.
Expand Down Expand Up @@ -152,8 +144,6 @@ end

# Create a plot directly from a TrixiODESolution for convenience
# The plot is created by a PlotData1D or PlotData2D object.
#
# Note: This is an experimental feature and may be changed in future releases without notice.
RecipesBase.@recipe function f(sol::TrixiODESolution)
# Redirect everything to the recipes below
return sol.u[end], sol.prob.p
Expand Down
27 changes: 0 additions & 27 deletions src/visualization/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# This is a union of a Trixi.jl-specific SciMLBase.ODESolution and of Trixi.jl's own
# TimeIntegratorSolution.
#
# Note: This is an experimental feature and may be changed in future releases without notice.
#! format: off
const TrixiODESolution = Union{ODESolution{T, N, uType, uType2, DType, tType, rateType, discType, P} where
{T, N, uType, uType2, DType, tType, rateType, discType, P<:ODEProblem{uType_, tType_, isinplace, P_, F_} where
Expand Down Expand Up @@ -42,9 +41,6 @@ end
Base.getindex(pd::AbstractPlotData, variable_name)

Extract a single variable `variable_name` from `pd` for plotting with `Plots.plot`.

!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.
"""
function Base.getindex(pd::AbstractPlotData, variable_name)
variable_id = findfirst(isequal(variable_name), pd.variable_names)
Expand All @@ -63,9 +59,6 @@ Base.eltype(pd::AbstractPlotData) = Pair{String, PlotDataSeries{typeof(pd)}}

Holds all relevant data for creating 2D plots of multiple solution variables and to visualize the
mesh.

!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.
"""
struct PlotData2DCartesian{Coordinates, Data, VariableNames, Vertices} <:
AbstractPlotData{2}
Expand Down Expand Up @@ -123,9 +116,6 @@ end

Holds all relevant data for creating 1D plots of multiple solution variables and to visualize the
mesh.

!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.
"""
struct PlotData1D{Coordinates, Data, VariableNames, Vertices} <: AbstractPlotData{1}
x::Coordinates
Expand All @@ -146,8 +136,6 @@ function Base.show(io::IO, pd::PlotData1D)
end

# Auxiliary data structure for visualizing a single variable
#
# Note: This is an experimental feature and may be changed in future releases without notice.
struct PlotDataSeries{PD <: AbstractPlotData}
plot_data::PD
variable_id::Int
Expand Down Expand Up @@ -177,9 +165,6 @@ end
getmesh(pd::AbstractPlotData)

Extract grid lines from `pd` for plotting with `Plots.plot`.

!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.
"""
getmesh(pd::AbstractPlotData) = PlotMesh(pd)

Expand Down Expand Up @@ -207,9 +192,6 @@ When visualizing data from a three-dimensional simulation, a 2D slice is extract
The slice position is specified by a `point` that lies on it, which defaults to `(0.0, 0.0, 0.0)`.
Both of these values are ignored when visualizing 2D data.

!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.

# Examples
```julia
julia> using Trixi, Plots
Expand Down Expand Up @@ -294,9 +276,6 @@ end
Create a `PlotData2D` object from a solution object created by either `OrdinaryDiffEq.solve!` (which
returns a `SciMLBase.ODESolution`) or Trixi.jl's own `solve!` (which returns a
`TimeIntegratorSolution`).

!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.
"""
function PlotData2D(sol::TrixiODESolution; kwargs...)
PlotData2D(sol.u[end], sol.prob.p; kwargs...)
Expand Down Expand Up @@ -548,9 +527,6 @@ This applies analogously to three-dimensional simulations, where `slice` may be
Another way to visualize 2D/3D data is by creating a plot along a given curve.
This is done with the keyword argument `curve`. It can be set to a list of 2D/3D points
which define the curve. When using `curve` any other input from `slice` or `point` will be ignored.

!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.
"""
function PlotData1D(u_ode, semi; kwargs...)
PlotData1D(wrap_array_native(u_ode, semi),
Expand Down Expand Up @@ -761,9 +737,6 @@ end
Create a `PlotData1D` object from a solution object created by either `OrdinaryDiffEq.solve!`
(which returns a `SciMLBase.ODESolution`) or Trixi.jl's own `solve!` (which returns a
`TimeIntegratorSolution`).

!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.
"""
function PlotData1D(sol::TrixiODESolution; kwargs...)
PlotData1D(sol.u[end], sol.prob.p; kwargs...)
Expand Down
13 changes: 9 additions & 4 deletions test/test_tree_1d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,17 @@ end
l2=[0.00017373554109980247],
linf=[0.0006021275678165239],
maxiters=1,
initial_condition=Trixi.initial_condition_sin)
initial_condition=Trixi.initial_condition_sin,
visualization=TrivialCallback())
end

@trixi_testset "elixir_advection_extended.jl with initial_condition_constant" begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"),
l2=[2.441369287653687e-16],
linf=[4.440892098500626e-16],
maxiters=1,
initial_condition=initial_condition_constant)
initial_condition=initial_condition_constant,
visualization=TrivialCallback())
end

@trixi_testset "elixir_advection_extended.jl with initial_condition_linear_x" begin
Expand All @@ -82,7 +84,8 @@ end
maxiters=1,
initial_condition=Trixi.initial_condition_linear_x,
boundary_conditions=Trixi.boundary_condition_linear_x,
periodicity=false)
periodicity=false,
visualization=TrivialCallback())
end

@trixi_testset "elixir_advection_extended.jl with initial_condition_convergence_test" begin
Expand All @@ -92,7 +95,8 @@ end
maxiters=1,
initial_condition=initial_condition_convergence_test,
boundary_conditions=BoundaryConditionDirichlet(initial_condition_convergence_test),
periodicity=false)
periodicity=false,
visualization=TrivialCallback())
end
end

Expand Down Expand Up @@ -181,6 +185,7 @@ end
redirect_stderr(f) do
trixi_include(joinpath(EXAMPLES_DIR,
"elixir_advection_extended.jl"),
visualization = TrivialCallback(),
summary_callback = TrivialCallback(),
analysis_callback = TrivialCallback(),
alive_callback = TrivialCallback())
Expand Down
3 changes: 2 additions & 1 deletion test/test_visualization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,8 @@ end
@test_nowarn_mod trixi_include(@__MODULE__,
joinpath(examples_dir(), "tree_2d_dgsem",
"elixir_advection_amr_visualization.jl"),
visualization = VisualizationCallback(interval = 20,
visualization = VisualizationCallback(semi;
interval = 20,
clims = (0, 1),
plot_creator = Trixi.save_plot),
tspan = (0.0, 3.0))
Expand Down
Loading