OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
AntiSymTenzor.h
Go to the documentation of this file.
1/***************************************************************************
2 *
3 * The IPPL Framework
4 *
5 ***************************************************************************/
6
7#ifndef ANTI_SYM_TENZOR_H
8#define ANTI_SYM_TENZOR_H
9
10// include files
11#include "Utility/PAssert.h"
12#include "Message/Message.h"
14#include "AppTypes/TSVMeta.h"
15#include "AppTypes/Tenzor.h"
16
17#include <iostream>
18
19
21//
22// Definition of class AntiSymTenzor.
23//
25
26//
27// | O -x10 -x20 |
28// | x10 0 -x21 |
29// | x20 x21 0 |
30//
31
32template<class T, unsigned D>
34{
35public:
36
37 typedef T Element_t;
38 enum { ElemDim = 2 };
39 enum { Size = D*(D-1)/2 };
40
41 // Default Constructor
44 }
45
46 // A noninitializing ctor.
49
50 // Construct an AntiSymTenzor from a single T.
51 // This doubles as the 2D AntiSymTenzor initializer.
52 AntiSymTenzor(const T& x00) {
54 }
55 // construct a 3D AntiSymTenzor
56 AntiSymTenzor(const T& x10, const T& x20, const T& x21) {
57 PInsist(D==3,
58 "Number of arguments does not match AntiSymTenzor dimension!!");
59 X[0]= x10; X[1]= x20; X[2]= x21;
60 }
61
62 // Copy Constructor
65 apply(*this,rhs);
66 }
67
68 // Construct from a Tenzor.
69 // Extract the antisymmetric part.
71 for (unsigned int i=1; i<D; ++i) {
72 for (unsigned int j=0; j<i; ++j)
73 (*this)[((i-1)*i/2)+j] = (t(i,j)-t(j,i))*0.5;
74 }
75 }
76
78
79 // assignment operators
82 apply(*this,rhs);
83 return *this;
84 }
85 template<class T1>
88 apply(*this,rhs);
89 return *this;
90 }
91 const AntiSymTenzor<T,D>& operator= (const T& rhs) {
93 apply(*this,rhs);
94 return *this;
95 }
96
97 // accumulation operators
98 template<class T1>
100 {
102 :: apply(*this,rhs);
103 return *this;
104 }
105
106 template<class T1>
108 {
110 OpSubtractAssign > :: apply(*this,rhs);
111 return *this;
112 }
113
114 template<class T1>
116 {
118 OpMultipplyAssign > :: apply(*this,rhs);
119 return *this;
120 }
122 {
124 apply(*this,rhs);
125 return *this;
126 }
127
128 template<class T1>
130 {
132 OpDivideAssign > :: apply(*this,rhs);
133 return *this;
134 }
136 {
138 apply(*this,rhs);
139 return *this;
140 }
141
142 // Methods
143
144 int len(void) const { return Size; }
145 int size(void) const { return sizeof(*this); }
146 int get_Size(void) const { return Size; }
147
149 public:
151 : elem_m(elem), where_m(where) { }
153 : elem_m(model.elem_m), where_m(model.where_m) { }
155 {
156 PAssert_EQ(where_m != 0 || (a.elem_m == -a.elem_m), true);
157 elem_m = where_m < 0 ? -a.elem_m : a.elem_m;
158 return *this;
159 }
161 {
162 PAssert_EQ(where_m != 0 || (e == -e), true);
163 elem_m = where_m < 0 ? -e : e;
164 return *this;
165 }
166
167 operator Element_t() const
168 {
169 return (where_m < 0 ? -elem_m : elem_m);
170 }
171
172 private:
173
176 };
177
178 // Operators
179
180 Element_t operator()(unsigned int i, unsigned int j) const {
181 if (i == j)
182 return T(0.0);
183 else if (i < j)
184 return -X[((j-1)*j/2) + i];
185 else
186 return X[((i-1)*i/2) + j];
187 }
188
189 Element_t operator()( std::pair<int,int> a) const {
190 int i = a.first;
191 int j = a.second;
192 return (*this)(i, j);
193 }
194
195 AssignProxy operator()(unsigned int i, unsigned int j) {
196 if (i == j)
198 else
199 {
200 int lo = i < j ? i : j;
201 int hi = i > j ? i : j;
202 return AssignProxy(X[((hi-1)*hi/2) + lo], i - j);
203 }
204 }
205
206 AssignProxy operator()(std::pair<int,int> a) {
207 int i = a.first;
208 int j = a.second;
209 return (*this)(i, j);
210 }
211
212 Element_t& operator[](unsigned int i) {
213 PAssert (i < Size);
214 return X[i];
215 }
216
217 Element_t operator[](unsigned int i) const {
218 PAssert (i < Size);
219 return X[i];
220 }
221
222 // These are the same as operator[] but with () instead:
223
224 Element_t& operator()(unsigned int i) {
225 PAssert (i < Size);
226 return X[i];
227 }
228
229 Element_t operator()(unsigned int i) const {
230 PAssert (i < Size);
231 return X[i];
232 }
233
234 //----------------------------------------------------------------------
235 // Comparison operators.
236 bool operator==(const AntiSymTenzor<T,D>& that) const {
237 return TSV_MetaCompareArrays<T,T,D*(D-1)/2>::apply(X,that.X);
238 }
239 bool operator!=(const AntiSymTenzor<T,D>& that) const {
240 return !(*this == that);
241 }
242
243 //----------------------------------------------------------------------
244 // parallel communication
246 m.setCopy(true);
247 ::putMessage(m, X, X + Size);
248 return m;
249 }
250
252 ::getMessage(m, X, X + Size);
253 return m;
254 }
255
256private:
257
258 friend class AssignProxy;
259
260 // The elements themselves.
262
263 // A place to store a zero element.
264 // We need to return a reference to this
265 // for the diagonal element.
266 static T Zero;
267};
268
269
270// Assign the static zero element value:
271template<class T, unsigned int D>
273
274
275
277// Specialization for 1D -- this is basically just the zero tensor
279
280template <class T>
282{
283public:
284
285 typedef T Element_t;
286 enum { ElemDim = 2 };
287
288 // Default Constructor
290
291 // Copy Constructor
293
294 // A noninitializing ctor.
295 class DontInitialize {};
296 AntiSymTenzor(DontInitialize) {}
297
298 // Construct from a Tenzor: still a no-op here:
299 AntiSymTenzor( const Tenzor<T,1>& /*t*/) { }
300
302
303 // assignment operators
305 return *this;
306 }
307 template <class T1>
309 return *this;
310 }
311 const AntiSymTenzor<T,1>& operator=(const T& rhs) {
312 PInsist(rhs==0, "Cannot assign non-zero value to a 1D AntiSymTenzor!");
313 return *this;
314 }
315
316 // accumulation operators
317 template <class T1>
319 return *this;
320 }
321
322 template <class T1>
324 return *this;
325 }
326
327 template <class T1>
329 return *this;
330 }
332 return *this;
333 }
334
335 template <class T1>
337 return *this;
338 }
340 return *this;
341 }
342
343 // Methods
344
345 int len(void) const { return Size; }
346 int size(void) const { return sizeof(*this); }
347 int get_Size(void) const { return Size; }
348
350 public:
352 : elem_m(elem), where_m(where) {}
354 : elem_m(model.elem_m), where_m(model.where_m) {}
356 {
357 PAssert_EQ(where_m != 0 || (a.elem_m == -a.elem_m), true);
358 elem_m = where_m < 0 ? -a.elem_m : a.elem_m;
359 return *this;
360 }
362 {
363 PAssert_EQ(where_m != 0 || (e == -e), true);
364 elem_m = where_m < 0 ? -e : e;
365 return *this;
366 }
367
368 operator Element_t() const
369 {
370 return (where_m < 0 ? -elem_m : elem_m);
371 }
372
373 private:
374
377 };
378
379 // Operators
380
381 Element_t operator()(unsigned int i, unsigned int j) const {
382 // PAssert and PAssert_EQ are macros. They are defined empty, if we
383 // compile for production. i and j are unused in this case. The
384 // following statement suppress the 'unused' warning.
385 (void)i; (void)j;
386 PAssert_EQ(i, j);
387 return T(0.0);
388 }
389
390 Element_t operator()( std::pair<int,int> a) const {
391 int i = a.first;
392 int j = a.second;
393 return (*this)(i, j);
394 }
395
396 AssignProxy operator()(unsigned int i, unsigned int j) {
397 (void)i; (void)j;
398 PAssert_EQ(i, j);
400 }
401
402 AssignProxy operator()(std::pair<int,int> a) {
403 int i = a.first;
404 int j = a.second;
405 return (*this)(i, j);
406 }
407
408 Element_t operator[](unsigned int i) const {
409 (void)i;
410 PAssert (i == 0);
412 }
413
414 // These are the same as operator[] but with () instead:
415
416 Element_t operator()(unsigned int i) const {
417 (void)i;
418 PAssert (i == 0);
420 }
421
422 //----------------------------------------------------------------------
423 // Comparison operators.
424 bool operator==(const AntiSymTenzor<T,1>& /*that*/) const {
425 return true;
426 }
427 bool operator!=(const AntiSymTenzor<T,1>& that) const {
428 return !(*this == that);
429 }
430
431 //----------------------------------------------------------------------
432 // parallel communication
434 m.setCopy(true);
436 return m;
437 }
438
440 T zero{};
441 m.get(zero);
442 return m;
443 }
444
445private:
446
447 friend class AssignProxy;
448
449 // The number of elements.
450 enum { Size = 0 };
451
452 // A place to store a zero element.
453 // We need to return a reference to this
454 // for the diagonal element.
455 static T Zero;
456};
457
458
459// Assign the static zero element value:
460template<class T>
462
463
464
466//
467// Free functions
468//
470
471template <class T, unsigned D>
472inline T trace(const AntiSymTenzor<T,D>&) {
473 return T(0.0);
474}
475
476template <class T, unsigned D>
478 return -rhs;
479}
480
481// Determinant: only implement for 1D, 2D, 3D:
482
483// For D=3, det is zero, because diagonal elements are zero:
484template<class T>
485inline T
487{
488 return T(0.0);
489}
490// For D=2, det is nonzero; use linear indexing of only stored element:
491template<class T>
492inline T
494{
495 T result;
496 result = t(0)*t(0);
497 return result;
498}
499// For D=1, det is zero, because diagonal elements are zero:
500template<class T>
501inline T
503{
504 return T(0.0);
505}
506
507// cofactors() - pow(-1, i+j)*M(i,j), where M(i,j) is a minor of the tensor.
508// See, for example, Arfken, Mathematical Methods for Physicists, 2nd Edition,
509// p. 157 (the section where the determinant of a matrix is defined).
510
511// Only implement for 1D, 2D, 3D:
512
513template <class T, unsigned D>
515 PInsist(D<4, "AntiSymTenzor cofactors() function not implemented for D>3!");
516 return Tenzor<T,D>(-999999.999999);
517}
518
519template <class T>
521
522 Tenzor<T,3> result = typename Tenzor<T,3>::DontInitialize();
523
524 result(0,0) = rhs(1,1)*rhs(2,2) - rhs(1,2)*rhs(2,1);
525 result(1,0) = rhs(0,2)*rhs(2,1) - rhs(0,1)*rhs(2,2);
526 result(2,0) = rhs(0,1)*rhs(1,2) - rhs(1,1)*rhs(0,2);
527 result(0,1) = rhs(2,0)*rhs(1,2) - rhs(1,0)*rhs(2,2);
528 result(1,1) = rhs(0,0)*rhs(2,2) - rhs(0,2)*rhs(2,0);
529 result(2,1) = rhs(1,0)*rhs(0,2) - rhs(0,0)*rhs(1,2);
530 result(0,2) = rhs(1,0)*rhs(2,1) - rhs(2,0)*rhs(1,1);
531 result(1,2) = rhs(0,1)*rhs(2,0) - rhs(0,0)*rhs(2,1);
532 result(2,2) = rhs(0,0)*rhs(1,1) - rhs(1,0)*rhs(0,1);
533 return result;
534}
535
536template <class T>
538
539 Tenzor<T,2> result = typename Tenzor<T,2>::DontInitialize();
540
541 result(0,0) = rhs(1,1);
542 result(1,0) = -rhs(0,1);
543 result(0,1) = -rhs(1,0);
544 result(1,1) = rhs(0,0);
545 return result;
546}
547
548// For D=1, cofactor is the unit tensor, because det = single tensor element
549// value:
550template <class T>
552 Tenzor<T,1> result = Tenzor<T,1>(1);
553 return result;
554}
555
556
558//
559// Unary Operators
560//
562
563//----------------------------------------------------------------------
564// unary operator-
565template<class T, unsigned D>
567{
568 return TSV_MetaUnary< AntiSymTenzor<T,D> , OpUnaryMinus > :: apply(op);
569}
570
571//----------------------------------------------------------------------
572// unary operator+
573template<class T, unsigned D>
575{
576 return op;
577}
578
580//
581// Binary Operators
582//
584
585//
586// Elementwise operators.
587//
588
595
596//----------------------------------------------------------------------
597// dot products.
598//----------------------------------------------------------------------
599
600template < class T1, class T2, unsigned D >
603{
605 apply(lhs,rhs);
606}
607
608template < class T1, class T2, unsigned D >
610dot(const AntiSymTenzor<T1,D> &lhs, const Tenzor<T2,D> &rhs)
611{
613 apply(Tenzor<T1,D>(lhs),rhs);
614}
615
616template < class T1, class T2, unsigned D >
618dot(const Tenzor<T1,D> &lhs, const AntiSymTenzor<T2,D> &rhs)
619{
621 apply(lhs,Tenzor<T2,D>(rhs));
622}
623
624template < class T1, class T2, unsigned D >
627{
629 apply(Tenzor<T1,D>(lhs),Tenzor<T2,D>(rhs));
630}
631
632template < class T1, class T2, unsigned D >
635{
637 apply(Tenzor<T1,D>(lhs),Tenzor<T2,D>(rhs));
638}
639
640template < class T1, class T2, unsigned D >
642dot(const Vektor<T1,D> &lhs, const AntiSymTenzor<T2,D> &rhs)
643{
644 return TSV_MetaDot< Vektor<T1,D> , AntiSymTenzor<T2,D> > :: apply(lhs,rhs);
645}
646
647template < class T1, class T2, unsigned D >
649dot(const AntiSymTenzor<T1,D> &lhs, const Vektor<T2,D> &rhs)
650{
651 return TSV_MetaDot< AntiSymTenzor<T1,D> , Vektor<T2,D> > :: apply(lhs,rhs);
652}
653
654//----------------------------------------------------------------------
655// double dot products.
656//----------------------------------------------------------------------
657
658template < class T1, class T2, unsigned D >
661{
663 apply(lhs,rhs);
664}
665
666template < class T1, class T2, unsigned D >
669{
671 apply(Tenzor<T1,D>(lhs),rhs);
672}
673
674template < class T1, class T2, unsigned D >
677{
679 apply(lhs,Tenzor<T2,D>(rhs));
680}
681
682template < class T1, class T2, unsigned D >
685{
687 apply(Tenzor<T1,D>(lhs),Tenzor<T2,D>(rhs));
688}
689
690template < class T1, class T2, unsigned D >
693{
695 apply(Tenzor<T1,D>(lhs),Tenzor<T2,D>(rhs));
696}
697
698//----------------------------------------------------------------------
699// I/O
700template<class T, unsigned D>
701inline std::ostream& operator<<(std::ostream& out, const AntiSymTenzor<T,D>& rhs) {
702 if (D >= 1) {
703 for (unsigned int i=0; i<D; i++) {
704 out << "(";
705 for (unsigned int j=0; j<D-1; j++) {
706 out << rhs(i,j) << " , ";
707 }
708 out << rhs(i,D-1) << ")";
709 // I removed this. --TJW: if (i < D - 1) out << endl;
710 }
711 } else {
712 out << "( " << rhs(0,0) << " )";
713 }
714 return out;
715}
716
718
719#endif // ANTI_SYM_TENZOR_H
std::complex< double > a
PETE_TTTree< OpWhere, typename Cond_t::PETE_Expr_t, typename True_t::PETE_Expr_t, PETE_Scalar< Vektor< T, Dim > > > where(const PETE_Expr< Cond_t > &c, const PETE_Expr< True_t > &t, const Vektor< T, Dim > &f)
PETEBinaryReturn< T1, T2, OpMultipply >::type dotdot(const AntiSymTenzor< T1, D > &lhs, const AntiSymTenzor< T2, D > &rhs)
std::ostream & operator<<(std::ostream &out, const AntiSymTenzor< T, D > &rhs)
const AntiSymTenzor< T, D > & operator+(const AntiSymTenzor< T, D > &op)
AntiSymTenzor< T, D > operator-(const AntiSymTenzor< T, D > &op)
Tenzor< T, D > cofactors(const AntiSymTenzor< T, D > &)
T det(const AntiSymTenzor< T, 3 > &)
AntiSymTenzor< T, D > transpose(const AntiSymTenzor< T, D > &rhs)
Tenzor< typename PETEBinaryReturn< T1, T2, OpMultipply >::type, D > dot(const AntiSymTenzor< T1, D > &lhs, const AntiSymTenzor< T2, D > &rhs)
T trace(const AntiSymTenzor< T, D > &)
#define TSV_ELEMENTWISE_OPERATOR(TSV, OP, APP)
Definition: TSVMeta.h:58
#define PInsist(c, m)
Definition: PAssert.h:120
#define PAssert_EQ(a, b)
Definition: PAssert.h:104
#define PAssert(c)
Definition: PAssert.h:102
double Min(double a, double b)
double Max(double a, double b)
constexpr double e
The value of.
Definition: Physics.h:39
Definition: Tenzor.h:35
AntiSymTenzor(DontInitialize)
Definition: AntiSymTenzor.h:48
Message & getMessage(Message &m)
bool operator!=(const AntiSymTenzor< T, D > &that) const
const AntiSymTenzor< T, D > & operator=(const AntiSymTenzor< T, D > &rhs)
Definition: AntiSymTenzor.h:80
AntiSymTenzor< T, D > & operator*=(const AntiSymTenzor< T1, D > &rhs)
Element_t & operator()(unsigned int i)
AssignProxy operator()(unsigned int i, unsigned int j)
Element_t operator[](unsigned int i) const
int get_Size(void) const
AntiSymTenzor< T, D > & operator-=(const AntiSymTenzor< T1, D > &rhs)
AntiSymTenzor(const Tenzor< T, D > &t)
Definition: AntiSymTenzor.h:70
Element_t & operator[](unsigned int i)
friend class AssignProxy
AssignProxy operator()(std::pair< int, int > a)
int size(void) const
Element_t operator()(unsigned int i, unsigned int j) const
AntiSymTenzor< T, D > & operator+=(const AntiSymTenzor< T1, D > &rhs)
Definition: AntiSymTenzor.h:99
Element_t operator()(std::pair< int, int > a) const
Element_t operator()(unsigned int i) const
AntiSymTenzor< T, D > & operator/=(const AntiSymTenzor< T1, D > &rhs)
AntiSymTenzor(const T &x10, const T &x20, const T &x21)
Definition: AntiSymTenzor.h:56
AntiSymTenzor(const AntiSymTenzor< T, D > &rhs)
Definition: AntiSymTenzor.h:63
AntiSymTenzor(const T &x00)
Definition: AntiSymTenzor.h:52
int len(void) const
AntiSymTenzor< T, D > & operator*=(const T &rhs)
bool operator==(const AntiSymTenzor< T, D > &that) const
Message & putMessage(Message &m) const
AntiSymTenzor< T, D > & operator/=(const T &rhs)
const AssignProxy & operator=(const AssignProxy &a)
const AssignProxy & operator=(const Element_t &e)
AssignProxy(const AssignProxy &model)
AssignProxy(Element_t &elem, int where)
AntiSymTenzor< T, 1 > & operator/=(const AntiSymTenzor< T1, 1 > &)
AntiSymTenzor(const Tenzor< T, 1 > &)
AntiSymTenzor< T, 1 > & operator-=(const AntiSymTenzor< T1, 1 > &)
const AntiSymTenzor< T, 1 > & operator=(const AntiSymTenzor< T, 1 > &)
AntiSymTenzor< T, 1 > & operator/=(const T &)
AntiSymTenzor(DontInitialize)
const AntiSymTenzor< T, 1 > & operator=(const T &rhs)
AntiSymTenzor< T, 1 > & operator*=(const T &)
Element_t operator()(unsigned int i, unsigned int j) const
Element_t operator()(std::pair< int, int > a) const
Message & putMessage(Message &m) const
AntiSymTenzor(const AntiSymTenzor< T, 1 > &)
int get_Size(void) const
AssignProxy operator()(unsigned int i, unsigned int j)
AntiSymTenzor< T, 1 > & operator+=(const AntiSymTenzor< T1, 1 > &)
int size(void) const
Element_t operator[](unsigned int i) const
Message & getMessage(Message &m)
bool operator!=(const AntiSymTenzor< T, 1 > &that) const
int len(void) const
AntiSymTenzor< T, 1 > & operator*=(const AntiSymTenzor< T1, 1 > &)
Element_t operator()(unsigned int i) const
const AntiSymTenzor< T, 1 > & operator=(const AntiSymTenzor< T1, 1 > &)
AssignProxy operator()(std::pair< int, int > a)
bool operator==(const AntiSymTenzor< T, 1 > &) const
const AssignProxy & operator=(const AssignProxy &a)
const AssignProxy & operator=(const Element_t &e)
AssignProxy(Element_t &elem, int where)
AssignProxy(const AssignProxy &model)
Definition: Vektor.h:32
Message & setCopy(const bool c)
Definition: Message.h:319
Message & put(const T &val)
Definition: Message.h:406
Message & get(const T &cval)
Definition: Message.h:476
PETE_ComputeBinaryType< T1, T2, Op, Op::tag >::type type