PSCF v1.1
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
22namespace 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
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
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
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
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
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
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>
730namespace 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
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
static MPI::Datatype type
MPI Datatype.
Definition: Tensor.h:388
static bool hasType
Is the MPI type initialized?
Definition: Tensor.h:389
Default MpiTraits class.
Definition: MpiTraits.h:40
A Tensor represents a Cartesian tensor.
Definition: Tensor.h:33
void operator/=(double s)
Divide this tensor by scalar s.
Definition: Tensor.h:528
friend bool operator==(const Tensor &t1, const Tensor &t2)
Equality for Tensors.
Definition: Tensor.cpp:43
Tensor & add(const Tensor &t1, const Tensor &t2)
Add tensors t1 and t2.
Definition: Tensor.h:567
Tensor & multiply(const Tensor &t, double s)
Multiply a tensor t by a scalar s.
Definition: Tensor.h:595
Tensor & symmetrize()
Symmetrize this tensor.
Definition: Tensor.h:701
Tensor()
Default constructor.
Definition: Tensor.h:399
Tensor & dyad(const Vector &v1, const Vector &v2)
Create dyad of two vectors.
Definition: Tensor.h:763
Tensor & subtract(const Tensor &t1, const Tensor &t2)
Subtract tensor t2 from t1.
Definition: Tensor.h:581
const double & operator()(int i, int j) const
Return one element by value.
Definition: Tensor.h:539
friend std::ostream & operator<<(std::ostream &out, const Tensor &tensor)
ostream inserter for a Tensor.
Definition: Tensor.cpp:104
Tensor & setColumn(int i, const Vector &r)
Set column i of this Tensor to elements of Vector r.
Definition: Tensor.h:749
void operator-=(const Tensor &dt)
Subtract tensor dt from this tensor.
Definition: Tensor.h:506
double trace() const
Return the trace of this tensor.
Definition: Tensor.h:621
void operator*=(double s)
Multiply this tensor by scalar s.
Definition: Tensor.h:517
Tensor & zero()
Set all elements of this tensor to zero.
Definition: Tensor.h:441
Tensor & operator=(const Tensor &t)
Copy assignment.
Definition: Tensor.h:468
friend std::istream & operator>>(std::istream &in, Tensor &tensor)
istream extractor for a Tensor.
Definition: Tensor.cpp:93
Tensor & divide(const Tensor &t, double s)
Divide a Tensor t by a scalar s.
Definition: Tensor.h:609
static const Tensor Zero
Constant Tensor with all zero elements.
Definition: Tensor.h:297
void operator+=(const Tensor &dt)
Add tensor dt to this tensor.
Definition: Tensor.h:495
Tensor & setRow(int i, const Vector &r)
Set row i of this Tensor to elements of Vector r.
Definition: Tensor.h:737
static void initStatic()
Call to guarantee initialization of Zero and Identity tensors.
Definition: Tensor.cpp:27
Tensor & identity()
Set this to the identity (unity) tensor.
Definition: Tensor.h:453
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
Tensor & transpose()
Transpose this tensor.
Definition: Tensor.h:657
static const Tensor Identity
Constant idenity Tensor (diagonal diagonal elements all 1).
Definition: Tensor.h:302
A Vector is a Cartesian vector.
Definition: Vector.h:76
File containing preprocessor macros for error handling.
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
const int DimensionSq
Square of Dimensionality of space.
Definition: Dimension.h:26
Utility classes for scientific computation.
Definition: accumulators.mod:1
bool operator==(Polynomial< T > const &a, Polynomial< T > const &b)
Equality operator for polynomials.
Definition: Polynomial.h:675
std::istream & operator>>(std::istream &in, Pair< Data > &pair)
Input a Pair from an istream.
Definition: Pair.h:44
std::ostream & operator<<(std::ostream &out, const Pair< Data > &pair)
Output a Pair to an ostream, without line breaks.
Definition: Pair.h:57
bool operator!=(Polynomial< T > const &a, Polynomial< T > const &b)
Inequality operator for polynomials.
Definition: Polynomial.h:694