Mixed Differential Forms

Let \(M\) and \(N\) be differentiable manifolds and \(\varphi : M \longrightarrow N\) a differentiable map. A mixed differential form along \(\varphi\) is an element of the graded algebra represented by MixedFormAlgebra. Its homogeneous components consist of differential forms along \(\varphi\). Mixed forms are useful to represent characteristic classes and perform computations of such.

AUTHORS:

  • Michael Jung (2019) : initial version

class sage.manifolds.differentiable.mixed_form.MixedForm(parent, name=None, latex_name=None)[source]

Bases: AlgebraElement, ModuleElementWithMutability

An instance of this class is a mixed form along some differentiable map \(\varphi: M \to N\) between two differentiable manifolds \(M\) and \(N\). More precisely, a mixed form \(a\) along \(\varphi: M \to N\) can be considered as a differentiable map

\[a: M \longrightarrow \bigoplus^n_{k=0} T^{(0,k)}N,\]

where \(T^{(0,k)}\) denotes the tensor bundle of type \((0,k)\), \(\bigoplus\) the Whitney sum and \(n\) the dimension of \(N\), such that

\[\forall x\in M, \quad a(x) \in \bigoplus^n_{k=0} \Lambda^k\left( T_{\varphi(x)}^* N \right),\]

where \(\Lambda^k(T^*_{\varphi(x)} N)\) is the \(k\)-th exterior power of the dual of the tangent space \(T_{\varphi(x)} N\). Thus, a mixed differential form \(a\) consists of homogeneous components \(a_i\), \(i=0,1, \dots, n\), where the \(i\)-th homogeneous component represents a differential form of degree \(i\).

The standard case of a mixed form on \(M\) corresponds to \(M=N\) with \(\varphi = \mathrm{Id}_M\).

INPUT:

  • parent – graded algebra of mixed forms represented by MixedFormAlgebra where the mixed form self shall belong to

  • comp – (default: None) homogeneous components of the mixed form as a list; if none is provided, the components are set to innocent unnamed differential forms

  • name – (default: None) name given to the mixed form

  • latex_name – (default: None) LaTeX symbol to denote the mixed form; if none is provided, the LaTeX symbol is set to name

EXAMPLES:

Initialize a mixed form on a 2-dimensional parallelizable differentiable manifold:

sage: M = Manifold(2, 'M')
sage: c_xy.<x,y> = M.chart()
sage: e_xy = c_xy.frame()
sage: A = M.mixed_form(name='A'); A
Mixed differential form A on the 2-dimensional differentiable manifold M
sage: A.parent()
Graded algebra Omega^*(M) of mixed differential forms on the
 2-dimensional differentiable manifold M
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M')
>>> c_xy = M.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2)
>>> e_xy = c_xy.frame()
>>> A = M.mixed_form(name='A'); A
Mixed differential form A on the 2-dimensional differentiable manifold M
>>> A.parent()
Graded algebra Omega^*(M) of mixed differential forms on the
 2-dimensional differentiable manifold M
M = Manifold(2, 'M')
c_xy.<x,y> = M.chart()
e_xy = c_xy.frame()
A = M.mixed_form(name='A'); A
A.parent()

The default way to specify the \(i\)-th homogeneous component of a mixed form is by accessing it via A[i] or using set_comp():

sage: A = M.mixed_form(name='A')
sage: A[0].set_expr(x) # scalar field
sage: A.set_comp(1)[0] = y*x
sage: A.set_comp(2)[0,1] = y^2*x
sage: A.display() # display names
A = A_0 + A_1 + A_2
sage: A.display_expansion() # display expansion in basis
A = x + x*y dx + x*y^2 dx∧dy
>>> from sage.all import *
>>> A = M.mixed_form(name='A')
>>> A[Integer(0)].set_expr(x) # scalar field
>>> A.set_comp(Integer(1))[Integer(0)] = y*x
>>> A.set_comp(Integer(2))[Integer(0),Integer(1)] = y**Integer(2)*x
>>> A.display() # display names
A = A_0 + A_1 + A_2
>>> A.display_expansion() # display expansion in basis
A = x + x*y dx + x*y^2 dx∧dy
A = M.mixed_form(name='A')
A[0].set_expr(x) # scalar field
A.set_comp(1)[0] = y*x
A.set_comp(2)[0,1] = y^2*x
A.display() # display names
A.display_expansion() # display expansion in basis

Another way to define the homogeneous components is using predefined differential forms:

sage: f = M.scalar_field(x, name='f'); f
Scalar field f on the 2-dimensional differentiable manifold M
sage: omega = M.diff_form(1, name='omega'); omega
1-form omega on the 2-dimensional differentiable manifold M
sage: omega[e_xy,0] = y*x; omega.display()
omega = x*y dx
sage: eta = M.diff_form(2, name='eta'); eta
2-form eta on the 2-dimensional differentiable manifold M
sage: eta[e_xy,0,1] = y^2*x; eta.display()
eta = x*y^2 dx∧dy
>>> from sage.all import *
>>> f = M.scalar_field(x, name='f'); f
Scalar field f on the 2-dimensional differentiable manifold M
>>> omega = M.diff_form(Integer(1), name='omega'); omega
1-form omega on the 2-dimensional differentiable manifold M
>>> omega[e_xy,Integer(0)] = y*x; omega.display()
omega = x*y dx
>>> eta = M.diff_form(Integer(2), name='eta'); eta
2-form eta on the 2-dimensional differentiable manifold M
>>> eta[e_xy,Integer(0),Integer(1)] = y**Integer(2)*x; eta.display()
eta = x*y^2 dx∧dy
f = M.scalar_field(x, name='f'); f
omega = M.diff_form(1, name='omega'); omega
omega[e_xy,0] = y*x; omega.display()
eta = M.diff_form(2, name='eta'); eta
eta[e_xy,0,1] = y^2*x; eta.display()

The components of a mixed form B can then be set as follows:

sage: B = M.mixed_form(name='B')
sage: B[:] = [f, omega, eta]; B.display() # display names
B = f + omega + eta
sage: B.display_expansion() # display in coordinates
B = x + x*y dx + x*y^2 dx∧dy
sage: B[0]
Scalar field f on the 2-dimensional differentiable manifold M
sage: B[1]
1-form omega on the 2-dimensional differentiable manifold M
sage: B[2]
2-form eta on the 2-dimensional differentiable manifold M
>>> from sage.all import *
>>> B = M.mixed_form(name='B')
>>> B[:] = [f, omega, eta]; B.display() # display names
B = f + omega + eta
>>> B.display_expansion() # display in coordinates
B = x + x*y dx + x*y^2 dx∧dy
>>> B[Integer(0)]
Scalar field f on the 2-dimensional differentiable manifold M
>>> B[Integer(1)]
1-form omega on the 2-dimensional differentiable manifold M
>>> B[Integer(2)]
2-form eta on the 2-dimensional differentiable manifold M
B = M.mixed_form(name='B')
B[:] = [f, omega, eta]; B.display() # display names
B.display_expansion() # display in coordinates
B[0]
B[1]
B[2]

As we can see, the names are applied. However note that the differential forms are different instances:

sage: f is B[0]
False
>>> from sage.all import *
>>> f is B[Integer(0)]
False
f is B[0]

Alternatively, the components can be determined from scratch:

sage: B = M.mixed_form([f, omega, eta], name='B')
sage: B.display()
B = f + omega + eta
>>> from sage.all import *
>>> B = M.mixed_form([f, omega, eta], name='B')
>>> B.display()
B = f + omega + eta
B = M.mixed_form([f, omega, eta], name='B')
B.display()

Mixed forms are elements of an algebra so they can be added, and multiplied via the wedge product:

sage: C = x*A; C
Mixed differential form x∧A on the 2-dimensional differentiable
 manifold M
sage: C.display_expansion()
x∧A = x^2 + x^2*y dx + x^2*y^2 dx∧dy
sage: D = A+C; D
Mixed differential form A+x∧A on the 2-dimensional differentiable
 manifold M
sage: D.display_expansion()
A+x∧A = x^2 + x + (x^2 + x)*y dx + (x^2 + x)*y^2 dx∧dy
sage: E = A*C; E
Mixed differential form A∧(x∧A) on the 2-dimensional differentiable
 manifold M
sage: E.display_expansion()
A∧(x∧A) = x^3 + 2*x^3*y dx + 2*x^3*y^2 dx∧dy
>>> from sage.all import *
>>> C = x*A; C
Mixed differential form x∧A on the 2-dimensional differentiable
 manifold M
