This code is supposed to be (if some one does the work in the future) located in **sage.tensor.differential_form_element**.

The code presented below is a slight modification of Joris code for differential forms manipulation on SAGE.

## Needed modules

from sage.symbolic.ring import SymbolicRing, SR from sage.rings.ring_element import RingElement from sage.algebras.algebra_element import AlgebraElement from sage.rings.integer import Integer from sage.combinat.permutation import Permutation

The advantage of using this is that, tensors defined here are an *Algebra* element, not just a python object as in the previous code.

The *sage.combinat.permutation* won’t be used (yet), but could be useful if tensor symmetries are defined.

#### TensorFormatter

class TensorFormatter: r""" This class contains all the functionality to print a tensor in a graphically pleasing way. This class is called by the ``_latex_`` and ``_repr_`` methods of the Tensor class. """ def __init__(self, space): r""" Construct a tensor formatter. See ``TensorFormatter`` for more information. """ self._space = space def repr(self, comp, fun): r""" String representation of a primitive tensor, i.e. a function times a tensor product of d's of the coordinate functions. INPUT: - ``comp`` -- a subscript of a differential form. - ``fun`` -- the component function of this form. EXAMPLES:: sage: from sage.tensor.tensor_element import TensorFormatter sage: x, y, z = var('x, y, z') sage: U = CoordinatePatch((x, y, z)) sage: D = TensorFormatter(U) sage: D.repr((0, 1), z^3) 'z^3*dx@dy' """ str = "@".join( \ [('d%s' % self._space.coordinate(c).__repr__()) for c in comp]) if fun == 1 and len(comp) > 0: # We have a non-trivial form whose component function is 1, # so we just return the formatted form part and ignore the 1. return str else: funstr = fun._repr_() if not self._is_atomic(funstr): funstr = '(' + funstr + ')' if len(str) > 0: return funstr + "*" + str else: return funstr def latex(self, comp, fun): r""" Latex representation of a primitive differential form, i.e. a function times a tensor product of d's of the coordinate functions. INPUT: - ``comp`` -- a subscript of a differential form. - ``fun`` -- the component function of this form. EXAMPLES:: sage: from sage.tensor.tensor_element import TensorFormatter sage: x, y, z = var('x, y, z') sage: U = CoordinatePatch((x, y, z)) sage: D = TensorFormatter(U) sage: D.latex((0, 1), z^3) 'z^{3} d x \otimes d y' """ from sage.misc.latex import latex str = " \otimes ".join( \ [('d %s' % latex(self._space.coordinate(c))) for c in comp]) if fun == 1 and len(comp) > 0: return str else: funstr = latex(fun) if not self._is_atomic(funstr): funstr = '(' + funstr + ')' return funstr + " " + str def _is_atomic(self, str): r""" Helper function to check whether a given string expression is atomic. EXAMPLES:: sage: x, y, z = var('x, y, z') sage: U = CoordinatePatch((x, y, z)) sage: from sage.tensor.tensor_element import TensorFormatter sage: D = TensorFormatter(U) sage: D._is_atomic('a + b') False sage: D._is_atomic('(a + b)') True """ level = 0 for n, c in enumerate(str): if c == '(': level += 1 elif c == ')': level -= 1 if c == '+' or c == '-': if level == 0 and n > 0: return False return True

The only I’ve changed here is “DifferentialForm” by “Tensor” and “\wedge” by “\otimes”

The above code allows to write the tensor product in a basis, . The chosen symbol for denoting the tensor product was @.

## Tensor Class

This code is incomplete due to:

class Tensor(AlgebraElement): r""" Tensor class. """ def __init__(self, parent, degree, fun = None): r""" Construct a tensor. INPUT: - ``parent`` -- Parent algebra of tensors. - ``degree`` -- Degree of the tensor. - ``fun`` (default: None) -- Initialize this differential form with the given function. If the degree is not zero, this argument is silently ignored. EXAMPLES:: sage: x, y, z = var('x, y, z') sage: F = Tensors(); F Algebra of tensors in the variables x, y, z sage: f = Tensor(F, 0, sin(z)); f sin(z) """ from sage.tensor.tensorss import Tensors if not isinstance(parent, Tensors): raise TypeError, "Parent not an algebra of tensors." RingElement.__init__(self, parent) self._degree = degree self._components = {} if degree == 0 and fun is not None: self.__setitem__([], fun) def __getitem__(self, subscript): r""" Return a given component of the tensor. INPUT: - ``subscript``: subscript of the component. Must be an integer or a list of integers. EXAMPLES:: sage: x, y, z = var('x, y, z') sage: F = Tensors(); F Algebra of tensors in the variables x, y, z sage: f = Tensor(F, 0, sin(x*y)); f sin(x*y) sage: f[()] sin(x*y) """ if isinstance(subscript, (Integer, int)): subscript = (subscript, ) else: subscript = tuple(subscript) dim = self.parent().base_space().dim() if any([s >= dim for s in subscript]): raise ValueError, "Index out of bounds." if len(subscript) != self._degree: raise TypeError, "%s is not a subscript of degree %s" %\ (subscript, self._degree) """sign, subscript = sort_subscript(subscript)""" if subscript in self._components: return sign*self._components[subscript] else: return 0 def __setitem__(self, subscript, fun): r""" Modify a given component of the tensor. INPUT: - ``subscript``: subscript of the component. Must be an integer or a list of integers. EXAMPLES:: sage: F = Tensors(); F Algebra of tensors in the variables x, y, z sage: f = Tensor(F, 2) sage: f[1, 2] = x; f x*dy@dz """ if isinstance(subscript, (Integer, int)): subscript = (subscript, ) else: subscript = tuple(subscript) dim = self.parent().base_space().dim() if any([s >= dim for s in subscript]): raise ValueError, "Index out of bounds." if len(subscript) != self._degree: raise TypeError, "%s is not a subscript of degree %s" %\ (subscript, self._degree) """sign, subscript = sort_subscript(subscript)""" self._components[subscript] = SR(fun)

Ok, so again I’ve changed “DifferentialForm(s)” by “Tensor(s)”, drop the permutation of indices (’cause tensors do not need to be neither symmetric nor anti-symmetric.

I’ll keep working with this code… It’s all by now. Oh! I’ll post next week the rest of the code based in Sergey’s GRPy.

Enjoy.

Dox