def __init__(self, n, name, metric_name='g', signature=None, base_manifold=None, diff_degree=infinity, latex_name=None, metric_latex_name=None, start_index=0, category=None, unique_tag=None): r""" Construct a pseudo-Riemannian manifold. TESTS:: sage: M = Manifold(4, 'M', structure='pseudo-Riemannian', ....: signature=0) sage: M 4-dimensional pseudo-Riemannian manifold M sage: type(M) <class 'sage.manifolds.differentiable.pseudo_riemannian.PseudoRiemannianManifold_with_category'> sage: X.<w,x,y,z> = M.chart() sage: M.metric() Pseudo-Riemannian metric g on the 4-dimensional pseudo-Riemannian manifold M sage: TestSuite(M).run() """ if base_manifold and not isinstance(base_manifold, PseudoRiemannianManifold): raise TypeError("the argument 'base_manifold' must be a " + "pseudo-Riemannian manifold") if signature is None or signature == n: structure = RiemannianStructure() elif signature == n - 2 or signature == 2 - n: structure = LorentzianStructure() else: structure = PseudoRiemannianStructure() DifferentiableManifold.__init__(self, n, name, 'real', structure, base_manifold=base_manifold, diff_degree=diff_degree, latex_name=latex_name, start_index=start_index, category=category) self._metric = None # to be initialized by metric() self._metric_signature = signature if not isinstance(metric_name, str): raise TypeError("{} is not a string".format(metric_name)) self._metric_name = metric_name if metric_latex_name is None: self._metric_latex_name = self._metric_name else: if not isinstance(metric_latex_name, str): raise TypeError("{} is not a string".format(metric_latex_name)) self._metric_latex_name = metric_latex_name
def __init__(self, n, name, metric_name=None, signature=None, base_manifold=None, diff_degree=infinity, latex_name=None, metric_latex_name=None, start_index=0, category=None, unique_tag=None): r""" Construct a degenerate manifold. TESTS:: sage: M = Manifold(3, 'M', structure='degenerate_metric') sage: M 3-dimensional degenerate_metric manifold M sage: type(M) <class 'sage.manifolds.differentiable.degenerate.DegenerateManifold_with_category'> sage: X.<x,y,z> = M.chart() sage: M.metric() degenerate metric g on the 3-dimensional degenerate_metric manifold M sage: TestSuite(M).run() """ if base_manifold and not isinstance(base_manifold, DegenerateManifold): raise TypeError("the argument 'base_manifold' must be a " + "Degenerate manifold") structure = DegenerateStructure() DifferentiableManifold.__init__(self, n, name, 'real', structure, base_manifold=base_manifold, diff_degree=diff_degree, latex_name=latex_name, start_index=start_index, category=category) self._metric = None # to be initialized by metric() self._metric_signature = signature if metric_name is None: metric_name = 'g' elif not isinstance(metric_name, str): raise TypeError("{} is not a string".format(metric_name)) self._metric_name = metric_name if metric_latex_name is None: self._metric_latex_name = self._metric_name else: if not isinstance(metric_latex_name, str): raise TypeError("{} is not a string".format(metric_latex_name)) self._metric_latex_name = metric_latex_name
def __init__(self, L, name, **kwds): r""" Initialize ``self``. TESTS:: sage: L = lie_algebras.Heisenberg(QQ, 2) sage: G = L.lie_group() sage: TestSuite(G).run() """ required_cat = LieAlgebras(L.base_ring()).FiniteDimensional() required_cat = required_cat.WithBasis().Nilpotent() if L not in required_cat: raise TypeError("L needs to be a finite dimensional nilpotent " "Lie algebra with basis") self._lie_algebra = L R = L.base_ring() category = kwds.pop('category', None) category = LieGroups(R).or_subcategory(category) if isinstance(R, RealField_class): structure = RealDifferentialStructure() else: structure = DifferentialStructure() DifferentiableManifold.__init__(self, L.dimension(), name, R, structure, category=category) # initialize exponential coordinates of the first kind basis_strs = [str(X) for X in L.basis()] split = list(zip(*[s.split('_') for s in basis_strs])) if len(split) == 2 and all(sk == split[0][0] for sk in split[0]): self._var_indexing = split[1] else: self._var_indexing = [str(k) for k in range(L.dimension())] variables = ' '.join('x_%s' % k for k in self._var_indexing) self._Exp1 = self.chart(variables) # compute a symbolic formula for the group law L_SR = _symbolic_lie_algebra_copy(L) n = L.dimension() a, b = (tuple(var('%s_%d' % (s, j)) for j in range(n)) for s in ['a', 'b']) self._group_law_vars = (a, b) bch = L_SR.bch(L_SR.from_vector(a), L_SR.from_vector(b), L.step()) self._group_law = vector(SR, (zk.expand() for zk in bch.to_vector()))
def __init__(self, n, name, metric_name='g', signature=None, ambient=None, diff_degree=infinity, latex_name=None, metric_latex_name=None, start_index=0, category=None, unique_tag=None): r""" Construct a pseudo-Riemannian manifold. TESTS:: sage: M = Manifold(4, 'M', structure='pseudo-Riemannian', ....: signature=0) sage: M 4-dimensional pseudo-Riemannian manifold M sage: type(M) <class 'sage.manifolds.differentiable.pseudo_riemannian.PseudoRiemannianManifold_with_category'> sage: X.<w,x,y,z> = M.chart() sage: M.metric() Pseudo-Riemannian metric g on the 4-dimensional pseudo-Riemannian manifold M sage: TestSuite(M).run() """ if ambient and not isinstance(ambient, PseudoRiemannianManifold): raise TypeError("the argument 'ambient' must be a " + "pseudo-Riemannian manifold") if signature is None or signature == n: structure = RiemannianStructure() elif signature == n-2 or signature == 2-n: structure = LorentzianStructure() else: structure = PseudoRiemannianStructure() DifferentiableManifold.__init__(self, n, name, 'real', structure, ambient=ambient, diff_degree=diff_degree, latex_name=latex_name, start_index=start_index, category=category) self._metric = None # to be initialized by metric() self._metric_signature = signature if not isinstance(metric_name, str): raise TypeError("{} is not a string".format(metric_name)) self._metric_name = metric_name if metric_latex_name is None: self._metric_latex_name = self._metric_name else: if not isinstance(metric_latex_name, str): raise TypeError("{} is not a string".format(metric_latex_name)) self._metric_latex_name = metric_latex_name
def __init__(self, n, name, field, structure, ambient=None, base_manifold=None, diff_degree=infinity, latex_name=None, start_index=0, category=None, unique_tag=None): r""" Construct a submanifold of a differentiable manifold. EXAMPLES:: sage: M = Manifold(3, 'M') sage: N = Manifold(2, 'N', ambient=M) sage: N 2-dimensional differentiable submanifold N embedded in 3-dimensional differentiable manifold M """ DifferentiableManifold.__init__(self, n, name, field, structure, base_manifold=base_manifold, diff_degree=diff_degree, latex_name=latex_name, start_index=start_index, category=category) TopologicalSubmanifold.__init__(self, n, name, field, structure, ambient=ambient, base_manifold=base_manifold, category=category)
def __init__(self, n, name, field, structure, ambient=None, base_manifold=None, diff_degree=infinity, latex_name=None, start_index=0, category=None, unique_tag=None): r""" Construct a submanifold of a differentiable manifold. TESTS:: sage: M = Manifold(3, 'M') sage: N = Manifold(2, 'N', ambient=M) sage: N 2-dimensional differentiable submanifold N immersed in the 3-dimensional differentiable manifold M sage: S = Manifold(2, 'S', latex_name=r'\Sigma', ambient=M, ....: start_index=1) sage: latex(S) \Sigma sage: S.start_index() 1 """ DifferentiableManifold.__init__(self, n, name, field, structure, base_manifold=base_manifold, diff_degree=diff_degree, latex_name=latex_name, start_index=start_index, category=category) self._init_immersion(ambient=ambient)
def metric(self, name=None, signature=None, latex_name=None, dest_map=None): r""" Return the metric giving the pseudo-Riemannian structure to the manifold, or define a new metric tensor on the manifold. INPUT: - ``name`` -- (default: ``None``) name given to the metric; if ``name`` is ``None`` or matches the name of the metric defining the pseudo-Riemannian structure of ``self``, the latter metric is returned - ``signature`` -- (default: ``None``; ignored if ``name`` is ``None``) signature `S` of the metric as a single integer: `S = n_+ - n_-`, where `n_+` (resp. `n_-`) is the number of positive terms (resp. number of negative terms) in any diagonal writing of the metric components; if ``signature`` is not provided, `S` is set to the manifold's dimension (Riemannian signature) - ``latex_name`` -- (default: ``None``; ignored if ``name`` is ``None``) LaTeX symbol to denote the metric; if ``None``, it is formed from ``name`` - ``dest_map`` -- (default: ``None``; ignored if ``name`` is ``None``) instance of class :class:`~sage.manifolds.differentiable.diff_map.DiffMap` representing the destination map `\Phi:\ U \rightarrow M`, where `U` is the current manifold; if ``None``, the identity map is assumed (case of a metric tensor field *on* `U`) OUTPUT: - instance of :class:`~sage.manifolds.differentiable.metric.PseudoRiemannianMetric` EXAMPLES: Metric of a 3-dimensional Riemannian manifold:: sage: M = Manifold(3, 'M', structure='Riemannian', start_index=1) sage: X.<x,y,z> = M.chart() sage: g = M.metric(); g Riemannian metric g on the 3-dimensional Riemannian manifold M The metric remains to be initialized, for instance by setting its components in the coordinate frame associated to the chart ``X``:: sage: g[1,1], g[2,2], g[3,3] = 1, 1, 1 sage: g.display() g = dx*dx + dy*dy + dz*dz Alternatively, the metric can be initialized from a given field of nondegenerate symmetric bilinear forms; we may create the former object by:: sage: X.coframe() Coordinate coframe (M, (dx,dy,dz)) sage: dx, dy, dz = X.coframe()[1], X.coframe()[2], X.coframe()[3] sage: b = dx*dx + dy*dy + dz*dz sage: b Field of symmetric bilinear forms dx*dx+dy*dy+dz*dz on the 3-dimensional Riemannian manifold M We then use the metric method :meth:`~sage.manifolds.differentiable.metric.PseudoRiemannianMetric.set` to make ``g`` being equal to ``b`` as a symmetric tensor field of type ``(0,2)``:: sage: g.set(b) sage: g.display() g = dx*dx + dy*dy + dz*dz Another metric can be defined on ``M`` by specifying a metric name distinct from that chosen at the creation of the manifold (which is ``g`` by default, but can be changed thanks to the keyword ``metric_name`` in :func:`~sage.manifolds.manifold.Manifold`):: sage: h = M.metric('h'); h Riemannian metric h on the 3-dimensional Riemannian manifold M sage: h[1,1], h[2,2], h[3,3] = 1+y^2, 1+z^2, 1+x^2 sage: h.display() h = (y^2 + 1) dx*dx + (z^2 + 1) dy*dy + (x^2 + 1) dz*dz The metric tensor ``h`` is distinct from the metric entering in the definition of the Riemannian manifold ``M``:: sage: h is M.metric() False while we have of course:: sage: g is M.metric() True Providing the same name as the manifold's default metric returns the latter:: sage: M.metric('g') is M.metric() True In the present case (``M`` is diffeomorphic to `\RR^3`), we can even create a Lorentzian metric on ``M``:: sage: h = M.metric('h', signature=1); h Lorentzian metric h on the 3-dimensional Riemannian manifold M """ if name is None or name == self._metric_name: # Default metric associated with the manifold if self._metric is None: if self._manifold is not self and self._manifold._metric is not None: # case of an open subset with a metric already defined on # the ambient manifold: self._metric = self._manifold._metric.restrict(self) else: # creation from scratch: self._metric = DifferentiableManifold.metric( self, self._metric_name, signature=self._metric_signature, latex_name=self._metric_latex_name) return self._metric # Metric distinct from the default one: it is created by the method # metric of the superclass for generic differentiable manifolds: return DifferentiableManifold.metric(self, name, signature=signature, latex_name=latex_name, dest_map=dest_map)
def __init__(self, lower, upper, ambient_interval=None, name=None, latex_name=None, coordinate=None, names=None, start_index=0): r""" Construct an open interval. TESTS:: sage: I = OpenInterval(-1,1); I Real interval (-1, 1) sage: TestSuite(I).run(skip='_test_elements') # pickling of elements fails sage: J = OpenInterval(-oo, 2); J Real interval (-Infinity, 2) sage: TestSuite(J).run(skip='_test_elements') # pickling of elements fails """ if latex_name is None: if name is None: latex_name = r"\left({}, {}\right)".format( latex(lower), latex(upper)) else: latex_name = name if name is None: name = "({}, {})".format(lower, upper) if ambient_interval is None: ambient_manifold = None else: if not isinstance(ambient_interval, OpenInterval): raise TypeError( "the argument ambient_interval must be an open interval") ambient_manifold = ambient_interval.manifold() field = 'real' structure = RealDifferentialStructure() DifferentiableManifold.__init__(self, 1, name, field, structure, base_manifold=ambient_manifold, latex_name=latex_name, start_index=start_index) if ambient_interval is None: if coordinate is None: if names is None: coordinate = 't' else: coordinate = names[0] self._canon_chart = self.chart(coordinates=coordinate) t = self._canon_chart[start_index] else: if lower < ambient_interval.lower_bound(): raise ValueError("the lower bound is smaller than that of " + "the containing interval") if upper > ambient_interval.upper_bound(): raise ValueError("the upper bound is larger than that of " + "the containing interval") self._supersets.update(ambient_interval._supersets) for sd in ambient_interval._supersets: sd._subsets.add(self) ambient_interval._top_subsets.add(self) t = ambient_interval.canonical_coordinate() if lower != minus_infinity: if upper != infinity: restrictions = [t > lower, t < upper] else: restrictions = t > lower else: if upper != infinity: restrictions = t < upper else: restrictions = None if ambient_interval is None: if restrictions is not None: self._canon_chart.add_restrictions(restrictions) else: self._canon_chart = ambient_interval.canonical_chart().restrict( self, restrictions=restrictions) self._lower = lower self._upper = upper
def metric(self, name=None, signature=None, latex_name=None, dest_map=None): r""" Return the metric giving the pseudo-Riemannian structure to the manifold, or define a new metric tensor on the manifold. INPUT: - ``name`` -- (default: ``None``) name given to the metric; if ``name`` is ``None`` or matches the name of the metric defining the pseudo-Riemannian structure of ``self``, the latter metric is returned - ``signature`` -- (default: ``None``; ignored if ``name`` is ``None``) signature `S` of the metric as a single integer: `S = n_+ - n_-`, where `n_+` (resp. `n_-`) is the number of positive terms (resp. number of negative terms) in any diagonal writing of the metric components; if ``signature`` is not provided, `S` is set to the manifold's dimension (Riemannian signature) - ``latex_name`` -- (default: ``None``; ignored if ``name`` is ``None``) LaTeX symbol to denote the metric; if ``None``, it is formed from ``name`` - ``dest_map`` -- (default: ``None``; ignored if ``name`` is ``None``) instance of class :class:`~sage.manifolds.differentiable.diff_map.DiffMap` representing the destination map `\Phi:\ U \rightarrow M`, where `U` is the current manifold; if ``None``, the identity map is assumed (case of a metric tensor field *on* `U`) OUTPUT: - instance of :class:`~sage.manifolds.differentiable.metric.PseudoRiemannianMetric` EXAMPLES: Metric of a 3-dimensional Riemannian manifold:: sage: M = Manifold(3, 'M', structure='Riemannian', start_index=1) sage: X.<x,y,z> = M.chart() sage: g = M.metric(); g Riemannian metric g on the 3-dimensional Riemannian manifold M The metric remains to be initialized, for instance by setting its components in the coordinate frame associated to the chart ``X``:: sage: g[1,1], g[2,2], g[3,3] = 1, 1, 1 sage: g.display() g = dx*dx + dy*dy + dz*dz Alternatively, the metric can be initialized from a given field of nondegenerate symmetric bilinear forms; we may create the former object by:: sage: X.coframe() Coordinate coframe (M, (dx,dy,dz)) sage: dx, dy, dz = X.coframe()[1], X.coframe()[2], X.coframe()[3] sage: b = dx*dx + dy*dy + dz*dz sage: b Field of symmetric bilinear forms dx*dx+dy*dy+dz*dz on the 3-dimensional Riemannian manifold M We then use the metric method :meth:`~sage.manifolds.differentiable.metric.PseudoRiemannianMetric.set` to make ``g`` being equal to ``b`` as a symmetric tensor field of type ``(0,2)``:: sage: g.set(b) sage: g.display() g = dx*dx + dy*dy + dz*dz Another metric can be defined on ``M`` by specifying a metric name distinct from that chosen at the creation of the manifold (which is ``g`` by default, but can be changed thanks to the keyword ``metric_name`` in :func:`~sage.manifolds.manifold.Manifold`):: sage: h = M.metric('h'); h Riemannian metric h on the 3-dimensional Riemannian manifold M sage: h[1,1], h[2,2], h[3,3] = 1+y^2, 1+z^2, 1+x^2 sage: h.display() h = (y^2 + 1) dx*dx + (z^2 + 1) dy*dy + (x^2 + 1) dz*dz The metric tensor ``h`` is distinct from the metric entering in the definition of the Riemannian manifold ``M``:: sage: h is M.metric() False while we have of course:: sage: g is M.metric() True Providing the same name as the manifold's default metric returns the latter:: sage: M.metric('g') is M.metric() True In the present case (``M`` is diffeomorphic to `\RR^3`), we can even create a Lorentzian metric on ``M``:: sage: h = M.metric('h', signature=1); h Lorentzian metric h on the 3-dimensional Riemannian manifold M """ if name is None or name == self._metric_name: # Default metric associated with the manifold if self._metric is None: if self._manifold is not self and self._manifold._metric is not None: # case of an open subset with a metric already defined on # the ambient manifold: self._metric = self._manifold._metric.restrict(self) else: # creation from scratch: self._metric = DifferentiableManifold.metric(self, self._metric_name, signature=self._metric_signature, latex_name=self._metric_latex_name) return self._metric # Metric distinct from the default one: it is created by the method # metric of the superclass for generic differentiable manifolds: return DifferentiableManifold.metric(self, name, signature=signature, latex_name=latex_name, dest_map=dest_map)
def __init__(self, lower, upper, ambient=None, name=None, latex_name=None, coordinate=None, names=None, start_index=0): r""" Construct an open interval. TESTS:: sage: I = OpenInterval(-1,1); I Real interval (-1, 1) sage: TestSuite(I).run(skip='_test_elements') # pickling of elements fails sage: J = OpenInterval(-oo, 2); J Real interval (-Infinity, 2) sage: TestSuite(J).run(skip='_test_elements') # pickling of elements fails """ if latex_name is None: if name is None: latex_name = r"\left({}, {}\right)".format(latex(lower), latex(upper)) else: latex_name = name if name is None: name = "({}, {})".format(lower, upper) if ambient is None: ambient_manifold = None else: if not isinstance(ambient, OpenInterval): raise TypeError("the argument ambient must be an open interval") ambient_manifold = ambient.manifold() field = 'real' structure = RealDifferentialStructure() DifferentiableManifold.__init__(self, 1, name, field, structure, ambient=ambient_manifold, latex_name=latex_name, start_index=start_index) if ambient is None: if coordinate is None: if names is None: coordinate = 't' else: coordinate = names[0] self._canon_chart = self.chart(coordinates=coordinate) t = self._canon_chart[start_index] else: if lower < ambient.lower_bound(): raise ValueError("the lower bound is smaller than that of " + "the containing interval") if upper > ambient.upper_bound(): raise ValueError("the upper bound is larger than that of " + "the containing interval") self._supersets.update(ambient._supersets) for sd in ambient._supersets: sd._subsets.add(self) ambient._top_subsets.add(self) t = ambient.canonical_coordinate() if lower != minus_infinity: if upper != infinity: restrictions = [t > lower, t < upper] else: restrictions = t > lower else: if upper != infinity: restrictions = t < upper else: restrictions = None if ambient is None: if restrictions is not None: self._canon_chart.add_restrictions(restrictions) else: self._canon_chart = ambient.canonical_chart().restrict(self, restrictions=restrictions) self._lower = lower self._upper = upper