>>> C.display_expansion()
x∧A = x^2 + x^2*y dx + x^2*y^2 dx∧dy
>>> D = A+C; D
Mixed differential form A+x∧A on the 2-dimensional differentiable
 manifold M
>>> D.display_expansion()
A+x∧A = x^2 + x + (x^2 + x)*y dx + (x^2 + x)*y^2 dx∧dy
>>> E = A*C; E
Mixed differential form A∧(x∧A) on the 2-dimensional differentiable
 manifold M
>>> E.display_expansion()
A∧(x∧A) = x^3 + 2*x^3*y dx + 2*x^3*y^2 dx∧dy
C = x*A; C
C.display_expansion()
D = A+C; D
D.display_expansion()
E = A*C; E
E.display_expansion()

Coercions are fully implemented:

sage: F = omega*A
sage: F.display_expansion()
omega∧A = x^2*y dx
sage: G = omega+A
sage: G.display_expansion()
omega+A = x + 2*x*y dx + x*y^2 dx∧dy
>>> from sage.all import *
>>> F = omega*A
>>> F.display_expansion()
omega∧A = x^2*y dx
>>> G = omega+A
>>> G.display_expansion()
omega+A = x + 2*x*y dx + x*y^2 dx∧dy
F = omega*A
F.display_expansion()
G = omega+A
G.display_expansion()

Moreover, it is possible to compute the exterior derivative of a mixed form:

sage: dA = A.exterior_derivative(); dA.display()
dA = zero + dA_0 + dA_1
sage: dA.display_expansion()
dA = dx - x dx∧dy
>>> from sage.all import *
>>> dA = A.exterior_derivative(); dA.display()
dA = zero + dA_0 + dA_1
>>> dA.display_expansion()
dA = dx - x dx∧dy
dA = A.exterior_derivative(); dA.display()
dA.display_expansion()

Initialize a mixed form on a 2-dimensional non-parallelizable differentiable manifold:

sage: M = Manifold(2, 'M')
sage: U = M.open_subset('U') ; V = M.open_subset('V')
sage: M.declare_union(U,V)   # M is the union of U and V
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
sage: transf = c_xy.transition_map(c_uv, (x+y, x-y),
....:                   intersection_name='W', restrictions1= x>0,
....:                   restrictions2= u+v>0)
sage: inv = transf.inverse()
sage: W = U.intersection(V)
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
sage: A = M.mixed_form(name='A')
sage: A[0].set_expr(x, c_xy)
sage: A[0].display()
A_0: M → ℝ
on U: (x, y) ↦ x
on W: (u, v) ↦ 1/2*u + 1/2*v
sage: A[1][0] = y*x; A[1].display(e_xy)
A_1 = x*y dx
sage: A[2][e_uv,0,1] = u*v^2; A[2].display(e_uv)
A_2 = u*v^2 du∧dv
sage: A.add_comp_by_continuation(e_uv, W, c_uv)
sage: A.display_expansion(e_uv)
A = 1/2*u + 1/2*v + (1/8*u^2 - 1/8*v^2) du + (1/8*u^2 - 1/8*v^2) dv + u*v^2 du∧dv
sage: A.add_comp_by_continuation(e_xy, W, c_xy)
sage: A.display_expansion(e_xy)
A = x + x*y dx + (-2*x^3 + 2*x^2*y + 2*x*y^2 - 2*y^3) dx∧dy
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M')
>>> U = M.open_subset('U') ; V = M.open_subset('V')
>>> M.declare_union(U,V)   # M is the union of U and V
>>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2); c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)
>>> transf = c_xy.transition_map(c_uv, (x+y, x-y),
...                   intersection_name='W', restrictions1= x>Integer(0),
...                   restrictions2= u+v>Integer(0))
>>> inv = transf.inverse()
>>> W = U.intersection(V)
>>> e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
>>> A = M.mixed_form(name='A')
>>> A[Integer(0)].set_expr(x, c_xy)
>>> A[Integer(0)].display()
A_0: M → ℝ
on U: (x, y) ↦ x
on W: (u, v) ↦ 1/2*u + 1/2*v
>>> A[Integer(1)][Integer(0)] = y*x; A[Integer(1)].display(e_xy)
A_1 = x*y dx
>>> A[Integer(2)][e_uv,Integer(0),Integer(1)] = u*v**Integer(2); A[Integer(2)].display(e_uv)
A_2 = u*v^2 du∧dv
>>> A.add_comp_by_continuation(e_uv, W, c_uv)
>>> A.display_expansion(e_uv)
A = 1/2*u + 1/2*v + (1/8*u^2 - 1/8*v^2) du + (1/8*u^2 - 1/8*v^2) dv + u*v^2 du∧dv
>>> A.add_comp_by_continuation(e_xy, W, c_xy)
>>> A.display_expansion(e_xy)
A = x + x*y dx + (-2*x^3 + 2*x^2*y + 2*x*y^2 - 2*y^3) dx∧dy
M = Manifold(2, 'M')
U = M.open_subset('U') ; V = M.open_subset('V')
M.declare_union(U,V)   # M is the union of U and V
c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
transf = c_xy.transition_map(c_uv, (x+y, x-y),
                  intersection_name='W', restrictions1= x>0,
                  restrictions2= u+v>0)
inv = transf.inverse()
W = U.intersection(V)
e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
A = M.mixed_form(name='A')
A[0].set_expr(x, c_xy)
A[0].display()
A[1][0] = y*x; A[1].display(e_xy)
A[2][e_uv,0,1] = u*v^2; A[2].display(e_uv)
A.add_comp_by_continuation(e_uv, W, c_uv)
A.display_expansion(e_uv)
A.add_comp_by_continuation(e_xy, W, c_xy)
A.display_expansion(e_xy)

Since zero and one are special elements, their components cannot be changed:

sage: z = M.mixed_form_algebra().zero()
sage: z[0] = 1
Traceback (most recent call last):
...
ValueError: the components of an immutable element cannot be changed
sage: one = M.mixed_form_algebra().one()
sage: one[0] = 0
Traceback (most recent call last):
...
ValueError: the components of an immutable element cannot be changed
>>> from sage.all import *
>>> z = M.mixed_form_algebra().zero()
>>> z[Integer(0)] = Integer(1)
Traceback (most recent call last):
...
ValueError: the components of an immutable element cannot be changed
>>> one = M.mixed_form_algebra().one()
>>> one[Integer(0)] = Integer(0)
Traceback (most recent call last):
...
ValueError: the components of an immutable element cannot be changed
z = M.mixed_form_algebra().zero()
z[0] = 1
one = M.mixed_form_algebra().one()
one[0] = 0
add_comp_by_continuation(frame, subdomain, chart=None)[source]

Set components with respect to a vector frame by continuation of the coordinate expression of the components in a subframe.

The continuation is performed by demanding that the components have the same coordinate expression as those on the restriction of the frame to a given subdomain.

INPUT:

  • frame – vector frame \(e\) in which the components are to be set

  • subdomain – open subset of \(e\)’s domain in which the components are known or can be evaluated from other components

  • chart – (default: None) coordinate chart on \(e\)’s domain in which the extension of the expression of the components is to be performed; if None, the default’s chart of \(e\)’s domain is assumed

EXAMPLES:

Mixed form defined by differential forms with components on different parts of the 2-sphere:

