diff --git a/src/callbacks_step/analysis.jl b/src/callbacks_step/analysis.jl index e5b4a01a88..ba23203295 100644 --- a/src/callbacks_step/analysis.jl +++ b/src/callbacks_step/analysis.jl @@ -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). @@ -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() @@ -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)` @@ -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 @@ -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 diff --git a/src/equations/equations.jl b/src/equations/equations.jl index efbcd40d43..7a3c326984 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -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) diff --git a/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl b/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl index cad5542aae..b5388cadc8 100644 --- a/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl +++ b/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl @@ -56,7 +56,8 @@ function initialize!(boundary_types_container::UnstructuredSortedBoundaryTypes{N for key in keys(boundary_dictionary) if !(key in all_names) println(stderr, - "ERROR: Key $(repr(key)) is not a valid boundary name") + "ERROR: Key $(repr(key)) is not a valid boundary name. " * + "Valid names are $all_names.") MPI.Abort(mpi_comm(), 1) end end @@ -67,7 +68,8 @@ function initialize!(boundary_types_container::UnstructuredSortedBoundaryTypes{N else for key in keys(boundary_dictionary) if !(key in unique_names) - error("Key $(repr(key)) is not a valid boundary name") + error("Key $(repr(key)) is not a valid boundary name. " * + "Valid names are $unique_names.") end end end diff --git a/test/test_tree_1d_advection.jl b/test/test_tree_1d_advection.jl index 7cfd78e0ad..a580a3b560 100644 --- a/test/test_tree_1d_advection.jl +++ b/test/test_tree_1d_advection.jl @@ -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],