Actual source code: Hierarchy.hh

  1: //rewritten Hierarchy.h made explicitly to output directly to DMMG
  2: #include <list>
  3: #include <Mesh.hh>
  4: #include <stdlib.h>
  5: #include <string>

  7: //#include "petscmesh.h"
 8:  #include petscdmmg.h
  9: //#include "petscmat.h"
 10:  #include private/meshimpl.h
 11: #include <Distribution.hh>
 12: #include <Generator.hh>
 13: #include <SieveAlgorithms.hh>
 14: #include <Selection.hh>
 15: //helper functions:

 17: bool PointIsInElement(ALE::Obj<PETSC_MESH_TYPE> m, PETSC_MESH_TYPE::point_type element, double * point);
 18: PetscErrorCode MeshLocateInMesh(Mesh finemesh, Mesh coarsemesh);
 19: //double PointDist(double * pointA, double * pointB, int dim);

 21: // Functions only used here

 23: PetscErrorCode MeshSpacingFunction(Mesh mesh); //builds the spacing function for the mesh
 24: PetscErrorCode MeshIDBoundary(Mesh mesh); //finds the boundary of the mesh.

 26: #ifdef PETSC_HAVE_TRIANGLE
 27: //SetupTriangulateio: set all the fields of the triangulateio structures to be good for initial input/output
 28: void SetupTriangulateio(triangulateio * input, triangulateio * output) {
 29:   input->numberofsegments = 0;
 30:   input->segmentlist = NULL;
 31:   input->numberoftriangles = 0;
 32:   input->numberofcorners = 0;
 33:   input->numberofpointattributes = 0;
 34:   input->pointattributelist = NULL;
 35:   input->numberoftriangleattributes = 0;
 36:   input->trianglelist = NULL;
 37:   input->triangleattributelist = NULL;
 38:   input->trianglearealist = NULL;
 39:   input->segmentmarkerlist = NULL;
 40:   input->holelist = NULL;
 41:   input->numberofholes = 0;
 42:   input->regionlist = NULL;
 43:   input->numberofregions = 0;
 44: 
 45:   output->pointlist = NULL;
 46:   output->pointattributelist = NULL;
 47:   output->pointmarkerlist = NULL;
 48:   output->trianglelist = NULL;
 49:   output->triangleattributelist = NULL;
 50:   output->trianglearealist = NULL;
 51:   output->neighborlist = NULL;
 52:   output->segmentlist = NULL;
 53:   output->segmentmarkerlist = NULL;
 54:   output->holelist = NULL;
 55:   output->regionlist = NULL;
 56:   output->edgelist = NULL;
 57:   output->edgemarkerlist = NULL;
 58:   output->normlist = NULL;
 59:   return;
 60: }
 61: #endif

 63: double vertex_angle (const ALE::Obj<PETSC_MESH_TYPE::real_section_type> coords, int dim, PETSC_MESH_TYPE::point_type p, PETSC_MESH_TYPE::point_type q, PETSC_MESH_TYPE::point_type r) {

 65: // o is our origin point, p is one endpoint, q is the other; find their angle given the coordinates
 66:   double *p_coords = new double[dim], *q_coords = new double[dim], *r_coords = new double[dim], mag_q, mag_r, dot_product, angle;
 68:   PetscMemcpy(p_coords, coords->restrictPoint(p), dim*sizeof(double));
 69:   PetscMemcpy(q_coords, coords->restrictPoint(q), dim*sizeof(double));
 70:   PetscMemcpy(r_coords, coords->restrictPoint(r), dim*sizeof(double));
 71:   for (int i = 0; i < dim; i++) {
 72:     mag_q += (p_coords[i] - q_coords[i])*(p_coords[i] - q_coords[i]);
 73:     mag_r += (p_coords[i] - r_coords[i])*(p_coords[i] - r_coords[i]);
 74:     dot_product += (p_coords[i] -q_coords[i])*(p_coords[i] - r_coords[i]);
 75:   }
 76:   if (mag_q == 0 || mag_r == 0) return 0.;
 77:   angle = acos(dot_product/sqrt(mag_q*mag_r));
 78:   delete [] p_coords; delete [] q_coords; delete [] r_coords;
 79:   return angle;
 80: }

 82: double Curvature(ALE::Obj<PETSC_MESH_TYPE> m, PETSC_MESH_TYPE::point_type v) {
 83:   //Make it work for 2D and 3D in an abstract fashion.  we know that the
 84:   //integral of the curvature over a triangle fan in 3D is merely the sum
 85:   //of the angles radiating from its centerpoint minus 2pi, and that
 86:   //the point on the triangle fan will be a singularity of curvature

 88:   double pi = M_PI;
 89:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& coordinates = m->getRealSection("coordinates");
 90:   double curvature;
 92:   int dim = m->getDimension();
 93:   if (m->depth(v) != 0) {
 94:     throw ALE::Exception("Curvature only defined on vertices");
 95:   }

 97:   double triangleSum = 0.;

 99:   ALE::Obj<PETSC_MESH_TYPE::sieve_type> s = m->getSieve();

101:   if (dim == 3) {
102:     if (m->depth() == 1) { //uninterpolated case, we have to ID the faces
103:       ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> cells = s->support(v);
104:       PETSC_MESH_TYPE::sieve_type::supportSequence::iterator c_iter = cells->begin();
105:       PETSC_MESH_TYPE::sieve_type::supportSequence::iterator c_iter_end = cells->end();
106:       while (c_iter != c_iter_end) {
107:         //why must cells and corners both start with c?
108:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSequence> tips = s->cone(*c_iter);
109:         PETSC_MESH_TYPE::sieve_type::coneSequence::iterator t_iter = tips->begin();
110:         PETSC_MESH_TYPE::sieve_type::coneSequence::iterator t_iter_exclude = tips->begin();
111:         PETSC_MESH_TYPE::sieve_type::coneSequence::iterator t_iter_end = tips->end();
112:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSet> face = new PETSC_MESH_TYPE::sieve_type::supportSet();
113:         while (t_iter_exclude != t_iter_end) {
114:           face->clear();
115:           if (*t_iter_exclude != v) {
116:             t_iter = tips->begin();
117:             while (t_iter != t_iter_end) {
118:               //make the face into a supportSet
119:               if (t_iter != t_iter_exclude) {
120:                 face->insert(*t_iter);
121:               }
122:               t_iter++;
123:             }
124:             if (s->nJoin1(face)->size() == 1) { //face on boundary
125:               //compute the angle
126:               if (face->size() != 3) throw ALE::Exception("Curvature: Bad face size");
127:               PETSC_MESH_TYPE::sieve_type::supportSet::iterator tf_iter = face->begin();
128:               PETSC_MESH_TYPE::sieve_type::supportSet::iterator tf_iter_end = face->end();
129: 
130:               PETSC_MESH_TYPE::point_type v_op[2]; //opposing vertices
131:               int index = 0;
132:               while (tf_iter != tf_iter_end) {
133:                 if (*tf_iter != v) {
134:                   v_op[index] = *tf_iter;
135:                   index++;
136:                 }
137:                 tf_iter++;
138:               }
139:               triangleSum += vertex_angle(coordinates, dim, v, v_op[0], v_op[1]);
140:             } //end face-on-boundary if
141:           } //end t_iter_exclude != v if
142:           t_iter_exclude++;
143:         }
144:         c_iter++;
145:       }
146:     } else {
147:     //the triangles are there for us!
148:       ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportArray> faces = s->nSupport(v, 2);
149:       PETSC_MESH_TYPE::sieve_type::supportArray::iterator f_iter = faces->begin();
150:       PETSC_MESH_TYPE::sieve_type::supportArray::iterator f_iter_end = faces->end();
151:       while (f_iter != f_iter_end) {
152:         if (s->support(*f_iter)->size() == 1) { //boundary edge
153:           ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneArray> tips = s->nCone(*f_iter, 2);
154:           if (tips->size() != 3) throw ALE::Exception("Curvature: wrong size face");
155:           PETSC_MESH_TYPE::sieve_type::coneArray::iterator tf_iter = tips->begin();
156:           PETSC_MESH_TYPE::sieve_type::coneArray::iterator tf_iter_end = tips->end();
157:           int index = 0;
158:           PETSC_MESH_TYPE::point_type v_op[2];
159:           while (tf_iter != tf_iter_end) {
160:                 if (*tf_iter != v) {
161:                   v_op[index] = *tf_iter;
162:                   index++;
163:                 }
164:                 tf_iter++;
165:           }
166:           triangleSum += vertex_angle(coordinates, dim, v, v_op[0], v_op[1]);
167:         }
168:         f_iter++;
169:       }
170:     }
171:     curvature = 2*pi - triangleSum;
172:   } else if (dim == 2) {
173:     ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportArray> surrounding_triangles = s->nSupport(v, m->depth());
174:     PETSC_MESH_TYPE::sieve_type::supportArray::iterator st_iter = surrounding_triangles->begin();
175:     PETSC_MESH_TYPE::sieve_type::supportArray::iterator st_iter_end = surrounding_triangles->end();
176:     while (st_iter != st_iter_end) {
177:       ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneArray> tips = s->nCone(*st_iter, m->depth());
178:       if (tips->size() != 3) throw ALE::Exception("Curvature: not a triangle!");
179:       PETSC_MESH_TYPE::sieve_type::coneArray::iterator t_iter = tips->begin();
180:       PETSC_MESH_TYPE::sieve_type::coneArray::iterator t_iter_end = tips->end();
181:       PETSC_MESH_TYPE::point_type v_op[2];
182:       int index = 0;
183:       while (t_iter != t_iter_end) {
184:         if (*t_iter != v) {
185:           v_op[index] = *t_iter;
186:           index++;
187:         }
188:         t_iter++;
189:       }
190:       triangleSum += vertex_angle(coordinates, dim, v, v_op[0], v_op[1]);
191:       st_iter++;
192:     }
193:     curvature = fabs(triangleSum - pi);
194:   } //end of dimension 2 case
195:   return curvature;
196: }


199: #if 0

201: double Curvature_2D(ALE::Obj<PETSC_MESH_TYPE> m, PETSC_MESH_TYPE::point_type p) {
203:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& coordinates = m->getRealSection("coordinates");
204:   ALE::Obj<PETSC_MESH_TYPE::label_type> boundary = m->getLabel("marker");
205:   int dim = m->getDimension();
206:   if (dim != 2) throw ALE::Exception("Called the 2D curvature routine on a non-2D mesh.");
207:   double pCoords[dim], qCoords[dim], rCoords[dim];
208:   double normvec[dim];
209: 
210:   const ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> neighbors = m->getSieve()->support(p); //get the set of edges with p as an endpoint
211:   PETSC_MESH_TYPE::sieve_type::supportSequence::iterator n_iter = neighbors->begin();
212:   PETSC_MESH_TYPE::sieve_type::supportSequence::iterator n_iter_end = neighbors->end();
213:   std::list<PETSC_MESH_TYPE::point_type> edgnlist;
214:   while (n_iter != n_iter_end) {
215:       if (m->getSieve()->support(*n_iter)->size() == 1) {
216:         PETSC_MESH_TYPE::sieve_type::coneSequence::iterator npoint = m->getSieve()->cone(*n_iter)->begin();
217:         if (*npoint != p) {
218:           edgnlist.push_front(*npoint);
219:         } else {
220:           npoint++;
221:           edgnlist.push_front(*npoint);
222:         }
223:     }
224:     n_iter++;
225:   }
226:   if (edgnlist.size() != 2) throw ALE::Exception("There is either a pathological boundary here, or this algorithm is wrong!");
227:   //ok, we have an arc. n1 -> p -> n2  we want to go through the arc in order, in order to get the normal.
228:   PETSC_MESH_TYPE::point_type n1 = *edgnlist.begin();
229:   PETSC_MESH_TYPE::point_type n2 = *(++edgnlist.begin());

231:   PetscMemcpy(pCoords, coordinates->restrictPoint(p), dim*sizeof(double));
232:   PetscMemcpy(qCoords, coordinates->restrictPoint(n1), dim*sizeof(double));
233:   PetscMemcpy(rCoords, coordinates->restrictPoint(n2), dim*sizeof(double));

235:   if (m->debug()) PetscPrintf(m->comm(), "Edges: %d--%d--%d : (%f, %f)--(%f, %f)--(%f, %f)\n", n1, p, n2, qCoords[0], qCoords[1], pCoords[0], pCoords[1], rCoords[0], rCoords[1]);

237:   normvec[0] = pCoords[1] - qCoords[1];
238:   normvec[1] = qCoords[0] - pCoords[0];

240:   normvec[0] += rCoords[1] - pCoords[1];
241:   normvec[1] += pCoords[0] - rCoords[0];
242:   //normalize the normal.
243:   double normlen = sqrt(normvec[0]*normvec[0] + normvec[1]*normvec[1]);
244:   if (normlen < 0.000000000001) return 0.; //give up
245:   normvec[0] = normvec[0]/normlen;
246:   normvec[1] = normvec[1]/normlen;
247:   if (m->debug()) PetscPrintf(m->comm(), "normal: (%f, %f)\n", normvec[0], normvec[1]);
248:   //ok, take the min dot product of this with the two edges used before.
249:   double qnorm = sqrt((pCoords[0] - qCoords[0])*(pCoords[0] - qCoords[0]) + (pCoords[1] - qCoords[1])*(pCoords[1] - qCoords[1]));
250:   double rnorm = sqrt((rCoords[0] - pCoords[0])*(rCoords[0] - pCoords[0]) + (rCoords[1] - pCoords[1])*(rCoords[1] - pCoords[1]));
251:   double c1 = ((qCoords[1] - pCoords[1])*normvec[1]+(qCoords[0] - pCoords[0])*normvec[0])/qnorm;
252:   double c2 = ((rCoords[1] - pCoords[1])*normvec[1]+(rCoords[0] - pCoords[0])*normvec[0])/rnorm;
253:   if (fabs(c1) > fabs(c2)) return fabs(c2);
254:   return fabs(c1);
255: }