sage: M = Manifold(2, 'M') # the 2-dimensional sphere S^2
sage: U = M.open_subset('U') # complement of the North pole
sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole
sage: V = M.open_subset('V') # complement of the South pole
sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole
sage: M.declare_union(U,V)   # S^2 is the union of U and V
sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
....:                intersection_name='W', restrictions1= x^2+y^2!=0,
....:                restrictions2= u^2+v^2!=0)
sage: uv_to_xy = xy_to_uv.inverse()
sage: W = U.intersection(V)
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
sage: F = M.mixed_form(name='F') # No predefined components, here
sage: F[0] = M.scalar_field(x, name='f')
sage: F[1] = M.diff_form(1, {e_xy: [x,0]}, name='omega')
sage: F[2].set_name(name='eta')
sage: F[2][e_uv,0,1] = u*v
sage: F.add_comp_by_continuation(e_uv, W, c_uv)
sage: F.add_comp_by_continuation(e_xy, W, c_xy) # Now, F is fully defined
sage: F.display_expansion(e_xy)
F = x + x dx - x*y/(x^8 + 4*x^6*y^2 + 6*x^4*y^4 + 4*x^2*y^6 + y^8) dx∧dy
sage: F.display_expansion(e_uv)
F = u/(u^2 + v^2) - (u^3 - u*v^2)/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) du - 2*u^2*v/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) dv + u*v du∧dv
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M') # the 2-dimensional sphere S^2
>>> U = M.open_subset('U') # complement of the North pole
>>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2)# stereographic coordinates from the North pole
>>> V = M.open_subset('V') # complement of the South pole
>>> c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)# stereographic coordinates from the South pole
>>> M.declare_union(U,V)   # S^2 is the union of U and V
>>> xy_to_uv = c_xy.transition_map(c_uv, (x/(x**Integer(2)+y**Integer(2)), y/(x**Integer(2)+y**Integer(2))),
...                intersection_name='W', restrictions1= x**Integer(2)+y**Integer(2)!=Integer(0),
...                restrictions2= u**Integer(2)+v**Integer(2)!=Integer(0))
>>> uv_to_xy = xy_to_uv.inverse()
>>> W = U.intersection(V)
>>> e_xy = c_xy.frame(); e_uv = c_uv.frame()
>>> F = M.mixed_form(name='F') # No predefined components, here
>>> F[Integer(0)] = M.scalar_field(x, name='f')
>>> F[Integer(1)] = M.diff_form(Integer(1), {e_xy: [x,Integer(0)]}, name='omega')
>>> F[Integer(2)].set_name(name='eta')
>>> F[Integer(2)][e_uv,Integer(0),Integer(1)] = u*v
>>> F.add_comp_by_continuation(e_uv, W, c_uv)
>>> F.add_comp_by_continuation(e_xy, W, c_xy) # Now, F is fully defined
>>> F.display_expansion(e_xy)
F = x + x dx - x*y/(x^8 + 4*x^6*y^2 + 6*x^4*y^4 + 4*x^2*y^6 + y^8) dx∧dy
>>> F.display_expansion(e_uv)
F = u/(u^2 + v^2) - (u^3 - u*v^2)/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) du - 2*u^2*v/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) dv + u*v du∧dv
M = Manifold(2, 'M') # the 2-dimensional sphere S^2
U = M.open_subset('U') # complement of the North pole
c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole
V = M.open_subset('V') # complement of the South pole
c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole
M.declare_union(U,V)   # S^2 is the union of U and V
xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
               intersection_name='W', restrictions1= x^2+y^2!=0,
               restrictions2= u^2+v^2!=0)
uv_to_xy = xy_to_uv.inverse()
W = U.intersection(V)
e_xy = c_xy.frame(); e_uv = c_uv.frame()
F = M.mixed_form(name='F') # No predefined components, here
F[0] = M.scalar_field(x, name='f')
F[1] = M.diff_form(1, {e_xy: [x,0]}, name='omega')
F[2].set_name(name='eta')
F[2][e_uv,0,1] = u*v
F.add_comp_by_continuation(e_uv, W, c_uv)
F.add_comp_by_continuation(e_xy, W, c_xy) # Now, F is fully defined
F.display_expansion(e_xy)
F.display_expansion(e_uv)
copy(name=None, latex_name=None)[source]

Return an exact copy of self.

Note

The name and names of the components are not copied.

INPUT:

  • name – (default: None) name given to the copy

  • latex_name – (default: None) LaTeX symbol to denote the copy; if none is provided, the LaTeX symbol is set to name

EXAMPLES:

Initialize a 2-dimensional manifold and differential forms:

