QMCPACK
Tensor.h
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
9 // Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
10 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
11 //
12 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
13 //////////////////////////////////////////////////////////////////////////////////////
14 
15 
16 #ifndef OHMMS_TENSOR_H
17 #define OHMMS_TENSOR_H
18 
19 #include "PETE/PETE.h"
21 /***************************************************************************
22  *
23  * The POOMA Framework
24  *
25  * This program was prepared by the Regents of the University of
26  * California at Los Alamos National Laboratory (the University) under
27  * Contract No. W-7405-ENG-36 with the U.S. Department of Energy (DOE).
28  * The University has certain rights in the program pursuant to the
29  * contract and the program should not be copied or distributed outside
30  * your organization. All rights in the program are reserved by the DOE
31  * and the University. Neither the U.S. Government nor the University
32  * makes any warranty, express or implied, or assumes any liability or
33  * responsibility for the use of this software
34  *
35  * Visit http://www.acl.lanl.gov/POOMA for more details
36  *
37  ***************************************************************************/
38 
39 
40 namespace qmcplusplus
41 {
42 // forward declarations
43 template<class T, unsigned D>
44 class SymTensor;
45 template<class T, unsigned D>
46 class AntiSymTensor;
47 
48 
49 /** Tensor<T,D> class for D by D tensor
50  *
51  * @tparam T datatype
52  * @tparam D dimension
53  */
54 template<class T, unsigned D>
55 class Tensor
56 {
57 public:
58  using Type_t = T;
59  enum
60  {
61  ElemDim = 2
62  };
63  enum
64  {
65  Size = D * D
66  };
67 
68  // Default Constructor
69  inline Tensor()
70  {
71  for (size_t d = 0; d < Size; ++d)
72  X[d] = T(0);
73  }
74 
75  // A noninitializing ctor.
77  {};
78  inline Tensor(DontInitialize) {}
79 
80  // Copy Constructor
81  inline Tensor(const Tensor& rhs) = default;
82 
83  template<class T1>
84  inline Tensor(const Tensor<T1, D>& rhs)
85  {
86  for (size_t d = 0; d < Size; ++d)
87  X[d] = rhs[d];
88  }
89 
90  // constructor from a single T
91  inline Tensor(const T& x00)
92  {
93  for (size_t d = 0; d < Size; ++d)
94  X[d] = x00;
95  }
96 
97  // constructors for fixed dimension
98  Tensor(const T& x00, const T& x10, const T& x01, const T& x11)
99  {
100  X[0] = x00;
101  X[1] = x10;
102  X[2] = x01;
103  X[3] = x11;
104  }
105 
106  Tensor(const T& x00,
107  const T& x10,
108  const T& x20,
109  const T& x01,
110  const T& x11,
111  const T& x21,
112  const T& x02,
113  const T& x12,
114  const T& x22)
115  {
116  X[0] = x00;
117  X[1] = x10;
118  X[2] = x20;
119  X[3] = x01;
120  X[4] = x11;
121  X[5] = x21;
122  X[6] = x02;
123  X[7] = x12;
124  X[8] = x22;
125  }
126 
127  //constructor from SymTensor
128  Tensor(const SymTensor<T, D>&);
129 
130  // constructor from AntiSymTensor
131  Tensor(const AntiSymTensor<T, D>&);
132 
133  // destructor
134  ~Tensor(){};
135 
136  // assignment operators
137  inline Tensor& operator=(const Tensor& rhs) = default;
138 
139  template<class T1>
141  {
142  OTAssign<Tensor<T, D>, Tensor<T1, D>, OpAssign>::apply(*this, rhs, OpAssign());
143  return *this;
144  }
145  inline Tensor<T, D>& operator=(const T& rhs)
146  {
147  OTAssign<Tensor<T, D>, T, OpAssign>::apply(*this, rhs, OpAssign());
148  return *this;
149  }
150 
151  // accumulation operators
152  template<class T1>
154  {
156  return *this;
157  }
158  inline Tensor<T, D>& operator+=(const T& rhs)
159  {
160  OTAssign<Tensor<T, D>, T, OpAddAssign>::apply(*this, rhs, OpAddAssign());
161  return *this;
162  }
163 
164  template<class T1>
166  {
168  return *this;
169  }
170 
171  inline Tensor<T, D>& operator-=(const T& rhs)
172  {
173  OTAssign<Tensor<T, D>, T, OpSubtractAssign>::apply(*this, rhs, OpSubtractAssign());
174  return *this;
175  }
176 
177  template<class T1>
179  {
181  return *this;
182  }
183 
184  inline Tensor<T, D>& operator*=(const T& rhs)
185  {
186  OTAssign<Tensor<T, D>, T, OpMultiplyAssign>::apply(*this, rhs, OpMultiplyAssign());
187  return *this;
188  }
189 
190  template<class T1>
192  {
194  return *this;
195  }
196 
197  inline Tensor<T, D>& operator/=(const T& rhs)
198  {
199  OTAssign<Tensor<T, D>, T, OpDivideAssign>::apply(*this, rhs, OpDivideAssign());
200  return *this;
201  }
202 
203  // Methods
204 
205  inline void diagonal(const T& rhs)
206  {
207  for (int i = 0; i < D; i++)
208  (*this)(i, i) = rhs;
209  }
210 
211  inline void add2diagonal(T rhs)
212  {
213  for (int i = 0; i < D; i++)
214  (*this)(i, i) += rhs;
215  }
216 
217  ///return the size
218  inline int len() const { return Size; }
219  ///return the size
220  inline int size() const { return Size; }
221 
222  /** return the i-th value or assign
223  * @param i index [0,D*D)
224  */
225  inline Type_t& operator[](unsigned int i) { return X[i]; }
226 
227  /** return the i-th value
228  * @param i index [0,D*D)
229  */
230  inline Type_t operator[](unsigned int i) const { return X[i]; }
231 
232  //TJW: add these 12/16/97 to help with NegReflectAndZeroFace BC:
233  // These are the same as operator[] but with () instead:
234  inline Type_t& operator()(unsigned int i) { return X[i]; }
235 
236  inline Type_t operator()(unsigned int i) const { return X[i]; }
237  //TJW.
238 
239  /** return the (i,j) component
240  * @param i index [0,D)
241  * @param j index [0,D)
242  */
243  inline Type_t operator()(unsigned int i, unsigned int j) const { return X[i * D + j]; }
244 
245  /** return/assign the (i,j) component
246  * @param i index [0,D)
247  * @param j index [0,D)
248  */
249  inline Type_t& operator()(unsigned int i, unsigned int j) { return X[i * D + j]; }
250 
251  inline TinyVector<T, D> getRow(unsigned int i)
252  {
253  TinyVector<T, D> res;
254  for (int j = 0; j < D; j++)
255  res[j] = X[i * D + j];
256  return res;
257  }
258 
259  inline TinyVector<T, D> getColumn(unsigned int i)
260  {
261  TinyVector<T, D> res;
262  for (int j = 0; j < D; j++)
263  res[j] = X[j * D + i];
264  return res;
265  }
266 
267  inline Type_t* data() { return X; }
268  inline const Type_t* data() const { return X; }
269  inline Type_t* begin() { return X; }
270  inline const Type_t* begin() const { return X; }
271  inline Type_t* end() { return X + Size; }
272  inline const Type_t* end() const { return X + Size; }
273 
274  // Removed operator using std::pair
275  // Type_t operator()(const std::pair<int,int> i) const {
276  // PAssert ( (i.first>=0) && (i.second>=0) && (i.first<D) && (i.second<D) );
277  // return (*this)(i.first,i.second);
278  // }
279 
280  // Type_t& operator()(const std::pair<int,int> i) {
281  // PAssert ( (i.first>=0) && (i.second>=0) && (i.first<D) && (i.second<D) );
282  // return (*this)(i.first,i.second);
283  // }
284 
285 
286  //----------------------------------------------------------------------
287  // Comparison operators.
288  // bool operator==(const Tensor<T,D>& that) const {
289  // return MetaCompareArrays<T,T,D*D>::apply(X,that.X);
290  // }
291  // bool operator!=(const Tensor<T,D>& that) const {
292  // return !(*this == that);
293  // }
294 
295  //----------------------------------------------------------------------
296  // parallel communication
297  // Message& putMessage(Message& m) const {
298  // m.setCopy(true);
299  // const T *p = X;
300  // ::putMessage(m, p, p + D*D);
301  // return m;
302  // }
303 
304  // Message& getMessage(Message& m) {
305  // T *p = X;
306  // ::getMessage(m, p, p + D*D);
307  // return m;
308  // }
309 
310 private:
311  // The elements themselves.
312  T X[Size];
313 };
314 
315 
316 //////////////////////////////////////////////////////////////////////
317 //
318 // Free functions
319 //
320 //////////////////////////////////////////////////////////////////////
321 
322 /** trace \f$ result = \sum_k rhs(k,k)\f$
323  * @param rhs a tensor
324  */
325 template<class T, unsigned D>
326 inline T trace(const Tensor<T, D>& rhs)
327 {
328  T result = 0.0;
329  for (int i = 0; i < D; i++)
330  result += rhs(i, i);
331  return result;
332 }
333 
334 /** transpose a tensor
335  */
336 template<class T, unsigned D>
338 {
339  Tensor<T, D> result; // = Tensor<T,D>::DontInitialize();
340  for (int j = 0; j < D; j++)
341  for (int i = 0; i < D; i++)
342  result(i, j) = rhs(j, i);
343  return result;
344 }
345 
346 /** Tr(a*b), \f$ \sum_i\sum_j a(i,j)*b(j,i) \f$
347  */
348 template<class T1, class T2, unsigned D>
349 inline T1 trace(const Tensor<T1, D>& a, const Tensor<T2, D>& b)
350 {
351  T1 result = 0.0;
352  for (int i = 0; i < D; i++)
353  for (int j = 0; j < D; j++)
354  result += a(i, j) * b(j, i);
355  return result;
356 }
357 
358 /** Tr(a^t *b), \f$ \sum_i\sum_j a(i,j)*b(i,j) \f$
359  */
360 template<class T, unsigned D>
361 inline T traceAtB(const Tensor<T, D>& a, const Tensor<T, D>& b)
362 {
363  T result = 0.0;
364  for (int i = 0; i < D * D; i++)
365  result += a(i) * b(i);
366  return result;
367 }
368 
369 /** Tr(a^t *b), \f$ \sum_i\sum_j a(i,j)*b(i,j) \f$
370  */
371 template<class T1, class T2, unsigned D>
373 {
374  using T = typename BinaryReturn<T1, T2, OpMultiply>::Type_t;
375  T result = 0.0;
376  for (int i = 0; i < D * D; i++)
377  result += a(i) * b(i);
378  return result;
379 }
380 
381 //////////////////////////////////////////////////////////////////////
382 //
383 // Unary Operators
384 //
385 //////////////////////////////////////////////////////////////////////
386 //----------------------------------------------------------------------
387 // unary operator-
388 //template<class T, unsigned D>
389 //inline Tensor<T,D> operator-(const Tensor<T,D> &op)
390 //{
391 // return MetaUnary< Tensor<T,D> , OpUnaryMinus > :: apply(op,OpUnaryMinus());
392 //}
393 //----------------------------------------------------------------------
394 // unary operator+
395 //template<class T, unsigned D>
396 //inline const Tensor<T,D> &operator+(const Tensor<T,D> &op)
397 //{
398 // return op;
399 //}
400 
401 /// Binary Operators
402 OHMMS_META_BINARY_OPERATORS(Tensor, operator+, OpAdd)
403 OHMMS_META_BINARY_OPERATORS(Tensor, operator-, OpSubtract)
404 OHMMS_META_BINARY_OPERATORS(Tensor, operator*, OpMultiply)
405 OHMMS_META_BINARY_OPERATORS(Tensor, operator/, OpDivide)
406 //TSV_ELEMENTWISE_OPERATOR(Tensor,Min,FnMin)
407 //TSV_ELEMENTWISE_OPERATOR(Tensor,Max,FnMax)
408 
409 /** Tensor-Tensor dot product \f$result(i,j)=\sum_k lhs(i,k)*rhs(k,j)\f$
410  * @param lhs a tensor
411  * @param rhs a tensor
412  */
413 template<class T1, class T2, unsigned D>
415  const Tensor<T2, D>& rhs)
416 {
417  return OTDot<Tensor<T1, D>, Tensor<T2, D>>::apply(lhs, rhs);
418 }
419 
420 /** Vector-Tensor dot product \f$result(i)=\sum_k lhs(k)*rhs(k,i)\f$
421  * @param lhs a vector
422  * @param rhs a tensor
423  */
424 template<class T1, class T2, unsigned D>
426  const Tensor<T2, D>& rhs)
427 {
428  return OTDot<TinyVector<T1, D>, Tensor<T2, D>>::apply(lhs, rhs);
429 }
430 
431 /** Tensor-Vector dot product \f$result(i)=\sum_k lhs(i,k)*rhs(k)\f$
432  * @param lhs a tensor
433  * @param rhs a vector
434  */
435 template<class T1, class T2, unsigned D>
437  const TinyVector<T2, D>& rhs)
438 {
439  return OTDot<Tensor<T1, D>, TinyVector<T2, D>>::apply(lhs, rhs);
440 }
441 
442 //----------------------------------------------------------------------
443 // double dot product.
444 //----------------------------------------------------------------------
445 
446 // template < class T1, class T2, unsigned D >
447 // inline typename BinaryReturn<T1,T2,OpMultiply>::Type_t
448 // dotdot(const Tensor<T1,D> &lhs, const Tensor<T2,D> &rhs)
449 // {
450 // return MetaDotDot< Tensor<T1,D> , Tensor<T2,D> > :: apply(lhs,rhs);
451 //}
452 
453 
454 //----------------------------------------------------------------------
455 // Outer product.
456 //----------------------------------------------------------------------
457 
458 ///** Vector-vector outter product \f$ result(i,j)=v1(i)*v2(j)\f$
459 // * @param v1 a vector
460 // * @param v2 a vector
461 // */
462 // template<class T1, class T2, unsigned int D>
463 // inline Tensor<typename BinaryReturn<T1,T2,OpMultiply>::type,D >
464 // outerProduct(const TinyVector<T1,D>& v1, const TinyVector<T2,D>& v2)
465 // {
466 // using T0 = typename BinaryReturn<T1,T2,OpMultiply>::Type_t;
467 //// //#if (defined(POOMA_SGI_CC_721_TYPENAME_BUG) || defined(__MWERKS__))
468 //// //Tensor<T0,D> ret = Tensor<T0,D>::DontInitialize();
469 //// //#else
470 // Tensor<T0,D> ret = typename Tensor<T0,D>::DontInitialize();
471 //// //#endif // POOMA_SGI_CC_721_TYPENAME_BUG
472 // for (unsigned int i=0; i<D; ++i)
473 // for (unsigned int j=0; j<D; ++j)
474 // ret(i,j) = v1[i]*v2[j];
475 // return ret;
476 // }
477 //
478 // template<class T1, unsigned int D>
479 // inline Tensor<T1,D >
480 // outerProduct(const TinyVector<T1,D>& v1, const TinyVector<T1,D>& v2)
481 // {
482 // Tensor<T1,D> ret = typename Tensor<T1,D>::DontInitialize();
483 //// //#endif // POOMA_SGI_CC_721_TYPENAME_BUG
484 // for (unsigned int i=0; i<D; ++i)
485 // for (unsigned int j=0; j<D; ++j)
486 // ret(i,j) = v1[i]*v2[j];
487 // return ret;
488 // }
489 //
490 
491 
492 //----------------------------------------------------------------------
493 // I/O
494 template<class T, unsigned D>
495 std::ostream& operator<<(std::ostream& out, const Tensor<T, D>& rhs)
496 {
497  if (D >= 1)
498  {
499  for (int i = 0; i < D; i++)
500  {
501  for (int j = 0; j < D - 1; j++)
502  {
503  out << rhs(i, j) << " ";
504  }
505  out << rhs(i, D - 1) << " ";
506  if (i < D - 1)
507  out << std::endl;
508  }
509  }
510  else
511  {
512  out << " " << rhs(0, 0) << " ";
513  }
514  return out;
515 }
516 
517 template<class T, unsigned D>
518 std::istream& operator>>(std::istream& is, Tensor<T, D>& rhs)
519 {
520  for (int i = 0; i < D * D; i++)
521  is >> rhs[i];
522  return is;
523 }
524 
525 template<class T, unsigned D>
526 bool operator==(const Tensor<T, D>& lhs, const Tensor<T, D>& rhs)
527 {
528  for (int i = 0; i < D * D; i++)
529  if (lhs[i] != rhs[i])
530  return false;
531  return true;
532 }
533 
534 template<class T, unsigned D>
535 bool operator!=(const Tensor<T, D>& lhs, const Tensor<T, D>& rhs)
536 {
537  return !(lhs == rhs);
538 }
539 
540 } // namespace qmcplusplus
541 // include header files for SymTensor and AntiSymTensor in order
542 // to define constructors for Tensor using these types
543 #include "OhmmsPETE/SymTensor.h"
544 #include "OhmmsPETE/AntiSymTensor.h"
545 
546 namespace qmcplusplus
547 {
548 template<class T, unsigned D>
550 {
551  for (int i = 0; i < D; ++i)
552  for (int j = 0; j < D; ++j)
553  (*this)(i, j) = rhs(i, j);
554 }
555 
556 template<class T, unsigned D>
558 {
559  for (int i = 0; i < D; ++i)
560  for (int j = 0; j < D; ++j)
561  (*this)(i, j) = rhs(i, j);
562 }
563 
564 } // namespace qmcplusplus
565 
566 #endif // OHMMS_TENSOR_H
typename Promote< T1, T2 >::Type_t Type_t
TinyVector< T, D > getRow(unsigned int i)
Definition: Tensor.h:251
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
Tensor(DontInitialize)
Definition: Tensor.h:78
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
Tensor< T, D > & operator=(const T &rhs)
Definition: Tensor.h:145
Tensor< T, D > & operator+=(const T &rhs)
Definition: Tensor.h:158
Tensor< T, D > & operator+=(const Tensor< T1, D > &rhs)
Definition: Tensor.h:153
bool operator==(const Matrix< T, Alloc > &lhs, const Matrix< T, Alloc > &rhs)
Definition: OhmmsMatrix.h:388
const Type_t * end() const
Definition: Tensor.h:272
const Type_t * begin() const
Definition: Tensor.h:270
T traceAtB(const Tensor< T, D > &a, const Tensor< T, D > &b)
Tr(a^t *b), .
Definition: Tensor.h:361
Tensor(const Tensor< T1, D > &rhs)
Definition: Tensor.h:84
Tensor< T, D > & operator-=(const T &rhs)
Definition: Tensor.h:171
Tensor< T, D > & operator/=(const T &rhs)
Definition: Tensor.h:197
TinyVector< T, D > getColumn(unsigned int i)
Definition: Tensor.h:259
Tensor<T,D> class for D by D tensor.
Definition: OhmmsTinyMeta.h:32
Tensor< T, D > & operator=(const Tensor< T1, D > &rhs)
Definition: Tensor.h:140
Tensor< T, D > & operator*=(const T &rhs)
Definition: Tensor.h:184
Tensor< T, D > & operator-=(const Tensor< T1, D > &rhs)
Definition: Tensor.h:165
Tensor & operator=(const Tensor &rhs)=default
#define OHMMS_META_BINARY_OPERATORS(TENT, FUNC, TAG)
Definition: OhmmsTinyMeta.h:75
AntiSymTensor< T, D > transpose(const AntiSymTensor< T, D > &rhs)
Tensor< T, D > & operator/=(const Tensor< T1, D > &rhs)
Definition: Tensor.h:191
Type_t operator[](unsigned int i) const
return the i-th value
Definition: Tensor.h:230
void diagonal(const T &rhs)
Definition: Tensor.h:205
int size() const
return the size
Definition: Tensor.h:220
Tensor< T, D > & operator*=(const Tensor< T1, D > &rhs)
Definition: Tensor.h:178
Type_t & operator()(unsigned int i)
Definition: Tensor.h:234
Type_t * data()
Definition: Tensor.h:267
Tensor< typename BinaryReturn< T1, T2, OpMultiply >::Type_t, D > dot(const AntiSymTensor< T1, D > &lhs, const AntiSymTensor< T2, D > &rhs)
Tensor(const T &x00, const T &x10, const T &x20, const T &x01, const T &x11, const T &x21, const T &x02, const T &x12, const T &x22)
Definition: Tensor.h:106
Type_t & operator()(unsigned int i, unsigned int j)
return/assign the (i,j) component
Definition: Tensor.h:249
Type_t * begin()
Definition: Tensor.h:269
std::istream & operator>>(std::istream &is, Matrix< T, Alloc > &rhs)
Definition: OhmmsMatrix.h:427
const Type_t * data() const
Definition: Tensor.h:268
T trace(const AntiSymTensor< T, D > &)
void add2diagonal(T rhs)
Definition: Tensor.h:211
Tensor(const T &x00)
Definition: Tensor.h:91
bool operator!=(const Matrix< T, Alloc > &lhs, const Matrix< T, Alloc > &rhs)
Definition: OhmmsMatrix.h:403
Type_t operator()(unsigned int i, unsigned int j) const
return the (i,j) component
Definition: Tensor.h:243
int len() const
return the size
Definition: Tensor.h:218
Type_t & operator[](unsigned int i)
return the i-th value or assign
Definition: Tensor.h:225
Type_t * end()
Definition: Tensor.h:271
Type_t operator()(unsigned int i) const
Definition: Tensor.h:236
Tensor(const T &x00, const T &x10, const T &x01, const T &x11)
Definition: Tensor.h:98