~martinal/ufl/1.0.1

« back to all changes in this revision

Viewing changes to ufl/tensoralgebra.py

  • Committer: Martin Sandve Alnæs
  • Date: 2012-06-15 11:23:25 UTC
  • Revision ID: martinal@simula.no-20120615112325-aihkz3gnzxmhn8mp
Add missing __slots__ to various classes, reducing memory consumption.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
    ri = set(ai) & set(bi)
36
36
    ufl_assert(not ri, "Not expecting repeated indices.")
37
37
    free_indices = ai+bi
38
 
    
 
38
 
39
39
    aid = a.index_dimensions()
40
40
    bid = b.index_dimensions()
41
41
    index_dimensions = dict(aid)
42
42
    index_dimensions.update(bid)
43
 
    
44
 
    return free_indices, index_dimensions 
 
43
 
 
44
    return free_indices, index_dimensions
45
45
 
46
46
### Algebraic operations on tensors:
47
47
# FloatValues:
71
71
# --- Classes representing compound tensor algebra operations ---
72
72
 
73
73
class CompoundTensorOperator(AlgebraOperator):
 
74
    __slots__ = ()
74
75
    def __init__(self):
75
76
        AlgebraOperator.__init__(self)
76
77
 
77
78
# TODO: Use this and make Sum handle scalars only?
78
79
#       This would simplify some algorithms. The only
79
 
#       problem is we can't use + in many algorithms because 
 
80
#       problem is we can't use + in many algorithms because
80
81
#       this type should be expanded by expand_compounds.
81
82
#class TensorSum(CompoundTensorOperator):
82
83
#    "Sum of nonscalar expressions."
84
85
 
85
86
# TODO: Use this similarly to TensorSum?
86
87
#       This would simplify some algorithms. The only
87
 
#       problem is we can't use / in many algorithms because 
 
88
#       problem is we can't use / in many algorithms because
88
89
#       this type should be expanded by expand_compounds.
89
90
#class TensorDivision(CompoundTensorOperator):
90
91
#    "Division of nonscalar expression with a scalar expression."
92
93
 
93
94
# TODO: Use this similarly to TensorSum?
94
95
#       This would simplify some algorithms. The only
95
 
#       problem is we can't use * in many algorithms because 
 
96
#       problem is we can't use * in many algorithms because
96
97
#       this type should be expanded by expand_compounds.
97
98
#class MatrixProduct(CompoundTensorOperator):
98
99
#    "Product of a matrix with a matrix or vector."
100
101
 
101
102
# TODO: Use this similarly to TensorSum?
102
103
#       This would simplify some algorithms. The only
103
 
#       problem is we can't use abs in many algorithms because 
 
104
#       problem is we can't use abs in many algorithms because
104
105
#       this type should be expanded by expand_compounds.
105
106
#class TensorAbs(CompoundTensorOperator):
106
107
#    "Absolute value of nonscalar expression."
114
115
            a, b = A.shape()
115
116
            return Zero((b, a), A.free_indices(), A.index_dimensions())
116
117
        return CompoundTensorOperator.__new__(cls)
117
 
    
 
118
 
118
119
    def __init__(self, A):
119
120
        CompoundTensorOperator.__init__(self)
120
121
        ufl_assert(A.rank() == 2, "Transposed is only defined for rank 2 tensors.")
121
122
        self._A = A
122
 
    
 
123
 
123
124
    def operands(self):
124
125
        return (self._A,)
125
 
    
 
126
 
126
127
    def free_indices(self):
127
128
        return self._A.free_indices()
128
 
    
 
129
 
129
130
    def index_dimensions(self):
130
131
        return self._A.index_dimensions()
131
 
    
 
132
 
132
133
    def shape(self):
133
134
        s = self._A.shape()
134
135
        return (s[1], s[0])
135
 
    
 
136
 
136
137
    def __str__(self):
137
138
        return "%s^T" % parstr(self._A, self)
138
 
    
 
139
 
139
140
    def __repr__(self):
140
141
        return "Transposed(%r)" % self._A
141
142
 
156
157
        self._a = a
157
158
        self._b = b
158
159
        self._free_indices, self._index_dimensions = merge_indices(a, b)
