def __invert__(self):
     r"""
     Return the inverse automorphism.
     """
     from sage.matrix.constructor import matrix
     from sage.tensor.modules.comp import Components
     from vectorframe import CoordFrame
     from utilities import simplify_chain
     if self._is_identity:
         return self
     if self._inverse is None:
         if self._name is None:
             inv_name = None
         else:
             inv_name = self._name + '^(-1)'
         if self._latex_name is None:
             inv_latex_name = None
         else:
             inv_latex_name = self._latex_name + r'^{-1}'
         fmodule = self._fmodule
         si = fmodule._sindex
         nsi = fmodule._rank + si
         self._inverse = fmodule.automorphism(name=inv_name,
                                              latex_name=inv_latex_name)
         for frame in self._components:
             if isinstance(frame, CoordFrame):
                 chart = frame._chart
             else:
                 chart = self._domain._def_chart  #!# to be improved
             try:
                 mat_self = matrix([[
                     self.comp(frame)[i, j, chart]._express
                     for j in range(si, nsi)
                 ] for i in range(si, nsi)])
             except (KeyError, ValueError):
                 continue
             mat_inv = mat_self.inverse()
             cinv = Components(fmodule._ring,
                               frame,
                               2,
                               start_index=si,
                               output_formatter=fmodule._output_formatter)
             for i in range(si, nsi):
                 for j in range(si, nsi):
                     cinv[i, j] = {
                         chart: simplify_chain(mat_inv[i - si, j - si])
                     }
             self._inverse._components[frame] = cinv
     return self._inverse
Exemple #2
0
 def inverse(self):
     r"""
     Return the inverse automorphism.
     
     """
     from sage.matrix.constructor import matrix
     from component import Components
     from utilities import simplify_chain
     if self._inverse is None:
         if self.name is None:
             inv_name = None
         else:
             inv_name = 'inv-' + self.name
         if self.latex_name is None:
             inv_latex_name = None
         else:
             inv_latex_name = self.latex_name + r'^{-1}'
         manif = self.manifold
         dom = self.domain
         si = manif.sindex
         nsi = manif.dim + si
         self._inverse = AutomorphismField(dom, inv_name, inv_latex_name)
         for frame_name in self.components:
             if frame_name[-2:] == '_b':
                 # coordinate basis
                 chart_name = frame_name[:-2]
             else:
                 chart_name = dom.def_chart.name  #!# to be improved
             try:
                 mat_self = matrix([[
                     self.comp(frame_name)[i, j, chart_name].express
                     for j in range(si, nsi)
                 ] for i in range(si, nsi)])
             except (KeyError, ValueError):
                 continue
             mat_inv = mat_self.inverse()
             cinv = Components(dom.frames[frame_name], 2)
             for i in range(si, nsi):
                 for j in range(si, nsi):
                     cinv[i, j,
                          chart_name] = simplify_chain(mat_inv[i - si,
                                                               j - si])
             self._inverse.components[frame_name] = cinv
     return self._inverse
