Reference documentation for deal.II version 9.1.0-pre
transformations.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2016 - 2017 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_transformations_h
17 #define dealii_transformations_h
18 
19 #include <deal.II/base/point.h>
21 #include <deal.II/base/tensor.h>
22 
23 DEAL_II_NAMESPACE_OPEN
24 
25 
26 namespace Physics
27 {
28  namespace Transformations
29  {
36  namespace Rotations
37  {
42 
58  template <typename Number>
60  rotation_matrix_2d(const Number &angle);
61 
62 
91  template <typename Number>
93  rotation_matrix_3d(const Point<3, Number> &axis, const Number &angle);
94 
96 
97  } // namespace Rotations
98 
117  namespace Contravariant
118  {
123 
137  template <int dim, typename Number>
139  push_forward(const Tensor<1, dim, Number> &V,
140  const Tensor<2, dim, Number> &F);
141 
156  template <int dim, typename Number>
158  push_forward(const Tensor<2, dim, Number> &T,
159  const Tensor<2, dim, Number> &F);
160 
176  template <int dim, typename Number>
178  push_forward(const SymmetricTensor<2, dim, Number> &T,
179  const Tensor<2, dim, Number> & F);
180 
194  template <int dim, typename Number>
196  push_forward(const Tensor<4, dim, Number> &H,
197  const Tensor<2, dim, Number> &F);
198 
213  template <int dim, typename Number>
215  push_forward(const SymmetricTensor<4, dim, Number> &H,
216  const Tensor<2, dim, Number> & F);
217 
219 
224 
238  template <int dim, typename Number>
241  const Tensor<2, dim, Number> &F);
242 
257  template <int dim, typename Number>
259  pull_back(const Tensor<2, dim, Number> &t,
260  const Tensor<2, dim, Number> &F);
261 
276  template <int dim, typename Number>
278  pull_back(const SymmetricTensor<2, dim, Number> &t,
279  const Tensor<2, dim, Number> & F);
280 
295  template <int dim, typename Number>
297  pull_back(const Tensor<4, dim, Number> &h,
298  const Tensor<2, dim, Number> &F);
299 
314  template <int dim, typename Number>
316  pull_back(const SymmetricTensor<4, dim, Number> &h,
317  const Tensor<2, dim, Number> & F);
318 
320  } // namespace Contravariant
321 
342  namespace Covariant
343  {
348 
362  template <int dim, typename Number>
364  push_forward(const Tensor<1, dim, Number> &V,
365  const Tensor<2, dim, Number> &F);
366 
381  template <int dim, typename Number>
383  push_forward(const Tensor<2, dim, Number> &T,
384  const Tensor<2, dim, Number> &F);
385 
401  template <int dim, typename Number>
403  push_forward(const SymmetricTensor<2, dim, Number> &T,
404  const Tensor<2, dim, Number> & F);
405 
420  template <int dim, typename Number>
422  push_forward(const Tensor<4, dim, Number> &H,
423  const Tensor<2, dim, Number> &F);
424 
440  template <int dim, typename Number>
442  push_forward(const SymmetricTensor<4, dim, Number> &H,
443  const Tensor<2, dim, Number> & F);
444 
446 
451 
465  template <int dim, typename Number>
467  pull_back(const Tensor<1, dim, Number> &v,
468  const Tensor<2, dim, Number> &F);
469 
484  template <int dim, typename Number>
486  pull_back(const Tensor<2, dim, Number> &t,
487  const Tensor<2, dim, Number> &F);
488 
503  template <int dim, typename Number>
505  pull_back(const SymmetricTensor<2, dim, Number> &t,
506  const Tensor<2, dim, Number> & F);
507 
522  template <int dim, typename Number>
524  pull_back(const Tensor<4, dim, Number> &h,
525  const Tensor<2, dim, Number> &F);
526 
541  template <int dim, typename Number>
543  pull_back(const SymmetricTensor<4, dim, Number> &h,
544  const Tensor<2, dim, Number> & F);
545 
547  } // namespace Covariant
548 
556  namespace Piola
557  {
562 
578  template <int dim, typename Number>
580  push_forward(const Tensor<1, dim, Number> &V,
581  const Tensor<2, dim, Number> &F);
582 
598  template <int dim, typename Number>
600  push_forward(const Tensor<2, dim, Number> &T,
601  const Tensor<2, dim, Number> &F);
602 
619  template <int dim, typename Number>
621  push_forward(const SymmetricTensor<2, dim, Number> &T,
622  const Tensor<2, dim, Number> & F);
623 
640  template <int dim, typename Number>
642  push_forward(const Tensor<4, dim, Number> &H,
643  const Tensor<2, dim, Number> &F);
644 
662  template <int dim, typename Number>
664  push_forward(const SymmetricTensor<4, dim, Number> &H,
665  const Tensor<2, dim, Number> & F);
666 
668 
673 
689  template <int dim, typename Number>
691  pull_back(const Tensor<1, dim, Number> &v,
692  const Tensor<2, dim, Number> &F);
693 
709  template <int dim, typename Number>
711  pull_back(const Tensor<2, dim, Number> &t,
712  const Tensor<2, dim, Number> &F);
713 
729  template <int dim, typename Number>
731  pull_back(const SymmetricTensor<2, dim, Number> &t,
732  const Tensor<2, dim, Number> & F);
733 
750  template <int dim, typename Number>
752  pull_back(const Tensor<4, dim, Number> &h,
753  const Tensor<2, dim, Number> &F);
754 
771  template <int dim, typename Number>
773  pull_back(const SymmetricTensor<4, dim, Number> &h,
774  const Tensor<2, dim, Number> & F);
775 
777  } // namespace Piola
778 
783 
806  template <int dim, typename Number>
809  const Tensor<2, dim, Number> &F);
810 
812  } // namespace Transformations
813 } // namespace Physics
814 
815 
816 
817 #ifndef DOXYGEN
818 
819 // ------------------------- inline functions ------------------------
820 
821 namespace internal
822 {
823  namespace Physics
824  {
825  template <int dim, typename Number>
827  transformation_contraction(const Tensor<1, dim, Number> &V,
828  const Tensor<2, dim, Number> &F)
829  {
830  return contract<1, 0>(F, V);
831  }
832 
833 
834 
835  template <int dim, typename Number>
837  transformation_contraction(const Tensor<2, dim, Number> &T,
838  const Tensor<2, dim, Number> &F)
839  {
840  return contract<1, 0>(F, contract<1, 1>(T, F));
841  }
842 
843 
844 
845  template <int dim, typename Number>
846  inline ::SymmetricTensor<2, dim, Number>
847  transformation_contraction(const ::SymmetricTensor<2, dim, Number> &T,
848  const Tensor<2, dim, Number> & F)
849  {
851  for (unsigned int i = 0; i < dim; ++i)
852  for (unsigned int J = 0; J < dim; ++J)
853  for (unsigned int I = 0; I < dim; ++I)
854  tmp_1[i][J] += F[i][I] * T[I][J];
855 
857  for (unsigned int i = 0; i < dim; ++i)
858  for (unsigned int j = i; j < dim; ++j)
859  for (unsigned int J = 0; J < dim; ++J)
860  out[i][j] += F[j][J] * tmp_1[i][J];
861 
862  return out;
863  }
864 
865 
866 
867  template <int dim, typename Number>
869  transformation_contraction(const Tensor<4, dim, Number> &H,
870  const Tensor<2, dim, Number> &F)
871  {
872  // This contraction order and indexing might look a bit dubious, so a
873  // quick explanation as to what's going on is probably in order:
874  //
875  // When the contract() function operates on the inner indices, the
876  // result has the inner index and outer index transposed, i.e.
877  // contract<2,1>(H,F) implies
878  // T_{IJLk} = (H_{IJMN} F_{mM}) \delta_{mL} \delta_{Nk}
879  // rather than T_{IJkL} (the desired result).
880  // So, in effect, contraction of the 3rd (inner) index with F as the
881  // second argument results in its transposition with respect to its
882  // adjacent neighbor. This is due to the position of the argument F,
883  // leading to the free index being on the right hand side of the result.
884  // However, given that we can do two transformations from the LHS of H
885  // and two from the right we can undo the otherwise erroneous
886  // swapping of the outer indices upon application of the second
887  // sets of contractions.
888  //
889  // Note: Its significantly quicker (in 3d) to push forward
890  // each index individually
891  return contract<1, 1>(
892  F, contract<1, 1>(F, contract<2, 1>(contract<2, 1>(H, F), F)));
893  }
894 
895 
896 
897  template <int dim, typename Number>
898  inline ::SymmetricTensor<4, dim, Number>
899  transformation_contraction(const ::SymmetricTensor<4, dim, Number> &H,
900  const Tensor<2, dim, Number> & F)
901  {
902  // The first and last transformation operations respectively
903  // break and recover the symmetry properties of the tensors.
904  // We also want to perform a minimal number of operations here
905  // and avoid some complications related to the transposition of
906  // tensor indices when contracting inner indices using the contract()
907  // function. (For an explanation of the contraction operations,
908  // please see the note in the equivalent function for standard
909  // Tensors.) So what we'll do here is manually perform the first
910  // and last contractions that break/recover the tensor symmetries
911  // on the inner indices, and use the contract() function only on
912  // the outer indices.
913  //
914  // Note: Its significantly quicker (in 3d) to push forward
915  // each index individually
916 
917  // Push forward (inner) index 1
919  for (unsigned int I = 0; I < dim; ++I)
920  for (unsigned int j = 0; j < dim; ++j)
921  for (unsigned int K = 0; K < dim; ++K)
922  for (unsigned int L = 0; L < dim; ++L)
923  for (unsigned int J = 0; J < dim; ++J)
924  tmp[I][j][K][L] += F[j][J] * H[I][J][K][L];
925 
926  // Push forward (outer) indices 0 and 3
927  tmp = contract<1, 0>(F, contract<3, 1>(tmp, F));
928 
929  // Push forward (inner) index 2
931  for (unsigned int i = 0; i < dim; ++i)
932  for (unsigned int j = i; j < dim; ++j)
933  for (unsigned int k = 0; k < dim; ++k)
934  for (unsigned int l = k; l < dim; ++l)
935  for (unsigned int K = 0; K < dim; ++K)
936  out[i][j][k][l] += F[k][K] * tmp[i][j][K][l];
937 
938  return out;
939  }
940  } // namespace Physics
941 } // namespace internal
942 
943 
944 
945 template <typename Number>
948 {
949  const double rotation[2][2] = {{std::cos(angle), -std::sin(angle)},
950  {std::sin(angle), std::cos(angle)}};
951  return Tensor<2, 2>(rotation);
952 }
953 
954 
955 
956 template <typename Number>
959  const Point<3, Number> &axis,
960  const Number & angle)
961 {
962  Assert(std::abs(axis.norm() - 1.0) < 1e-9,
963  ExcMessage("The supplied axial vector is not a unit vector."));
964  const Number c = std::cos(angle);
965  const Number s = std::sin(angle);
966  const Number t = 1. - c;
967  const double rotation[3][3] = {{t * axis[0] * axis[0] + c,
968  t * axis[0] * axis[1] - s * axis[2],
969  t * axis[0] * axis[2] + s * axis[1]},
970  {t * axis[0] * axis[1] + s * axis[2],
971  t * axis[1] * axis[1] + c,
972  t * axis[1] * axis[2] - s * axis[0]},
973  {t * axis[0] * axis[2] - s * axis[1],
974  t * axis[1] * axis[2] + s * axis[0],
975  t * axis[2] * axis[2] + c}};
976  return Tensor<2, 3, Number>(rotation);
977 }
978 
979 
980 
981 template <int dim, typename Number>
984  const Tensor<1, dim, Number> &V,
985  const Tensor<2, dim, Number> &F)
986 {
987  return internal::Physics::transformation_contraction(V, F);
988 }
989 
990 
991 
992 template <int dim, typename Number>
995  const Tensor<2, dim, Number> &T,
996  const Tensor<2, dim, Number> &F)
997 {
998  return internal::Physics::transformation_contraction(T, F);
999 }
1000 
1001 
1002 
1003 template <int dim, typename Number>
1007  const Tensor<2, dim, Number> & F)
1008 {
1009  return internal::Physics::transformation_contraction(T, F);
1010 }
1011 
1012 
1013 
1014 template <int dim, typename Number>
1017  const Tensor<4, dim, Number> &H,
1018  const Tensor<2, dim, Number> &F)
1019 {
1020  return internal::Physics::transformation_contraction(H, F);
1021 }
1022 
1023 
1024 
1025 template <int dim, typename Number>
1029  const Tensor<2, dim, Number> & F)
1030 {
1031  return internal::Physics::transformation_contraction(H, F);
1032 }
1033 
1034 
1035 
1036 template <int dim, typename Number>
1039  const Tensor<1, dim, Number> &v,
1040  const Tensor<2, dim, Number> &F)
1041 {
1042  return internal::Physics::transformation_contraction(v, invert(F));
1043 }
1044 
1045 
1046 
1047 template <int dim, typename Number>
1050  const Tensor<2, dim, Number> &t,
1051  const Tensor<2, dim, Number> &F)
1052 {
1053  return internal::Physics::transformation_contraction(t, invert(F));
1054 }
1055 
1056 
1057 
1058 template <int dim, typename Number>
1062  const Tensor<2, dim, Number> & F)
1063 {
1064  return internal::Physics::transformation_contraction(t, invert(F));
1065 }
1066 
1067 
1068 
1069 template <int dim, typename Number>
1072  const Tensor<4, dim, Number> &h,
1073  const Tensor<2, dim, Number> &F)
1074 {
1075  return internal::Physics::transformation_contraction(h, invert(F));
1076 }
1077 
1078 
1079 
1080 template <int dim, typename Number>
1084  const Tensor<2, dim, Number> & F)
1085 {
1086  return internal::Physics::transformation_contraction(h, invert(F));
1087 }
1088 
1089 
1090 
1091 template <int dim, typename Number>
1094  const Tensor<1, dim, Number> &V,
1095  const Tensor<2, dim, Number> &F)
1096 {
1097  return internal::Physics::transformation_contraction(V, transpose(invert(F)));
1098 }
1099 
1100 
1101 
1102 template <int dim, typename Number>
1105  const Tensor<2, dim, Number> &T,
1106  const Tensor<2, dim, Number> &F)
1107 {
1108  return internal::Physics::transformation_contraction(T, transpose(invert(F)));
1109 }
1110 
1111 
1112 
1113 template <int dim, typename Number>
1117  const Tensor<2, dim, Number> & F)
1118 {
1119  return internal::Physics::transformation_contraction(T, transpose(invert(F)));
1120 }
1121 
1122 
1123 
1124 template <int dim, typename Number>
1127  const Tensor<4, dim, Number> &H,
1128  const Tensor<2, dim, Number> &F)
1129 {
1130  return internal::Physics::transformation_contraction(H, transpose(invert(F)));
1131 }
1132 
1133 
1134 
1135 template <int dim, typename Number>
1139  const Tensor<2, dim, Number> & F)
1140 {
1141  return internal::Physics::transformation_contraction(H, transpose(invert(F)));
1142 }
1143 
1144 
1145 
1146 template <int dim, typename Number>
1149  const Tensor<2, dim, Number> &F)
1150 {
1151  return internal::Physics::transformation_contraction(v, transpose(F));
1152 }
1153 
1154 
1155 
1156 template <int dim, typename Number>
1159  const Tensor<2, dim, Number> &F)
1160 {
1161  return internal::Physics::transformation_contraction(t, transpose(F));
1162 }
1163 
1164 
1165 
1166 template <int dim, typename Number>
1170  const Tensor<2, dim, Number> & F)
1171 {
1172  return internal::Physics::transformation_contraction(t, transpose(F));
1173 }
1174 
1175 
1176 
1177 template <int dim, typename Number>
1180  const Tensor<2, dim, Number> &F)
1181 {
1182  return internal::Physics::transformation_contraction(h, transpose(F));
1183 }
1184 
1185 
1186 
1187 template <int dim, typename Number>
1191  const Tensor<2, dim, Number> & F)
1192 {
1193  return internal::Physics::transformation_contraction(h, transpose(F));
1194 }
1195 
1196 
1197 
1198 template <int dim, typename Number>
1201  const Tensor<2, dim, Number> &F)
1202 {
1203  return Number(1.0 / determinant(F)) * Contravariant::push_forward(V, F);
1204 }
1205 
1206 
1207 
1208 template <int dim, typename Number>
1211  const Tensor<2, dim, Number> &F)
1212 {
1213  return Number(1.0 / determinant(F)) * Contravariant::push_forward(T, F);
1214 }
1215 
1216 
1217 
1218 template <int dim, typename Number>
1222  const Tensor<2, dim, Number> & F)
1223 {
1224  return Number(1.0 / determinant(F)) * Contravariant::push_forward(T, F);
1225 }
1226 
1227 
1228 
1229 template <int dim, typename Number>
1232  const Tensor<2, dim, Number> &F)
1233 {
1234  return Number(1.0 / determinant(F)) * Contravariant::push_forward(H, F);
1235 }
1236 
1237 
1238 
1239 template <int dim, typename Number>
1243  const Tensor<2, dim, Number> & F)
1244 {
1245  return Number(1.0 / determinant(F)) * Contravariant::push_forward(H, F);
1246 }
1247 
1248 
1249 
1250 template <int dim, typename Number>
1253  const Tensor<2, dim, Number> &F)
1254 {
1255  return Number(determinant(F)) * Contravariant::pull_back(v, F);
1256 }
1257 
1258 
1259 
1260 template <int dim, typename Number>
1263  const Tensor<2, dim, Number> &F)
1264 {
1265  return Number(determinant(F)) * Contravariant::pull_back(t, F);
1266 }
1267 
1268 
1269 
1270 template <int dim, typename Number>
1274  const Tensor<2, dim, Number> & F)
1275 {
1276  return Number(determinant(F)) * Contravariant::pull_back(t, F);
1277 }
1278 
1279 
1280 
1281 template <int dim, typename Number>
1284  const Tensor<2, dim, Number> &F)
1285 {
1286  return Number(determinant(F)) * Contravariant::pull_back(h, F);
1287 }
1288 
1289 
1290 
1291 template <int dim, typename Number>
1295  const Tensor<2, dim, Number> & F)
1296 {
1297  return Number(determinant(F)) * Contravariant::pull_back(h, F);
1298 }
1299 
1300 
1301 
1302 template <int dim, typename Number>
1305  const Tensor<2, dim, Number> &F)
1306 {
1307  return cofactor(F) * N;
1308 }
1309 
1310 #endif // DOXYGEN
1311 
1312 DEAL_II_NAMESPACE_CLOSE
1313 
1314 #endif
Tensor< 1, dim, Number > pull_back(const Tensor< 1, dim, Number > &v, const Tensor< 2, dim, Number > &F)
Number determinant(const SymmetricTensor< 2, dim, Number > &)
Tensor< 2, 2, Number > rotation_matrix_2d(const Number &angle)
numbers::NumberTraits< Number >::real_type norm() const
Definition: point.h:106
Tensor< 1, dim, Number > nansons_formula(const Tensor< 1, dim, Number > &N, const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)
Tensor< 1, dim, Number > push_forward(const Tensor< 1, dim, Number > &V, const Tensor< 2, dim, Number > &F)
static::ExceptionBase & ExcMessage(std::string arg1)
Tensor< 2, 3, Number > rotation_matrix_3d(const Point< 3, Number > &axis, const Number &angle)
Tensor< 1, dim, Number > push_forward(const Tensor< 1, dim, Number > &V, const Tensor< 2, dim, Number > &F)
#define Assert(cond, exc)
Definition: exceptions.h:1227
Tensor< 1, dim, Number > pull_back(const Tensor< 1, dim, Number > &v, const Tensor< 2, dim, Number > &F)
SymmetricTensor< rank_, dim, Number > transpose(const SymmetricTensor< rank_, dim, Number > &t)
Tensor< 1, dim, Number > push_forward(const Tensor< 1, dim, Number > &V, const Tensor< 2, dim, Number > &F)
Tensor< 1, dim, Number > pull_back(const Tensor< 1, dim, Number > &v, const Tensor< 2, dim, Number > &F)
Definition: mpi.h:55