Exemple #1
0
    def hodge_star(self, metric):
        r"""
        Compute the Hodge dual of the differential form.

        If ``self`` is a `p`-form `A`, its Hodge dual is the `(n-p)`-form
        `*A` defined by (`n` being the manifold's dimension)

        .. MATH::

            *A_{i_1\ldots i_{n-p}} = \frac{1}{p!} A_{k_1\ldots k_p}
                \epsilon^{k_1\ldots k_p}_{\qquad\ i_1\ldots i_{n-p}}

        where `\epsilon` is the volume form associated with some
        pseudo-Riemannian metric `g` on the manifold, and the indices
        `k_1,\ldots, k_p` are raised with `g`.

        INPUT:

        - ``metric``: the pseudo-Riemannian metric `g` defining the Hodge dual,
          via the volume form `\epsilon`; must be an instance of
          :class:`~sage.geometry.manifolds.metric.Metric`

        OUTPUT:

        - the `(n-p)`-form `*A`

        EXAMPLES:

        """
        from sage.functions.other import factorial
        from sage.tensor.modules.format_utilities import format_unop_txt, \
                                                         format_unop_latex
        p = self._tensor_rank
        eps = metric.volume_form(p)
        args = range(p) + [eps] + range(p)
        resu = self.contract(*args)
        if p > 1:
            resu = resu / factorial(p)
        resu.set_name(name=format_unop_txt('*', self._name),
                      latex_name=format_unop_latex(r'\star ',
                                                   self._latex_name))
        return resu
Exemple #2
0
    def exterior_der(self):
        r"""
        Compute the exterior derivative of the differential form.

        OUTPUT:

        - the exterior derivative of ``self``.

        EXAMPLE:

        """
        from sage.tensor.modules.format_utilities import format_unop_txt, \
                                                         format_unop_latex
        if self._exterior_derivative is None:
            vmodule = self._vmodule  # shortcut
            rname = format_unop_txt('d', self._name)
            rlname = format_unop_latex(r'\mathrm{d}', self._latex_name)
            resu = vmodule.alternating_form(self._tensor_rank + 1,
                                            name=rname,
                                            latex_name=rlname)
            for dom, rst in self._restrictions.iteritems():
                resu._restrictions[dom] = rst.exterior_der()
            self._exterior_derivative = resu
        return self._exterior_derivative
Exemple #3
0
    def differential(self):
        r"""
        Return the differential of ``self``.

        OUTPUT:

        - a :class:`~sage.manifolds.differentiable.diff_form.DiffForm` (or of
          :class:`~sage.manifolds.differentiable.diff_form.DiffFormParal` if
          the scalar field's domain is parallelizable) representing the 1-form
          that is the differential of the scalar field

        EXAMPLES:

        Differential of a scalar field on a 3-dimensional differentiable
        manifold::

            sage: M = Manifold(3, 'M')
            sage: c_xyz.<x,y,z> = M.chart()
            sage: f = M.scalar_field(cos(x)*z^3 + exp(y)*z^2, name='f')
            sage: df = f.differential() ; df
            1-form df on the 3-dimensional differentiable manifold M
            sage: df.display()
            df = -z^3*sin(x) dx + z^2*e^y dy + (3*z^2*cos(x) + 2*z*e^y) dz
            sage: latex(df)
            \mathrm{d}f
            sage: df.parent()
            Free module /\^1(M) of 1-forms on the 3-dimensional differentiable
             manifold M

        The result is cached, i.e. is not recomputed unless ``f`` is changed::

            sage: f.differential() is df
            True

        Since the exterior derivative of a scalar field (considered a 0-form)
        is nothing but its differential, ``exterior_derivative()`` is an
        alias of ``differential()``::

            sage: df = f.exterior_derivative() ; df
            1-form df on the 3-dimensional differentiable manifold M
            sage: df.display()
            df = -z^3*sin(x) dx + z^2*e^y dy + (3*z^2*cos(x) + 2*z*e^y) dz
            sage: latex(df)
            \mathrm{d}f

        One may also use the global function
        :func:`~sage.manifolds.utilities.exterior_derivative`
        or its alias :func:`~sage.manifolds.utilities.xder` instead
        of the method ``exterior_derivative()``::

            sage: from sage.manifolds.utilities import xder
            sage: xder(f) is f.exterior_derivative()
            True

        Differential computed on a chart that is not the default one::

            sage: c_uvw.<u,v,w> = M.chart()
            sage: g = M.scalar_field(u*v^2*w^3, c_uvw, name='g')
            sage: dg = g.differential() ; dg
            1-form dg on the 3-dimensional differentiable manifold M
            sage: dg._components
            {Coordinate frame (M, (d/du,d/dv,d/dw)): 1-index components w.r.t.
             Coordinate frame (M, (d/du,d/dv,d/dw))}
            sage: dg.comp(c_uvw.frame())[:, c_uvw]
            [v^2*w^3, 2*u*v*w^3, 3*u*v^2*w^2]
            sage: dg.display(c_uvw.frame(), c_uvw)
            dg = v^2*w^3 du + 2*u*v*w^3 dv + 3*u*v^2*w^2 dw

        The exterior derivative is nilpotent::

            sage: ddf = df.exterior_derivative() ; ddf
            2-form ddf on the 3-dimensional differentiable manifold M
            sage: ddf == 0
            True
            sage: ddf[:] # for the incredule
            [0 0 0]
            [0 0 0]
            [0 0 0]
            sage: ddg = dg.exterior_derivative() ; ddg
            2-form ddg on the 3-dimensional differentiable manifold M
            sage: ddg == 0
            True

        """
        from sage.tensor.modules.format_utilities import (format_unop_txt,
                                                          format_unop_latex)
        if self._differential is None:
            # A new computation is necessary:
            rname = format_unop_txt('d', self._name)
            rlname = format_unop_latex(r'\mathrm{d}', self._latex_name)
            self._differential = self._domain.one_form(name=rname,
                                                       latex_name=rlname)
            if self._is_zero:
                for chart in self._domain._atlas:
                    self._differential.add_comp(chart._frame)  # since a newly
                    # created set of components is zero
            else:
                for chart, func in self._express.items():
                    diff_func = self._differential.add_comp(chart._frame)
                    for i in self._manifold.irange():
                        diff_func[i, chart] = func.diff(i)
        return self._differential
