From 83d2b223af965b8dc6aa177baa39560152a7c465 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20H=C3=B6rl?=
 <maximilian.hoerl@mathematik.uni-stuttgart.de>
Date: Fri, 17 Jan 2020 19:45:32 +0100
Subject: [PATCH] transfer assemblation of A and b to separate method

---
 dune/mmdg/dg.hh | 740 ++++++++++++++++++++++++------------------------
 1 file changed, 373 insertions(+), 367 deletions(-)

diff --git a/dune/mmdg/dg.hh b/dune/mmdg/dg.hh
index e576d2d..e76112b 100644
--- a/dune/mmdg/dg.hh
+++ b/dune/mmdg/dg.hh
@@ -18,7 +18,7 @@ class DG
 public:
   using Scalar = typename GridView::ctype;
   static constexpr int dim = GridView::dimension;
-  using Matrix = Dune::DynamicMatrix<Scalar>;
+  using Matrix = Dune::DynamicMatrix<Scalar>; //NOTE: what is an appropriate sparse matrix type? -> BCRS
   using Vector = Dune::DynamicVector<Scalar>;
 
   //constructor
@@ -34,372 +34,8 @@ public:
 
   const void operator() (const Scalar K, const Scalar mu)
   {
-    //NOTE: what is an appropriate sparse matrix type? -> BCRS
-
-    //NOTE:
-//    const int order = 3; //order of the quadrature rule
-    for(const auto& elem : elements(gridView_))
-    {
-      const auto& geo = elem.geometry();
-      std::cout << mapper_.index(elem) << "\t";
-      for (int k = 0; k < geo.corners(); k++)
-      {
-        std::cout << geo.corner(k) << "\t";
-      }
-      std::cout << "\n\n";
-    }
-
-
-    //we use the basis
-    // phi_elem,0 (x) = indicator(elem);
-    // phi_elem,i (x) = x[i]*indicator(elem);
-    //for elem in elements(gridView) and i = 1,...,dim
-    for (const auto& elem : elements(gridView_))
-    {
-      const int elemIdx = mapper_.index(elem);
-      const auto& geo = elem.geometry();
-      const double elemVol = geo.volume();
-      const auto& center = geo.center();
-
-      std::cout << "===============================\nElement " << elemIdx;
-      for (int k = 0; k < geo.corners(); k++)
-      {
-        std::cout << "\t" << geo.corner(k);
-      }
-      std::cout << "\n\n";
-
-      //in the system of linear equations (SLE) Ad = b,
-      //the index elemIdxSLE refers to the basis function phi_elem,0
-      //and the indices elemIdxSLE + i + 1, i = 1,...,dim, refer to the
-      //basis function phi_elem,i
-      const int elemIdxSLE = (dim + 1)*elemIdx;
-
-  /*    //TODO: can be done outside of the loop?
-      const Dune::QuadratureRule<double,dim>& rule =
-        Dune::QuadratureRules<double,dim>::rule(geo.type(),order);
-
-      //NOTE: how are quadrature rules in Dune applied correctly?
-      for (const auto& ip : rule)
-      {
-        const auto qp = ip.position();
-        //NOTE: is the volume of the element taken into account
-        //automatically?
-        const auto weight = ip.weight();
-
-        //quadrature for int_elem q*phi_elem,0 dV
-        b[elemIdxSLE] += weight * q(qp);
-
-        //quadrature for int_elem q*phi_elem,i dV
-        for (int i = 0; i < dim; i++)
-        {
-          b[elemIdxSLE + i + 1] += weight * qp[i] * q(qp);
-        }
-      }
-  */
-
-      //NOTE: makeshift solution for source term q = -1
-      b[elemIdxSLE] += -elemVol;
-      for (int i = 0; i < dim; i++)
-      {
-        b[elemIdxSLE + i + 1] += -elemVol * center[i];
-      }
-
-      for (int i = 0; i < dim; i++)
-      {
-        //exact evaluation of
-        // int_elem K*grad(phi_elem,i)*grad(phi_elem,i) dV
-        A[elemIdxSLE + i + 1][elemIdxSLE + i + 1] += K * elemVol;
-      }
-
-      //iterate over all intersection with the boundary of elem
-      for (const auto& intersct : intersections(gridView_, elem))
-      {
-        const auto& normal = intersct.centerUnitOuterNormal();
-        const auto& intersctGeo = intersct.geometry();
-        const double intersctVol = intersctGeo.volume();
-        const auto& intersctCenter = intersctGeo.center();
-
-        std::cout << "+++++++++++++++++++++++++++\nIntersection ";
-        for (int k = 0; k < intersctGeo.corners(); k++)
-        {
-          std::cout << "\t" << intersctGeo.corner(k);
-        }
-        std::cout << "\tnormal: " << normal << "\n\n";
-
-        //TODO: quadrature rule cannot be used for dim = 1!
-//        const Dune::QuadratureRule<double,dim-1>& secondOrderRule =
-//          Dune::QuadratureRules<double,dim-1>::rule(
-//          intersct.type(), 2);
-
-        //storage for multiply used integral values,
-        //note that only the lower diagonal and diagonal entries of
-        //quadraticIntregrals are used
-        Dune::FieldVector<Scalar, dim> linearIntegrals(0.0);
-        Dune::FieldMatrix<Scalar, dim, dim> quadraticIntregrals(0.0);
-        //NOTE: is there a better type for symmetric matrix?
-
-        for (int i = 0; i < dim; i++)
-        {
-          //use midpoint rule for exact evaluation of
-          // int_intersct x_i ds
-          linearIntegrals[i] = intersctVol * intersctCenter[i];
-
-          for (int j = 0; j <= i; j++)
-          {
-            const auto& leftCorner = intersctGeo.corner(0);
-            const auto& rightCorner = intersctGeo.corner(1);
-            std::cout << "left corner: " << leftCorner << "\tright corner: " << rightCorner << "\n";
-
-            quadraticIntregrals[i][j] = intersctVol / 3 *
-              ( leftCorner[i] * leftCorner[j] +
-                rightCorner[i] * rightCorner[j]
-              + 0.5 * (leftCorner[i] * rightCorner[j] +
-                leftCorner[j] * rightCorner[i]) );
-
-            std::cout << i << ", " << j << "\t" << leftCorner[i] * leftCorner[j] << "\t" <<
-              rightCorner[i] * rightCorner[j] << "\t" <<
-              0.5 * (leftCorner[i] * rightCorner[j] +
-              leftCorner[j] * rightCorner[i]) << "\t" << intersctVol / 3 *
-                ( leftCorner[i] * leftCorner[j] +
-                  rightCorner[i] * rightCorner[j]
-                + 0.5 * (leftCorner[i] * rightCorner[j] +
-                  leftCorner[j] * rightCorner[i]) ) << "\t" << quadraticIntregrals[i][j] << "\n\n";
-  /*
-            //use second order quadrature rule for exact evaluation of
-            // int_intersct x_i*x_j ds
-            //NOTE: use Simpson's rule instead manually?
-            for (const auto& ip : secondOrderRule)
-            {
-              const auto& qp = ip.position();
-              quadraticIntregrals[i][j] += //NOTE: volume necessary?
-                ip.weight() * qp[i] * qp[j] * intersctVol;
-            }
-*/
-            //NOTE: probably unnecessary
-            quadraticIntregrals[j][i] = quadraticIntregrals[i][j];
-          }
-        }
-        std::cout << "linearIntegrals:\n" << linearIntegrals << "\n\n";
-        std::cout << "quadraticIntregrals:\n" << quadraticIntregrals << "\n\n";
-
-        //exact evaluation of
-        // int_intersct mu*jump(phi_elem,0)*jump(phi_elem,0) ds
-        A[elemIdxSLE][elemIdxSLE] += mu * intersctVol;
-        std::cout << elemIdxSLE << ", " << elemIdxSLE <<"\t"  << intersctCenter<< ":\n"
-          << mu * intersctVol << "\t" << A[elemIdx][elemIdx] << "\n\n";
-
-        if (intersct.neighbor()) //intersct has neighboring element
-        {
-          std::cout << "------------------------------\nNeighbor\t";
-          for (int k = 0; k < intersct.outside().geometry().corners(); k++)
-          {
-            std::cout << "\t" << intersct.outside().geometry().corner(k);
-          }
-          std::cout << "\n\n";
-
-
-          //index of the neighboring element
-          const int neighborIdx = mapper_.index(intersct.outside());
-          const int neighborIdxSLE = (dim + 1)*neighborIdx;
-
-          for (int i = 0; i < dim; i++)
-          { //we use the relations
-            // int_intersct mu*jump(phi_elem,0)*jump(phi_elem,i) ds
-            // = mu * int_intersct x_i ds
-            //and
-            // int_intersct avg(K*grad(phi_elem,i))*jump(phi_elem,0) ds
-            // = 0.5 * K * normal[i] * vol(intersct)
-            A[elemIdxSLE + i + 1][elemIdxSLE] +=
-              mu * linearIntegrals[i] - 0.5 * K * normal[i] * intersctVol;
-            std::cout << elemIdxSLE + i + 1 << ", " << elemIdxSLE << ":\n"
-              << mu * linearIntegrals[i] << "\t" <<
-              - 0.5 * K * normal[i] * intersctVol << "\t"
-              << A[elemIdxSLE + i + 1][elemIdxSLE] << "\n\n";
-
-            for (int j = 0; j <= i; j++)
-            {
-              //we use the relations
-              // int_intersct mu*jump(phi_elem,i)*jump(phi_elem,j) ds
-              // = mu * int_intersct x_i*x_j ds
-              //and
-              // int_intersct avg(K*grad(phi_elem,i))*jump(phi_elem,j) ds
-              // = 0.5 * K * normal[i] * int_intersct x_j ds
-              A[elemIdxSLE + i + 1][elemIdxSLE + j + 1]
-                += mu * quadraticIntregrals[i][j]
-                  - 0.5 * K * (normal[i] * linearIntegrals[j]
-                    + normal[j] * linearIntegrals[i]);
-              std::cout << elemIdxSLE + i + 1 << ", " << elemIdxSLE + j + 1 << ":\n"
-                << mu * quadraticIntregrals[i][j] << "\t" <<
-                - 0.5 * K * (normal[i] * linearIntegrals[j]
-                  + normal[j] * linearIntegrals[i]) << "\t" <<
-                A[elemIdxSLE + i + 1][elemIdxSLE + j + 1] << "\n\n";
-            }
-          }
-
-          if (neighborIdx > elemIdx)
-          { //make sure that each facet is considered only once
-            continue;
-          }
-
-          //exact evaluation of
-          // int_intersct mu*jump(phi_elem,0)*jump(phi_neighbor,0) ds
-          A[elemIdxSLE][neighborIdxSLE] += -mu * intersctVol;
-
-          //stiffness matrix A is symmetric
-          A[neighborIdxSLE][elemIdxSLE] += A[elemIdxSLE][neighborIdxSLE];
-
-          for (int i = 0; i < dim; i++)
-          {
-            //we use the relations
-            // int_intersct mu*jump(phi_elem,i)
-            //  *jump(phi_neighbor,0) ds
-            // = -mu*int_intersct x_i ds
-            //and
-            // int_intersct avg(K*grad(phi_neighbor,i))
-            //  *jump(phi_elem,0) ds
-            // = 0.5 * K * normal[i] * vol(intersct)
-            A[elemIdxSLE + i + 1][neighborIdxSLE] +=
-              -mu * linearIntegrals[i] + 0.5 * K * normal[i] * intersctVol;
-            std::cout << elemIdxSLE + i + 1 << ", " << neighborIdxSLE << ":\n"
-              <<   -mu * linearIntegrals[i] << "\t" <<
-              0.5 * K * normal[i] * intersctVol << "\t" <<
-              A[elemIdxSLE + i + 1][neighborIdxSLE] << "\n\n";
-
-            //we use the relations
-            // int_intersct mu*jump(phi_elem,0)
-            //  *jump(phi_neighbor,i) ds
-            // = -mu*int_intersct x_i ds
-            //and
-            // int_intersct avg(K*grad(phi_neighbor,i))
-            //  *jump(phi_elem,0) ds
-            // = 0.5 * K * normal[i] * vol(intersct)
-            A[elemIdxSLE][neighborIdxSLE + i + 1] +=
-              -mu * linearIntegrals[i] - 0.5 * K * normal[i] * intersctVol;
-            std::cout << elemIdxSLE << ", " << neighborIdxSLE + i + 1<< ":\n"
-              << -mu * linearIntegrals[i] << "\t" <<
-              -0.5 * K * normal[i] * intersctVol << "\t" <<
-              A[elemIdxSLE][neighborIdxSLE + i + 1] << "\n\n";
-
-            //stiffness matrix A is symmetric
-            A[neighborIdxSLE][elemIdxSLE + i + 1] +=
-              A[elemIdxSLE + i + 1][neighborIdxSLE];
-            A[neighborIdxSLE + i + 1][elemIdxSLE] +=
-              A[elemIdxSLE][neighborIdxSLE + i + 1];
-
-            for (int j = 0; j <= i; j++)
-            {
-              //we use the relations
-              // int_intersct mu*jump(phi_elem,i)
-              //  *jump(phi_neighbor,j) ds
-              // = -mu*int_intersct x_i*x_j ds
-              //and
-              // int_intersct avg(K*grad(phi_neighbor,j))
-              //  *jump(phi_elem,i) ds
-              // = 0.5 * K * normal[j] * int_intersct x_i ds
-              //as well as
-              // int_intersct avg(K*grad(phi_elem,i))
-              //  *jump(phi_neighbor,j) ds
-              // = -0.5 * K * normal[i] * int_intersct x_j ds
-              A[elemIdxSLE + i + 1][neighborIdxSLE + j + 1] +=
-                -mu * quadraticIntregrals[i][j]
-                - 0.5 * K * (normal[j] * linearIntegrals[i]
-                  - normal[i] * linearIntegrals[j]);
-              std::cout << elemIdxSLE + i + 1 << ", " << neighborIdxSLE + j + 1<< ":\n"
-                << -mu * quadraticIntregrals[i][j] << "\t" <<
-                - 0.5 * K * (normal[j] * linearIntegrals[i]
-                  - normal[i] * linearIntegrals[j]) << "\t" <<
-                A[elemIdxSLE + i + 1][neighborIdxSLE + j + 1] << "\n\n";
-
-              //stiffness matrix A is symmetric
-              A[neighborIdxSLE + j + 1][elemIdxSLE + i + 1] +=
-                A[elemIdxSLE + i + 1][neighborIdxSLE + j + 1];
-
-              if (i != j)
-              {
-                // int_intersct mu*jump(phi_elem,j)
-                //  *jump(phi_neighbor,i) ds
-                // = -mu*int_intersct x_i*x_j ds
-                //and
-                // int_intersct avg(K*grad(phi_neighbor,i))
-                //  *jump(phi_elem,j) ds
-                // = 0.5 * K * normal[i] * int_intersct x_j ds
-                //as well as
-                // int_intersct avg(K*grad(phi_elem,j))
-                //  *jump(phi_neighbor,i) ds
-                // = -0.5 * K * normal[j] * int_intersct x_i ds
-                A[elemIdxSLE + j + 1][neighborIdxSLE + i + 1] +=
-                  -mu * quadraticIntregrals[i][j]
-                  - 0.5 * K * (normal[i] * linearIntegrals[j]
-                    - normal[j] * linearIntegrals[i]);
-                std::cout << elemIdxSLE + j + 1 << ", " << neighborIdxSLE + i + 1<< ":\n"
-                  << -mu * quadraticIntregrals[i][j] << "\t" <<
-                  - 0.5 * K * (normal[i] * linearIntegrals[j]
-                    - normal[j] * linearIntegrals[i]) << "\t" <<
-                  A[elemIdxSLE + j + 1][neighborIdxSLE + i + 1] << "\n\n";
-
-                //stiffness matrix A is symmetric
-                A[neighborIdxSLE + i + 1][elemIdxSLE + j + 1] +=
-                  A[elemIdxSLE + j + 1][neighborIdxSLE + i + 1];
-              }
-            }
-          }
-        }
-        else //boundary facet
-        {
-          std::cout << "------------------------------\nBoundary\n\n";
-          for (int i = 0; i < dim; i++)
-          { //we use the relations
-            // int_intersct mu*jump(phi_elem,0)*jump(phi_elem,i) ds
-            // = mu * int_intersct x_i ds
-            //and for boundary facets
-            // int_intersct avg(K*grad(phi_elem,i))
-            //  *jump(phi_elem,0) ds
-            // = K * normal[i] * vol(intersct)
-            A[elemIdxSLE + i + 1][elemIdxSLE] +=
-              mu * linearIntegrals[i] - 0.5 * K * normal[i] * intersctVol;
-            std::cout << elemIdxSLE + i + 1 << ", " << elemIdxSLE << "\t"
-            << intersctCenter << ":\n" << mu * linearIntegrals[i] << "\t" <<
-              - 0.5 * K * normal[i] * intersctVol << "\t"
-            << A[elemIdxSLE + i + 1][elemIdxSLE] << "\n\n";
-
-
-            for (int j = 0; j <= i; j++)
-            {
-              //we use the relations
-              // int_intersct mu*jump(phi_elem,i)*jump(phi_elem,j) ds
-              // = mu * int_intersct x_i*x_j ds
-              //and for boundary facets
-              // int_intersct avg(K*grad(phi_elem,i))
-              //  *jump(phi_elem,j) ds
-              // = 0.5 * K * normal[i] * int_intersct x_j ds
-              A[elemIdxSLE + i + 1][elemIdxSLE + j + 1] +=
-                mu * quadraticIntregrals[i][j]
-                - 0.5 * K * (normal[i] * linearIntegrals[j]
-                  + normal[j] * linearIntegrals[i]);
-              std::cout << elemIdxSLE + i + 1 << ", " << elemIdxSLE + j+ 1 << "\t"
-                << intersctCenter << ":\n" << mu * quadraticIntregrals[i][j] << "\t" <<
-                - 0.5 * K * (normal[i] * linearIntegrals[j]
-                  + normal[j] * linearIntegrals[i]) << "\t"
-                << A[elemIdxSLE + i + 1][elemIdxSLE + j + 1] << "\n\n";
-            }
-          }
-        }
-      }
-
-      //stiffness matrix A is symmetric
-      for (int i = 0; i < dim; i++)
-      {
-        A[elemIdxSLE][elemIdxSLE + i + 1] = A[elemIdxSLE + i + 1][elemIdxSLE];
-
-        for(int j = 0; j < i; j++)
-        {
-          A[elemIdxSLE + j + 1][elemIdxSLE + i + 1] =
-            A[elemIdxSLE + i + 1][elemIdxSLE + j + 1];
-        }
-      }
-    }
-
-    std::cout << A << std::endl;
+    //assemble stiffness matrix A and load vector b
+    assembleSLE(K, mu);
 
     //NOTE: what would be an appropiate solver here?
     A.solve(d, b);
@@ -488,6 +124,376 @@ public:
   const int dof; //degrees of freedom
 
 private:
+  //assemble stiffness matrix A and load vector b
+  void assembleSLE (const Scalar K, const Scalar mu)
+  {
+  //NOTE:
+//const int order = 3; //order of the quadrature rule
+
+  for (const auto& elem : elements(gridView_))
+  {
+    const auto& geo = elem.geometry();
+    std::cout << mapper_.index(elem) << "\t";
+    for (int k = 0; k < geo.corners(); k++)
+    {
+      std::cout << geo.corner(k) << "\t";
+    }
+    std::cout << "\n\n";
+  }
+
+  //we use the basis
+  // phi_elem,0 (x) = indicator(elem);
+  // phi_elem,i (x) = x[i]*indicator(elem);
+  //for elem in elements(gridView) and i = 1,...,dim
+  for (const auto& elem : elements(gridView_))
+  {
+    const int elemIdx = mapper_.index(elem);
+    const auto& geo = elem.geometry();
+    const double elemVol = geo.volume();
+    const auto& center = geo.center();
+
+    std::cout << "===============================\nElement " << elemIdx;
+    for (int k = 0; k < geo.corners(); k++)
+    {
+      std::cout << "\t" << geo.corner(k);
+    }
+    std::cout << "\n\n";
+
+    //in the system of linear equations (SLE) Ad = b,
+    //the index elemIdxSLE refers to the basis function phi_elem,0
+    //and the indices elemIdxSLE + i + 1, i = 1,...,dim, refer to the
+    //basis function phi_elem,i
+    const int elemIdxSLE = (dim + 1)*elemIdx;
+
+/*    //TODO: can be done outside of the loop?
+    const Dune::QuadratureRule<double,dim>& rule =
+      Dune::QuadratureRules<double,dim>::rule(geo.type(),order);
+
+    //NOTE: how are quadrature rules in Dune applied correctly?
+    for (const auto& ip : rule)
+    {
+      const auto qp = ip.position();
+      //NOTE: is the volume of the element taken into account
+      //automatically?
+      const auto weight = ip.weight();
+
+      //quadrature for int_elem q*phi_elem,0 dV
+      b[elemIdxSLE] += weight * q(qp);
+
+      //quadrature for int_elem q*phi_elem,i dV
+      for (int i = 0; i < dim; i++)
+      {
+        b[elemIdxSLE + i + 1] += weight * qp[i] * q(qp);
+      }
+    }
+*/
+
+    //NOTE: makeshift solution for source term q = -1
+    b[elemIdxSLE] += -elemVol;
+    for (int i = 0; i < dim; i++)
+    {
+      b[elemIdxSLE + i + 1] += -elemVol * center[i];
+    }
+
+    for (int i = 0; i < dim; i++)
+    {
+      //exact evaluation of
+      // int_elem K*grad(phi_elem,i)*grad(phi_elem,i) dV
+      A[elemIdxSLE + i + 1][elemIdxSLE + i + 1] += K * elemVol;
+    }
+
+    //iterate over all intersection with the boundary of elem
+    for (const auto& intersct : intersections(gridView_, elem))
+    {
+      const auto& normal = intersct.centerUnitOuterNormal();
+      const auto& intersctGeo = intersct.geometry();
+      const double intersctVol = intersctGeo.volume();
+      const auto& intersctCenter = intersctGeo.center();
+
+      std::cout << "+++++++++++++++++++++++++++\nIntersection ";
+      for (int k = 0; k < intersctGeo.corners(); k++)
+      {
+        std::cout << "\t" << intersctGeo.corner(k);
+      }
+      std::cout << "\tnormal: " << normal << "\n\n";
+
+      //TODO: quadrature rule cannot be used for dim = 1!
+//        const Dune::QuadratureRule<double,dim-1>& secondOrderRule =
+//          Dune::QuadratureRules<double,dim-1>::rule(
+//          intersct.type(), 2);
+
+      //storage for multiply used integral values,
+      //note that only the lower diagonal and diagonal entries of
+      //quadraticIntregrals are used
+      Dune::FieldVector<Scalar, dim> linearIntegrals(0.0);
+      Dune::FieldMatrix<Scalar, dim, dim> quadraticIntregrals(0.0);
+      //NOTE: is there a better type for symmetric matrix?
+
+      for (int i = 0; i < dim; i++)
+      {
+        //use midpoint rule for exact evaluation of
+        // int_intersct x_i ds
+        linearIntegrals[i] = intersctVol * intersctCenter[i];
+
+        for (int j = 0; j <= i; j++)
+        {
+          const auto& leftCorner = intersctGeo.corner(0);
+          const auto& rightCorner = intersctGeo.corner(1);
+          std::cout << "left corner: " << leftCorner << "\tright corner: " << rightCorner << "\n";
+
+          quadraticIntregrals[i][j] = intersctVol / 3 *
+            ( leftCorner[i] * leftCorner[j] +
+              rightCorner[i] * rightCorner[j]
+            + 0.5 * (leftCorner[i] * rightCorner[j] +
+              leftCorner[j] * rightCorner[i]) );
+
+          std::cout << i << ", " << j << "\t" << leftCorner[i] * leftCorner[j] << "\t" <<
+            rightCorner[i] * rightCorner[j] << "\t" <<
+            0.5 * (leftCorner[i] * rightCorner[j] +
+            leftCorner[j] * rightCorner[i]) << "\t" << intersctVol / 3 *
+              ( leftCorner[i] * leftCorner[j] +
+                rightCorner[i] * rightCorner[j]
+              + 0.5 * (leftCorner[i] * rightCorner[j] +
+                leftCorner[j] * rightCorner[i]) ) << "\t" << quadraticIntregrals[i][j] << "\n\n";
+/*
+          //use second order quadrature rule for exact evaluation of
+          // int_intersct x_i*x_j ds
+          //NOTE: use Simpson's rule instead manually?
+          for (const auto& ip : secondOrderRule)
+          {
+            const auto& qp = ip.position();
+            quadraticIntregrals[i][j] += //NOTE: volume necessary?
+              ip.weight() * qp[i] * qp[j] * intersctVol;
+          }
+*/
+          //NOTE: probably unnecessary
+          quadraticIntregrals[j][i] = quadraticIntregrals[i][j];
+        }
+      }
+      std::cout << "linearIntegrals:\n" << linearIntegrals << "\n\n";
+      std::cout << "quadraticIntregrals:\n" << quadraticIntregrals << "\n\n";
+
+      //exact evaluation of
+      // int_intersct mu*jump(phi_elem,0)*jump(phi_elem,0) ds
+      A[elemIdxSLE][elemIdxSLE] += mu * intersctVol;
+      std::cout << elemIdxSLE << ", " << elemIdxSLE <<"\t"  << intersctCenter<< ":\n"
+        << mu * intersctVol << "\t" << A[elemIdx][elemIdx] << "\n\n";
+
+      if (intersct.neighbor()) //intersct has neighboring element
+      {
+        std::cout << "------------------------------\nNeighbor\t";
+        for (int k = 0; k < intersct.outside().geometry().corners(); k++)
+        {
+          std::cout << "\t" << intersct.outside().geometry().corner(k);
+        }
+        std::cout << "\n\n";
+
+
+        //index of the neighboring element
+        const int neighborIdx = mapper_.index(intersct.outside());
+        const int neighborIdxSLE = (dim + 1)*neighborIdx;
+
+        for (int i = 0; i < dim; i++)
+        { //we use the relations
+          // int_intersct mu*jump(phi_elem,0)*jump(phi_elem,i) ds
+          // = mu * int_intersct x_i ds
+          //and
+          // int_intersct avg(K*grad(phi_elem,i))*jump(phi_elem,0) ds
+          // = 0.5 * K * normal[i] * vol(intersct)
+          A[elemIdxSLE + i + 1][elemIdxSLE] +=
+            mu * linearIntegrals[i] - 0.5 * K * normal[i] * intersctVol;
+          std::cout << elemIdxSLE + i + 1 << ", " << elemIdxSLE << ":\n"
+            << mu * linearIntegrals[i] << "\t" <<
+            - 0.5 * K * normal[i] * intersctVol << "\t"
+            << A[elemIdxSLE + i + 1][elemIdxSLE] << "\n\n";
+
+          for (int j = 0; j <= i; j++)
+          {
+            //we use the relations
+            // int_intersct mu*jump(phi_elem,i)*jump(phi_elem,j) ds
+            // = mu * int_intersct x_i*x_j ds
+            //and
+            // int_intersct avg(K*grad(phi_elem,i))*jump(phi_elem,j) ds
+            // = 0.5 * K * normal[i] * int_intersct x_j ds
+            A[elemIdxSLE + i + 1][elemIdxSLE + j + 1]
+              += mu * quadraticIntregrals[i][j]
+                - 0.5 * K * (normal[i] * linearIntegrals[j]
+                  + normal[j] * linearIntegrals[i]);
+            std::cout << elemIdxSLE + i + 1 << ", " << elemIdxSLE + j + 1 << ":\n"
+              << mu * quadraticIntregrals[i][j] << "\t" <<
+              - 0.5 * K * (normal[i] * linearIntegrals[j]
+                + normal[j] * linearIntegrals[i]) << "\t" <<
+              A[elemIdxSLE + i + 1][elemIdxSLE + j + 1] << "\n\n";
+          }
+        }
+
+        if (neighborIdx > elemIdx)
+        { //make sure that each facet is considered only once
+          continue;
+        }
+
+        //exact evaluation of
+        // int_intersct mu*jump(phi_elem,0)*jump(phi_neighbor,0) ds
+        A[elemIdxSLE][neighborIdxSLE] += -mu * intersctVol;
+
+        //stiffness matrix A is symmetric
+        A[neighborIdxSLE][elemIdxSLE] += A[elemIdxSLE][neighborIdxSLE];
+
+        for (int i = 0; i < dim; i++)
+        {
+          //we use the relations
+          // int_intersct mu*jump(phi_elem,i)
+          //  *jump(phi_neighbor,0) ds
+          // = -mu*int_intersct x_i ds
+          //and
+          // int_intersct avg(K*grad(phi_neighbor,i))
+          //  *jump(phi_elem,0) ds
+          // = 0.5 * K * normal[i] * vol(intersct)
+          A[elemIdxSLE + i + 1][neighborIdxSLE] +=
+            -mu * linearIntegrals[i] + 0.5 * K * normal[i] * intersctVol;
+          std::cout << elemIdxSLE + i + 1 << ", " << neighborIdxSLE << ":\n"
+            <<   -mu * linearIntegrals[i] << "\t" <<
+            0.5 * K * normal[i] * intersctVol << "\t" <<
+            A[elemIdxSLE + i + 1][neighborIdxSLE] << "\n\n";
+
+          //we use the relations
+          // int_intersct mu*jump(phi_elem,0)
+          //  *jump(phi_neighbor,i) ds
+          // = -mu*int_intersct x_i ds
+          //and
+          // int_intersct avg(K*grad(phi_neighbor,i))
+          //  *jump(phi_elem,0) ds
+          // = 0.5 * K * normal[i] * vol(intersct)
+          A[elemIdxSLE][neighborIdxSLE + i + 1] +=
+            -mu * linearIntegrals[i] - 0.5 * K * normal[i] * intersctVol;
+          std::cout << elemIdxSLE << ", " << neighborIdxSLE + i + 1<< ":\n"
+            << -mu * linearIntegrals[i] << "\t" <<
+            -0.5 * K * normal[i] * intersctVol << "\t" <<
+            A[elemIdxSLE][neighborIdxSLE + i + 1] << "\n\n";
+
+          //stiffness matrix A is symmetric
+          A[neighborIdxSLE][elemIdxSLE + i + 1] +=
+            A[elemIdxSLE + i + 1][neighborIdxSLE];
+          A[neighborIdxSLE + i + 1][elemIdxSLE] +=
+            A[elemIdxSLE][neighborIdxSLE + i + 1];
+
+          for (int j = 0; j <= i; j++)
+          {
+            //we use the relations
+            // int_intersct mu*jump(phi_elem,i)
+            //  *jump(phi_neighbor,j) ds
+            // = -mu*int_intersct x_i*x_j ds
+            //and
+            // int_intersct avg(K*grad(phi_neighbor,j))
+            //  *jump(phi_elem,i) ds
+            // = 0.5 * K * normal[j] * int_intersct x_i ds
+            //as well as
+            // int_intersct avg(K*grad(phi_elem,i))
+            //  *jump(phi_neighbor,j) ds
+            // = -0.5 * K * normal[i] * int_intersct x_j ds
+            A[elemIdxSLE + i + 1][neighborIdxSLE + j + 1] +=
+              -mu * quadraticIntregrals[i][j]
+              - 0.5 * K * (normal[j] * linearIntegrals[i]
+                - normal[i] * linearIntegrals[j]);
+            std::cout << elemIdxSLE + i + 1 << ", " << neighborIdxSLE + j + 1<< ":\n"
+              << -mu * quadraticIntregrals[i][j] << "\t" <<
+              - 0.5 * K * (normal[j] * linearIntegrals[i]
+                - normal[i] * linearIntegrals[j]) << "\t" <<
+              A[elemIdxSLE + i + 1][neighborIdxSLE + j + 1] << "\n\n";
+
+            //stiffness matrix A is symmetric
+            A[neighborIdxSLE + j + 1][elemIdxSLE + i + 1] +=
+              A[elemIdxSLE + i + 1][neighborIdxSLE + j + 1];
+
+            if (i != j)
+            {
+              // int_intersct mu*jump(phi_elem,j)
+              //  *jump(phi_neighbor,i) ds
+              // = -mu*int_intersct x_i*x_j ds
+              //and
+              // int_intersct avg(K*grad(phi_neighbor,i))
+              //  *jump(phi_elem,j) ds
+              // = 0.5 * K * normal[i] * int_intersct x_j ds
+              //as well as
+              // int_intersct avg(K*grad(phi_elem,j))
+              //  *jump(phi_neighbor,i) ds
+              // = -0.5 * K * normal[j] * int_intersct x_i ds
+              A[elemIdxSLE + j + 1][neighborIdxSLE + i + 1] +=
+                -mu * quadraticIntregrals[i][j]
+                - 0.5 * K * (normal[i] * linearIntegrals[j]
+                  - normal[j] * linearIntegrals[i]);
+              std::cout << elemIdxSLE + j + 1 << ", " << neighborIdxSLE + i + 1<< ":\n"
+                << -mu * quadraticIntregrals[i][j] << "\t" <<
+                - 0.5 * K * (normal[i] * linearIntegrals[j]
+                  - normal[j] * linearIntegrals[i]) << "\t" <<
+                A[elemIdxSLE + j + 1][neighborIdxSLE + i + 1] << "\n\n";
+
+              //stiffness matrix A is symmetric
+              A[neighborIdxSLE + i + 1][elemIdxSLE + j + 1] +=
+                A[elemIdxSLE + j + 1][neighborIdxSLE + i + 1];
+            }
+          }
+        }
+      }
+      else //boundary facet
+      {
+        std::cout << "------------------------------\nBoundary\n\n";
+        for (int i = 0; i < dim; i++)
+        { //we use the relations
+          // int_intersct mu*jump(phi_elem,0)*jump(phi_elem,i) ds
+          // = mu * int_intersct x_i ds
+          //and for boundary facets
+          // int_intersct avg(K*grad(phi_elem,i))
+          //  *jump(phi_elem,0) ds
+          // = K * normal[i] * vol(intersct)
+          A[elemIdxSLE + i + 1][elemIdxSLE] +=
+            mu * linearIntegrals[i] - 0.5 * K * normal[i] * intersctVol;
+          std::cout << elemIdxSLE + i + 1 << ", " << elemIdxSLE << "\t"
+          << intersctCenter << ":\n" << mu * linearIntegrals[i] << "\t" <<
+            - 0.5 * K * normal[i] * intersctVol << "\t"
+          << A[elemIdxSLE + i + 1][elemIdxSLE] << "\n\n";
+
+
+          for (int j = 0; j <= i; j++)
+          {
+            //we use the relations
+            // int_intersct mu*jump(phi_elem,i)*jump(phi_elem,j) ds
+            // = mu * int_intersct x_i*x_j ds
+            //and for boundary facets
+            // int_intersct avg(K*grad(phi_elem,i))
+            //  *jump(phi_elem,j) ds
+            // = 0.5 * K * normal[i] * int_intersct x_j ds
+            A[elemIdxSLE + i + 1][elemIdxSLE + j + 1] +=
+              mu * quadraticIntregrals[i][j]
+              - 0.5 * K * (normal[i] * linearIntegrals[j]
+                + normal[j] * linearIntegrals[i]);
+            std::cout << elemIdxSLE + i + 1 << ", " << elemIdxSLE + j+ 1 << "\t"
+              << intersctCenter << ":\n" << mu * quadraticIntregrals[i][j] << "\t" <<
+              - 0.5 * K * (normal[i] * linearIntegrals[j]
+                + normal[j] * linearIntegrals[i]) << "\t"
+              << A[elemIdxSLE + i + 1][elemIdxSLE + j + 1] << "\n\n";
+          }
+        }
+      }
+    }
+
+    //stiffness matrix A is symmetric
+    for (int i = 0; i < dim; i++)
+    {
+      A[elemIdxSLE][elemIdxSLE + i + 1] = A[elemIdxSLE + i + 1][elemIdxSLE];
+
+      for(int j = 0; j < i; j++)
+      {
+        A[elemIdxSLE + j + 1][elemIdxSLE + i + 1] =
+          A[elemIdxSLE + i + 1][elemIdxSLE + j + 1];
+      }
+    }
+  }
+
+  std::cout << A << std::endl;
+  }
+
+
   Matrix A; //stiffness matrix
   Vector b; //load vector
   Vector d; //solution vector
-- 
GitLab