sage: M = Manifold(2, 'M')
sage: U = M.open_subset('U') ; V = M.open_subset('V')
sage: M.declare_union(U,V)   # M is the union of U and V
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
sage: xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
....:                    intersection_name='W', restrictions1= x>0,
....:                    restrictions2= u+v>0)
sage: uv_to_xy = xy_to_uv.inverse()
sage: W = U.intersection(V)
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
sage: f = M.scalar_field(x, name='f', chart=c_xy)
sage: f.add_expr_by_continuation(c_uv, W)
sage: f.display()
f: M → ℝ
on U: (x, y) ↦ x
on V: (u, v) ↦ 1/2*u + 1/2*v
sage: omega = M.diff_form(1, name='omega')
sage: omega[e_xy,0] = x
sage: omega.add_comp_by_continuation(e_uv, W, c_uv)
sage: omega.display()
omega = x dx
sage: A = M.mixed_form([f, omega, 0], name='A'); A.display()
A = f + omega + zero
sage: A.display_expansion(e_uv)
A = 1/2*u + 1/2*v + (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M')
>>> U = M.open_subset('U') ; V = M.open_subset('V')
>>> M.declare_union(U,V)   # M is the union of U and V
>>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2); c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)
>>> xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
...                    intersection_name='W', restrictions1= x>Integer(0),
...                    restrictions2= u+v>Integer(0))
>>> uv_to_xy = xy_to_uv.inverse()
>>> W = U.intersection(V)
>>> e_xy = c_xy.frame(); e_uv = c_uv.frame()
>>> f = M.scalar_field(x, name='f', chart=c_xy)
>>> f.add_expr_by_continuation(c_uv, W)
>>> f.display()
f: M → ℝ
on U: (x, y) ↦ x
on V: (u, v) ↦ 1/2*u + 1/2*v
>>> omega = M.diff_form(Integer(1), name='omega')
>>> omega[e_xy,Integer(0)] = x
>>> omega.add_comp_by_continuation(e_uv, W, c_uv)
>>> omega.display()
omega = x dx
>>> A = M.mixed_form([f, omega, Integer(0)], name='A'); A.display()
A = f + omega + zero
>>> A.display_expansion(e_uv)
A = 1/2*u + 1/2*v + (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv
M = Manifold(2, 'M')
U = M.open_subset('U') ; V = M.open_subset('V')
M.declare_union(U,V)   # M is the union of U and V
c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
xy_to_uv = c_xy.transition_map(c_uv, (x+y, x-y),
                   intersection_name='W', restrictions1= x>0,
                   restrictions2= u+v>0)
uv_to_xy = xy_to_uv.inverse()
W = U.intersection(V)
e_xy = c_xy.frame(); e_uv = c_uv.frame()
f = M.scalar_field(x, name='f', chart=c_xy)
f.add_expr_by_continuation(c_uv, W)
f.display()
omega = M.diff_form(1, name='omega')
omega[e_xy,0] = x
omega.add_comp_by_continuation(e_uv, W, c_uv)
omega.display()
A = M.mixed_form([f, omega, 0], name='A'); A.display()
A.display_expansion(e_uv)

An exact copy is made. The copy is an entirely new instance and has a different name, but has the very same values:

sage: B = A.copy(); B.display()
(unnamed scalar field) + (unnamed 1-form) + (unnamed 2-form)
sage: B.display_expansion(e_uv)
1/2*u + 1/2*v + (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv
sage: A == B
True
sage: A is B
False
>>> from sage.all import *
>>> B = A.copy(); B.display()
(unnamed scalar field) + (unnamed 1-form) + (unnamed 2-form)
>>> B.display_expansion(e_uv)
1/2*u + 1/2*v + (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv
>>> A == B
True
>>> A is B
False
B = A.copy(); B.display()
B.display_expansion(e_uv)
A == B
A is B
derivative()[source]

Compute the exterior derivative of self.

More precisely, the exterior derivative on \(\Omega^k(M,\varphi)\) is a linear map

\[\mathrm{d}_{k} : \Omega^k(M,\varphi) \to \Omega^{k+1}(M,\varphi),\]

where \(\Omega^k(M,\varphi)\) denotes the space of differential forms of degree \(k\) along \(\varphi\) (see exterior_derivative() for further information). By linear extension, this induces a map on \(\Omega^*(M,\varphi)\):

\[\mathrm{d}: \Omega^*(M,\varphi) \to \Omega^*(M,\varphi).\]

OUTPUT:

  • a MixedForm representing the exterior derivative of the mixed form

EXAMPLES:

Exterior derivative of a mixed form on a 3-dimensional manifold:

sage: M = Manifold(3, 'M', start_index=1)
sage: c_xyz.<x,y,z> = M.chart()
sage: f = M.scalar_field(z^2, name='f')
sage: f.disp()
f: M → ℝ
    (x, y, z) ↦ z^2
sage: a = M.diff_form(2, 'a')
sage: a[1,2], a[1,3], a[2,3] = z+y^2, z+x, x^2
sage: a.disp()
a = (y^2 + z) dx∧dy + (x + z) dx∧dz + x^2 dy∧dz
sage: F = M.mixed_form([f, 0, a, 0], name='F'); F.display()
F = f + zero + a + zero
sage: dF = F.exterior_derivative()
sage: dF.display()
dF = zero + df + dzero + da
sage: dF = F.exterior_derivative()
sage: dF.display_expansion()
dF = 2*z dz + (2*x + 1) dx∧dy∧dz
>>> from sage.all import *
>>> M = Manifold(Integer(3), 'M', start_index=Integer(1))
>>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3)
>>> f = M.scalar_field(z**Integer(2), name='f')
>>> f.disp()
f: M → ℝ
    (x, y, z) ↦ z^2
>>> a = M.diff_form(Integer(2), 'a')
>>> a[Integer(1),Integer(2)], a[Integer(1),Integer(3)], a[Integer(2),Integer(3)] = z+y**Integer(2), z+x, x**Integer(2)
>>> a.disp()
a = (y^2 + z) dx∧dy + (x + z) dx∧dz + x^2 dy∧dz
>>> F = M.mixed_form([f, Integer(0), a, Integer(0)], name='F'); F.display()
F = f + zero + a + zero
>>> dF = F.exterior_derivative()
>>> dF.display()
dF = zero + df + dzero + da
>>> dF = F.exterior_derivative()
>>> dF.display_expansion()
dF = 2*z dz + (2*x + 1) dx∧dy∧dz
M = Manifold(3, 'M', start_index=1)
c_xyz.<x,y,z> = M.chart()
f = M.scalar_field(z^2, name='f')
f.disp()
a = M.diff_form(2, 'a')
a[1,2], a[1,3], a[2,3] = z+y^2, z+x, x^2
a.disp()
F = M.mixed_form([f, 0, a, 0], name='F'); F.display()
dF = F.exterior_derivative()
dF.display()
dF = F.exterior_derivative()
dF.display_expansion()

Due to long calculation times, the result is cached:

sage: F.exterior_derivative() is dF
True
>>> from sage.all import *
>>> F.exterior_derivative() is dF
True
F.exterior_derivative() is dF
disp()[source]

Display the homogeneous components of the mixed form.

The output is either text-formatted (console mode) or LaTeX-formatted (notebook mode).

EXAMPLES:

sage: M = Manifold(2, 'M')
sage: f = M.scalar_field(name='f')
sage: omega = M.diff_form(1, name='omega')
sage: eta = M.diff_form(2, name='eta')
sage: F = M.mixed_form([f, omega, eta], name='F'); F
Mixed differential form F on the 2-dimensional differentiable
 manifold M
sage: F.display() # display names of homogeneous components
F = f + omega + eta
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M')
>>> f = M.scalar_field(name='f')
>>> omega = M.diff_form(Integer(1), name='omega')
>>> eta = M.diff_form(Integer(2), name='eta')
>>> F = M.mixed_form([f, omega, eta], name='F'); F
Mixed differential form F on the 2-dimensional differentiable
 manifold M
>>> F.display() # display names of homogeneous components
F = f + omega + eta
M = Manifold(2, 'M')
f = M.scalar_field(name='f')
omega = M.diff_form(1, name='omega')
eta = M.diff_form(2, name='eta')
F = M.mixed_form([f, omega, eta], name='F'); F
F.display() # display names of homogeneous components
disp_exp(frame=None, chart=None, from_chart=None)[source]

Display the expansion in a particular basis and chart of mixed forms.

The output is either text-formatted (console mode) or LaTeX-formatted (notebook mode).

INPUT:

  • frame – (default: None) vector frame with respect to which the mixed form is expanded; if None, only the names of the components are displayed

  • chart – (default: None) chart with respect to which the components of the mixed form in the selected frame are expressed; if None, the default chart of the vector frame domain is assumed

EXAMPLES:

Display the expansion of a mixed form on a 2-dimensional non-parallelizable differentiable manifold:

sage: M = Manifold(2, 'M')
sage: U = M.open_subset('U') ; V = M.open_subset('V')
sage: M.declare_union(U,V)   # M is the union of U and V
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
sage: transf = c_xy.transition_map(c_uv, (x-y, x+y),
....:                   intersection_name='W', restrictions1= x>0,
....:                   restrictions2= u+v>0)
sage: inv = transf.inverse()
sage: W = U.intersection(V)
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
sage: omega = M.diff_form(1, name='omega')
sage: omega[e_xy,0] = x; omega.display(e_xy)
omega = x dx
sage: omega.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
sage: eta = M.diff_form(2, name='eta')
sage: eta[e_uv,0,1] = u*v; eta.display(e_uv)
eta = u*v du∧dv
sage: eta.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
sage: F = M.mixed_form([0, omega, eta], name='F'); F
Mixed differential form F on the 2-dimensional differentiable
 manifold M
sage: F.display() # display names of homogeneous components
F = zero + omega + eta
sage: F.display_expansion(e_uv)
F = (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv + u*v du∧dv
sage: F.display_expansion(e_xy)
F = x dx + (2*x^2 - 2*y^2) dx∧dy
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M')
>>> U = M.open_subset('U') ; V = M.open_subset('V')
>>> M.declare_union(U,V)   # M is the union of U and V
>>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2); c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)
>>> transf = c_xy.transition_map(c_uv, (x-y, x+y),
...                   intersection_name='W', restrictions1= x>Integer(0),
...                   restrictions2= u+v>Integer(0))
>>> inv = transf.inverse()
>>> W = U.intersection(V)
>>> e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
>>> omega = M.diff_form(Integer(1), name='omega')
>>> omega[e_xy,Integer(0)] = x; omega.display(e_xy)
omega = x dx
>>> omega.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
>>> eta = M.diff_form(Integer(2), name='eta')
>>> eta[e_uv,Integer(0),Integer(1)] = u*v; eta.display(e_uv)
eta = u*v du∧dv
>>> eta.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
>>> F = M.mixed_form([Integer(0), omega, eta], name='F'); F
Mixed differential form F on the 2-dimensional differentiable
 manifold M
>>> F.display() # display names of homogeneous components
F = zero + omega + eta
>>> F.display_expansion(e_uv)
F = (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv + u*v du∧dv
>>> F.display_expansion(e_xy)
F = x dx + (2*x^2 - 2*y^2) dx∧dy
M = Manifold(2, 'M')
U = M.open_subset('U') ; V = M.open_subset('V')
M.declare_union(U,V)   # M is the union of U and V
c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
transf = c_xy.transition_map(c_uv, (x-y, x+y),
                  intersection_name='W', restrictions1= x>0,
                  restrictions2= u+v>0)
inv = transf.inverse()
W = U.intersection(V)
e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
omega = M.diff_form(1, name='omega')
omega[e_xy,0] = x; omega.display(e_xy)
omega.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
eta = M.diff_form(2, name='eta')
eta[e_uv,0,1] = u*v; eta.display(e_uv)
eta.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
F = M.mixed_form([0, omega, eta], name='F'); F
F.display() # display names of homogeneous components
F.display_expansion(e_uv)
F.display_expansion(e_xy)
display()[source]

Display the homogeneous components of the mixed form.

The output is either text-formatted (console mode) or LaTeX-formatted (notebook mode).

EXAMPLES:

sage: M = Manifold(2, 'M')
sage: f = M.scalar_field(name='f')
sage: omega = M.diff_form(1, name='omega')
sage: eta = M.diff_form(2, name='eta')
sage: F = M.mixed_form([f, omega, eta], name='F'); F
Mixed differential form F on the 2-dimensional differentiable
 manifold M
sage: F.display() # display names of homogeneous components
F = f + omega + eta
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M')
>>> f = M.scalar_field(name='f')
>>> omega = M.diff_form(Integer(1), name='omega')
>>> eta = M.diff_form(Integer(2), name='eta')
>>> F = M.mixed_form([f, omega, eta], name='F'); F
Mixed differential form F on the 2-dimensional differentiable
 manifold M
>>> F.display() # display names of homogeneous components
F = f + omega + eta
M = Manifold(2, 'M')
f = M.scalar_field(name='f')
omega = M.diff_form(1, name='omega')
eta = M.diff_form(2, name='eta')
F = M.mixed_form([f, omega, eta], name='F'); F
F.display() # display names of homogeneous components
display_exp(frame=None, chart=None, from_chart=None)[source]

Display the expansion in a particular basis and chart of mixed forms.

The output is either text-formatted (console mode) or LaTeX-formatted (notebook mode).

INPUT:

  • frame – (default: None) vector frame with respect to which the mixed form is expanded; if None, only the names of the components are displayed

  • chart – (default: None) chart with respect to which the components of the mixed form in the selected frame are expressed; if None, the default chart of the vector frame domain is assumed

EXAMPLES:

Display the expansion of a mixed form on a 2-dimensional non-parallelizable differentiable manifold:

sage: M = Manifold(2, 'M')
sage: U = M.open_subset('U') ; V = M.open_subset('V')
sage: M.declare_union(U,V)   # M is the union of U and V
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
sage: transf = c_xy.transition_map(c_uv, (x-y, x+y),
....:                   intersection_name='W', restrictions1= x>0,
....:                   restrictions2= u+v>0)
sage: inv = transf.inverse()
sage: W = U.intersection(V)
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
sage: omega = M.diff_form(1, name='omega')
sage: omega[e_xy,0] = x; omega.display(e_xy)
omega = x dx
sage: omega.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
sage: eta = M.diff_form(2, name='eta')
sage: eta[e_uv,0,1] = u*v; eta.display(e_uv)
eta = u*v du∧dv
sage: eta.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
sage: F = M.mixed_form([0, omega, eta], name='F'); F
Mixed differential form F on the 2-dimensional differentiable
 manifold M
sage: F.display() # display names of homogeneous components
F = zero + omega + eta
sage: F.display_expansion(e_uv)
F = (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv + u*v du∧dv
sage: F.display_expansion(e_xy)
F = x dx + (2*x^2 - 2*y^2) dx∧dy
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M')
>>> U = M.open_subset('U') ; V = M.open_subset('V')
>>> M.declare_union(U,V)   # M is the union of U and V
>>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2); c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)
>>> transf = c_xy.transition_map(c_uv, (x-y, x+y),
...                   intersection_name='W', restrictions1= x>Integer(0),
...                   restrictions2= u+v>Integer(0))
>>> inv = transf.inverse()
>>> W = U.intersection(V)
>>> e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
>>> omega = M.diff_form(Integer(1), name='omega')
>>> omega[e_xy,Integer(0)] = x; omega.display(e_xy)
omega = x dx
>>> omega.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
>>> eta = M.diff_form(Integer(2), name='eta')
>>> eta[e_uv,Integer(0),Integer(1)] = u*v; eta.display(e_uv)
eta = u*v du∧dv
>>> eta.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
>>> F = M.mixed_form([Integer(0), omega, eta], name='F'); F
Mixed differential form F on the 2-dimensional differentiable
 manifold M
>>> F.display() # display names of homogeneous components
F = zero + omega + eta
>>> F.display_expansion(e_uv)
F = (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv + u*v du∧dv
>>> F.display_expansion(e_xy)
F = x dx + (2*x^2 - 2*y^2) dx∧dy
M = Manifold(2, 'M')
U = M.open_subset('U') ; V = M.open_subset('V')
M.declare_union(U,V)   # M is the union of U and V
c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
transf = c_xy.transition_map(c_uv, (x-y, x+y),
                  intersection_name='W', restrictions1= x>0,
                  restrictions2= u+v>0)
inv = transf.inverse()
W = U.intersection(V)
e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
omega = M.diff_form(1, name='omega')
omega[e_xy,0] = x; omega.display(e_xy)
omega.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
eta = M.diff_form(2, name='eta')
eta[e_uv,0,1] = u*v; eta.display(e_uv)
eta.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
F = M.mixed_form([0, omega, eta], name='F'); F
F.display() # display names of homogeneous components
F.display_expansion(e_uv)
F.display_expansion(e_xy)
display_expansion(frame=None, chart=None, from_chart=None)[source]

Display the expansion in a particular basis and chart of mixed forms.

The output is either text-formatted (console mode) or LaTeX-formatted (notebook mode).

INPUT:

  • frame – (default: None) vector frame with respect to which the mixed form is expanded; if None, only the names of the components are displayed

  • chart – (default: None) chart with respect to which the components of the mixed form in the selected frame are expressed; if None, the default chart of the vector frame domain is assumed

EXAMPLES:

Display the expansion of a mixed form on a 2-dimensional non-parallelizable differentiable manifold:

sage: M = Manifold(2, 'M')
sage: U = M.open_subset('U') ; V = M.open_subset('V')
sage: M.declare_union(U,V)   # M is the union of U and V
sage: c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
sage: transf = c_xy.transition_map(c_uv, (x-y, x+y),
....:                   intersection_name='W', restrictions1= x>0,
....:                   restrictions2= u+v>0)
sage: inv = transf.inverse()
sage: W = U.intersection(V)
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
sage: omega = M.diff_form(1, name='omega')
sage: omega[e_xy,0] = x; omega.display(e_xy)
omega = x dx
sage: omega.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
sage: eta = M.diff_form(2, name='eta')
sage: eta[e_uv,0,1] = u*v; eta.display(e_uv)
eta = u*v du∧dv
sage: eta.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
sage: F = M.mixed_form([0, omega, eta], name='F'); F
Mixed differential form F on the 2-dimensional differentiable
 manifold M
sage: F.display() # display names of homogeneous components
F = zero + omega + eta
sage: F.display_expansion(e_uv)
F = (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv + u*v du∧dv
sage: F.display_expansion(e_xy)
F = x dx + (2*x^2 - 2*y^2) dx∧dy
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M')
>>> U = M.open_subset('U') ; V = M.open_subset('V')
>>> M.declare_union(U,V)   # M is the union of U and V
>>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2); c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)
>>> transf = c_xy.transition_map(c_uv, (x-y, x+y),
...                   intersection_name='W', restrictions1= x>Integer(0),
...                   restrictions2= u+v>Integer(0))
>>> inv = transf.inverse()
>>> W = U.intersection(V)
>>> e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
>>> omega = M.diff_form(Integer(1), name='omega')
>>> omega[e_xy,Integer(0)] = x; omega.display(e_xy)
omega = x dx
>>> omega.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
>>> eta = M.diff_form(Integer(2), name='eta')
>>> eta[e_uv,Integer(0),Integer(1)] = u*v; eta.display(e_uv)
eta = u*v du∧dv
>>> eta.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
>>> F = M.mixed_form([Integer(0), omega, eta], name='F'); F
Mixed differential form F on the 2-dimensional differentiable
 manifold M
>>> F.display() # display names of homogeneous components
F = zero + omega + eta
>>> F.display_expansion(e_uv)
F = (1/4*u + 1/4*v) du + (1/4*u + 1/4*v) dv + u*v du∧dv
>>> F.display_expansion(e_xy)
F = x dx + (2*x^2 - 2*y^2) dx∧dy
M = Manifold(2, 'M')
U = M.open_subset('U') ; V = M.open_subset('V')
M.declare_union(U,V)   # M is the union of U and V
c_xy.<x,y> = U.chart() ; c_uv.<u,v> = V.chart()
transf = c_xy.transition_map(c_uv, (x-y, x+y),
                  intersection_name='W', restrictions1= x>0,
                  restrictions2= u+v>0)
inv = transf.inverse()
W = U.intersection(V)
e_xy = c_xy.frame(); e_uv = c_uv.frame() # define frames
omega = M.diff_form(1, name='omega')
omega[e_xy,0] = x; omega.display(e_xy)
omega.add_comp_by_continuation(e_uv, W, c_uv) # continuation onto M
eta = M.diff_form(2, name='eta')
eta[e_uv,0,1] = u*v; eta.display(e_uv)
eta.add_comp_by_continuation(e_xy, W, c_xy) # continuation onto M
F = M.mixed_form([0, omega, eta], name='F'); F
F.display() # display names of homogeneous components
F.display_expansion(e_uv)
F.display_expansion(e_xy)
exterior_derivative()[source]

Compute the exterior derivative of self.

More precisely, the exterior derivative on \(\Omega^k(M,\varphi)\) is a linear map

\[\mathrm{d}_{k} : \Omega^k(M,\varphi) \to \Omega^{k+1}(M,\varphi),\]

where \(\Omega^k(M,\varphi)\) denotes the space of differential forms of degree \(k\) along \(\varphi\) (see exterior_derivative() for further information). By linear extension, this induces a map on \(\Omega^*(M,\varphi)\):

\[\mathrm{d}: \Omega^*(M,\varphi) \to \Omega^*(M,\varphi).\]

OUTPUT:

  • a MixedForm representing the exterior derivative of the mixed form

EXAMPLES:

Exterior derivative of a mixed form on a 3-dimensional manifold:

sage: M = Manifold(3, 'M', start_index=1)
sage: c_xyz.<x,y,z> = M.chart()
sage: f = M.scalar_field(z^2, name='f')
sage: f.disp()
f: M → ℝ
    (x, y, z) ↦ z^2
sage: a = M.diff_form(2, 'a')
sage: a[1,2], a[1,3], a[2,3] = z+y^2, z+x, x^2
sage: a.disp()
a = (y^2 + z) dx∧dy + (x + z) dx∧dz + x^2 dy∧dz
sage: F = M.mixed_form([f, 0, a, 0], name='F'); F.display()
F = f + zero + a + zero
sage: dF = F.exterior_derivative()
sage: dF.display()
dF = zero + df + dzero + da
sage: dF = F.exterior_derivative()
sage: dF.display_expansion()
dF = 2*z dz + (2*x + 1) dx∧dy∧dz
>>> from sage.all import *
>>> M = Manifold(Integer(3), 'M', start_index=Integer(1))
>>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3)
>>> f = M.scalar_field(z**Integer(2), name='f')
>>> f.disp()
f: M → ℝ
    (x, y, z) ↦ z^2
