Skip to content

Commit

Permalink
Throw error in trixi_include when assignment is not found (trixi-fr…
Browse files Browse the repository at this point in the history
…amework#1737)

* Throw error in `trixi_include` when assignment is not found

* Add tests for `trixi_include`

* Reformat

* Update test/test_unit.jl

Co-authored-by: Michael Schlottke-Lakemper <[email protected]>

* Add more comments

* Fix convergence tests and `trixi_include` with `skip_coverage`

* Fix tests trying to override non-existing assignments

* Add `maxiters` to restart elixirs and exclude for coverage tests

* Reformat

* Reformat

* Add comment and more specific error in  `convergence_test`

* Update src/auxiliary/special_elixirs.jl

Co-authored-by: Michael Schlottke-Lakemper <[email protected]>

* Update src/auxiliary/special_elixirs.jl

Co-authored-by: Michael Schlottke-Lakemper <[email protected]>

* Fix tests

* Use `@test_nowarn_mod`

* Fix tests

* Fix tests (again)

---------

Co-authored-by: Michael Schlottke-Lakemper <[email protected]>
Co-authored-by: Hendrik Ranocha <[email protected]>
  • Loading branch information
3 people authored Nov 18, 2023
1 parent 09bdf97 commit 1635d31
Show file tree
Hide file tree
Showing 21 changed files with 196 additions and 45 deletions.
2 changes: 1 addition & 1 deletion examples/p4est_2d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false),
dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep = false, callback = callbacks);
save_everystep = false, callback = callbacks, maxiters = 100_000);

# Get the last time index and work with that.
load_timestep!(integrator, restart_filename)
Expand Down
2 changes: 1 addition & 1 deletion examples/p4est_3d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false),
dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep = false, callback = callbacks);
save_everystep = false, callback = callbacks, maxiters = 100_000);

# Get the last time index and work with that.
load_timestep!(integrator, restart_filename)
Expand Down
2 changes: 1 addition & 1 deletion examples/structured_2d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false),
dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep = false, callback = callbacks);
save_everystep = false, callback = callbacks, maxiters = 100_000);

# Get the last time index and work with that.
load_timestep!(integrator, restart_filename)
Expand Down
2 changes: 1 addition & 1 deletion examples/structured_3d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false),
dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep = false, callback = callbacks);
save_everystep = false, callback = callbacks, maxiters = 100_000);

# Get the last time index and work with that.
load_timestep!(integrator, restart_filename)
Expand Down
2 changes: 1 addition & 1 deletion examples/tree_2d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ save_solution.condition.save_initial_solution = false

integrator = init(ode, alg,
dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep = false, callback = callbacks; ode_default_options()...)
callback = callbacks, maxiters = 100_000; ode_default_options()...)

# Load saved context for adaptive time integrator
if integrator.opts.adaptive
Expand Down
2 changes: 1 addition & 1 deletion examples/tree_3d_dgsem/elixir_advection_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false),
dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep = false, callback = callbacks);
save_everystep = false, callback = callbacks, maxiters = 100_000);

# Get the last time index and work with that.
load_timestep!(integrator, restart_filename)
Expand Down
2 changes: 1 addition & 1 deletion examples/unstructured_2d_dgsem/elixir_euler_restart.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ save_solution.condition.save_initial_solution = false

integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false),
dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep = false, callback = callbacks);
save_everystep = false, callback = callbacks, maxiters = 100_000);

