Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/tensor/differential_form_element.py
4045 views
1
r"""
2
Elements of the algebra of differential forms
3
4
AUTHORS:
5
6
- Joris Vankerschaver (2010-07-25)
7
8
"""
9
10
#*****************************************************************************
11
# Copyright (C) 2010 Joris Vankerschaver <[email protected]>
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
26
from sage.symbolic.ring import SR
27
from sage.rings.ring_element import RingElement
28
from sage.algebras.algebra_element import AlgebraElement
29
from sage.rings.integer import Integer
30
from sage.combinat.permutation import Permutation
31
32
33
def 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
88
class 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
sage: D.latex((), 1)
200
'1'
201
sage: D.latex((), z^3)
202
'z^{3}'
203
sage: D.latex((0,), 1)
204
'd x'
205
"""
206
207
from sage.misc.latex import latex
208
209
s = " \\wedge ".join( \
210
[('d %s' % latex(self._space.coordinate(c))) for c in comp])
211
212
# Make sure this is a string and not a LatexExpr
213
s = str(s)
214
215
# Add coefficient except if it's 1
216
if fun == 1:
217
if s:
218
return s
219
else:
220
return "1"
221
222
funstr = fun._latex_()
223
if not self._is_atomic(funstr):
224
funstr = '(' + funstr + ')'
225
226
if s:
227
s = " " + s
228
return funstr + s
229
230
231
def _is_atomic(self, str):
232
r"""
233
Helper function to check whether a given string expression
234
is atomic.
235
236
EXAMPLES::
237
238
sage: x, y, z = var('x, y, z')
239
sage: U = CoordinatePatch((x, y, z))
240
sage: from sage.tensor.differential_form_element import DifferentialFormFormatter
241
sage: D = DifferentialFormFormatter(U)
242
sage: D._is_atomic('a + b')
243
False
244
sage: D._is_atomic('(a + b)')
245
True
246
"""
247
level = 0
248
for n, c in enumerate(str):
249
if c == '(':
250
level += 1
251
elif c == ')':
252
level -= 1
253
254
if c == '+' or c == '-':
255
if level == 0 and n > 0:
256
return False
257
return True
258
259
260
261
class DifferentialForm(AlgebraElement):
262
r"""
263
Differential form class.
264
265
EXAMPLES:
266
267
In order to instantiate differential forms of various degree, we begin
268
by specifying the CoordinatePatch on which they live, as well as their
269
parent DifferentialForms algebra.
270
271
::
272
273
sage: x, y, z = var('x, y, z')
274
sage: U = CoordinatePatch((x, y, z))
275
sage: F = DifferentialForms(U)
276
sage: form1 = DifferentialForm(F, 0, sin(x*y)); form1
277
sin(x*y)
278
279
In the previous example, we created a zero-form from a given function.
280
To create forms of higher degree, we can use the subscript operator
281
access the various components::
282
283
sage: form2 = DifferentialForm(F, 1); form2
284
0
285
sage: form2[0] = 1
286
sage: form2[1] = exp(cos(x))
287
sage: form2[2] = 1/ln(y)
288
sage: form2
289
1/log(y)*dz + dx + e^cos(x)*dy
290
291
We may calculate the exterior derivative of a form, and observe that
292
applying the exterior derivative twice always yields zero::
293
294
sage: dform = form1.diff(); dform
295
y*cos(x*y)*dx + x*cos(x*y)*dy
296
sage: dform.diff()
297
0
298
299
As can be seen from the previous example, the exterior derivative
300
increases the degree of a form by one::
301
302
sage: form2.degree()
303
1
304
sage: form2.diff().degree()
305
2
306
307
The ``d`` function provides a convenient shorthand for applying the
308
diff member function. Since d appears in other areas of mathematics
309
as well, this function is not imported in the global namespace
310
automatically::
311
312
sage: from sage.tensor.differential_form_element import d
313
sage: form2
314
1/log(y)*dz + dx + e^cos(x)*dy
315
sage: d(form2)
316
-(1/y)/log(y)^2*dy/\dz + -e^cos(x)*sin(x)*dx/\dy
317
sage: form2.diff()
318
-(1/y)/log(y)^2*dy/\dz + -e^cos(x)*sin(x)*dx/\dy
319
sage: d(form1) == form1.diff()
320
True
321
322
The wedge product of two forms can be computed by means of the wedge
323
member function::
324
325
sage: form1 = DifferentialForm(F, 2)
326
sage: form1[0, 1] = exp(z); form1
327
e^z*dx/\dy
328
sage: form2 = DifferentialForm(F, 1)
329
sage: form2[2] = exp(-z)
330
sage: form1.wedge(form2)
331
dx/\dy/\dz
332
333
For this member function, there exists again a procedural function
334
which is completely equivalent::
335
336
sage: from sage.tensor.differential_form_element import wedge
337
sage: form1.wedge(form2)
338
dx/\dy/\dz
339
sage: wedge(form1, form2)
340
dx/\dy/\dz
341
sage: form1.wedge(form2) == wedge(form1, form2)
342
True
343
344
345
NOTES:
346
347
Differential forms are stored behind the screens as dictionaries,
348
where the keys are the subscripts of the non-zero components, and
349
the values are those components.
350
351
For example, on a
352
space with coordinates x, y, z, the form
353
354
f = sin(x*y) dx /\\ dy + exp(z) dy /\\ dz
355
356
would be represented as the dictionary
357
358
{(0, 1): sin(x*y), (1, 2): exp(z)}.
359
360
Most differential forms are ''sparse'' in the sense that most of
361
their components are zero, so that this representation is more
362
efficient than storing all of the components in a vector.
363
364
"""
365
366
def __init__(self, parent, degree, fun = None):
367
r"""
368
Construct a differential form.
369
370
INPUT:
371
372
- ``parent`` -- Parent algebra of differential forms.
373
374
- ``degree`` -- Degree of the differential form.
375
376
- ``fun`` (default: None) -- Initialize this differential form with the given function. If the degree is not zero, this argument is silently ignored.
377
378
EXAMPLES::
379
380
sage: x, y, z = var('x, y, z')
381
sage: F = DifferentialForms(); F
382
Algebra of differential forms in the variables x, y, z
383
sage: f = DifferentialForm(F, 0, sin(z)); f
384
sin(z)
385
386
"""
387
388
from sage.tensor.differential_forms import DifferentialForms
389
if not isinstance(parent, DifferentialForms):
390
raise TypeError, "Parent not an algebra of differential forms."
391
392
RingElement.__init__(self, parent)
393
394
self._degree = degree
395
self._components = {}
396
397
if degree == 0 and fun is not None:
398
self.__setitem__([], fun)
399
400
401
def __getitem__(self, subscript):
402
r"""
403
Return a given component of the differential form.
404
405
INPUT:
406
407
- ``subscript``: subscript of the component. Must be an integer
408
or a list of integers.
409
410
411
EXAMPLES::
412
413
sage: x, y, z = var('x, y, z')
414
sage: F = DifferentialForms(); F
415
Algebra of differential forms in the variables x, y, z
416
sage: f = DifferentialForm(F, 0, sin(x*y)); f
417
sin(x*y)
418
sage: f[()]
419
sin(x*y)
420
421
sage: df = f.diff(); df
422
y*cos(x*y)*dx + x*cos(x*y)*dy
423
sage: df[0]
424
y*cos(x*y)
425
sage: df[1]
426
x*cos(x*y)
427
sage: df[2]
428
0
429
"""
430
431
if isinstance(subscript, (Integer, int)):
432
subscript = (subscript, )
433
else:
434
subscript = tuple(subscript)
435
436
dim = self.parent().base_space().dim()
437
if any([s >= dim for s in subscript]):
438
raise ValueError, "Index out of bounds."
439
440
if len(subscript) != self._degree:
441
raise TypeError, "%s is not a subscript of degree %s" %\
442
(subscript, self._degree)
443
444
sign, subscript = sort_subscript(subscript)
445
446
if subscript in self._components:
447
return sign*self._components[subscript]
448
else:
449
return 0
450
451
452
def __setitem__(self, subscript, fun):
453
r"""
454
Modify a given component of the differential form.
455
456
INPUT:
457
458
- ``subscript``: subscript of the component. Must be an integer or a list of integers.
459
460
EXAMPLES::
461
462
sage: F = DifferentialForms(); F
463
Algebra of differential forms in the variables x, y, z
464
sage: f = DifferentialForm(F, 2)
465
sage: f[1, 2] = x; f
466
x*dy/\dz
467
"""
468
469
if isinstance(subscript, (Integer, int)):
470
subscript = (subscript, )
471
else:
472
subscript = tuple(subscript)
473
474
dim = self.parent().base_space().dim()
475
if any([s >= dim for s in subscript]):
476
raise ValueError, "Index out of bounds."
477
478
if len(subscript) != self._degree:
479
raise TypeError, "%s is not a subscript of degree %s" %\
480
(subscript, self._degree)
481
482
sign, subscript = sort_subscript(subscript)
483
self._components[subscript] = sign*SR(fun)
484
485
486
def is_zero(self):
487
r"""
488
Return True if ``self`` is the zero form.
489
490
EXAMPLES::
491
492
sage: F = DifferentialForms()
493
sage: f = DifferentialForm(F, 1); f
494
0
495
sage: f.is_zero()
496
True
497
sage: f[1] = 1
498
sage: f.is_zero()
499
False
500
sage: f.diff()
501
0
502
sage: f.diff().is_zero()
503
True
504
"""
505
506
self._cleanup()
507
return len(self._components) == 0
508
509
510
def degree(self):
511
r"""
512
Return the degree of self.
513
514
EXAMPLES::
515
516
sage: F = DifferentialForms(); F
517
Algebra of differential forms in the variables x, y, z
518
sage: f = DifferentialForm(F, 2)
519
sage: f[1, 2] = x; f
520
x*dy/\dz
521
sage: f.degree()
522
2
523
524
The exterior differential increases the degree of forms by one::
525
526
sage: g = f.diff(); g
527
dx/\dy/\dz
528
sage: g.degree()
529
3
530
"""
531
return self._degree
532
533
534
def __eq__(self, other):
535
r"""
536
Test whether two differential forms are equal.
537
538
EXAMPLES::
539
540
sage: F = DifferentialForms(); F
541
Algebra of differential forms in the variables x, y, z
542
sage: f = DifferentialForm(F, 2)
543
sage: f[1,2] = x; f
544
x*dy/\dz
545
sage: f == f
546
True
547
548
sage: g = DifferentialForm(F, 3)
549
sage: g[0, 1, 2] = 1; g
550
dx/\dy/\dz
551
sage: f == g
552
False
553
sage: f.diff() == g
554
True
555
"""
556
if type(other) == type(self):
557
if self._degree != other._degree:
558
return False
559
else:
560
# TODO: the following two lines are where most of the
561
# execution time is spent.
562
self._cleanup()
563
other._cleanup()
564
565
if len(self._components) != len(other._components):
566
return False
567
568
569
# We compare the component dictionary of both differential
570
# forms, keeping in mind that the set of keys is
571
# lexicographically ordered, so that we can simply iterate
572
# over both dictionaries in one go and compare (key, value)
573
# pairs as we go along.
574
575
for (key1, val1), (key2, val2) in \
576
zip(self._components.iteritems(), \
577
other._components.iteritems()):
578
if key1 != key2 or str(val1) != str(val2):
579
return False
580
return True
581
else:
582
return False
583
584
585
def __ne__(self, other):
586
r"""
587
Test whether two differential forms are not equal.
588
589
EXAMPLES::
590
591
sage: F = DifferentialForms(); F
592
Algebra of differential forms in the variables x, y, z
593
sage: f = DifferentialForm(F, 2)
594
sage: f[1,2] = x; f
595
x*dy/\dz
596
sage: g = DifferentialForm(F, 3)
597
sage: g[0, 1, 2] = 1; g
598
dx/\dy/\dz
599
sage: f != g
600
True
601
"""
602
603
604
return not self.__eq__(other)
605
606
607
def _neg_(self):
608
r"""
609
Return the negative of self.
610
611
EXAMPLES::
612
613
sage: x, y, z = var('x, y, z')
614
sage: F = DifferentialForms()
615
sage: f = DifferentialForm(F, 1)
616
sage: f[0] = y
617
sage: f[1] = -x
618
sage: f
619
y*dx + -x*dy
620
sage: -f
621
-y*dx + x*dy
622
sage: -f == f._neg_()
623
True
624
"""
625
626
neg = DifferentialForm(self.parent(), self._degree)
627
for comp in self._components:
628
neg._components[comp] = -self._components[comp]
629
return neg
630
631
632
def _add_(self, other):
633
r"""
634
Add self and other
635
636
EXAMPLES::
637
638
sage: x, y, z = var('x, y, z')
639
sage: F = DifferentialForms()
640
sage: f = DifferentialForm(F, 1)
641
sage: g = DifferentialForm(F, 1)
642
sage: f[0] = exp(x); f
643
e^x*dx
644
sage: g[1] = sin(y); g
645
sin(y)*dy
646
sage: f + g
647
e^x*dx + sin(y)*dy
648
sage: f + g == f._add_(g)
649
True
650
651
Forms must have the same degree to be added::
652
653
sage: h = DifferentialForm(F, 2)
654
sage: h[1, 2] = x; h
655
x*dy/\dz
656
sage: f + h
657
Traceback (most recent call last):
658
...
659
TypeError: Cannot add forms of degree 1 and 2
660
661
"""
662
663
if self.is_zero():
664
return other
665
if other.is_zero():
666
return self
667
668
if self._degree != other._degree:
669
raise TypeError, \
670
"Cannot add forms of degree %s and %s" % \
671
(self._degree, other._degree)
672
673
sumform = DifferentialForm(self.parent(), self._degree)
674
sumform._components = self._components.copy()
675
for comp, fun in other._components.items():
676
sumform[comp] += fun
677
678
sumform._cleanup()
679
return sumform
680
681
682
def _sub_(self, other):
683
r"""
684
Subtract other from self.
685
686
EXAMPLES::
687
688
sage: x, y, z = var('x, y, z')
689
sage: F = DifferentialForms()
690
sage: f = DifferentialForm(F, 1)
691
sage: g = DifferentialForm(F, 1)
692
sage: f[0] = exp(x); f
693
e^x*dx
694
sage: g[1] = sin(y); g
695
sin(y)*dy
696
sage: f - g
697
e^x*dx + -sin(y)*dy
698
sage: f - g == f._sub_(g)
699
True
700
701
Forms must have the same degree to be subtracted::
702
703
sage: h = DifferentialForm(F, 2)
704
sage: h[1, 2] = x; h
705
x*dy/\dz
706
sage: f - h
707
Traceback (most recent call last):
708
...
709
TypeError: Cannot add forms of degree 1 and 2
710
711
"""
712
return self._add_(-other)
713
714
715
def _cleanup(self):
716
r"""
717
Helper function to clean up self, i.e. to remove any
718
zero components from the dictionary of components.
719
720
EXAMPLES::
721
722
sage: F = DifferentialForms()
723
sage: f = DifferentialForm(F, 1)
724
sage: f[0] = 0
725
sage: f[1] = 1
726
sage: f[2] = 0
727
sage: f._dump_all()
728
{(2,): 0, (0,): 0, (1,): 1}
729
sage: f._cleanup()
730
sage: f._dump_all()
731
{(1,): 1}
732
733
"""
734
zeros = []
735
736
for comp in self._components:
737
if self._components[comp].is_zero():
738
zeros.append(comp)
739
740
for comp in zeros:
741
del self._components[comp]
742
743
744
def _dump_all(self):
745
r"""
746
Helper function to dump the internal dictionary of form components.
747
748
EXAMPLES::
749
750
sage: x, y, z = var('x, y, z')
751
sage: F = DifferentialForms()
752
sage: f = DifferentialForm(F, 1)
753
sage: f[1] = exp(cos(x))
754
sage: f[2] = sin(ln(y))
755
sage: f
756
sin(log(y))*dz + e^cos(x)*dy
757
sage: f._dump_all()
758
{(2,): sin(log(y)), (1,): e^cos(x)}
759
sage: g = DifferentialForm(F, 2)
760
sage: g[1, 2] = x+y+z
761
sage: g
762
(x + y + z)*dy/\dz
763
sage: g._dump_all()
764
{(1, 2): x + y + z}
765
766
"""
767
print self._components
768
769
770
def diff(self):
771
r"""
772
Compute the exterior differential of ``self``.
773
774
EXAMPLES::
775
776
sage: x, y, z = var('x, y, z')
777
sage: F = DifferentialForms()
778
sage: f = DifferentialForm(F, 0, sin(x*y)); f
779
sin(x*y)
780
sage: f.diff()
781
y*cos(x*y)*dx + x*cos(x*y)*dy
782
sage: g = DifferentialForm(F, 1)
783
sage: g[0] = y/2
784
sage: g[1] = -x/2
785
sage: g
786
1/2*y*dx + -1/2*x*dy
787
sage: g.diff()
788
-1*dx/\dy
789
sage: h = DifferentialForm(F, 2)
790
sage: h[0, 1] = exp(z)
791
sage: h.diff()
792
e^z*dx/\dy/\dz
793
794
The square of the exterior differential operator is
795
identically zero::
796
797
sage: f
798
sin(x*y)
799
sage: f.diff()
800
y*cos(x*y)*dx + x*cos(x*y)*dy
801
sage: f.diff().diff()
802
0
803
804
sage: g.diff().diff()
805
0
806
807
The exterior differential operator is a derivation of degree one
808
on the space of differential forms. In this example we import the
809
operator d() as a short-hand for having to call the diff()
810
member function.
811
812
::
813
814
sage: from sage.tensor.differential_form_element import d
815
sage: d(f)
816
y*cos(x*y)*dx + x*cos(x*y)*dy
817
818
sage: d(f).wedge(g) + f.wedge(d(g))
819
(-x*y*cos(x*y) - sin(x*y))*dx/\dy
820
sage: d(f.wedge(g))
821
(-x*y*cos(x*y) - sin(x*y))*dx/\dy
822
823
sage: d(f.wedge(g)) == d(f).wedge(g) + f.wedge(d(g))
824
True
825
"""
826
827
diff_form = DifferentialForm(self.parent(), self._degree + 1)
828
829
for comp in self._components:
830
fun = self._components[comp]
831
for n, coord in enumerate(self.parent().base_space().coordinates()):
832
diff_form[(n, ) + comp] += fun.differentiate(coord)
833
834
diff_form._cleanup()
835
return diff_form
836
837
838
def derivative(self, *args, **kwargs):
839
r"""
840
Compute the exterior derivative of ``self``. This is the same as
841
calling the ``diff`` member function.
842
843
844
EXAMPLES::
845
846
sage: x, y = var('x, y')
847
sage: U = CoordinatePatch((x, y))
848
sage: F = DifferentialForms(U)
849
sage: q = DifferentialForm(F, 1)
850
sage: q[0] = -y/2
851
sage: q[1] = x/2
852
sage: q.diff()
853
dx/\dy
854
sage: q.derivative()
855
dx/\dy
856
857
Invoking ``diff`` on a differential form has the same effect as
858
calling this member function::
859
860
sage: diff(q)
861
dx/\dy
862
sage: diff(q) == q.derivative()
863
True
864
865
When additional arguments are supplied to ``diff``, an error is raised,
866
since only the exterior derivative has intrinsic meaning while
867
derivatives with respect to the coordinate variables (in whichever
868
way) are coordinate dependent, and hence not intrinsic.
869
870
::
871
872
sage: diff(q, x)
873
Traceback (most recent call last):
874
...
875
ValueError: Differentiation of a form does not take any arguments.
876
"""
877
878
if len(args) > 0 or len(kwargs) > 0:
879
raise ValueError, "Differentiation of a form does not take any arguments."
880
return self.diff()
881
882
883
def wedge(self, other):
884
r"""
885
Returns the wedge product of ``self`` and other.
886
887
EXAMPLES::
888
889
sage: x, y, z = var('x, y, z')
890
sage: F = DifferentialForms()
891
sage: f = DifferentialForm(F, 1)
892
sage: f[0] = x^2
893
sage: f[1] = y
894
sage: f
895
x^2*dx + y*dy
896
sage: g = DifferentialForm(F, 1)
897
sage: g[2] = z^3
898
sage: g
899
z^3*dz
900
sage: f.wedge(g)
901
y*z^3*dy/\dz + x^2*z^3*dx/\dz
902
903
The wedge product is graded commutative::
904
905
sage: f.wedge(g)
906
y*z^3*dy/\dz + x^2*z^3*dx/\dz
907
sage: g.wedge(f)
908
-y*z^3*dy/\dz + -x^2*z^3*dx/\dz
909
sage: f.wedge(f)
910
0
911
912
When the wedge product of forms belonging to different algebras
913
is computed, an error is raised::
914
915
sage: x, y, p, q = var('x, y, p, q')
916
sage: F = DifferentialForms(CoordinatePatch((x, y)))
917
sage: G = DifferentialForms(CoordinatePatch((p, q)))
918
sage: f = DifferentialForm(F, 0, 1); f
919
1
920
sage: g = DifferentialForm(G, 0, x); g
921
x
922
sage: f.parent()
923
Algebra of differential forms in the variables x, y
924
sage: g.parent()
925
Algebra of differential forms in the variables p, q
926
sage: f.wedge(g)
927
Traceback (most recent call last):
928
...
929
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'
930
931
"""
932
933
if self.parent() != other.parent():
934
raise TypeError, "unsupported operand parents for wedge: " +\
935
"\'%s\' and \'%s\'" % (self.parent(), other.parent())
936
937
output = DifferentialForm(self.parent(), self._degree + other._degree)
938
if self._degree + other._degree > self.parent().ngens():
939
return output
940
941
for lcomp, lfun in self._components.items():
942
for rcomp, rfun in other._components.items():
943
output[lcomp + rcomp] += lfun*rfun
944
945
output._cleanup()
946
return output
947
948
949
950
def _mul_(self, other):
951
r"""
952
Multiply self and other. This is identical to the wedge operator.
953
954
EXAMPLES::
955
956
sage: x, y, z = var('x, y, z')
957
sage: F = DifferentialForms()
958
sage: f = F.gen(0); f
959
dx
960
sage: g = F.gen(1); g
961
dy
962
sage: f*g
963
dx/\dy
964
sage: f.wedge(g)
965
dx/\dy
966
sage: f*g == f.wedge(g)
967
True
968
sage: f*g == f._mul_(g)
969
True
970
971
"""
972
return self.wedge(other)
973
974
975
def _latex_(self):
976
r"""
977
Return a latex representation of self.
978
979
EXAMPLES::
980
981
sage: x, y, z = var('x, y, z')
982
sage: F = DifferentialForms()
983
sage: f = DifferentialForm(F, 1)
984
sage: f[1] = exp(z); f
985
e^z*dy
986
sage: latex(f)
987
e^{z} d y
988
sage: g = f.diff(); g
989
-e^z*dy/\dz
990
sage: latex(g)
991
-e^{z} d y \wedge d z
992
sage: latex(g) == g._latex_()
993
True
994
995
"""
996
if len(self._components) == 0:
997
return '0'
998
999
format = DifferentialFormFormatter(self.parent().base_space())
1000
output = [format.latex(comp, fun) \
1001
for (comp, fun) in self._components.items()]
1002
return ' + '.join(output)
1003
1004
1005
def _repr_(self):
1006
r"""
1007
Return string representation of self.
1008
1009
EXAMPLES::
1010
1011
sage: x, y, z = var('x, y, z')
1012
sage: F = DifferentialForms()
1013
sage: f = DifferentialForm(F, 1)
1014
sage: f[1] = exp(z); f
1015
e^z*dy
1016
sage: print f
1017
e^z*dy
1018
sage: f._repr_()
1019
'e^z*dy'
1020
"""
1021
if len(self._components) == 0:
1022
return '0'
1023
1024
format = DifferentialFormFormatter(self.parent().base_space())
1025
output = [format.repr(comp, fun) \
1026
for (comp, fun) in self._components.items()]
1027
return ' + '.join(output)
1028
1029
1030
1031
# Unsupported methods
1032
1033
def abs(self):
1034
"""
1035
Method not defined for differential forms.
1036
1037
EXAMPLES::
1038
1039
sage: F = DifferentialForms()
1040
sage: f = DifferentialForm(F, 1)
1041
sage: f.abs()
1042
Traceback (most recent call last):
1043
...
1044
NotImplementedError: Absolute value not defined for differential forms.
1045
1046
"""
1047
raise NotImplementedError, "Absolute value not defined for differential forms."
1048
1049
1050
def leading_coefficient(self, cmp=None):
1051
"""
1052
Method not defined for differential forms.
1053
1054
EXAMPLES::
1055
1056
sage: F = DifferentialForms()
1057
sage: f = DifferentialForm(F, 1)
1058
sage: f.leading_coefficient()
1059
Traceback (most recent call last):
1060
...
1061
NotImplementedError: leading_coefficient not defined for differential forms.
1062
1063
"""
1064
raise NotImplementedError, "leading_coefficient not defined for differential forms."
1065
1066
1067
def leading_item(self, cmp=None):
1068
"""
1069
Method not defined for differential forms.
1070
1071
EXAMPLES::
1072
1073
sage: F = DifferentialForms()
1074
sage: f = DifferentialForm(F, 1)
1075
sage: f.leading_item()
1076
Traceback (most recent call last):
1077
...
1078
NotImplementedError: leading_item not defined for differential forms.
1079
1080
"""
1081
raise NotImplementedError, "leading_item not defined for differential forms."
1082
1083
1084
def leading_monomial(self, cmp=None):
1085
"""
1086
Method not defined for differential forms.
1087
1088
EXAMPLES::
1089
1090
sage: F = DifferentialForms()
1091
sage: f = DifferentialForm(F, 1)
1092
sage: f.leading_monomial()
1093
Traceback (most recent call last):
1094
...
1095
NotImplementedError: leading_monomial not defined for differential forms.
1096
1097
"""
1098
raise NotImplementedError, "leading_monomial not defined for differential forms."
1099
1100
1101
def leading_support(self, cmp=None):
1102
"""
1103
Method not defined for differential forms.
1104
1105
EXAMPLES::
1106
1107
sage: F = DifferentialForms()
1108
sage: f = DifferentialForm(F, 1)
1109
sage: f.leading_support()
1110
Traceback (most recent call last):
1111
...
1112
NotImplementedError: leading_support not defined for differential forms.
1113
1114
"""
1115
raise NotImplementedError, "leading_support not defined for differential forms."
1116
1117
1118
def leading_term(self, cmp=None):
1119
"""
1120
Method not defined for differential forms.
1121
1122
EXAMPLES::
1123
1124
sage: F = DifferentialForms()
1125
sage: f = DifferentialForm(F, 1)
1126
sage: f.leading_term()
1127
Traceback (most recent call last):
1128
...
1129
NotImplementedError: leading_term not defined for differential forms.
1130
1131
"""
1132
raise NotImplementedError, "leading_term not defined for differential forms."
1133
1134
1135
def trailing_coefficient(self, cmp=None):
1136
"""
1137
Method not defined for differential forms.
1138
1139
EXAMPLES::
1140
1141
sage: F = DifferentialForms()
1142
sage: f = DifferentialForm(F, 1)
1143
sage: f.trailing_coefficient()
1144
Traceback (most recent call last):
1145
...
1146
NotImplementedError: trailing_coefficient not defined for differential forms.
1147
1148
"""
1149
raise NotImplementedError, "trailing_coefficient not defined for differential forms."
1150
1151
1152
def trailing_item(self, cmp=None):
1153
"""
1154
Method not defined for differential forms.
1155
1156
EXAMPLES::
1157
1158
sage: F = DifferentialForms()
1159
sage: f = DifferentialForm(F, 1)
1160
sage: f.trailing_item()
1161
Traceback (most recent call last):
1162
...
1163
NotImplementedError: leading_coefficient not defined for differential forms.
1164
1165
"""
1166
raise NotImplementedError, "leading_coefficient not defined for differential forms."
1167
1168
1169
def trailing_monomial(self, cmp=None):
1170
"""
1171
Method not defined for differential forms.
1172
1173
EXAMPLES::
1174
1175
sage: F = DifferentialForms()
1176
sage: f = DifferentialForm(F, 1)
1177
sage: f.trailing_monomial()
1178
Traceback (most recent call last):
1179
...
1180
NotImplementedError: trailing_monomial not defined for differential forms.
1181
1182
"""
1183
raise NotImplementedError, "trailing_monomial not defined for differential forms."
1184
1185
1186
def trailing_support(self, cmp=None):
1187
"""
1188
Method not defined for differential forms.
1189
1190
EXAMPLES::
1191
1192
sage: F = DifferentialForms()
1193
sage: f = DifferentialForm(F, 1)
1194
sage: f.trailing_support()
1195
Traceback (most recent call last):
1196
...
1197
NotImplementedError: trailing_support not defined for differential forms.
1198
1199
"""
1200
raise NotImplementedError, "trailing_support not defined for differential forms."
1201
1202
1203
def trailing_term(self, cmp=None):
1204
"""
1205
Method not defined for differential forms.
1206
1207
EXAMPLES::
1208
1209
sage: F = DifferentialForms()
1210
sage: f = DifferentialForm(F, 1)
1211
sage: f.trailing_term()
1212
Traceback (most recent call last):
1213
...
1214
NotImplementedError: trailing_term not defined for differential forms.
1215
1216
"""
1217
raise NotImplementedError, "trailing_term not defined for differential forms."
1218
1219
1220
def map_coefficients(self, f):
1221
"""
1222
Method not defined for differential forms.
1223
1224
EXAMPLES::
1225
1226
sage: F = DifferentialForms()
1227
sage: f = DifferentialForm(F, 1)
1228
sage: f.map_coefficients(lambda x: x)
1229
Traceback (most recent call last):
1230
...
1231
NotImplementedError: map_coefficients not defined for differential forms.
1232
1233
"""
1234
raise NotImplementedError, "map_coefficients not defined for differential forms."
1235
1236
1237
def map_item(self, f):
1238
"""
1239
Method not defined for differential forms.
1240
1241
EXAMPLES::
1242
1243
sage: F = DifferentialForms()
1244
sage: f = DifferentialForm(F, 1)
1245
sage: f.map_item(lambda x: x)
1246
Traceback (most recent call last):
1247
...
1248
NotImplementedError: map_item not defined for differential forms.
1249
1250
"""
1251
raise NotImplementedError, "map_item not defined for differential forms."
1252
1253
1254
def map_support(self, f):
1255
"""
1256
Method not defined for differential forms.
1257
1258
EXAMPLES::
1259
1260
sage: F = DifferentialForms()
1261
sage: f = DifferentialForm(F, 1)
1262
sage: f.map_support(lambda x: x)
1263
Traceback (most recent call last):
1264
...
1265
NotImplementedError: map_support not defined for differential forms.
1266
1267
"""
1268
raise NotImplementedError, "map_support not defined for differential forms."
1269
1270
1271
1272
1273
def d(form):
1274
r"""
1275
Returns the exterior derivative of a given form, i.e. calls the diff()
1276
member function.
1277
1278
EXAMPLES::
1279
1280
sage: from sage.tensor.differential_form_element import d
1281
sage: x, y, z = var('x, y, z')
1282
sage: F = DifferentialForms()
1283
sage: f = DifferentialForm(F, 1)
1284
sage: f[2] = cos(x); f
1285
cos(x)*dz
1286
sage: d(f)
1287
-sin(x)*dx/\dz
1288
sage: f.diff()
1289
-sin(x)*dx/\dz
1290
sage: d(f) == f.diff()
1291
True
1292
"""
1293
return form.diff()
1294
1295
1296
def wedge(left, right):
1297
r"""
1298
Computes the wedge product of two forms, i.e. calls the wedge()
1299
member function.
1300
1301
EXAMPLES::
1302
1303
sage: from sage.tensor.differential_form_element import wedge
1304
sage: x, y, z = var('x, y, z')
1305
sage: F = DifferentialForms()
1306
sage: f = DifferentialForm(F, 1)
1307
sage: f[2] = cos(x); f
1308
cos(x)*dz
1309
sage: g = DifferentialForm(F, 1)
1310
sage: g[1] = sin(y); g
1311
sin(y)*dy
1312
sage: wedge(f, g)
1313
-sin(y)*cos(x)*dy/\dz
1314
sage: f.wedge(g)
1315
-sin(y)*cos(x)*dy/\dz
1316
sage: wedge(f, g) == f.wedge(g)
1317
True
1318
"""
1319
return left.wedge(right)
1320
1321