Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use trixi_include from TrixiBase.jl #1832

Merged
merged 12 commits into from
Feb 15, 2024
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
Triangulate = "f7e6ffb2-c36d-4f8f-a77e-16e897189344"
TriplotBase = "981d1d27-644d-49a2-9326-4793e63143c3"
TriplotRecipes = "808ab39a-a642-4abf-81ff-4cb34ebbffa3"
TrixiBase = "9a0f1c46-06d5-4909-a5a3-ce25d3fa3284"
efaulhaber marked this conversation as resolved.
Show resolved Hide resolved

[weakdeps]
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
Expand Down
3 changes: 2 additions & 1 deletion src/Trixi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ using Triangulate: Triangulate, TriangulateIO, triangulate
export TriangulateIO # for type parameter in DGMultiMesh
using TriplotBase: TriplotBase
using TriplotRecipes: DGTriPseudocolor
@reexport using TrixiBase: trixi_include
@reexport using SimpleUnPack: @unpack
using SimpleUnPack: @pack!
using DataStructures: BinaryHeap, FasterForward, extract_all!
Expand Down Expand Up @@ -129,7 +130,7 @@ include("callbacks_step/callbacks_step.jl")
include("callbacks_stage/callbacks_stage.jl")
include("semidiscretization/semidiscretization_euler_gravity.jl")

# `trixi_include` and special elixirs such as `convergence_test`
# Special elixirs such as `convergence_test`
include("auxiliary/special_elixirs.jl")

# Plot recipes and conversion functions to visualize results with Plots.jl
Expand Down
3 changes: 0 additions & 3 deletions src/auxiliary/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -577,9 +577,6 @@ function _precompile_manual_()
@assert Base.precompile(Tuple{typeof(show), Base.TTY, lbm_collision_callback_type})
@assert Base.precompile(Tuple{typeof(show), IOContext{Base.TTY}, MIME"text/plain",
lbm_collision_callback_type})

# infrastructure, special elixirs
@assert Base.precompile(Tuple{typeof(trixi_include), String})
sloede marked this conversation as resolved.
Show resolved Hide resolved
end

@assert Base.precompile(Tuple{typeof(init_mpi)})
Expand Down
52 changes: 0 additions & 52 deletions src/auxiliary/special_elixirs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,6 @@
@muladd begin
#! format: noindent

# Note: We can't call the method below `Trixi.include` since that is created automatically
# inside `module Trixi` to `include` source files and evaluate them within the global scope
# of `Trixi`. However, users will want to evaluate in the global scope of `Main` or something
# similar to manage dependencies on their own.
"""
trixi_include([mod::Module=Main,] elixir::AbstractString; kwargs...)

`include` the file `elixir` and evaluate its content in the global scope of module `mod`.
You can override specific assignments in `elixir` by supplying keyword arguments.
It's basic purpose is to make it easier to modify some parameters while running Trixi.jl from the
REPL. Additionally, this is used in tests to reduce the computational burden for CI while still
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
[documentation](https://docs.sciml.ai/DiffEqDocs/stable/basics/common_solver_opts/).

# Examples

```jldoctest
julia> redirect_stdout(devnull) do
trixi_include(@__MODULE__, joinpath(examples_dir(), "tree_1d_dgsem", "elixir_advection_extended.jl"),
tspan=(0.0, 0.1))
sol.t[end]
end
[ Info: You just called `trixi_include`. Julia may now compile the code, please be patient.
0.1
```
"""
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."
end
Base.include(ex -> replace_assignments(insert_maxiters(ex); kwargs...), mod, elixir)
end

function trixi_include(elixir::AbstractString; kwargs...)
trixi_include(Main, elixir; kwargs...)
end

"""
convergence_test([mod::Module=Main,] elixir::AbstractString, iterations; kwargs...)

Expand Down
97 changes: 0 additions & 97 deletions test/test_unit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1529,103 +1529,6 @@ end

@test mesh.boundary_faces[:entire_boundary] == [1, 2]
end

@testset "trixi_include" begin
@trixi_testset "Basic" begin
example = """
x = 4
"""

filename = tempname()
try
open(filename, "w") do file
write(file, example)
end

# Use `@trixi_testset`, which wraps code in a temporary module, and call
# `trixi_include` with `@__MODULE__` in order to isolate this test.
@test_warn "You just called" trixi_include(@__MODULE__, filename)
@test @isdefined x
@test x == 4

@test_warn "You just called" trixi_include(@__MODULE__, filename, x = 7)
@test x == 7

@test_throws "assignment `y` not found in expression" trixi_include(@__MODULE__,
filename,
y = 3)
finally
rm(filename, force = true)
end
end

@trixi_testset "With `solve` Without `maxiters`" begin
# `trixi_include` assumes this to be the `solve` function of OrdinaryDiffEq,
# and therefore tries to insert the kwarg `maxiters`, which will fail here.
example = """
solve() = 0
x = solve()
"""

filename = tempname()
try
open(filename, "w") do file
write(file, example)
end

# Use `@trixi_testset`, which wraps code in a temporary module, and call
# `trixi_include` with `@__MODULE__` in order to isolate this test.
@test_throws "no method matching solve(; maxiters::Int64)" trixi_include(@__MODULE__,
filename)

@test_throws "no method matching solve(; maxiters::Int64)" trixi_include(@__MODULE__,
filename,
maxiters = 3)
finally
rm(filename, force = true)
end
end

@trixi_testset "With `solve` with `maxiters`" begin
# We need another example file that we include with `Base.include` first, in order to
# define the `solve` method without `trixi_include` trying to insert `maxiters` kwargs.
# Then, we can test that `trixi_include` inserts the kwarg in the `solve()` call.
example1 = """
solve(; maxiters=0) = maxiters
"""

example2 = """
x = solve()
"""

filename1 = tempname()
filename2 = tempname()
try
open(filename1, "w") do file
write(file, example1)
end
open(filename2, "w") do file
write(file, example2)
end

# Use `@trixi_testset`, which wraps code in a temporary module, and call
# `Base.include` and `trixi_include` with `@__MODULE__` in order to isolate this test.
Base.include(@__MODULE__, filename1)
@test_warn "You just called" trixi_include(@__MODULE__, filename2)
@test @isdefined x
# This is the default `maxiters` inserted by `trixi_include`
@test x == 10^5

@test_warn "You just called" trixi_include(@__MODULE__, filename2,
maxiters = 7)
# Test that `maxiters` got overwritten
@test x == 7
finally
rm(filename1, force = true)
rm(filename2, force = true)
end
end
end
end

end #module
Loading