257: double Curvature_3D(ALE::Obj<PETSC_MESH_TYPE> m, PETSC_MESH_TYPE::point_type p) {
259:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& coordinates = m->getRealSection("coordinates");
260:   ALE::Obj<PETSC_MESH_TYPE::label_type> boundary = m->getLabel("marker");
261:   int dim = m->getDimension();
262:   if (dim != 3) throw ALE::Exception("Called the 3D curvature routine on a non-3D mesh.");
263:   if (m->height(p) != 3) throw ALE::Exception("Curvatures available for interpolated meshes only.");
264:   double pCoords[dim], qCoords[dim], rCoords[dim];
265:   PetscMemcpy(pCoords, coordinates->restrictPoint(p), dim*sizeof(double));
266:   double normvec[dim];
267:   normvec[0] = 0.;
268:   normvec[1] = 0.;
269:   normvec[2] = 0.;
270:   //ok, traverse the pointface in one direction.
271:   //find the first exterior face
272:   ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportArray> faces = m->getSieve()->nSupport(p, 2);
273:   PETSC_MESH_TYPE::sieve_type::supportArray::iterator f_iter = faces->begin();
274:   PETSC_MESH_TYPE::sieve_type::supportArray::iterator f_iter_end = faces->end();
275:   PETSC_MESH_TYPE::point_type curface, curpt, lastpt, firstpt;
276:   bool found = false;
277:   while (f_iter != f_iter_end && !found) {
278:     if (m->getSieve()->support(*f_iter)->size() == 1) {
279:       curface = *f_iter;
280:       found = true;
281:     }
282:     f_iter++;
283:   }
284: 
285:   ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneArray> neighbors = m->getSieve()->nCone(curface, 2);
286:   PETSC_MESH_TYPE::sieve_type::coneArray::iterator n_iter = neighbors->begin();
287:   PETSC_MESH_TYPE::sieve_type::coneArray::iterator n_iter_end = neighbors->end();
288:   //set cur and lastpt as appropriate.
289:   while (n_iter != n_iter_end) {
290:     if (*n_iter != p) {
291:       lastpt = curpt;
292:       curpt = *n_iter;
293:     }
294:     n_iter++;
295:   }
296:   firstpt = curpt;
297:   //ok, proceed in the following fashion:  compute the normal of curface, add it to normvec, and move on to the next triangle.  give up when you're back at firstpt.
298:     //printf("%d ->", curpt);
299:   bool startup = true;
300:   while (curpt != firstpt || startup) {
301:     startup = false;
302:     //normal computation:
303:     PetscMemcpy(qCoords, coordinates->restrictPoint(curpt), dim*sizeof(double));
304:     PetscMemcpy(rCoords, coordinates->restrictPoint(lastpt), dim*sizeof(double));
305:     double tmp = (qCoords[1] - pCoords[1])*(rCoords[2] - pCoords[2]) - (qCoords[2] - pCoords[2])*(rCoords[1] - pCoords[1]);
306:     normvec[0] += tmp;
307:     //printf("%f,",tmp);
308:     tmp = (qCoords[2] - pCoords[2])*(rCoords[0] - pCoords[0]) - (qCoords[0] - pCoords[0])*(rCoords[2] - pCoords[2]);
309:     normvec[1] += tmp;
310:     //printf("%f,",tmp);
311:     tmp = (qCoords[0] - pCoords[0])*(rCoords[1] - pCoords[1]) - (qCoords[1] - pCoords[1])*(rCoords[0] - pCoords[0]);
312:     normvec[2] += tmp;
313:     //printf("%f\n",tmp);
314:     found = false;
315:     f_iter = faces->begin();
316:     f_iter_end = faces->end();
317:     while (f_iter != f_iter_end && !found) {
318:       //get the points in the cone of this face and see if it a) isn't the current face, and b) has p, curpt, and NOT lastpt in its cone
319:       if (m->getSieve()->support(*f_iter)->size() < 2) {
320:         neighbors = m->getSieve()->nCone(*f_iter, 2);
321:         n_iter = neighbors->begin();
322:         n_iter_end = neighbors->end();
323:         bool containsp = false;
324:         bool containscurpt = false;
325:         bool containslastpt = false;
326:         PETSC_MESH_TYPE::point_type posspt;
327:         while (n_iter != n_iter_end) {
328:           if (*n_iter == p){ containsp = true;}
329:           else if (*n_iter == curpt) {containscurpt = true;}
330:           else if (*n_iter == lastpt) {containslastpt = true;}
331:           else posspt = *n_iter;
332:           n_iter++;
333:         }
334:         if (containscurpt && containsp && !containslastpt) {
335:           lastpt = curpt;
336:           curpt = posspt;
337:           found = true;
338:           curface = *f_iter;
339:         }
340:       }
341:       f_iter++;
342:     }
343:     //printf("%d ->", curpt);
344:   }
345:   //printf("\n");
346:   //normalize the normal.
347:   double normlen = sqrt(normvec[0]*normvec[0] + normvec[1]*normvec[1] + normvec[2]*normvec[2]);
348:   if (normlen < 0.000000000001) return 0.; //give up
349:   normvec[0] = normvec[0]/normlen;
350:   normvec[1] = normvec[1]/normlen;
351:   normvec[2] = normvec[2]/normlen;
352:   //PetscPrintf(m->comm(), "%f, %f, %f\n", normvec[0], normvec[1], normvec[2]);
353:   //now go through the adjacent edges, seeing how off they are from orthogonal with the normal.
354:   double curvature = 1.0;
355:   ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSet> pneighbors = m->getSieve()->cone(m->getSieve()->support(p));
356:   PETSC_MESH_TYPE::sieve_type::coneSet::iterator p_iter = pneighbors->begin();
357:   PETSC_MESH_TYPE::sieve_type::coneSet::iterator p_iter_end = pneighbors->end();
358:   while (p_iter != p_iter_end) {
359:     if (*p_iter != p) {
360:       PetscMemcpy(qCoords, coordinates->restrictPoint(*p_iter), dim*sizeof(double));
361:       double curlen = sqrt((qCoords[0] - pCoords[0])*(qCoords[0] - pCoords[0]) + (qCoords[1] - pCoords[1])*(qCoords[1] - pCoords[1]) + (qCoords[2] - pCoords[2])*(qCoords[2] - pCoords[2]));
362:       double curcurve = fabs((normvec[0]*(qCoords[0] - pCoords[0]) + normvec[1]*(qCoords[1] - pCoords[1]) + normvec[2]*(qCoords[2] - pCoords[2]))/curlen);
363:       if (curcurve < curvature)curvature = curcurve;
364:     }
365:     p_iter++;
366:   }
367:   //printf("Curvature: %f\n", curvature);
368:   return curvature;
369: }

371: double Curvature(ALE::Obj<PETSC_MESH_TYPE> m, PETSC_MESH_TYPE::point_type p) {
372:   int dim = m->getDimension();
373:   if (dim == 2) {return Curvature_2D(m, p);}
374:   else if (dim == 3) {return Curvature_3D(m, p);}
375:   else throw ALE::Exception("Cannot do Curvature in dimensions other than 2 and 3D.");
376: }

378: #endif

380: //MeshSpacingFunction: Build the spacing function in the "spacing" section on the mesh.

382: PetscErrorCode MeshSpacingFunction(Mesh mesh) {
383:   ALE::Obj<PETSC_MESH_TYPE> m;
386:   MeshGetMesh(mesh, m);
387:   int dim = m->getDimension();
388:   //setup the spacing section
389:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& spacing = m->getRealSection("spacing");
390:   spacing->setFiberDimension(m->depthStratum(0), 1);
391:   m->allocate(spacing);
392:   //vertices
393:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>&  coordinates = m->getRealSection("coordinates");
394:   const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& vertices = m->depthStratum(0);
395:   PETSC_MESH_TYPE::label_sequence::iterator v_iter = vertices->begin();
396:   PETSC_MESH_TYPE::label_sequence::iterator v_iter_end = vertices->end();
397:   double vCoords[3], nCoords[3];
398:   while (v_iter != v_iter_end) {
399:     const double * tmpCoords = coordinates->restrictPoint(*v_iter);
400:     for (int i = 0; i < dim; i++) {
401:       vCoords[i] = tmpCoords[i];
402:     }
403:     //get the neighbors
404:     ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSet> neighbors = m->getSieve()->cone(m->getSieve()->support(*v_iter));
405:     PETSC_MESH_TYPE::sieve_type::coneSet::iterator n_iter = neighbors->begin();
406:     PETSC_MESH_TYPE::sieve_type::coneSet::iterator n_iter_end = neighbors->end();
407:     //go through the neighbors
408:     double minDist = 0.;
409:     while (n_iter != n_iter_end) {
410:       double dist = 0.;
411:       const double * rBuf = coordinates->restrictPoint(*n_iter);
412:       PetscMemcpy(nCoords, rBuf, dim*sizeof(double));
413:       double d_tmp;
414:       for (int d = 0; d < dim; d++) {
415:         d_tmp = nCoords[d] - vCoords[d];
416:         dist += d_tmp * d_tmp;
417:       }
418:       dist = 0.5*sqrt(dist);
419:       if ((dist < minDist && dist > 0.) || minDist == 0.) minDist = dist;
420:       n_iter++;
421:     }
422:     spacing->updatePoint(*v_iter, &minDist);
423:     v_iter++;
424:   }
425:   return(0);
426: }

428: //MeshIDBoundary: create the "marker" label needed by many such things

430: PetscErrorCode MeshIDBoundary(Mesh mesh) {
431:   ALE::Obj<PETSC_MESH_TYPE> m;
434:   MeshGetMesh(mesh, m);
435:   //int dim = m->getDimension();
436:   ALE::Obj<PETSC_MESH_TYPE::label_type> boundary = m->createLabel("marker");

438:   int interplevels = m->height(*m->depthStratum(0)->begin());
439:   if (interplevels == 1) { //noninterpolated case
440:     ALE::Obj<PETSC_MESH_TYPE::label_sequence> cells = m->heightStratum(0);
441:     PETSC_MESH_TYPE::label_sequence::iterator c_iter = cells->begin();
442:     PETSC_MESH_TYPE::label_sequence::iterator c_iter_end = cells->end();
443:     while (c_iter != c_iter_end) {
444:       //for now just do for simplicial meshes
445:       ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSequence> corners = m->getSieve()->cone(*c_iter);
446:       PETSC_MESH_TYPE::sieve_type::coneSequence::iterator v_iter = corners->begin();
447:       PETSC_MESH_TYPE::sieve_type::coneSequence::iterator v_remove = corners->begin();
448:       PETSC_MESH_TYPE::sieve_type::coneSequence::iterator v_iter_end = corners->end();
449:       while (v_remove != v_iter_end) {
450:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSet> face = PETSC_MESH_TYPE::sieve_type::supportSet();
451:         v_iter = corners->begin();
452:         while (v_iter != v_iter_end) {
453:           if (v_iter != v_remove) {
454:           face->insert(*v_iter);
455:           }
456:           v_iter++;
457:         }
458:         if (m->getSieve()->nJoin1(face)->size() == 1) {
459:           PETSC_MESH_TYPE::sieve_type::supportSet::iterator f_iter = face->begin();
460:           PETSC_MESH_TYPE::sieve_type::supportSet::iterator f_iter_end = face->end();
461:           while (f_iter != f_iter_end){
462:             m->setValue(boundary, *f_iter, 1);
463:             ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> f_support = m->getSieve()->support(*f_iter);
464:             PETSC_MESH_TYPE::sieve_type::supportSequence::iterator fs_iter = f_support->begin();
465:             PETSC_MESH_TYPE::sieve_type::supportSequence::iterator fs_iter_end = f_support->end();
466:             while (fs_iter != fs_iter_end) {
467:               m->setValue(boundary,*fs_iter, 2);
468:               fs_iter++;
469:             }
470:             f_iter++;
471:           }
472:        }
473:         v_remove++;
474:       }
475:       c_iter++;
476:     }
477:   } else {
478:     const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& faces = m->heightStratum(1);
479:     PETSC_MESH_TYPE::label_sequence::iterator f_iter = faces->begin();
480:     PETSC_MESH_TYPE::label_sequence::iterator f_iter_end = faces->end();
481:     while (f_iter != f_iter_end) {
482:       //mark the boundary faces and every element of their closure as "1".  Mark their support tri/tet as "2" (Matt - Is this right?)
483:       ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> support = m->getSieve()->support(*f_iter);
484:       if (support->size() == 1) {
485:         m->setValue(boundary, *f_iter, 1);
486:         m->setValue(boundary, *support->begin(), 2);
487:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneArray> boundclose = ALE::SieveAlg<PETSC_MESH_TYPE>::closure(m, *f_iter);
488:         PETSC_MESH_TYPE::sieve_type::coneArray::iterator bc_iter = boundclose->begin();
489:         PETSC_MESH_TYPE::sieve_type::coneArray::iterator bc_iter_end = boundclose->end();
490:         while (bc_iter != bc_iter_end) {
491:           m->setValue(boundary, *bc_iter, 1);
492:           bc_iter++;
493:         }
494:       }
495:       f_iter++;
496:     }

498: /*    while (v_iter != v_iter_end) {
499:       ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportArray> vsupport = m->getSieve()->nSupport(*v_iter, interplevels-1); //3D faces or 2D edges
500:       PETSC_MESH_TYPE::sieve_type::supportArray::iterator s_iter = vsupport->begin();
501:       PETSC_MESH_TYPE::sieve_type::supportArray::iterator s_iter_end = vsupport->end();
502:       bool isBound = false;
503:       while (s_iter != s_iter_end) {
504:         //check the support of each dim-1 element; if it's supported on one side it is attached to boundary nodes
505:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> fsupport = m->getSieve()->support(*s_iter);
506:         if (fsupport->size() < 2) isBound = true;
507:         s_iter++;
508:       }
509:       if (isBound) m->setValue(boundary, *v_iter, 1);
510:       v_iter++;
511:     }
512: */
513:   }
514:   return(0);
515: }


520: #if defined PETSC_HAVE_TETGEN || defined PETSC_HAVE_TRIANGLE

