diff --git a/dune/microstructure/energies/CMakeLists.txt b/dune/microstructure/energies/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8c71e5f4c8702a8129b3b10a3423164bbf7f2b71
--- /dev/null
+++ b/dune/microstructure/energies/CMakeLists.txt
@@ -0,0 +1,3 @@
+#install headers
+install(FILES discretekirchhoffbendingenergyprestrained.hh 
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/energies)
diff --git a/dune/microstructure/energies/discretekirchhoffbendingenergyprestrained.hh b/dune/microstructure/energies/discretekirchhoffbendingenergyprestrained.hh
new file mode 100644
index 0000000000000000000000000000000000000000..d6e46988f5cb1f46813831d270d6dff8e56f54bc
--- /dev/null
+++ b/dune/microstructure/energies/discretekirchhoffbendingenergyprestrained.hh
@@ -0,0 +1,673 @@
+#ifndef DUNE_MICROSTRUCTURE_ENERGIES_DISCRETEKIRCHHOFFBENDINGENERGYPRESTRAINED_HH
+#define DUNE_MICROSTRUCTURE_ENERGIES_DISCRETEKIRCHHOFFBENDINGENERGYPRESTRAINED_HH
+
+#include <dune/common/fmatrix.hh>
+#include <dune/geometry/quadraturerules.hh>
+
+#include <dune/gfe/assemblers/localenergy.hh>
+#include <dune/gfe/bendingisometryhelper.hh>
+#include <dune/gfe/tensor3.hh>
+
+#include <dune/localfunctions/lagrange/lagrangesimplex.hh>
+
+#include <cmath>
+/** 
+ * \brief Assemble the discrete Kirchhoff bending energy for a single element. 
+ * 
+ *  The Kirchhoff bending energy consists of two parts: 
+ * 
+ *  1. The energy of  Qhom(II - Beff) where II is the second fundamental form of the surface parametrized by the deformation function 
+ *     and Beff is a (given) effective prestrain tensor. 
+ * 
+ *     This contribution is split intro three parts which corresponds to the binomial formula (a+b)^2 = a^2 + 2ab + b^2
+ *     each term is discretized separately.
+ * 
+ *  2. An integral over the scalar product of a forcing term and the discrete deformation 
+ *  (i.e. the evaluation of localFunction_ ).
+ */
+namespace Dune::GFE
+{
+  template<class Basis, class LocalDiscreteKirchhoffFunction, class LocalForce, class TargetSpace>
+  class DiscreteKirchhoffBendingEnergyPrestrained
+    : public Dune::GFE::LocalEnergy<Basis,TargetSpace>
+  {
+    // grid types
+    typedef typename Basis::GridView GridView;
+    typedef typename GridView::ctype DT;
+    typedef typename TargetSpace::ctype RT;
+    typedef typename LocalDiscreteKirchhoffFunction::DerivativeType DerivativeType;
+    typedef typename Dune::FieldMatrix<RT,2,2> PrestrainType;
+    typedef typename Dune::FieldMatrix<RT,3,3> MatrixType;
+    // Grid dimension
+    constexpr static int gridDim = GridView::dimension;
+    // P2-LocalFiniteElement used to represent the discrete Jacobian on the current element.
+    typedef typename Dune::LagrangeSimplexLocalFiniteElement<DT, double, gridDim, 2> P2LocalFiniteElement;
+
+  public:
+    DiscreteKirchhoffBendingEnergyPrestrained(LocalDiscreteKirchhoffFunction &localFunction,
+                                   LocalForce &localForce,
+                                   const Dune::ParameterTree& parameterSet,
+                                   Python::Module pyModule)
+        : localFunction_(localFunction),
+          localForce_(localForce),
+          parameterSet_(parameterSet),
+          module_(pyModule) 
+    {
+      setupEffectiveQuantities();
+    }
+
+
+
+
+    // Dune::FieldMatrix<RT,3,3> Qhom_(0);
+
+   void setupEffectiveQuantities()
+   {
+
+
+      Dune::FieldMatrix<double,3,3> Qhom_double(0);
+      module_.get("effectiveQuadraticForm").toC<Dune::FieldMatrix<double,3,3>>(Qhom_double);
+      convertFieldMatrix<RT,decltype(Qhom_double)>(Qhom_double,Qhom_);
+      printmatrix(std::cout, Qhom_, "Setup effective Quadratic form (Qhom) as  ", "--");
+
+      Dune::FieldMatrix<double,2,2> Beff_double(0);
+      module_.get("effectivePrestrain").toC<Dune::FieldMatrix<double,2,2>>(Beff_double);
+      convertFieldMatrix<RT,decltype(Beff_double)>(Beff_double,Beff_);
+      printmatrix(std::cout, Beff_, "Setup effective prestrain (Beff) as  ", "--");
+
+
+   }
+
+   void resetEffectiveQuantities()
+   {
+
+
+   }
+
+
+    
+    // auto applyQhom(const Dune::FieldMatrix<RT,1,3>& A, const Dune::FieldMatrix<RT,1,3>& B) const
+    // {
+    //   std::cout << "Apply Qhom" << std::endl;
+
+    //   return Qhom_[0][0]*A[0][0]*B[0][0] + Qhom_[0][1]*A[0][1]*B[0][0] + Qhom_[0][2]*A[0][2]*B[0][0] 
+    //         +  Qhom_[1][0]*A[0][0]*B[0][1] + Qhom_[1][1]*A[0][1]*B[0][1] + Qhom_[1][2]*A[0][2]*B[0][1] 
+    //         +  Qhom_[2][0]*A[0][0]*B[0][2] + Qhom_[2][1]*A[0][1]*B[0][2] + Qhom_[2][2]*A[0][2]*B[0][2];
+    // }
+
+
+    /**
+     * @brief 
+     * 
+     * @param A coefficient vector of first input
+     * @param B coefficient vector of second input
+     * @return auto template<class VectorType>
+     */
+    auto applyQhom(const Dune::FieldVector<RT,3>& A, const Dune::FieldVector<RT,3>& B) const
+    {
+      // std::cout << "Apply Qhom" << std::endl; 
+
+      return Qhom_[0][0]*A[0]*B[0] + Qhom_[0][1]*A[1]*B[0] + Qhom_[0][2]*A[2]*B[0] 
+          +  Qhom_[1][0]*A[0]*B[1] + Qhom_[1][1]*A[1]*B[1] + Qhom_[1][2]*A[2]*B[1] 
+          +  Qhom_[2][0]*A[0]*B[2] + Qhom_[2][1]*A[1]*B[2] + Qhom_[2][2]*A[2]*B[2];
+    }
+    // template<class Vector>
+    // auto applyQhom(const Vector& A, const Vector& B) const
+    // {
+    //   // std::cout << "Apply Qhom" << std::endl; 
+
+
+    //   return Qhom_[0][0] + Qhom_[0][1]*A[1]*B[0] + Qhom_[0][2]*A[2]*B[0] 
+    //       +  Qhom_[1][0]*A[0]*B[1] + Qhom_[1][1]*A[1]*B[1] + Qhom_[1][2]*A[2]*B[1] 
+    //       +  Qhom_[2][0]*A[0]*B[2] + Qhom_[2][1]*A[1]*B[2] + Qhom_[2][2]*A[2]*B[2];
+    // }
+
+//   // Template specialization for Matrix:
+//   template<>
+// string toCustomString<std::string>(std::vector<std::string> vec) {
+//     // strings
+// }
+
+//     template<>
+//     auto applyQhom<Dune:>(const Vector& A, const Vector& B) const
+//     {
+//       // std::cout << "Apply Qhom" << std::endl; 
+
+//       return Qhom_[0][0] + Qhom_[0][1]*A[1]*B[0] + Qhom_[0][2]*A[2]*B[0] 
+//           +  Qhom_[1][0]*A[0]*B[1] + Qhom_[1][1]*A[1]*B[1] + Qhom_[1][2]*A[2]*B[1] 
+//           +  Qhom_[2][0]*A[0]*B[2] + Qhom_[2][1]*A[1]*B[2] + Qhom_[2][2]*A[2]*B[2];
+//     }
+
+
+
+    /** \brief Assemble the energy for a single element */
+    virtual RT energy (const typename Basis::LocalView& localView,         
+               const  std::vector<TargetSpace>& localSolution) const       
+    {
+      RT energy = 0;
+
+
+      // if (parameterSet_.get<bool>("macroscopically_constant_microstructure", 1))
+      /**
+       * @brief Get effective prestrain Tensor
+       */
+      // Dune::FieldVector<RT,3> Beffvec = parameterSet_.get<Dune::FieldVector<RT,3>>("effectivePrestrain", {0.0, 0.0, 0.0});
+      // PrestrainType Beff = {{Beffvec[0], Beffvec[2]}, {Beffvec[2], Beffvec[1]} };
+
+
+
+      
+      // printmatrix(std::cout, Beff, "effective prestrain (Beff): ", "--");
+
+      /**
+       * @brief Get effective quadratic form Qhom
+       * 
+       *  input-vector: [q_1,q_2,q_3,q_12,q_13,q_23]
+       *  is assembled into a matrix where the off-diagonal entries are divided by 2 (compare with definition in the paper)
+       *            (   q_1    , 0.5*q_12  ,  0.5*q_13 )
+       *     Q =    ( 0.5*q_12 ,   q_2     ,  0.5*q_23 )
+       *            ( 0.5*q_13 , 0.5*q_23  ,    q_3    )
+       */
+      // Dune::FieldVector<RT,6> Qhomvec = parameterSet_.get<Dune::FieldVector<RT,6>>("effectiveQuadraticForm", {1.0, 1.0, 1.0, 0.0, 0.0, 0.0});
+      // MatrixType Qhom = {{Qhomvec[0]    , 0.5*Qhomvec[3], 0.5*Qhomvec[4]}, 
+      //                    {0.5*Qhomvec[3],     Qhomvec[1], 0.5*Qhomvec[5]},
+      //                    {0.5*Qhomvec[4], 0.5*Qhomvec[5],     Qhomvec[2]}};
+
+      // Dune::FieldMatrix<RT,3,3> TestMatrix(0);
+
+      // Dune::FieldMatrix<double,3,3> TestMatrix = parameterSet_.get<Dune::FieldMatrix<double,3,3>>("TestMatrixString");
+      // module_.get("TestMatrix").toC<Dune::FieldMatrix<RT,3,3>>(TestMatrix);
+      // printmatrix(std::cout, TestMatrix, "TestMatrix from pyModule: ", "--");
+
+
+      // Qhom_ = {{Qhomvec[0]    , 0.5*Qhomvec[3], 0.5*Qhomvec[4]}, 
+      //                    {0.5*Qhomvec[3],     Qhomvec[1], 0.5*Qhomvec[5]},
+      //                    {0.5*Qhomvec[4], 0.5*Qhomvec[5],     Qhomvec[2]}};
+      // printmatrix(std::cout, Qhom, "effective quadratic form (Qhom): ", "--");
+
+
+      // print some quantities for debugging purposes.
+      bool PRINT_DEBUG = parameterSet_.get<bool>("print_debug", 0);
+
+
+#if 1
+      // TODO: More serious order selection
+      int quadOrder = 3;
+      // int quadOrder = 6;
+#else
+      if (localFiniteElement.localBasis().order()==1)
+        quadOrder = 2;
+      else
+        quadOrder = (localFiniteElement.type().isSimplex()) ? (localFiniteElement.localBasis().order() - 1) * 2
+                                                            : (localFiniteElement.localBasis().order() * gridDim - 1) * 2;
+#endif
+      
+      const auto element = localView.element();
+      auto geometry = element.geometry();
+      auto gridView = localFunction_.gridView();
+      const auto &indexSet = gridView.indexSet();
+
+      // bind to current element.
+      localFunction_.bind(element);
+      localForce_.bind(element);
+      /**
+       * @brief We need to update the Coefficients of localFunction_
+       *        on the current element.
+       */
+      localFunction_.updateLocalCoefficients(localSolution,element);
+
+
+
+      if(PRINT_DEBUG)
+      {
+        std::cout << " -------------------------------------------- " << std::endl;
+        std::cout << "ELEMENT NUMBER( indexSet.index(element)) ):" << indexSet.index(element) << std::endl;
+        std::cout << "geometry.corner(0): " << geometry.corner(0) << std::endl;
+        std::cout << "geometry.corner(1)): " << geometry.corner(1) << std::endl;
+        std::cout << "geometry.corner(2): " << geometry.corner(2) << std::endl;
+      }
+
+
+      /**
+       * @brief  Get Coefficients of the discrete Gradient 
+       * 
+       * The discrete Gradient is a special linear combination represented in a [P2]^2 - (Lagrange) space
+       * The coefficients of this linear combination correspond to certain linear combinations of the Gradients of localfunction_ .
+       * The coefficients are stored in the form [Basisfunctions x components x gridDim]
+       * in a BlockVector<FieldMatrix<RT, 3, gridDim>> .
+       */
+      BlockVector<FieldMatrix<RT, 3, gridDim>> discreteJacobianCoefficients;
+      discreteGradientCoefficients(discreteJacobianCoefficients,lagrangeLFE_,localFunction_,element);
+    
+    
+    
+  
+
+      /**
+       * @brief Compute harmonic energy contribution:
+       */
+      RT harmonicEnergy = 0;
+
+
+      /**
+       * @brief Mixed version using the binomal formula (a-b)^2 = a^2 - 2ab + b^2 
+       *        for | II - Beff |^2 and discretize every term individually. 
+       */
+      // Gauss-Quadrature:
+      const auto &quadRule = QuadratureRules<double, gridDim>::rule(lagrangeLFE_.type(), quadOrder);
+      // Trapezoidal-rule:
+      // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} };
+      // Trapezoidal-rule + evaluation on edge centers (only for testing purposes):
+      // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{0.5,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,0.5}, 1.0/6.0}, {{0.5,0.5}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} };
+      for (auto&& quadPoint : quadRule)
+      {
+        const auto& quadPos = quadPoint.position();
+        const auto integrationElement = geometry.integrationElement(quadPos);
+
+        //Get values of the P2-Basis functions on current quadrature point
+        std::vector<FieldVector<double,1>> basisValues;
+        lagrangeLFE_.localBasis().evaluateFunction(quadPos, basisValues);
+
+        // Get Jacobians of the P2-Basis functions on current quadrature point
+        // std::vector<FieldMatrix<double, 1, gridDim>> referenceGradients;
+        // lagrangeLFE_.localBasis().evaluateJacobian(quadPos, referenceGradients);
+
+        // const auto jacobian = geometry.jacobianInverseTransposed(quadPos);
+        
+        // std::vector<FieldVector<RT, gridDim>> gradients(referenceGradients.size());
+        // for (size_t i = 0; i<gradients.size(); i++)
+        //   jacobian.mv(referenceGradients[i][0], gradients[i]);
+
+
+        // New compact way to write Gradient:
+        const auto geometryJacobianInverse = geometry.jacobianInverse(quadPos);
+        std::vector<FieldMatrix<double,1,gridDim> > gradients;
+        lagrangeLFE_.localBasis().evaluateJacobian(quadPos, gradients);
+
+        for (size_t i=0; i< gradients.size(); i++)
+           gradients[i] = gradients[i] * geometryJacobianInverse;
+
+
+        Tensor3<RT,3,gridDim,gridDim> discreteHessian(0); 
+        FieldMatrix<RT, 3, gridDim> discreteGradient(0);
+
+        for (int k=0; k<3; k++)
+        for (int l=0; l<gridDim; l++)
+        for (std::size_t i=0; i<lagrangeLFE_.size(); i++)
+        {
+            discreteGradient[k][l]    += discreteJacobianCoefficients[i][k][l]*basisValues[i];
+            discreteHessian[k][l][0]  += discreteJacobianCoefficients[i][k][l]*gradients[i][0][0];
+            discreteHessian[k][l][1]  += discreteJacobianCoefficients[i][k][l]*gradients[i][0][1];
+        }
+      
+        if(PRINT_DEBUG)
+        {
+          /**
+           * @brief print the (three) 2x2 slices of the discrete Hessian and check for symmetry
+           */
+          FieldMatrix<RT, gridDim, gridDim> discreteHessian_slice1(0);
+          FieldMatrix<RT, gridDim, gridDim> discreteHessian_slice2(0);
+          FieldMatrix<RT, gridDim, gridDim> discreteHessian_slice3(0);
+
+          for (int i=0; i<gridDim; i++)
+          for (int l=0; l<gridDim; l++)
+          {
+              discreteHessian_slice1[i][l] = discreteHessian[0][i][l];
+              discreteHessian_slice2[i][l] = discreteHessian[1][i][l];
+              discreteHessian_slice3[i][l] = discreteHessian[2][i][l];
+          }
+          printmatrix(std::cout, discreteHessian_slice1, "discreteHessian_slice1: ", "--");
+          printmatrix(std::cout, discreteHessian_slice2, "discreteHessian_slice2: ", "--");
+          printmatrix(std::cout, discreteHessian_slice3, "discreteHessian_slice3: ", "--");
+          printmatrix(std::cout, sym(discreteHessian_slice1), "SYM discreteHessian_slice1: ", "--");
+          printmatrix(std::cout, sym(discreteHessian_slice2), "SYM discreteHessian_slice2: ", "--");
+          printmatrix(std::cout, sym(discreteHessian_slice3), "SYM discreteHessian_slice3: ", "--");
+        }
+
+
+
+        /**
+         * @brief Compute the normal vector of the surface parametrized by the 
+         *        discrete deformation. This is given by the 
+         *        cross product of partial derivatives
+         */       
+        // FieldVector<RT,3> surfaceNormal(0);
+        FieldVector<RT,3> partialX = {discreteGradient[0][0], discreteGradient[1][0], discreteGradient[2][0]};
+        FieldVector<RT,3> partialY = {discreteGradient[0][1], discreteGradient[1][1], discreteGradient[2][1]};
+        // Normalize if requested
+        // auto normX = partialX.two_norm();
+        // auto normY = partialY.two_norm();
+        // partialX /= normX;
+        // partialY /= normY;
+        // surfaceNormal[0] = partialX[1]*partialY[2] - partialX[2]*partialY[1];
+        // surfaceNormal[1] = partialX[2]*partialY[0] - partialX[0]*partialY[2];
+        // surfaceNormal[2] = partialX[0]*partialY[1] - partialX[1]*partialY[0];
+        FieldVector<RT,3> surfaceNormal = {partialX[1]*partialY[2] - partialX[2]*partialY[1],
+                                           partialX[2]*partialY[0] - partialX[0]*partialY[2],
+                                           partialX[0]*partialY[1] - partialX[1]*partialY[0]};
+
+
+
+        /**
+         * @brief Compute the second fundamental form of the surface parametrized by the
+         *        discrete deformation.
+         *        We have to multiply by (-1.0) to get the right sign/normal/orientation.
+         */       
+        FieldMatrix<RT,gridDim,gridDim> secondFF(0);
+
+        for(size_t m=0; m<2; m++)
+        for(size_t n=0; n<2; n++)
+        for(size_t k=0; k<3; k++) 
+          secondFF[m][n] += -1.0*surfaceNormal[k]*discreteHessian[k][n][m];
+        // To get the right sign:
+        // secondFF = -1.0*secondFF;
+
+
+        //TODO : Add method "applyQhom"
+
+        /**
+         * @brief Compute the first term: Qhom(II)
+         */
+        auto weight = quadPoint.weight() * element.geometry().integrationElement(quadPos);
+
+        RT term1 = 0.0;
+
+        // FieldMatrix<RT,3,3> X_old = tensorToSymCoefficients(discreteHessian);
+        std::vector<FieldVector<RT,3>> X(3);
+        tensorToSymCoefficients(discreteHessian, X);
+
+
+        // printmatrix(std::cout, X_old, "X_old", "--");
+        // for(int k=0; k<3; k++)
+        // {
+        //   printvector(std::cout, X[k], "X[k]", "--");
+
+        // }
+
+
+
+        RT term1_old = 0.0;
+
+        for(int k=0; k<3; k++)
+        {
+          // term1 += Qhom[0][0]*pow((2.0*discreteHessian[k][0][0]),2)+ Qhom[0][1]* ... more efficient (TODO)  Qhom is symmetric
+          term1_old += Qhom_[0][0]*pow(X[k][0],2)    + Qhom_[0][1]*X[k][1]*X[k][0]  + Qhom_[0][2]*X[k][2]*X[k][0] 
+                    +  Qhom_[1][0]*X[k][0]*X[k][1]   + Qhom_[1][1]*pow(X[k][1],2)   + Qhom_[1][2]*X[k][2]*X[k][1] 
+                    +  Qhom_[2][0]*X[k][0]*X[k][2]   + Qhom_[2][1]*X[k][1]*X[k][2]  + Qhom_[2][2]*pow(X[k][2],2);
+
+          // apply Qhom to each slice of the Hessian... 
+          term1 += applyQhom(X[k], X[k]); 
+        }
+        // term1 = term1 * 0.5 * weight;
+
+        // std::cout << "term1: " << term1 << std::endl;
+        // std::cout << "term1_old: " << term1_old << std::endl;
+
+        term1 = term1 * weight;
+        term1_old = term1_old * weight;
+
+
+        if(abs(term1-term1_old) > 1e-6)
+          std::cout << "DIFFERENCE term1-term1_old " << term1-term1_old << std::endl; 
+
+
+
+      //  /**
+      //  * @brief Compute the second (mixed) term
+      //  */
+        FieldVector<RT,3> secondFFCoefficients = matrixToSymCoefficients(secondFF);
+        FieldVector<RT,3> BeffCoefficients = matrixToSymCoefficients(Beff_);
+
+        RT term2 = 0.0;
+        RT term2_old = 0.0;
+        term2_old += Qhom_[0][0]*BeffCoefficients[0]*secondFFCoefficients[0] + Qhom_[0][1]*BeffCoefficients[1]*secondFFCoefficients[0] + Qhom_[0][2]*BeffCoefficients[2]*secondFFCoefficients[0] 
+                  +  Qhom_[1][0]*BeffCoefficients[0]*secondFFCoefficients[1] + Qhom_[1][1]*BeffCoefficients[1]*secondFFCoefficients[1] + Qhom_[1][2]*BeffCoefficients[2]*secondFFCoefficients[1] 
+                  +  Qhom_[2][0]*BeffCoefficients[0]*secondFFCoefficients[2] + Qhom_[2][1]*BeffCoefficients[1]*secondFFCoefficients[2] + Qhom_[2][2]*BeffCoefficients[2]*secondFFCoefficients[2];
+
+
+
+        // term2 += applyQhom(secondFFCoefficients,BeffCoefficients);
+        term2 += applyQhom(BeffCoefficients,secondFFCoefficients);
+
+        // std::cout << "term2: " << term2 << std::endl;
+        // std::cout << "term2_old: " << term2_old << std::endl;
+
+        term2 = 2.0 * term2 * weight;
+        term2_old = 2.0 * term2_old * weight;
+
+        if(abs(term2-term2_old) > 1e-6)
+          std::cout << "DIFFERENCE term2-term2_old " << term2-term2_old << std::endl; 
+
+
+
+        // auto term3 = 0.5 * weight* Beff.frobenius_norm2();        
+
+        RT term3 = 0.0;   
+        RT term3_old = 0.0;   
+
+        term3_old += Qhom_[0][0]*BeffCoefficients[0]*BeffCoefficients[0] + Qhom_[0][1]*BeffCoefficients[1]*BeffCoefficients[0] + Qhom_[0][2]*BeffCoefficients[2]*BeffCoefficients[0] 
+                  +  Qhom_[1][0]*BeffCoefficients[0]*BeffCoefficients[1] + Qhom_[1][1]*BeffCoefficients[1]*BeffCoefficients[1] + Qhom_[1][2]*BeffCoefficients[2]*BeffCoefficients[1] 
+                  +  Qhom_[2][0]*BeffCoefficients[0]*BeffCoefficients[2] + Qhom_[2][1]*BeffCoefficients[1]*BeffCoefficients[2] + Qhom_[2][2]*BeffCoefficients[2]*BeffCoefficients[2];
+        // // term3 = term3 * 0.5 *  weight ;
+        term3 += applyQhom(BeffCoefficients,BeffCoefficients);
+
+        // std::cout << "term3: " << term3 << std::endl;
+        // std::cout << "term3_old: " << term3_old << std::endl;
+
+
+        term3 = term3 *  weight ;
+        term3_old = term3_old *  weight ;
+
+        if(abs(term3-term3_old) > 1e-6)
+          std::cout << "DIFFERENCE term3-term3_old " << term3-term3_old << std::endl; 
+
+
+
+
+
+        harmonicEnergy +=  term1 - term2 + term3;     
+        // harmonicEnergy +=  term1_old - term2_old + term3_old;     
+
+        // std::cout << "harmonicEnergy: " << harmonicEnergy << std::endl;
+      }
+      // #endif
+
+
+      #if 0
+      /**
+       * @brief VERSION - 3 : Mixed version using the binomal formula (a-b)^2 = a^2 - 2ab + b^2 
+       *                      for | II - Beff |^2 and discretize every term individually. 
+       *                      *But with |II|^2 instead of |D^2y|^2
+       */
+      // Gauss-Quadrature:
+      const auto &quadRule = QuadratureRules<double, gridDim>::rule(lagrangeLFE_.type(), quadOrder);
+      // Trapezoidal-rule:
+      // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} };
+      // Trapezoidal-rule + evaluation on edge centers (only for testing purposes):
+      // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{0.5,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,0.5}, 1.0/6.0}, {{0.5,0.5}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} };
+      for (auto&& quadPoint : quadRule)
+      {
+
+        //Get values of the P2-Basis functions on current quadrature point
+        std::vector<FieldVector<double,1>> basisValues;
+        lagrangeLFE_.localBasis().evaluateFunction(quadPoint.position(), basisValues);
+
+
+        // Get Jacobians of the P2-Basis functions on current quadrature point
+        std::vector<FieldMatrix<double, 1, gridDim>> referenceGradients;
+
+        lagrangeLFE_.localBasis().evaluateJacobian(quadPoint.position(), referenceGradients);
+        const auto jacobian = geometry.jacobianInverseTransposed(quadPoint.position());
+        const auto integrationElement = geometry.integrationElement(quadPoint.position());
+
+        std::vector<FieldVector<RT, gridDim>> gradients(referenceGradients.size());
+        for (size_t i = 0; i<gradients.size(); i++)
+          jacobian.mv(referenceGradients[i][0], gradients[i]);
+
+
+        Tensor3<RT,3,2,2> discreteHessian(0); 
+        FieldMatrix<RT, 3, gridDim> discreteGradient(0);
+
+        for (int k=0; k<3; k++)
+        for (int l=0; l<gridDim; l++)
+        for(std::size_t i=0; i<lagrangeLFE_.size(); i++)
+        {
+            discreteGradient[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues[i];
+            discreteHessian[k][l][0]  += discreteJacobianCoefficients[i][k][l]*gradients[i][0];
+            discreteHessian[k][l][1]  += discreteJacobianCoefficients[i][k][l]*gradients[i][1];
+            
+        }
+
+
+        //compute normal vector (cross product of partial derivatives)
+        FieldVector<RT,3> surfaceNormal(0);
+
+        FieldVector<RT,3> partialX = {discreteGradient[0][0], discreteGradient[1][0], discreteGradient[2][0]};
+        FieldVector<RT,3> partialY = {discreteGradient[0][1], discreteGradient[1][1], discreteGradient[2][1]};
+
+        auto normX = partialX.two_norm();
+        auto normY = partialY.two_norm();
+
+        // Normalize
+        // partialX /= normX;
+        // partialY /= normY;
+
+
+        surfaceNormal[0] = partialX[1]*partialY[2] - partialX[2]*partialY[1];
+        surfaceNormal[1] = partialX[2]*partialY[0] - partialX[0]*partialY[2];
+        surfaceNormal[2] = partialX[0]*partialY[1] - partialX[1]*partialY[0];
+        // printvector(std::cout, surfaceNormal, "surfaceNormal", "--");
+        // printvector(std::cout, surfaceNormal.two_norm(), "surfaceNormal.two_norm()", "--");
+
+        // RT surfaceNormalMag = sqrt(surfaceNormal[0]*surfaceNormal[0] + surfaceNormal[1]*surfaceNormal[1] + surfaceNormal[2]*surfaceNormal[2]);
+        // std::cout << "surfaceNormalMag: " << surfaceNormalMag << std::endl;
+
+
+        FieldMatrix<RT,2,2> secondFF(0);
+
+        for(size_t m=0; m<2; m++)
+        for(size_t n=0; n<2; n++)
+        for(size_t k=0; k<3; k++) 
+        {
+          secondFF[m][n] += surfaceNormal[k]*discreteHessian[k][n][m];
+          //Test: transposed version 
+          // secondFF[m][n] += discreteHessian[k][m][n]*surfaceNormal[k];
+          // secondFF[0][0] += surfaceNormal[k]*discreteHessian[k][0][0];
+          // secondFF[0][1] += surfaceNormal[k]*discreteHessian[k][1][0];
+          // secondFF[1][0] += surfaceNormal[k]*discreteHessian[k][0][1];
+          // secondFF[1][1] += surfaceNormal[k]*discreteHessian[k][1][1];
+        }
+
+        // substract effective prestrain 
+        // G = G + Beff; 
+
+        //Take symmetric part? 
+        // auto symG = 0.5*(G.transposed() + G);
+
+
+
+
+        // printmatrix(std::cout, G , "matrix G: ", "--");
+        // printmatrix(std::cout, symG , "matrix symG: ", "--");
+
+        // std::cout << " discreteHessian.frobenius_norm2(): " << discreteHessian.frobenius_norm2() << std::endl;
+        // std::cout << " G.frobenius_norm2() : " << G.frobenius_norm2() << std::endl;
+        // std::cout << " DIFFERENCE : " << G.frobenius_norm2()- discreteHessian.frobenius_norm2() << std::endl;
+
+        /**
+         * @brief Compute squared Frobenius norm of the discrete Hessian
+         */
+        // auto quadResult = discreteHessian.frobenius_norm2();
+        // std::cout << "quadResult: " << weight*quadResult << std::endl;
+        // auto weight = geometry.volume()/3.0 * element.geometry().integrationElement(geometry.local(geometry.corner(c)));
+
+        // auto weight = geometry.volume()/3.0;
+
+        // std::cout << "geometry.volume()/3.0 : " << geometry.volume()/3.0 << std::endl;
+
+        // we need to use the surface area of the reference element (which is 1/2)
+        // std::cout << "geometry.volume(): " << geometry.volume() << std::endl;
+        // auto weight = (1.0/6.0) * element.geometry().integrationElement(geometry.local(geometry.corner(c)));
+        auto weight = quadPoint.weight() * element.geometry().integrationElement(quadPoint.position());
+        // std::cout << "weight: " << weight << std::endl;
+
+        // harmonicEnergy += weight * discreteHessian.frobenius_norm2();
+        // harmonicEnergy += weight * symG.frobenius_norm2();
+
+        // auto term1 = 0.5 *  weight * discreteHessian.frobenius_norm2();
+        auto term1 = 0.5 *  weight * secondFF.frobenius_norm2();
+
+        RT term2 = 0.0;
+
+        for(size_t i=0; i<2; i++)
+        for(size_t j=0; j<2; j++)
+        {
+          term2 += weight * secondFF[i][j] * Beff[i][j];
+        }
+
+        auto term3 = 0.5 * weight* Beff.frobenius_norm2();           
+
+        // std::cout << "term1: " << term1 << std::endl;
+        // std::cout << "term2: " << term2 << std::endl;
+        // std::cout << "term3: " << term3 << std::endl;
+        // std::cout << "term1 - term2 + term3: " << term1 - term2 + term3 << std::endl;
+
+        // harmonicEnergy +=    weight *  G.frobenius_norm2();
+        harmonicEnergy +=   term1 - term2 + term3;     //eigentlich muss man term2 abziehen bei | II - Z | 
+
+        // std::cout << "harmonicEnergy: " << harmonicEnergy << std::endl;
+      }
+      #endif
+
+
+      /**
+       * @brief Compute contribution of the force Term
+       * 
+       * Integrate the scalar product of the force 'f' 
+       * with the local deformation function 'localFunction_'
+       * over the current element.
+       */
+      RT forceTermEnergy = 0;
+
+      if (parameterSet_.get<bool>("assemble_force_term", 1))
+      {
+        for (auto&& quadPoint : quadRule)
+        {
+            auto deformationValue = localFunction_.evaluate(quadPoint.position());
+            auto forceValue = localForce_(quadPoint.position());
+            // printvector(std::cout, deformationValue.globalCoordinates(), "deformationValue", "--");
+            // printvector(std::cout, forceValue, "forceValue", "--");
+            // const auto jacobian = geometry.jacobianInverseTransposed(quadPoint.position());
+            auto weight = quadPoint.weight() * element.geometry().integrationElement(quadPoint.position());
+            forceTermEnergy += deformationValue.globalCoordinates() * forceValue * weight;
+            // std::cout << "forceTermEnergy:" << forceTermEnergy << std::endl;
+        }
+      }
+    
+      return harmonicEnergy - forceTermEnergy;
+    }
+
+  protected:
+    LocalDiscreteKirchhoffFunction& localFunction_;
+
+    LocalForce& localForce_;
+
+    P2LocalFiniteElement lagrangeLFE_;
+
+    const Dune::ParameterTree parameterSet_;
+
+    // PrestrainType Beff_;
+    // Dune::FieldMatrix<RT,3,3> Qhom_;
+    MatrixType Qhom_;
+    PrestrainType Beff_;
+
+    Python::Module module_;
+
+    // const PrestrainType& prestrain_;
+    // const MatrixType& quadraticForm_;
+  };
+
+
+
+}  // namespace Dune::GFE
+#endif
\ No newline at end of file
diff --git a/dune/microstructure/energies/discretekirchhoffbendingenergyprestrained_debug.hh b/dune/microstructure/energies/discretekirchhoffbendingenergyprestrained_debug.hh
new file mode 100644
index 0000000000000000000000000000000000000000..c6c5091307d64b0c7902b242a0732bdae9dfd733
--- /dev/null
+++ b/dune/microstructure/energies/discretekirchhoffbendingenergyprestrained_debug.hh
@@ -0,0 +1,950 @@
+#ifndef DUNE_GFE_ENERGIES_DISCRETEKIRCHHOFFBENDINGENERGYPRESTRAINED_HH
+#define DUNE_GFE_ENERGIES_DISCRETEKIRCHHOFFBENDINGENERGYPRESTRAINED_HH
+
+#include <dune/common/fmatrix.hh>
+#include <dune/geometry/quadraturerules.hh>
+
+#include <dune/gfe/assemblers/localenergy.hh>
+#include <dune/gfe/bendingisometryhelper.hh>
+#include <dune/gfe/tensor3.hh>
+
+#include <dune/localfunctions/lagrange/lagrangesimplex.hh>
+
+#include <cmath>
+/** 
+ * \brief Assemble the discrete Kirchhoff bending energy for a single element. 
+ * 
+ *  The Kirchhoff bending energy consists of two parts: 
+ * 
+ *  1. The energy of  Qhom(II - Beff) where II is the second fundamental form of the surface parametrized by the deformation function 
+ *     and Beff is a (given) effective prestrain tensor. 
+ * 
+ *     This contribution is split intro three parts which corresponds to the binomial formula (a+b)^2 = a^2 + 2ab + b^2
+ *     each term is discretized separately.
+ * 
+ *  2. An integral over the scalar product of a forcing term and the discrete deformation 
+ *  (i.e. the evaluation of localFunction_ ).
+ */
+namespace Dune::GFE
+{
+  template<class Basis, class LocalDiscreteKirchhoffFunction, class LocalForce, class TargetSpace>
+  class DiscreteKirchhoffBendingEnergyPrestrained
+    : public Dune::GFE::LocalEnergy<Basis,TargetSpace>
+  {
+    // grid types
+    typedef typename Basis::GridView GridView;
+    typedef typename GridView::ctype DT;
+    typedef typename TargetSpace::ctype RT;
+    typedef typename LocalDiscreteKirchhoffFunction::DerivativeType DerivativeType;
+    typedef typename Dune::FieldMatrix<RT,2,2> PrestrainType;
+    typedef typename Dune::FieldMatrix<RT,3,3> MatrixType;
+    // Grid dimension
+    constexpr static int gridDim = GridView::dimension;
+    // P2-LocalFiniteElement used to represent the discrete Jacobian on the current element.
+    typedef typename Dune::LagrangeSimplexLocalFiniteElement<DT, double, gridDim, 2> P2LocalFiniteElement;
+
+  public:
+    DiscreteKirchhoffBendingEnergyPrestrained(LocalDiscreteKirchhoffFunction &localFunction,
+                                   LocalForce &localForce,
+                                   const Dune::ParameterTree& parameterSet)
+        : localFunction_(localFunction),
+          localForce_(localForce),
+          parameterSet_(parameterSet)
+    {}
+
+
+    /** \brief Assemble the energy for a single element */
+    virtual RT energy (const typename Basis::LocalView& localView,         
+               const  std::vector<TargetSpace>& localSolution) const       
+    {
+      RT energy = 0;
+
+      /**
+       * @brief Get Prestrain Tensor
+       */
+      // Dune::FieldMatrix<RT,2,2> Beff = prestrain_;
+
+      /**
+       * @brief Get effective quadratic form
+       */
+      // MatrixType Qhom = quadraticForm_;
+
+
+        /**
+       * @brief Get effective prestrain Tensor
+       */
+      Dune::FieldVector<RT,3> Beffvec = parameterSet_.get<Dune::FieldVector<RT,3>>("effectivePrestrain", {0.0, 0.0, 0.0});
+      Dune::FieldMatrix<RT,2,2> Beff = {{Beffvec[0], Beffvec[2]}, {Beffvec[2], Beffvec[1]} };
+      // printmatrix(std::cout, Beff, "effective prestrain (Beff): ", "--");
+
+
+      /**
+       * @brief Get effective quadratic form Qhom
+       * 
+       *  input-vector: [q_1,q_2,q_3,q_12,q_13,q_23]
+       *  is assembled into a matrix where the off-diagonal entries are divided by 2 (compare with definition in the paper)
+       *            (   q_1    , 0.5*q_12  ,  0.5*q_13 )
+       *     Q =    ( 0.5*q_12 ,   q_2     ,  0.5*q_23 )
+       *            ( 0.5*q_13 , 0.5*q_23  ,    q_3    )
+       */
+      Dune::FieldVector<RT,6> Qhomvec = parameterSet_.get<Dune::FieldVector<RT,6>>("effectiveQuadraticForm", {1.0, 1.0, 1.0, 0.0, 0.0, 0.0});
+      MatrixType Qhom = {{Qhomvec[0]    , 0.5*Qhomvec[3], 0.5*Qhomvec[4]}, 
+                         {0.5*Qhomvec[3],     Qhomvec[1], 0.5*Qhomvec[5]},
+                         {0.5*Qhomvec[4], 0.5*Qhomvec[5],     Qhomvec[2]}};
+      // printmatrix(std::cout, Qhom, "effective quadratic form (Qhom): ", "--");
+
+
+
+
+      bool PRINT_DEBUG = 0;
+
+
+#if 1
+      // TODO: More serious order selection
+      int quadOrder = 3;
+      // int quadOrder = 6;
+#else
+      if (localFiniteElement.localBasis().order()==1)
+        quadOrder = 2;
+      else
+        quadOrder = (localFiniteElement.type().isSimplex()) ? (localFiniteElement.localBasis().order() - 1) * 2
+                                                            : (localFiniteElement.localBasis().order() * gridDim - 1) * 2;
+#endif
+      
+      const auto element = localView.element();
+      auto geometry = element.geometry();
+      auto gridView = localFunction_.gridView();
+      const auto &indexSet = gridView.indexSet();
+
+      // bind to current element.
+      localFunction_.bind(element);
+      localForce_.bind(element);
+      /**
+       * @brief We need to update the Coefficients of localFunction_
+       *        on the current element.
+       */
+      localFunction_.updateLocalCoefficients(localSolution,element);
+
+
+
+      // std::cout << " -------------------------------------------- " << std::endl;
+      // std::cout <<"ELEMENT NUMBER( indexSet.index(element)) ):" << indexSet.index(element) << std::endl;
+      if(PRINT_DEBUG)
+      {
+      std::cout << "geometry.corner(0): " << geometry.corner(0) << std::endl;
+      std::cout << "geometry.corner(1)): " << geometry.corner(1) << std::endl;
+      std::cout << "geometry.corner(2): " << geometry.corner(2) << std::endl;
+      }
+
+
+      /**
+       * @brief  Get Coefficients of the discrete Jacobian 
+       * 
+       * The discrete Jacobian is a special linear combination represented in a [P2]^2 - (Lagrange) space
+       * The coefficients of this linear combination correspond to certain linear combinations of the Jacobians of localfunction_ .
+       * The coefficients are stored in the form [Basisfunctions x components x gridDim]
+       * in a BlockVector<FieldMatrix<RT, 3, gridDim>> .
+       */
+      BlockVector<FieldMatrix<RT, 3, gridDim>> discreteJacobianCoefficients;
+      discreteGradientCoefficients(discreteJacobianCoefficients,lagrangeLFE_,localFunction_,element);
+    
+    
+    
+  
+
+      /**
+       * @brief Compute harmonic energy contribution:
+       */
+      RT harmonicEnergy = 0;
+
+      
+
+      //VERSION - 1
+
+      #if 0
+      /**
+       * @brief Setup Quadrature rule. 
+       * 
+       */
+      // Gauss-Quadrature:
+      const auto &quadRule = QuadratureRules<double, gridDim>::rule(lagrangeLFE_.type(), quadOrder);
+      // Trapezoidal-rule:
+      // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} };
+      // Trapezoidal-rule + evaluation on edge centers (only for testing purposes):
+      // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{0.5,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,0.5}, 1.0/6.0}, {{0.5,0.5}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} };
+      for (auto&& quadPoint : quadRule)
+      {
+        //Get values of the P2-Basis functions on current quadrature point
+        std::vector<FieldVector<double,1>> basisValues;
+        lagrangeLFE_.localBasis().evaluateFunction(quadPoint.position(), basisValues);
+
+        // if(PRINT_DEBUG)
+        // {
+        // std::cout << "- * - * - * - * - * - *" << std::endl;
+        // std::cout << "quadPoint.position():" << quadPoint.position() << std::endl;
+        // std::cout << "geometry.global(quadPoint.position()): " << geometry.global(quadPoint.position()) << std::endl;
+        // }
+
+        // Get Jacobians of the P2-Basis functions on current quadrature point
+        std::vector<FieldMatrix<double, 1, gridDim>> referenceGradients;
+
+        lagrangeLFE_.localBasis().evaluateJacobian(quadPoint.position(), referenceGradients);
+        const auto jacobian = geometry.jacobianInverseTransposed(quadPoint.position());
+        const auto integrationElement = geometry.integrationElement(quadPoint.position());
+        // printmatrix(std::cout, jacobian , "jacobian : ", "--");
+
+        std::vector<FieldVector<RT, gridDim>> gradients(referenceGradients.size());
+        for (size_t i = 0; i<gradients.size(); i++)
+          jacobian.mv(referenceGradients[i][0], gradients[i]);
+
+
+        //TEST: Do not transform P2 basis
+        // std::vector<FieldMatrix<double, 1, gridDim>> gradients;
+        // lagrangeLFE_.localBasis().evaluateJacobian(quadPoint.position(), gradients);
+
+
+        Tensor3<RT,3,2,2> discreteHessian(0); 
+        FieldMatrix<RT, 3, gridDim> discreteGradient(0);
+
+
+      /**
+       * @brief Compute the discrete Hessian and discrete Gradient as a linear combination of 
+       * function and gradient evaluations of the P2-basis functions with the coefficients given 
+       * by 'discreteJacobianCoefficients'. 
+       * Since the deformation function has k=3 components we get 
+       * - discreteGradient : 3x2   matrix
+       * - discreteHessian:   3x2x2 tensor
+       */
+        for (int k=0; k<3; k++)
+        for (int l=0; l<gridDim; l++)
+        for(std::size_t i=0; i<lagrangeLFE_.size(); i++)
+        {
+            // Compute discrete gradient
+            discreteGradient[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues[i];
+            // Compute discrete Hessian
+            discreteHessian[k][l][0]  += discreteJacobianCoefficients[i][k][l]*gradients[i][0];
+            discreteHessian[k][l][1]  += discreteJacobianCoefficients[i][k][l]*gradients[i][1];
+            // discreteHessian[k][l][0]  += discreteJacobianCoefficients[i][k][l]*gradients[i][0][0];
+            // discreteHessian[k][l][1]  += discreteJacobianCoefficients[i][k][l]*gradients[i][0][1];
+        }
+
+
+        // DerivativeType whJacobianValue = localFunction_.evaluateDerivative(quadPoint.position());
+
+        // Check difference in discrete gradients:
+        // printmatrix(std::cout, localFunction_.evaluateDerivative(quadPoint.position()) , "localFunction_.evaluateDerivative(quadPoint.position()): ", "--");
+        // printmatrix(std::cout, discreteGradient, "discreteGradient: ", "--");
+
+        // printmatrix(std::cout, discreteGradient-localFunction_.evaluateDerivative(quadPoint.position()) , "gradient difference: ", "--");
+
+
+        //
+       
+
+
+
+        /**
+         * @brief Check if isometry constraint is satisfied (at the current quadrature point).
+         *        This should at least be satisfied on the nodes of the triangulation.
+         */
+        // FieldMatrix<RT, 2,2> isometryConstraint(0);
+        // for(size_t k=0; k<3; k++)
+        // for(size_t l=0; l<2; l++)
+        // for(size_t i=0; i<2; i++)
+        // {
+        //     isometryConstraint[l][i] += discreteGradient[k][l]*discreteGradient[k][i];
+        // }
+        // printmatrix(std::cout, isometryConstraint, "isometryConstraint: ", "--");
+
+
+
+
+
+        // if(PRINT_DEBUG)
+        // {
+          /**
+           * @brief print the (two) different 3x2 slices of the discrete Hessian
+           */
+        FieldMatrix<RT, 3, 2> discreteHessian_slice1(0);
+        FieldMatrix<RT, 3, 2> discreteHessian_slice2(0);
+        for (int k=0; k<3; k++)
+        for (int l=0; l<gridDim; l++)
+        {
+            discreteHessian_slice1[k][l] = discreteHessian[k][l][0];
+            discreteHessian_slice2[k][l] = discreteHessian[k][l][1];
+        }
+        //  printmatrix(std::cout, discreteHessian_slice1, "discreteHessian_slice1: ", "--");
+        //  printmatrix(std::cout, discreteHessian_slice2, "discreteHessian_slice2: ", "--");
+        // }
+
+
+        /**
+         * @brief Test: evaluate the deformation function and gradient at the current quadrature point.
+         */
+        //  auto test1= localFunction_.evaluateDerivative(quadPoint.position());
+        //  auto test2= localFunction_.evaluate(quadPoint.position()).globalCoordinates();
+
+
+
+        /**
+         * @brief Compute the surface normal given by the cross-product of the two different partial derivatives 
+         *        of the discrete gradient.
+         *        This is needed to compute the second fundamental form.
+         */
+        FieldVector<RT,3> surfaceNormal(0);
+        FieldVector<RT,3> partialX = {discreteGradient[0][0], discreteGradient[1][0], discreteGradient[2][0]};
+        FieldVector<RT,3> partialY = {discreteGradient[0][1], discreteGradient[1][1], discreteGradient[2][1]};
+
+        auto normX = partialX.two_norm();
+        auto normY = partialY.two_norm();
+
+        /**
+         * @brief Test: normalize 
+         */
+        // partialX /= normX;
+        // partialY /= normY;
+
+        surfaceNormal[0] = partialX[1]*partialY[2] - partialX[2]*partialY[1];
+        surfaceNormal[1] = partialX[2]*partialY[0] - partialX[0]*partialY[2];
+        surfaceNormal[2] = partialX[0]*partialY[1] - partialX[1]*partialY[0];
+        // printvector(std::cout, surfaceNormal, "surfaceNormal", "--");
+        // std::cout << "surfaceNormal.two_norm() : " << surfaceNormal.two_norm() << std::endl;
+
+        // surfaceNormal *= -1.0;
+ 
+        /**
+         * @brief Test: normalize 
+         */
+        // auto norm = surfaceNormal.two_norm();
+        // surfaceNormal /= norm;
+        // printvector(std::cout, surfaceNormal, "surfaceNormal", "--");
+
+
+        /**
+         * @brief Compute the second fundamental form. This is a 2x2 matrix.
+         */
+        FieldMatrix<RT,2,2> secondFF(0);
+
+        for(size_t m=0; m<2; m++)
+        for(size_t n=0; n<2; n++)
+        for(size_t k=0; k<3; k++) 
+        {
+          secondFF[m][n] += surfaceNormal[k]*discreteHessian[k][n][m];
+
+
+          //Test: transposed version 
+          // secondFF[m][n] += discreteHessian[k][m][n]*surfaceNormal[k];
+          // secondFF[0][0] += surfaceNormal[k]*discreteHessian[k][0][0];
+          // secondFF[0][1] += surfaceNormal[k]*discreteHessian[k][1][0];
+          // secondFF[1][0] += surfaceNormal[k]*discreteHessian[k][0][1];
+          // secondFF[1][1] += surfaceNormal[k]*discreteHessian[k][1][1];
+        }
+        // printmatrix(std::cout, secondFF , "secondFF: ", "--");
+
+
+        /**
+         * @brief Check orthogonality between discrete Hessian and discrete gradient 
+         *        at nodes.
+         */
+        // std::cout << "---- ORTHOGONALITY CHECK 1: ----" << std::endl;
+        // for(int i=0; i<2; i++)
+        // for(int j=0; j<2; j++)
+        // for(int l=0; l<2; l++)
+        // {
+        //   RT test = 0.0;
+        //   for(int k=0; k<3; k++)
+        //   {
+        //     test += discreteHessian[k][j][i] * discreteGradient[k][l];
+        //     // test += discreteHessian[k][i][j] * discreteGradient[k][l];
+        //   }
+        //   std::cout << "Partial_" << i << j << "U * Partial_" << l << "U = " << test << std::endl;
+        // }
+
+
+        /**
+         * @brief Print the (discrete) second partial derivatives.
+         */
+        // for(int i=0; i<2; i++)
+        // for(int j=0; j<2; j++)
+        // {
+        //   FieldVector<RT,3> partialTMP(0);
+        //   for(int k=0; k<3; k++)
+        //   {
+        //         partialTMP[k] = discreteHessian[k][j][i];
+        //   }
+        //  std::cout << "Partial_" << i << j << "U = " << std::endl;
+
+        //  printvector(std::cout , partialTMP, "PartialTMP:", "--");
+        // }
+
+        /**
+         * @brief Check if Norm-identity holds
+         */
+        // std::cout << "---- ORTHOGONALITY CHECK 2: ----" << std::endl;
+        // for(int i=0; i<2; i++)
+        // for(int j=0; j<2; j++)
+        // {
+        //   RT secondPartialDerNorm = 0.0;
+        //   RT secondPartialDerNorm_normalPart = 0.0;
+
+        //   for(int k=0; k<3; k++)
+        //   {
+        //     secondPartialDerNorm += discreteHessian[k][j][i] * discreteHessian[k][j][i];
+        //     secondPartialDerNorm_normalPart += (discreteHessian[k][j][i] * surfaceNormal[k]) * (discreteHessian[k][j][i] * surfaceNormal[k]);
+        //     // secondPartialDerNorm += discreteHessian[k][i][j] * discreteHessian[k][i][j];
+        //     // secondPartialDerNorm_normalPart += (discreteHessian[k][i][j] * surfaceNormal[k]) * (discreteHessian[k][i][j] * surfaceNormal[k]);
+        //   }
+        //   std::cout << "secondPartialDerNorm (" << i << j << ") = " << secondPartialDerNorm  << std::endl;
+        //   std::cout << "secondPartialDerNorm_normalPart (" << i << j << ") = " << secondPartialDerNorm_normalPart  << std::endl;
+        // }
+
+
+        /**
+         * @brief Subtract the effective prestrain
+         */
+        auto G = secondFF - Beff; 
+
+
+        // auto symG = 0.5*(G.transposed() + G);
+        // printmatrix(std::cout, G , "matrix G: ", "--");
+        // printmatrix(std::cout, symG , "matrix symG: ", "--");
+
+
+
+        // auto weight = (1.0/6.0) * element.geometry().integrationElement(quadPoint.position());
+        auto weight = quadPoint.weight() * element.geometry().integrationElement(quadPoint.position());
+
+        /**
+         * @brief TEST: Check the difference between the squared Frobenius norm of the 
+         *              second fundamental form and discrete Hessian.
+         *              (Note that for isometries, these should be equal.)
+         */
+        // auto DIFFERENCE = secondFF.frobenius_norm2() - discreteHessian.frobenius_norm2();
+        // if (abs(DIFFERENCE)>1e-1)
+        // {
+        //   std::cout << " discreteHessian.frobenius_norm2(): " << discreteHessian.frobenius_norm2() << std::endl;
+        //   std::cout << " secondFF.frobenius_norm2() : " << secondFF.frobenius_norm2() << std::endl;
+        //   std::cout << " DIFFERENCE : " << secondFF.frobenius_norm2() - discreteHessian.frobenius_norm2() << std::endl;
+        //   printmatrix(std::cout, secondFF , "secondFF: ", "--");
+        //   std::cout << "G.frobenius_norm2(): " << G.frobenius_norm2() << std::endl;
+        //   printmatrix(std::cout, isometryConstraint, "isometryConstraint: ", "--");
+
+        //   printvector(std::cout, surfaceNormal, "surfaceNormal", "--");
+        //  printmatrix(std::cout, discreteHessian_slice1, "discreteHessian_slice1: ", "--");
+        //  printmatrix(std::cout, discreteHessian_slice2, "discreteHessian_slice2: ", "--");
+
+        //   //compare with discretization that used binomial formula (a-b)^2 = a^2 - 2ab + b^2
+        //   auto term1 = 0.5 *  weight * discreteHessian.frobenius_norm2();
+        //   RT term2 = 0.0;
+        //   for(size_t i=0; i<2; i++)
+        //   for(size_t j=0; j<2; j++)
+        //   {
+        //     term2 += weight * secondFF[i][j] * Beff[i][j];
+        //   }
+        //   auto term3 = 0.5 * weight * Beff.frobenius_norm2();  
+        //   std::cout << "term1-term2+term3 :" << term1-term2+term3 << std::endl;
+        // }
+
+        /**
+         * @brief Compute harmonic energy contribution of the current quadrature point.
+         */
+        harmonicEnergy += 0.5 * weight * G.frobenius_norm2();
+        // std::cout << "harmonicEnergy: " << harmonicEnergy << std::endl;
+      }
+      #endif
+
+
+      /**
+       * @brief Debugging Tests
+       */
+      // std::cout << "Auswertung auf Kantenmitte: " << std::endl;
+      // auto edge1Geometry = element.template subEntity<1>(0).geometry();
+      // auto edge1Entity = element.template subEntity<1>(0);
+      // auto edge2Geometry = element.template subEntity<1>(1).geometry();
+      // auto edge2Entity = element.template subEntity<1>(1);
+      // auto edge3Geometry = element.template subEntity<1>(2).geometry();
+      // auto edge3Entity = element.template subEntity<1>(2);
+
+      // auto edge1Center = edge1Geometry.center();
+      // auto edge2Center = edge2Geometry.center();
+      // auto edge3Center = edge3Geometry.center();
+
+      // std::cout << "edge1Center: " << edge1Center << std::endl;
+      // std::cout << "edge2Center: " << edge2Center << std::endl;
+      // std::cout << "edge3Center: " << edge3Center << std::endl;
+
+      // std::cout << "geometry.local(edge1Center):" << geometry.local(edge1Center) << std::endl;
+      // std::cout << "geometry.local(edge2Center):" << geometry.local(edge2Center) << std::endl;
+      // std::cout << "geometry.local(edge3Center):" << geometry.local(edge3Center) << std::endl;
+      // // std::cout << "geometry.global({0.5,0.0}): "<< geometry.global({0.5,0.0}) << std::endl;
+      // // std::cout << "geometry.global({0.5,0.5}): "<< geometry.global({0.5,0.5}) << std::endl;
+      // // std::cout << "geometry.global({0.0,0.5}): "<< geometry.global({0.0,0.5}) << std::endl;
+      // std::vector<FieldVector<double,1>> basisValues_edge1;
+      // std::vector<FieldVector<double,1>> basisValues_edge2;
+      // std::vector<FieldVector<double,1>> basisValues_edge3;
+      // // lagrangeLFE_.localBasis().evaluateFunction({0.5,0.0}, basisValues_edge1);
+      // // lagrangeLFE_.localBasis().evaluateFunction({0.5,0.5}, basisValues_edge2);
+      // // lagrangeLFE_.localBasis().evaluateFunction({0.0,0.5}, basisValues_edge3);
+      // lagrangeLFE_.localBasis().evaluateFunction(geometry.local(edge1Center), basisValues_edge1);
+      // lagrangeLFE_.localBasis().evaluateFunction(geometry.local(edge2Center), basisValues_edge2);
+      // lagrangeLFE_.localBasis().evaluateFunction(geometry.local(edge3Center), basisValues_edge3);
+      // //TEST VERTICES
+      // // lagrangeLFE_.localBasis().evaluateFunction({0.0,0.0}, basisValues_edge1);
+      // // lagrangeLFE_.localBasis().evaluateFunction({1.0,0.0}, basisValues_edge2);
+      // // lagrangeLFE_.localBasis().evaluateFunction({0.0,1.0}, basisValues_edge3);
+
+      // std::cout << "------ print P2-Basis evaluation -----" << std::endl;
+      // for(std::size_t i=0; i<lagrangeLFE_.size(); i++)
+      // {
+      //   std::cout << i << "-th P2-basis function: " << std::endl; 
+      //   printvector(std::cout, basisValues_edge1[i]  , "basisValues_edge1[i]  ", "--");
+      // }
+      // for(std::size_t i=0; i<lagrangeLFE_.size(); i++)
+      // {
+      //   std::cout << i << "-th P2-basis function: " << std::endl; 
+      //   printvector(std::cout, basisValues_edge2[i]  , "basisValues_edge2[i]  ", "--");
+      // }
+      // for(std::size_t i=0; i<lagrangeLFE_.size(); i++)
+      // {
+      //   std::cout << i << "-th P2-basis function: " << std::endl; 
+      //   printvector(std::cout, basisValues_edge3[i]  , "basisValues_edge3[i]  ", "--");
+      // }
+
+      // FieldMatrix<RT, 3, gridDim> discreteGradient_edge1(0);
+      // FieldMatrix<RT, 3, gridDim> discreteGradient_edge2(0);
+      // FieldMatrix<RT, 3, gridDim> discreteGradient_edge3(0);
+
+      // for (int k=0; k<3; k++)
+      // for (int l=0; l<gridDim; l++)
+      // for(std::size_t i=0; i<lagrangeLFE_.size(); i++)
+      // {
+      //     discreteGradient_edge1[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues_edge1[i];
+      //     discreteGradient_edge2[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues_edge2[i];
+      //     discreteGradient_edge3[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues_edge3[i];
+      // }
+
+      // printmatrix(std::cout, discreteGradient_edge1, "discreteGradient_edge1: ", "--");
+      // printmatrix(std::cout, discreteGradient_edge2, "discreteGradient_edge2: ", "--");
+      // printmatrix(std::cout, discreteGradient_edge3, "discreteGradient_edge3: ", "--");
+      // std::cout << "sin(edge1Center[0]): " << sin(edge1Center[0]) << std::endl;
+      // std::cout << "cos(edge1Center[0]): " << cos(edge1Center[0]) << std::endl;
+      // std::cout << "sin(edge2Center[0]): " << sin(edge2Center[0]) << std::endl;
+      // std::cout << "cos(edge2Center[0]): " << cos(edge2Center[0]) << std::endl;
+      // std::cout << "sin(edge3Center[0]): " << sin(edge3Center[0]) << std::endl;
+      // std::cout << "cos(edge3Center[0]): " << cos(edge3Center[0]) << std::endl;
+      // // std::cout << "sin(geometry.global({0.5,0.0})[0]): " << sin(geometry.global({0.5,0.0})[0]) << std::endl;
+      // // std::cout << "cos(geometry.global({0.5,0.0})[0]): " << cos(geometry.global({0.5,0.0})[0]) << std::endl;
+      // // std::cout << "sin(geometry.global({0.5,0.5})[0]): " << sin(geometry.global({0.5,0.5})[0]) << std::endl;
+      // // std::cout << "cos(geometry.global({0.5,0.5})[0]): " << cos(geometry.global({0.5,0.5})[0]) << std::endl;
+      // // std::cout << "sin(geometry.global({0.0,0.5})[0]): " << sin(geometry.global({0.0,0.5})[0]) << std::endl;
+      // // std::cout << "cos(geometry.global({0.0,0.5})[0]): " << cos(geometry.global({0.0,0.5})[0]) << std::endl;
+      // // TEST VERTICES 
+      // // std::cout << "sin(geometry.global({0.0,0.0})[0]): " << sin(geometry.global({0.0,0.0})[0]) << std::endl;
+      // // std::cout << "cos(geometry.global({0.0,0.0})[0]): " << cos(geometry.global({0.0,0.0})[0]) << std::endl;
+      // // std::cout << "sin(geometry.global({1.0,0.0})[0]): " << sin(geometry.global({1.0,0.0})[0]) << std::endl;
+      // // std::cout << "cos(geometry.global({1.0,0.0})[0]): " << cos(geometry.global({1.0,0.0})[0]) << std::endl;
+      // // std::cout << "sin(geometry.global({0.0,1.0})[0]): " << sin(geometry.global({0.0,1.0})[0]) << std::endl;
+      // // std::cout << "cos(geometry.global({0.0,1.0})[0]): " << cos(geometry.global({0.0,1.0})[0]) << std::endl;
+      // exit(0);
+      // if(indexSet.index(element)==1)
+      // exit(0);
+
+
+      // #if 0 
+      /**
+       * @brief VERSION - 2 : Mixed version using the binomal formula (a-b)^2 = a^2 - 2ab + b^2 
+       *                      for | II - Beff |^2 and discretize every term individually. 
+       */
+      // Gauss-Quadrature:
+      const auto &quadRule = QuadratureRules<double, gridDim>::rule(lagrangeLFE_.type(), quadOrder);
+      // Trapezoidal-rule:
+      // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} };
+      // Trapezoidal-rule + evaluation on edge centers (only for testing purposes):
+      // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{0.5,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,0.5}, 1.0/6.0}, {{0.5,0.5}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} };
+      for (auto&& quadPoint : quadRule)
+      {
+
+        //Get values of the P2-Basis functions on current quadrature point
+        std::vector<FieldVector<double,1>> basisValues;
+        lagrangeLFE_.localBasis().evaluateFunction(quadPoint.position(), basisValues);
+
+
+        // Get Jacobians of the P2-Basis functions on current quadrature point
+        std::vector<FieldMatrix<double, 1, gridDim>> referenceGradients;
+
+        lagrangeLFE_.localBasis().evaluateJacobian(quadPoint.position(), referenceGradients);
+        const auto jacobian = geometry.jacobianInverseTransposed(quadPoint.position());
+        const auto integrationElement = geometry.integrationElement(quadPoint.position());
+
+        std::vector<FieldVector<RT, gridDim>> gradients(referenceGradients.size());
+        for (size_t i = 0; i<gradients.size(); i++)
+          jacobian.mv(referenceGradients[i][0], gradients[i]);
+
+
+        Tensor3<RT,3,2,2> discreteHessian(0); 
+        FieldMatrix<RT, 3, gridDim> discreteGradient(0);
+
+        for (int k=0; k<3; k++)
+        for (int l=0; l<gridDim; l++)
+        for(std::size_t i=0; i<lagrangeLFE_.size(); i++)
+        {
+            discreteGradient[k][l]    += discreteJacobianCoefficients[i][k][l]*basisValues[i];
+            discreteHessian[k][l][0]  += discreteJacobianCoefficients[i][k][l]*gradients[i][0];
+            discreteHessian[k][l][1]  += discreteJacobianCoefficients[i][k][l]*gradients[i][1];
+            
+        }
+      
+        /**
+           * @brief print the (three) 2x2 slices of the discrete Hessian (check for symmetry)
+           */
+        FieldMatrix<RT, 2, 2> discreteHessian_slice1(0);
+        FieldMatrix<RT, 2, 2> discreteHessian_slice2(0);
+        FieldMatrix<RT, 2, 2> discreteHessian_slice3(0);
+
+        for (int i=0; i<2; i++)
+        for (int l=0; l<gridDim; l++)
+        {
+            discreteHessian_slice1[i][l] = discreteHessian[0][i][l];
+            discreteHessian_slice2[i][l] = discreteHessian[1][i][l];
+            discreteHessian_slice3[i][l] = discreteHessian[2][i][l];
+        }
+
+        // printmatrix(std::cout, discreteHessian_slice1, "discreteHessian_slice1: ", "--");
+        // printmatrix(std::cout, discreteHessian_slice2, "discreteHessian_slice2: ", "--");
+        // printmatrix(std::cout, discreteHessian_slice3, "discreteHessian_slice3: ", "--");
+        // printmatrix(std::cout, sym(discreteHessian_slice1), "SYM discreteHessian_slice1: ", "--");
+        // printmatrix(std::cout, sym(discreteHessian_slice2), "SYM discreteHessian_slice2: ", "--");
+        // printmatrix(std::cout, sym(discreteHessian_slice3), "SYM discreteHessian_slice3: ", "--");
+
+
+        //compute normal vector (cross product of partial derivatives)
+        FieldVector<RT,3> surfaceNormal(0);
+
+        FieldVector<RT,3> partialX = {discreteGradient[0][0], discreteGradient[1][0], discreteGradient[2][0]};
+        FieldVector<RT,3> partialY = {discreteGradient[0][1], discreteGradient[1][1], discreteGradient[2][1]};
+
+        auto normX = partialX.two_norm();
+        auto normY = partialY.two_norm();
+
+        // Normalize
+        // partialX /= normX;
+        // partialY /= normY;
+
+
+        surfaceNormal[0] = partialX[1]*partialY[2] - partialX[2]*partialY[1];
+        surfaceNormal[1] = partialX[2]*partialY[0] - partialX[0]*partialY[2];
+        surfaceNormal[2] = partialX[0]*partialY[1] - partialX[1]*partialY[0];
+        // printvector(std::cout, surfaceNormal, "surfaceNormal", "--");
+        // printvector(std::cout, surfaceNormal.two_norm(), "surfaceNormal.two_norm()", "--");
+
+        // RT surfaceNormalMag = sqrt(surfaceNormal[0]*surfaceNormal[0] + surfaceNormal[1]*surfaceNormal[1] + surfaceNormal[2]*surfaceNormal[2]);
+        // std::cout << "surfaceNormalMag: " << surfaceNormalMag << std::endl;
+
+        // FieldMatrix<RT,2,2> G(0);
+        FieldMatrix<RT,2,2> secondFF(0);
+
+        for(size_t m=0; m<2; m++)
+        for(size_t n=0; n<2; n++)
+        for(size_t k=0; k<3; k++) 
+        {
+          secondFF[m][n] += surfaceNormal[k]*discreteHessian[k][n][m];
+        }
+
+        // To get the right sign:
+        secondFF = -1.0*secondFF;
+
+
+        // substract effective prestrain 
+        // G = G + Beff; 
+
+        //Take symmetric part? 
+        // auto symG = 0.5*(G.transposed() + G);
+
+
+
+
+        // printmatrix(std::cout, G , "matrix G: ", "--");
+        // printmatrix(std::cout, symG , "matrix symG: ", "--");
+
+        // std::cout << " discreteHessian.frobenius_norm2(): " << discreteHessian.frobenius_norm2() << std::endl;
+        // std::cout << " G.frobenius_norm2() : " << G.frobenius_norm2() << std::endl;
+        // std::cout << " DIFFERENCE : " << G.frobenius_norm2()- discreteHessian.frobenius_norm2() << std::endl;
+
+        /**
+         * @brief Compute squared Frobenius norm of the discrete Hessian
+         */
+        // auto quadResult = discreteHessian.frobenius_norm2();
+        // std::cout << "quadResult: " << weight*quadResult << std::endl;
+        // auto weight = geometry.volume()/3.0 * element.geometry().integrationElement(geometry.local(geometry.corner(c)));
+
+        // auto weight = geometry.volume()/3.0;
+
+        // std::cout << "geometry.volume()/3.0 : " << geometry.volume()/3.0 << std::endl;
+
+        // we need to use the surface area of the reference element (which is 1/2)
+        // std::cout << "geometry.volume(): " << geometry.volume() << std::endl;
+        // auto weight = (1.0/6.0) * element.geometry().integrationElement(geometry.local(geometry.corner(c)));
+        auto weight = quadPoint.weight() * element.geometry().integrationElement(quadPoint.position());
+        // std::cout << "weight: " << weight << std::endl;
+
+        // harmonicEnergy += weight * discreteHessian.frobenius_norm2();
+        // harmonicEnergy += weight * symG.frobenius_norm2();
+
+        // auto term1 = 0.5 *  weight * discreteHessian.frobenius_norm2();
+        RT term1 = 0.0;
+
+        FieldMatrix<RT,3,3> X = tensorToSymCoefficients(discreteHessian);
+
+        for(int k=0; k<3; k++)
+        {
+          // term1 += Qhom[0][0]*pow((2.0*discreteHessian[k][0][0]),2)+ Qhom[0][1]* ... more efficient (TODO)  Qhom is symmetric
+          term1 += Qhom[0][0]*pow(X[k][0],2)    + Qhom[0][1]*X[k][1]*X[k][0]  + Qhom[0][2]*X[k][2]*X[k][0] 
+                +  Qhom[1][0]*X[k][0]*X[k][1]   + Qhom[1][1]*pow(X[k][1],2)   + Qhom[1][2]*X[k][2]*X[k][1] 
+                +  Qhom[2][0]*X[k][0]*X[k][2]   + Qhom[2][1]*X[k][1]*X[k][2]  + Qhom[2][2]*pow(X[k][2],2);
+        }
+        // term1 = term1 * 0.5 *  weight;
+        term1 = term1 *  weight;
+
+
+
+
+        //TODO : Add method "applyQhom"
+
+
+        // Second Term
+
+        // RT term2 = 0.0;
+        // for(size_t i=0; i<2; i++)
+        // for(size_t j=0; j<2; j++)
+        // {
+        //   term2 += weight * secondFF[i][j] * Beff[i][j];
+        // }
+        
+
+        FieldVector<RT,3> secondFFCoefficients = matrixToSymCoefficients(secondFF);
+        FieldVector<RT,3> BeffCoefficients = matrixToSymCoefficients(Beff);
+
+        RT term2 = 0.0;
+          term2 += Qhom[0][0]*BeffCoefficients[0]*secondFFCoefficients[0] + Qhom[0][1]*BeffCoefficients[1]*secondFFCoefficients[0] + Qhom[0][2]*BeffCoefficients[2]*secondFFCoefficients[0] 
+                +  Qhom[1][0]*BeffCoefficients[0]*secondFFCoefficients[1] + Qhom[1][1]*BeffCoefficients[1]*secondFFCoefficients[1] + Qhom[1][2]*BeffCoefficients[2]*secondFFCoefficients[1] 
+                +  Qhom[2][0]*BeffCoefficients[0]*secondFFCoefficients[2] + Qhom[2][1]*BeffCoefficients[1]*secondFFCoefficients[2] + Qhom[2][2]*BeffCoefficients[2]*secondFFCoefficients[2];
+        term2 = 2.0 * term2 * weight;
+
+
+
+
+
+        // auto term3 = 0.5 * weight* Beff.frobenius_norm2();        
+
+        RT term3 = 0.0;   
+
+        term3 += Qhom[0][0]*BeffCoefficients[0]*BeffCoefficients[0]  + Qhom[0][1]*BeffCoefficients[1]*BeffCoefficients[0] + Qhom[0][2]*BeffCoefficients[2]*BeffCoefficients[0] 
+              +  Qhom[1][0]*BeffCoefficients[0]*BeffCoefficients[1]  + Qhom[1][1]*BeffCoefficients[1]*BeffCoefficients[1] + Qhom[1][2]*BeffCoefficients[2]*BeffCoefficients[1] 
+              +  Qhom[2][0]*BeffCoefficients[0]*BeffCoefficients[2]  + Qhom[2][1]*BeffCoefficients[1]*BeffCoefficients[2] + Qhom[2][2]*BeffCoefficients[2]*BeffCoefficients[2];
+      
+        // term3 = term3 * 0.5 *  weight ;
+        term3 = term3 *  weight ;
+
+        // std::cout << "term1: " << term1 << std::endl;
+        // std::cout << "term2: " << term2 << std::endl;
+        // std::cout << "term3: " << term3 << std::endl;
+        // std::cout << "term1 - term2 + term3: " << term1 - term2 + term3 << std::endl;
+
+        // harmonicEnergy +=    weight *  G.frobenius_norm2();
+        harmonicEnergy +=  term1 - term2 + term3;     //eigentlich muss man term2 abziehen bei | II - Z | 
+
+        // std::cout << "harmonicEnergy: " << harmonicEnergy << std::endl;
+      }
+      // #endif
+
+
+      #if 0
+      /**
+       * @brief VERSION - 3 : Mixed version using the binomal formula (a-b)^2 = a^2 - 2ab + b^2 
+       *                      for | II - Beff |^2 and discretize every term individually. 
+       *                      *But with |II|^2 instead of |D^2y|^2
+       */
+      // Gauss-Quadrature:
+      const auto &quadRule = QuadratureRules<double, gridDim>::rule(lagrangeLFE_.type(), quadOrder);
+      // Trapezoidal-rule:
+      // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} };
+      // Trapezoidal-rule + evaluation on edge centers (only for testing purposes):
+      // std::vector<Dune::QuadraturePoint<double,2>> quadRule = { {{0.0,0.0}, 1.0/6.0}, {{0.5,0.0}, 1.0/6.0}, {{1.0,0.0}, 1.0/6.0}, {{0.0,0.5}, 1.0/6.0}, {{0.5,0.5}, 1.0/6.0}, {{0.0,1.0}, 1.0/6.0} };
+      for (auto&& quadPoint : quadRule)
+      {
+
+        //Get values of the P2-Basis functions on current quadrature point
+        std::vector<FieldVector<double,1>> basisValues;
+        lagrangeLFE_.localBasis().evaluateFunction(quadPoint.position(), basisValues);
+
+
+        // Get Jacobians of the P2-Basis functions on current quadrature point
+        std::vector<FieldMatrix<double, 1, gridDim>> referenceGradients;
+
+        lagrangeLFE_.localBasis().evaluateJacobian(quadPoint.position(), referenceGradients);
+        const auto jacobian = geometry.jacobianInverseTransposed(quadPoint.position());
+        const auto integrationElement = geometry.integrationElement(quadPoint.position());
+
+        std::vector<FieldVector<RT, gridDim>> gradients(referenceGradients.size());
+        for (size_t i = 0; i<gradients.size(); i++)
+          jacobian.mv(referenceGradients[i][0], gradients[i]);
+
+
+        Tensor3<RT,3,2,2> discreteHessian(0); 
+        FieldMatrix<RT, 3, gridDim> discreteGradient(0);
+
+        for (int k=0; k<3; k++)
+        for (int l=0; l<gridDim; l++)
+        for(std::size_t i=0; i<lagrangeLFE_.size(); i++)
+        {
+            discreteGradient[k][l] += discreteJacobianCoefficients[i][k][l]*basisValues[i];
+            discreteHessian[k][l][0]  += discreteJacobianCoefficients[i][k][l]*gradients[i][0];
+            discreteHessian[k][l][1]  += discreteJacobianCoefficients[i][k][l]*gradients[i][1];
+            
+        }
+
+
+        //compute normal vector (cross product of partial derivatives)
+        FieldVector<RT,3> surfaceNormal(0);
+
+        FieldVector<RT,3> partialX = {discreteGradient[0][0], discreteGradient[1][0], discreteGradient[2][0]};
+        FieldVector<RT,3> partialY = {discreteGradient[0][1], discreteGradient[1][1], discreteGradient[2][1]};
+
+        auto normX = partialX.two_norm();
+        auto normY = partialY.two_norm();
+
+        // Normalize
+        // partialX /= normX;
+        // partialY /= normY;
+
+
+        surfaceNormal[0] = partialX[1]*partialY[2] - partialX[2]*partialY[1];
+        surfaceNormal[1] = partialX[2]*partialY[0] - partialX[0]*partialY[2];
+        surfaceNormal[2] = partialX[0]*partialY[1] - partialX[1]*partialY[0];
+        // printvector(std::cout, surfaceNormal, "surfaceNormal", "--");
+        // printvector(std::cout, surfaceNormal.two_norm(), "surfaceNormal.two_norm()", "--");
+
+        // RT surfaceNormalMag = sqrt(surfaceNormal[0]*surfaceNormal[0] + surfaceNormal[1]*surfaceNormal[1] + surfaceNormal[2]*surfaceNormal[2]);
+        // std::cout << "surfaceNormalMag: " << surfaceNormalMag << std::endl;
+
+
+        FieldMatrix<RT,2,2> secondFF(0);
+
+        for(size_t m=0; m<2; m++)
+        for(size_t n=0; n<2; n++)
+        for(size_t k=0; k<3; k++) 
+        {
+          secondFF[m][n] += surfaceNormal[k]*discreteHessian[k][n][m];
+          //Test: transposed version 
+          // secondFF[m][n] += discreteHessian[k][m][n]*surfaceNormal[k];
+          // secondFF[0][0] += surfaceNormal[k]*discreteHessian[k][0][0];
+          // secondFF[0][1] += surfaceNormal[k]*discreteHessian[k][1][0];
+          // secondFF[1][0] += surfaceNormal[k]*discreteHessian[k][0][1];
+          // secondFF[1][1] += surfaceNormal[k]*discreteHessian[k][1][1];
+        }
+
+        // substract effective prestrain 
+        // G = G + Beff; 
+
+        //Take symmetric part? 
+        // auto symG = 0.5*(G.transposed() + G);
+
+
+
+
+        // printmatrix(std::cout, G , "matrix G: ", "--");
+        // printmatrix(std::cout, symG , "matrix symG: ", "--");
+
+        // std::cout << " discreteHessian.frobenius_norm2(): " << discreteHessian.frobenius_norm2() << std::endl;
+        // std::cout << " G.frobenius_norm2() : " << G.frobenius_norm2() << std::endl;
+        // std::cout << " DIFFERENCE : " << G.frobenius_norm2()- discreteHessian.frobenius_norm2() << std::endl;
+
+        /**
+         * @brief Compute squared Frobenius norm of the discrete Hessian
+         */
+        // auto quadResult = discreteHessian.frobenius_norm2();
+        // std::cout << "quadResult: " << weight*quadResult << std::endl;
+        // auto weight = geometry.volume()/3.0 * element.geometry().integrationElement(geometry.local(geometry.corner(c)));
+
+        // auto weight = geometry.volume()/3.0;
+
+        // std::cout << "geometry.volume()/3.0 : " << geometry.volume()/3.0 << std::endl;
+
+        // we need to use the surface area of the reference element (which is 1/2)
+        // std::cout << "geometry.volume(): " << geometry.volume() << std::endl;
+        // auto weight = (1.0/6.0) * element.geometry().integrationElement(geometry.local(geometry.corner(c)));
+        auto weight = quadPoint.weight() * element.geometry().integrationElement(quadPoint.position());
+        // std::cout << "weight: " << weight << std::endl;
+
+        // harmonicEnergy += weight * discreteHessian.frobenius_norm2();
+        // harmonicEnergy += weight * symG.frobenius_norm2();
+
+        // auto term1 = 0.5 *  weight * discreteHessian.frobenius_norm2();
+        auto term1 = 0.5 *  weight * secondFF.frobenius_norm2();
+
+        RT term2 = 0.0;
+
+        for(size_t i=0; i<2; i++)
+        for(size_t j=0; j<2; j++)
+        {
+          term2 += weight * secondFF[i][j] * Beff[i][j];
+        }
+
+        auto term3 = 0.5 * weight* Beff.frobenius_norm2();           
+
+        // std::cout << "term1: " << term1 << std::endl;
+        // std::cout << "term2: " << term2 << std::endl;
+        // std::cout << "term3: " << term3 << std::endl;
+        // std::cout << "term1 - term2 + term3: " << term1 - term2 + term3 << std::endl;
+
+        // harmonicEnergy +=    weight *  G.frobenius_norm2();
+        harmonicEnergy +=   term1 - term2 + term3;     //eigentlich muss man term2 abziehen bei | II - Z | 
+
+        // std::cout << "harmonicEnergy: " << harmonicEnergy << std::endl;
+      }
+      #endif
+
+
+      /**
+       * @brief Compute contribution of the force Term
+       * 
+       * Integrate the scalar product of the force 'f' 
+       * with the local deformation function 'localFunction_'
+       * over the current element.
+       */
+      RT forceTermEnergy = 0;
+
+      if (parameterSet_.get<bool>("assemble_force_term", 1))
+      {
+        for (auto&& quadPoint : quadRule)
+        {
+            auto deformationValue = localFunction_.evaluate(quadPoint.position());
+            auto forceValue = localForce_(quadPoint.position());
+            // printvector(std::cout, deformationValue.globalCoordinates(), "deformationValue", "--");
+            // printvector(std::cout, forceValue, "forceValue", "--");
+            // const auto jacobian = geometry.jacobianInverseTransposed(quadPoint.position());
+            auto weight = quadPoint.weight() * element.geometry().integrationElement(quadPoint.position());
+            forceTermEnergy += deformationValue.globalCoordinates() * forceValue * weight;
+            // std::cout << "forceTermEnergy:" << forceTermEnergy << std::endl;
+        }
+      }
+    
+      return harmonicEnergy - forceTermEnergy;
+    }
+
+  private:
+    LocalDiscreteKirchhoffFunction& localFunction_;
+
+    LocalForce& localForce_;
+
+    P2LocalFiniteElement lagrangeLFE_;
+
+    const Dune::ParameterTree parameterSet_;
+
+    // const PrestrainType& prestrain_;
+
+    // const MatrixType& quadraticForm_;
+  };
+
+}  // namespace Dune::GFE
+#endif
\ No newline at end of file
diff --git a/src/macro-problem.cc b/src/macro-problem.cc
index 62526239e0beedc4842380df7b0142f730db7d64..e3102e5334e976c1563d40131af2d655bb989054 100644
--- a/src/macro-problem.cc
+++ b/src/macro-problem.cc
@@ -53,7 +53,8 @@
 #include <dune/gfe/energies/discretekirchhoffbendingenergyconforming.hh>
 #include <dune/gfe/energies/discretekirchhoffbendingenergyzienkiewicz.hh>
 #include <dune/gfe/energies/discretekirchhoffbendingenergyzienkiewiczprojected.hh>
-#include <dune/gfe/energies/discretekirchhoffbendingenergyprestrained.hh>
+
+#include <dune/microstructure/energies/discretekirchhoffbendingenergyprestrained.hh>
 
 #include <dune/gfe/spaces/stiefelmanifold.hh>
 // #include <dune/gfe/spaces/stiefelmatrix.hh>
@@ -309,29 +310,28 @@ int main(int argc, char *argv[])
   auto forceGVF  = Dune::Functions::makeGridViewFunction(pythonForce, gridView);
   auto localForce = localFunction(forceGVF);
 
-//  "def force(x): return [0, 0, 0]"
-  /**
-   * @brief Read effective prestrain Tensor
-   */
-  Dune::FieldVector<adouble,3> Beffvec = parameterSet.get<Dune::FieldVector<adouble,3>>("effectivePrestrain", {0.0, 0.0, 0.0});
-  Dune::FieldMatrix<adouble,2,2> effectivePrestrain = {{(adouble)Beffvec[0], (adouble)Beffvec[2]}, {(adouble)Beffvec[2],(adouble)Beffvec[1]} };
-  printmatrix(std::cout, effectivePrestrain, "effective prestrain (Beff): ", "--");
-
-
-  /**
-   * @brief Get effective quadratic form Qhom
-   * 
-   *  input-vector: [q_1,q_2,q_3,q_12,q_13,q_23]
-   *  is assembled into a matrix where the off-diagonal entries are divided by 2 (compare with definition in the paper)
-   *            (   q_1    , 0.5*q_12  ,  0.5*q_13 )
-   *     Q =    ( 0.5*q_12 ,   q_2     ,  0.5*q_23 )
-   *            ( 0.5*q_13 , 0.5*q_23  ,    q_3    )
-   */
-  Dune::FieldVector<adouble,6> Qhomvec = parameterSet.get<Dune::FieldVector<adouble,6>>("effectiveQuadraticForm", {1.0, 1.0, 1.0, 0.0, 0.0, 0.0});
-  Dune::FieldMatrix<adouble,3,3> Qhom = {{(adouble)Qhomvec[0], (adouble)0.5*Qhomvec[3], (adouble)0.5*Qhomvec[4]}, 
-                                        {(adouble)0.5*Qhomvec[3], (adouble)Qhomvec[1], (adouble)0.5*Qhomvec[5]},
-                                        {(adouble)0.5*Qhomvec[4], (adouble)0.5*Qhomvec[5], (adouble)Qhomvec[2]}};
-  printmatrix(std::cout, Qhom, "effective quadratic form (Qhom): ", "--");
+  // /**
+  //  * @brief Read effective prestrain Tensor
+  //  */
+  // Dune::FieldVector<adouble,3> Beffvec = parameterSet.get<Dune::FieldVector<adouble,3>>("effectivePrestrain", {0.0, 0.0, 0.0});
+  // Dune::FieldMatrix<adouble,2,2> effectivePrestrain = {{(adouble)Beffvec[0], (adouble)Beffvec[2]}, {(adouble)Beffvec[2],(adouble)Beffvec[1]} };
+  // printmatrix(std::cout, effectivePrestrain, "effective prestrain (Beff): ", "--");
+
+
+  // /**
+  //  * @brief Get effective quadratic form Qhom
+  //  * 
+  //  *  input-vector: [q_1,q_2,q_3,q_12,q_13,q_23]
+  //  *  is assembled into a matrix where the off-diagonal entries are divided by 2 (compare with definition in the paper)
+  //  *            (   q_1    , 0.5*q_12  ,  0.5*q_13 )
+  //  *     Q =    ( 0.5*q_12 ,   q_2     ,  0.5*q_23 )
+  //  *            ( 0.5*q_13 , 0.5*q_23  ,    q_3    )
+  //  */
+  // Dune::FieldVector<adouble,6> Qhomvec = parameterSet.get<Dune::FieldVector<adouble,6>>("effectiveQuadraticForm", {1.0, 1.0, 1.0, 0.0, 0.0, 0.0});
+  // Dune::FieldMatrix<adouble,3,3> Qhom = {{(adouble)Qhomvec[0], (adouble)0.5*Qhomvec[3], (adouble)0.5*Qhomvec[4]}, 
+  //                                       {(adouble)0.5*Qhomvec[3], (adouble)Qhomvec[1], (adouble)0.5*Qhomvec[5]},
+  //                                       {(adouble)0.5*Qhomvec[4], (adouble)0.5*Qhomvec[5], (adouble)Qhomvec[2]}};
+  // printmatrix(std::cout, Qhom, "effective quadratic form (Qhom): ", "--");
 
   ////////////////////////////////////////////////////////////////////////
   //   Create an assembler for the Discrete Kirchhoff Energy Functional  (using ADOL-C)
@@ -349,7 +349,8 @@ int main(int argc, char *argv[])
   /**
    * @brief Setup energy featuring prestrain
    */
-   auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce, Qhom, effectivePrestrain,  parameterSet);
+  //  auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce, Qhom, effectivePrestrain,  parameterSet);
+  auto localEnergy_prestrain = std::make_shared<GFE::DiscreteKirchhoffBendingEnergyPrestrained<CoefficientBasis, LocalDKFunction, decltype(localForce), ACoefficient>>(localDKFunction, localForce, parameterSet, pyModule);
 
   LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> localGFEADOLCStiffness_conforming(localEnergy_conforming.get());
   LocalGeodesicFEADOLCStiffness<CoefficientBasis, Coefficient> localGFEADOLCStiffness_nonconforming(localEnergy_nonconforming.get());