Given a \(k\)-form, express it in terms of linear combinations of the \(dx_i\)

pullback(K,M)
stretch(K,d)

Arguments

K

Object of class kform

M

Matrix of transformation

d

Numeric vector representing the diagonal elements of a diagonal matrix

Details

Function pullback() calculates the pullback of a function. A vignette is provided at pullback.Rmd.

Suppose we are given a two-form

$$ \omega=\sum_{i < j}a_{ij}\mathrm{d}x_i\wedge\mathrm{d}x_j$$

and relationships

$$\mathrm{d}x_i=\sum_rM_{ir}\mathrm{d}y_r$$

then we would have

$$\omega = \sum_{i < j} a_{ij}\left(\sum_rM_{ir}\mathrm{d}y_r\right)\wedge\left(\sum_rM_{jr}\mathrm{d}y_r\right). $$

The general situation would be a \(k\)-form where we would have $$ \omega=\sum_{i_1 < \cdots < i_k}a_{i_1\ldots i_k}\mathrm{d}x_{i_1}\wedge\cdots\wedge\mathrm{d}x_{i_k}$$

giving

$$\omega = \sum_{i_1 < \cdots < i_k}\left[ a_{i_1,\ldots, i_k}\left(\sum_rM_{i_1r}\mathrm{d}y_r\right)\wedge\cdots\wedge\left(\sum_rM_{i_kr}\mathrm{d}y_r\right)\right]. $$

The transform() function does all this but it is slow. I am not 100% sure that there isn't a much more efficient way to do such a transformation. There are a few tests in tests/testthat and a discussion in the stokes vignette.

Function stretch() carries out the same operation but for \(M\) a diagonal matrix. It is much faster than transform().

Value

The functions documented here return an object of class kform.

References

S. H. Weintraub 2019. Differential forms: theory and practice. Elsevier. (Chapter 3)

Author

Robin K. S. Hankin

See also

Examples


# Example in the text:
K <- as.kform(matrix(c(1,1,2,3),2,2),c(1,5))
M <- matrix(1:9,3,3)
pullback(K,M)
#> An alternating linear map from V^2 to R with V=R^3:
#>          val
#>  1 2  =  -33
#>  1 3  =  -66
#>  2 3  =  -33

# Demonstrate that the result can be complicated:
M <- matrix(rnorm(25),5,5)
pullback(as.kform(1:2),M)
#> An alternating linear map from V^2 to R with V=R^5:
#>                  val
#>  3 5  =  -0.98311942
#>  1 2  =  -0.36990935
#>  2 4  =  -0.20729935
#>  1 5  =  -0.54937477
#>  2 5  =   0.96506752
#>  3 4  =   0.27027023
#>  4 5  =   0.06051901
#>  1 4  =   0.09481045
#>  2 3  =  -0.94233222
#>  1 3  =   0.91326109

# Numerical verification:
o <- volume(3)

o2 <- pullback(pullback(o,M),solve(M))
max(abs(coeffs(o-o2))) # zero to numerical precision
#> [1] 4.718448e-16

# Following should be zero:
pullback(as.kform(1),M)-as.kform(matrix(1:5),c(crossprod(M,c(1,rep(0,4)))))
#> The zero alternating linear map from V^1 to R with V=R^n:
#> empty sparse array with 1 columns

# Following should be TRUE:
issmall(pullback(o,crossprod(matrix(rnorm(10),2,5))))
#> [1] TRUE

# Some stretch() use-cases:

p <- rform()
p
#> An alternating linear map from V^3 to R with V=R^7:
#>            val
#>  1 3 6  =   -8
#>  1 2 5  =   -6
#>  2 6 7  =    5
#>  3 6 7  =  -13
#>  1 2 6  =    3
#>  4 6 7  =    7
#>  2 4 7  =   -2
#>  1 3 5  =   -1
stretch(p,seq_len(7))
#> An alternating linear map from V^3 to R with V=R^7:
#>              val
#>  1 3 5  =    -15
#>  2 4 7  =   -112
#>  4 6 7  =   1176
#>  1 2 6  =     36
#>  3 6 7  =  -1638
#>  2 6 7  =    420
#>  1 2 5  =    -60
#>  1 3 6  =   -144
stretch(p,c(1,0,0,1,1,1,1))   # kills dimensions 2 and 3
#> An alternating linear map from V^3 to R with V=R^7:
#>            val
#>  4 6 7  =    7