522: ALE::Obj<PETSC_MESH_TYPE> MeshCreateHierarchyMesh(ALE::Obj<PETSC_MESH_TYPE> m, ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSet> includedVertices) {
523:   int curmeshsize = 0;
524:   int dim = m->getDimension();
525:   //const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& coordinates = m->getRealSection("coordinates");
526:   const ALE::Obj<PETSC_MESH_TYPE::label_type>& boundary = m->getLabel("marker");
527:   //const ALE::Obj<PETSC_MESH_TYPE::label_type> hdepth = m->getLabel("hdepth");
528:   //for (int i = curLevel; i < nLevels; i++) {
529:   //  curmeshsize += m->getLabelStratum("hdepth", i)->size();
530:   //}
531:   curmeshsize = includedVertices->size();
532:   //PetscPrintf(m->comm(), "new mesh size should be %d vertices.\n", curmeshsize);
533:   const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& vertices = m->depthStratum(0);
534:   PETSC_MESH_TYPE::label_sequence::iterator v_iter = vertices->begin();
535:   PETSC_MESH_TYPE::label_sequence::iterator v_iter_end = vertices->end();
536:   //double coords[dim * curmeshsize];
537:   //int indices[dim * curmeshsize];
538:   //const double * tmpcoords;
539:   //int index = 0;
540:     //PetscPrintf(m->comm(), "Mesh Size: %d\n", curmeshsize);
541:     //load the points and their names in this mesh into a list
542:     //triangulate/tetrahedralize
543:     //make into a new sieve.  place coordinates and names on the sieve.

545:     ALE::Obj<PETSC_MESH_TYPE::sieve_type> boundary_sieve = new PETSC_MESH_TYPE::sieve_type(m->comm(), m->debug());
546:     ALE::Obj<PETSC_MESH_TYPE> boundary_mesh = new PETSC_MESH_TYPE(m->comm(), m->debug());
547:     boundary_mesh->setSieve(boundary_sieve);
548:     ALE::Obj<PETSC_MESH_TYPE::label_type> boundary_marker = boundary_mesh->createLabel("marker");
549:     //rebuild the boundary, then coarsen it.
550:     if (dim == 2) {
551:       boundary_mesh->setDimension(1);
552:       ALE::Obj<PETSC_MESH_TYPE::label_sequence> bndPoints = m->getLabelStratum("marker", 1);
553:       PETSC_MESH_TYPE::label_sequence::iterator b_iter = bndPoints->begin();
554:       PETSC_MESH_TYPE::label_sequence::iterator b_iter_end = bndPoints->end();

556:       //PetscPrintf(m->comm(),"Copying the Boundary Mesh: %d items\n", bndPoints->size());
557:       while (b_iter != b_iter_end) {
558:         if (m->height(*b_iter) > 1) {
559:           ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> bnd_support = m->getSieve()->support(*b_iter);
560:           PETSC_MESH_TYPE::sieve_type::supportSequence::iterator bs_iter = bnd_support->begin();
561:           PETSC_MESH_TYPE::sieve_type::supportSequence::iterator bs_iter_end = bnd_support->end();
562:           while (bs_iter != bs_iter_end) {
563:             if (m->getValue(boundary, *bs_iter) == 1) {
564:               boundary_sieve->addArrow(*b_iter, *bs_iter);
565:               boundary_mesh->setValue(boundary_marker, *bs_iter, 1);
566:             }
567:             bs_iter++;
568:           }
569:         }
570:         b_iter++;
571:       }
572:       //coarsen the 2D boundary mesh
573:       v_iter = vertices->begin();
574:       v_iter_end = vertices->end();
575:       while (v_iter != v_iter_end) {
576:         if (m->getValue(boundary, *v_iter) == 1 && includedVertices->find(*v_iter) == includedVertices->end()) {
577:           //remove this one and reconnect its sides
578:           ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> rem_support = boundary_sieve->support(*v_iter);
579:           PETSC_MESH_TYPE::sieve_type::supportSequence::iterator rs_iter = rem_support->begin();
580:           PETSC_MESH_TYPE::sieve_type::supportSequence::iterator rs_iter_end = rem_support->end();
581:           PETSC_MESH_TYPE::point_type bnd_segments [2];
582:           PETSC_MESH_TYPE::point_type endpts [2];
583:           int bnd_index = 0;
584:           while (rs_iter != rs_iter_end) {
585:             bnd_segments[bnd_index] = *rs_iter;
586:             ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSequence> rs_cone = boundary_sieve->cone(*rs_iter);
587:             PETSC_MESH_TYPE::sieve_type::coneSequence::iterator rsc_iter = rs_cone->begin();
588:             PETSC_MESH_TYPE::sieve_type::coneSequence::iterator rsc_iter_end = rs_cone->end();
589:             while (rsc_iter != rsc_iter_end) {
590:               if (*rsc_iter != *v_iter) {
591:                 endpts[bnd_index] = *rsc_iter;
592:               }
593:               rsc_iter++;
594:             }
595:             bnd_index++;
596:             rs_iter++;
597:           }
598:           boundary_sieve->removeBasePoint(bnd_segments[0]);
599:           boundary_sieve->removeCapPoint(*v_iter);
600:           boundary_sieve->addArrow(endpts[0], bnd_segments[1]);
601:           //PetscPrintf(m->comm(), "taking %d -%d- %d -%d- %d to %d -%d- %d\n", endpts[0], bnd_segments[0], *v_iter, bnd_segments[1], endpts[1], endpts[0], bnd_segments[1], endpts[1]);
602:           //boundary_sieve->view();
603:         }
604:         v_iter++;
605:       }
606:     } else if (dim == 3) {
607:       boundary_mesh->setDimension(2);
608:     }
609:     //insert the interior vertices
610:     v_iter = vertices->begin();
611:     v_iter_end = vertices->end();
612:     while (v_iter != v_iter_end) {
613:       if ((!boundary_sieve->hasPoint(*v_iter)) && (includedVertices->find(*v_iter) != includedVertices->end())) {
614:         boundary_sieve->addCapPoint(*v_iter);
615:         if (m->getValue(boundary, *v_iter) == 1) boundary_mesh->setValue(boundary_marker, *v_iter, 1);
616:       }
617:       v_iter++;
618:     }
619:     boundary_mesh->stratify();
620:     //set the boundary meshes coordinate section
621:     boundary_mesh->setRealSection("coordinates", m->getRealSection("coordinates"));

623: #if 0    
624:     //boundary_sieve->view();
625:     //PetscPrintf(m->comm(),"Copied the Boundary Mesh: %d vertices, %d edges\n", boundary_mesh->depthStratum(0)->size(), boundary_mesh->depthStratum(1)->size());
626:     //call triangle or tetgen: turns out the options we want on are the same
627:     //std::string triangleOptions = "zQp"; //(z)ero indexing, output (e)dges, Quiet
628:     double * finalcoords;
629:     int * connectivity;
630:     int * oldpositions;
631:     int nelements;
632:     int nverts;
633:     if (dim == 2) {
634: #ifdef PETSC_HAVE_TRIANGLE
635:      boundary_mesh->stratify();
636:      ALE::Obj<PETSC_MESH_TYPE::label_type> numbering = boundary_mesh->createLabel("numbering");
637:        //now, take the edges of this sieve and use them to construct a segmentlist.
638:        //ALE::Obj<PETSC_MESH_TYPE::numbering_type> bnd_vertices_numbering  = boundary_mesh->getFactory()->getNumbering(boundary_mesh, 0);
639:        //ALE::Obj<PETSC_MESH_TYPE::numbering_type> bnd_edges_numbering = boundary_mesh->getFactory()->getNumbering(boundary_mesh, 1);
640: 
641:        //copy over the boundary vertex coordinates:
642:        ALE::Obj<PETSC_MESH_TYPE::label_sequence> bnd_vertices = boundary_mesh->depthStratum(0);
643:        PETSC_MESH_TYPE::label_sequence::iterator bndv_iter = bnd_vertices->begin();
644:        PETSC_MESH_TYPE::label_sequence::iterator bndv_iter_end = bnd_vertices->end();
645:        while (bndv_iter != bndv_iter_end) {
646:          tmpcoords = coordinates->restrictPoint(*bndv_iter);
647:          for (int j = 0; j < dim; j++) {
648:             coords[dim*index+j] = tmpcoords[j];
649:             boundary_mesh->setValue(numbering, *bndv_iter, index);
650:             //PetscPrintf(m->comm(), "%d\n", index);
651:          }
652:          indices[index] = *bndv_iter;
653:          bndv_iter++;
654:          index++;
655:       }
656:       ALE::Obj<PETSC_MESH_TYPE::label_sequence> bnd_edges = boundary_mesh->depthStratum(1);
657:       int segments[2*bnd_edges->size()];
658:       int nSegments = bnd_edges->size();
659:       PETSC_MESH_TYPE::label_sequence::iterator bnde_iter = bnd_edges->begin();
660:       PETSC_MESH_TYPE::label_sequence::iterator bnde_iter_end = bnd_edges->end();
661:       int bnd_index = 0;
662:       while (bnde_iter != bnde_iter_end) {
663:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSequence> bnde_cone = boundary_sieve->cone(*bnde_iter);
664:         PETSC_MESH_TYPE::sieve_type::coneSequence::iterator bndec_iter = bnde_cone->begin();
665:         segments[2*bnd_index] = boundary_mesh->getValue(numbering, *bndec_iter);
666:         bndec_iter++;
667:         segments[2*bnd_index + 1] = boundary_mesh->getValue(numbering, *bndec_iter);
668:         bnd_index++;
669:         bnde_iter++;
670:       }

672:      //PetscPrintf(m->comm(),"Created the segmentlist\n");
673:       for (int i = curLevel; i < nLevels; i++) {
674:         //PetscPrintf(m->comm(), "level %d\n", i);
675:         ALE::Obj<PETSC_MESH_TYPE::label_sequence> curLevVerts = m->getLabelStratum("hdepth", i);
676:         PETSC_MESH_TYPE::label_sequence::iterator clv_iter = curLevVerts->begin();
677:         PETSC_MESH_TYPE::label_sequence::iterator clv_iter_end = curLevVerts->end();
678:           while (clv_iter != clv_iter_end) {
679:             if (m->getValue(boundary, *clv_iter) != 1) {
680:             tmpcoords = coordinates->restrictPoint(*clv_iter);
681:             for (int j = 0; j < dim; j++) {
682:               coords[index*dim+j] = tmpcoords[j];
683:             }
684:             indices[index] = *clv_iter;
685:             //PetscPrintf(m->comm(), "%d\n", index);
686:             index++;
687:           }
688:           clv_iter++;
689:         }
690:       }
691:      //PetscPrintf(m->comm(),"Triangulate\n");
692:       //create a segmentlist to keep triangle from doing dumb things.
693:       triangulateio tridata[2];
694:       SetupTriangulateio(&tridata[0], &tridata[1]);
695:       tridata[0].segmentlist = segments;
696:       tridata[0].numberofsegments = nSegments;
697:       tridata[0].pointlist = coords;
698:       tridata[0].numberofpoints = curmeshsize;
699:       tridata[0].pointmarkerlist = indices;
700:       //triangulate
701:       triangulate((char *)triangleOptions.c_str(), &tridata[0], &tridata[1], NULL);
702:       finalcoords = tridata[1].pointlist;
703:       connectivity = tridata[1].trianglelist;
704:       oldpositions = tridata[1].pointmarkerlist;
705:       nelements = tridata[1].numberoftriangles;
706:       nverts = tridata[1].numberofpoints;
707: #else
708:       throw ALE::Exception("Must have Triangle installed to use this method. Reconfigure with --download-triangle");
709: #endif
710:     } else if (dim == 3) {
711: #ifdef PETSC_HAVE_TETGEN
712:       std::string tetgenOptions = "zQe"; //(z)ero indexing, output (e)dges, Quiet
713:       for (int i = curLevel; i < nLevels; i++) {
714:         ALE::Obj<PETSC_MESH_TYPE::label_sequence> curLevVerts = m->getLabelStratum("hdepth", i);
715:         PETSC_MESH_TYPE::label_sequence::iterator clv_iter = curLevVerts->begin();
716:         PETSC_MESH_TYPE::label_sequence::iterator clv_iter_end = curLevVerts->end();
717:           while (clv_iter != clv_iter_end) {
718:             tmpcoords = coordinates->restrictPoint(*clv_iter);
719:             for (int j = 0; j < dim; j++) {
720:               coords[index*dim+j] = tmpcoords[j];
721:             }
722:             indices[index] = *clv_iter;
723:             index++;
724:             clv_iter++;
725:         }
726:       }
727:       tetgenio * tetdata = new tetgenio[2];
728:       //push the points into the thing
729:       tetdata[0].pointlist = coords;
730:       tetdata[0].pointmarkerlist = indices;
731:       tetdata[0].numberofpoints = curmeshsize;
732:       //tetrahedralize
733:       tetrahedralize((char *)tetgenOptions.c_str(), &tetdata[0], &tetdata[1]);
734:       finalcoords = tetdata[1].pointlist;
735:       connectivity = tetdata[1].tetrahedronlist;
736:       oldpositions = tetdata[1].pointmarkerlist;
737:       nelements = tetdata[1].numberoftetrahedra;
738:       nverts = tetdata[1].numberofpoints;
739: #else
740:       throw ALE::Exception("Must have TetGen installed to use this method. Reconfigure with --download-tetgen");
741: #endif
742:     }
743:     //make it into a mesh;
744:     ALE::Obj<PETSC_MESH_TYPE> newmesh = new PETSC_MESH_TYPE(m->comm(), m->debug());
745:     newmesh->setDimension(dim);
746:     ALE::Obj<PETSC_MESH_TYPE::sieve_type> sieve = new PETSC_MESH_TYPE::sieve_type(m->comm(), m->debug());
747:     ALE::SieveBuilder<PETSC_MESH_TYPE>::buildTopology(sieve, dim, nelements, connectivity, nverts, true, dim+1, -1, newmesh->getArrowSection("orientation"));
748:     newmesh->setSieve(sieve);
749:     newmesh->stratify();
750:     //UPDATE THE MARKER AND FINEMESH VERTEX NUMBERING LABELS
751:     ALE::Obj<PETSC_MESH_TYPE::label_type> boundary_new = newmesh->createLabel("marker");
752:     ALE::Obj<PETSC_MESH_TYPE::label_type> fine_corresponds = newmesh->createLabel("fine");
753:     ALE::Obj<PETSC_MESH_TYPE::label_sequence> newverts = newmesh->depthStratum(0);
754:     PETSC_MESH_TYPE::label_sequence::iterator nv_iter = newverts->begin();
755:     PETSC_MESH_TYPE::label_sequence::iterator nv_iter_end = newverts->end();
756:     while (nv_iter != nv_iter_end) {
757:       newmesh->setValue(fine_corresponds, *nv_iter, oldpositions[*nv_iter - nelements]);
758:       if(m->getValue(boundary, oldpositions[*nv_iter - nelements]) == 1) newmesh->setValue(boundary_new, *nv_iter, 1);
759:       nv_iter++;
760:     }
761: #endif //end of LONG if 0
762:     if (dim == 3) {// HACKED UP: set the height of the vertices to be "1"
763:       ALE::Obj<PETSC_MESH_TYPE::label_sequence> bound_verts = boundary_mesh->depthStratum(0);
764:       PETSC_MESH_TYPE::label_sequence::iterator bv_iter = bound_verts->begin();
765:       PETSC_MESH_TYPE::label_sequence::iterator bv_iter_end = bound_verts->end();
766:       ALE::Obj<PETSC_MESH_TYPE::label_type> bound_height = boundary_mesh->getLabel("height");
767:       while (bv_iter != bv_iter_end) {
768:         boundary_mesh->setValue(bound_height, *bv_iter, 1);
769:         bv_iter++;
770:       }
771:     }
772:     //PetscPrintf(m->comm(), "%d, %d\n", boundary_mesh->depthStratum(0)->size(), boundary_mesh->heightStratum(0)->size());
773:     ALE::Obj<PETSC_MESH_TYPE> newmesh = ALE::Generator<PETSC_MESH_TYPE>::generateMesh(boundary_mesh, (m->depth() != 1), true);
774:     //PetscPrintf(m->comm(), "%d, %d\n", newmesh->depthStratum(0)->size(), newmesh->heightStratum(0)->size());
775:     ALE::Obj<PETSC_MESH_TYPE::real_section_type> s = newmesh->getRealSection("default");
776:     const Obj<std::set<std::string> >& discs = m->getDiscretizations();
777:     //set up the default section
778:     for(std::set<std::string>::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter) {
779:       newmesh->setDiscretization(*f_iter, m->getDiscretization(*f_iter));
780:      }
781:     newmesh->setupField(s);
782:     newmesh->markBoundaryCells("marker", 1, 2, true);
783:     return newmesh;
784: }