Exemple #3
0
 def __invert__(self):
     r"""
     Return the inverse automorphism.
     """
     from sage.matrix.constructor import matrix
     from sage.tensor.modules.comp import Components
     from vectorframe import CoordFrame
     from utilities import simplify_chain
     if self._is_identity:
         return self
     if self._inverse is None:
         if self._name is None:
             inv_name = None
         else:
             inv_name = self._name  + '^(-1)'
         if self._latex_name is None:
             inv_latex_name = None
         else:
             inv_latex_name = self._latex_name + r'^{-1}'
         fmodule = self._fmodule
         si = fmodule._sindex ; nsi = fmodule._rank + si
         self._inverse = fmodule.automorphism(name=inv_name,
                                              latex_name=inv_latex_name)
         for frame in self._components:
             if isinstance(frame, CoordFrame):
                 chart = frame._chart
             else:
                 chart = self._domain._def_chart #!# to be improved
             try:
                 mat_self = matrix(
                           [[self.comp(frame)[i, j, chart]._express
                           for j in range(si, nsi)] for i in range(si, nsi)])
             except (KeyError, ValueError):
                 continue
             mat_inv = mat_self.inverse()
             cinv = Components(fmodule._ring, frame, 2, start_index=si,
                               output_formatter=fmodule._output_formatter)
             for i in range(si, nsi):
                 for j in range(si, nsi):
                     cinv[i, j] = {chart: simplify_chain(mat_inv[i-si,j-si])}
             self._inverse._components[frame] = cinv
     return self._inverse
 def inverse(self):
     r"""
     Return the inverse automorphism.
     
     """
     from sage.matrix.constructor import matrix
     from component import Components
     from utilities import simplify_chain
     if self._inverse is None:
         if self.name is None:
             inv_name = None
         else:
             inv_name = 'inv-' + self.name
         if self.latex_name is None:
             inv_latex_name = None
         else:
             inv_latex_name = self.latex_name + r'^{-1}'
         manif = self.manifold
         dom = self.domain
         si = manif.sindex ; nsi = manif.dim + si
         self._inverse = AutomorphismField(dom, inv_name, inv_latex_name)
         for frame_name in self.components:
             if frame_name[-2:] == '_b':
                 # coordinate basis
                 chart_name = frame_name[:-2]
             else:
                 chart_name = dom.def_chart.name  #!# to be improved
             try:    
                 mat_self = matrix(
                           [[self.comp(frame_name)[i, j, chart_name].express 
                           for j in range(si, nsi)] for i in range(si, nsi)])
             except (KeyError, ValueError):
                 continue
             mat_inv = mat_self.inverse()
             cinv = Components(dom.frames[frame_name], 2)
             for i in range(si, nsi):
                 for j in range(si, nsi):   
                     cinv[i, j, chart_name] = simplify_chain(
                                                         mat_inv[i-si,j-si])
             self._inverse.components[frame_name] = cinv
     return self._inverse
    def inverse(self, chartname1=None, chartname2=None): 
        r"""
        Returns the inverse diffeomorphism. 
        
        INPUT:
    
        - ``chartname1`` -- (default: None) string defining the chart in which
          the computation of the inverse is performed; if none is provided, the
          default chart of self.manifold1 will be used
        - ``chartname2`` -- (default: None) string defining the chart in which
          the computation of the inverse is performed; if none is provided, the
          default chart of self.manifold2 will be used
        
        OUTPUT:
        
        - the inverse diffeomorphism
        
        EXAMPLES:
        
            The inverse of a rotation in the plane::
            
                sage: m = Manifold(2, "plane")
                sage: c_cart = Chart(m, 'x y', 'cart')
                sage: # A pi/3 rotation around the origin:
                sage: rot = Diffeomorphism(m, m, ((x - sqrt(3)*y)/2, (sqrt(3)*x + y)/2))
                sage: p = Point(m,(1,2))
                sage: q = rot(p)
                sage: irot = rot.inverse()
                sage: p1 = irot(q)
                sage: p1 == p
                True
        """
        from sage.symbolic.ring import SR
        from sage.symbolic.relation import solve
        from utilities import simplify_chain
        if self._inverse is not None:
            return self._inverse
            
        if chartname1 is None: chartname1 = self.manifold1.def_chart.name
        if chartname2 is None: chartname2 = self.manifold2.def_chart.name

        coord_map = self.coord_expression[(chartname1, chartname2)]
        chart1 = self.manifold1.atlas[chartname1]
        chart2 = self.manifold2.atlas[chartname2]
        
        n1 = len(chart1.xx)
        n2 = len(chart2.xx)
        
        # New symbolic variables (different from chart2.xx to allow for a 
        #  correct solution even when chart2 = chart1):
        x2 = [ SR.var('xxxx' + str(i)) for i in range(n2) ]
        equations = [x2[i] == coord_map.functions[i] for i in range(n2) ]
        solutions = solve(equations, chart1.xx, solution_dict=True)
        if len(solutions) == 0: 
            raise ValueError("No solution found")
        if len(solutions) > 1: 
            raise ValueError("Non-unique solution found")
            
        #!# This should be the Python 2.7 form: 
        # substitutions = {x2[i]: chart2.xx[i] for i in range(n2)}
        #
        # Here we use a form compatible with Python 2.6:
        substitutions = dict([(x2[i], chart2.xx[i]) for i in range(n2)])
       
        inv_functions = [solutions[0][chart1.xx[i]].subs(substitutions) 
                           for i in range(n1)]
        for i in range(n1):
            x = inv_functions[i]
            try:
                inv_functions[i] = simplify_chain(x)
            except AttributeError:
                pass        
        self._inverse = Diffeomorphism(self.manifold2, self.manifold1, 
                                       inv_functions, chartname2, chartname1)
        return self._inverse
