From e63caf5a564788a882d736bb10ad5e20af1b7957 Mon Sep 17 00:00:00 2001
From: Sebastian Eibl <sebastian.eibl@fau.de>
Date: Tue, 6 Nov 2018 15:25:20 +0100
Subject: [PATCH] replaced the common R*A*R^T pattern with an optimized version

---
 src/core/math/Matrix3.h         | 20 ++++++++++++++++++--
 src/pe/rigidbody/RigidBody.h    |  8 ++++----
 tests/core/math/Matrix3Test.cpp |  8 ++++++++
 3 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/src/core/math/Matrix3.h b/src/core/math/Matrix3.h
index 3f38c096b..54119bee9 100644
--- a/src/core/math/Matrix3.h
+++ b/src/core/math/Matrix3.h
@@ -1677,8 +1677,24 @@ Matrix3< typename MathTrait<T0,T1>::High > tensorProduct( Vector3<T0> v0, Vector
 }
 //**********************************************************************************************************************
 
-
-
+/**
+ * Equivalent to R*A*R.getTranspose().
+ */
+template< typename Type>
+inline Matrix3< Type > transformMatrixRART( const Matrix3<Type>& R, const Matrix3<Type>& A )
+{
+   const auto r0 = A[0]*R[0]*R[0] + A[1]*R[0]*R[1] + A[2]*R[0]*R[2] + A[3]*R[0]*R[1] + A[4]*R[1]*R[1] + A[5]*R[1]*R[2] + A[6]*R[0]*R[2] + A[7]*R[1]*R[2] + A[8]*R[2]*R[2];
+   const auto r1 = A[0]*R[0]*R[3] + A[1]*R[0]*R[4] + A[2]*R[0]*R[5] + A[3]*R[1]*R[3] + A[4]*R[1]*R[4] + A[5]*R[1]*R[5] + A[6]*R[2]*R[3] + A[7]*R[2]*R[4] + A[8]*R[2]*R[5];
+   const auto r2 = A[0]*R[0]*R[6] + A[1]*R[0]*R[7] + A[2]*R[0]*R[8] + A[3]*R[1]*R[6] + A[4]*R[1]*R[7] + A[5]*R[1]*R[8] + A[6]*R[2]*R[6] + A[7]*R[2]*R[7] + A[8]*R[2]*R[8];
+   const auto r3 = A[0]*R[0]*R[3] + A[1]*R[1]*R[3] + A[2]*R[2]*R[3] + A[3]*R[0]*R[4] + A[4]*R[1]*R[4] + A[5]*R[2]*R[4] + A[6]*R[0]*R[5] + A[7]*R[1]*R[5] + A[8]*R[2]*R[5];
+   const auto r4 = A[0]*R[3]*R[3] + A[1]*R[3]*R[4] + A[2]*R[3]*R[5] + A[3]*R[3]*R[4] + A[4]*R[4]*R[4] + A[5]*R[4]*R[5] + A[6]*R[3]*R[5] + A[7]*R[4]*R[5] + A[8]*R[5]*R[5];
+   const auto r5 = A[0]*R[3]*R[6] + A[1]*R[3]*R[7] + A[2]*R[3]*R[8] + A[3]*R[4]*R[6] + A[4]*R[4]*R[7] + A[5]*R[4]*R[8] + A[6]*R[5]*R[6] + A[7]*R[5]*R[7] + A[8]*R[5]*R[8];
+   const auto r6 = A[0]*R[0]*R[6] + A[1]*R[1]*R[6] + A[2]*R[2]*R[6] + A[3]*R[0]*R[7] + A[4]*R[1]*R[7] + A[5]*R[2]*R[7] + A[6]*R[0]*R[8] + A[7]*R[1]*R[8] + A[8]*R[2]*R[8];
+   const auto r7 = A[0]*R[3]*R[6] + A[1]*R[4]*R[6] + A[2]*R[5]*R[6] + A[3]*R[3]*R[7] + A[4]*R[4]*R[7] + A[5]*R[5]*R[7] + A[6]*R[3]*R[8] + A[7]*R[4]*R[8] + A[8]*R[5]*R[8];
+   const auto r8 = A[0]*R[6]*R[6] + A[1]*R[6]*R[7] + A[2]*R[6]*R[8] + A[3]*R[6]*R[7] + A[4]*R[7]*R[7] + A[5]*R[7]*R[8] + A[6]*R[6]*R[8] + A[7]*R[7]*R[8] + A[8]*R[8]*R[8];
+
+   return Matrix3<Type>(r0,r1,r2,r3,r4,r5,r6,r7,r8);
+}
 
 } // namespace math
 
