# Illustration of Jacobi Fields

This tutorial illustrates the usage of Jacobi Fields within `Manopt.jl`

. For this tutorial, you should be familiar with the basic terminology on a manifold like the exponential and logarithmic maps, as well as the shortest geodesics.

## Setup

If you open this notebook in Pluto locally it switches between two modes. If the tutorial is within the `Manopt.jl`

repository, this notebook tries to use the local package in development mode. Otherwise, the file uses the Pluto pacakge management version. In this case, the includsion of images might be broken. unless you create a subfolder `optimize`

and activate `asy`

-rendering.

Since the loading is a little complicated, we show, which versions of packages were installed in the following.

```
with_terminal() do
Pkg.status()
end
```

�[32m�[1mStatus�[22m�[39m `/private/var/folders/_v/wg192lpd3mb1lp55zz7drpcw0000gn/T/jl_8IOXV7/Project.toml` �[90m [5ae59095] �[39mColors v0.12.10 �[90m [af67fdf4] �[39mManifoldDiff v0.2.0 �[90m [1cead3c2] �[39mManifolds v0.8.42 �[90m [0fc0a36d] �[39mManopt v0.4.0 `~/Repositories/Julia/Manopt.jl` �[90m [7f904dfe] �[39mPlutoUI v0.7.49 �[90m [44cfe95a] �[39mPkg v1.8.0 �[90m [9a3f8284] �[39mRandom

and we define some colors from Paul Tol

```
begin
black = RGBA{Float64}(colorant"#000000")
TolVibrantMagenta = RGBA{Float64}(colorant"#EE3377")
TolVibrantOrange = RGBA{Float64}(colorant"#EE7733")
TolVibrantCyan = RGBA{Float64}(colorant"#33BBEE")
TolVibrantTeal = RGBA{Float64}(colorant"#009988")
end;
```

and setup our graphics paths

```
begin
localpath = join(splitpath(@__FILE__)[1:(end - 1)], "/") # files folder
image_prefix = localpath * "/jacobi_fields"
#@info image_prefix
render_asy = false # on CI or when you do not have asymptote, this should be false
end;
```

Assume we have two points on the equator of the Sphere$\mathcal M = \mathbb S^2$

`M = Sphere(2)`

Sphere(2, ℝ)

`p, q = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]`

2-element Vector{Vector{Float64}}: [1.0, 0.0, 0.0] [0.0, 1.0, 0.0]

Their connecting shortest geodesic (sampled at `100`

points)

`geodesic_curve = shortest_geodesic(M, p, q, [0:0.1:1.0...]);`

is just a curve along the equator

```
render_asy && asymptote_export_S2_signals(
image_prefix * "/jacobi_geodesic.asy";
curves=[geodesic_curve],
points=[[p, q]],
colors=Dict(:curves => [black], :points => [TolVibrantOrange]),
dot_size=3.5,
line_width=0.75,
camera_position=(1.0, 1.0, 0.5),
);
```

`render_asy && render_asymptote(image_prefix * "/jacobi_geodesic.asy"; render=2);`

`PlutoUI.LocalResource(image_prefix * "/jacobi_geodesic.png")`

where $p$ is on the left and $q$ on the right. We now solve the following task.

Given a direction $X ∈ T_p\mathcal M$, for example

3-element Vector{Float64}: 0.0 0.4 0.5

in which we move the starting point $x$, how does any point on the geodesic move?

Or mathematically: compute $D_p g(t; p,q)$ for some fixed $t∈[0,1]$ and a given direction $X_p$. Of course two cases are quite easy: for $t=0$ we are in $x$ and how $x$ “moves” is already known, so $D_x g(0;p,q) = X$. On the other side, for $t=1$, $g(1; p,q) = q$ which is fixed, so $D_p g(1; p,q)$ is the zero tangent vector (in $T_q\mathcal M$).

For all other cases we employ a `jacobi_field`

, which is a (tangent) vector field along the shortest geodesic given as follows: the *geodesic variation*$\Gamma_{g,X}(s,t)$ is defined for some $\varepsilon > 0$ as

$$\Gamma_{g,X}(s,t):=\exp_{\gamma_{p,X}(s)}[t\log_{g(s;p,X)}p],\qquad s∈(-\varepsilon,\varepsilon),\ t∈[0,1].$$

Intuitively, we make a small step $s$ into the direction of $ξ$ using the geodesic $g(⋅; p,X)$ and from $r=g(s; p,X)$ we follow (in $t$) the geodesic $g(⋅; r,q)$. The corresponding Jacobi field $J_{g,X}$ along $g(⋅; p,q)$ is given by

$$J_{g,X}(t):=\frac{D}{\partial s}\Gamma_{g,X}(s,t)\Bigl\rvert_{s=0}$$

which is an ODE and we know the boundary conditions $J_{g,X}(0)=X$ and $J_{g,X}(t) = 0$. In symmetric spaces we can compute the solution, since the system of ODEs decouples, see for example [doCarmo1992], Chapter 4.2. Within `Manopt.jl`

this is implemented as `jacobi_field(M,p,q,t,X[,β])`

, where the optional parameter (function) $β$ specifies which Jacobi field we want to evaluate and the one used here is the default.

We can hence evaluate that on the points on the geodesic at

`T = [0:0.1:1.0...];`

namely

`r = shortest_geodesic(M, p, q, T);`

The tangent vector now moves as a differential along the geodesic as

`W = Manopt.jacobi_field.(Ref(M), Ref(p), Ref(q), T, Ref(X), ManifoldDiff.:βdifferential_shortest_geodesic_startpoint);`

Which can also be called using `differential_shortest_geodesic_startpoint`

. We can add to the image above by creating extended tangent vectors that include their base points

`V = [Tuple([a, b]) for (a, b) in zip(r, W)];`

to add the vectors as one further set to the Asymptote export.

```
render_asy && asymptote_export_S2_signals(
image_prefix * "/jacobi_geodesic_diff_start.asy";
curves=[geodesic_curve],
points=[[p, q], r],
tangent_vectors=[V],
colors=Dict(
:curves => [black],
:points => [TolVibrantOrange, TolVibrantCyan],
:tvectors => [TolVibrantCyan],
),
dot_sizes=[3.5, 2.0],
line_width=0.75,
camera_position=(1.0, 1.0, 0.5),
);
```

`render_asy && render_asymptote(image_prefix * "/jacobi_geodesic_diff_start.asy"; render=2);`

The interpretation is as follows: if an infinitesimal change of the starting point in the direction of $X$ happened, the infinitesimal change of a point along the line would change as indicated.

Note that each new vector is a tangent vector to its point (up to a small numerical tolerance), so the blue vectors are not just “shifted and scaled versions” of $X$.

`all([is_vector(M, a[1], a[2]; atol=1e-15) for a in V])`

true

If we further move the end point, too, we can derive that differential in direction

```
begin
Y = [0.2, 0.0, -0.5]
W2 = Manopt.differential_shortest_geodesic_endpoint.(Ref(M), Ref(p), Ref(q), T, Ref(Y))
V2 = [Tuple([a, b]) for (a, b) in zip(r, W2)]
end;
```

and we can combine both vector fields we obtained

`V3 = [Tuple([a, b]) for (a, b) in zip(r, W2 + W)];`

```
render_asy && asymptote_export_S2_signals(
image_prefix * "/jacobi_geodesic_complete.asy";
curves=[geodesic_curve],
points=[[p, q], r],
tangent_vectors=[V, V2, V3],
colors=Dict(
:curves => [black],
:points => [TolVibrantOrange, TolVibrantCyan],
:tvectors => [TolVibrantCyan, TolVibrantMagenta, TolVibrantTeal],
),
dot_sizes=[3.5, 2.0],
line_width=0.75,
camera_position=(1.0, 1.0, 0.0),
);
```

`render_asy && render_asymptote(image_prefix * "/jacobi_geodesic_complete.asy"; render=2);`

`PlutoUI.LocalResource(image_prefix * "/jacobi_geodesic_complete.png")`

Here, the first vector field is still in blue, the second is in magenta, and their combined effect is in teal. Sure, as a differential this does not make much sense; maybe as an infinitesimal movement of both starting point and endpoint combined.

## Literature

doCarmo1992

do Carmo, Manfredo

Riemannian Geometry, Birkhäuser Boston, 1992, ISBN: 0-8176-3490-8.