OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
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"
13 #include "PETE/IpplExpressions.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 
32 template<class T, unsigned D>
34 {
35 public:
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.
47  class DontInitialize {};
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.
70  AntiSymTenzor( const Tenzor<T,D>& t ) {
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 
148  class AssignProxy {
149  public:
151  : elem_m(elem), where_m(where) { }
152  AssignProxy(const AssignProxy &model)
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 
175  int where_m;
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 
256 private:
257 
258  friend class AssignProxy;
259 
260  // The elements themselves.
261  T X[Size];
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:
271 template<class T, unsigned int D>
273 
274 
275 
277 // Specialization for 1D -- this is basically just the zero tensor
279 
280 template <class T>
281 class AntiSymTenzor<T,1>
282 {
283 public:
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 
349  class AssignProxy {
350  public:
352  : elem_m(elem), where_m(where) {}
353  AssignProxy(const AssignProxy& model)
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 
376  int where_m;
377  };
378 
379  // Operators
380 
381  Element_t operator()(unsigned int i, unsigned int j) const {
382  PAssert_EQ(i, j);
383  return T(0.0);
384  }
385 
386  Element_t operator()( std::pair<int,int> a) const {
387  int i = a.first;
388  int j = a.second;
389  return (*this)(i, j);
390  }
391 
392  AssignProxy operator()(unsigned int i, unsigned int j) {
393  PAssert_EQ(i, j);
395  }
396 
397  AssignProxy operator()(std::pair<int,int> a) {
398  int i = a.first;
399  int j = a.second;
400  return (*this)(i, j);
401  }
402 
403  Element_t operator[](unsigned int i) const {
404  PAssert (i == 0);
406  }
407 
408  // These are the same as operator[] but with () instead:
409 
410  Element_t operator()(unsigned int i) const {
411  PAssert (i == 0);
413  }
414 
415  //----------------------------------------------------------------------
416  // Comparison operators.
417  bool operator==(const AntiSymTenzor<T,1>& /*that*/) const {
418  return true;
419  }
420  bool operator!=(const AntiSymTenzor<T,1>& that) const {
421  return !(*this == that);
422  }
423 
424  //----------------------------------------------------------------------
425  // parallel communication
427  m.setCopy(true);
429  return m;
430  }
431 
433  T zero;
434  m.get(zero);
435  return m;
436  }
437 
438 private:
439 
440  friend class AssignProxy;
441 
442  // The number of elements.
443  enum { Size = 0 };
444 
445  // A place to store a zero element.
446  // We need to return a reference to this
447  // for the diagonal element.
448  static T Zero;
449 };
450 
451 
452 // Assign the static zero element value:
453 template<class T>
455 
456 
457 
459 //
460 // Free functions
461 //
463 
464 template <class T, unsigned D>
465 inline T trace(const AntiSymTenzor<T,D>&) {
466  return T(0.0);
467 }
468 
469 template <class T, unsigned D>
471  return -rhs;
472 }
473 
474 // Determinant: only implement for 1D, 2D, 3D:
475 
476 // For D=3, det is zero, because diagonal elements are zero:
477 template<class T>
478 inline T
479 det(const AntiSymTenzor<T,3>& /*t*/)
480 {
481  return T(0.0);
482 }
483 // For D=2, det is nonzero; use linear indexing of only stored element:
484 template<class T>
485 inline T
487 {
488  T result;
489  result = t(0)*t(0);
490  return result;
491 }
492 // For D=1, det is zero, because diagonal elements are zero:
493 template<class T>
494 inline T
495 det(const AntiSymTenzor<T,1>& /*t*/)
496 {
497  return T(0.0);
498 }
499 
500 // cofactors() - pow(-1, i+j)*M(i,j), where M(i,j) is a minor of the tensor.
501 // See, for example, Arfken, Mathematical Methods for Physicists, 2nd Edition,
502 // p. 157 (the section where the determinant of a matrix is defined).
503 
504 // Only implement for 1D, 2D, 3D:
505 
506 template <class T, unsigned D>
507 inline Tenzor<T,D> cofactors(const AntiSymTenzor<T,D>& /*rhs*/) {
508  PInsist(D<4, "AntiSymTenzor cofactors() function not implemented for D>3!");
509  return Tenzor<T,D>(-999999.999999);
510 }
511 
512 template <class T>
514 
515  Tenzor<T,3> result = typename Tenzor<T,3>::DontInitialize();
516 
517  result(0,0) = rhs(1,1)*rhs(2,2) - rhs(1,2)*rhs(2,1);
518  result(1,0) = rhs(0,2)*rhs(2,1) - rhs(0,1)*rhs(2,2);
519  result(2,0) = rhs(0,1)*rhs(1,2) - rhs(1,1)*rhs(0,2);
520  result(0,1) = rhs(2,0)*rhs(1,2) - rhs(1,0)*rhs(2,2);
521  result(1,1) = rhs(0,0)*rhs(2,2) - rhs(0,2)*rhs(2,0);
522  result(2,1) = rhs(1,0)*rhs(0,2) - rhs(0,0)*rhs(1,2);
523  result(0,2) = rhs(1,0)*rhs(2,1) - rhs(2,0)*rhs(1,1);
524  result(1,2) = rhs(0,1)*rhs(2,0) - rhs(0,0)*rhs(2,1);
525  result(2,2) = rhs(0,0)*rhs(1,1) - rhs(1,0)*rhs(0,1);
526  return result;
527 }
528 
529 template <class T>
531 
532  Tenzor<T,2> result = typename Tenzor<T,2>::DontInitialize();
533 
534  result(0,0) = rhs(1,1);
535  result(1,0) = -rhs(0,1);
536  result(0,1) = -rhs(1,0);
537  result(1,1) = rhs(0,0);
538  return result;
539 }
540 
541 // For D=1, cofactor is the unit tensor, because det = single tensor element
542 // value:
543 template <class T>
544 inline Tenzor<T,1> cofactors(const AntiSymTenzor<T,1>& /*rhs*/) {
545  Tenzor<T,1> result = Tenzor<T,1>(1);
546  return result;
547 }
548 
549 
551 //
552 // Unary Operators
553 //
555 
556 //----------------------------------------------------------------------
557 // unary operator-
558 template<class T, unsigned D>
560 {
561  return TSV_MetaUnary< AntiSymTenzor<T,D> , OpUnaryMinus > :: apply(op);
562 }
563 
564 //----------------------------------------------------------------------
565 // unary operator+
566 template<class T, unsigned D>
568 {
569  return op;
570 }
571 
573 //
574 // Binary Operators
575 //
577 
578 //
579 // Elementwise operators.
580 //
581 
588 
589 //----------------------------------------------------------------------
590 // dot products.
591 //----------------------------------------------------------------------
592 
593 template < class T1, class T2, unsigned D >
596 {
598  apply(lhs,rhs);
599 }
600 
601 template < class T1, class T2, unsigned D >
603 dot(const AntiSymTenzor<T1,D> &lhs, const Tenzor<T2,D> &rhs)
604 {
606  apply(Tenzor<T1,D>(lhs),rhs);
607 }
608 
609 template < class T1, class T2, unsigned D >
611 dot(const Tenzor<T1,D> &lhs, const AntiSymTenzor<T2,D> &rhs)
612 {
614  apply(lhs,Tenzor<T2,D>(rhs));
615 }
616 
617 template < class T1, class T2, unsigned D >
619 dot(const AntiSymTenzor<T1,D> &lhs, const SymTenzor<T2,D> &rhs)
620 {
622  apply(Tenzor<T1,D>(lhs),Tenzor<T2,D>(rhs));
623 }
624 
625 template < class T1, class T2, unsigned D >
627 dot(const SymTenzor<T1,D> &lhs, const AntiSymTenzor<T2,D> &rhs)
628 {
630  apply(Tenzor<T1,D>(lhs),Tenzor<T2,D>(rhs));
631 }
632 
633 template < class T1, class T2, unsigned D >
635 dot(const Vektor<T1,D> &lhs, const AntiSymTenzor<T2,D> &rhs)
636 {
637  return TSV_MetaDot< Vektor<T1,D> , AntiSymTenzor<T2,D> > :: apply(lhs,rhs);
638 }
639 
640 template < class T1, class T2, unsigned D >
642 dot(const AntiSymTenzor<T1,D> &lhs, const Vektor<T2,D> &rhs)
643 {
644  return TSV_MetaDot< AntiSymTenzor<T1,D> , Vektor<T2,D> > :: apply(lhs,rhs);
645 }
646 
647 //----------------------------------------------------------------------
648 // double dot products.
649 //----------------------------------------------------------------------
650 
651 template < class T1, class T2, unsigned D >
654 {
656  apply(lhs,rhs);
657 }
658 
659 template < class T1, class T2, unsigned D >
661 dotdot(const AntiSymTenzor<T1,D> &lhs, const Tenzor<T2,D> &rhs)
662 {
664  apply(Tenzor<T1,D>(lhs),rhs);
665 }
666 
667 template < class T1, class T2, unsigned D >
669 dotdot(const Tenzor<T1,D> &lhs, const AntiSymTenzor<T2,D> &rhs)
670 {
672  apply(lhs,Tenzor<T2,D>(rhs));
673 }
674 
675 template < class T1, class T2, unsigned D >
678 {
680  apply(Tenzor<T1,D>(lhs),Tenzor<T2,D>(rhs));
681 }
682 
683 template < class T1, class T2, unsigned D >
686 {
688  apply(Tenzor<T1,D>(lhs),Tenzor<T2,D>(rhs));
689 }
690 
691 //----------------------------------------------------------------------
692 // I/O
693 template<class T, unsigned D>
694 inline std::ostream& operator<<(std::ostream& out, const AntiSymTenzor<T,D>& rhs) {
695  if (D >= 1) {
696  for (unsigned int i=0; i<D; i++) {
697  out << "(";
698  for (unsigned int j=0; j<D-1; j++) {
699  out << rhs(i,j) << " , ";
700  }
701  out << rhs(i,D-1) << ")";
702  // I removed this. --TJW: if (i < D - 1) out << endl;
703  }
704  } else {
705  out << "( " << rhs(0,0) << " )";
706  }
707  return out;
708 }
709 
711 
712 #endif // ANTI_SYM_TENZOR_H
AntiSymTenzor< T, D > transpose(const AntiSymTenzor< T, D > &rhs)
Tenzor< T, D > cofactors(const AntiSymTenzor< T, D > &)
const AntiSymTenzor< T, D > & operator+(const AntiSymTenzor< T, D > &op)
AntiSymTenzor< T, D > operator-(const AntiSymTenzor< T, D > &op)
T det(const AntiSymTenzor< T, 3 > &)
std::ostream & operator<<(std::ostream &out, const AntiSymTenzor< T, D > &rhs)
PETEBinaryReturn< T1, T2, OpMultipply >::type dotdot(const AntiSymTenzor< T1, D > &lhs, const AntiSymTenzor< T2, 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
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)
std::complex< double > a
#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
bool operator!=(const AntiSymTenzor< T, D > &that) const
AntiSymTenzor< T, D > & operator+=(const AntiSymTenzor< T1, D > &rhs)
Definition: AntiSymTenzor.h:99
Message & getMessage(Message &m)
AssignProxy operator()(unsigned int i, unsigned int j)
Element_t operator[](unsigned int i) const
AntiSymTenzor< T, D > & operator*=(const T &rhs)
AntiSymTenzor< T, D > & operator/=(const AntiSymTenzor< T1, D > &rhs)
Element_t & operator[](unsigned int i)
int get_Size(void) const
AntiSymTenzor(const Tenzor< T, D > &t)
Definition: AntiSymTenzor.h:70
const AntiSymTenzor< T, D > & operator=(const AntiSymTenzor< T, D > &rhs)
Definition: AntiSymTenzor.h:80
friend class AssignProxy
AssignProxy operator()(std::pair< int, int > a)
AntiSymTenzor< T, D > & operator*=(const AntiSymTenzor< T1, D > &rhs)
int size(void) const
Element_t operator()(unsigned int i, unsigned int j) const
Element_t & operator()(unsigned int i)
Message & putMessage(Message &m) const
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
bool operator==(const AntiSymTenzor< T, D > &that) const
AntiSymTenzor< T, D > & operator/=(const T &rhs)
const AssignProxy & operator=(const AssignProxy &a)
AssignProxy(const AssignProxy &model)
AssignProxy(Element_t &elem, int where)
const AssignProxy & operator=(const Element_t &e)
AntiSymTenzor< T, 1 > & operator-=(const AntiSymTenzor< T1, 1 > &)
AntiSymTenzor(const Tenzor< T, 1 > &)
const AntiSymTenzor< T, 1 > & operator=(const AntiSymTenzor< T1, 1 > &)
AntiSymTenzor< T, 1 > & operator/=(const T &)
AntiSymTenzor(DontInitialize)
const AntiSymTenzor< T, 1 > & operator=(const AntiSymTenzor< T, 1 > &)
AntiSymTenzor< T, 1 > & operator+=(const AntiSymTenzor< T1, 1 > &)
Element_t operator()(unsigned int i, unsigned int j) const
const AntiSymTenzor< T, 1 > & operator=(const T &rhs)
Element_t operator()(std::pair< int, int > a) const
AntiSymTenzor< T, 1 > & operator*=(const AntiSymTenzor< T1, 1 > &)
Message & putMessage(Message &m) const
AntiSymTenzor(const AntiSymTenzor< T, 1 > &)
AntiSymTenzor< T, 1 > & operator*=(const T &)
Message & getMessage(Message &m)
int get_Size(void) const
AntiSymTenzor< T, 1 > & operator/=(const AntiSymTenzor< T1, 1 > &)
AssignProxy operator()(unsigned int i, unsigned int j)
int size(void) const
Element_t operator[](unsigned int i) const
bool operator!=(const AntiSymTenzor< T, 1 > &that) const
int len(void) const
Element_t operator()(unsigned int i) const
AssignProxy operator()(std::pair< int, int > a)
bool operator==(const AntiSymTenzor< T, 1 > &) const
const AssignProxy & operator=(const Element_t &e)
const AssignProxy & operator=(const AssignProxy &a)
AssignProxy(Element_t &elem, int where)
AssignProxy(const AssignProxy &model)
Definition: Vektor.h:32
Message & put(const T &val)
Definition: Message.h:406
Message & setCopy(const bool c)
Definition: Message.h:319
Message & get(const T &cval)
Definition: Message.h:476
PETE_ComputeBinaryType< T1, T2, Op, Op::tag >::type type