20 #ifndef LIBMESH_TYPE_TENSOR_H 21 #define LIBMESH_TYPE_TENSOR_H 24 #include "libmesh/libmesh_common.h" 25 #include "libmesh/type_vector.h" 32 #ifdef LIBMESH_HAVE_METAPHYSICL 33 #include "metaphysicl/dualnumber_decl.h" 42 template <
unsigned int N,
typename T>
class TypeNTensor;
54 template <
typename T2>
85 template <
typename Scalar>
96 const Scalar>::type & zz=0);
103 template<
typename T2>
106 template<
typename T2>
110 template<
typename T2>
130 template<
typename T2>
141 template<
typename T2>
149 template <
typename Scalar>
154 { libmesh_assert_equal_to (p, Scalar(0)); this->
zero();
return *
this; }
159 const T &
operator () (
const unsigned int i,
const unsigned int j)
const;
164 T &
operator () (
const unsigned int i,
const unsigned int j);
191 template<
typename T2>
200 template<
typename T2>
206 template<
typename T2>
212 template <
typename T2>
220 template<
typename T2>
229 template<
typename T2>
235 template<
typename T2>
242 template <
typename T2>
255 template <
typename Scalar>
270 for (
unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
281 template <
typename Scalar>
300 template <
typename T2>
309 template <
typename T2>
321 template <
typename T2>
331 template <
typename T2>
341 template <
typename T2>
401 bool operator == (const
TypeTensor<T> & rhs) const;
407 bool operator < (const
TypeTensor<T> & rhs) const;
412 bool operator > (const
TypeTensor<T> & rhs) const;
437 const bool newline =
true)
const;
448 template <
typename T>
472 for (
unsigned int i=0; i != LIBMESH_DIM; ++i)
479 const unsigned int _j;
483 template <
typename T>
498 const T &
slice (
const unsigned int i)
const 503 const unsigned int _j;
508 template <
typename T>
531 template <
typename T>
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);
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);
576 template <
typename T>
577 template <
typename Scalar>
589 const Scalar>::type & zz)
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);
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);
625 template <
typename T>
626 template<
typename T2>
631 for (
unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
636 template <
typename T>
637 template <
typename T2>
640 libmesh_assert_equal_to (LIBMESH_DIM, 1);
644 template <
typename T>
645 template <
typename T2>
649 libmesh_assert_equal_to (LIBMESH_DIM, 2);
660 template <
typename T>
661 template <
typename T2>
666 libmesh_assert_equal_to (LIBMESH_DIM, 3);
685 template <
typename T>
693 template <
typename T>
694 template<
typename T2>
698 for (
unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
704 template <
typename T>
707 const unsigned int j)
const 709 libmesh_assert_less (i, 3);
710 libmesh_assert_less (j, 3);
713 const static T my_zero = 0;
714 if (i >= LIBMESH_DIM || j >= LIBMESH_DIM)
718 return _coords[i*LIBMESH_DIM+j];
723 template <
typename T>
726 const unsigned int j)
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!");
735 libmesh_assert_less (i, LIBMESH_DIM);
736 libmesh_assert_less (j, LIBMESH_DIM);
738 return _coords[i*LIBMESH_DIM+j];
742 template <
typename T>
747 libmesh_assert_less (i, LIBMESH_DIM);
752 template <
typename T>
757 libmesh_assert_less (i, LIBMESH_DIM);
762 template <
typename T>
769 for (
unsigned int j=0; j<LIBMESH_DIM; j++)
770 return_vector.
_coords[j] = _coords[r*LIBMESH_DIM + j];
772 return return_vector;
776 template <
typename T>
783 for (
unsigned int i=0; i<LIBMESH_DIM; i++)
784 return_vector.
_coords[i] = _coords[i*LIBMESH_DIM + r];
786 return return_vector;
790 template <
typename T>
791 template<
typename T2>
825 template <
typename T>
826 template<
typename T2>
837 template <
typename T>
838 template<
typename T2>
842 for (
unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
848 template <
typename T>
849 template <
typename T2>
853 for (
unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
854 _coords[i] += factor*p.
_coords[i];
860 template <
typename T>
861 template<
typename T2>
895 template <
typename T>
896 template <
typename T2>
907 template <
typename T>
908 template <
typename T2>
912 for (
unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
918 template <
typename T>
919 template <
typename T2>
923 for (
unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
924 _coords[i] -= factor*p.
_coords[i];
929 template <
typename T>
961 template <
typename T>
962 template <
typename Scalar>
969 typedef decltype((*
this)(0, 0) * factor) TS;
998 template <
typename T,
typename Scalar>
1009 template <
typename T>
1010 template <
typename Scalar>
1012 typename boostcopy::enable_if_c<
1014 TypeTensor<typename CompareTypes<T, Scalar>::supertype>>::type
1017 libmesh_assert_not_equal_to (factor, static_cast<T>(0.));
1021 #if LIBMESH_DIM == 1 1025 #if LIBMESH_DIM == 2 1032 #if LIBMESH_DIM == 3 1048 template <
typename T>
1052 #if LIBMESH_DIM == 1 1056 #if LIBMESH_DIM == 2 1063 #if LIBMESH_DIM == 3 1078 template <
typename T>
1082 #if LIBMESH_DIM == 1 1083 if (_coords[0] == static_cast<T>(0.))
1084 libmesh_convergence_failure();
1088 #if LIBMESH_DIM == 2 1093 T a = A(0,0), b = A(0,1),
1094 c = A(1,0), d = A(1,1);
1097 T my_det = a*d - b*c;
1099 if (my_det == static_cast<T>(0.))
1100 libmesh_convergence_failure();
1102 return TypeTensor(d/my_det, -b/my_det, -c/my_det, a/my_det);
1105 #if LIBMESH_DIM == 3 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);
1113 T my_det = a11*(a33*a22-a32*a23) - a21*(a33*a12-a32*a13) + a31*(a23*a12-a22*a13);
1115 if (my_det == static_cast<T>(0.))
1116 libmesh_convergence_failure();
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);
1127 template <
typename T>
1131 #if LIBMESH_DIM == 1 1132 if (_coords[0] == static_cast<T>(0.))
1133 libmesh_convergence_failure();
1134 x(0) = b(0) / _coords[0];
1137 #if LIBMESH_DIM == 2 1138 T my_det = _coords[0]*_coords[3] - _coords[1]*_coords[2];
1140 if (my_det == static_cast<T>(0.))
1141 libmesh_convergence_failure();
1143 T my_det_inv = 1./my_det;
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));
1149 #if LIBMESH_DIM == 3 1152 _coords[0]*(_coords[8]*_coords[4] - _coords[7]*_coords[5])
1154 -_coords[3]*(_coords[8]*_coords[1] - _coords[7]*_coords[2]) +
1156 +_coords[6]*(_coords[5]*_coords[1] - _coords[4]*_coords[2]);
1158 if (my_det == static_cast<T>(0.))
1159 libmesh_convergence_failure();
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));
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));
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));
1178 template <
typename T>
1182 libmesh_assert_not_equal_to (factor, static_cast<T>(0.));
1184 for (
unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
1185 _coords[i] /= factor;
1193 template <
typename T>
1194 template <
typename T2>
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);
1207 template <
typename T>
1208 template <
typename T2>
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);
1221 template <
typename T,
typename T2>
1229 template <
typename T>
1230 template <
typename T2>
1232 TypeTensor<typename CompareTypes<T, T2>::supertype>
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);
1244 template <
typename T>
1245 template <
typename T2>
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);
1264 template <
typename T>
1265 template <
typename T2>
1271 for (
unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
1272 sum += _coords[i]*t.
_coords[i];
1278 template <
typename T>
1282 return std::sqrt(this->
norm_sq());
1286 template <
typename T>
1290 for (
const auto & val : _coords)
1296 template <
typename T>
1300 #if LIBMESH_DIM == 1 1304 #if LIBMESH_DIM == 2 1305 return (_coords[0] * _coords[3]
1306 - _coords[1] * _coords[2]);
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]);
1319 template <
typename T>
1323 #if LIBMESH_DIM == 1 1327 #if LIBMESH_DIM == 2 1328 return _coords[0] + _coords[3];
1331 #if LIBMESH_DIM == 3 1332 return _coords[0] + _coords[4] + _coords[8];
1336 template <
typename T>
1340 for (
unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
1346 template <
typename T>
1351 for (
unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
1358 template <
typename T>
1362 #if LIBMESH_DIM == 1 1363 return (std::abs(_coords[0] - rhs.
_coords[0])
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]))
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]))
1390 template <
typename T>
1393 #if LIBMESH_DIM == 1 1395 os <<
"x=" << (*this)(0,0) << std::endl;
1398 #if LIBMESH_DIM == 2 1401 << std::setw(8) << (*this)(0,0) <<
", " 1402 << std::setw(8) << (*this)(0,1) <<
")" 1405 << std::setw(8) << (*this)(1,0) <<
", " 1406 << std::setw(8) << (*this)(1,1) <<
")" 1410 #if LIBMESH_DIM == 3 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) <<
")" 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) <<
")" 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) <<
")" 1430 template <
typename T,
typename T2>
1436 for (
unsigned int i=0; i<LIBMESH_DIM; i++)
1437 for (
unsigned int j=0; j<LIBMESH_DIM; j++)
1446 #ifdef LIBMESH_HAVE_METAPHYSICL 1449 template <
typename T>
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));
1465 template <
typename T,
typename U>
1466 struct ReplaceAlgebraicType<
libMesh::TypeTensor<T>, U>
1473 #endif // LIBMESH_TYPE_TENSOR_H const T & operator()(const unsigned int i) const
Return the element of the tensor.
TypeTensorColumn< T > & operator=(const TypeVector< T > &rhs)
Assign values to this column of the tensor.
T _coords[LIBMESH_DIM]
The coordinates of the TypeVector.
const TypeTensor< T > & operator/=(const T &)
Divide each entry of this tensor by a scalar value.
TypeTensor< typename CompareTypes< T, T2 >::supertype > outer_product(const TypeVector< T > &a, const TypeVector< T2 > &b)
const T & slice(const unsigned int i) const
TypeTensor< T > * _tensor
T & operator()(const unsigned int i)
T value_type
Helper typedef for C++98 generic programming.
static constexpr Real TOLERANCE
std::tuple< unsigned int, unsigned int > index_type
Helper typedef for generic index programming.
TypeTensor< T > transpose() const
void zero()
Set all entries of the tensor to 0.
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.
TypeTensor()
Empty constructor.
auto norm_sq() const -> decltype(std::norm(T()))
ConstTypeTensorColumn(const TypeTensor< T > &tensor, unsigned int j)
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 ...
TypeVector< T > row(const unsigned int r) const
The libMesh namespace provides an interface to certain functionality in the library.
T _coords[LIBMESH_DIM *LIBMESH_DIM]
The coordinates of the TypeTensor.
const TypeTensor< T > * _tensor
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.
auto norm() const -> decltype(std::norm(T()))
This class defines a tensor in LIBMESH_DIM dimensional space of type T.
TypeTensor< typename CompareTypes< T, T2 >::supertype > operator+(const TypeTensor< T2 > &) const
Add another tensor to this tensor.
void libmesh_ignore(const Args &...)
TypeVector< T > column(const unsigned int r) const
TypeTensorColumn(TypeTensor< T > &tensor, unsigned int j)
void subtract_scaled(const TypeTensor< T2 > &, const T &)
Subtract a scaled value from this tensor without creating a temporary.
TypeTensor< T > operator-() const
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.
void assign(const TypeTensor< T2 > &)
Assign to this tensor without creating a temporary.
void write_unformatted(std::ostream &out_stream, const bool newline=true) const
Unformatted print to the stream out.
This class defines a vector in LIBMESH_DIM dimensional space of type T.
void add(const TypeTensor< T2 > &)
Add to this tensor without creating a temporary.
void add_scaled(const TypeTensor< T2 > &, const T &)
Add a scaled tensor to this tensor without creating a temporary.
CompareTypes< T, T2 >::supertype contract(const TypeTensor< T2 > &) const
Multiply 2 tensors together to return a scalar, i.e.
This class will eventually define a rank-N tensor in LIBMESH_DIM dimensional space of type T...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
TypeTensor< T > inverse() const
boostcopy::enable_if_c< ScalarTraits< Scalar >::value, TypeTensor & >::type operator=(const Scalar &libmesh_dbg_var(p))
Assignment-from-scalar operator.
const TypeTensor< T > & operator-=(const TypeTensor< T2 > &)
Subtract from this tensor.
ConstTypeTensorColumn< T > slice(const unsigned int i) const
const TypeTensor< T > & operator+=(const TypeTensor< T2 > &)
Add to this tensor.
T & slice(const unsigned int i)
bool operator==(const TypeTensor< T > &rhs) const
TypeVector< typename CompareTypes< T, T2 >::supertype > left_multiply(const TypeVector< T2 > &p) const
Left-multiply this tensor by a vector, i.e.
const TypeTensor< T > & operator*=(const Scalar &factor)
Multiply this tensor by a scalar value in place.
void print(std::ostream &os=libMesh::out) const
Formatted print to a stream which defaults to libMesh::out.
const T & operator()(const unsigned int i, const unsigned int j) const