Skip to content

Commit a51dade

Browse files
DanielDoehringbennibolmranocha
authored
Save additional node variables in SaveSolutionCallback (#2298)
* Save additional node variables in `SaveSolutionCallback` * dispatch functions correctly, document new dict * use vorticity computation * continue * working version * parallel (to be tested!) * clean up * mpi tests * 3d fix * 3d * access non-exported func * comment * remove doubled method * simplify * use singular * need to figure out which elixirs are MPI-parallel, but single I/O * add example for coverage * Update examples/tree_2d_dgsem/elixir_advection_timeintegration_adaptive.jl * not needed, mpi tests windows tiem out * send data * fmt * add ":limiting_coefficient" as "extra_node_variables" * Subcell + CNS * fmt * fix path * test vals * Update src/callbacks_step/save_solution.jl * comments * Update src/solvers/dg.jl Co-authored-by: Benjamin Bolm <[email protected]> * docu + news entry * fix merge errors * fmt * Apply suggestions from code review Co-authored-by: Hendrik Ranocha <[email protected]> --------- Co-authored-by: Benjamin Bolm <[email protected]> Co-authored-by: Hendrik Ranocha <[email protected]>
1 parent 31e3d56 commit a51dade

26 files changed

+436
-60
lines changed

NEWS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,18 @@ for human readability.
99

1010
#### Added
1111

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

16+
- When using the `VolumeIntegralSubcellLimiting` with the `SubcellLimiterIDP` the
17+
`:limiting_coefficient` must be explicitly provided to the `SaveSolutionCallback` via
18+
```julia
19+
save_sol_cb = SaveSolutionCallback(interval = 42,
20+
extra_node_variables = (:limiting_coefficient,))
21+
```
22+
i.e., is no longer automatically saved ([#2298]).
23+
1424
#### Deprecated
1525

1626
#### Removed

examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
8080

8181
save_solution = SaveSolutionCallback(interval = 300,
8282
save_initial_solution = true,
83-
save_final_solution = true)
83+
save_final_solution = true,
84+
extra_node_variables = (:limiting_coefficient,))
8485

8586
stepsize_callback = StepsizeCallback(cfl = 0.5)
8687

examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
144144
save_solution = SaveSolutionCallback(interval = 1000,
145145
save_initial_solution = true,
146146
save_final_solution = true,
147-
solution_variables = cons2prim)
147+
solution_variables = cons2prim,
148+
extra_node_variables = (:limiting_coefficient,))
148149

149150
stepsize_callback = StepsizeCallback(cfl = 0.8)
150151

examples/p4est_2d_dgsem/elixir_navierstokes_vortex_street.jl

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,52 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval)
102102

103103
alive_callback = AliveCallback(analysis_interval = analysis_interval)
104104

105+
# Add `:vorticity` to `extra_node_variables` tuple ...
106+
extra_node_variables = (:vorticity,)
107+
108+
# ... and specify the function `get_node_variable` for this symbol,
109+
# with first argument matching the symbol (turned into a type via `Val`) for dispatching.
110+
# Note that for parabolic(-extended) equations, `equations_parabolic` and `cache_parabolic`
111+
# must be declared as the last two arguments of the function to match the expected signature.
112+
function Trixi.get_node_variable(::Val{:vorticity}, u, mesh, equations, dg, cache,
113+
equations_parabolic, cache_parabolic)
114+
n_nodes = nnodes(dg)
115+
n_elements = nelements(dg, cache)
116+
# By definition, the variable must be provided at every node of every element!
117+
# Otherwise, the `SaveSolutionCallback` will crash.
118+
vorticity_array = zeros(eltype(cache.elements),
119+
n_nodes, n_nodes, # equivalent: `ntuple(_ -> n_nodes, ndims(mesh))...,`
120+
n_elements)
121+
122+
@unpack viscous_container = cache_parabolic
123+
@unpack gradients = viscous_container
124+
gradients_x, gradients_y = gradients
125+
126+
# We can accelerate the computation by thread-parallelizing the loop over elements
127+
# by using the `@threaded` macro.
128+
Trixi.@threaded for element in eachelement(dg, cache)
129+
for j in eachnode(dg), i in eachnode(dg)
130+
u_node = get_node_vars(u, equations, dg, i, j, element)
131+
132+
gradients_1 = get_node_vars(gradients_x, equations_parabolic, dg,
133+
i, j, element)
134+
gradients_2 = get_node_vars(gradients_y, equations_parabolic, dg,
135+
i, j, element)
136+
137+
vorticity_nodal = vorticity(u_node, (gradients_1, gradients_2),
138+
equations_parabolic)
139+
vorticity_array[i, j, element] = vorticity_nodal
140+
end
141+
end
142+
143+
return vorticity_array
144+
end
145+
105146
save_solution = SaveSolutionCallback(dt = 1.0,
106147
save_initial_solution = true,
107148
save_final_solution = true,
108-
solution_variables = cons2prim)
149+
solution_variables = cons2prim,
150+
extra_node_variables = extra_node_variables) # Supply the additional `extra_node_variables` here
109151