786: #else


789: ALE::Obj<PETSC_MESH_TYPE> MeshCreateHierarchyMesh(ALE::Obj<PETSC_MESH_TYPE> m, ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSet> includedVertices) {
790:   throw ALE::Exception("reconfigure PETSc with --download-triangle and --download-tetgen to use this method.");
791:   return m;
792: }

794: #endif


799: PetscErrorCode MeshCreateHierarchyLabel_Link(Mesh finemesh, double beta, int nLevels, Mesh * outmeshes, Mat * outmats = PETSC_NULL, double curvatureCutoff = 1.0) {
801: 

804:   //initialization
805:   ALE::Obj<PETSC_MESH_TYPE> m;
806:   ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSet> includedVertices = new PETSC_MESH_TYPE::sieve_type::supportSet();
807:   includedVertices->clear();
808:   int nComparisons;
809:   PetscTruth info;
810:   PetscOptionsHasName(PETSC_NULL, "-dmmg_coarsen_info", &info);
811:   double nComparisons_perPoint_Total = 0.;
812:   double maxspace = -1., minspace = -1., dist, current_beta;
813:   double n_space, c_space, v_space;
814:   double n_coords[3], c_coords[3];
815:   PETSC_MESH_TYPE::point_type v_point;
816:   PETSC_MESH_TYPE::point_type c_point, n_point;
817:   int v_bound;
818: 
819:   std::list<PETSC_MESH_TYPE::point_type> comparison_list;
820:   std::list<PETSC_MESH_TYPE::point_type> coarsen_candidates;
821:   std::list<PETSC_MESH_TYPE::point_type> support_list;
822: 
823:   MeshGetMesh(finemesh, m);
824:   int interplevels = m->height(*m->depthStratum(0)->begin());
825:   //if (interplevels == 1) { //noninterpolated case -- fix later as join is broken
826:   //  throw ALE::Exception("Cannot Coarsen a Non-Interpolated Mesh (for now, fix is easy)");
827:   //}
828:   int dim = m->getDimension();

830:   if (!m->hasLabel("marker"))MeshIDBoundary(finemesh);
831:   const ALE::Obj<PETSC_MESH_TYPE::label_type>& boundary = m->getLabel("marker");

833:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& coordinates = m->getRealSection("coordinates");
834:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& spacing = m->getRealSection("spacing");
835:   const ALE::Obj<PETSC_MESH_TYPE::int_section_type>& seen = m->getIntSection("seen");
836:   seen->setFiberDimension(m->depthStratum(0), 1);
837:   m->allocate(seen);
838:   //PetscPrintf(m->comm(), "allocated seen");
839:   //const ALE::Obj<PETSC_MESH_TYPE::label_type> hdepth = m->createLabel("hdepth");
840:   if (info)PetscPrintf(m->comm(), "Original Mesh: %d vertices, %d elements\n", m->depthStratum(0)->size(), m->heightStratum(0)->size());
841:   const ALE::Obj<PETSC_MESH_TYPE::sieve_type> sieve = m->getSieve();
842:   const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& vertices = m->depthStratum(0);
843:   PETSC_MESH_TYPE::label_sequence::iterator v_iter = vertices->begin();
844:   PETSC_MESH_TYPE::label_sequence::iterator v_iter_end = vertices->end();
845:   PETSC_MESH_TYPE::point_type max_vertex_index = -1;

847:   //Setup, find the minimum and maximum spacing values and force in high-curvature nodes.

849:   while(v_iter != v_iter_end) {

851:     v_point = *v_iter;
852:     v_bound = m->getValue(boundary, v_point);
853:     //m->setValue(hdepth, v_point, 0);
854:     v_space = *spacing->restrictPoint(v_point);
855:     if (*v_iter > max_vertex_index) max_vertex_index = *v_iter;
856:     if ((v_space > maxspace) || (maxspace == -1.)) maxspace = v_space;
857:     if ((v_space < minspace) || (minspace == -1.)) minspace = v_space;
858:     if (m->depth(v_point) == 0 && v_bound == 1) {
859:         double cur_curvature = Curvature(m, v_point);
860:         if (info && fabs(cur_curvature) > curvatureCutoff) PetscPrintf(m->comm(), "Curvy point: %f\n", cur_curvature);
861:         if (fabs(cur_curvature) > curvatureCutoff) includedVertices->insert(*v_iter);
862:     }
863:     int pt_val = 0;
864:     seen->updatePoint(*v_iter, &pt_val);
865:     v_iter++;
866:   }
867:   for (int curLevel = nLevels-1; curLevel > 0; curLevel--) {
868:     coarsen_candidates.clear();
869:     nComparisons = 0;
870:     current_beta = pow(beta, curLevel);
871:     if (info) PetscPrintf(m->comm(), "coarsening by %f\n", current_beta);
872:     //recopy the first two levels of the sieve into a new sieve.
873:     ALE::Obj<PETSC_MESH_TYPE::sieve_type> coarsen_sieve = new PETSC_MESH_TYPE::sieve_type(m->comm(), m->debug());
874:     ALE::Obj<PETSC_MESH_TYPE> coarsen_mesh = new PETSC_MESH_TYPE(m->comm(), m->debug());
875:     coarsen_mesh->setSieve(coarsen_sieve);
876:     //INEFFICIENT!
877:     coarsen_candidates.clear();
878:     //ALE::Obj<PETSC_MESH_TYPE::label_type> coarsen_candidates = m->createLabel("candidates");
879:     v_iter = vertices->begin();
880:     v_iter_end = vertices->end();
881:     if (interplevels > 1) { //interpolated case; merely copy the edges out
882:       while (v_iter != v_iter_end) {
883:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> adjacent_edges = sieve->support(*v_iter);
884:         PETSC_MESH_TYPE::sieve_type::supportSequence::iterator ae_iter = adjacent_edges->begin();
885:         PETSC_MESH_TYPE::sieve_type::supportSequence::iterator ae_iter_end = adjacent_edges->end();
886:         while (ae_iter != ae_iter_end) {
887:           coarsen_sieve->addArrow(*v_iter, *ae_iter);
888:           ae_iter++;
889:         }
890:         v_iter++;
891:       }
892:     } else { //noninterpolated case, build the edges
893:       //PETSC_MESH_TYPE::sieve_type::supportSet seen; sets have logarithmic complexity
894:       PETSC_MESH_TYPE::point_type min_coarsen_edge_index = max_vertex_index + 1;
895:       while (v_iter != v_iter_end) {
896:         //get the neighbors of this point
897:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSet> mockup_edge_endpoints = sieve->cone(sieve->support(*v_iter));
898:         PETSC_MESH_TYPE::sieve_type::coneSet::iterator m_iter = mockup_edge_endpoints->begin();
899:         PETSC_MESH_TYPE::sieve_type::coneSet::iterator m_iter_end = mockup_edge_endpoints->end();
900:         while (m_iter != m_iter_end) {
901:           if (*m_iter != *v_iter && *seen->restrictPoint(*m_iter) == 0) {
902:             coarsen_sieve->addArrow(*v_iter, min_coarsen_edge_index);
903:             coarsen_sieve->addArrow(*m_iter, min_coarsen_edge_index);
904:             min_coarsen_edge_index++;
905:           }
906:           m_iter++;
907:         }
908:         int pt_val = 1;
909:         seen->updatePoint(*v_iter, &pt_val);
910:         v_iter++;
911:       }
912:     }
913:     coarsen_mesh->stratify();
914:     //PetscPrintf(coarsen_mesh->comm(), "%d vertices, %d edges in the coarsen structure\n", coarsen_mesh->depthStratum(0)->size(), coarsen_mesh->heightStratum(0)->size());
915:     //Interior Pass: Eliminate Nodes that collide with already included nodes or the boundary.
916:     //now, take the points that neighbor the already included points in the main sieve AND THE BOUNDARY:
917:     //for (int compare_marker = 1; compare_marker <= 2; compare_marker++) { //two passes, interior and boundary
918:     v_iter = vertices->begin();
919:     v_iter_end = vertices->end();
920:     while (v_iter != v_iter_end) {
921:       if ((includedVertices->find(*v_iter) != includedVertices->end()) || (m->getValue(boundary, *v_iter) == 1)) {
922:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> tangent_edges = coarsen_sieve->support(*v_iter);
923:         PETSC_MESH_TYPE::sieve_type::supportSequence::iterator te_iter = tangent_edges->begin();
924:         PETSC_MESH_TYPE::sieve_type::supportSequence::iterator te_iter_end = tangent_edges->end();
925:         while (te_iter != te_iter_end) {
926:           if ((m->getValue(boundary, *te_iter) == 0)) {
927:             comparison_list.push_back(*te_iter);
928:           }
929:           te_iter++;
930:         }
931:       }
932:       if ((includedVertices->find(*v_iter) == includedVertices->end()) && (m->getValue(boundary, *v_iter) == 0)) {
933:         //m->setValue(coarsen_candidates, *v_iter, 1);
934:         coarsen_candidates.push_front(*v_iter);
935:       }
936:       v_iter++;
937:     }
938:     //Interior Run: Treat the boundaries as barriers
939:     bool notDone = true;
940:     while (notDone) {
941:     while (!comparison_list.empty()){
942:       PETSC_MESH_TYPE::point_type c_edge = *comparison_list.begin();
943:       comparison_list.pop_front();
944:       //PetscPrintf(m->comm(), "comparing across edge %d\n", c_edge);
945:       ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSequence> end_points = coarsen_sieve->cone(c_edge);
946:       PETSC_MESH_TYPE::sieve_type::coneSequence::iterator ep_iter = end_points->begin();
947:       PETSC_MESH_TYPE::point_type ep_1 = *ep_iter;
948:       ep_iter++;
949:       PETSC_MESH_TYPE::point_type  ep_2 = *ep_iter;
950:       bool ep_1_hdepth = (includedVertices->find(ep_1) != includedVertices->end()); //m->getValue(hdepth, ep_1);
951:       bool ep_2_hdepth = (includedVertices->find(ep_2) != includedVertices->end());//m->getValue(hdepth, ep_2);
952:       int ep_1_bound = m->getValue(boundary, ep_1);
953:       int ep_2_bound = m->getValue(boundary, ep_2);
954:       bool ep_1_dominates = ((ep_1_hdepth == true)  || ((ep_1_bound == 1)));
955:       bool ep_2_dominates = ((ep_2_hdepth == true)  || ((ep_2_bound == 1)));
956:       //if ((!ep_1_dominates) && (!ep_2_dominates)) {
957:       //  PetscPrintf(m->comm(),"%d, %d\n", ep_1_bound, ep_2_bound);
958:       //  throw ALE::Exception("Coarse To Coarse Comparison: This Should Not Have Happened");
959:       //}
960:       if ((!ep_1_dominates && ep_2_dominates) || (ep_1_dominates && !ep_2_dominates)) {
961:         if (ep_1_dominates) {
962:         c_point = ep_2;
963:         n_point = ep_1;
964:         } else {
965:          c_point = ep_1;
966:          n_point = ep_2;
967:         }
968:         nComparisons++;
969:         PetscMemcpy(c_coords, coordinates->restrictPoint(c_point), dim*sizeof(double));
970:         c_space = *spacing->restrictPoint(c_point);
971:         PetscMemcpy(n_coords, coordinates->restrictPoint(n_point), dim*sizeof(double));
972:         n_space = *spacing->restrictPoint(n_point);
973:         dist = 0.;
974:         for (int i = 0; i < dim; i++) {
975:             dist += (n_coords[i] - c_coords[i])*(n_coords[i] - c_coords[i]);
976:         }
977:         dist = sqrt(dist);
978:         if (dist < current_beta*(n_space + c_space)) {
979:           //remove the point and this edge from existence and link its neighbors up with the eliminating point, adding the neighboring edges to THE LIST.
980:           //m->setValue(coarsen_candidates, c_point, 0);

982:           //Replace this with a more intelligent topology reconnection eventually.

984:           ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> move_these_edges = coarsen_sieve->support(c_point);
985:           PETSC_MESH_TYPE::sieve_type::supportSequence::iterator mte_iter = move_these_edges->begin();
986:           PETSC_MESH_TYPE::sieve_type::supportSequence::iterator mte_iter_end = move_these_edges->end();

988:           while (mte_iter != mte_iter_end) {
989:             if (*mte_iter != c_edge) {
990:               coarsen_sieve->addArrow(n_point, *mte_iter);
991:               if (coarsen_sieve->cone(*mte_iter)->size() == 2) {  //it's one of the edges that should be eliminated here, don't compare across it.
992:                 support_list.push_front(*mte_iter); //save for elimination because we don't want to screw up the iterator
993:               } else { //compare across the just-changed edge
994:                 comparison_list.push_back(*mte_iter);
995:               }
996:             }
997:             mte_iter++;
998:           }
999:           while (!support_list.empty()) {
1000:             PETSC_MESH_TYPE::point_type delete_this_point = *support_list.begin();
1001:             support_list.pop_front();
1002:             coarsen_sieve->removeBasePoint(delete_this_point);
1003:           }
1004:           coarsen_sieve->removeBasePoint(c_edge);
1005:           coarsen_sieve->removeCapPoint(c_point);

1007:         }
1008:       } else {
1009:         //do nothing .. this edge will never be bothered again save for the difference between the boundary and non-boundary passes.
1010:       }
1011:     }


1014:     //KILL THIS IT'S INEFFICENT
1015:     //ALE::Obj<PETSC_MESH_TYPE::label_sequence> new_candidate_options = m->getLabelStratum("candidates", 1);
1016:     PETSC_MESH_TYPE::point_type new_candidate_point = *coarsen_candidates.begin();
1017:     coarsen_candidates.pop_front();
1018:     while (!coarsen_sieve->hasPoint(new_candidate_point) && coarsen_candidates.size() > 0) {
1019:       new_candidate_point = *coarsen_candidates.begin();
1020:       coarsen_candidates.pop_front();
1021:     }
1022:     if (coarsen_candidates.size() == 0) {
1023:       notDone = false;
1024:     } else { //add this point to the mesh, adding its neighbors to the comparison queue.
1025:       //m->setValue(coarsen_candidates, new_candidate_point, 0);
1026:       //      m->setValue(hdepth, new_candidate_point, curLevel);
1027:       includedVertices->insert(new_candidate_point);
1028:       ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> neighbor_edges = coarsen_sieve->support(new_candidate_point);
1029:       PETSC_MESH_TYPE::sieve_type::supportSequence::iterator ne_iter = neighbor_edges->begin();
1030:       PETSC_MESH_TYPE::sieve_type::supportSequence::iterator ne_iter_end = neighbor_edges->end();
1031:       //PetscPrintf(coarsen_mesh->comm(), "%d edges added to the comparison queue for vertex %d.\n", neighbor_edges->size(), new_candidate_point);
1032:       while (ne_iter != ne_iter_end) {
1033:         if ((m->getValue(boundary, *ne_iter) == 0)) {
1034:           comparison_list.push_back(*ne_iter);
1035:         }
1036:         ne_iter++;
1037:       }
1038:     }
1039:     }
1040:     //Boundary Run: ONLY treat the boundary.
1041:     ALE::Obj<PETSC_MESH_TYPE::label_sequence> bound_points = m->getLabelStratum("marker", 1);
1042:     v_iter = bound_points->begin();
1043:     v_iter_end = bound_points->end();
1044:     while (v_iter != v_iter_end) {
1045:       if ((m->depth(*v_iter) == 0)&&(includedVertices->find(*v_iter) != includedVertices->end())) {
1046:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> tangent_edges = coarsen_sieve->support(*v_iter);
1047:         PETSC_MESH_TYPE::sieve_type::supportSequence::iterator te_iter = tangent_edges->begin();
1048:         PETSC_MESH_TYPE::sieve_type::supportSequence::iterator te_iter_end = tangent_edges->end();
1049:         while (te_iter != te_iter_end) {
1050:           if ((m->getValue(boundary, *te_iter) == 1)) {
1051:             comparison_list.push_back(*te_iter);
1052:           }
1053:           te_iter++;
1054:         }
1055:       }
1056:       if ((includedVertices->find(*v_iter) == includedVertices->end()) && (m->getValue(boundary, *v_iter) == 1) && (m->depth(*v_iter) == 0)) {
1057:         //m->setValue(coarsen_candidates, *v_iter, 1);
1058:         coarsen_candidates.push_front(*v_iter);
1059:         //PetscPrintf(coarsen_mesh->comm(), "Size of the support of %d is %d\n", *v_iter, coarsen_sieve->support(*v_iter)->size());
1060:       }
1061:       v_iter++;
1062:     }
1063:     //PetscPrintf(m->comm(), "Comparison_queue size: %d, Candidate_list size %d\n", comparison_list.size(), coarsen_candidates.size());
1064:     notDone = true;
1065:     while (notDone) {
1066:     while (!comparison_list.empty()){
1067:       PETSC_MESH_TYPE::point_type c_edge = *comparison_list.begin();
1068:       comparison_list.pop_front();
1069:       //PetscPrintf(m->comm(), "comparing across edge %d\n", c_edge);
1070:       ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSequence> end_points = coarsen_sieve->cone(c_edge);
1071:       PETSC_MESH_TYPE::sieve_type::coneSequence::iterator ep_iter = end_points->begin();
1072:       PETSC_MESH_TYPE::point_type ep_1 = *ep_iter;
1073:       ep_iter++;
1074:       PETSC_MESH_TYPE::point_type  ep_2 = *ep_iter;
1075:       //int ep_1_hdepth = m->getValue(hdepth, ep_1);
1076:       //int ep_2_hdepth = m->getValue(hdepth, ep_2);
1077:       bool ep_1_dominates = (includedVertices->find(ep_1) != includedVertices->end()); //((ep_1_hdepth != 0));
1078:       bool ep_2_dominates = (includedVertices->find(ep_2) != includedVertices->end()); //((ep_2_hdepth != 0));
1079:       //if ((!ep_1_dominates) && (!ep_2_dominates)) {
1080:       //  PetscPrintf(m->comm(),"%d, %d\n", ep_1_bound, ep_2_bound);
1081:       //  throw ALE::Exception("Coarse To Coarse Comparison: This Should Not Have Happened");
1082:       //}
1083:       if ((!ep_1_dominates && ep_2_dominates) || (ep_1_dominates && !ep_2_dominates)) {
1084:         if (ep_1_dominates) {
1085:         c_point = ep_2;
1086:         n_point = ep_1;
1087:         } else {
1088:          c_point = ep_1;
1089:          n_point = ep_2;
1090:         }
1091:         nComparisons++;
1092:         PetscMemcpy(c_coords, coordinates->restrictPoint(c_point), dim*sizeof(double));
1093:         c_space = *spacing->restrictPoint(c_point);
1094:         PetscMemcpy(n_coords, coordinates->restrictPoint(n_point), dim*sizeof(double));
1095:         n_space = *spacing->restrictPoint(n_point);
1096:         dist = 0.;
1097:         for (int i = 0; i < dim; i++) {
1098:             dist += (n_coords[i] - c_coords[i])*(n_coords[i] - c_coords[i]);
1099:         }
1100:         dist = sqrt(dist);
1101:         if (dist < current_beta*(n_space + c_space)) {
1102:           //remove the point and this edge from existence and link its neighbors up with the eliminating point, adding the neighboring edges to THE LIST.
1103:           //m->setValue(coarsen_candidates, c_point, 0);
1104:           ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> move_these_edges = coarsen_sieve->support(c_point);
1105:           PETSC_MESH_TYPE::sieve_type::supportSequence::iterator mte_iter = move_these_edges->begin();
1106:           PETSC_MESH_TYPE::sieve_type::supportSequence::iterator mte_iter_end = move_these_edges->end();
1107:           while (mte_iter != mte_iter_end) {
1108:             if (*mte_iter != c_edge) {
1109:               coarsen_sieve->addArrow(n_point, *mte_iter);
1110:               if (coarsen_sieve->cone(*mte_iter)->size() == 2) {  //it's one of the edges that should be eliminated here, don't compare across it.
1111:                 support_list.push_front(*mte_iter); //save for elimination because we don't want to screw up the iterator
1112:               } else { //compare across the just-changed edge
1113:                 if (m->getValue(boundary, *mte_iter) == 1)
1114:                 comparison_list.push_back(*mte_iter);
1115:               }
1116:             }
1117:             mte_iter++;
1118:           }
1119:           while (!support_list.empty()) {
1120:             PETSC_MESH_TYPE::point_type delete_this_point = *support_list.begin();
1121:             support_list.pop_front();
1122:             coarsen_sieve->removeBasePoint(delete_this_point);
1123:           }
1124:           coarsen_sieve->removeBasePoint(c_edge);
1125:           coarsen_sieve->removeCapPoint(c_point);
1126:           //PetscPrintf(m->comm(), "Removed %d\n", c_point);
1127:         }
1128:       } else {
1129:         //do nothing .. this edge will never be bothered again save for the difference between the boundary and non-boundary passes.
1130:       }
1131:     }

1133:     //ALE::Obj<PETSC_MESH_TYPE::label_sequence> new_candidate_options = m->getLabelStratum("candidates", 1);

1135:     PETSC_MESH_TYPE::point_type new_candidate_point = *coarsen_candidates.begin();
1136:     coarsen_candidates.pop_front();
1137:     while (!coarsen_sieve->hasPoint(new_candidate_point) && coarsen_candidates.size() > 0) {
1138:       new_candidate_point = *coarsen_candidates.begin();
1139:       coarsen_candidates.pop_front();
1140:       //PetscPrintf(coarsen_mesh->comm(), "%d edges in the support of the current coarsen candidate; %d somethings in the cone\n", coarsen_sieve->support(new_candidate_point)->size(), coarsen_sieve->cone(new_candidate_point)->size());
1141:     }
1142:     if (coarsen_candidates.size() == 0) {
1143:       notDone = false;
1144:     } else { //add this point to the mesh, adding its neighbors to the comparison queue.
1145:       //m->setValue(coarsen_candidates, *new_candidate, 0);
1146:       //m->setValue(hdepth, new_candidate_point, curLevel);
1147:       includedVertices->insert(new_candidate_point);
1148:       ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSequence> neighbor_edges = coarsen_sieve->support(new_candidate_point);
1149:       PETSC_MESH_TYPE::sieve_type::supportSequence::iterator ne_iter = neighbor_edges->begin();
1150:       PETSC_MESH_TYPE::sieve_type::supportSequence::iterator ne_iter_end = neighbor_edges->end();
1151:       //PetscPrintf(coarsen_mesh->comm(), "%d edges added to the comparison queue for vertex %d.\n", neighbor_edges->size(), new_candidate_point);
1152:       if (neighbor_edges->size() == 0) throw ALE::Exception("bad vertex.");
1153:       while (ne_iter != ne_iter_end) {
1154:         if (m->getValue(boundary, *ne_iter) == 1) {
1155:           comparison_list.push_back(*ne_iter);
1156:         }
1157:         ne_iter++;
1158:       }
1159:     }
1160:     }


1163:     //}
1164:     coarsen_mesh->stratify();
1165:     ALE::Obj<PETSC_MESH_TYPE::label_sequence> coarsen_vertices = coarsen_mesh->depthStratum(0);
1166:     PETSC_MESH_TYPE::label_sequence::iterator cv_iter = coarsen_vertices->begin();
1167:     PETSC_MESH_TYPE::label_sequence::iterator cv_iter_end = coarsen_vertices->end();
1168:     //what does this part do again?
1169:     includedVertices->clear();
1170:     while (cv_iter != cv_iter_end) {
1171:       // m->setValue(hdepth, *cv_iter, curLevel);
1172:       includedVertices->insert(*cv_iter);
1173:       cv_iter++;
1174:     }
1175:   if(info) PetscPrintf(m->comm(), "%d points in %d comparisons\n", coarsen_mesh->depthStratum(0)->size(), nComparisons);
1176:   nComparisons_perPoint_Total += nComparisons;
1177:   ALE::Obj<PETSC_MESH_TYPE> newmesh = MeshCreateHierarchyMesh(m, includedVertices);
1178:   if(info) PetscPrintf(m->comm(), "%d: %d vertices, %d elements\n", curLevel, newmesh->depthStratum(0)->size(), newmesh->heightStratum(0)->size());
1179:   MeshSetMesh(outmeshes[curLevel-1], newmesh);
1180:   }
1181:   nComparisons_perPoint_Total = nComparisons_perPoint_Total/((double)m->depthStratum(0)->size());
1182:   if(info) PetscPrintf(m->comm(), "Comparisons Per Point: %f\n", nComparisons_perPoint_Total);
1183:   return(0);
1184: }


