libMesh
type_tensor.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 #ifndef LIBMESH_TYPE_TENSOR_H
21 #define LIBMESH_TYPE_TENSOR_H
22 
23 // Local includes
24 #include "libmesh/libmesh_common.h"
25 #include "libmesh/type_vector.h"
26 
27 // C++ includes
28 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
29 #include <cmath>
30 #include <tuple>
31 
32 #ifdef LIBMESH_HAVE_METAPHYSICL
33 #include "metaphysicl/dualnumber_decl.h"
34 #endif
35 
36 namespace libMesh
37 {
38 
39 // Forward declarations
40 template <typename T> class TypeTensorColumn;
41 template <typename T> class ConstTypeTensorColumn;
42 template <unsigned int N, typename T> class TypeNTensor;
43 
51 template <typename T>
52 class TypeTensor
53 {
54  template <typename T2>
55  friend class TypeTensor;
56 
57 public:
62  TypeTensor ();
63 
64 protected:
71  explicit TypeTensor (const T & xx,
72  const T & xy=0,
73  const T & xz=0,
74  const T & yx=0,
75  const T & yy=0,
76  const T & yz=0,
77  const T & zx=0,
78  const T & zy=0,
79  const T & zz=0);
80 
81 
85  template <typename Scalar>
86  explicit TypeTensor (const Scalar & xx,
87  const Scalar & xy=0,
88  const Scalar & xz=0,
89  const Scalar & yx=0,
90  const Scalar & yy=0,
91  const Scalar & yz=0,
92  const Scalar & zx=0,
93  const Scalar & zy=0,
94  typename
96  const Scalar>::type & zz=0);
97 
103  template<typename T2>
104  TypeTensor(const TypeVector<T2> & vx);
105 
106  template<typename T2>
107  TypeTensor(const TypeVector<T2> & vx,
108  const TypeVector<T2> & vy);
109 
110  template<typename T2>
111  TypeTensor(const TypeVector<T2> & vx,
112  const TypeVector<T2> & vy,
113  const TypeVector<T2> & vz);
114 
115 public:
116 
120  typedef T value_type;
121 
125  typedef std::tuple<unsigned int, unsigned int> index_type;
126 
130  template<typename T2>
131  TypeTensor(const TypeTensor<T2> & p);
132 
136  ~TypeTensor();
137 
141  template<typename T2>
142  void assign (const TypeTensor<T2> &);
143 
149  template <typename Scalar>
150  typename boostcopy::enable_if_c<
152  TypeTensor &>::type
153  operator = (const Scalar & libmesh_dbg_var(p))
154  { libmesh_assert_equal_to (p, Scalar(0)); this->zero(); return *this; }
155 
159  const T & operator () (const unsigned int i, const unsigned int j) const;
160 
164  T & operator () (const unsigned int i, const unsigned int j);
165 
169  ConstTypeTensorColumn<T> slice (const unsigned int i) const;
170 
174  TypeTensorColumn<T> slice (const unsigned int i);
175 
179  TypeVector<T> row(const unsigned int r) const;
180 
184  TypeVector<T> column(const unsigned int r) const;
185 
191  template<typename T2>
193  operator + (const TypeTensor<T2> &) const;
194 
200  template<typename T2>
201  const TypeTensor<T> & operator += (const TypeTensor<T2> &);
202 
206  template<typename T2>
207  void add (const TypeTensor<T2> &);
208 
212  template <typename T2>
213  void add_scaled (const TypeTensor<T2> &, const T &);
214 
220  template<typename T2>
222  operator - (const TypeTensor<T2> &) const;
223 
229  template<typename T2>
230  const TypeTensor<T> & operator -= (const TypeTensor<T2> &);
231 
235  template<typename T2>
236  void subtract (const TypeTensor<T2> &);
237 
242  template <typename T2>
243  void subtract_scaled (const TypeTensor<T2> &, const T &);
244 
248  TypeTensor<T> operator - () const;
249 
255  template <typename Scalar>
256  auto
257  operator * (const Scalar & scalar) const -> typename boostcopy::enable_if_c<
260 
266  template <typename Scalar, typename boostcopy::enable_if_c<
267  ScalarTraits<Scalar>::value, int>::type = 0>
268  const TypeTensor<T> & operator *= (const Scalar & factor)
269  {
270  for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
271  _coords[i] *= factor;
272 
273  return *this;
274  }
275 
281  template <typename Scalar>
282  typename boostcopy::enable_if_c<
285  operator / (const Scalar &) const;
286 
292  const TypeTensor<T> & operator /= (const T &);
293 
300  template <typename T2>
302  operator * (const TypeTensor<T2> &) const;
303 
309  template <typename T2>
310  const TypeTensor<T> & operator *= (const TypeTensor<T2> &);
311 
321  template <typename T2>
323  contract (const TypeTensor<T2> &) const;
324 
331  template <typename T2>
333  operator * (const TypeVector<T2> &) const;
334 
341  template <typename T2>
343  left_multiply (const TypeVector<T2> & p) const;
344 
348  TypeTensor<T> transpose() const;
349 
353  TypeTensor<T> inverse() const;
354 
361  void solve(const TypeVector<T> & b, TypeVector<T> & x) const;
362 
367  auto norm() const -> decltype(std::norm(T()));
368 
373  auto norm_sq() const -> decltype(std::norm(T()));
374 
378  bool is_zero() const;
379 
386  T det() const;
387 
391  T tr() const;
392 
396  void zero();
397 
401  bool operator == (const TypeTensor<T> & rhs) const;
402 
407  bool operator < (const TypeTensor<T> & rhs) const;
408 
412  bool operator > (const TypeTensor<T> & rhs) const;
413 
417  void print(std::ostream & os = libMesh::out) const;
418 
426  friend std::ostream & operator << (std::ostream & os, const TypeTensor<T> & t)
427  {
428  t.print(os);
429  return os;
430  }
431 
436  void write_unformatted (std::ostream & out_stream,
437  const bool newline = true) const;
438 
439 protected:
440 
444  T _coords[LIBMESH_DIM*LIBMESH_DIM];
445 };
446 
447 
448 template <typename T>
449 class TypeTensorColumn
450 {
451 public:
452 
454  unsigned int j) :
455  _tensor(&tensor), _j(j) {}
456 
461  T & operator () (const unsigned int i)
462  { return (*_tensor)(i,_j); }
463 
464  T & slice (const unsigned int i)
465  { return (*_tensor)(i,_j); }
466 
471  {
472  for (unsigned int i=0; i != LIBMESH_DIM; ++i)
473  (*this)(i) = rhs(i);
474  return *this;
475  }
476 
477 private:
479  const unsigned int _j;
480 };
481 
482 
483 template <typename T>
485 {
486 public:
487 
489  unsigned int j) :
490  _tensor(&tensor), _j(j) {}
491 
495  const T & operator () (const unsigned int i) const
496  { return (*_tensor)(i,_j); }
497 
498  const T & slice (const unsigned int i) const
499  { return (*_tensor)(i,_j); }
500 
501 private:
503  const unsigned int _j;
504 };
505 
506 //------------------------------------------------------
507 // Inline functions
508 template <typename T>
509 inline
511 {
512  _coords[0] = {};
513 
514 #if LIBMESH_DIM > 1
515  _coords[1] = {};
516  _coords[2] = {};
517  _coords[3] = {};
518 #endif
519 
520 #if LIBMESH_DIM > 2
521  _coords[4] = {};
522  _coords[5] = {};
523  _coords[6] = {};
524  _coords[7] = {};
525  _coords[8] = {};
526 #endif
527 }
528 
529 
530 
531 template <typename T>
532 inline
534  const T & xy,
535  const T & xz,
536  const T & yx,
537  const T & yy,
538  const T & yz,
539  const T & zx,
540  const T & zy,
541  const T & zz)
542 {
543  _coords[0] = xx;
544 
545 #if LIBMESH_DIM == 2
546  _coords[1] = xy;
547  _coords[2] = yx;
548  _coords[3] = yy;
549 #elif LIBMESH_DIM == 1
550  libmesh_assert_equal_to (xy, 0);
551  libmesh_assert_equal_to (yx, 0);
552  libmesh_assert_equal_to (yy, 0);
553  libmesh_ignore(xy, yx, yy);
554 #endif
555 
556 #if LIBMESH_DIM == 3
557  _coords[1] = xy;
558  _coords[2] = xz;
559  _coords[3] = yx;
560  _coords[4] = yy;
561  _coords[5] = yz;
562  _coords[6] = zx;
563  _coords[7] = zy;
564  _coords[8] = zz;
565 #else
566  libmesh_assert_equal_to (xz, 0);
567  libmesh_assert_equal_to (yz, 0);
568  libmesh_assert_equal_to (zx, 0);
569  libmesh_assert_equal_to (zy, 0);
570  libmesh_assert_equal_to (zz, 0);
571  libmesh_ignore(xz, yz, zx, zy, zz);
572 #endif
573 }
574 
575 
576 template <typename T>
577 template <typename Scalar>
578 inline
579 TypeTensor<T>::TypeTensor (const Scalar & xx,
580  const Scalar & xy,
581  const Scalar & xz,
582  const Scalar & yx,
583  const Scalar & yy,
584  const Scalar & yz,
585  const Scalar & zx,
586  const Scalar & zy,
587  typename
589  const Scalar>::type & zz)
590 {
591  _coords[0] = xx;
592 
593 #if LIBMESH_DIM == 2
594  _coords[1] = xy;
595  _coords[2] = yx;
596  _coords[3] = yy;
597 #elif LIBMESH_DIM == 1
598  libmesh_assert_equal_to (xy, 0);
599  libmesh_assert_equal_to (yx, 0);
600  libmesh_assert_equal_to (yy, 0);
601  libmesh_ignore(xy, yx, yy);
602 #endif
603 
604 #if LIBMESH_DIM == 3
605  _coords[1] = xy;
606  _coords[2] = xz;
607  _coords[3] = yx;
608  _coords[4] = yy;
609  _coords[5] = yz;
610  _coords[6] = zx;
611  _coords[7] = zy;
612  _coords[8] = zz;
613 #else
614  libmesh_assert_equal_to (xz, 0);
615  libmesh_assert_equal_to (yz, 0);
616  libmesh_assert_equal_to (zx, 0);
617  libmesh_assert_equal_to (zy, 0);
618  libmesh_assert_equal_to (zz, 0);
619  libmesh_ignore(xz, yz, zx, zy, zz);
620 #endif
621 }
622 
623 
624 
625 template <typename T>
626 template<typename T2>
627 inline
629 {
630  // copy the nodes from vector p to me
631  for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
632  _coords[i] = p._coords[i];
633 }
634 
635 
636 template <typename T>
637 template <typename T2>
639 {
640  libmesh_assert_equal_to (LIBMESH_DIM, 1);
641  _coords[0] = vx(0);
642 }
643 
644 template <typename T>
645 template <typename T2>
647  const TypeVector<T2> & vy)
648 {
649  libmesh_assert_equal_to (LIBMESH_DIM, 2);
650 #if LIBMESH_DIM > 1
651  _coords[0] = vx(0);
652  _coords[1] = vx(1);
653  _coords[2] = vy(0);
654  _coords[3] = vy(1);
655 #else
656  libmesh_ignore(vx, vy);
657 #endif
658 }
659 
660 template <typename T>
661 template <typename T2>
663  const TypeVector<T2> & vy,
664  const TypeVector<T2> & vz)
665 {
666  libmesh_assert_equal_to (LIBMESH_DIM, 3);
667 #if LIBMESH_DIM > 2
668  _coords[0] = vx(0);
669  _coords[1] = vx(1);
670  _coords[2] = vx(2);
671  _coords[3] = vy(0);
672  _coords[4] = vy(1);
673  _coords[5] = vy(2);
674  _coords[6] = vz(0);
675  _coords[7] = vz(1);
676  _coords[8] = vz(2);
677 #else
678  libmesh_ignore(vx, vy, vz);
679 #endif
680 }
681 
682 
683 
684 
685 template <typename T>
686 inline
688 {
689 }
690 
691 
692 
693 template <typename T>
694 template<typename T2>
695 inline
697 {
698  for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
699  _coords[i] = p._coords[i];
700 }
701 
702 
703 
704 template <typename T>
705 inline
706 const T & TypeTensor<T>::operator () (const unsigned int i,
707  const unsigned int j) const
708 {
709  libmesh_assert_less (i, 3);
710  libmesh_assert_less (j, 3);
711 
712 #if LIBMESH_DIM < 3
713  const static T my_zero = 0;
714  if (i >= LIBMESH_DIM || j >= LIBMESH_DIM)
715  return my_zero;
716 #endif
717 
718  return _coords[i*LIBMESH_DIM+j];
719 }
720 
721 
722 
723 template <typename T>
724 inline
725 T & TypeTensor<T>::operator () (const unsigned int i,
726  const unsigned int j)
727 {
728 #if LIBMESH_DIM < 3
729 
730  libmesh_error_msg_if(i >= LIBMESH_DIM || j >= LIBMESH_DIM,
731  "ERROR: You are assigning to a tensor component that is out of range for the compiled LIBMESH_DIM!");
732 
733 #endif
734 
735  libmesh_assert_less (i, LIBMESH_DIM);
736  libmesh_assert_less (j, LIBMESH_DIM);
737 
738  return _coords[i*LIBMESH_DIM+j];
739 }
740 
741 
742 template <typename T>
743 inline
745 TypeTensor<T>::slice (const unsigned int i) const
746 {
747  libmesh_assert_less (i, LIBMESH_DIM);
748  return ConstTypeTensorColumn<T>(*this, i);
749 }
750 
751 
752 template <typename T>
753 inline
755 TypeTensor<T>::slice (const unsigned int i)
756 {
757  libmesh_assert_less (i, LIBMESH_DIM);
758  return TypeTensorColumn<T>(*this, i);
759 }
760 
761 
762 template <typename T>
763 inline
765 TypeTensor<T>::row(const unsigned int r) const
766 {
767  TypeVector<T> return_vector;
768 
769  for (unsigned int j=0; j<LIBMESH_DIM; j++)
770  return_vector._coords[j] = _coords[r*LIBMESH_DIM + j];
771 
772  return return_vector;
773 }
774 
775 
776 template <typename T>
777 inline
779 TypeTensor<T>::column(const unsigned int r) const
780 {
781  TypeVector<T> return_vector;
782 
783  for (unsigned int i=0; i<LIBMESH_DIM; i++)
784  return_vector._coords[i] = _coords[i*LIBMESH_DIM + r];
785 
786  return return_vector;
787 }
788 
789 
790 template <typename T>
791 template<typename T2>
792 inline
795 {
796 
797 #if LIBMESH_DIM == 1
799 #endif
800 
801 #if LIBMESH_DIM == 2
803  _coords[1] + p._coords[1],
804  0.,
805  _coords[2] + p._coords[2],
806  _coords[3] + p._coords[3]);
807 #endif
808 
809 #if LIBMESH_DIM == 3
811  _coords[1] + p._coords[1],
812  _coords[2] + p._coords[2],
813  _coords[3] + p._coords[3],
814  _coords[4] + p._coords[4],
815  _coords[5] + p._coords[5],
816  _coords[6] + p._coords[6],
817  _coords[7] + p._coords[7],
818  _coords[8] + p._coords[8]);
819 #endif
820 
821 }
822 
823 
824 
825 template <typename T>
826 template<typename T2>
827 inline
829 {
830  this->add (p);
831 
832  return *this;
833 }
834 
835 
836 
837 template <typename T>
838 template<typename T2>
839 inline
841 {
842  for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
843  _coords[i] += p._coords[i];
844 }
845 
846 
847 
848 template <typename T>
849 template <typename T2>
850 inline
851 void TypeTensor<T>::add_scaled (const TypeTensor<T2> & p, const T & factor)
852 {
853  for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
854  _coords[i] += factor*p._coords[i];
855 
856 }
857 
858 
859 
860 template <typename T>
861 template<typename T2>
862 inline
865 {
866 
867 #if LIBMESH_DIM == 1
869 #endif
870 
871 #if LIBMESH_DIM == 2
873  _coords[1] - p._coords[1],
874  0.,
875  _coords[2] - p._coords[2],
876  _coords[3] - p._coords[3]);
877 #endif
878 
879 #if LIBMESH_DIM == 3
881  _coords[1] - p._coords[1],
882  _coords[2] - p._coords[2],
883  _coords[3] - p._coords[3],
884  _coords[4] - p._coords[4],
885  _coords[5] - p._coords[5],
886  _coords[6] - p._coords[6],
887  _coords[7] - p._coords[7],
888  _coords[8] - p._coords[8]);
889 #endif
890 
891 }
892 
893 
894 
895 template <typename T>
896 template <typename T2>
897 inline
899 {
900  this->subtract (p);
901 
902  return *this;
903 }
904 
905 
906 
907 template <typename T>
908 template <typename T2>
909 inline
911 {
912  for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
913  _coords[i] -= p._coords[i];
914 }
915 
916 
917 
918 template <typename T>
919 template <typename T2>
920 inline
921 void TypeTensor<T>::subtract_scaled (const TypeTensor<T2> & p, const T & factor)
922 {
923  for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
924  _coords[i] -= factor*p._coords[i];
925 }
926 
927 
928 
929 template <typename T>
930 inline
932 {
933 
934 #if LIBMESH_DIM == 1
935  return TypeTensor(-_coords[0]);
936 #endif
937 
938 #if LIBMESH_DIM == 2
939  return TypeTensor(-_coords[0],
940  -_coords[1],
941  -_coords[2],
942  -_coords[3]);
943 #endif
944 
945 #if LIBMESH_DIM == 3
946  return TypeTensor(-_coords[0],
947  -_coords[1],
948  -_coords[2],
949  -_coords[3],
950  -_coords[4],
951  -_coords[5],
952  -_coords[6],
953  -_coords[7],
954  -_coords[8]);
955 #endif
956 
957 }
958 
959 
960 
961 template <typename T>
962 template <typename Scalar>
963 inline
964 auto
965 TypeTensor<T>::operator * (const Scalar & factor) const -> typename boostcopy::enable_if_c<
968 {
969  typedef decltype((*this)(0, 0) * factor) TS;
970 
971 
972 #if LIBMESH_DIM == 1
973  return TypeTensor<TS>(_coords[0]*factor);
974 #endif
975 
976 #if LIBMESH_DIM == 2
977  return TypeTensor<TS>(_coords[0]*factor,
978  _coords[1]*factor,
979  _coords[2]*factor,
980  _coords[3]*factor);
981 #endif
982 
983 #if LIBMESH_DIM == 3
984  return TypeTensor<TS>(_coords[0]*factor,
985  _coords[1]*factor,
986  _coords[2]*factor,
987  _coords[3]*factor,
988  _coords[4]*factor,
989  _coords[5]*factor,
990  _coords[6]*factor,
991  _coords[7]*factor,
992  _coords[8]*factor);
993 #endif
994 }
995 
996 
997 
998 template <typename T, typename Scalar>
999 inline
1000 typename boostcopy::enable_if_c<
1003 operator * (const Scalar & factor,
1004  const TypeTensor<T> & t)
1005 {
1006  return t * factor;
1007 }
1008 
1009 template <typename T>
1010 template <typename Scalar>
1011 inline
1012 typename boostcopy::enable_if_c<
1014  TypeTensor<typename CompareTypes<T, Scalar>::supertype>>::type
1015 TypeTensor<T>::operator / (const Scalar & factor) const
1016 {
1017  libmesh_assert_not_equal_to (factor, static_cast<T>(0.));
1018 
1019  typedef typename CompareTypes<T, Scalar>::supertype TS;
1020 
1021 #if LIBMESH_DIM == 1
1022  return TypeTensor<TS>(_coords[0]/factor);
1023 #endif
1024 
1025 #if LIBMESH_DIM == 2
1026  return TypeTensor<TS>(_coords[0]/factor,
1027  _coords[1]/factor,
1028  _coords[2]/factor,
1029  _coords[3]/factor);
1030 #endif
1031 
1032 #if LIBMESH_DIM == 3
1033  return TypeTensor<TS>(_coords[0]/factor,
1034  _coords[1]/factor,
1035  _coords[2]/factor,
1036  _coords[3]/factor,
1037  _coords[4]/factor,
1038  _coords[5]/factor,
1039  _coords[6]/factor,
1040  _coords[7]/factor,
1041  _coords[8]/factor);
1042 #endif
1043 
1044 }
1045 
1046 
1047 
1048 template <typename T>
1049 inline
1051 {
1052 #if LIBMESH_DIM == 1
1053  return TypeTensor(_coords[0]);
1054 #endif
1055 
1056 #if LIBMESH_DIM == 2
1057  return TypeTensor(_coords[0],
1058  _coords[2],
1059  _coords[1],
1060  _coords[3]);
1061 #endif
1062 
1063 #if LIBMESH_DIM == 3
1064  return TypeTensor(_coords[0],
1065  _coords[3],
1066  _coords[6],
1067  _coords[1],
1068  _coords[4],
1069  _coords[7],
1070  _coords[2],
1071  _coords[5],
1072  _coords[8]);
1073 #endif
1074 }
1075 
1076 
1077 
1078 template <typename T>
1079 inline
1081 {
1082 #if LIBMESH_DIM == 1
1083  if (_coords[0] == static_cast<T>(0.))
1084  libmesh_convergence_failure();
1085  return TypeTensor(1. / _coords[0]);
1086 #endif
1087 
1088 #if LIBMESH_DIM == 2
1089  // Get convenient reference to this.
1090  const TypeTensor<T> & A = *this;
1091 
1092  // Use temporary variables, avoid multiple accesses
1093  T a = A(0,0), b = A(0,1),
1094  c = A(1,0), d = A(1,1);
1095 
1096  // Make sure det = ad - bc is not zero
1097  T my_det = a*d - b*c;
1098 
1099  if (my_det == static_cast<T>(0.))
1100  libmesh_convergence_failure();
1101 
1102  return TypeTensor(d/my_det, -b/my_det, -c/my_det, a/my_det);
1103 #endif
1104 
1105 #if LIBMESH_DIM == 3
1106  // Get convenient reference to this.
1107  const TypeTensor<T> & A = *this;
1108 
1109  T a11 = A(0,0), a12 = A(0,1), a13 = A(0,2),
1110  a21 = A(1,0), a22 = A(1,1), a23 = A(1,2),
1111  a31 = A(2,0), a32 = A(2,1), a33 = A(2,2);
1112 
1113  T my_det = a11*(a33*a22-a32*a23) - a21*(a33*a12-a32*a13) + a31*(a23*a12-a22*a13);
1114 
1115  if (my_det == static_cast<T>(0.))
1116  libmesh_convergence_failure();
1117 
1118  // Inline comment characters are for lining up columns.
1119  return TypeTensor( (a33*a22-a32*a23)/my_det, -(a33*a12-a32*a13)/my_det, (a23*a12-a22*a13)/my_det,
1120  -(a33*a21-a31*a23)/my_det, (a33*a11-a31*a13)/my_det, -(a23*a11-a21*a13)/my_det,
1121  (a32*a21-a31*a22)/my_det, -(a32*a11-a31*a12)/my_det, (a22*a11-a21*a12)/my_det);
1122 #endif
1123 }
1124 
1125 
1126 
1127 template <typename T>
1128 inline
1130 {
1131 #if LIBMESH_DIM == 1
1132  if (_coords[0] == static_cast<T>(0.))
1133  libmesh_convergence_failure();
1134  x(0) = b(0) / _coords[0];
1135 #endif
1136 
1137 #if LIBMESH_DIM == 2
1138  T my_det = _coords[0]*_coords[3] - _coords[1]*_coords[2];
1139 
1140  if (my_det == static_cast<T>(0.))
1141  libmesh_convergence_failure();
1142 
1143  T my_det_inv = 1./my_det;
1144 
1145  x(0) = my_det_inv*( _coords[3]*b(0) - _coords[1]*b(1));
1146  x(1) = my_det_inv*(-_coords[2]*b(0) + _coords[0]*b(1));
1147 #endif
1148 
1149 #if LIBMESH_DIM == 3
1150  T my_det =
1151  // a11*(a33 *a22 - a32 *a23)
1152  _coords[0]*(_coords[8]*_coords[4] - _coords[7]*_coords[5])
1153  // -a21*(a33 *a12 - a32 *a13)
1154  -_coords[3]*(_coords[8]*_coords[1] - _coords[7]*_coords[2]) +
1155  // +a31*(a23 *a12 - a22 *a13)
1156  +_coords[6]*(_coords[5]*_coords[1] - _coords[4]*_coords[2]);
1157 
1158  if (my_det == static_cast<T>(0.))
1159  libmesh_convergence_failure();
1160 
1161  T my_det_inv = 1./my_det;
1162  x(0) = my_det_inv*((_coords[8]*_coords[4] - _coords[7]*_coords[5])*b(0) -
1163  (_coords[8]*_coords[1] - _coords[7]*_coords[2])*b(1) +
1164  (_coords[5]*_coords[1] - _coords[4]*_coords[2])*b(2));
1165 
1166  x(1) = my_det_inv*((_coords[6]*_coords[5] - _coords[8]*_coords[3])*b(0) +
1167  (_coords[8]*_coords[0] - _coords[6]*_coords[2])*b(1) -
1168  (_coords[5]*_coords[0] - _coords[3]*_coords[2])*b(2));
1169 
1170  x(2) = my_det_inv*((_coords[7]*_coords[3] - _coords[6]*_coords[4])*b(0) -
1171  (_coords[7]*_coords[0] - _coords[6]*_coords[1])*b(1) +
1172  (_coords[4]*_coords[0] - _coords[3]*_coords[1])*b(2));
1173 #endif
1174 }
1175 
1176 
1177 
1178 template <typename T>
1179 inline
1181 {
1182  libmesh_assert_not_equal_to (factor, static_cast<T>(0.));
1183 
1184  for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
1185  _coords[i] /= factor;
1186 
1187  return *this;
1188 }
1189 
1190 
1191 
1192 
1193 template <typename T>
1194 template <typename T2>
1195 inline
1198 {
1200  for (unsigned int i=0; i<LIBMESH_DIM; i++)
1201  for (unsigned int j=0; j<LIBMESH_DIM; j++)
1202  returnval(i) += (*this)(i,j)*p(j);
1203 
1204  return returnval;
1205 }
1206 
1207 template <typename T>
1208 template <typename T2>
1209 inline
1212 {
1214  for (unsigned int i=0; i<LIBMESH_DIM; i++)
1215  for (unsigned int j=0; j<LIBMESH_DIM; j++)
1216  returnval(i) += p(j)*(*this)(j,i);
1217 
1218  return returnval;
1219 }
1220 
1221 template <typename T, typename T2>
1222 inline
1225 {
1226  return b.left_multiply(a);
1227 }
1228 
1229 template <typename T>
1230 template <typename T2>
1231 inline
1232 TypeTensor<typename CompareTypes<T, T2>::supertype>
1234 {
1236  for (unsigned int i=0; i<LIBMESH_DIM; i++)
1237  for (unsigned int j=0; j<LIBMESH_DIM; j++)
1238  for (unsigned int k=0; k<LIBMESH_DIM; k++)
1239  returnval(i,j) += (*this)(i,k)*p(k,j);
1240 
1241  return returnval;
1242 }
1243 
1244 template <typename T>
1245 template <typename T2>
1246 inline
1248 {
1249  TypeTensor<T> temp;
1250  for (unsigned int i=0; i<LIBMESH_DIM; i++)
1251  for (unsigned int j=0; j<LIBMESH_DIM; j++)
1252  for (unsigned int k=0; k<LIBMESH_DIM; k++)
1253  temp(i,j) += (*this)(i,k)*p(k,j);
1254 
1255  this->assign(temp);
1256  return *this;
1257 }
1258 
1259 
1264 template <typename T>
1265 template <typename T2>
1266 inline
1269 {
1270  typename CompareTypes<T,T2>::supertype sum = 0.;
1271  for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
1272  sum += _coords[i]*t._coords[i];
1273  return sum;
1274 }
1275 
1276 
1277 
1278 template <typename T>
1279 inline
1280 auto TypeTensor<T>::norm() const -> decltype(std::norm(T()))
1281 {
1282  return std::sqrt(this->norm_sq());
1283 }
1284 
1285 
1286 template <typename T>
1287 inline
1289 {
1290  for (const auto & val : _coords)
1291  if (val != T(0))
1292  return false;
1293  return true;
1294 }
1295 
1296 template <typename T>
1297 inline
1299 {
1300 #if LIBMESH_DIM == 1
1301  return _coords[0];
1302 #endif
1303 
1304 #if LIBMESH_DIM == 2
1305  return (_coords[0] * _coords[3]
1306  - _coords[1] * _coords[2]);
1307 #endif
1308 
1309 #if LIBMESH_DIM == 3
1310  return (_coords[0] * _coords[4] * _coords[8]
1311  + _coords[1] * _coords[5] * _coords[6]
1312  + _coords[2] * _coords[3] * _coords[7]
1313  - _coords[0] * _coords[5] * _coords[7]
1314  - _coords[1] * _coords[3] * _coords[8]
1315  - _coords[2] * _coords[4] * _coords[6]);
1316 #endif
1317 }
1318 
1319 template <typename T>
1320 inline
1322 {
1323 #if LIBMESH_DIM == 1
1324  return _coords[0];
1325 #endif
1326 
1327 #if LIBMESH_DIM == 2
1328  return _coords[0] + _coords[3];
1329 #endif
1330 
1331 #if LIBMESH_DIM == 3
1332  return _coords[0] + _coords[4] + _coords[8];
1333 #endif
1334 }
1335 
1336 template <typename T>
1337 inline
1339 {
1340  for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
1341  _coords[i] = 0.;
1342 }
1343 
1344 
1345 
1346 template <typename T>
1347 inline
1348 auto TypeTensor<T>::norm_sq () const -> decltype(std::norm(T()))
1349 {
1350  Real sum = 0.;
1351  for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
1352  sum += TensorTools::norm_sq(_coords[i]);
1353  return sum;
1354 }
1355 
1356 
1357 
1358 template <typename T>
1359 inline
1361 {
1362 #if LIBMESH_DIM == 1
1363  return (std::abs(_coords[0] - rhs._coords[0])
1364  < TOLERANCE);
1365 #endif
1366 
1367 #if LIBMESH_DIM == 2
1368  return ((std::abs(_coords[0] - rhs._coords[0]) +
1369  std::abs(_coords[1] - rhs._coords[1]) +
1370  std::abs(_coords[2] - rhs._coords[2]) +
1371  std::abs(_coords[3] - rhs._coords[3]))
1372  < 4.*TOLERANCE);
1373 #endif
1374 
1375 #if LIBMESH_DIM == 3
1376  return ((std::abs(_coords[0] - rhs._coords[0]) +
1377  std::abs(_coords[1] - rhs._coords[1]) +
1378  std::abs(_coords[2] - rhs._coords[2]) +
1379  std::abs(_coords[3] - rhs._coords[3]) +
1380  std::abs(_coords[4] - rhs._coords[4]) +
1381  std::abs(_coords[5] - rhs._coords[5]) +
1382  std::abs(_coords[6] - rhs._coords[6]) +
1383  std::abs(_coords[7] - rhs._coords[7]) +
1384  std::abs(_coords[8] - rhs._coords[8]))
1385  < 9.*TOLERANCE);
1386 #endif
1387 
1388 }
1389 
1390 template <typename T>
1391 void TypeTensor<T>::print(std::ostream & os) const
1392 {
1393 #if LIBMESH_DIM == 1
1394 
1395  os << "x=" << (*this)(0,0) << std::endl;
1396 
1397 #endif
1398 #if LIBMESH_DIM == 2
1399 
1400  os << "(xx,xy)=("
1401  << std::setw(8) << (*this)(0,0) << ", "
1402  << std::setw(8) << (*this)(0,1) << ")"
1403  << std::endl;
1404  os << "(yx,yy)=("
1405  << std::setw(8) << (*this)(1,0) << ", "
1406  << std::setw(8) << (*this)(1,1) << ")"
1407  << std::endl;
1408 
1409 #endif
1410 #if LIBMESH_DIM == 3
1411 
1412  os << "(xx,xy,xz)=("
1413  << std::setw(8) << (*this)(0,0) << ", "
1414  << std::setw(8) << (*this)(0,1) << ", "
1415  << std::setw(8) << (*this)(0,2) << ")"
1416  << std::endl;
1417  os << "(yx,yy,yz)=("
1418  << std::setw(8) << (*this)(1,0) << ", "
1419  << std::setw(8) << (*this)(1,1) << ", "
1420  << std::setw(8) << (*this)(1,2) << ")"
1421  << std::endl;
1422  os << "(zx,zy,zz)=("
1423  << std::setw(8) << (*this)(2,0) << ", "
1424  << std::setw(8) << (*this)(2,1) << ", "
1425  << std::setw(8) << (*this)(2,2) << ")"
1426  << std::endl;
1427 #endif
1428 }
1429 
1430 template <typename T, typename T2>
1431 inline
1434 {
1436  for (unsigned int i=0; i<LIBMESH_DIM; i++)
1437  for (unsigned int j=0; j<LIBMESH_DIM; j++)
1438  ret(i,j) = a(i) * libmesh_conj(b(j));
1439 
1440  return ret;
1441 }
1442 
1443 
1444 } // namespace libMesh
1445 
1446 #ifdef LIBMESH_HAVE_METAPHYSICL
1447 namespace MetaPhysicL
1448 {
1449 template <typename T>
1450 struct RawType<libMesh::TypeTensor<T>>
1451 {
1453 
1455  {
1456  value_type ret;
1457  for (unsigned int i = 0; i < LIBMESH_DIM; ++i)
1458  for (unsigned int j = 0; j < LIBMESH_DIM; ++j)
1459  ret(i,j) = raw_value(in(i,j));
1460 
1461  return ret;
1462  }
1463 };
1464 
1465 template <typename T, typename U>
1466 struct ReplaceAlgebraicType<libMesh::TypeTensor<T>, U>
1467 {
1468  typedef U type;
1469 };
1470 }
1471 #endif
1472 
1473 #endif // LIBMESH_TYPE_TENSOR_H
const T & operator()(const unsigned int i) const
Return the element of the tensor.
Definition: type_tensor.h:495
TypeTensorColumn< T > & operator=(const TypeVector< T > &rhs)
Assign values to this column of the tensor.
Definition: type_tensor.h:470
T _coords[LIBMESH_DIM]
The coordinates of the TypeVector.
Definition: type_vector.h:417
const unsigned int _j
Definition: type_tensor.h:479
const TypeTensor< T > & operator/=(const T &)
Divide each entry of this tensor by a scalar value.
Definition: type_tensor.h:1180
TypeTensor< typename CompareTypes< T, T2 >::supertype > outer_product(const TypeVector< T > &a, const TypeVector< T2 > &b)
Definition: type_tensor.h:1433
static value_type value(const libMesh::TypeTensor< T > &in)
Definition: type_tensor.h:1454
const T & slice(const unsigned int i) const
Definition: type_tensor.h:498
T libmesh_conj(T a)
TypeTensor< T > * _tensor
Definition: type_tensor.h:478
T & operator()(const unsigned int i)
Definition: type_tensor.h:461
T value_type
Helper typedef for C++98 generic programming.
Definition: type_tensor.h:120
static constexpr Real TOLERANCE
std::tuple< unsigned int, unsigned int > index_type
Helper typedef for generic index programming.
Definition: type_tensor.h:125
TypeTensor< T > transpose() const
Definition: type_tensor.h:1050
void zero()
Set all entries of the tensor to 0.
Definition: type_tensor.h:1338
auto operator*(const Scalar &scalar) const -> typename boostcopy::enable_if_c< ScalarTraits< Scalar >::value, TypeTensor< decltype(T() *scalar)>>::type
Multiply this tensor by a scalar value.
Definition: type_tensor.h:965
TypeTensor()
Empty constructor.
Definition: type_tensor.h:510
auto norm_sq() const -> decltype(std::norm(T()))
Definition: type_tensor.h:1348
ConstTypeTensorColumn(const TypeTensor< T > &tensor, unsigned int j)
Definition: type_tensor.h:488
void solve(const TypeVector< T > &b, TypeVector< T > &x) const
Solve the 2x2 or 3x3 system of equations A*x = b for x by directly inverting A and multiplying it by ...
Definition: type_tensor.h:1129
TypeVector< T > row(const unsigned int r) const
Definition: type_tensor.h:765
bool is_zero() const
Definition: type_tensor.h:1288
The libMesh namespace provides an interface to certain functionality in the library.
T _coords[LIBMESH_DIM *LIBMESH_DIM]
The coordinates of the TypeTensor.
Definition: type_tensor.h:444
const TypeTensor< T > * _tensor
Definition: type_tensor.h:502
libMesh::TypeTensor< typename RawType< T >::value_type > value_type
Definition: type_tensor.h:1452
boostcopy::enable_if_c< ScalarTraits< Scalar >::value, TypeTensor< typename CompareTypes< T, Scalar >::supertype > >::type operator/(const Scalar &) const
Divide each entry of this tensor by a scalar value.
Definition: type_tensor.h:1015
auto norm() const -> decltype(std::norm(T()))
Definition: type_tensor.h:1280
This class defines a tensor in LIBMESH_DIM dimensional space of type T.
Definition: tensor_tools.h:36
TypeTensor< typename CompareTypes< T, T2 >::supertype > operator+(const TypeTensor< T2 > &) const
Add another tensor to this tensor.
Definition: type_tensor.h:794
void libmesh_ignore(const Args &...)
TypeVector< T > column(const unsigned int r) const
Definition: type_tensor.h:779
TypeTensorColumn(TypeTensor< T > &tensor, unsigned int j)
Definition: type_tensor.h:453
void subtract_scaled(const TypeTensor< T2 > &, const T &)
Subtract a scaled value from this tensor without creating a temporary.
Definition: type_tensor.h:921
TypeTensor< T > operator-() const
Definition: type_tensor.h:931
boostcopy::enable_if_c< ScalarTraits< Scalar >::value, TypeNTensor< N, typename CompareTypes< Scalar, T >::supertype > >::type operator*(const Scalar &, const TypeNTensor< N, T > &)
void subtract(const TypeTensor< T2 > &)
Subtract from this tensor without creating a temporary.
Definition: type_tensor.h:910
void assign(const TypeTensor< T2 > &)
Assign to this tensor without creating a temporary.
Definition: type_tensor.h:696
void write_unformatted(std::ostream &out_stream, const bool newline=true) const
Unformatted print to the stream out.
Definition: type_tensor.C:39
This class defines a vector in LIBMESH_DIM dimensional space of type T.
Definition: tensor_tools.h:34
void add(const TypeTensor< T2 > &)
Add to this tensor without creating a temporary.
Definition: type_tensor.h:840
~TypeTensor()
Destructor.
Definition: type_tensor.h:687
auto norm(const T &a) -> decltype(std::abs(a))
Definition: tensor_tools.h:74
void add_scaled(const TypeTensor< T2 > &, const T &)
Add a scaled tensor to this tensor without creating a temporary.
Definition: type_tensor.h:851
CompareTypes< T, T2 >::supertype contract(const TypeTensor< T2 > &) const
Multiply 2 tensors together to return a scalar, i.e.
Definition: type_tensor.h:1268
This class will eventually define a rank-N tensor in LIBMESH_DIM dimensional space of type T...
Definition: tensor_tools.h:38
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
auto norm_sq(const T &a) -> decltype(std::norm(a))
Definition: tensor_tools.h:104
TypeTensor< T > inverse() const
Definition: type_tensor.h:1080
OStreamProxy out
boostcopy::enable_if_c< ScalarTraits< Scalar >::value, TypeTensor & >::type operator=(const Scalar &libmesh_dbg_var(p))
Assignment-from-scalar operator.
Definition: type_tensor.h:153
const TypeTensor< T > & operator-=(const TypeTensor< T2 > &)
Subtract from this tensor.
Definition: type_tensor.h:898
ConstTypeTensorColumn< T > slice(const unsigned int i) const
Definition: type_tensor.h:745
const TypeTensor< T > & operator+=(const TypeTensor< T2 > &)
Add to this tensor.
Definition: type_tensor.h:828
T & slice(const unsigned int i)
Definition: type_tensor.h:464
bool operator==(const TypeTensor< T > &rhs) const
Definition: type_tensor.h:1360
TypeVector< typename CompareTypes< T, T2 >::supertype > left_multiply(const TypeVector< T2 > &p) const
Left-multiply this tensor by a vector, i.e.
Definition: type_tensor.h:1211
const TypeTensor< T > & operator*=(const Scalar &factor)
Multiply this tensor by a scalar value in place.
Definition: type_tensor.h:268
static const bool value
Definition: compare_types.h:64
void print(std::ostream &os=libMesh::out) const
Formatted print to a stream which defaults to libMesh::out.
Definition: type_tensor.h:1391
const T & operator()(const unsigned int i, const unsigned int j) const
Definition: type_tensor.h:706