Skip to content

Commit e564501

Browse files
committed
changed dc_dual to be a vector of the right size;
re-sizing implemented differently; removing dependency ArrayInterface
1 parent 6ee3863 commit e564501

File tree

3 files changed

+52
-38
lines changed

3 files changed

+52
-38
lines changed

Project.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ authors = ["Chris Rackauckas <accounts@chrisrackauckas.com>"]
44
version = "0.1.1"
55

66
[deps]
7-
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
8-
LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800"
97
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
8+
LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800"
109

1110
[compat]
12-
ArrayInterface = "2.6, 3.0"
1311
ForwardDiff = "0.10.3"
1412
LabelledArrays = "1"
1513
julia = "1.6"

src/PreallocationTools.jl

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,49 @@ module PreallocationTools
22

33
using ForwardDiff, ArrayInterface, LabelledArrays
44

5-
struct DiffCache{T<:AbstractArray, S<:AbstractArray}
5+
struct DiffCache{T<:AbstractArray,S<:AbstractArray}
66
du::T
77
dual_du::S
88
end
99

10+
#= removed dependency on ArrayInterface, because it seemed not necessary anymore;
11+
not sure whether it breaks things that are not in the testset; needs checking. =#
1012
function DiffCache(u::AbstractArray{T}, siz, ::Type{Val{chunk_size}}) where {T, chunk_size}
11-
x = ArrayInterface.restructure(u,zeros(ForwardDiff.Dual{nothing,T,chunk_size}, siz...))
13+
x = zeros(T,(chunk_size+1)*prod(siz))
1214
DiffCache(u, x)
1315
end
1416

1517
"""
1618
1719
`dualcache(u::AbstractArray, N = Val{default_cache_size(length(u))})`
1820
19-
Builds a `DualCache` object that stores both a version of the cache for `u`
20-
and for the `Dual` version of `u`, allowing use of pre-cached vectors with
21+
Builds a `DualCache` object that stores versions of the cache for `u` and for the `Dual` version of `u` allowing use of pre-cached arrays with
2122
forward-mode automatic differentiation.
2223
2324
"""
2425
dualcache(u::AbstractArray, N=Val{ForwardDiff.pickchunksize(length(u))}) = DiffCache(u, size(u), N)
2526

26-
chunksize(::Type{ForwardDiff.Dual{T,V,N}}) where {T,V,N} = N
27+
"""
28+
29+
`get_tmp(dc::DiffCache, u)`
30+
31+
Returns the `Dual` or normal cache array stored in `dc` based on the type of `u`.
2732
33+
"""
2834
function get_tmp(dc::DiffCache, u::T) where T<:ForwardDiff.Dual
29-
x = reinterpret(T, dc.dual_du)
30-
if chunksize(T) === chunksize(eltype(dc.dual_du))
31-
x
32-
else
33-
@view x[axes(dc.du)...]
34-
end
35+
nelem = div(sizeof(T), sizeof(eltype(dc.dual_du)))*prod(size(dc.du))
36+
reshape(reinterpret(T, view(dc.dual_du, 1:nelem)), size(dc.du))
3537
end
3638

3739
function get_tmp(dc::DiffCache, u::AbstractArray{T}) where T<:ForwardDiff.Dual
38-
x = reinterpret(T, dc.dual_du)
39-
if chunksize(T) === chunksize(eltype(dc.dual_du))
40-
x
41-
else
42-
@view x[axes(dc.du)...]
43-
end
40+
nelem = div(sizeof(T), sizeof(eltype(dc.dual_du)))*prod(size(dc.du))
41+
reshape(reinterpret(T, view(dc.dual_du, 1:nelem)), size(dc.du))
4442
end
4543

4644
function get_tmp(dc::DiffCache, u::LabelledArrays.LArray{T,N,D,Syms}) where {T,N,D,Syms}
47-
x = reinterpret(T, dc.dual_du.__x)
48-
_x = if chunksize(T) === chunksize(eltype(dc.dual_du))
49-
x
50-
else
51-
@view x[axes(dc.du)...]
52-
end
53-
LabelledArrays.LArray{T,N,D,Syms}(_x)
45+
nelem = div(sizeof(T), sizeof(eltype(dc.dual_du)))*prod(size(dc.du))
46+
_x = reshape(reinterpret(T, view(dc.dual_du, 1:nelem)), size(dc.du))
47+
LabelledArrays.LArray{T,N,D,Syms}(_x)
5448
end
5549