110152
callbacks = CallbackSet(summary_callback,
111153
analysis_callback,

examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,8 @@ function Trixi.analyze(::Val{:energy_potential}, du, u_euler, t,
132132
u_gravity) do u, i, j, element,
133133
equations_euler, dg,
134134
equations_gravity, u_gravity
135-
u_euler_local = Trixi.get_node_vars(u_euler, equations_euler, dg, i, j, element)
136-
u_gravity_local = Trixi.get_node_vars(u_gravity, equations_gravity, dg, i, j,
137-
element)
135+
u_euler_local = get_node_vars(u_euler, equations_euler, dg, i, j, element)
136+
u_gravity_local = get_node_vars(u_gravity, equations_gravity, dg, i, j, element)
138137
# OBS! subtraction is specific to Jeans instability test where rho0 = 1.5e7
139138
# For formula of potential energy see
140139
# "Galactic Dynamics" by Binney and Tremaine, 2nd ed., equation (2.18)

examples/structured_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
9595
save_solution = SaveSolutionCallback(interval = 100,
9696
save_initial_solution = true,
9797
save_final_solution = true,
98-
solution_variables = cons2prim)
98+
solution_variables = cons2prim,
99+
extra_node_variables = (:limiting_coefficient,))
99100

100101
stepsize_callback = StepsizeCallback(cfl = 0.6)
101102

examples/t8code_3d_dgsem/elixir_euler_ec.jl

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,37 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval)
6868

6969
alive_callback = AliveCallback(analysis_interval = analysis_interval)
7070

71+
# Add `:thermodynamic_entropy` to `extra_node_variables` tuple ...
72+
extra_node_variables = (:thermodynamic_entropy,)
73+
74+
# ... and specify the function `get_node_variable` for this symbol,
75+
# with first argument matching the symbol (turned into a type via `Val`) for dispatching.
76+
function Trixi.get_node_variable(::Val{:thermodynamic_entropy}, u, mesh, equations,
77+
dg, cache)
78+
n_nodes = nnodes(dg)
79+
n_elements = nelements(dg, cache)
80+
# By definition, the variable must be provided at every node of every element!
81+
# Otherwise, the `SaveSolutionCallback` will crash.
82+
entropy_array = zeros(eltype(cache.elements),
83+
ntuple(_ -> n_nodes, ndims(mesh))..., # equivalent: `n_nodes, n_nodes, n_nodes`
84+
n_elements)
85+
86+
# We can accelerate the computation by thread-parallelizing the loop over elements
87+
# by using the `@threaded` macro.
88+
Trixi.@threaded for element in eachelement(dg, cache)
89+
for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)
90+
u_node = get_node_vars(u, equations, dg, i, j, k, element)
91+
92+
entropy_array[i, j, k, element] = Trixi.entropy_thermodynamic(u_node, equations)
93+
end
94+
end
95+
96+
return entropy_array
97+
end
7198
save_solution = SaveSolutionCallback(interval = 100,
7299
save_initial_solution = true,
73-
save_final_solution = true)
100+
save_final_solution = true,
101+
extra_node_variables = extra_node_variables) # Supply the additional `extra_node_variables` here
74102

75103
stepsize_callback = StepsizeCallback(cfl = 1.0)
76104

examples/tree_2d_dgsem/elixir_euler_blast_wave_amr.jl

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,40 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval)
6969

7070
alive_callback = AliveCallback(analysis_interval = analysis_interval)
7171

72+
# Add `:mach` to `extra_node_variables` tuple ...
73+
extra_node_variables = (:mach,)
74+
75+
# ... and specify the function `get_node_variable` for this symbol,
76+
# with first argument matching the symbol (turned into a type via `Val`) for dispatching.
77+
function Trixi.get_node_variable(::Val{:mach}, u, mesh, equations, dg, cache)
78+
n_nodes = nnodes(dg)
79+
n_elements = nelements(dg, cache)
80+
# By definition, the variable must be provided at every node of every element!
81+
# Otherwise, the `SaveSolutionCallback` will crash.
82+
mach_array = zeros(eltype(cache.elements),
83+
n_nodes, n_nodes, # equivalent: `ntuple(_ -> n_nodes, ndims(mesh))...,`
84+
n_elements)
85+
86+
# We can accelerate the computation by thread-parallelizing the loop over elements
87+
# by using the `@threaded` macro.
88+
Trixi.@threaded for element in eachelement(dg, cache)
89+
for j in eachnode(dg), i in eachnode(dg)
90+
u_node = get_node_vars(u, equations, dg, i, j, element)
91+
rho, v1, v2, p = prim2cons(u_node, equations)
92+
c = sqrt(equations.gamma * p / rho) # speed of sound
93+
v_magnitude = sqrt(v1^2 + v2^2)
94+
95+
mach_array[i, j, element] = v_magnitude / c
96+
end
97+
end
98+
99+
return mach_array
100+
end
72101
save_solution = SaveSolutionCallback(interval = 100,
73102
save_initial_solution = true,
74103
save_final_solution = true,
75-
solution_variables = cons2prim)
104+
solution_variables = cons2prim,
105+
extra_node_variables = extra_node_variables) # Supply the additional `extra_node_variables` here
76106

77107
amr_indicator = IndicatorHennemannGassner(semi,
78108
alpha_max = 0.5,

examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
7777
save_solution = SaveSolutionCallback(interval = 100,
7878
save_initial_solution = true,
7979
save_final_solution = true,
80-
solution_variables = cons2prim)
80+
solution_variables = cons2prim,
81+
extra_node_variables = (:limiting_coefficient,))
8182

8283
stepsize_callback = StepsizeCallback(cfl = 0.3)
8384

examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
6666
save_solution = SaveSolutionCallback(interval = 100,
6767
save_initial_solution = true,
6868
save_final_solution = true,
69-
solution_variables = cons2prim)
69+
solution_variables = cons2prim,
70+
extra_node_variables = (:limiting_coefficient,))
7071

7172
save_restart = SaveRestartCallback(interval = 1000,
7273
save_final_restart = true)

0 commit comments

Comments
 (0)