NuTo
Numerics Tool
Jacobian.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <Eigen/Dense> // for determinant
5 #include "nuto/base/Exception.h"
6 
7 namespace NuTo
8 {
9 
10 class Jacobian
11 {
12 public:
15 
16  Jacobian(const Eigen::VectorXd& nodeValues, const Eigen::MatrixXd& derivativeShapeFunctions)
17  {
18  const int interpolationDimension = derivativeShapeFunctions.cols();
19  const int numNodes = derivativeShapeFunctions.rows();
20  const int globalDimension = nodeValues.rows() / numNodes;
21  if (interpolationDimension == globalDimension)
22  {
23  switch (globalDimension)
24  {
25  case 1:
26  {
27  Eigen::Matrix<double, 1, 1> jacobian = CalculateFixedSize<1, 1>(nodeValues, derivativeShapeFunctions);
28  mJacobian = jacobian;
29  mInvJacobian = jacobian.inverse();
30  mDetJacobian = jacobian.determinant();
31  break;
32  }
33  case 2:
34  {
35  Eigen::Matrix<double, 2, 2> jacobian = CalculateFixedSize<2, 2>(nodeValues, derivativeShapeFunctions);
36  mJacobian = jacobian;
37  mInvJacobian = jacobian.inverse();
38  mDetJacobian = jacobian.determinant();
39  break;
40  }
41  case 3:
42  {
43  Eigen::Matrix<double, 3, 3> jacobian = CalculateFixedSize<3, 3>(nodeValues, derivativeShapeFunctions);
44  mJacobian = jacobian;
45  mInvJacobian = jacobian.inverse();
46  mDetJacobian = jacobian.determinant();
47  break;
48  }
49  }
50  }
51  else if (globalDimension == interpolationDimension + 1)
52  {
53  switch (globalDimension)
54  {
55  case 2:
56  {
57  Eigen::Matrix<double, 2, 1> jacobian = CalculateFixedSize<2, 1>(nodeValues, derivativeShapeFunctions);
58  Eigen::Matrix<double, 2, 2> extendedJacobian;
59  mNormal = Eigen::Vector2d(jacobian(1, 0), -jacobian(0, 0)).normalized();
60  extendedJacobian.col(0) = jacobian;
61  extendedJacobian.col(1) = mNormal;
62  mJacobian = jacobian;
63  mInvJacobian = extendedJacobian.inverse().block<1, 2>(0, 0);
64  mDetJacobian = -extendedJacobian.determinant();
65  break;
66  }
67  case 3:
68  {
69  Eigen::Matrix<double, 3, 2> jacobian = CalculateFixedSize<3, 2>(nodeValues, derivativeShapeFunctions);
70  Eigen::Matrix<double, 3, 3> extendedJacobian;
71  mNormal = (jacobian.col(0)).cross(jacobian.col(1)).normalized();
72  extendedJacobian.col(0) = jacobian.col(0);
73  extendedJacobian.col(1) = jacobian.col(1);
74  extendedJacobian.col(2) = mNormal;
75  mJacobian = jacobian;
76  mInvJacobian = extendedJacobian.inverse().block<2, 3>(0, 0);
77  ;
78  mDetJacobian = extendedJacobian.determinant();
79  break;
80  }
81  default:
82  {
83  throw Exception(__PRETTY_FUNCTION__,
84  "Global dimension should be 2 or 3 for codimension 1 objects, got: " +
85  std::to_string(globalDimension) + ".");
86  }
87  }
88  }
89  else
90  {
91  throw Exception(__PRETTY_FUNCTION__,
92  "Jacobian only implemented for interpolationDimension equal to globaldimension or one "
93  "less, got: \n"
94  "InterpolationDimension: " +
95  std::to_string(interpolationDimension) + "\n" +
96  "GlobalDimension: " + std::to_string(globalDimension));
97  }
98  }
99 
100  Eigen::MatrixXd TransformDerivativeShapeFunctions(const Eigen::MatrixXd& global) const
101  {
102  return global * Inv();
103  }
104 
105  const Dynamic3by3& Inv() const
106  {
107  return mInvJacobian;
108  }
109 
110  const Dynamic3by3& Get() const
111  {
112  return mJacobian;
113  }
114 
115  const Dynamic3by1& Normal() const
116  {
117  if (mJacobian.cols() != (mJacobian.rows() - 1))
118  {
119  throw Exception(__PRETTY_FUNCTION__,
120  "Normal not available for elements with SpaceDimension - LocalDimension != 1");
121  }
122  return mNormal;
123  }
124 
125  double Det() const
126  {
127  return mDetJacobian;
128  }
129 
130 private:
131  template <int TSpaceDim, int TLocalDim>
132  Eigen::Matrix<double, TSpaceDim, TLocalDim> CalculateFixedSize(Eigen::VectorXd nodeValues,
133  const Eigen::MatrixXd& derivativeShapeFunctions)
134  {
135  const int numShapes = derivativeShapeFunctions.rows();
136  auto nodeBlockCoordinates =
137  Eigen::Map<Eigen::Matrix<double, TSpaceDim, Eigen::Dynamic>>(nodeValues.data(), TSpaceDim, numShapes);
138  // This mapping converts a vector
139  // (x0 y0 z0 x1 y1 z1 x2 y2 z3 ...)^T
140  // to the matrix
141  // x0 x1 x2 x3 ...
142  // y0 y1 y2 y3 ...
143  // z0 z1 z2 z3 ...
144  Eigen::Matrix<double, TSpaceDim, TLocalDim> jacobian = nodeBlockCoordinates * derivativeShapeFunctions;
145  return jacobian;
146  }
147 
148  Dynamic3by1 mNormal;
149  Dynamic3by3 mJacobian;
150  Dynamic3by3 mInvJacobian;
151  double mDetJacobian;
152 };
153 } /* NuTo */
Base class for all exceptions thrown in NuTo.
Definition: Exception.h:9
Definition: Jacobian.h:10
const Dynamic3by3 & Inv() const
Definition: Jacobian.h:105
const Dynamic3by1 & Normal() const
Definition: Jacobian.h:115
Eigen::MatrixXd TransformDerivativeShapeFunctions(const Eigen::MatrixXd &global) const
Definition: Jacobian.h:100
double Det() const
Definition: Jacobian.h:125
const Dynamic3by3 & Get() const
Definition: Jacobian.h:110
Definition: Exception.h:6
Jacobian(const Eigen::VectorXd &nodeValues, const Eigen::MatrixXd &derivativeShapeFunctions)
Definition: Jacobian.h:16