UnPack.jl provides functionality to get fields out of structs (@unpack) or replace fields back into structs (@pack!) with clean syntax. But it produces incorrect results with Enzyme. Running this code
using Enzyme
using UnPack
mutable struct PrognosticVars{F<:AbstractFloat, FV <: AbstractArray{F,1}}
# var: sea surface height [m]
# dim: (nCells)
a::FV
function PrognosticVars(a::AT2D) where {AT2D}
type = eltype(a)
new{type, AT2D}(a)
end
end
function get_sum(Prog::PrognosticVars)
sum = 0.0
for j = 1:size(Prog.a)[1]
sum = sum + Prog.a[j]
end
return sum
end
function get_sum_pack(Prog::PrognosticVars)
@unpack a = Prog
sum = 0.0
for j = 1:size(a)[1]
sum = sum + a[j]
end
@pack! Prog = a
return sum
end
a = [1., 2., 3.]
prog = PrognosticVars(a)
#sum = get_sum(prog)
d_prog = Enzyme.make_zero(prog)
d_sum = autodiff(Enzyme.Reverse, get_sum, Duplicated(prog, d_prog))
@show d_sum, d_prog
d_prog_pack = Enzyme.make_zero(prog)
d_sum_pack = autodiff(Enzyme.Reverse, get_sum_pack, Duplicated(prog, d_prog))
@show d_sum_pack, d_prog_pack
UnPack.jl provides functionality to get fields out of structs (
@unpack
) or replace fields back into structs (@pack!
) with clean syntax. But it produces incorrect results with Enzyme. Running this codeproduces these results:
Logically
d_prog_pack
should equald_prog
, since they both sum up the contents ofa
. Thepack!
andunpack
macros are just for syntax convenience.