This notebook is part of the Introduction to manifolds in SageMath by Andrzej Chrzeszczyk (Jan Kochanowski University of Kielce, Poland).
version()
'SageMath version 9.6, Release Date: 2022-05-15'
Warning: in this notebook there are many repetitions with respect to notebook 10. Although mathematically alternating forms on modules from notebook 10 are generalizations of differential forms, the SageMath code in the present notebook differs significantly from that in notebook 10.
Let $M$ be a smooth manifold.
A differential $k$-form or simply $k$-form on a manifold $M$ is a smooth map $ω$ that, to each point $p ∈ M$, assigns $k$-linear antisymmetric form $ω(p)=ω_p$ on the tangent space $T_pM$.
Reminder. $k$-linear antisymmetric forms on arbitrary modules were presented in notebook 10, and smoothness of covariant tensor fields in notebook 13.
One can use an equivalent definition:
A differential form of degree $k$, or differential $k$-form, $ω$ on a manifold $M$ is a smooth tensor field of type $(0,k)$ on $M$, with the antisymmetry property:
\begin{equation} ω(X_1 , . . . , X_i , . . . , X_j , . . . , X_k ) = −ω(X_1, . . . , X_j , . . . , X_i , . . . , X_k ), \label{}\tag{14.1} \end{equation}for
$1\leq i < j \leq k$, $ X_1 , . . . , X_k ∈ \mathfrak{X}(M)$.
Note that from (14.1) it follows that if $X_i=X_j$ then $ω(X_1 , . . . , X_i , . . . , X_j , . . . , X_k ) = 0$.
for $\sigma\in S_k$ (permutations and their signs were defined in notebook 10).
A 0-form is a smooth real-valued
function on $M$.
The set of the k-forms on a manifold $M$, is denoted by $\Omega^k(M)$. It is a submodule of the module of covariant tensor fields
$T^{(0,k)} M$ on the manifold $M$.
Example 14.1
Let us define a differential 2-form on a 3-dimensional manifold.
M = Manifold(3, 'M') # manifold M
X.<x,y,z> = M.chart()
a = M.diff_form(2, name='a') ; # define 2-form
print(a) # show information on a
2-form a on the 3-dimensional differentiable manifold M
# parent?
# mathematical object of which "a" is an element
show(a.parent())
The obtained module can be defined independently:
Om2 = M.diff_form_module(2) # define module of 2-forms
show(Om2)
If $t$ is a covariant tensor field from $T^{(0,k)}M$, then we can define a differential $k$-form called Alt($t$) in the following way
\begin{equation} \mathrm{Alt}(t)(X_1,\ldots,X_k)=\frac{1}{k!}\sum_{\sigma\in S_k}\mathrm{sign}(\sigma)\;t(X_{\sigma(1)},\ldots,X_{\sigma(k)}), \label{}\tag{14.2} \end{equation}for $X_i\in\mathfrak{X}(M)$.
Alt is a linear map on the module $T^{(0,k)}M$ (over $C^\infty(M)$) into $\Omega^k(M)$.
To prove that for $t\in T^{(0,k)}M$ we have $\text{Alt}(t)\in \Omega^k(M)$ note that for arbitrary permutation $\tau\in S_k$
$$\text{Alt}(t)(v_{\tau(1)},\ldots,v_{\tau(k)}) =\frac{1}{k!}\sum_{\sigma\in S_k}\text{sign}\sigma\, t(v_{\sigma(\tau(1))},\ldots,v_{\sigma(\tau(k))})\\ =\frac{1}{k!}\sum_{\sigma\in S_k}\text{sign}\sigma\, \text{sign}\sigma\,t(v_{\tau(1)},\ldots,v_{\tau(k)})=\text{sign}\tau\,t(v_{1},\ldots,v_{k}). $$We can check also that if $t\in \Omega^k(M)$, then Alt($t$)=$t$.
In fact, assume that $t(v_{\sigma(1)},\ldots,v_{\sigma(k)})=\text{sign}\sigma\, t(v_1,\ldots,v_k)$.
Then
$$\text{Alt}(t)(v_1,\ldots,v_k)=
\frac{1}{k!}\sum_{\sigma\in S_k}(\text{sign} \sigma)t(v_{\sigma(1)},\ldots,v_{\sigma(k)})\\
=\frac{1}{k!}\sum_{\sigma\in S_k}(\text{sign} \sigma)(\text{sign} \sigma)\,
t(v_{1},\ldots,v_{k})=t(v_{1},\ldots,v_{k}).
$$
The last two observations lead to the relation $$\text{Alt}(\text{Alt}(t))=\text{Alt}(t), \quad \text{or equivalently}\quad \text{Alt}^2=\text{Alt}.$$
If $ω$ is a $k$-differential form and $η$ is an $l$-differential form on $M$, the exterior, or wedge, product $ω ∧ η\in\Omega^{(k+l)}(M)$, is defined by \begin{equation} \omega\wedge\eta=\frac{(k+l)!}{k!l!}\mathrm{Alt}(\omega\otimes\eta). \label{}\tag{14.3} \end{equation}
Remark. Some authors use different coefficients in this formula. Our version is in accordance with that in SageMath Manifolds.
Example 14.2
If $α$ and $β$ are 1-forms, applying (14.3), (14.2) and using the fact that there are only two permutations of two elements with opposite signs we have $$(α ∧ β)(X_1 , X_2 ) = \frac{(1+1)!}{1!1!}\mathrm{Alt} (α ⊗ β)(X_1 , X_2 )\\ = \frac{2!}{1!1!}\frac{1}{2!} [ (α ⊗ β)(X_1 , X_2 ) − (α ⊗ β)(X_2 , X_1 )]\\ = α(X_1 )β(X_2 ) − α(X_2 )β(X_1 ) = (α ⊗ β − β ⊗ α)(X_1 , X_2 ),$$
for $X_1 , X_2 ∈ \mathfrak{X}(M).$ Consequently $$α ∧ β = (α ⊗ β − β ⊗ α) = −β ∧ α,\quad \mbox{for }\quad α, β ∈ \Omega^1 (M).$$
From the multilinearity of the tensor product and linearity of antisymmetrization it follows.
For $\alpha,\alpha_1,\alpha_2\in \Omega^k(M),\beta,\beta_1,\beta_2\in \Omega^m(M)$ and $a\in C^\infty(M)$
\begin{equation} \begin{matrix} (\alpha_1+\alpha_2)\wedge\beta=\alpha_1\wedge\beta+\alpha_2\wedge\beta,\\ \alpha\wedge(\beta_1+\beta_2)=\alpha\wedge\beta_1+\alpha\wedge\beta_2,\\ (a\alpha)\wedge\beta=a(\alpha\wedge\beta)=\alpha\wedge(a\beta). \end{matrix} \tag{14.4} \end{equation}To check the associativity of the wedge product we need some properties of the antisymmetrization operation.
First observe that if $t\in T^{(0,k)}M$ and $s\in T^{(0,m)}M$, then
\begin{equation} \text{Alt}(t)=0\quad \Longrightarrow\quad \text{Alt}(t\otimes s)=\text{Alt}(s\otimes t)=0. \tag{Alt1} \end{equation}To prove this, let us note that
$$(k + m)!\, \text{Alt}(t ⊗ s)(v_1 , . . . , v_{k+m} ) = \sum_{\sigma\in S_{k+m}} (\text{sign}\, σ) t (v_{σ(1)} , . . . , v_{σ(k)} )s(v_{σ(k+1)} , . . . , v_{σ(k+m)} ). $$First define the subgroup of $S_{k+m}$,
$$G=\{\sigma\in S_{k+m}: (\sigma(k+1),\ldots,\sigma(k+m))=(k+1,\ldots,k+m)\},$$and compute the sum from the right hand side of the previous equality restricted to this subgroup.
$$\sum_{\sigma\in G}(\text{sign}\, σ)\,t (v_{σ(1)} , . . . , v_{σ(k)} )s(v_{σ(k+1)} , . . . , v_{σ(k+m)} )\\ =\Big[\sum_{\sigma\in G}(\text{sign}\, σ)\,t (v_{σ(1)} , . . . , v_{σ(k)} )\Big] s(v_{k+1} , . . . , v_{k+m} )\\= k!(\text{Alt}(t))(v_{1} , . . . , v_{k} ) s(v_{k+1} , . . . , v_{k+m} )= k!(\text{Alt}(t)\otimes s)(v_1,\ldots,v_{k+m}), $$so the entire sum vanishes if the sum in brackets vanishes, i.e. Alt($t$) vanishes.
Now for fixed $\tilde\sigma\in S_{k+m}$ let us sum over the coset $G\tilde\sigma=\{\sigma\tilde\sigma: \sigma \in G$}.
Thus if $\text{Alt}(t)$ vanishes then the sums over all cosets $G\tilde\sigma$ vanish. Since the group $S_{k+m}$ is a sum of cosets $G\tilde\sigma$, the implication (Alt1) holds true.
The second ingredient of our associativity proof is the following
\begin{equation} \text{Alt}(\text{Alt}(t ⊗ s) ⊗ r) = \text{Alt}(t ⊗ s ⊗ r) = \text{Alt}(t ⊗ \text{Alt}(s ⊗ r)). \tag{Alt2} \end{equation}
In fact, the linearity of Alt and the relation $ \text{Alt}^2=\text{Alt}$ implies
$$\text{Alt}(\text{Alt}(s ⊗ r) − s ⊗ r)=\text{Alt}(\text{Alt}(s ⊗ r))-\text{Alt}(s\otimes r)=0. $$
Applying the implication (Alt1) to $\ \text{Alt}(s ⊗ r) − s ⊗ r\ $ we obtain
$$\text{Alt}(t\otimes\text{Alt}(s\otimes r))-\text{Alt}(t\otimes s\otimes r)= \text{Alt}(t\otimes[\text{Alt}(s\otimes r)-s\otimes r]). $$
Since we have checked that the value of Alt on the expression in brackets vanishes, then the implication (Alt1) gives us
$$\text{Alt}(t\otimes\text{Alt}(s\otimes r)-\text{Alt}(t\otimes s\otimes r)) =\text{Alt}(t\otimes[\text{Alt}(s\otimes r)-s\otimes r])=0, $$
i.e., the second equality from (Alt2) holds true
$$\text{Alt}(t ⊗ \text{Alt}(s ⊗ r)) = \text{Alt}(t ⊗ s ⊗ r).$$
The first equality in (Alt2) can be proved analogously.
From (Alt2) it follows for $\alpha\in\Omega^k(M),\ \beta\in \Omega^l(M), \ \gamma\in \Omega^m(M)$
$$(\alpha\wedge \beta)\wedge \gamma= \frac{(k+m+l)!}{(k+m)!l!}\text{Alt}((\alpha\wedge\beta)\otimes\gamma)\\ =\frac{(k+m+l)!}{(k+m)!l!}\text{Alt}(\frac{(k+m)!}{k!m!}(\text{Alt}(\alpha\otimes\beta)\otimes\gamma)\\= \frac{(k+m+l)!}{k!m!l!}\text{Alt}(\alpha\otimes\beta\otimes\gamma). $$Analogously for $α ∧ (β ∧ γ )$. We have proved associativity of the wedge product:
for $\alpha\in\Omega^k(M),\ \beta\in \Omega^l(M), \ \gamma\in \Omega^m(M)$, and more generally
\begin{equation} α_1 ∧ \ldots ∧ \alpha_r = \frac{(k_1+\ldots k_r)!}{k_1!\dots k_r!}\mathrm{Alt}(α_1\otimes \ldots\otimes \alpha_r ), \label{}\tag{14.6} \end{equation}for $\alpha_i\in\Omega^{k_i}(M).$
For example if $x^1,\ldots,x^n$ are local coordinates on $M$, then since $dx^i$ are 1-forms, then $dx^{i_1}\wedge\ldots\wedge dx^{i_k}$ are $k$-forms on $M$.
Let $(x^1 , . . . , x^n )$ be a local coordinate system on $M$. According to (13.7) a $k$-differential form possesses the local representation
\begin{equation} ω = ω_{i_1 ...i_k} dx^{i_1} ⊗ · · · ⊗ dx^{i_k}, \label{}\tag{14.7} \end{equation}where
\begin{equation} ω_{i_1 ...i_k} = ω\Big(\frac{\partial}{\partial x^{i_1}},\ldots,\frac{\partial}{\partial x^{i_k}}\Big). \label{}\tag{14.8} \end{equation}Since $\omega$ is antisymmetric, $ω_{i_1 ...i_k}$ is also antisymmetric.
Since Alt is linear and Alt($\omega$)=$\omega\ $ we have
From (14.6) it follows that (note that $dx^{i_j}$ are 1-forms) $$\mathrm{Alt}(dx^{i_1}\otimes\ldots\otimes dx^{i_k})=\frac{1}{k!}dx^{i_1}\wedge\ldots\wedge dx^{i_k}.$$ Thus we have \begin{equation} \begin{matrix} \omega=\frac{1}{k!}\sum_{i_1,\ldots,i_k=1}^n ω_{i_1 ...i_k}dx^{i_1}\wedge\ldots\wedge dx^{i_k}\\ =\sum_{1\leq i_1<\ldots<i_k\leq n}ω_{i_1 ...i_k}dx^{i_1}\wedge\ldots\wedge dx^{i_k}. \end{matrix} \label{}\tag{14.9} \end{equation}
Note that every element of the sum with increasing indices has $k!$ counterparts in the sum with arbitrarily ordered indices. For arbitrary permutation $\sigma\in S_k$ (no summation here)
$$\omega_{\sigma(i_1)\ldots\sigma(i_k)}dx^{\sigma(i_1)}\wedge\ldots\wedge dx^{\sigma(i_k)}=\mathrm{sign}(\sigma)^2ω_{i_1 ...i_k}dx^{i_1}\wedge\ldots\wedge dx^{i_k}\\=ω_{i_1 ...i_k}dx^{i_1}\wedge\ldots\wedge dx^{i_k}.$$Elements of the set
$$\{dx^{i_1}\wedge\dots\wedge dx^{i_k}: 1\leq i_1<\ldots<i_k\leq n\}$$are linearly independent, since if
$$0=\omega=\sum_{i_1<...<i_k}\omega_{i_1\ldots i_k}dx^{i_1}\wedge\dots\wedge dx^{i_k}, $$then taking the basis $\{\frac{\partial}{\partial x^{1}},\ldots,\frac{\partial}{\partial x^{n}}\}$ and an increasing index sequence $(j_1,\ldots,j_k)$, we obtain
$$0=\omega(\frac{\partial}{\partial x^{j_1}},\ldots,\frac{\partial}{\partial x^{j_k}})=k!\sum_{i_1<...<i_k}\omega_{i_1\ldots i_k} \text{Alt}(\{dx^{i_1}\otimes\dots\otimes dx^{i_k})\big( \frac{\partial}{\partial x^{j_1}},\ldots,\frac{\partial}{\partial x^{j_k}}\big)\\ =\sum_{i_1<...<i_k}\omega_{i_1\ldots i_k} \sum_{\sigma\in S_k}(\text{sign}\, \sigma) dx^{i_1}(\frac{\partial}{\partial x^{j_{\sigma(1)}}})\ldots dx^{i_k}(\frac{\partial}{\partial x^{j_{\sigma(k)}}}). $$Since $(i_1 , . . . , i_k )$ and $( j_1 , . . . , j_k )$ are both increasing, there is only one choice of $i_1,..., i_k\ $ which gives a nonzero value, namely $\ i_1 = j_1,\ldots,i_k =j_k.$ Since
$$dx^{j_1}(\frac{\partial}{\partial x^{j_{1}}})\ldots dx^{j_k}(\frac{\partial}{\partial x^{j_{k}}})=1 $$we have $$ 0=\omega(\frac{\partial}{\partial x^{j_1}},\ldots,\frac{\partial}{\partial x^{j_k}})=\omega_{j_1\ldots j_k}. $$
If $\omega ∈ \Omega^k(M)$ and $\eta ∈ \Omega^l(M)$, then
$$ \omega ∧ \eta = (−1)^{kl} \eta ∧ \omega. $$This is consequence of (we use the unordered version of (14.9))
$$ (k+l)!ω ∧ η = ω_{i_1 ...i_k} η_{ j_1 ... j_l} dx^{i_1} ∧ · · · ∧ dx^{i_k} ∧ dx^{j_1} ∧ · · · ∧ dx^{j_l}\\ = (−1)^{kl} ω_{i_1 ...i_k} η_{j_1 ... j_l} dx^{j_1} ∧ · · · ∧ dx^{j_l} ∧ dx^{i_1} ∧ · · · ∧ dx^{i_k} = (k+l)!(−1)^{kl} η ∧ ω. $$For arbitrary differential forms in $\Omega^k(M)$
sometimes we would not want to actually write out all of the elements
of the local frames of $\Omega^k(M)$, so
instead we write
\begin{equation}
α =\sum_I a_I dx^I .
\label{}\tag{14.10}
\end{equation}
Here the $I$ stands for the sequence of $k$ increasing indices $i_1 i_2 \ldots i_k$: $1 ≤ i_1 < i_2 < \ldots < i_k ≤ n$. That is, we sum over
$I ∈ J_{k,n} = \{(i_1 i_2 \ldots i_k ) : 1 ≤ i_1 < i_2 < \ldots < i_k ≤ n\}.$
For example, for $k = 3$ and $n = 4$ we have $I\in\{123,124,134,234\}.$
If $I$ and $J$ are disjoint, then we have $dx^I ∧ dx^J = ±dx^K$ where $K = I ∪ J$, but is reordered to be in increasing order. Elements with repeated indices are dropped. Using this notation we can compute the wedge product as follows \begin{equation} \Big(\sum_I a_Idx^I\Big)\wedge\Big(\sum_J b_Jdx^J\Big)= \sum_K\Big(\sum_{\substack{I\cup J=K\\I\cap J=\emptyset}}\pm a_Ib_J\Big)dx^K. \label{}\tag{14.11} \end{equation}
Example 14.3
Let us define a differential 2-form on a 3-dimensional manifold.
%display latex
N = 3 # dimension of manifold M
M = Manifold(N, 'M') # manifold M
X = M.chart(' '.join(['x'+str(i)+':x^{'+str(i)+'}' for i in range(N)])) # chart on M
x0, x1, x2 = X[:] # coordinates x^0, x^1, x^2 of chart X as the Python variables x0, x1, x2
a = M.diff_form(2, name='a') # differential 2-form on M
a01 = M.scalar_field(function('a01')(x0,x1,x2), name='a01') # component a_{01}
a02 = M.scalar_field(function('a02')(x0,x1,x2), name='a02') # component a_{02}
a12 = M.scalar_field(function('a12')(x0,x1,x2), name='a12') # component a_{12}
a[0,1] = a01; a[0,2] = a02 # by antisymmetry, 6 nonzero components defined
a[1,2] = a12
a.disp()
The arguments of components can be omitted
Manifold.options.omit_function_arguments=True
a.disp()
# mathematical object of which "a" is an element
a.parent()
The matrix of 2-form must be antisymmetric.
a[:]
We can check the formula $\ a_{ij}=a(\frac{\partial}{\partial x^0},\frac{\partial}{\partial x^1})$.
# check the matrix a(d/dxi,d/dxj)
fr = X.frame();
matrix([[a(fr[i0],fr[i1]).expr() for i1 in range(3)] for i0 in range(3)])
Example 14.4
Let us show how the antisymmetrization operation works for tensor fields $t\in T^{(0,2)}M$.
N = 3 # dimension of manifold M
M = Manifold(N, 'M') # manifold M
X = M.chart(' '.join(['x'+str(i)+':x^{'+str(i)+'}' for i in range(N)])) # chart on M
x0, x1, x2 = X[:] # coordinates x^0, x^1, x^2 of chart X as the Python variables x0, x1, x2
t = M.tensor_field(0,2, name='t') # tensor field of type (0,2)
f2 = [['f'+str(i)+str(j) for j in range(N)] for i in range(N)] # table of comp. names
f = [[M.scalar_field(function(f2[j][k])(x0,x1,x2), name=f2[j][k]) # table of comp. funcs
for k in range(N)] for j in range(N)]
t[:] = f # define all components
t.disp() # show tensor t
Now we apply the antisymmetrization operation, the result is 2-form at.
at = t.antisymmetrize() # antisymmetrization of t
print(at) # show info on at
2-form on the 3-dimensional differentiable manifold M
Manifold.options.omit_function_arguments=True
at.disp() # show at
The matrix of components of $t$ is a full 3-3 matrix:
t[:] # components of t
and the antisymmetrized tensor has the antisymmetric matrix of components:
at[:] # components of antisymmetrization
Example 14.5
Consider a tensor field of type $(0,3)$ on a 4-dimensional manifold and its antisymmetrization.
%display latex
N = 4 # dimension of the manifold M
M = Manifold(N, 'M') # manifold M
X = M.chart(' '.join(['x'+str(i)+':x^{'+str(i)+'}' for i in range(N)])) # chart on M
t3 = M.tensor_field(0,3, name='t3') # tensor field of type (0,3)
print(t3) # show info on t3
# table of component names:
f3 = [[['a'+str(i)+str(j)+str(k) for k in range(N)]
for j in range(N)] for i in range(N)]
# table of component functions:
f = [[[M.scalar_field(function(f3[i][j][k])(*X), name=f3[i][j][k])
for k in range(N)] for j in range(N)] for i in range(N)]
t3[:] = f # define all components
Tensor field t3 of type (0,3) on the 4-dimensional differentiable manifold M
Let $e$ be the frame:
e = X.frame(); e # frame of M
and let's show how the definition of the antisymmetrization works if we take $(v_1,v_2,v_3)=(\frac{\partial}{\partial x^0}, \frac{\partial}{\partial x^1},\frac{\partial}{\partial x^2})$ in (14.2):
S3 = Permutations(3).list() # S_3 group
s = 1/factorial(3)*sum([sign(p)*t3(e[p[0]-1],e[p[1]-1],e[p[2]-1])
for p in S3]) # special case of (14.2)
Manifold.options.omit_function_arguments=True
s.disp() # show the result
#s.expr()
As we can see the sum contains 3!=6 elements with signs equal to permutations signs.
For comparison one can use the antisymmetrize
method:
# built in
t3a = t3.antisymmetrize() # antisymmetrization
t3a(e[0],e[1],e[2]).disp()
Example 14.6
Define two 1-forms with symbolic components and compute their wedge product.
N = 3 # dimension of manifold M
M = Manifold(N, 'M') # manifold M
X = M.chart(' '.join(['x'+str(i)+':x^{'+str(i)+'}' for i in range(N)])) # chart on M
a = M.diff_form(1,name='a') # 1-form a
b = M.diff_form(1,name='b') # 1-form b
ast = ['a'+str(j) for j in range(N)] # list of component names
bst = ['b'+str(j) for j in range(N)] # list of component names
af = [M.scalar_field(function(ast[j])(*X),name=ast[j])
for j in range(N)] # list of component functions
bf = [M.scalar_field(function(bst[j])(*X),name=bst[j])
for j in range(N)] # list of component functions
a[:] = af # define all components of a
b[:] = bf # define all components of b
Manifold.options.omit_function_arguments=True
%display latex
a.disp() # show a
b.disp() # show b
# mathematical object of which "b" is an element.
b.parent()
Wedge product $a\wedge b$:
ab = a.wedge(b) # wedge product
ab.disp() # in SageMath
Compare with the result obtained from definition (14.3):
ab1 = factorial(1+1)/factorial(1)/factorial(1)*(a*b).antisymmetrize()
ab1.disp() # use formula (14.3)
ab1 == ab # check if both methods agree
Define the matrix containing the components of 1-forms in rows:
ma = matrix([a[:],b[:]])
ma
The components of the wedge product of 1-forms are minors of the matrix of components of these 1-forms.
ma.minors(2)
Example 14.7
Consider the wedge product of three 1-forms (in 3-dimensional manifold).
# continuation
Manifold.options.omit_function_arguments=True
cst = ['c'+str(j) for j in range(N)] # list of component names
cf = [M.scalar_field(function(cst[j])(*X),name=cst[j])
for j in range(N)] # list of component functions
c = M.diff_form(1,name='c') # 1-form c
c[:] = cf # define all coefficients
abc = (a.wedge(b)).wedge(c) # wedge prod. a /\ b /\ c
abc.disp()
We can recognize in the result the Laplace expansion of the determinant $\ $ det $\left(\begin{matrix} a_0,a_1,a_2\\ b_0,b_1,b_2\\ c_0,c_1,c2 \end{matrix}\right),\ \ $ so we have
We can check the observation using SageMath:
d = X.coframe()
d
# compare abc with the 3-form with the determinant as coefficient
abc == det(matrix([a[:],b[:],c[:]]))*(d[0].wedge(d[1])).wedge(d[2])
The unique component of the wedge product $abc=a\wedge b\wedge c$ must be equal to $\ \ abc(\frac{\partial}{\partial x^0},\frac{\partial}{\partial x^1},\frac{\partial}{\partial x^2})$.
Let us check it with SageMath Manifolds.
X.frame() # default frame
# check if the value of abc on the frame
# is equal to det([a[:],b[:],c[:]])
abc(*X.frame()) == det(matrix([a[:],b[:],c[:]]))
# the same in an other way
abc[0,1,2] == det(matrix([a[:],b[:],c[:]]))
Example 14.8
Consider two 2-forms on a 4-dimensional manifold.
N = 4 # dimension of manifold M
M = Manifold(N, 'M') # manifold M
X = M.chart(' '.join(['x'+str(i)+':x^{'+str(i)+'}' for i in range(N)])) # chart on M
a=M.diff_form(2,name='a') # 2-form a
b=M.diff_form(2,name='b') # 2-form b
We define first the names of functions,
def ast(i,j): return 'a'+str(i)+str(j) # names of comp. for a
def bst(i,j): return 'b'+str(i)+str(j) # names of comp. for b
and the upper triangles of component matrices.
for i0 in range(N): # component functions for a
for i1 in range(N):
if i1>i0:
a[i0,i1] = M.scalar_field(function(ast(i0,i1))(*X),
name=ast(i0,i1))
for i0 in range(N): # component functions for b
for i1 in range(N):
if i1>i0:
b[i0,i1] = M.scalar_field(function(bst(i0,i1))(*X),
name=bst(i0,i1))
Manifold.options.omit_function_arguments=True
%display latex
a[:] # show components of a
b[:] # show components of b
Recall that according to the general rule, to obtain the wedge product we use all possible strictly increasing and disjoint sequences $I=(i_1,i_2),\ J=(j_1,j_2)$ and define $dx^K=e^1\wedge e^2\wedge e^3\wedge e^4,$ where $K=(1,2,3,4)$ is reordered disjoint union $I\cup J$. We have
$$\Big(\sum_I a_Idx^I\Big)\wedge\Big(\sum_J b_Jdx^J\Big)= \sum_K\Big(\sum_{\substack{I\cup J=K\\I\cap J=\emptyset}}\pm a_Ib_J\Big)dx^K.$$To be less formal, to compute the wedge product we
a) take all possible components of the first 2-form with increasing permutations $I$ of two indices from (0,1,2,3);
b) multiply them by components of the second 2-form with increasing permutations $J$ of the remaining 2 indices;
c) the products are taken with + or - depending on the sign of the joined permutation $(I,J)$ of (0,1,2,3).
w = a.wedge(b) # w=a/\b
w.display() # show w
Take a look at the notebook Pullback of tensor fields.