From 4386e226401a523a8a3c1639e9a4d7ac30ad5762 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Fri, 20 Oct 2023 08:08:08 -0400 Subject: [PATCH 1/2] Add matrix resizing and fix cases with u0 as a matrix --- Project.toml | 2 +- src/broyden.jl | 6 +++--- src/klement.jl | 8 ++++---- src/raphson.jl | 2 +- src/utils.jl | 4 ++++ test/matrix_resizing_tests.jl | 11 +++++++++++ test/runtests.jl | 10 +++------- 7 files changed, 27 insertions(+), 16 deletions(-) create mode 100644 test/matrix_resizing_tests.jl diff --git a/Project.toml b/Project.toml index 61fe5f1..28a6b0e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SimpleNonlinearSolve" uuid = "727e6d20-b764-4bd8-a329-72de5adea6c7" authors = ["SciML"] -version = "0.1.22" +version = "0.1.23" [deps] ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" diff --git a/src/broyden.jl b/src/broyden.jl index 6c5c3ce..2f518df 100644 --- a/src/broyden.jl +++ b/src/broyden.jl @@ -58,12 +58,12 @@ function SciMLBase.__solve(prob::NonlinearProblem, alg::Broyden, args...; xₙ₋₁ = x fₙ₋₁ = fₙ for _ in 1:maxiters - xₙ = xₙ₋₁ - J⁻¹ * fₙ₋₁ + xₙ = xₙ₋₁ - ArrayInterface.restructure(xₙ₋₁, J⁻¹ * _vec(fₙ₋₁)) fₙ = f(xₙ) Δxₙ = xₙ - xₙ₋₁ Δfₙ = fₙ - fₙ₋₁ - J⁻¹Δfₙ = J⁻¹ * Δfₙ - J⁻¹ += ((Δxₙ .- J⁻¹Δfₙ) ./ (Δxₙ' * J⁻¹Δfₙ)) * (Δxₙ' * J⁻¹) + J⁻¹Δfₙ = ArrayInterface.restructure(Δfₙ, J⁻¹ * _vec(Δfₙ)) + J⁻¹ += ArrayInterface.restructure(J⁻¹, ((_vec(Δxₙ) .- _vec(J⁻¹Δfₙ)) ./ (_vec(Δxₙ)' * _vec(J⁻¹Δfₙ))) * (_vec(Δxₙ)' * J⁻¹)) if termination_condition(fₙ, xₙ, xₙ₋₁, atol, rtol) return SciMLBase.build_solution(prob, alg, xₙ, fₙ; retcode = ReturnCode.Success) diff --git a/src/klement.jl b/src/klement.jl index 00264d3..7235487 100644 --- a/src/klement.jl +++ b/src/klement.jl @@ -75,7 +75,7 @@ function SciMLBase.__solve(prob::NonlinearProblem, F = lu(J, check = false) end - tmp = F \ fₙ₋₁ + tmp = ArrayInterface.restructure(fₙ₋₁, F \ _vec(fₙ₋₁)) xₙ = xₙ₋₁ - tmp fₙ = f(xₙ) @@ -92,10 +92,10 @@ function SciMLBase.__solve(prob::NonlinearProblem, Δfₙ = fₙ - fₙ₋₁ # Prevent division by 0 - denominator = max.(J' .^ 2 * Δxₙ .^ 2, 1e-9) + denominator = ArrayInterface.restructure(Δxₙ, max.(J' .^ 2 * _vec(Δxₙ) .^ 2, 1e-9)) - k = (Δfₙ - J * Δxₙ) ./ denominator - J += (k * Δxₙ' .* J) * J + k = (Δfₙ - ArrayInterface.restructure(Δxₙ, J * _vec(Δxₙ))) ./ denominator + J += (_vec(k) * _vec(Δxₙ)' .* J) * J xₙ₋₁ = xₙ fₙ₋₁ = fₙ diff --git a/src/raphson.jl b/src/raphson.jl index 48b8f75..a7d9858 100644 --- a/src/raphson.jl +++ b/src/raphson.jl @@ -100,7 +100,7 @@ function SciMLBase.__solve(prob::NonlinearProblem, end iszero(fx) && return SciMLBase.build_solution(prob, alg, x, fx; retcode = ReturnCode.Success) - Δx = dfx \ fx + Δx = ArrayInterface.restructure(fx, dfx \ _vec(fx)) x -= Δx if isapprox(x, xo, atol = atol, rtol = rtol) return SciMLBase.build_solution(prob, alg, x, fx; retcode = ReturnCode.Success) diff --git a/src/utils.jl b/src/utils.jl index 12462a0..4f56177 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -82,3 +82,7 @@ function dogleg_method(H, g, Δ) tau = (-dot_δsd_δN_δsd + sqrt(fact)) / dot_δN_δsd return δsd + tau * δN_δsd end + +@inline _vec(v) = vec(v) +@inline _vec(v::Number) = v +@inline _vec(v::AbstractVector) = v \ No newline at end of file diff --git a/test/matrix_resizing_tests.jl b/test/matrix_resizing_tests.jl new file mode 100644 index 0000000..9612cbb --- /dev/null +++ b/test/matrix_resizing_tests.jl @@ -0,0 +1,11 @@ +using SimpleNonlinearSolve + +ff(u, p) = u .* u .- p +u0 = rand(2,2) +p = 2.0 +vecprob = NonlinearProblem(ff, vec(u0), p) +prob = NonlinearProblem(ff, u0, p) + +for alg in (Klement(), Broyden(), SimpleNewtonRaphson()) + @test vec(solve(prob, alg).u) == solve(vecprob, alg).u +end diff --git a/test/runtests.jl b/test/runtests.jl index bea57ea..98a01bd 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,12 +4,8 @@ const GROUP = get(ENV, "GROUP", "All") @time begin if GROUP == "All" || GROUP == "Core" - @time @safetestset "Basic Tests + Some AD" begin - include("basictests.jl") - end - - @time @safetestset "Inplace Tests" begin - include("inplace.jl") - end + @time @safetestset "Basic Tests + Some AD" include("basictests.jl") + @time @safetestset "Inplace Tests" include("inplace.jl") + @time @safetestset "Matrix Resizing Tests" include("matrix_resizing_tests.jl") end end From bae8815709625aa85297ec6babc1c1e9b7c093d3 Mon Sep 17 00:00:00 2001 From: Chris Rackauckas Date: Fri, 20 Oct 2023 08:57:38 -0400 Subject: [PATCH 2/2] don't restructure on number --- src/broyden.jl | 6 +++--- src/klement.jl | 6 +++--- src/raphson.jl | 2 +- src/utils.jl | 5 ++++- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/broyden.jl b/src/broyden.jl index 2f518df..9f3c225 100644 --- a/src/broyden.jl +++ b/src/broyden.jl @@ -58,12 +58,12 @@ function SciMLBase.__solve(prob::NonlinearProblem, alg::Broyden, args...; xₙ₋₁ = x fₙ₋₁ = fₙ for _ in 1:maxiters - xₙ = xₙ₋₁ - ArrayInterface.restructure(xₙ₋₁, J⁻¹ * _vec(fₙ₋₁)) + xₙ = xₙ₋₁ - _restructure(xₙ₋₁, J⁻¹ * _vec(fₙ₋₁)) fₙ = f(xₙ) Δxₙ = xₙ - xₙ₋₁ Δfₙ = fₙ - fₙ₋₁ - J⁻¹Δfₙ = ArrayInterface.restructure(Δfₙ, J⁻¹ * _vec(Δfₙ)) - J⁻¹ += ArrayInterface.restructure(J⁻¹, ((_vec(Δxₙ) .- _vec(J⁻¹Δfₙ)) ./ (_vec(Δxₙ)' * _vec(J⁻¹Δfₙ))) * (_vec(Δxₙ)' * J⁻¹)) + J⁻¹Δfₙ = _restructure(Δfₙ, J⁻¹ * _vec(Δfₙ)) + J⁻¹ += _restructure(J⁻¹, ((_vec(Δxₙ) .- _vec(J⁻¹Δfₙ)) ./ (_vec(Δxₙ)' * _vec(J⁻¹Δfₙ))) * (_vec(Δxₙ)' * J⁻¹)) if termination_condition(fₙ, xₙ, xₙ₋₁, atol, rtol) return SciMLBase.build_solution(prob, alg, xₙ, fₙ; retcode = ReturnCode.Success) diff --git a/src/klement.jl b/src/klement.jl index 7235487..799ba59 100644 --- a/src/klement.jl +++ b/src/klement.jl @@ -75,7 +75,7 @@ function SciMLBase.__solve(prob::NonlinearProblem, F = lu(J, check = false) end - tmp = ArrayInterface.restructure(fₙ₋₁, F \ _vec(fₙ₋₁)) + tmp = _restructure(fₙ₋₁, F \ _vec(fₙ₋₁)) xₙ = xₙ₋₁ - tmp fₙ = f(xₙ) @@ -92,9 +92,9 @@ function SciMLBase.__solve(prob::NonlinearProblem, Δfₙ = fₙ - fₙ₋₁ # Prevent division by 0 - denominator = ArrayInterface.restructure(Δxₙ, max.(J' .^ 2 * _vec(Δxₙ) .^ 2, 1e-9)) + denominator = _restructure(Δxₙ, max.(J' .^ 2 * _vec(Δxₙ) .^ 2, 1e-9)) - k = (Δfₙ - ArrayInterface.restructure(Δxₙ, J * _vec(Δxₙ))) ./ denominator + k = (Δfₙ - _restructure(Δxₙ, J * _vec(Δxₙ))) ./ denominator J += (_vec(k) * _vec(Δxₙ)' .* J) * J xₙ₋₁ = xₙ diff --git a/src/raphson.jl b/src/raphson.jl index a7d9858..c36dc35 100644 --- a/src/raphson.jl +++ b/src/raphson.jl @@ -100,7 +100,7 @@ function SciMLBase.__solve(prob::NonlinearProblem, end iszero(fx) && return SciMLBase.build_solution(prob, alg, x, fx; retcode = ReturnCode.Success) - Δx = ArrayInterface.restructure(fx, dfx \ _vec(fx)) + Δx = _restructure(fx, dfx \ _vec(fx)) x -= Δx if isapprox(x, xo, atol = atol, rtol = rtol) return SciMLBase.build_solution(prob, alg, x, fx; retcode = ReturnCode.Success) diff --git a/src/utils.jl b/src/utils.jl index 4f56177..c0245ec 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -85,4 +85,7 @@ end @inline _vec(v) = vec(v) @inline _vec(v::Number) = v -@inline _vec(v::AbstractVector) = v \ No newline at end of file +@inline _vec(v::AbstractVector) = v + +@inline _restructure(y::Number, x::Number) = x +@inline _restructure(y, x) = ArrayInterface.restructure(y,x) \ No newline at end of file