Exemple #4
0
    def differential(self):
        r"""
        Return the differential of ``self``.

        OUTPUT:

        - a :class:`~sage.manifolds.differentiable.diff_form.DiffForm` (or of
          :class:`~sage.manifolds.differentiable.diff_form.DiffFormParal` if
          the scalar field's domain is parallelizable) representing the 1-form
          that is the differential of the scalar field

        EXAMPLES:

        Differential of a scalar field on a 3-dimensional differentiable
        manifold::

            sage: M = Manifold(3, 'M')
            sage: c_xyz.<x,y,z> = M.chart()
            sage: f = M.scalar_field(cos(x)*z^3 + exp(y)*z^2, name='f')
            sage: df = f.differential() ; df
            1-form df on the 3-dimensional differentiable manifold M
            sage: df.display()
            df = -z^3*sin(x) dx + z^2*e^y dy + (3*z^2*cos(x) + 2*z*e^y) dz
            sage: latex(df)
            \mathrm{d}f
            sage: df.parent()
            Free module Omega^1(M) of 1-forms on the 3-dimensional
             differentiable manifold M

        The result is cached, i.e. is not recomputed unless ``f`` is changed::

            sage: f.differential() is df
            True

        Since the exterior derivative of a scalar field (considered a 0-form)
        is nothing but its differential, ``exterior_derivative()`` is an
        alias of ``differential()``::

            sage: df = f.exterior_derivative() ; df
            1-form df on the 3-dimensional differentiable manifold M
            sage: df.display()
            df = -z^3*sin(x) dx + z^2*e^y dy + (3*z^2*cos(x) + 2*z*e^y) dz
            sage: latex(df)
            \mathrm{d}f

        One may also use the function
        :func:`~sage.manifolds.utilities.exterior_derivative`
        or its alias :func:`~sage.manifolds.utilities.xder` instead
        of the method ``exterior_derivative()``::

            sage: from sage.manifolds.utilities import xder
            sage: xder(f) is f.exterior_derivative()
            True

        Differential computed on a chart that is not the default one::

            sage: c_uvw.<u,v,w> = M.chart()
            sage: g = M.scalar_field(u*v^2*w^3, c_uvw, name='g')
            sage: dg = g.differential() ; dg
            1-form dg on the 3-dimensional differentiable manifold M
            sage: dg._components
            {Coordinate frame (M, (d/du,d/dv,d/dw)): 1-index components w.r.t.
             Coordinate frame (M, (d/du,d/dv,d/dw))}
            sage: dg.comp(c_uvw.frame())[:, c_uvw]
            [v^2*w^3, 2*u*v*w^3, 3*u*v^2*w^2]
            sage: dg.display(c_uvw.frame(), c_uvw)
            dg = v^2*w^3 du + 2*u*v*w^3 dv + 3*u*v^2*w^2 dw

        The exterior derivative is nilpotent::

            sage: ddf = df.exterior_derivative() ; ddf
            2-form ddf on the 3-dimensional differentiable manifold M
            sage: ddf == 0
            True
            sage: ddf[:] # for the incredule
            [0 0 0]
            [0 0 0]
            [0 0 0]
            sage: ddg = dg.exterior_derivative() ; ddg
            2-form ddg on the 3-dimensional differentiable manifold M
            sage: ddg == 0
            True

        """
        from sage.tensor.modules.format_utilities import (format_unop_txt,
                                                          format_unop_latex)
        if self._differential is None:
            # A new computation is necessary:
            rname = format_unop_txt('d', self._name)
            rlname = format_unop_latex(r'\mathrm{d}', self._latex_name)
            self._differential = self._domain.one_form(name=rname,
                                                       latex_name=rlname)
            if self._is_zero:
                for chart in self._domain._atlas:
                    self._differential.add_comp(chart._frame) # since a newly
                                            # created set of components is zero
            else:
                for chart, func in self._express.items():
                    diff_func = self._differential.add_comp(chart._frame)
                    for i in self._manifold.irange():
                        diff_func[i, chart] = func.diff(i)
        return self._differential
