Skip to content

Save additional node variables in SaveSolutionCallback #2298

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 40 commits into from
May 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6b36d38
Save additional node variables in `SaveSolutionCallback`
DanielDoehring Feb 25, 2025
23797da
dispatch functions correctly, document new dict
DanielDoehring Feb 25, 2025
5da8b16
use vorticity computation
DanielDoehring Feb 25, 2025
5170311
Merge branch 'main' into AdditionalNodeVariables
DanielDoehring May 23, 2025
464e913
continue
DanielDoehring May 23, 2025
b7e00d5
working version
DanielDoehring May 23, 2025
dc7dac8
Merge branch 'main' into AdditionalNodeVariables
DanielDoehring May 23, 2025
23694d1
parallel (to be tested!)
DanielDoehring May 23, 2025
a1b090d
clean up
DanielDoehring May 23, 2025
c89ecfe
mpi tests
DanielDoehring May 23, 2025
93fd30a
3d fix
DanielDoehring May 23, 2025
74edc9f
3d
DanielDoehring May 23, 2025
10a629e
access non-exported func
DanielDoehring May 23, 2025
95a701d
comment
DanielDoehring May 23, 2025
8ba6990
remove doubled method
DanielDoehring May 23, 2025
a914f8e
simplify
DanielDoehring May 23, 2025
04096c8
use singular
DanielDoehring May 24, 2025
6862c0d
Merge branch 'main' into AdditionalNodeVariables
DanielDoehring May 24, 2025
1d223a7
need to figure out which elixirs are MPI-parallel, but single I/O
DanielDoehring May 24, 2025
108e91f
add example for coverage
DanielDoehring May 24, 2025
a18662c
Update examples/tree_2d_dgsem/elixir_advection_timeintegration_adapti…
DanielDoehring May 24, 2025
e50906c
not needed, mpi tests windows tiem out
DanielDoehring May 24, 2025
a76c0a5
Merge branch 'AdditionalNodeVariables' of https://github.com/DanielDo…
DanielDoehring May 24, 2025
b756991
send data
DanielDoehring May 24, 2025
3a8fae5
fmt
DanielDoehring May 24, 2025
e33ba7e
add ":limiting_coefficient" as "extra_node_variables"
DanielDoehring May 25, 2025
8e380ae
Subcell + CNS
DanielDoehring May 25, 2025
7ef0998
fmt
DanielDoehring May 25, 2025
aafc1e5
fix path
DanielDoehring May 25, 2025
7cecf02
test vals
DanielDoehring May 25, 2025
79c204a
Update src/callbacks_step/save_solution.jl
DanielDoehring May 25, 2025
b4747b3
comments
DanielDoehring May 25, 2025
920d6c1
Merge branch 'AdditionalNodeVariables' of https://github.com/DanielDo…
DanielDoehring May 25, 2025
adc46ad
Update src/solvers/dg.jl
DanielDoehring May 26, 2025
2b4aab5
Merge branch 'main' into AdditionalNodeVariables
DanielDoehring May 26, 2025
1ae2c0c
docu + news entry
DanielDoehring May 26, 2025
9be75aa
Merge branch 'main' into AdditionalNodeVariables
DanielDoehring May 27, 2025
917daeb
fix merge errors
DanielDoehring May 27, 2025
a074775
fmt
DanielDoehring May 27, 2025
5b84b2c
Apply suggestions from code review
DanielDoehring May 27, 2025
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
10 changes: 10 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,18 @@ for human readability.

#### Added

