diff --git a/dune/gfe/localprojectedfefunction.hh b/dune/gfe/localprojectedfefunction.hh
index 237b0ab88f948e8a19e50c9651cb156c2c86cd58..9f9c5d77c8b9a1924bb90d6a1e6c4e03b25a36e9 100644
--- a/dune/gfe/localprojectedfefunction.hh
+++ b/dune/gfe/localprojectedfefunction.hh
@@ -10,6 +10,7 @@
 #include <dune/gfe/rotation.hh>
 #include <dune/gfe/rigidbodymotion.hh>
 #include <dune/gfe/linearalgebra.hh>
+#include <dune/gfe/polardecomposition.hh>
 
 namespace Dune {
 
@@ -174,22 +175,6 @@ namespace Dune {
 
       static const int spaceDim = TargetSpace::TangentVector::dimension;
 
-      static FieldMatrix<field_type,3,3> polarFactor(const FieldMatrix<field_type,3,3>& matrix)
-      {
-        // Use Higham's method
-        auto polar = matrix;
-        for (size_t i=0; i<3; i++)
-        {
-          auto polarInvert = polar;
-          polarInvert.invert();
-          for (size_t j=0; j<polar.N(); j++)
-            for (size_t k=0; k<polar.M(); k++)
-              polar[j][k] = 0.5 * (polar[j][k] + polarInvert[k][j]);
-        }
-
-        return polar;
-      }
-
       /**
        * \param A The argument of the projection
        * \param polar The image of the projection, i.e., the polar factor of A
@@ -208,9 +193,11 @@ namespace Dune {
         polar = A;
 
         // Use Heron's method
-        const size_t maxIterations = 3;
+        const size_t maxIterations = 100;
+        double tol = 0.001;
         for (size_t iteration=0; iteration<maxIterations; iteration++)
         {
+          auto oldPolar = polar;
           auto polarInvert = polar;
           polarInvert.invert();
           for (size_t i=0; i<polar.N(); i++)
@@ -241,6 +228,11 @@ namespace Dune {
               for (int k=0; k<3; k++)
                 for (int l=0; l<3; l++)
                   result[i][j][k][l] = 0.5 * (result[i][j][k][l] - tmp2[i][j][k][l]);
+
+          oldPolar -= polar;
+          if (oldPolar.frobenius_norm() < tol) {
+            break;
+          }
         }
 
         return result;
@@ -295,7 +287,7 @@ namespace Dune {
         }
 
         // Project back onto SO(3)
-        result.set(polarFactor(interpolatedMatrix));
+        result.set(Dune::GFE::PolarDecomposition()(interpolatedMatrix));
 
         return result;
       }
diff --git a/dune/gfe/nonplanarcosseratshellenergy.hh b/dune/gfe/nonplanarcosseratshellenergy.hh
index 4a5daa42e0ab4a1b834c4713739562674910d4a1..f8d4b3bf8ba55e79cbd29b14dc270dc18177426f 100644
--- a/dune/gfe/nonplanarcosseratshellenergy.hh
+++ b/dune/gfe/nonplanarcosseratshellenergy.hh
@@ -307,15 +307,15 @@ energy(const typename Basis::LocalView& localView,
     //////////////////////////////////////////////////////////
 
     // Add the membrane energy density
-    auto energyDensity = (thickness_ - K*Dune::Power<3>::eval(thickness_) / 12.0) * W_m(Ee)
-                       + (Dune::Power<3>::eval(thickness_) / 12.0 - K * Dune::Power<5>::eval(thickness_) / 80.0)*W_m(Ee*b + c*Ke)
-                       + Dune::Power<3>::eval(thickness_) / 6.0 * W_mixt(Ee, c*Ke*b - 2*H*c*Ke)
-                       + Dune::Power<5>::eval(thickness_) / 80.0 * W_mp( (Ee*b + c*Ke)*b);
+    auto energyDensity = (thickness_ - K*Dune::power(thickness_,3) / 12.0) * W_m(Ee)
+                       + (Dune::power(thickness_,3) / 12.0 - K * Dune::power(thickness_,5) / 80.0)*W_m(Ee*b + c*Ke)
+                       + Dune::power(thickness_,3) / 6.0 * W_mixt(Ee, c*Ke*b - 2*H*c*Ke)
+                       + Dune::power(thickness_,5) / 80.0 * W_mp( (Ee*b + c*Ke)*b);
 
     // Add the bending energy density
-    energyDensity += (thickness_ - K*Dune::Power<3>::eval(thickness_) / 12.0) * W_curv(Ke)
-                   + (Dune::Power<3>::eval(thickness_) / 12.0 - K * Dune::Power<5>::eval(thickness_) / 80.0)*W_curv(Ke*b)
-                   + Dune::Power<5>::eval(thickness_) / 80.0 * W_curv(Ke*b*b);
+    energyDensity += (thickness_ - K*Dune::power(thickness_,3) / 12.0) * W_curv(Ke)
+                   + (Dune::power(thickness_,3) / 12.0 - K * Dune::power(thickness_,5) / 80.0)*W_curv(Ke*b)
+                   + Dune::power(thickness_,5) / 80.0 * W_curv(Ke*b*b);
 
     // Add energy density
     energy += quad[pt].weight() * integrationElement * energyDensity;
diff --git a/dune/gfe/periodic1dpq1nodalbasis.hh b/dune/gfe/periodic1dpq1nodalbasis.hh
index aa9f2abdc2048d1e31c1efde99831719522d44e8..f1f415e7b8a2d64b60a133eabb4fdeb7578eec4e 100644
--- a/dune/gfe/periodic1dpq1nodalbasis.hh
+++ b/dune/gfe/periodic1dpq1nodalbasis.hh
@@ -4,6 +4,7 @@
 #define DUNE_GFE_PERIODIC_1D_PQ1NODALBASIS_HH
 
 #include <dune/common/exceptions.hh>
+#include <dune/common/math.hh>
 
 #include <dune/localfunctions/lagrange/pqkfactory.hh>
 
@@ -109,7 +110,7 @@ public:
 
   size_type maxNodeSize() const
   {
-    return StaticPower<2,GV::dimension>::power;
+    return Dune::power(2,GV::dimension);
   }
 
 //protected:
@@ -123,7 +124,7 @@ class Periodic1DPQ1Node :
   public LeafBasisNode
 {
   static const int dim = GV::dimension;
-  static const int maxSize = StaticPower<2,GV::dimension>::power;
+  static const int maxSize = Dune::power(2,GV::dimension);
 
   using FiniteElementCache = typename Dune::PQkLocalFiniteElementCache<typename GV::ctype, double, dim, 1>;
 
diff --git a/dune/gfe/polardecomposition.hh b/dune/gfe/polardecomposition.hh
new file mode 100644
index 0000000000000000000000000000000000000000..6f3ecb862113d5e241bc267d0bdd701ec3e43406
--- /dev/null
+++ b/dune/gfe/polardecomposition.hh
@@ -0,0 +1,326 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_GFE_POLARDECOMPOSITION_HH
+#define DUNE_GFE_POLARDECOMPOSITION_HH
+
+#include <dune/common/fmatrix.hh>
+#include <dune/common/version.hh>
+#include <dune/common/exceptions.hh>
+#include <dune/gfe/rotation.hh>
+#include <dune/gfe/linearalgebra.hh>
+
+///////////////////////////////////////////////////////////////////////////////////////////
+//  Two Methods to compute the Polar Factor of a 3x3 matrix
+///////////////////////////////////////////////////////////////////////////////////////////
+
+namespace Dune::GFE {
+
+    class PolarDecomposition
+    {
+    public:
+
+        /** \brief Compute the polar factor  of a matrix iteratively
+                             Attention: For matrices that are quite far away from an orthogonal matrix,
+                             this might return a matrix with determinant = -1 ! */
+        template <class field_type>
+        FieldMatrix<field_type,3,3> operator() (const FieldMatrix<field_type,3,3>& matrix, double tol = 0.001) const
+        {
+            int maxIterations = 100;
+            // Use Higham's method
+            auto polar = matrix;
+            for (size_t i=0; i<maxIterations; i++)
+            {
+                auto oldPolar = polar;
+                auto polarInvert = polar;
+                polarInvert.invert();
+                for (size_t j=0; j<polar.N(); j++)
+                    for (size_t k=0; k<polar.M(); k++)
+                        polar[j][k] = 0.5 * (polar[j][k] + polarInvert[k][j]);
+                oldPolar -= polar;
+                if (oldPolar.frobenius_norm() < tol) {
+                    break;
+                }
+            }
+            return polar;
+        }
+    };
+
+    class HighamNoferiniPolarDecomposition
+    {
+    public:
+        /** \brief Compute the polar factor part of a matrix using the paper 
+                             "An algorithm to compute the polar decomposition of a 3 × 3 matrix" from Higham and Noferini (2015)  
+         *  \param matrix Compute the polar factor part of this matrix
+         *  \param tau1 tolerance, default value taken from Higham and Noferini
+         *  \param tau2 tolerance, default value taken from Higham and Noferini
+        */
+        template <class field_type>
+        FieldMatrix<field_type, 3, 3> operator() (const FieldMatrix<field_type, 3, 3>& matrix, double tau1 = 0.0001, double tau2 = 0.0001) const
+        {
+            auto normedMatrix = matrix;
+            normedMatrix /= normedMatrix.frobenius_norm();
+            FieldMatrix<field_type,4,4> bilinearmatrix = bilinearMatrix(normedMatrix);
+            auto detB = determinantLaplace(bilinearmatrix);
+            auto detM = normedMatrix.determinant();
+            field_type domEV = 0;
+            if (detM < 0) {
+                detM = -detM;
+                bilinearmatrix = -bilinearmatrix;
+            }
+
+            if ( detB + 1./3 > tau1) { // estimate dominant eigenvalue if well separated => use formula
+                domEV = dominantEV( detB, detM );
+            } else { // eignevalue nearly a double root => use newtons method
+                auto  coefficients = characteristicCoefficients(bilinearmatrix);
+                domEV = dominantEVNewton(coefficients,detB);
+            }
+            // compute iterationmatrix B_S
+            FieldMatrix<field_type,4,4> BS  = {{domEV,0,0,0},{0,domEV,0,0},{0,0,domEV,0},{0,0,0,domEV}};
+            BS -= bilinearmatrix;
+            if (detB < 1 - tau2) {
+                Rotation<field_type,3> v(obtainQuaternion(BS));
+                FieldMatrix<field_type,3,3> mat;
+                v.matrix(mat);
+                return mat;
+            } else {
+                DUNE_THROW(NotImplemented, "The eigenvalues are not wellseparated => inverse iteration won't converge!");
+            }
+        }
+
+    protected:
+
+        /** \brief Compute the bilinear matrix for a given 3x3 matrix*/
+        template <class field_type>
+        static FieldMatrix<field_type,4,4> bilinearMatrix(const FieldMatrix<field_type,3,3> matrix)
+        {
+            FieldMatrix<field_type,4,4> bilinearmatrix;
+            bilinearmatrix[0][0] = matrix[0][0] + matrix[1][1] + matrix[2][2];
+            bilinearmatrix[0][1] = matrix[1][2] - matrix[2][1];
+            bilinearmatrix[0][2] = matrix[2][0] - matrix[0][2];
+            bilinearmatrix[0][3] = matrix[0][1] - matrix[1][0];
+            bilinearmatrix[1][0] = bilinearmatrix[0][1];
+            bilinearmatrix[1][1] = matrix[0][0] - matrix[1][1] - matrix[2][2];
+            bilinearmatrix[1][2] = matrix[0][1] + matrix[1][0];
+            bilinearmatrix[1][3] = matrix[2][0] + matrix[0][2];
+            bilinearmatrix[2][0] = bilinearmatrix[0][2];
+            bilinearmatrix[2][1] = bilinearmatrix[1][2];
+            bilinearmatrix[2][2] = matrix[1][1] - matrix[0][0] - matrix[2][2];
+            bilinearmatrix[2][3] = matrix[1][2] + matrix[2][1];
+            bilinearmatrix[3][0] = bilinearmatrix[0][3];
+            bilinearmatrix[3][1] = bilinearmatrix[1][3];
+            bilinearmatrix[3][2] = bilinearmatrix[2][3];
+            bilinearmatrix[3][3] = matrix[2][2] - matrix[0][0] - matrix[1][1];
+            return bilinearmatrix;
+        }
+
+        /** \brief Compute the determinant of a 4x4 matrix using the Laplace method
+                                The implementation is faster than calling matrix.determinant()*/
+        template <class field_type>
+        static field_type determinantLaplace( const FieldMatrix<field_type,4,4>& matrix)
+        {
+            field_type T2233 = matrix[2][2] * matrix[3][3];
+            field_type T3223 = matrix[3][2] * matrix[2][3];
+            field_type T1       = T2233 - T3223;
+
+            field_type T1233 = matrix[1][2] * matrix[3][3]; 
+            field_type T3213 = matrix[3][2] * matrix[1][3];
+            field_type T2 = T1233 - T3213;
+
+            field_type T1223 = matrix[1][2] * matrix[2][3]; 
+            field_type T2213 = matrix[2][2] * matrix[1][3];
+            field_type T3       = T1223 - T2213; 
+
+            field_type T0233 = matrix[0][2] * matrix[3][3];
+            field_type T3203 = matrix[3][2] * matrix[0][3];
+            field_type T4       =  T3203 - T0233;
+
+            field_type T0223 = matrix[0][2] * matrix[2][3]; 
+            field_type T2203 = matrix[2][2] * matrix[0][3];
+            field_type T5       = T0223- T2203;   
+
+            field_type T0213 = matrix[0][2] * matrix[1][3];
+            field_type T1203 = matrix[1][2] * matrix[0][3];
+            field_type T6       = T0213-T1203;
+
+            return matrix[0][0] * (matrix[1][1] * T1 - matrix[2][1] * T3 + matrix[3][1] * T3)
+                 - matrix[1][0] * (matrix[0][1] * T1 + matrix[2][1] * T4 + matrix[3][1] * T5)
+                 + matrix[2][0] * (matrix[0][1] * T2 + matrix[1][1] * T4 + matrix[3][1] * T6)
+                 - matrix[3][0] * (matrix[0][1] * T2 - matrix[1][1] * T5 + matrix[2][1] * T6);
+        }
+
+        /** \brief Return the factors a,b,c of the characteristic polynomial x^4+a*x^3+b*x^2+c*x + detB */
+        template <class field_type>
+        static FieldVector<field_type,3> characteristicCoefficients(const FieldMatrix<field_type,4,4>& matrix)
+        {
+            field_type a = - Dune::GFE::trace(matrix);
+            field_type b =  matrix[0][0] * (matrix[1][1] + matrix[2][2]  + matrix[3][3])  
+                         +  matrix[3][3] * (matrix[1][1] + matrix[2][2]) 
+                         - (matrix[1][0] *  matrix[0][1] + matrix[2][0]  * matrix[0][2] + 
+                            matrix[3][0] * matrix[0][3] + matrix[1][2] * matrix[2][1] + 
+                            matrix[1][3] * matrix[3][1] + matrix[3][2] * matrix[2][3]);
+
+            field_type c =  matrix[0][0] * (matrix[1][2] *  matrix[2][1] + matrix[1][3] *  matrix[3][1] + matrix[2][3] * matrix[3][2] -(matrix[2][2] * matrix[3][3] + matrix[1][1] * (matrix[2][2] + matrix[3][3])))
+                         +  matrix[0][1] * (matrix[1][0] * (matrix[2][2] + matrix[3][3]) -(matrix[1][2] * matrix[2][0] + matrix[1][3] * matrix[3][0]))
+                         +  matrix[0][2] * (matrix[2][0] * (matrix[1][1] + matrix[3][3]) -(matrix[1][0] * matrix[2][1] + matrix[2][3] * matrix[3][0]))
+                         +  matrix[0][3] * (matrix[3][0] * (matrix[1][1] + matrix[2][2]) -(matrix[1][0] * matrix[3][1] + matrix[2][0] * matrix[3][2]))
+                         +  matrix[1][1] * (matrix[2][3] *  matrix[3][2] - matrix[2][2] *  matrix[3][3])
+                         +  matrix[1][2] * (matrix[2][1] *  matrix[3][3] - matrix[2][3] *  matrix[3][1])
+                         +  matrix[1][3] * (matrix[2][2] *  matrix[3][1] - matrix[2][1] *  matrix[3][2]); 
+            return {a, b, c};   
+        }
+
+        /** \brief Return the dominant Eigenvalue of the matrix B */
+        template <class field_type>
+        static field_type dominantEV(field_type detB, field_type detM )
+        {
+            auto c = 8 * detM;
+            auto sigma0 = 1 + 3 * detB;
+            auto sigma1 = 27/16*c*c + 9 * detB - 1;
+            auto alpha  = sigma1/std::pow(sigma0, 1.5 );
+            auto z = 4/3 * (1 + std::sqrt(sigma0) * std::cos(std::acos(alpha)/3));
+            auto s = std::sqrt(z)/ 2;
+            auto x = 4-z+c/s;
+            if (x > 0)
+                return s + std::sqrt(x)/2;
+            else
+                return s;
+        }
+
+        /** \brief Return the dominant Eigenvalue of the matrix B.
+                             This algorithm corresponds to Algorithm 3.4 in 
+                             "An algorithm to compute the polar decomposition
+                                of a 3 × 3 matrix" from Higham and Noferini (2015)
+         *  \param coefficients Coefficients of the characteristic polynomial for the matrix b
+         *  \param detB Determinant of the matrix B
+         *  \param tol Tolerance for the Newton method, the value is taken from the paper by Higham and Noferini
+         */
+        template <class field_type>
+        static field_type dominantEVNewton(const FieldVector<field_type,3>& coefficients, field_type detB, double tol = 10e-5)
+        { 
+            field_type charPol = 0;
+            field_type charPolDeriv = 0;
+            field_type lambdaOld = 3;
+            field_type domEV = std::sqrt(3);
+            while ((lambdaOld - domEV)/domEV > tol) {
+                lambdaOld = domEV;
+                charPol   = detB + domEV*( coefficients[2] + domEV*( coefficients[1] + domEV*( coefficients[0]+  domEV ) ) );
+                charPolDeriv= coefficients[2] + domEV * ( 2*coefficients[1]+ domEV * ( 3*coefficients[0] + 4*domEV) );
+                domEV = domEV- charPol / charPolDeriv;
+            }
+            return domEV;
+        }
+
+        /** \brief Return quaternion vector resulting from step 7 and 8 in Algorithm 3.2 from Higham and Noferini (2015)
+                            Step 7: Calculate the LDLT factorization of the given matrix with diagonal pivoting
+                            Step 8: Using L and the pivotmatix, calculate the vector v
+            * \param shiftedB  shifted matrix B as given in chapter 3 of Higham an Noferini: shiftedB = lambda * Id - B, where lambda is the dominant eigenvalue of B
+                \returns v       the respective polar factor in quaternion form 
+            *\
+        */
+        template <class field_type>
+        static FieldVector<field_type,4> obtainQuaternion(const FieldMatrix<field_type,4,4> shiftedB)
+        {
+            FieldMatrix<field_type,4,4> P = 0;
+            FieldMatrix<field_type,4,4> Pleft = 0;
+            FieldMatrix<field_type,4,4> Pright = 0;
+            FieldMatrix<field_type,4,4> L = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}; 
+            FieldVector<field_type,4>   D = {0,0,0,0};
+            FieldVector<field_type,4> Bdiag = {shiftedB[0][0], shiftedB[1][1], shiftedB[2][2], shiftedB[3][3]};
+            int maxi = 0; // Index of the maximal element
+            int secmax = 0;
+            int secmin = 0;
+            int mini = 0; // Index of the minimal element
+
+            // Find Pivotmatrix
+            for (int i = 0; i < 4; ++i) // going through the diagonal searching for the maximum
+                if ( Bdiag[maxi] < Bdiag[i] )  // found a bigger one but smaler than the older ones 
+                    maxi = i;
+
+            Pleft[0][maxi]  = 1;
+            Pright[maxi][0] = 1;        // Largest element to the first position
+
+            for (int i = 0; i < 4; ++i) // going through the diagonal searching for the minimum
+                if ( Bdiag[mini] > Bdiag[i] )  // found a smaler one but smaler than the older ones 
+                    mini = i;
+
+            Pleft[3][mini]  = 1;
+            Pright[mini][3] = 1;      // Smalest element to the last position
+
+
+            for (int i = 0; i < 4; ++i) {
+                if ( i != maxi & i != mini ) {
+                    for (int j = 0; j < 4; ++j) {
+                        if ( j != maxi & j != mini & j != i  ) {
+                            if ( Bdiag[i] < Bdiag[j] ) {
+                                Pleft[1][j]  = 1;   // Second largest element at the second position
+                                Pright[j][1] = 1;
+                                Pleft[2][i]  = 1;   // Third largest element at the third position
+                                Pright[i][2] = 1;
+                                secmin = i;
+                                secmax = j;
+                            } else {
+                                Pleft[2][j]  = 1;
+                                Pright[j][2] = 1;
+                                Pleft[1][i]  = 1;
+                                Pright[i][1] = 1;
+                                secmin = j;
+                                secmax = i;
+                            }  
+                        }
+                    }
+                }
+            }
+
+            //P = Pleft*shiftedB*Pright; 
+            P[maxi][maxi] = shiftedB[0][0];
+            P[maxi][secmax] = shiftedB[0][1];
+            P[maxi][secmin] = shiftedB[0][2];
+            P[maxi][mini] = shiftedB[0][3];
+
+            P[secmax][maxi] = shiftedB[1][0];
+            P[secmax][secmax] = shiftedB[1][1];
+            P[secmax][secmin] = shiftedB[1][2];
+            P[secmax][mini] = shiftedB[1][3];
+
+            P[secmin][maxi] = shiftedB[2][0];
+            P[secmin][secmax] = shiftedB[2][1];
+            P[secmin][secmin] = shiftedB[2][2];
+            P[secmin][mini] = shiftedB[2][3];
+
+            P[mini][maxi] = shiftedB[3][0];
+            P[mini][secmax] = shiftedB[3][1];
+            P[mini][secmin] = shiftedB[3][2];
+            P[mini][mini] = shiftedB[3][3];
+
+            // Choleskydecomposition
+
+            for (int k = 0; k < 4; ++k) { //columns
+                D[k] = P[k][k];
+                for (int j = 0; j < k; ++j)//sum
+                    D[k] -= L[k][j]*L[k][j] * D[j];
+
+                for (int i = k+1; i < 4; ++i) { //rows 
+                    L[i][k] = P[i][k];
+                    for (int j = 0; j < k; ++j)//sum
+                        L[i][k] -= L[i][j]*L[k][j] * D[j];
+                    L[i][k] /= D[k];
+                }
+            }
+
+            FieldVector<field_type,4> v = {0,0,0,0};
+            FieldVector<field_type,4> unnormed = {0,0,0,1};
+            auto neg = -L[3][2];
+            unnormed[0] = L[1][0] * ( L[3][1] + L[2][1]*neg ) + L[2][0] * L[3][2] - L[3][0];
+            unnormed[1] = L[2][1] * L[3][2] - L[3][1];
+            unnormed[2] = neg;
+            unnormed  /= unnormed.two_norm();
+            v[0] = unnormed[maxi];
+            v[1] = unnormed[secmax];
+            v[2] = unnormed[secmin];
+            v[3] = unnormed[mini];
+            return v;
+        }
+    };
+}
+
+#endif
\ No newline at end of file
diff --git a/dune/gfe/rotation.hh b/dune/gfe/rotation.hh
index 3ad4023be07c66fc0941471f44128c46d7a54799..6a1cc01a69ab3be0d888c0981fbdf0c28ac2d0c3 100644
--- a/dune/gfe/rotation.hh
+++ b/dune/gfe/rotation.hh
@@ -10,6 +10,7 @@
 #include <dune/common/fvector.hh>
 #include <dune/common/fmatrix.hh>
 #include <dune/common/exceptions.hh>
