diff --git a/.github/workflows/Tests.yml b/.github/workflows/Tests.yml index 7a27a1d9e..978d8d18e 100644 --- a/.github/workflows/Tests.yml +++ b/.github/workflows/Tests.yml @@ -38,10 +38,17 @@ jobs: - "NoPre" - "LinearSolveAutotune" - "Preferences" + - "Trim" os: - ubuntu-latest - macos-latest - windows-latest + exclude: + # Don't run trim tests on Julia versions below 1.12 + - group: Trim + version: "lts" + - group: Trim + version: "pre" uses: "SciML/.github/.github/workflows/tests.yml@v1" with: group: "${{ matrix.group }}" diff --git a/Project.toml b/Project.toml index 7f89526d8..5f386a640 100644 --- a/Project.toml +++ b/Project.toml @@ -41,13 +41,13 @@ EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" FastAlmostBandedMatrices = "9d29842c-ecb8-4973-b1e9-a27b1157504e" FastLapackInterface = "29a986be-02c6-4525-aec4-84b980013641" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" -Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" HYPRE = "b5ffcf37-a2bd-41ab-a3da-4bd9bc8ad771" IterativeSolvers = "42fd0dbc-a981-5370-80f2-aaf504508153" KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77" LAPACK_jll = "51474c39-65e3-53ba-86ba-03b1b862ec14" Metal = "dde4c033-4e86-420c-a63e-0dd931031962" +Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" Pardiso = "46dd5b70-b6fb-5a00-ae2d-e8fea33afaf2" RecursiveFactorization = "f2c3362d-daeb-58d1-803e-2bc74f2840b4" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" @@ -90,8 +90,8 @@ CUDSS = "0.4, 0.6.1" CUSOLVERRF = "0.2.6" ChainRulesCore = "1.25" CliqueTrees = "1.11.0" -ConcreteStructs = "0.2.3" ComponentArrays = "0.15.29" +ConcreteStructs = "0.2.3" DocStringExtensions = "0.9.3" EnumX = "1.0.4" EnzymeCore = "0.8.5" @@ -129,8 +129,8 @@ RecursiveFactorization = "0.2.26" Reexport = "1.2.2" SafeTestsets = "0.1" SciMLBase = "2.70" -SciMLOperators = "1.7.1" SciMLLogging = "1.3.1" +SciMLOperators = "1.7.1" Setfield = "1.1.1" SparseArrays = "1.10" Sparspak = "0.3.9" @@ -163,13 +163,13 @@ KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77" KrylovPreconditioners = "45d422c2-293f-44ce-8315-2cb988662dec" MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" Metal = "dde4c033-4e86-420c-a63e-0dd931031962" +Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" MultiFloats = "bdf0d083-296b-4888-a5b6-7498122e68a5" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" RecursiveFactorization = "f2c3362d-daeb-58d1-803e-2bc74f2840b4" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" -Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Sparspak = "e56a9233-b9d6-4f03-8d0f-1825330902ac" StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" diff --git a/test/runtests.jl b/test/runtests.jl index 2d2b5dc2e..15ab5554d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -73,3 +73,10 @@ end if Base.Sys.islinux() && (GROUP == "All" || GROUP == "LinearSolveHYPRE") && HAS_EXTENSIONS @time @safetestset "LinearSolveHYPRE" include("hypretests.jl") end + +if GROUP == "Trim" && VERSION >= v"1.12.0" + Pkg.activate("trim") + Pkg.develop(PackageSpec(path = dirname(@__DIR__))) + Pkg.instantiate() + @time @safetestset "Trim Tests" include("trim/runtests.jl") +end diff --git a/test/trim/Project.toml b/test/trim/Project.toml new file mode 100644 index 000000000..bdde4ead0 --- /dev/null +++ b/test/trim/Project.toml @@ -0,0 +1,25 @@ +name = "TrimTest" +uuid = "e59a8f5e-4b8c-4d8e-9c8e-8e8e8e8e8e8e" +version = "0.1.0" + +[deps] +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" +RecursiveFactorization = "f2c3362d-daeb-58d1-803e-2bc74f2840b4" +SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[extras] +JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" +SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" + +[targets] +test = ["JET", "SafeTestsets"] + +[compat] +LinearSolve = "3" +RecursiveFactorization = "0.2" +SciMLBase = "2" +StaticArrays = "1" +julia = "1.10" diff --git a/test/trim/linear_lu.jl b/test/trim/linear_lu.jl new file mode 100644 index 000000000..733f2e6e8 --- /dev/null +++ b/test/trim/linear_lu.jl @@ -0,0 +1,22 @@ +module TestLUFactorization +using LinearSolve +using LinearAlgebra +using StaticArrays +import SciMLBase + +# Define a simple linear problem with a dense matrix +const A_matrix = [4.0 1.0; 1.0 3.0] +const b_vector = [1.0, 2.0] + +const alg = LUFactorization() +const prob = LinearProblem(A_matrix, b_vector) +const cache = init(prob, alg) + +function solve_linear(x) + # Create a new problem with a modified b vector + b_new = [x, 2.0 * x] + reinit!(cache; b = b_new) + sol = solve!(cache) + return sol +end +end diff --git a/test/trim/linear_mkl.jl b/test/trim/linear_mkl.jl new file mode 100644 index 000000000..76b20c386 --- /dev/null +++ b/test/trim/linear_mkl.jl @@ -0,0 +1,22 @@ +module TestMKLLUFactorization +using LinearSolve +using LinearAlgebra +using StaticArrays +import SciMLBase + +# Define a simple linear problem with a dense matrix +const A_matrix = [4.0 1.0; 1.0 3.0] +const b_vector = [1.0, 2.0] + +const alg = MKLLUFactorization() +const prob = LinearProblem(A_matrix, b_vector) +const cache = init(prob, alg) + +function solve_linear(x) + # Create a new problem with a modified b vector + b_new = [x, 2.0 * x] + reinit!(cache; b = b_new) + sol = solve!(cache) + return sol +end +end diff --git a/test/trim/linear_rf.jl b/test/trim/linear_rf.jl new file mode 100644 index 000000000..fb90403a1 --- /dev/null +++ b/test/trim/linear_rf.jl @@ -0,0 +1,23 @@ +module TestRFLUFactorization +using LinearSolve +using LinearAlgebra +using StaticArrays +using RecursiveFactorization +import SciMLBase + +# Define a simple linear problem with a dense matrix +const A_matrix = [4.0 1.0; 1.0 3.0] +const b_vector = [1.0, 2.0] + +const alg = RFLUFactorization() +const prob = LinearProblem(A_matrix, b_vector) +const cache = init(prob, alg) + +function solve_linear(x) + # Create a new problem with a modified b vector + b_new = [x, 2.0 * x] + reinit!(cache; b = b_new) + sol = solve!(cache) + return sol +end +end diff --git a/test/trim/main_lu.jl b/test/trim/main_lu.jl new file mode 100644 index 000000000..3bc97767e --- /dev/null +++ b/test/trim/main_lu.jl @@ -0,0 +1,8 @@ +using TrimTest + +function (@main)(argv::Vector{String})::Cint + x = parse(Float64, argv[1]) + sol = TrimTest.TestLUFactorization.solve_linear(x) + println(Core.stdout, sum(sol.u)) + return 0 +end diff --git a/test/trim/main_mkl.jl b/test/trim/main_mkl.jl new file mode 100644 index 000000000..c2a1128f2 --- /dev/null +++ b/test/trim/main_mkl.jl @@ -0,0 +1,8 @@ +using TrimTest + +function (@main)(argv::Vector{String})::Cint + x = parse(Float64, argv[1]) + sol = TrimTest.TestMKLLUFactorization.solve_linear(x) + println(Core.stdout, sum(sol.u)) + return 0 +end diff --git a/test/trim/main_rf.jl b/test/trim/main_rf.jl new file mode 100644 index 000000000..e16e7e67c --- /dev/null +++ b/test/trim/main_rf.jl @@ -0,0 +1,8 @@ +using TrimTest + +function (@main)(argv::Vector{String})::Cint + x = parse(Float64, argv[1]) + sol = TrimTest.TestRFLUFactorization.solve_linear(x) + println(Core.stdout, sum(sol.u)) + return 0 +end diff --git a/test/trim/runtests.jl b/test/trim/runtests.jl new file mode 100644 index 000000000..d26228281 --- /dev/null +++ b/test/trim/runtests.jl @@ -0,0 +1,87 @@ +using SafeTestsets + +@safetestset "LUFactorization implementation" begin + using LinearAlgebra + include("linear_lu.jl") + sol = TestLUFactorization.solve_linear(1.0) + @test sol.u ≈ [0.09090909090909091, 0.6363636363636364] +end + +@safetestset "MKLLUFactorization implementation" begin + using LinearAlgebra + using LinearSolve + # Only test if MKL is available + if LinearSolve.usemkl + include("linear_mkl.jl") + sol = TestMKLLUFactorization.solve_linear(1.0) + @test sol.u ≈ [0.09090909090909091, 0.6363636363636364] + else + @test_skip "MKL not available" + end +end + +@safetestset "RFLUFactorization implementation" begin + using LinearAlgebra + include("linear_rf.jl") + sol = TestRFLUFactorization.solve_linear(1.0) + @test sol.u ≈ [0.09090909090909091, 0.6363636363636364] +end + +@safetestset "Run trim" begin + # https://discourse.julialang.org/t/capture-stdout-and-stderr-in-case-a-command-fails/101772/3?u=romeov + """ + Run a Cmd object, returning the stdout & stderr contents plus the exit code + """ + function _execute(cmd::Cmd) + out = Pipe() + err = Pipe() + process = run(pipeline(ignorestatus(cmd); stdout = out, stderr = err)) + close(out.in) + close(err.in) + out = ( + stdout = String(read(out)), stderr = String(read(err)), + exitcode = process.exitcode + ) + return out + end + + JULIAC = normpath( + joinpath( + Sys.BINDIR, Base.DATAROOTDIR, "julia", "juliac", + "juliac.jl" + ) + ) + @test isfile(JULIAC) + + using LinearSolve + # Build list of tests to run, conditionally including MKL + test_files = [ + ("main_lu.jl", true), + ("main_rf.jl", true) + ] + if LinearSolve.usemkl + push!(test_files, ("main_mkl.jl", true)) + end + + for (mainfile, expectedtopass) in test_files + binpath = tempname() + cmd = `$(Base.julia_cmd()) --project=. --depwarn=error $(JULIAC) --experimental --trim=unsafe-warn --output-exe $(binpath) $(mainfile)` + + # since we are calling Julia from Julia, we first need to clean some + # environment variables + clean_env = copy(ENV) + delete!(clean_env, "JULIA_PROJECT") + delete!(clean_env, "JULIA_LOAD_PATH") + # We could just check for success, but then failures are hard to debug. + # Instead we use `_execute` to also capture `stdout` and `stderr`. + # @test success(setenv(cmd, clean_env)) + trimcall = _execute(setenv(cmd, clean_env; dir = @__DIR__)) + if trimcall.exitcode != 0 && expectedtopass + @show trimcall.stdout + @show trimcall.stderr + end + @test trimcall.exitcode == 0 broken = !expectedtopass + @test isfile(binpath) broken = !expectedtopass + @test success(`$(binpath) 1.0`) broken = !expectedtopass + end +end diff --git a/test/trim/src/TrimTest.jl b/test/trim/src/TrimTest.jl new file mode 100644 index 000000000..ad9e43be6 --- /dev/null +++ b/test/trim/src/TrimTest.jl @@ -0,0 +1,7 @@ +module TrimTest + +include("../linear_lu.jl") +include("../linear_mkl.jl") +include("../linear_rf.jl") + +end