159
 
    
 
160
 
160
161
    def operands(self):
161
162
        return (self._a, self._b)
162
 
    
 
163
 
163
164
    def free_indices(self):
164
165
        return self._free_indices
165
 
    
 
166
 
166
167
    def index_dimensions(self):
167
168
        return self._index_dimensions
168
 
    
 
169
 
169
170
    def shape(self):
170
171
        return self._a.shape() + self._b.shape()
171
 
    
 
172
 
172
173
    def __str__(self):
173
174
        return "%s (X) %s" % (parstr(self._a, self), parstr(self._b, self))
174
 
    
 
175
 
175
176
    def __repr__(self):
176
177
        return "Outer(%r, %r)" % (self._a, self._b)
177
178
 
195
196
        self._a = a
196
197
        self._b = b
197
198
        self._free_indices, self._index_dimensions = merge_indices(a, b)
198
 
    
 
199
 
199
200
    def operands(self):
200
201
        return (self._a, self._b)
201
 
    
 
202
 
202
203
    def free_indices(self):
203
204
        return self._free_indices
204
 
    
 
205
 
205
206
    def index_dimensions(self):
206
207
        return self._index_dimensions
207
 
    
 
208
 
208
209
    def shape(self):
209
210
        return ()
210
 
    
 
211
 
211
212
    def __str__(self):
212
213
        return "%s : %s" % (parstr(self._a, self), parstr(self._b, self))
213
 
    
 
214
 
214
215
    def __repr__(self):
215
216
        return "Inner(%r, %r)" % (self._a, self._b)
216
217
 
236
237
        self._a = a
237
238
        self._b = b
238
239
        self._free_indices, self._index_dimensions = merge_indices(a, b)
239
 
    
 
240
 
240
241
    def operands(self):
241
242
        return (self._a, self._b)
242
 
    
 
243
 
243
244
    def free_indices(self):
244
245
        return self._free_indices
245
 
    
 
246
 
246
247
    def index_dimensions(self):
247
248
        return self._index_dimensions
248
 
    
 
249
 
249
250
    def shape(self):
250
251
        return self._a.shape()[:-1] + self._b.shape()[1:]
251
252
 
252
253
    def __str__(self):
253
254
        return "%s . %s" % (parstr(self._a, self), parstr(self._b, self))
254
 
    
 
255
 
255
256
    def __repr__(self):
256
257
        return "Dot(%r, %r)" % (self._a, self._b)
257
258
 
274
275
        self._a = a
275
276
        self._b = b
276
277
        self._free_indices, self._index_dimensions = merge_indices(a, b)
277
 
    
 
278
 
278
279
    def operands(self):
279
280
        return (self._a, self._b)
280
 
    
 
281
 
281
282
    def free_indices(self):
282
283
        return self._free_indices
283
 
    
 
284
 
284
285
    def index_dimensions(self):
285
286
        return self._index_dimensions
286
 
    
 
287
 
287
288
    def shape(self):
288
289
        return (3,)
289
290
 
290
291
    def __str__(self):
291
292
        return "%s x %s" % (parstr(self._a, self), parstr(self._b, self))
292
 
    
 
293
 
293
294
    def __repr__(self):
294
295
        return "Cross(%r, %r)" % (self._a, self._b)
295
296
 
305
306
    def __init__(self, A):
306
307
        CompoundTensorOperator.__init__(self)
307
308
        self._A = A
308
 
    
 
309
 
309
310
    def operands(self):
310
311
        return (self._A, )
311
 
    
 
312
 
312
313
    def free_indices(self):
313
314
        return self._A.free_indices()
314
 
    
 
315
 
315
316
    def index_dimensions(self):
316
317
        return self._A.index_dimensions()
317
 
    
 
318
 
318
319
    def shape(self):
319
320
        return ()
320
 
    
 
321
 
321
322
    def __str__(self):
322
323
        return "tr(%s)" % self._A
323
 
    
 
324
 
324
325
    def __repr__(self):
325
326
        return "Trace(%r)" % self._A
326
327
 
345
346
    def __init__(self, A):
346
347
        CompoundTensorOperator.__init__(self)
