Function phi() function in the stokes package

phi
function (n) 
{
    ktensor(spray(n, 1))
}

To cite the stokes package in publications, please use Hankin (2022b). Function phi() returns a tensor dual to the standard basis of V = ℝn. Here I discuss phi() but there is some overlap between this vignette and the tensorprod vignette.

In a memorable passage, Spivak (1965) states (theorem 4.1):

Integration on chains

Let v1, …, vn be a basis for V, and let ϕ1, …, ϕn be the dual basis, ϕi(vj) = δij. Then the set of all k-fold tensor products

ϕi1 ⊗ ⋯ ⊗ ϕik   1 ≤ i1, …, ik ≤ n

is a basis for 𝒥(V), which therefore has dimension nk.

- Michael Spivak, 1969 (Calculus on Manifolds, Perseus books). Page 75

Function phi() returns a very simple tensor:

phi(4)
## A linear map from V^1 to R with V=R^4:
##        val
##  4  =    1

First we will verify the properties of phi(), using V = ℝ5, specifically

$$ \phi_i(e_j) = \delta_{ij} = \begin{cases} 1, & i=j\\ 0 & i\neq j. \end{cases} $$

(package idiom is to use e() for basis vectors as opposed to Spivak’s v). As numerical verification, we will check that ϕ3(e2) = 0, ϕ3(e3) = 1, ϕ3(e4) = 0:

f <- as.function(phi(3))
c(f(as.matrix(e(2,5))), f(as.matrix(e(3,5))), f(as.matrix(e(4,5))))
## [1] 0 1 0

A more severe test might be

aa <- function(n){
   outer(seq_len(n), seq_len(n),
   Vectorize(function(i, j){as.function(phi(i))(as.matrix(e(j, n)))}))
}

aa(5)
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    0    0    0    0
## [2,]    0    1    0    0    0
## [3,]    0    0    1    0    0
## [4,]    0    0    0    1    0
## [5,]    0    0    0    0    1

Above, we see that the matrix is I5, as expected. Further:

all(aa(9) == diag(9))
## [1] TRUE

The objects created by phi() may be multiplied together using tensorprod() or its binary operator %X%:

phi(4) %X% phi(3) %X% phi(5)
## A linear map from V^3 to R with V=R^5:
##            val
##  4 3 5  =    1

If we want to create arbitrary tensor products of ϕ objects the most natural way would be to use tensorprod() repeatedly:

Reduce(`%X%`,sapply(4:8,phi))
## A linear map from V^5 to R with V=R^8:
##                val
##  4 5 6 7 8  =    1

However, function phi() simply takes a vector:

phi(c(2,5,1))
## A linear map from V^3 to R with V=R^5:
##            val
##  2 5 1  =    1

This creates an element of the basis set, in this case ϕ2 ⊗ ϕ5 ⊗ ϕ1. Verification is straightforward:

(v <- sample(9))
## [1] 9 4 7 1 2 6 3 8 5
phi(v) == Reduce(`%X%`,sapply(v,phi))
## [1] TRUE

We will consider an element X of 𝒥2(V) where V = ℝ3 and construct an explicit basis for it along the lines of Spivak’s observation above.

(X <- ktensor(spray(matrix(c(1,2,3,2,1,1),3,2),1:3)))
## A linear map from V^2 to R with V=R^3:
##          val
##  3 1  =    3
##  2 1  =    2
##  1 2  =    1

Thus X = ϕ1 ⊗ ϕ2 + 2ϕ2 ⊗ ϕ1 + 3ϕ3 ⊗ ϕ1. Spivak asserts that 𝒥2(V) has dimension nk = 32 = 9.

1*phi(c(1,2)) + 2*phi(c(2,1)) + 3*phi(c(3,1))
## A linear map from V^2 to R with V=R^3:
##          val
##  2 1  =    2
##  1 2  =    1
##  3 1  =    3

With a little effort, we can create all 32 = 9 elements of a basis as follows:

apply(expand.grid(rep(list(seq_len(3)),2)),1,phi)
## [[1]]
## A linear map from V^2 to R with V=R^1:
##          val
##  1 1  =    1
## 
## [[2]]
## A linear map from V^2 to R with V=R^2:
##          val
##  2 1  =    1
## 
## [[3]]
## A linear map from V^2 to R with V=R^3:
##          val
##  3 1  =    1
## 
## [[4]]
## A linear map from V^2 to R with V=R^2:
##          val
##  1 2  =    1
## 
## [[5]]
## A linear map from V^2 to R with V=R^2:
##          val
##  2 2  =    1
## 
## [[6]]
## A linear map from V^2 to R with V=R^3:
##          val
##  3 2  =    1
## 
## [[7]]
## A linear map from V^2 to R with V=R^3:
##          val
##  1 3  =    1
## 
## [[8]]
## A linear map from V^2 to R with V=R^3:
##          val
##  2 3  =    1
## 
## [[9]]
## A linear map from V^2 to R with V=R^3:
##          val
##  3 3  =    1

Or it might be logically better to use ellipsis constructs to pass multiple arguments:

s <- function(...){phi(unlist(list(...)))}
s(3,4,6)
## A linear map from V^3 to R with V=R^6:
##            val
##  3 4 6  =    1

Then we could have

1*s(1,2) + 2*s(2,1) + 3*s(3,1)
## A linear map from V^2 to R with V=R^3:
##          val
##  2 1  =    2
##  1 2  =    1
##  3 1  =    3
1*s(1,2) + 2*s(2,1) + 3*s(3,1) == X
## [1] TRUE

Distributivity

The tensor product is left- and right distributive. To illustrate this we can use the package to calculate, say, (2ϕ1 + 3ϕ2) ⊗ (5ϕ3 + 7ϕ4):

(2*phi(1) + 3*phi(2)) %X% (5*phi(3) + 7*phi(4) )
## A linear map from V^2 to R with V=R^4:
##          val
##  2 4  =   21
##  1 4  =   14
##  2 3  =   15
##  1 3  =   10

Above we see package form for the result which is 10ϕ1ϕ3 + 14ϕ1ϕ4 + 15ϕ2ϕ3 + 21ϕ2ϕ4 in algebraic notation.

Reconstruction of a given tensor

Consider the following tensor

(b <- ktensor(spray(matrix(c(3,4,7,5,4,3),3,2),7:9)))
## A linear map from V^2 to R with V=R^7:
##          val
##  4 4  =    8
##  7 3  =    9
##  3 5  =    7

We may express b as the sum of its three terms, each with a coefficient:

7*phi(c(3,5)) + 8*phi(c(4,4)) + 9*phi(c(7,3))
## A linear map from V^2 to R with V=R^7:
##          val
##  4 4  =    8
##  3 5  =    7
##  7 3  =    9

Above, observe that the order of the terms may differ between the two methods, as per disordR discipline (Hankin 2022a), but they are algebraically identical:

b == 7*phi(c(3,5)) + 8*phi(c(4,4)) + 9*phi(c(7,3))
## [1] TRUE

Function Alt()

Function Alt() returns an alternating tensor as documented in the Alt vignette in the package. It works nicely with phi():

phi(1:3)
## A linear map from V^3 to R with V=R^3:
##            val
##  1 2 3  =    1
Alt(6*phi(1:3))
## A linear map from V^3 to R with V=R^3:
##            val
##  3 2 1  =   -1
##  3 1 2  =    1
##  2 3 1  =    1
##  2 1 3  =   -1
##  1 3 2  =   -1
##  1 2 3  =    1

References

Hankin, R. K. S. 2022a. “Disordered Vectors in R: Introducing the disordR Package.” https://arxiv.org/abs/2210.03856; arXiv. https://doi.org/10.48550/ARXIV.2210.03856.
———. 2022b. “Stokes’s Theorem in R.” arXiv. https://doi.org/10.48550/ARXIV.2210.17008.
Spivak, M. 1965. Calculus on Manifolds. Addison-Wesley.