Exemple #6
0
    def inverse(self, chart1=None, chart2=None): 
        r"""
        Return the inverse diffeomorphism. 
        
        INPUT:
    
        - ``chart1`` -- (default: None) chart in which the computation of the 
          inverse is performed if necessary; if none is provided, the default 
          chart of the start domain will be used
        - ``chart2`` -- (default: None) chart in which the computation of the 
          inverse is performed if necessary; if none is provided, the default 
          chart of the arrival domain will be used
        
        OUTPUT:
        
        - the inverse diffeomorphism
        
        EXAMPLES:
        
            The inverse of a rotation in the Euclidean plane::
            
                sage: m = Manifold(2, 'R^2', r'\RR^2')
                sage: c_cart.<x,y> = m.chart('x y')
                sage: # A pi/3 rotation around the origin:
                sage: rot = Diffeomorphism(m, m, ((x - sqrt(3)*y)/2, (sqrt(3)*x + y)/2), name='R')
                sage: rot.inverse() 
                diffeomorphism 'R^(-1)' on the 2-dimensional manifold 'R^2'
                sage: rot.inverse().view()
                R^(-1): R^2 --> R^2, (x, y) |--> (1/2*sqrt(3)*y + 1/2*x, -1/2*sqrt(3)*x + 1/2*y)

            Checking that applying successively the diffeomorphism and its 
            inverse results in the identity::
            
                sage: (a, b) = var('a b')
                sage: p = Point(m, (a,b)) # a generic point on M
                sage: q = rot(p)
                sage: p1 = rot.inverse()(q)
                sage: p1 == p 
                True

        """
        from sage.symbolic.ring import SR
        from sage.symbolic.relation import solve
        from utilities import simplify_chain
        if self._inverse is not None:
            return self._inverse
            
        if chart1 is None: chart1 = self.domain1.def_chart
        if chart2 is None: chart2 = self.domain2.def_chart
        coord_map = self.coord_expression[(chart1, chart2)]
        n1 = len(chart1.xx)
        n2 = len(chart2.xx)
        
        # New symbolic variables (different from chart2.xx to allow for a 
        #  correct solution even when chart2 = chart1):
        x2 = [ SR.var('xxxx' + str(i)) for i in range(n2) ]
        equations = [ x2[i] == coord_map.functions[i].express 
                      for i in range(n2) ]
        solutions = solve(equations, chart1.xx, solution_dict=True)
        if len(solutions) == 0: 
            raise ValueError("No solution found")
        if len(solutions) > 1: 
            raise ValueError("Non-unique solution found")
            
        #!# This should be the Python 2.7 form: 
        # substitutions = {x2[i]: chart2.xx[i] for i in range(n2)}
        #
        # Here we use a form compatible with Python 2.6:
        substitutions = dict([(x2[i], chart2.xx[i]) for i in range(n2)])
       
        inv_functions = [solutions[0][chart1.xx[i]].subs(substitutions) 
                           for i in range(n1)]
        for i in range(n1):
            x = inv_functions[i]
            try:
                inv_functions[i] = simplify_chain(x)
            except AttributeError:
                pass
        if self.name is None:
            name = None
        else:
            name = self.name + '^(-1)'
        
        if self.latex_name is None:
            latex_name = None
        else:
            latex_name = self.latex_name + r'^{-1}'
        self._inverse = Diffeomorphism(self.domain2, self.domain1, 
                                       inv_functions, chart2, chart1,
                                       name=name, latex_name=latex_name)
        return self._inverse
    def sqrt_abs_det(self, frame=None):
        r"""
        Square root of the absolute value of the determinant of the metric 
        components in the specified frame.
        
        INPUT:
        
        - ``frame`` -- (default: None) vector frame with 
          respect to which the components `g_{ij}` of ``self`` are defined; 
          if None, the domain's default frame is used. If a chart is 
          provided, the associated coordinate frame is used
          
        OUTPUT:
        
        -  `\sqrt{|\det (g_{ij})|}`, as an instance of :class:`ScalarField`
        
        EXAMPLES:
        
        Standard metric in the Euclidean space `\RR^3` with spherical 
        coordinates::
        
            sage: m = Manifold(3, 'M', start_index=1)
            sage: c_spher.<r,th,ph> = m.chart(r'r:[0,+oo) th:[0,pi]:\theta ph:[0,2*pi):\phi')
            sage: g = Metric(m, 'g')
            sage: g[1,1], g[2,2], g[3,3] = 1, r^2, (r*sin(th))^2
            sage: g.view()
            g = dr*dr + r^2 dth*dth + r^2*sin(th)^2 dph*dph
            sage: g.sqrt_abs_det().expr()
            r^2*sin(th)
            
        Metric determinant on a 2-dimensional manifold::
        
            sage: M = Manifold(2, 'M', start_index=1)
            sage: X.<x,y> = M.chart('x y')
            sage: g = Metric(M, 'g')
            sage: g[1,1], g[1, 2], g[2, 2] = 1+x, x*y , 1-y
            sage: g[:]
            [ x + 1    x*y]
            [   x*y -y + 1]
            sage: s = g.sqrt_abs_det() ; s
            scalar field on the 2-dimensional manifold 'M'
            sage: s.expr()
            sqrt(-x^2*y^2 - (x + 1)*y + x + 1)

        Determinant in a frame different from the default's one::
            
            sage: Y.<u,v> = M.chart('u v')
            sage: ch_X_Y = CoordChange(X, Y, x+y, x-y)   
            sage: ch_X_Y.inverse()
            coordinate change from chart (M, (u, v)) to chart (M, (x, y))                    
            sage: g.comp(Y.frame)[:, Y]
            [ 1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2                            1/4*u]
            [                           1/4*u -1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2]
            sage: g.sqrt_abs_det(Y.frame).expr()
            1/2*sqrt(-x^2*y^2 - (x + 1)*y + x + 1)
            sage: g.sqrt_abs_det(Y.frame).expr(Y)
            1/8*sqrt(-u^4 - v^4 + 2*(u^2 + 2)*v^2 - 4*u^2 + 16*v + 16)

        A chart can be passed instead of a frame::
        
            sage: g.sqrt_abs_det(Y) is g.sqrt_abs_det(Y.frame)
            True

        The metric determinant depends on the frame::
        
            sage: g.sqrt_abs_det(X.frame) == g.sqrt_abs_det(Y.frame) 
            False

        """
        from sage.functions.other import sqrt
        from scalarfield import ScalarField
        from utilities import simplify_chain
        manif = self.manifold
        dom = self.domain
        if frame is None:
            frame = dom.def_frame
        if frame in dom.atlas:   
            # frame is actually a chart and is changed to the associated 
            # coordinate frame:
            frame = frame.frame
        if frame not in self._sqrt_abs_dets:
            # a new computation is necessary
            detg = self.determinant(frame)
            resu = ScalarField(dom)
            for chart in detg.express:
                x = self._indic_signat * detg.express[chart].express # |g|
                x = simplify_chain(sqrt(x))
                resu.add_expr(x, chart=chart)
            self._sqrt_abs_dets[frame] = resu
        return self._sqrt_abs_dets[frame]
    def determinant(self, frame=None):
        r"""
        Determinant of the metric components in the specified frame.
        
        INPUT:
        
        - ``frame`` -- (default: None) vector frame with 
          respect to which the components `g_{ij}` of ``self`` are defined; 
          if None, the domain's default frame is used. If a chart is 
          provided, the associated coordinate frame is used
          
        OUTPUT:
        
        - the determinant `\det (g_{ij})`, as an instance of :class:`ScalarField`
        
        EXAMPLES:
        
        Metric determinant on a 2-dimensional manifold::
        
            sage: M = Manifold(2, 'M', start_index=1)
            sage: X.<x,y> = M.chart('x y')
            sage: g = Metric(M, 'g')
            sage: g[1,1], g[1, 2], g[2, 2] = 1+x, x*y , 1-y
            sage: g[:]
            [ x + 1    x*y]
            [   x*y -y + 1]
            sage: s = g.determinant()  # determinant in M's default frame
            sage: s.expr()
            -x^2*y^2 - (x + 1)*y + x + 1

        Determinant in a frame different from the default's one::
            
            sage: Y.<u,v> = M.chart('u v')
            sage: ch_X_Y = CoordChange(X, Y, x+y, x-y)   
            sage: ch_X_Y.inverse()
            coordinate change from chart (M, (u, v)) to chart (M, (x, y))                 
            sage: g.comp(Y.frame)[:, Y]
            [ 1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2                            1/4*u]
            [                           1/4*u -1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2]
            sage: g.determinant(Y.frame).expr()
            -1/4*x^2*y^2 - 1/4*(x + 1)*y + 1/4*x + 1/4
            sage: g.determinant(Y.frame).expr(Y)
            -1/64*u^4 - 1/64*v^4 + 1/32*(u^2 + 2)*v^2 - 1/16*u^2 + 1/4*v + 1/4

        A chart can be passed instead of a frame::
        
            sage: g.determinant(X) is g.determinant(X.frame)
            True
            sage: g.determinant(Y) is g.determinant(Y.frame)
            True

        The metric determinant depends on the frame::
        
            sage: g.determinant(X.frame) == g.determinant(Y.frame)
            False
        
        """
        from sage.matrix.constructor import matrix
        from scalarfield import ScalarField
        from utilities import simple_determinant, simplify_chain
        manif = self.manifold
        dom = self.domain
        if frame is None:
            frame = dom.def_frame
        if frame in dom.atlas:   
            # frame is actually a chart and is changed to the associated 
            # coordinate frame:
            frame = frame.frame
        if frame not in self._determinants:
            # a new computation is necessary
            resu = ScalarField(dom)
            gg = self.comp(frame)
            i1 = manif.sindex
            for chart in gg[[i1, i1]].express:
                gm = matrix( [[ gg[i, j, chart].express 
                            for j in manif.irange()] for i in manif.irange()] )
                detgm = simplify_chain(simple_determinant(gm))
                resu.add_expr(detgm, chart=chart)
            self._determinants[frame] = resu
        return self._determinants[frame]
    def inverse(self):
        r"""
        Return the inverse metric.
        
        EXAMPLES:
        
        Inverse metric on a 2-dimensional manifold::
    
            sage: m = Manifold(2, 'M', start_index=1)
            sage: c_xy.<x,y> = m.chart('x y')
            sage: g = Metric(m, 'g') 
            sage: g[1,1], g[1,2], g[2,2] = 1+x, x*y, 1-x 
            sage: g[:]  # components in the manifold's default frame
            [ x + 1    x*y]
            [   x*y -x + 1]
            sage: ig = g.inverse() ; ig
            tensor field 'inv_g' of type (2,0) on the 2-dimensional manifold 'M'
            sage: ig[:]
            [ (x - 1)/(x^2*y^2 + x^2 - 1)      x*y/(x^2*y^2 + x^2 - 1)]
            [     x*y/(x^2*y^2 + x^2 - 1) -(x + 1)/(x^2*y^2 + x^2 - 1)]

        If the metric is modified, the inverse metric is automatically updated::
        
            sage: g[1,2] = 0 ; g[:]
            [ x + 1      0]
            [     0 -x + 1]
            sage: g.inverse()[:]
            [ 1/(x + 1)          0]
            [         0 -1/(x - 1)]

        """
        from sage.matrix.constructor import matrix
        from component import CompFullySym
        from vectorframe import CoordFrame
        from utilities import simplify_chain
        # Is the inverse metric up to date ?
        for frame in self.components:
            if frame not in self._inverse.components:
                # the computation is necessary
                manif = self.manifold
                dom = self.domain
                if isinstance(frame, CoordFrame):
                    chart = frame.chart
                else:
                    chart = dom.def_chart
                si = manif.sindex
                nsi = manif.dim + si
                try:    
                    gmat = matrix(
                              [[self.comp(frame)[i, j, chart].express 
                              for j in range(si, nsi)] for i in range(si, nsi)])
                except (KeyError, ValueError):
                    continue
                gmat_inv = gmat.inverse()
                cinv = CompFullySym(frame, 2)
                for i in range(si, nsi):
                    for j in range(i, nsi):   # symmetry taken into account
                        cinv[i, j, chart] = simplify_chain(
                                                        gmat_inv[i-si,j-si])
                self._inverse.components[frame] = cinv
        return self._inverse
