@@ -4,7 +4,7 @@ Klement()
44```
55
66A low-overhead implementation of [Klement](https://jatm.com.br/jatm/article/view/373).
7- This method is non-allocating on scalar and static array problems.
7+ This method is non-allocating on scalar problems.
88"""
99struct Klement <: AbstractSimpleNonlinearSolveAlgorithm end
1010
@@ -16,7 +16,7 @@ function SciMLBase.solve(prob::NonlinearProblem,
1616 x = float (prob. u0)
1717 fₙ = f (x)
1818 T = eltype (x)
19- J = init_J (x)
19+ singular_tol = 1e-9
2020
2121 if SciMLBase. isinplace (prob)
2222 error (" Klement currently only supports out-of-place nonlinear problems" )
@@ -29,36 +29,78 @@ function SciMLBase.solve(prob::NonlinearProblem,
2929 xₙ = x
3030 xₙ₋₁ = x
3131 fₙ₋₁ = fₙ
32- for _ in 1 : maxiters
33- tmp = J \ fₙ₋₁
34- xₙ = xₙ₋₁ - tmp
35- fₙ = f (xₙ)
36-
37- iszero (fₙ) &&
38- return SciMLBase. build_solution (prob, alg, xₙ, fₙ;
39- retcode = ReturnCode. Success)
40-
41- if isapprox (xₙ, xₙ₋₁, atol = atol, rtol = rtol)
42- return SciMLBase. build_solution (prob, alg, xₙ, fₙ;
43- retcode = ReturnCode. Success)
44- end
4532
46- Δxₙ = xₙ - xₙ₋₁
47- Δfₙ = fₙ - fₙ₋₁
33+ # x is scalar
34+ if isa (x, Number)
35+ J = 1.0
36+ for _ in 1 : maxiters
37+
38+ xₙ = xₙ₋₁ - fₙ₋₁/ J
39+ fₙ = f (xₙ)
40+
41+ iszero (fₙ) &&
42+ return SciMLBase. build_solution (prob, alg, xₙ, fₙ;
43+ retcode = ReturnCode. Success)
44+
45+ if isapprox (xₙ, xₙ₋₁, atol = atol, rtol = rtol)
46+ return SciMLBase. build_solution (prob, alg, xₙ, fₙ;
47+ retcode = ReturnCode. Success)
48+ end
4849
49- # Prevent division by 0
50- denominator = max .(J ' .^ 2 * Δxₙ .^ 2 , 1e-9 )
50+ Δxₙ = xₙ - xₙ₋₁
51+ Δfₙ = fₙ - fₙ₋₁
5152
52- k = (Δfₙ - J * Δxₙ) ./ denominator
53- J += (k * Δxₙ ' .* J) * J
53+ # Prevent division by 0
54+ denominator = max (J ^ 2 * Δxₙ ^ 2 , 1e-9 )
5455
55- # Singularity test
56- if cond (J) > 1e9
57- J = init_J (xₙ)
56+ k = (Δfₙ - J * Δxₙ) / denominator
57+ J += (k * Δxₙ * J) * J
58+
59+ # Singularity test
60+ if J < singular_tol
61+ J = 1.0
62+ end
63+
64+ xₙ₋₁ = xₙ
65+ fₙ₋₁ = fₙ
5866 end
67+ # x is a vector
68+ else
69+ J = init_J (x)
70+ F = lu (J, check = false )
71+ for _ in 1 : maxiters
72+ tmp = F \ fₙ₋₁
73+ xₙ = xₙ₋₁ - tmp
74+ fₙ = f (xₙ)
75+
76+ iszero (fₙ) &&
77+ return SciMLBase. build_solution (prob, alg, xₙ, fₙ;
78+ retcode = ReturnCode. Success)
5979
60- xₙ₋₁ = xₙ
61- fₙ₋₁ = fₙ
80+ if isapprox (xₙ, xₙ₋₁, atol = atol, rtol = rtol)
81+ return SciMLBase. build_solution (prob, alg, xₙ, fₙ;
82+ retcode = ReturnCode. Success)
83+ end
84+
85+ Δxₙ = xₙ - xₙ₋₁
86+ Δfₙ = fₙ - fₙ₋₁
87+
88+ # Prevent division by 0
89+ denominator = max .(J' .^ 2 * Δxₙ .^ 2 , 1e-9 )
90+
91+ k = (Δfₙ - J * Δxₙ) ./ denominator
92+ J += (k * Δxₙ' .* J) * J
93+ F = lu (J, check = false )
94+
95+ # Singularity test
96+ if any (abs .(F. U[diagind (F. U)]) .< singular_tol)
97+ J = init_J (xₙ)
98+ F = lu (J, check = false )
99+ end
100+
101+ xₙ₋₁ = xₙ
102+ fₙ₋₁ = fₙ
103+ end
62104 end
63105
64106 return SciMLBase. build_solution (prob, alg, xₙ, fₙ; retcode = ReturnCode. MaxIters)
0 commit comments