# Issue with ForwardDiff custom AD rule

**URL:** <https://discourse.julialang.org/t/issue-with-forwarddiff-custom-ad-rule/72886>\
**Category:** Specific Domains\
**Tags:** question, forwarddiff\
**Created:** [December 10, 2021, 10:44am UTC](https://discourse.julialang.org/t/issue-with-forwarddiff-custom-ad-rule/72886 "2021-12-10T10:44:36Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [December 10, 2021, 10:44am UTC](https://discourse.julialang.org/t/issue-with-forwarddiff-custom-ad-rule/72886/1 "2021-12-10T10:44:36Z")

</div>

I have the following issue:

```julia
import ForwardDiff, DiffRules, IrrationalConstants, SpecialFunctions
∂logerfcx(x) = 2 * (x - inv(SpecialFunctions.erfcx(x)) / IrrationalConstants.sqrtπ)
DiffRules.@define_diffrule SpecialFunctions.logerfcx(x) = :(∂logerfcx($x))
ForwardDiff.derivative(SpecialFunctions.logerfcx, 4)

```

This gives the following error:

> ERROR: MethodError: no method matching \_logerfcx(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(SpecialFunctions.logerfcx), Int64}, Float64, 1})  
> Closest candidates are:  
> \_logerfcx(::Union{Float32, Float64, BigFloat}) at ~/.julia/packages/SpecialFunctions/NBIqR/src/erf.jl:552  
> Stacktrace:  
> [1] logerfcx(x::ForwardDiff.Dual{ForwardDiff.Tag{typeof(SpecialFunctions.logerfcx), Int64}, Int64, 1})  
> @ SpecialFunctions ~/.julia/packages/SpecialFunctions/NBIqR/src/erf.jl:550  
> [2] derivative(f::typeof(SpecialFunctions.logerfcx), x::Int64)  
> @ ForwardDiff ~/.julia/packages/ForwardDiff/tZ5o1/src/derivative.jl:14  
> [3] top-level scope  
> @ REPL[15]:1

Why is ForwardDiff not picking up the custom rule I defined?

Related: [Broadcast gradient error · Issue #1132 · FluxML/Zygote.jl · GitHub](https://github.com/FluxML/Zygote.jl/issues/1132)

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [December 10, 2021, 11:40am UTC](https://discourse.julialang.org/t/issue-with-forwarddiff-custom-ad-rule/72886/2 "2021-12-10T11:40:55Z")

</div>

The rules for ForwardDiff are generated at using time. You need to add the rules to DiffRules.jl directly.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [December 10, 2021, 11:41am UTC](https://discourse.julialang.org/t/issue-with-forwarddiff-custom-ad-rule/72886/3 "2021-12-10T11:41:47Z")

</div>

You mean in a pull request to the DiffRules.jl package?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [December 10, 2021, 11:48am UTC](https://discourse.julialang.org/t/issue-with-forwarddiff-custom-ad-rule/72886/4 "2021-12-10T11:48:45Z")

</div>

yes

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [December 10, 2021, 11:53am UTC](https://discourse.julialang.org/t/issue-with-forwarddiff-custom-ad-rule/72886/5 "2021-12-10T11:53:21Z")

</div>

Ok done [https://github.com/JuliaDiff/DiffRules.jl/pull/74](https://github.com/JuliaDiff/DiffRules.jl/pull/74).  
Hope it gets merged quick.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [December 10, 2021, 12:19pm UTC](https://discourse.julialang.org/t/issue-with-forwarddiff-custom-ad-rule/72886/6 "2021-12-10T12:19:07Z")

</div>

Is there a hacky way to do it? Like defining a method for `::Dual` args?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [December 10, 2021, 1:08pm UTC](https://discourse.julialang.org/t/issue-with-forwarddiff-custom-ad-rule/72886/7 "2021-12-10T13:08:13Z")

</div>

> [@e3c6](#):
>
> Like defining a method for `::Dual` args?

Yes, see [https://github.com/JuliaDiff/ForwardDiff.jl/blob/ab0e239452cfa059e3c0d7467d6bb489e57ea1ab/src/dual.jl#L402](https://github.com/JuliaDiff/ForwardDiff.jl/blob/ab0e239452cfa059e3c0d7467d6bb489e57ea1ab/src/dual.jl#L402).

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [December 10, 2021, 1:22pm UTC](https://discourse.julialang.org/t/issue-with-forwarddiff-custom-ad-rule/72886/8 "2021-12-10T13:22:40Z")

</div>

Ah thanks @kristoffer.carlsson that works! For future reference,

```julia
∂logerfcx(x) = 2 * (x - inv(SpecialFunctions.erfcx(x)) / IrrationalConstants.sqrtπ)
DiffRules.@define_diffrule SpecialFunctions.logerfcx(x) = :(∂logerfcx($x))
eval(ForwardDiff.unary_dual_definition(:SpecialFunctions, :logerfcx))

```

And now `ForwardDiff.derivative(SpecialFunctions.logerfcx, 4)` works 🙂
