00001 
00002 
00003 
00004 #ifndef __ParFUM_Bulk_Adapt_H
00005 #define __ParFUM_Bulk_Adapt_H
00006 
00007 #define SLIVERAREA 1.0e-18
00008 #define REFINE_TOL 1.1  // Refine elements with average edge length > 
00009                         
00010 #define COARSEN_TOL 0.8 // Coarsen element with average edge length <
00011                         
00012 #define QUALITY_MIN 0.7
00013 
00014 
00015 #define SCALED_SIZING 0
00016 #define ABSOLUTE_SIZING 1
00017 
00018 class Bulk_Adapt;
00019 CtvExtern(Bulk_Adapt *, _bulkAdapt);
00020 
00022 
00029 class Element_Bucket {
00030  public:
00032   typedef struct {
00033     int elID;     
00034     double len;   
00035     int leftIdx;  
00036     int rightIdx; 
00037   } elemEntry;
00039   elemEntry *elements;
00041   int numElements;
00043   int bucketSz;
00045   int root;
00046   Element_Bucket() { 
00047     root = -1;
00048     numElements = bucketSz = 0;
00049     elements = NULL;
00050   }
00051   void Alloc(int n) {
00052     elements = new elemEntry[n];
00053     for (int i=0; i<n; i++) {
00054       elements[i].elID = -1;
00055       elements[i].len = -1.0;
00056       elements[i].leftIdx = -1;
00057       elements[i].rightIdx = -1;
00058     }
00059     bucketSz = n;
00060     numElements = 0;
00061     root = -1;
00062   }
00063   void Resize(int n) {
00064     elemEntry *newBkt = new elemEntry[n];
00065     for (int i=0; i<n; i++) {
00066       newBkt[i].elID = -1;
00067       newBkt[i].len = -1.0;
00068       newBkt[i].leftIdx = -1;
00069       newBkt[i].rightIdx = -1;
00070     }
00071     for (int i=0; i<bucketSz; i++) {
00072       newBkt[i].elID = elements[i].elID;
00073       newBkt[i].len = elements[i].len;
00074       newBkt[i].leftIdx = elements[i].leftIdx;
00075       newBkt[i].rightIdx = elements[i].rightIdx;
00076     }
00077     bucketSz = n;
00078     if (elements) delete[] elements;
00079     elements = newBkt;
00080   }
00081   void Clear() {
00082     if (elements) delete[] elements;
00083     bucketSz = numElements = 0;
00084     root = -1;
00085   }
00086   bool IsBucketEmpty() { return(numElements == 0); }
00088   void Insert(int elID, double len) {
00089     CkAssert(numElements <= bucketSz);
00090     if (numElements == bucketSz) {
00091       Resize(bucketSz+100);
00092     }
00093     CkAssert(elID < bucketSz);
00094     if (root==-1) {
00095       root = 0;
00096       elements[0].elID = elID;
00097       elements[0].len = len;
00098       elements[0].leftIdx = elements[0].rightIdx = -1;
00099       numElements++;
00100     }
00101     else {
00102       int pos = findEmptySlot();
00103       elements[pos].elID = elID;
00104       elements[pos].len = len;
00105       elements[pos].leftIdx = elements[pos].rightIdx = -1;
00106       if ((len < elements[root].len) || ((len == elements[root].len) && (elID < elements[root].elID))) { 
00107     
00108     if (elements[root].leftIdx == -1) {
00109       elements[root].leftIdx = pos;
00110     }
00111     else {
00112       Insert_help(elements[root].leftIdx, pos);
00113     }
00114     numElements++;
00115       }
00116       else if ((len > elements[root].len) || ((len == elements[root].len) && (elID >= elements[root].elID))) { 
00117     
00118     if (elements[root].rightIdx == -1) {
00119       elements[root].rightIdx = pos;
00120     }
00121     else {
00122       Insert_help(elements[root].rightIdx, pos);
00123     }
00124     numElements++;
00125       }
00126       else { 
00127     CkAbort("ERROR: Element_Bucket::Insert: unreachable case!\n");
00128       }
00129     }
00130     sanity_check();
00131   }
00132 
00133   void Insert_help(int subtree, int pos) {
00134     if ((elements[pos].len < elements[subtree].len) || 
00135     ((elements[pos].len == elements[subtree].len) && (elements[pos].elID < elements[subtree].elID))) { 
00136       
00137       if (elements[subtree].leftIdx == -1) {
00138     elements[subtree].leftIdx = pos;
00139       }
00140       else {
00141     Insert_help(elements[subtree].leftIdx, pos);
00142       }
00143     }
00144     else if ((elements[pos].len > elements[subtree].len) || 
00145          ((elements[pos].len == elements[subtree].len) && (elements[pos].elID >=elements[subtree].elID))) { 
00146       
00147       if (elements[subtree].rightIdx == -1) {
00148     elements[subtree].rightIdx = pos;
00149       }
00150       else {
00151     Insert_help(elements[subtree].rightIdx, pos);
00152       }
00153     }
00154     else { 
00155       CkAbort("ERROR: Element_Bucket::Insert_help: unreachable case!\n");
00156     }
00157   }
00158 
00160   int Remove(double *len) {
00161     
00162     int elID, leftIdx, rightIdx;
00163     if (numElements == 0) {
00164       return -1;
00165     }
00166     int idx = root;
00167     int parent = root;
00168     while (elements[idx].leftIdx != -1) {
00169       if (parent != idx) parent = idx;
00170       idx = elements[idx].leftIdx;
00171     }
00172     elID = elements[idx].elID;
00173     CkAssert((elID < bucketSz) && (elID >=0));
00174     (*len) = elements[idx].len;
00175     if (elements[idx].rightIdx == -1) { 
00176       elements[idx].elID = -1;
00177       elements[idx].len = -1.0;
00178       elements[parent].leftIdx = -1;
00179     }
00180     else { 
00181       elements[idx].elID = -1;
00182       elements[idx].len = -1.0;
00183       if (parent == idx) {
00184     root = elements[idx].rightIdx;
00185       }
00186       else {
00187     elements[parent].leftIdx = elements[idx].rightIdx;
00188       }
00189       elements[idx].rightIdx = -1;
00190     }
00191     numElements--;
00192     if (numElements==0) {
00193       root=-1;
00194     }
00195     CkPrintf("In Element_Bucket::Remove: the elId to be returned is: %d\n", elID);
00196     sanity_check();
00197     return elID;
00198   }
00199 
00200   int findEmptySlot() {
00201     for (int i=0; i<numElements+1; i++) {
00202       if (elements[i].elID == -1) {
00203     return i;
00204       }
00205     }
00206     CkAbort("ERROR: Element_Bucket::findEmptySlot: more than numElements solts appear to be full!\n");
00207   }
00208 
00209   void sanity_check() {
00210     int idx = root;
00211     int count = 0;
00212     CkAssert((root == -1) || ((root < bucketSz) && (root >=0)));
00213     if (root == -1) {
00214       CkAssert(numElements == 0);
00215     }
00216     else {
00217       sanity_check_helper(idx, &count);
00218       CkAssert(count == numElements);
00219     }
00220   }
00221   
00222   void sanity_check_helper(int idx, int *count) {
00223     (*count)++;
00224     CkAssert((elements[idx].elID < bucketSz) && (elements[idx].elID >= 0));
00225     CkAssert(elements[idx].len > 0.0);
00226     int leftIdx, rightIdx;
00227     leftIdx = elements[idx].leftIdx;
00228     CkAssert((leftIdx == -1) || ((leftIdx < bucketSz) && (leftIdx >=0)));
00229     rightIdx = elements[idx].rightIdx;
00230     CkAssert((rightIdx == -1) || ((rightIdx < bucketSz) && (rightIdx >=0)));
00231     if (leftIdx != -1) {
00232       sanity_check_helper(leftIdx, count);
00233     }
00234     if (rightIdx != -1) {
00235       sanity_check_helper(rightIdx, count);
00236     }
00237   }
00238 };
00239 
00240 
00242 
00245 class Bulk_Adapt {
00246   friend class FEM_Interpolate;
00247  protected: 
00249   FEM_Mesh *theMesh; 
00250   int theMeshID;
00252     int dim, elemType;
00253  public:
00255   Bulk_Adapt() { theMesh = NULL; }
00257   Bulk_Adapt(FEM_Mesh *m, int d) { theMesh = m; dim=d; }
00259   void Bulk_Adapt_SetMesh(FEM_Mesh *m) { theMesh = m; }
00261   void Bulk_Adapt_SetDim(int dimension) { dim = dimension; }
00262   void Bulk_Adapt_SetElemType(int et) { elemType = et; }
00264   ~Bulk_Adapt() {}
00266   void pup(PUP::er &p) {
00267     p|dim;
00268   }
00269 
00270   void Bulk_Adapt_Init(int mid, FEM_Mesh *mp, int d) { 
00271     int rank;
00272     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
00273     theMesh = mp;
00274     theMeshID = mid;
00275     dim = d;
00276     CkPrintf("[%d] Adapt init...\n", rank);
00277     FEM_Mesh_allocate_valid_attr(theMeshID,FEM_NODE);
00278     FEM_Mesh_allocate_valid_attr(theMeshID,FEM_ELEM);
00279     MPI_Barrier(MPI_COMM_WORLD);
00280     CkPrintf("[%d] Creating adapt adjacencies...\n", rank);
00281     CreateAdaptAdjacencies(theMeshID, 0);
00282     ParFUM_SA_Init(theMeshID);  
00283     MPI_Barrier(MPI_COMM_WORLD);
00284     CkPrintf("[%d] End Adapt init...\n", rank);
00285   }
00286 
00288   void ParFUM_Refine(int qm, int method, double factor, double *sizes);
00290   void ParFUM_Coarsen(int qm, int method, double factor, double *sizes);
00292   void ParFUM_AdaptMesh(int qm, int method, double factor, double *sizes);
00294   void ParFUM_Smooth(int qm, int method);
00296   void ParFUM_Repair(int qm);
00298   void ParFUM_Remesh(int qm, int method, double factor, double *sizes);
00299   
00301   void ParFUM_SetReferenceMesh();
00303   void ParFUM_GradateMesh(double smoothness);
00304   void findEdgeLengths(int elemID, double *avgEdgeLength, double *maxEdgeLength, int *maxEdge, 
00305                double *minEdgeLength, int *minEdge);
00306 
00307  private:
00308   
00310   int Refine_h(int qm, int method, double factor, double *sizes);
00312   int Coarsen_h(int qm, int method, double factor, double *sizes);
00313 
00315   void SetMeshSize(int method, double factor, double *sizes);
00316 
00318   double length(int n1, int n2);
00319   double length3D(int n1, int n2);
00321   double length(double *n1_coord, double *n2_coord);
00322   double length3D(double *n1_coord, double *n2_coord);
00323 
00325   double getArea(int n1, int n2, int n3);
00327   double getArea(double *n1_coord, double *n2_coord, double *n3_coord);
00329   double getSignedArea(int n1, int n2, int n3);
00331   double getSignedArea(double *n1_coord, double *n2_coord, double *n3_coord);
00333   int getCoord(int n1, double *crds);
00335   int getShortestEdge(int n1, int n2, int n3, int* shortestEdge);
00336 
00338   double getAreaQuality(int elem);
00340   void ensureQuality(int n1, int n2, int n3);
00342   bool controlQualityF(int n1, int n2, int n3, int n4);
00344   bool controlQualityR(int n1, int n2, int n3, int n4);
00346   bool controlQualityR(double *n1_coord, double *n2_coord, double *n3_coord);
00348   bool controlQualityC(int n1, int n2, int n3, double *n4_coord);
00350   bool controlQualityC(double *n1_coord, double *n2_coord, double *n3_coord, double *n4_coord);
00351   bool flipOrBisect(int elId, int n1, int n2, int maxEdgeIdx, double maxlen);
00352 };
00353 
00354 #endif