1189: //MeshCreateHierarchyLabel: Create a label that tells what the highest level a given vertex appears in where 0 is fine and n is coarsest.
1190: PetscErrorCode MeshCreateHierarchyLabel(Mesh finemesh, double beta, int nLevels, Mesh * outmeshes, Mat * outmats = PETSC_NULL) {
1192:   ALE::Obj<PETSC_MESH_TYPE> m;
1194:   PetscTruth info;
1195:   int overallComparisons = 0;
1196:   PetscOptionsHasName(PETSC_NULL, "-dmmg_coarsen_info", &info);
1197:   MeshGetMesh(finemesh, m);
1198:   int dim = m->getDimension();
1199:   if (info)PetscPrintf(m->comm(), "Original Mesh: %d vertices, %d elements\n", m->depthStratum(0)->size(), m->heightStratum(0)->size());
1200:   if (!m->hasLabel("marker"))MeshIDBoundary(finemesh);
1201:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& coordinates = m->getRealSection("coordinates");
1202:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& spacing = m->getRealSection("spacing");
1203:   const ALE::Obj<PETSC_MESH_TYPE::label_type> hdepth = m->createLabel("hdepth");
1204:   const ALE::Obj<PETSC_MESH_TYPE::label_type> dompoint = m->createLabel("dompoint");
1205:   const ALE::Obj<PETSC_MESH_TYPE::label_type> traversal = m->createLabel("traversal");
1206:   const ALE::Obj<PETSC_MESH_TYPE::label_type>& boundary = m->getLabel("marker");
1207:   const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& vertices = m->depthStratum(0);
1208:   PETSC_MESH_TYPE::label_sequence::iterator v_iter = vertices->begin();
1209:   PETSC_MESH_TYPE::label_sequence::iterator v_iter_end = vertices->end();
1210:   double maxspace = -1., minspace = -1., dist;
1211:   PETSC_MESH_TYPE::point_type max_vertex_index = -1;
1212:   while(v_iter != v_iter_end) {
1213:     //initialize the label to 0.
1214:     m->setValue(hdepth, *v_iter, 0);
1215:     //discover the maximum and minimum spacing functions in the mesh.
1216:     double vspace = *spacing->restrictPoint(*v_iter);
1217:     if ((vspace > maxspace) || (maxspace == -1.)) maxspace = vspace;
1218:     if ((vspace < minspace) || (minspace == -1.)) minspace = vspace;
1219:     if (*v_iter > max_vertex_index) max_vertex_index = *v_iter;
1220:     v_iter++;
1221:   }
1222:   //PUT IN PART FOR AUTOMATICALLY ADDING HIGH-CURVATURE BOUNDARY NODES
1223:   const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& boundaryvertices = m->getLabelStratum("marker", 1); //boundary
1224:   PETSC_MESH_TYPE::label_sequence::iterator bv_iter = boundaryvertices->begin();
1225:   PETSC_MESH_TYPE::label_sequence::iterator bv_iter_end = boundaryvertices->end();
1226:  // PetscPrintf(m->comm(), "NUMBER OF BOUNDARY POINTS: %d\n", boundaryvertices->size());
1227:   while (bv_iter != bv_iter_end) {
1228:     if (m->depth(*bv_iter) == 0) if (Curvature(m, *bv_iter) > 0.1) {
1229:       m->setValue(hdepth, *bv_iter, nLevels-1);
1230:     }
1231:     bv_iter++;
1232:   }
1233:  // PetscPrintf(m->comm(), "Forced in %d especially curved boundary nodes.\n", m->getLabelStratum("hdepth", nLevels-1)->size());
1234:   double *bvCoords = new double[dim];
1235:   PETSC_MESH_TYPE::point_type bvdom;
1236:   std::list<PETSC_MESH_TYPE::point_type> complist;
1237:   std::list<PETSC_MESH_TYPE::point_type> domlist; //stores the points dominated by the current point.
1238:   for (int curLevel = nLevels-1; curLevel > 0; curLevel--) {
1239:     double curBeta = pow(beta, curLevel);
1240:    //OUR MODUS OPERANDI:
1241:     //1. do the boundary and the interior identically but separately
1242:     //2. keep track of the point that eliminates each point on each level.  This should work sort of like an approximation to the voronoi partitions.  Compare against these first as they're more likely to collide than neighbors.  Also compare to the points that eliminate the neighbors in the same fashion.
1243:     //3. If the point is not eliminated by its old eliminator we must traverse out to max(space(v)) + space(i).
1244:     //GOAL: only eliminate each point once! if we add a point that eliminates other points get rid of them in the traversal! (and set their elimination marker appropriately.)
1245:     double comparison_const;
1246:     PETSC_MESH_TYPE::label_sequence::iterator bv_iter = boundaryvertices->begin();
1247:     PETSC_MESH_TYPE::label_sequence::iterator bv_iter_end = boundaryvertices->end();
1248:     ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSet> neighbors = m->getSieve()->cone(m->getSieve()->support(*bv_iter));
1249:     PETSC_MESH_TYPE::sieve_type::coneSet::iterator n_iter = neighbors->begin();
1250:     PETSC_MESH_TYPE::sieve_type::coneSet::iterator n_iter_end = neighbors->end();
1251:     int nComparisonsTotal = 0;
1252:     while (bv_iter != bv_iter_end) {
1253:       bvdom = m->getValue(dompoint, *bv_iter);
1254:       bool skip = false;
1255:       if (bvdom != -1) {
1256:         if (m->getValue(hdepth, bvdom) == curLevel) skip = true;
1257:       }
1258:       bool canAdd = true;
1259:       if (m->getValue(hdepth, *bv_iter) == 0 && !skip && m->depth(*bv_iter) == 0) { //if not yet included or invalidated
1260:         m->setValue(traversal, *bv_iter, 1);
1261:         double bvSpace = *spacing->restrictPoint(*bv_iter);
1262:         PetscMemcpy(bvCoords, coordinates->restrictPoint(*bv_iter), dim*sizeof(double));
1263:         //get its neighbors and add them to the comparison queue.
1264:         neighbors = m->getSieve()->cone(m->getSieve()->support(*bv_iter));
1265:         n_iter = neighbors->begin();
1266:         n_iter_end = neighbors->end();
1267:         while (n_iter != n_iter_end) {
1268:           if (m->getValue(boundary, *n_iter) == 1) {
1269:             m->setValue(traversal, *n_iter, 1);
1270:             complist.push_front(*n_iter);
1271:           }
1272:           n_iter++;
1273:         }
1274:         //push the last point to invalidate the current point to the front of the list of comparisons.
1275:         bool setDist = false;
1276:         if (bvdom != -1) {
1277:            setDist = true;
1278:            complist.push_front(bvdom);
1279:         }

1281:         while ((!complist.empty()) && canAdd) {
1282:           nComparisonsTotal++;
1283:           PETSC_MESH_TYPE::point_type curpt = *complist.begin();
1284:           complist.pop_front();
1285:           dist = 0.;
1286:           double curSpace = *spacing->restrictPoint(curpt);
1287:           const double * curCoords = coordinates->restrictPoint(curpt);
1288:           for (int i = 0; i < dim; i++) {
1289:             dist += (curCoords[i] - bvCoords[i])*(curCoords[i] - bvCoords[i]);
1290:           }
1291:           //gets the distance to bvdom as the maximum radius to compare out
1292:           dist = sqrt(dist);
1293:           comparison_const = 0.5*curBeta;
1294:           if (setDist == true) {
1295:             maxspace = dist;
1296:             setDist = false;
1297:           } else {
1298:             maxspace = 3.*curSpace*comparison_const;
1299:           }
1300:           PETSC_MESH_TYPE::point_type curpt_dom = m->getValue(dompoint, curpt);
1301:           int curpt_depth = m->getValue(hdepth, curpt);
1302:           int curpt_bound = m->getValue(boundary, curpt);
1303:           if ((dist < comparison_const*(bvSpace + curSpace))&&(curpt_depth > 0)) { //collision with an already added node
1304:             canAdd = false;
1305:             m->setValue(dompoint, *bv_iter, curpt);
1306:           } else if (dist < maxspace) { //go out to the dompoint
1307:             neighbors = m->getSieve()->cone(m->getSieve()->support(curpt));
1308:             n_iter = neighbors->begin();
1309:             n_iter_end = neighbors->end();
1310:             while (n_iter != n_iter_end) {
1311:               if ((m->getValue(traversal, *n_iter) == 0)) {
1312:                 m->setValue(traversal, *n_iter, 1);
1313:                 complist.push_back(*n_iter);
1314:               }
1315:               n_iter++;
1316:             }
1317:           }
1318:           if ((dist < comparison_const*(bvSpace + curSpace)) && (curpt_depth == 0)) { //add the point to the list of points dominated by this node; points eliminated in one step later
1319:             domlist.push_front(curpt);
1320:             if (curpt_bound == 0) {
1321:               m->setValue(dompoint, curpt, *bv_iter);
1322:             }
1323:           }
1324:           if ((dist < maxspace) && (curpt_depth == 0)) {
1325:             if (curpt_dom != -1) {
1326:               if (m->getValue(traversal, curpt_dom) == 0) {
1327:                 complist.push_front(curpt_dom);
1328:                 m->setValue(traversal, curpt_dom, 1);
1329:               }
1330:             }
1331:           }
1332:         }  //end of complist deal
1333:         complist.clear();
1334:         if (canAdd == true) {
1335:           m->setValue(hdepth, *bv_iter, curLevel);
1336:           std::list<PETSC_MESH_TYPE::point_type>::iterator dom_iter = domlist.begin();
1337:           std::list<PETSC_MESH_TYPE::point_type>::iterator dom_iter_end = domlist.end();
1338:           while (dom_iter != dom_iter_end) {
1339:             m->setValue(dompoint, *dom_iter, *bv_iter);
1340:             dom_iter++;
1341:           }
1342:         }
1343:         domlist.clear();
1344:         //unset the traversal listing
1345:         ALE::Obj<PETSC_MESH_TYPE::label_sequence> travnodes = m->getLabelStratum("traversal", 1);
1346:         PETSC_MESH_TYPE::label_sequence::iterator tn_iter = travnodes->begin();
1347:         PETSC_MESH_TYPE::label_sequence::iterator tn_iter_end = travnodes->end();
1348:         while (tn_iter != tn_iter_end) {
1349:           complist.push_front(*tn_iter);
1350:           tn_iter++;
1351:         }
1352:         while (!complist.empty()) {
1353:           PETSC_MESH_TYPE::point_type emptpt = *complist.begin();
1354:           complist.pop_front();
1355:           m->setValue(traversal, emptpt, 0);
1356:         }
1357:       }
1358:       bv_iter++;
1359:     }
1360:  //   PetscPrintf(m->comm(), "Added %d new boundary vertices\n", m->getLabelStratum("hdepth", curLevel)->size());
1361:     //INTERIOR NODES:
1362:     complist.clear();
1363:     ALE::Obj<PETSC_MESH_TYPE::label_sequence> intverts = m->depthStratum(0);
1364:     bv_iter = intverts->begin();
1365:     bv_iter_end = intverts->end();
1366:     while (bv_iter != bv_iter_end) {
1367:       bvdom = m->getValue(dompoint, *bv_iter);
1368:       bool skip = false;
1369:       if (bvdom != -1) {
1370:         if (m->getValue(hdepth, bvdom) == curLevel) skip = true;
1371:       }
1372:       bool canAdd = true;
1373:       if ((m->getValue(boundary, *bv_iter) != 1) && (m->getValue(hdepth, *bv_iter) == 0) && !skip) { //if not in the boundary and not included (or excluded)
1374:         double bvSpace = *spacing->restrictPoint(*bv_iter);
1375:         PetscMemcpy(bvCoords, coordinates->restrictPoint(*bv_iter), dim*sizeof(double));
1376:         //get its neighbors and add them to the comparison queue.
1377:         neighbors = m->getSieve()->cone(m->getSieve()->support(*bv_iter));
1378:         n_iter = neighbors->begin();
1379:         n_iter_end = neighbors->end();
1380:         m->setValue(traversal, *bv_iter, 1);
1381:         while (n_iter != n_iter_end) {
1382:           if (*n_iter != *bv_iter) {
1383:             //PetscPrintf(m->comm(), "Added %d to the list\n", *n_iter);
1384:             m->setValue(traversal, *n_iter, 1);
1385:             complist.push_front(*n_iter);
1386:           }
1387:           n_iter++;
1388:         }
1389:         maxspace = 0.5*bvSpace*curBeta;
1390:         bool setDist = false;
1391:         if (bvdom != -1) {
1392:            setDist = true;
1393:            complist.push_front(bvdom);
1394:         }
1395:         while ((!complist.empty()) && canAdd) {
1396:           nComparisonsTotal++;
1397:           PETSC_MESH_TYPE::point_type curpt = *complist.begin();
1398:           complist.pop_front();
1399:           //PetscPrintf(m->comm(), "Comparing %d to %d\n", *bv_iter, curpt);
1400:           dist = 0.;
1401:           double curSpace = *spacing->restrictPoint(curpt);
1402:           const double * curCoords = coordinates->restrictPoint(curpt);
1403:           for (int i = 0; i < dim; i++) {
1404:             dist += (curCoords[i] - bvCoords[i])*(curCoords[i] - bvCoords[i]);
1405:           }
1406:           comparison_const = 0.5*curBeta;
1407:           dist = sqrt(dist);
1408:           if (setDist == true) {
1409:             maxspace = dist;
1410:             setDist = false;
1411:           } else {
1412:             maxspace = 3.*curSpace*comparison_const;
1413:           }
1414:           int curpt_depth = m->getValue(hdepth, curpt);
1415:           int curpt_bound = m->getValue(boundary, curpt);
1416:           PETSC_MESH_TYPE::point_type curpt_dom = m->getValue(dompoint, curpt);
1417:           if ((dist < comparison_const*(bvSpace + curSpace))&&(curpt_depth > 0)) {
1418:             canAdd = false;
1419:             m->setValue(dompoint, *bv_iter, curpt);
1420:           } else if ((dist < comparison_const*(bvSpace+curSpace)) && (curpt_bound == 1)) {
1421:             canAdd = false;
1422:             m->setValue(dompoint, *bv_iter, curpt);
1423:           } else if (dist < maxspace) {
1424:             neighbors = m->getSieve()->cone(m->getSieve()->support(curpt));
1425:             n_iter = neighbors->begin();
1426:             n_iter_end = neighbors->end();
1427:             while (n_iter != n_iter_end) {
1428:               if ((m->getValue(boundary, *n_iter) != 1) && (m->getValue(traversal, *n_iter) != 1)) {
1429:                 m->setValue(traversal, *n_iter, 1);
1430:                 complist.push_back(*n_iter);
1431:               }
1432:               n_iter++;
1433:             }
1434:           }
1435:           if ((dist < comparison_const*(bvSpace + curSpace)) && (curpt_depth == 0)) {
1436:             domlist.push_front(curpt);
1437:           }
1438:           if ((dist < maxspace) && (curpt_depth == 0)) {
1439:             if (curpt_dom != -1) {
1440:               if (m->getValue(traversal, curpt_dom) == 0) {
1441:                 complist.push_front(curpt_dom);
1442:                 m->setValue(traversal, curpt_dom, 1);
1443:               }
1444:             }
1445:           }
1446:         }  //end of complist deal
1447:         complist.clear();
1448:         if (canAdd == true) {
1449:           m->setValue(hdepth, *bv_iter, curLevel);
1450:           std::list<PETSC_MESH_TYPE::point_type>::iterator dom_iter = domlist.begin();
1451:           std::list<PETSC_MESH_TYPE::point_type>::iterator dom_iter_end = domlist.end();
1452:           while (dom_iter != dom_iter_end) {
1453:             m->setValue(dompoint, *dom_iter, *bv_iter);
1454:             dom_iter++;
1455:           }
1456:         }
1457:         domlist.clear();
1458:         complist.clear();
1459:         //unset the traversal listing
1460:         ALE::Obj<PETSC_MESH_TYPE::label_sequence> travnodes = m->getLabelStratum("traversal", 1);
1461:         PETSC_MESH_TYPE::label_sequence::iterator tn_iter = travnodes->begin();
1462:         PETSC_MESH_TYPE::label_sequence::iterator tn_iter_end = travnodes->end();
1463:         while (tn_iter != tn_iter_end) {
1464:           complist.push_front(*tn_iter);
1465:           tn_iter++;
1466:         }
1467:         while (!complist.empty()) {
1468:           PETSC_MESH_TYPE::point_type emptpt = *complist.begin();
1469:           complist.pop_front();
1470:           m->setValue(traversal, emptpt, 0);
1471:         }
1472:       }
1473:       bv_iter++;
1474:     }
1475:   //  PetscPrintf(m->comm(), "Included %d new points in level %d\n", m->getLabelStratum("hdepth", curLevel)->size(), curLevel);
1476:     ALE::Obj<PETSC_MESH_TYPE> newmesh;
1477:     // = MeshCreateHierarchyMesh(m, nLevels, curLevel);
1478:     if (info)PetscPrintf(m->comm(), "%d: %d vertices, %d elements in %d comparisons\n", curLevel, newmesh->depthStratum(0)->size(), newmesh->heightStratum(0)->size(), nComparisonsTotal);
1479:     overallComparisons += nComparisonsTotal; //yeah yeah horrible names

1481:     MeshSetMesh(outmeshes[curLevel-1], newmesh);
1482: /*    SectionRealCreate(newmesh->comm(), &section);
1483:     SectionRealGetBundle(section, newmesh);
1484:     SectionRealGetSection(section, s);
1485:     PetscObjectSetName((PetscObject) section, "default");
1486:     MeshSetSectionReal(outmeshes[curLevel-1], section);
1487:     SectionRealDestroy(section);*/
1488:   } //end of level for
1489:   delete [] bvCoords;
1490:   if (info)PetscPrintf(m->comm(), "Comparisons per Point: %f\n", (float)overallComparisons/vertices->size());
1491:   //std::list<PETSC_MESH_TYPE::point_type> tricomplist;
1492: /*  for (int curLevel = 0; curLevel < nLevels-1; curLevel++) {
1493:     if (info) PetscPrintf(m->comm(), "Building the prolongation section from level %d to level %d\n", curLevel, curLevel+1);
1494:     ALE::Obj<PETSC_MESH_TYPE> c_m;
1495:     ALE::Obj<PETSC_MESH_TYPE> f_m;
1496:     if (curLevel == 0) {
1497:       f_m = m;
1498:     } else {
1499:       MeshGetMesh(outmeshes[curLevel-1], f_m);
1500:     }
1501:     MeshGetMesh(outmeshes[curLevel], c_m);
1502:     ALE::Obj<PETSC_MESH_TYPE::label_type> prolongation = f_m->createLabel("prolongation");
1503:     ALE::Obj<PETSC_MESH_TYPE::label_type> coarse_traversal = c_m->createLabel("traversal");
1504:     ALE::Obj<PETSC_MESH_TYPE::label_sequence> levelVertices = m->getLabelStratum("hdepth", curLevel);
1505:    // PetscPrintf(m->comm(), "%d points in level %d\n", levelVertices->size(), curLevel);
1506:     PETSC_MESH_TYPE::label_sequence::iterator lv_iter = levelVertices->begin();
1507:     PETSC_MESH_TYPE::label_sequence::iterator lv_iter_end = levelVertices->end();
1508:     int interpolatelevels = c_m->height(*c_m->depthStratum(0)->begin()); //see if the mesh is interpolated or not
1509:     double lvCoords[dim];
1510:     while (lv_iter != lv_iter_end) {
1511:       int ncomps = 0;
1512:       PetscMemcpy(lvCoords, coordinates->restrictPoint(*lv_iter), dim*sizeof(double));
1513:       if (m->getValue(boundary, *lv_iter) != 1) {
1514:         //get the triangle/tet fan around the dominating point in the next level up
1515:         PETSC_MESH_TYPE::point_type dp = m->getValue(dompoint, *lv_iter);
1516:         if (m->getValue(hdepth, dp) < curLevel+1) dp = m->getValue(dompoint, dp); //if it's a boundary node it can be a dominating point and NOT be in the topmesh
1517:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportArray> trifan = c_m->getSieve()->nSupport(*c_m->getLabelStratum("fine", dp)->begin(), interpolatelevels);
1518:         PETSC_MESH_TYPE::sieve_type::supportArray::iterator tf_iter = trifan->begin();
1519:         PETSC_MESH_TYPE::sieve_type::supportArray::iterator tf_iter_end = trifan->end();
1520:         while (tf_iter != tf_iter_end) {
1521:           tricomplist.push_front(*tf_iter); //initialize the closest-guess comparison list.
1522:           c_m->setValue(coarse_traversal, *tf_iter, 1);
1523:           tf_iter++;
1524:         }
1525:         //PetscPrintf(m->comm(), "%d initial guesses\n", trifan->size());
1526:         bool isFound = false;
1527:         while (!tricomplist.empty() && !isFound) {
1528:           PETSC_MESH_TYPE::point_type curTri = *tricomplist.begin();
1529:           tricomplist.pop_front();
1530:           ncomps++;
1531:           if (PointIsInElement(c_m, curTri, lvCoords)) {
1532:             PETSC_MESH_TYPE::point_type fmpoint;
1533:             if (curLevel == 0) {
1534:               fmpoint = *lv_iter;
1535:             } else {
1536:               fmpoint = *f_m->getLabelStratum("fine", *lv_iter)->begin();
1537:             } 
1538:             f_m->setValue(prolongation, fmpoint, curTri);
1539:             isFound = true;
1540:           //  PetscPrintf(m->comm(), "%d located in %d\n", *lv_iter, curTri);
1541:           } else {
1542:             ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSet> trineighbors = c_m->getSieve()->support(c_m->getSieve()->cone(curTri));
1543:             PETSC_MESH_TYPE::sieve_type::supportSet::iterator tn_iter = trineighbors->begin();
1544:             PETSC_MESH_TYPE::sieve_type::supportSet::iterator tn_iter_end = trineighbors->end();
1545:             while (tn_iter != tn_iter_end) {
1546:               if (c_m->getValue(coarse_traversal, *tn_iter) != 1){
1547:                 tricomplist.push_back(*tn_iter);
1548:                 c_m->setValue(coarse_traversal, *tn_iter, 1);
1549:               }
1550:               tn_iter++;
1551:             }
1552:           }
1553:         }
1554:         ALE::Obj<PETSC_MESH_TYPE::label_sequence> travtris = c_m->getLabelStratum("traversal", 1);
1555:         PETSC_MESH_TYPE::label_sequence::iterator tt_iter = travtris->begin();
1556:         PETSC_MESH_TYPE::label_sequence::iterator tt_iter_end = travtris->end();
1557:         while (tt_iter != tt_iter_end) {
1558:           tricomplist.push_front(*tt_iter);
1559:           tt_iter++;
1560:         }
1561:         while (!tricomplist.empty()) {
1562:           c_m->setValue(coarse_traversal, *tricomplist.begin(), 0);
1563:           tricomplist.pop_front();
1564:         }
1565:         if (!isFound) {
1566:           PetscPrintf(m->comm(), "ERROR: Could Not Locate Point %d (%f, %f) in %d comparisons\n", *lv_iter, lvCoords[0], lvCoords[1], ncomps);
1567:         }
1568:       } else { //DO NOT correct the boundary nodes only added on this level. (might break neumann)
1569:         PETSC_MESH_TYPE::point_type fmpoint;
1570:         if (curLevel == 0) {
1571:           fmpoint = *lv_iter;
1572:         } else {
1573:           fmpoint = *f_m->getLabelStratum("fine", *lv_iter)->begin();
1574:         } 
1575:         f_m->setValue(prolongation, fmpoint, -1);
1576:       }
1577:       lv_iter++;
1578:     }
1579:     //set the prolongation label for the guys in this mesh in such a way that there's an element associated for the points in higher levels also.
1580:     for (int upLevel = curLevel + 1; upLevel < nLevels - 1; upLevel++) {
1581:       levelVertices = m->getLabelStratum("hdepth", upLevel);
1582:       lv_iter = levelVertices->begin();
1583:       lv_iter_end = levelVertices->end();
1584:       while (lv_iter != lv_iter_end) {
1585:         //if (m->getValue(boundary, *lv_iter) != 1) { we CAN correct for the boundary, and should!
1586:           //nothing complicated, just take the FIRST element of the nSupport of it in the next mesh up.
1587:           PETSC_MESH_TYPE::point_type cmpt = *c_m->getLabelStratum("fine", *lv_iter)->begin();
1588:           PETSC_MESH_TYPE::point_type fmpoint;
1589:           if (curLevel == 0) {
1590:             fmpoint = *lv_iter;
1591:           } else {
1592:             fmpoint = *f_m->getLabelStratum("fine", *lv_iter)->begin();
1593:           } 
1594:           f_m->setValue(prolongation, fmpoint, *c_m->getSieve()->nSupport(cmpt, interpolatelevels)->begin());
1595:         //}
1596:         lv_iter++;
1597:       }
1598:     }
1599:   }*/
1600: /*  if (info) PetscPrintf(m->comm(), "Building the prolongation section from level %d to level %d\n", 0, 1);
1601:   MeshLocateInMesh(finemesh, outmeshes[0]);
1602:   for (int curLevel = 1; curLevel < nLevels-1; curLevel++) {
1603:     if (info) PetscPrintf(m->comm(), "Building the prolongation section from level %d to level %d\n", curLevel, curLevel+1);
1604:     MeshLocateInMesh(outmeshes[curLevel-1], outmeshes[curLevel]);
1605:   }
1606: */
1607:  return(0);
1608: }