Exemple #10
0
    def sqrt_abs_det(self, frame_name=None):
        r"""
        Square root of the absolute value of the determinant of the metric 
        components in the specified frame.
        
        INPUT:
        
        - ``frame_name`` -- (default: None) name of the vector frame with 
          respect to which the components `g_{ij}` of ``self`` are defined; 
          if None, the manifold's default frame is used. If a chart name is 
          provided, the associated coordinate basis is used
          
        OUTPUT:
        
        -  `\sqrt{|\det (g_{ij})|}`, as an instance of :class:`ScalarField`
        
        EXAMPLES:
        
        Standard metric in the Euclidean space `\RR^3` with spherical 
        coordinates::
        
            sage: m = Manifold(3, 'M', start_index=1)
            sage: c_spher = Chart(m, r'r:positive th:positive:\theta ph:\phi', 'spher')
            sage: assume(th>=0); assume(th<=pi)
            sage: g = Metric(m, 'g')
            sage: g[1,1], g[2,2], g[3,3] = 1, r^2, (r*sin(th))^2
            sage: g.show()
            g = dr*dr + r^2 dth*dth + r^2*sin(th)^2 dph*dph
            sage: g.sqrt_abs_det().expr()
            r^2*sin(th)
            
        Metric determinant on a 2-dimensional manifold::
        
            sage: M = Manifold(2, 'M', start_index=1)
            sage: X = Chart(M, 'x y', 'xy')
            sage: g = Metric(M, 'g')
            sage: g[1,1], g[1, 2], g[2, 2] = 1+x, x*y , 1-y
            sage: g[:]
            [ x + 1    x*y]
            [   x*y -y + 1]
            sage: s = g.sqrt_abs_det() ; s
            scalar field on the 2-dimensional manifold 'M'
            sage: s.expr()
            sqrt(-x^2*y^2 - (x + 1)*y + x + 1)

        Determinant in a frame different from the default's one::
            
            sage: Y = Chart(M, 'u v', 'uv')
            sage: ch_X_Y = CoordChange(X, Y, x+y, x-y)   
            sage: ch_X_Y.inverse()                    
            coordinate change from chart 'uv' (u, v) to chart 'xy' (x, y)
            sage: g.comp('uv_b')[:, 'uv']
            [ 1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2                            1/4*u]
            [                           1/4*u -1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2]
            sage: g.sqrt_abs_det('uv_b').expr()
            1/2*sqrt(-x^2*y^2 - (x + 1)*y + x + 1)
            sage: g.sqrt_abs_det('uv_b').expr('uv')
            1/8*sqrt(-u^4 - 4*u^2 - v^4 + 2*(u^2 + 2)*v^2 + 16*v + 16)

        The name of a chart can be passed instead of the name of a frame::
        
            sage: g.sqrt_abs_det('uv') is g.sqrt_abs_det('uv_b')
            True

        The metric determinant depends on the frame::
        
            sage: g.sqrt_abs_det('xy_b') == g.sqrt_abs_det('uv_b') 
            False

        """
        from sage.functions.other import sqrt
        from scalarfield import ScalarField
        from utilities import simplify_chain
        manif = self.manifold
        if frame_name is None:
            frame_name = manif.def_frame.name
        if frame_name in manif.atlas:
            # frame_name is actually the name of a chart and is changed to the
            # name of the associated coordinate basis:
            frame_name = manif.atlas[frame_name].frame.name
        if frame_name not in self._sqrt_abs_dets:
            # a new computation is necessary
            detg = self.determinant(frame_name)
            resu = ScalarField(manif)
            for chart_name in detg.express:
                x = self._indic_signat * detg.express[chart_name].express  # |g|
                x = simplify_chain(sqrt(x))
                resu.set_expr(x, chart_name=chart_name, delete_others=False)
            self._sqrt_abs_dets[frame_name] = resu
        return self._sqrt_abs_dets[frame_name]