>>> a = M.diff_form(Integer(2), 'a')
>>> a[Integer(1),Integer(2)], a[Integer(1),Integer(3)], a[Integer(2),Integer(3)] = z+y**Integer(2), z+x, x**Integer(2)
>>> a.disp()
a = (y^2 + z) dx∧dy + (x + z) dx∧dz + x^2 dy∧dz
>>> F = M.mixed_form([f, Integer(0), a, Integer(0)], name='F'); F.display()
F = f + zero + a + zero
>>> dF = F.exterior_derivative()
>>> dF.display()
dF = zero + df + dzero + da
>>> dF = F.exterior_derivative()
>>> dF.display_expansion()
dF = 2*z dz + (2*x + 1) dx∧dy∧dz
M = Manifold(3, 'M', start_index=1)
c_xyz.<x,y,z> = M.chart()
f = M.scalar_field(z^2, name='f')
f.disp()
a = M.diff_form(2, 'a')
a[1,2], a[1,3], a[2,3] = z+y^2, z+x, x^2
a.disp()
F = M.mixed_form([f, 0, a, 0], name='F'); F.display()
dF = F.exterior_derivative()
dF.display()
dF = F.exterior_derivative()
dF.display_expansion()

Due to long calculation times, the result is cached:

sage: F.exterior_derivative() is dF
True
>>> from sage.all import *
>>> F.exterior_derivative() is dF
True
F.exterior_derivative() is dF
irange(start=None)[source]

