---
title: "The `hodge()` function in the `stokes` package"
author: "Robin K. S. Hankin"
output: html_vignette
bibliography: stokes.bib
link-citations: true
vignette: >
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteIndexEntry{hodge}
  %\usepackage[utf8]{inputenc}
---

```{r setup, include=FALSE}
set.seed(0)
library("permutations")
library("stokes")
options(rmarkdown.html_vignette.check_title = FALSE)
options(polyform = FALSE)
knitr::opts_chunk$set(echo = TRUE)
knit_print.function <- function(x, ...){dput(x)}
registerS3method(
  "knit_print", "function", knit_print.function,
  envir = asNamespace("knitr")
)
```

```{r out.width='20%', out.extra='style="float:right; padding:10px"',echo=FALSE}
knitr::include_graphics(system.file("help/figures/stokes.png", package = "stokes"))
```

```{r, label=showhodge,comment=""}
hodge
```

To cite the `stokes` package in publications, please use
@hankin2022_stokes.  Given a $k$-form $\beta$, function `hodge()`
returns its Hodge dual $\star\beta$.  Formally, if $V={\mathbb R}^n$,
and $\Lambda^k(V)$ is the space of alternating linear maps from $V^k$
to ${\mathbb R}$, then
$\star\colon\Lambda^k(V)\longrightarrow\Lambda^{n-k}(V)$.  To define
the Hodge dual, we need an inner product
$\left\langle\cdot,\cdot\right\rangle$ [function `kinner()` in the
package] and, given this and $\beta\in\Lambda^k(V)$ we define
$\star\beta$ to be the (unique) $n-k$-form satisfying the fundamental
relation:

$$
\alpha\wedge\left(\star\beta\right)=\left\langle\alpha,\beta\right\rangle\omega,$$

for every $\alpha\in\Lambda^k(V)$.  Here $\omega=e_1\wedge
e_2\wedge\cdots\wedge e_n$ is the unit $n$-vector of $\Lambda^n(V)$.
Taking determinants of this relation shows the following.  If we use
multi-index notation so $e_I=e_{i_1}\wedge\cdots\wedge e_{i_k}$ with
$I=\left\lbrace i_1,\cdots,i_k\right\rbrace$, then

$$\star e_I=(-1)^{\sigma(I)}e_J$$

where $J=\left\lbrace
j_i,\ldots,j_k\right\rbrace=[n]\setminus\left\lbrace
i_1,\ldots,i_k\right\rbrace$ is the complement of $I$, and
$(-1)^{\sigma(I)}$ is the sign of the permutation $\sigma(I)=i_1\cdots
i_kj_1\cdots j_{n-k}$.  We extend to the whole of $\Lambda^k(V)$ using
linearity.  Package idiom for calculating the Hodge dual is
straightforward, being simply `hodge()`.

```{r, label=setsymbprint,include = FALSE}
options(kform_symbolic_print = NULL)
```

## The Hodge dual on basis elements of $\Lambda^k(V)$

We start by demonstrating `hodge()` on basis elements of
$\Lambda^k(V)$.  Recall that if $\left\lbrace
e_1,\ldots,e_n\right\rbrace$ is a basis of vector space
$V=\mathbb{R}^n$, then
$\left\lbrace\omega_1,\ldots,\omega_k\right\rbrace$ is a basis of
$\Lambda^1(V)$, where $\omega_i(e_j)=\delta_{ij}$.  A basis of
$\Lambda^k(V)$ is given by the set

\[
\bigcup_{1\leqslant i_1 < \cdots < i_k\leqslant n}
\bigwedge_{j=1}^k\omega_{i_j}
=
\left\lbrace
\left.\omega_{i_1}\wedge\cdots\wedge\omega_{i_k}
\right|1\leqslant i_1 < \cdots < i_k\leqslant n
\right\rbrace.
\]

This means that basis elements are things like
$\omega_2\wedge\omega_6\wedge\omega_7$.  If $V=\mathbb{R}^9$, what is
$\star\omega_2\wedge\omega_6\wedge\omega_7$?


```{r,label=simpexamp}
(a <- d(2) ^ d(6) ^ d(7))
hodge(a,9)
```

See how $\star a$ has index entries 1-9 except $2,6,7$ (from $a$).
The (numerical) sign is negative because the permutation has negative
(permutational) sign.  We can verify this using the `permutations`
package:

```{r,label=useperm}
p <- c(2,6,7,  1,3,4,5,8,9)
(pw <- as.word(p))
print_word(pw)
sgn(pw)
```


Above we see the sign of the permutation is negative.  More succinct
idiom would be

```{r,label=shorthodge}
hodge(d(c(2,6,7)),9)
```

The second argument to `hodge()` is needed if the largest index $i_k$
of the first argument is less than $n$; the default value is indeed
$n$.  In the example above, this is $7$:

```{r label=defaulthodge}
hodge(d(c(2,6,7)))
```

Above we see the result if $V=\mathbb{R}^7$.

## More complicated examples

The hodge operator is linear and it is interesting to verify this.

```{r,defineo}
(o <- rform())
hodge(o)
```

We verify that the fundamental relation holds by direct inspection:

```{r verifyhodgeo}
o ^ hodge(o)
kinner(o,o)*volume(dovs(o))
```

