-
-
Notifications
You must be signed in to change notification settings - Fork 24
Implemented a Klement solver #18
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
""" | ||
```julia | ||
Klement() | ||
``` | ||
|
||
A low-overhead implementation of [Klement](https://jatm.com.br/jatm/article/view/373). | ||
This method is non-allocating on scalar and static array problems. | ||
""" | ||
struct Klement <: AbstractSimpleNonlinearSolveAlgorithm end | ||
|
||
function SciMLBase.solve(prob::NonlinearProblem, | ||
alg::Klement, args...; abstol = nothing, | ||
reltol = nothing, | ||
maxiters = 1000, kwargs...) | ||
f = Base.Fix2(prob.f, prob.p) | ||
x = float(prob.u0) | ||
fₙ = f(x) | ||
T = eltype(x) | ||
J = ArrayInterfaceCore.zeromatrix(x) + I | ||
|
||
if SciMLBase.isinplace(prob) | ||
error("Klement currently only supports out-of-place nonlinear problems") | ||
end | ||
|
||
atol = abstol !== nothing ? abstol : | ||
real(oneunit(eltype(T))) * (eps(real(one(eltype(T)))))^(4 // 5) | ||
rtol = reltol !== nothing ? reltol : eps(real(one(eltype(T))))^(4 // 5) | ||
|
||
xₙ = x | ||
xₙ₋₁ = x | ||
fₙ₋₁ = fₙ | ||
for _ in 1:maxiters | ||
xₙ = xₙ₋₁ - inv(J) * fₙ₋₁ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Always use the matrix factorization object to solve. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I missed that. Instead, just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or |
||
fₙ = f(xₙ) | ||
Δxₙ = xₙ - xₙ₋₁ | ||
Δfₙ = fₙ - fₙ₋₁ | ||
|
||
# Prevent division by 0 | ||
denominator = max.(J' .^ 2 * Δxₙ .^ 2, 1e-9) | ||
|
||
k = (Δfₙ - J * Δxₙ) ./ denominator | ||
J += (k * Δxₙ' .* J) * J | ||
|
||
# Prevent inverting singular matrix | ||
if det(J) ≈ 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, by default, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, this was left for a follow-up: #19 |
||
J = ArrayInterfaceCore.zeromatrix(x) + I | ||
Comment on lines
+45
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems a little hacky. Is it part of the method? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, yeah, it's hacky... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's merge and improve. |
||
end | ||
|
||
iszero(fₙ) && | ||
return SciMLBase.build_solution(prob, alg, xₙ, fₙ; | ||
retcode = ReturnCode.Success) | ||
|
||
if isapprox(xₙ, xₙ₋₁, atol = atol, rtol = rtol) | ||
return SciMLBase.build_solution(prob, alg, xₙ, fₙ; | ||
retcode = ReturnCode.Success) | ||
end | ||
xₙ₋₁ = xₙ | ||
fₙ₋₁ = fₙ | ||
end | ||
|
||
return SciMLBase.build_solution(prob, alg, xₙ, fₙ; retcode = ReturnCode.MaxIters) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be a fallback. If
x
is mutable, then we could doJ = ArrayInterfaceCore.zeromatrix(x); J[diagind(J)] .= one(eltype(x))
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Open an issue.