14#include <Eigen/Geometry>
24static double const tolerance = std::numeric_limits<double>::epsilon();
28 Eigen::Matrix<double, Dim, Dim, Eigen::ColMajor, Dim, Dim>
const& t)
30 if (std::abs(t.determinant() - 1) >
tolerance)
33 "The determinant of the coordinate system transformation matrix is "
34 "'{:g}', which is not sufficiently close to unity with the "
35 "tolerance of '{:g}'. Please adjust the accuracy of the local "
39 if (((t * t.transpose() - Eigen::Matrix<double, Dim, Dim>::Identity())
44 "The transformation is not orthogonal because the difference "
45 "A*A^T - I is:\n{}\nand at least one component deviates from zero "
46 "by more then '{:g}'.",
47 (t * t.transpose() - Eigen::Matrix<double, Dim, Dim>::Identity())
53template <
typename Derived>
55 std::string_view
const parmeter_name)
57 if (std::abs(vec.squaredNorm() - 1.0) >
tolerance)
60 "The direction vector given by parameter {:s} for the "
61 "local_coordinate_system is not normalized to unit length. Vector "
62 "norm is {:g} and |v|^2-1 = {:g}.",
63 parmeter_name, vec.norm(), vec.squaredNorm() - 1.0);
68 : _base{nullptr, nullptr, &unit_direction}, _has_implicit_base(true)
70 if (
_base[2]->isTimeDependent())
73 "The unit_normal parameter named {} must not be time dependent.",
80 : _base{&e0, &e1, nullptr}, _has_implicit_base(false)
85 "The parameter types for the basis must be equal but they are "
87 typeid(
_base[0]).name(),
88 typeid(
_base[1]).name());
90 if (
_base[0]->isTimeDependent() ||
_base[1]->isTimeDependent())
92 OGS_FATAL(
"The parameters for the basis must not be time dependent.");
94 if (
_base[0]->getNumberOfGlobalComponents() != 2 ||
95 _base[1]->getNumberOfGlobalComponents() != 2)
97 OGS_FATAL(
"The parameters for the 2D basis must have two components.");
104 : _base{&e0, &e1, &e2}, _has_implicit_base(false)
111 "The parameter types for the basis must be equal but they are "
112 "'{:s}', '{:s}', and '{:s}'.",
113 typeid(
_base[0]).name(),
114 typeid(
_base[1]).name(),
115 typeid(
_base[2]).name());
117 if (
_base[0]->isTimeDependent() ||
_base[1]->isTimeDependent(),
118 _base[2]->isTimeDependent())
120 OGS_FATAL(
"The parameters for the basis must not be time dependent.");
122 if (
_base[0]->getNumberOfGlobalComponents() != 3 ||
123 _base[1]->getNumberOfGlobalComponents() != 3 ||
124 _base[2]->getNumberOfGlobalComponents() != 3)
127 "The parameters for the 3D basis must have three components.");
134 auto const& normal = unit_direction(0 , pos);
136 unit_direction.
name);
138 Eigen::Matrix<double, 2, 2> t;
141 t << normal[1], normal[0], -normal[0], normal[1];
156 if (
_base[2] !=
nullptr)
159 "The coordinate system is 3D but a transformation for 2D case is "
163 Eigen::Matrix<double, 2, 2> t;
164 t.col(0) = Eigen::Map<Eigen::Vector2d>(
165 (*
_base[0])(0 , pos).data());
166 t.col(1) = Eigen::Map<Eigen::Vector2d>(
167 (*
_base[1])(0 , pos).data());
176 auto const& normal = unit_direction(0 , pos);
178 Eigen::Matrix<double, 3, 3> t;
180 e2 = Eigen::Map<Eigen::Vector3d const>(normal.data());
185 e2.cwiseAbs().maxCoeff(&
id);
188 const auto id_a = (
id + 1) % 3;
189 const auto id_b = (
id + 2) % 3;
193 e1 = Eigen::Vector3d::Zero();
206 e1[id_b] = -e2[id_a] / e2[id_b];
214 t.col(0) = e1.cross(e2);
230 if (
_base[2] ==
nullptr)
233 "The coordinate system is 2D but a transformation for 3D case is "
237 Eigen::Matrix<double, 3, 3> t;
238 t.col(0) = Eigen::Map<Eigen::Vector3d>(
239 (*
_base[0])(0 , pos).data());
240 t.col(1) = Eigen::Map<Eigen::Vector3d>(
241 (*
_base[1])(0 , pos).data());
242 t.col(2) = Eigen::Map<Eigen::Vector3d>(
243 (*
_base[2])(0 , pos).data());
253 if ((*
_base[2])(0 , pos).size() == 3)
259 Eigen::Matrix<double, 3, 3> t = Eigen::Matrix<double, 3, 3>::Identity();
273 if (
_base[2] !=
nullptr)
278 auto e0 = (*
_base[0])(0 , pos);
279 auto e1 = (*
_base[1])(0 , pos);
280 Eigen::Matrix<double, 3, 3> t = Eigen::Matrix<double, 3, 3>::Identity();
281 t.template topLeftCorner<2, 2>() << e0[0], e1[0], e0[1], e1[1];
287template <
int Dimension>
291 assert(values.size() == Dimension * Dimension ||
292 "Input vector has wrong dimension; expected 4 or 9 entries.");
294 Eigen::Map<Eigen::Matrix<double, Dimension, Dimension>
const>(
295 values.data(), Dimension, Dimension);
299template <
int Dimension>
300Eigen::Matrix<double, Dimension, Dimension>
304 assert(values.size() == Dimension ||
305 "Input vector has wrong dimension; expected 2 or 3 entries.");
306 auto const tensor = Eigen::Map<Eigen::Matrix<double, Dimension, 1>
const>(
307 values.data(), Dimension, 1);
309 return R * tensor.asDiagonal() * R.transpose();
Eigen::Matrix< double, 2, 2 > getTransformationFromSingleBase2D(Parameter< double > const &unit_direction, SpatialPosition const &pos)
static double const tolerance
static void checkNormalization(Eigen::MatrixBase< Derived > const &vec, std::string_view const parmeter_name)
static void checkTransformationIsSON(Eigen::Matrix< double, Dim, Dim, Eigen::ColMajor, Dim, Dim > const &t)
Eigen::Matrix< double, 3, 3 > getTransformationFromSingleBase3D(Parameter< double > const &unit_direction, SpatialPosition const &pos)
std::array< Parameter< double > const *, 3 > _base
Eigen::Matrix< double, Dimension, Dimension > transformation(SpatialPosition const &pos) const
Eigen::Matrix< double, 3, 3 > transformationFromSingleBase_3d(SpatialPosition const &pos) const
Eigen::Matrix< double, 3, 3 > transformation_3d(SpatialPosition const &pos) const
Eigen::Matrix< double, Dimension, Dimension > rotateTensor(std::vector< double > const &values, SpatialPosition const &pos) const
Eigen::Matrix< double, Dimension, Dimension > rotateDiagonalTensor(std::vector< double > const &values, SpatialPosition const &pos) const
CoordinateSystem(Parameter< double > const &unit_direction)