@@ -42,10 +42,28 @@ function SciMLBase.__solve(prob::NonlinearProblem,
4242 maxiters = 1000 , kwargs... )
4343 f = Base. Fix2 (prob. f, prob. p)
4444 x = float (prob. u0)
45- fx = f (x)
46- # fx = float(prob.u0)
47- if ! isa (fx, Number) || ! isa (x, Number)
48- error (" Halley currently only supports scalar-valued single-variable functions" )
45+ # Defining all derivative expressions in one place before the iterations
46+ if isa (x, AbstractArray)
47+ if alg_autodiff (alg)
48+ n = length (x)
49+ a_dfdx (x) = ForwardDiff. jacobian (f, x)
50+ a_d2fdx (x) = ForwardDiff. jacobian (a_dfdx, x)
51+ A = Array {Union{Nothing, Number}} (nothing , n, n)
52+ # fx = f(x)
53+ else
54+ n = length (x)
55+ f_dfdx (x) = FiniteDiff. finite_difference_jacobian (f, x, diff_type (alg), eltype (x))
56+ f_d2fdx (x) = FiniteDiff. finite_difference_jacobian (f_dfdx, x, diff_type (alg), eltype (x))
57+ A = Array {Union{Nothing, Number}} (nothing , n, n)
58+ end
59+ elseif isa (x, Number)
60+ if alg_autodiff (alg)
61+ sa_dfdx (x) = ForwardDiff. derivative (f, x)
62+ sa_d2fdx (x) = ForwardDiff. derivative (sa_dfdx, x)
63+ else
64+ sf_dfdx (x) = FiniteDiff. finite_difference_derivative (f, x, diff_type (alg), eltype (x))
65+ sf_d2fdx (x) = FiniteDiff. finite_difference_derivative (sf_dfdx, x, diff_type (alg), eltype (x))
66+ end
4967 end
5068 T = typeof (x)
5169
@@ -65,22 +83,49 @@ function SciMLBase.__solve(prob::NonlinearProblem,
6583
6684 for i in 1 : maxiters
6785 if alg_autodiff (alg)
68- fx = f (x)
69- dfdx (x) = ForwardDiff. derivative (f, x)
70- dfx = dfdx (x)
71- d2fx = ForwardDiff. derivative (dfdx, x)
86+ if isa (x, Number)
87+ fx = f (x)
88+ dfx = sa_dfdx (x)
89+ d2fx = sa_d2fdx (x)
90+ else
91+ fx = f (x)
92+ dfx = a_dfdx (x)
93+ d2fx = reshape (a_d2fdx (x), (n,n,n)) # A 3-dim Hessian Tensor
94+ ai = - (dfx \ fx)
95+ for j in 1 : n
96+ tmp = transpose (d2fx[:, :, j] * ai)
97+ A[j, :] = tmp
98+ end
99+ bi = (dfx) \ (A * ai)
100+ ci = (ai .* ai) ./ (ai .+ (0.5 .* bi))
101+ end
72102 else
73- fx = f (x)
74- dfx = FiniteDiff. finite_difference_derivative (f, x, diff_type (alg), eltype (x),
75- fx)
76- d2fx = FiniteDiff. finite_difference_derivative (x -> FiniteDiff. finite_difference_derivative (f,
77- x),
78- x, diff_type (alg), eltype (x), fx)
103+ if isa (x, Number)
104+ fx = f (x)
105+ dfx = sf_dfdx (x)
106+ d2fx = sf_d2fdx (x)
107+ else
108+ fx = f (x)
109+ dfx = f_dfdx (x)
110+ d2fx = reshape (f_d2fdx (x), (n,n,n)) # A 3-dim Hessian Tensor
111+ ai = - (dfx \ fx)
112+ for j in 1 : n
113+ tmp = transpose (d2fx[:, :, j] * ai)
114+ A[j, :] = tmp
115+ end
116+ bi = (dfx) \ (A * ai)
117+ ci = (ai .* ai) ./ (ai .+ (0.5 .* bi))
118+ end
79119 end
80120 iszero (fx) &&
81121 return SciMLBase. build_solution (prob, alg, x, fx; retcode = ReturnCode. Success)
82- Δx = (2 * dfx^ 2 - fx * d2fx) \ (2 fx * dfx)
83- x -= Δx
122+ if isa (x, Number)
123+ Δx = (2 * dfx^ 2 - fx * d2fx) \ (2 fx * dfx)
124+ x -= Δx
125+ else
126+ Δx = ci
127+ x += Δx
128+ end
84129 if isapprox (x, xo, atol = atol, rtol = rtol)
85130 return SciMLBase. build_solution (prob, alg, x, fx; retcode = ReturnCode. Success)
86131 end
0 commit comments