Ejemplo n.º 1
0
 def __init__(self, manifold, name, signature=None, latex_name=None):
     SymBilinFormField.__init__(self, manifold, name, latex_name)
     # signature:
     ndim = self.manifold.dim
     if signature is None:
         signature = ndim
     else:
         if not isinstance(signature, (int, Integer)):
             raise TypeError("The metric signature must be an integer.")
         if (signature < -ndim) or (signature > ndim):
             raise ValueError("Metric signature out of range.")
         if (signature + ndim) % 2 == 1:
             if ndim % 2 == 0:
                 raise ValueError("The metric signature must be even.")
             else:
                 raise ValueError("The metric signature must be odd.")
     self._signature = signature
     # the pair (n_+, n_-):
     self._signature_pm = ((ndim + signature) / 2, (ndim - signature) / 2)
     self._indic_signat = 1 - 2 * (self._signature_pm[1] % 2)  # (-1)^n_-
     # inverse metric:
     inv_name = 'inv_' + self.name
     inv_latex_name = self.latex_name + r'^{-1}'
     self._inverse = TensorField(self.manifold,
                                 2,
                                 0,
                                 inv_name,
                                 inv_latex_name,
                                 sym=(0, 1))
     self._connection = None  # Levi-Civita connection (not set yet)
     self._weyl = None  # Weyl tensor (not set yet)
     self._determinants = {}  # determinants in various frames
     self._sqrt_abs_dets = {}  # sqrt(abs(det g)) in various frames
     self._vol_forms = []  # volume form and associated tensors
Ejemplo n.º 2
0
 def _init_derived(self):
     r"""
     Initialize the derived quantities
     """
     # Initialization of quantities pertaining to the mother class:
     SymBilinFormField._init_derived(self) 
     # inverse metric:
     inv_name = 'inv_' + self.name
     inv_latex_name = self.latex_name + r'^{-1}'
     self._inverse = TensorField(self.domain, 2, 0, inv_name, 
                                 inv_latex_name, sym=(0,1))   
     self._connection = None  # Levi-Civita connection (not set yet)
     self._weyl = None # Weyl tensor (not set yet)
     self._determinants = {} # determinants in various frames
     self._sqrt_abs_dets = {} # sqrt(abs(det g)) in various frames
     self._vol_forms = [] # volume form and associated tensors
