-
Notifications
You must be signed in to change notification settings - Fork 112
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add implementation of subcell bounds check (#1672)
* Add implementation of bounds check * Shorten code by relocate use of `interval` * Add note in docstring * Fix note in docstring of `SubcellLimiterIDP` * Add test for deviations file * Adapt last commit to specific setup in test * Adapt test * Disable test if `!coverage` * Remove non-needed code * Implement first suggestions * Dispatch `init/finalize_callback()` routines * Revise docstring * Rework calculation of bounds * Fix typo * Add comment * Replace construction of `Symbol`s * Implement suggestions for docstring
- Loading branch information
Showing
9 changed files
with
203 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). | ||
# Since these FMAs can increase the performance of many numerical algorithms, | ||
# we need to opt-in explicitly. | ||
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. | ||
@muladd begin | ||
#! format: noindent | ||
|
||
""" | ||
BoundsCheckCallback(; output_directory="out", save_errors=false, interval=1) | ||
Subcell limiting techniques with [`SubcellLimiterIDP`](@ref) are constructed to adhere certain | ||
local or global bounds. To make sure that these bounds are actually met, this callback calculates | ||
the maximum deviation from the bounds. The maximum deviation per applied bound is printed to | ||
the screen at the end of the simulation. | ||
For more insights, when setting `save_errors=true` the occurring errors are exported every | ||
`interval` time steps during the simulation. Then, the maximum deviations since the last | ||
export are saved in "`output_directory`/deviations.txt". | ||
The `BoundsCheckCallback` has to be applied as a stage callback for the SSPRK time integration scheme. | ||
!!! note | ||
For `SubcellLimiterIDP`, the solution is corrected in the a posteriori correction stage | ||
[`SubcellLimiterIDPCorrection`](@ref). So, to check the final solution, this bounds check | ||
callback must be called after the correction stage. | ||
""" | ||
struct BoundsCheckCallback | ||
output_directory::String | ||
save_errors::Bool | ||
interval::Int | ||
end | ||
|
||
function BoundsCheckCallback(; output_directory = "out", save_errors = false, | ||
interval = 1) | ||
BoundsCheckCallback(output_directory, save_errors, interval) | ||
end | ||
|
||
function (callback::BoundsCheckCallback)(u_ode, integrator, stage) | ||
mesh, equations, solver, cache = mesh_equations_solver_cache(integrator.p) | ||
(; t, iter, alg) = integrator | ||
u = wrap_array(u_ode, mesh, equations, solver, cache) | ||
|
||
save_errors = callback.save_errors && (callback.interval > 0) && | ||
(stage == length(alg.c)) && | ||
(iter % callback.interval == 0 || integrator.finalstep) | ||
@trixi_timeit timer() "check_bounds" check_bounds(u, mesh, equations, solver, cache, | ||
solver.volume_integral, t, | ||
iter + 1, | ||
callback.output_directory, | ||
save_errors) | ||
end | ||
|
||
function check_bounds(u, mesh, equations, solver, cache, | ||
volume_integral::AbstractVolumeIntegral, t, iter, | ||
output_directory, save_errors) | ||
return nothing | ||
end | ||
|
||
function check_bounds(u, mesh, equations, solver, cache, | ||
volume_integral::VolumeIntegralSubcellLimiting, t, iter, | ||
output_directory, save_errors) | ||
check_bounds(u, mesh, equations, solver, cache, volume_integral.limiter, t, iter, | ||
output_directory, save_errors) | ||
end | ||
|
||
function init_callback(callback::BoundsCheckCallback, semi) | ||
init_callback(callback, semi, semi.solver.volume_integral) | ||
end | ||
|
||
init_callback(callback::BoundsCheckCallback, semi, volume_integral::AbstractVolumeIntegral) = nothing | ||
|
||
function init_callback(callback::BoundsCheckCallback, semi, | ||
volume_integral::VolumeIntegralSubcellLimiting) | ||
init_callback(callback, semi, volume_integral.limiter) | ||
end | ||
|
||
function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterIDP) | ||
if !callback.save_errors || (callback.interval == 0) | ||
return nothing | ||
end | ||
|
||
(; positivity) = limiter | ||
(; output_directory) = callback | ||
variables = varnames(cons2cons, semi.equations) | ||
|
||
mkpath(output_directory) | ||
open("$output_directory/deviations.txt", "a") do f | ||
print(f, "# iter, simu_time") | ||
if positivity | ||
for v in limiter.positivity_variables_cons | ||
print(f, ", " * string(variables[v]) * "_min") | ||
end | ||
end | ||
println(f) | ||
end | ||
|
||
return nothing | ||
end | ||
|
||
function finalize_callback(callback::BoundsCheckCallback, semi) | ||
finalize_callback(callback, semi, semi.solver.volume_integral) | ||
end | ||
|
||
finalize_callback(callback::BoundsCheckCallback, semi, volume_integral::AbstractVolumeIntegral) = nothing | ||
|
||
function finalize_callback(callback::BoundsCheckCallback, semi, | ||
volume_integral::VolumeIntegralSubcellLimiting) | ||
finalize_callback(callback, semi, volume_integral.limiter) | ||
end | ||
|
||
@inline function finalize_callback(callback::BoundsCheckCallback, semi, | ||
limiter::SubcellLimiterIDP) | ||
(; positivity) = limiter | ||
(; idp_bounds_delta) = limiter.cache | ||
variables = varnames(cons2cons, semi.equations) | ||
|
||
println("─"^100) | ||
println("Maximum deviation from bounds:") | ||
println("─"^100) | ||
if positivity | ||
for v in limiter.positivity_variables_cons | ||
println(string(variables[v]) * ":\n- positivity: ", | ||
idp_bounds_delta[Symbol(string(v), "_min")][2]) | ||
end | ||
end | ||
println("─"^100 * "\n") | ||
|
||
return nothing | ||
end | ||
|
||
include("subcell_bounds_check_2d.jl") | ||
end # @muladd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). | ||
# Since these FMAs can increase the performance of many numerical algorithms, | ||
# we need to opt-in explicitly. | ||
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. | ||
@muladd begin | ||
#! format: noindent | ||
|
||
@inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, | ||
limiter::SubcellLimiterIDP, | ||
time, iter, output_directory, save_errors) | ||
(; positivity) = solver.volume_integral.limiter | ||
(; variable_bounds) = limiter.cache.subcell_limiter_coefficients | ||
(; idp_bounds_delta) = limiter.cache | ||
|
||
if positivity | ||
for v in limiter.positivity_variables_cons | ||
key = Symbol(string(v), "_min") | ||
deviation = idp_bounds_delta[key] | ||
for element in eachelement(solver, cache), j in eachnode(solver), | ||
i in eachnode(solver) | ||
|
||
var = u[v, i, j, element] | ||
deviation[1] = max(deviation[1], | ||
variable_bounds[key][i, j, element] - var) | ||
end | ||
deviation[2] = max(deviation[2], deviation[1]) | ||
end | ||
end | ||
if save_errors | ||
# Print to output file | ||
open("$output_directory/deviations.txt", "a") do f | ||
print(f, iter, ", ", time) | ||
if positivity | ||
for v in limiter.positivity_variables_cons | ||
key = Symbol(string(v), "_min") | ||
print(f, ", ", idp_bounds_delta[key][1]) | ||
end | ||
end | ||
println(f) | ||
end | ||
# Reset first entries of idp_bounds_delta | ||
for (key, _) in idp_bounds_delta | ||
idp_bounds_delta[key][1] = zero(eltype(idp_bounds_delta[key][1])) | ||
end | ||
end | ||
|
||
return nothing | ||
end | ||
end # @muladd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters