Skip to content

Commit

Permalink
Make error norm calculation optional (#1755)
Browse files Browse the repository at this point in the history
* Make error norm calculation optional

* test no errors

* no errors

* comment more clear

* shorter version?

* add text

* update docstring

* cut error passing

* Update src/callbacks_step/analysis.jl

Co-authored-by: Hendrik Ranocha <[email protected]>

* print in if clause

* shorten

* Update src/callbacks_step/analysis.jl

Co-authored-by: Hendrik Ranocha <[email protected]>

* Add docstring for default_analysis_errors

* Update src/equations/equations.jl

---------

Co-authored-by: Hendrik Ranocha <[email protected]>
  • Loading branch information
DanielDoehring and ranocha authored Dec 6, 2023
1 parent 7a7ce48 commit 3d899bc
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 22 deletions.
54 changes: 32 additions & 22 deletions src/callbacks_step/analysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ Additional errors can be computed, e.g. by passing
`extra_analysis_errors = (:l2_error_primitive, :linf_error_primitive)`
or `extra_analysis_errors = (:conservation_error,)`.
If you want to omit the computation (to safe compute-time) of the [`default_analysis_errors`](@ref), specify
`analysis_errors = Symbol[]`.
Note: `default_analysis_errors` are `:l2_error` and `:linf_error` for all equations.
If you want to compute `extra_analysis_errors` such as `:conservation_error` solely, i.e.,
without `:l2_error, :linf_error` you need to specify
`analysis_errors = [:conservation_error]` instead of `extra_analysis_errors = [:conservation_error]`.
Further scalar functions `func` in `extra_analysis_integrals` are applied to the numerical
solution and integrated over the computational domain. Some examples for this are
[`entropy`](@ref), [`energy_kinetic`](@ref), [`energy_internal`](@ref), and [`energy_total`](@ref).
Expand Down Expand Up @@ -332,7 +339,8 @@ function (analysis_callback::AnalysisCallback)(u_ode, du_ode, integrator, semi)
@notimeit timer() integrator.f(du_ode, u_ode, semi, t)
u = wrap_array(u_ode, mesh, equations, solver, cache)
du = wrap_array(du_ode, mesh, equations, solver, cache)
l2_error, linf_error = analysis_callback(io, du, u, u_ode, t, semi)
# Compute l2_error, linf_error
analysis_callback(io, du, u, u_ode, t, semi)

mpi_println(""^100)
mpi_println()
Expand All @@ -354,8 +362,7 @@ function (analysis_callback::AnalysisCallback)(u_ode, du_ode, integrator, semi)
analysis_callback.start_time_last_analysis = time_ns()
analysis_callback.ncalls_rhs_last_analysis = ncalls(semi.performance_counter)

# Return errors for EOC analysis
return l2_error, linf_error
return nothing
end

# This method is just called internally from `(analysis_callback::AnalysisCallback)(integrator)`
Expand All @@ -377,28 +384,31 @@ function (analysis_callback::AnalysisCallback)(io, du, u, u_ode, t, semi)
println()
end

# Calculate L2/Linf errors, which are also returned
l2_error, linf_error = calc_error_norms(u_ode, t, analyzer, semi, cache_analysis)
if :l2_error in analysis_errors || :linf_error in analysis_errors
# Calculate L2/Linf errors
l2_error, linf_error = calc_error_norms(u_ode, t, analyzer, semi,
cache_analysis)

if mpi_isroot()
# L2 error
if :l2_error in analysis_errors
print(" L2 error: ")
for v in eachvariable(equations)
@printf(" % 10.8e", l2_error[v])
@printf(io, " % 10.8e", l2_error[v])
if mpi_isroot()
# L2 error
if :l2_error in analysis_errors
print(" L2 error: ")
for v in eachvariable(equations)
@printf(" % 10.8e", l2_error[v])
@printf(io, " % 10.8e", l2_error[v])
end
println()
end
println()
end

# Linf error
if :linf_error in analysis_errors
print(" Linf error: ")
for v in eachvariable(equations)
@printf(" % 10.8e", linf_error[v])
@printf(io, " % 10.8e", linf_error[v])
# Linf error
if :linf_error in analysis_errors
print(" Linf error: ")
for v in eachvariable(equations)
@printf(" % 10.8e", linf_error[v])
@printf(io, " % 10.8e", linf_error[v])
end
println()
end
println()
end
end

Expand Down Expand Up @@ -477,7 +487,7 @@ function (analysis_callback::AnalysisCallback)(io, du, u, u_ode, t, semi)
# additional integrals
analyze_integrals(analysis_integrals, io, du, u, t, semi)

return l2_error, linf_error
return nothing
end

# Print level information only if AMR is enabled
Expand Down
7 changes: 7 additions & 0 deletions src/equations/equations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,14 @@ combined with certain solvers (e.g., subcell limiting).
function n_nonconservative_terms end
have_constant_speed(::AbstractEquations) = False()

"""
default_analysis_errors(equations)
Default analysis errors (`:l2_error` and `:linf_error`) used by the
[`AnalysisCallback`](@ref).
"""
default_analysis_errors(::AbstractEquations) = (:l2_error, :linf_error)

"""
default_analysis_integrals(equations)
Expand Down
14 changes: 14 additions & 0 deletions test/test_tree_1d_advection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ end
end
end

@trixi_testset "elixir_advection_basic.jl (No errors)" begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"),
analysis_callback=AnalysisCallback(semi, interval = 42,
analysis_errors = Symbol[]))
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
t = sol.t[end]
u_ode = sol.u[end]
du_ode = similar(u_ode)
@test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000
end
end

@trixi_testset "elixir_advection_finite_volume.jl" begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_finite_volume.jl"),
l2=[0.011662300515980219],
Expand Down

0 comments on commit 3d899bc

Please sign in to comment.