Exemple #11
0
    def determinant(self, frame_name=None):
        r"""
        Determinant of the metric components in the specified frame.
        
        INPUT:
        
        - ``frame_name`` -- (default: None) name of the vector frame with 
          respect to which the components `g_{ij}` of ``self`` are defined; 
          if None, the manifold's default frame is used. If a chart name is 
          provided, the associated coordinate basis is used
          
        OUTPUT:
        
        - the determinant `\det (g_{ij})`, as an instance of :class:`ScalarField`
        
        EXAMPLES:
        
        Metric determinant on a 2-dimensional manifold::
        
            sage: M = Manifold(2, 'M', start_index=1)
            sage: X = Chart(M, 'x y', 'xy')
            sage: g = Metric(M, 'g')
            sage: g[1,1], g[1, 2], g[2, 2] = 1+x, x*y , 1-y
            sage: g[:]
            [ x + 1    x*y]
            [   x*y -y + 1]
            sage: s = g.determinant()  # determinant in M's default frame
            sage: s.expr()
            -x^2*y^2 - (x + 1)*y + x + 1

        Determinant in a frame different from the default's one::
            
            sage: Y = Chart(M, 'u v', 'uv')
            sage: ch_X_Y = CoordChange(X, Y, x+y, x-y)   
            sage: ch_X_Y.inverse()                    
            coordinate change from chart 'uv' (u, v) to chart 'xy' (x, y)
            sage: g.comp('uv_b')[:, 'uv']
            [ 1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2                            1/4*u]
            [                           1/4*u -1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2]
            sage: g.determinant('uv_b').expr()
            -1/4*x^2*y^2 - 1/4*(x + 1)*y + 1/4*x + 1/4
            sage: g.determinant('uv_b').expr('uv')
            -1/64*u^4 - 1/16*u^2 - 1/64*v^4 + 1/32*(u^2 + 2)*v^2 + 1/4*v + 1/4

        The name of a chart can be passed instead of the name of a frame::
        
            sage: g.determinant('xy') is g.determinant('xy_b')
            True
            sage: g.determinant('uv') is g.determinant('uv_b')
            True

        The metric determinant depends on the frame::
        
            sage: g.determinant('xy_b') == g.determinant('uv_b')
            False
        
        """
        from sage.matrix.constructor import matrix
        from scalarfield import ScalarField
        from utilities import simple_determinant, simplify_chain
        manif = self.manifold
        if frame_name is None:
            frame_name = manif.def_frame.name
        if frame_name in manif.atlas:
            # frame_name is actually the name of a chart and is changed to the
            # name of the associated coordinate basis:
            frame_name = manif.atlas[frame_name].frame.name
        if frame_name not in self._determinants:
            # a new computation is necessary
            resu = ScalarField(manif)
            gg = self.comp(frame_name)
            i1 = manif.sindex
            for chart_name in gg[[i1, i1]].express:
                gm = matrix(
                    [[gg[i, j, chart_name].express for j in manif.irange()]
                     for i in manif.irange()])
                detgm = simplify_chain(simple_determinant(gm))
                resu.set_expr(detgm,
                              chart_name=chart_name,
                              delete_others=False)
            self._determinants[frame_name] = resu
        return self._determinants[frame_name]
