Skip to content

Commit

Permalink
Merge branch 'main' into hr/ics
Browse files Browse the repository at this point in the history
  • Loading branch information
ranocha authored Sep 12, 2021
2 parents c695909 + d064627 commit 4d9e924
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 71 deletions.
2 changes: 1 addition & 1 deletion docs/src/visualization.md
Original file line number Diff line number Diff line change
Expand Up @@ -415,5 +415,5 @@ Both `plot` and `iplot` use `colormap = :inferno` by default.
by providing an appropriate keyword argument. For example, `plot(sol, colormap=:blues)` and
`iplot(sol, colormap=:blues)` produce the following figures:

![makie-plot-example](https://user-images.githubusercontent.com/1156048/131539853-2ab51c33-5fd3-4d3b-a49b-3b1de8f63a98.png)
![makie-plot-example](https://user-images.githubusercontent.com/1156048/132954265-e7d395a8-f894-4056-841b-87711b7ba012.png)
![makie-iplot-example](https://user-images.githubusercontent.com/1156048/131613266-8a86a074-62fb-49d6-bf6b-8df94d2a9b65.png)
24 changes: 15 additions & 9 deletions src/visualization/recipes_makie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ function Makie.plot!(myplot::TrixiHeatmap)
pd = pds.plot_data
solution_z = vec(StructArrays.component(pd.data, variable_id))
Makie.mesh!(myplot, plotting_mesh, color=solution_z, shading=false, colormap=myplot[:colormap])
myplot.colorrange=extrema(solution_z)
myplot.colorrange = extrema(solution_z)

# Makie hides keyword arguments within `myplot`; see also
# https://github.com/JuliaPlots/Makie.jl/issues/837#issuecomment-845985070
Expand All @@ -145,11 +145,11 @@ function Makie.plot!(myplot::TrixiHeatmap)
end

# redirects Makie.plot(pd::PlotDataSeries) to custom recipe TrixiHeatmap(pd)
Makie.plottype(::Trixi.PlotDataSeries{<:Trixi.UnstructuredPlotData2D}) = TrixiHeatmap
Makie.plottype(::Trixi.PlotDataSeries{<:Trixi.PlotData2DTriangulated}) = TrixiHeatmap

# Makie does not yet support layouts in its plot recipes, so we overload `Makie.plot` directly.
function Makie.plot(sol::TrixiODESolution;
plot_mesh=true, solution_variables=nothing, colormap=default_Makie_colormap())
plot_mesh=false, solution_variables=nothing, colormap=default_Makie_colormap())
return Makie.plot(PlotData2D(sol; solution_variables); plot_mesh, colormap)
end

Expand All @@ -160,7 +160,7 @@ struct FigureAndAxes{Axes}
end

# for "quiet" return arguments to Makie.plot(::TrixiODESolution) and
# Makie.plot(::UnstructuredPlotData2D)
# Makie.plot(::PlotData2DTriangulated)
Base.show(io::IO, fa::FigureAndAxes) = nothing

# allows for returning fig, axes = Makie.plot(...)
Expand All @@ -174,15 +174,15 @@ function Base.iterate(fa::FigureAndAxes, state=1)
end
end

function Makie.plot(pd::UnstructuredPlotData2D, fig=Makie.Figure();
plot_mesh=true, colormap=default_Makie_colormap())
function Makie.plot(pd::PlotData2DTriangulated, fig=Makie.Figure();
plot_mesh=false, colormap=default_Makie_colormap())
figAxes = Makie.plot!(fig, pd; plot_mesh, colormap)
display(figAxes.fig)
return figAxes
end

function Makie.plot!(fig, pd::UnstructuredPlotData2D;
plot_mesh=true, colormap=default_Makie_colormap())
function Makie.plot!(fig, pd::PlotData2DTriangulated;
plot_mesh=false, colormap=default_Makie_colormap())
# 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.
if length(pd) <= 3
Expand All @@ -194,10 +194,16 @@ function Makie.plot!(fig, pd::UnstructuredPlotData2D;
end

axes = [Makie.Axis(fig[i,j], xlabel="x", ylabel="y") for j in 1:rows, i in 1:cols]
row_list, col_list = [i for j in 1:rows, i in 1:cols], [j for j in 1:rows, i in 1:cols]

for (variable_to_plot, (variable_name, pds)) in enumerate(pd)
ax = axes[variable_to_plot]
trixiheatmap!(ax, pds; plot_mesh, colormap)
plt = trixiheatmap!(ax, pds; plot_mesh, colormap)

row = row_list[variable_to_plot]
col = col_list[variable_to_plot]
Makie.Colorbar(fig[row, col][1,2], plt)

ax.aspect = Makie.DataAspect() # equal aspect ratio
ax.title = variable_name
Makie.xlims!(ax, extrema(pd.x))
Expand Down
41 changes: 5 additions & 36 deletions src/visualization/recipes_plots.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,37 +30,6 @@ RecipesBase.@recipe function f(pds::PlotDataSeries{<:AbstractPlotData{2}})
x, y, data[variable_id]
end


# Visualize a single variable in a 2D plot. Only works for `scatter` right now.
#
# Note: This is an experimental feature and may be changed in future releases without notice.
RecipesBase.@recipe function f(pds::PlotDataSeries{<:PlotData2D{<:Any, <:AbstractVector{<:AbstractVector}}})
@unpack plot_data, variable_id = pds
@unpack x, y, data, variable_names, orientation_x, orientation_y = plot_data

# Set geometric properties
xlims --> (minimum(x), maximum(x))
ylims --> (minimum(y), maximum(y))
aspect_ratio --> :equal

# Set annotation properties
legend --> :none
title --> variable_names[variable_id]
colorbar --> :true
xguide --> _get_guide(orientation_x)
yguide --> _get_guide(orientation_y)

# Set series properties
seriestype --> :scatter
markerstrokewidth --> 0

marker_z --> data[variable_id]

# Return data for plotting
x, y
end


# Visualize the mesh in a 2D plot
#
# Note: This is an experimental feature and may be changed in future releases without notice.
Expand Down Expand Up @@ -88,7 +57,7 @@ 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{<:PlotData2D{<:Any, <:AbstractVector{<:AbstractVector}}})
RecipesBase.@recipe function f(pm::PlotMesh{<:PlotData2DCartesian{<:Any, <:AbstractVector{<:AbstractVector}}})
@unpack plot_data = pm
@unpack x, y, mesh_vertices_x, mesh_vertices_y = plot_data

Expand Down Expand Up @@ -216,8 +185,8 @@ RecipesBase.@recipe function f(u, semi::SemidiscretizationHyperbolic{<:TreeMesh}
end
end

# Series recipe for UnstructuredPlotData2D
RecipesBase.@recipe function f(pds::PlotDataSeries{<:UnstructuredPlotData2D})
# Series recipe for PlotData2DTriangulated
RecipesBase.@recipe function f(pds::PlotDataSeries{<:PlotData2DTriangulated})

pd = pds.plot_data
@unpack variable_id = pds
Expand All @@ -242,8 +211,8 @@ RecipesBase.@recipe function f(pds::PlotDataSeries{<:UnstructuredPlotData2D})
return DGTriPseudocolor(global_plotting_triangulation_triplot((x, y), data_field, t)...)
end

# Visualize a 2D mesh given an `UnstructuredPlotData2D` object
RecipesBase.@recipe function f(pm::PlotMesh{<:UnstructuredPlotData2D})
# Visualize a 2D mesh given an `PlotData2DTriangulated` object
RecipesBase.@recipe function f(pm::PlotMesh{<:PlotData2DTriangulated})
pd = pm.plot_data
@unpack x_face, y_face = pd

Expand Down
26 changes: 13 additions & 13 deletions src/visualization/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ mesh.
!!! warning "Experimental implementation"
This is an experimental feature and may change in future releases.
"""
struct PlotData2D{Coordinates, Data, VariableNames, Vertices} <: AbstractPlotData{2}
struct PlotData2DCartesian{Coordinates, Data, VariableNames, Vertices} <: AbstractPlotData{2}
x::Coordinates
y::Coordinates
data::Data
Expand All @@ -69,10 +69,10 @@ struct PlotData2D{Coordinates, Data, VariableNames, Vertices} <: AbstractPlotDat
end

# Show only a truncated output for convenience (the full data does not make sense)
function Base.show(io::IO, pd::PlotData2D)
function Base.show(io::IO, pd::PlotData2DCartesian)
@nospecialize pd # reduce precompilation time

print(io, "PlotData2D{",
print(io, "PlotData2DCartesian{",
typeof(pd.x), ",",
typeof(pd.data), ",",
typeof(pd.variable_names), ",",
Expand All @@ -82,7 +82,7 @@ end


# holds plotting information for UnstructuredMesh2D and DGMulti-compatible meshes
struct UnstructuredPlotData2D{DataType, FaceDataType, VariableNames, PlottingTriangulation, RealT} <: AbstractPlotData{2}
struct PlotData2DTriangulated{DataType, FaceDataType, VariableNames, PlottingTriangulation, RealT} <: AbstractPlotData{2}
x::Array{RealT, 2} # physical nodal coordinates, size (num_plotting_nodes x num_elements)
y::Array{RealT, 2}
data::DataType
Expand All @@ -94,10 +94,10 @@ struct UnstructuredPlotData2D{DataType, FaceDataType, VariableNames, PlottingTri
end

# Show only a truncated output for convenience (the full data does not make sense)
function Base.show(io::IO, pd::UnstructuredPlotData2D)
function Base.show(io::IO, pd::PlotData2DTriangulated)
@nospecialize pd # reduce precompilation time

print(io, "UnstructuredPlotData2D{",
print(io, "PlotData2DTriangulated{",
typeof(pd.x), ", ",
typeof(pd.data), ", ",
typeof(pd.x_face), ", ",
Expand Down Expand Up @@ -257,8 +257,8 @@ function PlotData2D(u, mesh::TreeMesh, equations, solver, cache;

orientation_x, orientation_y = _get_orientations(mesh, slice)

return PlotData2D(x, y, data, variable_names, mesh_vertices_x, mesh_vertices_y,
orientation_x, orientation_y)
return PlotData2DCartesian(x, y, data, variable_names, mesh_vertices_x, mesh_vertices_y,
orientation_x, orientation_y)
end


Expand Down Expand Up @@ -289,7 +289,7 @@ function PlotData2D(u::Array{<:SVector, 2}, mesh, equations, dg::DGMulti, cache;
solution_variables=solution_variables, nvisnodes=nvisnodes)
end

# constructor which returns an `UnstructuredPlotData2D` object.
# constructor which returns an `PlotData2DTriangulated` object.
function PlotData2D(u::StructArray, mesh, equations, dg::DGMulti, cache;
solution_variables=nothing, nvisnodes=2*nnodes(dg))

Expand Down Expand Up @@ -328,12 +328,12 @@ function PlotData2D(u::StructArray, mesh, equations, dg::DGMulti, cache;
# only 2D heatmap plots are supported through TriplotBase/TriplotRecipes.
face_data = nothing

return UnstructuredPlotData2D(x_plot, y_plot, u_plot, t, x_face, y_face, face_data, variable_names)
return PlotData2DTriangulated(x_plot, y_plot, u_plot, t, x_face, y_face, face_data, variable_names)
end

# specializes the PlotData2D constructor to return an UnstructuredPlotData2D if the mesh is
# specializes the PlotData2D constructor to return an PlotData2DTriangulated if the mesh is
# a non-TreeMesh type.
function PlotData2D(u, mesh::Union{StructuredMesh, UnstructuredMesh2D}, equations, dg, cache;
function PlotData2D(u, mesh::Union{StructuredMesh, UnstructuredMesh2D, P4estMesh}, equations, dg, cache;
solution_variables=nothing, nvisnodes=2*polydeg(dg))
@assert ndims(mesh) == 2

Expand Down Expand Up @@ -405,7 +405,7 @@ function PlotData2D(u, mesh::Union{StructuredMesh, UnstructuredMesh2D}, equation
transform_to_solution_variables!(uplot, solution_variables_, equations)
transform_to_solution_variables!(ufp, solution_variables_, equations)

return UnstructuredPlotData2D(xplot, yplot, uplot, t, xfp, yfp, ufp, variable_names)
return PlotData2DTriangulated(xplot, yplot, uplot, t, xfp, yfp, ufp, variable_names)
end


Expand Down
4 changes: 2 additions & 2 deletions src/visualization/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ end

# Given a reference plotting triangulation, this function generates a plotting triangulation for
# the entire global mesh. The output can be plotted using `Makie.mesh`.
function global_plotting_triangulation_makie(pds::PlotDataSeries{<:UnstructuredPlotData2D};
function global_plotting_triangulation_makie(pds::PlotDataSeries{<:PlotData2DTriangulated};
set_z_coordinate_zero = false)
@unpack variable_id = pds
pd = pds.plot_data
Expand Down Expand Up @@ -1119,7 +1119,7 @@ end

# Returns a list of `Makie.Point`s which can be used to plot the mesh, or a solution "wireframe"
# (e.g., a plot of the mesh lines but with the z-coordinate equal to the value of the solution).
function mesh_plotting_wireframe(pds::PlotDataSeries{<:UnstructuredPlotData2D};
function mesh_plotting_wireframe(pds::PlotDataSeries{<:PlotData2DTriangulated};
set_z_coordinate_zero = false)
@unpack variable_id = pds
pd = pds.plot_data
Expand Down
22 changes: 12 additions & 10 deletions test/test_visualization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ isdir(outdir) && rm(outdir, recursive=true)

# Run various visualization tests
@testset "Visualization tests" begin
# Run 2D tests with elixirs for both mesh types
# Run 2D tests with elixirs for all mesh types
test_examples_2d = Dict(
"TreeMesh" => ("tree_2d_dgsem", "elixir_euler_blast_wave_amr.jl"),
"StructuredMesh" => ("structured_2d_dgsem", "elixir_euler_source_terms_waving_flag.jl"),
"UnstructuredMesh" => ("unstructured_2d_dgsem", "elixir_euler_basic.jl"),
"P4estMesh" => ("p4est_2d_dgsem", "elixir_euler_source_terms_nonperiodic.jl"),
"DGMulti" => ("dgmulti_2d", "elixir_euler_weakform.jl"),
)

Expand All @@ -35,11 +37,11 @@ isdir(outdir) && rm(outdir, recursive=true)

# Constructor tests
if mesh == "TreeMesh"
@test PlotData2D(sol) isa PlotData2D
@test PlotData2D(sol; nvisnodes=0, grid_lines=false, solution_variables=cons2cons) isa PlotData2D
@test PlotData2D(sol) isa Trixi.PlotData2DCartesian
@test PlotData2D(sol; nvisnodes=0, grid_lines=false, solution_variables=cons2cons) isa Trixi.PlotData2DCartesian
else
@test PlotData2D(sol) isa Trixi.UnstructuredPlotData2D
@test PlotData2D(sol; nvisnodes=0, solution_variables=cons2cons) isa Trixi.UnstructuredPlotData2D
@test PlotData2D(sol) isa Trixi.PlotData2DTriangulated
@test PlotData2D(sol; nvisnodes=0, solution_variables=cons2cons) isa Trixi.PlotData2DTriangulated
end
pd = PlotData2D(sol)

Expand Down Expand Up @@ -91,8 +93,8 @@ isdir(outdir) && rm(outdir, recursive=true)
@testset "1D plot from 2D solution" begin
if mesh != "DGMulti"
@testset "Create 1D plot as slice" begin
@test_nowarn_debug PlotData1D(sol, slice=:y, point=(-0.5, 0.0)) isa PlotData1D
pd1D = PlotData1D(sol, slice=:y, point=(-0.5, 0.0))
@test_nowarn_debug PlotData1D(sol, slice=:y, point=(0.5, 0.0)) isa PlotData1D
pd1D = PlotData1D(sol, slice=:y, point=(0.5, 0.0))
@test_nowarn_debug Plots.plot(pd1D)
end
end
Expand Down Expand Up @@ -182,7 +184,7 @@ isdir(outdir) && rm(outdir, recursive=true)
data2d = [rand(11,11) for _ in 1:5]
mesh_vertices_x2d = [0.0, 1.0, 1.0, 0.0]
mesh_vertices_y2d = [0.0, 0.0, 1.0, 1.0]
fake2d = PlotData2D(x, y, data2d, variable_names, mesh_vertices_x2d, mesh_vertices_y2d, 0, 0)
fake2d = Trixi.PlotData2DCartesian(x, y, data2d, variable_names, mesh_vertices_x2d, mesh_vertices_y2d, 0, 0)
@test_nowarn_debug Plots.plot(fake2d)
end
end
Expand Down Expand Up @@ -212,7 +214,7 @@ isdir(outdir) && rm(outdir, recursive=true)
@timed_testset "plot 3D" begin
@test_nowarn_debug trixi_include(@__MODULE__, joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_basic.jl"),
tspan=(0,0.1))
@test PlotData2D(sol) isa PlotData2D
@test PlotData2D(sol) isa Trixi.PlotData2DCartesian

@testset "1D plot from 3D solution" begin
@testset "Create 1D plot as slice" begin
Expand Down Expand Up @@ -279,7 +281,7 @@ isdir(outdir) && rm(outdir, recursive=true)
@timed_testset "Makie visualization tests for UnstructuredMesh2D" begin
@test_nowarn_debug trixi_include(@__MODULE__, joinpath(examples_dir(), "unstructured_2d_dgsem", "elixir_euler_wall_bc.jl"))
@test_nowarn_debug Trixi.iplot(sol) # test interactive surface plot
@test_nowarn_debug Makie.plot(sol) # test heatmap plot
@test_nowarn_debug Makie.plot(sol, plot_mesh=true) # test heatmap plot

fa = Makie.plot(sol) # test heatmap plot
fig, axes = fa # test unpacking/iteration for FigureAndAxes
Expand Down

0 comments on commit 4d9e924

Please sign in to comment.