@@ -62,8 +62,11 @@ function EnzymeReverseADHvprod(
6262 return EnzymeReverseADHvprod (grad,f)
6363end
6464
65- struct EnzymeReverseADJprod{T} <: InPlaceADbackend
66- cx:: Vector{T}
65+ struct EnzymeReverseADJprod{V} <: InPlaceADbackend
66+ cx:: V # length ncon, primal output buffer
67+ xbuf:: V # length nvar, input x buffer
68+ vbuf:: V # length nvar, input v buffer (tangent direction)
69+ jvbuf:: V # length ncon, output Jv buffer
6770end
6871
6972function EnzymeReverseADJprod (
@@ -74,12 +77,18 @@ function EnzymeReverseADJprod(
7477 x0:: AbstractVector{T} = rand (nvar),
7578 kwargs... ,
7679) where {T}
77- cx = zeros (T, ncon)
78- return EnzymeReverseADJprod (cx)
80+ cx = fill! (similar (x0, ncon), zero (T))
81+ xbuf = similar (x0)
82+ vbuf = similar (x0)
83+ jvbuf = fill! (similar (x0, ncon), zero (T))
84+ return EnzymeReverseADJprod (cx, xbuf, vbuf, jvbuf)
7985end
8086
81- struct EnzymeReverseADJtprod{T} <: InPlaceADbackend
82- cx:: Vector{T}
87+ struct EnzymeReverseADJtprod{V} <: InPlaceADbackend
88+ cx:: V # length ncon, primal output buffer
89+ xbuf:: V # length nvar, input x buffer
90+ vbuf:: V # length ncon, cotangent seed buffer
91+ jtvbuf:: V # length nvar, output Jtv buffer
8392end
8493
8594function EnzymeReverseADJtprod (
@@ -90,20 +99,24 @@ function EnzymeReverseADJtprod(
9099 x0:: AbstractVector{T} = rand (nvar),
91100 kwargs... ,
92101) where {T}
93- cx = zeros (T, ncon)
94- return EnzymeReverseADJtprod (cx)
102+ cx = fill! (similar (x0, ncon), zero (T))
103+ xbuf = similar (x0)
104+ vbuf = fill! (similar (x0, ncon), zero (T))
105+ jtvbuf = similar (x0)
106+ return EnzymeReverseADJtprod (cx, xbuf, vbuf, jtvbuf)
95107end
96108
97- struct SparseEnzymeADJacobian{R, C, S} <: ADBackend
109+ struct SparseEnzymeADJacobian{R, C, S, V } <: ADBackend
98110 nvar:: Int
99111 ncon:: Int
100112 rowval:: Vector{Int}
101113 colptr:: Vector{Int}
102114 nzval:: Vector{R}
103115 result_coloring:: C
104116 compressed_jacobian:: S
105- v:: Vector{R}
106- cx:: Vector{R}
117+ v:: V
118+ cx:: V
119+ xbuf:: V
107120end
108121
109122function SparseEnzymeADJacobian (
@@ -154,7 +167,8 @@ function SparseEnzymeADJacobian(
154167
155168 timer = @elapsed begin
156169 v = similar (x0)
157- cx = zeros (T, ncon)
170+ cx = fill! (similar (x0, ncon), zero (T))
171+ xbuf = similar (x0)
158172 end
159173 show_time && println (" • Allocation of the AD buffers for the sparse Jacobian: $timer seconds." )
160174
@@ -168,24 +182,26 @@ function SparseEnzymeADJacobian(
168182 compressed_jacobian,
169183 v,
170184 cx,
185+ xbuf,
171186 )
172187end
173188
174- struct SparseEnzymeADHessian{R, C, S, L, F} <: ADBackend
189+ struct SparseEnzymeADHessian{R, C, S, L, F, V } <: ADBackend
175190 nvar:: Int
176191 rowval:: Vector{Int}
177192 colptr:: Vector{Int}
178193 nzval:: Vector{R}
179194 result_coloring:: C
180195 coloring_mode:: Symbol
181- compressed_hessian_icol:: Vector{R}
196+ compressed_hessian_icol:: V
182197 compressed_hessian:: S
183- v:: Vector{R}
184- y:: Vector{R}
185- grad:: Vector{R}
186- cx:: Vector{R}
198+ v:: V
199+ y:: V
200+ grad:: V
201+ cx:: V
187202 f:: F
188203 ℓ:: L
204+ xbuf:: V
189205end
190206
191207function SparseEnzymeADHessian (
@@ -248,6 +264,7 @@ function SparseEnzymeADHessian(
248264 y = similar (x0, ncon)
249265 cx = similar (x0, ncon)
250266 grad = similar (x0)
267+ xbuf = similar (x0)
251268
252269 function ℓ (x, y, obj_weight, cx)
253270 if ncon != 0
@@ -279,6 +296,7 @@ function SparseEnzymeADHessian(
279296 cx,
280297 f,
281298 ℓ,
299+ xbuf,
282300 )
283301end
284302
@@ -366,23 +384,29 @@ end
366384 end
367385
368386 function Jprod! (b:: EnzymeReverseADJprod , Jv, c!, x, v, :: Val )
387+ copyto! (b. xbuf, x)
388+ copyto! (b. vbuf, v)
369389 Enzyme. autodiff (
370390 Enzyme. Forward,
371391 Enzyme. Const (c!),
372- Enzyme. Duplicated (b. cx, Jv ),
373- Enzyme. Duplicated (x, v ),
392+ Enzyme. Duplicated (b. cx, b . jvbuf ),
393+ Enzyme. Duplicated (b . xbuf, b . vbuf ),
374394 )
395+ copyto! (Jv, b. jvbuf)
375396 return Jv
376397 end
377398
378399 function Jtprod! (b:: EnzymeReverseADJtprod , Jtv, c!, x, v, :: Val )
379- Enzyme. make_zero! (Jtv)
400+ copyto! (b. xbuf, x)
401+ copyto! (b. vbuf, v)
402+ Enzyme. make_zero! (b. jtvbuf)
380403 Enzyme. autodiff (
381404 Enzyme. Reverse,
382405 Enzyme. Const (c!),
383- Enzyme. Duplicated (b. cx, v ),
384- Enzyme. Duplicated (x, Jtv ),
406+ Enzyme. Duplicated (b. cx, b . vbuf ),
407+ Enzyme. Duplicated (b . xbuf, b . jtvbuf ),
385408 )
409+ copyto! (Jtv, b. jtvbuf)
386410 return Jtv
387411 end
388412
442466 # SparseMatrixColorings.jl requires a SparseMatrixCSC for the decompression
443467 A = SparseMatrixCSC (b. ncon, b. nvar, b. colptr, b. rowval, b. nzval)
444468
469+ # Enzyme.Duplicated requires primal and shadow to have the same type.
470+ # Copy x into a pre-allocated buffer to ensure type match with b.v.
471+ copyto! (b. xbuf, x)
472+
445473 groups = column_groups (b. result_coloring)
446474 for (icol, cols) in enumerate (groups)
447475 # Update the seed
456484 Enzyme. Forward,
457485 Enzyme. Const (c!),
458486 Enzyme. Duplicated (b. cx, b. compressed_jacobian),
459- Enzyme. Duplicated (x , b. v),
487+ Enzyme. Duplicated (b . xbuf , b. v),
460488 )
461489
462490 # Update the columns of the Jacobian that have the color `icol`
531559 # SparseMatrixColorings.jl requires a SparseMatrixCSC for the decompression
532560 A = SparseMatrixCSC (b. nvar, b. nvar, b. colptr, b. rowval, b. nzval)
533561
562+ # Enzyme.Duplicated requires primal and shadow to have the same type.
563+ # Copy x into a pre-allocated buffer to ensure type match with b.v.
564+ copyto! (b. xbuf, x)
565+
534566 groups = column_groups (b. result_coloring)
535567 for (icol, cols) in enumerate (groups)
536568 # Update the seed
542574 _hvp! (
543575 Enzyme. DuplicatedNoNeed (b. grad, b. compressed_hessian_icol),
544576 b. ℓ,
545- x ,
577+ b . xbuf ,
546578 b. v,
547579 y,
548580 obj_weight,
0 commit comments