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