- Arbitrary solution-dependent quantities can now be saved in the `SaveSolutionCallback` (and thus later on visualized) ([#2298]).

#### Changed

- When using the `VolumeIntegralSubcellLimiting` with the `SubcellLimiterIDP` the
`:limiting_coefficient` must be explicitly provided to the `SaveSolutionCallback` via
```julia
save_sol_cb = SaveSolutionCallback(interval = 42,
extra_node_variables = (:limiting_coefficient,))
```
i.e., is no longer automatically saved ([#2298]).

#### Deprecated

#### Removed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)

save_solution = SaveSolutionCallback(interval = 300,
save_initial_solution = true,
save_final_solution = true)
save_final_solution = true,
extra_node_variables = (:limiting_coefficient,))

stepsize_callback = StepsizeCallback(cfl = 0.5)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
save_solution = SaveSolutionCallback(interval = 1000,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = (:limiting_coefficient,))

stepsize_callback = StepsizeCallback(cfl = 0.8)

Expand Down
44 changes: 43 additions & 1 deletion examples/p4est_2d_dgsem/elixir_navierstokes_vortex_street.jl
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,52 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval)

alive_callback = AliveCallback(analysis_interval = analysis_interval)

# Add `:vorticity` to `extra_node_variables` tuple ...
extra_node_variables = (:vorticity,)

# ... and specify the function `get_node_variable` for this symbol,
# with first argument matching the symbol (turned into a type via `Val`) for dispatching.
# Note that for parabolic(-extended) equations, `equations_parabolic` and `cache_parabolic`
# must be declared as the last two arguments of the function to match the expected signature.
function Trixi.get_node_variable(::Val{:vorticity}, u, mesh, equations, dg, cache,
equations_parabolic, cache_parabolic)
n_nodes = nnodes(dg)
n_elements = nelements(dg, cache)
# By definition, the variable must be provided at every node of every element!
# Otherwise, the `SaveSolutionCallback` will crash.
vorticity_array = zeros(eltype(cache.elements),
n_nodes, n_nodes, # equivalent: `ntuple(_ -> n_nodes, ndims(mesh))...,`
n_elements)

@unpack viscous_container = cache_parabolic
@unpack gradients = viscous_container
gradients_x, gradients_y = gradients

# We can accelerate the computation by thread-parallelizing the loop over elements
# by using the `@threaded` macro.
Trixi.@threaded for element in eachelement(dg, cache)
for j in eachnode(dg), i in eachnode(dg)
u_node = get_node_vars(u, equations, dg, i, j, element)

gradients_1 = get_node_vars(gradients_x, equations_parabolic, dg,
i, j, element)
gradients_2 = get_node_vars(gradients_y, equations_parabolic, dg,
i, j, element)

vorticity_nodal = vorticity(u_node, (gradients_1, gradients_2),
equations_parabolic)
vorticity_array[i, j, element] = vorticity_nodal
end
end

return vorticity_array
end

save_solution = SaveSolutionCallback(dt = 1.0,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = extra_node_variables) # Supply the additional `extra_node_variables` here

callbacks = CallbackSet(summary_callback,
analysis_callback,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,8 @@ function Trixi.analyze(::Val{:energy_potential}, du, u_euler, t,
u_gravity) do u, i, j, element,
equations_euler, dg,
equations_gravity, u_gravity
u_euler_local = Trixi.get_node_vars(u_euler, equations_euler, dg, i, j, element)
u_gravity_local = Trixi.get_node_vars(u_gravity, equations_gravity, dg, i, j,
element)
u_euler_local = get_node_vars(u_euler, equations_euler, dg, i, j, element)
u_gravity_local = get_node_vars(u_gravity, equations_gravity, dg, i, j, element)
# OBS! subtraction is specific to Jeans instability test where rho0 = 1.5e7
# For formula of potential energy see
# "Galactic Dynamics" by Binney and Tremaine, 2nd ed., equation (2.18)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
save_solution = SaveSolutionCallback(interval = 100,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = (:limiting_coefficient,))

stepsize_callback = StepsizeCallback(cfl = 0.6)

Expand Down
30 changes: 29 additions & 1 deletion examples/t8code_3d_dgsem/elixir_euler_ec.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,37 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval)

alive_callback = AliveCallback(analysis_interval = analysis_interval)

# Add `:thermodynamic_entropy` to `extra_node_variables` tuple ...
extra_node_variables = (:thermodynamic_entropy,)

# ... and specify the function `get_node_variable` for this symbol,
# with first argument matching the symbol (turned into a type via `Val`) for dispatching.
function Trixi.get_node_variable(::Val{:thermodynamic_entropy}, u, mesh, equations,
dg, cache)
n_nodes = nnodes(dg)
n_elements = nelements(dg, cache)
# By definition, the variable must be provided at every node of every element!
# Otherwise, the `SaveSolutionCallback` will crash.
entropy_array = zeros(eltype(cache.elements),
ntuple(_ -> n_nodes, ndims(mesh))..., # equivalent: `n_nodes, n_nodes, n_nodes`
n_elements)

# We can accelerate the computation by thread-parallelizing the loop over elements
# by using the `@threaded` macro.
Trixi.@threaded for element in eachelement(dg, cache)
for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)
u_node = get_node_vars(u, equations, dg, i, j, k, element)

entropy_array[i, j, k, element] = Trixi.entropy_thermodynamic(u_node, equations)
end
end

return entropy_array
end
save_solution = SaveSolutionCallback(interval = 100,
save_initial_solution = true,
save_final_solution = true)
save_final_solution = true,
extra_node_variables = extra_node_variables) # Supply the additional `extra_node_variables` here

stepsize_callback = StepsizeCallback(cfl = 1.0)

