19constexpr int size(
int const displacement_dim)
21 if (displacement_dim == 1)
25 if (displacement_dim == 2)
29 if (displacement_dim == 3)
34 "Cannot convert displacement dimension {} to vectorized tensor size.",
39template <
typename VectorizedTensor>
42 static_assert(VectorizedTensor::ColsAtCompileTime == 1);
43 constexpr int rows = VectorizedTensor::RowsAtCompileTime;
57 "Cannot convert vectorized tensor of size {} to displacement "
65template <
int DisplacementDim>
66using Type = Eigen::Matrix<double,
size(DisplacementDim), 1, Eigen::ColMajor>;
70template <
int DisplacementDim>
74 0 < DisplacementDim && DisplacementDim <= 3,
75 "Identity is implemented only for displacement dimension 1, 2, or 3.");
77 size(DisplacementDim), 1,
78 [](Eigen::Index
const row, [[maybe_unused]] Eigen::Index
const col)
81 if constexpr (DisplacementDim == 1)
85 if constexpr (DisplacementDim == 2)
87 if (row == 0 || row == 3 || row == 4)
92 if constexpr (DisplacementDim == 3)
94 if (row == 0 || row == 4 || row == 8)
104template <
typename Derived>
108 static_assert(0 < displacement_dim && displacement_dim <= 3,
109 "Vectorized tensor determinant is implemented only for "
110 "displacement dimension 1, 2, or 3.");
112 if constexpr (displacement_dim == 1)
114 return tensor[0] * tensor[1] * tensor[2];
116 if constexpr (displacement_dim == 2)
118 Eigen::Map<Eigen::Matrix2d const>
const top_left{
119 tensor.derived().data()};
121 return top_left.determinant() * tensor[4];
123 if constexpr (displacement_dim == 3)
125 return Eigen::Map<Eigen::Matrix3d const>(tensor.derived().data())
145template <
int DisplacementDim,
typename Derived>
148 static_assert(0 < DisplacementDim && DisplacementDim <= 3,
149 "Conversion to displacement dimension other than 1, 2, or 3 "
152 constexpr int rows = Derived::RowsAtCompileTime;
153 constexpr int cols = Derived::ColsAtCompileTime;
154 static_assert(rows == 3 || rows == Eigen::Dynamic);
155 static_assert(cols == 3 || cols == Eigen::Dynamic);
156 if (tensor.rows() != 3 || tensor.cols() != 3)
159 "Incorrect tensor size, must be 3x3, but tensor is {:d}x{:d}.",
160 tensor.rows(), tensor.cols());
163 if constexpr (DisplacementDim == 1)
168 "Cannot convert a tensor with non-zero off-diagonal elements "
169 "to a 1d vectorized tensor representation.");
171 return tensor.diagonal();
173 if constexpr (DisplacementDim == 2)
178 "Cannot convert a tensor with non-zero elements at (0, 2), (1, "
179 "2), (2, 0), and (2, 1) positions to a 2d vectorized tensor "
183 result.template head<4>() =
184 tensor.template block<2, 2>(0, 0).reshaped();
185 result(4) = tensor(2, 2);
188 if constexpr (DisplacementDim == 3)
190 return tensor.reshaped();
193 "Not all cases handled in the VectorizedTensor::toVector() function.");
197template <
int DisplacementDim>
201 DisplacementDim == 1 || DisplacementDim == 2 || DisplacementDim == 3,
202 "Conversion from displacement dimension other than 1, 2, or 3 "
205 using Matrix = Eigen::Matrix3d;
206 if constexpr (DisplacementDim == 1)
208 return tensor.asDiagonal();
210 if constexpr (DisplacementDim == 2)
212 Matrix m = Matrix::Zero();
213 m.template block<2, 2>(0, 0) =
214 Eigen::Map<Eigen::Matrix<double, 2, 2>
const>(tensor.data());
218 if constexpr (DisplacementDim == 3)
220 return Eigen::Map<Matrix const>(tensor.data());
constexpr int dimension()
Displacement dimension of a vectorized tensor.
bool isTensorConvertibleTo2d(Eigen::Matrix3d const &tensor)
double determinant(Eigen::MatrixBase< Derived > const &tensor)
Computes determinant of a vectorized tensor.
constexpr int size(int const displacement_dim)
Vectorized tensor size for given displacement dimension.
bool isTensorConvertibleTo1d(Eigen::Matrix3d const &tensor)
Only a diagonal tensor can be converted to a 1d vectorized tensor.
Eigen::Matrix< double, size(DisplacementDim), 1, Eigen::ColMajor > Type
constexpr auto identity()
Eigen::Matrix3d toTensor(Type< DisplacementDim > const &tensor)
Converts a vectorized tensor to a 3x3 matrix.
Type< DisplacementDim > toVector(Eigen::MatrixBase< Derived > const &tensor)