Single index generator.

INPUT:

  • start – (default: None) initial value \(i_0\) of the index between 0 and \(n\), where \(n\) is the manifold’s dimension; if none is provided, the value 0 is assumed

OUTPUT:

  • an iterable index, starting from \(i_0\) and ending at \(n\), where \(n\) is the manifold’s dimension

EXAMPLES:

sage: M = Manifold(3, 'M')
sage: a = M.mixed_form(name='a')
sage: list(a.irange())
[0, 1, 2, 3]
sage: list(a.irange(2))
[2, 3]
>>> from sage.all import *
>>> M = Manifold(Integer(3), 'M')
>>> a = M.mixed_form(name='a')
>>> list(a.irange())
[0, 1, 2, 3]
>>> list(a.irange(Integer(2)))
[2, 3]
M = Manifold(3, 'M')
a = M.mixed_form(name='a')
list(a.irange())
list(a.irange(2))
restrict(subdomain, dest_map=None)[source]

Return the restriction of self to some subdomain.

INPUT:

  • subdomainDifferentiableManifold; open subset \(U\) of the domain of self

  • dest_mapDiffMap (default: None); destination map \(\Psi:\ U \rightarrow V\), where \(V\) is an open subset of the manifold \(N\) where the mixed form takes it values; if None, the restriction of \(\Phi\) to \(U\) is used, \(\Phi\) being the differentiable map \(S \rightarrow M\) associated with the mixed form

OUTPUT: MixedForm representing the restriction

EXAMPLES:

Initialize the 2-sphere:

sage: M = Manifold(2, 'M') # the 2-dimensional sphere S^2
sage: U = M.open_subset('U') # complement of the North pole
sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole
sage: V = M.open_subset('V') # complement of the South pole
sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole
sage: M.declare_union(U,V)   # S^2 is the union of U and V
sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
....:                intersection_name='W', restrictions1= x^2+y^2!=0,
....:                restrictions2= u^2+v^2!=0)
sage: uv_to_xy = xy_to_uv.inverse()
sage: W = U.intersection(V)
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M') # the 2-dimensional sphere S^2
>>> U = M.open_subset('U') # complement of the North pole
>>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2)# stereographic coordinates from the North pole
>>> V = M.open_subset('V') # complement of the South pole
>>> c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)# stereographic coordinates from the South pole
>>> M.declare_union(U,V)   # S^2 is the union of U and V
>>> xy_to_uv = c_xy.transition_map(c_uv, (x/(x**Integer(2)+y**Integer(2)), y/(x**Integer(2)+y**Integer(2))),
...                intersection_name='W', restrictions1= x**Integer(2)+y**Integer(2)!=Integer(0),
...                restrictions2= u**Integer(2)+v**Integer(2)!=Integer(0))
>>> uv_to_xy = xy_to_uv.inverse()
>>> W = U.intersection(V)
>>> e_xy = c_xy.frame(); e_uv = c_uv.frame()
M = Manifold(2, 'M') # the 2-dimensional sphere S^2
U = M.open_subset('U') # complement of the North pole
c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole
V = M.open_subset('V') # complement of the South pole
c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole
M.declare_union(U,V)   # S^2 is the union of U and V
xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
               intersection_name='W', restrictions1= x^2+y^2!=0,
               restrictions2= u^2+v^2!=0)
uv_to_xy = xy_to_uv.inverse()
W = U.intersection(V)
e_xy = c_xy.frame(); e_uv = c_uv.frame()

And predefine some forms:

sage: f = M.scalar_field(x^2, name='f', chart=c_xy)
sage: f.add_expr_by_continuation(c_uv, W)
sage: omega = M.diff_form(1, name='omega')
sage: omega[e_xy,0] = y^2
sage: omega.add_comp_by_continuation(e_uv, W, c_uv)
sage: eta = M.diff_form(2, name='eta')
sage: eta[e_xy,0,1] = x^2*y^2
sage: eta.add_comp_by_continuation(e_uv, W, c_uv)
>>> from sage.all import *
>>> f = M.scalar_field(x**Integer(2), name='f', chart=c_xy)
>>> f.add_expr_by_continuation(c_uv, W)
>>> omega = M.diff_form(Integer(1), name='omega')
>>> omega[e_xy,Integer(0)] = y**Integer(2)
>>> omega.add_comp_by_continuation(e_uv, W, c_uv)
>>> eta = M.diff_form(Integer(2), name='eta')
>>> eta[e_xy,Integer(0),Integer(1)] = x**Integer(2)*y**Integer(2)
>>> eta.add_comp_by_continuation(e_uv, W, c_uv)
f = M.scalar_field(x^2, name='f', chart=c_xy)
f.add_expr_by_continuation(c_uv, W)
omega = M.diff_form(1, name='omega')
omega[e_xy,0] = y^2
omega.add_comp_by_continuation(e_uv, W, c_uv)
eta = M.diff_form(2, name='eta')
eta[e_xy,0,1] = x^2*y^2
eta.add_comp_by_continuation(e_uv, W, c_uv)

Now, a mixed form can be restricted to some subdomain:

sage: F = M.mixed_form([f, omega, eta], name='F')
sage: FV = F.restrict(V); FV
Mixed differential form F on the Open subset V of the 2-dimensional
 differentiable manifold M
sage: FV[:]
[Scalar field f on the Open subset V of the 2-dimensional
 differentiable manifold M,
 1-form omega on the Open subset V of the 2-dimensional
 differentiable manifold M,
 2-form eta on the Open subset V of the 2-dimensional
 differentiable manifold M]
sage: FV.display_expansion(e_uv)
F = u^2/(u^4 + 2*u^2*v^2 + v^4) - (u^2*v^2 - v^4)/(u^8 + 4*u^6*v^2 + 6*u^4*v^4 + 4*u^2*v^6 + v^8) du - 2*u*v^3/(u^8 + 4*u^6*v^2 + 6*u^4*v^4 + 4*u^2*v^6 + v^8) dv - u^2*v^2/(u^12 + 6*u^10*v^2 + 15*u^8*v^4 + 20*u^6*v^6 + 15*u^4*v^8 + 6*u^2*v^10 + v^12) du∧dv
>>> from sage.all import *
>>> F = M.mixed_form([f, omega, eta], name='F')
>>> FV = F.restrict(V); FV
Mixed differential form F on the Open subset V of the 2-dimensional
 differentiable manifold M
>>> FV[:]
[Scalar field f on the Open subset V of the 2-dimensional
 differentiable manifold M,
 1-form omega on the Open subset V of the 2-dimensional
 differentiable manifold M,
 2-form eta on the Open subset V of the 2-dimensional
 differentiable manifold M]
