From 1ef3e6b45f30a9c9fb94d9ba486b6eaae1714f38 Mon Sep 17 00:00:00 2001
From: Thomas Witkowski <thomas.witkowski@gmx.de>
Date: Fri, 27 Jun 2008 06:47:31 +0000
Subject: [PATCH] * Residual estimator around 50% faster!

---
 AMDiS/src/ElInfo3d.cc          | 19 +++----
 AMDiS/src/ResidualEstimator.cc | 91 +++++++++++++++++-----------------
 AMDiS/src/ResidualEstimator.h  | 18 +++++++
 3 files changed, 69 insertions(+), 59 deletions(-)

diff --git a/AMDiS/src/ElInfo3d.cc b/AMDiS/src/ElInfo3d.cc
index 9114c498..2e284a2e 100644
--- a/AMDiS/src/ElInfo3d.cc
+++ b/AMDiS/src/ElInfo3d.cc
@@ -37,10 +37,6 @@ namespace AMDiS {
       }
     }
 
-    //   if(fillFlag_.isSet(Mesh::FILL_DET) || fillFlag_.isSet(Mesh::FILL_GRD_LAMBDA)) {
-    //     det = calcGrdLambda(*Lambda);
-    //   }
-
     int neighbours = mesh_->getGeo(NEIGH);
 
     if (fillFlag_.isSet(Mesh::FILL_OPP_COORDS) || 
@@ -81,9 +77,6 @@ namespace AMDiS {
       }
     }
 
