Mixed Differential Forms - Manifolds

Skip to content
Back to top
View this page
Edit this page

# 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)

  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

      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

  Python

      >>> 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

  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

      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

  [Python]

      >>> 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

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

  Sage

      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

  Python

      >>> 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

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

  Sage

      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

  [Python]

      >>> 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

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

  Sage

      sage: f is B[0]
      False

  Python

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

  Alternatively, the components can be determined from scratch:

  Sage

      sage: B = M.mixed_form([f, omega, eta], name='B')
      sage: B.display()
      B = f + omega + eta

  [Python]

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

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

  Sage

      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

  Python

      >>> 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

  Coercions are fully implemented:

  Sage

      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

  [Python]

      >>> 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

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

  Sage

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

  Python

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

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

  Sage

      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

  [Python]

      >>> 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

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

  Sage

      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

  Python

      >>> 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

  add_comp_by_continuation(frame, subdomain, chart=None)

    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

        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

    Python

        >>> 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

  copy(name=None, latex_name=None)

    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

        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

    Python

        >>> 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

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

    Sage

        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

    [Python]

        >>> 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

  derivative()

    alias of `exterior_derivative()`.

  disp()

    alias of `display()`.

  disp_exp(frame=None, chart=None, from_chart=None)

    alias of `display_expansion()`.

  display()

    Display the homogeneous components of the mixed form.

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

    EXAMPLES:

    Sage

        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

    Python

        >>> 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

  display_exp(frame=None, chart=None, from_chart=None)

    alias of `display_expansion()`.

  display_expansion(frame=None, chart=None, from_chart=None)

    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

        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

    Python

        >>> 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

  exterior_derivative()

    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

        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

    Python

        >>> 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

    Due to long calculation times, the result is cached:

    Sage

        sage: F.exterior_derivative() is dF
        True

    [Python]

        >>> from sage.all import *
        >>> F.exterior_derivative() is dF
        True

  irange(start=None)

    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

        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]

    Python

        >>> 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]

  restrict(subdomain, dest_map=None)

    Return the restriction of `self` to some subdomain.

    INPUT:

    - `subdomain` – `DifferentiableManifold`; open subset \(U\) of the domain of `self`

    - `dest_map` – `DiffMap` (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

        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()

    Python

        >>> 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()

    And predefine some forms:

    Sage

        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)

    [Python]

        >>> 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)

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

    Sage

        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

    Python

        >>> 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

  set_comp(i)

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

    EXAMPLES:

    Sage

        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

    Python

        >>> 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

  set_immutable()

    Set `self` and homogeneous components of `self` immutable.

    EXAMPLES:

    Sage

        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

    Python

        >>> 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

  set_name(name=None, latex_name=None, apply_to_comp=True)

    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

        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}

    Python

        >>> 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}

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

    Sage

        sage: F.display()
        F = F_0 + F_1 + F_2 + F_3 + F_4

    [Python]

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

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

    Sage

        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

    Python

        >>> 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

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

    Sage

        sage: F[0].set_name(name='g'); F.display()
        eta = g + F_1 + F_2 + F_3 + F_4

    [Python]

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

  set_restriction(rst)

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

    INPUT:

    - `rst` – `MixedForm` of the same type as `self`, defined on a subdomain of the domain of `self`

    EXAMPLES:

    Initialize the 2-sphere:

    Sage

        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()

    Python

        >>> 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()

    And define some forms on the subset `U`:

    Sage

        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

    [Python]

        >>> 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

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

    Sage

        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

    Python

        >>> 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

  wedge(other)

    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

        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

    Python

        >>> 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

    The wedge product of `A` and `B` yields:

    Sage

        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

    [Python]

        >>> 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

    Alternatively, the multiplication symbol can be used:

    Sage

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

    Python

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

    Yet, the multiplication includes coercions:

    Sage

        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

    [Python]

        >>> 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