# ForwardDiff.gradient of function with nested functions calls

I’m trying to get gradient of function that calls another one.

``````using ForwardDiff, BenchmarkTools

const f_l, f_r = 0.0,0.0;
function J(f::AbstractArray, α::AbstractArray, mesh::AbstractArray)
J = 0.0;
N = length(f);

for i = 2:N - 1
J += ( (f[i+1] - f[i])/mesh[i] - α[i] )^2 ;
end

norm = x -> sobolev_1_1_norm(x,mesh);
J += norm(f);
return J
end
function sobolev_1_1_norm(f::AbstractArray,mesh::AbstractArray)
out = 0.0;
N = length(f);
for i = 1:N-1
out += f[i] + ((f[i+1] - f[i])/mesh[i])^2;
end
out += f[end] + ((f[end ] - f[end - 1])/mesh[end])^2;
end
∇J(z,α,mesh)  = ForwardDiff.gradient( x -> J(x, α, mesh), α, mesh);

size = 50;
α = rand(-pi:0.01:pi, size);
mesh = fill(0.2, size);
f = rand(size);

@btime J(f,α,mesh)
@btime ∇J(f,α,mesh)
``````

results in

``````julia> @btime J(f,α,mesh)

556.403 ns (1 allocation: 16 bytes)
678.466801231054

julia> @btime ∇J(f,α,mesh)

ERROR: MethodError: no method matching gradient(::getfield(Main, Symbol("##15#16")){Array{Float64,1},Array{Float64,1}}, ::Array{Float64,1}, ::Array{Float64,1})
Closest candidates are:
...
Stacktrace:
[1] ∇J(::Array{Float64,1}, ::Array{Float64,1}, ::Array{Float64,1}) at ./REPL[26]:1
[2] ##core#404() at /Users/user/.julia/packages/BenchmarkTools/dtwnm/src/execution.jl:293
[3] ##sample#405(::BenchmarkTools.Parameters) at /Users/user/.julia/packages/BenchmarkTools/dtwnm/src/execution.jl:299
[4] #_run#18(::Bool, ::String, ::Base.Iterators.Pairs{Symbol,Integer,NTuple{4,Symbol},NamedTuple{(:samples, :evals, :gctrial, :gcsample),Tuple{Int64,Int64,Bool,Bool}}}, ::Function, ::BenchmarkTools.Benchmark{Symbol("##benchmark#403")}, ::BenchmarkTools.Parameters) at /Users/user/.julia/packages/BenchmarkTools/dtwnm/src/execution.jl:327
[5] (::getfield(Base, Symbol("#inner#2")){Base.Iterators.Pairs{Symbol,Integer,NTuple{5,Symbol},NamedTuple{(:verbose, :samples, :evals, :gctrial, :gcsample),Tuple{Bool,Int64,Int64,Bool,Bool}}},typeof(BenchmarkTools._run),Tuple{BenchmarkTools.Benchmark{Symbol("##benchmark#403")},BenchmarkTools.Parameters}})() at ./none:0
[6] #invokelatest#1 at ./essentials.jl:690 [inlined]
[7] #invokelatest at ./none:0 [inlined]
[8] #run_result#16 at /Users/user/.julia/packages/BenchmarkTools/dtwnm/src/execution.jl:32 [inlined]
[9] #run_result at ./none:0 [inlined]
[10] #run#18(::Base.Iterators.Pairs{Symbol,Integer,NTuple{5,Symbol},NamedTuple{(:verbose, :samples, :evals, :gctrial, :gcsample),Tuple{Bool,Int64,Int64,Bool,Bool}}}, ::Function, ::BenchmarkTools.Benchmark{Symbol("##benchmark#403")}, ::BenchmarkTools.Parameters) at /Users/user/.julia/packages/BenchmarkTools/dtwnm/src/execution.jl:46
[11] #run at ./none:0 [inlined] (repeats 2 times)
[12] #warmup#21 at /Users/user/.julia/packages/BenchmarkTools/dtwnm/src/execution.jl:79 [inlined]
[13] warmup(::BenchmarkTools.Benchmark{Symbol("##benchmark#403")}) at /Users/user/.julia/packages/BenchmarkTools/dtwnm/src/execution.jl:79
[14] top-level scope at /Users/user/.julia/packages/BenchmarkTools/dtwnm/src/execution.jl:387
``````

What I’m missing?

``````∇J(z,α,mesh)  = ForwardDiff.gradient( x -> J(x, α, mesh), α, mesh);
``````

`z` is unused and you are giving two arguments to `gradient` after the function.

Did you mean

``````julia> ∇J(z,α,mesh)  = ForwardDiff.gradient( x -> J(x, α, mesh), z);

julia> @btime ∇J(f,α,mesh)
14.267 μs (4 allocations: 5.88 KiB)
``````

?

3 Likes

Yeah, that is what i mean and the answer.

Thx!