Skip to content

Commit

Permalink
Trac sagemath#34589: VectorFieldModule, TensorFieldModule, DiffFormMo…
Browse files Browse the repository at this point in the history
…dule: Add methods tensor_product, tensor_power, update category of TensorFieldModule

... as previously done for `FiniteRankFreeModule` etc.

We introduce abstract base classes `ReflexiveModule_*` to unify the
implementations of `VectorFieldModule`... and
`FiniteRankFreeModule`/`VectorFieldFreeModule`...

Follow-up: sagemath#34621 Method `dual_pairing` for modules in `sage.tensor`

URL: https://trac.sagemath.org/34589
Reported by: mkoeppe
Ticket author(s): Matthias Koeppe
Reviewer(s): Eric Gourgoulhon
  • Loading branch information
Release Manager committed Nov 15, 2022
2 parents 9e0f156 + 74601e6 commit 4b9a500
Show file tree
Hide file tree
Showing 8 changed files with 526 additions and 225 deletions.
2 changes: 2 additions & 0 deletions src/doc/en/reference/tensor_free_modules/tensors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Tensors
.. toctree::
:maxdepth: 2

sage/tensor/modules/reflexive_module

sage/tensor/modules/tensor_free_module

sage/tensor/modules/tensor_free_submodule
Expand Down
26 changes: 26 additions & 0 deletions src/sage/manifolds/differentiable/diff_form_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from sage.manifolds.differentiable.diff_form import DiffForm, DiffFormParal
from sage.manifolds.differentiable.tensorfield import TensorField
from sage.manifolds.differentiable.tensorfield_paral import TensorFieldParal
from sage.tensor.modules.reflexive_module import ReflexiveModule_abstract


