Ticket #9650: trac9650_differential_forms_v2.patch

File trac9650_differential_forms_v2.patch, 57.2 KB (added by jvkersch, 11 years ago)
  • doc/en/reference/index.rst

    # HG changeset patch
    # User Joris Vankerschaver <joris.vankerschaver@gmail.com>
    # Date 1283673022 -7200
    # Node ID 77cf8caa3554417432b47b0e674e0cd6df76edf5
    # Parent  5b338f2e484f2065d3d30d47bc204d6e9ed13d12
    #9650: Add support for differential forms
    
    diff -r 5b338f2e484f -r 77cf8caa3554 doc/en/reference/index.rst
    a b  
    9090   modfrm
    9191   modabvar
    9292   modmisc
     93   tensor
    9394
    9495   history_and_license
    9596
  • new file doc/en/reference/tensor.rst

    diff -r 5b338f2e484f -r 77cf8caa3554 doc/en/reference/tensor.rst
    - +  
     1Differential Forms
     2==================
     3
     4.. toctree::
     5   :maxdepth: 2
     6
     7   sage/tensor/coordinate_patch
     8   sage/tensor/differential_forms
     9   sage/tensor/differential_form_element
     10
  • sage/all.py

    diff -r 5b338f2e484f -r 77cf8caa3554 sage/all.py
    a b  
    138138from sage.ext.fast_callable  import fast_callable
    139139from sage.ext.fast_eval      import fast_float
    140140
     141from sage.tensor.all     import *
     142
    141143from copy import copy, deepcopy
    142144
    143145# The code executed here uses a large amount of Sage components
  • new file sage/tensor/__init__.py

    diff -r 5b338f2e484f -r 77cf8caa3554 sage/tensor/__init__.py
    - +  
     1# This comment is here so the file is non-empty (so Mercurial will check it in).
  • new file sage/tensor/all.py

    diff -r 5b338f2e484f -r 77cf8caa3554 sage/tensor/all.py
    - +  
     1from coordinate_patch import CoordinatePatch
     2from differential_forms import DifferentialForms
     3from differential_form_element import DifferentialForm, wedge
  • new file sage/tensor/coordinate_patch.py

    diff -r 5b338f2e484f -r 77cf8caa3554 sage/tensor/coordinate_patch.py
    - +  
     1r"""
     2Open subset of Euclidian space with coordinates.
     3
     4An open subset of Euclidian space with a specific set of coordinates.  This
     5is the background on which differential forms can be defined.
     6
     7AUTHORS:
     8
     9- Joris Vankerschaver (2010-07-25)
     10
     11EXAMPLES::
     12
     13    sage: x, y, z = var('x, y, z')
     14    sage: S = CoordinatePatch((x, y, z)); S
     15    Open subset of R^3 with coordinates x, y, z
     16
     17::
     18
     19    sage: u, v = var('u, v')
     20    sage: S = CoordinatePatch((u, v)); S
     21    Open subset of R^2 with coordinates u, v
     22
     23TODO:
     24
     25- Add functionality for metric tensors
     26
     27"""
     28
     29#*****************************************************************************
     30#    Copyright (C) 2010 Joris Vankerschaver <joris.vankerschaver@gmail.com>
     31#
     32#  Distributed under the terms of the GNU General Public License (GPL)
     33#
     34#    This code is distributed in the hope that it will be useful,
     35#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     36#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     37#    General Public License for more details.
     38#
     39#  The full text of the GPL is available at:
     40#
     41#                  http://www.gnu.org/licenses/
     42#*****************************************************************************
     43
     44
     45from sage.structure.parent import Parent
     46from sage.symbolic.ring import SR, var
     47
     48class CoordinatePatch(Parent):
     49    """
     50        Construct a coordinate patch, i.e. an open subset of
     51        Euclidian space with a given set of coordinates.
     52
     53        EXAMPLES::
     54
     55            sage: x, y, z = var('x, y, z')
     56            sage: S = CoordinatePatch((x, y, z)); S
     57            Open subset of R^3 with coordinates x, y, z
     58
     59            sage: u, v = var('u, v')
     60            sage: T = CoordinatePatch((u, v)); T
     61            Open subset of R^2 with coordinates u, v
     62            sage: loads(T.dumps()) == T
     63            True
     64
     65        In a future release, it will be possible to specify a
     66        metric tensor on a coordinate patch.  For now, providing
     67        any kind of metric raises an exception::
     68
     69            sage: x, y, z = var('x, y, z')
     70            sage: m = matrix(SR, 3)
     71            sage: S = CoordinatePatch((x, y, z), metric=m)
     72            Traceback (most recent call last):
     73            ...
     74            NotImplementedError: Metric geometry not supported yet.
     75
     76    """
     77    def __init__(self, coordinates, metric = None):
     78        """
     79        An open subset of Euclidian space with a specific set of
     80        coordinates. See ``CoordinatePatch`` for details.
     81
     82        INPUT::
     83
     84        - ``coordinates`` -- a set of symbolic variables that serve
     85        as coordinates on this space.
     86
     87        - ``metric`` (default: None) -- a metric tensor on this
     88        coordinate patch.  Providing anything other than ``None``
     89        is currently not defined.
     90
     91
     92        EXAMPLES::
     93       
     94            sage: x, y, z = var('x, y, z')
     95            sage: S = CoordinatePatch((x, y, z)); S
     96            Open subset of R^3 with coordinates x, y, z
     97
     98        """
     99
     100        from sage.symbolic.ring import is_SymbolicVariable
     101
     102        if not all(is_SymbolicVariable(c) for c in coordinates):
     103            raise TypeError, "%s is not a valid vector of coordinates." % \
     104                coordinates
     105
     106        self._coordinates = tuple(coordinates)
     107        dim = len(self._coordinates)
     108       
     109        if metric is not None:
     110            raise NotImplementedError, "Metric geometry not supported yet."
     111
     112
     113   
     114    def __cmp__(self, other):   
     115        """
     116        Compare self and other.  Return equality if and only if other
     117        has the same coordinates as self.
     118   
     119        EXAMPLES::
     120
     121            sage: x, y, z = var('x, y, z')
     122            sage: S = CoordinatePatch((x, y, z)); S
     123            Open subset of R^3 with coordinates x, y, z
     124            sage: u, v = var('u, v')
     125            sage: T = CoordinatePatch((u, v)); T
     126            Open subset of R^2 with coordinates u, v
     127            sage: U = CoordinatePatch((x, y, z)); U
     128            Open subset of R^3 with coordinates x, y, z
     129            sage: cmp(U, S)
     130            0
     131            sage: cmp(U, U)
     132            0
     133            sage: cmp(U, T)
     134            1
     135        """       
     136        return cmp(self._coordinates, other._coordinates)
     137       
     138       
     139    def coordinates(self):
     140        """
     141        Return coordinates on this coordinate patch.
     142       
     143        OUTPUT:
     144
     145        - list - a list of coordinates on this space.
     146 
     147        EXAMPLES::
     148
     149            sage: x, y, z = var('x, y, z')
     150            sage: S = CoordinatePatch((x, y, z)); S
     151            Open subset of R^3 with coordinates x, y, z
     152            sage: S.coordinates()
     153            (x, y, z)
     154       
     155        """
     156        return self._coordinates
     157
     158       
     159    def coordinate(self, i=0):
     160        """
     161        Return the `i^{th}` coordinate on ``self``
     162               
     163        INPUT:
     164
     165        - ``i`` - integer (optional, default 0)
     166
     167       
     168        EXAMPLES::
     169
     170            sage: x, y, z = var('x, y, z')
     171            sage: S = CoordinatePatch((x, y, z)); S
     172            Open subset of R^3 with coordinates x, y, z
     173            sage: S.coordinate(0)
     174            x
     175            sage: S.coordinate(1)
     176            y
     177            sage: S.coordinate(2)
     178            z
     179
     180        """
     181        return self._coordinates[i]
     182
     183   
     184    def dim(self):
     185        """
     186        Return the dimension of this coordinate patch, i.e. the dimension
     187        of the Euclidian space of which this coordinate patch is an open
     188        subset.
     189
     190        EXAMPLES::
     191
     192            sage: a, b, c, d, e = var('a, b, c, d, e')
     193            sage: U = CoordinatePatch((a, b, c, d, e)); U
     194            Open subset of R^5 with coordinates a, b, c, d, e
     195            sage: U.dim()
     196            5
     197        """
     198        return len(self._coordinates)   
     199
     200       
     201    def _repr_(self):
     202        r"""
     203        Return string representation of this coordinate patch.
     204
     205        EXAMPLES::
     206
     207            sage: x, y, z = var('x, y, z')
     208            sage: S = CoordinatePatch((x, y, z)); S
     209            Open subset of R^3 with coordinates x, y, z
     210            sage: S._repr_()
     211            'Open subset of R^3 with coordinates x, y, z'
     212            sage: S.rename('coordinate patch'); S
     213            coordinate patch
     214            sage: S.rename(); S
     215            Open subset of R^3 with coordinates x, y, z
     216        """
     217        return r"Open subset of R^%s with coordinates %s" % \
     218            (self.dim(), ', '.join([x._latex_() for x in self._coordinates]))
     219 
     220           
     221    def _latex_(self):
     222        r"""
     223        Return latex representation of this coordinate patch.
     224
     225        EXAMPLES::
     226       
     227            sage: x, y, z = var('x, y, z')
     228            sage: S = CoordinatePatch((x, y, z)); S
     229            Open subset of R^3 with coordinates x, y, z
     230            sage: latex(S)
     231            \mathbb{\RR}^3
     232            sage: latex(S) == S._latex_()
     233            True
     234        """
     235        return "\\mathbb{\RR}^%s" % self.dim()
     236
     237
  • new file sage/tensor/differential_form_element.py

    diff -r 5b338f2e484f -r 77cf8caa3554 sage/tensor/differential_form_element.py
    - +  
     1r"""
     2Elements of the algebra of differential forms.
     3
     4AUTHORS:
     5
     6- Joris Vankerschaver (2010-07-25)
     7
     8"""
     9
     10#*****************************************************************************
     11#  Copyright (C) 2010 Joris Vankerschaver <joris.vankerschaver@gmail.com>
     12#
     13#  Distributed under the terms of the GNU General Public License (GPL)
     14#
     15#    This code is distributed in the hope that it will be useful,
     16#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     17#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     18#    General Public License for more details.
     19#
     20#  The full text of the GPL is available at:
     21#
     22#                  http://www.gnu.org/licenses/
     23#*****************************************************************************
     24
     25
     26from sage.symbolic.ring import SymbolicRing, SR
     27from sage.rings.ring_element import RingElement
     28from sage.algebras.algebra_element import AlgebraElement
     29from sage.rings.integer import Integer
     30from sage.combinat.permutation import Permutation
     31
     32
     33def sort_subscript(subscript):
     34    """
     35    A subscript is a range of integers.  This function sorts a subscript
     36    in the sense of arranging it in ascending order.  The return values
     37    are the sign of the subscript and the sorted subscript, where the
     38    sign is defined as follows:
     39
     40    #. sign == 0 if two or more entries in the subscript were equal.
     41    #. sign == +1, -1 if a positive (resp. negative) permutation was used to sort the subscript.
     42
     43
     44    INPUT:
     45
     46    - ``subscript`` -- a subscript, i.e. a range of not necessarily
     47        distinct integers
     48
     49
     50    OUTPUT:
     51
     52    - Sign of the permutation used to arrange the subscript, where 0
     53        means that the original subscript had two or more entries that
     54        were the same
     55
     56    - Sorted subscript.
     57
     58
     59    EXAMPLES::
     60
     61        sage: from sage.tensor.differential_form_element import sort_subscript
     62        sage: sort_subscript((1, 3, 2))
     63        (-1, (1, 2, 3))
     64        sage: sort_subscript((1, 3))
     65        (1, (1, 3))
     66        sage: sort_subscript((4, 2, 7, 9, 8))
     67        (1, (2, 4, 7, 8, 9))
     68
     69    """
     70    if len(subscript) == 0:
     71        return 1, ()
     72       
     73    sub_list = list(subscript)
     74    sub_list.sort()
     75    offsets = [subscript.index(x)+1 for x in sub_list]
     76       
     77    # Check that offsets is a true permutation of 1..n
     78    n = len(offsets)
     79    if sum(offsets) != n*(n+1)/2:
     80        sign = 0
     81    else:
     82        sign = Permutation(offsets).signature()
     83   
     84    return sign, tuple(sub_list)       
     85
     86
     87
     88class DifferentialFormFormatter:
     89    r"""
     90    This class contains all the functionality to print a differential form in a
     91    graphically pleasing way.  This class is called by the ``_latex_`` and
     92    ``_repr_`` methods of the DifferentialForm class.
     93
     94    In a nutshell (see the documentation of ``DifferentialForm`` for more
     95    details), differential forms are represented internally as a dictionary,
     96    where the keys are tuples representing the non-zero components of the
     97    form and the values are the component functions.  The methods of this
     98    class create string and latex representations out of the specification
     99    of a subscript and a component function.
     100
     101
     102    EXAMPLES::
     103
     104        sage: from sage.tensor.differential_form_element import DifferentialFormFormatter
     105        sage: x, y, z = var('x, y, z')
     106        sage: U = CoordinatePatch((x, y, z))
     107        sage: D = DifferentialFormFormatter(U)
     108        sage: D.repr((0, 2), sin(x*y))
     109        'sin(x*y)*dx/\\dz'
     110        sage: D.latex((0, 2), sin(x*y))
     111        '\\sin\\left(x y\\right) d x \\wedge d z'
     112        sage: D.latex((1, 2), exp(z))
     113        'e^{z} d y \\wedge d z'
     114
     115    """
     116    def __init__(self, space):
     117        r"""
     118        Construct a differential form formatter.  See
     119        ``DifferentialFormFormatter`` for more information.
     120
     121        INPUT:
     122
     123        - space -- CoordinatePatch where the differential forms live.
     124
     125        EXAMPLES::
     126
     127            sage: from sage.tensor.differential_form_element import DifferentialFormFormatter
     128            sage: x, y, z = var('x, y, z')
     129            sage: U = CoordinatePatch((x, y, z))
     130            sage: D = DifferentialFormFormatter(U)
     131            sage: D.repr((0, 2), sin(x*y))
     132            'sin(x*y)*dx/\\dz'
     133
     134        """
     135        self._space = space
     136     
     137
     138    def repr(self, comp, fun):
     139        r"""
     140        String representation of a primitive differential form, i.e. a function
     141        times a wedge product of d's of the coordinate functions.
     142
     143        INPUT:
     144
     145        - ``comp`` -- a subscript of a differential form.
     146
     147        - ``fun`` -- the component function of this form.
     148
     149
     150        EXAMPLES::
     151
     152            sage: from sage.tensor.differential_form_element import DifferentialFormFormatter
     153            sage: x, y, z = var('x, y, z')
     154            sage: U = CoordinatePatch((x, y, z))
     155            sage: D = DifferentialFormFormatter(U)
     156            sage: D.repr((0, 1), z^3)
     157            'z^3*dx/\\dy'
     158
     159        """
     160
     161        str = "/\\".join( \
     162            [('d%s' % self._space.coordinate(c).__repr__()) for c in comp])
     163             
     164        if fun == 1 and len(comp) > 0:
     165            # We have a non-trivial form whose component function is 1,
     166            # so we just return the formatted form part and ignore the 1.
     167            return str
     168        else:
     169            funstr = fun._repr_()
     170           
     171            if not self._is_atomic(funstr):
     172                funstr = '(' + funstr + ')'
     173           
     174            if len(str) > 0:
     175                return funstr + "*" + str
     176            else:
     177                return funstr
     178     
     179             
     180    def latex(self, comp, fun):
     181        r"""
     182        Latex representation of a primitive differential form, i.e. a function
     183        times a wedge product of d's of the coordinate functions.
     184
     185        INPUT:
     186
     187        - ``comp`` -- a subscript of a differential form.
     188
     189        - ``fun`` -- the component function of this form.
     190
     191        EXAMPLES::
     192
     193            sage: from sage.tensor.differential_form_element import DifferentialFormFormatter
     194            sage: x, y, z = var('x, y, z')
     195            sage: U = CoordinatePatch((x, y, z))
     196            sage: D = DifferentialFormFormatter(U)
     197            sage: D.latex((0, 1), z^3)
     198            'z^{3} d x \\wedge d y'
     199
     200        """
     201
     202        from sage.misc.latex import latex
     203
     204        str = " \\wedge ".join( \
     205            [('d %s' % latex(self._space.coordinate(c))) for c in comp])
     206         
     207        if fun == 1 and len(comp) > 0:
     208            return str
     209        else:
     210            funstr = latex(fun)
     211           
     212            if not self._is_atomic(funstr):
     213                funstr = '(' + funstr + ')'
     214           
     215            return funstr + " " + str
     216       
     217       
     218    def _is_atomic(self, str):
     219        r"""
     220        Helper function to check whether a given string expression
     221        is atomic.
     222
     223        EXAMPLES::
     224
     225            sage: x, y, z = var('x, y, z')
     226            sage: U = CoordinatePatch((x, y, z))
     227            sage: from sage.tensor.differential_form_element import DifferentialFormFormatter
     228            sage: D = DifferentialFormFormatter(U)
     229            sage: D._is_atomic('a + b')
     230            False
     231            sage: D._is_atomic('(a + b)')
     232            True
     233        """
     234        level = 0
     235        for n, c in enumerate(str):
     236            if c == '(':
     237                level += 1
     238            elif c == ')':
     239                level -= 1
     240               
     241            if c == '+' or c == '-':
     242                if level == 0 and n > 0:
     243                    return False
     244        return True
     245
     246
     247
     248class DifferentialForm(AlgebraElement):
     249    r"""
     250    Differential form class.
     251
     252    EXAMPLES:
     253
     254    In order to instantiate differential forms of various degree, we begin
     255    by specifying the CoordinatePatch on which they live, as well as their
     256    parent DifferentialForms algebra.
     257
     258    ::
     259
     260        sage: x, y, z = var('x, y, z')
     261        sage: U = CoordinatePatch((x, y, z))
     262        sage: F = DifferentialForms(U)
     263        sage: form1 = DifferentialForm(F, 0, sin(x*y)); form1
     264        sin(x*y)
     265
     266    In the previous example, we created a zero-form from a given function.
     267    To create forms of higher degree, we can use the subscript operator
     268    access the various components::
     269
     270        sage: form2 = DifferentialForm(F, 1); form2
     271        0
     272        sage: form2[0] = 1
     273        sage: form2[1] = exp(cos(x))
     274        sage: form2[2] = 1/ln(y)
     275        sage: form2
     276        1/log(y)*dz + dx + e^cos(x)*dy
     277
     278    We may calculate the exterior derivative of a form, and observe that
     279    applying the exterior derivative twice always yields zero::
     280
     281        sage: dform = form1.diff(); dform
     282        y*cos(x*y)*dx + x*cos(x*y)*dy
     283        sage: dform.diff()
     284        0
     285
     286    As can be seen from the previous example, the exterior derivative
     287    increases the degree of a form by one::
     288
     289        sage: form2.degree()
     290        1
     291        sage: form2.diff().degree()
     292        2
     293
     294    The ``d`` function provides a convenient shorthand for applying the
     295    diff member function.  Since d appears in other areas of mathematics
     296    as well, this function is not imported in the global namespace
     297    automatically::
     298
     299        sage: from sage.tensor.differential_form_element import d
     300        sage: form2
     301        1/log(y)*dz + dx + e^cos(x)*dy
     302        sage: d(form2)
     303        -(1/y)/log(y)^2*dy/\dz + -e^cos(x)*sin(x)*dx/\dy
     304        sage: form2.diff()
     305        -(1/y)/log(y)^2*dy/\dz + -e^cos(x)*sin(x)*dx/\dy
     306        sage: d(form1) == form1.diff()
     307        True
     308
     309    The wedge product of two forms can be computed by means of the wedge
     310    member function::
     311
     312        sage: form1 = DifferentialForm(F, 2)
     313        sage: form1[0, 1] = exp(z); form1
     314        e^z*dx/\dy
     315        sage: form2 = DifferentialForm(F, 1)
     316        sage: form2[2] = exp(-z)
     317        sage: form1.wedge(form2)
     318        dx/\dy/\dz
     319
     320    For this member function, there exists again a procedural function
     321    which is completely equivalent::
     322
     323        sage: from sage.tensor.differential_form_element import wedge
     324        sage: form1.wedge(form2)
     325        dx/\dy/\dz
     326        sage: wedge(form1, form2)
     327        dx/\dy/\dz
     328        sage: form1.wedge(form2) == wedge(form1, form2)
     329        True
     330
     331
     332    NOTES:
     333
     334        Differential forms are stored behind the screens as dictionaries,
     335        where the keys are the subscripts of the non-zero components, and
     336        the values are those components. 
     337
     338        For example, on a
     339        space with coordinates x, y, z, the form
     340
     341            f = sin(x*y) dx /\\ dy + exp(z) dy /\\ dz
     342
     343        would be represented as the dictionary
     344
     345            {(0, 1): sin(x*y), (1, 2): exp(z)}.
     346   
     347        Most differential forms are ''sparse'' in the sense that most of
     348        their components are zero, so that this representation is more
     349        efficient than storing all of the components in a vector.
     350
     351    """
     352
     353    def __init__(self, parent, degree, fun = None):
     354        r"""
     355        Construct a differential form.
     356
     357        INPUT:
     358
     359        - ``parent`` -- Parent algebra of differential forms.
     360
     361        - ``degree`` -- Degree of the differential form.
     362
     363        - ``fun`` (default: None) -- Initialize this differential form with the given function.  If the degree is not zero, this argument is silently ignored.
     364
     365        EXAMPLES::
     366
     367            sage: x, y, z = var('x, y, z')
     368            sage: F = DifferentialForms(); F
     369            Algebra of differential forms in the variables x, y, z
     370            sage: f = DifferentialForm(F, 0, sin(z)); f
     371            sin(z)
     372
     373        """
     374
     375        from sage.tensor.differential_forms import DifferentialForms
     376        if not isinstance(parent, DifferentialForms):
     377            raise TypeError, "Parent not an algebra of differential forms."
     378
     379        RingElement.__init__(self, parent)
     380
     381        self._degree = degree
     382        self._components = {}
     383
     384        if degree == 0 and fun is not None:
     385            self.__setitem__([], fun)
     386
     387
     388    def __getitem__(self, subscript):
     389        r"""
     390        Return a given component of the differential form.
     391
     392        INPUT:
     393
     394        - ``subscript``: subscript of the component.  Must be an integer
     395        or a list of integers.
     396
     397
     398        EXAMPLES::
     399
     400            sage: x, y, z = var('x, y, z')
     401            sage: F = DifferentialForms(); F
     402            Algebra of differential forms in the variables x, y, z
     403            sage: f = DifferentialForm(F, 0, sin(x*y)); f
     404            sin(x*y)
     405            sage: f[()]
     406            sin(x*y)
     407
     408            sage: df = f.diff(); df
     409            y*cos(x*y)*dx + x*cos(x*y)*dy
     410            sage: df[0]
     411            y*cos(x*y)
     412            sage: df[1]
     413            x*cos(x*y)
     414            sage: df[2]
     415            0
     416        """
     417
     418        if isinstance(subscript, (Integer, int)):
     419            subscript = (subscript, )
     420        else:
     421            subscript = tuple(subscript)
     422
     423        dim = self.parent().base_space().dim()
     424        if any([s >= dim for s in subscript]):
     425            raise ValueError, "Index out of bounds."
     426
     427        if len(subscript) != self._degree:
     428            raise TypeError, "%s is not a subscript of degree %s" %\
     429                (subscript, self._degree)
     430       
     431        sign, subscript = sort_subscript(subscript)
     432
     433        if subscript in self._components:
     434            return sign*self._components[subscript]
     435        else:
     436            return 0
     437
     438
     439    def __setitem__(self, subscript, fun): 
     440        r"""
     441        Modify a given component of the differential form.
     442
     443        INPUT:
     444
     445        - ``subscript``: subscript of the component.  Must be an integer or a list of integers.
     446
     447        EXAMPLES::
     448
     449            sage: F = DifferentialForms(); F
     450            Algebra of differential forms in the variables x, y, z
     451            sage: f = DifferentialForm(F, 2)
     452            sage: f[1, 2] = x; f
     453            x*dy/\dz
     454        """
     455
     456        if isinstance(subscript, (Integer, int)):
     457            subscript = (subscript, )
     458        else:
     459            subscript = tuple(subscript)
     460
     461        dim = self.parent().base_space().dim()
     462        if any([s >= dim for s in subscript]):
     463            raise ValueError, "Index out of bounds."
     464
     465        if len(subscript) != self._degree:
     466            raise TypeError, "%s is not a subscript of degree %s" %\
     467                (subscript, self._degree)
     468
     469        sign, subscript = sort_subscript(subscript)
     470        self._components[subscript] = sign*SR(fun)
     471
     472
     473    def is_zero(self):
     474        r"""
     475        Return True if ``self`` is the zero form.
     476
     477        EXAMPLES::
     478
     479            sage: F = DifferentialForms()
     480            sage: f = DifferentialForm(F, 1); f
     481            0
     482            sage: f.is_zero()
     483            True
     484            sage: f[1] = 1
     485            sage: f.is_zero()
     486            False
     487            sage: f.diff()
     488            0
     489            sage: f.diff().is_zero()
     490            True
     491        """
     492
     493        self._cleanup()
     494        return len(self._components) == 0
     495   
     496       
     497    def degree(self):
     498        r"""
     499        Return the degree of self.
     500
     501        EXAMPLES::
     502
     503            sage: F = DifferentialForms(); F
     504            Algebra of differential forms in the variables x, y, z
     505            sage: f = DifferentialForm(F, 2)
     506            sage: f[1, 2] = x; f
     507            x*dy/\dz
     508            sage: f.degree()
     509            2
     510
     511        The exterior differential increases the degree of forms by one::
     512
     513            sage: g = f.diff(); g
     514            dx/\dy/\dz
     515            sage: g.degree()
     516            3
     517        """
     518        return self._degree
     519   
     520   
     521    def __eq__(self, other):
     522        r"""
     523        Test whether two differential forms are equal.
     524
     525        EXAMPLES::
     526
     527            sage: F = DifferentialForms(); F
     528            Algebra of differential forms in the variables x, y, z
     529            sage: f = DifferentialForm(F, 2)
     530            sage: f[1,2] = x; f
     531            x*dy/\dz
     532            sage: f == f
     533            True
     534
     535            sage: g = DifferentialForm(F, 3)
     536            sage: g[0, 1, 2] = 1; g
     537            dx/\dy/\dz
     538            sage: f == g
     539            False
     540            sage: f.diff() == g
     541            True
     542        """
     543        if type(other) == type(self):
     544            return self.__dict__ == other.__dict__
     545        return False
     546       
     547   
     548    #def __ne__(self, other):
     549    #    return not self.__eq__(other)
     550
     551
     552    def _neg_(self):
     553        r"""
     554        Return the negative of self.
     555
     556        EXAMPLES::
     557
     558            sage: x, y, z = var('x, y, z')
     559            sage: F = DifferentialForms()
     560            sage: f = DifferentialForm(F, 1)
     561            sage: f[0] = y
     562            sage: f[1] = -x
     563            sage: f
     564            y*dx + -x*dy
     565            sage: -f
     566            -y*dx + x*dy
     567            sage: -f == f._neg_()
     568            True
     569        """
     570
     571        neg = DifferentialForm(self.parent(), self._degree)
     572        for comp in self._components:
     573            neg._components[comp] = -self._components[comp]
     574        return neg
     575
     576   
     577    def _add_(self, other):
     578        r"""
     579        Add self and other
     580
     581        EXAMPLES::
     582
     583            sage: x, y, z = var('x, y, z')
     584            sage: F = DifferentialForms()
     585            sage: f = DifferentialForm(F, 1)
     586            sage: g = DifferentialForm(F, 1)
     587            sage: f[0] = exp(x); f
     588            e^x*dx
     589            sage: g[1] = sin(y); g
     590            sin(y)*dy
     591            sage: f + g
     592            e^x*dx + sin(y)*dy
     593            sage: f + g == f._add_(g)
     594            True
     595
     596        Forms must have the same degree to be added::
     597
     598            sage: h = DifferentialForm(F, 2)
     599            sage: h[1, 2] = x; h
     600            x*dy/\dz
     601            sage: f + h
     602            Traceback (most recent call last):
     603            ...
     604            TypeError: Cannot add forms of degree 1 and 2
     605
     606        """
     607
     608        if self.is_zero():
     609            return other
     610        if other.is_zero():
     611            return self
     612
     613        if self._degree != other._degree:
     614            raise TypeError, \
     615                "Cannot add forms of degree %s and %s" % \
     616                    (self._degree, other._degree)
     617               
     618        sumform = DifferentialForm(self.parent(), self._degree)
     619        sumform._components = self._components.copy()
     620        for comp, fun in other._components.items():
     621            sumform[comp] += fun
     622       
     623        sumform._cleanup()   
     624        return sumform
     625
     626
     627    def _sub_(self, other):
     628        r"""
     629        Subtract other from self.
     630
     631        EXAMPLES::
     632
     633            sage: x, y, z = var('x, y, z')
     634            sage: F = DifferentialForms()
     635            sage: f = DifferentialForm(F, 1)
     636            sage: g = DifferentialForm(F, 1)
     637            sage: f[0] = exp(x); f
     638            e^x*dx
     639            sage: g[1] = sin(y); g
     640            sin(y)*dy
     641            sage: f - g
     642            e^x*dx + -sin(y)*dy
     643            sage: f - g == f._sub_(g)
     644            True
     645
     646        Forms must have the same degree to be subtracted::
     647           
     648            sage: h = DifferentialForm(F, 2)
     649            sage: h[1, 2] = x; h
     650            x*dy/\dz
     651            sage: f - h
     652            Traceback (most recent call last):
     653            ...
     654            TypeError: Cannot add forms of degree 1 and 2
     655
     656        """
     657        return self._add_(-other)
     658
     659
     660    def _cleanup(self):
     661        r"""
     662        Helper function to clean up self, i.e. to remove any
     663        zero components from the dictionary of components.
     664
     665        EXAMPLES::
     666
     667            sage: F = DifferentialForms()
     668            sage: f = DifferentialForm(F, 1)
     669            sage: f[0] = 0
     670            sage: f[1] = 1
     671            sage: f[2] = 0
     672            sage: f._dump_all()
     673            {(2,): 0, (0,): 0, (1,): 1}
     674            sage: f._cleanup()
     675            sage: f._dump_all()
     676            {(1,): 1}
     677
     678        """
     679        zeros = []
     680       
     681        for comp in self._components:
     682            if self._components[comp] == 0:
     683                zeros.append(comp)
     684               
     685        for comp in zeros: 
     686            del self._components[comp]     
     687
     688           
     689    def _dump_all(self):
     690        r"""
     691        Helper function to dump the internal dictionary of form components.
     692
     693        EXAMPLES::
     694
     695            sage: x, y, z = var('x, y, z')
     696            sage: F = DifferentialForms()
     697            sage: f = DifferentialForm(F, 1)
     698            sage: f[1] = exp(cos(x))
     699            sage: f[2] = sin(ln(y))
     700            sage: f
     701            sin(log(y))*dz + e^cos(x)*dy
     702            sage: f._dump_all()
     703            {(2,): sin(log(y)), (1,): e^cos(x)}
     704            sage: g = DifferentialForm(F, 2)
     705            sage: g[1, 2] = x+y+z
     706            sage: g
     707            (x + y + z)*dy/\dz
     708            sage: g._dump_all()
     709            {(1, 2): x + y + z}
     710
     711        """
     712        print self._components
     713   
     714
     715    def diff(self):
     716        r"""
     717        Compute the exterior differential of ``self``.
     718
     719        EXAMPLES::
     720
     721            sage: x, y, z = var('x, y, z')
     722            sage: F = DifferentialForms()
     723            sage: f = DifferentialForm(F, 0, sin(x*y)); f
     724            sin(x*y)
     725            sage: f.diff()
     726            y*cos(x*y)*dx + x*cos(x*y)*dy
     727            sage: g = DifferentialForm(F, 1)
     728            sage: g[0] = y/2
     729            sage: g[1] = -x/2
     730            sage: g
     731            1/2*y*dx + -1/2*x*dy
     732            sage: g.diff()
     733            -1*dx/\dy
     734            sage: h = DifferentialForm(F, 2)
     735            sage: h[0, 1] = exp(z)
     736            sage: h.diff()
     737            e^z*dx/\dy/\dz
     738
     739        The square of the exterior differential operator is
     740        identically zero::
     741
     742            sage: f
     743            sin(x*y)
     744            sage: f.diff()
     745            y*cos(x*y)*dx + x*cos(x*y)*dy
     746            sage: f.diff().diff()
     747            0
     748
     749            sage: g.diff().diff()
     750            0
     751
     752        The exterior differential operator is a derivation of degree one
     753        on the space of differential forms.  In this example we import the
     754        operator d() as a short-hand for having to call the diff()
     755        member function.
     756
     757        ::
     758
     759            sage: from sage.tensor.differential_form_element import d
     760            sage: d(f)
     761            y*cos(x*y)*dx + x*cos(x*y)*dy
     762
     763            sage: d(f).wedge(g) + f.wedge(d(g))
     764            (-x*y*cos(x*y) - sin(x*y))*dx/\dy
     765            sage: d(f.wedge(g))
     766            (-x*y*cos(x*y) - sin(x*y))*dx/\dy
     767
     768            sage: d(f.wedge(g)) == d(f).wedge(g) + f.wedge(d(g))
     769            True
     770        """
     771
     772        diff_form = DifferentialForm(self.parent(), self._degree + 1)
     773       
     774        for comp in self._components:
     775            fun = self._components[comp]
     776            for n, coord in enumerate(self.parent().base_space().coordinates()):
     777                diff_form[(n, ) + comp] += fun.differentiate(coord)
     778               
     779        diff_form._cleanup()       
     780        return diff_form
     781
     782
     783    def derivative(self, *args, **kwargs):
     784        r"""
     785        Compute the exterior derivative of ``self``.  This is the same as
     786        calling the ``diff`` member function.
     787
     788
     789        EXAMPLES::
     790
     791            sage: x, y = var('x, y')
     792            sage: U = CoordinatePatch((x, y))
     793            sage: F = DifferentialForms(U)
     794            sage: q = DifferentialForm(F, 1)
     795            sage: q[0] = -y/2
     796            sage: q[1] =  x/2
     797            sage: q.diff()
     798            dx/\dy
     799            sage: q.derivative()
     800            dx/\dy
     801
     802        Invoking ``diff`` on a differential form has the same effect as
     803        calling this member function::
     804
     805            sage: diff(q)
     806            dx/\dy
     807            sage: diff(q) == q.derivative()
     808            True
     809
     810        When additional arguments are supplied to ``diff``, an error is raised,
     811        since only the exterior derivative has intrinsic meaning while
     812        derivatives with respect to the coordinate variables (in whichever
     813        way) are coordinate dependent, and hence not intrinsic.
     814
     815        ::
     816
     817            sage: diff(q, x)
     818            Traceback (most recent call last):
     819            ...
     820            ValueError: Differentiation of a form does not take any arguments.
     821        """
     822
     823        if len(args) > 0 or len(kwargs) > 0:
     824            raise ValueError, "Differentiation of a form does not take any arguments."
     825        return self.diff()
     826
     827
     828    def wedge(self, other):
     829        r"""
     830        Returns the wedge product of ``self`` and other.
     831
     832        EXAMPLES::
     833
     834            sage: x, y, z = var('x, y, z')
     835            sage: F = DifferentialForms()
     836            sage: f = DifferentialForm(F, 1)
     837            sage: f[0] = x^2
     838            sage: f[1] = y
     839            sage: f
     840            x^2*dx + y*dy
     841            sage: g = DifferentialForm(F, 1)
     842            sage: g[2] = z^3
     843            sage: g
     844            z^3*dz
     845            sage: f.wedge(g)
     846            y*z^3*dy/\dz + x^2*z^3*dx/\dz
     847
     848        The wedge product is graded commutative::
     849
     850            sage: f.wedge(g)
     851            y*z^3*dy/\dz + x^2*z^3*dx/\dz
     852            sage: g.wedge(f)
     853            -y*z^3*dy/\dz + -x^2*z^3*dx/\dz
     854            sage: f.wedge(f)
     855            0
     856
     857        When the wedge product of forms belonging to different algebras
     858        is computed, an error is raised::
     859
     860            sage: x, y, p, q = var('x, y, p, q')
     861            sage: F = DifferentialForms(CoordinatePatch((x, y)))
     862            sage: G = DifferentialForms(CoordinatePatch((p, q)))
     863            sage: f = DifferentialForm(F, 0, 1); f
     864            1
     865            sage: g = DifferentialForm(G, 0, x); g
     866            x
     867            sage: f.parent()
     868            Algebra of differential forms in the variables x, y
     869            sage: g.parent()
     870            Algebra of differential forms in the variables p, q
     871            sage: f.wedge(g)
     872            Traceback (most recent call last):
     873            ...
     874            TypeError: unsupported operand parents for wedge: 'Algebra of differential forms in the variables x, y' and  'Algebra of differential forms in the variables p, q'
     875
     876        """
     877
     878        if self.parent() != other.parent():
     879            raise TypeError, "unsupported operand parents for wedge: " +\
     880                "\'%s\' and  \'%s\'" % (self.parent(), other.parent())
     881           
     882        output = DifferentialForm(self.parent(), self._degree + other._degree)
     883        if self._degree + other._degree > self.parent().ngens():
     884            return output
     885           
     886        for lcomp, lfun in self._components.items():
     887            for rcomp, rfun in other._components.items():
     888                output[lcomp + rcomp] += lfun*rfun
     889               
     890        output._cleanup()       
     891        return output
     892
     893
     894   
     895    def _mul_(self, other):
     896        r"""
     897        Multiply self and other.  This is identical to the wedge operator.
     898
     899        EXAMPLES::
     900
     901            sage: x, y, z = var('x, y, z')
     902            sage: F = DifferentialForms()
     903            sage: f = F.gen(0); f
     904            dx
     905            sage: g = F.gen(1); g
     906            dy
     907            sage: f*g
     908            dx/\dy
     909            sage: f.wedge(g)
     910            dx/\dy
     911            sage: f*g == f.wedge(g)
     912            True
     913            sage: f*g == f._mul_(g)
     914            True
     915
     916        """
     917        return self.wedge(other)
     918
     919           
     920    def _latex_(self):
     921        r"""
     922        Return a latex representation of self.
     923
     924        EXAMPLES::
     925
     926            sage: x, y, z = var('x, y, z')
     927            sage: F = DifferentialForms()
     928            sage: f = DifferentialForm(F, 1)
     929            sage: f[1] = exp(z); f
     930            e^z*dy
     931            sage: latex(f)
     932            e^{z} d y
     933            sage: g = f.diff(); g
     934            -e^z*dy/\dz
     935            sage: latex(g)
     936            -e^{z} d y \wedge d z
     937            sage: latex(g) == g._latex_()
     938            True
     939
     940        """
     941        if len(self._components) == 0:
     942            return '0'
     943       
     944        format = DifferentialFormFormatter(self.parent().base_space())
     945        output = [format.latex(comp, fun) \
     946                      for (comp, fun) in self._components.items()]
     947        return ' + '.join(output)
     948
     949
     950    def _repr_(self):
     951        r"""
     952        Return string representation of self.
     953
     954        EXAMPLES::
     955
     956            sage: x, y, z = var('x, y, z')
     957            sage: F = DifferentialForms()
     958            sage: f = DifferentialForm(F, 1)
     959            sage: f[1] = exp(z); f
     960            e^z*dy
     961            sage: print f
     962            e^z*dy
     963            sage: f._repr_()
     964            'e^z*dy'
     965        """
     966        if len(self._components) == 0:
     967            return '0'
     968       
     969        format = DifferentialFormFormatter(self.parent().base_space())
     970        output = [format.repr(comp, fun) \
     971                      for (comp, fun) in self._components.items()]
     972        return ' + '.join(output)
     973
     974
     975
     976    # Unsupported methods
     977
     978    def abs(self):
     979        """
     980        Method not defined for differential forms.
     981
     982        EXAMPLES::
     983            sage: F = DifferentialForms()
     984            sage: f = DifferentialForm(F, 1)
     985            sage: f.abs()
     986            Traceback (most recent call last):
     987            ...
     988            NotImplementedError: Absolute value not defined for differential forms.
     989
     990        """
     991        raise NotImplementedError, "Absolute value not defined for differential forms."
     992
     993
     994    def leading_coefficient(self, cmp=None):
     995        """
     996        Method not defined for differential forms.
     997
     998        EXAMPLES::
     999            sage: F = DifferentialForms()
     1000            sage: f = DifferentialForm(F, 1)
     1001            sage: f.leading_coefficient()
     1002            Traceback (most recent call last):
     1003            ...
     1004            NotImplementedError: leading_coefficient not defined for differential forms.
     1005
     1006        """
     1007        raise NotImplementedError, "leading_coefficient not defined for differential forms."
     1008
     1009
     1010    def leading_item(self, cmp=None):
     1011        """
     1012        Method not defined for differential forms.
     1013
     1014        EXAMPLES::
     1015            sage: F = DifferentialForms()
     1016            sage: f = DifferentialForm(F, 1)
     1017            sage: f.leading_item()
     1018            Traceback (most recent call last):
     1019            ...
     1020            NotImplementedError: leading_item not defined for differential forms.
     1021
     1022        """
     1023        raise NotImplementedError, "leading_item not defined for differential forms."
     1024
     1025
     1026    def leading_monomial(self, cmp=None):
     1027        """
     1028        Method not defined for differential forms.
     1029
     1030        EXAMPLES::
     1031            sage: F = DifferentialForms()
     1032            sage: f = DifferentialForm(F, 1)
     1033            sage: f.leading_monomial()
     1034            Traceback (most recent call last):
     1035            ...
     1036            NotImplementedError: leading_monomial not defined for differential forms.
     1037
     1038        """
     1039        raise NotImplementedError, "leading_monomial not defined for differential forms."     
     1040
     1041
     1042    def leading_support(self, cmp=None):
     1043        """
     1044        Method not defined for differential forms.
     1045
     1046        EXAMPLES::
     1047            sage: F = DifferentialForms()
     1048            sage: f = DifferentialForm(F, 1)
     1049            sage: f.leading_support()
     1050            Traceback (most recent call last):
     1051            ...
     1052            NotImplementedError: leading_support not defined for differential forms.
     1053
     1054        """
     1055        raise NotImplementedError, "leading_support not defined for differential forms."     
     1056
     1057
     1058    def leading_term(self, cmp=None):
     1059        """
     1060        Method not defined for differential forms.
     1061
     1062        EXAMPLES::
     1063            sage: F = DifferentialForms()
     1064            sage: f = DifferentialForm(F, 1)
     1065            sage: f.leading_term()
     1066            Traceback (most recent call last):
     1067            ...
     1068            NotImplementedError: leading_term not defined for differential forms.
     1069
     1070        """
     1071        raise NotImplementedError, "leading_term not defined for differential forms."     
     1072
     1073
     1074    def trailing_coefficient(self, cmp=None):
     1075        """
     1076        Method not defined for differential forms.
     1077
     1078        EXAMPLES::
     1079            sage: F = DifferentialForms()
     1080            sage: f = DifferentialForm(F, 1)
     1081            sage: f.trailing_coefficient()
     1082            Traceback (most recent call last):
     1083            ...
     1084            NotImplementedError: trailing_coefficient not defined for differential forms.
     1085
     1086        """
     1087        raise NotImplementedError, "trailing_coefficient not defined for differential forms."
     1088
     1089
     1090    def trailing_item(self, cmp=None):
     1091        """
     1092        Method not defined for differential forms.
     1093
     1094        EXAMPLES::
     1095            sage: F = DifferentialForms()
     1096            sage: f = DifferentialForm(F, 1)
     1097            sage: f.trailing_item()
     1098            Traceback (most recent call last):
     1099            ...
     1100            NotImplementedError: leading_coefficient not defined for differential forms.
     1101
     1102        """
     1103        raise NotImplementedError, "leading_coefficient not defined for differential forms."     
     1104
     1105
     1106    def trailing_monomial(self, cmp=None):
     1107        """
     1108        Method not defined for differential forms.
     1109
     1110        EXAMPLES::
     1111            sage: F = DifferentialForms()
     1112            sage: f = DifferentialForm(F, 1)
     1113            sage: f.trailing_monomial()
     1114            Traceback (most recent call last):
     1115            ...
     1116            NotImplementedError: trailing_monomial not defined for differential forms.
     1117
     1118        """
     1119        raise NotImplementedError, "trailing_monomial not defined for differential forms."     
     1120
     1121
     1122    def trailing_support(self, cmp=None):
     1123        """
     1124        Method not defined for differential forms.
     1125
     1126        EXAMPLES::
     1127            sage: F = DifferentialForms()
     1128            sage: f = DifferentialForm(F, 1)
     1129            sage: f.trailing_support()
     1130            Traceback (most recent call last):
     1131            ...
     1132            NotImplementedError: trailing_support not defined for differential forms.
     1133
     1134        """
     1135        raise NotImplementedError, "trailing_support not defined for differential forms."
     1136
     1137
     1138    def trailing_term(self, cmp=None):
     1139        """
     1140        Method not defined for differential forms.
     1141
     1142        EXAMPLES::
     1143            sage: F = DifferentialForms()
     1144            sage: f = DifferentialForm(F, 1)
     1145            sage: f.trailing_term()
     1146            Traceback (most recent call last):
     1147            ...
     1148            NotImplementedError: trailing_term not defined for differential forms.
     1149
     1150        """
     1151        raise NotImplementedError, "trailing_term not defined for differential forms."     
     1152
     1153
     1154    def map_coefficients(self, f):
     1155        """
     1156        Method not defined for differential forms.
     1157
     1158        EXAMPLES::
     1159            sage: F = DifferentialForms()
     1160            sage: f = DifferentialForm(F, 1)
     1161            sage: f.map_coefficients(lambda x: x)
     1162            Traceback (most recent call last):
     1163            ...
     1164            NotImplementedError: map_coefficients not defined for differential forms.
     1165
     1166        """
     1167        raise NotImplementedError, "map_coefficients not defined for differential forms."
     1168
     1169
     1170    def map_item(self, f):
     1171        """
     1172        Method not defined for differential forms.
     1173
     1174        EXAMPLES::
     1175            sage: F = DifferentialForms()
     1176            sage: f = DifferentialForm(F, 1)
     1177            sage: f.map_item(lambda x: x)
     1178            Traceback (most recent call last):
     1179            ...
     1180            NotImplementedError: map_item not defined for differential forms.
     1181
     1182        """
     1183        raise NotImplementedError, "map_item not defined for differential forms."
     1184
     1185
     1186    def map_support(self, f):
     1187        """
     1188        Method not defined for differential forms.
     1189
     1190        EXAMPLES::
     1191            sage: F = DifferentialForms()
     1192            sage: f = DifferentialForm(F, 1)
     1193            sage: f.map_support(lambda x: x)
     1194            Traceback (most recent call last):
     1195            ...
     1196            NotImplementedError: map_support not defined for differential forms.
     1197
     1198        """
     1199        raise NotImplementedError, "map_support not defined for differential forms."
     1200
     1201
     1202
     1203                   
     1204def d(form):
     1205    r"""
     1206    Returns the exterior derivative of a given form, i.e. calls the diff()
     1207    member function.
     1208
     1209    EXAMPLES::
     1210
     1211        sage: from sage.tensor.differential_form_element import d
     1212        sage: x, y, z = var('x, y, z')
     1213        sage: F = DifferentialForms()
     1214        sage: f = DifferentialForm(F, 1)
     1215        sage: f[2] = cos(x); f
     1216        cos(x)*dz
     1217        sage: d(f)
     1218        -sin(x)*dx/\dz
     1219        sage: f.diff()
     1220        -sin(x)*dx/\dz
     1221        sage: d(f) == f.diff()
     1222        True
     1223    """
     1224    return form.diff()
     1225   
     1226   
     1227def wedge(left, right):
     1228    r"""
     1229    Computes the wedge product of two forms, i.e. calls the wedge()
     1230    member function.
     1231
     1232    EXAMPLES::
     1233
     1234        sage: from sage.tensor.differential_form_element import wedge
     1235        sage: x, y, z = var('x, y, z')
     1236        sage: F = DifferentialForms()
     1237        sage: f = DifferentialForm(F, 1)
     1238        sage: f[2] = cos(x); f
     1239        cos(x)*dz
     1240        sage: g = DifferentialForm(F, 1)
     1241        sage: g[1] = sin(y); g
     1242        sin(y)*dy
     1243        sage: wedge(f, g)
     1244        -sin(y)*cos(x)*dy/\dz
     1245        sage: f.wedge(g)
     1246        -sin(y)*cos(x)*dy/\dz
     1247        sage: wedge(f, g) == f.wedge(g)
     1248        True
     1249    """
     1250    return left.wedge(right)
  • new file sage/tensor/differential_forms.py

    diff -r 5b338f2e484f -r 77cf8caa3554 sage/tensor/differential_forms.py
    - +  
     1r"""
     2Algebra of differential forms.
     3
     4Algebra of differential forms defined on a CoordinatePatch (an open subset of
     5Euclidian space, see ``CoordinatePatch`` for details).
     6
     7AUTHORS:
     8
     9 - Joris Vankerschaver (2010-05-26)
     10
     11TODO:
     12
     13 - Allow for forms with values in a vector space
     14
     15 - Incorporate Kahler differentials
     16
     17REFERENCES:
     18
     19- R. Abraham, J. E. Marsden, and T. S. Ratiu: Manifolds, tensor analysis,
     20  and applications.  Springer-Verlag 1988, texts in Applied Mathematical
     21  Sciences, volume 75, 2nd edition.
     22
     23- http://en.wikipedia.org/wiki/Differential_form
     24
     25"""
     26
     27#*****************************************************************************
     28#    Copyright (C) 2010 Joris Vankerschaver (joris.vankerschaver@gmail.com)
     29#
     30#  Distributed under the terms of the GNU General Public License (GPL)
     31#
     32#    This code is distributed in the hope that it will be useful,
     33#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     34#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     35#    General Public License for more details.
     36#
     37#  The full text of the GPL is available at:
     38#
     39#                  http://www.gnu.org/licenses/
     40#*****************************************************************************
     41
     42
     43from sage.rings.ring import Algebra
     44from sage.tensor.coordinate_patch import CoordinatePatch
     45from sage.tensor.differential_form_element import DifferentialForm
     46from sage.symbolic.ring import SR, var
     47
     48
     49
     50class DifferentialForms(Algebra):
     51    """
     52    The algebra of all differential forms on an open subset of Euclidian space
     53    of arbitrary dimension.
     54
     55    EXAMPLES:
     56
     57    To define an algebra of differential forms, first create a coordinate
     58    patch::
     59
     60        sage: p, q = var('p, q')
     61        sage: U = CoordinatePatch((p, q)); U
     62        Open subset of R^2 with coordinates p, q
     63        sage: F = DifferentialForms(U); F
     64        Algebra of differential forms in the variables p, q
     65       
     66    If no coordinate patch is supplied, a default one (using the variables
     67    x, y, z) will be used::
     68
     69        sage: F = DifferentialForms(); F
     70        Algebra of differential forms in the variables x, y, z
     71
     72    """
     73
     74    Element = DifferentialForm
     75
     76    def __init__(self, coordinate_patch = None): 
     77        """
     78        Construct the algebra of differential forms on a given coordinate patch.
     79        See ``DifferentialForms`` for details.
     80
     81        INPUT::
     82       
     83        - ``coordinate_patch`` -- Coordinate patch where the algebra lives. 
     84        If no coordinate patch is given, a default coordinate patch with
     85        coordinates (x, y, z) is used.
     86
     87        EXAMPLES::
     88
     89            sage: p, q = var('p, q')
     90            sage: U = CoordinatePatch((p, q)); U
     91            Open subset of R^2 with coordinates p, q
     92            sage: F = DifferentialForms(U); F
     93            Algebra of differential forms in the variables p, q
     94
     95        """
     96     
     97        from sage.categories.graded_algebras_with_basis \
     98            import GradedAlgebrasWithBasis
     99        from sage.structure.parent_gens import ParentWithGens
     100       
     101        if not coordinate_patch:
     102            x, y, z = var('x, y, z')
     103            coordinate_patch = CoordinatePatch((x, y, z))
     104
     105        if not isinstance(coordinate_patch, CoordinatePatch):
     106            raise TypeError, \
     107                "%s not a valid Coordinate Patch" % coordinate_patch
     108        self._patch = coordinate_patch
     109       
     110        ParentWithGens.__init__(self, SR, \
     111                                category = GradedAlgebrasWithBasis(SR))
     112
     113
     114    def __cmp__(self, other):
     115        """
     116        Compare self with other.
     117
     118        EXAMPLES::
     119
     120            sage: x, y, z = var('x, y, z')
     121            sage: U = CoordinatePatch((x, y, z)); U
     122            Open subset of R^3 with coordinates x, y, z
     123            sage: F = DifferentialForms(U); F
     124            Algebra of differential forms in the variables x, y, z
     125            sage: p, q = var('p, q')
     126            sage: V = CoordinatePatch((p, q)); V
     127            Open subset of R^2 with coordinates p, q
     128            sage: G = DifferentialForms(V); G
     129            Algebra of differential forms in the variables p, q
     130            sage: H = DifferentialForms(U); H
     131            Algebra of differential forms in the variables x, y, z
     132            sage: cmp(F, G)
     133            1
     134            sage: cmp(F, H)
     135            0
     136        """
     137
     138        if type(other) == type(self):
     139            return cmp(self._patch, other._patch)
     140        else:
     141            return -1
     142
     143   
     144    def ngens(self):
     145        """
     146        Return the number of generators of this algebra.
     147
     148        EXAMPLES::
     149
     150            sage: x, y, z = var('x, y, z')
     151            sage: U = CoordinatePatch((x, y, z)); U
     152            Open subset of R^3 with coordinates x, y, z
     153            sage: F = DifferentialForms(U); F
     154            Algebra of differential forms in the variables x, y, z
     155            sage: F.ngens()
     156            3
     157        """
     158        return len(self._patch.coordinates())
     159           
     160       
     161    def gen(self, i=0):
     162        """
     163        Return the `i^{th}` generator of ``self``.  This is a one-form,
     164        more precisely the exterior derivative of the i-th coordinate.
     165               
     166        INPUT:
     167
     168        - ``i`` - integer (optional, default 0)
     169       
     170
     171        EXAMPLES::
     172
     173            sage: x, y, z = var('x, y, z')
     174            sage: U = CoordinatePatch((x, y, z)); U
     175            Open subset of R^3 with coordinates x, y, z
     176            sage: F = DifferentialForms(U); F
     177            Algebra of differential forms in the variables x, y, z
     178            sage: F.gen(0)
     179            dx
     180            sage: F.gen(1)
     181            dy
     182            sage: F.gen(2)
     183            dz
     184
     185        """
     186
     187        form = DifferentialForm(self, 0, self._patch.coordinate(i))
     188        return form.diff()
     189       
     190       
     191    def gens(self):
     192        """
     193        Return a list of the generators of ``self``. 
     194       
     195        EXAMPLES::
     196
     197            sage: x, y, z = var('x, y, z')
     198            sage: U = CoordinatePatch((x, y, z)); U
     199            Open subset of R^3 with coordinates x, y, z
     200            sage: F = DifferentialForms(U); F
     201            Algebra of differential forms in the variables x, y, z
     202            sage: F.gens()
     203            (dx, dy, dz)
     204
     205        """
     206
     207        return tuple(self.gen(n) for n in xrange(0, self._patch.dim()))
     208
     209
     210    def base_space(self):
     211        """
     212        Return the coordinate patch on which this algebra is defined.
     213
     214        EXAMPLES::
     215
     216            sage: x, y, z = var('x, y, z')
     217            sage: U = CoordinatePatch((x, y, z)); U
     218            Open subset of R^3 with coordinates x, y, z
     219            sage: F = DifferentialForms(U); F
     220            Algebra of differential forms in the variables x, y, z
     221            sage: F.base_space()
     222            Open subset of R^3 with coordinates x, y, z
     223        """
     224        return self._patch
     225     
     226       
     227    def _element_constructor_(self, fun):
     228        """
     229        Coerce a given function (element of the symbolic ring)
     230        into a differential form of degree zero.
     231
     232        EXAMPLES::
     233
     234            sage: x, y, z = var('x, y, z')
     235            sage: U = CoordinatePatch((x, y, z))
     236            sage: F = DifferentialForms(U); F
     237            Algebra of differential forms in the variables x, y, z
     238            sage: F(sin(x*y))    # indirect doctest
     239            sin(x*y)
     240
     241        """
     242
     243
     244        fun = SR(fun)
     245        if fun not in self:
     246            raise ValueError, \
     247                "Function not an element of this algebra of differential forms."
     248           
     249        return DifferentialForm(self, 0, fun)
     250           
     251       
     252    def __contains__(self, element):
     253        """
     254        Check if a given element belongs to this algebra of differential forms.
     255
     256        EXAMPLES::
     257
     258            sage: x, y, p, q = var('x, y, p, q')
     259            sage: U = CoordinatePatch((x, y)); U
     260            Open subset of R^2 with coordinates x, y
     261            sage: F = DifferentialForms(U); F
     262            Algebra of differential forms in the variables x, y
     263            sage: x in F
     264            True
     265            sage: sin(y) in F
     266            True
     267            sage: p in F
     268            False
     269            sage: cos(q) in F
     270            False
     271        """
     272
     273        parent = None
     274        try:
     275            parent = element.parent()
     276        except AttributeError:
     277            pass
     278
     279        if parent == self:
     280            return True
     281
     282        if parent == SR:       
     283            for coordinate in element.variables():
     284                if coordinate not in self._patch.coordinates():
     285                    return False
     286            return True
     287       
     288        return False
     289
     290     
     291    def _coerce_map_from_(self, S):
     292        """
     293        Only the symbolic ring coerces into the algebra of differential forms.
     294
     295        EXAMPLES::
     296
     297            sage: F = DifferentialForms(); F
     298            Algebra of differential forms in the variables x, y, z
     299            sage: F._coerce_map_from_(SR)
     300            True
     301            sage: F._coerce_map_from_(F)
     302            True
     303            sage: F._coerce_map_from_(CC)
     304            False
     305            sage: F._coerce_map_from_(RR)
     306            False
     307
     308        """
     309        return S is SR or S is self
     310       
     311   
     312    def _repr_(self):
     313        r"""
     314        String representation of this algebra of differential forms.
     315
     316        EXAMPLES::
     317
     318            sage: x, y, z = var('x, y, z')
     319            sage: U = CoordinatePatch((x, y, z)); U
     320            Open subset of R^3 with coordinates x, y, z
     321            sage: F = DifferentialForms(U); F
     322            Algebra of differential forms in the variables x, y, z
     323            sage: F._repr_()
     324            'Algebra of differential forms in the variables x, y, z'
     325        """
     326
     327        from string import join
     328        return "Algebra of differential forms in the variables " + \
     329            ', '.join([str(var) for var in self._patch.coordinates()])
     330   
     331       
     332    def _latex_(self):
     333        r"""
     334        Latex representation of this algebra of differential forms.
     335
     336        EXAMPLES::
     337
     338            sage: x, y, z = var('x, y, z')
     339            sage: U = CoordinatePatch((x, y, z)); U
     340            Open subset of R^3 with coordinates x, y, z
     341            sage: F = DifferentialForms(U); F
     342            Algebra of differential forms in the variables x, y, z
     343            sage: latex(F)
     344            \Omega^\ast(\mathbb{\RR}^3)
     345            sage: latex(F) == F._latex_()
     346            True
     347        """
     348
     349        return "\\Omega^\\ast(\mathbb{\\RR}^%s)" % self._patch.dim()
  • setup.py

    diff -r 5b338f2e484f -r 77cf8caa3554 setup.py
    a b  
    922922                     'sage.server.trac',
    923923                     
    924924                     'sage.structure',
    925                      'sage.structure.proof'
     925                     'sage.structure.proof',
     926
     927                     'sage.tensor'
    926928                     ],
    927929      scripts = [],
    928930