Skip to content

Commit 8109845

Browse files
JoshuaLampertDanielDoehringranocha
authored
Allow disabling reinterpolation in 1D plots (#2258)
* allow disabling reinterpolation in 1D plots * Apply suggestions from code review Co-authored-by: Daniel Doehring <[email protected]> * Apply suggestions from code review Co-authored-by: Hendrik Ranocha <[email protected]> * use reinterpolate = false for FDSBP * format * simplify for reinterpolate = false (don't do anything) * clarify docstring * reintroduce blank line * Update src/visualization/types.jl Co-authored-by: Hendrik Ranocha <[email protected]> * Update src/visualization/utilities.jl Co-authored-by: Daniel Doehring <[email protected]> --------- Co-authored-by: Daniel Doehring <[email protected]> Co-authored-by: Hendrik Ranocha <[email protected]>
1 parent c24ce91 commit 8109845

File tree

4 files changed

+72
-48
lines changed

4 files changed

+72
-48
lines changed

src/visualization/recipes_plots.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,13 @@ end
190190
RecipesBase.@recipe function f(u, semi::SemidiscretizationHyperbolic{<:TreeMesh};
191191
solution_variables = nothing,
192192
grid_lines = true, max_supported_level = 11,
193-
nvisnodes = nothing, slice = :xy,
194-
point = (0.0, 0.0, 0.0), curve = nothing)
193+
nvisnodes = nothing,
194+
reinterpolate = default_reinterpolate(semi.solver),
195+
slice = :xy, point = (0.0, 0.0, 0.0), curve = nothing)
195196
# Create a PlotData1D or PlotData2D object depending on the dimension.
196197
if ndims(semi) == 1
197-
return PlotData1D(u, semi; solution_variables, nvisnodes, slice, point, curve)
198+
return PlotData1D(u, semi; solution_variables, nvisnodes, reinterpolate,
199+
slice, point, curve)
198200
else
199201
return PlotData2D(u, semi;
200202
solution_variables, grid_lines, max_supported_level,

src/visualization/types.jl

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,9 @@ end
516516

517517
"""
518518
PlotData1D(u, semi [or mesh, equations, solver, cache];
519-
solution_variables=nothing, nvisnodes=nothing)
519+
solution_variables=nothing, nvisnodes=nothing,
520+
reinterpolate=Trixi.default_reinterpolate(solver),
521+
slice=:x, point=(0.0, 0.0, 0.0), curve=nothing)
520522
521523
Create a new `PlotData1D` object that can be used for visualizing 1D DGSEM solution data array
522524
`u` with `Plots.jl`. All relevant geometrical information is extracted from the
@@ -531,7 +533,10 @@ e.g., to visualize an analytical solution.
531533
532534
`nvisnodes` specifies the number of visualization nodes to be used. If it is `nothing`,
533535
twice the number of solution DG nodes are used for visualization, and if set to `0`,
534-
exactly the number of nodes in the DG elements are used.
536+
exactly the number of nodes as in the DG elements are used. The solution is interpolated to these
537+
nodes for plotting. If `reinterpolate` is `false`, the solution is not interpolated to the `visnodes`,
538+
i.e., the solution is plotted at the solution nodes. In this case `nvisnodes` is ignored. By default,
539+
`reinterpolate` is set to `false` for `FDSBP` approximations and to `true` otherwise.
535540
536541
When visualizing data from a two-dimensional simulation, a 1D slice is extracted for plotting.
537542
`slice` specifies the axis along which the slice is extracted and may be `:x`, or `:y`.
@@ -560,6 +565,7 @@ end
560565

561566
function PlotData1D(u, mesh::TreeMesh, equations, solver, cache;
562567
solution_variables = nothing, nvisnodes = nothing,
568+
reinterpolate = default_reinterpolate(solver),
563569
slice = :x, point = (0.0, 0.0, 0.0), curve = nothing,
564570
variable_names = nothing)
565571
solution_variables_ = digest_solution_variables(equations, solution_variables)
@@ -574,7 +580,7 @@ function PlotData1D(u, mesh::TreeMesh, equations, solver, cache;
574580

575581
if ndims(mesh) == 1
576582
x, data, mesh_vertices_x = get_data_1d(original_nodes, unstructured_data,
577-
nvisnodes)
583+
nvisnodes, reinterpolate)
578584
orientation_x = 1
579585

580586
# Special care is required for first-order FV approximations since the nodes are the
@@ -608,7 +614,8 @@ function PlotData1D(u, mesh::TreeMesh, equations, solver, cache;
608614
else
609615
x, data, mesh_vertices_x = unstructured_2d_to_1d(original_nodes,
610616
unstructured_data,
611-
nvisnodes, slice, point)
617+
nvisnodes, reinterpolate,
618+
slice, point)
612619
end
613620
else # ndims(mesh) == 3
614621
if curve !== nothing
@@ -619,7 +626,8 @@ function PlotData1D(u, mesh::TreeMesh, equations, solver, cache;
619626
else
620627
x, data, mesh_vertices_x = unstructured_3d_to_1d(original_nodes,
621628
unstructured_data,
622-
nvisnodes, slice, point)
629+
nvisnodes, reinterpolate,
630+
slice, point)
623631
end
624632
end
625633

@@ -629,6 +637,7 @@ end
629637

630638
function PlotData1D(u, mesh, equations, solver, cache;
631639
solution_variables = nothing, nvisnodes = nothing,
640+
reinterpolate = default_reinterpolate(solver),
632641
slice = :x, point = (0.0, 0.0, 0.0), curve = nothing,
633642
variable_names = nothing)
634643
solution_variables_ = digest_solution_variables(equations, solution_variables)
@@ -643,7 +652,7 @@ function PlotData1D(u, mesh, equations, solver, cache;
643652

644653
if ndims(mesh) == 1
645654
x, data, mesh_vertices_x = get_data_1d(original_nodes, unstructured_data,
646-
nvisnodes)
655+
nvisnodes, reinterpolate)
647656
orientation_x = 1
648657
elseif ndims(mesh) == 2
649658
# Create a 'PlotData2DTriangulated' object so a triangulation can be used when extracting relevant data.

src/visualization/utilities.jl

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -391,54 +391,66 @@ function get_data_2d(center_level_0, length_level_0, leaf_cells, coordinates, le
391391
return xs, ys, node_centered_data, mesh_vertices_x, mesh_vertices_y
392392
end
393393

394+
# For finite difference methods (FDSBP), we do not want to reinterpolate the data, but use the same
395+
# nodes as input nodes. For DG methods, we usually want to reinterpolate the data on an equidistant grid.
396+
default_reinterpolate(solver) = solver isa FDSBP ? false : true
397+
394398
# Extract data from a 1D DG solution and prepare it for visualization as a line plot.
395399
# This returns a tuple with
396400
# - x coordinates
397401
# - nodal 1D data
398402
#
399403
# Note: This is a low-level function that is not considered as part of Trixi's interface and may
400-
# thus be changed in future releases.
401-
function get_data_1d(original_nodes, unstructured_data, nvisnodes)
404+
# thus be changed in future releases.
405+
function get_data_1d(original_nodes, unstructured_data, nvisnodes, reinterpolate)
402406
# Get the dimensions of u; where n_vars is the number of variables, n_nodes the number of nodal values per element and n_elements the total number of elements.
403407
n_nodes, n_elements, n_vars = size(unstructured_data)
404408

405-
# Set the amount of nodes visualized according to nvisnodes.
406-
if nvisnodes === nothing
407-
max_nvisnodes = 2 * n_nodes
408-
elseif nvisnodes == 0
409-
max_nvisnodes = n_nodes
409+
# If `reinterpolate` is `false`, we do nothing.
410+
# If `reinterpolate` is `true`, the output nodes are equidistantly spaced.
411+
if reinterpolate == false
412+
interpolated_nodes = original_nodes
413+
interpolated_data = unstructured_data
410414
else
411-
@assert nvisnodes>=2 "nvisnodes must be zero or >= 2"
412-
max_nvisnodes = nvisnodes
413-
end
415+
# Set the amount of nodes visualized according to nvisnodes.
416+
if nvisnodes === nothing
417+
max_nvisnodes = 2 * n_nodes
418+
elseif nvisnodes == 0
419+
max_nvisnodes = n_nodes
420+
else
421+
@assert nvisnodes>=2 "nvisnodes must be zero or >= 2"
422+
max_nvisnodes = nvisnodes
423+
end
414424

415-
interpolated_nodes = Array{eltype(original_nodes), 2}(undef, max_nvisnodes,
416-
n_elements)
417-
interpolated_data = Array{eltype(unstructured_data), 3}(undef, max_nvisnodes,
418-
n_elements, n_vars)
425+
interpolated_nodes = Array{eltype(original_nodes), 2}(undef, max_nvisnodes,
426+
n_elements)
427+
interpolated_data = Array{eltype(unstructured_data), 3}(undef, max_nvisnodes,
428+
n_elements, n_vars)
419429

420-
for j in 1:n_elements
421-
# Interpolate on an equidistant grid.
422-
interpolated_nodes[:, j] .= range(original_nodes[1, 1, j],
423-
original_nodes[1, end, j],
424-
length = max_nvisnodes)
425-
end
430+
for j in 1:n_elements
431+
# Interpolate on an equidistant grid.
432+
interpolated_nodes[:, j] .= range(original_nodes[1, 1, j],
433+
original_nodes[1, end, j],
434+
length = max_nvisnodes)
435+
end
426436

427-
nodes_in, _ = gauss_lobatto_nodes_weights(n_nodes)
428-
nodes_out = collect(range(-1, 1, length = max_nvisnodes))
429-
430-
# Calculate vandermonde matrix for interpolation.
431-
vandermonde = polynomial_interpolation_matrix(nodes_in, nodes_out)
432-
433-
# Iterate over all variables.
434-
for v in 1:n_vars
435-
# Interpolate data for each element.
436-
for element in 1:n_elements
437-
multiply_scalar_dimensionwise!(@view(interpolated_data[:, element, v]),
438-
vandermonde,
439-
@view(unstructured_data[:, element, v]))
437+
nodes_in, _ = gauss_lobatto_nodes_weights(n_nodes)
438+
nodes_out = collect(range(-1, 1, length = max_nvisnodes))
439+
440+
# Calculate vandermonde matrix for interpolation.
441+
vandermonde = polynomial_interpolation_matrix(nodes_in, nodes_out)
442+
443+
# Iterate over all variables.
444+
for v in 1:n_vars
445+
# Interpolate data for each element.
446+
for element in 1:n_elements
447+
multiply_scalar_dimensionwise!(@view(interpolated_data[:, element, v]),
448+
vandermonde,
449+
@view(unstructured_data[:, element, v]))
450+
end
440451
end
441452
end
453+
442454
# Return results after data is reshaped
443455
return vec(interpolated_nodes), reshape(interpolated_data, :, n_vars),
444456
vcat(original_nodes[1, 1, :], original_nodes[1, end, end])
@@ -675,8 +687,8 @@ function unstructured_3d_to_2d(unstructured_data, coordinates, levels,
675687
end
676688

677689
# Convert 2d unstructured data to 1d slice and interpolate them.
678-
function unstructured_2d_to_1d(original_nodes, unstructured_data, nvisnodes, slice,
679-
point)
690+
function unstructured_2d_to_1d(original_nodes, unstructured_data, nvisnodes,
691+
reinterpolate, slice, point)
680692
if slice === :x
681693
slice_dimension = 2
682694
other_dimension = 1
@@ -749,7 +761,7 @@ function unstructured_2d_to_1d(original_nodes, unstructured_data, nvisnodes, sli
749761
end
750762

751763
return get_data_1d(reshape(new_nodes[:, 1:new_id], 1, n_nodes_in, new_id),
752-
new_unstructured_data[:, 1:new_id, :], nvisnodes)
764+
new_unstructured_data[:, 1:new_id, :], nvisnodes, reinterpolate)
753765
end
754766

755767
# Calculate the arc length of a curve given by ndims x npoints point coordinates (piece-wise linear approximation)
@@ -1085,8 +1097,8 @@ function get_value_at_point(point, nodes, data)
10851097
end
10861098

10871099
# Convert 3d unstructured data to 1d slice and interpolate them.
1088-
function unstructured_3d_to_1d(original_nodes, unstructured_data, nvisnodes, slice,
1089-
point)
1100+
function unstructured_3d_to_1d(original_nodes, unstructured_data, nvisnodes,
1101+
reinterpolate, slice, point)
10901102
if slice === :x
10911103
slice_dimension = 1
10921104
other_dimensions = [2, 3]
@@ -1178,7 +1190,7 @@ function unstructured_3d_to_1d(original_nodes, unstructured_data, nvisnodes, sli
11781190
end
11791191

11801192
return get_data_1d(reshape(new_nodes[:, 1:new_id], 1, n_nodes_in, new_id),
1181-
new_unstructured_data[:, 1:new_id, :], nvisnodes)
1193+
new_unstructured_data[:, 1:new_id, :], nvisnodes, reinterpolate)
11821194
end
11831195

11841196
# Interpolate unstructured DG data to structured data (cell-centered)

test/test_visualization.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ end
185185
pd = PlotData1D(sol)
186186

187187
@test_nowarn_mod Plots.plot(sol)
188+
@test_nowarn_mod Plots.plot(sol, reinterpolate = false)
188189
@test_nowarn_mod Plots.plot(pd)
189190
@test_nowarn_mod Plots.plot(pd["p"])
190191
@test_nowarn_mod Plots.plot(getmesh(pd))

0 commit comments

Comments
 (0)