Exemple #5
0
    def exterior_derivative(self):
        r"""
        Compute the exterior derivative of ``self``.

        OUTPUT:

        - instance of :class:`DiffForm` representing the exterior derivative
          of the differential form

        EXAMPLES:

        Exterior derivative of a 1-form on 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: e_xy = c_xy.frame(); e_uv = c_uv.frame()

        The 1-form::

            sage: a = M.diff_form(1, name='a')
            sage: a[e_xy,:] = -y^2, x^2
            sage: a.add_comp_by_continuation(e_uv, U.intersection(V), c_uv)
            sage: a.display(e_xy)
            a = -y^2 dx + x^2 dy
            sage: a.display(e_uv)
            a = -(2*u^3*v - 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
             + (u^4 - u^2*v^2 + 2*u*v^3)/(u^8 + 4*u^6*v^2 + 6*u^4*v^4 + 4*u^2*v^6 + v^8) dv

        Its exterior derivative::

            sage: da = a.exterior_derivative(); da
            2-form da on the 2-dimensional differentiable manifold M
            sage: da.display(e_xy)
            da = (2*x + 2*y) dx/\dy
            sage: da.display(e_uv)
            da = -2*(u + v)/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) du/\dv

        The result is cached, i.e. is not recomputed unless ``a`` is changed::

            sage: a.exterior_derivative() is da
            True

        Instead of invoking the method :meth:`exterior_derivative`, one may
        use the global function
        :func:`~sage.manifolds.utilities.exterior_derivative`
        or its alias :func:`~sage.manifolds.utilities.xder`::

            sage: from sage.manifolds.utilities import xder
            sage: xder(a) is a.exterior_derivative()
            True

        Let us check Cartan's identity::

            sage: v = M.vector_field(name='v')
            sage: v[e_xy, :] = -y, x
            sage: v.add_comp_by_continuation(e_uv, U.intersection(V), c_uv)
            sage: a.lie_der(v) == v.contract(xder(a)) + xder(a(v))  # long time
            True

        """
        from sage.tensor.modules.format_utilities import (format_unop_txt,
                                                          format_unop_latex)
        vmodule = self._vmodule  # shortcut
        rname = format_unop_txt('d', self._name)
        rlname = format_unop_latex(r'\mathrm{d}', self._latex_name)
        resu = vmodule.alternating_form(self._tensor_rank + 1,
                                        name=rname,
                                        latex_name=rlname)
        for dom, rst in self._restrictions.items():
            resu._restrictions[dom] = rst.exterior_derivative()
        return resu
