From 7bc441152d523b8c74e4e88abfb341481ba2d264 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Thu, 8 Feb 2024 17:31:09 -0500 Subject: [PATCH 1/3] Parallel Testing --- .buildkite/pipeline.yml | 6 +- .github/workflows/CI.yml | 10 +- Project.toml | 4 +- test/core/23_test_problems.jl | 52 +++--- test/core/forward_ad.jl | 7 +- test/core/nlls.jl | 20 ++- test/core/rootfind.jl | 317 ++++++++++------------------------ test/gpu/Project.toml | 6 +- test/gpu/core.jl | 6 +- test/misc/banded_matrices.jl | 6 +- test/misc/bruss.jl | 58 ++++--- test/misc/matrix_resizing.jl | 14 +- test/misc/polyalgs.jl | 34 ++-- test/misc/qa.jl | 4 +- test/runtests.jl | 44 ++--- test/wrappers/fixedpoint.jl | 8 +- test/wrappers/nlls.jl | 34 ++-- test/wrappers/rootfind.jl | 15 +- 18 files changed, 253 insertions(+), 392 deletions(-) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 2281e4b90..52ebdda7a 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -4,15 +4,15 @@ steps: - JuliaCI/julia#v1: version: "1" - JuliaCI/julia-test#v1: - coverage: false # 1000x slowdown + coverage: true agents: queue: "juliagpu" cuda: "*" - timeout_in_minutes: 30 + timeout_in_minutes: 60 # Don't run Buildkite if the commit message includes the text [skip tests] if: build.message !~ /\[skip tests\]/ env: GROUP: GPU JULIA_PKG_SERVER: "" # it often struggles with our large artifacts - # SECRET_CODECOV_TOKEN: "..." \ No newline at end of file + SECRET_CODECOV_TOKEN: "HC7K/ymhi62KUQ5OLU4DOl+11gaQt4JhXX/2nfTGlTsBB8mEMxQ8R+sHIp/2HjEup5eSXAN2IWQDQ7RDBuQvVp0T1UVtr2e4YNZFztKnsJXrFO15hXxYShJodI//X/8DzhlQd/lyTDOAOJu3eznsc3sC2CUgJzXZxLUtQN9YaZ1i3a+NoN1mO5UpkkHVhXigwF5gjy+0tei8fCdcP+SIhG0EanS5yd9q/SurtCpMHsHyUG97+ZVPglSKgdaqr31+PdmiPJ+ynp4+Hnc/esosxUSHSIL+ryRTO+28RNwPTiNf99J51RJLQmz1knWTR1ky6tiYIZ5218O6wvNil0SqNw==;U2FsdGVkX18nBY3t4LZYlEIz3EVKjpqCd994JNeJGt006up+sAjXEssI0tgCVXnfXsenVsP3NCCEoOS1GXc44g==" \ No newline at end of file diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8c6fc00d6..5fb920004 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -18,13 +18,9 @@ jobs: fail-fast: false matrix: group: - - RootFinding - - NLLSSolvers - - 23TestProblems - - Wrappers - - Miscellaneous + - Core version: - - '1.10' + - '1' os: - ubuntu-latest - macos-latest @@ -48,7 +44,7 @@ jobs: - uses: julia-actions/julia-runtest@v1 env: GROUP: ${{ matrix.group }} - JULIA_NUM_THREADS: 11 + JULIA_NUM_THREADS: 8 - uses: julia-actions/julia-processcoverage@v1 with: directories: src,ext diff --git a/Project.toml b/Project.toml index bb435aa35..fd602834a 100644 --- a/Project.toml +++ b/Project.toml @@ -101,6 +101,7 @@ Symbolics = "5.13" Test = "1.10" TimerOutputs = "0.5.23" Zygote = "0.6.67" +XUnit = "1.1" julia = "1.10" [extras] @@ -131,7 +132,8 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +XUnit = "3e3c03f2-1a94-11e9-2981-050a4ca824ab" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [targets] -test = ["Aqua", "Enzyme", "BenchmarkTools", "SafeTestsets", "Pkg", "Test", "ForwardDiff", "StaticArrays", "Symbolics", "LinearSolve", "Random", "LinearAlgebra", "Zygote", "SparseDiffTools", "NonlinearProblemLibrary", "LeastSquaresOptim", "FastLevenbergMarquardt", "NaNMath", "BandedMatrices", "DiffEqBase", "StableRNGs", "MINPACK", "NLsolve", "OrdinaryDiffEq", "SpeedMapping", "FixedPointAcceleration", "SIAMFANLEquations", "Sundials"] +test = ["Aqua", "Enzyme", "BenchmarkTools", "SafeTestsets", "Pkg", "Test", "ForwardDiff", "StaticArrays", "Symbolics", "LinearSolve", "Random", "LinearAlgebra", "Zygote", "SparseDiffTools", "NonlinearProblemLibrary", "LeastSquaresOptim", "FastLevenbergMarquardt", "NaNMath", "BandedMatrices", "DiffEqBase", "StableRNGs", "MINPACK", "NLsolve", "OrdinaryDiffEq", "SpeedMapping", "FixedPointAcceleration", "SIAMFANLEquations", "Sundials", "XUnit"] diff --git a/test/core/23_test_problems.jl b/test/core/23_test_problems.jl index 8f1f07322..3146d49f5 100644 --- a/test/core/23_test_problems.jl +++ b/test/core/23_test_problems.jl @@ -1,4 +1,4 @@ -using NonlinearSolve, LinearAlgebra, LinearSolve, NonlinearProblemLibrary, Test +using NonlinearSolve, LinearAlgebra, LinearSolve, NonlinearProblemLibrary, XUnit problems = NonlinearProblemLibrary.problems dicts = NonlinearProblemLibrary.dicts @@ -36,7 +36,7 @@ function test_on_library(problems, dicts, alg_ops, broken_tests, ϵ = 1e-4; end end -@testset "NewtonRaphson 23 Test Problems" begin +@testcase "NewtonRaphson 23 Test Problems" begin alg_ops = (NewtonRaphson(),) broken_tests = Dict(alg => Int[] for alg in alg_ops) @@ -45,26 +45,26 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -# @testset "TrustRegion 23 Test Problems" begin -# alg_ops = (TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Simple), -# TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Fan), -# TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Hei), -# TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Yuan), -# TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Bastin), -# TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.NLsolve)) - -# broken_tests = Dict(alg => Int[] for alg in alg_ops) -# broken_tests[alg_ops[1]] = [11, 21] -# broken_tests[alg_ops[2]] = [11, 21] -# broken_tests[alg_ops[3]] = [11, 21] -# broken_tests[alg_ops[4]] = [11, 21] -# broken_tests[alg_ops[5]] = [21] -# broken_tests[alg_ops[6]] = [21] - -# test_on_library(problems, dicts, alg_ops, broken_tests) -# end - -@testset "LevenbergMarquardt 23 Test Problems" begin +@testcase "TrustRegion 23 Test Problems" begin + alg_ops = (TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Simple), + TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Fan), + TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Hei), + TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Yuan), + TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Bastin), + TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.NLsolve)) + + broken_tests = Dict(alg => Int[] for alg in alg_ops) + broken_tests[alg_ops[1]] = [11, 21] + broken_tests[alg_ops[2]] = [11, 21] + broken_tests[alg_ops[3]] = [11, 21] + broken_tests[alg_ops[4]] = [8, 11, 21] + broken_tests[alg_ops[5]] = [21] + broken_tests[alg_ops[6]] = [11, 21] + + test_on_library(problems, dicts, alg_ops, broken_tests) +end + +@testcase "LevenbergMarquardt 23 Test Problems" begin alg_ops = (LevenbergMarquardt(), LevenbergMarquardt(; α_geodesic = 0.1), LevenbergMarquardt(; linsolve = CholeskyFactorization())) @@ -77,7 +77,7 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testset "DFSane 23 Test Problems" begin +@testcase "DFSane 23 Test Problems" begin alg_ops = (DFSane(),) broken_tests = Dict(alg => Int[] for alg in alg_ops) @@ -86,7 +86,7 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testset "Broyden 23 Test Problems" begin +@testcase "Broyden 23 Test Problems" begin alg_ops = (Broyden(), Broyden(; init_jacobian = Val(:true_jacobian)), Broyden(; update_rule = Val(:bad_broyden)), @@ -101,7 +101,7 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testset "Klement 23 Test Problems" begin +@testcase "Klement 23 Test Problems" begin alg_ops = (Klement(), Klement(; init_jacobian = Val(:true_jacobian_diagonal))) broken_tests = Dict(alg => Int[] for alg in alg_ops) @@ -111,7 +111,7 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testset "PseudoTransient 23 Test Problems" begin +@testcase "PseudoTransient 23 Test Problems" begin # PT relies on the root being a stable equilibrium for convergence, so it won't work on # most problems alg_ops = (PseudoTransient(),) diff --git a/test/core/forward_ad.jl b/test/core/forward_ad.jl index 41fe5015e..b0b4fee03 100644 --- a/test/core/forward_ad.jl +++ b/test/core/forward_ad.jl @@ -1,5 +1,5 @@ using ForwardDiff, - NonlinearSolve, MINPACK, NLsolve, StaticArrays, Sundials, Test, LinearAlgebra + NonlinearSolve, MINPACK, NLsolve, StaticArrays, Sundials, XUnit, LinearAlgebra test_f!(du, u, p) = (@. du = u^2 - p) test_f(u, p) = (@. u^2 - p) @@ -58,9 +58,10 @@ __compatible(::NLsolveJL, ::Val{:oop_cache}) = false __compatible(::KINSOL, ::Val{:iip_cache}) = false __compatible(::KINSOL, ::Val{:oop_cache}) = false -@testset "ForwardDiff.jl Integration: $(alg)" for alg in (NewtonRaphson(), TrustRegion(), +@testcase "ForwardDiff.jl Integration: $(alg)" for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), PseudoTransient(; alpha_initial = 10.0), Broyden(), Klement(), - DFSane(), nothing, NLsolveJL(), CMINPACK(), KINSOL()) + DFSane(), nothing, NLsolveJL(), CMINPACK(), + KINSOL(; globalization_strategy = :LineSearch)) us = (2.0, @SVector[1.0, 1.0], [1.0, 1.0], ones(2, 2), @SArray ones(2, 2)) @testset "Scalar AD" begin diff --git a/test/core/nlls.jl b/test/core/nlls.jl index 07c0dbff2..daddc9f3f 100644 --- a/test/core/nlls.jl +++ b/test/core/nlls.jl @@ -1,5 +1,5 @@ using NonlinearSolve, - LinearSolve, LinearAlgebra, Test, StableRNGs, Random, ForwardDiff, Zygote + LinearSolve, LinearAlgebra, XUnit, StableRNGs, Random, ForwardDiff, Zygote true_function(x, θ) = @. θ[1] * exp(θ[2] * x) * cos(θ[3] * x + θ[4]) true_function(y, x, θ) = (@. y = θ[1] * exp(θ[2] * x) * cos(θ[3] * x + θ[4])) @@ -52,10 +52,12 @@ for radius_update_scheme in [RadiusUpdateSchemes.Simple, RadiusUpdateSchemes.Noc push!(solvers, TrustRegion(; radius_update_scheme)) end -for prob in nlls_problems, solver in solvers - @time sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) - @test SciMLBase.successful_retcode(sol) - @test maximum(abs, sol.resid) < 1e-6 +@testcase "General NLLS Solvers" begin + for prob in nlls_problems, solver in solvers + sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) + @test SciMLBase.successful_retcode(sol) + @test maximum(abs, sol.resid) < 1e-6 + end end # This is just for testing that we can use vjp provided by the user @@ -79,7 +81,9 @@ probs = [ resid_prototype = zero(y_target), vjp = vjp), θ_init, x), ] -for prob in probs, solver in solvers - sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) - @test maximum(abs, sol.resid) < 1e-6 +@testcase "Custom VJP" begin + for prob in probs, solver in solvers + sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) + @test maximum(abs, sol.resid) < 1e-6 + end end diff --git a/test/core/rootfind.jl b/test/core/rootfind.jl index f64dcda88..d6e36ade9 100644 --- a/test/core/rootfind.jl +++ b/test/core/rootfind.jl @@ -1,5 +1,5 @@ using BenchmarkTools, LinearSolve, NonlinearSolve, StaticArrays, Random, LinearAlgebra, - Test, ForwardDiff, Zygote, Enzyme, SparseDiffTools, DiffEqBase + XUnit, ForwardDiff, Zygote, Enzyme, SparseDiffTools, DiffEqBase function __autosparseenzyme() @static if Sys.iswindows() @@ -35,20 +35,31 @@ const TERMINATION_CONDITIONS = [ AbsSafeTerminationMode(), RelSafeBestTerminationMode(), AbsSafeBestTerminationMode(), ] -# --- NewtonRaphson tests --- +function benchmark_nlsolve_oop(f, u0, p = 2.0; solver, kwargs...) + prob = NonlinearProblem{false}(f, u0, p) + return solve(prob, solver; abstol = 1e-9, kwargs...) +end -@testset "NewtonRaphson" begin - function benchmark_nlsolve_oop(f, u0, p = 2.0; linesearch = nothing) - prob = NonlinearProblem{false}(f, u0, p) - return solve(prob, NewtonRaphson(; linesearch), abstol = 1e-9) - end +function benchmark_nlsolve_iip(f, u0, p = 2.0; solver, kwargs...) + prob = NonlinearProblem{true}(f, u0, p) + return solve(prob, solver; abstol = 1e-9, kwargs...) +end - function benchmark_nlsolve_iip(f, u0, p = 2.0; linsolve, precs, - linesearch = nothing) - prob = NonlinearProblem{true}(f, u0, p) - return solve(prob, NewtonRaphson(; linsolve, precs, linesearch), abstol = 1e-9) +function nlprob_iterator_interface(f, p_range, ::Val{iip}, solver) where {iip} + probN = NonlinearProblem{iip}(f, iip ? [0.5] : 0.5, p_range[begin]) + cache = init(probN, solver; maxiters = 100, abstol = 1e-10) + sols = zeros(length(p_range)) + for (i, p) in enumerate(p_range) + reinit!(cache, iip ? [cache.u[1]] : cache.u; p = p) + sol = solve!(cache) + sols[i] = iip ? sol.u[1] : sol.u end + return sols +end + +# --- NewtonRaphson tests --- +@testcase "NewtonRaphson" begin @testset "LineSearch: $(_nameof(lsmethod)) LineSearch AD: $(_nameof(ad))" for lsmethod in (Static(), StrongWolfe(), BackTracking(), HagerZhang(), MoreThuente()), ad in (AutoFiniteDiff(), AutoZygote()) @@ -57,7 +68,8 @@ const TERMINATION_CONDITIONS = [ u0s = ([1.0, 1.0], @SVector[1.0, 1.0], 1.0) @testset "[OOP] u0: $(typeof(u0))" for u0 in u0s - sol = benchmark_nlsolve_oop(quadratic_f, u0; linesearch) + solver = NewtonRaphson(; linesearch) + sol = benchmark_nlsolve_oop(quadratic_f, u0; solver) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -77,8 +89,8 @@ const TERMINATION_CONDITIONS = [ if prec === :Random prec = (args...) -> (Diagonal(randn!(similar(u0))), nothing) end - sol = benchmark_nlsolve_iip(quadratic_f!, u0; linsolve, precs = prec(u0), - linesearch) + solver = NewtonRaphson(; linsolve, precs = prec(u0), linesearch) + sol = benchmark_nlsolve_iip(quadratic_f!, u0; solver) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -89,20 +101,9 @@ const TERMINATION_CONDITIONS = [ end # Iterator interface - function nlprob_iterator_interface(f, p_range, ::Val{iip}) where {iip} - probN = NonlinearProblem{iip}(f, iip ? [0.5] : 0.5, p_range[begin]) - cache = init(probN, NewtonRaphson(); maxiters = 100, abstol = 1e-10) - sols = zeros(length(p_range)) - for (i, p) in enumerate(p_range) - reinit!(cache, iip ? [cache.u[1]] : cache.u; p = p) - sol = solve!(cache) - sols[i] = iip ? sol.u[1] : sol.u - end - return sols - end p = range(0.01, 2, length = 200) - @test nlprob_iterator_interface(quadratic_f, p, Val(false)) ≈ sqrt.(p) - @test nlprob_iterator_interface(quadratic_f!, p, Val(true)) ≈ sqrt.(p) + @test nlprob_iterator_interface(quadratic_f, p, Val(false), NewtonRaphson()) ≈ sqrt.(p) + @test nlprob_iterator_interface(quadratic_f!, p, Val(true), NewtonRaphson()) ≈ sqrt.(p) @testset "ADType: $(autodiff) u0: $(_nameof(u0))" for autodiff in (AutoSparseForwardDiff(), AutoSparseFiniteDiff(), AutoZygote(), AutoSparseZygote(), __autosparseenzyme()), u0 in (1.0, [1.0, 1.0]) @@ -120,21 +121,7 @@ end # --- TrustRegion tests --- -@testset "TrustRegion" begin - function benchmark_nlsolve_oop(f, u0, p = 2.0; radius_update_scheme, linsolve = nothing, - vjp_autodiff = nothing, kwargs...) - prob = NonlinearProblem{false}(f, u0, p) - return solve(prob, TrustRegion(; radius_update_scheme, linsolve, vjp_autodiff); - abstol = 1e-9, kwargs...) - end - - function benchmark_nlsolve_iip(f, u0, p = 2.0; radius_update_scheme, linsolve = nothing, - vjp_autodiff = nothing, kwargs...) - prob = NonlinearProblem{true}(f, u0, p) - return solve(prob, TrustRegion(; radius_update_scheme, linsolve, vjp_autodiff); - abstol = 1e-9, kwargs...) - end - +@testcase "TrustRegion" begin radius_update_schemes = [RadiusUpdateSchemes.Simple, RadiusUpdateSchemes.NocedalWright, RadiusUpdateSchemes.NLsolve, RadiusUpdateSchemes.Hei, RadiusUpdateSchemes.Yuan, RadiusUpdateSchemes.Fan, RadiusUpdateSchemes.Bastin] @@ -146,7 +133,8 @@ end abstol = ifelse(linsolve isa KrylovJL, 1e-6, 1e-9) - sol = benchmark_nlsolve_oop(quadratic_f, u0; radius_update_scheme, linsolve, abstol) + solver = TrustRegion(; radius_update_scheme, linsolve) + sol = benchmark_nlsolve_oop(quadratic_f, u0; solver, abstol) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< abstol) @@ -158,8 +146,8 @@ end @testset "[IIP] u0: $(typeof(u0)) radius_update_scheme: $(radius_update_scheme) linear_solver: $(linsolve)" for u0 in ([ 1.0, 1.0],), radius_update_scheme in radius_update_schemes, linsolve in linear_solvers abstol = ifelse(linsolve isa KrylovJL, 1e-6, 1e-9) - sol = benchmark_nlsolve_iip(quadratic_f!, u0; radius_update_scheme, linsolve, - abstol) + solver = TrustRegion(; radius_update_scheme, linsolve) + sol = benchmark_nlsolve_iip(quadratic_f!, u0; solver, abstol) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< abstol) @@ -169,20 +157,9 @@ end end # Iterator interface - function nlprob_iterator_interface(f, p_range, ::Val{iip}) where {iip} - probN = NonlinearProblem{iip}(f, iip ? [0.5] : 0.5, p_range[begin]) - cache = init(probN, TrustRegion(); maxiters = 100, abstol = 1e-10) - sols = zeros(length(p_range)) - for (i, p) in enumerate(p_range) - reinit!(cache, iip ? [cache.u[1]] : cache.u; p = p) - sol = solve!(cache) - sols[i] = iip ? sol.u[1] : sol.u - end - return sols - end p = range(0.01, 2, length = 200) - @test nlprob_iterator_interface(quadratic_f, p, Val(false)) ≈ sqrt.(p) - @test nlprob_iterator_interface(quadratic_f!, p, Val(true)) ≈ sqrt.(p) + @test nlprob_iterator_interface(quadratic_f, p, Val(false), TrustRegion()) ≈ sqrt.(p) + @test nlprob_iterator_interface(quadratic_f!, p, Val(true), TrustRegion()) ≈ sqrt.(p) @testset "ADType: $(autodiff) u0: $(_nameof(u0)) radius_update_scheme: $(radius_update_scheme)" for autodiff in (AutoSparseForwardDiff(), AutoSparseFiniteDiff(), AutoZygote(), AutoSparseZygote(), __autosparseenzyme()), u0 in (1.0, [1.0, 1.0]), @@ -198,7 +175,8 @@ end RadiusUpdateSchemes.Simple, RadiusUpdateSchemes.Fan, RadiusUpdateSchemes.Bastin] u0 = [-10.0, -1.0, 1.0, 2.0, 3.0, 4.0, 10.0] p = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] - sol = benchmark_nlsolve_oop(newton_fails, u0, p; radius_update_scheme) + solver = TrustRegion(; radius_update_scheme) + sol = benchmark_nlsolve_oop(newton_fails, u0, p; solver) @test SciMLBase.successful_retcode(sol) @test all(abs.(newton_fails(sol.u, p)) .< 1e-9) end @@ -238,10 +216,9 @@ end @testset "radius_update_scheme: $(radius_update_scheme) maxiters: $(maxiters)" for radius_update_scheme in radius_update_schemes, maxiters in maxiterations - sol_iip = benchmark_nlsolve_iip(quadratic_f!, u0; radius_update_scheme, - maxiters) - sol_oop = benchmark_nlsolve_oop(quadratic_f, u0; radius_update_scheme, - maxiters) + solver = TrustRegion(; radius_update_scheme) + sol_iip = benchmark_nlsolve_iip(quadratic_f!, u0; solver, maxiters) + sol_oop = benchmark_nlsolve_oop(quadratic_f, u0; solver, maxiters) @test sol_iip.u ≈ sol_oop.u end end @@ -256,20 +233,10 @@ end # --- LevenbergMarquardt tests --- -@testset "LevenbergMarquardt" begin - function benchmark_nlsolve_oop(f, u0, p = 2.0) - prob = NonlinearProblem{false}(f, u0, p) - return solve(prob, LevenbergMarquardt(), abstol = 1e-9) - end - - function benchmark_nlsolve_iip(f, u0, p = 2.0) - prob = NonlinearProblem{true}(f, u0, p) - return solve(prob, LevenbergMarquardt(), abstol = 1e-9) - end - +@testcase "LevenbergMarquardt" begin u0s = ([1.0, 1.0], @SVector[1.0, 1.0], 1.0) @testset "[OOP] u0: $(typeof(u0))" for u0 in u0s - sol = benchmark_nlsolve_oop(quadratic_f, u0) + sol = benchmark_nlsolve_oop(quadratic_f, u0; solver = LevenbergMarquardt()) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -279,7 +246,7 @@ end end @testset "[IIP] u0: $(typeof(u0))" for u0 in ([1.0, 1.0],) - sol = benchmark_nlsolve_iip(quadratic_f!, u0) + sol = benchmark_nlsolve_iip(quadratic_f!, u0; solver = LevenbergMarquardt()) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -299,11 +266,18 @@ end @testset "Newton Raphson Fails" begin u0 = [-10.0, -1.0, 1.0, 2.0, 3.0, 4.0, 10.0] p = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] - sol = benchmark_nlsolve_oop(newton_fails, u0, p) + sol = benchmark_nlsolve_oop(newton_fails, u0, p; solver = LevenbergMarquardt()) @test SciMLBase.successful_retcode(sol) @test all(abs.(newton_fails(sol.u, p)) .< 1e-9) end + # Iterator interface + p = range(0.01, 2, length = 200) + @test abs.(nlprob_iterator_interface(quadratic_f, p, Val(false), + LevenbergMarquardt())) ≈ sqrt.(p) + @test abs.(nlprob_iterator_interface(quadratic_f!, p, Val(true), + LevenbergMarquardt())) ≈ sqrt.(p) + # Test kwargs in `LevenbergMarquardt` @testset "Keyword Arguments" begin damping_initial = [0.5, 2.0, 5.0] @@ -341,21 +315,11 @@ end # --- DFSane tests --- -@testset "DFSane" begin - function benchmark_nlsolve_oop(f, u0, p = 2.0) - prob = NonlinearProblem{false}(f, u0, p) - return solve(prob, DFSane(), abstol = 1e-9) - end - - function benchmark_nlsolve_iip(f, u0, p = 2.0) - prob = NonlinearProblem{true}(f, u0, p) - return solve(prob, DFSane(), abstol = 1e-9) - end - +@testcase "DFSane" begin u0s = ([1.0, 1.0], @SVector[1.0, 1.0], 1.0) @testset "[OOP] u0: $(typeof(u0))" for u0 in u0s - sol = benchmark_nlsolve_oop(quadratic_f, u0) + sol = benchmark_nlsolve_oop(quadratic_f, u0; solver = DFSane()) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -365,7 +329,7 @@ end end @testset "[IIP] u0: $(typeof(u0))" for u0 in ([1.0, 1.0],) - sol = benchmark_nlsolve_iip(quadratic_f!, u0) + sol = benchmark_nlsolve_iip(quadratic_f!, u0; solver = DFSane()) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -374,26 +338,15 @@ end end # Iterator interface - function nlprob_iterator_interface(f, p_range, ::Val{iip}) where {iip} - probN = NonlinearProblem{iip}(f, iip ? [0.5] : 0.5, p_range[begin]) - cache = init(probN, DFSane(); maxiters = 100, abstol = 1e-10) - sols = zeros(length(p_range)) - for (i, p) in enumerate(p_range) - reinit!(cache, iip ? [cache.u[1]] : cache.u; p = p) - sol = solve!(cache) - sols[i] = iip ? sol.u[1] : sol.u - end - return sols - end p = range(0.01, 2, length = 200) - @test abs.(nlprob_iterator_interface(quadratic_f, p, Val(false))) ≈ sqrt.(p) - @test abs.(nlprob_iterator_interface(quadratic_f!, p, Val(true))) ≈ sqrt.(p) + @test abs.(nlprob_iterator_interface(quadratic_f, p, Val(false), DFSane())) ≈ sqrt.(p) + @test abs.(nlprob_iterator_interface(quadratic_f!, p, Val(true), DFSane())) ≈ sqrt.(p) # Test that `DFSane` passes a test that `NewtonRaphson` fails on. @testset "Newton Raphson Fails" begin u0 = [-10.0, -1.0, 1.0, 2.0, 3.0, 4.0, 10.0] p = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] - sol = benchmark_nlsolve_oop(newton_fails, u0, p) + sol = benchmark_nlsolve_oop(newton_fails, u0, p; solver = DFSane()) @test SciMLBase.successful_retcode(sol) @test all(abs.(newton_fails(sol.u, p)) .< 1e-9) end @@ -438,27 +391,16 @@ end # --- PseudoTransient tests --- -@testset "PseudoTransient" begin +@testcase "PseudoTransient" begin # These are tests for NewtonRaphson so we should set alpha_initial to be high so that we # converge quickly - - function benchmark_nlsolve_oop(f, u0, p = 2.0; alpha_initial = 10.0) - prob = NonlinearProblem{false}(f, u0, p) - return solve(prob, PseudoTransient(; alpha_initial), abstol = 1e-9) - end - - function benchmark_nlsolve_iip(f, u0, p = 2.0; linsolve, precs, - alpha_initial = 10.0) - prob = NonlinearProblem{true}(f, u0, p) - return solve(prob, PseudoTransient(; linsolve, precs, alpha_initial), abstol = 1e-9) - end - @testset "PT: alpha_initial = 10.0 PT AD: $(ad)" for ad in (AutoFiniteDiff(), AutoZygote()) u0s = ([1.0, 1.0], @SVector[1.0, 1.0], 1.0) @testset "[OOP] u0: $(typeof(u0))" for u0 in u0s - sol = benchmark_nlsolve_oop(quadratic_f, u0) + solver = PseudoTransient(; alpha_initial = 10.0) + sol = benchmark_nlsolve_oop(quadratic_f, u0; solver) # Failing by a margin for some # @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -476,32 +418,22 @@ end if prec === :Random prec = (args...) -> (Diagonal(randn!(similar(u0))), nothing) end - sol = benchmark_nlsolve_iip(quadratic_f!, u0; linsolve, precs = prec) + solver = PseudoTransient(; alpha_initial = 10.0, linsolve, precs = prec) + sol = benchmark_nlsolve_iip(quadratic_f!, u0; solver) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) - cache = init(NonlinearProblem{true}(quadratic_f!, u0, 2.0), - PseudoTransient(; alpha_initial = 10.0, linsolve, precs = prec), + cache = init(NonlinearProblem{true}(quadratic_f!, u0, 2.0), solver; abstol = 1e-9) @test (@ballocated solve!($cache)) ≤ 64 end end - function nlprob_iterator_interface(f, p_range, ::Val{iip}) where {iip} - probN = NonlinearProblem{iip}(f, iip ? [0.5] : 0.5, p_range[begin]) - cache = init(probN, PseudoTransient(alpha_initial = 10.0); maxiters = 100, - abstol = 1e-10) - sols = zeros(length(p_range)) - for (i, p) in enumerate(p_range) - reinit!(cache, iip ? [cache.u[1]] : cache.u; p = p, alpha = 10.0) - sol = solve!(cache) - sols[i] = iip ? sol.u[1] : sol.u - end - return sols - end p = range(0.01, 2, length = 200) - @test nlprob_iterator_interface(quadratic_f, p, Val(false)) ≈ sqrt.(p) - @test nlprob_iterator_interface(quadratic_f!, p, Val(true)) ≈ sqrt.(p) + @test nlprob_iterator_interface(quadratic_f, p, Val(false), + PseudoTransient(; alpha_initial = 10.0)) ≈ sqrt.(p) + @test nlprob_iterator_interface(quadratic_f!, p, Val(true), + PseudoTransient(; alpha_initial = 10.0)) ≈ sqrt.(p) @testset "ADType: $(autodiff) u0: $(_nameof(u0))" for autodiff in (AutoSparseForwardDiff(), AutoSparseFiniteDiff(), AutoZygote(), AutoSparseZygote(), __autosparseenzyme()), u0 in (1.0, [1.0, 1.0]) @@ -521,21 +453,7 @@ end # --- Broyden tests --- -@testset "Broyden" begin - function benchmark_nlsolve_oop(f, u0, p = 2.0; linesearch = nothing, - init_jacobian = Val(:identity), update_rule = Val(:good_broyden)) - prob = NonlinearProblem{false}(f, u0, p) - return solve(prob, Broyden(; linesearch, init_jacobian, update_rule); - abstol = 1e-9) - end - - function benchmark_nlsolve_iip(f, u0, p = 2.0; linesearch = nothing, - init_jacobian = Val(:identity), update_rule = Val(:good_broyden)) - prob = NonlinearProblem{true}(f, u0, p) - return solve(prob, Broyden(; linesearch, init_jacobian, update_rule); - abstol = 1e-9) - end - +@testcase "Broyden" begin @testset "LineSearch: $(_nameof(lsmethod)) LineSearch AD: $(_nameof(ad)) Init Jacobian: $(init_jacobian) Update Rule: $(update_rule)" for lsmethod in (Static(), StrongWolfe(), BackTracking(), HagerZhang(), MoreThuente(), LiFukushimaLineSearch()), @@ -547,8 +465,8 @@ end u0s = ([1.0, 1.0], @SVector[1.0, 1.0], 1.0) @testset "[OOP] u0: $(typeof(u0))" for u0 in u0s - sol = benchmark_nlsolve_oop(quadratic_f, u0; linesearch, update_rule, - init_jacobian) + solver = Broyden(; linesearch, init_jacobian, update_rule) + sol = benchmark_nlsolve_oop(quadratic_f, u0; solver) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -559,8 +477,8 @@ end @testset "[IIP] u0: $(typeof(u0))" for u0 in ([1.0, 1.0],) ad isa AutoZygote && continue - sol = benchmark_nlsolve_iip(quadratic_f!, u0; linesearch, update_rule, - init_jacobian) + solver = Broyden(; linesearch, init_jacobian, update_rule) + sol = benchmark_nlsolve_iip(quadratic_f!, u0; solver) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -571,20 +489,9 @@ end end # Iterator interface - function nlprob_iterator_interface(f, p_range, ::Val{iip}) where {iip} - probN = NonlinearProblem{iip}(f, iip ? [0.5] : 0.5, p_range[begin]) - cache = init(probN, Broyden(); maxiters = 100, abstol = 1e-10) - sols = zeros(length(p_range)) - for (i, p) in enumerate(p_range) - reinit!(cache, iip ? [cache.u[1]] : cache.u; p = p) - sol = solve!(cache) - sols[i] = iip ? sol.u[1] : sol.u - end - return sols - end p = range(0.01, 2, length = 200) - @test nlprob_iterator_interface(quadratic_f, p, Val(false)) ≈ sqrt.(p) - @test nlprob_iterator_interface(quadratic_f!, p, Val(true)) ≈ sqrt.(p) + @test nlprob_iterator_interface(quadratic_f, p, Val(false), Broyden()) ≈ sqrt.(p) + @test nlprob_iterator_interface(quadratic_f!, p, Val(true), Broyden()) ≈ sqrt.(p) @testset "Termination condition: $(termination_condition) u0: $(_nameof(u0))" for termination_condition in TERMINATION_CONDITIONS, u0 in (1.0, [1.0, 1.0]) @@ -596,19 +503,7 @@ end # --- Klement tests --- -@testset "Klement" begin - function benchmark_nlsolve_oop(f, u0, p = 2.0; linesearch = nothing, - init_jacobian = Val(:identity)) - prob = NonlinearProblem{false}(f, u0, p) - return solve(prob, Klement(; linesearch, init_jacobian), abstol = 1e-9) - end - - function benchmark_nlsolve_iip(f, u0, p = 2.0; linesearch = nothing, - init_jacobian = Val(:identity)) - prob = NonlinearProblem{true}(f, u0, p) - return solve(prob, Klement(; linesearch, init_jacobian), abstol = 1e-9) - end - +@testcase "Klement" begin @testset "LineSearch: $(_nameof(lsmethod)) LineSearch AD: $(_nameof(ad)) Init Jacobian: $(init_jacobian)" for lsmethod in (Static(), StrongWolfe(), BackTracking(), HagerZhang(), MoreThuente()), ad in (AutoFiniteDiff(), AutoZygote()), @@ -618,7 +513,8 @@ end u0s = ([1.0, 1.0], @SVector[1.0, 1.0], 1.0) @testset "[OOP] u0: $(typeof(u0))" for u0 in u0s - sol = benchmark_nlsolve_oop(quadratic_f, u0; linesearch, init_jacobian) + solver = Klement(; linesearch, init_jacobian) + sol = benchmark_nlsolve_oop(quadratic_f, u0; solver) # Some are failing by a margin # @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 3e-9) @@ -630,7 +526,8 @@ end @testset "[IIP] u0: $(typeof(u0))" for u0 in ([1.0, 1.0],) ad isa AutoZygote && continue - sol = benchmark_nlsolve_iip(quadratic_f!, u0; linesearch, init_jacobian) + solver = Klement(; linesearch, init_jacobian) + sol = benchmark_nlsolve_iip(quadratic_f!, u0; solver) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -641,20 +538,9 @@ end end # Iterator interface - function nlprob_iterator_interface(f, p_range, ::Val{iip}) where {iip} - probN = NonlinearProblem{iip}(f, iip ? [0.5] : 0.5, p_range[begin]) - cache = init(probN, Klement(); maxiters = 100, abstol = 1e-10) - sols = zeros(length(p_range)) - for (i, p) in enumerate(p_range) - reinit!(cache, iip ? [cache.u[1]] : cache.u; p = p) - sol = solve!(cache) - sols[i] = iip ? sol.u[1] : sol.u - end - return sols - end p = range(0.01, 2, length = 200) - @test nlprob_iterator_interface(quadratic_f, p, Val(false)) ≈ sqrt.(p) - @test nlprob_iterator_interface(quadratic_f!, p, Val(true)) ≈ sqrt.(p) + @test nlprob_iterator_interface(quadratic_f, p, Val(false), Klement()) ≈ sqrt.(p) + @test nlprob_iterator_interface(quadratic_f!, p, Val(true), Klement()) ≈ sqrt.(p) @testset "Termination condition: $(termination_condition) u0: $(_nameof(u0))" for termination_condition in TERMINATION_CONDITIONS, u0 in (1.0, [1.0, 1.0]) @@ -666,21 +552,7 @@ end # --- LimitedMemoryBroyden tests --- -@testset "LimitedMemoryBroyden" begin - function benchmark_nlsolve_oop(f, u0, p = 2.0; linesearch = nothing, - termination_condition = AbsNormTerminationMode()) - prob = NonlinearProblem{false}(f, u0, p) - return solve(prob, LimitedMemoryBroyden(; linesearch); abstol = 1e-9, - termination_condition) - end - - function benchmark_nlsolve_iip(f, u0, p = 2.0; linesearch = nothing, - termination_condition = AbsNormTerminationMode()) - prob = NonlinearProblem{true}(f, u0, p) - return solve(prob, LimitedMemoryBroyden(; linesearch); abstol = 1e-9, - termination_condition) - end - +@testcase "LimitedMemoryBroyden" begin @testset "LineSearch: $(_nameof(lsmethod)) LineSearch AD: $(_nameof(ad))" for lsmethod in (Static(), StrongWolfe(), BackTracking(), HagerZhang(), MoreThuente(), LiFukushimaLineSearch()), @@ -690,7 +562,8 @@ end u0s = ([1.0, 1.0], @SVector[1.0, 1.0], 1.0) @testset "[OOP] u0: $(typeof(u0))" for u0 in u0s - sol = benchmark_nlsolve_oop(quadratic_f, u0; linesearch) + solver = LimitedMemoryBroyden(; linesearch) + sol = benchmark_nlsolve_oop(quadratic_f, u0; solver) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -701,7 +574,8 @@ end @testset "[IIP] u0: $(typeof(u0))" for u0 in ([1.0, 1.0],) ad isa AutoZygote && continue - sol = benchmark_nlsolve_iip(quadratic_f!, u0; linesearch) + solver = LimitedMemoryBroyden(; linesearch) + sol = benchmark_nlsolve_iip(quadratic_f!, u0; solver) @test SciMLBase.successful_retcode(sol) @test all(abs.(sol.u .* sol.u .- 2) .< 1e-9) @@ -712,20 +586,11 @@ end end # Iterator interface - function nlprob_iterator_interface(f, p_range, ::Val{iip}) where {iip} - probN = NonlinearProblem{iip}(f, iip ? [0.5] : 0.5, p_range[begin]) - cache = init(probN, LimitedMemoryBroyden(); maxiters = 100, abstol = 1e-10) - sols = zeros(length(p_range)) - for (i, p) in enumerate(p_range) - reinit!(cache, iip ? [cache.u[1]] : cache.u; p = p) - sol = solve!(cache) - sols[i] = iip ? sol.u[1] : sol.u - end - return sols - end p = range(0.01, 2, length = 200) - @test nlprob_iterator_interface(quadratic_f, p, Val(false))≈sqrt.(p) atol=1e-2 - @test nlprob_iterator_interface(quadratic_f!, p, Val(true))≈sqrt.(p) atol=1e-2 + @test nlprob_iterator_interface(quadratic_f, p, Val(false), + LimitedMemoryBroyden())≈sqrt.(p) atol=1e-2 + @test nlprob_iterator_interface(quadratic_f!, p, Val(true), + LimitedMemoryBroyden())≈sqrt.(p) atol=1e-2 @testset "Termination condition: $(termination_condition) u0: $(_nameof(u0))" for termination_condition in TERMINATION_CONDITIONS, u0 in (1.0, [1.0, 1.0]) @@ -737,7 +602,7 @@ end end # Miscellaneous Tests -@testset "Custom JVP" begin +@testcase "Custom JVP" begin function F(u::Vector{Float64}, p::Vector{Float64}) Δ = Tridiagonal(-ones(99), 2 * ones(100), -ones(99)) return u + 0.1 * u .* Δ * u - p diff --git a/test/gpu/Project.toml b/test/gpu/Project.toml index 2c366f675..6ec065323 100644 --- a/test/gpu/Project.toml +++ b/test/gpu/Project.toml @@ -3,8 +3,4 @@ CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" - -[compat] -CUDA = "5" -LinearSolve = "2" -NonlinearSolve = "3" +XUnit = "3e3c03f2-1a94-11e9-2981-050a4ca824ab" diff --git a/test/gpu/core.jl b/test/gpu/core.jl index eff394853..bd4c2e4f6 100644 --- a/test/gpu/core.jl +++ b/test/gpu/core.jl @@ -1,4 +1,4 @@ -using CUDA, NonlinearSolve, LinearSolve, StableRNGs, Test +using CUDA, NonlinearSolve, LinearSolve, StableRNGs, XUnit CUDA.allowscalar(false) @@ -18,7 +18,7 @@ SOLVERS = (NewtonRaphson(), LevenbergMarquardt(; linsolve = QRFactorization()), TrustRegion(; linsolve = KrylovJL_GMRES(), concrete_jac = true), # Needed if Zygote not loaded nothing) -@testset "[IIP] GPU Solvers" begin +@testcase "[IIP] GPU Solvers" begin for alg in SOLVERS @test_nowarn sol = solve(prob, alg; abstol = 1.0f-5, reltol = 1.0f-5) end @@ -28,7 +28,7 @@ linear_f(u, p) = A * u .+ b prob = NonlinearProblem{false}(linear_f, u0) -@testset "[OOP] GPU Solvers" begin +@testcase "[OOP] GPU Solvers" begin for alg in SOLVERS @test_nowarn sol = solve(prob, alg; abstol = 1.0f-5, reltol = 1.0f-5) end diff --git a/test/misc/banded_matrices.jl b/test/misc/banded_matrices.jl index e00a8fb01..ff5951089 100644 --- a/test/misc/banded_matrices.jl +++ b/test/misc/banded_matrices.jl @@ -1,7 +1,9 @@ # Miscellaneous Tests -using BandedMatrices, LinearAlgebra, NonlinearSolve, SparseArrays, Test +using BandedMatrices, LinearAlgebra, NonlinearSolve, SparseArrays, XUnit b = BandedMatrix(Ones(5, 5), (1, 1)) d = Diagonal(ones(5, 5)) -@test NonlinearSolve._vcat(b, d) == vcat(sparse(b), d) +@testcase "BandedMatrix vcat" begin + @test NonlinearSolve._vcat(b, d) == vcat(sparse(b), d) +end diff --git a/test/misc/bruss.jl b/test/misc/bruss.jl index 96f1a4241..25dd3b026 100644 --- a/test/misc/bruss.jl +++ b/test/misc/bruss.jl @@ -1,4 +1,4 @@ -using NonlinearSolve, LinearAlgebra, SparseArrays, Symbolics +using NonlinearSolve, LinearAlgebra, SparseArrays, Symbolics, XUnit const N = 32 const xyd_brusselator = range(0, stop = 1, length = N) @@ -38,37 +38,39 @@ function init_brusselator_2d(xyd) return u end -u0 = init_brusselator_2d(xyd_brusselator) -prob_brusselator_2d = NonlinearProblem(brusselator_2d_loop, u0, p) -sol = solve(prob_brusselator_2d, NewtonRaphson(); abstol = 1e-8) -@test norm(sol.resid, Inf) < 1e-8 +@testcase "Brusselator" begin + u0 = init_brusselator_2d(xyd_brusselator) + prob_brusselator_2d = NonlinearProblem(brusselator_2d_loop, u0, p) + sol = solve(prob_brusselator_2d, NewtonRaphson(); abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-8 -sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseForwardDiff()); - abstol = 1e-8) -@test norm(sol.resid, Inf) < 1e-8 + sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseForwardDiff()); + abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-8 -sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseFiniteDiff()); - abstol = 1e-8) -@test norm(sol.resid, Inf) < 1e-8 + sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseFiniteDiff()); + abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-8 -du0 = copy(u0) -jac_sparsity = Symbolics.jacobian_sparsity((du, u) -> brusselator_2d_loop(du, u, p), du0, - u0) -jac_prototype = float.(jac_sparsity) -fill!(jac_prototype, 0) -@test all(iszero, jac_prototype) + du0 = copy(u0) + jac_sparsity = Symbolics.jacobian_sparsity((du, u) -> brusselator_2d_loop(du, u, p), + du0, u0) + jac_prototype = float.(jac_sparsity) + fill!(jac_prototype, 0) + @test all(iszero, jac_prototype) -ff_iip = NonlinearFunction(brusselator_2d_loop; jac_prototype) -prob_brusselator_2d = NonlinearProblem(ff_iip, u0, p) + ff_iip = NonlinearFunction(brusselator_2d_loop; jac_prototype) + prob_brusselator_2d = NonlinearProblem(ff_iip, u0, p) -sol = solve(prob_brusselator_2d, NewtonRaphson(); abstol = 1e-8) -@test norm(sol.resid, Inf) < 1e-8 -@test !all(iszero, jac_prototype) + sol = solve(prob_brusselator_2d, NewtonRaphson(); abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-8 + @test !all(iszero, jac_prototype) -sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseFiniteDiff()); - abstol = 1e-8) -@test norm(sol.resid, Inf) < 1e-8 + sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseFiniteDiff()); + abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-8 -cache = init(prob_brusselator_2d, NewtonRaphson(; autodiff = AutoSparseForwardDiff())); -@test maximum(cache.jac_cache.jac_cache.coloring.colorvec) == 12 -@test cache.jac_cache.autodiff isa AutoSparseForwardDiff + cache = init(prob_brusselator_2d, NewtonRaphson(; autodiff = AutoSparseForwardDiff())) + @test maximum(cache.jac_cache.jac_cache.coloring.colorvec) == 12 + @test cache.jac_cache.autodiff isa AutoSparseForwardDiff +end diff --git a/test/misc/matrix_resizing.jl b/test/misc/matrix_resizing.jl index 978517525..49e07d245 100644 --- a/test/misc/matrix_resizing.jl +++ b/test/misc/matrix_resizing.jl @@ -1,4 +1,4 @@ -using NonlinearSolve, Test, StableRNGs +using NonlinearSolve, XUnit, StableRNGs ff(u, p) = u .* u .- p u0 = rand(StableRNG(0), 2, 2) @@ -6,9 +6,9 @@ p = 2.0 vecprob = NonlinearProblem(ff, vec(u0), p) prob = NonlinearProblem(ff, u0, p) -for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), PseudoTransient(), - RobustMultiNewton(), FastShortcutNonlinearPolyalg(), Broyden(), Klement(), - LimitedMemoryBroyden(; threshold = 2)) +@testcase "$(alg)" for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), + PseudoTransient(), RobustMultiNewton(), FastShortcutNonlinearPolyalg(), Broyden(), + Klement(), LimitedMemoryBroyden(; threshold = 2)) @test vec(solve(prob, alg).u) == solve(vecprob, alg).u end @@ -18,8 +18,8 @@ p = 2.0 vecprob = NonlinearProblem(fiip, vec(u0), p) prob = NonlinearProblem(fiip, u0, p) -for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), PseudoTransient(), - RobustMultiNewton(), FastShortcutNonlinearPolyalg(), Broyden(), Klement(), - LimitedMemoryBroyden(; threshold = 2)) +@testcase "$(alg)" for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), + PseudoTransient(), RobustMultiNewton(), FastShortcutNonlinearPolyalg(), Broyden(), + Klement(), LimitedMemoryBroyden(; threshold = 2)) @test vec(solve(prob, alg).u) == solve(vecprob, alg).u end diff --git a/test/misc/polyalgs.jl b/test/misc/polyalgs.jl index 1709aa018..13cd8ecd4 100644 --- a/test/misc/polyalgs.jl +++ b/test/misc/polyalgs.jl @@ -1,6 +1,6 @@ -using NonlinearSolve, Test, NaNMath, OrdinaryDiffEq, StaticArrays, LinearAlgebra +using NonlinearSolve, XUnit, NaNMath, OrdinaryDiffEq, StaticArrays, LinearAlgebra -@testset "Basic PolyAlgorithms" begin +@testcase "Basic PolyAlgorithms" begin f(u, p) = u .* u .- 2 u0 = [1.0, 1.0] probN = NonlinearProblem{false}(f, u0) @@ -8,31 +8,31 @@ using NonlinearSolve, Test, NaNMath, OrdinaryDiffEq, StaticArrays, LinearAlgebra custom_polyalg = NonlinearSolvePolyAlgorithm((Broyden(), LimitedMemoryBroyden())) # Uses the `__solve` function - @time solver = solve(probN; abstol = 1e-9) + solver = solve(probN; abstol = 1e-9) @test SciMLBase.successful_retcode(solver) - @time solver = solve(probN, RobustMultiNewton(); abstol = 1e-9) + solver = solve(probN, RobustMultiNewton(); abstol = 1e-9) @test SciMLBase.successful_retcode(solver) - @time solver = solve(probN, FastShortcutNonlinearPolyalg(); abstol = 1e-9) + solver = solve(probN, FastShortcutNonlinearPolyalg(); abstol = 1e-9) @test SciMLBase.successful_retcode(solver) - @time solver = solve(probN, custom_polyalg; abstol = 1e-9) + solver = solve(probN, custom_polyalg; abstol = 1e-9) @test SciMLBase.successful_retcode(solver) # Test the caching interface cache = init(probN; abstol = 1e-9) - @time solver = solve!(cache) + solver = solve!(cache) @test SciMLBase.successful_retcode(solver) cache = init(probN, RobustMultiNewton(); abstol = 1e-9) - @time solver = solve!(cache) + solver = solve!(cache) @test SciMLBase.successful_retcode(solver) cache = init(probN, FastShortcutNonlinearPolyalg(); abstol = 1e-9) - @time solver = solve!(cache) + solver = solve!(cache) @test SciMLBase.successful_retcode(solver) cache = init(probN, custom_polyalg; abstol = 1e-9) - @time solver = solve!(cache) + solver = solve!(cache) @test SciMLBase.successful_retcode(solver) end -@testset "Testing #153 Singular Exception" begin +@testcase "Testing #153 Singular Exception" begin # https://github.com/SciML/NonlinearSolve.jl/issues/153 function f(du, u, p) s1, s1s2, s2 = u @@ -48,7 +48,7 @@ end @test SciMLBase.successful_retcode(sol) end -@testset "Simple Scalar Problem #187" begin +@testcase "Simple Scalar Problem #187" begin # https://github.com/SciML/NonlinearSolve.jl/issues/187 # If we use a General Nonlinear Solver the solution might go out of the domain! ff_interval(u, p) = 0.5 / 1.5 * NaNMath.log.(u ./ (1.0 .- u)) .- 2.0 * u .+ 1.0 @@ -68,7 +68,7 @@ end # Shooting Problem: Taken from BoundaryValueDiffEq.jl # Testing for Complex Valued Root Finding. For Complex valued inputs we drop some of the # algorithms which dont support those. -@testset "Complex Valued Problems: Single-Shooting" begin +@testcase "Complex Valued Problems: Single-Shooting" begin function ode_func!(du, u, p, t) du[1] = u[2] du[2] = -u[1] @@ -96,7 +96,7 @@ end no_ad_fast = FastShortcutNonlinearPolyalg(autodiff = AutoFiniteDiff()) no_ad_robust = RobustMultiNewton(autodiff = AutoFiniteDiff()) no_ad_algs = Set([no_ad_fast, no_ad_robust, no_ad_fast.algs..., no_ad_robust.algs...]) -@testset "[IIP] no AD" begin +@testcase "[IIP] no AD" begin f_iip = Base.Experimental.@opaque (du, u, p) -> du .= u .* u .- p u0 = [0.5] prob = NonlinearProblem(f_iip, u0, 1.0) @@ -107,7 +107,7 @@ no_ad_algs = Set([no_ad_fast, no_ad_robust, no_ad_fast.algs..., no_ad_robust.alg end end -@testset "[OOP] no AD" begin +@testcase "[OOP] no AD" begin f_oop = Base.Experimental.@opaque (u, p) -> u .* u .- p u0 = [0.5] prob = NonlinearProblem{false}(f_oop, u0, 1.0) @@ -157,7 +157,7 @@ function f1_infeasible(u, p) return [a - 42.0e6, e - 1e-5, i - 1e-5] end -@testset "[IIP] Infeasible" begin +@testcase "[IIP] Infeasible" begin u0 = [0.0, 0.0, 0.0] prob = NonlinearProblem(f1_infeasible!, u0) sol = solve(prob) @@ -166,7 +166,7 @@ end @test !SciMLBase.successful_retcode(sol.retcode) end -@testset "[OOP] Infeasible" begin +@testcase "[OOP] Infeasible" begin u0 = [0.0, 0.0, 0.0] prob = NonlinearProblem(f1_infeasible, u0) sol = solve(prob) diff --git a/test/misc/qa.jl b/test/misc/qa.jl index 4629c2132..9cfbe2421 100644 --- a/test/misc/qa.jl +++ b/test/misc/qa.jl @@ -1,6 +1,6 @@ -using NonlinearSolve, Aqua +using NonlinearSolve, Aqua, XUnit -@testset "Aqua" begin +@testcase "Aqua" begin Aqua.find_persistent_tasks_deps(NonlinearSolve) Aqua.test_ambiguities(NonlinearSolve; recursive = false) Aqua.test_deps_compat(NonlinearSolve) diff --git a/test/runtests.jl b/test/runtests.jl index 5a1be8e22..7777a0e30 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,4 @@ -using Pkg, SafeTestsets +using Pkg, SafeTestsets, XUnit const GROUP = get(ENV, "GROUP", "All") @@ -8,36 +8,24 @@ function activate_env(env) Pkg.instantiate() end -@time begin - if GROUP == "All" || GROUP == "RootFinding" - @time @safetestset "Basic Root Finding Tests" include("core/rootfind.jl") - @time @safetestset "Forward AD" include("core/forward_ad.jl") - end - - if GROUP == "All" || GROUP == "NLLSSolvers" - @time @safetestset "Basic NLLS Solvers" include("core/nlls.jl") - end - - if GROUP == "All" || GROUP == "Wrappers" - @time @safetestset "Fixed Point Solvers" include("wrappers/fixedpoint.jl") - @time @safetestset "Root Finding Solvers" include("wrappers/rootfind.jl") - @time @safetestset "Nonlinear Least Squares Solvers" include("wrappers/nlls.jl") - end - - if GROUP == "All" || GROUP == "23TestProblems" - @time @safetestset "23 Test Problems" include("core/23_test_problems.jl") - end - - if GROUP == "All" || GROUP == "Miscellaneous" - @time @safetestset "Quality Assurance" include("misc/qa.jl") - @time @safetestset "Sparsity Tests: Bruss Steady State" include("misc/bruss.jl") - @time @safetestset "Polyalgs" include("misc/polyalgs.jl") - @time @safetestset "Matrix Resizing" include("misc/matrix_resizing.jl") - @time @safetestset "Banded Matrices" include("misc/banded_matrices.jl") +@testset runner=ParallelTestRunner() "NonlinearSolve.jl" begin + if GROUP == "All" || GROUP == "Core" + @safetestset "Basic Root Finding Tests" include("core/rootfind.jl") + @safetestset "Forward AD" include("core/forward_ad.jl") + @safetestset "Basic NLLS Solvers" include("core/nlls.jl") + @safetestset "Fixed Point Solvers" include("wrappers/fixedpoint.jl") + @safetestset "Root Finding Solvers" include("wrappers/rootfind.jl") + @safetestset "Nonlinear Least Squares Solvers" include("wrappers/nlls.jl") + @safetestset "23 Test Problems" include("core/23_test_problems.jl") + @safetestset "Quality Assurance" include("misc/qa.jl") + @safetestset "Sparsity Tests" include("misc/bruss.jl") + @safetestset "Polyalgs" include("misc/polyalgs.jl") + @safetestset "Matrix Resizing" include("misc/matrix_resizing.jl") + @safetestset "Banded Matrices" include("misc/banded_matrices.jl") end if GROUP == "GPU" activate_env("gpu") - @time @safetestset "GPU Tests" include("gpu/core.jl") + @safetestset "GPU Tests" include("gpu/core.jl") end end diff --git a/test/wrappers/fixedpoint.jl b/test/wrappers/fixedpoint.jl index 87d8e9d7b..52ca1963d 100644 --- a/test/wrappers/fixedpoint.jl +++ b/test/wrappers/fixedpoint.jl @@ -1,8 +1,8 @@ -using NonlinearSolve, LinearAlgebra, Test +using NonlinearSolve, LinearAlgebra, XUnit import SIAMFANLEquations, FixedPointAcceleration, SpeedMapping, NLsolve # Simple Scalar Problem -@testset "Simple Scalar Problem" begin +@testcase "Simple Scalar Problem" begin f1(x, p) = cos(x) - x prob = NonlinearProblem(f1, 1.1) @@ -19,7 +19,7 @@ import SIAMFANLEquations, FixedPointAcceleration, SpeedMapping, NLsolve end # Simple Vector Problem -@testset "Simple Vector Problem" begin +@testcase "Simple Vector Problem" begin f2(x, p) = cos.(x) .- x prob = NonlinearProblem(f2, [1.1, 1.1]) @@ -38,7 +38,7 @@ end # Fixed Point for Power Method # Taken from https://github.com/NicolasL-S/SpeedMapping.jl/blob/95951db8f8a4457093090e18802ad382db1c76da/test/runtests.jl -@testset "Power Method" begin +@testcase "Power Method" begin C = [1 2 3; 4 5 6; 7 8 9] A = C + C' B = Hermitian(ones(10) * ones(10)' .* im + Diagonal(1:10)) diff --git a/test/wrappers/nlls.jl b/test/wrappers/nlls.jl index dfd8aa5fe..fed44ac6f 100644 --- a/test/wrappers/nlls.jl +++ b/test/wrappers/nlls.jl @@ -1,5 +1,5 @@ using NonlinearSolve, - LinearAlgebra, Test, StableRNGs, StaticArrays, Random, ForwardDiff, Zygote + LinearAlgebra, XUnit, StableRNGs, StaticArrays, Random, ForwardDiff, Zygote import FastLevenbergMarquardt, LeastSquaresOptim, MINPACK true_function(x, θ) = @. θ[1] * exp(θ[2] * x) * cos(θ[3] * x + θ[4]) @@ -32,10 +32,12 @@ nlls_problems = [prob_oop, prob_iip] solvers = [LeastSquaresOptimJL(alg; autodiff) for alg in (:lm, :dogleg), autodiff in (nothing, AutoForwardDiff(), AutoFiniteDiff(), :central, :forward)] -for prob in nlls_problems, solver in solvers - @time sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) - @test SciMLBase.successful_retcode(sol) - @test norm(sol.resid, Inf) < 1e-6 +@testcase "LeastSquaresOptim.jl" begin + for prob in nlls_problems, solver in solvers + sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) + @test SciMLBase.successful_retcode(sol) + @test norm(sol.resid, Inf) < 1e-6 + end end function jac!(J, θ, p) @@ -57,9 +59,11 @@ probs = [ solvers = Any[FastLevenbergMarquardtJL(linsolve) for linsolve in (:cholesky, :qr)] push!(solvers, CMINPACK()) -for solver in solvers, prob in probs - @time sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) - @test maximum(abs, sol.resid) < 1e-6 +@testcase "FastLevenbergMarquardt.jl + CMINPACK: Jacobian Provided" begin + for solver in solvers, prob in probs + sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) + @test maximum(abs, sol.resid) < 1e-6 + end end probs = [ @@ -75,9 +79,11 @@ solvers = vec(Any[FastLevenbergMarquardtJL(linsolve; autodiff) autodiff in (nothing, AutoForwardDiff(), AutoFiniteDiff())]) append!(solvers, [CMINPACK(; method) for method in (:auto, :lm, :lmdif)]) -for solver in solvers, prob in probs - @time sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) - @test norm(sol.resid, Inf) < 1e-6 +@testcase "FastLevenbergMarquardt.jl + CMINPACK: Jacobian Not Provided" begin + for solver in solvers, prob in probs + sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-6 + end end # Static Arrays -- Fast Levenberg-Marquardt @@ -93,5 +99,7 @@ end θ_init_sa = SVector{4}(θ_init) prob_sa = NonlinearLeastSquaresProblem{false}(loss_function_sa, θ_init_sa, x) -@time sol = solve(prob_sa, FastLevenbergMarquardtJL()) -@test norm(sol.resid, Inf) < 1e-6 +@testcase "FastLevenbergMarquardt.jl + StaticArrays" begin + sol = solve(prob_sa, FastLevenbergMarquardtJL()) + @test norm(sol.resid, Inf) < 1e-6 +end diff --git a/test/wrappers/rootfind.jl b/test/wrappers/rootfind.jl index 47021fb77..5600dbc56 100644 --- a/test/wrappers/rootfind.jl +++ b/test/wrappers/rootfind.jl @@ -1,7 +1,7 @@ -using NonlinearSolve, LinearAlgebra, SciMLBase, Test +using NonlinearSolve, LinearAlgebra, SciMLBase, XUnit import NLsolve, SIAMFANLEquations, MINPACK -@testset "Steady State Problems" begin +@testcase "Steady State Problems" begin # IIP Tests function f_iip(du, u, p, t) du[1] = 2 - 2u[1] @@ -28,7 +28,7 @@ import NLsolve, SIAMFANLEquations, MINPACK end end -@testset "Nonlinear Root Finding Problems" begin +@testcase "Nonlinear Root Finding Problems" begin # IIP Tests function f_iip(du, u, p) du[1] = 2 - 2u[1] @@ -91,17 +91,14 @@ end @test maximum(abs, sol.resid) < 1e-6 # Custom Jacobian - problem(x, A) = x .^ 2 - A - problemJacobian(x, A) = diagm(2 .* x) - - f!(F, u, p) = (F[1:152] = problem(u, p)) - j!(J, u, p) = (J[1:152, 1:152] = problemJacobian(u, p)) + f_custom_jac!(F, u, p) = (F[1:152] = u .^ 2 .- p) + j_custom_jac!(J, u, p) = (J[1:152, 1:152] = diagm(2 .* u)) init = ones(152) A = ones(152) A[6] = 0.8 - f = NonlinearFunction(f!; jac = j!) + f = NonlinearFunction(f_custom_jac!; jac = j_custom_jac!) p = A ProbN = NonlinearProblem(f, init, p) From 4c978a6904a8bceb37cf672b3fc2e9546628da5e Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Thu, 8 Feb 2024 21:44:23 -0500 Subject: [PATCH 2/3] Distributed Testing using ReTestItems --- .github/workflows/CI.yml | 4 +- Project.toml | 9 +- src/algorithms/levenberg_marquardt.jl | 5 +- ..._problems.jl => 23_test_problems_tests.jl} | 22 ++-- .../{forward_ad.jl => forward_ad_tests.jl} | 82 +++++++------ test/core/{nlls.jl => nlls_tests.jl} | 60 +++++----- test/core/{rootfind.jl => rootfind_tests.jl} | 29 +++-- test/gpu/Project.toml | 2 +- test/gpu/core.jl | 49 ++++---- test/misc/banded_matrices.jl | 9 -- test/misc/banded_matrices_tests.jl | 8 ++ test/misc/bruss.jl | 76 ------------ test/misc/bruss_tests.jl | 78 ++++++++++++ test/misc/matrix_resizing.jl | 25 ---- test/misc/matrix_resizing_tests.jl | 31 +++++ test/misc/{polyalgs.jl => polyalg_tests.jl} | 69 ++++++----- test/misc/{qa.jl => qa_tests.jl} | 4 +- test/runtests.jl | 29 ++--- .../{fixedpoint.jl => fixedpoint_tests.jl} | 11 +- test/wrappers/nlls.jl | 105 ----------------- test/wrappers/nlls_tests.jl | 111 ++++++++++++++++++ .../{rootfind.jl => rootfind_tests.jl} | 10 +- 22 files changed, 440 insertions(+), 388 deletions(-) rename test/core/{23_test_problems.jl => 23_test_problems_tests.jl} (88%) rename test/core/{forward_ad.jl => forward_ad_tests.jl} (50%) rename test/core/{nlls.jl => nlls_tests.jl} (57%) rename test/core/{rootfind.jl => rootfind_tests.jl} (96%) delete mode 100644 test/misc/banded_matrices.jl create mode 100644 test/misc/banded_matrices_tests.jl delete mode 100644 test/misc/bruss.jl create mode 100644 test/misc/bruss_tests.jl delete mode 100644 test/misc/matrix_resizing.jl create mode 100644 test/misc/matrix_resizing_tests.jl rename test/misc/{polyalgs.jl => polyalg_tests.jl} (76%) rename test/misc/{qa.jl => qa_tests.jl} (90%) rename test/wrappers/{fixedpoint.jl => fixedpoint_tests.jl} (92%) delete mode 100644 test/wrappers/nlls.jl create mode 100644 test/wrappers/nlls_tests.jl rename test/wrappers/{rootfind.jl => rootfind_tests.jl} (92%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 5fb920004..6f59b6b2b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -44,7 +44,9 @@ jobs: - uses: julia-actions/julia-runtest@v1 env: GROUP: ${{ matrix.group }} - JULIA_NUM_THREADS: 8 + JULIA_NUM_THREADS: 11 + RETESTITEMS_NWORKERS: 4 + RETESTITEMS_NWORKER_THREADS: 2 - uses: julia-actions/julia-processcoverage@v1 with: directories: src,ext diff --git a/Project.toml b/Project.toml index fd602834a..ff61a9212 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "NonlinearSolve" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" authors = ["SciML"] -version = "3.5.3" +version = "3.5.4" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" @@ -84,6 +84,7 @@ PrecompileTools = "1.2" Preferences = "1.4" Printf = "1.10" Random = "1.91" +ReTestItems = "1" RecursiveArrayTools = "3.4" Reexport = "1.2" SIAMFANLEquations = "1.0.1" @@ -101,7 +102,6 @@ Symbolics = "5.13" Test = "1.10" TimerOutputs = "0.5.23" Zygote = "0.6.67" -XUnit = "1.1" julia = "1.10" [extras] @@ -123,6 +123,8 @@ NonlinearProblemLibrary = "b7050fa9-e91f-4b37-bcee-a89a063da141" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +ReTestItems = "817f1d60-ba6b-4fd5-9520-3cf149f6a823" +Reexport = "189a3867-3050-52da-a836-e630ba90ab69" SIAMFANLEquations = "084e46ad-d928-497d-ad5e-07fa361a48c4" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" SparseDiffTools = "47a9eef4-7e08-11e9-0b38-333d64bd3804" @@ -132,8 +134,7 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -XUnit = "3e3c03f2-1a94-11e9-2981-050a4ca824ab" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [targets] -test = ["Aqua", "Enzyme", "BenchmarkTools", "SafeTestsets", "Pkg", "Test", "ForwardDiff", "StaticArrays", "Symbolics", "LinearSolve", "Random", "LinearAlgebra", "Zygote", "SparseDiffTools", "NonlinearProblemLibrary", "LeastSquaresOptim", "FastLevenbergMarquardt", "NaNMath", "BandedMatrices", "DiffEqBase", "StableRNGs", "MINPACK", "NLsolve", "OrdinaryDiffEq", "SpeedMapping", "FixedPointAcceleration", "SIAMFANLEquations", "Sundials", "XUnit"] +test = ["Aqua", "Enzyme", "BenchmarkTools", "SafeTestsets", "Pkg", "Test", "ForwardDiff", "StaticArrays", "Symbolics", "LinearSolve", "Random", "LinearAlgebra", "Zygote", "SparseDiffTools", "NonlinearProblemLibrary", "LeastSquaresOptim", "FastLevenbergMarquardt", "NaNMath", "BandedMatrices", "DiffEqBase", "StableRNGs", "MINPACK", "NLsolve", "OrdinaryDiffEq", "SpeedMapping", "FixedPointAcceleration", "SIAMFANLEquations", "Sundials", "ReTestItems", "Reexport"] diff --git a/src/algorithms/levenberg_marquardt.jl b/src/algorithms/levenberg_marquardt.jl index 72dd63957..0757b6d4c 100644 --- a/src/algorithms/levenberg_marquardt.jl +++ b/src/algorithms/levenberg_marquardt.jl @@ -69,10 +69,11 @@ end J_diag_cache J_damped damping_f + initial_damping end function reinit_cache!(cache::LevenbergMarquardtDampingCache, args...; kwargs...) - cache.λ = cache.damping_f.initial_damping + cache.λ = cache.initial_damping cache.λ_factor = cache.damping_f.increase_factor if !(cache.DᵀD isa Number) if can_setindex(cache.DᵀD.diag) @@ -110,7 +111,7 @@ function __internal_init(prob::AbstractNonlinearProblem, J_damped = T(initial_damping) .* DᵀD return LevenbergMarquardtDampingCache(T(f.increase_factor), T(f.decrease_factor), T(f.min_damping), T(f.increase_factor), T(initial_damping), DᵀD, J_diag_cache, - J_damped, f) + J_damped, f, T(initial_damping)) end (damping::LevenbergMarquardtDampingCache)(::Nothing) = damping.J_damped diff --git a/test/core/23_test_problems.jl b/test/core/23_test_problems_tests.jl similarity index 88% rename from test/core/23_test_problems.jl rename to test/core/23_test_problems_tests.jl index 3146d49f5..cf6fa129f 100644 --- a/test/core/23_test_problems.jl +++ b/test/core/23_test_problems_tests.jl @@ -1,4 +1,5 @@ -using NonlinearSolve, LinearAlgebra, LinearSolve, NonlinearProblemLibrary, XUnit +@testsetup module RobustnessTesting +using NonlinearSolve, LinearAlgebra, LinearSolve, NonlinearProblemLibrary, Test problems = NonlinearProblemLibrary.problems dicts = NonlinearProblemLibrary.dicts @@ -36,7 +37,10 @@ function test_on_library(problems, dicts, alg_ops, broken_tests, ϵ = 1e-4; end end -@testcase "NewtonRaphson 23 Test Problems" begin +export test_on_library, problems, dicts +end + +@testitem "NewtonRaphson" setup=[RobustnessTesting] begin alg_ops = (NewtonRaphson(),) broken_tests = Dict(alg => Int[] for alg in alg_ops) @@ -45,7 +49,7 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testcase "TrustRegion 23 Test Problems" begin +@testitem "TrustRegion" setup=[RobustnessTesting] begin alg_ops = (TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Simple), TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Fan), TrustRegion(; radius_update_scheme = RadiusUpdateSchemes.Hei), @@ -64,7 +68,9 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testcase "LevenbergMarquardt 23 Test Problems" begin +@testitem "LevenbergMarquardt" setup=[RobustnessTesting] begin + using LinearSolve + alg_ops = (LevenbergMarquardt(), LevenbergMarquardt(; α_geodesic = 0.1), LevenbergMarquardt(; linsolve = CholeskyFactorization())) @@ -77,7 +83,7 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testcase "DFSane 23 Test Problems" begin +@testitem "DFSane" setup=[RobustnessTesting] begin alg_ops = (DFSane(),) broken_tests = Dict(alg => Int[] for alg in alg_ops) @@ -86,7 +92,7 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testcase "Broyden 23 Test Problems" begin +@testitem "Broyden" setup=[RobustnessTesting] begin alg_ops = (Broyden(), Broyden(; init_jacobian = Val(:true_jacobian)), Broyden(; update_rule = Val(:bad_broyden)), @@ -101,7 +107,7 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testcase "Klement 23 Test Problems" begin +@testitem "Klement" setup=[RobustnessTesting] begin alg_ops = (Klement(), Klement(; init_jacobian = Val(:true_jacobian_diagonal))) broken_tests = Dict(alg => Int[] for alg in alg_ops) @@ -111,7 +117,7 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testcase "PseudoTransient 23 Test Problems" begin +@testitem "PseudoTransient" setup=[RobustnessTesting] begin # PT relies on the root being a stable equilibrium for convergence, so it won't work on # most problems alg_ops = (PseudoTransient(),) diff --git a/test/core/forward_ad.jl b/test/core/forward_ad_tests.jl similarity index 50% rename from test/core/forward_ad.jl rename to test/core/forward_ad_tests.jl index b0b4fee03..22882cbec 100644 --- a/test/core/forward_ad.jl +++ b/test/core/forward_ad_tests.jl @@ -1,5 +1,6 @@ -using ForwardDiff, - NonlinearSolve, MINPACK, NLsolve, StaticArrays, Sundials, XUnit, LinearAlgebra +@testsetup module ForwardADTesting +using Reexport, NonlinearSolve +@reexport using ForwardDiff, MINPACK, NLsolve, StaticArrays, Sundials, LinearAlgebra test_f!(du, u, p) = (@. du = u^2 - p) test_f(u, p) = (@. u^2 - p) @@ -58,50 +59,55 @@ __compatible(::NLsolveJL, ::Val{:oop_cache}) = false __compatible(::KINSOL, ::Val{:iip_cache}) = false __compatible(::KINSOL, ::Val{:oop_cache}) = false -@testcase "ForwardDiff.jl Integration: $(alg)" for alg in (NewtonRaphson(), TrustRegion(), - LevenbergMarquardt(), PseudoTransient(; alpha_initial = 10.0), Broyden(), Klement(), - DFSane(), nothing, NLsolveJL(), CMINPACK(), - KINSOL(; globalization_strategy = :LineSearch)) - us = (2.0, @SVector[1.0, 1.0], [1.0, 1.0], ones(2, 2), @SArray ones(2, 2)) +export test_f!, test_f, jacobian_f, solve_with, __compatible +end + +@testitem "ForwardDiff.jl Integration" setup=[ForwardADTesting] begin + for alg in (NewtonRaphson(), TrustRegion(), + LevenbergMarquardt(), PseudoTransient(; alpha_initial = 10.0), Broyden(), Klement(), + DFSane(), nothing, NLsolveJL(), CMINPACK(), + KINSOL(; globalization_strategy = :LineSearch)) + us = (2.0, @SVector[1.0, 1.0], [1.0, 1.0], ones(2, 2), @SArray ones(2, 2)) - @testset "Scalar AD" begin - for p in 1.0:0.1:100.0, u0 in us, mode in (:iip, :oop, :iip_cache, :oop_cache) - __compatible(u0, alg) || continue - __compatible(u0, Val(mode)) || continue - __compatible(alg, Val(mode)) || continue + @testset "Scalar AD" begin + for p in 1.0:0.1:100.0, u0 in us, mode in (:iip, :oop, :iip_cache, :oop_cache) + __compatible(u0, alg) || continue + __compatible(u0, Val(mode)) || continue + __compatible(alg, Val(mode)) || continue - sol = solve(NonlinearProblem(test_f, u0, p), alg) - if SciMLBase.successful_retcode(sol) - gs = abs.(ForwardDiff.derivative(solve_with(Val{mode}(), u0, alg), p)) - gs_true = abs.(jacobian_f(u0, p)) - if !(isapprox(gs, gs_true, atol = 1e-5)) - @show sol.retcode, sol.u - @error "ForwardDiff Failed for u0=$(u0) and p=$(p) with $(alg)" forwardiff_gradient=gs true_gradient=gs_true - else - @test abs.(gs)≈abs.(gs_true) atol=1e-5 + sol = solve(NonlinearProblem(test_f, u0, p), alg) + if SciMLBase.successful_retcode(sol) + gs = abs.(ForwardDiff.derivative(solve_with(Val{mode}(), u0, alg), p)) + gs_true = abs.(jacobian_f(u0, p)) + if !(isapprox(gs, gs_true, atol = 1e-5)) + @show sol.retcode, sol.u + @error "ForwardDiff Failed for u0=$(u0) and p=$(p) with $(alg)" forwardiff_gradient=gs true_gradient=gs_true + else + @test abs.(gs)≈abs.(gs_true) atol=1e-5 + end end end end - end - @testset "Jacobian" begin - for u0 in us, p in ([2.0, 1.0], [2.0 1.0; 3.0 4.0]), - mode in (:iip, :oop, :iip_cache, :oop_cache) + @testset "Jacobian" begin + for u0 in us, p in ([2.0, 1.0], [2.0 1.0; 3.0 4.0]), + mode in (:iip, :oop, :iip_cache, :oop_cache) - __compatible(u0, p) || continue - __compatible(u0, alg) || continue - __compatible(u0, Val(mode)) || continue - __compatible(alg, Val(mode)) || continue + __compatible(u0, p) || continue + __compatible(u0, alg) || continue + __compatible(u0, Val(mode)) || continue + __compatible(alg, Val(mode)) || continue - sol = solve(NonlinearProblem(test_f, u0, p), alg) - if SciMLBase.successful_retcode(sol) - gs = abs.(ForwardDiff.jacobian(solve_with(Val{mode}(), u0, alg), p)) - gs_true = abs.(jacobian_f(u0, p)) - if !(isapprox(gs, gs_true, atol = 1e-5)) - @show sol.retcode, sol.u - @error "ForwardDiff Failed for u0=$(u0) and p=$(p) with $(alg)" forwardiff_jacobian=gs true_jacobian=gs_true - else - @test abs.(gs)≈abs.(gs_true) atol=1e-5 + sol = solve(NonlinearProblem(test_f, u0, p), alg) + if SciMLBase.successful_retcode(sol) + gs = abs.(ForwardDiff.jacobian(solve_with(Val{mode}(), u0, alg), p)) + gs_true = abs.(jacobian_f(u0, p)) + if !(isapprox(gs, gs_true, atol = 1e-5)) + @show sol.retcode, sol.u + @error "ForwardDiff Failed for u0=$(u0) and p=$(p) with $(alg)" forwardiff_jacobian=gs true_jacobian=gs_true + else + @test abs.(gs)≈abs.(gs_true) atol=1e-5 + end end end end diff --git a/test/core/nlls.jl b/test/core/nlls_tests.jl similarity index 57% rename from test/core/nlls.jl rename to test/core/nlls_tests.jl index daddc9f3f..1720d77fa 100644 --- a/test/core/nlls.jl +++ b/test/core/nlls_tests.jl @@ -1,5 +1,7 @@ -using NonlinearSolve, - LinearSolve, LinearAlgebra, XUnit, StableRNGs, Random, ForwardDiff, Zygote +@testsetup module CoreNLLSTesting +using Reexport +@reexport using NonlinearSolve, + LinearSolve, LinearAlgebra, StableRNGs, Random, ForwardDiff, Zygote true_function(x, θ) = @. θ[1] * exp(θ[2] * x) * cos(θ[3] * x + θ[4]) true_function(y, x, θ) = (@. y = θ[1] * exp(θ[2] * x) * cos(θ[3] * x + θ[4])) @@ -22,11 +24,6 @@ function loss_function(resid, θ, p) end θ_init = θ_true .+ randn!(StableRNG(0), similar(θ_true)) * 0.1 -prob_oop = NonlinearLeastSquaresProblem{false}(loss_function, θ_init, x) -prob_iip = NonlinearLeastSquaresProblem(NonlinearFunction(loss_function; - resid_prototype = zero(y_target)), θ_init, x) - -nlls_problems = [prob_oop, prob_iip] solvers = [] for linsolve in [nothing, LUFactorization(), KrylovJL_GMRES(), KrylovJL_LSMR()] @@ -52,7 +49,16 @@ for radius_update_scheme in [RadiusUpdateSchemes.Simple, RadiusUpdateSchemes.Noc push!(solvers, TrustRegion(; radius_update_scheme)) end -@testcase "General NLLS Solvers" begin +export solvers, θ_init, x, y_target, true_function, θ_true, loss_function +end + +@testitem "General NLLS Solvers" setup=[CoreNLLSTesting] begin + prob_oop = NonlinearLeastSquaresProblem{false}(loss_function, θ_init, x) + prob_iip = NonlinearLeastSquaresProblem(NonlinearFunction(loss_function; + resid_prototype = zero(y_target)), θ_init, x) + + nlls_problems = [prob_oop, prob_iip] + for prob in nlls_problems, solver in solvers sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) @test SciMLBase.successful_retcode(sol) @@ -60,28 +66,28 @@ end end end -# This is just for testing that we can use vjp provided by the user -function vjp(v, θ, p) - resid = zeros(length(p)) - J = ForwardDiff.jacobian((resid, θ) -> loss_function(resid, θ, p), resid, θ) - return vec(v' * J) -end +@testitem "Custom VJP" setup=[CoreNLLSTesting] begin + # This is just for testing that we can use vjp provided by the user + function vjp(v, θ, p) + resid = zeros(length(p)) + J = ForwardDiff.jacobian((resid, θ) -> loss_function(resid, θ, p), resid, θ) + return vec(v' * J) + end -function vjp!(Jv, v, θ, p) - resid = zeros(length(p)) - J = ForwardDiff.jacobian((resid, θ) -> loss_function(resid, θ, p), resid, θ) - mul!(vec(Jv), transpose(J), v) - return nothing -end + function vjp!(Jv, v, θ, p) + resid = zeros(length(p)) + J = ForwardDiff.jacobian((resid, θ) -> loss_function(resid, θ, p), resid, θ) + mul!(vec(Jv), transpose(J), v) + return nothing + end -probs = [ - NonlinearLeastSquaresProblem(NonlinearFunction{true}(loss_function; - resid_prototype = zero(y_target), vjp = vjp!), θ_init, x), - NonlinearLeastSquaresProblem(NonlinearFunction{false}(loss_function; - resid_prototype = zero(y_target), vjp = vjp), θ_init, x), -] + probs = [ + NonlinearLeastSquaresProblem(NonlinearFunction{true}(loss_function; + resid_prototype = zero(y_target), vjp = vjp!), θ_init, x), + NonlinearLeastSquaresProblem(NonlinearFunction{false}(loss_function; + resid_prototype = zero(y_target), vjp = vjp), θ_init, x), + ] -@testcase "Custom VJP" begin for prob in probs, solver in solvers sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) @test maximum(abs, sol.resid) < 1e-6 diff --git a/test/core/rootfind.jl b/test/core/rootfind_tests.jl similarity index 96% rename from test/core/rootfind.jl rename to test/core/rootfind_tests.jl index d6e36ade9..412d7f1ac 100644 --- a/test/core/rootfind.jl +++ b/test/core/rootfind_tests.jl @@ -1,5 +1,7 @@ -using BenchmarkTools, LinearSolve, NonlinearSolve, StaticArrays, Random, LinearAlgebra, - XUnit, ForwardDiff, Zygote, Enzyme, SparseDiffTools, DiffEqBase +@testsetup module CoreRootfindTesting +using Reexport +@reexport using BenchmarkTools, LinearSolve, NonlinearSolve, StaticArrays, Random, + LinearAlgebra, ForwardDiff, Zygote, Enzyme, SparseDiffTools, DiffEqBase function __autosparseenzyme() @static if Sys.iswindows() @@ -57,9 +59,14 @@ function nlprob_iterator_interface(f, p_range, ::Val{iip}, solver) where {iip} return sols end +export nlprob_iterator_interface, benchmark_nlsolve_oop, benchmark_nlsolve_iip, + TERMINATION_CONDITIONS, _nameof, newton_fails, quadratic_f, quadratic_f!, + __autosparseenzyme +end + # --- NewtonRaphson tests --- -@testcase "NewtonRaphson" begin +@testitem "NewtonRaphson" setup=[CoreRootfindTesting] begin @testset "LineSearch: $(_nameof(lsmethod)) LineSearch AD: $(_nameof(ad))" for lsmethod in (Static(), StrongWolfe(), BackTracking(), HagerZhang(), MoreThuente()), ad in (AutoFiniteDiff(), AutoZygote()) @@ -121,7 +128,7 @@ end # --- TrustRegion tests --- -@testcase "TrustRegion" begin +@testitem "TrustRegion" setup=[CoreRootfindTesting] begin radius_update_schemes = [RadiusUpdateSchemes.Simple, RadiusUpdateSchemes.NocedalWright, RadiusUpdateSchemes.NLsolve, RadiusUpdateSchemes.Hei, RadiusUpdateSchemes.Yuan, RadiusUpdateSchemes.Fan, RadiusUpdateSchemes.Bastin] @@ -233,7 +240,7 @@ end # --- LevenbergMarquardt tests --- -@testcase "LevenbergMarquardt" begin +@testitem "LevenbergMarquardt" setup=[CoreRootfindTesting] begin u0s = ([1.0, 1.0], @SVector[1.0, 1.0], 1.0) @testset "[OOP] u0: $(typeof(u0))" for u0 in u0s sol = benchmark_nlsolve_oop(quadratic_f, u0; solver = LevenbergMarquardt()) @@ -315,7 +322,7 @@ end # --- DFSane tests --- -@testcase "DFSane" begin +@testitem "DFSane" setup=[CoreRootfindTesting] begin u0s = ([1.0, 1.0], @SVector[1.0, 1.0], 1.0) @testset "[OOP] u0: $(typeof(u0))" for u0 in u0s @@ -391,7 +398,7 @@ end # --- PseudoTransient tests --- -@testcase "PseudoTransient" begin +@testitem "PseudoTransient" setup=[CoreRootfindTesting] begin # These are tests for NewtonRaphson so we should set alpha_initial to be high so that we # converge quickly @testset "PT: alpha_initial = 10.0 PT AD: $(ad)" for ad in (AutoFiniteDiff(), @@ -453,7 +460,7 @@ end # --- Broyden tests --- -@testcase "Broyden" begin +@testitem "Broyden" setup=[CoreRootfindTesting] begin @testset "LineSearch: $(_nameof(lsmethod)) LineSearch AD: $(_nameof(ad)) Init Jacobian: $(init_jacobian) Update Rule: $(update_rule)" for lsmethod in (Static(), StrongWolfe(), BackTracking(), HagerZhang(), MoreThuente(), LiFukushimaLineSearch()), @@ -503,7 +510,7 @@ end # --- Klement tests --- -@testcase "Klement" begin +@testitem "Klement" setup=[CoreRootfindTesting] begin @testset "LineSearch: $(_nameof(lsmethod)) LineSearch AD: $(_nameof(ad)) Init Jacobian: $(init_jacobian)" for lsmethod in (Static(), StrongWolfe(), BackTracking(), HagerZhang(), MoreThuente()), ad in (AutoFiniteDiff(), AutoZygote()), @@ -552,7 +559,7 @@ end # --- LimitedMemoryBroyden tests --- -@testcase "LimitedMemoryBroyden" begin +@testitem "LimitedMemoryBroyden" setup=[CoreRootfindTesting] begin @testset "LineSearch: $(_nameof(lsmethod)) LineSearch AD: $(_nameof(ad))" for lsmethod in (Static(), StrongWolfe(), BackTracking(), HagerZhang(), MoreThuente(), LiFukushimaLineSearch()), @@ -602,7 +609,7 @@ end end # Miscellaneous Tests -@testcase "Custom JVP" begin +@testitem "Custom JVP" setup=[CoreRootfindTesting] begin function F(u::Vector{Float64}, p::Vector{Float64}) Δ = Tridiagonal(-ones(99), 2 * ones(100), -ones(99)) return u + 0.1 * u .* Δ * u - p diff --git a/test/gpu/Project.toml b/test/gpu/Project.toml index 6ec065323..5b5241a2e 100644 --- a/test/gpu/Project.toml +++ b/test/gpu/Project.toml @@ -2,5 +2,5 @@ CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" +ReTestItems = "817f1d60-ba6b-4fd5-9520-3cf149f6a823" StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" -XUnit = "3e3c03f2-1a94-11e9-2981-050a4ca824ab" diff --git a/test/gpu/core.jl b/test/gpu/core.jl index bd4c2e4f6..074098072 100644 --- a/test/gpu/core.jl +++ b/test/gpu/core.jl @@ -1,35 +1,38 @@ -using CUDA, NonlinearSolve, LinearSolve, StableRNGs, XUnit +@testitem "CUDA Tests" begin + using CUDA, NonlinearSolve, LinearSolve, StableRNGs -CUDA.allowscalar(false) + CUDA.allowscalar(false) -A = cu(rand(StableRNG(0), 4, 4)) -u0 = cu(rand(StableRNG(0), 4)) -b = cu(rand(StableRNG(0), 4)) + A = cu(rand(StableRNG(0), 4, 4)) + u0 = cu(rand(StableRNG(0), 4)) + b = cu(rand(StableRNG(0), 4)) -linear_f(du, u, p) = (du .= A * u .+ b) + linear_f(du, u, p) = (du .= A * u .+ b) -prob = NonlinearProblem(linear_f, u0) + prob = NonlinearProblem(linear_f, u0) -SOLVERS = (NewtonRaphson(), LevenbergMarquardt(; linsolve = QRFactorization()), - LevenbergMarquardt(; linsolve = KrylovJL_GMRES()), PseudoTransient(), Klement(), - Broyden(; linesearch = LiFukushimaLineSearch()), - LimitedMemoryBroyden(; threshold = 2, linesearch = LiFukushimaLineSearch()), - DFSane(), TrustRegion(; linsolve = QRFactorization()), - TrustRegion(; linsolve = KrylovJL_GMRES(), concrete_jac = true), # Needed if Zygote not loaded - nothing) + SOLVERS = (NewtonRaphson(), LevenbergMarquardt(; linsolve = QRFactorization()), + LevenbergMarquardt(; linsolve = KrylovJL_GMRES()), PseudoTransient(), Klement(), + Broyden(; linesearch = LiFukushimaLineSearch()), + LimitedMemoryBroyden(; threshold = 2, linesearch = LiFukushimaLineSearch()), + DFSane(), TrustRegion(; linsolve = QRFactorization()), + TrustRegion(; linsolve = KrylovJL_GMRES(), + concrete_jac = true), # Needed if Zygote not loaded + nothing) -@testcase "[IIP] GPU Solvers" begin - for alg in SOLVERS - @test_nowarn sol = solve(prob, alg; abstol = 1.0f-5, reltol = 1.0f-5) + @testset "[IIP] GPU Solvers" begin + for alg in SOLVERS + @test_nowarn sol = solve(prob, alg; abstol = 1.0f-5, reltol = 1.0f-5) + end end -end -linear_f(u, p) = A * u .+ b + linear_f(u, p) = A * u .+ b -prob = NonlinearProblem{false}(linear_f, u0) + prob = NonlinearProblem{false}(linear_f, u0) -@testcase "[OOP] GPU Solvers" begin - for alg in SOLVERS - @test_nowarn sol = solve(prob, alg; abstol = 1.0f-5, reltol = 1.0f-5) + @testset "[OOP] GPU Solvers" begin + for alg in SOLVERS + @test_nowarn sol = solve(prob, alg; abstol = 1.0f-5, reltol = 1.0f-5) + end end end diff --git a/test/misc/banded_matrices.jl b/test/misc/banded_matrices.jl deleted file mode 100644 index ff5951089..000000000 --- a/test/misc/banded_matrices.jl +++ /dev/null @@ -1,9 +0,0 @@ -# Miscellaneous Tests -using BandedMatrices, LinearAlgebra, NonlinearSolve, SparseArrays, XUnit - -b = BandedMatrix(Ones(5, 5), (1, 1)) -d = Diagonal(ones(5, 5)) - -@testcase "BandedMatrix vcat" begin - @test NonlinearSolve._vcat(b, d) == vcat(sparse(b), d) -end diff --git a/test/misc/banded_matrices_tests.jl b/test/misc/banded_matrices_tests.jl new file mode 100644 index 000000000..d4b8fbee5 --- /dev/null +++ b/test/misc/banded_matrices_tests.jl @@ -0,0 +1,8 @@ +@testitem "Banded Matrix vcat" begin + using BandedMatrices, LinearAlgebra, SparseArrays + + b = BandedMatrix(Ones(5, 5), (1, 1)) + d = Diagonal(ones(5, 5)) + + @test NonlinearSolve._vcat(b, d) == vcat(sparse(b), d) +end diff --git a/test/misc/bruss.jl b/test/misc/bruss.jl deleted file mode 100644 index 25dd3b026..000000000 --- a/test/misc/bruss.jl +++ /dev/null @@ -1,76 +0,0 @@ -using NonlinearSolve, LinearAlgebra, SparseArrays, Symbolics, XUnit - -const N = 32 -const xyd_brusselator = range(0, stop = 1, length = N) - -brusselator_f(x, y) = (((x - 0.3)^2 + (y - 0.6)^2) <= 0.1^2) * 5.0 -limit(a, N) = a == N + 1 ? 1 : a == 0 ? N : a - -function brusselator_2d_loop(du, u, p) - A, B, alpha, dx = p - alpha = alpha / dx^2 - @inbounds for I in CartesianIndices((N, N)) - i, j = Tuple(I) - x, y = xyd_brusselator[I[1]], xyd_brusselator[I[2]] - ip1, im1, jp1, jm1 = limit(i + 1, N), limit(i - 1, N), limit(j + 1, N), - limit(j - 1, N) - du[i, j, 1] = alpha * (u[im1, j, 1] + u[ip1, j, 1] + u[i, jp1, 1] + u[i, jm1, 1] - - 4u[i, j, 1]) + - B + u[i, j, 1]^2 * u[i, j, 2] - (A + 1) * u[i, j, 1] + - brusselator_f(x, y) - du[i, j, 2] = alpha * (u[im1, j, 2] + u[ip1, j, 2] + u[i, jp1, 2] + u[i, jm1, 2] - - 4u[i, j, 2]) + - A * u[i, j, 1] - u[i, j, 1]^2 * u[i, j, 2] - end -end - -p = (3.4, 1.0, 10.0, step(xyd_brusselator)) - -function init_brusselator_2d(xyd) - N = length(xyd) - u = zeros(N, N, 2) - for I in CartesianIndices((N, N)) - x = xyd[I[1]] - y = xyd[I[2]] - u[I, 1] = 22 * (y * (1 - y))^(3 / 2) - u[I, 2] = 27 * (x * (1 - x))^(3 / 2) - end - return u -end - -@testcase "Brusselator" begin - u0 = init_brusselator_2d(xyd_brusselator) - prob_brusselator_2d = NonlinearProblem(brusselator_2d_loop, u0, p) - sol = solve(prob_brusselator_2d, NewtonRaphson(); abstol = 1e-8) - @test norm(sol.resid, Inf) < 1e-8 - - sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseForwardDiff()); - abstol = 1e-8) - @test norm(sol.resid, Inf) < 1e-8 - - sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseFiniteDiff()); - abstol = 1e-8) - @test norm(sol.resid, Inf) < 1e-8 - - du0 = copy(u0) - jac_sparsity = Symbolics.jacobian_sparsity((du, u) -> brusselator_2d_loop(du, u, p), - du0, u0) - jac_prototype = float.(jac_sparsity) - fill!(jac_prototype, 0) - @test all(iszero, jac_prototype) - - ff_iip = NonlinearFunction(brusselator_2d_loop; jac_prototype) - prob_brusselator_2d = NonlinearProblem(ff_iip, u0, p) - - sol = solve(prob_brusselator_2d, NewtonRaphson(); abstol = 1e-8) - @test norm(sol.resid, Inf) < 1e-8 - @test !all(iszero, jac_prototype) - - sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseFiniteDiff()); - abstol = 1e-8) - @test norm(sol.resid, Inf) < 1e-8 - - cache = init(prob_brusselator_2d, NewtonRaphson(; autodiff = AutoSparseForwardDiff())) - @test maximum(cache.jac_cache.jac_cache.coloring.colorvec) == 12 - @test cache.jac_cache.autodiff isa AutoSparseForwardDiff -end diff --git a/test/misc/bruss_tests.jl b/test/misc/bruss_tests.jl new file mode 100644 index 000000000..a1fcd6761 --- /dev/null +++ b/test/misc/bruss_tests.jl @@ -0,0 +1,78 @@ +@testitem "Brusselator 2D" begin + using LinearAlgebra, SparseArrays, Symbolics + + const N = 32 + const xyd_brusselator = range(0, stop = 1, length = N) + + brusselator_f(x, y) = (((x - 0.3)^2 + (y - 0.6)^2) <= 0.1^2) * 5.0 + limit(a, N) = a == N + 1 ? 1 : a == 0 ? N : a + + function brusselator_2d_loop(du, u, p) + A, B, alpha, dx = p + alpha = alpha / dx^2 + @inbounds for I in CartesianIndices((N, N)) + i, j = Tuple(I) + x, y = xyd_brusselator[I[1]], xyd_brusselator[I[2]] + ip1, im1, jp1, jm1 = limit(i + 1, N), limit(i - 1, N), limit(j + 1, N), + limit(j - 1, N) + du[i, j, 1] = alpha * + (u[im1, j, 1] + u[ip1, j, 1] + u[i, jp1, 1] + u[i, jm1, 1] - + 4u[i, j, 1]) + + B + u[i, j, 1]^2 * u[i, j, 2] - (A + 1) * u[i, j, 1] + + brusselator_f(x, y) + du[i, j, 2] = alpha * + (u[im1, j, 2] + u[ip1, j, 2] + u[i, jp1, 2] + u[i, jm1, 2] - + 4u[i, j, 2]) + + A * u[i, j, 1] - u[i, j, 1]^2 * u[i, j, 2] + end + end + + p = (3.4, 1.0, 10.0, step(xyd_brusselator)) + + function init_brusselator_2d(xyd) + N = length(xyd) + u = zeros(N, N, 2) + for I in CartesianIndices((N, N)) + x = xyd[I[1]] + y = xyd[I[2]] + u[I, 1] = 22 * (y * (1 - y))^(3 / 2) + u[I, 2] = 27 * (x * (1 - x))^(3 / 2) + end + return u + end + + u0 = init_brusselator_2d(xyd_brusselator) + prob_brusselator_2d = NonlinearProblem(brusselator_2d_loop, u0, p) + sol = solve(prob_brusselator_2d, NewtonRaphson(); abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-8 + + sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseForwardDiff()); + abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-8 + + sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseFiniteDiff()); + abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-8 + + du0 = copy(u0) + jac_sparsity = Symbolics.jacobian_sparsity((du, u) -> brusselator_2d_loop(du, u, p), + du0, u0) + jac_prototype = float.(jac_sparsity) + fill!(jac_prototype, 0) + @test all(iszero, jac_prototype) + + ff_iip = NonlinearFunction(brusselator_2d_loop; jac_prototype) + prob_brusselator_2d = NonlinearProblem(ff_iip, u0, p) + + sol = solve(prob_brusselator_2d, NewtonRaphson(); abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-8 + @test !all(iszero, jac_prototype) + + sol = solve(prob_brusselator_2d, NewtonRaphson(autodiff = AutoSparseFiniteDiff()); + abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-8 + + cache = init(prob_brusselator_2d, NewtonRaphson(; autodiff = AutoSparseForwardDiff())) + @test maximum(cache.jac_cache.jac_cache.coloring.colorvec) == 12 + @test cache.jac_cache.autodiff isa AutoSparseForwardDiff +end diff --git a/test/misc/matrix_resizing.jl b/test/misc/matrix_resizing.jl deleted file mode 100644 index 49e07d245..000000000 --- a/test/misc/matrix_resizing.jl +++ /dev/null @@ -1,25 +0,0 @@ -using NonlinearSolve, XUnit, StableRNGs - -ff(u, p) = u .* u .- p -u0 = rand(StableRNG(0), 2, 2) -p = 2.0 -vecprob = NonlinearProblem(ff, vec(u0), p) -prob = NonlinearProblem(ff, u0, p) - -@testcase "$(alg)" for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), - PseudoTransient(), RobustMultiNewton(), FastShortcutNonlinearPolyalg(), Broyden(), - Klement(), LimitedMemoryBroyden(; threshold = 2)) - @test vec(solve(prob, alg).u) == solve(vecprob, alg).u -end - -fiip(du, u, p) = (du .= u .* u .- p) -u0 = rand(StableRNG(0), 2, 2) -p = 2.0 -vecprob = NonlinearProblem(fiip, vec(u0), p) -prob = NonlinearProblem(fiip, u0, p) - -@testcase "$(alg)" for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), - PseudoTransient(), RobustMultiNewton(), FastShortcutNonlinearPolyalg(), Broyden(), - Klement(), LimitedMemoryBroyden(; threshold = 2)) - @test vec(solve(prob, alg).u) == solve(vecprob, alg).u -end diff --git a/test/misc/matrix_resizing_tests.jl b/test/misc/matrix_resizing_tests.jl new file mode 100644 index 000000000..e13704c96 --- /dev/null +++ b/test/misc/matrix_resizing_tests.jl @@ -0,0 +1,31 @@ +@testitem "Out-of-place Matrix Resizing" begin + using StableRNGs + + ff(u, p) = u .* u .- p + u0 = rand(StableRNG(0), 2, 2) + p = 2.0 + vecprob = NonlinearProblem(ff, vec(u0), p) + prob = NonlinearProblem(ff, u0, p) + + for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), + PseudoTransient(), RobustMultiNewton(), FastShortcutNonlinearPolyalg(), Broyden(), + Klement(), LimitedMemoryBroyden(; threshold = 2)) + @test vec(solve(prob, alg).u) == solve(vecprob, alg).u + end +end + +@testitem "Inplace Matrix Resizing" begin + using StableRNGs + + fiip(du, u, p) = (du .= u .* u .- p) + u0 = rand(StableRNG(0), 2, 2) + p = 2.0 + vecprob = NonlinearProblem(fiip, vec(u0), p) + prob = NonlinearProblem(fiip, u0, p) + + for alg in (NewtonRaphson(), TrustRegion(), LevenbergMarquardt(), + PseudoTransient(), RobustMultiNewton(), FastShortcutNonlinearPolyalg(), Broyden(), + Klement(), LimitedMemoryBroyden(; threshold = 2)) + @test vec(solve(prob, alg).u) == solve(vecprob, alg).u + end +end diff --git a/test/misc/polyalgs.jl b/test/misc/polyalg_tests.jl similarity index 76% rename from test/misc/polyalgs.jl rename to test/misc/polyalg_tests.jl index 13cd8ecd4..761270c9a 100644 --- a/test/misc/polyalgs.jl +++ b/test/misc/polyalg_tests.jl @@ -1,6 +1,4 @@ -using NonlinearSolve, XUnit, NaNMath, OrdinaryDiffEq, StaticArrays, LinearAlgebra - -@testcase "Basic PolyAlgorithms" begin +@testitem "Basic PolyAlgorithms" begin f(u, p) = u .* u .- 2 u0 = [1.0, 1.0] probN = NonlinearProblem{false}(f, u0) @@ -32,7 +30,7 @@ using NonlinearSolve, XUnit, NaNMath, OrdinaryDiffEq, StaticArrays, LinearAlgebr @test SciMLBase.successful_retcode(solver) end -@testcase "Testing #153 Singular Exception" begin +@testitem "Testing #153 Singular Exception" begin # https://github.com/SciML/NonlinearSolve.jl/issues/153 function f(du, u, p) s1, s1s2, s2 = u @@ -48,7 +46,9 @@ end @test SciMLBase.successful_retcode(sol) end -@testcase "Simple Scalar Problem #187" begin +@testitem "Simple Scalar Problem #187" begin + using NaNMath + # https://github.com/SciML/NonlinearSolve.jl/issues/187 # If we use a General Nonlinear Solver the solution might go out of the domain! ff_interval(u, p) = 0.5 / 1.5 * NaNMath.log.(u ./ (1.0 .- u)) .- 2.0 * u .+ 1.0 @@ -68,7 +68,9 @@ end # Shooting Problem: Taken from BoundaryValueDiffEq.jl # Testing for Complex Valued Root Finding. For Complex valued inputs we drop some of the # algorithms which dont support those. -@testcase "Complex Valued Problems: Single-Shooting" begin +@testitem "Complex Valued Problems: Single-Shooting" begin + using OrdinaryDiffEq + function ode_func!(du, u, p, t) du[1] = u[2] du[2] = -u[1] @@ -93,31 +95,37 @@ end maxiters = 10) end -no_ad_fast = FastShortcutNonlinearPolyalg(autodiff = AutoFiniteDiff()) -no_ad_robust = RobustMultiNewton(autodiff = AutoFiniteDiff()) -no_ad_algs = Set([no_ad_fast, no_ad_robust, no_ad_fast.algs..., no_ad_robust.algs...]) -@testcase "[IIP] no AD" begin - f_iip = Base.Experimental.@opaque (du, u, p) -> du .= u .* u .- p - u0 = [0.5] - prob = NonlinearProblem(f_iip, u0, 1.0) - for alg in no_ad_algs - sol = solve(prob, alg) - @test isapprox(only(sol.u), 1.0) - @test SciMLBase.successful_retcode(sol.retcode) +@testitem "No AD" begin + no_ad_fast = FastShortcutNonlinearPolyalg(autodiff = AutoFiniteDiff()) + no_ad_robust = RobustMultiNewton(autodiff = AutoFiniteDiff()) + no_ad_algs = Set([no_ad_fast, no_ad_robust, no_ad_fast.algs..., no_ad_robust.algs...]) + + @testset "Inplace" begin + f_iip = Base.Experimental.@opaque (du, u, p) -> du .= u .* u .- p + u0 = [0.5] + prob = NonlinearProblem(f_iip, u0, 1.0) + for alg in no_ad_algs + sol = solve(prob, alg) + @test isapprox(only(sol.u), 1.0) + @test SciMLBase.successful_retcode(sol.retcode) + end end -end -@testcase "[OOP] no AD" begin - f_oop = Base.Experimental.@opaque (u, p) -> u .* u .- p - u0 = [0.5] - prob = NonlinearProblem{false}(f_oop, u0, 1.0) - for alg in no_ad_algs - sol = solve(prob, alg) - @test isapprox(only(sol.u), 1.0) - @test SciMLBase.successful_retcode(sol.retcode) + @testset "Out of Place" begin + f_oop = Base.Experimental.@opaque (u, p) -> u .* u .- p + u0 = [0.5] + prob = NonlinearProblem{false}(f_oop, u0, 1.0) + for alg in no_ad_algs + sol = solve(prob, alg) + @test isapprox(only(sol.u), 1.0) + @test SciMLBase.successful_retcode(sol.retcode) + end end end +@testsetup module InfeasibleFunction +using LinearAlgebra, StaticArrays + # this is infeasible function f1_infeasible!(out, u, p) μ = 3.986004415e14 @@ -157,7 +165,10 @@ function f1_infeasible(u, p) return [a - 42.0e6, e - 1e-5, i - 1e-5] end -@testcase "[IIP] Infeasible" begin +export f1_infeasible!, f1_infeasible +end + +@testitem "[IIP] Infeasible" setup=[InfeasibleFunction] begin u0 = [0.0, 0.0, 0.0] prob = NonlinearProblem(f1_infeasible!, u0) sol = solve(prob) @@ -166,7 +177,9 @@ end @test !SciMLBase.successful_retcode(sol.retcode) end -@testcase "[OOP] Infeasible" begin +@testitem "[OOP] Infeasible" setup=[InfeasibleFunction] begin + using StaticArrays + u0 = [0.0, 0.0, 0.0] prob = NonlinearProblem(f1_infeasible, u0) sol = solve(prob) diff --git a/test/misc/qa.jl b/test/misc/qa_tests.jl similarity index 90% rename from test/misc/qa.jl rename to test/misc/qa_tests.jl index 9cfbe2421..e182ac22f 100644 --- a/test/misc/qa.jl +++ b/test/misc/qa_tests.jl @@ -1,6 +1,6 @@ -using NonlinearSolve, Aqua, XUnit +@testitem "Aqua" begin + using NonlinearSolve, Aqua -@testcase "Aqua" begin Aqua.find_persistent_tasks_deps(NonlinearSolve) Aqua.test_ambiguities(NonlinearSolve; recursive = false) Aqua.test_deps_compat(NonlinearSolve) diff --git a/test/runtests.jl b/test/runtests.jl index 7777a0e30..378fd0cf7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,4 @@ -using Pkg, SafeTestsets, XUnit +using Pkg, ReTestItems const GROUP = get(ENV, "GROUP", "All") @@ -8,24 +8,13 @@ function activate_env(env) Pkg.instantiate() end -@testset runner=ParallelTestRunner() "NonlinearSolve.jl" begin - if GROUP == "All" || GROUP == "Core" - @safetestset "Basic Root Finding Tests" include("core/rootfind.jl") - @safetestset "Forward AD" include("core/forward_ad.jl") - @safetestset "Basic NLLS Solvers" include("core/nlls.jl") - @safetestset "Fixed Point Solvers" include("wrappers/fixedpoint.jl") - @safetestset "Root Finding Solvers" include("wrappers/rootfind.jl") - @safetestset "Nonlinear Least Squares Solvers" include("wrappers/nlls.jl") - @safetestset "23 Test Problems" include("core/23_test_problems.jl") - @safetestset "Quality Assurance" include("misc/qa.jl") - @safetestset "Sparsity Tests" include("misc/bruss.jl") - @safetestset "Polyalgs" include("misc/polyalgs.jl") - @safetestset "Matrix Resizing" include("misc/matrix_resizing.jl") - @safetestset "Banded Matrices" include("misc/banded_matrices.jl") - end +if GROUP == "All" || GROUP == "Core" + ReTestItems.runtests(joinpath(@__DIR__, "core/"), + joinpath(@__DIR__, "misc/"), + joinpath(@__DIR__, "wrappers/")) +end - if GROUP == "GPU" - activate_env("gpu") - @safetestset "GPU Tests" include("gpu/core.jl") - end +if GROUP == "GPU" + activate_env("gpu") + ReTestItems.runtests(joinpath(@__DIR__, "gpu/")) end diff --git a/test/wrappers/fixedpoint.jl b/test/wrappers/fixedpoint_tests.jl similarity index 92% rename from test/wrappers/fixedpoint.jl rename to test/wrappers/fixedpoint_tests.jl index 52ca1963d..3d5713844 100644 --- a/test/wrappers/fixedpoint.jl +++ b/test/wrappers/fixedpoint_tests.jl @@ -1,8 +1,11 @@ -using NonlinearSolve, LinearAlgebra, XUnit +@testsetup module WrapperFixedPointImports +using Reexport +@reexport using LinearAlgebra import SIAMFANLEquations, FixedPointAcceleration, SpeedMapping, NLsolve +end # Simple Scalar Problem -@testcase "Simple Scalar Problem" begin +@testitem "Simple Scalar Problem" setup=[WrapperFixedPointImports] begin f1(x, p) = cos(x) - x prob = NonlinearProblem(f1, 1.1) @@ -19,7 +22,7 @@ import SIAMFANLEquations, FixedPointAcceleration, SpeedMapping, NLsolve end # Simple Vector Problem -@testcase "Simple Vector Problem" begin +@testitem "Simple Vector Problem" setup=[WrapperFixedPointImports] begin f2(x, p) = cos.(x) .- x prob = NonlinearProblem(f2, [1.1, 1.1]) @@ -38,7 +41,7 @@ end # Fixed Point for Power Method # Taken from https://github.com/NicolasL-S/SpeedMapping.jl/blob/95951db8f8a4457093090e18802ad382db1c76da/test/runtests.jl -@testcase "Power Method" begin +@testitem "Power Method" setup=[WrapperFixedPointImports] begin C = [1 2 3; 4 5 6; 7 8 9] A = C + C' B = Hermitian(ones(10) * ones(10)' .* im + Diagonal(1:10)) diff --git a/test/wrappers/nlls.jl b/test/wrappers/nlls.jl deleted file mode 100644 index fed44ac6f..000000000 --- a/test/wrappers/nlls.jl +++ /dev/null @@ -1,105 +0,0 @@ -using NonlinearSolve, - LinearAlgebra, XUnit, StableRNGs, StaticArrays, Random, ForwardDiff, Zygote -import FastLevenbergMarquardt, LeastSquaresOptim, MINPACK - -true_function(x, θ) = @. θ[1] * exp(θ[2] * x) * cos(θ[3] * x + θ[4]) -true_function(y, x, θ) = (@. y = θ[1] * exp(θ[2] * x) * cos(θ[3] * x + θ[4])) - -θ_true = [1.0, 0.1, 2.0, 0.5] - -x = [-1.0, -0.5, 0.0, 0.5, 1.0] - -const y_target = true_function(x, θ_true) - -function loss_function(θ, p) - ŷ = true_function(p, θ) - return ŷ .- y_target -end - -function loss_function(resid, θ, p) - true_function(resid, p, θ) - resid .= resid .- y_target - return resid -end - -θ_init = θ_true .+ randn!(StableRNG(0), similar(θ_true)) * 0.1 -prob_oop = NonlinearLeastSquaresProblem{false}(loss_function, θ_init, x) -prob_iip = NonlinearLeastSquaresProblem(NonlinearFunction(loss_function; - resid_prototype = zero(y_target)), θ_init, x) - -nlls_problems = [prob_oop, prob_iip] - -solvers = [LeastSquaresOptimJL(alg; autodiff) for alg in (:lm, :dogleg), -autodiff in (nothing, AutoForwardDiff(), AutoFiniteDiff(), :central, :forward)] - -@testcase "LeastSquaresOptim.jl" begin - for prob in nlls_problems, solver in solvers - sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) - @test SciMLBase.successful_retcode(sol) - @test norm(sol.resid, Inf) < 1e-6 - end -end - -function jac!(J, θ, p) - resid = zeros(length(p)) - ForwardDiff.jacobian!(J, (resid, θ) -> loss_function(resid, θ, p), resid, θ) - return J -end - -jac(θ, p) = ForwardDiff.jacobian(θ -> loss_function(θ, p), θ) - -probs = [ - NonlinearLeastSquaresProblem(NonlinearFunction{true}(loss_function; - resid_prototype = zero(y_target), jac = jac!), θ_init, x), - NonlinearLeastSquaresProblem(NonlinearFunction{false}(loss_function; - resid_prototype = zero(y_target), jac = jac), θ_init, x), - NonlinearLeastSquaresProblem(NonlinearFunction{false}(loss_function; jac), θ_init, x), -] - -solvers = Any[FastLevenbergMarquardtJL(linsolve) for linsolve in (:cholesky, :qr)] -push!(solvers, CMINPACK()) - -@testcase "FastLevenbergMarquardt.jl + CMINPACK: Jacobian Provided" begin - for solver in solvers, prob in probs - sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) - @test maximum(abs, sol.resid) < 1e-6 - end -end - -probs = [ - NonlinearLeastSquaresProblem(NonlinearFunction{true}(loss_function; - resid_prototype = zero(y_target)), θ_init, x), - NonlinearLeastSquaresProblem(NonlinearFunction{false}(loss_function; - resid_prototype = zero(y_target)), θ_init, x), - NonlinearLeastSquaresProblem(NonlinearFunction{false}(loss_function), θ_init, x), -] - -solvers = vec(Any[FastLevenbergMarquardtJL(linsolve; autodiff) - for linsolve in (:cholesky, :qr), -autodiff in (nothing, AutoForwardDiff(), AutoFiniteDiff())]) -append!(solvers, [CMINPACK(; method) for method in (:auto, :lm, :lmdif)]) - -@testcase "FastLevenbergMarquardt.jl + CMINPACK: Jacobian Not Provided" begin - for solver in solvers, prob in probs - sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) - @test norm(sol.resid, Inf) < 1e-6 - end -end - -# Static Arrays -- Fast Levenberg-Marquardt -x_sa = SA[-1.0, -0.5, 0.0, 0.5, 1.0] - -const y_target_sa = true_function(x_sa, θ_true) - -function loss_function_sa(θ, p) - ŷ = true_function(p, θ) - return ŷ .- y_target_sa -end - -θ_init_sa = SVector{4}(θ_init) -prob_sa = NonlinearLeastSquaresProblem{false}(loss_function_sa, θ_init_sa, x) - -@testcase "FastLevenbergMarquardt.jl + StaticArrays" begin - sol = solve(prob_sa, FastLevenbergMarquardtJL()) - @test norm(sol.resid, Inf) < 1e-6 -end diff --git a/test/wrappers/nlls_tests.jl b/test/wrappers/nlls_tests.jl new file mode 100644 index 000000000..fbcf3cf84 --- /dev/null +++ b/test/wrappers/nlls_tests.jl @@ -0,0 +1,111 @@ +@testsetup module WrapperNLLSSetup +using Reexport +@reexport using LinearAlgebra, StableRNGs, StaticArrays, Random, ForwardDiff, Zygote +import FastLevenbergMarquardt, LeastSquaresOptim, MINPACK + +true_function(x, θ) = @. θ[1] * exp(θ[2] * x) * cos(θ[3] * x + θ[4]) +true_function(y, x, θ) = (@. y = θ[1] * exp(θ[2] * x) * cos(θ[3] * x + θ[4])) + +θ_true = [1.0, 0.1, 2.0, 0.5] + +x = [-1.0, -0.5, 0.0, 0.5, 1.0] + +const y_target = true_function(x, θ_true) + +function loss_function(θ, p) + ŷ = true_function(p, θ) + return ŷ .- y_target +end + +function loss_function(resid, θ, p) + true_function(resid, p, θ) + resid .= resid .- y_target + return resid +end + +θ_init = θ_true .+ randn!(StableRNG(0), similar(θ_true)) * 0.1 + +export loss_function, θ_init, y_target, true_function, x, θ_true +end + +@testitem "LeastSquaresOptim.jl" setup=[WrapperNLLSSetup] begin + prob_oop = NonlinearLeastSquaresProblem{false}(loss_function, θ_init, x) + prob_iip = NonlinearLeastSquaresProblem(NonlinearFunction(loss_function; + resid_prototype = zero(y_target)), θ_init, x) + + nlls_problems = [prob_oop, prob_iip] + + solvers = [LeastSquaresOptimJL(alg; autodiff) for alg in (:lm, :dogleg), + autodiff in (nothing, AutoForwardDiff(), AutoFiniteDiff(), :central, :forward)] + + for prob in nlls_problems, solver in solvers + sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) + @test SciMLBase.successful_retcode(sol) + @test norm(sol.resid, Inf) < 1e-6 + end +end + +@testitem "FastLevenbergMarquardt.jl + CMINPACK: Jacobian Provided" setup=[ + WrapperNLLSSetup] begin + function jac!(J, θ, p) + resid = zeros(length(p)) + ForwardDiff.jacobian!(J, (resid, θ) -> loss_function(resid, θ, p), resid, θ) + return J + end + + jac(θ, p) = ForwardDiff.jacobian(θ -> loss_function(θ, p), θ) + + probs = [ + NonlinearLeastSquaresProblem(NonlinearFunction{true}(loss_function; + resid_prototype = zero(y_target), jac = jac!), θ_init, x), + NonlinearLeastSquaresProblem(NonlinearFunction{false}(loss_function; + resid_prototype = zero(y_target), jac = jac), θ_init, x), + NonlinearLeastSquaresProblem(NonlinearFunction{false}(loss_function; jac), + θ_init, x), + ] + + solvers = Any[FastLevenbergMarquardtJL(linsolve) for linsolve in (:cholesky, :qr)] + push!(solvers, CMINPACK()) + for solver in solvers, prob in probs + sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) + @test maximum(abs, sol.resid) < 1e-6 + end +end + +@testitem "FastLevenbergMarquardt.jl + CMINPACK: Jacobian Not Provided" setup=[ + WrapperNLLSSetup] begin + probs = [ + NonlinearLeastSquaresProblem(NonlinearFunction{true}(loss_function; + resid_prototype = zero(y_target)), θ_init, x), + NonlinearLeastSquaresProblem(NonlinearFunction{false}(loss_function; + resid_prototype = zero(y_target)), θ_init, x), + NonlinearLeastSquaresProblem(NonlinearFunction{false}(loss_function), θ_init, x), + ] + + solvers = vec(Any[FastLevenbergMarquardtJL(linsolve; autodiff) + for linsolve in (:cholesky, :qr), + autodiff in (nothing, AutoForwardDiff(), AutoFiniteDiff())]) + append!(solvers, [CMINPACK(; method) for method in (:auto, :lm, :lmdif)]) + + for solver in solvers, prob in probs + sol = solve(prob, solver; maxiters = 10000, abstol = 1e-8) + @test norm(sol.resid, Inf) < 1e-6 + end +end + +@testitem "FastLevenbergMarquardt.jl + StaticArrays" setup=[WrapperNLLSSetup] begin + x_sa = SA[-1.0, -0.5, 0.0, 0.5, 1.0] + + const y_target_sa = true_function(x_sa, θ_true) + + function loss_function_sa(θ, p) + ŷ = true_function(p, θ) + return ŷ .- y_target_sa + end + + θ_init_sa = SVector{4}(θ_init) + prob_sa = NonlinearLeastSquaresProblem{false}(loss_function_sa, θ_init_sa, x) + + sol = solve(prob_sa, FastLevenbergMarquardtJL()) + @test norm(sol.resid, Inf) < 1e-6 +end diff --git a/test/wrappers/rootfind.jl b/test/wrappers/rootfind_tests.jl similarity index 92% rename from test/wrappers/rootfind.jl rename to test/wrappers/rootfind_tests.jl index 5600dbc56..889fa8b57 100644 --- a/test/wrappers/rootfind.jl +++ b/test/wrappers/rootfind_tests.jl @@ -1,7 +1,9 @@ -using NonlinearSolve, LinearAlgebra, SciMLBase, XUnit -import NLsolve, SIAMFANLEquations, MINPACK +@testsetup module WrapperRootfindImports +using Reexport +@reexport using LinearAlgebra, NLsolve, SIAMFANLEquations, MINPACK +end -@testcase "Steady State Problems" begin +@testitem "Steady State Problems" setup=[WrapperRootfindImports] begin # IIP Tests function f_iip(du, u, p, t) du[1] = 2 - 2u[1] @@ -28,7 +30,7 @@ import NLsolve, SIAMFANLEquations, MINPACK end end -@testcase "Nonlinear Root Finding Problems" begin +@testitem "Nonlinear Root Finding Problems" setup=[WrapperRootfindImports] begin # IIP Tests function f_iip(du, u, p) du[1] = 2 - 2u[1] From 49ca687980825ab81a4047618fb9b7eda1289c50 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Thu, 8 Feb 2024 22:33:16 -0500 Subject: [PATCH 3/3] Add codecov token --- .buildkite/pipeline.yml | 6 ++++-- .github/workflows/CI.yml | 5 ++++- .github/workflows/Downgrade.yml | 13 ++++++++----- Project.toml | 4 +++- test/core/23_test_problems_tests.jl | 4 ++-- test/gpu/Project.toml | 6 ------ test/gpu/{core.jl => core_tests.jl} | 0 test/runtests.jl | 9 +-------- 8 files changed, 22 insertions(+), 25 deletions(-) delete mode 100644 test/gpu/Project.toml rename test/gpu/{core.jl => core_tests.jl} (100%) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 52ebdda7a..5fa49569e 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -4,7 +4,7 @@ steps: - JuliaCI/julia#v1: version: "1" - JuliaCI/julia-test#v1: - coverage: true + coverage: true agents: queue: "juliagpu" cuda: "*" @@ -15,4 +15,6 @@ steps: env: GROUP: GPU JULIA_PKG_SERVER: "" # it often struggles with our large artifacts - SECRET_CODECOV_TOKEN: "HC7K/ymhi62KUQ5OLU4DOl+11gaQt4JhXX/2nfTGlTsBB8mEMxQ8R+sHIp/2HjEup5eSXAN2IWQDQ7RDBuQvVp0T1UVtr2e4YNZFztKnsJXrFO15hXxYShJodI//X/8DzhlQd/lyTDOAOJu3eznsc3sC2CUgJzXZxLUtQN9YaZ1i3a+NoN1mO5UpkkHVhXigwF5gjy+0tei8fCdcP+SIhG0EanS5yd9q/SurtCpMHsHyUG97+ZVPglSKgdaqr31+PdmiPJ+ynp4+Hnc/esosxUSHSIL+ryRTO+28RNwPTiNf99J51RJLQmz1knWTR1ky6tiYIZ5218O6wvNil0SqNw==;U2FsdGVkX18nBY3t4LZYlEIz3EVKjpqCd994JNeJGt006up+sAjXEssI0tgCVXnfXsenVsP3NCCEoOS1GXc44g==" \ No newline at end of file + RETESTITEMS_NWORKERS: 4 + RETESTITEMS_NWORKER_THREADS: 2 + SECRET_CODECOV_TOKEN: "HC7K/ymhi62KUQ5OLU4DOl+11gaQt4JhXX/2nfTGlTsBB8mEMxQ8R+sHIp/2HjEup5eSXAN2IWQDQ7RDBuQvVp0T1UVtr2e4YNZFztKnsJXrFO15hXxYShJodI//X/8DzhlQd/lyTDOAOJu3eznsc3sC2CUgJzXZxLUtQN9YaZ1i3a+NoN1mO5UpkkHVhXigwF5gjy+0tei8fCdcP+SIhG0EanS5yd9q/SurtCpMHsHyUG97+ZVPglSKgdaqr31+PdmiPJ+ynp4+Hnc/esosxUSHSIL+ryRTO+28RNwPTiNf99J51RJLQmz1knWTR1ky6tiYIZ5218O6wvNil0SqNw==;U2FsdGVkX18nBY3t4LZYlEIz3EVKjpqCd994JNeJGt006up+sAjXEssI0tgCVXnfXsenVsP3NCCEoOS1GXc44g==" diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6f59b6b2b..3fde89bb4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -20,7 +20,7 @@ jobs: group: - Core version: - - '1' + - "1" os: - ubuntu-latest - macos-latest @@ -53,3 +53,6 @@ jobs: - uses: codecov/codecov-action@v4 with: file: lcov.info + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true + fail_ci_if_error: true diff --git a/.github/workflows/Downgrade.yml b/.github/workflows/Downgrade.yml index 01ff8cad5..8e5efd609 100644 --- a/.github/workflows/Downgrade.yml +++ b/.github/workflows/Downgrade.yml @@ -4,26 +4,29 @@ on: branches: - master paths-ignore: - - 'docs/**' + - "docs/**" push: branches: - master paths-ignore: - - 'docs/**' + - "docs/**" jobs: test: runs-on: ubuntu-latest strategy: matrix: - version: ['1'] + version: ["1"] steps: - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v1 with: version: ${{ matrix.version }} - uses: cjdoris/julia-downgrade-compat-action@v1 -# if: ${{ matrix.version == '1.6' }} with: skip: Pkg,TOML - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-runtest@v1 \ No newline at end of file + - uses: julia-actions/julia-runtest@v1 + env: + JULIA_NUM_THREADS: 11 + RETESTITEMS_NWORKERS: 4 + RETESTITEMS_NWORKER_THREADS: 2 diff --git a/Project.toml b/Project.toml index ff61a9212..9afd3d558 100644 --- a/Project.toml +++ b/Project.toml @@ -60,6 +60,7 @@ ArrayInterface = "7.7" BandedMatrices = "1.4" BenchmarkTools = "1.4" ConcreteStructs = "0.2.3" +CUDA = "5.1" DiffEqBase = "6.146.0" Enzyme = "0.11.11" FastBroadcast = "0.2.8" @@ -108,6 +109,7 @@ julia = "1.10" Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" BandedMatrices = "aae01518-5342-5314-be14-df237901396f" BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" +CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" FastLevenbergMarquardt = "7a0df574-e128-4d35-8cbd-3d84502bf7ce" @@ -137,4 +139,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [targets] -test = ["Aqua", "Enzyme", "BenchmarkTools", "SafeTestsets", "Pkg", "Test", "ForwardDiff", "StaticArrays", "Symbolics", "LinearSolve", "Random", "LinearAlgebra", "Zygote", "SparseDiffTools", "NonlinearProblemLibrary", "LeastSquaresOptim", "FastLevenbergMarquardt", "NaNMath", "BandedMatrices", "DiffEqBase", "StableRNGs", "MINPACK", "NLsolve", "OrdinaryDiffEq", "SpeedMapping", "FixedPointAcceleration", "SIAMFANLEquations", "Sundials", "ReTestItems", "Reexport"] +test = ["Aqua", "Enzyme", "BenchmarkTools", "SafeTestsets", "Pkg", "Test", "ForwardDiff", "StaticArrays", "Symbolics", "LinearSolve", "Random", "LinearAlgebra", "Zygote", "SparseDiffTools", "NonlinearProblemLibrary", "LeastSquaresOptim", "FastLevenbergMarquardt", "NaNMath", "BandedMatrices", "DiffEqBase", "StableRNGs", "MINPACK", "NLsolve", "OrdinaryDiffEq", "SpeedMapping", "FixedPointAcceleration", "SIAMFANLEquations", "Sundials", "ReTestItems", "Reexport", "CUDA"] diff --git a/test/core/23_test_problems_tests.jl b/test/core/23_test_problems_tests.jl index cf6fa129f..43a361958 100644 --- a/test/core/23_test_problems_tests.jl +++ b/test/core/23_test_problems_tests.jl @@ -92,7 +92,7 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testitem "Broyden" setup=[RobustnessTesting] begin +@testitem "Broyden" retries=5 setup=[RobustnessTesting] begin alg_ops = (Broyden(), Broyden(; init_jacobian = Val(:true_jacobian)), Broyden(; update_rule = Val(:bad_broyden)), @@ -107,7 +107,7 @@ end test_on_library(problems, dicts, alg_ops, broken_tests) end -@testitem "Klement" setup=[RobustnessTesting] begin +@testitem "Klement" retries=5 setup=[RobustnessTesting] begin alg_ops = (Klement(), Klement(; init_jacobian = Val(:true_jacobian_diagonal))) broken_tests = Dict(alg => Int[] for alg in alg_ops) diff --git a/test/gpu/Project.toml b/test/gpu/Project.toml deleted file mode 100644 index 5b5241a2e..000000000 --- a/test/gpu/Project.toml +++ /dev/null @@ -1,6 +0,0 @@ -[deps] -CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" -LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" -NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -ReTestItems = "817f1d60-ba6b-4fd5-9520-3cf149f6a823" -StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" diff --git a/test/gpu/core.jl b/test/gpu/core_tests.jl similarity index 100% rename from test/gpu/core.jl rename to test/gpu/core_tests.jl diff --git a/test/runtests.jl b/test/runtests.jl index 378fd0cf7..0c3f7d855 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,13 +1,7 @@ -using Pkg, ReTestItems +using ReTestItems const GROUP = get(ENV, "GROUP", "All") -function activate_env(env) - Pkg.activate(env) - Pkg.develop(PackageSpec(path = dirname(@__DIR__))) - Pkg.instantiate() -end - if GROUP == "All" || GROUP == "Core" ReTestItems.runtests(joinpath(@__DIR__, "core/"), joinpath(@__DIR__, "misc/"), @@ -15,6 +9,5 @@ if GROUP == "All" || GROUP == "Core" end if GROUP == "GPU" - activate_env("gpu") ReTestItems.runtests(joinpath(@__DIR__, "gpu/")) end