>>> FV.display_expansion(e_uv)
F = u^2/(u^4 + 2*u^2*v^2 + v^4) - (u^2*v^2 - v^4)/(u^8 + 4*u^6*v^2 + 6*u^4*v^4 + 4*u^2*v^6 + v^8) du - 2*u*v^3/(u^8 + 4*u^6*v^2 + 6*u^4*v^4 + 4*u^2*v^6 + v^8) dv - u^2*v^2/(u^12 + 6*u^10*v^2 + 15*u^8*v^4 + 20*u^6*v^6 + 15*u^4*v^8 + 6*u^2*v^10 + v^12) du∧dv
F = M.mixed_form([f, omega, eta], name='F')
FV = F.restrict(V); FV
FV[:]
FV.display_expansion(e_uv)
set_comp(i)[source]

Return the \(i\)-th homogeneous component for assignment.

EXAMPLES:

sage: M = Manifold(2, 'M')
sage: X.<x,y> = M.chart()
sage: A = M.mixed_form(name='A')
sage: A.set_comp(0).set_expr(x^2) # scalar field
sage: A.set_comp(1)[:] = [-y, x]
sage: A.set_comp(2)[0,1] = x-y
sage: A.display()
A = A_0 + A_1 + A_2
sage: A.display_expansion()
A = x^2 - y dx + x dy + (x - y) dx∧dy
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M')
>>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2)
>>> A = M.mixed_form(name='A')
>>> A.set_comp(Integer(0)).set_expr(x**Integer(2)) # scalar field
>>> A.set_comp(Integer(1))[:] = [-y, x]
>>> A.set_comp(Integer(2))[Integer(0),Integer(1)] = x-y
>>> A.display()
A = A_0 + A_1 + A_2
>>> A.display_expansion()
A = x^2 - y dx + x dy + (x - y) dx∧dy
M = Manifold(2, 'M')
X.<x,y> = M.chart()
A = M.mixed_form(name='A')
A.set_comp(0).set_expr(x^2) # scalar field
A.set_comp(1)[:] = [-y, x]
A.set_comp(2)[0,1] = x-y
A.display()
A.display_expansion()
set_immutable()[source]

Set self and homogeneous components of self immutable.

EXAMPLES:

sage: M = Manifold(2, 'M')
sage: X.<x,y> = M.chart()
sage: f = M.scalar_field(x^2, name='f')
sage: A = M.mixed_form([f, 0, 0], name='A')
sage: A.set_immutable()
sage: A.is_immutable()
True
sage: A[0].is_immutable()
True
sage: f.is_immutable()
False
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M')
>>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2)
>>> f = M.scalar_field(x**Integer(2), name='f')
>>> A = M.mixed_form([f, Integer(0), Integer(0)], name='A')
>>> A.set_immutable()
>>> A.is_immutable()
True
>>> A[Integer(0)].is_immutable()
True
>>> f.is_immutable()
False
M = Manifold(2, 'M')
X.<x,y> = M.chart()
f = M.scalar_field(x^2, name='f')
A = M.mixed_form([f, 0, 0], name='A')
A.set_immutable()
A.is_immutable()
A[0].is_immutable()
f.is_immutable()
set_name(name=None, latex_name=None, apply_to_comp=True)[source]

Redefine the string and LaTeX representation of the object.

INPUT:

  • name – (default: None) name given to the mixed form

  • latex_name – (default: None) LaTeX symbol to denote the mixed form; if none is provided, the LaTeX symbol is set to name

  • apply_to_comp – boolean (default: True); if True all homogeneous components will be renamed accordingly. If False only the mixed form will be renamed

EXAMPLES:

Rename a mixed form:

sage: M = Manifold(4, 'M')
sage: F = M.mixed_form(name='dummy', latex_name=r'\ugly'); F
Mixed differential form dummy on the 4-dimensional differentiable
 manifold M
sage: latex(F)
\ugly
sage: F.set_name(name='F', latex_name=r'\mathcal{F}'); F
Mixed differential form F on the 4-dimensional differentiable
 manifold M
sage: latex(F)
\mathcal{F}
>>> from sage.all import *
>>> M = Manifold(Integer(4), 'M')
>>> F = M.mixed_form(name='dummy', latex_name=r'\ugly'); F
Mixed differential form dummy on the 4-dimensional differentiable
 manifold M
>>> latex(F)
\ugly
>>> F.set_name(name='F', latex_name=r'\mathcal{F}'); F
Mixed differential form F on the 4-dimensional differentiable
 manifold M
>>> latex(F)
\mathcal{F}
M = Manifold(4, 'M')
F = M.mixed_form(name='dummy', latex_name=r'\ugly'); F
latex(F)
F.set_name(name='F', latex_name=r'\mathcal{F}'); F
latex(F)

If not stated otherwise, all homogeneous components are renamed accordingly:

sage: F.display()
F = F_0 + F_1 + F_2 + F_3 + F_4
>>> from sage.all import *
>>> F.display()
F = F_0 + F_1 + F_2 + F_3 + F_4
F.display()

Setting the argument set_all to False prevents the renaming in the homogeneous components:

sage: F.set_name(name='eta', latex_name=r'\eta', apply_to_comp=False)
sage: F.display()
eta = F_0 + F_1 + F_2 + F_3 + F_4
>>> from sage.all import *
>>> F.set_name(name='eta', latex_name=r'\eta', apply_to_comp=False)
>>> F.display()
eta = F_0 + F_1 + F_2 + F_3 + F_4
F.set_name(name='eta', latex_name=r'\eta', apply_to_comp=False)
F.display()

To rename a homogeneous component individually, we simply access the homogeneous component and use its set_name() method:

sage: F[0].set_name(name='g'); F.display()
eta = g + F_1 + F_2 + F_3 + F_4
>>> from sage.all import *
>>> F[Integer(0)].set_name(name='g'); F.display()
eta = g + F_1 + F_2 + F_3 + F_4
F[0].set_name(name='g'); F.display()
set_restriction(rst)[source]

Set a (component-wise) restriction of self to some subdomain.

INPUT:

  • rstMixedForm of the same type as self, defined on a subdomain of the domain of self

EXAMPLES:

Initialize the 2-sphere:

sage: M = Manifold(2, 'M') # the 2-dimensional sphere S^2
sage: U = M.open_subset('U') # complement of the North pole
sage: c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole
sage: V = M.open_subset('V') # complement of the South pole
sage: c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole
sage: M.declare_union(U,V)   # S^2 is the union of U and V
sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
....:                intersection_name='W', restrictions1= x^2+y^2!=0,
....:                restrictions2= u^2+v^2!=0)
sage: uv_to_xy = xy_to_uv.inverse()
sage: W = U.intersection(V)
sage: e_xy = c_xy.frame(); e_uv = c_uv.frame()
>>> from sage.all import *
>>> M = Manifold(Integer(2), 'M') # the 2-dimensional sphere S^2
>>> U = M.open_subset('U') # complement of the North pole
>>> c_xy = U.chart(names=('x', 'y',)); (x, y,) = c_xy._first_ngens(2)# stereographic coordinates from the North pole
>>> V = M.open_subset('V') # complement of the South pole
>>> c_uv = V.chart(names=('u', 'v',)); (u, v,) = c_uv._first_ngens(2)# stereographic coordinates from the South pole
>>> M.declare_union(U,V)   # S^2 is the union of U and V
>>> xy_to_uv = c_xy.transition_map(c_uv, (x/(x**Integer(2)+y**Integer(2)), y/(x**Integer(2)+y**Integer(2))),
...                intersection_name='W', restrictions1= x**Integer(2)+y**Integer(2)!=Integer(0),
...                restrictions2= u**Integer(2)+v**Integer(2)!=Integer(0))
>>> uv_to_xy = xy_to_uv.inverse()
>>> W = U.intersection(V)
>>> e_xy = c_xy.frame(); e_uv = c_uv.frame()
M = Manifold(2, 'M') # the 2-dimensional sphere S^2
U = M.open_subset('U') # complement of the North pole
c_xy.<x,y> = U.chart() # stereographic coordinates from the North pole
V = M.open_subset('V') # complement of the South pole
c_uv.<u,v> = V.chart() # stereographic coordinates from the South pole
M.declare_union(U,V)   # S^2 is the union of U and V
xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)),
               intersection_name='W', restrictions1= x^2+y^2!=0,
               restrictions2= u^2+v^2!=0)
