Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 8 additions & 17 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ NonlinearSolveSpectralMethods = "26075421-4e9a-44e1-8bd1-420ed7ad02b2"
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
SCCNonlinearSolve = "9dfe8606-65a1-4bb3-9748-cb89d1561431"
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
SimpleNonlinearSolve = "727e6d20-b764-4bd8-a329-72de5adea6c7"
StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
Expand All @@ -43,23 +44,13 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
SpeedMapping = "f1835b91-879b-4a3f-a438-e4baacf14412"
Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4"

[sources.BracketingNonlinearSolve]
path = "lib/BracketingNonlinearSolve"

[sources.NonlinearSolveBase]
path = "lib/NonlinearSolveBase"

[sources.NonlinearSolveFirstOrder]
path = "lib/NonlinearSolveFirstOrder"

[sources.NonlinearSolveQuasiNewton]
path = "lib/NonlinearSolveQuasiNewton"

[sources.NonlinearSolveSpectralMethods]
path = "lib/NonlinearSolveSpectralMethods"

[sources.SimpleNonlinearSolve]
path = "lib/SimpleNonlinearSolve"
[sources]
BracketingNonlinearSolve = {path = "lib/BracketingNonlinearSolve"}
NonlinearSolveBase = {path = "lib/NonlinearSolveBase"}
NonlinearSolveFirstOrder = {path = "lib/NonlinearSolveFirstOrder"}
NonlinearSolveQuasiNewton = {path = "lib/NonlinearSolveQuasiNewton"}
NonlinearSolveSpectralMethods = {path = "lib/NonlinearSolveSpectralMethods"}
SimpleNonlinearSolve = {path = "lib/SimpleNonlinearSolve"}

[extensions]
NonlinearSolveFastLevenbergMarquardtExt = "FastLevenbergMarquardt"
Expand Down
4 changes: 3 additions & 1 deletion lib/SCCNonlinearSolve/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ BenchmarkTools = "1.5.0"
CommonSolve = "0.2.4"
ExplicitImports = "1.5"
Hwloc = "3"
LinearAlgebra = "1.10"
InteractiveUtils = "<0.0.1, 1"
NonlinearProblemLibrary = "0.1.2"
NonlinearSolve = "4.8"
Expand All @@ -42,6 +43,7 @@ BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
ExplicitImports = "7d51a73a-1435-4ff3-83d9-f097790105c7"
Hwloc = "0e44f5e4-bd66-52a0-8798-143a42290a1d"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
NonlinearProblemLibrary = "b7050fa9-e91f-4b37-bcee-a89a063da141"
NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
NonlinearSolveBase = "be0214bd-f91f-a760-ac4e-3421ce2b2da0"
Expand All @@ -53,4 +55,4 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Aqua", "BenchmarkTools", "ExplicitImports", "Hwloc", "InteractiveUtils", "NonlinearProblemLibrary", "NonlinearSolveBase", "NonlinearSolveFirstOrder", "NonlinearSolve", "Pkg", "ReTestItems", "StableRNGs", "StaticArrays", "Test"]
test = ["Aqua", "BenchmarkTools", "ExplicitImports", "Hwloc", "InteractiveUtils", "LinearAlgebra", "NonlinearProblemLibrary", "NonlinearSolveBase", "NonlinearSolveFirstOrder", "NonlinearSolve", "Pkg", "ReTestItems", "StableRNGs", "StaticArrays", "Test"]
4 changes: 3 additions & 1 deletion lib/SCCNonlinearSolve/src/SCCNonlinearSolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ function iteratively_build_sols(alg, sols, (prob, explicitfun), args...; kwargs.
# `remake` to recalculate `A` and `b` based on updated parameters from `explicitfun`.
# Pass `A` and `b` to avoid unnecessarily copying them.
sol = SciMLBase.solve(SciMLBase.remake(prob; A, b), alg.linalg; kwargs...)
# LinearSolution may have resid=nothing, so compute it: resid = A*u - b
resid = isnothing(sol.resid) ? A * sol.u - b : sol.resid
SciMLBase.build_linear_solution(
alg.linalg, sol.u, nothing, nothing, retcode = sol.retcode)
alg.linalg, sol.u, resid, nothing, retcode = sol.retcode)
else
sol = SciMLBase.solve(prob, alg.nlalg; kwargs...)
SciMLBase.build_solution(
Expand Down
72 changes: 72 additions & 0 deletions lib/SCCNonlinearSolve/test/core_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,75 @@ end
scc_sol_default=solve(sccprob)
@test sol ≈ manualscc ≈ scc_sol_default
end

@testitem "SCC Residuals Transfer" setup=[CoreRootfindTesting] tags=[:core] begin
using NonlinearSolveFirstOrder
using LinearAlgebra

# Create a simple SCC problem with both nonlinear and linear components
# to test that residuals are properly computed and transferred

# Nonlinear problem
function f1(du, u, p)
du[1] = u[1]^2 - 2.0
du[2] = u[2] - u[1]
end
explicitfun1(p, sols) = nothing
prob1 = NonlinearProblem(
NonlinearFunction{true, SciMLBase.NoSpecialize}(f1), [1.0, 1.0], nothing)

# Linear problem
A2 = [1.0 0.5; 0.5 1.0]
b2 = [1.0, 2.0]
prob2 = LinearProblem(A2, b2)
explicitfun2(p, sols) = nothing

# Another nonlinear problem
function f3(du, u, p)
du[1] = u[1] + u[2] - 3.0
du[2] = u[1] * u[2] - 2.0
end
explicitfun3(p, sols) = nothing
prob3 = NonlinearProblem(
NonlinearFunction{true, SciMLBase.NoSpecialize}(f3), [1.0, 2.0], nothing)

# Create SCC problem
sccprob = SciMLBase.SCCNonlinearProblem((prob1, prob2, prob3),
SciMLBase.Void{Any}.([explicitfun1, explicitfun2, explicitfun3]))

# Solve with SCCAlg
using SCCNonlinearSolve
scc_alg = SCCNonlinearSolve.SCCAlg(nlalg = NewtonRaphson(), linalg = nothing)
scc_sol = solve(sccprob, scc_alg)

# Test that solution was successful
@test SciMLBase.successful_retcode(scc_sol)

# Test that residuals are not nothing
@test scc_sol.resid !== nothing
@test !any(isnothing, scc_sol.resid)

# Test that residuals have the correct length
expected_length = length(prob1.u0) + length(prob2.b) + length(prob3.u0)
@test length(scc_sol.resid) == expected_length

# Test that residuals are small (near zero for converged solution)
@test norm(scc_sol.resid) < 1e-10

# Manually compute residuals to verify correctness
u1 = scc_sol.u[1:2]
u2 = scc_sol.u[3:4]
u3 = scc_sol.u[5:6]

# Compute residuals for each component
resid1 = zeros(2)
f1(resid1, u1, nothing)

resid2 = A2 * u2 - b2

resid3 = zeros(2)
f3(resid3, u3, nothing)

expected_resid = vcat(resid1, resid2, resid3)
@test scc_sol.resid ≈ expected_resid atol=1e-10
end
Loading