1615: //MeshCreateHierarchyLabel: Create a label that tells what the highest level a given vertex appears in where 0 is fine and n is coarsest.
1616: PetscErrorCode MeshCreateHierarchyLabel_NEW(Mesh finemesh, double beta, int nLevels, Mesh * outmeshes) {
1618: 

1621:   //initialization
1622:   ALE::Obj<PETSC_MESH_TYPE> m;
1623:   double maxspace = -1., minspace = -1., dist, current_beta;
1624:   double v_space, c_space, total_space, max_total_space;
1625:   double v_coords[3], c_coords[3];

1627:   int mesh_vertices_size = 0;

1629:   int v_point, v_bound, v_hdepth, v_dominating_point;
1630:   int c_point, c_bound, c_hdepth, c_dominating_point;
1631:   int n_point, n_bound, n_traversal;
1632: 
1633:   std::list<PETSC_MESH_TYPE::point_type> comparison_list;

1635:   std::list<PETSC_MESH_TYPE::point_type> traversed_list;

1637:   std::list<PETSC_MESH_TYPE::point_type> dominated_list;
1638:   std::list<PETSC_MESH_TYPE::point_type>::iterator dominated_list_iter = dominated_list.begin();
1639:   std::list<PETSC_MESH_TYPE::point_type>::iterator dominated_list_iter_end = dominated_list.end();

1641: 
1642:   bool canAdd, skip;
1643: 
1644:   MeshGetMesh(finemesh, m);

1646:   int dim = m->getDimension();

1648:   if (!m->hasLabel("marker"))MeshIDBoundary(finemesh);
1649:   const ALE::Obj<PETSC_MESH_TYPE::label_type>& boundary = m->getLabel("marker");

1651:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& coordinates = m->getRealSection("coordinates");
1652:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& spacing = m->getRealSection("spacing");
1653:   const ALE::Obj<PETSC_MESH_TYPE::label_type> hdepth = m->createLabel("hierarchy_depth");
1654:   const ALE::Obj<PETSC_MESH_TYPE::label_type> dompoint = m->createLabel("dominating_point");
1655:   const ALE::Obj<PETSC_MESH_TYPE::label_type> traversal = m->createLabel("traversal");

1657:   const ALE::Obj<PETSC_MESH_TYPE::sieve_type> sieve = m->getSieve();
1658:   const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& vertices = m->depthStratum(0);
1659:   PETSC_MESH_TYPE::label_sequence::iterator v_iter = vertices->begin();
1660:   PETSC_MESH_TYPE::label_sequence::iterator v_iter_end = vertices->end();
1661: 
1662:   //Setup, find the minimum and maximum spacing values and force in high-curvature nodes.
1663:   while(v_iter != v_iter_end) {

1665:     v_point = *v_iter;
1666:     v_bound = m->getValue(boundary, v_point);
1667:     m->setValue(dompoint, v_point, -1);
1668:     m->setValue(hdepth, v_point, 0);
1669:     v_space = *spacing->restrictPoint(v_point);

1671:     if ((v_space > maxspace) || (maxspace == -1.)) maxspace = v_space;
1672:     if ((v_space < minspace) || (minspace == -1.)) minspace = v_space;

1674:     if (m->depth(v_point) == 0 && v_bound == 1) if (Curvature(m, v_point) > 0.01) {
1675:       m->setValue(hdepth, v_point, nLevels-1);
1676:     }

1678:     v_iter++;
1679:   }

1681:   //main loop over levels
1682:   for (int current_level = nLevels - 1; current_level > 0; current_level--) {

1684:     current_beta = 0.5*pow(beta, current_level);
1685:     v_iter = vertices->begin();
1686:     v_iter_end = vertices->end();
1687:     while (v_iter != v_iter_end) {

1689:       v_point = *v_iter;
1690:       v_hdepth = m->getValue(hdepth, v_point);
1691:       v_dominating_point = m->getValue(dompoint, v_point);

1693:       //determine if this point has already been eliminated this round
1694:       skip = false;
1695:       if (v_dominating_point != -1) {
1696:         if (m->getValue(hdepth, v_dominating_point) == current_level) skip = true;
1697:       }

1699:       if (v_hdepth == 0 && !skip) {
1700:         v_bound = m->getValue(boundary, v_point);
1701:         //PetscPrintf(m->comm(), "%d\n", v_point);
1702:         //get the coordinates and spacing function values for this point.
1703:         v_space = *spacing->restrictPoint(v_point);
1704:         PetscMemcpy(v_coords, coordinates->restrictPoint(v_point), dim*sizeof(double));
1705:         max_total_space = current_beta*(v_space*3);  //keep EVERYTHING local, max-space blows up on highly-graded meshes

1707:         //seed the comparison list and set the current point as traversed
1708:         m->setValue(traversal, v_point, 1);
1709:         traversed_list.push_front(v_point);
1710:         if (v_dominating_point != -1) {
1711:           comparison_list.push_front(v_dominating_point);
1712:           traversed_list.push_front(v_dominating_point);
1713:           m->setValue(traversal, v_dominating_point, 1);
1714:         }
1715:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSet> neighbors = sieve->cone(sieve->support(v_point));
1716:         PETSC_MESH_TYPE::sieve_type::coneSet::iterator n_iter = neighbors->begin();
1717:         PETSC_MESH_TYPE::sieve_type::coneSet::iterator n_iter_end = neighbors->end();
1718: 

1720:         while (n_iter != n_iter_end) {
1721:           n_point = *n_iter;
1722:           if ((v_point != n_point)&&((m->getValue(boundary, n_point) == 1 && v_bound == 1) || v_bound == 0)) {
1723:             m->setValue(traversal, n_point, 1);
1724:             traversed_list.push_front(n_point);
1725:             comparison_list.push_back(n_point);
1726:           }
1727:           n_iter++;
1728:         }
1729: 
1730:         //traverse the mesh out to the point where nothing can collide with this point
1731:         canAdd = true;
1732:         while (!comparison_list.empty() && canAdd) {
1733: 
1734:           c_point = comparison_list.front();
1735:           comparison_list.pop_front();
1736:           //PetscPrintf(m->comm(), "%d\n", c_point);
1737:           c_bound = m->getValue(boundary, c_point);
1738:           c_hdepth = m->getValue(hdepth, c_point);
1739:           c_dominating_point = m->getValue(dompoint, c_point);
1740:           PetscMemcpy(c_coords, coordinates->restrictPoint(c_point), dim*sizeof(double));
1741: 
1742:           //compute the distance
1743:           dist = 0.;
1744:           for (int i = 0; i < dim; i++) {
1745:             dist += (c_coords[i] - v_coords[i])*(c_coords[i] - v_coords[i]);
1746:           }
1747:           dist = sqrt(dist);
1748: 
1749:           if (dist < max_total_space) { //if it could possibly collide in the function-ball sense:
1750:             c_space = *spacing->restrictPoint(c_point);
1751:             // if it collides in the function-ball sense:
1752:             total_space = current_beta*(v_space + c_space);
1753:             if (dist < total_space) {
1754:               if (v_bound == 1) { //boundary case
1755:                 if (c_hdepth != 0) {
1756:                   canAdd = false;
1757:                   m->setValue(dompoint, v_point, c_point);
1758:                 } else {
1759:                   dominated_list.push_front(c_point);
1760:                 }
1761:               } else { //interior case
1762:                 if (c_hdepth != 0 || c_bound == 1) {
1763:                    canAdd = false;
1764:                    m->setValue(dompoint, v_point, c_point);
1765:                 } else {  //add the current inspected point to the list of points potentially dominated
1766:                   dominated_list.push_front(c_point);
1767:                   //if the dominating point is defined, test against it next.
1768:                   if (c_dominating_point != -1) {
1769:                     if (m->getValue(traversal, c_dominating_point) != 1) {
1770:                       comparison_list.push_front(c_dominating_point);
1771:                       traversed_list.push_front(c_dominating_point);
1772:                       m->setValue(traversal, c_dominating_point, 1);
1773:                     }
1774:                   }
1775:                 }
1776:               }
1777:             }
1778:             //add neighbors to the comparison queue
1779:             neighbors = sieve->cone(sieve->support(c_point));
1780:             n_iter = neighbors->begin();
1781:             n_iter_end = neighbors->end();
1782:             while (n_iter != n_iter_end) {
1783: 
1784:               n_point = *n_iter;
1785:               //PetscPrintf(m->comm(), "-%d\n", n_point);
1786:               n_traversal = m->getValue(traversal, n_point);

1788:               if (n_traversal != 1) {

1790:                 n_bound = m->getValue(boundary, n_point);

1792:                 if (c_bound == 1) { //boundary c_point case: only add boundary points
1793:                   if (n_bound == 1) {
1794:                     comparison_list.push_back(n_point);
1795:                     m->setValue(traversal, n_point, 1);
1796:                     traversed_list.push_front(n_point);
1797:                   }
1798:                 } else { //nonboundary c_point case: add anything
1799:                     comparison_list.push_back(n_point);
1800:                     m->setValue(traversal, n_point, 1);
1801:                     traversed_list.push_front(n_point);
1802:                 }
1803:               }

1805:               n_iter++;
1806:             }

1808:           }  // collision endif

1810:         }  // comparison traversal loop end

1812:         comparison_list.clear();

1814:         //clean up the traversal label
1815:         while (!traversed_list.empty()) {
1816:           n_point = traversed_list.front();
1817:           traversed_list.pop_front();
1818:           m->setValue(traversal, n_point, 0);
1819:         }

1821:         if (canAdd == true) {
1822:           //we can add the point, so put it at this level and set the points it dominates
1823:           m->setValue (hdepth, v_point, current_level);
1824:           dominated_list_iter = dominated_list.begin();
1825:           dominated_list_iter_end = dominated_list.end();
1826:           while (dominated_list_iter != dominated_list_iter_end) {
1827:             m->setValue(dompoint, *dominated_list_iter, v_point);
1828:             dominated_list_iter++;
1829:           }
1830:         }
1831:         dominated_list.clear();
1832:       }  // eligible for comparison endif
1833:       v_iter++;
1834:     } // vertices loop end
1835:     mesh_vertices_size += m->getLabelStratum("hierarchy_depth", current_level)->size();
1836:     PetscPrintf(m->comm(), "Size of mesh: %d\n", mesh_vertices_size);
1837:   } // levels loop end

1839:   return(0);
1840: }

