The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Function phi() function in the stokes package

Robin K. S. Hankin

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=\mathbb{R}^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 \(v_1,\ldots,v_n\) be a basis for \(V\), and let \(\phi_1,\ldots,\phi_n\) be the dual basis, \(\phi_i(v_j)=\delta_{ij}\). Then 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 \]

is a basis for \(\mathcal{J}(V)\), which therefore has dimension \(n^k\).

- 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=\mathbb{R}^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 \(\phi_3(e_2)=0\), \(\phi_3(e_3)=1\), \(\phi_3(e_4)=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 \(I_5\), 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 \(\phi\) 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 \(\phi_2\otimes\phi_5\otimes\phi_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 \(\mathcal{J}^{2}(V)\) where \(V=\mathbb{R}^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=\phi_1\otimes\phi_2 +2\phi_2\otimes\phi_1 +3\phi_3\otimes\phi_1\). Spivak asserts that \(\mathcal{J}^{2}(V)\) has dimension \(n^k=3^2=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 \(3^2=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\phi_1+3\phi_2)\otimes(5\phi_3+7\phi_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\phi_1\phi_3 + 14\phi_1\phi_4 + 15\phi_2\phi_3 + 21\phi_2\phi_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.

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.