Exemple #12
0
    def inverse(self):
        r"""
        Return the inverse metric.
        
        EXAMPLES:
        
        Inverse metric on a 2-dimensional manifold::
    
            sage: m = Manifold(2, 'M', start_index=1)
            sage: c_xy = Chart(m, 'x y', 'xy')
            sage: g = Metric(m, 'g') 
            sage: g[1,1], g[1,2], g[2,2] = 1+x, x*y, 1-x 
            sage: g[:]  # components in the manifold's default frame
            [ x + 1    x*y]
            [   x*y -x + 1]
            sage: ig = g.inverse() ; ig
            tensor field 'inv_g' of type (2,0) on the 2-dimensional manifold 'M'
            sage: ig[:]
            [ (x - 1)/(x^2*y^2 + x^2 - 1)      x*y/(x^2*y^2 + x^2 - 1)]
            [     x*y/(x^2*y^2 + x^2 - 1) -(x + 1)/(x^2*y^2 + x^2 - 1)]

        If the metric is modified, the inverse metric is automatically updated::
        
            sage: g[1,2] = 0 ; g[:]
            [ x + 1      0]
            [     0 -x + 1]
            sage: g.inverse()[:]
            [ 1/(x + 1)          0]
            [         0 -1/(x - 1)]

        """
        from sage.matrix.constructor import matrix
        from component import CompFullySym
        from utilities import simplify_chain
        # Is the inverse metric up to date ?
        for frame_name in self.components:
            if frame_name not in self._inverse.components:
                # the computation is necessary
                manif = self.manifold
                if frame_name[-2:] == '_b':
                    # coordinate basis
                    chart_name = frame_name[:-2]
                else:
                    chart_name = manif.def_chart.name
                si = manif.sindex
                nsi = manif.dim + si
                try:
                    gmat = matrix([[
                        self.comp(frame_name)[i, j, chart_name].express
                        for j in range(si, nsi)
                    ] for i in range(si, nsi)])
                except KeyError:
                    continue
                gmat_inv = gmat.inverse()
                cinv = CompFullySym(manif, 2, frame_name)
                for i in range(si, nsi):
                    for j in range(i, nsi):  # symmetry taken into account
                        cinv[i, j,
                             chart_name] = simplify_chain(gmat_inv[i - si,
                                                                   j - si])
                self._inverse.components[frame_name] = cinv
        return self._inverse