# Get the last time index and work with that.
load_timestep!(integrator, restart_filename)
Expand Down
47 changes: 37 additions & 10 deletions src/auxiliary/special_elixirs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ providing examples with sensible default values for users.
Before replacing assignments in `elixir`, the keyword argument `maxiters` is inserted
into calls to `solve` and `Trixi.solve` with it's default value used in the SciML ecosystem
for ODEs, see the "Miscellaneous" section of the
for ODEs, see the "Miscellaneous" section of the
[documentation](https://docs.sciml.ai/DiffEqDocs/stable/basics/common_solver_opts/).
# Examples
Expand All @@ -36,6 +36,16 @@ julia> redirect_stdout(devnull) do
```
"""
function trixi_include(mod::Module, elixir::AbstractString; kwargs...)
# Check that all kwargs exist as assignments
code = read(elixir, String)
expr = Meta.parse("begin \n$code \nend")
expr = insert_maxiters(expr)

for (key, val) in kwargs
# This will throw an error when `key` is not found
find_assignment(expr, key)
end

# Print information on potential wait time only in non-parallel case
if !mpi_isparallel()
@info "You just called `trixi_include`. Julia may now compile the code, please be patient."
Expand Down Expand Up @@ -243,19 +253,25 @@ end
function find_assignment(expr, destination)
# declare result to be able to assign to it in the closure
local result
found = false

# find explicit and keyword assignments
walkexpr(expr) do x
if x isa Expr
if (x.head === Symbol("=") || x.head === :kw) &&
x.args[1] === Symbol(destination)
result = x.args[2]
found = true
# dump(x)
end
end
return x
end

if !found
throw(ArgumentError("assignment `$destination` not found in expression"))
end

result
end

Expand All @@ -274,17 +290,28 @@ function extract_initial_resolution(elixir, kwargs)
return initial_refinement_level
end
catch e
if isa(e, UndefVarError)
# get cells_per_dimension from the elixir
cells_per_dimension = eval(find_assignment(expr, :cells_per_dimension))

if haskey(kwargs, :cells_per_dimension)
return kwargs[:cells_per_dimension]
else
return cells_per_dimension
# If `initial_refinement_level` is not found, we will get an `ArgumentError`
if isa(e, ArgumentError)
try
# get cells_per_dimension from the elixir
cells_per_dimension = eval(find_assignment(expr, :cells_per_dimension))

if haskey(kwargs, :cells_per_dimension)
return kwargs[:cells_per_dimension]
else
return cells_per_dimension
end
catch e2
# If `cells_per_dimension` is not found either
if isa(e2, ArgumentError)
throw(ArgumentError("`convergence_test` requires the elixir to define " *
"`initial_refinement_level` or `cells_per_dimension`"))
else
rethrow()
end
end
else
throw(e)
rethrow()
end
end
end
Expand Down
5 changes: 4 additions & 1 deletion test/test_mpi_p4est_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_2d_dgsem")
@trixi_testset "elixir_advection_restart.jl" begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"),
l2=[4.507575525876275e-6],
linf=[6.21489667023134e-5])
linf=[6.21489667023134e-5],
# With the default `maxiters = 1` in coverage tests,
# there would be no time steps after the restart.
coverage_override=(maxiters = 100_000,))
end

@trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_flag.jl" begin
Expand Down
5 changes: 4 additions & 1 deletion test/test_mpi_p4est_3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem")
@trixi_testset "elixir_advection_restart.jl" begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"),
l2=[0.002590388934758452],
linf=[0.01840757696885409])
linf=[0.01840757696885409],
# With the default `maxiters = 1` in coverage tests,
# there would be no time steps after the restart.
coverage_override=(maxiters = 100_000,))
end

@trixi_testset "elixir_advection_cubed_sphere.jl" begin
Expand Down
9 changes: 6 additions & 3 deletions test/test_p4est_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@ end
@trixi_testset "elixir_advection_restart.jl" begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"),
l2=[4.507575525876275e-6],
linf=[6.21489667023134e-5])
linf=[6.21489667023134e-5],
# With the default `maxiters = 1` in coverage tests,
# there would be no time steps after the restart.
coverage_override=(maxiters = 100_000,))
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
Expand Down Expand Up @@ -216,8 +219,8 @@ end
],
surface_flux=flux_hlle,
tspan=(0.0, 0.3))
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
t = sol.t[end]
u_ode = sol.u[end]
Expand Down
9 changes: 6 additions & 3 deletions test/test_p4est_3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ end
@trixi_testset "elixir_advection_restart.jl" begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"),
l2=[0.002590388934758452],
linf=[0.01840757696885409])
linf=[0.01840757696885409],
# With the default `maxiters = 1` in coverage tests,
# there would be no time steps after the restart.
coverage_override=(maxiters = 100_000,))
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
Expand Down Expand Up @@ -305,8 +308,8 @@ end
],
tspan=(0.0, 0.3),
surface_flux=flux_hlle)
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
t = sol.t[end]
u_ode = sol.u[end]
Expand Down
13 changes: 5 additions & 8 deletions test/test_special_elixirs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,18 @@ coverage = occursin("--code-coverage", cmd) && !occursin("--code-coverage=none",
# the convergence test logic
@test_nowarn_mod convergence_test(@__MODULE__,
joinpath(EXAMPLES_DIR, "tree_2d_dgsem",
"elixir_advection_basic.jl"), 2,
tspan = (0.0, 0.01))
"elixir_advection_basic.jl"), 2)
@test_nowarn_mod convergence_test(@__MODULE__,
joinpath(EXAMPLES_DIR, "tree_2d_dgsem",
"elixir_advection_extended.jl"), 2,
initial_refinement_level = 0,
tspan = (0.0, 0.1))
@test_nowarn_mod convergence_test(@__MODULE__,
joinpath(EXAMPLES_DIR, "structured_2d_dgsem",
"elixir_advection_basic.jl"), 2,
tspan = (0.0, 0.01))
"elixir_advection_basic.jl"), 2)
@test_nowarn_mod convergence_test(@__MODULE__,
joinpath(EXAMPLES_DIR, "structured_2d_dgsem",
"elixir_advection_coupled.jl"), 2,
tspan = (0.0, 0.01))
"elixir_advection_coupled.jl"), 2)
@test_nowarn_mod convergence_test(@__MODULE__,
joinpath(EXAMPLES_DIR, "structured_2d_dgsem",
"elixir_advection_extended.jl"), 2,
Expand Down Expand Up @@ -345,8 +342,8 @@ end
end

@timed_testset "elixir_euler_ad.jl" begin
@test_trixi_include(joinpath(examples_dir(), "special_elixirs",
"elixir_euler_ad.jl"))
@test_nowarn_mod trixi_include(joinpath(examples_dir(), "special_elixirs",
"elixir_euler_ad.jl"))
end
end
end
Expand Down
15 changes: 12 additions & 3 deletions test/test_structured_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ end
@trixi_testset "elixir_advection_restart.jl" begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"),
l2=[4.219208035582454e-6],
linf=[3.438434404412494e-5])
linf=[3.438434404412494e-5],
# With the default `maxiters = 1` in coverage tests,
# there would be no time steps after the restart.
coverage_override=(maxiters = 100_000,))
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
Expand All @@ -211,7 +214,10 @@ end
linf=[0.0015194252169410394],
rtol=5.0e-5, # Higher tolerance to make tests pass in CI (in particular with macOS)
elixir_file="elixir_advection_waving_flag.jl",
restart_file="restart_000021.h5")
restart_file="restart_000021.h5",
# With the default `maxiters = 1` in coverage tests,
# there would be no time steps after the restart.
coverage_override=(maxiters = 100_000,))
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
Expand All @@ -227,7 +233,10 @@ end
l2=[7.841217436552029e-15],
linf=[1.0857981180834031e-13],
elixir_file="elixir_advection_free_stream.jl",
restart_file="restart_000036.h5")
restart_file="restart_000036.h5",
# With the default `maxiters = 1` in coverage tests,
# there would be no time steps after the restart.
coverage_override=(maxiters = 100_000,))
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
Expand Down
5 changes: 4 additions & 1 deletion test/test_structured_3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ end
@trixi_testset "elixir_advection_restart.jl" begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"),
l2=[0.0025903889347585777],
linf=[0.018407576968841655])
linf=[0.018407576968841655],
# With the default `maxiters = 1` in coverage tests,
# there would be no time steps after the restart.
coverage_override=(maxiters = 100_000,))
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
Expand Down
5 changes: 4 additions & 1 deletion test/test_threaded.jl
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,10 @@ end
linf=[0.0015194252169410394],
rtol=5.0e-5, # Higher tolerance to make tests pass in CI (in particular with macOS)
elixir_file="elixir_advection_waving_flag.jl",
restart_file="restart_000021.h5")
restart_file="restart_000021.h5",
# With the default `maxiters = 1` in coverage tests,
# there would be no time steps after the restart.
coverage_override=(maxiters = 100_000,))

# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
Expand Down
5 changes: 4 additions & 1 deletion test/test_tree_3d_advection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ end
@trixi_testset "elixir_advection_restart.jl" begin
@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"),
l2=[0.00016017848135651983],
linf=[0.0014175368788298393])
linf=[0.0014175368788298393],
# With the default `maxiters = 1` in coverage tests,
# there would be no time steps after the restart.
coverage_override=(maxiters = 100_000,))
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
Expand Down
2 changes: 1 addition & 1 deletion test/test_trixi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ macro test_trixi_include(elixir, args...)
local kwargs = Pair{Symbol, Any}[]
for arg in args
if (arg.head == :(=) &&
!(arg.args[1] in (:l2, :linf, :atol, :rtol, :coverage_override))
!(arg.args[1] in (:l2, :linf, :atol, :rtol, :coverage_override, :skip_coverage))
&& !(coverage && arg.args[1] in keys(coverage_override)))
push!(kwargs, Pair(arg.args...))
end
Expand Down
Loading

0 comments on commit 1635d31

Please sign in to comment.