From c690175088457abffc7ce012bf2143d166f7babc Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 18 Jan 2025 09:14:58 +0100 Subject: [PATCH 1/5] Fix interpretation of nonlinear system overdetermined defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ```julia using ModelingToolkit, NonlinearSolve # Define the nonlinear system @variables x=1.0 y z=0.0 @parameters σ=10.0 ρ=26.0 β=8 / 3 eqs = [0 ~ σ * (y - x), 0 ~ x * (ρ - z) - y, 0 ~ x * y - β * z] @mtkbuild ns = NonlinearSystem(eqs, [x, y, z], [σ, ρ, β]) # Convert the symbolic system into a numerical system prob = NonlinearProblem(ns, []) # Solve the numerical problem sol = solve(prob, NewtonRaphson()) ``` This failed because of an initialization failure. This is because those conditions cannot be satisfied with the nonlinear system. But that doesn't make sense: the purpose of a nonlinear system is to find the set of values that satisfies the system. So this case should not be building initialization problems, there is no reason to assume that the user's initial guess satisfies the system, and in fact, you should assume if basically never does as the point is to solve the system. There can be an argument to have the initialization specifically for the parameters, but that can be added in the future. For now, this is fixing a major regression and adding a test to make sure this doesn't regress again. OptimizationSystem should be similarly checked as its initial conditions should be handled similarly. --- src/systems/nonlinear/nonlinearsystem.jl | 17 ++++++++++------- test/nonlinearsystem.jl | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/systems/nonlinear/nonlinearsystem.jl b/src/systems/nonlinear/nonlinearsystem.jl index 6b0b0cc759..4e9de5336c 100644 --- a/src/systems/nonlinear/nonlinearsystem.jl +++ b/src/systems/nonlinear/nonlinearsystem.jl @@ -539,7 +539,7 @@ function DiffEqBase.NonlinearProblem{iip}(sys::NonlinearSystem, u0map, end end f, u0, p = process_SciMLProblem(NonlinearFunction{iip}, sys, u0map, parammap; - check_length, kwargs...) + check_length, build_initializeprob = false, kwargs...) pt = something(get_metadata(sys), StandardNonlinearProblem()) NonlinearProblem{iip}(f, u0, p, pt; filter_kwargs(kwargs)...) end @@ -568,7 +568,7 @@ function DiffEqBase.NonlinearLeastSquaresProblem{iip}(sys::NonlinearSystem, u0ma error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearLeastSquaresProblem`") end f, u0, p = process_SciMLProblem(NonlinearFunction{iip}, sys, u0map, parammap; - check_length, kwargs...) + check_length, build_initializeprob = false, kwargs...) pt = something(get_metadata(sys), StandardNonlinearProblem()) NonlinearLeastSquaresProblem{iip}(f, u0, p; filter_kwargs(kwargs)...) end @@ -681,7 +681,8 @@ function SciMLBase.SCCNonlinearProblem{iip}(sys::NonlinearSystem, u0map, obs = observed(sys) _, u0, p = process_SciMLProblem( - EmptySciMLFunction, sys, u0map, parammap; eval_expression, eval_module, kwargs...) + EmptySciMLFunction, sys, u0map, parammap; eval_expression, eval_module, + build_initializeprob = false, kwargs...) explicitfuns = [] nlfuns = [] @@ -832,7 +833,8 @@ function DiffEqBase.IntervalNonlinearProblem(sys::NonlinearSystem, uspan::NTuple error("`IntervalNonlinearProblem` only supports with a single equation and a single unknown.") end f, u0, p = process_SciMLProblem( - IntervalNonlinearFunction, sys, unknowns(sys) .=> uspan[1], parammap; kwargs...) + IntervalNonlinearFunction, sys, unknowns(sys) .=> uspan[1], parammap; + build_initializeprob = false, kwargs...) return IntervalNonlinearProblem(f, uspan, p; filter_kwargs(kwargs)...) end @@ -865,7 +867,7 @@ function NonlinearProblemExpr{iip}(sys::NonlinearSystem, u0map, error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearProblemExpr`") end f, u0, p = process_SciMLProblem(NonlinearFunctionExpr{iip}, sys, u0map, parammap; - check_length, kwargs...) + check_length, build_initializeprob = false, kwargs...) linenumbers = get(kwargs, :linenumbers, true) ex = quote @@ -905,7 +907,7 @@ function NonlinearLeastSquaresProblemExpr{iip}(sys::NonlinearSystem, u0map, error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `NonlinearProblemExpr`") end f, u0, p = process_SciMLProblem(NonlinearFunctionExpr{iip}, sys, u0map, parammap; - check_length, kwargs...) + check_length, build_initializeprob = false, kwargs...) linenumbers = get(kwargs, :linenumbers, true) ex = quote @@ -933,7 +935,8 @@ function IntervalNonlinearProblemExpr(sys::NonlinearSystem, uspan::NTuple{2}, error("`IntervalNonlinearProblemExpr` only supports with a single equation and a single unknown.") end f, u0, p = process_SciMLProblem( - IntervalNonlinearFunctionExpr, sys, unknowns(sys) .=> uspan[1], parammap; kwargs...) + IntervalNonlinearFunctionExpr, sys, unknowns(sys) .=> uspan[1], parammap; + build_initializeprob = false, kwargs...) linenumbers = get(kwargs, :linenumbers, true) ex = quote diff --git a/test/nonlinearsystem.jl b/test/nonlinearsystem.jl index cbd95a50d3..33123e3d02 100644 --- a/test/nonlinearsystem.jl +++ b/test/nonlinearsystem.jl @@ -380,3 +380,22 @@ end @test_throws ["single equation", "unknown"] IntervalNonlinearFunctionExpr( sys, (0.0, 1.0)) end + +@testset "Overconditioned Initial Conditions" begin + # Define the nonlinear system + @variables x=1.0 y=0.0 z=0.0 + @parameters σ=10.0 ρ=26.0 β=8 / 3 + + eqs = [0 ~ σ * (y - x), + 0 ~ x * (ρ - z) - y, + 0 ~ x * y - β * z] + @mtkbuild ns = NonlinearSystem(eqs, [x, y, z], [σ, ρ, β]) + + # Convert the symbolic system into a numerical system + prob = NonlinearProblem(ns, []) + + # Solve the numerical problem + sol = solve(prob, NewtonRaphson()) + @test SciMLBase.successful_retcode(sol) + @test norm(sol.resid) < 1e-12 +end \ No newline at end of file From 9d01b7ebc11a1fbe2e7ca1b57674fa01272ea44b Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 18 Jan 2025 09:16:55 +0100 Subject: [PATCH 2/5] Update test/nonlinearsystem.jl Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- test/nonlinearsystem.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/nonlinearsystem.jl b/test/nonlinearsystem.jl index 33123e3d02..a457d27d15 100644 --- a/test/nonlinearsystem.jl +++ b/test/nonlinearsystem.jl @@ -397,5 +397,5 @@ end # Solve the numerical problem sol = solve(prob, NewtonRaphson()) @test SciMLBase.successful_retcode(sol) - @test norm(sol.resid) < 1e-12 + @test norm(sol.resid) < 1e-12 end \ No newline at end of file From 8f9d10cd3882a9e980d0ead8ec82e56e84c03623 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 18 Jan 2025 09:17:01 +0100 Subject: [PATCH 3/5] Update src/systems/nonlinear/nonlinearsystem.jl Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/systems/nonlinear/nonlinearsystem.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/systems/nonlinear/nonlinearsystem.jl b/src/systems/nonlinear/nonlinearsystem.jl index 4e9de5336c..9953944dd6 100644 --- a/src/systems/nonlinear/nonlinearsystem.jl +++ b/src/systems/nonlinear/nonlinearsystem.jl @@ -935,7 +935,7 @@ function IntervalNonlinearProblemExpr(sys::NonlinearSystem, uspan::NTuple{2}, error("`IntervalNonlinearProblemExpr` only supports with a single equation and a single unknown.") end f, u0, p = process_SciMLProblem( - IntervalNonlinearFunctionExpr, sys, unknowns(sys) .=> uspan[1], parammap; + IntervalNonlinearFunctionExpr, sys, unknowns(sys) .=> uspan[1], parammap; build_initializeprob = false, kwargs...) linenumbers = get(kwargs, :linenumbers, true) From bc40f9ab78fac560adf8b7992a2f39c95d0707c6 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 18 Jan 2025 09:17:07 +0100 Subject: [PATCH 4/5] Update src/systems/nonlinear/nonlinearsystem.jl Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/systems/nonlinear/nonlinearsystem.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/systems/nonlinear/nonlinearsystem.jl b/src/systems/nonlinear/nonlinearsystem.jl index 9953944dd6..c35abecf9a 100644 --- a/src/systems/nonlinear/nonlinearsystem.jl +++ b/src/systems/nonlinear/nonlinearsystem.jl @@ -681,7 +681,7 @@ function SciMLBase.SCCNonlinearProblem{iip}(sys::NonlinearSystem, u0map, obs = observed(sys) _, u0, p = process_SciMLProblem( - EmptySciMLFunction, sys, u0map, parammap; eval_expression, eval_module, + EmptySciMLFunction, sys, u0map, parammap; eval_expression, eval_module, build_initializeprob = false, kwargs...) explicitfuns = [] From d83aec921e86b2efc8348900181edb6e4dfd83f2 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 18 Jan 2025 09:17:13 +0100 Subject: [PATCH 5/5] Update src/systems/nonlinear/nonlinearsystem.jl Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/systems/nonlinear/nonlinearsystem.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/systems/nonlinear/nonlinearsystem.jl b/src/systems/nonlinear/nonlinearsystem.jl index c35abecf9a..938735ea9e 100644 --- a/src/systems/nonlinear/nonlinearsystem.jl +++ b/src/systems/nonlinear/nonlinearsystem.jl @@ -833,7 +833,7 @@ function DiffEqBase.IntervalNonlinearProblem(sys::NonlinearSystem, uspan::NTuple error("`IntervalNonlinearProblem` only supports with a single equation and a single unknown.") end f, u0, p = process_SciMLProblem( - IntervalNonlinearFunction, sys, unknowns(sys) .=> uspan[1], parammap; + IntervalNonlinearFunction, sys, unknowns(sys) .=> uspan[1], parammap; build_initializeprob = false, kwargs...) return IntervalNonlinearProblem(f, uspan, p; filter_kwargs(kwargs)...)