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)

examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.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 = 1000,
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.4)
8384

examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
6969
save_solution = SaveSolutionCallback(dt = 0.1,
7070
save_initial_solution = true,
7171
save_final_solution = true,
72-
solution_variables = cons2prim)
72+
solution_variables = cons2prim,
73+
extra_node_variables = (:limiting_coefficient,))
7374

7475
stepsize_callback = StepsizeCallback(cfl = 0.6)
7576

examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,39 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval,
143143

144144
alive_callback = AliveCallback(analysis_interval = analysis_interval)
145145

146+
# Add `:temperature` to `extra_node_variables` tuple ...
147+
extra_node_variables = (:temperature,)
148+
149+
# ... and specify the function `get_node_variable` for this symbol,
150+
# with first argument matching the symbol (turned into a type via `Val`) for dispatching.
151+
function Trixi.get_node_variable(::Val{:temperature}, u, mesh, equations, dg, cache)
152+
n_nodes = nnodes(dg)
153+
n_elements = nelements(dg, cache)
154+
# By definition, the variable must be provided at every node of every element!
155+
# Otherwise, the `SaveSolutionCallback` will crash.
156+
temp_array = zeros(eltype(cache.elements),
157+
n_nodes, n_nodes, # equivalent: `ntuple(_ -> n_nodes, ndims(mesh))...,`
158+
n_elements)
159+
160+
# We can accelerate the computation by thread-parallelizing the loop over elements
161+
# by using the `@threaded` macro.
162+
Trixi.@threaded for element in eachelement(dg, cache)
163+
for j in eachnode(dg), i in eachnode(dg)
164+
u_node = get_node_vars(u, equations, dg, i, j, element)
165+
rho, _, _, p = prim2cons(u_node, equations)
166+
temp = p / rho # ideal gas equation with R = 1
167+
168+
temp_array[i, j, element] = temp
169+
end
170+
end
171+
172+
return temp_array
173+
end
146174
save_solution = SaveSolutionCallback(interval = 50,
147175
save_initial_solution = true,
148176
save_final_solution = true,
149-
solution_variables = cons2prim)
177+
solution_variables = cons2prim,
178+
extra_node_variables = extra_node_variables) # Supply the additional `extra_node_variables` here
150179

151180
amr_controller = ControllerThreeLevel(semi, TrixiExtension.IndicatorVortex(semi),
152181
base_level = 3,

examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
119119
save_solution = SaveSolutionCallback(interval = 600,
120120
save_initial_solution = true,
121121
save_final_solution = true,
122-
solution_variables = cons2prim)
122+
solution_variables = cons2prim,
123+
extra_node_variables = (:limiting_coefficient,))
123124

124125
stepsize_callback = StepsizeCallback(cfl = 0.4)
125126

examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
120120
save_solution = SaveSolutionCallback(interval = 300,
121121
save_initial_solution = true,
122122
save_final_solution = true,
123-
solution_variables = cons2prim)
123+
solution_variables = cons2prim,
124+
extra_node_variables = (:limiting_coefficient,))
124125

125126
stepsize_callback = StepsizeCallback(cfl = 0.9)
126127

examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval)
8282
save_solution = SaveSolutionCallback(interval = 100,
8383
save_initial_solution = true,
8484
save_final_solution = true,
85-
solution_variables = cons2prim)
85+
solution_variables = cons2prim,
86+
extra_node_variables = (:limiting_coefficient,))
8687

8788
cfl = 0.4
8889
stepsize_callback = StepsizeCallback(cfl = cfl)

0 commit comments

Comments
 (0)