1842: //MeshLocateInMesh: Create a label between the meshes.

1844: PetscErrorCode MeshLocateInMesh(Mesh finemesh, Mesh coarsemesh) {
1845:   ALE::Obj<PETSC_MESH_TYPE> fm, cm;
1848:   //int maxSearches = 30;
1849:   MeshGetMesh(finemesh, fm);
1850:   MeshGetMesh(coarsemesh, cm);

1852:   //set up the prolongation section if it doesn't already exist
1853:   //bool prolongexists = fm->hasLabel("prolongation");
1854:   const ALE::Obj<PETSC_MESH_TYPE::label_type>& prolongation = fm->createLabel("prolongation");

1856:   //we have a prolongation label that does not correspond to our current mesh.  Reset it to -1s.
1857:   const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& finevertices = fm->depthStratum(0);
1858:   PETSC_MESH_TYPE::label_sequence::iterator fv_iter = finevertices->begin();
1859:   PETSC_MESH_TYPE::label_sequence::iterator fv_iter_end = finevertices->end();

1861:   while (fv_iter != fv_iter_end) {
1862:     fm->setValue(prolongation, *fv_iter, -1);
1863:     fv_iter++;
1864:   }
1865:   //traversal labels on both layers
1866:   ALE::Obj<PETSC_MESH_TYPE::label_type> coarsetraversal = cm->createLabel("traversal");
1867:   const ALE::Obj<PETSC_MESH_TYPE::real_section_type>&  finecoordinates = fm->getRealSection("coordinates");
1868:   //const ALE::Obj<PETSC_MESH_TYPE::real_section_type>&  coarsecoordinates = cm->getRealSection("coordinates");
1869:   int dim = fm->getDimension();
1870:   //PetscPrintf(cm->comm(), "Dimensions: %d and %d\n", dim, cm->getDimension());
1871:   if (dim != cm->getDimension()) throw ALE::Exception("Dimensions of the fine and coarse meshes do not match");
1872:   //do the tandem traversal thing.  it is possible that if the section already existed then the locations of some of the points are known if they exist in both the meshes.
1873:   fv_iter = finevertices->begin();
1874:   fv_iter_end = finevertices->end();
1875:   const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& coarseelements = cm->heightStratum(0);
1876:   PETSC_MESH_TYPE::label_sequence::iterator ce_iter = coarseelements->begin();
1877:   PETSC_MESH_TYPE::label_sequence::iterator ce_iter_end = coarseelements->end();
1878:   double *fvCoords = new double[dim], *nvCoords = new double[dim];
1879:   std::list<PETSC_MESH_TYPE::point_type> travlist;  //store point
1880: //  std::list<PETSC_MESH_TYPE::point_type> travElist; //store element location "guesses"
1881:   std::list<PETSC_MESH_TYPE::point_type> eguesslist; // store the next guesses for the location of the current point.
1882:   while (fv_iter != fv_iter_end) {

1884:     //locate an initial point.
1885:     if (fm->getValue(prolongation, *fv_iter) == -1) {
1886:       ce_iter = coarseelements->begin();
1887:       ce_iter_end = coarseelements->end();
1888:       bool isLocated = false;
1889:       PetscMemcpy(fvCoords, finecoordinates->restrictPoint(*fv_iter), dim*sizeof(double));
1890:       while ((ce_iter != ce_iter_end) && (!isLocated)) {
1891:         if (PointIsInElement(cm, *ce_iter, fvCoords)) {
1892:           isLocated = true;
1893:           fm->setValue(prolongation, *fv_iter, *ce_iter);
1894:           //PetscPrintf(fm->comm(), "INITIAL: Point %d located in %d.\n",  *fv_iter, *ce_iter);
1895:           //OK WE HAVE A STARTING POINT.  Go through its neighbors looking at the unfound ones and finding them homes.
1896:           ALE::Obj<PETSC_MESH_TYPE::sieve_type::coneSet> neighbors = fm->getSieve()->cone(fm->getSieve()->support(*fv_iter));
1897:           PETSC_MESH_TYPE::sieve_type::coneSet::iterator n_iter = neighbors->begin();
1898:           PETSC_MESH_TYPE::sieve_type::coneSet::iterator n_iter_end = neighbors->end();
1899:           while (n_iter != n_iter_end) {
1900:             if (fm->getValue(prolongation, *n_iter) == -1) {
1901: //              travElist.push_front(*ce_iter);
1902:               travlist.push_back(*n_iter);
1903:               fm->setValue(prolongation, *n_iter, *ce_iter); //guess the next prolongation
1904:             }
1905:             n_iter++;
1906:           }

1908:           //do a DFS across the finemesh with BFSes on the coarse mesh for each point using assumed regularity of edgelength as a justification for guessing neighboring point's locations.
1909:           while (!travlist.empty()) {
1910:             PETSC_MESH_TYPE::point_type curVert = *travlist.begin();
1911:             PetscMemcpy(nvCoords, finecoordinates->restrictPoint(curVert), dim*sizeof(double));
1912:             PETSC_MESH_TYPE::point_type curEle =  fm->getValue(prolongation, curVert);
1913:             travlist.pop_front();
1914:             //travElist.pop_front();
1915:             eguesslist.push_front(curEle);
1916:             cm->setValue(coarsetraversal, curEle, 1);
1917:             bool locationDiscovered = false;
1918:             while ((!eguesslist.empty()) && (!locationDiscovered)) {
1919:               PETSC_MESH_TYPE::point_type curguess = *eguesslist.begin();
1920:               eguesslist.pop_front();
1921:               if (PointIsInElement(cm, curguess, nvCoords)) {
1922:                 locationDiscovered = true;
1923:                 //set the label.
1924:                 fm->setValue(prolongation, curVert, curguess);
1925:                 //PetscPrintf(fm->comm(), "Point %d located in %d.\n",  curVert, curguess);
1926:                 //stick its neighbors in the queue along with its location as a good guess of the location of its neighbors
1927:                 neighbors = fm->getSieve()->cone(fm->getSieve()->support(curVert));
1928:                 n_iter = neighbors->begin();
1929:                 n_iter_end = neighbors->end();
1930:                 while (n_iter != n_iter_end) {
1931:                   if (fm->getValue(prolongation, *n_iter) == -1) { //unlocated neighbor
1932:                     travlist.push_back(*n_iter);
1933:                     //travElist.push_front(curguess);
1934:                     fm->setValue(prolongation, *n_iter, curguess);
1935:                   }
1936:                   n_iter++;
1937:                 }
1938:               } else {
1939:               //add the current guesses neighbors to the comparison queue and start over.
1940:                 ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSet> curguessneighbors = cm->getSieve()->support(cm->getSieve()->cone(curguess));
1941:                 PETSC_MESH_TYPE::sieve_type::supportSet::iterator cgn_iter = curguessneighbors->begin();
1942:                 PETSC_MESH_TYPE::sieve_type::supportSet::iterator cgn_iter_end = curguessneighbors->end();
1943:                 while (cgn_iter != cgn_iter_end) {
1944:                   if (cm->getValue(coarsetraversal, *cgn_iter) != 1) {
1945:                     eguesslist.push_back(*cgn_iter);
1946:                     cm->setValue(coarsetraversal, *cgn_iter, 1);
1947:                   }
1948:                   cgn_iter++;
1949:                 }
1950:               }
1951:             }
1952:             if (!locationDiscovered) {
1953:               fm->setValue(prolongation, curVert, -2); //put it back in the list of orphans.
1954:               if(fm->debug())PetscPrintf(fm->comm(), "Point %d (%f, %f) not located.\n",  curVert, nvCoords[0], nvCoords[1]);
1955:             }
1956:             eguesslist.clear(); //we've discovered the location of the point or exhausted our possibilities on this contiguous block of elements.
1957:             //unset the traversed element list
1958:             ALE::Obj<PETSC_MESH_TYPE::label_sequence> traved_elements = cm->getLabelStratum("traversal", 1);
1959:             //PetscPrintf(cm->comm(), "%d\n", traved_elements->size());
1960:             PETSC_MESH_TYPE::label_sequence::iterator tp_iter = traved_elements->begin();
1961:             PETSC_MESH_TYPE::label_sequence::iterator tp_iter_end = traved_elements->end();
1962:             while (tp_iter != tp_iter_end) {
1963:               eguesslist.push_back(*tp_iter);
1964:               tp_iter++;
1965:             }
1966:             while (!eguesslist.empty()) {
1967:               cm->setValue(coarsetraversal, *eguesslist.begin(), 0);
1968:               eguesslist.pop_front();
1969:             }
1970:           }
1971:         }
1972:         ce_iter++;
1973:       }
1974:       if (!isLocated) {
1975:        fm->setValue(prolongation, *fv_iter, -2);
1976:       }
1977:     }
1978:    // printf("-");
1979:     fv_iter++;
1980:   }
1981:   delete [] fvCoords; delete [] nvCoords;
1982:   return(0);
1983: }

