From 06dbd114430271eacf34b063df4225ed2b938a65 Mon Sep 17 00:00:00 2001
From: Thomas Witkowski <thomas.witkowski@gmx.de>
Date: Fri, 20 Nov 2009 08:35:36 +0000
Subject: [PATCH] Made some operators a little bit faster.

---
 AMDiS/src/DOFVector.hh            |  12 +-
 AMDiS/src/FirstOrderAssembler.cc  |  18 +--
 AMDiS/src/Operator.cc             |  88 +++++++++---
 AMDiS/src/Operator.h              | 178 +++++++++++++++----------
 AMDiS/src/ProblemVec.cc           | 213 ++++++++++++++++++++++++++++--
 AMDiS/src/ProblemVec.h            |  13 ++
 AMDiS/src/SecondOrderAssembler.cc |  15 +--
 AMDiS/src/ZeroOrderAssembler.cc   |  34 ++---
 AMDiS/src/ZeroOrderAssembler.h    |   3 +
 9 files changed, 436 insertions(+), 138 deletions(-)

diff --git a/AMDiS/src/DOFVector.hh b/AMDiS/src/DOFVector.hh
index e78ea500..83d38ed7 100644
--- a/AMDiS/src/DOFVector.hh
+++ b/AMDiS/src/DOFVector.hh
@@ -981,13 +981,13 @@ namespace AMDiS {
   {
     FUNCNAME("DOFVector<T>::getVecAtQPs()");
   
-    TEST_EXIT(quad || quadFast)("neither quad nor quadFast defined\n");
+    TEST_EXIT_DBG(quad || quadFast)("neither quad nor quadFast defined\n");
 
     if (quad && quadFast)
-      TEST_EXIT(quad == quadFast->getQuadrature())
+      TEST_EXIT_DBG(quad == quadFast->getQuadrature())
 	("quad != quadFast->quadrature\n");
 
-    TEST_EXIT(!quadFast || quadFast->getBasisFunctions() == feSpace->getBasisFcts())
+    TEST_EXIT_DBG(!quadFast || quadFast->getBasisFunctions() == feSpace->getBasisFcts())
       ("invalid basis functions");
 
     Element *el = elInfo->getElement();
@@ -1012,8 +1012,8 @@ namespace AMDiS {
 
       result = localvec;
     }
-  
-    T *localVec = new T[nBasFcts];
+
+    T *localVec = localVectors[omp_get_thread_num()];
     getLocalVector(el, localVec);
 
     for (int i = 0; i < nPoints; i++) {
@@ -1025,8 +1025,6 @@ namespace AMDiS {
 	   ((*(basFcts->getPhi(j)))(quad->getLambda(i))));      
     }
 
-    delete [] localVec;
-
     return const_cast<const T*>(result);
   }
 
diff --git a/AMDiS/src/FirstOrderAssembler.cc b/AMDiS/src/FirstOrderAssembler.cc
index 6122c7be..b1b34018 100644
--- a/AMDiS/src/FirstOrderAssembler.cc
+++ b/AMDiS/src/FirstOrderAssembler.cc
@@ -338,8 +338,6 @@ namespace AMDiS {
 
   void Quad01::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat)
   {
-    VectorOfFixVecs<DimVec<double> > *grdPhi;
-
     if (firstCall) {
 #ifdef _OPENMP
 #pragma omp critical
@@ -363,25 +361,23 @@ namespace AMDiS {
 
     for (int i = 0; i < static_cast<int>(terms[myRank].size()); i++)
       (static_cast<FirstOrderTerm*>((terms[myRank][i])))->getLb(elInfo, nPoints, Lb);
-  
+
     for (int iq = 0; iq < nPoints; iq++) {
       Lb[iq] *= elInfo->getDet();
-
       const double *psi = psiFast->getPhi(iq);
-      grdPhi = phiFast->getGradient(iq);
 
-      for (int i = 0; i < nRow; i++) {
-	double factor = quadrature->getWeight(iq) * psi[i];
-	for (int j = 0; j < nCol; j++)
-	  mat[i][j] += factor * (Lb[iq] * (*grdPhi)[j]);
+      for (int i = 0; i < nCol; i++) {
+	double factor = 
+	  quadrature->getWeight(iq) * (Lb[iq] * phiFast->getGradient(iq, i));	
+	for (int j = 0; j < nRow; j++)
+	  mat[j][i] += factor * psi[j];
       }
     }
   }
 
   Pre01::Pre01(Operator *op, Assembler *assembler, Quadrature *quad) 
     : FirstOrderAssembler(op, assembler, quad, true, GRD_PHI)
-  {
-  }
+  {}
 
   void Pre01::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat)
   {
diff --git a/AMDiS/src/Operator.cc b/AMDiS/src/Operator.cc
index 9f5bc807..a5757ecf 100644
--- a/AMDiS/src/Operator.cc
+++ b/AMDiS/src/Operator.cc
@@ -697,6 +697,17 @@ namespace AMDiS {
     auxFESpaces.push_back(dv->getFESpace());
   }
 
+  VecAtQP_FOT::VecAtQP_FOT(DOFVectorBase<double> *dv,
+			   AbstractFunction<double, double> *af,
+			   int bIdx)
+    : FirstOrderTerm(af->getDegree()), vec(dv), f(af)
+  {
+    TEST_EXIT(dv)("No vector!\n");
+
+    bOne = bIdx;
+    auxFESpaces.push_back(dv->getFESpace());
+  }
+
   VectorGradient_FOT::VectorGradient_FOT(DOFVectorBase<double> *dv,
 					 AbstractFunction<WorldVector<double>, WorldVector<double> > *af)
     : FirstOrderTerm(af->getDegree()), vec(dv), f(af)
@@ -824,6 +835,15 @@ namespace AMDiS {
     auxFESpaces.push_back(dv2->getFESpace());
   }
 
+  Vec2AtQP_FOT::Vec2AtQP_FOT(DOFVectorBase<double> *dv1, DOFVectorBase<double> *dv2,
+			     int bIdx)
+    : FirstOrderTerm(8), vec1(dv1), vec2(dv2)
+  {   
+    bOne = bIdx;
+    auxFESpaces.push_back(dv1->getFESpace()); 
+    auxFESpaces.push_back(dv2->getFESpace());
+  }
+
   void Vec2AtQP_FOT::initElement(const ElInfo* elInfo, 
 				 SubAssembler* subAssembler,
 				 Quadrature *quad) 
@@ -836,16 +856,21 @@ namespace AMDiS {
 			   VectorOfFixVecs<DimVec<double> >& Lb) const 
   {
     const DimVec<WorldVector<double> > &Lambda = elInfo->getGrdLambda();
-    for (int iq = 0; iq < nPoints; iq++) {
-      if (b)
+
+    if (bOne > -1) {
+      for (int iq = 0; iq < nPoints; iq++)
+	lb_one(Lambda, Lb[iq], vec1AtQPs[iq] * vec2AtQPs[iq]);
+    } else if (b) {
+      for (int iq = 0; iq < nPoints; iq++)
 	lb(Lambda, *b, Lb[iq], vec1AtQPs[iq] * vec2AtQPs[iq]);
-      else
+    } else {
+      for (int iq = 0; iq < nPoints; iq++)
 	l1(Lambda, Lb[iq], vec1AtQPs[iq] * vec2AtQPs[iq]);
     }
   }
   
   void Vec2AtQP_FOT::eval(int nPoints,
-			  const double              *uhAtQP,
+			  const double *uhAtQP,
 			  const WorldVector<double> *grdUhAtQP,
 			  const WorldMatrix<double> *D2UhAtQP,
 			  double *result,
@@ -858,14 +883,34 @@ namespace AMDiS {
 
   Vec3FctAtQP_FOT::Vec3FctAtQP_FOT(DOFVectorBase<double> *dv1, DOFVectorBase<double> *dv2,DOFVectorBase<double> *dv3,
 				   BinaryAbstractFunction<double, double, double> *f_,
-				   WorldVector<double> *b_)
-    : FirstOrderTerm(10), vec1(dv1), vec2(dv2), vec3(dv3), f(f_), b(b_)
+				   WorldVector<double> *bvec)
+    : FirstOrderTerm(10), 
+      vec1(dv1), 
+      vec2(dv2), 
+      vec3(dv3), 
+      f(f_),
+      b(bvec)
   { 
     auxFESpaces.push_back(dv1->getFESpace()); 
     auxFESpaces.push_back(dv2->getFESpace()); 
     auxFESpaces.push_back(dv3->getFESpace());   
   }
 
+  Vec3FctAtQP_FOT::Vec3FctAtQP_FOT(DOFVectorBase<double> *dv1, DOFVectorBase<double> *dv2,DOFVectorBase<double> *dv3,
+				   BinaryAbstractFunction<double, double, double> *f_,
+				   int b)
+    : FirstOrderTerm(10), 
+      vec1(dv1), 
+      vec2(dv2), 
+      vec3(dv3), 
+      f(f_)
+  { 
+    bOne = b;
+    auxFESpaces.push_back(dv1->getFESpace()); 
+    auxFESpaces.push_back(dv2->getFESpace()); 
+    auxFESpaces.push_back(dv3->getFESpace());   
+  }
+
   void Vec3FctAtQP_FOT::initElement(const ElInfo* elInfo, 
 				    SubAssembler* subAssembler,
 				    Quadrature *quad) 
@@ -876,19 +921,25 @@ namespace AMDiS {
   }
   
   
-  void Vec3FctAtQP_FOT::getLb(const ElInfo *elInfo, int nPoints, VectorOfFixVecs<DimVec<double> >& Lb) const 
+  void Vec3FctAtQP_FOT::getLb(const ElInfo *elInfo, int nPoints, 
+			      VectorOfFixVecs<DimVec<double> >& Lb) const 
   {
     const DimVec<WorldVector<double> > &Lambda = elInfo->getGrdLambda();
-    for (int iq = 0; iq < nPoints; iq++) {
-      if (b)
-	lb(Lambda, *b, Lb[iq], (vec1AtQPs[iq])*(*f)(vec2AtQPs[iq],vec3AtQPs[iq]));
-      else
-	l1(Lambda, Lb[iq], (vec1AtQPs[iq])*(*f)(vec2AtQPs[iq],vec3AtQPs[iq]));
+    if (bOne > -1) {
+      for (int iq = 0; iq < nPoints; iq++)
+	lb_one(Lambda, Lb[iq], vec1AtQPs[iq] * (*f)(vec2AtQPs[iq], vec3AtQPs[iq]));
+    } else {
+      for (int iq = 0; iq < nPoints; iq++) {
+	if (b)
+	  lb(Lambda, *b, Lb[iq], vec1AtQPs[iq] * (*f)(vec2AtQPs[iq], vec3AtQPs[iq]));
+	else
+	  l1(Lambda, Lb[iq], vec1AtQPs[iq] * (*f)(vec2AtQPs[iq], vec3AtQPs[iq]));
+      }
     }
   }
 
   void Vec3FctAtQP_FOT::eval(int nPoints,
-			     const double              *uhAtQP,
+			     const double *uhAtQP,
 			     const WorldVector<double> *grdUhAtQP,
 			     const WorldMatrix<double> *D2UhAtQP,
 			     double *result,
@@ -1582,10 +1633,15 @@ namespace AMDiS {
 			  VectorOfFixVecs<DimVec<double> >& Lb) const 
   {
     const DimVec<WorldVector<double> > &Lambda = elInfo->getGrdLambda();
-    for (int iq = 0; iq < nPoints; iq++) {
-      if (b)
+
+    if (bOne > -1) {
+      for (int iq = 0; iq < nPoints; iq++)
+	lb_one(Lambda, Lb[iq], (*f)(vecAtQPs[iq]));
+    } else if (b) {
+      for (int iq = 0; iq < nPoints; iq++)
 	lb(Lambda, *b, Lb[iq], (*f)(vecAtQPs[iq]));
-      else
+    } else {
+      for (int iq = 0; iq < nPoints; iq++)
 	l1(Lambda, Lb[iq], (*f)(vecAtQPs[iq]));      
     }
   }
diff --git a/AMDiS/src/Operator.h b/AMDiS/src/Operator.h
index 1094f876..c274d643 100644
--- a/AMDiS/src/Operator.h
+++ b/AMDiS/src/Operator.h
@@ -54,7 +54,9 @@ namespace AMDiS {
     OperatorTerm(int deg) 
       : properties(0), 
 	degree(deg),
-	auxFESpaces(0)
+	dimOfWorld(Global::getGeo(WORLD)),
+	auxFESpaces(0),
+	bOne(-1)
     {}
 
     /// Destructor.
@@ -65,14 +67,11 @@ namespace AMDiS {
      * each OperatorTerm belonging to this SubAssembler. E.g., vectors
      * and coordinates at quadrature points can be calculated here.
      */
-    virtual void initElement(const ElInfo*, 
-			     SubAssembler*,
-			     Quadrature *quad = NULL) 
+    virtual void initElement(const ElInfo*, SubAssembler*, Quadrature *quad = NULL) 
     {}
 
-    virtual void initElement(const ElInfo* largeElInfo,
-			     const ElInfo* smallElInfo,
-			     SubAssembler*,
+    virtual void initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo,
+			     SubAssembler*, 
 			     Quadrature *quad = NULL)
     {}
 
@@ -100,6 +99,12 @@ namespace AMDiS {
       return degree; 
     }
 
+    /// Sets one component of the b vector to be one. See \ref bOne.
+    void setB(int b)
+    {
+      bOne = b;
+    }
+
     /// Evaluation of the OperatorTerm at all quadrature points.
     virtual void eval(int nPoints,
 		      const double *uhAtQP,
@@ -166,12 +171,11 @@ namespace AMDiS {
 	      double factor) const;
 
     /// Evaluation of \f$ \Lambda \cdot b\f$.
-    static inline void lb(const DimVec<WorldVector<double> >& Lambda,
-			  const WorldVector<double>& b,
-			  DimVec<double>& Lb,
-			  double factor)
+    inline void lb(const DimVec<WorldVector<double> >& Lambda,
+		   const WorldVector<double>& b,
+		   DimVec<double>& Lb,
+		   double factor) const
     {
-      const int dimOfWorld = Global::getGeo(WORLD);
       const int dim = Lambda.size() - 1;
 
       for (int i = 0; i <= dim; i++) {
@@ -184,15 +188,25 @@ namespace AMDiS {
       }    
     }
 
+    /// Evaluation of \f$ \Lambda \cdot b\f$.
+    inline void lb_one(const DimVec<WorldVector<double> >& Lambda,
+		       DimVec<double>& Lb,
+		       double factor) const
+    {
+      const int dim = Lambda.size();
+
+      for (int i = 0; i < dim; i++)
+	Lb[i] += Lambda[i][bOne] * factor;
+    }
+
     /** \brief
      * Evaluation of \f$ \Lambda \cdot b\f$ if b contains the value 1.0 in 
      * each component.
      */
-    static inline void l1(const DimVec<WorldVector<double> >& Lambda,
-			  DimVec<double>& Lb,
-			  double factor)
+    inline void l1(const DimVec<WorldVector<double> >& Lambda,
+		   DimVec<double>& Lb,
+		   double factor) const
     {
-      const int dimOfWorld = Global::getGeo(WORLD);
       const int dim = Lambda.size() - 1;
 
       for (int i = 0; i <= dim; i++) {
@@ -212,12 +226,24 @@ namespace AMDiS {
     /// Polynomial degree of the term. Used to detemine the degree of the quadrature.
     int degree;
 
+    /// Stores the dimension of the world.
+    int dimOfWorld;
+
     /// List off all fe spaces, the operator term makes use off.
     std::vector<const FiniteElemSpace*> auxFESpaces;
 
     /// Pointer to the Operator this OperatorTerm belongs to.
     Operator* operat;
 
+    /** \brief
+     * In many cases, the vector b in the evaluation \f$ \Lambda \cdot b\f$ has zeros
+     * in all components expect one that is set to one. Using the function \ref lb is
+     * then unnecessary time consuming. Instead, this variable defines the component
+     * of the vector b to be one. The function \ref lb_one is used if this variable is
+     * not -1.
+     */
+    int bOne;
+
     /// Flag for piecewise constant terms
     static const Flag PW_CONST;
 
@@ -1466,17 +1492,27 @@ namespace AMDiS {
       : FirstOrderTerm(0), b(wv) 
     {}
 
-    /** \brief
-     * Implements FirstOrderTerm::getLb().
-     */
+    /// Constructor.
+    Vector_FOT(int bIdx) 
+      : FirstOrderTerm(0) 
+    {
+      bOne = bIdx;
+    }
+
+    /// Implements FirstOrderTerm::getLb().
     inline void getLb(const ElInfo *elInfo, 
 		      int nPoints, 
 		      VectorOfFixVecs<DimVec<double> >&Lb) const 
     {
       const DimVec<WorldVector<double> > &Lambda = elInfo->getGrdLambda();
 
-      for (int iq = 0; iq < nPoints; iq++)
-	lb(Lambda, b, Lb[iq], 1.0);
+      if (bOne > -1) {
+	for (int iq = 0; iq < nPoints; iq++)
+	  lb_one(Lambda, Lb[iq], 1.0);
+      } else {
+	for (int iq = 0; iq < nPoints; iq++)
+	  lb(Lambda, b, Lb[iq], 1.0);
+      }
     }
 
     /// Implements FirstOrderTerm::eval().
@@ -1507,10 +1543,15 @@ namespace AMDiS {
   {
   public:
     /// Constructor.
-    VecAtQP_FOT(DOFVectorBase<double> *dv,
+    VecAtQP_FOT(DOFVectorBase<double> *dv, 
 		AbstractFunction<double, double> *af,
 		WorldVector<double> *wv);
 
+    /// Constructor.
+    VecAtQP_FOT(DOFVectorBase<double> *dv,
+		AbstractFunction<double, double> *af,
+		int bIdx);
+
     /// Implementation of \ref OperatorTerm::initElement().
     void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
 		     Quadrature *quad = NULL);
@@ -1931,22 +1972,22 @@ namespace AMDiS {
   class FctVecAtQP_FOT : public FirstOrderTerm
   {
   public:
-    
     FctVecAtQP_FOT(DOFVectorBase<double> *dv,
 		   AbstractFunction<double, WorldVector<double> > *f_,
 		   WorldVector<double> *b_);
-
-   void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
+    
+    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
 		     Quadrature *quad = NULL);
-
-   void getLb(const ElInfo *elInfo, int nPoints, VectorOfFixVecs<DimVec<double> >& Lb) const;
-
-   void eval(int nPoints,
-	     const double              *uhAtQP,
-	     const WorldVector<double> *grdUhAtQP,
-	     const WorldMatrix<double> *D2UhAtQP,
-	     double *result,
-	     double factor) const;
+    
+    void getLb(const ElInfo *elInfo, int nPoints, 
+	       VectorOfFixVecs<DimVec<double> >& Lb) const;
+    
+    void eval(int nPoints,
+	      const double *uhAtQP,
+	      const WorldVector<double> *grdUhAtQP,
+	      const WorldMatrix<double> *D2UhAtQP,
+	      double *result,
+	      double factor) const;
     
   protected:
     DOFVectorBase<double>* vec;
@@ -1960,22 +2001,25 @@ namespace AMDiS {
   class Vec2AtQP_FOT : public FirstOrderTerm
   {
   public:
-
     Vec2AtQP_FOT(DOFVectorBase<double> *dv1, DOFVectorBase<double> *dv2,
 		 WorldVector<double> *b_);
 
-   void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
+    Vec2AtQP_FOT(DOFVectorBase<double> *dv1, DOFVectorBase<double> *dv2,
+		 int bIdx);
+    
+    void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
 		     Quadrature *quad = NULL);
-
-   void getLb(const ElInfo *elInfo, int nPoints, VectorOfFixVecs<DimVec<double> >& Lb) const;
-
-   void eval(int nPoints,
-	      const double              *uhAtQP,
+    
+    void getLb(const ElInfo *elInfo, int nPoints, 
+	       VectorOfFixVecs<DimVec<double> >& Lb) const;
+    
+    void eval(int nPoints,
+	      const double *uhAtQP,
 	      const WorldVector<double> *grdUhAtQP,
 	      const WorldMatrix<double> *D2UhAtQP,
 	      double *result,
 	      double factor) const;
-
+    
   protected:
     DOFVectorBase<double>* vec1;
     DOFVectorBase<double>* vec2;
@@ -1988,18 +2032,22 @@ namespace AMDiS {
   class Vec3FctAtQP_FOT : public FirstOrderTerm
   {
   public:
+    Vec3FctAtQP_FOT(DOFVectorBase<double> *dv1, DOFVectorBase<double> *dv2, DOFVectorBase<double> *dv3,
+		    BinaryAbstractFunction<double, double, double> *f,
+		    WorldVector<double> *b);
     
-    Vec3FctAtQP_FOT(DOFVectorBase<double> *dv1, DOFVectorBase<double> *dv2,DOFVectorBase<double> *dv3,
-		    BinaryAbstractFunction<double, double, double> *f_,
-		    WorldVector<double> *b_);
+    Vec3FctAtQP_FOT(DOFVectorBase<double> *dv1, DOFVectorBase<double> *dv2, DOFVectorBase<double> *dv3,
+		    BinaryAbstractFunction<double, double, double> *f,
+		    int b);
     
     void initElement(const ElInfo* elInfo, SubAssembler* subAssembler,
 		     Quadrature *quad = NULL);
     
-    void getLb(const ElInfo *elInfo, int nPoints, VectorOfFixVecs<DimVec<double> >& Lb) const;
+    void getLb(const ElInfo *elInfo, int nPoints, 
+	       VectorOfFixVecs<DimVec<double> >& Lb) const;
     
     void eval(int nPoints,
-	      const double              *uhAtQP,
+	      const double *uhAtQP,
 	      const WorldVector<double> *grdUhAtQP,
 	      const WorldMatrix<double> *D2UhAtQP,
 	      double *result,
@@ -3513,42 +3561,30 @@ namespace AMDiS {
 	     const FiniteElemSpace *rowFESpace,
 	     const FiniteElemSpace *colFESpace = NULL);
 
-    /** \brief
-     * Destructor.
-     */
+    /// Destructor.
     virtual ~Operator() {}
 
-    /** \brief
-     * Sets \ref optimized.
-     */
+    /// Sets \ref optimized.
     inline void useOptimizedAssembler(bool opt) 
     {
       optimized = opt;
     }
 
-    /** \brief
-     * Returns \ref optimized.
-     */
+    /// Returns \ref optimized.
     inline bool isOptimized() 
     {
       return optimized;
     }
 
-    /** \brief
-     * Adds a SecondOrderTerm to the Operator
-     */
+    /// Adds a SecondOrderTerm to the Operator
     template <typename T>
     void addSecondOrderTerm(T *term);
 
-    /** \brief
-     * Adds a FirstOrderTerm to the Operator
-     */
+    /// Adds a FirstOrderTerm to the Operator
     template <typename T>
-    void addFirstOrderTerm(T *term, 
-			   FirstOrderType type = GRD_PHI);
-    /** \brief
-     * Adds a ZeroOrderTerm to the Operator
-     */
+    void addFirstOrderTerm(T *term, FirstOrderType type = GRD_PHI);
+
+    /// Adds a ZeroOrderTerm to the Operator
     template <typename T>
     void addZeroOrderTerm(T *term);
 
@@ -3604,14 +3640,10 @@ namespace AMDiS {
       return auxFESpaces;
     }
 
-    /** \brief
-     * Sets \ref uhOld.
-     */
+    /// Sets \ref uhOld.
     void setUhOld(const DOFVectorBase<double> *uhOld);
 
-    /** \brief
-     * Returns \ref uhOld.
-     */
+    /// Returns \ref uhOld.
     inline const DOFVectorBase<double> *getUhOld() 
     {
       return uhOld;
diff --git a/AMDiS/src/ProblemVec.cc b/AMDiS/src/ProblemVec.cc
index a5244b25..65233cd7 100644
--- a/AMDiS/src/ProblemVec.cc
+++ b/AMDiS/src/ProblemVec.cc
@@ -619,8 +619,9 @@ namespace AMDiS {
   {
     FUNCNAME("ProblemVec::buildAfterCoarsen()");
 
-    clock_t first = clock();
+    //    buildAfterCoarsen_sebastianMode(adaptInfo, flag);
 
+    clock_t first = clock();
 #ifdef _OPENMP
     double wtime = omp_get_wtime();
 #endif
@@ -648,13 +649,6 @@ namespace AMDiS {
 
     for (int i = 0; i < nComponents; i++) {
 
-#if 0
-      std::vector<int> nnzInRow;
-      int overallNnz, averageNnz;
-      componentSpaces[i]->getMesh()->computeMatrixFillin(componentSpaces[i],
-							 nnzInRow, overallNnz, averageNnz);     
-#endif
-
       MSG("%d DOFs for %s\n", 
 	  componentSpaces[i]->getAdmin()->getUsedSize(), 
 	  componentSpaces[i]->getName().c_str());
@@ -795,6 +789,201 @@ namespace AMDiS {
 #endif     
   }
 
+  void ProblemVec::buildAfterCoarsen_sebastianMode(AdaptInfo *adaptInfo, Flag flag)
+  {
+    FUNCNAME("ProblemVec::buildAfterCoarsen()");
+
+    clock_t first = clock();
+#ifdef _OPENMP
+    double wtime = omp_get_wtime();
+#endif
+
+    for (int i = 0; i < static_cast<int>(meshes.size()); i++)
+      meshes[i]->dofCompress();
+
+    Flag assembleFlag = 
+      flag | 
+      (*systemMatrix)[0][0]->getAssembleFlag() | 
+      rhs->getDOFVector(0)->getAssembleFlag()  |
+      Mesh::CALL_LEAF_EL                        | 
+      Mesh::FILL_COORDS                         |
+      Mesh::FILL_DET                            |
+      Mesh::FILL_GRD_LAMBDA |
+      Mesh::FILL_NEIGH;
+
+    if (useGetBound)
+      assembleFlag |= Mesh::FILL_BOUND;
+
+    traverseInfo.updateStatus();
+
+    // Used to calculate the overall number of non zero entries.
+    int nnz = 0;  
+
+
+    /// === INITIALIZE ===
+
+    for (int i = 0; i < nComponents; i++) {
+      MSG("%d DOFs for %s\n", 
+	  componentSpaces[i]->getAdmin()->getUsedSize(), 
+	  componentSpaces[i]->getName().c_str());
+
+      rhs->getDOFVector(i)->set(0.0);
+
+      for (int j = 0; j < nComponents; j++) {
+	// Only if this variable is true, the current matrix will be assembled.	
+	bool assembleMatrix = true;
+	// The DOFMatrix which should be assembled (or not, if assembleMatrix
+	// will be set to false).
+	DOFMatrix *matrix = (*systemMatrix)[i][j];
+
+	if (matrix) 
+	  matrix->calculateNnz();
+	
+	// If the matrix was assembled before and it is marked to be assembled
+	// only once, it will not be assembled.
+	if (assembleMatrixOnlyOnce[i][j] && assembledMatrix[i][j]) {
+	  assembleMatrix = false;
+	} else if (matrix) {
+	  matrix->getBaseMatrix().
+	    change_dim(componentSpaces[i]->getAdmin()->getUsedSize(), 
+		       componentSpaces[j]->getAdmin()->getUsedSize());
+
+	  set_to_zero(matrix->getBaseMatrix());	  
+	}
+
+	// If there is no DOFMatrix, e.g., if it is completly 0, do not assemble.
+	if (!matrix || !assembleMatrix)
+	  assembleMatrix = false;
+
+	// If the matrix should not be assembled, the rhs vector has to be considered.
+	// This will be only done, if i == j. So, if both is not true, we can jump
+	// to the next matrix.
+	if (!assembleMatrix && i != j) {
+	  if (matrix)
+	    nnz += matrix->getBaseMatrix().nnz();
+
+	  continue;
+	}
+
+	if (assembleMatrix && matrix->getBoundaryManager())
+	  matrix->getBoundaryManager()->initMatrix(matrix);
+
+	if (matrix && assembleMatrix) 
+	  matrix->startInsertion(matrix->getNnz());
+      }
+    }
+
+
+    // === TRAVERSE ===
+
+    Mesh *mesh = componentMeshes[0];
+    const FiniteElemSpace *feSpace = componentSpaces[0];
+    const BasisFunction *basisFcts = feSpace->getBasisFcts();
+    ElementMatrix elMat(basisFcts->getNumber(), basisFcts->getNumber());
+    ElementMatrix tmpElMat(elMat);
+    ElementVector elVec(basisFcts->getNumber());
+    ElementVector tmpElVec(elVec);
+    TraverseStack stack;
+    BoundaryType *bound = 
+      useGetBound ? new BoundaryType[basisFcts->getNumber()] : NULL;
+    ElInfo *elInfo = stack.traverseFirst(mesh, -1, assembleFlag);
+    while (elInfo) {
+      if (useGetBound)
+	basisFcts->getBound(elInfo, bound);
+
+      for (std::map<Operator*, std::vector<OperatorPos> >::iterator opIt = operators.begin();
+	   opIt != operators.end(); ++opIt) {
+	if (opIt->first->getNeedDualTraverse() == true)
+	  continue;
+
+	if (opFlags[opIt->first].isSet(Operator::MATRIX_OPERATOR)) {
+	  set_to_zero(elMat);
+	  opIt->first->getElementMatrix(elInfo, elMat, 1.0);
+	}
+	if (opFlags[opIt->first].isSet(Operator::VECTOR_OPERATOR)) {
+	  set_to_zero(elVec);
+	  opIt->first->getElementVector(elInfo, elVec, 1.0);
+	}
+	
+	for (std::vector<OperatorPos>::iterator posIt = opIt->second.begin();
+	     posIt != opIt->second.end(); ++posIt) {
+
+	  if (posIt->operatorType.isSet(Operator::MATRIX_OPERATOR)) {
+	    if (*(posIt->factor) == 1.0) {
+	      (*systemMatrix)[posIt->row][posIt->col]->addElementMatrix(elMat, bound, elInfo, NULL);
+	    } else {
+	      tmpElMat = *(posIt->factor) * elMat;
+	      (*systemMatrix)[posIt->row][posIt->col]->addElementMatrix(tmpElMat, bound, elInfo, NULL);
+	    }
+	  }
+	  
+	  if (posIt->operatorType.isSet(Operator::VECTOR_OPERATOR)) {
+	    if (*(posIt->factor) == 1.0) {
+	      rhs->getDOFVector(posIt->row)->addElementVector(1.0, elVec, bound, elInfo);
+	    } else {
+	      tmpElVec = *(posIt->factor) * elVec;
+	      rhs->getDOFVector(posIt->row)->addElementVector(1.0, tmpElVec, bound, elInfo);
+	    }
+	  }
+	}	
+      }
+
+      elInfo = stack.traverseNext(elInfo);
+    } 
+      
+    if (useGetBound)
+      delete [] bound;
+
+    // === FINELIZE ===
+
+    for (int i = 0; i < nComponents; i++) {
+      for (int j = 0; j < nComponents; j++) {
+	bool assembleMatrix = true;
+	DOFMatrix *matrix = (*systemMatrix)[i][j];
+
+	if (assembleMatrixOnlyOnce[i][j] && assembledMatrix[i][j])
+	  assembleMatrix = false;
+	if (!matrix || !assembleMatrix)
+	  assembleMatrix = false;
+	if (!assembleMatrix && i != j)
+	  continue;
+
+	assembledMatrix[i][j] = true;
+
+	if (assembleMatrix) {
+	  matrix->removeRowsWithDBC(matrix->getApplyDBCs());
+	  matrix->finishInsertion();
+	}
+ 	if (assembleMatrix && matrix->getBoundaryManager())
+ 	  matrix->getBoundaryManager()->exitMatrix(matrix);
+	if (matrix)
+	  nnz += matrix->getBaseMatrix().nnz();
+      }
+
+      assembleBoundaryConditions(rhs->getDOFVector(i),
+				 solution->getDOFVector(i),
+				 componentMeshes[i],
+				 assembleFlag);     
+    }
+
+    solverMatrix.setMatrix(*systemMatrix);
+
+    createPrecon();
+
+    INFO(info, 8)("fillin of assembled matrix: %d\n", nnz);
+
+#ifdef _OPENMP
+    INFO(info, 8)("buildAfterCoarsen needed %.5f seconds system time / %.5f seconds wallclock time\n",
+		  TIME_USED(first, clock()), omp_get_wtime() - wtime);
+#else
+    INFO(info, 8)("buildAfterCoarsen needed %.5f seconds\n", 
+		  TIME_USED(first, clock()));
+#endif     
+
+    exit(0);
+
+  }
+
   void ProblemVec::createPrecon()
   {
     std::string preconType("no");
@@ -884,6 +1073,10 @@ namespace AMDiS {
 	break;
       }          
     } 
+
+    OperatorPos opPos = {i, j, factor, estFactor, Operator::MATRIX_OPERATOR};
+    operators[op].push_back(opPos);
+    opFlags[op].setFlag(Operator::MATRIX_OPERATOR);
   }
 
   void ProblemVec::addVectorOperator(Operator *op, int i,
@@ -902,6 +1095,10 @@ namespace AMDiS {
 	break;      
       }    
     }
+
+    OperatorPos opPos = {i, -1, factor, estFactor, Operator::VECTOR_OPERATOR};
+    operators[op].push_back(opPos);
+    opFlags[op].setFlag(Operator::VECTOR_OPERATOR);
   }
 
   void ProblemVec::addDirichletBC(BoundaryType type, int row, int col,
diff --git a/AMDiS/src/ProblemVec.h b/AMDiS/src/ProblemVec.h
index 4f6266e4..c6740d38 100644
--- a/AMDiS/src/ProblemVec.h
+++ b/AMDiS/src/ProblemVec.h
@@ -37,6 +37,13 @@
 
 namespace AMDiS {
 
+  struct OperatorPos 
+  {
+    int row, col;
+    double *factor, *estFactor;
+    Flag operatorType;
+  };
+
   class ProblemVec : public ProblemStatBase,
 		     public StandardProblemIteration
   {
@@ -171,6 +178,8 @@ namespace AMDiS {
 				   bool assembleMatrix = true,
 				   bool assembleVector = true);
 
+    void buildAfterCoarsen_sebastianMode(AdaptInfo *adaptInfo, Flag flag);
+
     void createPrecon();
 
 
@@ -594,6 +603,10 @@ namespace AMDiS {
      * defined by \ref exactSolutionFcts.
      */
     bool computeExactError;
+
+    std::map<Operator*, std::vector<OperatorPos> > operators;
+
+    std::map<Operator*, Flag> opFlags;
   };
 }
 
diff --git a/AMDiS/src/SecondOrderAssembler.cc b/AMDiS/src/SecondOrderAssembler.cc
index dbe5ad65..0d6fd931 100644
--- a/AMDiS/src/SecondOrderAssembler.cc
+++ b/AMDiS/src/SecondOrderAssembler.cc
@@ -210,33 +210,32 @@ namespace AMDiS {
     for (int i = 0; i < static_cast<int>(terms[myRank].size()); i++)
       (static_cast<SecondOrderTerm*>(terms[myRank][i]))->getLALt(elInfo, nPoints, LALt);
 
+    VectorOfFixVecs< DimVec<double> > *grdPsi, *grdPhi;
+
     if (symmetric) {
       // === Symmetric assembling. ===
-
       TEST_EXIT_DBG(nCol == nRow)("nCol != nRow, but symmetric assembling!\n");
 
       for (int iq = 0; iq < nPoints; iq++) {
 	(*LALt[iq]) *= elInfo->getDet();
+	grdPsi = psiFast->getGradient(iq);
+	grdPhi = phiFast->getGradient(iq);
 
 	for (int i = 0; i < nCol; i++) {	  
-	  amv(quadrature->getWeight(iq), 
-	      (*LALt[iq]), phiFast->getGradient(iq, i), dimVec);
+	  amv(quadrature->getWeight(iq), (*LALt[iq]), (*grdPhi)[i], dimVec);
 
-	  mat[i][i] += (psiFast->getGradient(iq, i) * dimVec);
+	  mat[i][i] += (*grdPsi)[i] * dimVec;
 	  for (int j = i + 1; j < nRow; j++) {
-	    double tmp = (phiFast->getGradient(iq, j) * dimVec);
+	    double tmp = (*grdPhi)[j] * dimVec;
 	    mat[i][j] += tmp;
 	    mat[j][i] += tmp;
 	  }
 	}
       }
     } else {      
-      VectorOfFixVecs< DimVec<double> > *grdPsi, *grdPhi;
-
       // === Non symmetric assembling. ===
       for (int iq = 0; iq < nPoints; iq++) {
 	(*LALt[iq]) *= elInfo->getDet();
-
 	grdPsi = psiFast->getGradient(iq);
 	grdPhi = phiFast->getGradient(iq);
 
diff --git a/AMDiS/src/ZeroOrderAssembler.cc b/AMDiS/src/ZeroOrderAssembler.cc
index c7975367..fc6b4000 100644
--- a/AMDiS/src/ZeroOrderAssembler.cc
+++ b/AMDiS/src/ZeroOrderAssembler.cc
@@ -155,7 +155,9 @@ namespace AMDiS {
 
   FastQuadZOA::FastQuadZOA(Operator *op, Assembler *assembler, Quadrature *quad)
     : ZeroOrderAssembler(op, assembler, quad, true)
-  {}
+  {
+    tmpC.resize(omp_get_overall_max_threads());
+  }
 
   void FastQuadZOA::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat)
   {
@@ -175,24 +177,28 @@ namespace AMDiS {
       }
     }
 
-    std::vector<double> c(nPoints, 0.0);
-    std::vector<OperatorTerm*>::iterator termIt;
-    for (termIt = terms[myRank].begin(); termIt != terms[myRank].end(); ++termIt) {
+    std::vector<double> &c = tmpC[myRank];
+    if (c.size() < static_cast<int>(nPoints))
+      c.resize(nPoints);
+    for (int i = 0; i < static_cast<int>(nPoints); i++)
+      c[i] = 0.0;
+
+    for (std::vector<OperatorTerm*>::iterator termIt = terms[myRank].begin(); 
+	 termIt != terms[myRank].end(); ++termIt)
       (static_cast<ZeroOrderTerm*>((*termIt)))->getC(elInfo, nPoints, c);
-    }
 
     if (symmetric) {
       TEST_EXIT_DBG(nCol == nRow)("nCol != nRow, but symmetric assembling!\n");
 
       for (int iq = 0; iq < nPoints; iq++) {
-	c[iq] *= elInfo->getDet();
-
+	c[iq] *= elInfo->getDet() * quadrature->getWeight(iq);
 	const double *psi = psiFast->getPhi(iq);
 	const double *phi = phiFast->getPhi(iq);
+
 	for (int i = 0; i < nRow; i++) {
-	  mat[i][i] += quadrature->getWeight(iq) * c[iq] * psi[i] * phi[i];
+	  mat[i][i] += c[iq] * psi[i] * phi[i];
 	  for (int j = i + 1; j < nCol; j++) {
-	    double val = quadrature->getWeight(iq) * c[iq] * psi[i] * phi[j];
+	    double val = c[iq] * psi[i] * phi[j];
 	    mat[i][j] += val;
 	    mat[j][i] += val;
 	  }
@@ -200,15 +206,13 @@ namespace AMDiS {
       }
     } else {      /*  non symmetric assembling   */
       for (int iq = 0; iq < nPoints; iq++) {
-	c[iq] *= elInfo->getDet();
+	c[iq] *= elInfo->getDet() * quadrature->getWeight(iq);
 
 	const double *psi = psiFast->getPhi(iq);
 	const double *phi = phiFast->getPhi(iq);
-	for (int i = 0; i < nRow; i++) {
-	  for (int j = 0; j < nCol; j++) {
-	    mat[i][j] += quadrature->getWeight(iq) * c[iq] * psi[i] * phi[j];
-	  }
-	}
+	for (int i = 0; i < nRow; i++)
+	  for (int j = 0; j < nCol; j++)
+	    mat[i][j] += c[iq] * psi[i] * phi[j];
       }
     }
   }
diff --git a/AMDiS/src/ZeroOrderAssembler.h b/AMDiS/src/ZeroOrderAssembler.h
index 0b3e63fa..8b349c1a 100644
--- a/AMDiS/src/ZeroOrderAssembler.h
+++ b/AMDiS/src/ZeroOrderAssembler.h
@@ -85,6 +85,9 @@ namespace AMDiS {
 
     /// Implements SubAssembler::calculateElementVector().
     void calculateElementVector(const ElInfo *elInfo, ElementVector& vec);
+
+  protected:
+    std::vector<std::vector<double> > tmpC;
   };
 
 
-- 
GitLab