From 214572e4285100ac2a5d2f8cd4df6de6f1416b0f Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Mon, 23 May 2011 15:23:26 +0000 Subject: [PATCH] implement all the methods that are necessary to use this with the general gfe infrastructure [[Imported from SVN: r7314]] --- dune/gfe/rotation.hh | 132 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/dune/gfe/rotation.hh b/dune/gfe/rotation.hh index e002b6ca..58f74544 100644 --- a/dune/gfe/rotation.hh +++ b/dune/gfe/rotation.hh @@ -11,6 +11,8 @@ #include <dune/common/exceptions.hh> #include "quaternion.hh" +#include <dune/gfe/tensor3.hh> +#include <dune/gfe/unitvector.hh> template <int dim, class T> @@ -145,8 +147,14 @@ public: typedef T ctype; /** \brief Global coordinates wrt an isometric embedding function are available */ - static const bool globalIsometricCoordinates = false; + static const bool globalIsometricCoordinates = true; + /** \brief The type used for global coordinates */ + typedef Dune::FieldVector<double,4> CoordinateType; + + /** \brief Dimension of the manifold formed by the 3d rotations */ + static const int dim = 3; + /** \brief Member of the corresponding Lie algebra. This really is a skew-symmetric matrix */ typedef Dune::FieldVector<T,3> TangentVector; @@ -157,7 +165,21 @@ public: Rotation() : Quaternion<T>(0,0,0,1) {} + + Rotation<3,T>(const Dune::array<T,4>& c) + { + for (int i=0; i<4; i++) + (*this)[i] = c[i]; + *this /= this->two_norm(); + } + + Rotation<3,T>(const Dune::FieldVector<T,4>& c) + : Quaternion<T>(c) + { + *this /= this->two_norm(); + } + Rotation<3,T>(Dune::FieldVector<T,3> axis, T angle) : Quaternion<T>(axis, angle) {} @@ -263,6 +285,27 @@ public: return exp(p, vMatrix); } + static Rotation<3,T> exp(const Rotation<3,T>& p, const Dune::FieldVector<T,4>& v) { + + assert( std::fabs(p*v) < 1e-8 ); + + // The vector v as a quaternion + Quaternion<T> vQuat(v); + + // left multiplication by the inverse base point yields a tangent vector at the identity + Quaternion<T> vAtIdentity = p.inverse().mult(vQuat); + assert( std::fabs(vAtIdentity[3]) < 1e-8 ); + + // vAtIdentity as a skew matrix + TangentVector vMatrix; + vMatrix[0] = 2*vAtIdentity[0]; + vMatrix[1] = 2*vAtIdentity[1]; + vMatrix[2] = 2*vAtIdentity[2]; + + // The actual exponential map + return exp(p, vMatrix); + } + static Dune::FieldMatrix<T,4,3> Dexp(const Dune::FieldVector<T,3>& v) { Dune::FieldMatrix<T,4,3> result(0); @@ -450,6 +493,69 @@ public: return projectedResult; } + + /** \brief Compute the Hessian of the squared distance function keeping the first argument fixed + + Unlike the distance itself the squared distance is differentiable at zero + */ + static Dune::FieldMatrix<double,4,4> secondDerivativeOfDistanceSquaredWRTSecondArgument(const Rotation<3,T>& p, const Rotation<3,T>& q) { + // use the functionality from the unitvector class + Dune::FieldMatrix<double,4,4> result = UnitVector<4>::secondDerivativeOfDistanceSquaredWRTSecondArgument(p.globalCoordinates(), + q.globalCoordinates()); + // for some reason that I don't really understand, the distance we have defined for the rotations (== Unit quaternions) + // is twice the corresponding distance on the unit quaternions seen as a sphere. Hence the derivative of the + // squared distance needs to be multiplied by 4. + result *= 4; + return result; + } + + /** \brief Compute the mixed second derivate \partial d^2 / \partial da db + + Unlike the distance itself the squared distance is differentiable at zero + */ + static Dune::FieldMatrix<double,4,4> secondDerivativeOfDistanceSquaredWRTFirstAndSecondArgument(const Rotation<3,T>& p, const Rotation<3,T>& q) { + // use the functionality from the unitvector class + Dune::FieldMatrix<double,4,4> result = UnitVector<4>::secondDerivativeOfDistanceSquaredWRTFirstAndSecondArgument(p.globalCoordinates(), + q.globalCoordinates()); + // for some reason that I don't really understand, the distance we have defined for the rotations (== Unit quaternions) + // is twice the corresponding distance on the unit quaternions seen as a sphere. Hence the derivative of the + // squared distance needs to be multiplied by 4. + result *= 4; + return result; + } + + /** \brief Compute the third derivative \partial d^3 / \partial dq^3 + + Unlike the distance itself the squared distance is differentiable at zero + */ + static Tensor3<double,4,4,4> thirdDerivativeOfDistanceSquaredWRTSecondArgument(const Rotation<3,T>& p, const Rotation<3,T>& q) { + // use the functionality from the unitvector class + Tensor3<double,4,4,4> result = UnitVector<4>::thirdDerivativeOfDistanceSquaredWRTSecondArgument(p.globalCoordinates(), + q.globalCoordinates()); + // for some reason that I don't really understand, the distance we have defined for the rotations (== Unit quaternions) + // is twice the corresponding distance on the unit quaternions seen as a sphere. Hence the derivative of the + // squared distance needs to be multiplied by 4. + result *= 4; + return result; + } + + /** \brief Compute the mixed third derivative \partial d^3 / \partial da db^2 + + Unlike the distance itself the squared distance is differentiable at zero + */ + static Tensor3<double,4,4,4> thirdDerivativeOfDistanceSquaredWRTFirst1AndSecond2Argument(const Rotation<3,T>& p, const Rotation<3,T>& q) { + // use the functionality from the unitvector class + Tensor3<double,4,4,4> result = UnitVector<4>::thirdDerivativeOfDistanceSquaredWRTFirst1AndSecond2Argument(p.globalCoordinates(), + q.globalCoordinates()); + // for some reason that I don't really understand, the distance we have defined for the rotations (== Unit quaternions) + // is twice the corresponding distance on the unit quaternions seen as a sphere. Hence the derivative of the + // squared distance needs to be multiplied by 4. + result *= 4; + return result; + } + + + /** \brief Interpolate between two rotations */ static Rotation<3,T> interpolate(const Rotation<3,T>& a, const Rotation<3,T>& b, double omega) { @@ -607,6 +713,30 @@ public: return r; } + /** \brief Project tangent vector of R^n onto the tangent space */ + EmbeddedTangentVector projectOntoTangentSpace(const EmbeddedTangentVector& v) const { + EmbeddedTangentVector result = v; + EmbeddedTangentVector data = *this; + result.axpy(-1*(data*result), data); + return result; + } + + /** \brief The global coordinates, if you really want them */ + const CoordinateType& globalCoordinates() const { + return *this; + } + + /** \brief Compute an orthonormal basis of the tangent space of S^n. + + This basis is of course not globally continuous. + */ + Dune::FieldMatrix<double,3,4> orthonormalFrame() const { + Dune::FieldMatrix<double,3,4> result; + for (int i=0; i<3; i++) + result[i] = B(i); + return result; + } + }; -- GitLab