Exemple #6
0
    def exterior_derivative(self):
        r"""
        Compute the exterior derivative of ``self``.

        OUTPUT:

        - a :class:`DiffFormParal` representing the exterior
          derivative of the differential form

        EXAMPLES:

        Exterior derivative of a 1-form on a 4-dimensional manifold::

            sage: M = Manifold(4, 'M')
            sage: c_txyz.<t,x,y,z> = M.chart()
            sage: a = M.one_form('A')
            sage: a[:] = (t*x*y*z, z*y**2, x*z**2, x**2 + y**2)
            sage: da = a.exterior_derivative() ; da
            2-form dA on the 4-dimensional differentiable manifold M
            sage: da.display()
            dA = -t*y*z dt/\dx - t*x*z dt/\dy - t*x*y dt/\dz
             + (-2*y*z + z^2) dx/\dy + (-y^2 + 2*x) dx/\dz
             + (-2*x*z + 2*y) dy/\dz
            sage: latex(da)
            \mathrm{d}A

        The result is cached, i.e. is not recomputed unless ``a`` is changed::

            sage: a.exterior_derivative() is da
            True

        Instead of invoking the method :meth:`exterior_derivative`, one may
        use the global function
        :func:`~sage.manifolds.utilities.exterior_derivative`
        or its alias :func:`~sage.manifolds.utilities.xder`::

            sage: from sage.manifolds.utilities import xder
            sage: xder(a) is a.exterior_derivative()
            True

        The exterior derivative is nilpotent::

            sage: dda = da.exterior_derivative() ; dda
            3-form ddA on the 4-dimensional differentiable manifold M
            sage: dda.display()
            ddA = 0
            sage: dda == 0
            True

        Let us check Cartan's identity::

            sage: v = M.vector_field(name='v')
            sage: v[:] = -y, x, t, z
            sage: a.lie_der(v) == v.contract(xder(a)) + xder(a(v)) # long time
            True

        """
        from sage.calculus.functional import diff
        from sage.tensor.modules.format_utilities import (format_unop_txt,
                                                          format_unop_latex)
        from sage.tensor.modules.comp import CompFullyAntiSym
        from sage.manifolds.differentiable.vectorframe import CoordFrame
        fmodule = self._fmodule  # shortcut
        rname = format_unop_txt('d', self._name)
        rlname = format_unop_latex(r'\mathrm{d}', self._latex_name)
        resu = fmodule.alternating_form(self._tensor_rank + 1,
                                        name=rname,
                                        latex_name=rlname)
        # 1/ List of all coordinate frames in which the components of self
        # are known
        coord_frames = []
        for frame in self._components:
            if isinstance(frame, CoordFrame):
                coord_frames.append(frame)
        if not coord_frames:
            # A coordinate frame is searched, at the price of a change of
            # frame, privileging the frame of the domain's default chart
            dom = self._domain
            def_coordf = dom._def_chart._frame
            for frame in self._components:
                if (frame, def_coordf) in dom._frame_changes:
                    self.comp(def_coordf, from_basis=frame)
                    coord_frames = [def_coordf]
                    break
            if not coord_frames:
                for chart in dom._atlas:
                    if chart != dom._def_chart:  # the case def_chart is
                        # treated above
                        coordf = chart._frame
                        for frame in self._components:
                            if (frame, coordf) in dom._frame_changes:
                                self.comp(coordf, from_basis=frame)
                                coord_frames[coordf]
                                break
                        if coord_frames:
                            break
        # 2/ The computation:
        for frame in coord_frames:
            chart = frame._chart
            sc = self._components[frame]
            dc = CompFullyAntiSym(fmodule._ring,
                                  frame,
                                  self._tensor_rank + 1,
                                  start_index=fmodule._sindex,
                                  output_formatter=fmodule._output_formatter)
            for ind, val in sc._comp.items():
                for i in fmodule.irange():
                    ind_d = (i, ) + ind
                    if len(ind_d) == len(set(ind_d)):
                        # all indices are different
                        dc[[ind_d]] += \
                           val.coord_function(chart).diff(i).scalar_field()
            resu._components[frame] = dc
        return resu