uv_to_xy = xy_to_uv.inverse()
W = U.intersection(V)
e_xy = c_xy.frame(); e_uv = c_uv.frame()

And define some forms on the subset U:

sage: f = U.scalar_field(x, name='f', chart=c_xy)
sage: omega = U.diff_form(1, name='omega')
sage: omega[e_xy,0] = y
sage: AU = U.mixed_form([f, omega, 0], name='A'); AU
Mixed differential form A on the Open subset U of the 2-dimensional
 differentiable manifold M
sage: AU.display_expansion(e_xy)
A = x + y dx
>>> from sage.all import *
>>> f = U.scalar_field(x, name='f', chart=c_xy)
>>> omega = U.diff_form(Integer(1), name='omega')
>>> omega[e_xy,Integer(0)] = y
>>> AU = U.mixed_form([f, omega, Integer(0)], name='A'); AU
Mixed differential form A on the Open subset U of the 2-dimensional
 differentiable manifold M
>>> AU.display_expansion(e_xy)
A = x + y dx
f = U.scalar_field(x, name='f', chart=c_xy)
omega = U.diff_form(1, name='omega')
omega[e_xy,0] = y
AU = U.mixed_form([f, omega, 0], name='A'); AU
AU.display_expansion(e_xy)

A mixed form on M can be specified by some mixed form on a subset:

sage: A = M.mixed_form(name='A'); A
Mixed differential form A on the 2-dimensional differentiable
 manifold M
sage: A.set_restriction(AU)
sage: A.display_expansion(e_xy)
A = x + y dx
sage: A.add_comp_by_continuation(e_uv, W, c_uv)
sage: A.display_expansion(e_uv)
A = u/(u^2 + v^2) - (u^2*v - v^3)/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) du - 2*u*v^2/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) dv
sage: A.restrict(U) == AU
True
>>> from sage.all import *
>>> A = M.mixed_form(name='A'); A
Mixed differential form A on the 2-dimensional differentiable
 manifold M
>>> A.set_restriction(AU)
>>> A.display_expansion(e_xy)
A = x + y dx
>>> A.add_comp_by_continuation(e_uv, W, c_uv)
>>> A.display_expansion(e_uv)
A = u/(u^2 + v^2) - (u^2*v - v^3)/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) du - 2*u*v^2/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) dv
>>> A.restrict(U) == AU
True
A = M.mixed_form(name='A'); A
A.set_restriction(AU)
A.display_expansion(e_xy)
A.add_comp_by_continuation(e_uv, W, c_uv)
A.display_expansion(e_uv)
A.restrict(U) == AU
wedge(other)[source]

Wedge product on the graded algebra of mixed forms.

More precisely, the wedge product is a bilinear map

\[\wedge: \Omega^k(M,\varphi) \times \Omega^l(M,\varphi) \to \Omega^{k+l}(M,\varphi),\]

where \(\Omega^k(M,\varphi)\) denotes the space of differential forms of degree \(k\) along \(\varphi\). By bilinear extension, this induces a map

\[\wedge: \Omega^*(M,\varphi) \times \Omega^*(M,\varphi) \to \Omega^*(M,\varphi) ``\]

and equips \(\Omega^*(M,\varphi)\) with a multiplication such that it becomes a graded algebra.

INPUT:

  • other – mixed form in the same algebra as self

OUTPUT:

  • the mixed form resulting from the wedge product of self with other

EXAMPLES:

Initialize a mixed form on a 3-dimensional manifold:

sage: M = Manifold(3, 'M')
sage: c_xyz.<x,y,z> = M.chart()
sage: f = M.scalar_field(x, name='f')
sage: f.display()
f: M → ℝ
   (x, y, z) ↦ x
sage: g = M.scalar_field(y, name='g')
sage: g.display()
g: M → ℝ
   (x, y, z) ↦ y
sage: omega = M.diff_form(1, name='omega')
sage: omega[0] = x
sage: omega.display()
omega = x dx
sage: eta = M.diff_form(1, name='eta')
sage: eta[1] = y
sage: eta.display()
eta = y dy
sage: mu = M.diff_form(2, name='mu')
sage: mu[0,2] = z
sage: mu.display()
mu = z dx∧dz
sage: A = M.mixed_form([f, omega, mu, 0], name='A')
sage: A.display_expansion()
A = x + x dx + z dx∧dz
sage: B = M.mixed_form([g, eta, mu, 0], name='B')
sage: B.display_expansion()
B = y + y dy + z dx∧dz
>>> from sage.all import *
>>> M = Manifold(Integer(3), 'M')
>>> c_xyz = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = c_xyz._first_ngens(3)
>>> f = M.scalar_field(x, name='f')
>>> f.display()
f: M → ℝ
   (x, y, z) ↦ x
>>> g = M.scalar_field(y, name='g')
>>> g.display()
g: M → ℝ
   (x, y, z) ↦ y
>>> omega = M.diff_form(Integer(1), name='omega')
>>> omega[Integer(0)] = x
>>> omega.display()
omega = x dx
>>> eta = M.diff_form(Integer(1), name='eta')
>>> eta[Integer(1)] = y
>>> eta.display()
eta = y dy
>>> mu = M.diff_form(Integer(2), name='mu')
>>> mu[Integer(0),Integer(2)] = z
>>> mu.display()
mu = z dx∧dz
>>> A = M.mixed_form([f, omega, mu, Integer(0)], name='A')
>>> A.display_expansion()
A = x + x dx + z dx∧dz
>>> B = M.mixed_form([g, eta, mu, Integer(0)], name='B')
>>> B.display_expansion()
B = y + y dy + z dx∧dz
M = Manifold(3, 'M')
c_xyz.<x,y,z> = M.chart()
f = M.scalar_field(x, name='f')
f.display()
g = M.scalar_field(y, name='g')
g.display()
omega = M.diff_form(1, name='omega')
omega[0] = x
omega.display()
eta = M.diff_form(1, name='eta')
eta[1] = y
eta.display()
mu = M.diff_form(2, name='mu')
mu[0,2] = z
mu.display()
A = M.mixed_form([f, omega, mu, 0], name='A')
A.display_expansion()
B = M.mixed_form([g, eta, mu, 0], name='B')
B.display_expansion()

The wedge product of A and B yields:

sage: C = A.wedge(B); C
Mixed differential form A∧B on the 3-dimensional differentiable
 manifold M
sage: C.display_expansion()
A∧B = x*y + x*y dx + x*y dy + x*y dx∧dy + (x + y)*z dx∧dz - y*z dx∧dy∧dz
sage: D = B.wedge(A); D # Don't even try, it's not commutative!
Mixed differential form B∧A on the 3-dimensional differentiable
 manifold M
sage: D.display_expansion() # I told you so!
B∧A = x*y + x*y dx + x*y dy - x*y dx∧dy + (x + y)*z dx∧dz - y*z dx∧dy∧dz
>>> from sage.all import *
>>> C = A.wedge(B); C
Mixed differential form A∧B on the 3-dimensional differentiable
 manifold M
>>> C.display_expansion()
A∧B = x*y + x*y dx + x*y dy + x*y dx∧dy + (x + y)*z dx∧dz - y*z dx∧dy∧dz
>>> D = B.wedge(A); D # Don't even try, it's not commutative!
Mixed differential form B∧A on the 3-dimensional differentiable
 manifold M
>>> D.display_expansion() # I told you so!
B∧A = x*y + x*y dx + x*y dy - x*y dx∧dy + (x + y)*z dx∧dz - y*z dx∧dy∧dz
C = A.wedge(B); C
C.display_expansion()
D = B.wedge(A); D # Don't even try, it's not commutative!
D.display_expansion() # I told you so!

Alternatively, the multiplication symbol can be used:

sage: A*B
Mixed differential form A∧B on the 3-dimensional differentiable
 manifold M
sage: A*B == C
True
>>> from sage.all import *
>>> A*B
Mixed differential form A∧B on the 3-dimensional differentiable
 manifold M
>>> A*B == C
True
A*B
A*B == C

Yet, the multiplication includes coercions:

sage: E = x*A; E.display_expansion()
x∧A = x^2 + x^2 dx + x*z dx∧dz
sage: F = A*eta; F.display_expansion()
A∧eta = x*y dy + x*y dx∧dy - y*z dx∧dy∧dz
>>> from sage.all import *
>>> E = x*A; E.display_expansion()
x∧A = x^2 + x^2 dx + x*z dx∧dz
>>> F = A*eta; F.display_expansion()
A∧eta = x*y dy + x*y dx∧dy - y*z dx∧dy∧dz
E = x*A; E.display_expansion()
F = A*eta; F.display_expansion()