class DiffFormModule(UniqueRepresentation, Parent):
Expand Down Expand Up @@ -534,6 +535,31 @@ def base_module(self):
"""
return self._vmodule

tensor = tensor_product = ReflexiveModule_abstract.tensor_product

def tensor_type(self):
r"""
Return the tensor type of ``self`` if ``self`` is a module of 1-forms.
In this case, the pair `(0, 1)` is returned, indicating that the module
is identified with the dual of the base module.
For differential forms of other degrees, an exception is raised.
EXAMPLES::
sage: M = Manifold(3, 'M')
sage: M.diff_form_module(1).tensor_type()
(0, 1)
sage: M.diff_form_module(2).tensor_type()
Traceback (most recent call last):
...
NotImplementedError
"""
if self._degree == 1:
return (0, 1)
raise NotImplementedError

def degree(self):
r"""
Return the degree of the differential forms in ``self``.
Expand Down
4 changes: 2 additions & 2 deletions src/sage/manifolds/differentiable/tensorfield.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ class TensorField(ModuleElementWithMutability):
Module T^(0,2)(S^2) of type-(0,2) tensors fields on the 2-dimensional
differentiable manifold S^2
sage: t.parent().category()
Category of modules over Algebra of differentiable scalar fields on the
2-dimensional differentiable manifold S^2
Category of tensor products of modules over Algebra of differentiable scalar fields
on the 2-dimensional differentiable manifold S^2
The parent of `t` is not a free module, for the sphere `S^2` is not
parallelizable::
Expand Down
27 changes: 19 additions & 8 deletions src/sage/manifolds/differentiable/tensorfield_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
"""

# *****************************************************************************
# Copyright (C) 2015 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
# Copyright (C) 2015 Michal Bejger <bejger@camk.edu.pl>
# Copyright (C) 2016 Travis Scrimshaw <tscrimsh@umn.edu>
# Copyright (C) 2015-2018 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
# 2015 Michal Bejger <bejger@camk.edu.pl>
# 2016 Travis Scrimshaw <tscrimsh@umn.edu>
# 2020 Michael Jung
# 2022 Matthias Koeppe
#
# Distributed under the terms of the GNU General Public License (GPL)
# as published by the Free Software Foundation; either version 2 of
Expand All @@ -41,6 +43,7 @@
from sage.structure.unique_representation import UniqueRepresentation
from sage.structure.parent import Parent
from sage.categories.modules import Modules
from sage.tensor.modules.reflexive_module import ReflexiveModule_tensor
from sage.tensor.modules.tensor_free_module import TensorFreeModule
from sage.manifolds.differentiable.tensorfield import TensorField
from sage.manifolds.differentiable.tensorfield_paral import TensorFieldParal
Expand All @@ -51,7 +54,8 @@
from sage.manifolds.differentiable.automorphismfield import (AutomorphismField,
AutomorphismFieldParal)

class TensorFieldModule(UniqueRepresentation, Parent):

class TensorFieldModule(UniqueRepresentation, ReflexiveModule_tensor):
r"""
Module of tensor fields of a given type `(k,l)` along a differentiable
manifold `U` with values on a differentiable manifold `M`, via a
Expand Down Expand Up @@ -123,8 +127,8 @@ class TensorFieldModule(UniqueRepresentation, Parent):
`T^{(2,0)}(M)` is a module over the algebra `C^k(M)`::
sage: T20.category()
Category of modules over Algebra of differentiable scalar fields on the
2-dimensional differentiable manifold M
Category of tensor products of modules over Algebra of differentiable scalar fields
on the 2-dimensional differentiable manifold M
sage: T20.base_ring() is M.scalar_field_algebra()
True
Expand Down Expand Up @@ -226,10 +230,16 @@ class TensorFieldModule(UniqueRepresentation, Parent):
[1 0]
[0 1]
TESTS::
sage: T11.tensor_factors()
[Module X(M) of vector fields on the 2-dimensional differentiable manifold M,
Module Omega^1(M) of 1-forms on the 2-dimensional differentiable manifold M]
"""
Element = TensorField

def __init__(self, vector_field_module, tensor_type):
def __init__(self, vector_field_module, tensor_type, category=None):
r"""
Construct a module of tensor fields taking values on a (a priori) not
parallelizable differentiable manifold.
Expand Down Expand Up @@ -281,7 +291,8 @@ def __init__(self, vector_field_module, tensor_type):
# the member self._ring is created for efficiency (to avoid calls to
# self.base_ring()):
self._ring = domain.scalar_field_algebra()
Parent.__init__(self, base=self._ring, category=Modules(self._ring))
category = Modules(self._ring).TensorProducts().or_subcategory(category)
Parent.__init__(self, base=self._ring, category=category)
self._domain = domain
self._dest_map = dest_map
self._ambient_domain = vector_field_module._ambient_domain
Expand Down
87 changes: 80 additions & 7 deletions src/sage/manifolds/differentiable/vectorfield_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@
from sage.structure.parent import Parent
from sage.structure.unique_representation import UniqueRepresentation
from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule
from sage.tensor.modules.reflexive_module import ReflexiveModule_base

if TYPE_CHECKING:
from sage.manifolds.differentiable.diff_map import DiffMap
from sage.manifolds.differentiable.manifold import DifferentiableManifold