Exemple #7
0
    def exterior_derivative(self):
        r"""
        Compute the exterior derivative of ``self``.

        OUTPUT:

        - instance of :class:`DiffForm` representing the exterior derivative
          of the differential form

        EXAMPLES:

        Exterior derivative of a 1-form on 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: e_xy = c_xy.frame(); e_uv = c_uv.frame()

        The 1-form::

            sage: a = M.diff_form(1, name='a')
            sage: a[e_xy,:] = -y^2, x^2
            sage: a.add_comp_by_continuation(e_uv, U.intersection(V), c_uv)
            sage: a.display(e_xy)
            a = -y^2 dx + x^2 dy
            sage: a.display(e_uv)
            a = -(2*u^3*v - 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
             + (u^4 - u^2*v^2 + 2*u*v^3)/(u^8 + 4*u^6*v^2 + 6*u^4*v^4 + 4*u^2*v^6 + v^8) dv

        Its exterior derivative::

            sage: da = a.exterior_derivative(); da
            2-form da on the 2-dimensional differentiable manifold M
            sage: da.display(e_xy)
            da = (2*x + 2*y) dx/\dy
            sage: da.display(e_uv)
            da = -2*(u + v)/(u^6 + 3*u^4*v^2 + 3*u^2*v^4 + v^6) du/\dv

        The result is cached, i.e. is not recomputed unless ``a`` is changed::

            sage: a.exterior_derivative() is da
            True

        Instead of invoking the method :meth:`exterior_derivative`, one may
        use the global function
        :func:`~sage.manifolds.utilities.exterior_derivative`
        or its alias :func:`~sage.manifolds.utilities.xder`::

            sage: from sage.manifolds.utilities import xder
            sage: xder(a) is a.exterior_derivative()
            True

        Let us check Cartan's identity::

            sage: v = M.vector_field(name='v')
            sage: v[e_xy, :] = -y, x
            sage: v.add_comp_by_continuation(e_uv, U.intersection(V), c_uv)
            sage: a.lie_der(v) == v.contract(xder(a)) + xder(a(v))  # long time
            True

        """
        from sage.tensor.modules.format_utilities import (format_unop_txt,
                                                          format_unop_latex)
        vmodule = self._vmodule # shortcut
        rname = format_unop_txt('d', self._name)
        rlname = format_unop_latex(r'\mathrm{d}', self._latex_name)
        resu = vmodule.alternating_form(self._tensor_rank+1, name=rname,
                                        latex_name=rlname)
        for dom, rst in self._restrictions.items():
            resu._restrictions[dom] = rst.exterior_derivative()
        return resu
Exemple #8
0
    def exterior_derivative(self):
        r"""
        Compute the exterior derivative of ``self``.

        OUTPUT:

        - a :class:`DiffFormParal` representing the exterior
          derivative of the differential form

        EXAMPLES:

        Exterior derivative of a 1-form on a 4-dimensional manifold::

            sage: M = Manifold(4, 'M')
            sage: c_txyz.<t,x,y,z> = M.chart()
            sage: a = M.one_form('A')
            sage: a[:] = (t*x*y*z, z*y**2, x*z**2, x**2 + y**2)
            sage: da = a.exterior_derivative() ; da
            2-form dA on the 4-dimensional differentiable manifold M
            sage: da.display()
            dA = -t*y*z dt/\dx - t*x*z dt/\dy - t*x*y dt/\dz
             + (-2*y*z + z^2) dx/\dy + (-y^2 + 2*x) dx/\dz
             + (-2*x*z + 2*y) dy/\dz
            sage: latex(da)
            \mathrm{d}A

        The result is cached, i.e. is not recomputed unless ``a`` is changed::

            sage: a.exterior_derivative() is da
            True

        Instead of invoking the method :meth:`exterior_derivative`, one may
        use the global function
        :func:`~sage.manifolds.utilities.exterior_derivative`
        or its alias :func:`~sage.manifolds.utilities.xder`::

            sage: from sage.manifolds.utilities import xder
            sage: xder(a) is a.exterior_derivative()
            True

        The exterior derivative is nilpotent::

            sage: dda = da.exterior_derivative() ; dda
            3-form ddA on the 4-dimensional differentiable manifold M
            sage: dda.display()
            ddA = 0
            sage: dda == 0
            True

        Let us check Cartan's identity::

            sage: v = M.vector_field(name='v')
            sage: v[:] = -y, x, t, z
            sage: a.lie_der(v) == v.contract(xder(a)) + xder(a(v)) # long time
            True

        """
        from sage.calculus.functional import diff
        from sage.tensor.modules.format_utilities import (format_unop_txt,
                                                          format_unop_latex)
        from sage.tensor.modules.comp import CompFullyAntiSym
        from sage.manifolds.differentiable.vectorframe import CoordFrame
        fmodule = self._fmodule # shortcut
        rname = format_unop_txt('d', self._name)
        rlname = format_unop_latex(r'\mathrm{d}', self._latex_name)
        resu = fmodule.alternating_form(self._tensor_rank + 1,
                                        name=rname,
                                        latex_name=rlname)
        # 1/ List of all coordinate frames in which the components of self
        # are known
        coord_frames = []
        for frame in self._components:
            if isinstance(frame, CoordFrame):
                coord_frames.append(frame)
        if not coord_frames:
            # A coordinate frame is searched, at the price of a change of
            # frame, privileging the frame of the domain's default chart
            dom = self._domain
            def_coordf = dom._def_chart._frame
            for frame in self._components:
                if (frame, def_coordf) in dom._frame_changes:
                    self.comp(def_coordf, from_basis=frame)
                    coord_frames = [def_coordf]
                    break
            if not coord_frames:
                for chart in dom._atlas:
                    if chart != dom._def_chart: # the case def_chart is
                                                # treated above
                        coordf = chart._frame
                        for frame in self._components:
                            if (frame, coordf) in dom._frame_changes:
                                self.comp(coordf, from_basis=frame)
                                coord_frames[coordf]
                                break
                        if coord_frames:
                            break
        # 2/ The computation:
        for frame in coord_frames:
            chart = frame._chart
            sc = self._components[frame]
            dc = CompFullyAntiSym(fmodule._ring, frame,
                                  self._tensor_rank+1,
                                  start_index=fmodule._sindex,
                                output_formatter=fmodule._output_formatter)
            for ind, val in sc._comp.items():
                for i in fmodule.irange():
                    ind_d = (i,) + ind
                    if len(ind_d) == len(set(ind_d)):
                        # all indices are different
                        dc[[ind_d]] += \
                           val.coord_function(chart).diff(i).scalar_field()
            resu._components[frame] = dc
        return resu