-    //int faces = mesh->getGeo(FACE);
-    //int edges = mesh->getGeo(EDGE);
-
     if (fillFlag_.isSet(Mesh::FILL_BOUND)) {
       for (int i = 0; i < element_->getGeo(BOUNDARY); i++) {
 	boundary_[i] = mel->getBoundary(i);
@@ -583,14 +576,15 @@ namespace AMDiS {
       boundary_[2] = elinfo_old->getBoundary(cv[2]);
       boundary_[3] = elinfo_old->getBoundary(ochild);
       
+      int geoFace = mesh_->getGeo(FACE);
+
       ce = const_cast<int*>(Tetrahedron::childEdge[el_type_local][ichild]);
       for (int iedge = 0; iedge < 4; iedge++) {
-	boundary_[mesh_->getGeo(FACE) + iedge] = 
-	  elinfo_old->getBoundary(mesh_->getGeo(FACE)+ce[iedge]);
+	boundary_[geoFace + iedge] = elinfo_old->getBoundary(geoFace + ce[iedge]);
       }
       for (int iedge = 4; iedge < 6; iedge++) {
 	int i = 5 - cv[iedge - 3];                /* old vertex opposite new edge */
-	boundary_[mesh_->getGeo(FACE) + iedge] = elinfo_old->getBoundary(i);
+	boundary_[geoFace + iedge] = elinfo_old->getBoundary(i);
       }
 
       if (elinfo_old->getProjection(0) &&
@@ -604,12 +598,11 @@ namespace AMDiS {
 	projection_[3] = elinfo_old->getProjection(ochild);
 	
 	for (int iedge = 0; iedge < 4; iedge++) {
-	  projection_[mesh_->getGeo(FACE)+iedge] = 
-	    elinfo_old->getProjection(mesh_->getGeo(FACE)+ce[iedge]);
+	  projection_[geoFace + iedge] = elinfo_old->getProjection(mesh_->getGeo(FACE)+ce[iedge]);
 	}
 	for (int iedge = 4; iedge < 6; iedge++) {
 	  int i = 5 - cv[iedge - 3];                /* old vertex opposite new edge */
-	  projection_[mesh_->getGeo(FACE) + iedge] = elinfo_old->getProjection(i);
+	  projection_[geoFace + iedge] = elinfo_old->getProjection(i);
 	}
       }
     }
diff --git a/AMDiS/src/ResidualEstimator.cc b/AMDiS/src/ResidualEstimator.cc
index aeb70274..a0bb11f2 100644
--- a/AMDiS/src/ResidualEstimator.cc
+++ b/AMDiS/src/ResidualEstimator.cc
@@ -64,10 +64,12 @@ namespace AMDiS {
     }
   
     uhEl = GET_MEMORY(double*, numSystems);
+    uhNeigh = GET_MEMORY(double*, numSystems);
     uhOldEl = timestep ? GET_MEMORY(double*, numSystems) : NULL;
 
     for (int system = 0; system < numSystems; system++) {
       uhEl[system] = GET_MEMORY(double, basFcts[system]->getNumber()); 
+      uhNeigh[system] = GET_MEMORY(double, basFcts[system]->getNumber());
       if (timestep)
 	uhOldEl[system] = GET_MEMORY(double, basFcts[system]->getNumber());
     }
@@ -104,6 +106,19 @@ namespace AMDiS {
       Mesh::FILL_GRD_LAMBDA |
       Mesh::FILL_DET        |
       Mesh::CALL_LEAF_EL;
+
+    neighInfo = mesh->createNewElInfo();
+
+    // prepare date for computing jump residual
+    if (C1 && (dim > 1)) {
+      surfaceQuad_ = Quadrature::provideQuadrature(dim - 1, degree);
+      nPointsSurface_ = surfaceQuad_->getNumPoints();
+      grdUhEl_.resize(nPointsSurface_);
+      grdUhNeigh_.resize(nPointsSurface_);
+      jump_.resize(nPointsSurface_);
+      localJump_.resize(nPointsSurface_);
+      neighbours_ = Global::getGeo(NEIGH, dim);
+    }
   }
 
   void ResidualEstimator::exit(bool output)
@@ -115,11 +130,13 @@ namespace AMDiS {
 
     for (int system = 0; system < numSystems; system++) {
       FREE_MEMORY(uhEl[system], double, basFcts[system]->getNumber());
+      FREE_MEMORY(uhNeigh[system], double, basFcts[system]->getNumber());
       if (timestep)
 	FREE_MEMORY(uhOldEl[system], double, basFcts[system]->getNumber());    
     }
 
     FREE_MEMORY(uhEl, double*, numSystems);
+    FREE_MEMORY(uhNeigh, double*, numSystems);
 
     if (timestep) {
       FREE_MEMORY(uhOldEl, double*, numSystems);
@@ -148,6 +165,8 @@ namespace AMDiS {
     if (D2uhqp != NULL) {
       FREE_MEMORY(D2uhqp, WorldMatrix<double>, numPoints);
     }
+
+    DELETE neighInfo;
   }
 
   void ResidualEstimator::estimateElement(ElInfo *elInfo)
@@ -265,17 +284,11 @@ namespace AMDiS {
 
     // ===== jump residuals 
     if (C1 && (dim > 1)) {
-      int neighbours = Global::getGeo(NEIGH, dim);
-      int face;
-      Quadrature *surfaceQuad = Quadrature::provideQuadrature(dim - 1, degree);
-      int numPointsSurface = surfaceQuad->getNumPoints();
-      Vector<WorldVector<double> > jump(numPointsSurface);
-
+      int dow = Global::getGeo(WORLD);
 
-      for (face = 0; face < neighbours; face++) {  
+      for (int face = 0; face < neighbours_; face++) {  
 	neigh = const_cast<Element*>(elInfo->getNeighbour(face));
 	if (neigh && neigh->getMark()) {      
-	  ElInfo *neighInfo = mesh->createNewElInfo();
 	  WorldVector<int> faceIndEl, faceIndNeigh;
 	  int oppV = elInfo->getOppVertex(face);
 	  DimVec<WorldVector<double> > LambdaNeigh(dim, NO_INIT);
@@ -287,9 +300,7 @@ namespace AMDiS {
 	    
 	  neighInfo->setElement(const_cast<Element*>(neigh));
 	  neighInfo->setFillFlag(Mesh::FILL_COORDS);
-	      
-	  int dow = Global::getGeo(WORLD);
-		
+	      	
 	  int j, i1, i2;
 
 	  for (int i = 0; i < dow; i++)
@@ -346,11 +357,8 @@ namespace AMDiS {
 	      
 	  detNeigh = abs(neighInfo->calcGrdLambda(LambdaNeigh));
 	      
-	  Vector<WorldVector<double> > grdUhEl(numPointsSurface);
-	  Vector<WorldVector<double> > grdUhNeigh(numPointsSurface);
-
-	  for (iq = 0; iq < numPointsSurface; iq++) {
-	    jump[iq].set(0.0);
+	  for (iq = 0; iq < nPointsSurface_; iq++) {
+	    jump_[iq].set(0.0);
 	  }
 	     
 
@@ -358,69 +366,62 @@ namespace AMDiS {
 	    if (matrix[system] == NULL) 
 	      continue;
 	      
-	    uh[system]->getLocalVector(el, uhEl[system]);
-		
-	    double* uhNeigh;
-	    uhNeigh = new double[basFcts[system]->getNumber()];		
-	    uh[system]->getLocalVector(neigh, uhNeigh);
-
+	    uh[system]->getLocalVector(el, uhEl[system]);	
+	    uh[system]->getLocalVector(neigh, uhNeigh[system]);
 			
-	    for (iq = 0; iq < numPointsSurface; iq++) {
+	    for (iq = 0; iq < nPointsSurface_; iq++) {
 	      lambda[face] = 0.0;
 	      for (int i = 0; i < dim; i++) {
-		lambda[faceIndEl[i]] = surfaceQuad->getLambda(iq, i);
+		lambda[faceIndEl[i]] = surfaceQuad_->getLambda(iq, i);
 	      }
 		  
 	      basFcts[system]->evalGrdUh(lambda, 
 					 Lambda, 
 					 uhEl[system], 
-					 &grdUhEl[iq]);
+					 &grdUhEl_[iq]);
 		  
 	      lambda[oppV] = 0.0;
 	      for (int i = 0; i < dim; i++) {
-		lambda[faceIndNeigh[i]] = surfaceQuad->getLambda(iq, i);
+		lambda[faceIndNeigh[i]] = surfaceQuad_->getLambda(iq, i);
 	      }
 		  
 	      basFcts[system]->evalGrdUh(lambda, 
 					 LambdaNeigh, 
-					 uhNeigh, 
-					 &grdUhNeigh[iq]);
+					 uhNeigh[system], 
+					 &grdUhNeigh_[iq]);
 		  
-	      grdUhEl[iq] -= grdUhNeigh[iq];
+	      grdUhEl_[iq] -= grdUhNeigh_[iq];
 	    }				
 
-	    delete [] uhNeigh;
-
 	    ::std::vector<double*>::iterator fac;
 
 	    for (it = const_cast<DOFMatrix*>(matrix[system])->getOperatorsBegin(),
 		   fac = const_cast<DOFMatrix*>(matrix[system])->getOperatorEstFactorBegin(); 
 		 it != const_cast<DOFMatrix*>(matrix[system])->getOperatorsEnd(); 
 		 ++it, ++fac) {
-	      Vector<WorldVector<double> > localJump(numPointsSurface);
-	      for (iq = 0; iq < numPointsSurface; iq++) {
-		localJump[iq].set(0.0);
+	      for (iq = 0; iq < nPointsSurface_; iq++) {
+		localJump_[iq].set(0.0);
 	      }
 		  
-	      (*it)->weakEvalSecondOrder(numPointsSurface,
-					 grdUhEl.getValArray(),
-					 localJump.getValArray());
+	      (*it)->weakEvalSecondOrder(nPointsSurface_,
+					 grdUhEl_.getValArray(),
+					 localJump_.getValArray());
 	      double factor = *fac ? **fac : 1.0;
 	      if (factor != 1.0) {
-		for (int i = 0; i < numPointsSurface; i++) {
-		  localJump[i] *= factor;
+		for (int i = 0; i < nPointsSurface_; i++) {
+		  localJump_[i] *= factor;
 		}
 	      }
 		  
-	      for (int i = 0; i < numPointsSurface; i++) {
-		jump[i] += localJump[i];
+	      for (int i = 0; i < nPointsSurface_; i++) {
+		jump_[i] += localJump_[i];
 	      }
 	    }				     
 	  }
 	      
-  
-	  for (val = iq = 0; iq < numPointsSurface; iq++) {
-	    val += surfaceQuad->getWeight(iq) * (jump[iq] * jump[iq]);
+	  val = 0.0;
+	  for (iq = 0; iq < nPointsSurface_; iq++) {
+	    val += surfaceQuad_->getWeight(iq) * (jump_[iq] * jump_[iq]);
 	  }
 	      
 	  double d = 0.5 * (det + detNeigh);
@@ -434,8 +435,6 @@ namespace AMDiS {
 	    neighInfo = parametric->removeParametricInfo(neighInfo);
 	  }
 
-	  DELETE neighInfo;
-
 	  neigh->setEstimation(neigh->getEstimation(row) + val, row);
 
 	  est_el += val;
diff --git a/AMDiS/src/ResidualEstimator.h b/AMDiS/src/ResidualEstimator.h
index ccf394b4..b111703f 100644
--- a/AMDiS/src/ResidualEstimator.h
+++ b/AMDiS/src/ResidualEstimator.h
@@ -143,6 +143,8 @@ namespace AMDiS {
 
     double **uhOldEl;
 
+    double **uhNeigh;
+
     double *uhQP;
 
     double *uhOldQP;
@@ -152,6 +154,22 @@ namespace AMDiS {
     WorldVector<double> *grdUh_qp;
 
     WorldMatrix<double> *D2uhqp; 
+
+    ElInfo *neighInfo;
+
+    Quadrature *surfaceQuad_;
+
+    int nPointsSurface_;
+
+    Vector<WorldVector<double> > grdUhEl_;
+
+    Vector<WorldVector<double> > grdUhNeigh_;
+
+    Vector<WorldVector<double> > jump_;
+
+    Vector<WorldVector<double> > localJump_;
+
+    int neighbours_;
   };
 }
 
-- 
GitLab