Exemple #13
0
    def inverse(self, chartname1=None, chartname2=None):
        r"""
        Returns the inverse diffeomorphism. 
        
        INPUT:
    
        - ``chartname1`` -- (default: None) string defining the chart in which
          the computation of the inverse is performed; if none is provided, the
          default chart of self.manifold1 will be used
        - ``chartname2`` -- (default: None) string defining the chart in which
          the computation of the inverse is performed; if none is provided, the
          default chart of self.manifold2 will be used
        
        OUTPUT:
        
        - the inverse diffeomorphism
        
        EXAMPLES:
        
            The inverse of a rotation in the plane::
            
                sage: m = Manifold(2, "plane")
                sage: c_cart = Chart(m, 'x y', 'cart')
                sage: # A pi/3 rotation around the origin:
                sage: rot = Diffeomorphism(m, m, ((x - sqrt(3)*y)/2, (sqrt(3)*x + y)/2))
                sage: p = Point(m,(1,2))
                sage: q = rot(p)
                sage: irot = rot.inverse()
                sage: p1 = irot(q)
                sage: p1 == p
                True
        """
        from sage.symbolic.ring import SR
        from sage.symbolic.relation import solve
        from utilities import simplify_chain
        if self._inverse is not None:
            return self._inverse

        if chartname1 is None: chartname1 = self.manifold1.def_chart.name
        if chartname2 is None: chartname2 = self.manifold2.def_chart.name

        coord_map = self.coord_expression[(chartname1, chartname2)]
        chart1 = self.manifold1.atlas[chartname1]
        chart2 = self.manifold2.atlas[chartname2]

        n1 = len(chart1.xx)
        n2 = len(chart2.xx)

        # New symbolic variables (different from chart2.xx to allow for a
        #  correct solution even when chart2 = chart1):
        x2 = [SR.var('xxxx' + str(i)) for i in range(n2)]
        equations = [x2[i] == coord_map.functions[i] for i in range(n2)]
        solutions = solve(equations, chart1.xx, solution_dict=True)
        if len(solutions) == 0:
            raise ValueError("No solution found")
        if len(solutions) > 1:
            raise ValueError("Non-unique solution found")

        #!# This should be the Python 2.7 form:
        # substitutions = {x2[i]: chart2.xx[i] for i in range(n2)}
        #
        # Here we use a form compatible with Python 2.6:
        substitutions = dict([(x2[i], chart2.xx[i]) for i in range(n2)])

        inv_functions = [
            solutions[0][chart1.xx[i]].subs(substitutions) for i in range(n1)
        ]
        for i in range(n1):
            x = inv_functions[i]
            try:
                inv_functions[i] = simplify_chain(x)
            except AttributeError:
                pass
        self._inverse = Diffeomorphism(self.manifold2, self.manifold1,
                                       inv_functions, chartname2, chartname1)
        return self._inverse
