--- title: "Function `tensorprod()` function in the `stokes` package" author: "Robin K. S. Hankin" output: html_vignette bibliography: stokes.bib link-citations: true vignette: > %\VignetteEngine{knitr::rmarkdown} %\VignetteIndexEntry{tensorprod} %\usepackage[utf8]{inputenc} --- ```{r setup, include=FALSE} set.seed(0) library("spray") library("stokes") options(rmarkdown.html_vignette.check_title = 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=showAlt,comment=""} tensorprod tensorprod2 ``` To cite the `stokes` package in publications, please use @hankin2022_stokes. Function `tensorprod()` returns the tensor cross product of any number of `ktensor` objects; `tensorprod2()` is a lower-level helper function that returns the product of two such objects. These functions use `spraycross()` from the `spray` package [@hankin2022_spray]. ### The tensor cross product In a memorable passage, @spivak1965 states: <div class="warning" style='padding:0.1em; background-color:#E9D8FD; color:#69337A'> <span> <p style='margin-top:1em; text-align:center'> <b>Integration on chains</b></p> <p style='margin-left:1em;'> If $V$ is a vector space over $\mathbb{R}$, we denote the $k$-fold product $V\times\cdots\times V$ by $V^k$. A function $T\colon V^k\longrightarrow\mathbb{R}$ is called *multilinear* if for each $i$ with $1\leqslant i\leqslant k$ we have $$ T\left(v_1,\ldots, v_i + {v'}_i,\ldots, v_k\right)= T\left(v_1,\ldots,v_i,\ldots,v_k\right)+ T\left(v_1,\ldots,{v'}_i,\ldots,v_k\right),\\ T\left(v_1,\ldots,av_i,\ldots,v_k\right)=aT\left(v_1,\ldots,v_i,\ldots,v_k\right). $$ A multilinear function $T\colon V^k\longrightarrow\mathbb{R}$ is called a *$k$-tensor* on $V$ and the set of all $k$-tensors, denoted by $\mathcal{J}^k(V)$, becomes a vector space (over $\mathbb{R}$) if for $S,T\in\mathcal{J}^k(V)$ and $a\in\mathbb{R}$ we define $$ (S+T)(v_1,\ldots,v_k) = S(v_1,\ldots,v_k) + T(v_1,\ldots,v_k)\\ (aS)(v_1,\ldots,v_k) = a\cdot S(v_1,\ldots,v_k). $$ There is also an operation connecting the various spaces $\mathcal{J}(V)$. If $S\in\mathcal{J}^k(V)$ and $T\in\mathcal{J}^l(V)$, we define the *tensor product* $S\otimes T\in\mathcal{J}^{k+l}(V)$ by $$ S\otimes T(v_1,\ldots,v_k,v_{k+1},\ldots,v_{k+l})= S(v_1,\ldots,v_k)\cdot T(v_{k+1},\ldots,v_{k+l}). $$ </p> <p style='margin-bottom:1em; margin-right:1em; text-align:right; font-family:Georgia'> <b>- Michael Spivak, 1969</b> <i>(Calculus on Manifolds, Perseus books). Page 75</i> </p></span> </div> Spivak goes on to observe that the tensor product is distributive and associative but not commutative. He then proves that the set of all $k$-fold tensor products $$ \phi_{i_1}\otimes\cdots\otimes\phi_{i_k},\qquad 1\leqslant i_1,\ldots,i_k\leqslant n $$ [where $\phi_i(v_j)=\delta_{ij}$,$v_1,\ldots,v_k$ being a basis for $V$] is a basis for $\mathcal{J}^k(V)$, which therefore has dimension $n^k$. Function `tensorprod()` evaluates the tensor product and I give examples here. ```{r} (a <- ktensor(spray(matrix(c(1,1,2,1),2,2),3:4))) (b <- ktensor(spray(matrix(c(3,4,7,5,4,3),3,2),7:9))) ``` Thus $a=4\phi_1\otimes\phi_1+3\phi_1\otimes\phi_2$ and $b=7\phi_3\otimes\phi_5+8\phi_4\otimes\phi_4+9\phi_7\otimes\phi_3$. Now the cross product $a\otimes b$ is given by `tensorprod()`: ```{r} tensorprod(a,b) ``` We can see that the product includes the term $21\phi_1\otimes\phi_2\otimes\phi_3\otimes\phi_5$ and five others. ## Verification Spivak proves that the tensor product is associative and distributive, which are demonstrated here. ```{r} S <- rtensor() T <- rtensor() U <- rtensor() c( left_distributive = S %X% (T+U) == S*T + S*U, right_distributive = (S+T) %X% U == S %X% U + T %X% U, associative = S %X% (T %X% U) == (S %X% T) %X% U ) ``` ### Note on associativity It is interesting to note that, while the tensor product is associative, disord discipline obscures this fact. Consider the following: ```{r} x <- ktensor(spray(matrix(c(1,1,2,1),2,2),1:2)) y <- ktensor(spray(matrix(c(3,4,7,5,4,3),3,2),1:3)) z <- ktensor(spray(matrix(c(1,1,2,1),2,2),1:2)) tensorprod(x, tensorprod(y, z)) tensorprod(tensorprod(x, y), z) ``` The two products are algebraically identical but the terms appear in a different order. ```{r echo=FALSE} rm(T) # tidyup ``` # References