diff --git a/src/pe/rigidbody/RigidBody.h b/src/pe/rigidbody/RigidBody.h
index fdebc3ff6..4f872a685 100644
--- a/src/pe/rigidbody/RigidBody.h
+++ b/src/pe/rigidbody/RigidBody.h
@@ -874,7 +874,7 @@ inline const Mat3& RigidBody::getBodyInertia() const
  */
 inline const Mat3 RigidBody::getInertia() const
 {
-   return R_ * I_ * R_.getTranspose();
+   return math::transformMatrixRART(R_, I_);
 }
 //*************************************************************************************************
 
@@ -898,7 +898,7 @@ inline const Mat3& RigidBody::getInvBodyInertia() const
  */
 inline const Mat3 RigidBody::getInvInertia() const
 {
-   return R_ * Iinv_ * R_.getTranspose();
+   return math::transformMatrixRART(R_, Iinv_);
 }
 //*************************************************************************************************
 
@@ -1810,7 +1810,7 @@ inline void RigidBody::addImpulseAtPos( const Vec3& j, const Vec3& p )
 {
    if( !hasSuperBody() ) {
       v_ += j * invMass_;
-      w_ += ( R_ * Iinv_ * R_.getTranspose() ) * ( ( p - gpos_ ) % j );
+      w_ += getInvInertia() * ( ( p - gpos_ ) % j );
       wake();
    }
    else sb_->addImpulseAtPos( j, p );
@@ -2002,7 +2002,7 @@ inline const Vec3 RigidBody::accFromWF( const Vec3& gpos ) const
       const Vec3 vdot( force_ * invMass_ );
 
       // Calculating the angular acceleration
-      const Vec3 wdot( R_ * Iinv_ * R_.getTranspose() * ( torque_ - w_ % ( R_ * I_ * R_.getTranspose() * w_ ) ) );
+      const Vec3 wdot( getInvInertia() * ( torque_ - w_ % ( getInertia() * w_ ) ) );
 
       // Calculating the distance to the center of mass of the superordinate body
       const Vec3 r( gpos - gpos_ );
diff --git a/tests/core/math/Matrix3Test.cpp b/tests/core/math/Matrix3Test.cpp
index 1cfbb83a2..7fd6aea27 100644
--- a/tests/core/math/Matrix3Test.cpp
+++ b/tests/core/math/Matrix3Test.cpp
@@ -62,6 +62,13 @@ void rotationTest()
    WALBERLA_CHECK_FLOAT_EQUAL_EPSILON( result, cmp, real_t(1e-5) );
 }
 
+void RARTTest()
+{
+   Matrix3<real_t> A ( 1,2,3,4,5,6,7,8,9 );
+   Matrix3<real_t> R ( 2,3,4,5,6,7,8,9,1 );
+   WALBERLA_CHECK_FLOAT_EQUAL( math::transformMatrixRART(R,A), R * A * R.getTranspose() );
+}
+
 int main()
 {
 
@@ -72,6 +79,7 @@ int main()
    m1 * m2;
 
    rotationTest();
+   RARTTest();
 
    return 0;
 }
-- 
GitLab