# ZeroTangent definition

Hi,
I am using chainrulecore for gradient calculation and rrule. I am trying to follow tutorial 18 of gridap. I cant understand the ZeroTangent in the code why we are using that and what it is suppose to do. I’ve read some thing on documentations but it is not clear to me.
thank you

``````using ChainRulesCore, Zygote
import ChainRulesCore: rrule
NO_FIELDS = ZeroTangent()
``````
``````function gf_pf(pf_vec; β, η, phys_params, fem_params)
pfh = FEFunction(fem_params.Pf, pf_vec)
pth = (pf -> Threshold(pf; β, η)) ∘ pfh
A_mat = MatrixA(pth; phys_params, fem_params)
b_vec = assemble_vector(v->(∫(v)fem_params.dΓ_s), fem_params.V)
u_vec = A_mat \ b_vec

O_mat = MatrixOf(fem_params)
real(u_vec' * O_mat * u_vec)
end

function rrule(::typeof(gf_pf), pf_vec; β, η, phys_params, fem_params)
function U_pullback(dgdg)
NO_FIELDS, dgdg * Dgfdpf(pf_vec; β, η, phys_params, fem_params)
end
gf_pf(pf_vec; β, η, phys_params, fem_params), U_pullback
end
``````

One thing that somewhat helped my understanding of ChainRulesCore.jl is testing my code using ChainRulesTestUtils.jl:

At first glance it seems this one should actually be `NoTangent()`, but the `NO_FIELDS` renaming is a good clue. The pullback takes an output perturbation and “pulls it back” into an input perturbation. But the input includes the function `gf_pf` itself: it might be that this function has internal fields involved in differentiation (for instance if it is a closure or a callable `struct`). Here, the first element returned by `U_pullback` tells us that the derivative of the function output with respect to the function object itself is zero (or undefined with `NoTangent`).