Exemple #9
0
    def exterior_derivative(self):
        r"""
        Compute the exterior derivative of ``self``.

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

        .. MATH::

            \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 :meth:`~sage.manifolds.differentiable.diff_form.DiffForm.exterior_derivative`
        for further information). By linear extension, this induces a map on
        `\Omega^*(M,\varphi)`:

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

        OUTPUT:

        - a :class:`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 --> R
                (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(name='F', comp=[f, 0, a, 0]); F.disp()
            F = f + zero + a + zero
            sage: dF = F.exterior_derivative()
            sage: dF.disp()
            dF = zero + df + dzero + da
            sage: dF = F.exterior_derivative()
            sage: dF.disp(c_xyz.frame())
            dF = [0] + [2*z dz] + [0] + [(2*x + 1) dx/\dy/\dz]

        Due to long calculation times, the result is cached, i.e. is not
        recomputed unless ``F`` is changed::

            sage: F.exterior_derivative() is dF
            True

        """
        resu_comp = list()
        resu_comp.append(self._domain.scalar_field_algebra().zero())
        resu_comp.append(self[0].differential())
        resu_comp.extend(
            [self[j].exterior_derivative() for j in range(1, self._max_deg)])
        resu = type(self)(self.parent(), comp=resu_comp)
        # Compose name:
        from sage.tensor.modules.format_utilities import (format_unop_txt,
                                                          format_unop_latex)
        resu._name = format_unop_txt('d', self._name)
        resu._latex_name = format_unop_latex(r'\mathrm{d}', self._latex_name)

        return resu
