Simpatico  v1.10
Tensor.h
1 #ifndef UTIL_TENSOR_H
2 #define UTIL_TENSOR_H
3 
4 /*
5 * Util Package - C++ Utilities for Scientific Computation
6 *
7 * Copyright 2010 - 2017, The Regents of the University of Minnesota
8 * Distributed under the terms of the GNU General Public License.
9 */
10 
11 
12 #include <util/space/Dimension.h>
13 #include <util/global.h>
14 
15 #ifdef UTIL_MPI
16 #include <util/mpi/MpiTraits.h>
17 #endif
18 
19 #include <iostream>
20 #include <cmath>
21 
22 namespace Util
23 {
24 
25  class Vector;
26 
32  class Tensor
33  {
34 
35  public:
36 
38 
39 
43  Tensor();
44 
48  Tensor(const Tensor& t);
49 
55  explicit Tensor(double scalar);
56 
62  explicit Tensor(const double a[][Dimension]);
63 
65 
67 
68 
74  Tensor& operator=(const Tensor& t);
75 
81  Tensor& operator=(const double a[][Dimension]);
82 
84 
86 
94  void operator+=(const Tensor& dt);
95 
103  void operator-=(const Tensor& dt);
104 
112  void operator*=(double s);
113 
121  void operator/=(double s);
122 
124 
126 
134  const double& operator ()(int i, int j) const;
135 
143  double& operator () (int i, int j);
144 
146 
148 
154  Tensor& zero();
155 
161  Tensor& identity();
162 
168  Tensor& setRow(int i, const Vector& r);
169 
175  Tensor& setColumn(int i, const Vector& r);
176 
186  Tensor& add(const Tensor& t1, const Tensor& t2);
187 
197  Tensor& subtract(const Tensor& t1, const Tensor& t2);
198 
208  Tensor& multiply(const Tensor& t, double s);
209 
219  Tensor& divide(const Tensor& t, double s);
220 
229  Tensor& transpose(const Tensor& t);
230 
238  Tensor& transpose();
239 
248  Tensor& symmetrize(const Tensor& t);
249 
258  Tensor& symmetrize();
259 
270  Tensor& dyad(const Vector& v1, const Vector& v2);
271 
273 
275 
279  double trace() const;
280 
287  template <class Archive>
288  void serialize(Archive& ar, const unsigned int version);
289 
291 
293 
297  static const Tensor Zero;
298 
302  static const Tensor Identity;
303 
307  static void initStatic();
308 
309  #ifdef UTIL_MPI
310 
313  static void commitMpiType();
314  #endif
315 
317 
318  private:
319 
321  static const int Width = 13;
322 
324  static const int Precision = 5;
325 
327  double elem_[DimensionSq];
328 
329  //friends:
330 
331  friend bool operator == (const Tensor& t1, const Tensor& t2);
332 
333  friend bool operator == (const Tensor& t1, const double t2[][Dimension]);
334 
335  friend std::istream& operator >> (std::istream& in, Tensor &tensor);
336 
337  friend std::ostream& operator << (std::ostream& out, const Tensor &tensor);
338 
339  };
340 
342  bool operator == (const Tensor& t1, const Tensor& t2);
343 
345  bool operator == (const Tensor& t1, const double t2[][Dimension]);
346 
348  bool operator == (const double t1[][Dimension], const Tensor& t2);
349 
351  bool operator != (const Tensor& t1, const Tensor& t2);
352 
354  bool operator != (const Tensor& t1, const double t2[][Dimension]);
355 
357  bool operator != (const double t1[][Dimension], const Tensor& t2);
358 
368  std::istream& operator >> (std::istream& in, Tensor &tensor);
369 
378  std::ostream& operator << (std::ostream& out, const Tensor &tensor);
379 
380  #ifdef UTIL_MPI
381 
384  template <>
386  {
387  public:
388  static MPI::Datatype type;
389  static bool hasType;
390  };
391  #endif
392 
393  // Inline methods
394 
395  /*
396  * Default constructor
397  */
398  inline
400  {}
401 
402  /*
403  * Copy constructor
404  */
405  inline
407  {
408  for (int i = 0; i < DimensionSq; ++i) {
409  elem_[i] = t.elem_[i];
410  }
411  }
412 
413  /*
414  * Constructor, initialize all elements to a scalar value.
415  */
416  inline
417  Tensor::Tensor(double scalar)
418  {
419  for (int i = 0; i < DimensionSq; ++i) {
420  elem_[i] = scalar;
421  }
422  }
423 
424  /*
425  * Construct Tensor from C double [][Dimension] array.
426  */
427  inline
428  Tensor::Tensor(const double a[][Dimension])
429  {
430  for (int i = 0; i < Dimension; ++i) {
431  for (int j = 0; j < Dimension; ++j) {
432  elem_[i*Dimension + j] = a[i][j];
433  }
434  }
435  }
436 
437  /*
438  * Set all elements of this tensor to zero.
439  */
440  inline
442  {
443  for (int i = 0; i < DimensionSq; ++i) {
444  elem_[i] = 0.0;
445  }
446  return *this;
447  }
448 
449  /*
450  * Set this to the identity (unity) tensor.
451  */
452  inline
454  {
455  for (int i = 0; i < DimensionSq; ++i) {
456  elem_[i] = 0.0;
457  }
458  for (int i = 0; i < Dimension; ++i) {
459  elem_[i*Dimension + i] = 1.0;
460  }
461  return *this;
462  }
463 
464  /*
465  * Assignment.
466  */
467  inline
469  {
470  for (int i = 0; i < DimensionSq; ++i) {
471  elem_[i] = t.elem_[i];
472  }
473  return *this;
474  }
475 
476  /*
477  * Assignment from C double [][Dimension] array.
478  */
479  inline
480  Tensor& Tensor::operator=(const double a[][Dimension])
481  {
482  int i, j;
483  for (i = 0; i < Dimension; ++i) {
484  for (j = 0; j < Dimension; ++j) {
485  elem_[i*Dimension + j] = a[i][j];
486  }
487  }
488  return *this;
489  }
490 
491  /*
492  * Add tensor dt to this tensor.
493  */
494  inline
495  void Tensor::operator+=(const Tensor& dt)
496  {
497  for (int i = 0; i < DimensionSq; ++i) {
498  elem_[i] += dt.elem_[i];
499  }
500  }
501 
502  /*
503  * Subtract tensor dt from this tensor.
504  */
505  inline
506  void Tensor::operator-=(const Tensor& dt)
507  {
508  for (int i = 0; i < DimensionSq; ++i) {
509  elem_[i] -= dt.elem_[i];
510  }
511  }
512 
513  /*
514  * Multiply this tensor by scalar s.
515  */
516  inline
517  void Tensor::operator*=(double s)
518  {
519  for (int i = 0; i < DimensionSq; ++i) {
520  elem_[i] *= s;
521  }
522  }
523 
524  /*
525  * Divide this tensor by scalar s.
526  */
527  inline
528  void Tensor::operator/=(double s)
529  {
530  for (int i = 0; i < DimensionSq; ++i) {
531  elem_[i] /= s;
532  }
533  }
534 
535  /*
536  * Return one element by value.
537  */
538  inline
539  const double& Tensor::operator()(int i, int j) const
540  {
541  assert(i >=0);
542  assert(i < Dimension);
543  assert(j >=0);
544  assert(j < Dimension);
545  return elem_[i*Dimension + j];
546  }
547 
548  /*
549  * Return a reference to one element of the tensor.
550  */
551  inline
552  double& Tensor::operator()(int i, int j)
553  {
554  assert(i >=0);
555  assert(i < Dimension);
556  assert(j >=0);
557  assert(j < Dimension);
558  return elem_[i*Dimension + j];
559  }
560 
561  /*
562  * Add tensors t1 and t2.
563  *
564  * Upon return, *this = t1 + t2.
565  */
566  inline
567  Tensor& Tensor::add(const Tensor& t1, const Tensor& t2)
568  {
569  for (int i = 0; i < DimensionSq; ++i) {
570  elem_[i] = t1.elem_[i] + t2.elem_[i];
571  }
572  return *this;
573  }
574 
575  /*
576  * Subtract tensor t2 from t1.
577  *
578  * Upon return, *this = t1 - t2.
579  */
580  inline
581  Tensor& Tensor::subtract(const Tensor& t1, const Tensor& t2)
582  {
583  for (int i = 0; i < DimensionSq; ++i) {
584  elem_[i] = t1.elem_[i] - t2.elem_[i];
585  }
586  return *this;
587  }
588 
589  /*
590  * Multiply a tensor t by a scalar s.
591  *
592  * Upon return, *this = t*s.
593  */
594  inline
595  Tensor& Tensor::multiply(const Tensor& t, double s)
596  {
597  for (int i = 0; i < DimensionSq; ++i) {
598  elem_[i] = t.elem_[i]*s;
599  }
600  return *this;
601  }
602 
603  /*
604  * Divide tensor t by scalar s.
605  *
606  * Upon return, *this = t/s;
607  */
608  inline
609  Tensor& Tensor::divide(const Tensor& t, double s)
610  {
611  for (int i = 0; i < DimensionSq; ++i) {
612  elem_[i] = t.elem_[i]/s;
613  }
614  return *this;
615  }
616 
617  /*
618  * Return trace of a tensor.
619  */
620  inline
621  double Tensor::trace() const
622  {
623  double trace = 0.0;
624  for (int i = 0; i < Dimension; ++i) {
625  trace += (*this)(i, i);
626  }
627  return trace;
628  }
629 
630  /*
631  * Compute the transpose of a tensor.
632  *
633  * Upon return, this tensor is the transpose of t.
634  */
635  inline
637  {
638  int i, j;
639  for (i = 0; i < Dimension; ++i) {
640  (*this)(i, i) = t(i, i);
641  }
642  for (i = 1; i < Dimension; ++i) {
643  for (j = 0; j < i; ++j) {
644  (*this)(i, j) = t(j, i);
645  (*this)(j, i) = t(i, j);
646  }
647  }
648  return *this;
649  }
650 
651  /*
652  * Transpose this tensor.
653  *
654  * Upon return, this tensor is transposed.
655  */
656  inline
658  {
659  double save;
660  int i, j;
661  for (i = 1; i < Dimension; ++i) {
662  for (j = 0; j < i; ++j) {
663  save = (*this)(i, j);
664  (*this)(i, j) = (*this)(j, i);
665  (*this)(j, i) = save;
666  }
667  }
668  return *this;
669  }
670 
671  /*
672  * Compute symmetric part of a tensor.
673  *
674  * Upon return, this is symmetric part of t:
675  * *this = 0.5*(t + t.transpose());
676  */
677  inline
679  {
680  double ave;
681  int i, j;
682  for (i = 0; i < Dimension; ++i) {
683  (*this)(i, i) = t(i, i);
684  }
685  for (i = 1; i < Dimension; ++i) {
686  for (j = 0; j < i; ++j) {
687  ave = 0.5*( t(i, j) + t(j, i) );
688  (*this)(i, j) = ave;
689  (*this)(j, i) = ave;
690  }
691  }
692  return *this;
693  }
694 
695  /*
696  * Symmetrize this tensor.
697  *
698  * Upon return, t is symmetrized:
699  */
700  inline
702  {
703  double ave;
704  int i, j;
705  for (i = 1; i < Dimension; ++i) {
706  for (j = 0; j < i; ++j) {
707  ave = 0.5*( (*this)(i, j) + (*this)(j, i) );
708  (*this)(i, j) = ave;
709  (*this)(j, i) = ave;
710  }
711  }
712  return *this;
713  }
714 
715  /*
716  * Serialize to/from an archive.
717  */
718  template <class Archive>
719  inline
720  void Tensor::serialize(Archive& ar, const unsigned int version)
721  {
722  for (int i = 0; i < DimensionSq; ++i) {
723  ar & elem_[i];
724  }
725  }
726 
727 }
728 
729 #include <util/space/Vector.h>
730 namespace Util
731 {
732 
733  /*
734  * Set row i of the tensor to elements of vector r.
735  */
736  inline
737  Tensor& Tensor::setRow(int i, const Vector& r)
738  {
739  for (int j = 0; j < Dimension; j++) {
740  elem_[i*Dimension+j] = r[j];
741  }
742  return *this;
743  }
744 
745  /*
746  * Set column i of the tensor to elements of vector r.
747  */
748  inline
749  Tensor& Tensor::setColumn(int j, const Vector& r)
750  {
751  for (int i = 0; i < Dimension; i++) {
752  elem_[i*Dimension+j] = r[i];
753  }
754  return *this;
755  }
756 
757  /*
758  * Multiply two vectors to create a dyadic tensor.
759  *
760  * Upon return, *this = t*s.
761  */
762  inline
763  Tensor& Tensor::dyad(const Vector& v1, const Vector& v2)
764  {
765  int i, j;
766  for (i = 0; i < Dimension; ++i) {
767  for (j = 0; j < Dimension; ++j) {
768  elem_[i*Dimension + j] = v1[i]*v2[j];
769  }
770  }
771  return *this;
772  }
773 
774 }
775 #endif
Tensor & setColumn(int i, const Vector &r)
Set column i of this Tensor to elements of Vector r.
Definition: Tensor.h:749
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
static void initStatic()
Call to guarantee initialization of Zero and Identity tensors.
Definition: Tensor.cpp:27
A Vector is a Cartesian vector.
Definition: Vector.h:75
static MPI::Datatype type
MPI Datatype.
Definition: Tensor.h:388
void operator-=(const Tensor &dt)
Subtract tensor dt from this tensor.
Definition: Tensor.h:506
Tensor & zero()
Set all elements of this tensor to zero.
Definition: Tensor.h:441
Tensor()
Default constructor.
Definition: Tensor.h:399
File containing preprocessor macros for error handling.
Tensor & identity()
Set this to the identity (unity) tensor.
Definition: Tensor.h:453
void operator*=(double s)
Multiply this tensor by scalar s.
Definition: Tensor.h:517
friend std::istream & operator>>(std::istream &in, Tensor &tensor)
istream extractor for a Tensor.
Definition: Tensor.cpp:93
double trace() const
Return the trace of this tensor.
Definition: Tensor.h:621
A Tensor represents a Cartesian tensor.
Definition: Tensor.h:32
Tensor & add(const Tensor &t1, const Tensor &t2)
Add tensors t1 and t2.
Definition: Tensor.h:567
void operator/=(double s)
Divide this tensor by scalar s.
Definition: Tensor.h:528
Tensor & setRow(int i, const Vector &r)
Set row i of this Tensor to elements of Vector r.
Definition: Tensor.h:737
Tensor & transpose()
Transpose this tensor.
Definition: Tensor.h:657
static void commitMpiType()
Commit MPI datatype MpiTraits<Tensor>::type.
Definition: Tensor.cpp:125
void serialize(Archive &ar, const unsigned int version)
Serialize this to/from an archive.
Definition: Tensor.h:720
void operator+=(const Tensor &dt)
Add tensor dt to this tensor.
Definition: Tensor.h:495
Tensor & multiply(const Tensor &t, double s)
Multiply a tensor t by a scalar s.
Definition: Tensor.h:595
Utility classes for scientific computation.
Definition: accumulators.mod:1
Default MpiTraits class.
Definition: MpiTraits.h:39
Tensor & divide(const Tensor &t, double s)
Divide a Tensor t by a scalar s.
Definition: Tensor.h:609
const double & operator()(int i, int j) const
Return one element by value.
Definition: Tensor.h:539
Tensor & symmetrize()
Symmetrize this tensor.
Definition: Tensor.h:701
Tensor & subtract(const Tensor &t1, const Tensor &t2)
Subtract tensor t2 from t1.
Definition: Tensor.h:581
static bool hasType
Is the MPI type initialized?
Definition: Tensor.h:389
const int DimensionSq
Square of Dimensionality of space.
Definition: Dimension.h:26
friend bool operator==(const Tensor &t1, const Tensor &t2)
Equality for Tensors.
Definition: Tensor.cpp:43
Tensor & operator=(const Tensor &t)
Copy assignment.
Definition: Tensor.h:468
static const Tensor Identity
Constant idenity Tensor (diagonal diagonal elements all 1).
Definition: Tensor.h:302
Tensor & dyad(const Vector &v1, const Vector &v2)
Create dyad of two vectors.
Definition: Tensor.h:763
static const Tensor Zero
Constant Tensor with all zero elements.
Definition: Tensor.h:297
friend std::ostream & operator<<(std::ostream &out, const Tensor &tensor)
ostream inserter for a Tensor.
Definition: Tensor.cpp:104
bool operator!=(const PointSymmetry &A, const PointSymmetry &B)
Are two PointSymmetry objects not equivalent?