# Automatic differentiation in different cases

**URL:** https://discourse.julialang.org/t/automatic-differentiation-in-different-cases/98268
**Category:** Numerics
**Tags:** differentiation, math, autodiff
**Created:** [May 3, 2023, 6:22pm UTC](https://discourse.julialang.org/t/automatic-differentiation-in-different-cases/98268 "2023-05-03T18:22:19Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![Djamil\_Lakhdar-Hamin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djamil_lakhdar-hamin/32/19910_2.png) [@Djamil\_Lakhdar-Hamin](https://discourse.julialang.org/u/Djamil_Lakhdar-Hamin)
#### Post date: [May 3, 2023, 6:22pm UTC](https://discourse.julialang.org/t/automatic-differentiation-in-different-cases/98268/1 "2023-05-03T18:22:20Z")

</div>

I am trying to figure out :

1. how to automatically differentiate some function f(x1,x2,x3…) for vector of numbers. I want to use one package preferably , but if I have to mix, I want to mix zygote with ForwardDiff.

I think I have this down in using something like :

g(x,y)=x^2+y^2  
ForwardDiff.gradient(z → g(z[1], z[2]), [1.0, 2.0])

I guess if I wanted to take gradient for a vector, where I evaluate each partial derivative at the _same_ point I could do :

X=[1.0,2.0,3.0]

for elem in X  
ForwardDiff.gradient(z -\>g(z[1], z[2]),[elem,elem])  
end

This seems hacky and inefficient , and I know I can use static vectors to speed things up somewhat.

Next:

1. I want to evaluate a laplacian , a double gradient, for some multivariable function f(x1,x2,x3…) for a vector of numbers.

I guess I could chain the gradient function?

1. I want to evaluate a gradient f(x1,x2,x3,…) where I only evaluate for one variable, and I set say x2=1.0, x3=3.0

The way I have been doing this is grotesque , I simply recompile my function as a single variable function with a new global variable value put in for the x2,x3…

Thank you! I feel that this thread should be very useful.

---

<div class="post-metadata">

### Author: ![JonasWickman](https://avatars.discourse-cdn.com/v4/letter/j/9de0a6/32.png) [@JonasWickman](https://discourse.julialang.org/u/JonasWickman)
#### Post date: [May 3, 2023, 7:54pm UTC](https://discourse.julialang.org/t/automatic-differentiation-in-different-cases/98268/2 "2023-05-03T19:54:09Z")

</div>

I didn’t fully understand all those questions, but here is some code for ForwardDiff that can hopefully be helpful. Generally, I’d say it’s easier to work with functions `f(x)` where `x` is a vector, rather than functions `f(x1,x2,x3,...)` when using ForwardDiff. To make your future posts easier to read, include code in backticks ` (single for inline, triple for multiline).

```julia
using ForwardDiff
using StaticArrays
## --

# Function
f(x1,x2) = x1^2 + x2^2
f(x) = f(x[1],x[2])

# Gradient
∇f(x) = ForwardDiff.gradient( f , x )
∇f(x1,x2) = ∇f(SVector(x1,x2))

# Double gradient (?)
∇²f(x) = ForwardDiff.hessian( f , x )
∇²f(x1,x2) = ∇²f(SVector(x1,x2))

# Laplacian 
f1(x) = ForwardDiff.derivative( x1 -> f(x1,x[2]) , x[1] )
f2(x) = ForwardDiff.derivative( x2 -> f(x[1],x2) , x[2] )
f11(x) = ForwardDiff.derivative( x1 -> f1( SVector(x1,x[2]) ) , x[1] )
f22(x) = ForwardDiff.derivative( x2 -> f2( SVector(x[1],x2) ) , x[2] )
Δf(x) = f11(x) + f22(x) 
Δf(x1,x2) = Δf( SVector(x1,x2) )

# Evaluate

x1 = 1.0
x2 = 2.0

f(x1,x2)
∇f(x1,x2)
∇²f(x1,x2)
Δf(x1,x2)

# For a vector of numbers?

num_vec = [SVector(rand(),rand()) for _ ∈ 1:5]

Δf.(num_vec)

```

The code for the Laplacian is admittedly a little gnarly, if you want to do many higher-order directional derivatives, then [TaylorDiff.jl](https://github.com/JuliaDiff/TaylorDiff.jl) is probably a better choice.

---

<div class="post-metadata">

### Author: ![empet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empet/32/221303_2.png) [@empet](https://discourse.julialang.org/u/empet)
#### Post date: [May 3, 2023, 8:10pm UTC](https://discourse.julialang.org/t/automatic-differentiation-in-different-cases/98268/3 "2023-05-03T20:10:57Z")

</div>

Laplacian is the trace of Hessian.

```julia
import LinearAlgebra:tr
g(x) = x[1]^2*sin(x[2]-x[1])
Δg=tr(ForwardDiff.hessian(g, [π/2, π/6]))

```