Exemple #10
0
    def hodge_star(self, metric):
        r"""
        Compute the Hodge dual of the differential form.

        If ``self`` is a `p`-form `A`, its Hodge dual is the `(n-p)`-form
        `*A` defined by (`n` being the manifold's dimension)

        .. MATH::

            *A_{i_1\ldots i_{n-p}} = \frac{1}{p!} A_{k_1\ldots k_p}
                \epsilon^{k_1\ldots k_p}_{\qquad\ i_1\ldots i_{n-p}}

        where `\epsilon` is the volume form associated with some
        pseudo-Riemannian metric `g` on the manifold, and the indices
        `k_1,\ldots, k_p` are raised with `g`.

        INPUT:

        - ``metric``: the pseudo-Riemannian metric `g` defining the Hodge dual,
          via the volume form `\epsilon`; must be an instance of
          :class:`~sage.geometry.manifolds.metric.Metric`

        OUTPUT:

        - the `(n-p)`-form `*A`

        EXAMPLES:

        Hodge star of a 1-form in the Euclidean space `R^3`::

            sage: M = Manifold(3, 'M', start_index=1)
            sage: X.<x,y,z> = M.chart()
            sage: g = M.metric('g')
            sage: g[1,1], g[2,2], g[3,3] = 1, 1, 1
            sage: a = M.one_form('A')
            sage: var('Ax Ay Az')
            (Ax, Ay, Az)
            sage: a[:] = (Ax, Ay, Az)
            sage: sa = a.hodge_star(g) ; sa
            2-form '*A' on the 3-dimensional manifold 'M'
            sage: sa.display()
            *A = Az dx/\dy - Ay dx/\dz + Ax dy/\dz
            sage: ssa = sa.hodge_star(g) ; ssa
            1-form '**A' on the 3-dimensional manifold 'M'
            sage: ssa.display()
            **A = Ax dx + Ay dy + Az dz
            sage: ssa == a  # must hold for a Riemannian metric in dimension 3
            True

        Hodge star of a 0-form (scalar field) in `R^3`::

            sage: f = M.scalar_field(function('F',x,y,z), name='f')
            sage: sf = f.hodge_star(g) ; sf
            3-form '*f' on the 3-dimensional manifold 'M'
            sage: sf.display()
            *f = F(x, y, z) dx/\dy/\dz
            sage: ssf = sf.hodge_star(g) ; ssf
            scalar field '**f' on the 3-dimensional manifold 'M'
            sage: ssf.display()
            **f: M --> R
               (x, y, z) |--> F(x, y, z)
            sage: ssf == f # must hold for a Riemannian metric
            True

        Hodge star of a 0-form in Minkowksi spacetime::

            sage: M = Manifold(4, 'M')
            sage: X.<t,x,y,z> = M.chart()
            sage: g = M.metric('g', signature=2)
            sage: g[0,0], g[1,1], g[2,2], g[3,3] = -1, 1, 1, 1
            sage: g.display()  # Minkowski metric
            g = -dt*dt + dx*dx + dy*dy + dz*dz
            sage: var('f0')
            f0
            sage: f = M.scalar_field(f0, name='f')
            sage: sf = f.hodge_star(g) ; sf
            4-form '*f' on the 4-dimensional manifold 'M'
            sage: sf.display()
            *f = f0 dt/\dx/\dy/\dz
            sage: ssf = sf.hodge_star(g) ; ssf
            scalar field '**f' on the 4-dimensional manifold 'M'
            sage: ssf.display()
            **f: M --> R
               (t, x, y, z) |--> -f0
            sage: ssf == -f  # must hold for a Lorentzian metric
            True

        Hodge star of a 1-form in Minkowksi spacetime::

            sage: a = M.one_form('A')
            sage: var('At Ax Ay Az')
            (At, Ax, Ay, Az)
            sage: a[:] = (At, Ax, Ay, Az)
            sage: a.display()
            A = At dt + Ax dx + Ay dy + Az dz
            sage: sa = a.hodge_star(g) ; sa
            3-form '*A' on the 4-dimensional manifold 'M'
            sage: sa.display()
            *A = -Az dt/\dx/\dy + Ay dt/\dx/\dz - Ax dt/\dy/\dz - At dx/\dy/\dz
            sage: ssa = sa.hodge_star(g) ; ssa
            1-form '**A' on the 4-dimensional manifold 'M'
            sage: ssa.display()
            **A = At dt + Ax dx + Ay dy + Az dz
            sage: ssa == a  # must hold for a Lorentzian metric in dimension 4
            True

        Hodge star of a 2-form in Minkowksi spacetime::

            sage: F = M.diff_form(2, 'F')
            sage: var('Ex Ey Ez Bx By Bz')
            (Ex, Ey, Ez, Bx, By, Bz)
            sage: F[0,1], F[0,2], F[0,3] = -Ex, -Ey, -Ez
            sage: F[1,2], F[1,3], F[2,3] = Bz, -By, Bx
            sage: F[:]
            [  0 -Ex -Ey -Ez]
            [ Ex   0  Bz -By]
            [ Ey -Bz   0  Bx]
            [ Ez  By -Bx   0]
            sage: sF = F.hodge_star(g) ; sF
            2-form '*F' on the 4-dimensional manifold 'M'
            sage: sF[:]
            [  0  Bx  By  Bz]
            [-Bx   0  Ez -Ey]
            [-By -Ez   0  Ex]
            [-Bz  Ey -Ex   0]
            sage: ssF = sF.hodge_star(g) ; ssF
            2-form '**F' on the 4-dimensional manifold 'M'
            sage: ssF[:]
            [  0  Ex  Ey  Ez]
            [-Ex   0 -Bz  By]
            [-Ey  Bz   0 -Bx]
            [-Ez -By  Bx   0]
            sage: ssF.display()
            **F = Ex dt/\dx + Ey dt/\dy + Ez dt/\dz - Bz dx/\dy + By dx/\dz - Bx dy/\dz
            sage: F.display()
            F = -Ex dt/\dx - Ey dt/\dy - Ez dt/\dz + Bz dx/\dy - By dx/\dz + Bx dy/\dz
            sage: ssF == -F  # must hold for a Lorentzian metric in dimension 4
            True

        Test of the standard identity

        .. MATH::

            *(A\wedge B) = \epsilon(A^\sharp, B^\sharp, ., .)

        where `A` and `B` are any 1-forms and `A^\sharp` and `B^\sharp` the
        vectors associated to them by the metric `g` (index raising)::

            sage: b = M.one_form('B')
            sage: var('Bt Bx By Bz')
            (Bt, Bx, By, Bz)
            sage: b[:] = (Bt, Bx, By, Bz) ; b.display()
            B = Bt dt + Bx dx + By dy + Bz dz
            sage: epsilon = g.volume_form()
            sage: (a.wedge(b)).hodge_star(g) == epsilon.contract(0,a.up(g)).contract(0,b.up(g))
            True

        """
        from sage.functions.other import factorial
        from sage.tensor.modules.format_utilities import format_unop_txt, \
                                                         format_unop_latex
        p = self._tensor_rank
        eps = metric.volume_form(p)
        resu = self.contract(0, eps, 0)
        for j in range(1, p):
            resu = resu.trace(0, p - j)
        if p > 1:
            resu = resu / factorial(p)
        resu.set_name(name=format_unop_txt('*', self._name),
                      latex_name=format_unop_latex(r'\star ',
                                                   self._latex_name))
        return resu