1985: bool PointIsInElement(ALE::Obj<PETSC_MESH_TYPE> mesh, PETSC_MESH_TYPE::point_type e, double * point) {
1986:       int dim = mesh->getDimension();
1987:       static double v0[3], J[9], invJ[9], detJ;
1988:       mesh->computeElementGeometry(mesh->getRealSection("coordinates"), e, v0, J, invJ, detJ);
1989:       if (dim == 2) {
1990:         double xi   = invJ[0*dim+0]*(point[0] - v0[0]) + invJ[0*dim+1]*(point[1] - v0[1]);
1991:         double eta  = invJ[1*dim+0]*(point[0] - v0[0]) + invJ[1*dim+1]*(point[1] - v0[1]);
1992:         //PetscPrintf(mesh->comm(), "Location Try: (%d) (%f, %f, %f)\n", e, xi, eta, xi + eta);
1993:         if ((xi >= -0.000001) && (eta >= -0.000001) && (xi + eta <= 2.000001)) {return true;
1994:         } else return false;
1995:       } else if (dim == 3) {
1996:         double xi   = invJ[0*dim+0]*(point[0] - v0[0]) + invJ[0*dim+1]*(point[1] - v0[1]) + invJ[0*dim+2]*(point[2] - v0[2]);
1997:         double eta  = invJ[1*dim+0]*(point[0] - v0[0]) + invJ[1*dim+1]*(point[1] - v0[1]) + invJ[1*dim+2]*(point[2] - v0[2]);
1998:         double zeta = invJ[2*dim+0]*(point[0] - v0[0]) + invJ[2*dim+1]*(point[1] - v0[1]) + invJ[2*dim+2]*(point[2] - v0[2]);

2000:         if ((xi >= -0.00000000001) && (eta >= -0.00000000001) && (zeta >= -0.00000000001) && (xi + eta + zeta <= 2.00000000001)) { return true;
2001:         } else return false;
2002:       } else throw ALE::Exception("Location only in 2D or 3D");
2003: /*      double coeffs[dim];
2004:       double sum = 0.;
2005:       for (int i = 0; i < dim; i++) {
2006:         coeffs[i] = 0.;
2007:         for (int j = 0; j < dim; j++) {
2008:           coeffs[i] += invJ[i*dim+j]*(point[j] - v0[j]);
2009:         }
2010:         sum += coeffs[i];
2011:       }
2012:       if (sum > 1.) return false;
2013:       for (int i = 0; i < dim; i++) {
2014:         if (coeffs[i] < 0.) return false;
2015:       }
2016:       return true; */
2017: }