# ZeroTangent definition

**URL:** <https://discourse.julialang.org/t/zerotangent-definition/118069>\
**Category:** New to Julia\
**Tags:** differentiation, chainrulescore, gradient\
**Created:** [August 11, 2024, 6:17pm UTC](https://discourse.julialang.org/t/zerotangent-definition/118069 "2024-08-11T18:17:04Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![mary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mary/32/53139_2.png) [@mary](https://discourse.julialang.org/u/mary)\
**Post date:** [August 11, 2024, 6:17pm UTC](https://discourse.julialang.org/t/zerotangent-definition/118069/1 "2024-08-11T18:17:04Z")

</div>

Hi,  
I am using chainrulecore for gradient calculation and rrule. I am trying to follow tutorial [18](https://gridap.github.io/Tutorials/dev/pages/t018_TopOptEMFocus/) 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

```julia
using ChainRulesCore, Zygote
import ChainRulesCore: rrule
NO_FIELDS = ZeroTangent()

```

```julia
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

```

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [August 11, 2024, 7:12pm UTC](https://discourse.julialang.org/t/zerotangent-definition/118069/2 "2024-08-11T19:12:30Z")

</div>

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

[https://juliadiff.org/ChainRulesTestUtils.jl/stable/](https://juliadiff.org/ChainRulesTestUtils.jl/stable/)

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [August 12, 2024, 4:55am UTC](https://discourse.julialang.org/t/zerotangent-definition/118069/3 "2024-08-12T04:55:02Z")

</div>

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`).