347
348
        self._A = A
348
 
    
 
349
 
349
350
    def operands(self):
350
351
        return (self._A, )
351
 
    
 
352
 
352
353
    def free_indices(self):
353
354
        return ()
354
 
    
 
355
 
355
356
    def index_dimensions(self):
356
357
        return {}
357
 
    
 
358
 
358
359
    def shape(self):
359
360
        return ()
360
 
    
 
361
 
361
362
    def __str__(self):
362
363
        return "det(%s)" % self._A
363
 
    
 
364
 
364
365
    def __repr__(self):
365
366
        return "Determinant(%r)" % self._A
366
367
 
388
389
    def __init__(self, A):
389
390
        CompoundTensorOperator.__init__(self)
390
391
        self._A = A
391
 
    
 
392
 
392
393
    def operands(self):
393
394
        return (self._A, )
394
 
    
 
395
 
395
396
    def free_indices(self):
396
397
        return ()
397
 
    
 
398
 
398
399
    def index_dimensions(self):
399
400
        return {}
400
 
    
 
401
 
401
402
    def shape(self):
402
403
        return self._A.shape()
403
 
    
 
404
 
404
405
    def __str__(self):
405
406
        return "%s^-1" % parstr(self._A, self)
406
 
    
 
407
 
407
408
    def __repr__(self):
408
409
        return "Inverse(%r)" % self._A
409
410
 
421
422
 
422
423
    def operands(self):
423
424
        return (self._A, )
424
 
    
 
425
 
425
426
    def free_indices(self):
426
427
        return ()
427
 
    
 
428
 
428
429
    def index_dimensions(self):
429
430
        return {}
430
 
    
 
431
 
431
432
    def shape(self):
432
433
        return self._A.shape()
433
434
 
434
435
    def __str__(self):
435
436
        return "cofactor(%s)" % self._A
436
 
    
 
437
 
437
438
    def __repr__(self):
438
439
        return "Cofactor(%r)" % self._A
439
440
 
456
457
 
457
458
    def operands(self):
458
459
        return (self._A, )
459
 
    
 
460
 
460
461
    def free_indices(self):
461
462
        return self._A.free_indices()
462
 
    
 
463
 
463
464
    def index_dimensions(self):
464
465
        return self._A.index_dimensions()
465
 
    
 
466
 
466
467
    def shape(self):
467
468
        return self._A.shape()
468
 
    
 
469
 
469
470
    def __str__(self):
470
471
        return "dev(%s)" % self._A
471
 
    
 
472
 
472
473
    def __repr__(self):
473
474
        return "Deviatoric(%r)" % self._A
474
475
 
488
489
    def __init__(self, A):
489
490
        CompoundTensorOperator.__init__(self)
490
491
        self._A = A
491
 
    
 
492
 
492
493
    def operands(self):
493
494
        return (self._A, )
494
 
    
 
495
 
495
496
    def free_indices(self):
496
497
        return self._A.free_indices()
497
 
    
 
498
 
498
499
    def index_dimensions(self):
499
500
        return self._A.index_dimensions()
500
 
    
 
501
 
501
502
    def shape(self):
502
503
        return self._A.shape()
503
 
    
 
504
 
504
505
    def __str__(self):
505
506
        return "skew(%s)" % self._A
506
 
    
 
507
 
507
508
    def __repr__(self):
508
509
        return "Skew(%r)" % self._A
509
510
 
523
524
    def __init__(self, A):
524
525
        CompoundTensorOperator.__init__(self)
525
526
        self._A = A
526
 
    
 
527
 
527
528
    def operands(self):
528
529
        return (self._A, )
529
 
    
 
530
 
530
531
    def free_indices(self):
531
532
        return self._A.free_indices()
532
 
    
 
533
 
533
534
    def index_dimensions(self):
534
535
        return self._A.index_dimensions()
535
 
    
 
536
 
536
537
    def shape(self):
537
538
        return self._A.shape()
538
 
    
 
539
 
539
540
    def __str__(self):
540
541
        return "sym(%s)" % self._A
541
 
    
 
542
 
542
543
    def __repr__(self):
543
544
        return "Sym(%r)" % self._A