From 60cb7db82098efbf4a838a9dc7028ca7bcb07281 Mon Sep 17 00:00:00 2001
From: Klaus <klaus.boehnlein@tu-dresden.de>
Date: Mon, 22 Aug 2022 00:45:22 +0200
Subject: [PATCH] Outsource Corrector-Computation to class

---
 dune/microstructure/CorrectorComputer.hh | 1279 ++++++++++
 src/Cell-Problem-New.cc                  | 2746 ++++++++++++++++++++++
 2 files changed, 4025 insertions(+)
 create mode 100644 dune/microstructure/CorrectorComputer.hh
 create mode 100644 src/Cell-Problem-New.cc

diff --git a/dune/microstructure/CorrectorComputer.hh b/dune/microstructure/CorrectorComputer.hh
new file mode 100644
index 00000000..a2fef077
--- /dev/null
+++ b/dune/microstructure/CorrectorComputer.hh
@@ -0,0 +1,1279 @@
+#ifndef DUNE_MICROSTRUCTURE_CORRECTORCOMPUTER_HH
+#define DUNE_MICROSTRUCTURE_CORRECTORCOMPUTER_HH
+
+
+#include <dune/common/parametertree.hh>
+#include <dune/common/float_cmp.hh>
+#include <dune/istl/matrixindexset.hh>
+#include <dune/functions/functionspacebases/interpolate.hh>
+#include <dune/functions/gridfunctions/gridviewfunction.hh> 
+#include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh> 
+#include <dune/microstructure/matrix_operations.hh>
+
+#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number 
+#include <dune/solvers/solvers/umfpacksolver.hh> 
+
+using namespace Dune;
+// using namespace Functions;
+using namespace MatrixOperations;
+
+using std::shared_ptr;
+using std::make_shared;
+using std::fstream;
+
+
+template <class Basis> //, class LocalScalar, class Local2Tensor> // LocalFunction derived from basis?
+class CellAssembler {
+
+public:
+	static const int dimworld = 3; //GridView::dimensionworld;
+	static const int dim = Basis::GridView::dimension; //const int dim = Domain::dimension;
+	
+	using GridView = typename Basis::GridView;
+	using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate;
+
+	using ScalarRT = FieldVector< double, 1>;
+	using VectorRT = FieldVector< double, dimworld>;
+	using MatrixRT = FieldMatrix< double, dimworld, dimworld>;
+
+	using FuncScalar = std::function< ScalarRT(const Domain&) >;
+	using FuncVector = std::function< VectorRT(const Domain&) >;
+	using Func2Tensor = std::function< MatrixRT(const Domain&) >;
+
+	using VectorCT = BlockVector<FieldVector<double,1> >;
+	using MatrixCT = BCRSMatrix<FieldMatrix<double,1,1> >;
+	using ElementMatrixCT = Matrix<FieldMatrix<double,1,1> >;
+
+	using HierarchicVectorView = Dune::Functions::HierarchicVectorWrapper< VectorCT, double>;
+	
+protected:
+//private:
+	const Basis& basis_; 
+
+	fstream& log_;      // Output-log
+	const ParameterTree& parameterSet_;
+
+	const FuncScalar mu_; 
+    const FuncScalar lambda_; 
+    double gamma_;
+
+    MatrixCT stiffnessMatrix_; 
+	VectorCT load_alpha1_,load_alpha2_,load_alpha3_; //right-hand side(load) vectors
+
+    VectorCT x_1_, x_2_, x_3_;            // (all) Corrector coefficient vectors 
+    VectorCT phi_1_, phi_2_, phi_3_;      // Corrector phi_i coefficient vectors 
+    FieldVector<double,3> m_1_, m_2_, m_3_;  // Corrector m_i coefficient vectors 
+
+    MatrixRT M1_, M2_, M3_;  // (assembled) corrector matrices M_i
+    const std::array<MatrixRT*, 3 > mContainer = {&M1_ , &M2_, &M3_};
+
+    // ---- Basis for R_sym^{2x2}
+    MatrixRT G1_ {{1.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0, 0.0}};
+    MatrixRT G2_ {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0, 0.0, 0.0}};
+    MatrixRT G3_ {{0.0, 1.0/sqrt(2.0), 0.0}, {1.0/sqrt(2.0), 0.0, 0.0}, {0.0, 0.0, 0.0}};
+    std::array<MatrixRT,3 > basisContainer_ = {G1_, G2_, G3_};
+
+    Func2Tensor x3G_1_ = [] (const Domain& x) {
+                            return MatrixRT{{1.0*x[2], 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};    //TODO könnte hier sign übergeben?
+                        };
+
+    Func2Tensor x3G_2_ = [] (const Domain& x) {
+                            return MatrixRT{{0.0, 0.0, 0.0}, {0.0, 1.0*x[2], 0.0}, {0.0, 0.0, 0.0}};
+                        };
+
+    Func2Tensor x3G_3_ = [] (const Domain& x) {                                                                               
+                            return MatrixRT{{0.0, (1.0/sqrt(2.0))*x[2], 0.0}, {(1.0/sqrt(2.0))*x[2], 0.0, 0.0}, {0.0, 0.0, 0.0}};
+                        };
+
+    const std::array<Func2Tensor, 3> x3MatrixBasis_ = {x3G_1_, x3G_2_, x3G_3_};
+
+    // --- Offset between basis indices 
+    const int phiOffset_;
+
+public: 
+	///////////////////////////////
+	// constructor
+	///////////////////////////////
+	CellAssembler(  const Basis& basis, 
+					const FuncScalar& mu, 
+					const FuncScalar& lambda, 
+					double gamma,
+					std::fstream& log, 
+					const ParameterTree& parameterSet)
+        : basis_(basis), 
+          mu_(mu),
+          lambda_(lambda),
+          gamma_(gamma),
+          log_(log),
+          parameterSet_(parameterSet),
+          phiOffset_(basis.size())
+  {
+
+  	assemble();
+
+  	// if (parameterSet.get<bool>("stiffnessmatrix_cellproblem_to_csv"))
+  	// 	csvSystemMatrix();
+  	// if (parameterSet.get<bool>("rhs_cellproblem_to_csv"))
+	// 		csvRHSs();
+  	// if (parameterSet.get<bool>("rhs_cellproblem_to_vtk"))
+  	// 	vtkLoads();
+  } 
+
+
+// -----------------------------------------------------------------
+// --- Assemble Corrector problems
+void assemble()
+{
+    assembleCellStiffness(stiffnessMatrix_);
+
+
+    // // lateral stretch strain		E_U1 = e1 ot e1  				= MatrixRT{{1, 0, 0}, {0, 0, 0}, {0, 0, 0}};
+    // 	Func2Tensor neg_E_a  = [] (const Domain& z) { return biotStrainApprox({-1, 0, 0}, {0, 0, 0}, {0, z[dim-2], z[dim-1]}); }; 
+
+    // // twist in x2-x3 plane 		E_K1 = (e1 x (0,x2,x3)^T ot e1) = MatrixRT{{0,-z[2], z[1]}, {0, 0 , 0 }, {0,0,0}}; 
+    // Func2Tensor neg_E_K1 = [] (const Domain& z) { return biotStrainApprox({0, 0, 0}, {-1, 0, 0}, {0, z[dim-2], z[dim-1]}); };
+
+    // //  bend strain in x1-x2 plane	E_K2 = (e2 x (0,x2,x3)^T ot e1) = MatrixRT{{z[2], 0, 0}, {0, 0, 0}, {0, 0, 0}}; 
+    // Func2Tensor neg_E_K2 = [] (const Domain& z) { return biotStrainApprox({0, 0, 0}, {0, -1, 0}, {0, z[dim-2], z[dim-1]}); };
+    
+    // // bend strain in x1-x3 plane	E_K3 = (e3 x (0,x2,x3)^T ot e1) = MatrixRT{{-z[1], 0, 0}, {0, 0, 0}, {0, 0, 0}};
+    // Func2Tensor neg_E_K3 = [] (const Domain& z) { return biotStrainApprox({0, 0, 0}, {0, 0, -1}, {0, z[dim-2], z[dim-1]});  };
+
+    // assembleLoadVector(neg_E_a, load_a_); 
+    // //log_ << "\n\n\n\n\n\n";
+    // assembleLoadVector(neg_E_K1, load_K1_);
+    // assembleLoadVector(neg_E_K2, load_K2_);
+    // assembleLoadVector(neg_E_K3, load_K3_);
+/////////////////////////////////////////////////////////
+// Define "rhs"-functions
+/////////////////////////////////////////////////////////
+
+                    
+
+// Func2Tensor x3G_1neg = [x3G_1_] (const Domain& x) {return -1.0*x3G_1_(x);};
+// Func2Tensor x3G_2neg = [x3G_2_] (const Domain& x) {return -1.0*x3G_2_(x);};
+// Func2Tensor x3G_3neg = [x3G_3_] (const Domain& x) {return -1.0*x3G_3_(x);};
+// Func2Tensor x3G_1neg = [] (const Domain& x) {return -1.0*x3G_1_(x);};
+// Func2Tensor x3G_2neg = [] (const Domain& x) {return -1.0*x3G_2_(x);};
+// Func2Tensor x3G_3neg = [] (const Domain& x) {return -1.0*x3G_3_(x);};
+    // assembleCellLoad(load_alpha1_ ,x3G_1neg);
+    // assembleCellLoad(load_alpha2_ ,x3G_2neg);
+    // assembleCellLoad(load_alpha3_ ,x3G_3neg);
+
+    assembleCellLoad(load_alpha1_ ,x3G_1_);
+    assembleCellLoad(load_alpha2_ ,x3G_2_);
+    assembleCellLoad(load_alpha3_ ,x3G_3_);
+};
+
+
+
+  ///////////////////////////////
+  // getter
+  ///////////////////////////////
+  const shared_ptr<Basis> getBasis() {return make_shared<Basis>(basis_);}
+
+	// std::map<int,int> getIndexMapPeriodicBoundary(){return perIndexMap_;}
+
+  ParameterTree getParameterSet() const {return parameterSet_;} 
+
+  fstream* getLog(){return &log_;}
+
+
+  double getGamma(){return gamma_;}
+
+  shared_ptr<MatrixCT> getStiffnessMatrix(){return make_shared<MatrixCT>(stiffnessMatrix_);}
+  shared_ptr<VectorCT> getLoad_alpha1(){return make_shared<VectorCT>(load_alpha1_);}
+  shared_ptr<VectorCT> getLoad_alpha2(){return make_shared<VectorCT>(load_alpha2_);}
+  shared_ptr<VectorCT> getLoad_alpha3(){return make_shared<VectorCT>(load_alpha3_);}
+
+
+// Get the occupation pattern of the stiffness matrix
+void getOccupationPattern(MatrixIndexSet& nb)
+{
+  //  OccupationPattern:
+  // | phi*phi    m*phi |
+  // | phi *m     m*m   |
+  auto localView = basis_.localView();
+  const int phiOffset = basis_.dimension();
+
+  nb.resize(basis_.size()+3, basis_.size()+3);
+
+  for (const auto& element : elements(basis_.gridView()))
+  {
+    localView.bind(element);
+    for (size_t i=0; i<localView.size(); i++)
+    {
+      // The global index of the i-th vertex of the element
+      auto row = localView.index(i);
+      for (size_t j=0; j<localView.size(); j++ )
+      {
+        // The global index of the j-th vertex of the element
+        auto col = localView.index(j);
+        nb.add(row[0],col[0]);                   // nun würde auch nb.add(row,col) gehen..
+      }
+    }
+    for (size_t i=0; i<localView.size(); i++)
+    {
+      auto row = localView.index(i);
+
+      for (size_t j=0; j<3; j++ )
+      {
+        nb.add(row,phiOffset+j);               // m*phi part of StiffnessMatrix
+        nb.add(phiOffset+j,row);               // phi*m part of StiffnessMatrix
+      }
+    }
+    for (size_t i=0; i<3; i++ )
+      for (size_t j=0; j<3; j++ )
+      {
+        nb.add(phiOffset+i,phiOffset+j);       // m*m part of StiffnessMatrix
+      }
+  }
+  //////////////////////////////////////////////////////////////////
+  // setOneBaseFunctionToZero
+  //////////////////////////////////////////////////////////////////
+  if(parameterSet_.get<bool>("set_oneBasisFunction_Zero ", true)){
+    FieldVector<int,3> row;
+    unsigned int arbitraryLeafIndex =  parameterSet_.get<unsigned int>("arbitraryLeafIndex", 0);
+    unsigned int arbitraryElementNumber =  parameterSet_.get<unsigned int>("arbitraryElementNumber", 0);
+
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();    // macht keinen Unterschied ob hier k oder 0..
+    const auto nSf = localFiniteElement.localBasis().size();
+    assert(arbitraryLeafIndex < nSf );
+    assert(arbitraryElementNumber  < basis_.gridView().size(0));   // "arbitraryElementNumber larger than total Number of Elements"
+
+    //Determine 3 global indices (one for each component of an arbitrary local FE-function)
+    row = arbitraryComponentwiseIndices(arbitraryElementNumber,arbitraryLeafIndex);
+
+    for (int k = 0; k<3; k++)
+      nb.add(row[k],row[k]);
+  }
+  std::cout << "finished occupation pattern\n";
+}
+
+
+template<class localFunction1, class localFunction2>
+void computeElementStiffnessMatrix(const typename Basis::LocalView& localView,
+                                   ElementMatrixCT& elementMatrix,
+                                   const localFunction1& mu,
+                                   const localFunction2& lambda
+                                   )
+{
+  // Local StiffnessMatrix of the form:
+  // | phi*phi    m*phi |
+  // | phi *m     m*m   |
+  auto element = localView.element();
+  auto geometry = element.geometry();
+//   using MatrixRT = FieldMatrix< double, dimworld, dimworld>;
+
+  elementMatrix.setSize(localView.size()+3, localView.size()+3);         //extend by dim ´R_sym^{2x2}
+  elementMatrix = 0;
+
+  // LocalBasis-Offset
+  const int localPhiOffset = localView.size();
+
+  const auto& localFiniteElement = localView.tree().child(0).finiteElement();     
+  const auto nSf = localFiniteElement.localBasis().size();
+//   std::cout << "localView.size(): " << localView.size() << std::endl;
+//   std::cout << "nSf : " << nSf << std::endl;
+
+  ///////////////////////////////////////////////
+  // Basis for R_sym^{2x2}            // wird nicht als Funktion benötigt da konstant...
+  //////////////////////////////////////////////
+  MatrixRT G_1 {{1.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
+  MatrixRT G_2 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 0.0}};
+  MatrixRT G_3 {{0.0, 1.0/sqrt(2.0), 0.0}, {1.0/sqrt(2.0), 0.0, 0.0}, {0.0, 0.0, 0.0}};
+  std::array<MatrixRT,3 > basisContainer = {G_1, G_2, G_3};
+
+//   int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5;  // TEST
+  int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+//   int orderQR = 0;
+//   int orderQR = 1;
+//   int orderQR = 2;
+//   int orderQR = 3;
+  const auto& quad = QuadratureRules<double,dim>::rule(element.type(), orderQR);
+  
+//   double elementContribution = 0.0;
+  
+//   std::cout << "Print QuadratureOrder:" << orderQR << std::endl;  //TEST`
+
+  int QPcounter= 0;
+  for (const auto& quadPoint : quad)
+  {
+    QPcounter++;
+    const auto& quadPos = quadPoint.position();
+    const auto jacobianInverseTransposed = geometry.jacobianInverseTransposed(quadPos);
+    const auto integrationElement = geometry.integrationElement(quadPos);
+
+    std::vector< FieldMatrix< double, 1, dim> > referenceGradients;
+    localFiniteElement.localBasis().evaluateJacobian(quadPos,
+                                                     referenceGradients);
+    // Compute the shape function gradients on the grid element
+    std::vector<FieldVector<double,dim> > gradients(referenceGradients.size());
+
+    for (size_t i=0; i<gradients.size(); i++)
+      jacobianInverseTransposed.mv(referenceGradients[i][0], gradients[i]);
+
+    for (size_t l=0; l< dimworld; l++)
+    for (size_t j=0; j < nSf; j++ )
+    {
+        size_t row = localView.tree().child(l).localIndex(j);
+        // (scaled)  Deformation gradient of the test basis function
+        MatrixRT defGradientV(0);
+        defGradientV[l][0] = gradients[j][0];                       // Y
+        defGradientV[l][1] = gradients[j][1];                       //X2
+//         defGradientV[l][2] = (1.0/gamma)*gradients[j][2];           //X3
+        defGradientV[l][2] = gradients[j][2];           //X3
+        
+        defGradientV = crossSectionDirectionScaling((1.0/gamma_),defGradientV);
+        // "phi*phi"-part
+        for (size_t k=0; k < dimworld; k++)
+        for (size_t i=0; i < nSf; i++)
+        {
+            // (scaled) Deformation gradient of the ansatz basis function
+            MatrixRT defGradientU(0);
+            defGradientU[k][0] = gradients[i][0];                       // Y
+            defGradientU[k][1] = gradients[i][1];                       //X2
+//             defGradientU[k][2] = (1.0/gamma)*gradients[i][2];           //X3
+            defGradientU[k][2] = gradients[i][2];           //X3
+            // printmatrix(std::cout, defGradientU , "defGradientU", "--");
+            defGradientU = crossSectionDirectionScaling((1.0/gamma_),defGradientU);
+
+            double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), defGradientU, defGradientV);
+//             double energyDensity = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), defGradientU, defGradientV); //TEST
+//             double energyDensity = generalizedDensity(mu(quadPos), lambda(quadPos), defGradientU, defGradientV);  // also works..
+
+            size_t col = localView.tree().child(k).localIndex(i);                       
+            
+            elementMatrix[row][col] += energyDensity * quadPoint.weight() * integrationElement;
+        }
+            
+        // "m*phi"  & "phi*m" - part
+        for( size_t m=0; m<3; m++)
+        {
+            double energyDensityGphi = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], defGradientV);
+//             double energyDensityGphi = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), basisContainer[m], defGradientV); //TEST 
+            auto value = energyDensityGphi * quadPoint.weight() * integrationElement;
+            elementMatrix[row][localPhiOffset+m] += value;
+            elementMatrix[localPhiOffset+m][row] += value;
+        }
+          
+    }
+    // "m*m"-part
+    for(size_t m=0; m<3; m++)                //TODO ist symmetric.. reicht die hälfte zu berechnen!!!
+      for(size_t n=0; n<3; n++)
+      {
+          
+//        std::cout << "QPcounter: " << QPcounter << std::endl; 
+//         std::cout << "m= " << m  << "   n = " << n << std::endl;
+//         printmatrix(std::cout, basisContainer[m] , "basisContainer[m]", "--");
+//         printmatrix(std::cout, basisContainer[n] , "basisContainer[n]", "--");
+//         std::cout  << "integrationElement:" << integrationElement << std::endl;
+//         std::cout << "quadPoint.weight(): "<< quadPoint.weight() << std::endl;
+//         std::cout << "mu(quadPos): " << mu(quadPos) << std::endl;
+//         std::cout << "lambda(quadPos): " << lambda(quadPos) << std::endl;
+
+        double energyDensityGG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], basisContainer[n]);
+//         double energyDensityGG = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), basisContainer[m], basisContainer[n]); //TEST 
+        elementMatrix[localPhiOffset+m][localPhiOffset+n]  += energyDensityGG * quadPoint.weight() * integrationElement;                           // += !!!!! (Fixed-Bug)
+        
+//         std::cout  << "energyDensityGG:" << energyDensityGG<< std::endl;
+//         std::cout << "product " << energyDensityGG * quadPoint.weight() * integrationElement << std::endl;
+//         printmatrix(std::cout, elementMatrix, "elementMatrix", "--");
+      }
+  }
+//   std::cout << "Number of QuadPoints:" << QPcounter << std::endl;
+//   printmatrix(std::cout, elementMatrix, "elementMatrix", "--");
+}
+
+
+
+// Compute the source term for a single element
+// < L (sym[D_gamma*nabla phi_i] + M_i ), x_3G_alpha >
+template<class LocalFunction1, class LocalFunction2, class Vector, class LocalForce>
+void computeElementLoadVector( const typename Basis::LocalView& localView,
+                               LocalFunction1& mu,
+                               LocalFunction2& lambda,
+                               Vector& elementRhs,
+                               const LocalForce& forceTerm
+                               )
+{
+  // | f*phi|
+  // | ---  |
+  // | f*m  |
+//   using Element = typename LocalView::Element;
+  const auto element = localView.element();
+  const auto geometry = element.geometry();
+//   constexpr int dim = Element::dimension;
+//   constexpr int dimworld = dim;
+
+//   using MatrixRT = FieldMatrix< double, dimworld, dimworld>;
+
+  // Set of shape functions for a single element
+  const auto& localFiniteElement= localView.tree().child(0).finiteElement();
+  const auto nSf = localFiniteElement.localBasis().size();
+
+  elementRhs.resize(localView.size() +3);
+  elementRhs = 0;
+
+  // LocalBasis-Offset
+  const int localPhiOffset = localView.size();
+
+  ///////////////////////////////////////////////
+  // Basis for R_sym^{2x2}
+  //////////////////////////////////////////////
+  MatrixRT G_1 {{1.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
+  MatrixRT G_2 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 0.0}};
+  MatrixRT G_3 {{0.0, 1.0/sqrt(2.0), 0.0}, {1.0/sqrt(2.0), 0.0, 0.0}, {0.0, 0.0, 0.0}};
+  std::array<MatrixRT,3 > basisContainer = {G_1, G_2, G_3};
+
+//   int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5;  // TEST
+//   int orderQR = 0;
+//   int orderQR = 1;
+//   int orderQR = 2;
+//   int orderQR = 3;
+  int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);  
+  const auto& quad = QuadratureRules<double,dim>::rule(element.type(), orderQR);
+//   std::cout << "Quad-Rule order used: " << orderQR << std::endl;
+
+  for (const auto& quadPoint : quad)
+  {
+    const FieldVector<double,dim>& quadPos = quadPoint.position();
+    const auto jacobian = geometry.jacobianInverseTransposed(quadPos);
+    const double integrationElement = geometry.integrationElement(quadPos);
+
+    std::vector<FieldMatrix<double,1,dim> > referenceGradients;
+    localFiniteElement.localBasis().evaluateJacobian(quadPos, referenceGradients);
+
+    std::vector< FieldVector< double, dim> > gradients(referenceGradients.size());  
+    for (size_t i=0; i< gradients.size(); i++)
+      jacobian.mv(referenceGradients[i][0], gradients[i]);
+    
+    //TEST
+//     std::cout << "forceTerm(element.geometry().global(quadPos)):"  << std::endl;
+//     std::cout << forceTerm(element.geometry().global(quadPos)) << std::endl;
+//     std::cout << "forceTerm(quadPos)" << std::endl;
+//     std::cout << forceTerm(quadPos) << std::endl;
+//     
+//     //TEST QUadrature 
+//     std::cout << "quadPos:" << quadPos << std::endl;
+//     std::cout << "element.geometry().global(quadPos):" << element.geometry().global(quadPos) << std::endl;
+// // //     
+// // //     
+//     std::cout << "quadPoint.weight() :" << quadPoint.weight()  << std::endl;
+//     std::cout << "integrationElement(quadPos):" << integrationElement << std::endl;
+//     std::cout << "mu(quadPos) :" << mu(quadPos) << std::endl;
+//     std::cout << "lambda(quadPos) :" << lambda(quadPos) << std::endl;
+    
+
+    // "f*phi"-part
+    for (size_t i=0; i < nSf; i++)
+      for (size_t k=0; k < dimworld; k++)
+      {
+        // Deformation gradient of the ansatz basis function
+        MatrixRT defGradientV(0);
+        defGradientV[k][0] = gradients[i][0];                                 // Y
+        defGradientV[k][1] = gradients[i][1];                                 // X2
+//         defGradientV[k][2] = (1.0/gamma_)*gradients[i][2];                     // 
+        defGradientV[k][2] = gradients[i][2];                     // X3
+        
+        defGradientV = crossSectionDirectionScaling((1.0/gamma_),defGradientV);
+
+        double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos),(-1.0)*forceTerm(quadPos), defGradientV ); 
+//         double energyDensity = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)),forceTerm(quadPos), defGradientV ); //TEST 
+//         double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos),(-1.0)*forceTerm(quadPos), defGradientV ); //TEST
+//         double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos),forceTerm(element.geometry().global(quadPos)), defGradientV ); //TEST 
+        
+        size_t row = localView.tree().child(k).localIndex(i);
+        elementRhs[row] += energyDensity * quadPoint.weight() * integrationElement;
+      }
+
+    // "f*m"-part
+    for (size_t m=0; m<3; m++)
+    {
+      double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), (-1.0)*forceTerm(quadPos),basisContainer[m] );
+//       double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), forceTerm(quadPos),basisContainer[m] ); //TEST 
+//       double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), (-1.0)*forceTerm(quadPos),basisContainer[m] ); //TEST
+//       double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), forceTerm(element.geometry().global(quadPos)),basisContainer[m] );//TEST 
+      elementRhs[localPhiOffset+m] += energyDensityfG * quadPoint.weight() * integrationElement;
+//       std::cout << "energyDensityfG * quadPoint.weight() * integrationElement: " << energyDensityfG * quadPoint.weight() * integrationElement << std::endl;   
+    }
+  }
+}
+
+
+void assembleCellStiffness(MatrixCT& matrix)
+{
+  std::cout << "assemble Stiffness-Matrix begins." << std::endl;
+
+  MatrixIndexSet occupationPattern;
+  getOccupationPattern(occupationPattern);
+  occupationPattern.exportIdx(matrix);
+  matrix = 0;
+
+  auto localView = basis_.localView();
+  const int phiOffset = basis_.dimension();
+
+  auto muGridF  = makeGridViewFunction(mu_, basis_.gridView());
+  auto muLocal = localFunction(muGridF);
+  auto lambdaGridF  = makeGridViewFunction(lambda_, basis_.gridView());
+  auto lambdaLocal = localFunction(lambdaGridF);
+
+  for (const auto& element : elements(basis_.gridView()))
+  {
+    localView.bind(element);
+    muLocal.bind(element);
+    lambdaLocal.bind(element);
+    const int localPhiOffset = localView.size();
+//     Dune::Timer Time;
+    //std::cout << "localPhiOffset : " << localPhiOffset << std::endl;
+    Matrix<FieldMatrix<double,1,1> > elementMatrix;
+    computeElementStiffnessMatrix(localView, elementMatrix, muLocal, lambdaLocal);
+    
+//     std::cout << "local assembly time:" << Time.elapsed() << std::endl;
+    
+    //printmatrix(std::cout, elementMatrix, "ElementMatrix", "--");
+    //std::cout << "elementMatrix.N() : " << elementMatrix.N() << std::endl;
+    //std::cout << "elementMatrix.M() : " << elementMatrix.M() << std::endl;
+    
+    //TEST
+    //Check Element-Stiffness-Symmetry:
+    for (size_t i=0; i<localPhiOffset; i++)
+    for (size_t j=0; j<localPhiOffset; j++ )
+    {
+        if(abs(elementMatrix[i][j] - elementMatrix[j][i]) > 1e-12 )
+            std::cout << "ELEMENT-STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl;
+    }
+    //////////////////////////////////////////////////////////////////////////////
+    // GLOBAL STIFFNES ASSEMBLY
+    //////////////////////////////////////////////////////////////////////////////
+    for (size_t i=0; i<localPhiOffset; i++)
+    for (size_t j=0; j<localPhiOffset; j++ )
+    {
+        auto row = localView.index(i);
+        auto col = localView.index(j);
+        matrix[row][col] += elementMatrix[i][j];
+    }
+    for (size_t i=0; i<localPhiOffset; i++)
+    for(size_t m=0; m<3; m++)
+    {
+        auto row = localView.index(i);
+        matrix[row][phiOffset+m] += elementMatrix[i][localPhiOffset+m];
+        matrix[phiOffset+m][row] += elementMatrix[localPhiOffset+m][i];
+    }
+    for (size_t m=0; m<3; m++ )
+    for (size_t n=0; n<3; n++ )
+        matrix[phiOffset+m][phiOffset+n] += elementMatrix[localPhiOffset+m][localPhiOffset+n];
+
+    //  printmatrix(std::cout, matrix, "StiffnessMatrix", "--");
+  }
+}
+
+
+void assembleCellLoad(VectorCT& b,
+                      const Func2Tensor&  forceTerm
+                      )
+{
+  //     std::cout << "assemble load vector." << std::endl;
+  b.resize(basis_.size()+3);
+  b = 0;
+
+  auto localView = basis_.localView();
+  const int phiOffset = basis_.dimension();
+
+  // Transform G_alpha's to GridViewFunctions/LocalFunctions 
+  auto loadGVF  = Dune::Functions::makeGridViewFunction(forceTerm, basis_.gridView());
+  auto loadFunctional = localFunction(loadGVF);      
+
+  auto muGridF  = makeGridViewFunction(mu_, basis_.gridView());
+  auto muLocal = localFunction(muGridF);
+  auto lambdaGridF  = makeGridViewFunction(lambda_, basis_.gridView());
+  auto lambdaLocal = localFunction(lambdaGridF);
+
+
+//   int counter = 1;
+  for (const auto& element : elements(basis_.gridView()))
+  {
+    localView.bind(element);
+    muLocal.bind(element);
+    lambdaLocal.bind(element);
+    loadFunctional.bind(element);
+
+    const int localPhiOffset = localView.size();
+    //         std::cout << "localPhiOffset : " << localPhiOffset << std::endl;
+
+    VectorCT elementRhs;
+//     std::cout << "----------------------------------Element : " <<  counter << std::endl; //TEST
+//     counter++;
+    computeElementLoadVector(localView, muLocal, lambdaLocal, elementRhs, loadFunctional);
+//     computeElementLoadVector(localView, muLocal, lambdaLocal, gamma, elementRhs, forceTerm); //TEST
+//     printvector(std::cout, elementRhs, "elementRhs", "--");
+//     printvector(std::cout, elementRhs, "elementRhs", "--");
+    //////////////////////////////////////////////////////////////////////////////
+    // GLOBAL LOAD ASSEMBLY
+    //////////////////////////////////////////////////////////////////////////////
+    for (size_t p=0; p<localPhiOffset; p++)
+    {
+      auto row = localView.index(p);
+      b[row] += elementRhs[p];
+    }
+    for (size_t m=0; m<3; m++ )
+      b[phiOffset+m] += elementRhs[localPhiOffset+m];
+      //printvector(std::cout, b, "b", "--");
+  }
+}
+
+// -----------------------------------------------------------------
+// --- Functions for global integral mean equals zero constraint
+auto arbitraryComponentwiseIndices(const int elementNumber,
+                                   const int leafIdx
+                                   )
+{
+  // (Local Approach -- works for non Lagrangian-Basis too)
+  // Input  : elementNumber & localIdx
+  // Output : determine all Component-Indices that correspond to that basis-function
+  auto localView = basis_.localView();
+
+  FieldVector<int,3> row;
+  int elementCounter = 0;
+
+  for (const auto& element : elements(basis_.gridView()))
+  {
+    if(elementCounter == elementNumber)             // get arbitraryIndex(global) for each Component        ..alternativ:gridView.indexSet
+    {
+      localView.bind(element);
+
+      for (int k = 0; k < 3; k++)
+      {
+        auto rowLocal = localView.tree().child(k).localIndex(leafIdx);    //Input: LeafIndex! TODO bräuchte hier (Inverse )  Local-to-Leaf Idx Map
+        row[k] = localView.index(rowLocal);
+        //         std::cout << "rowLocal:" << rowLocal << std::endl;
+        //         std::cout << "row[k]:" << row[k] << std::endl;
+      }
+    }
+    elementCounter++;
+  }
+  return row;
+}
+
+void setOneBaseFunctionToZero()
+{
+  std::cout << "Setting one Basis-function to zero" << std::endl;
+
+//   constexpr int dim = Basis::LocalView::Element::dimension;
+  
+  unsigned int arbitraryLeafIndex =  parameterSet_.template get<unsigned int>("arbitraryLeafIndex", 0);
+  unsigned int arbitraryElementNumber =  parameterSet_.template get<unsigned int>("arbitraryElementNumber", 0);
+  //Determine 3 global indices (one for each component of an arbitrary local FE-function)
+  FieldVector<int,3> row = arbitraryComponentwiseIndices(arbitraryElementNumber,arbitraryLeafIndex);
+
+  for (int k = 0; k<dim; k++)
+  {
+    load_alpha1_[row[k]] = 0.0;
+    load_alpha2_[row[k]] = 0.0;
+    load_alpha3_[row[k]] = 0.0;
+    auto cIt    = stiffnessMatrix_[row[k]].begin();
+    auto cEndIt = stiffnessMatrix_[row[k]].end();
+    for (; cIt!=cEndIt; ++cIt)
+      *cIt = (cIt.index()==row[k]) ? 1.0 : 0.0;
+  }
+}
+
+
+auto childToIndexMap(const int k)
+{
+  // Input  : child/component
+  // Output : determine all Indices that belong to that component
+  auto localView = basis_.localView();
+
+  std::vector<int> r = { };
+  //     for (int n: r)
+  //         std::cout << n << ","<< std::endl;
+
+  // Determine global indizes for each component k = 1,2,3.. in order to subtract correct (component of) integral Mean
+  // (global) Indices that correspond to component k = 1,2,3
+  for(const auto& element : elements(basis_.gridView()))
+  {
+    localView.bind(element);
+    const auto& localFiniteElement = localView.tree().child(k).finiteElement();        
+    const auto nSf = localFiniteElement.localBasis().size();                           
+
+    for(size_t j=0; j<nSf; j++)
+    {
+      auto Localidx = localView.tree().child(k).localIndex(j);  // local  indices
+      r.push_back(localView.index(Localidx));                   // global indices
+    }
+  }
+  // Delete duplicate elements
+  // first remove consecutive (adjacent) duplicates
+  auto last = std::unique(r.begin(), r.end());
+  r.erase(last, r.end());
+  // sort followed by unique, to remove all duplicates
+  std::sort(r.begin(), r.end());
+  last = std::unique(r.begin(), r.end());
+  r.erase(last, r.end());
+  return r;
+}
+
+
+auto integralMean(VectorCT& coeffVector)
+{
+  auto GVFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,dim>>(basis_,coeffVector);
+  auto localfun = localFunction(GVFunction);
+
+  auto localView = basis_.localView();
+
+  FieldVector<double,3> r = {0.0, 0.0, 0.0};
+  double area = 0.0;
+
+  // Compute Area integral & integral of FE-function
+  for(const auto& element : elements(basis_.gridView()))
+  {
+    localView.bind(element);
+    localfun.bind(element);
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();
+    
+//     int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5; //TEST
+    int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+    const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(element.type(), orderQR);
+
+    for(const auto& quadPoint : quad)
+    {
+      const auto& quadPos = quadPoint.position();
+      const double integrationElement = element.geometry().integrationElement(quadPos);
+      area += quadPoint.weight() * integrationElement;
+      
+      r += localfun(quadPos) * quadPoint.weight() * integrationElement;
+    }
+  }
+  //     std::cout << "Domain-Area: " << area << std::endl;
+  return (1.0/area) * r ;
+}
+
+
+auto subtractIntegralMean(VectorCT& coeffVector)
+{
+  // Substract correct Integral mean from each associated component function
+  auto IM = integralMean(coeffVector);
+
+  for(size_t k=0; k<dim; k++)
+  {
+    //std::cout << "Integral-Mean: " << IM[k] << std::endl;
+    auto idx = childToIndexMap(k);
+    for ( int i : idx)
+      coeffVector[i] -= IM[k];
+  }
+}
+
+
+// -----------------------------------------------------------------
+// --- Solving the Corrector-problem:
+auto solve()
+{
+
+    bool set_oneBasisFunction_Zero = parameterSet_.get<bool>("set_oneBasisFunction_Zero", false);
+    bool substract_integralMean = false;
+    if(parameterSet_.get<bool>("set_IntegralZero", false))
+    {
+        set_oneBasisFunction_Zero = true;
+        substract_integralMean = true;
+    }
+    // set one basis-function to zero
+    if(set_oneBasisFunction_Zero)
+        setOneBaseFunctionToZero();
+
+    //TEST: Compute Condition Number  (Can be very expensive !) 
+    const bool verbose = true;
+    const unsigned int arppp_a_verbosity_level = 2;
+    const unsigned int pia_verbosity_level = 1;
+    MatrixInfo<MatrixCT> matrixInfo(stiffnessMatrix_,verbose,arppp_a_verbosity_level,pia_verbosity_level);
+    std::cout << "Get condition number of Stiffness_CE: " << matrixInfo.getCond2(true) << std::endl;
+
+    ///////////////////////////////////
+    // --- Choose Solver ---
+    // 1 : CG-Solver
+    // 2 : GMRES
+    // 3 : QR (default)
+    // 4 : UMFPACK
+    ///////////////////////////////////
+    unsigned int Solvertype = parameterSet_.get<unsigned int>("Solvertype", 3);
+    unsigned int Solver_verbosity = parameterSet_.get<unsigned int>("Solver_verbosity", 2);
+
+    // --- set initial values for solver
+    x_1_ = load_alpha1_;
+    x_2_ = load_alpha2_;
+    x_3_ = load_alpha3_;
+
+    Dune::Timer SolverTimer;
+    if (Solvertype==1)  // CG - SOLVER
+    {
+        std::cout << "------------ CG - Solver ------------" << std::endl;
+        MatrixAdapter<MatrixCT, VectorCT, VectorCT> op(stiffnessMatrix_);
+
+        // Sequential incomplete LU decomposition as the preconditioner
+        SeqILU<MatrixCT, VectorCT, VectorCT> ilu0(stiffnessMatrix_,1.0);
+        int iter = parameterSet_.get<double>("iterations_CG", 999);
+        // Preconditioned conjugate-gradient solver
+        CGSolver<VectorCT> solver(op,
+                                ilu0, //NULL,
+                                1e-8, // desired residual reduction factorlack
+                                iter,   // maximum number of iterations
+                                Solver_verbosity,
+                                true    // Try to estimate condition_number
+                                 );   // verbosity of the solver
+        InverseOperatorResult statistics;
+        std::cout << "solve linear system for x_1.\n";
+        solver.apply(x_1_, load_alpha1_, statistics);
+        std::cout << "solve linear system for x_2.\n";
+        solver.apply(x_2_, load_alpha2_, statistics);
+        std::cout << "solve linear system for x_3.\n";
+        solver.apply(x_3_, load_alpha3_, statistics);
+        log_ << "Solver-type used: " <<" CG-Solver" << std::endl;
+
+        std::cout << "statistics.converged " << statistics.converged << std::endl;
+        std::cout << "statistics.condition_estimate: " << statistics.condition_estimate << std::endl;
+        std::cout << "statistics.iterations: " << statistics.iterations << std::endl;
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    else if (Solvertype==2)  // GMRES - SOLVER
+    {
+        std::cout << "------------ GMRES - Solver ------------" << std::endl;
+        // Turn the matrix into a linear operator
+        MatrixAdapter<MatrixCT,VectorCT,VectorCT> stiffnessOperator(stiffnessMatrix_);
+
+        // Fancy (but only) way to not have a preconditioner at all
+        Richardson<VectorCT,VectorCT> preconditioner(1.0);
+
+        // Construct the iterative solver
+        RestartedGMResSolver<VectorCT> solver(
+            stiffnessOperator, // Operator to invert
+            preconditioner,    // Preconditioner
+            1e-10,             // Desired residual reduction factor
+            500,               // Number of iterations between restarts,
+                            // here: no restarting
+            500,               // Maximum number of iterations
+            Solver_verbosity);                // Verbosity of the solver
+
+        // Object storing some statistics about the solving process
+        InverseOperatorResult statistics;
+
+        // solve for different Correctors (alpha = 1,2,3)
+        solver.apply(x_1_, load_alpha1_, statistics);     //load_alpha1 now contains the corresponding residual!!
+        solver.apply(x_2_, load_alpha2_, statistics);
+        solver.apply(x_3_, load_alpha3_, statistics);
+        log_ << "Solver-type used: " <<" GMRES-Solver" << std::endl;
+        
+        std::cout << "statistics.converged " << statistics.converged << std::endl;
+        std::cout << "statistics.condition_estimate: " << statistics.condition_estimate << std::endl;
+        std::cout << "statistics.iterations: " << statistics.iterations << std::endl;
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    else if ( Solvertype==3)// QR - SOLVER
+    {
+        std::cout << "------------ QR - Solver ------------" << std::endl;
+        log_ << "solveLinearSystems: We use QR solver.\n";
+        //TODO install suitesparse
+        SPQR<MatrixCT> sPQR(stiffnessMatrix_);
+        sPQR.setVerbosity(1);
+        InverseOperatorResult statisticsQR;
+
+        sPQR.apply(x_1_, load_alpha1_, statisticsQR);
+        std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+        std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+        std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+        sPQR.apply(x_2_, load_alpha2_, statisticsQR);
+        std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+        std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+        std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+        sPQR.apply(x_3_, load_alpha3_, statisticsQR);
+        std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+        std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+        std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+        log_ << "Solver-type used: " <<" QR-Solver" << std::endl;
+
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    else if (Solvertype==4)// UMFPACK - SOLVER
+    {
+        std::cout << "------------ UMFPACK - Solver ------------" << std::endl;
+        log_ << "solveLinearSystems: We use UMFPACK solver.\n";
+        
+        Dune::Solvers::UMFPackSolver<MatrixCT,VectorCT> solver;
+        solver.setProblem(stiffnessMatrix_,x_1_,load_alpha1_);
+//         solver.preprocess();
+        solver.solve();
+        solver.setProblem(stiffnessMatrix_,x_2_,load_alpha2_);
+//         solver.preprocess();
+        solver.solve();
+        solver.setProblem(stiffnessMatrix_,x_3_,load_alpha3_);
+//         solver.preprocess();
+        solver.solve();
+//         sPQR.apply(x_1, load_alpha1, statisticsQR);
+//         std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+//         std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+//         std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+//         sPQR.apply(x_2, load_alpha2, statisticsQR);
+//         std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+//         std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+//         std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+//         sPQR.apply(x_3, load_alpha3, statisticsQR);
+//         std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+//         std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+//         std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+        log_ << "Solver-type used: " <<" UMFPACK-Solver" << std::endl;
+    }
+    std::cout <<  "Finished solving Corrector problems!" << std::endl;
+    std::cout << "Time for solving:" << SolverTimer.elapsed() << std::endl;
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // Extract phi_alpha  &  M_alpha coefficients
+    ////////////////////////////////////////////////////////////////////////////////////
+    phi_1_.resize(basis_.size());
+    phi_1_ = 0;
+    phi_2_.resize(basis_.size());
+    phi_2_ = 0;
+    phi_3_.resize(basis_.size());
+    phi_3_ = 0;
+
+    for(size_t i=0; i<basis_.size(); i++)
+    {
+        phi_1_[i] = x_1_[i];
+        phi_2_[i] = x_2_[i];
+        phi_3_[i] = x_3_[i];
+    }
+    for(size_t i=0; i<3; i++)
+    {
+        m_1_[i] = x_1_[phiOffset_+i];
+        m_2_[i] = x_2_[phiOffset_+i];
+        m_3_[i] = x_3_[phiOffset_+i];
+    }
+    // assemble M_alpha's (actually iota(M_alpha) )
+
+    // MatrixRT M_1(0), M_2(0), M_3(0);
+
+    M1_ = 0;
+    M2_ = 0;
+    M3_ = 0;
+
+    for(size_t i=0; i<3; i++)
+    {
+        M1_ += m_1_[i]*basisContainer_[i];
+        M2_ += m_2_[i]*basisContainer_[i];
+        M3_ += m_3_[i]*basisContainer_[i];
+    }
+
+    std::cout << "--- plot corrector-Matrices M_alpha --- " << std::endl;
+    printmatrix(std::cout, M1_, "Corrector-Matrix M_1", "--");
+    printmatrix(std::cout, M2_, "Corrector-Matrix M_2", "--");
+    printmatrix(std::cout, M3_, "Corrector-Matrix M_3", "--");
+    log_ << "---------- OUTPUT ----------" << std::endl;
+    log_ << " --------------------" << std::endl;
+    log_ << "Corrector-Matrix M_1: \n" << M1_ << std::endl;
+    log_ << " --------------------" << std::endl;
+    log_ << "Corrector-Matrix M_2: \n" << M2_ << std::endl;
+    log_ << " --------------------" << std::endl;
+    log_ << "Corrector-Matrix M_3: \n" << M3_ << std::endl;
+    log_ << " --------------------" << std::endl;
+
+
+    if(parameterSet_.get<bool>("write_IntegralMean", false))
+    {
+        std::cout << "check integralMean phi_1: " << std::endl;
+        auto A = integralMean(phi_1_);
+        for(size_t i=0; i<3; i++)
+        {
+            std::cout << "Integral-Mean phi_1 : " << A[i] << std::endl;
+        }
+    }
+    if(substract_integralMean)
+    {
+        std::cout << " --- substracting integralMean --- " << std::endl;
+        subtractIntegralMean(phi_1_);
+        subtractIntegralMean(phi_2_);
+        subtractIntegralMean(phi_3_);
+        subtractIntegralMean(x_1_);
+        subtractIntegralMean(x_2_);
+        subtractIntegralMean(x_3_);
+        //////////////////////////////////////////
+        // Check Integral-mean again:
+        //////////////////////////////////////////
+        if(parameterSet_.get<bool>("write_IntegralMean", false))
+        {
+            auto A = integralMean(phi_1_);
+            for(size_t i=0; i<3; i++)
+            {
+            std::cout << "Integral-Mean phi_1 (Check again)  : " << A[i] << std::endl;
+            }
+        }
+    }
+    /////////////////////////////////////////////////////////
+    // Write Solution (Corrector Coefficients) in Logs
+    /////////////////////////////////////////////////////////
+    if(parameterSet_.get<bool>("write_corrector_phi1", false))
+    {
+        log_ << "\nSolution of Corrector problems:\n";
+        log_ << "\n Corrector_phi1:\n";
+        log_ << x_1_ << std::endl;
+    }
+    if(parameterSet_.get<bool>("write_corrector_phi2", false))
+    {
+        log_ << "-----------------------------------------------------";
+        log_ << "\n Corrector_phi2:\n";
+        log_ << x_2_ << std::endl;
+    }
+    if(parameterSet_.get<bool>("write_corrector_phi3", false))
+    {
+        log_ << "-----------------------------------------------------";
+        log_ << "\n Corrector_phi3:\n";
+        log_ << x_3_ << std::endl;
+    }
+
+}
+
+
+// -----------------------------------------------------------------
+// --- Write Correctos to VTK:
+void writeCorrectorsVTK(const int level)
+{
+    std::string vtkOutputName = parameterSet_.get("outputPath", "../../outputs") + "/CellProblem-result"; 
+    std::cout << "vtkOutputName:" << vtkOutputName << std::endl;
+
+    VTKWriter<typename Basis::GridView> vtkWriter(basis_.gridView());
+    vtkWriter.addVertexData(
+        Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_, phi_1_),
+        VTK::FieldInfo("Corrector phi_1 level"+ std::to_string(level) , VTK::FieldInfo::Type::vector, dim));     
+    vtkWriter.addVertexData(
+        Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_, phi_2_),
+        VTK::FieldInfo("Corrector phi_2 level"+ std::to_string(level) , VTK::FieldInfo::Type::vector, dim));
+    vtkWriter.addVertexData(
+        Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_, phi_3_),
+        VTK::FieldInfo("Corrector phi_3 level"+ std::to_string(level) , VTK::FieldInfo::Type::vector, dim));
+    vtkWriter.write(vtkOutputName  + "-level"+ std::to_string(level));
+    std::cout << "wrote Corrector-VTK data to file: " + vtkOutputName + "-level" + std::to_string(level) << std::endl;
+}
+
+// -----------------------------------------------------------------
+// --- Compute norms of the corrector functions:
+void computeNorms()
+{
+    computeL2Norm();
+    computeL2SymGrad();
+}
+
+void computeL2Norm()
+{
+  // IMPLEMENTATION with makeDiscreteGlobalBasisFunction
+  double error_1 = 0.0;
+  double error_2 = 0.0;
+  double error_3 = 0.0;
+
+  auto localView = basis_.localView();
+  auto GVFunc_1 = Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_1_);
+  auto GVFunc_2 = Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_2_);
+  auto GVFunc_3 = Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_3_);
+  auto localfun_1 = localFunction(GVFunc_1);
+  auto localfun_2 = localFunction(GVFunc_2);
+  auto localfun_3 = localFunction(GVFunc_3);
+
+  for(const auto& element : elements(basis_.gridView()))
+  {
+    localView.bind(element);
+    localfun_1.bind(element);
+    localfun_2.bind(element);
+    localfun_3.bind(element);
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();
+
+    int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+    const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(element.type(), orderQR);
+
+    for(const auto& quadPoint : quad)
+    {
+      const auto& quadPos = quadPoint.position();
+      const double integrationElement = element.geometry().integrationElement(quadPos);
+      error_1 += localfun_1(quadPos)*localfun_1(quadPos) * quadPoint.weight() * integrationElement;
+      error_2 += localfun_2(quadPos)*localfun_2(quadPos) * quadPoint.weight() * integrationElement;
+      error_3 += localfun_3(quadPos)*localfun_3(quadPos) * quadPoint.weight() * integrationElement;
+    }
+  }
+  std::cout << "L2-Norm(Corrector phi_1): " << sqrt(error_1) << std::endl;
+  std::cout << "L2-Norm(Corrector phi_2): " << sqrt(error_2) << std::endl;
+  std::cout << "L2-Norm(Corrector phi_3): " << sqrt(error_3) << std::endl;
+
+  return;
+}
+
+void computeL2SymGrad()
+{
+  double error_1 = 0.0;
+  double error_2 = 0.0;
+  double error_3 = 0.0;
+
+  auto localView = basis_.localView();
+
+  auto GVFunc_1 = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_1_));
+  auto GVFunc_2 = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_2_));
+  auto GVFunc_3 = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_3_));
+  auto localfun_1 = localFunction(GVFunc_1);
+  auto localfun_2 = localFunction(GVFunc_2);
+  auto localfun_3 = localFunction(GVFunc_3);
+
+  for (const auto& element : elements(basis_.gridView()))
+  {
+    localView.bind(element);
+    localfun_1.bind(element);
+    localfun_2.bind(element);
+    localfun_3.bind(element);
+    auto geometry = element.geometry();
+
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();             
+    const auto nSf = localFiniteElement.localBasis().size();
+
+    int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1 );  
+    const auto& quad = QuadratureRules<double,dim>::rule(element.type(), orderQR);
+
+    for (const auto& quadPoint : quad)
+    {
+        const auto& quadPos = quadPoint.position();
+        const auto integrationElement = geometry.integrationElement(quadPos);
+
+        auto scaledSymGrad1 = sym(crossSectionDirectionScaling(1.0/gamma_, localfun_1(quadPos)));
+        auto scaledSymGrad2 = sym(crossSectionDirectionScaling(1.0/gamma_, localfun_2(quadPos)));
+        auto scaledSymGrad3 = sym(crossSectionDirectionScaling(1.0/gamma_, localfun_3(quadPos)));
+
+        error_1 += scalarProduct(scaledSymGrad1,scaledSymGrad1) * quadPoint.weight() * integrationElement;
+        error_2 += scalarProduct(scaledSymGrad2,scaledSymGrad2) * quadPoint.weight() * integrationElement;
+        error_3 += scalarProduct(scaledSymGrad3,scaledSymGrad3) * quadPoint.weight() * integrationElement;
+    }
+  }
+  std::cout << "L2-Norm(Symmetric scaled gradient of Corrector phi_1): " << sqrt(error_1) << std::endl;
+  std::cout << "L2-Norm(Symmetric scaled gradient of Corrector phi_2): " << sqrt(error_2) << std::endl;
+  std::cout << "L2-Norm(Symmetric scaled gradient of Corrector phi_3): " << sqrt(error_3) << std::endl;
+  return;
+}
+
+
+
+// -----------------------------------------------------------------
+// --- Check Orthogonality relation Paper (75)
+
+
+
+auto check_Orthogonality()
+{
+  std::cout << "CHECK ORTHOGONALITY" << std::endl;
+
+  auto localView = basis_.localView();
+
+  auto GVFunc_1 = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_1_));
+  auto GVFunc_2 = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_2_));
+  auto GVFunc_3 = derivative(Functions::makeDiscreteGlobalBasisFunction<VectorRT>(basis_,phi_3_));
+  auto localfun_1 = localFunction(GVFunc_1);
+  auto localfun_2 = localFunction(GVFunc_2);
+  auto localfun_3 = localFunction(GVFunc_3);
+  const std::array<decltype(localfun_1)*,3> phiDerContainer = {&localfun_1 , &localfun_2 , &localfun_3 };
+
+
+  auto muGridF  = makeGridViewFunction(mu_, basis_.gridView());
+  auto mu = localFunction(muGridF);
+  auto lambdaGridF  = makeGridViewFunction(lambda_, basis_.gridView());
+  auto lambda= localFunction(lambdaGridF);
+
+  for(int a=0; a<3; a++)
+  for(int b=0; b<3; b++)
+  {
+    double energy = 0.0;
+
+    auto DerPhi1 = *phiDerContainer[a];
+    auto DerPhi2 = *phiDerContainer[b];
+    
+    auto matrixFieldGGVF  = Dune::Functions::makeGridViewFunction(x3MatrixBasis_[a], basis_.gridView());
+    auto matrixFieldG = localFunction(matrixFieldGGVF);
+    //   auto matrixFieldBGVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncB, basis.gridView());
+    //   auto matrixFieldB = localFunction(matrixFieldBGVF);
+
+    //   using GridView = typename Basis::GridView;
+    //   using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate;
+    //   using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>;
+    
+    //   std::cout << "Press key.." << std::endl;
+    //   std::cin.get();
+    
+    //   TEST
+    //   FieldVector<double,3> testvector = {1.0 , 1.0 , 1.0};
+    //   printmatrix(std::cout, matrixFieldFuncB(testvector) , "matrixFieldB(testvector) ", "--");
+
+    for (const auto& e : elements(basis_.gridView()))
+    {
+        localView.bind(e);
+        matrixFieldG.bind(e);
+        DerPhi1.bind(e);
+        DerPhi2.bind(e);
+        mu.bind(e);
+        lambda.bind(e);
+
+        double elementEnergy = 0.0;
+        //double elementEnergy_HP = 0.0;
+
+        auto geometry = e.geometry();
+        const auto& localFiniteElement = localView.tree().child(0).finiteElement();
+
+        int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+    //     int orderQR = 0;
+    //     int orderQR = 1;
+    //     int orderQR = 2;
+    //     int orderQR = 3;
+        const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(e.type(), orderQR);
+
+        for (const auto& quadPoint : quad) 
+        {
+        const auto& quadPos = quadPoint.position();
+        const double integrationElement = geometry.integrationElement(quadPos);
+        
+        
+        auto Chi = sym(crossSectionDirectionScaling(1.0/gamma_, DerPhi2(quadPos))) + *mContainer[b];
+
+        auto strain1 = DerPhi1(quadPos);
+    //       printmatrix(std::cout, strain1 , "strain1", "--");
+        //cale with GAMMA
+        strain1 = crossSectionDirectionScaling(1.0/gamma_, strain1);
+        strain1 = sym(strain1);
+        
+        
+        // ADD M 
+    //       auto test = strain1 + *M ; 
+    //       std::cout << "test:" << test << std::endl;
+        
+    //       for (size_t m=0; m<3; m++ )
+    //       for (size_t n=0; n<3; n++ )
+    //           strain1[m][n] += M[m][n];
+        
+        auto G = matrixFieldG(quadPos);
+    //       auto G = matrixFieldG(e.geometry().global(quadPos)); //TEST
+        
+        auto tmp = G + *mContainer[a] + strain1;
+
+        double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), tmp, Chi);
+
+        elementEnergy += energyDensity * quadPoint.weight() * integrationElement;    
+        
+    //       elementEnergy += strain1 * quadPoint.weight() * integrationElement;        
+        //elementEnergy_HP += energyDensity * quadPoint.weight() * integrationElement;
+        }
+        energy += elementEnergy;
+        //higherPrecEnergy += elementEnergy_HP;
+    }
+    std::cout << "check_Orthogonality:" << "("<< a <<"," << b << "): " << energy << std::endl;
+    //   TEST
+    //   std::cout << std::setprecision(std::numeric_limits<float_50>::digits10) << higherPrecEnergy << std::endl;
+  }
+
+  return 0;
+}
+
+
+
+
+
+
+}; // end class
+
+#endif
\ No newline at end of file
diff --git a/src/Cell-Problem-New.cc b/src/Cell-Problem-New.cc
new file mode 100644
index 00000000..8c91ae68
--- /dev/null
+++ b/src/Cell-Problem-New.cc
@@ -0,0 +1,2746 @@
+#include <config.h>
+#include <array>
+#include <vector>
+#include <fstream>
+
+#include <iostream>
+#include <dune/common/indices.hh>
+#include <dune/common/bitsetvector.hh>
+#include <dune/common/parametertree.hh>
+#include <dune/common/parametertreeparser.hh>
+#include <dune/common/float_cmp.hh>
+#include <dune/common/math.hh>
+
+
+
+#include <dune/geometry/quadraturerules.hh>
+
+#include <dune/grid/uggrid.hh>
+#include <dune/grid/yaspgrid.hh>
+#include <dune/grid/utility/structuredgridfactory.hh> //TEST
+
+#include <dune/grid/io/file/vtk/subsamplingvtkwriter.hh>
+
+#include <dune/istl/matrix.hh>
+#include <dune/istl/bcrsmatrix.hh>
+#include <dune/istl/multitypeblockmatrix.hh>
+#include <dune/istl/multitypeblockvector.hh>
+#include <dune/istl/matrixindexset.hh>
+#include <dune/istl/solvers.hh>
+#include <dune/istl/spqr.hh>
+#include <dune/istl/preconditioners.hh>
+#include <dune/istl/io.hh>
+
+#include <dune/functions/functionspacebases/interpolate.hh>
+
+#include <dune/functions/backends/istlvectorbackend.hh>
+#include <dune/functions/functionspacebases/powerbasis.hh>
+#include <dune/functions/functionspacebases/compositebasis.hh>
+
+#include <dune/functions/functionspacebases/lagrangebasis.hh>
+#include <dune/functions/functionspacebases/periodicbasis.hh>
+
+#include <dune/functions/functionspacebases/subspacebasis.hh>
+#include <dune/functions/functionspacebases/boundarydofs.hh>
+#include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh>
+#include <dune/functions/gridfunctions/gridviewfunction.hh>
+
+#include <dune/common/fvector.hh>
+#include <dune/common/fmatrix.hh>
+
+#include <dune/microstructure/prestrain_material_geometry.hh>
+#include <dune/microstructure/matrix_operations.hh>
+#include <dune/microstructure/vtk_filler.hh>    //TEST
+#include <dune/microstructure/CorrectorComputer.hh>    //TEST
+
+#include <dune/solvers/solvers/umfpacksolver.hh>  //TEST 
+
+
+#include <dune/istl/eigenvalue/test/matrixinfo.hh> // TEST: compute condition Number 
+
+#include <dune/functions/functionspacebases/hierarchicvectorwrapper.hh>
+
+#include <dune/fufem/dunepython.hh>
+#include <python2.7/Python.h>
+
+// #include <dune/fufem/discretizationerror.hh>
+// #include <boost/multiprecision/cpp_dec_float.hpp>
+// #include <boost/any.hpp>
+
+#include <any>
+#include <variant>
+#include <string>
+#include <iomanip>   // needed when working with relative paths e.g. from python-scripts
+
+using namespace Dune;
+using namespace MatrixOperations;
+
+
+//////////////////////////////////////////////////////////////////////
+// Helper functions for Table-Output
+//////////////////////////////////////////////////////////////////////
+/*! Center-aligns string within a field of width w. Pads with blank spaces
+    to enforce alignment. */
+std::string center(const std::string s, const int w) {
+    std::stringstream ss, spaces;
+    int padding = w - s.size();                 // count excess room to pad
+    for(int i=0; i<padding/2; ++i)
+        spaces << " ";
+    ss << spaces.str() << s << spaces.str();    // format with padding
+    if(padding>0 && padding%2!=0)               // if odd #, add 1 space
+        ss << " ";
+    return ss.str();
+}
+
+/* Convert double to string with specified number of places after the decimal
+   and left padding. */
+template<class type>
+std::string prd(const type x, const int decDigits, const int width) {
+    std::stringstream ss;
+//     ss << std::fixed << std::right;
+    ss << std::scientific << std::right;                     // Use scientific Output!
+    ss.fill(' ');        // fill space around displayed #
+    ss.width(width);     // set  width around displayed #
+    ss.precision(decDigits); // set # places after decimal
+    ss << x;
+    return ss.str();
+}
+
+
+
+
+template<class Basis, class Matrix>
+void checkSymmetry(const Basis& basis,
+                    Matrix& matrix
+                  )
+{
+  std::cout << "--- Check Symmetry ---" << std::endl;
+
+  auto localView = basis.localView();
+  const int phiOffset = basis.dimension();
+
+  for (const auto& element : elements(basis.gridView()))
+  {
+    localView.bind(element);
+
+    const int localPhiOffset = localView.size();
+
+    for (size_t i=0; i<localPhiOffset; i++)
+    for (size_t j=0; j<localPhiOffset; j++ )
+    {
+        auto row = localView.index(i);
+        auto col = localView.index(j);
+        if(abs( matrix[row][col] - matrix[col][row]) > 1e-12 )
+            std::cout << "STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl;
+    }
+    for (size_t i=0; i<localPhiOffset; i++)
+    for(size_t m=0; m<3; m++)
+    {
+        auto row = localView.index(i);
+        if(abs( matrix[row][phiOffset+m] - matrix[phiOffset+m][row]) > 1e-12 )
+            std::cout << "STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl;
+
+    }
+    for (size_t m=0; m<3; m++ )
+    for (size_t n=0; n<3; n++ )
+    {
+        if(abs( matrix[phiOffset+m][phiOffset+n] - matrix[phiOffset+n][phiOffset+m]) > 1e-12 )
+            std::cout << "STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl;
+    }
+
+  }
+  std::cout << "--- Symmetry test passed ---" << std::endl;
+}
+
+
+
+
+template<class Basis>
+auto arbitraryComponentwiseIndices(const Basis& basis,
+                                   const int elementNumber,
+                                   const int leafIdx
+                                   )
+{
+  // (Local Approach -- works for non Lagrangian-Basis too)
+  // Input  : elementNumber & localIdx
+  // Output : determine all Component-Indices that correspond to that basis-function
+  auto localView = basis.localView();
+
+  FieldVector<int,3> row;
+  int elementCounter = 0;
+
+  for (const auto& element : elements(basis.gridView()))
+  {
+    if(elementCounter == elementNumber)             // get arbitraryIndex(global) for each Component        ..alternativ:gridView.indexSet
+    {
+      localView.bind(element);
+
+      for (int k = 0; k < 3; k++)
+      {
+        auto rowLocal = localView.tree().child(k).localIndex(leafIdx);    //Input: LeafIndex! TODO bräuchte hier (Inverse )  Local-to-Leaf Idx Map
+        row[k] = localView.index(rowLocal);
+        //         std::cout << "rowLocal:" << rowLocal << std::endl;
+        //         std::cout << "row[k]:" << row[k] << std::endl;
+      }
+    }
+    elementCounter++;
+  }
+  return row;
+}
+
+
+
+
+template<class LocalView, class Matrix, class localFunction1, class localFunction2>
+void computeElementStiffnessMatrix(const LocalView& localView,
+                                   Matrix& elementMatrix,
+                                   const localFunction1& mu,
+                                   const localFunction2& lambda,
+                                   const double gamma
+                                   )
+{
+  // Local StiffnessMatrix of the form:
+  // | phi*phi    m*phi |
+  // | phi *m     m*m   |
+  using Element = typename LocalView::Element;
+  const Element element = localView.element();
+  auto geometry = element.geometry();
+  constexpr int dim = Element::dimension;
+  constexpr int dimWorld = dim;
+  using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>;
+
+  elementMatrix.setSize(localView.size()+3, localView.size()+3);         //extend by dim ´R_sym^{2x2}
+  elementMatrix = 0;
+
+  // LocalBasis-Offset
+  const int localPhiOffset = localView.size();
+
+  const auto& localFiniteElement = localView.tree().child(0).finiteElement();     
+  const auto nSf = localFiniteElement.localBasis().size();
+//   std::cout << "localView.size(): " << localView.size() << std::endl;
+//   std::cout << "nSf : " << nSf << std::endl;
+
+  ///////////////////////////////////////////////
+  // Basis for R_sym^{2x2}            // wird nicht als Funktion benötigt da konstant...
+  //////////////////////////////////////////////
+  MatrixRT G_1 {{1.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
+  MatrixRT G_2 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 0.0}};
+  MatrixRT G_3 {{0.0, 1.0/sqrt(2.0), 0.0}, {1.0/sqrt(2.0), 0.0, 0.0}, {0.0, 0.0, 0.0}};
+  std::array<MatrixRT,3 > basisContainer = {G_1, G_2, G_3};
+
+//   int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5;  // TEST
+  int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+//   int orderQR = 0;
+//   int orderQR = 1;
+//   int orderQR = 2;
+//   int orderQR = 3;
+  const auto& quad = QuadratureRules<double,dim>::rule(element.type(), orderQR);
+  
+//   double elementContribution = 0.0;
+  
+//   std::cout << "Print QuadratureOrder:" << orderQR << std::endl;  //TEST`
+
+  int QPcounter= 0;
+  for (const auto& quadPoint : quad)
+  {
+    QPcounter++;
+    const auto& quadPos = quadPoint.position();
+    const auto jacobianInverseTransposed = geometry.jacobianInverseTransposed(quadPos);
+    const auto integrationElement = geometry.integrationElement(quadPos);
+
+    std::vector< FieldMatrix< double, 1, dim> > referenceGradients;
+    localFiniteElement.localBasis().evaluateJacobian(quadPos,
+                                                     referenceGradients);
+    // Compute the shape function gradients on the grid element
+    std::vector<FieldVector<double,dim> > gradients(referenceGradients.size());
+
+    for (size_t i=0; i<gradients.size(); i++)
+      jacobianInverseTransposed.mv(referenceGradients[i][0], gradients[i]);
+
+    for (size_t l=0; l< dimWorld; l++)
+    for (size_t j=0; j < nSf; j++ )
+    {
+        size_t row = localView.tree().child(l).localIndex(j);
+        // (scaled)  Deformation gradient of the test basis function
+        MatrixRT defGradientV(0);
+        defGradientV[l][0] = gradients[j][0];                       // Y
+        defGradientV[l][1] = gradients[j][1];                       //X2
+//         defGradientV[l][2] = (1.0/gamma)*gradients[j][2];           //X3
+        defGradientV[l][2] = gradients[j][2];           //X3
+        
+        defGradientV = crossSectionDirectionScaling((1.0/gamma),defGradientV);
+        // "phi*phi"-part
+        for (size_t k=0; k < dimWorld; k++)
+        for (size_t i=0; i < nSf; i++)
+        {
+            // (scaled) Deformation gradient of the ansatz basis function
+            MatrixRT defGradientU(0);
+            defGradientU[k][0] = gradients[i][0];                       // Y
+            defGradientU[k][1] = gradients[i][1];                       //X2
+//             defGradientU[k][2] = (1.0/gamma)*gradients[i][2];           //X3
+            defGradientU[k][2] = gradients[i][2];           //X3
+            // printmatrix(std::cout, defGradientU , "defGradientU", "--");
+            defGradientU = crossSectionDirectionScaling((1.0/gamma),defGradientU);
+
+            double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), defGradientU, defGradientV);
+//             double energyDensity = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), defGradientU, defGradientV); //TEST
+//             double energyDensity = generalizedDensity(mu(quadPos), lambda(quadPos), defGradientU, defGradientV);  // also works..
+
+            size_t col = localView.tree().child(k).localIndex(i);                       
+            
+            elementMatrix[row][col] += energyDensity * quadPoint.weight() * integrationElement;
+        }
+            
+        // "m*phi"  & "phi*m" - part
+        for( size_t m=0; m<3; m++)
+        {
+            double energyDensityGphi = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], defGradientV);
+//             double energyDensityGphi = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), basisContainer[m], defGradientV); //TEST 
+            auto value = energyDensityGphi * quadPoint.weight() * integrationElement;
+            elementMatrix[row][localPhiOffset+m] += value;
+            elementMatrix[localPhiOffset+m][row] += value;
+        }
+          
+    }
+    // "m*m"-part
+    for(size_t m=0; m<3; m++)                //TODO ist symmetric.. reicht die hälfte zu berechnen!!!
+      for(size_t n=0; n<3; n++)
+      {
+          
+//        std::cout << "QPcounter: " << QPcounter << std::endl; 
+//         std::cout << "m= " << m  << "   n = " << n << std::endl;
+//         printmatrix(std::cout, basisContainer[m] , "basisContainer[m]", "--");
+//         printmatrix(std::cout, basisContainer[n] , "basisContainer[n]", "--");
+//         std::cout  << "integrationElement:" << integrationElement << std::endl;
+//         std::cout << "quadPoint.weight(): "<< quadPoint.weight() << std::endl;
+//         std::cout << "mu(quadPos): " << mu(quadPos) << std::endl;
+//         std::cout << "lambda(quadPos): " << lambda(quadPos) << std::endl;
+        
+
+        double energyDensityGG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), basisContainer[m], basisContainer[n]);
+//         double energyDensityGG = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), basisContainer[m], basisContainer[n]); //TEST 
+        elementMatrix[localPhiOffset+m][localPhiOffset+n]  += energyDensityGG * quadPoint.weight() * integrationElement;                           // += !!!!! (Fixed-Bug)
+        
+//         std::cout  << "energyDensityGG:" << energyDensityGG<< std::endl;
+//         std::cout << "product " << energyDensityGG * quadPoint.weight() * integrationElement << std::endl;
+//         printmatrix(std::cout, elementMatrix, "elementMatrix", "--");
+
+      }
+  }
+  
+//   std::cout << "Number of QuadPoints:" << QPcounter << std::endl;
+//   printmatrix(std::cout, elementMatrix, "elementMatrix", "--");
+}
+
+
+
+// Get the occupation pattern of the stiffness matrix
+template<class Basis, class ParameterSet>
+void getOccupationPattern(const Basis& basis, MatrixIndexSet& nb, ParameterSet& parameterSet)
+{
+  //  OccupationPattern:
+  // | phi*phi    m*phi |
+  // | phi *m     m*m   |
+
+  auto localView = basis.localView();
+  const int phiOffset = basis.dimension();
+
+  nb.resize(basis.size()+3, basis.size()+3);
+
+  for (const auto& element : elements(basis.gridView()))
+  {
+    localView.bind(element);
+    for (size_t i=0; i<localView.size(); i++)
+    {
+      // The global index of the i-th vertex of the element
+      auto row = localView.index(i);
+      for (size_t j=0; j<localView.size(); j++ )
+      {
+        // The global index of the j-th vertex of the element
+        auto col = localView.index(j);
+        nb.add(row[0],col[0]);                   // nun würde auch nb.add(row,col) gehen..
+      }
+    }
+    for (size_t i=0; i<localView.size(); i++)
+    {
+      auto row = localView.index(i);
+
+      for (size_t j=0; j<3; j++ )
+      {
+        nb.add(row,phiOffset+j);               // m*phi part of StiffnessMatrix
+        nb.add(phiOffset+j,row);               // phi*m part of StiffnessMatrix
+      }
+    }
+    for (size_t i=0; i<3; i++ )
+      for (size_t j=0; j<3; j++ )
+      {
+        nb.add(phiOffset+i,phiOffset+j);       // m*m part of StiffnessMatrix
+      }
+  }
+  //////////////////////////////////////////////////////////////////
+  // setOneBaseFunctionToZero
+  //////////////////////////////////////////////////////////////////
+  if(parameterSet.template get<bool>("set_oneBasisFunction_Zero ", true)){
+    FieldVector<int,3> row;
+    unsigned int arbitraryLeafIndex =  parameterSet.template get<unsigned int>("arbitraryLeafIndex", 0);
+    unsigned int arbitraryElementNumber =  parameterSet.template get<unsigned int>("arbitraryElementNumber", 0);
+
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();    // macht keinen Unterschied ob hier k oder 0..
+    const auto nSf = localFiniteElement.localBasis().size();
+    assert(arbitraryLeafIndex < nSf );
+    assert(arbitraryElementNumber  < basis.gridView().size(0));   // "arbitraryElementNumber larger than total Number of Elements"
+
+    //Determine 3 global indices (one for each component of an arbitrary local FE-function)
+    row = arbitraryComponentwiseIndices(basis,arbitraryElementNumber,arbitraryLeafIndex);
+
+    for (int k = 0; k<3; k++)
+      nb.add(row[k],row[k]);
+  }
+}
+
+
+
+// Compute the source term for a single element
+// < L (sym[D_gamma*nabla phi_i] + M_i ), x_3G_alpha >
+template<class LocalView, class LocalFunction1, class LocalFunction2, class Vector, class LocalForce>
+void computeElementLoadVector( const LocalView& localView,
+                               LocalFunction1& mu,
+                               LocalFunction2& lambda,
+                               const double gamma,
+                               Vector& elementRhs,
+                               const LocalForce& forceTerm
+                               )
+{
+  // | f*phi|
+  // | ---  |
+  // | f*m  |
+  using Element = typename LocalView::Element;
+  const auto element = localView.element();
+  const auto geometry = element.geometry();
+  constexpr int dim = Element::dimension;
+  constexpr int dimWorld = dim;
+
+  using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>;
+
+  // Set of shape functions for a single element
+  const auto& localFiniteElement= localView.tree().child(0).finiteElement();
+  const auto nSf = localFiniteElement.localBasis().size();
+
+  elementRhs.resize(localView.size() +3);
+  elementRhs = 0;
+
+  // LocalBasis-Offset
+  const int localPhiOffset = localView.size();
+
+  ///////////////////////////////////////////////
+  // Basis for R_sym^{2x2}
+  //////////////////////////////////////////////
+  MatrixRT G_1 {{1.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
+  MatrixRT G_2 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 0.0}};
+  MatrixRT G_3 {{0.0, 1.0/sqrt(2.0), 0.0}, {1.0/sqrt(2.0), 0.0, 0.0}, {0.0, 0.0, 0.0}};
+  std::array<MatrixRT,3 > basisContainer = {G_1, G_2, G_3};
+
+//   int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5;  // TEST
+//   int orderQR = 0;
+//   int orderQR = 1;
+//   int orderQR = 2;
+//   int orderQR = 3;
+  int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);  
+  const auto& quad = QuadratureRules<double,dim>::rule(element.type(), orderQR);
+//   std::cout << "Quad-Rule order used: " << orderQR << std::endl;
+
+  for (const auto& quadPoint : quad)
+  {
+    const FieldVector<double,dim>& quadPos = quadPoint.position();
+    const auto jacobian = geometry.jacobianInverseTransposed(quadPos);
+    const double integrationElement = geometry.integrationElement(quadPos);
+
+    std::vector<FieldMatrix<double,1,dim> > referenceGradients;
+    localFiniteElement.localBasis().evaluateJacobian(quadPos, referenceGradients);
+
+    std::vector< FieldVector< double, dim> > gradients(referenceGradients.size());  
+    for (size_t i=0; i< gradients.size(); i++)
+      jacobian.mv(referenceGradients[i][0], gradients[i]);
+    
+    //TEST
+//     std::cout << "forceTerm(element.geometry().global(quadPos)):"  << std::endl;
+//     std::cout << forceTerm(element.geometry().global(quadPos)) << std::endl;
+//     std::cout << "forceTerm(quadPos)" << std::endl;
+//     std::cout << forceTerm(quadPos) << std::endl;
+//     
+//     //TEST QUadrature 
+//     std::cout << "quadPos:" << quadPos << std::endl;
+//     std::cout << "element.geometry().global(quadPos):" << element.geometry().global(quadPos) << std::endl;
+// // //     
+// // //     
+//     std::cout << "quadPoint.weight() :" << quadPoint.weight()  << std::endl;
+//     std::cout << "integrationElement(quadPos):" << integrationElement << std::endl;
+//     std::cout << "mu(quadPos) :" << mu(quadPos) << std::endl;
+//     std::cout << "lambda(quadPos) :" << lambda(quadPos) << std::endl;
+    
+
+    // "f*phi"-part
+    for (size_t i=0; i < nSf; i++)
+      for (size_t k=0; k < dimWorld; k++)
+      {
+        // Deformation gradient of the ansatz basis function
+        MatrixRT defGradientV(0);
+        defGradientV[k][0] = gradients[i][0];                                 // Y
+        defGradientV[k][1] = gradients[i][1];                                 // X2
+//         defGradientV[k][2] = (1.0/gamma)*gradients[i][2];                     // 
+        defGradientV[k][2] = gradients[i][2];                     // X3
+        
+        defGradientV = crossSectionDirectionScaling((1.0/gamma),defGradientV);
+
+        double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos),forceTerm(quadPos), defGradientV ); 
+//         double energyDensity = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)),forceTerm(quadPos), defGradientV ); //TEST 
+//         double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos),(-1.0)*forceTerm(quadPos), defGradientV ); //TEST
+//         double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos),forceTerm(element.geometry().global(quadPos)), defGradientV ); //TEST 
+        
+        size_t row = localView.tree().child(k).localIndex(i);
+        elementRhs[row] += energyDensity * quadPoint.weight() * integrationElement;
+      }
+
+    // "f*m"-part
+    for (size_t m=0; m<3; m++)
+    {
+      double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), forceTerm(quadPos),basisContainer[m] );
+//       double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(element.geometry().global(quadPos)), lambda(element.geometry().global(quadPos)), forceTerm(quadPos),basisContainer[m] ); //TEST 
+//       double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), (-1.0)*forceTerm(quadPos),basisContainer[m] ); //TEST
+//       double energyDensityfG = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), forceTerm(element.geometry().global(quadPos)),basisContainer[m] );//TEST 
+      elementRhs[localPhiOffset+m] += energyDensityfG * quadPoint.weight() * integrationElement;
+//       std::cout << "energyDensityfG * quadPoint.weight() * integrationElement: " << energyDensityfG * quadPoint.weight() * integrationElement << std::endl;   
+    }
+  }
+}
+
+
+
+template<class Basis, class Matrix, class LocalFunction1, class LocalFunction2, class ParameterSet>
+void assembleCellStiffness(const Basis& basis,
+                           LocalFunction1& muLocal,
+                           LocalFunction2& lambdaLocal,
+                           const double gamma,
+                           Matrix& matrix,
+                           ParameterSet& parameterSet
+                           )
+{
+  std::cout << "assemble Stiffness-Matrix begins." << std::endl;
+
+  MatrixIndexSet occupationPattern;
+  getOccupationPattern(basis, occupationPattern, parameterSet);
+  occupationPattern.exportIdx(matrix);
+  matrix = 0;
+
+  auto localView = basis.localView();
+  const int phiOffset = basis.dimension();
+
+  for (const auto& element : elements(basis.gridView()))
+  {
+    localView.bind(element);
+    muLocal.bind(element);
+    lambdaLocal.bind(element);
+    const int localPhiOffset = localView.size();
+//     Dune::Timer Time;
+    //std::cout << "localPhiOffset : " << localPhiOffset << std::endl;
+    Dune::Matrix<FieldMatrix<double,1,1> > elementMatrix;
+    computeElementStiffnessMatrix(localView, elementMatrix, muLocal, lambdaLocal, gamma);
+    
+//     std::cout << "local assembly time:" << Time.elapsed() << std::endl;
+    
+    //printmatrix(std::cout, elementMatrix, "ElementMatrix", "--");
+    //std::cout << "elementMatrix.N() : " << elementMatrix.N() << std::endl;
+    //std::cout << "elementMatrix.M() : " << elementMatrix.M() << std::endl;
+    
+    //TEST
+    //Check Element-Stiffness-Symmetry:
+    for (size_t i=0; i<localPhiOffset; i++)
+    for (size_t j=0; j<localPhiOffset; j++ )
+    {
+        if(abs( elementMatrix[i][j] - elementMatrix[j][i]) > 1e-12 )
+            std::cout << "ELEMENT-STIFFNESS MATRIX NOT SYMMETRIC!!!" << std::endl;
+    }
+    //////////////////////////////////////////////////////////////////////////////
+    // GLOBAL STIFFNES ASSEMBLY
+    //////////////////////////////////////////////////////////////////////////////
+    for (size_t i=0; i<localPhiOffset; i++)
+    for (size_t j=0; j<localPhiOffset; j++ )
+    {
+        auto row = localView.index(i);
+        auto col = localView.index(j);
+        matrix[row][col] += elementMatrix[i][j];
+    }
+    for (size_t i=0; i<localPhiOffset; i++)
+    for(size_t m=0; m<3; m++)
+    {
+        auto row = localView.index(i);
+        matrix[row][phiOffset+m] += elementMatrix[i][localPhiOffset+m];
+        matrix[phiOffset+m][row] += elementMatrix[localPhiOffset+m][i];
+    }
+    for (size_t m=0; m<3; m++ )
+    for (size_t n=0; n<3; n++ )
+        matrix[phiOffset+m][phiOffset+n] += elementMatrix[localPhiOffset+m][localPhiOffset+n];
+
+    //  printmatrix(std::cout, matrix, "StiffnessMatrix", "--");
+  }
+}
+
+
+template<class Basis, class LocalFunction1, class LocalFunction2, class Vector, class Force>
+void assembleCellLoad(const Basis& basis,
+                      LocalFunction1& muLocal,
+                      LocalFunction2& lambdaLocal,
+                      const double gamma,
+                      Vector& b,
+                      const Force& forceTerm
+                      )
+{
+  //     std::cout << "assemble load vector." << std::endl;
+  b.resize(basis.size()+3);
+  b = 0;
+
+  auto localView = basis.localView();
+  const int phiOffset = basis.dimension();
+
+  // Transform G_alpha's to GridViewFunctions/LocalFunctions 
+  auto loadGVF  = Dune::Functions::makeGridViewFunction(forceTerm, basis.gridView());
+  auto loadFunctional = localFunction(loadGVF);      
+
+//   int counter = 1;
+  for (const auto& element : elements(basis.gridView()))
+  {
+    localView.bind(element);
+    muLocal.bind(element);
+    lambdaLocal.bind(element);
+    loadFunctional.bind(element);
+
+    const int localPhiOffset = localView.size();
+    //         std::cout << "localPhiOffset : " << localPhiOffset << std::endl;
+
+    BlockVector<FieldVector<double,1> > elementRhs;
+//     std::cout << "----------------------------------Element : " <<  counter << std::endl; //TEST
+//     counter++;
+    computeElementLoadVector(localView, muLocal, lambdaLocal, gamma, elementRhs, loadFunctional);
+//     computeElementLoadVector(localView, muLocal, lambdaLocal, gamma, elementRhs, forceTerm); //TEST
+//     printvector(std::cout, elementRhs, "elementRhs", "--");
+//     printvector(std::cout, elementRhs, "elementRhs", "--");
+    //////////////////////////////////////////////////////////////////////////////
+    // GLOBAL LOAD ASSEMBLY
+    //////////////////////////////////////////////////////////////////////////////
+    for (size_t p=0; p<localPhiOffset; p++)
+    {
+      auto row = localView.index(p);
+      b[row] += elementRhs[p];
+    }
+    for (size_t m=0; m<3; m++ )
+      b[phiOffset+m] += elementRhs[localPhiOffset+m];
+      //printvector(std::cout, b, "b", "--");
+  }
+}
+
+
+
+template<class Basis, class LocalFunction1, class LocalFunction2, class MatrixFunction>
+auto energy(const Basis& basis,
+            LocalFunction1& mu,
+            LocalFunction2& lambda,
+            const MatrixFunction& matrixFieldFuncA,
+            const MatrixFunction& matrixFieldFuncB)
+{
+
+//   TEST HIGHER PRECISION
+//   using float_50 = boost::multiprecision::cpp_dec_float_50;
+//   float_50 higherPrecEnergy = 0.0;
+  double energy = 0.0;
+  constexpr int dim = Basis::LocalView::Element::dimension;
+  constexpr int dimWorld = dim;
+
+  auto localView = basis.localView();
+
+  auto matrixFieldAGVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncA, basis.gridView());
+  auto matrixFieldA = localFunction(matrixFieldAGVF);
+  auto matrixFieldBGVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncB, basis.gridView());
+  auto matrixFieldB = localFunction(matrixFieldBGVF);
+
+  using GridView = typename Basis::GridView;
+  using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate;
+  using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>;
+//   TEST
+//   FieldVector<double,3> testvector = {1.0 , 1.0 , 1.0};
+//   printmatrix(std::cout, matrixFieldFuncB(testvector) , "matrixFieldB(testvector) ", "--");
+
+  for (const auto& e : elements(basis.gridView()))
+  {
+    localView.bind(e);
+    matrixFieldA.bind(e);
+    matrixFieldB.bind(e);
+    mu.bind(e);
+    lambda.bind(e);
+
+    double elementEnergy = 0.0;
+    //double elementEnergy_HP = 0.0;
+
+    auto geometry = e.geometry();
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();
+
+//     int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1 + 5 );  // TEST
+    int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+//     int orderQR = 0;
+//     int orderQR = 1;
+//     int orderQR = 2;
+//     int orderQR = 3;
+    const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(e.type(), orderQR);
+
+    for (const auto& quadPoint : quad) 
+    {
+      const auto& quadPos = quadPoint.position();
+      const double integrationElement = geometry.integrationElement(quadPos);
+
+      auto strain1 = matrixFieldA(quadPos);
+      auto strain2 = matrixFieldB(quadPos);
+
+      double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), strain1, strain2);
+
+      elementEnergy += energyDensity * quadPoint.weight() * integrationElement;          
+      //elementEnergy_HP += energyDensity * quadPoint.weight() * integrationElement;
+    }
+    energy += elementEnergy;
+    //higherPrecEnergy += elementEnergy_HP;
+  }
+//   TEST
+//   std::cout << std::setprecision(std::numeric_limits<float_50>::digits10) << higherPrecEnergy << std::endl;
+  return energy;
+}
+
+
+
+template<class Basis, class Matrix, class Vector, class ParameterSet>
+void setOneBaseFunctionToZero(const Basis& basis,
+                              Matrix& stiffnessMatrix,
+                              Vector& load_alpha1,
+                              Vector& load_alpha2,
+                              Vector& load_alpha3,
+                              ParameterSet& parameterSet
+                              )
+{
+  std::cout << "Setting one Basis-function to zero" << std::endl;
+
+  constexpr int dim = Basis::LocalView::Element::dimension;
+  
+  unsigned int arbitraryLeafIndex =  parameterSet.template get<unsigned int>("arbitraryLeafIndex", 0);
+  unsigned int arbitraryElementNumber =  parameterSet.template get<unsigned int>("arbitraryElementNumber", 0);
+  //Determine 3 global indices (one for each component of an arbitrary local FE-function)
+  FieldVector<int,3> row = arbitraryComponentwiseIndices(basis,arbitraryElementNumber,arbitraryLeafIndex);
+
+  for (int k = 0; k < dim; k++)
+  {
+    load_alpha1[row[k]] = 0.0;
+    load_alpha2[row[k]] = 0.0;
+    load_alpha3[row[k]] = 0.0;
+    auto cIt    = stiffnessMatrix[row[k]].begin();
+    auto cEndIt = stiffnessMatrix[row[k]].end();
+    for (; cIt!=cEndIt; ++cIt)
+      *cIt = (cIt.index()==row[k]) ? 1.0 : 0.0;
+  }
+}
+
+
+
+template<class Basis>
+auto childToIndexMap(const Basis& basis,
+                     const int k
+                     )
+{
+  // Input  : child/component
+  // Output : determine all Indices that belong to that component
+  auto localView = basis.localView();
+
+  std::vector<int> r = { };
+  //     for (int n: r)
+  //         std::cout << n << ","<< std::endl;
+
+  // Determine global indizes for each component k = 1,2,3.. in order to subtract correct (component of) integral Mean
+  // (global) Indices that correspond to component k = 1,2,3
+  for(const auto& element : elements(basis.gridView()))
+  {
+    localView.bind(element);
+    const auto& localFiniteElement = localView.tree().child(k).finiteElement();        
+    const auto nSf = localFiniteElement.localBasis().size();                           
+
+    for(size_t j=0; j<nSf; j++)
+    {
+      auto Localidx = localView.tree().child(k).localIndex(j);  // local  indices
+      r.push_back(localView.index(Localidx));                   // global indices
+    }
+  }
+  // Delete duplicate elements
+  // first remove consecutive (adjacent) duplicates
+  auto last = std::unique(r.begin(), r.end());
+  r.erase(last, r.end());
+  // sort followed by unique, to remove all duplicates
+  std::sort(r.begin(), r.end());
+  last = std::unique(r.begin(), r.end());
+  r.erase(last, r.end());
+
+  return r;
+}
+
+
+template<class Basis, class Vector>
+auto integralMean(const Basis& basis,
+                  Vector& coeffVector
+                  )
+{
+  // computes integral mean of given LocalFunction
+
+  constexpr int dim = Basis::LocalView::Element::dimension;
+
+  auto GVFunction = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,dim>>(basis,coeffVector);
+  auto localfun = localFunction(GVFunction);
+
+  auto localView = basis.localView();
+
+  FieldVector<double,3> r = {0.0, 0.0, 0.0};
+  double area = 0.0;
+
+  // Compute Area integral & integral of FE-function
+  for(const auto& element : elements(basis.gridView()))
+  {
+    localView.bind(element);
+    localfun.bind(element);
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();
+    
+//     int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5; //TEST
+    int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+    const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(element.type(), orderQR);
+
+    for(const auto& quadPoint : quad)
+    {
+      const auto& quadPos = quadPoint.position();
+      const double integrationElement = element.geometry().integrationElement(quadPos);
+      area += quadPoint.weight() * integrationElement;
+      
+      r += localfun(quadPos) * quadPoint.weight() * integrationElement;
+    }
+  }
+  //     std::cout << "Domain-Area: " << area << std::endl;
+  return (1.0/area) * r ;
+}
+
+
+template<class Basis, class Vector>
+auto subtractIntegralMean(const Basis& basis,
+                          Vector& coeffVector
+                          )
+{
+  // Substract correct Integral mean from each associated component function
+  auto IM = integralMean(basis, coeffVector);
+
+  constexpr int dim = Basis::LocalView::Element::dimension;
+
+  for(size_t k=0; k<dim; k++)
+  {
+    //std::cout << "Integral-Mean: " << IM[k] << std::endl;
+    auto idx = childToIndexMap(basis,k);
+
+    for ( int i : idx)
+      coeffVector[i] -= IM[k];
+  }
+}
+
+
+
+//////////////////////////////////////////////////
+//   Infrastructure for handling periodicity
+//////////////////////////////////////////////////
+
+// Check whether two points are equal on R/Z x R/Z x R
+auto equivalent = [](const FieldVector<double,3>& x, const FieldVector<double,3>& y)
+                {
+                    return ( (FloatCmp::eq(x[0],y[0]) or FloatCmp::eq(x[0]+1,y[0]) or FloatCmp::eq(x[0]-1,y[0]))
+                            and (FloatCmp::eq(x[1],y[1]) or FloatCmp::eq(x[1]+1,y[1]) or FloatCmp::eq(x[1]-1,y[1]))
+                            and (FloatCmp::eq(x[2],y[2]))
+                        );
+                };
+
+
+                
+////////////////////////////////////////////////////////////// L2-ERROR /////////////////////////////////////////////////////////////////
+template<class Basis, class Vector, class MatrixFunction>
+double computeL2SymError(const Basis& basis,
+                         Vector& coeffVector,
+                         const double gamma,
+                         const MatrixFunction& matrixFieldFunc)
+{
+  double error = 0.0;
+
+
+  auto localView = basis.localView();
+  
+
+  constexpr int dim = Basis::LocalView::Element::dimension;             //TODO TEST 
+  constexpr int dimWorld = 3;                                           // Hier auch möglich? 
+  
+  auto matrixFieldGVF  = Dune::Functions::makeGridViewFunction(matrixFieldFunc, basis.gridView());
+  auto matrixField = localFunction(matrixFieldGVF);
+  using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>;
+
+  for (const auto& element : elements(basis.gridView()))
+  {
+    localView.bind(element);
+    matrixField.bind(element);
+    auto geometry = element.geometry();
+
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();             
+    const auto nSf = localFiniteElement.localBasis().size();
+
+//     int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5; //TEST
+    int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1 );  
+    const auto& quad = QuadratureRules<double,dim>::rule(element.type(), orderQR);
+
+    for (const auto& quadPoint : quad)
+    {
+        const auto& quadPos = quadPoint.position();
+        const auto jacobianInverseTransposed = geometry.jacobianInverseTransposed(quadPos);
+        const auto integrationElement = geometry.integrationElement(quadPos);
+
+        std::vector< FieldMatrix<double, 1, dim>> referenceGradients;
+        localFiniteElement.localBasis().evaluateJacobian(quadPos,referenceGradients);
+
+        // Compute the shape function gradients on the grid element
+        std::vector<FieldVector<double,dim>> gradients(referenceGradients.size());
+
+        for (size_t i=0; i<gradients.size(); i++)
+          jacobianInverseTransposed.mv(referenceGradients[i][0], gradients[i]);
+
+        MatrixRT tmp(0);
+        double sum = 0.0;
+
+        for (size_t k=0; k < dimWorld; k++)
+        for (size_t i=0; i < nSf; i++)
+        {
+            size_t localIdx = localView.tree().child(k).localIndex(i);  // hier i:leafIdx
+            size_t globalIdx = localView.index(localIdx);
+
+            // (scaled) Deformation gradient of the ansatz basis function
+            MatrixRT defGradientU(0);
+            defGradientU[k][0] = coeffVector[globalIdx]*gradients[i][0];                       // Y  //hier i:leafIdx
+            defGradientU[k][1] = coeffVector[globalIdx]*gradients[i][1];                       //X2
+            defGradientU[k][2] = coeffVector[globalIdx]*(1.0/gamma)*gradients[i][2];           //X3
+
+            tmp += sym(defGradientU);
+        }
+//         printmatrix(std::cout, matrixField(quadPos), "matrixField(quadPos)", "--");
+//         printmatrix(std::cout, tmp, "tmp", "--");                                    // TEST Symphi_1 hat andere Struktur als analytic?
+//         tmp = tmp - matrixField(quadPos);
+//         printmatrix(std::cout, tmp - matrixField(quadPos), "Difference", "--");
+        for (int ii=0; ii<dimWorld; ii++)
+        for (int jj=0; jj<dimWorld; jj++)
+        {
+            sum +=  std::pow(tmp[ii][jj]-matrixField(quadPos)[ii][jj],2);
+        }
+//         std::cout << "sum:" << sum << std::endl;
+        error += sum * quadPoint.weight() * integrationElement;
+//         std::cout << "error:" << error << std::endl;
+    }
+  }
+  return sqrt(error);
+}
+////////////////////////////////////////////////////////////// L2-NORM /////////////////////////////////////////////////////////////////
+template<class Basis, class Vector>
+double computeL2Norm(const Basis& basis,
+                     Vector& coeffVector)
+{
+  // IMPLEMENTATION with makeDiscreteGlobalBasisFunction
+  double error = 0.0;
+
+  constexpr int dim = Basis::LocalView::Element::dimension;
+  constexpr int dimWorld = dim;
+  auto localView = basis.localView();
+  auto GVFunc = Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,dim>>(basis,coeffVector);
+  auto localfun = localFunction(GVFunc);
+
+  for(const auto& element : elements(basis.gridView()))
+  {
+    localView.bind(element);
+    localfun.bind(element);
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();
+
+    
+//     int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1)+5; //TEST
+    int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+    const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(element.type(), orderQR);
+
+    for(const auto& quadPoint : quad)
+    {
+      const auto& quadPos = quadPoint.position();
+      const double integrationElement = element.geometry().integrationElement(quadPos);
+      error += localfun(quadPos)*localfun(quadPos) * quadPoint.weight() * integrationElement;
+    }
+  }
+  return sqrt(error);
+}
+
+
+
+
+
+
+template<class Basis,class LocalFunction1, class LocalFunction2, class GVFunction , class MatrixFunction, class Matrix>
+auto test_derivative(const Basis& basis,
+                    LocalFunction1& mu,
+                    LocalFunction2& lambda,
+                    const double& gamma,
+                    Matrix& M,
+                    const GVFunction& matrixFieldFuncA,
+//                     const GVFunction& matrixFieldA,
+                    const MatrixFunction& matrixFieldFuncB
+                    )
+{
+
+//   TEST HIGHER PRECISION
+//   using float_50 = boost::multiprecision::cpp_dec_float_50;
+//   float_50 higherPrecEnergy = 0.0;
+  double energy = 0.0;
+  constexpr int dim = Basis::LocalView::Element::dimension;
+  constexpr int dimWorld = dim;
+
+  auto localView = basis.localView();
+
+//   auto matrixFieldAGVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncA, basis.gridView());
+  auto matrixFieldA = localFunction(matrixFieldFuncA);
+  auto matrixFieldBGVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncB, basis.gridView());
+  auto matrixFieldB = localFunction(matrixFieldBGVF);
+
+  using GridView = typename Basis::GridView;
+  using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate;
+  using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>;
+//   TEST
+//   FieldVector<double,3> testvector = {1.0 , 1.0 , 1.0};
+//   printmatrix(std::cout, matrixFieldFuncB(testvector) , "matrixFieldB(testvector) ", "--");
+
+  for (const auto& e : elements(basis.gridView()))
+  {
+    localView.bind(e);
+    matrixFieldA.bind(e);
+    matrixFieldB.bind(e);
+    mu.bind(e);
+    lambda.bind(e);
+
+
+    double elementEnergy = 0.0;
+    //double elementEnergy_HP = 0.0;
+
+    auto geometry = e.geometry();
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();
+
+//     int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1 + 5 );  // TEST
+//     int orderQR = 0;
+//     int orderQR = 1;
+//     int orderQR = 2;
+//     int orderQR = 3;
+    int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+    const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(e.type(), orderQR);
+
+    for (const auto& quadPoint : quad) 
+    {
+      const auto& quadPos = quadPoint.position();
+      const double integrationElement = geometry.integrationElement(quadPos);
+
+      auto strain1 = matrixFieldA(quadPos);
+      auto strain2 = matrixFieldB(quadPos);
+//       printmatrix(std::cout, strain1 , "strain1", "--");
+      
+      //cale with GAMMA
+      strain1 = crossSectionDirectionScaling(1.0/gamma, strain1);
+      strain1 = sym(strain1);
+      // ADD M 
+      auto test = strain1 + *M ; 
+//       std::cout << "test:" << test << std::endl;
+      
+//       for (size_t m=0; m<3; m++ )
+//       for (size_t n=0; n<3; n++ )
+//           strain1[m][n] += M[m][n];
+      
+
+
+//       double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), strain1, strain2);
+      double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), test, strain2);
+
+      elementEnergy += energyDensity * quadPoint.weight() * integrationElement;    
+      
+      
+//       elementEnergy += strain1 * quadPoint.weight() * integrationElement;        
+      //elementEnergy_HP += energyDensity * quadPoint.weight() * integrationElement;
+    }
+    energy += elementEnergy;
+    //higherPrecEnergy += elementEnergy_HP;
+  }
+//   TEST
+//   std::cout << std::setprecision(std::numeric_limits<float_50>::digits10) << higherPrecEnergy << std::endl;
+  return energy;
+}
+
+
+
+
+
+template<class Basis, class LocalFunction1, class LocalFunction2, class MatrixFunction, class Matrix>
+auto energy_MG(const Basis& basis,
+            LocalFunction1& mu,
+            LocalFunction2& lambda,
+            Matrix& M,
+            const MatrixFunction& matrixFieldFuncB)
+{
+
+//   TEST HIGHER PRECISION
+//   using float_50 = boost::multiprecision::cpp_dec_float_50;
+//   float_50 higherPrecEnergy = 0.0;
+  double energy = 0.0;
+  constexpr int dim = Basis::LocalView::Element::dimension;
+  constexpr int dimWorld = dim;
+
+  auto localView = basis.localView();
+
+//   auto matrixFieldAGVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncA, basis.gridView());
+//   auto matrixFieldA = localFunction(matrixFieldAGVF);
+  auto matrixFieldBGVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncB, basis.gridView());
+  auto matrixFieldB = localFunction(matrixFieldBGVF);
+
+  using GridView = typename Basis::GridView;
+  using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate;
+  using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>;
+//   TEST
+//   FieldVector<double,3> testvector = {1.0 , 1.0 , 1.0};
+//   printmatrix(std::cout, matrixFieldFuncB(testvector) , "matrixFieldB(testvector) ", "--");
+
+  for (const auto& e : elements(basis.gridView()))
+  {
+    localView.bind(e);
+//     matrixFieldA.bind(e);
+    matrixFieldB.bind(e);
+    mu.bind(e);
+    lambda.bind(e);
+
+    double elementEnergy = 0.0;
+    //double elementEnergy_HP = 0.0;
+
+    auto geometry = e.geometry();
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();
+
+//     int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1 + 5 );  // TEST
+    int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+    const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(e.type(), orderQR);
+
+    for (const auto& quadPoint : quad) 
+    {
+      const auto& quadPos = quadPoint.position();
+      const double integrationElement = geometry.integrationElement(quadPos);
+
+//       auto strain1 = matrixFieldA(quadPos);
+      auto strain2 = matrixFieldB(quadPos);
+
+      double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), *M, strain2);
+
+      elementEnergy += energyDensity * quadPoint.weight() * integrationElement;          
+      //elementEnergy_HP += energyDensity * quadPoint.weight() * integrationElement;
+    }
+    energy += elementEnergy;
+    //higherPrecEnergy += elementEnergy_HP;
+  }
+//   TEST
+//   std::cout << std::setprecision(std::numeric_limits<float_50>::digits10) << higherPrecEnergy << std::endl;
+  return energy;
+}
+
+
+
+
+
+
+
+
+
+template<class Basis,class LocalFunction1, class LocalFunction2, class GVFunction , class MatrixFunction, class Matrix>
+auto check_Orthogonality(const Basis& basis,
+                    LocalFunction1& mu,
+                    LocalFunction2& lambda,
+                    const double& gamma,
+                    Matrix& M1,
+                    Matrix& M2,
+                    const GVFunction& DerPhi_1,
+                    const GVFunction& DerPhi_2,
+//                     const GVFunction& matrixFieldA,
+                    const MatrixFunction& matrixFieldFuncG
+                    )
+{
+
+//   TEST HIGHER PRECISION
+//   using float_50 = boost::multiprecision::cpp_dec_float_50;
+//   float_50 higherPrecEnergy = 0.0;
+  double energy = 0.0;
+  constexpr int dim = Basis::LocalView::Element::dimension;
+  constexpr int dimWorld = dim;
+
+  auto localView = basis.localView();
+
+  
+  auto DerPhi1 = localFunction(DerPhi_1);
+  auto DerPhi2 = localFunction(DerPhi_2);
+  
+  auto matrixFieldGGVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncG, basis.gridView());
+  auto matrixFieldG = localFunction(matrixFieldGGVF);
+//   auto matrixFieldBGVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncB, basis.gridView());
+//   auto matrixFieldB = localFunction(matrixFieldBGVF);
+
+  using GridView = typename Basis::GridView;
+  using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate;
+  using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>;
+  
+//   std::cout << "Press key.." << std::endl;
+//   std::cin.get();
+  
+//   TEST
+//   FieldVector<double,3> testvector = {1.0 , 1.0 , 1.0};
+//   printmatrix(std::cout, matrixFieldFuncB(testvector) , "matrixFieldB(testvector) ", "--");
+
+  for (const auto& e : elements(basis.gridView()))
+  {
+    localView.bind(e);
+    matrixFieldG.bind(e);
+    DerPhi1.bind(e);
+    DerPhi2.bind(e);
+    mu.bind(e);
+    lambda.bind(e);
+
+
+    double elementEnergy = 0.0;
+    //double elementEnergy_HP = 0.0;
+
+    auto geometry = e.geometry();
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();
+
+//     int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1 + 5 );  // TEST
+    int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+//     int orderQR = 0;
+//     int orderQR = 1;
+//     int orderQR = 2;
+//     int orderQR = 3;
+    const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(e.type(), orderQR);
+
+    for (const auto& quadPoint : quad) 
+    {
+      const auto& quadPos = quadPoint.position();
+      const double integrationElement = geometry.integrationElement(quadPos);
+      
+      
+      auto Chi = sym(crossSectionDirectionScaling(1.0/gamma, DerPhi2(quadPos))) + *M2;
+
+      auto strain1 = DerPhi1(quadPos);
+//       printmatrix(std::cout, strain1 , "strain1", "--");
+      //cale with GAMMA
+      strain1 = crossSectionDirectionScaling(1.0/gamma, strain1);
+      strain1 = sym(strain1);
+      
+      
+      // ADD M 
+//       auto test = strain1 + *M ; 
+//       std::cout << "test:" << test << std::endl;
+      
+//       for (size_t m=0; m<3; m++ )
+//       for (size_t n=0; n<3; n++ )
+//           strain1[m][n] += M[m][n];
+      
+      auto G = matrixFieldG(quadPos);
+//       auto G = matrixFieldG(e.geometry().global(quadPos)); //TEST
+      
+      
+      auto tmp = G + *M1 + strain1;
+
+      double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), tmp, Chi);
+
+      elementEnergy += energyDensity * quadPoint.weight() * integrationElement;    
+      
+      
+//       elementEnergy += strain1 * quadPoint.weight() * integrationElement;        
+      //elementEnergy_HP += energyDensity * quadPoint.weight() * integrationElement;
+    }
+    energy += elementEnergy;
+    //higherPrecEnergy += elementEnergy_HP;
+  }
+//   TEST
+//   std::cout << std::setprecision(std::numeric_limits<float_50>::digits10) << higherPrecEnergy << std::endl;
+  return energy;
+}
+
+
+
+
+template<class Basis,class LocalFunction1, class LocalFunction2, class GVFunction , class MatrixFunction, class Matrix>
+auto computeFullQ(const Basis& basis,
+                    LocalFunction1& mu,
+                    LocalFunction2& lambda,
+                    const double& gamma,
+                    Matrix& M1,
+                    Matrix& M2,
+                    const GVFunction& DerPhi_1,
+                    const GVFunction& DerPhi_2,
+//                     const GVFunction& matrixFieldA,
+                    const MatrixFunction& matrixFieldFuncG1,
+                    const MatrixFunction& matrixFieldFuncG2
+                    )
+{
+
+//   TEST HIGHER PRECISION
+//   using float_50 = boost::multiprecision::cpp_dec_float_50;
+//   float_50 higherPrecEnergy = 0.0;
+  double energy = 0.0;
+  constexpr int dim = Basis::LocalView::Element::dimension;
+  constexpr int dimWorld = dim;
+
+  auto localView = basis.localView();
+
+  
+  auto DerPhi1 = localFunction(DerPhi_1);
+  auto DerPhi2 = localFunction(DerPhi_2);
+  
+  auto matrixFieldG1GVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncG1, basis.gridView());
+  auto matrixFieldG1 = localFunction(matrixFieldG1GVF);
+  auto matrixFieldG2GVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncG2, basis.gridView());
+  auto matrixFieldG2 = localFunction(matrixFieldG2GVF);
+//   auto matrixFieldBGVF  = Dune::Functions::makeGridViewFunction(matrixFieldFuncB, basis.gridView());
+//   auto matrixFieldB = localFunction(matrixFieldBGVF);
+
+  using GridView = typename Basis::GridView;
+  using Domain = typename GridView::template Codim<0>::Geometry::GlobalCoordinate;
+  using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>;
+//   TEST
+//   FieldVector<double,3> testvector = {1.0 , 1.0 , 1.0};
+//   printmatrix(std::cout, matrixFieldFuncB(testvector) , "matrixFieldB(testvector) ", "--");
+
+  for (const auto& e : elements(basis.gridView()))
+  {
+    localView.bind(e);
+    matrixFieldG1.bind(e);
+    matrixFieldG2.bind(e);
+    DerPhi1.bind(e);
+    DerPhi2.bind(e);
+    mu.bind(e);
+    lambda.bind(e);
+
+
+    double elementEnergy = 0.0;
+    //double elementEnergy_HP = 0.0;
+
+    auto geometry = e.geometry();
+    const auto& localFiniteElement = localView.tree().child(0).finiteElement();
+
+//     int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1 + 5 );  // TEST
+    int orderQR = 2*(dim*localFiniteElement.localBasis().order()-1);
+//     int orderQR = 0;
+//     int orderQR = 1;
+//     int orderQR = 2;
+//     int orderQR = 3;
+    const QuadratureRule<double, dim>& quad = QuadratureRules<double, dim>::rule(e.type(), orderQR);
+
+    for (const auto& quadPoint : quad) 
+    {
+      const auto& quadPos = quadPoint.position();
+      const double integrationElement = geometry.integrationElement(quadPos);
+      
+      auto Chi1 = sym(crossSectionDirectionScaling(1.0/gamma, DerPhi1(quadPos))) + *M1;
+      auto Chi2 = sym(crossSectionDirectionScaling(1.0/gamma, DerPhi2(quadPos))) + *M2;
+
+//       auto strain1 = DerPhi1(quadPos);
+// //       printmatrix(std::cout, strain1 , "strain1", "--");
+//       //cale with GAMMA
+//       strain1 = crossSectionDirectionScaling(1.0/gamma, strain1);
+//       strain1 = sym(strain1);
+      
+      
+      // ADD M 
+//       auto test = strain1 + *M ; 
+//       std::cout << "test:" << test << std::endl;
+      
+//       for (size_t m=0; m<3; m++ )
+//       for (size_t n=0; n<3; n++ )
+//           strain1[m][n] += M[m][n];
+      
+      auto G1 = matrixFieldG1(quadPos);
+      auto G2 = matrixFieldG2(quadPos);
+//       auto G1 = matrixFieldG1(e.geometry().global(quadPos)); //TEST
+//       auto G2 = matrixFieldG2(e.geometry().global(quadPos)); //TEST
+      
+      auto X1 = G1 + Chi1;
+      auto X2 = G2 + Chi2;
+      
+     
+      double energyDensity = linearizedStVenantKirchhoffDensity(mu(quadPos), lambda(quadPos), X1, X2);
+
+      elementEnergy += energyDensity * quadPoint.weight() * integrationElement;      // quad[quadPoint].weight() ???
+      
+      
+//       elementEnergy += strain1 * quadPoint.weight() * integrationElement;        
+      //elementEnergy_HP += energyDensity * quadPoint.weight() * integrationElement;
+    }
+    energy += elementEnergy;
+    //higherPrecEnergy += elementEnergy_HP;
+  }
+//   TEST
+//   std::cout << std::setprecision(std::numeric_limits<float_50>::digits10) << higherPrecEnergy << std::endl;
+  return energy;
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+int main(int argc, char *argv[])
+{
+  MPIHelper::instance(argc, argv);
+  
+  Dune::Timer globalTimer;
+
+  ParameterTree parameterSet;
+  if (argc < 2)
+    ParameterTreeParser::readINITree("../../inputs/cellsolver.parset", parameterSet);
+  else
+  {
+    ParameterTreeParser::readINITree(argv[1], parameterSet);
+    ParameterTreeParser::readOptions(argc, argv, parameterSet);
+  }
+
+  //--- Output setter
+//   std::string outputPath = parameterSet.get("outputPath", "../../outputs/output.txt");
+//   std::string outputPath = parameterSet.get("outputPath", "/home/klaus/Desktop/DUNE/dune-microstructure/outputs/output.txt");
+//   std::string outputPath = parameterSet.get("outputPath", "/home/klaus/Desktop/DUNE/dune-microstructure/outputs");
+  std::string outputPath = parameterSet.get("outputPath", "../../outputs");
+//   std::string MatlabPath = parameterSet.get("MatlabPath", "/home/klaus/Desktop/DUNE/dune-microstructure/Matlab-Programs");
+//     std::string outputPath = "/home/klaus/Desktop/DUNE/dune-microstructure/outputs/output.txt";
+  std::fstream log;
+  log.open(outputPath + "/output.txt" ,std::ios::out);
+
+  std::cout << "outputPath:" << outputPath << std::endl;
+  
+//   parameterSet.report(log); // short Alternativ
+  
+  
+    std::string geometryFunctionPath = parameterSet.get<std::string>("geometryFunctionPath");
+    //Start Python interpreter
+    Python::start();
+    Python::Reference main = Python::import("__main__");
+    Python::run("import math");
+
+    //"sys.path.append('/home/klaus/Desktop/DUNE/dune-gfe/problems')"
+    Python::runStream()
+        << std::endl << "import sys"
+        << std::endl << "sys.path.append('" << geometryFunctionPath << "')"
+        << std::endl;
+//         
+//     // Use python-function for initialIterate
+//     // Read initial iterate into a Python function
+//     Python::Module module = Python::import(parameterSet.get<std::string>("geometryFunction"));
+//     auto pythonInitialIterate = Python::make_function<double>(module.get("f"));
+  
+        
+        
+  std::cout << "machine epsilon:" << std::numeric_limits<double>::epsilon() << std::endl;
+  
+  constexpr int dim = 3;
+  constexpr int dimWorld = 3;
+
+  ///////////////////////////////////
+  // Get Parameters/Data
+  ///////////////////////////////////
+  double gamma = parameterSet.get<double>("gamma",1.0);   // ratio dimension reduction to homogenization
+  double alpha = parameterSet.get<double>("alpha", 2.0);
+  double theta = parameterSet.get<double>("theta",1.0/4.0); 
+  ///////////////////////////////////
+  // Get Material Parameters
+  ///////////////////////////////////
+  std::string imp = parameterSet.get<std::string>("material_prestrain_imp", "analytical_Example");
+  log << "material_prestrain used: "<< imp  << std::endl;
+  double beta = parameterSet.get<double>("beta",2.0); 
+  double mu1 = parameterSet.get<double>("mu1",1.0);;
+  double mu2 = beta*mu1;
+  double lambda1 = parameterSet.get<double>("lambda1",0.0);;
+  double lambda2 = beta*lambda1;
+  
+  // Plate geometry settings
+  double width = parameterSet.get<double>("width", 1.0);   //geometry cell, cross section
+  //     double len  = parameterSet.get<double>("len", 10.0); //length
+  //     double height  = parameterSet.get<double>("h", 0.1); //rod thickness
+  //     double eps  = parameterSet.get<double>("eps", 0.1); //size of perioticity cell
+  
+  if(imp == "material_neukamm")
+  {
+      std::cout <<"mu: " <<parameterSet.get<std::array<double,3>>("mu", {1.0,3.0,2.0}) << std::endl;
+      std::cout <<"lambda: " << parameterSet.get<std::array<double,3>>("lambda", {1.0,3.0,2.0}) << std::endl;
+  }
+  else
+  {
+      std::cout <<"mu: "     <<  parameterSet.get<double>("mu1",1.0) << std::endl;
+      std::cout <<"lambda: " <<  parameterSet.get<double>("lambda1",0.0) << std::endl;
+  }
+  
+
+
+  ///////////////////////////////////
+  // Get Prestrain/Parameters
+  ///////////////////////////////////
+//   unsigned int prestraintype = parameterSet.get<unsigned int>("prestrainType", "analytical_Example");  //OLD 
+//   std::string prestraintype = parameterSet.get<std::string>("prestrainType", "analytical_Example");
+//   double rho1 = parameterSet.get<double>("rho1", 1.0);
+//   double rho2 = alpha*rho1;
+//   auto prestrainImp = PrestrainImp(rho1, rho2, theta, width);
+//   auto B_Term = prestrainImp.getPrestrain(prestraintype);
+  
+  
+  
+  auto prestrainImp = PrestrainImp<dim>(); //NEW 
+  auto B_Term = prestrainImp.getPrestrain(parameterSet);
+
+  log << "----- Input Parameters -----: " << std::endl;
+//   log << "prestrain imp: " <<  prestraintype << "\nrho1 = " << rho1 << "\nrho2 = " << rho2  << std::endl;
+  log << "alpha: " << alpha << std::endl;
+  log << "gamma: " << gamma << std::endl;
+  log << "theta: " << theta << std::endl;
+  log << "beta: " << beta << std::endl;
+  log << "material parameters: " << std::endl;
+  log << "mu1: " << mu1 << "\nmu2: " << mu2 << std::endl;
+  log << "lambda1: " << lambda1 <<"\nlambda2: " << lambda2 << std::endl;
+  log << "----------------------------: " << std::endl;
+
+  ///////////////////////////////////
+  // Generate the grid
+  ///////////////////////////////////
+
+  //Corrector Problem Domain:
+  unsigned int cellDomain = parameterSet.get<unsigned int>("cellDomain", 1);
+  // (shifted) Domain (-1/2,1/2)^3
+  FieldVector<double,dim> lower({-1.0/2.0, -1.0/2.0, -1.0/2.0});
+  FieldVector<double,dim> upper({1.0/2.0, 1.0/2.0, 1.0/2.0});
+  if (cellDomain == 2)
+  {
+    // Domain : [0,1)^2 x (-1/2, 1/2)
+    FieldVector<double,dim> lower({0.0, 0.0, -1.0/2.0});
+    FieldVector<double,dim> upper({1.0, 1.0, 1.0/2.0});
+  }
+
+  std::array<int,2> numLevels = parameterSet.get<std::array<int,2>>("numLevels", {1,3});
+
+  int levelCounter = 0;
+   
+  
+//   FieldVector<double,2> mu = parameterSet.get<FieldVector<double,2>>("mu", {1.0,3.0});
+
+  ///////////////////////////////////
+  // Create Data Storage
+  ///////////////////////////////////
+  // Storage:: #1 level #2 L2SymError #3 L2SymErrorOrder #4  L2Norm(sym) #5 L2Norm(sym-analytic) #6 L2Norm(phi_1)
+  std::vector<std::variant<std::string, size_t , double>> Storage_Error;
+  
+  // Storage:: #1 level #2 |q1_a-q1_c| #3 |q2_a-q2_c| #4 |q3_a-q3_c| #5 |b1_a-b1_c| #6 |b2_a-b2_c| #7 |b3_a-b3_c|           
+   std::vector<std::variant<std::string, size_t , double>> Storage_Quantities;         
+
+
+//   for(const size_t &level : numLevels)                             // explixite Angabe der levels.. {2,4}
+  for(size_t level = numLevels[0] ; level <= numLevels[1]; level++)    // levels von bis.. [2,4]
+  {
+    std::cout << " ----------------------------------" << std::endl;
+    std::cout << "Level: " << level << std::endl;
+    std::cout << " ----------------------------------" << std::endl;
+
+    Storage_Error.push_back(level);
+    Storage_Quantities.push_back(level);
+    std::array<int, dim> nElements = { (int)std::pow(2,level) , (int)std::pow(2,level) , (int)std::pow(2,level) };
+    
+//     std::array<unsigned int, dim> nElements_test = { (int)std::pow(2,level) , (int)std::pow(2,level) , (int)std::pow(2,level) };
+
+    std::cout << "Number of Elements in each direction: " << nElements << std::endl;
+    log << "Number of Elements in each direction: " << nElements << std::endl;
+
+    using CellGridType = YaspGrid<dim, EquidistantOffsetCoordinates<double, dim> >;
+    CellGridType grid_CE(lower,upper,nElements);
+    using GridView = CellGridType::LeafGridView;
+    const GridView gridView_CE = grid_CE.leafGridView();
+    std::cout << "Host grid has " << gridView_CE.size(dim) << " vertices." << std::endl;
+    
+    
+    //TEST 
+//     using CellGridTypeT = StructuredGridFactory<UGGrid<dim> >;
+//     auto grid = StructuredGridFactory<UGGrid<dim> >::createCubeGrid(lower,upper,nElements_test);
+//     auto gridView_CE = grid::leafGridView();
+
+//     FieldVector<double,3> lowerLeft = {0.0, 0.0, 0.0};
+//     FieldVector<double,3> upperRight = {1.0, 1.0, 1.0};
+//     std::array<unsigned int,3> elements = {10, 10, 10};
+//     auto grid = StructuredGridFactory<UGGrid<3> >::createCubeGrid(lowerLeft,
+//                                                                 upperRight,
+//                                                                 elements);
+//         
+
+    using MatrixRT = FieldMatrix< double, dimWorld, dimWorld>;
+    using Domain = GridView::Codim<0>::Geometry::GlobalCoordinate;
+    using Func2Tensor = std::function< MatrixRT(const Domain&) >;
+    using VectorCT = BlockVector<FieldVector<double,1> >;
+    using MatrixCT = BCRSMatrix<FieldMatrix<double,1,1> >;
+
+    ///////////////////////////////////
+    //  Create Lambda-Functions for material Parameters depending on microstructure
+    ///////////////////////////////////
+    auto materialImp = IsotropicMaterialImp<dim>();
+    auto muTerm = materialImp.getMu(parameterSet);
+    auto lambdaTerm = materialImp.getLambda(parameterSet);
+
+/*  
+    auto muTerm = [mu1, mu2, theta] (const Domain& z) {
+                    if (abs(z[0]) >= (theta/2.0))                                                   
+                        return mu1;
+                    else
+                        return mu2;
+                    };
+
+    auto lambdaTerm = [lambda1,lambda2, theta] (const Domain& z) {
+                    if (abs(z[0]) >= (theta/2.0))
+                        return lambda1;
+                    else
+                        return lambda2;
+                    };*/
+    auto muGridF  = Dune::Functions::makeGridViewFunction(muTerm, gridView_CE);
+    auto muLocal = localFunction(muGridF);
+    auto lambdaGridF  = Dune::Functions::makeGridViewFunction(lambdaTerm, gridView_CE);
+    auto lambdaLocal = localFunction(lambdaGridF);
+
+    ///////////////////////////////////
+    // --- Choose Solver ---
+    // 1 : CG-Solver
+    // 2 : GMRES
+    // 3 : QR
+    ///////////////////////////////////
+    unsigned int Solvertype = parameterSet.get<unsigned int>("Solvertype", 3);
+    
+    unsigned int Solver_verbosity = parameterSet.get<unsigned int>("Solver_verbosity", 2);
+    
+    // Print Options 
+    bool print_debug = parameterSet.get<bool>("print_debug", false);
+
+    //VTK-Write 
+    bool write_materialFunctions = parameterSet.get<bool>("write_materialFunctions", false);
+    bool write_prestrainFunctions  = parameterSet.get<bool>("write_prestrainFunctions", false);
+    bool write_corrector_phi1 = parameterSet.get<bool>("write_corrector_phi1", false);
+    bool write_corrector_phi2 = parameterSet.get<bool>("write_corrector_phi2", false);
+    bool write_corrector_phi3 = parameterSet.get<bool>("write_corrector_phi3", false);
+    bool write_L2Error = parameterSet.get<bool>("write_L2Error", false);
+    bool write_IntegralMean = parameterSet.get<bool>("write_IntegralMean", false);
+    bool write_VTK = parameterSet.get<bool>("write_VTK", false);
+
+    /////////////////////////////////////////////////////////
+    // Choose a finite element space for Cell Problem
+    /////////////////////////////////////////////////////////
+    using namespace Functions::BasisFactory;
+    Functions::BasisFactory::Experimental::PeriodicIndexSet periodicIndices;
+
+    // Don't do the following in real life: It has quadratic run-time in the number of vertices.
+    for (const auto& v1 : vertices(gridView_CE))
+        for (const auto& v2 : vertices(gridView_CE))
+            if (equivalent(v1.geometry().corner(0), v2.geometry().corner(0)))
+            {
+                periodicIndices.unifyIndexPair({gridView_CE.indexSet().index(v1)}, {gridView_CE.indexSet().index(v2)});
+            }
+
+    // First order periodic Lagrange-Basis
+    auto Basis_CE = makeBasis(
+        gridView_CE,
+        power<dim>(                                                                             // eig dimworld?!?! 
+        Functions::BasisFactory::Experimental::periodic(lagrange<1>(), periodicIndices),
+        flatLexicographic()
+//         blockedInterleaved()             // ERROR 
+        ));     
+    
+    std::cout << "power<periodic> basis has " << Basis_CE.dimension() << " degrees of freedom" << std::endl;
+
+    log << "size of FiniteElementBasis: " << Basis_CE.size() << std::endl;
+    const int phiOffset = Basis_CE.size();
+
+    /////////////////////////////////////////////////////////
+    // Data structures: Stiffness matrix and right hand side vectors
+    /////////////////////////////////////////////////////////
+    VectorCT load_alpha1, load_alpha2, load_alpha3;
+    MatrixCT stiffnessMatrix_CE;
+
+    bool set_IntegralZero = parameterSet.get<bool>("set_IntegralZero", false);
+    bool set_oneBasisFunction_Zero = parameterSet.get<bool>("set_oneBasisFunction_Zero", false);
+//     bool set_oneBasisFunction_Zero = false;
+    bool substract_integralMean = false;
+    if(set_IntegralZero)
+    {
+        set_oneBasisFunction_Zero = true;
+        substract_integralMean = true;
+    }
+
+    /////////////////////////////////////////////////////////
+    // Define "rhs"-functions
+    /////////////////////////////////////////////////////////
+    Func2Tensor x3G_1 = [] (const Domain& x) {
+                            return MatrixRT{{1.0*x[2], 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};    //TODO könnte hier sign übergeben?
+                        };
+
+    Func2Tensor x3G_2 = [] (const Domain& x) {
+                            return MatrixRT{{0.0, 0.0, 0.0}, {0.0, 1.0*x[2], 0.0}, {0.0, 0.0, 0.0}};
+                        };
+
+    Func2Tensor x3G_3 = [] (const Domain& x) {                                                                               
+                            return MatrixRT{{0.0, (1.0/sqrt(2.0))*x[2], 0.0}, {(1.0/sqrt(2.0))*x[2], 0.0, 0.0}, {0.0, 0.0, 0.0}};
+                        };
+                        
+    Func2Tensor x3G_1neg = [x3G_1] (const Domain& x) {return -1.0*x3G_1(x);};
+    Func2Tensor x3G_2neg = [x3G_2] (const Domain& x) {return -1.0*x3G_2(x);};
+    Func2Tensor x3G_3neg = [x3G_3] (const Domain& x) {return -1.0*x3G_3(x);};
+    
+    //TODO eigentlich funtkioniert es ja mit x3G_1 etc doch auch ?!
+    
+    
+    
+
+    //TEST : 
+
+    // Compute reduced model
+    std::cout << "\ncompute effective model\n";
+    auto cellAssembler = CellAssembler(Basis_CE,  muTerm, lambdaTerm, gamma, log, parameterSet);
+    
+    cellAssembler.solve();
+    cellAssembler.computeNorms();
+    cellAssembler.writeCorrectorsVTK(level);
+    cellAssembler.check_Orthogonality();
+
+    // break;
+
+    //TODO 
+    // cellAssembler.computeNorms();
+    // cellAssembler.writeVTK(); 
+
+
+    std::cout << "\n WORKED \n";
+    
+    //TEST 
+//     std::cout << "Test crossSectionDirectionScaling:" << std::endl;
+/*    
+    MatrixRT T {{1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}};
+    printmatrix(std::cout, T, "Matrix T", "--");
+    
+    auto ST = crossSectionDirectionScaling((1.0/5.0),T);
+    printmatrix(std::cout, ST, "scaled Matrix T", "--");*/
+    
+    //TEST 
+//     auto QuadraticForm = [] (const double mu, const double lambda, const MatrixRT& M) {
+// 
+//                                 return lambda*std::pow(trace(M),2) + 2*mu*pow(norm(sym(M)),2);
+//                         };
+
+
+    // TEST - energy method ///
+    // different indicatorFunction in muTerm has impact here !!
+    //     double GGterm = 0.0;
+    //     GGterm = energy(Basis_CE, muLocal, lambdaLocal, x3G_1, x3G_1  );   // <L i(x3G_alpha) , i(x3G_beta) >
+    //     std::cout << "GGTerm:" << GGterm << std::endl;
+    //     std::cout << " analyticGGTERM:" << (mu1*(1-theta)+mu2*theta)/6.0 << std::endl;
+
+
+    ///////////////////////////////////////////////
+    // Basis for R_sym^{2x2}
+    //////////////////////////////////////////////
+    MatrixRT G_1 {{1.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0, 0.0}};
+    MatrixRT G_2 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0, 0.0, 0.0}};
+    MatrixRT G_3 {{0.0, 1.0/sqrt(2.0), 0.0}, {1.0/sqrt(2.0), 0.0, 0.0}, {0.0, 0.0, 0.0}};
+    std::array<MatrixRT,3 > basisContainer = {G_1, G_2, G_3};
+    //  printmatrix(std::cout, basisContainer[0] , "G_1", "--");
+    //  printmatrix(std::cout, basisContainer[1] , "G_2", "--");
+    //  printmatrix(std::cout, basisContainer[2] , "´G_3", "--");
+    //  log <<  basisContainer[0] << std::endl;
+
+
+    //////////////////////////////////////////////////////////////////////
+    // Determine global indices of components for arbitrary (local) index
+    //////////////////////////////////////////////////////////////////////
+    int arbitraryLeafIndex =  parameterSet.get<unsigned int>("arbitraryLeafIndex", 0);            // localIdx..assert Number < #ShapeFcts 
+    int arbitraryElementNumber =  parameterSet.get<unsigned int>("arbitraryElementNumber", 0);
+
+    
+    if(print_debug)
+    {
+      FieldVector<int,3> row;
+      row = arbitraryComponentwiseIndices(Basis_CE,arbitraryElementNumber,arbitraryLeafIndex); 
+      printvector(std::cout, row, "row" , "--");
+    }
+
+    /////////////////////////////////////////////////////////
+    // Assemble the system
+    /////////////////////////////////////////////////////////
+    Dune::Timer StiffnessTimer;
+    assembleCellStiffness(Basis_CE, muLocal, lambdaLocal, gamma,  stiffnessMatrix_CE, parameterSet);
+    std::cout << "Stiffness assembly Timer: " << StiffnessTimer.elapsed() << std::endl;
+    assembleCellLoad(Basis_CE, muLocal, lambdaLocal,gamma, load_alpha1 ,x3G_1neg);
+    assembleCellLoad(Basis_CE, muLocal, lambdaLocal,gamma, load_alpha2 ,x3G_2neg);
+    assembleCellLoad(Basis_CE, muLocal, lambdaLocal,gamma, load_alpha3 ,x3G_3neg);
+    //TEST
+//     assembleCellStiffness(Basis_CE, muTerm, lambdaTerm, gamma,  stiffnessMatrix_CE, parameterSet);
+//     std::cout << "Stiffness assembly Timer: " << StiffnessTimer.elapsed() << std::endl;
+//     assembleCellLoad(Basis_CE, muTerm, lambdaTerm,gamma, load_alpha1 ,x3G_1neg);
+//     assembleCellLoad(Basis_CE, muTerm, lambdaTerm,gamma, load_alpha2 ,x3G_2neg);
+//     assembleCellLoad(Basis_CE, muTerm, lambdaTerm,gamma, load_alpha3 ,x3G_3neg);
+    
+    //TEST
+//     assembleCellLoad(Basis_CE, muLocal, lambdaLocal,gamma, load_alpha1 ,x3G_1);
+//     assembleCellLoad(Basis_CE, muLocal, lambdaLocal,gamma, load_alpha2 ,x3G_2);
+//     assembleCellLoad(Basis_CE, muLocal, lambdaLocal,gamma, load_alpha3 ,x3G_3);
+//     printmatrix(std::cout, stiffnessMatrix_CE, "StiffnessMatrix", "--");
+//     printvector(std::cout, load_alpha1, "load_alpha1", "--");
+
+    //TODO Add Option for this
+    // CHECK SYMMETRY:
+//     checkSymmetry(Basis_CE,stiffnessMatrix_CE);
+    
+    
+
+
+    // set one basis-function to zero
+    if(set_oneBasisFunction_Zero)
+    {
+        setOneBaseFunctionToZero(Basis_CE, stiffnessMatrix_CE, load_alpha1, load_alpha2, load_alpha3, parameterSet);
+    //     printmatrix(std::cout, stiffnessMatrix_CE, "StiffnessMatrix after setOneBasisFunctionToZero", "--");
+//         printvector(std::cout, load_alpha1, "load_alpha1 after setOneBaseFunctionToZero", "--");
+    }
+    
+    //TEST: Compute Condition Number  (Can be very expensive !) 
+    const bool verbose = true;
+    const unsigned int arppp_a_verbosity_level = 2;
+    const unsigned int pia_verbosity_level = 1;
+    MatrixInfo<MatrixCT> matrixInfo(stiffnessMatrix_CE,verbose,arppp_a_verbosity_level,pia_verbosity_level);
+    std::cout << "Get condition number of Stiffness_CE: " << matrixInfo.getCond2(true) << std::endl;
+//     std::cout << "Get condition number of Stiffness_CE: " << matrixInfo.getCond2(false) << std::endl;
+
+    ////////////////////////////////////////////////////
+    // Compute solution
+    ////////////////////////////////////////////////////
+    VectorCT x_1 = load_alpha1;
+    VectorCT x_2 = load_alpha2;
+    VectorCT x_3 = load_alpha3;
+
+//     auto load_alpha1BS = load_alpha1;
+    //   printvector(std::cout, load_alpha1, "load_alpha1 before SOLVER", "--" );
+    //   printvector(std::cout, load_alpha2, "load_alpha2 before SOLVER", "--" );
+
+    if (Solvertype == 1)  // CG - SOLVER
+    {
+        std::cout << "------------ CG - Solver ------------" << std::endl;
+        MatrixAdapter<MatrixCT, VectorCT, VectorCT> op(stiffnessMatrix_CE);
+
+
+
+        // Sequential incomplete LU decomposition as the preconditioner
+        SeqILU<MatrixCT, VectorCT, VectorCT> ilu0(stiffnessMatrix_CE,1.0);
+        int iter = parameterSet.get<double>("iterations_CG", 999);
+        // Preconditioned conjugate-gradient solver
+        CGSolver<VectorCT> solver(op,
+                                ilu0, //NULL,
+                                1e-8, // desired residual reduction factorlack
+                                iter,   // maximum number of iterations
+                                Solver_verbosity,
+                                true    // Try to estimate condition_number
+                                 );   // verbosity of the solver
+        InverseOperatorResult statistics;
+        std::cout << "solve linear system for x_1.\n";
+        solver.apply(x_1, load_alpha1, statistics);
+        std::cout << "solve linear system for x_2.\n";
+        solver.apply(x_2, load_alpha2, statistics);
+        std::cout << "solve linear system for x_3.\n";
+        solver.apply(x_3, load_alpha3, statistics);
+        log << "Solver-type used: " <<" CG-Solver" << std::endl;
+        
+        
+        std::cout << "statistics.converged " << statistics.converged << std::endl;
+        std::cout << "statistics.condition_estimate: " << statistics.condition_estimate << std::endl;
+        std::cout << "statistics.iterations: " << statistics.iterations << std::endl;
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    else if (Solvertype ==2)  // GMRES - SOLVER
+    {
+
+        std::cout << "------------ GMRES - Solver ------------" << std::endl;
+        // Turn the matrix into a linear operator
+        MatrixAdapter<MatrixCT,VectorCT,VectorCT> stiffnessOperator(stiffnessMatrix_CE);
+
+        // Fancy (but only) way to not have a preconditioner at all
+        Richardson<VectorCT,VectorCT> preconditioner(1.0);
+
+        // Construct the iterative solver
+        RestartedGMResSolver<VectorCT> solver(
+            stiffnessOperator, // Operator to invert
+            preconditioner,    // Preconditioner
+            1e-10,             // Desired residual reduction factor
+            500,               // Number of iterations between restarts,
+                            // here: no restarting
+            500,               // Maximum number of iterations
+            Solver_verbosity);                // Verbosity of the solver
+
+        // Object storing some statistics about the solving process
+        InverseOperatorResult statistics;
+
+        // solve for different Correctors (alpha = 1,2,3)
+        solver.apply(x_1, load_alpha1, statistics);     //load_alpha1 now contains the corresponding residual!!
+        solver.apply(x_2, load_alpha2, statistics);
+        solver.apply(x_3, load_alpha3, statistics);
+        log << "Solver-type used: " <<" GMRES-Solver" << std::endl;
+        
+        std::cout << "statistics.converged " << statistics.converged << std::endl;
+        std::cout << "statistics.condition_estimate: " << statistics.condition_estimate << std::endl;
+        std::cout << "statistics.iterations: " << statistics.iterations << std::endl;
+    }
+    ////////////////////////////////////////////////////////////////////////////////////
+    else if ( Solvertype == 3)// QR - SOLVER
+    {
+
+        std::cout << "------------ QR - Solver ------------" << std::endl;
+        log << "solveLinearSystems: We use QR solver.\n";
+        //TODO install suitesparse
+        SPQR<MatrixCT> sPQR(stiffnessMatrix_CE);
+        sPQR.setVerbosity(1);
+        InverseOperatorResult statisticsQR;
+
+        sPQR.apply(x_1, load_alpha1, statisticsQR);
+        std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+        std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+        std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+        sPQR.apply(x_2, load_alpha2, statisticsQR);
+        std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+        std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+        std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+        sPQR.apply(x_3, load_alpha3, statisticsQR);
+        std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+        std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+        std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+        log << "Solver-type used: " <<" QR-Solver" << std::endl;
+        
+
+    }
+    else if ( Solvertype == 4)// UMFPACK - SOLVER
+    {
+
+        std::cout << "------------ UMFPACK - Solver ------------" << std::endl;
+        log << "solveLinearSystems: We use UMFPACK solver.\n";
+        
+        Dune::Solvers::UMFPackSolver<MatrixCT,VectorCT> solver;
+        solver.setProblem(stiffnessMatrix_CE,x_1,load_alpha1);
+//         solver.preprocess();
+        solver.solve();
+        solver.setProblem(stiffnessMatrix_CE,x_2,load_alpha2);
+//         solver.preprocess();
+        solver.solve();
+        solver.setProblem(stiffnessMatrix_CE,x_3,load_alpha3);
+//         solver.preprocess();
+        solver.solve();
+
+//         sPQR.apply(x_1, load_alpha1, statisticsQR);
+//         std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+//         std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+//         std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+//         sPQR.apply(x_2, load_alpha2, statisticsQR);
+//         std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+//         std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+//         std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+//         sPQR.apply(x_3, load_alpha3, statisticsQR);
+//         std::cout << "statistics.converged " << statisticsQR.converged << std::endl;
+//         std::cout << "statistics.condition_estimate: " << statisticsQR.condition_estimate << std::endl;
+//         std::cout << "statistics.iterations: " << statisticsQR.iterations << std::endl;
+        log << "Solver-type used: " <<" UMFPACK-Solver" << std::endl;
+        
+
+    }
+    //     printvector(std::cout, load_alpha1BS, "load_alpha1 before SOLVER", "--" );
+    //     printvector(std::cout, load_alpha1, "load_alpha1 AFTER SOLVER", "--" );
+    //     printvector(std::cout, load_alpha2, "load_alpha2 AFTER SOLVER", "--" );
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // Extract phi_alpha  &  M_alpha coefficients
+    ////////////////////////////////////////////////////////////////////////////////////
+    VectorCT phi_1, phi_2, phi_3;
+    phi_1.resize(Basis_CE.size());
+    phi_1 = 0;
+    phi_2.resize(Basis_CE.size());
+    phi_2 = 0;
+    phi_3.resize(Basis_CE.size());
+    phi_3 = 0;
+
+    for(size_t i=0; i<Basis_CE.size(); i++)
+    {
+        phi_1[i] = x_1[i];
+        phi_2[i] = x_2[i];
+        phi_3[i] = x_3[i];
+    }
+
+    FieldVector<double,3> m_1, m_2, m_3;
+
+    for(size_t i=0; i<3; i++)
+    {
+        m_1[i] = x_1[phiOffset+i];
+        m_2[i] = x_2[phiOffset+i];
+        m_3[i] = x_3[phiOffset+i];
+    }
+    // assemble M_alpha's (actually iota(M_alpha) )
+
+    MatrixRT M_1(0), M_2(0), M_3(0);
+
+    for(size_t i=0; i<3; i++)
+    {
+        M_1 += m_1[i]*basisContainer[i];
+        M_2 += m_2[i]*basisContainer[i];
+        M_3 += m_3[i]*basisContainer[i];
+    }
+
+    std::cout << "--- plot corrector-Matrices M_alpha --- " << std::endl;
+    printmatrix(std::cout, M_1, "Corrector-Matrix M_1", "--");
+    printmatrix(std::cout, M_2, "Corrector-Matrix M_2", "--");
+    printmatrix(std::cout, M_3, "Corrector-Matrix M_3", "--");
+    log << "---------- OUTPUT ----------" << std::endl;
+    log << " --------------------" << std::endl;
+    log << "Corrector-Matrix M_1: \n" << M_1 << std::endl;
+    log << " --------------------" << std::endl;
+    log << "Corrector-Matrix M_2: \n" << M_2 << std::endl;
+    log << " --------------------" << std::endl;
+    log << "Corrector-Matrix M_3: \n" << M_3 << std::endl;
+    log << " --------------------" << std::endl;
+    
+    
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Substract Integral-mean
+    ////////////////////////////////////////////////////////////////////////////                                                                         
+    using SolutionRange = FieldVector<double,dim>;
+
+    if(write_IntegralMean)
+    {
+        std::cout << "check integralMean phi_1: " << std::endl;
+        auto A = integralMean(Basis_CE,phi_1);
+        for(size_t i=0; i<3; i++)
+        {
+            std::cout << "Integral-Mean : " << A[i] << std::endl;
+        }
+    }
+    if(substract_integralMean)
+    {
+        std::cout << " --- substracting integralMean --- " << std::endl;
+        subtractIntegralMean(Basis_CE,  phi_1);
+        subtractIntegralMean(Basis_CE,  phi_2);
+        subtractIntegralMean(Basis_CE,  phi_3);
+        subtractIntegralMean(Basis_CE,  x_1);
+        subtractIntegralMean(Basis_CE,  x_2);
+        subtractIntegralMean(Basis_CE,  x_3);
+        //////////////////////////////////////////
+        // CHECK INTEGRAL-MEAN:
+        //////////////////////////////////////////
+        if(write_IntegralMean)
+        {
+            auto A = integralMean(Basis_CE, phi_1);
+            for(size_t i=0; i<3; i++)
+            {
+            std::cout << "Integral-Mean (CHECK)  : " << A[i] << std::endl;
+            }
+        }
+    }
+
+    /////////////////////////////////////////////////////////
+    // Write Solution (Corrector Coefficients) in Logs
+    /////////////////////////////////////////////////////////
+//     log << "\nSolution of Corrector problems:\n";
+    if(write_corrector_phi1)
+    {
+        log << "\nSolution of Corrector problems:\n";
+        log << "\n Corrector_phi1:\n";
+        log << x_1 << std::endl;
+    }
+    if(write_corrector_phi2)
+    {
+        log << "-----------------------------------------------------";
+        log << "\n Corrector_phi2:\n";
+        log << x_2 << std::endl;
+    }
+    if(write_corrector_phi3)
+    {
+        log << "-----------------------------------------------------";
+        log << "\n Corrector_phi3:\n";
+        log << x_3 << std::endl;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Make a discrete function from the FE basis and the coefficient vector
+    ////////////////////////////////////////////////////////////////////////////                                                                                     // ERROR
+    auto correctorFunction_1 = Functions::makeDiscreteGlobalBasisFunction<SolutionRange>(
+        Basis_CE,
+        phi_1);
+
+    auto correctorFunction_2 = Functions::makeDiscreteGlobalBasisFunction<SolutionRange>(
+        Basis_CE,
+        phi_2);
+
+    auto correctorFunction_3 = Functions::makeDiscreteGlobalBasisFunction<SolutionRange>(
+        Basis_CE,
+        phi_3);
+
+    /////////////////////////////////////////////////////////
+    // Create Containers for Basis-Matrices, Correctors and Coefficients
+    /////////////////////////////////////////////////////////
+    const std::array<Func2Tensor, 3> x3MatrixBasis = {x3G_1, x3G_2, x3G_3};
+    const std::array<VectorCT, 3> coeffContainer = {x_1, x_2, x_3};
+    const std::array<VectorCT, 3> loadContainer = {load_alpha1, load_alpha2, load_alpha3};
+    const std::array<MatrixRT*, 3 > mContainer = {&M_1 , &M_2, & M_3};
+
+    //TEST 
+    
+    auto zeroFunction = [] (const Domain& x) {
+                    return MatrixRT{{0.0 , 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
+                    };
+     auto L2Norm_1 = computeL2Norm(Basis_CE,phi_1);
+     auto L2Norm_Symphi_1 = computeL2SymError(Basis_CE,phi_1,gamma,zeroFunction);    
+     auto L2Norm_2 = computeL2Norm(Basis_CE,phi_2);
+     auto L2Norm_Symphi_2 = computeL2SymError(Basis_CE,phi_2,gamma,zeroFunction);    
+     auto L2Norm_3 = computeL2Norm(Basis_CE,phi_3);
+     auto L2Norm_Symphi_3 = computeL2SymError(Basis_CE,phi_3,gamma,zeroFunction);    
+    
+    std::cout<< "L2Norm - Corrector 1: " << L2Norm_1 << std::endl;
+    std::cout<< "L2Norm (symgrad) - Corrector 1: " << L2Norm_Symphi_1 << std::endl;
+    std::cout<< "L2Norm - Corrector 2: " << L2Norm_2 << std::endl;
+    std::cout<< "L2Norm (symgrad) - Corrector 2: " << L2Norm_Symphi_2 << std::endl;
+    std::cout<< "L2Norm - Corrector 3: " << L2Norm_3 << std::endl;
+    std::cout<< "L2Norm (symgrad) - Corrector 3: " << L2Norm_Symphi_3 << std::endl;
+    
+    std::cout<< "Frobenius-Norm of M_1: " << M_1.frobenius_norm() << std::endl;
+    std::cout<< "Frobenius-Norm of M_2: " << M_2.frobenius_norm() << std::endl;
+    std::cout<< "Frobenius-Norm of M_3: " << M_3.frobenius_norm() << std::endl;
+    
+    //TEST 
+    
+//     auto local_cor1 = localFunction(correctorFunction_1);
+//     auto local_cor2 = localFunction(correctorFunction_2);
+//     auto local_cor3 = localFunction(correctorFunction_3);
+//     
+//     auto Der1 = derivative(local_cor1);
+//     auto Der2 = derivative(local_cor2);
+//     auto Der3 = derivative(local_cor3);
+    
+    auto Der1 = derivative(correctorFunction_1);
+    auto Der2 = derivative(correctorFunction_2);
+    auto Der3 = derivative(correctorFunction_3);
+    
+    const std::array<decltype(Der1)*,3> phiDerContainer = {&Der1, &Der2, &Der3};
+    
+//     auto output_der = test_derivative(Basis_CE,Der1);
+    
+    
+//     std::cout << "evaluate derivative " << output_der << std::endl;
+
+    
+    
+    // TODO : MOVE All of this into a separate class : 'computeEffectiveQuantities'
+    /////////////////////////////////////////////////////////
+    // Compute effective quantities: Elastic law & Prestrain
+    /////////////////////////////////////////////////////////
+    MatrixRT Q(0);
+    VectorCT tmp1,tmp2;
+    FieldVector<double,3> B_hat ;
+    
+    
+    
+    //VARIANT 1
+    //Compute effective elastic law Q
+    for(size_t a = 0; a < 3; a++)
+        for(size_t b=0; b < 3; b++)
+        {
+            assembleCellLoad(Basis_CE, muLocal, lambdaLocal, gamma, tmp1 ,x3MatrixBasis[b]);   // <L i(M_alpha) + sym(grad phi_alpha), i(x3G_beta) >
+
+            double GGterm = 0.0;
+            double MGterm = 0.0;
+            GGterm = energy(Basis_CE, muLocal, lambdaLocal, x3MatrixBasis[a] , x3MatrixBasis[b]  );   // <L i(x3G_alpha) , i(x3G_beta) >
+            MGterm = energy_MG(Basis_CE, muLocal, lambdaLocal, mContainer[a], x3MatrixBasis[b]); 
+            
+            double tmp = 0.0;
+            
+            tmp = test_derivative(Basis_CE, muLocal, lambdaLocal,gamma,mContainer[a],*phiDerContainer[a],x3MatrixBasis[b]);
+            
+            
+            
+            std::cout << "---- (" << a << "," << b << ") ---- " << std::endl; 
+            
+            std::cout << "check_Orthogonality:" << check_Orthogonality(Basis_CE, muLocal, lambdaLocal,gamma,mContainer[a],mContainer[b],*phiDerContainer[a],*phiDerContainer[b],x3MatrixBasis[a])  << std::endl;
+            
+            
+            
+            
+//             if(a==0)
+//             {
+//                 tmp = test_derivative(Basis_CE, muLocal, lambdaLocal,gamma,mContainer[a],Der1,x3MatrixBasis[b]);
+//                 std::cout << "check_Orthogonality:" << check_Orthogonality(Basis_CE, muLocal, lambdaLocal,gamma,mContainer[a],mContainer[1],Der1,Der2,x3MatrixBasis[a])  << std::endl;
+//             }
+//             else if (a==1)
+//             {
+//                 tmp = test_derivative(Basis_CE, muLocal, lambdaLocal,gamma,mContainer[a],Der2,x3MatrixBasis[b]);
+//                 std::cout << "check_Orthogonality:" << check_Orthogonality(Basis_CE, muLocal, lambdaLocal,gamma,mContainer[a],mContainer[1],Der2,Der2,x3MatrixBasis[a])  << std::endl;
+//             }
+//             else 
+//             {
+//                 tmp = test_derivative(Basis_CE, muLocal, lambdaLocal,gamma,mContainer[a],Der3,x3MatrixBasis[b]);
+//                 std::cout << "check_Orthogonality:" << check_Orthogonality(Basis_CE, muLocal, lambdaLocal,gamma,mContainer[a],mContainer[1],Der3,Der2,x3MatrixBasis[a])  << std::endl;
+//             }
+            
+            
+            std::cout << "GGTerm:" << GGterm << std::endl;
+            std::cout << "MGTerm:" << MGterm << std::endl;
+            std::cout << "tmp:" << tmp << std::endl;
+            std::cout << "(coeffContainer[a]*tmp1):" << (coeffContainer[a]*tmp1) << std::endl;
+            
+    
+            // TEST
+            // std::setprecision(std::numeric_limits<float>::digits10);
+
+//             Q[a][b] =  (coeffContainer[a]*tmp1) + GGterm;                         // seems symmetric...check positiv definitness?
+            Q[a][b] =  tmp + GGterm;     // TODO : Zusammenfassen in einer Funktion ...
+        
+            if (print_debug)
+            {
+                std::cout << "analyticGGTERM:" << (mu1*(1-theta)+mu2*theta)/6.0 << std::endl;
+                std::cout << "GGTerm:" << GGterm << std::endl;
+                std::cout << "coeff*tmp: " << coeffContainer[a]*tmp1 << std::endl;
+            }
+        }
+    printmatrix(std::cout, Q, "Matrix Q", "--");
+    log << "Effective Matrix Q: " << std::endl;
+    log << Q << std::endl;
+        
+        
+        
+    //---VARIANT 2
+    //Compute effective elastic law Q
+    MatrixRT Q_2(0);
+    for(size_t a = 0; a < 3; a++)
+        for(size_t b=0; b < 3; b++)
+        {
+            std::cout << "check_Orthogonality:" << check_Orthogonality(Basis_CE, muLocal, lambdaLocal,gamma,mContainer[a],mContainer[b],*phiDerContainer[a],*phiDerContainer[b],x3MatrixBasis[a])  << std::endl;
+            Q_2[a][b] = computeFullQ(Basis_CE, muLocal, lambdaLocal,gamma,mContainer[a],mContainer[b],*phiDerContainer[a],*phiDerContainer[b],x3MatrixBasis[a],x3MatrixBasis[b]);
+        }
+    printmatrix(std::cout, Q_2, "Matrix Q_2", "--");
+//     Q = Q_2; 
+    
+    //--- VARIANT 3
+    // Compute effective elastic law Q
+//     MatrixRT Q_3(0);
+//     for(size_t a = 0; a < 3; a++)
+//         for(size_t b=0; b < 3; b++)
+//         {
+//             assembleCellLoad(Basis_CE, muLocal, lambdaLocal, gamma, tmp1 ,x3MatrixBasis[b]);   // <L i(M_alpha) + sym(grad phi_alpha), i(x3G_beta) >
+// 
+//             double GGterm = 0.0;
+//             GGterm = energy(Basis_CE, muLocal, lambdaLocal, x3MatrixBasis[a] , x3MatrixBasis[b]  );   // <L i(x3G_alpha) , i(x3G_beta) >
+// 
+//             // TEST
+//             // std::setprecision(std::numeric_limits<float>::digits10);
+// 
+//             Q_3[a][b] =  (coeffContainer[a]*tmp1) + GGterm;                         // seems symmetric...check positiv definitness?
+//         
+//             if (print_debug)
+//             {
+//                 std::cout << "analyticGGTERM:" << (mu1*(1-theta)+mu2*theta)/6.0 << std::endl;
+//                 std::cout << "GGTerm:" << GGterm << std::endl;
+//                 std::cout << "coeff*tmp: " << coeffContainer[a]*tmp1 << std::endl;
+//             }
+//         }
+//     printmatrix(std::cout, Q_3, "Matrix Q_3", "--");
+
+
+
+
+    // compute B_hat
+    for(size_t a = 0; a<3; a++)
+    {
+        assembleCellLoad(Basis_CE, muLocal, lambdaLocal, gamma, tmp2 ,B_Term);  // <L i(M_alpha) + sym(grad phi_alpha), B >
+        auto GBterm = energy(Basis_CE, muLocal, lambdaLocal, x3MatrixBasis[a] , B_Term); // <L i(x3G_alpha) , B>
+        B_hat[a] = (coeffContainer[a]*tmp2) + GBterm;
+        
+        if (print_debug)
+        {
+            std::cout << "check this Contribution: " << (coeffContainer[a]*tmp2) << std::endl;  //see orthotropic.tex
+        }
+    }
+
+//     log << B_hat << std::endl;
+//     log << "Prestrain B_hat: " << std::endl;
+//     log << B_hat << std::endl;
+
+    std::cout << "check this Contribution: " << (coeffContainer[2]*tmp2) << std::endl;  //see orthotropic.tex
+
+    ///////////////////////////////
+    // Compute effective Prestrain B_eff
+    //////////////////////////////
+    FieldVector<double, 3> Beff;
+    Q.solve(Beff,B_hat);
+    
+    log << "--- Prestrain Output --- " << std::endl;
+    log << "B_hat: " << B_hat << std::endl;
+    log << "B_eff: " << Beff <<  " (Effective Prestrain)" << std::endl;
+    log << "------------------------ " << std::endl;
+//     log << Beff << std::endl;
+//     log << "Effective Prestrain B_eff: " << std::endl;
+//     log << Beff << std::endl;
+//     printvector(std::cout, Beff, "Beff", "--");
+
+    auto q1 = Q[0][0];
+    auto q2 = Q[1][1];
+    auto q3 = Q[2][2];
+    
+//     std::cout<< "q1 : " << q1 << std::endl;
+//     std::cout<< "q2 : " << q2 << std::endl;
+    std::cout.precision(10);
+//     std::cout << "q3 : " << std::fixed << q3 << std::endl;
+//     std::cout<< "q3 : " << q3 << std::endl;
+    std::cout<< std::fixed << std::setprecision(6) << "q_onetwo=" << Q[0][1] << std::endl;
+//     std::cout<< std::fixed << std::setprecision(6) << "q_onetwo=" << Q[1][0] << std::endl; //TEST 
+    printvector(std::cout, B_hat, "B_hat", "--");
+    printvector(std::cout, Beff, "Beff", "--");
+    
+    std::cout << "Theta: " << theta << std::endl;
+    std::cout << "Gamma: " << gamma << std::endl;
+    std::cout << "Number of Elements in each direction: " << nElements << std::endl;
+    log << "q1=" << q1 << std::endl;
+    log << "q2=" << q2 << std::endl;
+    log << "q3=" << q3 << std::endl;
+    log << "q12=" << Q[0][1] << std::endl;
+    
+    log << "b1=" << Beff[0] << std::endl;
+    log << "b2=" << Beff[1] << std::endl;
+    log << "b3=" << Beff[2] << std::endl;
+    log << "b1_hat: " << B_hat[0] << std::endl;
+    log << "b2_hat: " << B_hat[1] << std::endl;
+    log << "b3_hat: " << B_hat[2] << std::endl;
+    log << "mu_gamma=" << q3 << std::endl;           // added for Python-Script
+ 
+    log << std::fixed << std::setprecision(6) << "q_onetwo=" << Q[0][1] << std::endl;
+//     log << "q_onetwo=" << Q[0][1] << std::endl;           // added for Python-Script
+
+    //////////////////////////////////////////////////////////////
+    // Define Analytic Solutions
+    //////////////////////////////////////////////////////////////
+
+    
+    
+    
+    
+    
+    std::cout << "Test B_hat & B_eff" << std::endl;
+     double p1 = parameterSet.get<double>("rho1", 1.0);
+     double alpha = parameterSet.get<double>("alpha", 2.0);
+     double p2 = alpha*p1;
+     
+    if (imp == "parametrized_Laminate" && lambda1==0 )  // only in this case we know an analytical solution
+    {
+        double rho1 = parameterSet.get<double>("rho1", 1.0);
+//         double b1_hat_ana = (-(theta/4.0)*mu1*mu2)/(theta*mu1+(1.0-theta)*mu2);
+//         double b2_hat_ana = -(theta/4.0)*mu2;
+//         double b3_hat_ana = 0.0;
+    
+        double b1_eff_ana = (3.0/2.0)*rho1*(1-theta*(1+alpha));
+        double b2_eff_ana = (3.0/2.0)*rho1*((1-theta*(1+beta*alpha))/(1-theta+theta*beta));
+        double b3_eff_ana = 0.0;
+        
+    //     double q1_ana = ((mu1*mu2)/6.0)/(theta*mu1+ (1.0- theta)*mu2);
+    //     double q2_ana = ((1.0-theta)*mu1+theta*mu2)/6.0;
+        double q1_ana = mu1*(beta/(theta+(1-theta)*beta)) *(1.0/6.0);  // 1/6 * harmonicMean
+        double q2_ana = mu1*((1-theta)+theta*beta)        *(1.0/6.0);     // 1/6 * arithmeticMean
+
+        std::cout << "----- print analytic solutions -----" << std::endl;
+//         std::cout << "b1_hat_ana : " << b1_hat_ana << std::endl;
+//         std::cout << "b2_hat_ana : " << b2_hat_ana << std::endl;
+//         std::cout << "b3_hat_ana : " << b3_hat_ana << std::endl;
+        std::cout << "b1_eff_ana : " << b1_eff_ana << std::endl;
+        std::cout << "b2_eff_ana : " << b2_eff_ana << std::endl;
+        std::cout << "b3_eff_ana : " << b3_eff_ana << std::endl;
+        
+        std::cout << "q1_ana : "     << q1_ana << std::endl;
+        std::cout << "q2_ana : "     << q2_ana << std::endl;
+        std::cout << "q3 should be between q1 and q2"  << std::endl;
+        log << "----- print analytic solutions -----" << std::endl;
+//         log << "b1_hat_ana : " << b1_hat_ana << std::endl;
+//         log << "b2_hat_ana : " << b2_hat_ana << std::endl;
+//         log << "b3_hat_ana : " << b3_hat_ana << std::endl;
+        log << "b1_eff_ana : " << b1_eff_ana << std::endl;
+        log << "b2_eff_ana : " << b2_eff_ana << std::endl;
+        log << "b3_eff_ana : " << b3_eff_ana << std::endl;
+        log << "q1_ana : "     << q1_ana << std::endl;
+        log << "q2_ana : "     << q2_ana << std::endl;
+        log << "q3 should be between q1 and q2"  << std::endl;
+        
+        Storage_Quantities.push_back(std::abs(q1_ana - q1));
+        Storage_Quantities.push_back(std::abs(q2_ana - q2));
+        Storage_Quantities.push_back(q3);
+        Storage_Quantities.push_back(std::abs(b1_eff_ana - Beff[0]));
+        Storage_Quantities.push_back(std::abs(b2_eff_ana - Beff[1]));
+        Storage_Quantities.push_back(std::abs(b3_eff_ana - Beff[2]));
+    }
+    else if (imp == "analytical_Example")   // print Errors only for analytical_Example
+    {
+        std::cout << ((3.0*p1)/2.0)*beta*(1-(theta*(1+alpha)))   << std::endl;  // TODO ERROR in paper ?? 
+        
+        // double b1 = (mu1*p1/4)*(beta/(theta+(1-theta)*beta))*(1-theta*(1+alpha));
+        // double b2 = (mu1*p1/8)*(1-theta*(1+beta*alpha));
+        double b1_hat_ana = (-(theta/4.0)*mu1*mu2)/(theta*mu1+(1.0-theta)*mu2);
+        double b2_hat_ana = -(theta/4.0)*mu2;
+        double b3_hat_ana = 0.0;
+    
+        double b1_eff_ana = (-3.0/2.0)*theta;
+        double b2_eff_ana = (-3.0/2.0)*(theta*mu2)/(mu1*(1-theta)+mu2*theta);
+        double b3_eff_ana = 0.0;
+        
+    //     double q1_ana = ((mu1*mu2)/6.0)/(theta*mu1+ (1.0- theta)*mu2);
+    //     double q2_ana = ((1.0-theta)*mu1+theta*mu2)/6.0;
+        double q1_ana = mu1*(beta/(theta+(1-theta)*beta)) *(1.0/6.0);  // 1/6 * harmonicMean
+        double q2_ana = mu1*((1-theta)+theta*beta)        *(1.0/6.0);     // 1/6 * arithmeticMean
+
+        std::cout << "----- print analytic solutions -----" << std::endl;
+        std::cout << "b1_hat_ana : " << b1_hat_ana << std::endl;
+        std::cout << "b2_hat_ana : " << b2_hat_ana << std::endl;
+        std::cout << "b3_hat_ana : " << b3_hat_ana << std::endl;
+        std::cout << "b1_eff_ana : " << b1_eff_ana << std::endl;
+        std::cout << "b2_eff_ana : " << b2_eff_ana << std::endl;
+        std::cout << "b3_eff_ana : " << b3_eff_ana << std::endl;
+        
+        std::cout << "q1_ana : "     << q1_ana << std::endl;
+        std::cout << "q2_ana : "     << q2_ana << std::endl;
+        std::cout << "q3 should be between q1 and q2"  << std::endl;
+        log << "----- print analytic solutions -----" << std::endl;
+        log << "b1_hat_ana : " << b1_hat_ana << std::endl;
+        log << "b2_hat_ana : " << b2_hat_ana << std::endl;
+        log << "b3_hat_ana : " << b3_hat_ana << std::endl;
+        log << "b1_eff_ana : " << b1_eff_ana << std::endl;
+        log << "b2_eff_ana : " << b2_eff_ana << std::endl;
+        log << "b3_eff_ana : " << b3_eff_ana << std::endl;
+        log << "q1_ana : "     << q1_ana << std::endl;
+        log << "q2_ana : "     << q2_ana << std::endl;
+        log << "q3 should be between q1 and q2"  << std::endl;
+        
+        Storage_Quantities.push_back(std::abs(q1_ana - q1));
+        Storage_Quantities.push_back(std::abs(q2_ana - q2));
+        Storage_Quantities.push_back(q3);
+        Storage_Quantities.push_back(std::abs(b1_eff_ana - Beff[0]));
+        Storage_Quantities.push_back(std::abs(b2_eff_ana - Beff[1]));
+        Storage_Quantities.push_back(std::abs(b3_eff_ana - Beff[2]));
+    }
+    else
+    {
+        Storage_Quantities.push_back(q1);
+        Storage_Quantities.push_back(q2);
+        Storage_Quantities.push_back(q3);
+        Storage_Quantities.push_back(Beff[0]);
+        Storage_Quantities.push_back(Beff[1]);
+        Storage_Quantities.push_back(Beff[2]);
+    }
+
+
+    auto symPhi_1_analytic = [mu1, mu2, theta, muTerm] (const Domain& x) {
+                        return MatrixRT{{  (((mu1*mu2)/((theta*mu1 +(1-theta)*mu2)*muTerm(x))) - 1)*x[2] , 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
+                    };
+
+
+
+    if(write_L2Error)
+    {
+        
+//         std::cout << " ----- L2ErrorSym ----" << std::endl;
+        auto L2SymError = computeL2SymError(Basis_CE,phi_1,gamma,symPhi_1_analytic);
+//         std::cout << "L2SymError: " << L2SymError << std::endl;
+//         std::cout << " -----------------" << std::endl;
+
+//         std::cout << " ----- L2NORMSym ----" << std::endl;
+        auto L2Norm_Symphi = computeL2SymError(Basis_CE,phi_1,gamma,zeroFunction);                           
+//         std::cout << "L2-Norm(Symphi_1): " << L2Norm_Symphi << std::endl;           
+        VectorCT zeroVec;
+        zeroVec.resize(Basis_CE.size());
+        zeroVec = 0;
+        auto L2Norm_SymAnalytic = computeL2SymError(Basis_CE,zeroVec ,gamma, symPhi_1_analytic);
+//         std::cout << "L2-Norm(SymAnalytic): " << L2Norm_SymAnalytic << std::endl;
+//         std::cout << " -----------------" << std::endl;
+
+//         std::cout << " ----- L2NORM ----" << std::endl;
+        auto L2Norm = computeL2Norm(Basis_CE,phi_1); 
+//         std::cout << "L2Norm(phi_1): "  << L2Norm << std::endl;
+//         std::cout << " -----------------" << std::endl;
+        
+        
+        
+//         log << "L2-Error (symmetric Gradient phi_1):" << L2SymError << std::endl;
+//         log << "L2-Norm(Symphi_1): "    << L2Norm_Symphi<< std::endl;
+//         log << "L2-Norm(SymAnalytic): " << L2Norm_SymAnalytic << std::endl;
+
+        double EOC = 0.0;
+        Storage_Error.push_back(L2SymError);
+
+        //Compute Experimental order of convergence (EOC)
+        if(levelCounter > 0)
+        {
+            // Storage_Error:: #1 level #2 L2SymError #3 L2SymErrorOrder #4  L2Norm(sym) #5 L2Norm(sym-analytic) #6 L2Norm(phi_1)
+//             std::cout << " ((levelCounter-1)*6)+1: " << ((levelCounter-1)*6)+1 << std::endl;           // Besser std::map ???
+//             std::cout << " ((levelCounter-1)*6)+1: " << ((levelCounter)*6)+1 << std::endl;             // für Storage_Error[idx] muss idx zur compile time feststehen?!
+            auto ErrorOld = std::get<double>(Storage_Error[((levelCounter-1)*6)+1]);
+            auto ErrorNew = std::get<double>(Storage_Error[(levelCounter*6)+1]);
+//
+            EOC = std::log(ErrorNew/ErrorOld)/(-1*std::log(2));
+            //   std::cout << "Storage_Error[0] :" << std::get<1>(Storage_Error[0]) << std::endl;
+            //   std::cout << "output variant :" << std::get<std::string>(Storage_Error[1]) << std::endl;
+            //   std::cout << "output variant :" << std::get<0>(Storage_Error[1]) << std::endl;
+        }
+//         Storage_Error.push_back(level);
+        Storage_Error.push_back(EOC);
+        Storage_Error.push_back(L2Norm_Symphi);
+        Storage_Error.push_back(L2Norm_SymAnalytic);
+        Storage_Error.push_back(L2Norm);
+    }
+  //////////////////////////////////////////////////////////////////////////////////////////////
+  // Write Data to Matlab / Optimization-Code
+  //////////////////////////////////////////////////////////////////////////////////////////////
+//   writeMatrixToMatlab(Q, "../../Matlab-Programs/QMatrix.txt");
+  writeMatrixToMatlab(Q, outputPath + "/QMatrix.txt");
+  
+  // write effective Prestrain in Matrix for Output
+  FieldMatrix<double,1,3> BeffMat;
+  BeffMat[0] = Beff;
+//   writeMatrixToMatlab(BeffMat, "../../Matlab-Programs/BMatrix.txt");
+  writeMatrixToMatlab(BeffMat, outputPath + "/BMatrix.txt");
+  
+  //////////////////////////////////////////////////////////////////////////////////////////////
+  // Write result to VTK file
+  //////////////////////////////////////////////////////////////////////////////////////////////
+  if(write_VTK) 
+  {
+        std::string vtkOutputName = outputPath + "/CellProblem-result";
+        
+        std::cout << "vtkOutputName:" << vtkOutputName << std::endl;
+        
+        VTKWriter<GridView> vtkWriter(gridView_CE);
+
+        vtkWriter.addVertexData(
+            correctorFunction_1,
+            VTK::FieldInfo("Corrector phi_1 level"+ std::to_string(level) , VTK::FieldInfo::Type::vector, dim));     
+        vtkWriter.addVertexData(
+            correctorFunction_2,
+            VTK::FieldInfo("Corrector phi_2 level"+ std::to_string(level) , VTK::FieldInfo::Type::vector, dim));
+        vtkWriter.addVertexData(
+            correctorFunction_3,
+            VTK::FieldInfo("Corrector phi_3 level"+ std::to_string(level) , VTK::FieldInfo::Type::vector, dim));
+        //   vtkWriter.write( vtkOutputName );
+        vtkWriter.write(vtkOutputName  + "-level"+ std::to_string(level));
+        //     vtkWriter.pwrite( vtkOutputName  + "-level"+ std::to_string(level), outputPath, "");   // TEST Write to folder "/outputs" 
+        //   vtkWriter.pwrite( vtkOutputName  + "-level"+ std::to_string(level), outputPath, "", VTK::OutputType::ascii, 0, 0 );
+        std::cout << "wrote data to file: " + vtkOutputName + "-level" + std::to_string(level) << std::endl;      
+  }
+  
+  
+   if (write_materialFunctions)
+   {
+        using VTKGridType = YaspGrid<dim, EquidistantOffsetCoordinates<double, dim> >;
+//         VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},{80,80,80});
+//         VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},{40,40,40});
+        VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},nElements);
+        
+        using GridViewVTK = VTKGridType::LeafGridView;
+        const GridViewVTK gridView_VTK = grid_VTK.leafGridView();
+        
+        auto scalarP0FeBasis = makeBasis(gridView_VTK,lagrange<0>());
+        auto scalarP1FeBasis = makeBasis(gridView_VTK,lagrange<1>());
+
+        std::vector<double> mu_CoeffP0;
+        Functions::interpolate(scalarP0FeBasis, mu_CoeffP0, muTerm);
+        auto mu_DGBF_P0 = Functions::makeDiscreteGlobalBasisFunction<double>(scalarP0FeBasis, mu_CoeffP0);
+        
+        std::vector<double> mu_CoeffP1;
+        Functions::interpolate(scalarP1FeBasis, mu_CoeffP1, muTerm);
+        auto mu_DGBF_P1 = Functions::makeDiscreteGlobalBasisFunction<double>(scalarP1FeBasis, mu_CoeffP1);
+        
+        
+        std::vector<double> lambda_CoeffP0;
+        Functions::interpolate(scalarP0FeBasis, lambda_CoeffP0, lambdaTerm);
+        auto lambda_DGBF_P0 = Functions::makeDiscreteGlobalBasisFunction<double>(scalarP0FeBasis, lambda_CoeffP0);
+        
+        std::vector<double> lambda_CoeffP1;
+        Functions::interpolate(scalarP1FeBasis, lambda_CoeffP1, lambdaTerm);
+        auto lambda_DGBF_P1 = Functions::makeDiscreteGlobalBasisFunction<double>(scalarP1FeBasis, lambda_CoeffP1);
+        
+        VTKWriter<GridView> MaterialVtkWriter(gridView_VTK);
+        
+        MaterialVtkWriter.addVertexData(
+            mu_DGBF_P1,
+            VTK::FieldInfo("mu_P1", VTK::FieldInfo::Type::scalar, 1));    
+        MaterialVtkWriter.addCellData(
+            mu_DGBF_P0,
+            VTK::FieldInfo("mu_P0", VTK::FieldInfo::Type::scalar, 1));    
+        MaterialVtkWriter.addVertexData(
+            lambda_DGBF_P1,
+            VTK::FieldInfo("lambda_P1", VTK::FieldInfo::Type::scalar, 1));    
+        MaterialVtkWriter.addCellData(
+            lambda_DGBF_P0,
+            VTK::FieldInfo("lambda_P0", VTK::FieldInfo::Type::scalar, 1));    
+        
+        MaterialVtkWriter.write(outputPath + "/MaterialFunctions-level"+ std::to_string(level) );
+        std::cout << "wrote data to file:" + outputPath +"/MaterialFunctions-level" + std::to_string(level) << std::endl;  
+        
+   }
+  
+   if (write_prestrainFunctions)
+   {
+    using VTKGridType = YaspGrid<dim, EquidistantOffsetCoordinates<double, dim> >;
+//     VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},{80,80,80});
+//     VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},{40,40,40});
+    VTKGridType grid_VTK({-1.0/2.0, -1.0/2.0, -1.0/2.0},{1.0/2.0, 1.0/2.0, 1.0/2.0},nElements);
+    using GridViewVTK = VTKGridType::LeafGridView;
+    const GridViewVTK gridView_VTK = grid_VTK.leafGridView();
+   
+    FTKfillerContainer<dim> VTKFiller;
+    VTKFiller.vtkPrestrainNorm(gridView_VTK, B_Term, "PrestrainBNorm");
+    
+    // WORKS Too 
+    VTKFiller.vtkProblemCell(gridView_VTK, B_Term, muLocal,"VTKProblemCell");;
+    
+    
+    // TEST 
+    auto scalarP0FeBasis = makeBasis(gridView_VTK,lagrange<0>());
+    auto scalarP1FeBasis = makeBasis(gridView_VTK,lagrange<1>());
+
+    std::vector<double> B_CoeffP0;
+    Functions::interpolate(scalarP0FeBasis, B_CoeffP0, B_Term);
+    auto B_DGBF_P0 = Functions::makeDiscreteGlobalBasisFunction<double>(scalarP0FeBasis, B_CoeffP0);
+        
+
+        
+    VTKWriter<GridView> PrestrainVtkWriter(gridView_VTK);
+         
+    PrestrainVtkWriter.addCellData(
+            B_DGBF_P0,
+            VTK::FieldInfo("B_P0", VTK::FieldInfo::Type::scalar, 1));     
+        
+    PrestrainVtkWriter.write(outputPath + "/PrestrainFunctions-level"+ std::to_string(level) );
+    std::cout << "wrote data to file:" + outputPath +"/PrestrainFunctions-level" + std::to_string(level) << std::endl; 
+
+   }
+  
+  
+  levelCounter++; 
+  } // Level-Loop End
+  
+    
+  
+
+    /////////////////////////////////////////
+    // Print Storage
+    /////////////////////////////////////////
+    int tableWidth = 12;
+    if (imp == "analytical_Example")   // print Errors only for analytical_Example
+    {
+        std::cout << std::string(tableWidth*7 + 3*7, '-') << "\n";
+        std::cout << center("Levels",tableWidth)       << " | "
+                << center("L2SymError",tableWidth)     << " | "
+                << center("Order",tableWidth)     << " | "
+                << center("L2SymNorm",tableWidth)     << " | "
+                << center("L2SymNorm_ana",tableWidth)     << " | "
+                << center("L2Norm",tableWidth)  << " | " << "\n";
+        std::cout << std::string(tableWidth*6 + 3*6, '-') << "\n";
+        log     << std::string(tableWidth*6 + 3*6, '-') << "\n";
+        log     << center("Levels",tableWidth)       << " | "
+                << center("L2SymError",tableWidth)     << " | "
+                << center("Order",tableWidth)     << " | "
+                << center("L2SymNorm",tableWidth)     << " | "
+                << center("L2SNorm_ana",tableWidth)     << " | "
+                << center("L2Norm",tableWidth)  << " | " << "\n";
+        log     << std::string(tableWidth*6 + 3*6, '-') << "\n";
+        
+        int StorageCount = 0;
+
+        for(auto& v: Storage_Error) 
+        {
+            std::visit([tableWidth](auto&& arg){std::cout << center(prd(arg,5,1),tableWidth)      << " | ";}, v);      // Anzahl-Nachkommastellen
+            std::visit([tableWidth, &log](auto&& arg){log << center(prd(arg,5,1),tableWidth)      << " & ";}, v);
+            StorageCount++;
+            if(StorageCount % 6 == 0 )
+            {
+                std::cout << std::endl;
+                log << std::endl;
+            }
+        }
+    }
+    
+    //////////////// OUTPUT QUANTITIES TABLE //////////////
+    if (imp == "analytical_Example" || (imp == "parametrized_Laminate" && lambda1==0 ) )   // print Errors only for analytical_Example
+    {
+    std::cout << std::string(tableWidth*7 + 3*7, '-') << "\n";
+    std::cout << center("Levels ",tableWidth)       << " | "
+              << center("|q1_ana-q1|",tableWidth)       << " | "
+              << center("|q2_ana-q2|",tableWidth)       << " | "
+              << center("q3",tableWidth)           << " | "
+              << center("|b1_ana-b1|",tableWidth)       << " | "
+              << center("|b2_ana-b2|",tableWidth)       << " | "
+              << center("|b3_ana-b3|",tableWidth)       << " | " << "\n";
+    std::cout << std::string(tableWidth*7 + 3*7, '-') << "\n";
+    log       << std::string(tableWidth*7 + 3*7, '-') << "\n";
+    log       << center("Levels ",tableWidth)       << " | "
+              << center("|q1_ana-q1|",tableWidth)       << " | "
+              << center("|q2_ana-q2|",tableWidth)       << " | "
+              << center("q3",tableWidth)           << " | "
+              << center("|b1_ana-b1|",tableWidth)       << " | "
+              << center("|b2_ana-b2|",tableWidth)       << " | "
+              << center("|b3_ana-b3|",tableWidth)       << " | " << "\n";
+    log       << std::string(tableWidth*7 + 3*7, '-') << "\n";
+    }
+    else
+    {
+    std::cout << center("Levels ",tableWidth)       << " | "
+              << center("q1",tableWidth)       << " | "
+              << center("q2",tableWidth)       << " | "
+              << center("q3",tableWidth)           << " | "
+              << center("b1",tableWidth)       << " | "
+              << center("b2",tableWidth)       << " | "
+              << center("b3",tableWidth)       << " | " << "\n";
+    std::cout << std::string(tableWidth*7 + 3*7, '-') << "\n";
+    log       << std::string(tableWidth*7 + 3*7, '-') << "\n";   
+    log       << center("Levels ",tableWidth)       << " | "
+              << center("q1",tableWidth)       << " | "
+              << center("q2",tableWidth)       << " | "
+              << center("q3",tableWidth)           << " | "
+              << center("b1",tableWidth)       << " | "
+              << center("b2",tableWidth)       << " | "
+              << center("b3",tableWidth)       << " | " << "\n";
+    log       << std::string(tableWidth*7 + 3*7, '-') << "\n";   
+    }
+    
+    int StorageCount2 = 0;
+    for(auto& v: Storage_Quantities) 
+    {
+        std::visit([tableWidth](auto&& arg){std::cout << center(prd(arg,5,1),tableWidth)      << " | ";}, v);
+        std::visit([tableWidth, &log](auto&& arg){log << center(prd(arg,5,1),tableWidth)      << " & ";}, v);
+        StorageCount2++;
+        if(StorageCount2 % 7 == 0 )
+        {
+            std::cout << std::endl;
+            log << std::endl;
+        }
+    }
+    std::cout << std::string(tableWidth*7 + 3*7, '-') << "\n";
+    log       << std::string(tableWidth*7 + 3*7, '-') << "\n";  
+
+    log.close();
+    
+    std::cout << "Total time elapsed: " << globalTimer.elapsed() << std::endl;
+}
-- 
GitLab