Skip to content

Commit 1d62d8a

Browse files
Merge pull request #861 from SciML/sccnonlinear1
Add SCCNonlinearProblem
2 parents ca77954 + 4645c43 commit 1d62d8a

File tree

3 files changed

+150
-4
lines changed

3 files changed

+150
-4
lines changed

src/SciMLBase.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -791,9 +791,10 @@ export isinplace
791791

792792
export solve, solve!, init, discretize, symbolic_discretize
793793

794-
export LinearProblem, NonlinearProblem, IntervalNonlinearProblem,
795-
IntegralProblem, SampledIntegralProblem, OptimizationProblem,
796-
NonlinearLeastSquaresProblem
794+
export LinearProblem, IntervalNonlinearProblem,
795+
IntegralProblem, SampledIntegralProblem, OptimizationProblem
796+
797+
export NonlinearProblem, SCCNonlinearProblem, NonlinearLeastSquaresProblem
797798

798799
export DiscreteProblem, ImplicitDiscreteProblem
799800
export SteadyStateProblem, SteadyStateSolution

src/problems/nonlinear_problems.jl

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,148 @@ end
321321
function NonlinearLeastSquaresProblem(f, u0, p = NullParameters(); kwargs...)
322322
return NonlinearLeastSquaresProblem(NonlinearFunction(f), u0, p; kwargs...)
323323
end
324+
325+
@doc doc"""
326+
SCCNonlinearProblem(probs, explicitfuns!)
327+
328+
Defines an SCC-split nonlinear system to be solved iteratively.
329+
330+
## Mathematical Specification of an SCC-Split Nonlinear Problem
331+
332+
An SCC-Split Nonlinear Problem is a system of nonlinear equations
333+
334+
```math
335+
f(u,p) = 0
336+
```
337+
338+
with the special property that its Jacobian is in block-lower-triangular
339+
form. In this form, the nonlinear problem can be decomposed into a system
340+
of nonlinear systems.
341+
342+
```math
343+
f_1(u_1,p) = 0
344+
f_2(u_2,u_1,p) = 0
345+
f_3(u_3,u_2,u_1,p) = 0
346+
\vdots
347+
f_n(u_n,\ldots,u_3,u_2,u_1,p) = 0
348+
```
349+
350+
Splitting the system in this form can have multiple advantages, including:
351+
352+
* Improved numerical stability and robustness of the solving process
353+
* Improved performance due to using smaller Jacobians
354+
355+
The SCC-Split Nonlinear Problem is the ordered collection of nonlinear systems
356+
to solve in order solve the system in the optimized split form.
357+
358+
## Representation
359+
360+
The representation of the SCCNonlinearProblem is via an ordered collection
361+
of `NonlinearProblem`s, `probs`, with an attached explicit function for pre-processing
362+
a cache. This can be interpreted as follows:
363+
364+
```math
365+
p_1 = g_1(u,p)
366+
f_1(u_1,p_1) = 0
367+
p_2 = g_2(u,p)
368+
f_2(u_2,u_1,p_2) = 0
369+
p_3 = g_3(u,p)
370+
f_3(u_3,u_2,u_1,p_3) = 0
371+
\vdots
372+
p_n = g_n(u,p)
373+
f_n(u_n,\ldots,u_3,u_2,u_1,p_n) = 0
374+
```
375+
376+
where ``g_i`` is `explicitfuns![i]`. In a computational sense, `explictfuns!`
377+
is instead a mutating function `explictfuns![i](prob.probs[i],sols)` which
378+
updates the values of prob.probs[i] using the previous solutions `sols[i-1]`
379+
and below.
380+
381+
!!! warn
382+
For the purposes of differentiation, it's assumed that `explictfuns!` does
383+
not modify tunable parameters!
384+
385+
!!! warn
386+
While `explictfuns![i]` could in theory use `sols[i+1]` in its computation,
387+
these values will not be updated. It is thus the contract of the interface
388+
to not use those values except for as caches to be overriden.
389+
390+
!!! note
391+
prob.probs[i].p can be aliased with each other as a performance / memory
392+
optimization. If they are aliased before the construction of the `probs`
393+
the runtime guarantees the aliasing behavior is kept.
394+
395+
## Example
396+
397+
For the following nonlinear problem:
398+
399+
```julia
400+
function f(du,u,p)
401+
du[1] = cos(u[2]) - u[1]
402+
du[2] = sin(u[1] + u[2]) + u[2]
403+
du[3] = 2u[4] + u[3] + 1.0
404+
du[4] = u[5]^2 + u[4]
405+
du[5] = u[3]^2 + u[5]
406+
du[6] = u[1] + u[2] + u[3] + u[4] + u[5] + 2.0u[6] + 2.5u[7] + 1.5u[8]
407+
du[7] = u[1] + u[2] + u[3] + 2.0u[4] + u[5] + 4.0u[6] - 1.5u[7] + 1.5u[8]
408+
du[8] = u[1] + 2.0u[2] + 3.0u[3] + 5.0u[4] + 6.0u[5] + u[6] - u[7] - u[8]
409+
end
410+
prob = NonlinearProblem(f, zeros(8))
411+
sol = solve(prob)
412+
```
413+
414+
The split SCC form is:
415+
416+
```julia
417+
cache = zeros(3)
418+
419+
function f1(du,u,cache)
420+
du[1] = cos(u[2]) - u[1]
421+
du[2] = sin(u[1] + u[2]) + u[2]
422+
end
423+
explicitfun1(cache,sols) = nothing
424+
prob1 = NonlinearProblem(NonlinearFunction{true, SciMLBase.NoSpecialize}(f1), zeros(2), cache)
425+
sol1 = solve(prob1, NewtonRaphson())
426+
427+
function f2(du,u,cache)
428+
du[1] = 2u[2] + u[1] + 1.0
429+
du[2] = u[3]^2 + u[2]
430+
du[3] = u[1]^2 + u[3]
431+
end
432+
explicitfun2(cache,sols) = nothing
433+
prob2 = NonlinearProblem(NonlinearFunction{true, SciMLBase.NoSpecialize}(f2), zeros(3), cache)
434+
sol2 = solve(prob2, NewtonRaphson())
435+
436+
function f3(du,u,cache)
437+
du[1] = cache[1] + 2.0u[1] + 2.5u[2] + 1.5u[3]
438+
du[2] = cache[2] + 4.0u[1] - 1.5u[2] + 1.5u[3]
439+
du[3] = cache[3] + + u[1] - u[2] - u[3]
440+
end
441+
prob3 = NonlinearProblem(NonlinearFunction{true, SciMLBase.NoSpecialize}(f3), zeros(3), cache)
442+
function explicitfun3(cache,sols)
443+
cache[1] = sols[1][1] + sols[1][2] + sols[2][1] + sols[2][2] + sols[2][3]
444+
cache[2] = sols[1][1] + sols[1][2] + sols[2][1] + 2.0sols[2][2] + sols[2][3]
445+
cache[3] = sols[1][1] + 2.0sols[1][2] + 3.0sols[2][1] + 5.0sols[2][2] + 6.0sols[2][3]
446+
end
447+
explicitfun3(cache,[sol1,sol2])
448+
sol3 = solve(prob3, NewtonRaphson())
449+
manualscc = [sol1; sol2; sol3]
450+
451+
sccprob = SciMLBase.SCCNonlinearProblem([prob1,prob2,prob3], SciMLBase.Void{Any}.([explicitfun1,explicitfun2,explicitfun3]))
452+
```
453+
454+
Note that this example aliases the parameters together for a memory-reduced representation.
455+
456+
## Problem Type
457+
458+
### Constructors
459+
460+
### Fields
461+
462+
* `probs`: the collection of problems to solve
463+
* `explictfuns!`: the explicit functions for mutating the parameter set
464+
"""
465+
mutable struct SCCNonlinearProblem{P, E}
466+
probs::P
467+
explictfuns!::E
468+
end

src/solutions/nonlinear_solutions.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ const SteadyStateSolution = NonlinearSolution
7070

7171
get_p(p::AbstractNonlinearSolution) = p.prob.p
7272

73-
function build_solution(prob::AbstractNonlinearProblem,
73+
function build_solution(prob::Union{AbstractNonlinearProblem, SCCNonlinearProblem},
7474
alg, u, resid; calculate_error = true,
7575
retcode = ReturnCode.Default,
7676
original = nothing,

0 commit comments

Comments
 (0)