showing agreement (above, we use function `volume()` in lieu of
calculating the permutation's sign explicitly.  See the `volume`
vignette for more details).  We may work more formally by defining a
function that returns `TRUE` if the left and right hand sides match

```{r defdif}
diff <- function(a,b){a^hodge(b) ==  kinner(a,b)*volume(dovs(a))}
```

and call it with random $k$-forms:

```{r calldefdif}
diff(rform(),rform())
```

Or even

```{r alldefdif}
all(replicate(10,diff(rform(),rform())))
```

## Small-dimensional vector spaces

We can work in three dimensions in which case we have three linearly
independent $1$-forms: $dx$, $dy$, and $dz$.  To work in this system
it is better to use `dx` print method:

```{r}
options(kform_symbolic_print = "dx")
hodge(dx,3)
```

This is further discussed in the `dovs` vignette.

## Vector cross product identities

The three dimensional vector cross product
$\mathbf{u}\times\mathbf{v}=\det\begin{pmatrix} i & j & k \\
u_1&u_2&u_3\\ v_1&v_2&v_3 \end{pmatrix}$ is a standard part of
elementary vector calculus.  In the package the idiom is as follows:

```{r showvcp}
vcp3
```

revealing the formal definition of cross product as
$\mathbf{u}\times\mathbf{v}=\star{\left(\mathbf{u}\wedge\mathbf{v}\right)}$.
There are several elementary identities that are satisfied by the
cross product:

$$
\begin{aligned}
\mathbf{u}\times(\mathbf{v}\times\mathbf{w}) &= \mathbf{v}(\mathbf{w}\cdot\mathbf{u})-\mathbf{w}(\mathbf{u}\cdot\mathbf{v})\\
(\mathbf{u}\times\mathbf{v})\times\mathbf{w} &= \mathbf{v}(\mathbf{w}\cdot\mathbf{u})-\mathbf{u}(\mathbf{v}\cdot\mathbf{w})\\
(\mathbf{u}\times\mathbf{v})\times(\mathbf{u}\times\mathbf{w}) &= (\mathbf{u}\cdot(\mathbf{v}\times\mathbf{w}))\mathbf{u}  \\
(\mathbf{u}\times\mathbf{v})\cdot(\mathbf{w}\times\mathbf{x})  &= (\mathbf{u}\cdot\mathbf{w})(\mathbf{v}\cdot\mathbf{x}) -
                                                                  (\mathbf{u}\cdot\mathbf{x})(\mathbf{v}\cdot\mathbf{w})
\end{aligned}
$$

We may verify all four together:

```{r}
u <- c(1,4,2)
v <- c(2,1,5)
w <- c(1,-3,2)
x <- c(-6,5,7)
c(
  hodge(as.1form(u) ^ vcp3(v,w))        == as.1form(v*sum(w*u) - w*sum(u*v)),
  hodge(vcp3(u,v) ^ as.1form(w))        == as.1form(v*sum(w*u) - u*sum(v*w)),
  as.1form(as.function(vcp3(v,w))(u)*u) == hodge(vcp3(u,v) ^ vcp3(u,w))     ,
  hodge(hodge(vcp3(u,v)) ^ vcp3(w,x))   == sum(u*w)*sum(v*x) - sum(u*x)*sum(v*w)
)		  
```

Above, note the use of the hodge operator to define triple vector
cross products.  For example we have
$\mathbf{u}\times\left(\mathbf{v}\times\mathbf{w}\right)=
\star\left(\mathbf{u}\wedge\star\left(\mathbf{v}\wedge\mathbf{w}\right)\right)$.

# Non positive-definite metrics

The inner product $\left\langle\alpha,\beta\right\rangle$ above may be
generalized by defining it on decomposable vectors
$\alpha=\alpha_1\wedge\cdots\wedge\alpha_k$ and
$\beta=\beta_1\wedge\cdots\wedge\beta_k$ as

$$\left\langle\alpha,\beta\right\rangle=
\det\left(\left\langle\alpha_i,\beta_j\right\rangle_{i,j}\right)$$

where $\left\langle\alpha_i,\beta_j\right\rangle=\pm\delta_{ij}$ is an
inner product on $\Lambda^1(V)$ [the inner product is given by
`kinner()`].  The resulting Hodge star operator is implemented in the
package and one can specify the metric.  For example, if we consider
the Minkowski metric this would be $-1,1,1,1$.

## Print methods for the Minkowski metric

The standard print method is not particularly suitable for working
with the Minkowski metric:

```{r}
options(kform_symbolic_print = NULL)  # default print method
(o <- kform_general(4,2,1:6))
```

Above we see an unhelpful representation.  To work with $2$-forms in
relativistic physics, it is often preferable to use bespoke print
method `usetxyz`:

```{r}
options(kform_symbolic_print = "txyz")
o
```

## Specifying the Minkowski metric

Function `hodge()` takes a `g` argument to specify the metric:

```{r}
hodge(o)
hodge(o,g=c(-1,1,1,1))
hodge(o)-hodge(o,g=c(-1,1,1,1))
```


```{r reset_default_print_method, include=FALSE}
options(kform_symbolic_print = NULL)
```

# References