5650
get_tmp(dc::DiffCache, u::Number) = dc.du
@@ -62,6 +56,7 @@ get_tmp(dc::DiffCache, u::AbstractArray) = dc.du
6256
A lazily allocated buffer object. Given a vector `u`, `b[u]` returns a `Vector` of the
6357
same element type and length `f(length(u))` (defaulting to the same length), which is
6458
allocated as needed and then cached within `b` for subsequent usage.
59+
6560
"""
6661
struct LazyBufferCache{F<:Function}
6762
bufs::Dict # a dictionary mapping types to buffers

test/runtests.jl

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using LinearAlgebra, OrdinaryDiffEq, Test, PreallocationTools, ForwardDiff
1+
using LinearAlgebra, OrdinaryDiffEq, Test, PreallocationTools, ForwardDiff, LabelledArrays
22

3+
## Check ODE problem with specified chunk_size
34
function foo(du, u, (A, tmp), t)
45
tmp = get_tmp(tmp, u)
56
mul!(tmp, A, u)
@@ -10,16 +11,17 @@ chunk_size = 5
1011
prob = ODEProblem(foo, ones(5, 5), (0., 1.0), (ones(5,5), dualcache(zeros(5,5), Val{chunk_size})))
1112
solve(prob, TRBDF2(chunk_size=chunk_size))
1213

14+
## Check ODE problem with auto-detected chunk_size
1315
function foo(du, u, (A, tmp), t)
1416
tmp = get_tmp(tmp, u)
1517
mul!(tmp, A, u)
1618
@. du = u + tmp
1719
nothing
1820
end
19-
chunk_size = 5
2021
prob = ODEProblem(foo, ones(5, 5), (0., 1.0), (ones(5,5), dualcache(zeros(5,5))))
2122
solve(prob, TRBDF2())
2223

24+
## Check ODE problem with a lazy buffer cache
2325
function foo(du, u, (A, lbc), t)
2426
tmp = lbc[u]
2527
mul!(tmp, A, u)
@@ -29,24 +31,43 @@ end
2931
prob = ODEProblem(foo, ones(5, 5), (0., 1.0), (ones(5,5), LazyBufferCache()))
3032
solve(prob, TRBDF2())
3133

32-
## Check resizing
34+
## Check ODE problem with auto-detected chunk_size and LArray
35+
A = LArray((2,2); a=1.0, b=1.0, c=1.0, d=1.0)
36+
u0 = LArray((2,2); a=1.0, b=1.0, c=1.0, d=1.0)
37+
function foo(du, u, (A, tmp), t)
38+
tmp = get_tmp(tmp, u)
39+
mul!(tmp, A, u)
40+
@. du = u + tmp
41+
nothing
42+
end
43+
prob = ODEProblem(foo, u0, (0., 1.0), (A, dualcache(A)))
44+
solve(prob, TRBDF2())
3345

34-
randmat = rand(10, 2)
46+
## Check resizing
47+
randmat = rand(5, 3)
3548
sto = similar(randmat)
3649
stod = dualcache(sto)
3750

38-
function claytonsample!(sto, τ; randmat=randmat)
51+
function claytonsample!(sto, τ, α; randmat=randmat)
3952
sto = get_tmp(sto, τ)
4053
sto .= randmat
4154
τ == 0 && return sto
4255

4356
n = size(sto, 1)
44-
for i in 1:n
45-
v = sto[i, 2]
46-
u = sto[i, 1]
47-
sto[i, 2] = (1 - u^(-τ) + u^(-τ)*v^(-/(1 + τ))))^(-1/τ)
48-
end
57+
println(size(sto))
58+
v = @view sto[:, 2]
59+
u = @view sto[:, 1]
60+
sto[i, 1] = (1 - u^(-τ) + u^(-τ)*v^(-/(1 + τ))))^(-1/τ)*α
61+
sto[i, 2] = (1 - u^(-τ) + u^(-τ)*v^(-/(1 + τ))))^(-1/τ)
62+
4963
return sto
5064
end
5165

52-
ForwardDiff.derivative-> claytonsample!(stod, τ), 0.3)
66+
#taking the derivative of claytonsample! with respect to τ only
67+
df1 = ForwardDiff.derivative-> claytonsample!(stod, τ, 0.0), 0.3)
68+
69+
#calculating the jacobian of claytonsample! with respect to τ and α
70+
df2 = ForwardDiff.jacobian(x -> claytonsample!(stod, x[1], x[2]), [0.3; 0.0]) #should give a 15x2 array,
71+
#because ForwardDiff flattens the output of jacobian, see: https://juliadiff.org/ForwardDiff.jl/stable/user/api/#ForwardDiff.jacobian
72+
73+
@test all(df1[1:5,2] df2[6:10,1])

0 commit comments

Comments
 (0)