Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
sage.tensor.modules.reflexive_module: New, refactor finite rank free …
Browse files Browse the repository at this point in the history
…modules and vector field modules through the new classes
  • Loading branch information
Matthias Koeppe committed Nov 12, 2022
1 parent 20bd0d3 commit 38e6b3e
Show file tree
Hide file tree
Showing 5 changed files with 298 additions and 254 deletions.
7 changes: 3 additions & 4 deletions src/sage/manifolds/differentiable/tensorfield_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,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 @@ -55,7 +56,7 @@
from sage.manifolds.differentiable.vectorfield_module import VectorFieldModule_abstract


class TensorFieldModule(VectorFieldModule_abstract):
class TensorFieldModule(ReflexiveModule_tensor, VectorFieldModule_abstract):
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 @@ -297,8 +298,6 @@ def __init__(self, vector_field_module, tensor_type, category=None):
self._dest_map = dest_map
self._ambient_domain = vector_field_module._ambient_domain

tensor_factors = TensorFreeModule.tensor_factors

#### Parent methods

def _element_constructor_(self, comp=[], frame=None, name=None,
Expand Down Expand Up @@ -601,7 +600,7 @@ def zero(self):

#***********************************************************************

class TensorFieldFreeModule(TensorFreeModule):
class TensorFieldFreeModule(TensorFreeModule, VectorFieldModule_abstract):
r"""
Free module of tensor fields of a given type `(k,l)` along a
differentiable manifold `U` with values on a parallelizable manifold `M`,
Expand Down
47 changes: 7 additions & 40 deletions src/sage/manifolds/differentiable/vectorfield_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,29 +53,24 @@
from sage.rings.integer import Integer
from sage.structure.parent import Parent
from sage.structure.unique_representation import UniqueRepresentation
from sage.tensor.modules.finite_rank_free_module import (
FiniteRankFreeModule_abstract,
FiniteRankFreeModule,
from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule
from sage.tensor.modules.reflexive_module import (
ReflexiveModule_abstract,
ReflexiveModule_base
)

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


class VectorFieldModule_abstract(UniqueRepresentation, Parent):
class VectorFieldModule_abstract(UniqueRepresentation, ReflexiveModule_abstract):
r"""
Abstract base class for modules of vector fields.
"""

tensor_power = FiniteRankFreeModule_abstract.tensor_power

tensor_product = FiniteRankFreeModule_abstract.tensor_product

tensor = FiniteRankFreeModule_abstract.tensor


class VectorFieldModule(VectorFieldModule_abstract):
class VectorFieldModule(ReflexiveModule_base, VectorFieldModule_abstract):
r"""
Module of vector fields along a differentiable manifold `U`
with values on a differentiable manifold `M`, via a differentiable
Expand Down Expand Up @@ -521,34 +516,6 @@ def destination_map(self):
"""
return self._dest_map

def base_module(self):
r"""
Return the module on which ``self`` is constructed, namely ``self`` itself.
EXAMPLES::
sage: M = Manifold(2, 'M')
sage: XM = M.vector_field_module()
sage: XM.base_module() is XM
True
"""
return self

def tensor_type(self):
r"""
Return the tensor type of ``self``, the pair `(1, 0)`.
EXAMPLES::
sage: M = Manifold(2, 'M')
sage: XM = M.vector_field_module()
sage: XM.tensor_type()
(1, 0)
"""
return (1, 0)

def tensor_module(self, k, l, *, sym=None, antisym=None):
r"""
Return the module of type-`(k,l)` tensors on ``self``.
Expand Down Expand Up @@ -1305,7 +1272,7 @@ def poisson_tensor(

#******************************************************************************

class VectorFieldFreeModule(FiniteRankFreeModule):
class VectorFieldFreeModule(FiniteRankFreeModule, VectorFieldModule_abstract):
r"""
Free module of vector fields along a differentiable manifold `U` with
values on a parallelizable manifold `M`, via a differentiable map
Expand Down
193 changes: 9 additions & 184 deletions src/sage/tensor/modules/finite_rank_free_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,8 +548,14 @@ class :class:`~sage.modules.free_module.FreeModule_generic`
from sage.tensor.modules.free_module_alt_form import FreeModuleAltForm
from sage.tensor.modules.free_module_element import FiniteRankFreeModuleElement
from sage.tensor.modules.free_module_tensor import FreeModuleTensor
from sage.tensor.modules.reflexive_module import (
ReflexiveModule_abstract,
ReflexiveModule_base,
ReflexiveModule_dual,
)

class FiniteRankFreeModule_abstract(UniqueRepresentation, Parent):

class FiniteRankFreeModule_abstract(UniqueRepresentation, ReflexiveModule_abstract):
r"""
Abstract base class for free modules of finite rank over a commutative ring.
"""
Expand Down Expand Up @@ -619,130 +625,6 @@ def _latex_(self):
else:
return self._latex_name

def tensor_power(self, n):
r"""
Return the ``n``-fold tensor product of ``self``.
EXAMPLES::
sage: M = FiniteRankFreeModule(QQ, 2)
sage: M.tensor_power(3)
Free module of type-(3,0) tensors on the 2-dimensional vector space over the Rational Field
sage: M.tensor_module(1,2).tensor_power(3)
Free module of type-(3,6) tensors on the 2-dimensional vector space over the Rational Field
"""
tensor_type = self.tensor_type()
return self.base_module().tensor_module(n * tensor_type[0], n * tensor_type[1])

def tensor_product(self, *others):
r"""
Return the tensor product of ``self`` and ``others``.
EXAMPLES::
sage: M = FiniteRankFreeModule(QQ, 2)
sage: M.tensor_product(M)
Free module of type-(2,0) tensors on the 2-dimensional vector space over the Rational Field
sage: M.tensor_product(M.dual())
Free module of type-(1,1) tensors on the 2-dimensional vector space over the Rational Field
sage: M.dual().tensor_product(M, M.dual())
Free module of type-(1,2) tensors on the 2-dimensional vector space over the Rational Field
sage: M.tensor_product(M.tensor_module(1,2))
Free module of type-(2,2) tensors on the 2-dimensional vector space over the Rational Field
sage: M.tensor_module(1,2).tensor_product(M)
Free module of type-(2,2) tensors on the 2-dimensional vector space over the Rational Field
sage: M.tensor_module(1,1).tensor_product(M.tensor_module(1,2))
Free module of type-(2,3) tensors on the 2-dimensional vector space over the Rational Field
sage: Sym2M = M.tensor_module(2, 0, sym=range(2)); Sym2M
Free module of fully symmetric type-(2,0) tensors on the 2-dimensional vector space over the Rational Field
sage: Sym01x23M = Sym2M.tensor_product(Sym2M); Sym01x23M
Free module of type-(4,0) tensors on the 2-dimensional vector space over the Rational Field,
with symmetry on the index positions (0, 1), with symmetry on the index positions (2, 3)
sage: Sym01x23M._index_maps
((0, 1), (2, 3))
sage: N = M.tensor_module(3, 3, sym=[1, 2], antisym=[3, 4]); N
Free module of type-(3,3) tensors on the 2-dimensional vector space over the Rational Field,
with symmetry on the index positions (1, 2),
with antisymmetry on the index positions (3, 4)
sage: NxN = N.tensor_product(N); NxN
Free module of type-(6,6) tensors on the 2-dimensional vector space over the Rational Field,
with symmetry on the index positions (1, 2), with symmetry on the index positions (4, 5),
with antisymmetry on the index positions (6, 7), with antisymmetry on the index positions (9, 10)
sage: NxN._index_maps
((0, 1, 2, 6, 7, 8), (3, 4, 5, 9, 10, 11))
"""
from sage.modules.free_module_element import vector
from .comp import CompFullySym, CompFullyAntiSym, CompWithSym

base_module = self.base_module()
if not all(module.base_module() == base_module for module in others):
raise NotImplementedError('all factors must be tensor modules over the same base module')
factors = [self] + list(others)
result_tensor_type = sum(vector(factor.tensor_type()) for factor in factors)
result_sym = []
result_antisym = []
# Keep track of reordering of the contravariant and covariant indices
# (compatible with FreeModuleTensor.__mul__)
index_maps = []
running_indices = vector([0, result_tensor_type[0]])
for factor in factors:
tensor_type = factor.tensor_type()
index_map = tuple(i + running_indices[0] for i in range(tensor_type[0]))
index_map += tuple(i + running_indices[1] for i in range(tensor_type[1]))
index_maps.append(index_map)

if tensor_type[0] + tensor_type[1] > 1:
basis_sym = factor._basis_sym()
all_indices = tuple(range(tensor_type[0] + tensor_type[1]))
if isinstance(basis_sym, CompFullySym):
sym = [all_indices]
antisym = []
elif isinstance(basis_sym, CompFullyAntiSym):
sym = []
antisym = [all_indices]
elif isinstance(basis_sym, CompWithSym):
sym = basis_sym._sym
antisym = basis_sym._antisym
else:
sym = antisym = []

def map_isym(isym):
return tuple(index_map[i] for i in isym)

result_sym.extend(tuple(index_map[i] for i in isym) for isym in sym)
result_antisym.extend(tuple(index_map[i] for i in isym) for isym in antisym)

running_indices += vector(tensor_type)

result = base_module.tensor_module(*result_tensor_type,
sym=result_sym, antisym=result_antisym)
result._index_maps = tuple(index_maps)
return result

def tensor(self, *args, **kwds):
# Until https://trac.sagemath.org/ticket/30373 is done,
# TensorProductFunctor._functor_name is "tensor", so here we delegate.
r"""
Return the tensor product of ``self`` and ``others``.
This method is invoked when :class:`~sage.categories.tensor.TensorProductFunctor`
is applied to parents.
It just delegates to :meth:`tensor_product`.
EXAMPLES::
sage: M = FiniteRankFreeModule(QQ, 2); M
2-dimensional vector space over the Rational Field
sage: M20 = M.tensor_module(2, 0); M20
Free module of type-(2,0) tensors on the 2-dimensional vector space over the Rational Field
sage: tensor([M20, M20])
Free module of type-(4,0) tensors on the 2-dimensional vector space over the Rational Field
"""
return self.tensor_product(*args, **kwds)

def rank(self) -> int:
r"""
Return the rank of the free module ``self``.
Expand Down Expand Up @@ -1092,7 +974,7 @@ def _test_isomorphism_with_fixed_basis(self, **options):
tester.assertEqual(morphism.codomain().rank(), self.rank())


class FiniteRankFreeModule(FiniteRankFreeModule_abstract):
class FiniteRankFreeModule(ReflexiveModule_base, FiniteRankFreeModule_abstract):
r"""
Free module of finite rank over a commutative ring.
Expand Down Expand Up @@ -3430,34 +3312,8 @@ def identity_map(self, name='Id', latex_name=None):
self._identity_map.set_name(name=name, latex_name=latex_name)
return self._identity_map

def base_module(self):
r"""
Return the free module on which ``self`` is constructed, namely ``self`` itself.
EXAMPLES::

sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: M.base_module() is M
True
"""
return self

def tensor_type(self):
r"""
Return the tensor type of ``self``, the pair `(1, 0)`.
EXAMPLES::
sage: M = FiniteRankFreeModule(ZZ, 3)
sage: M.tensor_type()
(1, 0)
"""
return (1, 0)


class FiniteRankDualFreeModule(FiniteRankFreeModule_abstract):
class FiniteRankDualFreeModule(ReflexiveModule_dual, FiniteRankFreeModule_abstract):
r"""
Dual of a free module of finite rank over a commutative ring.
Expand Down Expand Up @@ -3584,24 +3440,6 @@ def __init__(self, fmodule, name=None, latex_name=None):
latex_name=latex_name)
fmodule._all_modules.add(self)

def construction(self):
r"""
Return the functorial construction of ``self``.
This implementation just returns ``None``, as no functorial construction is implemented.
TESTS::
sage: from sage.tensor.modules.ext_pow_free_module import ExtPowerDualFreeModule
sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: A = M.dual()
sage: A.construction() is None
True
"""
# No construction until we extend VectorFunctor with a parameter 'dual'
return None

#### Parent methods

def _element_constructor_(self, comp=[], basis=None, name=None,
Expand Down Expand Up @@ -3736,16 +3574,3 @@ def base_module(self):
"""
return self._fmodule

def tensor_type(self):
r"""
Return the tensor type of ``self``.
EXAMPLES::
sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: M.dual().tensor_type()
(0, 1)
"""
return (0, 1)
Loading

0 comments on commit 38e6b3e

Please sign in to comment.