From 1cf85829c92877416f56a732aaf4d2575a2d8905 Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Tue, 3 Sep 2013 16:29:36 +0000
Subject: [PATCH] Use type parameters instead of 'double' much more often

The only exception is the material parameters.  ADOL-C (for which
we are doing this), doesn't need to have them in a special type.

[[Imported from SVN: r9401]]
---
 dune/gfe/cosseratenergystiffness.hh | 293 ++++++++++++++--------------
 1 file changed, 147 insertions(+), 146 deletions(-)

diff --git a/dune/gfe/cosseratenergystiffness.hh b/dune/gfe/cosseratenergystiffness.hh
index 5505e0a3..9aea2674 100644
--- a/dune/gfe/cosseratenergystiffness.hh
+++ b/dune/gfe/cosseratenergystiffness.hh
@@ -19,13 +19,13 @@
 //#define QUADRATIC_MEMBRANE_ENERGY
 
 
-template<class GridView, class LocalFiniteElement, int dim>
+template<class GridView, class LocalFiniteElement, int dim, class field_type=double>
 class CosseratEnergyLocalStiffness
-    : public LocalGeodesicFEStiffness<GridView,LocalFiniteElement,RigidBodyMotion<double,dim> >
+    : public LocalGeodesicFEStiffness<GridView,LocalFiniteElement,RigidBodyMotion<field_type,dim> >
 {
     // grid types
     typedef typename GridView::Grid::ctype DT;
-    typedef RigidBodyMotion<double,dim> TargetSpace;
+    typedef RigidBodyMotion<field_type,dim> TargetSpace;
     typedef typename TargetSpace::ctype RT;
     typedef typename GridView::template Codim<0>::Entity Entity;
 
@@ -34,9 +34,9 @@ class CosseratEnergyLocalStiffness
 
 
     /** \brief Compute the symmetric part of a matrix A, i.e. \f$ \frac 12 (A + A^T) \f$ */
-    static Dune::FieldMatrix<double,dim,dim> sym(const Dune::FieldMatrix<double,dim,dim>& A)
+    static Dune::FieldMatrix<field_type,dim,dim> sym(const Dune::FieldMatrix<field_type,dim,dim>& A)
     {
-        Dune::FieldMatrix<double,dim,dim> result;
+        Dune::FieldMatrix<field_type,dim,dim> result;
         for (int i=0; i<dim; i++)
             for (int j=0; j<dim; j++)
                 result[i][j] = 0.5 * (A[i][j] + A[j][i]);
@@ -44,9 +44,9 @@ class CosseratEnergyLocalStiffness
     }
 
     /** \brief Compute the antisymmetric part of a matrix A, i.e. \f$ \frac 12 (A - A^T) \f$ */
-    static Dune::FieldMatrix<double,dim,dim> skew(const Dune::FieldMatrix<double,dim,dim>& A)
+    static Dune::FieldMatrix<field_type,dim,dim> skew(const Dune::FieldMatrix<field_type,dim,dim>& A)
     {
-        Dune::FieldMatrix<double,dim,dim> result;
+        Dune::FieldMatrix<field_type,dim,dim> result;
         for (int i=0; i<dim; i++)
             for (int j=0; j<dim; j++)
                 result[i][j] = 0.5 * (A[i][j] - A[j][i]);
@@ -55,9 +55,9 @@ class CosseratEnergyLocalStiffness
 
     /** \brief Return the square of the trace of a matrix */
     template <int N>
-    static double traceSquared(const Dune::FieldMatrix<double,N,N>& A)
+    static field_type traceSquared(const Dune::FieldMatrix<field_type,N,N>& A)
     {
-        double trace = 0;
+        field_type trace = 0;
         for (int i=0; i<N; i++)
             trace += A[i][i];
         return trace*trace;
@@ -66,9 +66,9 @@ class CosseratEnergyLocalStiffness
     /** \brief Compute the (row-wise) curl of a matrix R \f$
         \param DR The partial derivatives of the matrix R
      */
-    static Dune::FieldMatrix<double,dim,dim> curl(const Tensor3<double,dim,dim,dim>& DR)
+    static Dune::FieldMatrix<field_type,dim,dim> curl(const Tensor3<field_type,dim,dim,dim>& DR)
     {
-        Dune::FieldMatrix<double,dim,dim> result;
+        Dune::FieldMatrix<field_type,dim,dim> result;
 
         for (int i=0; i<dim; i++) {
             result[i][0] = DR[i][2][1] - DR[i][1][2];
@@ -83,9 +83,9 @@ class CosseratEnergyLocalStiffness
      *
      * Optimized for U, as we know a bit about its structure
      */
-    static Dune::FieldMatrix<double,dim,dim> adjugateU(const Dune::FieldMatrix<double,dim,dim>& U)
+    static Dune::FieldMatrix<field_type,dim,dim> adjugateU(const Dune::FieldMatrix<field_type,dim,dim>& U)
     {
-        Dune::FieldMatrix<double,dim,dim> result;
+        Dune::FieldMatrix<field_type,dim,dim> result;
 
         result[0][0] =  U[1][1];
         result[0][1] = -U[0][1];
@@ -109,9 +109,9 @@ public:  // for testing
         \param derivative First derivative of the gfe function wrt x at that point, in quaternion coordinates
         \param DR First derivative of the gfe function wrt x at that point, in matrix coordinates
      */
-    static void computeDR(const RigidBodyMotion<double,3>& value,
-                          const Dune::FieldMatrix<double,7,gridDim>& derivative,
-                          Tensor3<double,3,3,3>& DR)
+    static void computeDR(const RigidBodyMotion<field_type,3>& value,
+                          const Dune::FieldMatrix<field_type,7,gridDim>& derivative,
+                          Tensor3<field_type,3,3,3>& DR)
     {
         // The LocalGFEFunction class gives us the derivatives of the orientation variable,
         // but as a map into quaternion space.  To obtain matrix coordinates we use the
@@ -122,10 +122,10 @@ public:  // for testing
         // corresponding orthogonal matrix, we need to invert the i and j indices
         //
         // So, if I am not mistaken, DR[i][j][k] contains \partial R_ij / \partial k
-        Tensor3<double,3 , 3, 4> dd_dq;
+        Tensor3<field_type,3 , 3, 4> dd_dq;
         value.q.getFirstDerivativesOfDirectors(dd_dq);
 
-        DR = 0;
+        DR = field_type(0);
         for (int i=0; i<3; i++)
             for (int j=0; j<3; j++)
                 for (int k=0; k<gridDim; k++)
@@ -138,9 +138,9 @@ public:  // for testing
         \param value Value of the gfe function at a certain point
         \param derivative First derivative of the gfe function wrt the coefficients at that point, in quaternion coordinates
      */
-    static void computeDR_dv(const RigidBodyMotion<double,3>& value,
-                          const Dune::FieldMatrix<double,7,7>& derivative,
-                          Tensor3<double,3,3,4>& dR_dv)
+    static void computeDR_dv(const RigidBodyMotion<field_type,3>& value,
+                          const Dune::FieldMatrix<field_type,7,7>& derivative,
+                          Tensor3<field_type,3,3,4>& dR_dv)
     {
         // The LocalGFEFunction class gives us the derivatives of the orientation variable,
         // but as a map into quaternion space.  To obtain matrix coordinates we use the
@@ -151,10 +151,10 @@ public:  // for testing
         // corresponding orthogonal matrix, we need to invert the i and j indices
         //
         // So, if I am not mistaken, DR[i][j][k] contains \partial R_ij / \partial k
-        Tensor3<double,3 , 3, 4> dd_dq;
+        Tensor3<field_type,3 , 3, 4> dd_dq;
         value.q.getFirstDerivativesOfDirectors(dd_dq);
 
-        dR_dv = 0;
+        dR_dv = field_type(0);
         for (int i=0; i<3; i++)
             for (int j=0; j<3; j++)
                 for (int k=0; k<4; k++)
@@ -169,12 +169,12 @@ public:  // for testing
         \param value Value of the gfe function at a certain point
         \param derivative First derivative of the gfe function wrt the coefficients at that point, in quaternion coordinates
      */
-    static void compute_dDR_dv(const RigidBodyMotion<double,3>& value,
-                               const Dune::FieldMatrix<double,7,gridDim>& derOfValueWRTx,
-                               const Dune::FieldMatrix<double,7,7>& derOfValueWRTCoefficient,
-                               const Tensor3<double,7,7,gridDim>& derOfGradientWRTCoefficient,
-                               Dune::array<Tensor3<double,3,3,4>, 3>& dDR_dv,
-                               Tensor3<double,3,gridDim,4>& dDR3_dv)
+    static void compute_dDR_dv(const RigidBodyMotion<field_type,3>& value,
+                               const Dune::FieldMatrix<field_type,7,gridDim>& derOfValueWRTx,
+                               const Dune::FieldMatrix<field_type,7,7>& derOfValueWRTCoefficient,
+                               const Tensor3<field_type,7,7,gridDim>& derOfGradientWRTCoefficient,
+                               Dune::array<Tensor3<field_type,3,3,4>, 3>& dDR_dv,
+                               Tensor3<field_type,3,gridDim,4>& dDR3_dv)
     {
         // The LocalGFEFunction class gives us the derivatives of the orientation variable,
         // but as a map into quaternion space.  To obtain matrix coordinates we use the
@@ -185,15 +185,15 @@ public:  // for testing
         // corresponding orthogonal matrix, we need to invert the i and j indices
         //
         // So, if I am not mistaken, DR[i][j][k] contains \partial R_ij / \partial k
-        Tensor3<double,3 , 3, 4> dd_dq;
+        Tensor3<field_type,3 , 3, 4> dd_dq;
         value.q.getFirstDerivativesOfDirectors(dd_dq);
 
         /** \todo This is a constant -- don't recompute it every time */
-        Dune::array<Tensor3<double,3,4,4>, 3> dd_dq_dq;
-        Rotation<double,3>::getSecondDerivativesOfDirectors(dd_dq_dq);
+        Dune::array<Tensor3<field_type,3,4,4>, 3> dd_dq_dq;
+        Rotation<field_type,3>::getSecondDerivativesOfDirectors(dd_dq_dq);
 
         for (size_t i=0; i<dDR_dv.size(); i++)
-            dDR_dv[i] = 0;
+            dDR_dv[i] = field_type(0);
 
         for (int i=0; i<3; i++)
             for (int j=0; j<3; j++)
@@ -215,23 +215,23 @@ public:  // for testing
         // by projecting onto the tangent space at S^2.  Yes, that is something different!
         ///////////////////////////////////////////////////////////////////////////////////////////
 
-        Dune::FieldMatrix<double,3,3> Mtmp;
+        Dune::FieldMatrix<field_type,3,3> Mtmp;
         value.q.matrix(Mtmp);
-        OrthogonalMatrix<double,3> M(Mtmp);
+        OrthogonalMatrix<field_type,3> M(Mtmp);
 
-        Dune::FieldVector<double,3> tmpDirector;
+        Dune::FieldVector<field_type,3> tmpDirector;
         for (int i=0; i<3; i++)
             tmpDirector[i] = M.data()[i][2];
-        UnitVector<double,3> director(tmpDirector);
+        UnitVector<field_type,3> director(tmpDirector);
 
         for (int k=0; k<gridDim; k++)
             for (int v_i=0; v_i<4; v_i++) {
 
-                Dune::FieldVector<double,3> unprojected;
+                Dune::FieldVector<field_type,3> unprojected;
                 for (int i=0; i<3; i++)
                     unprojected[i] = dDR_dv[i][2][k][v_i];
 
-                Dune::FieldVector<double,3> projected = director.projectOntoTangentSpace(unprojected);
+                Dune::FieldVector<field_type,3> projected = director.projectOntoTangentSpace(unprojected);
 
                 for (int i=0; i<3; i++)
                     dDR3_dv[i][k][v_i] = projected[i];
@@ -245,12 +245,12 @@ public:  // for testing
         for (int k=0; k<gridDim; k++)
             for (int v_i=0; v_i<4; v_i++) {
 
-                Dune::FieldMatrix<double,3,3> unprojected;
+                Dune::FieldMatrix<field_type,3,3> unprojected;
                 for (int i=0; i<3; i++)
                     for (int j=0; j<3; j++)
                         unprojected[i][j] = dDR_dv[i][j][k][v_i];
 
-                Dune::FieldMatrix<double,3,3> projected = M.projectOntoTangentSpace(unprojected);
+                Dune::FieldMatrix<field_type,3,3> projected = M.projectOntoTangentSpace(unprojected);
 
                 for (int i=0; i<3; i++)
                     for (int j=0; j<3; j++)
@@ -304,9 +304,9 @@ public:
     /** \brief The energy \f$ W_{mp}(\overline{U}) \f$, as written in
      * the first equation of (4.4) in Neff's paper
      */
-    RT quadraticMembraneEnergy(const Dune::FieldMatrix<double,3,3>& U) const
+    RT quadraticMembraneEnergy(const Dune::FieldMatrix<field_type,3,3>& U) const
     {
-        Dune::FieldMatrix<double,3,3> UMinus1 = U;
+        Dune::FieldMatrix<field_type,3,3> UMinus1 = U;
         for (int i=0; i<dim; i++)
             UMinus1[i][i] -= 1;
 
@@ -318,12 +318,12 @@ public:
     /** \brief The energy \f$ W_{mp}(\overline{U}) \f$, as written in
      * the second equation of (4.4) in Neff's paper
      */
-    RT longQuadraticMembraneEnergy(const Dune::FieldMatrix<double,3,3>& U) const
+    RT longQuadraticMembraneEnergy(const Dune::FieldMatrix<field_type,3,3>& U) const
     {
         RT result = 0;
 
         // shear-stretch energy
-        Dune::FieldMatrix<double,dim-1,dim-1> sym2x2;
+        Dune::FieldMatrix<field_type,dim-1,dim-1> sym2x2;
         for (int i=0; i<dim-1; i++)
             for (int j=0; j<dim-1; j++)
                 sym2x2[i][j] = 0.5 * (U[i][j] + U[j][i]) - (i==j);
@@ -331,7 +331,7 @@ public:
         result += mu_ * sym2x2.frobenius_norm2();
 
         // first order drill energy
-        Dune::FieldMatrix<double,dim-1,dim-1> skew2x2;
+        Dune::FieldMatrix<field_type,dim-1,dim-1> skew2x2;
         for (int i=0; i<dim-1; i++)
             for (int j=0; j<dim-1; j++)
                 skew2x2[i][j] = 0.5 * (U[i][j] - U[j][i]);
@@ -350,9 +350,9 @@ public:
 
     /** \brief Energy for large-deformation problems (private communication by Patrizio Neff)
      */
-    RT nonquadraticMembraneEnergy(const Dune::FieldMatrix<double,3,3>& U) const
+    RT nonquadraticMembraneEnergy(const Dune::FieldMatrix<field_type,3,3>& U) const
     {
-        Dune::FieldMatrix<double,3,3> UMinus1 = U;
+        Dune::FieldMatrix<field_type,3,3> UMinus1 = U;
         for (int i=0; i<dim; i++)
             UMinus1[i][i] -= 1;
 
@@ -362,7 +362,7 @@ public:
                 + (mu_*lambda_)/(2*mu_ + lambda_) * 0.5 * ((detU-1)*(detU-1) + (1.0/detU -1)*(1.0/detU -1));
     }
 
-    RT curvatureEnergy(const Tensor3<double,3,3,3>& DR) const
+    RT curvatureEnergy(const Tensor3<field_type,3,3,3>& DR) const
     {
 #ifdef DONT_USE_CURL
         return mu_ * std::pow(L_c_ * DR.frobenius_norm2(),q_/2.0);
@@ -371,10 +371,10 @@ public:
 #endif
     }
 
-    RT bendingEnergy(const Dune::FieldMatrix<double,dim,dim>& R, const Tensor3<double,3,3,3>& DR) const
+    RT bendingEnergy(const Dune::FieldMatrix<field_type,dim,dim>& R, const Tensor3<field_type,3,3,3>& DR) const
     {
         // left-multiply the derivative of the third director (in DR[][2][]) with R^T
-        Dune::FieldMatrix<double,3,3> RT_DR3;
+        Dune::FieldMatrix<field_type,3,3> RT_DR3;
         for (int i=0; i<3; i++)
             for (int j=0; j<3; j++) {
                 RT_DR3[i][j] = 0;
@@ -393,29 +393,29 @@ public:
     //  Methods to compute the energy gradient
     ///////////////////////////////////////////////////////////////////////////////////////
     void longQuadraticMembraneEnergyGradient(typename TargetSpace::EmbeddedTangentVector& localGradient,
-                                    const Dune::FieldMatrix<double,3,3>& R,
-                                    const Tensor3<double,3,3,4>& dR_dv,
-                                    const Dune::FieldMatrix<double,7,gridDim>& derivative,
-                                    const Tensor3<double,7,7,gridDim>& derOfGradientWRTCoefficient,
-                                    const Dune::FieldMatrix<double,3,3>& U) const;
+                                    const Dune::FieldMatrix<field_type,3,3>& R,
+                                    const Tensor3<field_type,3,3,4>& dR_dv,
+                                    const Dune::FieldMatrix<field_type,7,gridDim>& derivative,
+                                    const Tensor3<field_type,7,7,gridDim>& derOfGradientWRTCoefficient,
+                                    const Dune::FieldMatrix<field_type,3,3>& U) const;
 
     void nonquadraticMembraneEnergyGradient(typename TargetSpace::EmbeddedTangentVector& localGradient,
-                                    const Dune::FieldMatrix<double,3,3>& R,
-                                    const Tensor3<double,3,3,4>& dR_dv,
-                                    const Dune::FieldMatrix<double,7,gridDim>& derivative,
-                                    const Tensor3<double,7,7,gridDim>& derOfGradientWRTCoefficient,
-                                    const Dune::FieldMatrix<double,3,3>& U) const;
+                                    const Dune::FieldMatrix<field_type,3,3>& R,
+                                    const Tensor3<field_type,3,3,4>& dR_dv,
+                                    const Dune::FieldMatrix<field_type,7,gridDim>& derivative,
+                                    const Tensor3<field_type,7,7,gridDim>& derOfGradientWRTCoefficient,
+                                    const Dune::FieldMatrix<field_type,3,3>& U) const;
 
     void curvatureEnergyGradient(typename TargetSpace::EmbeddedTangentVector& embeddedLocalGradient,
-                                 const Dune::FieldMatrix<double,3,3>& R,
-                                 const Tensor3<double,3,3,3>& DR,
-                                 const Dune::array<Tensor3<double,3,3,4>, 3>& dDR_dv) const;
+                                 const Dune::FieldMatrix<field_type,3,3>& R,
+                                 const Tensor3<field_type,3,3,3>& DR,
+                                 const Dune::array<Tensor3<field_type,3,3,4>, 3>& dDR_dv) const;
 
     void bendingEnergyGradient(typename TargetSpace::EmbeddedTangentVector& embeddedLocalGradient,
-                               const Dune::FieldMatrix<double,3,3>& R,
-                               const Tensor3<double,3,3,4>& dR_dv,
-                               const Tensor3<double,3,3,3>& DR,
-                               const Tensor3<double,3,gridDim,4>& dDR3_dv) const;
+                               const Dune::FieldMatrix<field_type,3,3>& R,
+                               const Tensor3<field_type,3,3,4>& dR_dv,
+                               const Tensor3<field_type,3,3,3>& DR,
+                               const Tensor3<field_type,3,gridDim,4>& dDR3_dv) const;
 
 
     /** \brief The shell thickness */
@@ -443,12 +443,12 @@ public:
     const Dune::VirtualFunction<Dune::FieldVector<double,gridDim>, Dune::FieldVector<double,3> >* neumannFunction_;
 };
 
-template <class GridView, class LocalFiniteElement, int dim>
-typename CosseratEnergyLocalStiffness<GridView,LocalFiniteElement,dim>::RT
-CosseratEnergyLocalStiffness<GridView,LocalFiniteElement,dim>::
+template <class GridView, class LocalFiniteElement, int dim, class field_type>
+typename CosseratEnergyLocalStiffness<GridView,LocalFiniteElement,dim,field_type>::RT
+CosseratEnergyLocalStiffness<GridView,LocalFiniteElement,dim,field_type>::
 energy(const Entity& element,
        const LocalFiniteElement& localFiniteElement,
-       const std::vector<RigidBodyMotion<double,dim> >& localSolution) const
+       const std::vector<RigidBodyMotion<field_type,dim> >& localSolution) const
 {
     assert(element.type() == localFiniteElement.type());
     typedef typename GridView::template Codim<0>::Entity::Geometry Geometry;
@@ -461,22 +461,22 @@ energy(const Entity& element,
     int quadOrder = (element.type().isSimplex()) ? localFiniteElement.localBasis().order()
                                                  : localFiniteElement.localBasis().order() * gridDim;
 
-    const Dune::QuadratureRule<double, gridDim>& quad
-        = Dune::QuadratureRules<double, gridDim>::rule(element.type(), quadOrder);
+    const Dune::QuadratureRule<DT, gridDim>& quad
+        = Dune::QuadratureRules<DT, gridDim>::rule(element.type(), quadOrder);
 
     for (size_t pt=0; pt<quad.size(); pt++) {
 
         // Local position of the quadrature point
-        const Dune::FieldVector<double,gridDim>& quadPos = quad[pt].position();
+        const Dune::FieldVector<DT,gridDim>& quadPos = quad[pt].position();
 
-        const double integrationElement = element.geometry().integrationElement(quadPos);
+        const DT integrationElement = element.geometry().integrationElement(quadPos);
 
         const typename Geometry::JacobianInverseTransposed& jacobianInverseTransposed = element.geometry().jacobianInverseTransposed(quadPos);
 
-        double weight = quad[pt].weight() * integrationElement;
+        DT weight = quad[pt].weight() * integrationElement;
 
         // The value of the local function
-        RigidBodyMotion<double,dim> value = localGeodesicFEFunction.evaluate(quadPos);
+        RigidBodyMotion<field_type,dim> value = localGeodesicFEFunction.evaluate(quadPos);
 
         // The derivative of the local function defined on the reference element
         typename LocalGFEFunctionType::DerivativeType referenceDerivative = localGeodesicFEFunction.evaluateDerivative(quadPos,value);
@@ -493,7 +493,7 @@ energy(const Entity& element,
         dune_static_assert(dim>=gridDim, "Codim of the grid must be nonnegative");
 
         //
-        Dune::FieldMatrix<double,dim,dim> R;
+        Dune::FieldMatrix<field_type,dim,dim> R;
         value.q.matrix(R);
 
         /* Compute F, the deformation gradient.
@@ -502,7 +502,7 @@ energy(const Entity& element,
            In the case of a shell it is
           \f$ \hat{F} = (\nabla m | \overline{R}_3) \f$
         */
-        Dune::FieldMatrix<double,dim,dim> F;
+        Dune::FieldMatrix<field_type,dim,dim> F;
         for (int i=0; i<dim; i++)
             for (int j=0; j<gridDim; j++)
                 F[i][j] = derivative[i][j];
@@ -512,7 +512,7 @@ energy(const Entity& element,
                 F[i][j] = R[i][j];
 
         // U = R^T F
-        Dune::FieldMatrix<double,dim,dim> U;
+        Dune::FieldMatrix<field_type,dim,dim> U;
         for (int i=0; i<dim; i++)
             for (int j=0; j<dim; j++) {
                 U[i][j] = 0;
@@ -525,7 +525,7 @@ energy(const Entity& element,
         //  Note: we need it in matrix coordinates
         //////////////////////////////////////////////////////////
 
-        Tensor3<double,3,3,3> DR;
+        Tensor3<field_type,3,3,3> DR;
         computeDR(value, derivative, DR);
 
         // Add the local energy density
@@ -559,18 +559,18 @@ energy(const Entity& element,
         if (not neumannBoundary_ or not neumannBoundary_->contains(*it))
             continue;
 
-        const Dune::QuadratureRule<double, gridDim-1>& quad
-            = Dune::QuadratureRules<double, gridDim-1>::rule(it->type(), quadOrder);
+        const Dune::QuadratureRule<DT, gridDim-1>& quad
+            = Dune::QuadratureRules<DT, gridDim-1>::rule(it->type(), quadOrder);
 
         for (size_t pt=0; pt<quad.size(); pt++) {
 
             // Local position of the quadrature point
-            const Dune::FieldVector<double,gridDim>& quadPos = it->geometryInInside().global(quad[pt].position());
+            const Dune::FieldVector<DT,gridDim>& quadPos = it->geometryInInside().global(quad[pt].position());
 
-            const double integrationElement = it->geometry().integrationElement(quad[pt].position());
+            const DT integrationElement = it->geometry().integrationElement(quad[pt].position());
 
             // The value of the local function
-            RigidBodyMotion<double,dim> value = localGeodesicFEFunction.evaluate(quadPos);
+            RigidBodyMotion<field_type,dim> value = localGeodesicFEFunction.evaluate(quadPos);
 
             // Value of the Neumann data at the current position
             Dune::FieldVector<double,3> neumannValue;
@@ -581,7 +581,8 @@ energy(const Entity& element,
                 neumannFunction_->evaluate(it->geometry().global(quad[pt].position()), neumannValue);
 
             // Only translational dofs are affected by the Neumann force
-            energy += thickness_ * (neumannValue * value.r) * quad[pt].weight() * integrationElement;
+            for (size_t i=0; i<neumannValue.size(); i++)
+                energy += thickness_ * (neumannValue[i] * value.r[i]) * quad[pt].weight() * integrationElement;
 
         }
 
@@ -590,18 +591,18 @@ energy(const Entity& element,
     return energy;
 }
 
-template <class GridView, class LocalFiniteElement, int dim>
-void CosseratEnergyLocalStiffness<GridView, LocalFiniteElement, dim>::
+template <class GridView, class LocalFiniteElement, int dim, class field_type>
+void CosseratEnergyLocalStiffness<GridView, LocalFiniteElement, dim, field_type>::
 nonquadraticMembraneEnergyGradient(typename TargetSpace::EmbeddedTangentVector& embeddedLocalGradient,
-                                    const Dune::FieldMatrix<double,3,3>& R,
-                                    const Tensor3<double,3,3,4>& dR_dv,
-                                    const Dune::FieldMatrix<double,7,gridDim>& derivative,
-                                    const Tensor3<double,7,7,gridDim>& derOfGradientWRTCoefficient,
-                                    const Dune::FieldMatrix<double,3,3>& U
+                                    const Dune::FieldMatrix<field_type,3,3>& R,
+                                    const Tensor3<field_type,3,3,4>& dR_dv,
+                                    const Dune::FieldMatrix<field_type,7,gridDim>& derivative,
+                                    const Tensor3<field_type,7,7,gridDim>& derOfGradientWRTCoefficient,
+                                    const Dune::FieldMatrix<field_type,3,3>& U
                                    ) const
 {
     // Compute partial/partial v ((R_1|R_2)^T\nablam)
-    Tensor3<double,3,3,7> dU_dv(0);
+    Tensor3<field_type,3,3,7> dU_dv(0);
 
     for (size_t i=0; i<3; i++) {
 
@@ -634,7 +635,7 @@ nonquadraticMembraneEnergyGradient(typename TargetSpace::EmbeddedTangentVector&
 
         for (size_t i=0; i<3; i++)
             for (size_t j=0; j<3; j++) {
-                double symUMinusI = 0.5*U[i][j] + 0.5*U[j][i] - (i==j);
+                field_type symUMinusI = 0.5*U[i][j] + 0.5*U[j][i] - (i==j);
                 embeddedLocalGradient[v_i] += mu_ * symUMinusI * (dU_dv[i][j][v_i] + dU_dv[j][i][v_i]);
             }
 
@@ -655,18 +656,18 @@ nonquadraticMembraneEnergyGradient(typename TargetSpace::EmbeddedTangentVector&
 }
 
 
-template <class GridView, class LocalFiniteElement, int dim>
-void CosseratEnergyLocalStiffness<GridView, LocalFiniteElement, dim>::
+template <class GridView, class LocalFiniteElement, int dim, class field_type>
+void CosseratEnergyLocalStiffness<GridView, LocalFiniteElement, dim, field_type>::
 longQuadraticMembraneEnergyGradient(typename TargetSpace::EmbeddedTangentVector& embeddedLocalGradient,
-                                    const Dune::FieldMatrix<double,3,3>& R,
-                                    const Tensor3<double,3,3,4>& dR_dv,
-                                    const Dune::FieldMatrix<double,7,gridDim>& derivative,
-                                    const Tensor3<double,7,7,gridDim>& derOfGradientWRTCoefficient,
-                                    const Dune::FieldMatrix<double,3,3>& U
+                                    const Dune::FieldMatrix<field_type,3,3>& R,
+                                    const Tensor3<field_type,3,3,4>& dR_dv,
+                                    const Dune::FieldMatrix<field_type,7,gridDim>& derivative,
+                                    const Tensor3<field_type,7,7,gridDim>& derOfGradientWRTCoefficient,
+                                    const Dune::FieldMatrix<field_type,3,3>& U
                                    ) const
 {
     // Compute partial/partial v ((R_1|R_2)^T\nablam)
-    Tensor3<double,2,2,7> dR1R2Tnablam_dv(0);
+    Tensor3<field_type,2,2,7> dR1R2Tnablam_dv(0);
 
     for (size_t i=0; i<2; i++) {
 
@@ -697,7 +698,7 @@ longQuadraticMembraneEnergyGradient(typename TargetSpace::EmbeddedTangentVector&
 
         for (size_t i=0; i<2; i++)
             for (size_t j=0; j<2; j++) {
-                double symUMinusI = 0.5*U[i][j] + 0.5*U[j][i] - (i==j);
+                field_type symUMinusI = 0.5*U[i][j] + 0.5*U[j][i] - (i==j);
                 embeddedLocalGradient[v_i] += mu_ * symUMinusI * (dR1R2Tnablam_dv[i][j][v_i] + dR1R2Tnablam_dv[j][i][v_i]);
             }
 
@@ -724,10 +725,10 @@ longQuadraticMembraneEnergyGradient(typename TargetSpace::EmbeddedTangentVector&
     for (size_t v_i=0; v_i<7; v_i++) {
 
         for (size_t j=0; j<2; j++) {
-            double sp = 0;
+            field_type sp = 0;
             for (size_t k=0; k<3; k++)
                 sp += R[k][2]*derivative[k][j];
-            double spDer = 0;
+            field_type spDer = 0;
 
             if (v_i < 3)
                 for (size_t k=0; k<3; k++)
@@ -746,7 +747,7 @@ longQuadraticMembraneEnergyGradient(typename TargetSpace::EmbeddedTangentVector&
     //  Elongational Stretch Energy
     ////////////////////////////////////////////////////////////////////////////////////
 
-    double trace = U[0][0] + U[1][1] - 2;
+    field_type trace = U[0][0] + U[1][1] - 2;
 
     for (size_t v_i=0; v_i<7; v_i++)
         for (size_t i=0; i<2; i++)
@@ -755,12 +756,12 @@ longQuadraticMembraneEnergyGradient(typename TargetSpace::EmbeddedTangentVector&
 }
 
 
-template <class GridView, class LocalFiniteElement, int dim>
-void CosseratEnergyLocalStiffness<GridView, LocalFiniteElement, dim>::
+template <class GridView, class LocalFiniteElement, int dim, class field_type>
+void CosseratEnergyLocalStiffness<GridView, LocalFiniteElement, dim, field_type>::
 curvatureEnergyGradient(typename TargetSpace::EmbeddedTangentVector& embeddedLocalGradient,
-                        const Dune::FieldMatrix<double,3,3>& R,
-                        const Tensor3<double,3,3,3>& DR,
-                        const Dune::array<Tensor3<double,3,3,4>, 3>& dDR_dv) const
+                        const Dune::FieldMatrix<field_type,3,3>& R,
+                        const Tensor3<field_type,3,3,3>& DR,
+                        const Dune::array<Tensor3<field_type,3,3,4>, 3>& dDR_dv) const
 {
 #ifndef DONT_USE_CURL
 #error curvatureEnergyGradient not implemented for the curl curvature energy
@@ -781,18 +782,18 @@ curvatureEnergyGradient(typename TargetSpace::EmbeddedTangentVector& embeddedLoc
 }
 
 
-template <class GridView, class LocalFiniteElement, int dim>
-void CosseratEnergyLocalStiffness<GridView, LocalFiniteElement, dim>::
+template <class GridView, class LocalFiniteElement, int dim, class field_type>
+void CosseratEnergyLocalStiffness<GridView, LocalFiniteElement, dim, field_type>::
 bendingEnergyGradient(typename TargetSpace::EmbeddedTangentVector& embeddedLocalGradient,
-                      const Dune::FieldMatrix<double,3,3>& R,
-                      const Tensor3<double,3,3,4>& dR_dv,
-                      const Tensor3<double,3,3,3>& DR,
-                      const Tensor3<double,3,gridDim,4>& dDR3_dv) const
+                      const Dune::FieldMatrix<field_type,3,3>& R,
+                      const Tensor3<field_type,3,3,4>& dR_dv,
+                      const Tensor3<field_type,3,3,3>& DR,
+                      const Tensor3<field_type,3,gridDim,4>& dDR3_dv) const
 {
     embeddedLocalGradient = 0;
 
     // left-multiply the derivative of the third director (in DR[][2][]) with R^T
-    Dune::FieldMatrix<double,3,3> RT_DR3(0);
+    Dune::FieldMatrix<field_type,3,3> RT_DR3(0);
     for (int i=0; i<3; i++)
         for (int j=0; j<gridDim; j++)
             for (int k=0; k<3; k++)
@@ -803,7 +804,7 @@ bendingEnergyGradient(typename TargetSpace::EmbeddedTangentVector& embeddedLocal
 
     // -----------------------------------------------------------------------------
 
-    Tensor3<double,3,3,4> d_RT_DR3(0);
+    Tensor3<field_type,3,3,4> d_RT_DR3(0);
     for (size_t v_i=0; v_i<4; v_i++)
         for (int i=0; i<3; i++)
             for (int j=0; j<gridDim; j++)
@@ -839,15 +840,15 @@ bendingEnergyGradient(typename TargetSpace::EmbeddedTangentVector& embeddedLocal
     //  "Elongational Stretch Energy"
     ////////////////////////////////////////////////////////////////////////////////
 
-    double factor = 2 * mu_*lambda_ / (2*mu_ + lambda_) * (RT_DR3[0][0] + RT_DR3[1][1] + RT_DR3[2][2]);
+    field_type factor = 2 * mu_*lambda_ / (2*mu_ + lambda_) * (RT_DR3[0][0] + RT_DR3[1][1] + RT_DR3[2][2]);
     for (size_t v_i=0; v_i<4; v_i++)
         for (int i=0; i<3; i++)
             embeddedLocalGradient[v_i+3] += factor * d_RT_DR3[i][i][v_i];
 
 }
 
-template <class GridView, class LocalFiniteElement, int dim>
-void CosseratEnergyLocalStiffness<GridView, LocalFiniteElement, dim>::
+template <class GridView, class LocalFiniteElement, int dim, class field_type>
+void CosseratEnergyLocalStiffness<GridView, LocalFiniteElement, dim, field_type>::
 assembleGradient(const Entity& element,
                  const LocalFiniteElement& localFiniteElement,
                  const std::vector<TargetSpace>& localSolution,
@@ -865,22 +866,22 @@ assembleGradient(const Entity& element,
     int quadOrder = (element.type().isSimplex()) ? localFiniteElement.localBasis().order()
                                                  : localFiniteElement.localBasis().order() * gridDim;
 
-    const Dune::QuadratureRule<double, gridDim>& quad
-        = Dune::QuadratureRules<double, gridDim>::rule(element.type(), quadOrder);
+    const Dune::QuadratureRule<DT, gridDim>& quad
+        = Dune::QuadratureRules<DT, gridDim>::rule(element.type(), quadOrder);
 
     for (size_t pt=0; pt<quad.size(); pt++) {
 
         // Local position of the quadrature point
-        const Dune::FieldVector<double,gridDim>& quadPos = quad[pt].position();
+        const Dune::FieldVector<DT,gridDim>& quadPos = quad[pt].position();
 
-        const double integrationElement = element.geometry().integrationElement(quadPos);
+        const DT integrationElement = element.geometry().integrationElement(quadPos);
 
         const typename Geometry::JacobianInverseTransposed& jacobianInverseTransposed = element.geometry().jacobianInverseTransposed(quadPos);
 
-        double weight = quad[pt].weight() * integrationElement;
+        field_type weight = quad[pt].weight() * integrationElement;
 
         // The value of the local function
-        RigidBodyMotion<double,dim> value = localGeodesicFEFunction.evaluate(quadPos);
+        RigidBodyMotion<field_type,dim> value = localGeodesicFEFunction.evaluate(quadPos);
 
         // The derivative of the local function defined on the reference element
         typename LocalGFEFunctionType::DerivativeType referenceDerivative = localGeodesicFEFunction.evaluateDerivative(quadPos,value);
@@ -897,7 +898,7 @@ assembleGradient(const Entity& element,
         dune_static_assert(dim>=gridDim, "Codim of the grid must be nonnegative");
 
         //
-        Dune::FieldMatrix<double,dim,dim> R;
+        Dune::FieldMatrix<field_type,dim,dim> R;
         value.q.matrix(R);
 
         /* Compute F, the deformation gradient.
@@ -906,7 +907,7 @@ assembleGradient(const Entity& element,
            In the case of a shell it is
           \f$ \hat{F} = (\nabla m | \overline{R}_3) \f$
         */
-        Dune::FieldMatrix<double,dim,dim> F;
+        Dune::FieldMatrix<field_type,dim,dim> F;
         for (int i=0; i<dim; i++)
             for (int j=0; j<gridDim; j++)
                 F[i][j] = derivative[i][j];
@@ -916,7 +917,7 @@ assembleGradient(const Entity& element,
                 F[i][j] = R[i][j];
 
         // U = R^T F
-        Dune::FieldMatrix<double,dim,dim> U;
+        Dune::FieldMatrix<field_type,dim,dim> U;
         for (int i=0; i<dim; i++)
             for (int j=0; j<dim; j++) {
                 U[i][j] = 0;
@@ -929,25 +930,25 @@ assembleGradient(const Entity& element,
         //  Note: we need it in matrix coordinates
         //////////////////////////////////////////////////////////
 
-        Tensor3<double,3,3,3> DR;
+        Tensor3<field_type,3,3,3> DR;
         computeDR(value, derivative, DR);
 
         // loop over all the element's degrees of freedom and compute the gradient wrt it
         for (size_t i=0; i<localSolution.size(); i++) {
 
             // --------------------------------------------------------------------
-            Dune::FieldMatrix<double,7,7> derOfValueWRTCoefficient;
+            Dune::FieldMatrix<field_type,7,7> derOfValueWRTCoefficient;
             localGeodesicFEFunction.evaluateDerivativeOfValueWRTCoefficient(quadPos, i, derOfValueWRTCoefficient);
 
-            Tensor3<double,3,3,4> dR_dv;
+            Tensor3<field_type,3,3,4> dR_dv;
             computeDR_dv(value, derOfValueWRTCoefficient, dR_dv);
 
             // --------------------------------------------------------------------
-            Tensor3<double, TargetSpace::EmbeddedTangentVector::dimension,TargetSpace::EmbeddedTangentVector::dimension,gridDim> referenceDerivativeDerivative;
+            Tensor3<field_type, TargetSpace::EmbeddedTangentVector::dimension,TargetSpace::EmbeddedTangentVector::dimension,gridDim> referenceDerivativeDerivative;
             localGeodesicFEFunction.evaluateDerivativeOfGradientWRTCoefficient(quadPos, i, referenceDerivativeDerivative);
 
             // multiply the transformation from the reference element to the actual element
-            Tensor3<double, TargetSpace::EmbeddedTangentVector::dimension,TargetSpace::EmbeddedTangentVector::dimension,gridDim> derOfGradientWRTCoefficient;
+            Tensor3<field_type, TargetSpace::EmbeddedTangentVector::dimension,TargetSpace::EmbeddedTangentVector::dimension,gridDim> derOfGradientWRTCoefficient;
             for (int ii=0; ii<TargetSpace::EmbeddedTangentVector::dimension; ii++)
                 for (int jj=0; jj<TargetSpace::EmbeddedTangentVector::dimension; jj++)
                     for (int kk=0; kk<gridDim; kk++) {
@@ -957,8 +958,8 @@ assembleGradient(const Entity& element,
                     }
 
             // ---------------------------------------------------------------------
-            Dune::array<Tensor3<double,3,3,4>, 3> dDR_dv;
-            Tensor3<double,3,gridDim,4> dDR3_dv;
+            Dune::array<Tensor3<field_type,3,3,4>, 3> dDR_dv;
+            Tensor3<field_type,3,gridDim,4> dDR3_dv;
             compute_dDR_dv(value, derivative, derOfValueWRTCoefficient, derOfGradientWRTCoefficient, dDR_dv, dDR3_dv);
 
             // Add the local energy density
@@ -998,15 +999,15 @@ assembleGradient(const Entity& element,
         if (not neumannBoundary_ or not neumannBoundary_->contains(*it))
             continue;
 
-        const Dune::QuadratureRule<double, gridDim-1>& quad
-            = Dune::QuadratureRules<double, gridDim-1>::rule(it->type(), quadOrder);
+        const Dune::QuadratureRule<DT, gridDim-1>& quad
+            = Dune::QuadratureRules<DT, gridDim-1>::rule(it->type(), quadOrder);
 
         for (size_t pt=0; pt<quad.size(); pt++) {
 
             // Local position of the quadrature point
-            const Dune::FieldVector<double,gridDim>& quadPos = it->geometryInInside().global(quad[pt].position());
+            const Dune::FieldVector<DT,gridDim>& quadPos = it->geometryInInside().global(quad[pt].position());
 
-            const double integrationElement = it->geometry().integrationElement(quad[pt].position());
+            const DT integrationElement = it->geometry().integrationElement(quad[pt].position());
 
             // Value of the Neumann data at the current position
             Dune::FieldVector<double,3> neumannValue;
@@ -1020,7 +1021,7 @@ assembleGradient(const Entity& element,
             for (size_t i=0; i<localSolution.size(); i++) {
 
                 // --------------------------------------------------------------------
-                Dune::FieldMatrix<double,7,7> derOfValueWRTCoefficient;
+                Dune::FieldMatrix<field_type,7,7> derOfValueWRTCoefficient;
                 localGeodesicFEFunction.evaluateDerivativeOfValueWRTCoefficient(quadPos, i, derOfValueWRTCoefficient);
 
                 // Only translational dofs are affected by the Neumann force
-- 
GitLab