+#include <dune/common/math.hh>
 
 #include "quaternion.hh"
 #include <dune/gfe/tensor3.hh>
diff --git a/dune/gfe/surfacecosseratenergy.hh b/dune/gfe/surfacecosseratenergy.hh
index a9d55824589c0cf932c25d066863706195ef82d1..393d8d897c1f12614d839525ce47b065a23749e2 100644
--- a/dune/gfe/surfacecosseratenergy.hh
+++ b/dune/gfe/surfacecosseratenergy.hh
@@ -331,15 +331,15 @@ RT energy(const typename Basis::LocalView& localView,
       //////////////////////////////////////////////////////////
 
       // Add the membrane energy density
-      auto energyDensity = (thickness - K*Dune::Power<3>::eval(thickness) / 12.0) * W_m(Ee, mu, lambda);
-      energyDensity += (Dune::Power<3>::eval(thickness) / 12.0 - K * Dune::Power<5>::eval(thickness) / 80.0)*W_m(Ee*b + c*Ke, mu, lambda);
-      energyDensity += Dune::Power<3>::eval(thickness) / 6.0 * W_mixt(Ee, c*Ke*b - 2*H*c*Ke, mu, lambda);
-      energyDensity += Dune::Power<5>::eval(thickness) / 80.0 * W_mp( (Ee*b + c*Ke)*b, mu, lambda);
+      auto energyDensity = (thickness - K*Dune::power(thickness,3) / 12.0) * W_m(Ee, mu, lambda);
+      energyDensity += (Dune::power(thickness,3) / 12.0 - K * Dune::power(thickness,5) / 80.0)*W_m(Ee*b + c*Ke, mu, lambda);
+      energyDensity += Dune::power(thickness,3) / 6.0 * W_mixt(Ee, c*Ke*b - 2*H*c*Ke, mu, lambda);
+      energyDensity += Dune::power(thickness,5) / 80.0 * W_mp( (Ee*b + c*Ke)*b, mu, lambda);
 
       // Add the bending energy density
-      energyDensity += (thickness - K*Dune::Power<3>::eval(thickness) / 12.0) * W_curv(Ke, mu)
-                     + (Dune::Power<3>::eval(thickness) / 12.0 - K * Dune::Power<5>::eval(thickness) / 80.0)*W_curv(Ke*b, mu)
-                     + Dune::Power<5>::eval(thickness) / 80.0 * W_curv(Ke*b*b, mu);
+      energyDensity += (thickness - K*Dune::power(thickness,3) / 12.0) * W_curv(Ke, mu)
+                     + (Dune::power(thickness,3) / 12.0 - K * Dune::power(thickness,5) / 80.0)*W_curv(Ke*b, mu)
+                     + Dune::power(thickness,5) / 80.0 * W_curv(Ke*b*b, mu);
 
       // Add energy density
       energy += quad[pt].weight() * integrationElement * energyDensity;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 2f725374e6975ed9aeae9ce6fe65d28a4107faad..b292a33af2b6da6b5cdb459a61db0020f7a67a3a 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -8,6 +8,7 @@ set(TESTS
   localgfetestfunctiontest
   localprojectedfefunctiontest
   orthogonalmatrixtest
+  polardecompositiontest
   rigidbodymotiontest
   rotationtest
   svdtest
diff --git a/test/polardecompositiontest.cc b/test/polardecompositiontest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cc10676d24424d59fc4316dace27efa2a9fb9720
--- /dev/null
+++ b/test/polardecompositiontest.cc
@@ -0,0 +1,243 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include <dune/common/fmatrix.hh>
+#include <dune/common/fvector.hh>
+#include <dune/gfe/polardecomposition.hh>
+#include <dune/gfe/rotation.hh>
+
+#include <chrono>
+#include <fstream>
+#include <random> 
+
+
+using namespace Dune;
+using field_type = double;
+
+
+class PolarDecompositionTest : public Dune::GFE::HighamNoferiniPolarDecomposition {
+    public:
+        using HighamNoferiniPolarDecomposition::HighamNoferiniPolarDecomposition;
+        using HighamNoferiniPolarDecomposition::bilinearMatrix;
+        using HighamNoferiniPolarDecomposition::determinantLaplace;
+        using HighamNoferiniPolarDecomposition::dominantEVNewton;
+        using HighamNoferiniPolarDecomposition::characteristicCoefficients;
+        using HighamNoferiniPolarDecomposition::obtainQuaternion;
+};
+
+/** \brief Check if the matrix is not orthogonal */
+static bool isNotOrthogonal(const FieldMatrix<field_type,3,3>& matrix) {
+    bool notOrthogonal = std::abs(1-matrix.determinant()) > 1e-12;
+    notOrthogonal = notOrthogonal or (( matrix[0]*matrix[1] ) > 1e-12);
+    notOrthogonal = notOrthogonal or (( matrix[0]*matrix[2] ) > 1e-12);
+    notOrthogonal = notOrthogonal or (( matrix[1]*matrix[2] ) > 1e-12);
+    return notOrthogonal;
+}
+
+/** \brief Return the time needed for 1000 polar decompositions of the given matrix using the iterative algorithm
+        and the algorithm by Higham. */
+static FieldVector<field_type,2> measureTimeForPolarDecomposition(const FieldMatrix<field_type, 3, 3>& matrix, double tol = 10e-3)
+{
+    FieldMatrix<field_type, 3, 3> Q1;
+    FieldMatrix<field_type, 3, 3> Q2;
+    FieldVector<field_type,2> actualtime;
+    std::chrono::steady_clock::time_point begindecomold = std::chrono::steady_clock::now();
+    for (int i = 0; i < 1000; ++i) {
+        Q1 = Dune::GFE::PolarDecomposition()(matrix, tol);
+    }
+    std::chrono::steady_clock::time_point enddecomold = std::chrono::steady_clock::now();
+    actualtime[0] = (enddecomold - begindecomold).count();
+
+    std::chrono::steady_clock::time_point begindecom = std::chrono::steady_clock::now();
+    for (int i = 0; i < 1000; ++i) {
+        Q2 = Dune::GFE::HighamNoferiniPolarDecomposition()(matrix, tol, tol);
+    }
+    std::chrono::steady_clock::time_point enddecom = std::chrono::steady_clock::now();
+    actualtime[1] = (enddecom - begindecom).count();
+    return actualtime;
+}
+
+/** \brief Returns a 3x3-Matrix with random entries between 0 and upper Bound*/
+static FieldMatrix<field_type, 3, 3> randomMatrix3d(double upperBound = 1.0)
+{
+    const int dim = 3;
+    FieldMatrix<field_type, dim, dim> matrix;
+    std::random_device rd;  // Will be used to obtain a seed for the random number engine
+    std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
+    std::uniform_real_distribution<> dis(0.0, upperBound); // equally distributed between 0 and upper bound
+    for (int i = 0; i < dim; ++i)
+        for (int j = 0; j < dim; ++j)
+            matrix[i][j] = dis(gen);
+    
+    return matrix;
+}
+
+/** \brief Returns an "almost orthogonal" 3x3-Matrix where a random perturbation
+                     between 0 and maxPerturbation is added to each entry.*/
+static FieldMatrix<field_type, 3, 3> randomMatrixAlmostOrthogonal(double maxPerturbation = 0.1)
+{
+    const int dim = 3;
+    FieldVector<field_type,4> f;
+    std::random_device rd;  // Will be used to obtain a seed for the random number engine
+    std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
+    std::uniform_real_distribution<> dis(0.0, 1.0); // equally distributed between 0 and upper bound
+    for (int i = 0; i < 4; ++i)
+        f[i] = dis(gen);
+    Rotation<field_type,3> q(f);
+    q.normalize();
+
+    assert(std::abs(1-q.two_norm()) < 1e-12);
+
+    // Turn it into a matrix
+    FieldMatrix<double,3,3> matrix;
+    q.matrix(matrix);
+
+    if (isNotOrthogonal(matrix))
+        DUNE_THROW(Exception, "Expected the matrix " << matrix << " to be orthogonal, but it is not!");
+
+    //Now perturb this a little bit
+    for (int i = 0; i < dim; ++i)
+        for (int j = 0; j < dim; ++j)
+            matrix[i][j] += dis(gen)*maxPerturbation;
+    return matrix;
+}
+
+static double timeTest(double perturbationFromSO3 = 1.0) {
+    // Define matrices we want to use for testing
+    int numberOfTests = 100;
+    std::vector<double> timeOld(numberOfTests);
+    std::vector<double> timeNew(numberOfTests);
+    double totalTimeOld = 0;
+    double totalTimeNew = 0;
+
+    for (int j = 0; j < numberOfTests; ++j) { // testing loop
+        FieldMatrix<field_type,3,3> N;
+        // Only measure the time if the decomposition is unique and if both algorithms will retun an orthogonal matrix!
+        // Attention: For matrices that are quite far away from an orthogonal matrix, Dune::GFE::PolarDecomposition() might return a matrix with determinant = -1 !
+        double normOfDifference = 10;
+        FieldMatrix<field_type,3,3> Q1;
+        FieldMatrix<field_type,3,3> Q2;
+        while(isNotOrthogonal(Q1) or isNotOrthogonal(Q2) or normOfDifference > 0.001) {
+            N = randomMatrixAlmostOrthogonal(perturbationFromSO3);
+            Q1 = PolarDecompositionTest()(N);
+            Q2 = Dune::GFE::PolarDecomposition()(N);
+            normOfDifference = (Q1-Q2).frobenius_norm();
+        }
+        auto actualtime = measureTimeForPolarDecomposition(N);
+        timeOld[j] = actualtime[0];
+        timeNew[j] = actualtime[1];
+    }
+
+    std::sort(timeOld.begin(), timeOld.end());
+    std::sort(timeNew.begin(), timeNew.end());
+
+    for (int j = 0; j < numberOfTests; ++j) {
+         totalTimeOld += timeOld[j]; 
+         totalTimeNew += timeNew[j]; 
+    }
+    std::cout << "Perturbation from an orthogonal matrix: " << perturbationFromSO3 << std::endl;
+    std::cout << "Average (old): " << totalTimeOld/numberOfTests << "[ns]" << std::endl;
+    std::cout << "Average (new): " << totalTimeNew/numberOfTests << "[ns]" << std::endl;
+    std::cout << "Relative: " << totalTimeOld/totalTimeNew << std::endl << std::endl;
+
+    return totalTimeOld/totalTimeNew;
+}
+
+static bool testBilinearMatrix() {
+    FieldMatrix<field_type,3,3> M = { { 20,    0,  -3 },
+                                                                        {  3,  2.0, 310 },
+                                                                        {  5, 0.22,   0 } };
+    M /= M.frobenius_norm();
+    FieldMatrix<field_type,4,4> B = { { 0.0096632,  0.997822,   0.0257685,  0.00644213 },
+                                                                        { 0.997822,  -0.00322107, 0.0708635,  0.00644213 },
+                                                                        { 0.0257685,  0.0708635,  0.00322107, 0.999239   },
+                                                                        { 0.00644213, 0.00644213, 0.999239,  -0.0096632  } };
+    auto Btest = PolarDecompositionTest::bilinearMatrix(M);
+    Btest -= B;
+    return Btest.frobenius_norm() < 0.001;
+}
+
+static bool test4dDeterminant() {
+    FieldMatrix<field_type,4,4> B = { { 0.0096632,  0.997822,   0.0257685,  0.00644213 },
+                                                                        { 0.997822,  -0.00322107, 0.0708635,  0.00644213 },
+                                                                        { 0.0257685,  0.0708635,  0.00322107, 0.999239   },
+                                                                        { 0.00644213, 0.00644213, 0.999239,  -0.0096632  } };
+    double detBtest = PolarDecompositionTest::determinantLaplace(B);
+    detBtest -= B.determinant();
+    return std::abs(detBtest) < 0.001;
+}
+
+static bool testdominantEVNewton() {
+    field_type detB = 0.992928;
+    field_type detM = 0.000620104;
+    FieldVector<field_type,3>  minpol = {0, -1.99999, -0.00496083};
+    double correctDominantEV = 1.05397;
+
+    auto dominantEVNewton = PolarDecompositionTest::dominantEVNewton(minpol, detB);
+    return std::abs(correctDominantEV - dominantEVNewton) < 0.001;
+}
+
+static bool testCharacteristicPolynomial4D() {
+    FieldMatrix<field_type,4,4> B = { { 0.0096632,  0.997822,   0.0257685,  0.00644213 },
+                                                                        { 0.997822,  -0.00322107, 0.0708635,  0.00644213 },
+                                                                        { 0.0257685,  0.0708635,  0.00322107, 0.999239   },
+                                                                        { 0.00644213, 0.00644213, 0.999239,  -0.0096632  } };
+    FieldVector<field_type,3>  minpol = {0, -1.99999, -0.00496083};
+
+    auto coefficients = PolarDecompositionTest::characteristicCoefficients(B);
+    coefficients -= minpol;
+    return coefficients.two_norm() < 0.001;
+}
+
+static bool testQuaternionFunction() {
+    FieldMatrix<field_type,4,4> BS = { {  1.04431,    -0.997822,   -0.0257685, -0.00644213 },
+                                                                         { -0.997822,    1.05719,    -0.0708635, -0.00644213 },
+                                                                         { -0.0257685,  -0.0708635,   1.05075,   -0.999239   },
+                                                                         { -0.00644213, -0.00644213, -0.999239,   1.06363    } };
+
+    FieldVector<field_type, 4 > v = { 0.508566, 0.516353, 0.499062, 0.475055 };
+    auto vtest = PolarDecompositionTest::obtainQuaternion(BS);
+    vtest -= v;
+    return vtest.two_norm() < 0.001;
+}
+
+int main (int argc, char *argv[]) try
+{
+    //test the correctness of the algorithm
+    auto testMatrix = randomMatrix3d();
+    auto Q = PolarDecompositionTest()(testMatrix,1e-12,1e-12);
+    if (isNotOrthogonal(Q)) {
+        std::cerr << "The polar decomposition did not return an orthogonal matrix when decomposing: " << std::endl << testMatrix << std::endl;
+        return 1;
+    }
+
+    if (testBilinearMatrix()) {
+        std::cerr << "The test calculation of the bilinearMatrix is wrong!" << std::endl;
+        return 1;
+    }
+    if (!test4dDeterminant()) {
+        std::cerr << "The test calculation of the 4d determinant is wrong!" << std::endl;
+        return 1;
+    }
+    if (!testdominantEVNewton()) {
+        std::cerr << "The test calculation of the dominant eigenvalue is wrong!" << std::endl;
+        return 1;
+    }
+    if (!testCharacteristicPolynomial4D()) {
+        std::cerr << "The test calculation of the characteristic polynomial is wrong!" << std::endl;
+        return 1;
+    }
+    if (!testQuaternionFunction()) {
+        std::cerr << "The test calculation of the quaternion function is wrong!" << std::endl;
+        return 1;
+    }
+
+    timeTest(.1);
+    timeTest(2);
+    timeTest(30);
+
+    return 0;
+ 
+} catch (Exception& e) {
+    std::cout << e.what() << std::endl;
+}
+