class VectorFieldModule(UniqueRepresentation, Parent):
class VectorFieldModule(UniqueRepresentation, ReflexiveModule_base):
r"""
Module of vector fields along a differentiable manifold `U`
with values on a differentiable manifold `M`, via a differentiable
Expand Down Expand Up @@ -731,8 +732,8 @@ def general_linear_group(self):
self._general_linear_group = AutomorphismFieldGroup(self)
return self._general_linear_group

def tensor(self, tensor_type, name=None, latex_name=None, sym=None,
antisym=None, specific_type=None):
def _tensor(self, tensor_type, name=None, latex_name=None, sym=None,
antisym=None, specific_type=None):
r"""
Construct a tensor on ``self``.
Expand Down Expand Up @@ -776,10 +777,6 @@ def tensor(self, tensor_type, name=None, latex_name=None, sym=None,
sage: XM.tensor((1,2), name='t')
Tensor field t of type (1,2) on the 2-dimensional differentiable
manifold M
sage: XM.tensor((1,0), name='a')
Vector field a on the 2-dimensional differentiable manifold M
sage: XM.tensor((0,2), name='a', antisym=(0,1))
2-form a on the 2-dimensional differentiable manifold M
.. SEEALSO::
Expand Down Expand Up @@ -824,6 +821,82 @@ def tensor(self, tensor_type, name=None, latex_name=None, sym=None,
self, tensor_type, name=name, latex_name=latex_name,
sym=sym, antisym=antisym)

def tensor(self, *args, **kwds):
r"""
Construct a tensor field on the domain of ``self`` or a tensor product of ``self`` with other modules.
If ``args`` consist of other parents, just delegate to :meth:`tensor_product`.
Otherwise, construct a tensor (i.e., a tensor field on the domain of
the vector field module) from the following input.
INPUT:
- ``tensor_type`` -- pair (k,l) with k being the contravariant rank
and l the covariant rank
- ``name`` -- (string; default: ``None``) name given to the tensor
- ``latex_name`` -- (string; default: ``None``) LaTeX symbol to denote
the tensor; if none is provided, the LaTeX symbol is set to ``name``
- ``sym`` -- (default: ``None``) a symmetry or a list of symmetries
among the tensor arguments: each symmetry is described by a tuple
containing the positions of the involved arguments, with the
convention position=0 for the first argument; for instance:
* ``sym=(0,1)`` for a symmetry between the 1st and 2nd arguments
* ``sym=[(0,2),(1,3,4)]`` for a symmetry between the 1st and 3rd
arguments and a symmetry between the 2nd, 4th and 5th arguments
- ``antisym`` -- (default: ``None``) antisymmetry or list of
antisymmetries among the arguments, with the same convention
as for ``sym``
- ``specific_type`` -- (default: ``None``) specific subclass of
:class:`~sage.manifolds.differentiable.tensorfield.TensorField` for
the output
OUTPUT:
- instance of
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
representing the tensor defined on the vector field module with the
provided characteristics
EXAMPLES::
sage: M = Manifold(2, 'M')
sage: XM = M.vector_field_module()
sage: XM.tensor((1,2), name='t')
Tensor field t of type (1,2) on the 2-dimensional differentiable
manifold M
sage: XM.tensor((1,0), name='a')
Vector field a on the 2-dimensional differentiable manifold M
sage: XM.tensor((0,2), name='a', antisym=(0,1))
2-form a on the 2-dimensional differentiable manifold M
Delegation to :meth:`tensor_product`::
sage: M = Manifold(2, 'M')
sage: XM = M.vector_field_module()
sage: XM.tensor(XM)
Module T^(2,0)(M) of type-(2,0) tensors fields on the 2-dimensional differentiable manifold M
sage: XM.tensor(XM, XM.dual(), XM)
Module T^(3,1)(M) of type-(3,1) tensors fields on the 2-dimensional differentiable manifold M
sage: XM.tensor(XM).tensor(XM.dual().tensor(XM.dual()))
Traceback (most recent call last):
...
AttributeError: 'TensorFieldModule_with_category' object has no attribute '_basis_sym'
.. SEEALSO::
:class:`~sage.manifolds.differentiable.tensorfield.TensorField`
for more examples and documentation.
"""
# Until https://trac.sagemath.org/ticket/30373 is done,
# TensorProductFunctor._functor_name is "tensor", so this method
# also needs to double as the tensor product construction
if isinstance(args[0], Parent):
return self.tensor_product(*args, **kwds)
return self._tensor(*args, **kwds)

def alternating_contravariant_tensor(self, degree, name=None,
latex_name=None):
r"""
Expand Down
Loading

0 comments on commit 4b9a500

Please sign in to comment.