|
13 | 13 |
|
14 | 14 | (uf::ImmutableJacobianWrapper)(u) = uf.f(u, uf.p)
|
15 | 15 |
|
16 |
| -function calc_J(solver, cache) |
17 |
| - @unpack u, f, p, alg = solver |
18 |
| - @unpack uf = cache |
19 |
| - uf.f = f |
20 |
| - uf.p = p |
21 |
| - J = jacobian(uf, u, solver) |
22 |
| - return J |
| 16 | +function sparsity_colorvec(f, x) |
| 17 | + sparsity = f.sparsity |
| 18 | + colorvec = DiffEqBase.has_colorvec(f) ? f.colorvec : |
| 19 | + (isnothing(sparsity) ? (1:length(x)) : matrix_colors(sparsity)) |
| 20 | + sparsity, colorvec |
23 | 21 | end
|
24 | 22 |
|
25 |
| -function calc_J(solver, uf::ImmutableJacobianWrapper) |
26 |
| - @unpack u, f, p, alg = solver |
27 |
| - J = jacobian(uf, u, solver) |
28 |
| - return J |
| 23 | +function jacobian_finitediff_forward!(J, f, x, jac_config, forwardcache, cache) |
| 24 | + (FiniteDiff.finite_difference_jacobian!(J, f, x, jac_config, forwardcache, |
| 25 | + dir = diffdir(cache)); |
| 26 | + maximum(jac_config.colorvec)) |
| 27 | +end |
| 28 | +function jacobian_finitediff!(J, f, x, jac_config, cache) |
| 29 | + (FiniteDiff.finite_difference_jacobian!(J, f, x, jac_config, |
| 30 | + dir = diffdir(cache)); |
| 31 | + 2 * maximum(jac_config.colorvec)) |
29 | 32 | end
|
30 | 33 |
|
31 |
| -function jacobian(f, x::Number, solver) |
32 |
| - if alg_autodiff(solver.alg) |
33 |
| - J = ForwardDiff.derivative(f, x) |
| 34 | +function jacobian!(J::AbstractMatrix{<:Number}, f, x::AbstractArray{<:Number}, |
| 35 | + fx::AbstractArray{<:Number}, cache, |
| 36 | + jac_config) |
| 37 | + alg = unwrap_alg(cache, true) |
| 38 | + if alg_autodiff(alg) |
| 39 | + forwarddiff_color_jacobian!(J, f, x, jac_config) |
| 40 | + #cache.destats.nf += 1 |
34 | 41 | else
|
35 |
| - J = FiniteDiff.finite_difference_derivative(f, x, alg_difftype(solver.alg), |
36 |
| - eltype(x)) |
| 42 | + isforward = alg_difftype(alg) === Val{:forward} |
| 43 | + if isforward |
| 44 | + forwardcache = get_tmp_cache(cache, alg, unwrap_cache(cache, true))[2] |
| 45 | + f(forwardcache, x) |
| 46 | + #cache.destats.nf += 1 |
| 47 | + tmp = jacobian_finitediff_forward!(J, f, x, jac_config, forwardcache, |
| 48 | + cache) |
| 49 | + else # not forward difference |
| 50 | + tmp = jacobian_finitediff!(J, f, x, jac_config, cache) |
| 51 | + end |
| 52 | + cache.destats.nf += tmp |
37 | 53 | end
|
38 |
| - return J |
| 54 | + nothing |
39 | 55 | end
|
40 | 56 |
|
41 |
| -function jacobian(f, x, solver) |
42 |
| - if alg_autodiff(solver.alg) |
43 |
| - J = ForwardDiff.jacobian(f, x) |
| 57 | +function build_jac_config(alg, f::F1, uf::F2, du1, u, tmp, du2) where {F1, F2} |
| 58 | + haslinsolve = hasfield(typeof(alg), :linsolve) |
| 59 | + |
| 60 | + if SciMLBase.has_jac(f) && # No Jacobian if has analytical solution |
| 61 | + ((concrete_jac(alg) === nothing && (!haslinsolve || (haslinsolve && # No Jacobian if linsolve doesn't want it |
| 62 | + (alg.linsolve === nothing || LinearSolve.needs_concrete_A(alg.linsolve))))) || |
| 63 | + (concrete_jac(alg) !== nothing && concrete_jac(alg))) # Jacobian if explicitly asked for |
| 64 | + jac_prototype = f.jac_prototype |
| 65 | + sparsity, colorvec = sparsity_colorvec(f, u) |
| 66 | + |
| 67 | + if alg_autodiff(alg) |
| 68 | + _chunksize = get_chunksize(alg) === Val(0) ? nothing : get_chunksize(alg) # SparseDiffEq uses different convection... |
| 69 | + |
| 70 | + T = if standardtag(alg) |
| 71 | + typeof(ForwardDiff.Tag(OrdinaryDiffEqTag(), eltype(u))) |
| 72 | + else |
| 73 | + typeof(ForwardDiff.Tag(uf, eltype(u))) |
| 74 | + end |
| 75 | + jac_config = ForwardColorJacCache(uf, u, _chunksize; colorvec = colorvec, |
| 76 | + sparsity = sparsity, tag = T) |
| 77 | + else |
| 78 | + if alg_difftype(alg) !== Val{:complex} |
| 79 | + jac_config = FiniteDiff.JacobianCache(tmp, du1, du2, alg_difftype(alg), |
| 80 | + colorvec = colorvec, |
| 81 | + sparsity = sparsity) |
| 82 | + else |
| 83 | + jac_config = FiniteDiff.JacobianCache(Complex{eltype(tmp)}.(tmp), |
| 84 | + Complex{eltype(du1)}.(du1), nothing, |
| 85 | + alg_difftype(alg), eltype(u), |
| 86 | + colorvec = colorvec, |
| 87 | + sparsity = sparsity) |
| 88 | + end |
| 89 | + end |
44 | 90 | else
|
45 |
| - J = FiniteDiff.finite_difference_jacobian(f, x, alg_difftype(solver.alg), eltype(x)) |
| 91 | + jac_config = nothing |
46 | 92 | end
|
47 |
| - return J |
| 93 | + jac_config |
48 | 94 | end
|
49 | 95 |
|
50 |
| -function calc_J!(J, solver, cache) |
51 |
| - @unpack f, u, p, alg = solver |
52 |
| - @unpack du1, uf, jac_config = cache |
| 96 | +function get_chunksize(jac_config::ForwardDiff.JacobianConfig{T, V, N, D}) where {T, V, N, D |
| 97 | + } |
| 98 | + Val(N) |
| 99 | +end # don't degrade compile time information to runtime information |
53 | 100 |
|
54 |
| - uf.f = f |
55 |
| - uf.p = p |
56 |
| - |
57 |
| - jacobian!(J, uf, u, du1, solver, jac_config) |
| 101 | +function jacobian_finitediff(f, x, ::Type{diff_type}, dir, colorvec, sparsity, |
| 102 | + jac_prototype) where {diff_type} |
| 103 | + (FiniteDiff.finite_difference_derivative(f, x, diff_type, eltype(x), dir = dir), 2) |
58 | 104 | end
|
59 |
| - |
60 |
| -function jacobian!(J, f, x, fx, solver, jac_config) |
61 |
| - alg = solver.alg |
| 105 | +function jacobian_finitediff(f, x::AbstractArray, ::Type{diff_type}, dir, colorvec, |
| 106 | + sparsity, jac_prototype) where {diff_type} |
| 107 | + f_in = diff_type === Val{:forward} ? f(x) : similar(x) |
| 108 | + ret_eltype = eltype(f_in) |
| 109 | + J = FiniteDiff.finite_difference_jacobian(f, x, diff_type, ret_eltype, f_in, |
| 110 | + dir = dir, colorvec = colorvec, |
| 111 | + sparsity = sparsity, |
| 112 | + jac_prototype = jac_prototype) |
| 113 | + return J, _nfcount(maximum(colorvec), diff_type) |
| 114 | +end |
| 115 | +function jacobian(f, x, cache) |
| 116 | + alg = unwrap_alg(cache, true) |
| 117 | + local tmp |
62 | 118 | if alg_autodiff(alg)
|
63 |
| - ForwardDiff.jacobian!(J, f, fx, x, jac_config) |
| 119 | + J, tmp = jacobian_autodiff(f, x, cache.f, alg) |
64 | 120 | else
|
65 |
| - FiniteDiff.finite_difference_jacobian!(J, f, x, jac_config) |
| 121 | + jac_prototype = cache.f.jac_prototype |
| 122 | + sparsity, colorvec = sparsity_colorvec(cache.f, x) |
| 123 | + dir = diffdir(cache) |
| 124 | + J, tmp = jacobian_finitediff(f, x, alg_difftype(alg), dir, colorvec, sparsity, |
| 125 | + jac_prototype) |
66 | 126 | end
|
67 |
| - nothing |
| 127 | + cache.destats.nf += tmp |
| 128 | + J |
| 129 | +end |
| 130 | + |
| 131 | +jacobian_autodiff(f, x, nonlinfun, alg) = (ForwardDiff.derivative(f, x), 1, alg) |
| 132 | +function jacobian_autodiff(f, x::AbstractArray, nonlinfun, alg) |
| 133 | + jac_prototype = nonlinfun.jac_prototype |
| 134 | + sparsity, colorvec = sparsity_colorvec(nonlinfun, x) |
| 135 | + maxcolor = maximum(colorvec) |
| 136 | + chunk_size = get_chunksize(alg) === Val(0) ? nothing : get_chunksize(alg) |
| 137 | + num_of_chunks = chunk_size === nothing ? |
| 138 | + Int(ceil(maxcolor / getsize(ForwardDiff.pickchunksize(maxcolor)))) : |
| 139 | + Int(ceil(maxcolor / _unwrap_val(chunk_size))) |
| 140 | + (forwarddiff_color_jacobian(f, x, colorvec = colorvec, sparsity = sparsity, |
| 141 | + jac_prototype = jac_prototype, chunksize = chunk_size), |
| 142 | + num_of_chunks) |
68 | 143 | end
|
0 commit comments