Ejemplo n.º 3
0
    def pullback(self, tensor):
        r""" 
        Pullback operator associated with the differentiable mapping. 
        
        INPUT:
        
        - ``tensor`` -- instance of :class:`TensorField` representing a fully 
          covariant tensor field `T` on the *arrival* domain, i.e. a tensor 
          field of type (0,p), with p a positive or zero integer. The case p=0 
          corresponds to a scalar field.
          
        OUTPUT:
        
        - instance of :class:`TensorField` representing a fully 
          covariant tensor field on the *start* domain that is the 
          pullback of `T` given by ``self``. 
          
        EXAMPLES:
        
        Pullback on `S^2` of a scalar field defined on `R^3`::
        
            sage: m = Manifold(2, 'S^2', start_index=1)
            sage: c_spher.<th,ph> = m.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') # spherical coord. on S^2
            sage: n = Manifold(3, 'R^3', r'\RR^3', start_index=1)
            sage: c_cart.<x,y,z> = n.chart('x y z') # Cartesian coord. on R^3
            sage: Phi = DiffMapping(m, n, (sin(th)*cos(ph), sin(th)*sin(ph), cos(th)), name='Phi', latex_name=r'\Phi')
            sage: f = ScalarField(n, x*y*z, name='f') ; f
            scalar field 'f' on the 3-dimensional manifold 'R^3'
            sage: f.view()
            f: (x, y, z) |--> x*y*z
            sage: pf = Phi.pullback(f) ; pf
            scalar field 'Phi_*(f)' on the 2-dimensional manifold 'S^2'
            sage: pf.view()
            Phi_*(f): (th, ph) |--> cos(ph)*cos(th)*sin(ph)*sin(th)^2
            
        Pullback on `S^2` of the standard Euclidean metric on `R^3`::
                
            sage: g = SymBilinFormField(n, 'g')
            sage: g[1,1], g[2,2], g[3,3] = 1, 1, 1
            sage: g.view()
            g = dx*dx + dy*dy + dz*dz
            sage: pg = Phi.pullback(g) ; pg
            field of symmetric bilinear forms 'Phi_*(g)' on the 2-dimensional manifold 'S^2'
            sage: pg.view()
            Phi_*(g) = dth*dth + sin(th)^2 dph*dph

        Pullback on `S^2` of a 3-form on `R^3`::
                
            sage: a = DiffForm(n, 3, 'A')
            sage: a[1,2,3] = f 
            sage: a.view()
            A = x*y*z dx/\dy/\dz
            sage: pa = Phi.pullback(a) ; pa
            3-form 'Phi_*(A)' on the 2-dimensional manifold 'S^2'
            sage: pa.view() # should be zero (as any 3-form on a 2-dimensional manifold)
            Phi_*(A) = 0

        """
        from scalarfield import ScalarField
        from vectorframe import CoordFrame
        from rank2field import SymBilinFormField
        from diffform import DiffForm, OneForm

        if not isinstance(tensor, TensorField):
            raise TypeError("The argument 'tensor' must be a tensor field.")
        dom1 = self.domain1
        dom2 = self.domain2
        if not tensor.domain.is_subdomain(dom2):
            raise TypeError("The tensor field is not defined on the mapping " +
                            "arrival domain.")
        (ncon, ncov) = tensor.tensor_type
        if ncon != 0:
            raise TypeError("The pullback cannot be taken on a tensor " + 
                            "with some contravariant part.")
        resu_name = None ; resu_latex_name = None
        if self.name is not None and tensor.name is not None:
            resu_name = self.name + '_*(' + tensor.name + ')'
        if self.latex_name is not None and tensor.latex_name is not None:
            resu_latex_name = self.latex_name + '_*' + tensor.latex_name                
        if ncov == 0:
            # Case of a scalar field
            # ----------------------
            resu = ScalarField(dom1, name=resu_name, 
                               latex_name=resu_latex_name)
            for chart2 in tensor.express:
                for chart1 in dom1.atlas:
                    if (chart1, chart2) in self.coord_expression:
                        phi = self.coord_expression[(chart1, chart2)]
                        coord1 = chart1.xx
                        ff = tensor.express[chart2]
                        resu.add_expr( ff(*(phi(*coord1))), chart1)
            return resu
        else:
            # Case of tensor field of rank >= 1
            # ---------------------------------
            if isinstance(tensor, OneForm):
                resu = OneForm(dom1, name=resu_name, 
                               latex_name=resu_latex_name)
            elif isinstance(tensor, DiffForm):
                resu = DiffForm(dom1, ncov, name=resu_name, 
                                latex_name=resu_latex_name)
            elif isinstance(tensor, SymBilinFormField):
                resu = SymBilinFormField(dom1, name=resu_name, 
                                         latex_name=resu_latex_name)                
            else:
                resu = TensorField(dom1, 0, ncov, name=resu_name, 
                                   latex_name=resu_latex_name, sym=tensor.sym,
                                   antisym=tensor.antisym)
            for frame2 in tensor.components:
                if isinstance(frame2, CoordFrame):
                    chart2 = frame2.chart
                    for chart1 in dom1.atlas:
                        if (chart1, chart2) in self.coord_expression:
                            # Computation at the component level:
                            frame1 = chart1.frame
                            tcomp = tensor.components[frame2]
                            if isinstance(tcomp, CompFullySym):
                                ptcomp = CompFullySym(frame1, ncov)
                            elif isinstance(tcomp, CompFullyAntiSym):
                                ptcomp = CompFullyAntiSym(frame1, ncov)
                            elif isinstance(tcomp, CompWithSym):
                                ptcomp = CompWithSym(frame1, ncov, sym=tcomp.sym, 
                                                     antisym=tcomp.antisym)
                            else:
                                ptcomp = Components(frame1, ncov)
                            phi = self.coord_expression[(chart1, chart2)]
                            jacob = phi.jacobian()
                            # X2 coordinates expressed in terms of X1 ones via the mapping:
                            coord2_1 = phi(*(chart1.xx)) 
                            si1 = dom1.manifold.sindex
                            si2 = dom2.manifold.sindex
                            for ind_new in ptcomp.non_redundant_index_generator(): 
                                res = 0 
                                for ind_old in dom2.manifold.index_generator(ncov): 
                                    ff = tcomp[[ind_old]].function_chart(chart2)
                                    t = FunctionChart(chart1, ff(*coord2_1))
                                    for i in range(ncov):
                                        t *= jacob[ind_old[i]-si2][ind_new[i]-si1]
                                    res += t
                                ptcomp[ind_new] = res
                            resu.components[frame1] = ptcomp
            return resu