dovs() in the
stokes packagefunction (K)
{
if (is.zero(K) || is.scalar(K)) {
return(0)
}
else {
return(max(index(K)))
}
}
To cite the stokes package in publications, please use
Hankin (2022); this function monograph
discusses dovs(). Function dovs() returns the
dimensionality of the underlying vector space of a \(k\)-form. Recall that a \(k\)-form is an alternating linear map from
\(V^k\) to \(\mathbb{R}\), where \(V=\mathbb{R}^n\) (Spivak 1965). Function
dovs() returns \(n\)
[compare arity(), which returns \(k\)]. As seen above, the function is very
simple, essentially being max(index(K)), but its use is not
entirely straightforward in the context of stokes idiom.
Consider the following:
## An alternating linear map from V^2 to R with V=R^4:
## val
## 2 4 = 9
## 1 4 = 8
## 2 3 = 1
## 1 3 = -3
## 3 4 = -2
## 1 2 = 2
Now object a is notionally a map from \(\left(\mathbb{R}^4\right)^2\) to \(\mathbb{R}\):
## [,1] [,2]
## [1,] 1 5
## [2,] 2 6
## [3,] 3 7
## [4,] 4 8
## [1] -148
However, a can equally be considered to be a map from
\(\left(\mathbb{R}^5\right)^2\) to
\(\mathbb{R}\):
## [,1] [,2]
## [1,] 1 5
## [2,] 2 6
## [3,] 3 7
## [4,] 4 8
## [5,] 1454 -9564
## [1] -148
If we view \(a\) [or indeed
f()] in this way, that is \(a\colon\left(\mathbb{R}^5\right)^2\longrightarrow\mathbb{R}\),
we observe that row 5 is ignored: \(e_5=\left(0,0,0,0,1\right)^T\) maps to zero
in the sense that \(f(e_5,\mathbf{v})=f(\mathbf{v},e_5)=0\),
for any \(\mathbf{v}\in\mathbb{R}^5\).
## [,1] [,2]
## [1,] 0 0.3800352
## [2,] 0 0.7774452
## [3,] 0 0.9347052
## [4,] 0 0.2121425
## [5,] 1 0.6516738
## [1] 0
(above we see that rows 1-4 of M are ignored because of
the zero in column 1; row 5 is ignored because the index of
a does not include the number 5). Because a is
alternating, we could have put \(e_5\)
in the second column with the same result. Alternatively we see that the
\(k\)-form a, evaluated
with \(e_5\) as one of its arguments,
returns zero because the index matrix of a does not include
the number 5. Most of the time, this kind of consideration does not
matter. However, consider this:
## An alternating linear map from V^1 to R with V=R^1:
## val
## 1 = 1
Now, we know that dx is supposed to be a map
from \(\left(\mathbb{R}^3\right)^1\) to
\(\mathbb{R}\); but:
## [1] 1
So according to stokes, \(\operatorname{dx}\colon\left(\mathbb{R}^1\right)^1\longrightarrow\mathbb{R}\).
This does not really matter numerically, until we consider the Hodge
star operator. We know that \(\star\operatorname{dx}=\operatorname{dy}\wedge\operatorname{dz}\),
but
## [1] 1
Above we see the package giving, correctly, that the Hodge star of
\(\operatorname{dx}\) is the
zero-dimensional volume element (otherwise known as “1”). To get the
answer appropriate if \(\operatorname{dx}\) is considered as a map
from \(\left(\mathbb{R}^3\right)^1\) to
\(\mathbb{R}\) [that is, \(\operatorname{dx}\colon\left(\mathbb{R}^3\right)^1\longrightarrow\mathbb{R}\)],
we need to specify dovs explicitly:
## An alternating linear map from V^2 to R with V=R^3:
## val
## 2 3 = 1
Actually this looks a lot better with a more appropriate print method:
## An alternating linear map from V^2 to R with V=R^3:
## + dy^dz
keep() and discard()Given a \(k\)-form \(\omega\), we have \(\omega(v_1,\ldots,v_k)\in\mathbb{R}\), where \(v_1,\ldots,v_k\in\mathbb{R}^n\). Now, discarding dimension \(i\) is equivalent to asserting (or guaranteeing) that \(e_i\cdot v_j=0\) for \(j=1,\ldots,k\). Alternatively, we may say that \(\omega(v_1,\ldots,v_k)\) is independent of \(e_i\cdot v_j\) for \(j=1,\ldots,k\). If this is the case, we may ignore any row in which an \(i\) appears.
For \(k\)-forms, discarding (and its
dual, keeping) is carried out in the package by functions
keep() and discard(). In these functions,
dovs() is used internally, but its role is somewhat opaque.
Consider keep():
## function (K, yes)
## {
## jj <- rep(0L, dovs(K))
## jj[yes] <- 1
## stretch(K, jj)
## }
Above we see that dovs() is used to create vector
jj, which specifies which dimensions to keep and which to
discard. This is so that argument yes can use standard
square bracket replacement idiom to overwrite jj. Kept
dimensions are then stretched (with function stretch()) by
a factor of 1 and discarded dimensions are stretched by a factor of
0.
Now, given the current package setup, there is no point in specifying
whether a dimension greater than dovs(x) is to be kept or
not—such things are already discarded. As a concrete example:
## An alternating linear map from V^2 to R with V=R^3:
## val
## 2 3 = 3
## 1 3 = 2
## 1 2 = 1
## [1] 3
Above we see a kform x with dovs of 5.
Recall that object x is a map from \(V^2\) to \(\mathbb{R}\), where vector space \(V=\mathbb{R}^5\). So, for example, \(x\left(\left(\begin{array}{c}a_1\\a_2\\a_3\end{array}\right),\left(\begin{array}{c}b_1\\b_2\\b_3\end{array}\right)\right)=a_1b_2+2a_1b_3+3a_2b_3\).
Now, for example, I might only care about the first and third row of
each argument [that would be the \(x\)-
and \(z\)- components of a 3-vector].
If I wished to simplify x I would only keep the first and
third:
## An alternating linear map from V^2 to R with V=R^3:
## val
## 1 3 = 2
Observe that there is no point asking whether to keep “the fourth component”, for that has already been discarded by the class.