Expand Down
32 changes: 31 additions & 1 deletion examples/tree_2d_dgsem/elixir_euler_blast_wave_amr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,40 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval)

alive_callback = AliveCallback(analysis_interval = analysis_interval)

# Add `:mach` to `extra_node_variables` tuple ...
extra_node_variables = (:mach,)

# ... and specify the function `get_node_variable` for this symbol,
# with first argument matching the symbol (turned into a type via `Val`) for dispatching.
function Trixi.get_node_variable(::Val{:mach}, u, mesh, equations, dg, cache)
n_nodes = nnodes(dg)
n_elements = nelements(dg, cache)
# By definition, the variable must be provided at every node of every element!
# Otherwise, the `SaveSolutionCallback` will crash.
mach_array = zeros(eltype(cache.elements),
n_nodes, n_nodes, # equivalent: `ntuple(_ -> n_nodes, ndims(mesh))...,`
n_elements)

# We can accelerate the computation by thread-parallelizing the loop over elements
# by using the `@threaded` macro.
Trixi.@threaded for element in eachelement(dg, cache)
for j in eachnode(dg), i in eachnode(dg)
u_node = get_node_vars(u, equations, dg, i, j, element)
rho, v1, v2, p = prim2cons(u_node, equations)
c = sqrt(equations.gamma * p / rho) # speed of sound
v_magnitude = sqrt(v1^2 + v2^2)

mach_array[i, j, element] = v_magnitude / c
end
end

return mach_array
end
save_solution = SaveSolutionCallback(interval = 100,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = extra_node_variables) # Supply the additional `extra_node_variables` here

amr_indicator = IndicatorHennemannGassner(semi,
alpha_max = 0.5,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
save_solution = SaveSolutionCallback(interval = 100,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = (:limiting_coefficient,))

stepsize_callback = StepsizeCallback(cfl = 0.3)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
save_solution = SaveSolutionCallback(interval = 100,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = (:limiting_coefficient,))

save_restart = SaveRestartCallback(interval = 1000,
save_final_restart = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
save_solution = SaveSolutionCallback(interval = 1000,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = (:limiting_coefficient,))

stepsize_callback = StepsizeCallback(cfl = 0.4)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
save_solution = SaveSolutionCallback(dt = 0.1,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = (:limiting_coefficient,))

stepsize_callback = StepsizeCallback(cfl = 0.6)

Expand Down
31 changes: 30 additions & 1 deletion examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,39 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval,

alive_callback = AliveCallback(analysis_interval = analysis_interval)

# Add `:temperature` to `extra_node_variables` tuple ...
extra_node_variables = (:temperature,)

# ... and specify the function `get_node_variable` for this symbol,
# with first argument matching the symbol (turned into a type via `Val`) for dispatching.
function Trixi.get_node_variable(::Val{:temperature}, u, mesh, equations, dg, cache)
n_nodes = nnodes(dg)
n_elements = nelements(dg, cache)
# By definition, the variable must be provided at every node of every element!
# Otherwise, the `SaveSolutionCallback` will crash.
temp_array = zeros(eltype(cache.elements),
n_nodes, n_nodes, # equivalent: `ntuple(_ -> n_nodes, ndims(mesh))...,`
n_elements)

# We can accelerate the computation by thread-parallelizing the loop over elements
# by using the `@threaded` macro.
Trixi.@threaded for element in eachelement(dg, cache)
for j in eachnode(dg), i in eachnode(dg)
u_node = get_node_vars(u, equations, dg, i, j, element)
rho, _, _, p = prim2cons(u_node, equations)
temp = p / rho # ideal gas equation with R = 1

temp_array[i, j, element] = temp
end
end

return temp_array
end
save_solution = SaveSolutionCallback(interval = 50,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = extra_node_variables) # Supply the additional `extra_node_variables` here

amr_controller = ControllerThreeLevel(semi, TrixiExtension.IndicatorVortex(semi),
base_level = 3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
save_solution = SaveSolutionCallback(interval = 600,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = (:limiting_coefficient,))

stepsize_callback = StepsizeCallback(cfl = 0.4)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
save_solution = SaveSolutionCallback(interval = 300,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = (:limiting_coefficient,))

stepsize_callback = StepsizeCallback(cfl = 0.9)

Expand Down
3 changes: 2 additions & 1 deletion examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
save_solution = SaveSolutionCallback(interval = 100,
save_initial_solution = true,
save_final_solution = true,
solution_variables = cons2prim)
solution_variables = cons2prim,
extra_node_variables = (:limiting_coefficient,))

cfl = 0.4
stepsize_callback = StepsizeCallback(cfl = cfl)
Expand Down
Loading
Loading