Exemple #11
0
    def exterior_der(self):
        r"""
        Compute the exterior derivative of the differential form.

        OUTPUT:

        - the exterior derivative of ``self``.

        EXAMPLE:

        Exterior derivative of a 1-form on a 4-dimensional manifold::

            sage: M = Manifold(4, 'M')
            sage: c_txyz.<t,x,y,z> = M.chart()
            sage: a = M.one_form('A')
            sage: a[:] = (t*x*y*z, z*y**2, x*z**2, x**2 + y**2)
            sage: da = a.exterior_der() ; da
            2-form 'dA' on the 4-dimensional manifold 'M'
            sage: da.display()
            dA = -t*y*z dt/\dx - t*x*z dt/\dy - t*x*y dt/\dz + (-2*y*z + z^2) dx/\dy + (-y^2 + 2*x) dx/\dz + (-2*x*z + 2*y) dy/\dz
            sage: latex(da)
            \mathrm{d}A

        The exterior derivative is nilpotent::

            sage: dda = da.exterior_der() ; dda
            3-form 'ddA' on the 4-dimensional manifold 'M'
            sage: dda.display()
            ddA = 0
            sage: dda == 0
            True

        """
        from sage.calculus.functional import diff
        from sage.tensor.modules.format_utilities import format_unop_txt, \
                                                         format_unop_latex
        from sage.tensor.modules.comp import CompFullyAntiSym
        from vectorframe import CoordFrame
        if self._exterior_derivative is None:
            # A new computation is necessary:
            fmodule = self._fmodule  # shortcut
            rname = format_unop_txt('d', self._name)
            rlname = format_unop_latex(r'\mathrm{d}', self._latex_name)
            self._exterior_derivative = fmodule.alternating_form(
                self._tensor_rank + 1, name=rname, latex_name=rlname)
            # 1/ List of all coordinate frames in which the components of self
            # are known
            coord_frames = []
            for frame in self._components:
                if isinstance(frame, CoordFrame):
                    coord_frames.append(frame)
            if coord_frames == []:
                # A coordinate frame is searched, at the price of a change of
                # frame, priveleging the frame of the domain's default chart
                dom = self._domain
                def_coordf = dom._def_chart._frame
                for frame in self._components:
                    if (frame, def_coordf) in dom._frame_changes:
                        self.comp(def_coordf, from_basis=frame)
                        coord_frames = [def_coordf]
                        break
                if coord_frames == []:
                    for chart in dom._atlas:
                        if chart != dom._def_chart:  # the case def_chart is treated above
                            coordf = chart._frame
                            for frame in self._components:
                                if (frame, coordf) in dom._frame_changes:
                                    self.comp(coordf, from_basis=frame)
                                    coord_frames[coordf]
                                    break
                            if coord_frames != []:
                                break
            # 2/ The computation:
            for frame in coord_frames:
                chart = frame._chart
                sc = self._components[frame]
                dc = CompFullyAntiSym(
                    fmodule._ring,
                    frame,
                    self._tensor_rank + 1,
                    start_index=fmodule._sindex,
                    output_formatter=fmodule._output_formatter)
                for ind, val in sc._comp.iteritems():
                    for i in fmodule.irange():
                        ind_d = (i, ) + ind
                        if len(ind_d) == len(set(ind_d)):
                            # all indices are different
                            dc[[ind_d]] += \
                               val.function_chart(chart).diff(i).scalar_field()
                self._exterior_derivative._components[frame] = dc
        return self._exterior_derivative