Exemple #14
0
    def sqrt_abs_det(self, frame=None):
        r"""
        Square root of the absolute value of the determinant of the metric 
        components in the specified frame.
        
        INPUT:
        
        - ``frame`` -- (default: None) vector frame with 
          respect to which the components `g_{ij}` of ``self`` are defined; 
          if None, the domain's default frame is used. If a chart is 
          provided, the associated coordinate frame is used
          
        OUTPUT:
        
        -  `\sqrt{|\det (g_{ij})|}`, as an instance of :class:`ScalarField`
        
        EXAMPLES:
        
        Standard metric in the Euclidean space `\RR^3` with spherical 
        coordinates::
        
            sage: m = Manifold(3, 'M', start_index=1)
            sage: c_spher.<r,th,ph> = m.chart(r'r:[0,+oo) th:[0,pi]:\theta ph:[0,2*pi):\phi')
            sage: g = Metric(m, 'g')
            sage: g[1,1], g[2,2], g[3,3] = 1, r^2, (r*sin(th))^2
            sage: g.view()
            g = dr*dr + r^2 dth*dth + r^2*sin(th)^2 dph*dph
            sage: g.sqrt_abs_det().expr()
            r^2*sin(th)
            
        Metric determinant on a 2-dimensional manifold::
        
            sage: M = Manifold(2, 'M', start_index=1)
            sage: X.<x,y> = M.chart('x y')
            sage: g = Metric(M, 'g')
            sage: g[1,1], g[1, 2], g[2, 2] = 1+x, x*y , 1-y
            sage: g[:]
            [ x + 1    x*y]
            [   x*y -y + 1]
            sage: s = g.sqrt_abs_det() ; s
            scalar field on the 2-dimensional manifold 'M'
            sage: s.expr()
            sqrt(-x^2*y^2 - (x + 1)*y + x + 1)

        Determinant in a frame different from the default's one::
            
            sage: Y.<u,v> = M.chart('u v')
            sage: ch_X_Y = CoordChange(X, Y, x+y, x-y)   
            sage: ch_X_Y.inverse()
            coordinate change from chart (M, (u, v)) to chart (M, (x, y))                    
            sage: g.comp(Y.frame)[:, Y]
            [ 1/8*u^2 - 1/8*v^2 + 1/4*v + 1/2                            1/4*u]
            [                           1/4*u -1/8*u^2 + 1/8*v^2 + 1/4*v + 1/2]
            sage: g.sqrt_abs_det(Y.frame).expr()
            1/2*sqrt(-x^2*y^2 - (x + 1)*y + x + 1)
            sage: g.sqrt_abs_det(Y.frame).expr(Y)
            1/8*sqrt(-u^4 - v^4 + 2*(u^2 + 2)*v^2 - 4*u^2 + 16*v + 16)

        A chart can be passed instead of a frame::
        
            sage: g.sqrt_abs_det(Y) is g.sqrt_abs_det(Y.frame)
            True

        The metric determinant depends on the frame::
        
            sage: g.sqrt_abs_det(X.frame) == g.sqrt_abs_det(Y.frame) 
            False

        """
        from sage.functions.other import sqrt
        from scalarfield import ScalarField
        from utilities import simplify_chain
        manif = self.manifold
        dom = self.domain
        if frame is None:
            frame = dom.def_frame
        if frame in dom.atlas:
            # frame is actually a chart and is changed to the associated
            # coordinate frame:
            frame = frame.frame
        if frame not in self._sqrt_abs_dets:
            # a new computation is necessary
            detg = self.determinant(frame)
            resu = ScalarField(dom)
            for chart in detg.express:
                x = self._indic_signat * detg.express[chart].express  # |g|
                x = simplify_chain(sqrt(x))
                resu.add_expr(x, chart=chart)
            self._sqrt_abs_dets[frame] = resu
        return self._sqrt_abs_dets[frame]