Actual source code: MeshSurgery.hh
1: //routines for doing various pieces of mesh surgery
3: //Inputs: The mesh, a supportSet containing all the relevant cell names for the ear,
4: // and the former maxindex;
5: //Returns: the new maxindex.
8: namespace ALE {
10: /*
12: b
13: |
14: |-
15: | \ angle
16: | |
17: a------c
19: */
22: double corner_angle (int dim, double * a, double * b, double * c) {
24: // o is our origin point, p is one endpoint, q is the other; find their angle given the coordinates
25: double tmp_b = 0, tmp_c = 0, mag_b = 0, mag_c = 0, dot_product = 0, angle;
26: for (int i = 0; i < dim; i++) {
27: tmp_b = (a[i] - b[i]);
28: tmp_c = (a[i] - c[i]);
29: mag_b += tmp_b*tmp_b;
30: mag_c += tmp_c*tmp_c;
31: dot_product += tmp_b*tmp_c;
32: }
33: if (mag_b == 0 || mag_c == 0) return 0.;
34: angle = acos(dot_product/sqrt(mag_b*mag_c));
35: // PetscPrintf(PETSC_COMM_WORLD, "angle: %f\n", angle);
36: return angle;
37: }
39: /*
40: c
41: /|
42: n1 //
43: /\ /e|..
44: \ / / ..
45: a---b : <- angle
46: / \ \ ..
47: \/ \f|..
48: n2 \\
49: \|
50: d
51: */
53: double doublet_angle (int dim, double * a, double * b, double * c, double * d) {
54: if (dim != 3) return 0.;
55: const int nDim = 3;
56: double b_r[nDim], c_r[nDim], d_r[nDim], n1[nDim], n2[nDim], n1mag = 0, n2mag = 0, n1dotn2 = 0, angle;
57: for (int i = 0; i < dim; i++) {
58: b_r[i] = b[i] - a[i];
59: c_r[i] = c[i] - a[i];
60: d_r[i] = d[i] - a[i];
61: }
62: n1[0] = b_r[1]*c_r[2] - b_r[2]*c_r[1];
63: n1[1] = b_r[2]*c_r[0] - b_r[0]*c_r[2];
64: n1[2] = b_r[0]*c_r[1] - b_r[1]*c_r[0];
65: n2[0] = b_r[1]*d_r[2] - b_r[2]*d_r[1];
66: n2[1] = b_r[2]*d_r[0] - b_r[0]*d_r[2];
67: n2[2] = b_r[0]*d_r[1] - b_r[1]*d_r[0];
68: for (int i = 0; i < dim; i++) {
69: n1mag += n1[i]*n1[i];
70: n2mag += n2[i]*n2[i];
71: n1dotn2 += n1[i]*n2[i];
72: }
73: if (n1mag == 0. || n2mag == 0.) return 0;
74: angle = acos(fabs(n1dotn2)/sqrt(n1mag*n2mag));
75: return angle;
76: }
78: /*
79: ^
80: /|\
81: / | \
82: / | \ volume
83: / | \
84: /____|____\
87: */
89: double tetrahedron_volume (int dim, double * a, double * b, double * c, double * d) {
90: if (dim != 3) return 0.;
91: const int nDim = 3;
92: double x[nDim];
93: double y[nDim];
94: double z[nDim];
95: for (int i = 0; i < dim; i++) {
96: x[i] = b[i] - a[i];
97: y[i] = c[i] - a[i];
98: z[i] = d[i] - a[i];
99: }
100: double volume = x[0]*y[1]*z[2] + x[1]*y[2]*z[0] + x[2]*y[1]*z[2]
101: - x[0]*y[2]*z[1] - x[1]*y[0]*z[2] - x[2]*y[0]*z[1];
102: volume = volume / 2;
103: return fabs(volume);
104: }
108: //noninterpolated for now
110: /*
111: a a
112: /|\ / \
113: / | \ / \
114: / | \ / 1 \
115: / | \ / \
116: c 1 | 2 d -> c---------d
117: \ | / \ /
118: \ | / \ 2 /
119: \ | / \ /
120: \|/ \ /
121: b b
123: a = vertices[0];
124: b = vertices[1];
125: c = vertices[2];
126: d = vertices[3];
128: 1 = cells[0];
129: 2 = cells[1];
131: a = order[0];
132: b = order[1];
133: c = order[2];
135: a = order[3];
136: b = order[4];
137: d = order[5];
139: //NOTE: REWRITE TO BE ORDERED
141: */
144: void Surgery_2D_22Flip_Setup(Obj<Mesh> m, Mesh::point_type a, Mesh::point_type b, Mesh::point_type * cells, Mesh::point_type * vertices, int * order) {
145: //given a and b, set up the rest of the data structure needed for the 2-2 ear flip
146: vertices[0] = a;
147: vertices[1] = b;
148: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
149: line->clear();
150: line->insert(a);
151: line->insert(b);
152: Obj<Mesh::sieve_type::supportSet> doublet = m->getSieve()->nJoin1(line); //check to see if this works
153: //PetscPrintf(m->comm(), "%d in line, %d in doublet %d, %d\n", line->size(), doublet->size(), a, b);
154: if (doublet->size() != 2) throw Exception("bad flip setup 2-2"); //CHECK EXTERNALLY TO MAKE SURE WE'RE NOT FLIPPING ACROSS INTERIOR BOUND
155: Mesh::sieve_type::supportSet::iterator d_iter = doublet->begin();
156: cells[0] = *d_iter;
157: d_iter++;
158: cells[1] = *d_iter;
159: Obj<Mesh::sieve_type::coneSequence> corners = m->getSieve()->cone(cells[0]);
160: Mesh::sieve_type::coneSequence::iterator c_iter = corners->begin();
161: Mesh::sieve_type::coneSequence::iterator c_iter_end = corners->end();
162: int index = 0;
163: while (c_iter != c_iter_end) {
164: //PetscPrintf(m->comm(), "color: %d\n", c_iter.color());
165: if (*c_iter != a && *c_iter != b) {
166: vertices[2] = *c_iter;
167: order[2] = index;
168: } else if (*c_iter == a) {
169: order[0] = index;
170: } else {
171: order[1] = index;
172: }
173: c_iter++;
174: index++;
175: }
176: index = 0;
177: corners = m->getSieve()->cone(cells[1]);
178: c_iter = corners->begin();
179: c_iter_end = corners->end();
180: while (c_iter != c_iter_end) {
181: if (*c_iter != a && *c_iter != b) {
182: vertices[3] = *c_iter;
183: order[5] = index;
184: } else if (*c_iter == a) {
185: order[3] = index;
186: } else order[4] = index;
187: c_iter++;
188: index++;
189: }
190: //PetscPrintf(m->comm(), "2-2 Ear: %d %d %d %d, %d %d\n", vertices[0], vertices[1], vertices[2], vertices[3], cells[0], cells[1]);
191: return;
192: }
194: PetscTruth Surgery_2D_22Flip_Possible(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, int * order) {
195: const double pi = M_PI;
196: //VALIDITY CONDITION FOR THIS FLIP: cad and cbd must be (much) less than 180.
197: //we could probably have some angle heuristic for local delaunay approximation, but whatever.
198: //must compute it in terms of acb + bad etc.
199: int dim = m->getDimension();
200: //if (dim != 2) throw ALE::Exception("Wrong dimension");
201: const int nDim = 3;
202: double a_coords[nDim], b_coords[nDim], c_coords[nDim], d_coords[nDim];
203: const ALE::Obj<ALE::Mesh::real_section_type>& coordinates = m->getRealSection("coordinates");
204: PetscMemcpy(a_coords, coordinates->restrictPoint(vertices[0]), dim*sizeof(double));
205: PetscMemcpy(b_coords, coordinates->restrictPoint(vertices[1]), dim*sizeof(double));
206: PetscMemcpy(c_coords, coordinates->restrictPoint(vertices[2]), dim*sizeof(double));
207: PetscMemcpy(d_coords, coordinates->restrictPoint(vertices[3]), dim*sizeof(double));
208: double current_angle = corner_angle(dim, a_coords, c_coords, b_coords) + corner_angle(dim, a_coords, d_coords, b_coords);
209: //PetscPrintf(m->comm(), "%f angle\n", current_angle);
210: if (current_angle >= pi) return PETSC_FALSE; //give this vertex some "wiggle" as it's likely to just disappear anyways
211: current_angle = corner_angle(dim, b_coords, c_coords, a_coords) + corner_angle(dim, b_coords, d_coords, a_coords);
212: //PetscPrintf(m->comm(), "%f angle\n", current_angle);
213: if (current_angle >= pi) return PETSC_FALSE;
214: return PETSC_TRUE;
215: }
217: //if this flip improves the ratio between the maximum angle, do it
219: PetscTruth Surgery_2D_22Flip_Preferable(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, int * order) {
220: //does a BASIC test to see if this edge would do better flipped
221: //change of plan: ALWAYS chuck the maximum angle
222: //if abc + abd + bac + bad < cda + cdb + dca + dcb then flip (divide the larger angle)
223: const ALE::Obj<ALE::Mesh::real_section_type>& coordinates = m->getRealSection("coordinates");
224: int dim = m->getDimension();
225: //if (dim != 2) throw ALE::Exception("Wrong dimension");
226: const int nDim = 3;
227: double a_coords[nDim], b_coords[nDim], c_coords[nDim], d_coords[nDim];
228: PetscMemcpy(a_coords, coordinates->restrictPoint(vertices[0]), dim*sizeof(double));
229: PetscMemcpy(b_coords, coordinates->restrictPoint(vertices[1]), dim*sizeof(double));
230: PetscMemcpy(c_coords, coordinates->restrictPoint(vertices[2]), dim*sizeof(double));
231: PetscMemcpy(d_coords, coordinates->restrictPoint(vertices[3]), dim*sizeof(double));
232: double angle_a = corner_angle(dim, a_coords, b_coords, c_coords) + corner_angle(dim, a_coords, b_coords, d_coords);
233: double angle_b = corner_angle(dim, b_coords, a_coords, c_coords) + corner_angle(dim, b_coords, a_coords, d_coords);
234: double angle_c = corner_angle(dim, c_coords, d_coords, a_coords) + corner_angle(dim, c_coords, d_coords, b_coords);
235: double angle_d = corner_angle(dim, d_coords, c_coords, a_coords) + corner_angle(dim, d_coords, c_coords, b_coords);
236: //double ang_threshhold = M_PI - 0.01;
237: //if (angle_c > ang_threshhold && angle_a < ang_threshhold && angle_b < ang_threshhold) return PETSC_TRUE;
238: //if (angle_d > ang_threshhold && angle_a < ang_threshhold && angle_b < ang_threshhold) return PETSC_TRUE;
239: if (angle_a + angle_b < angle_c + angle_d){
240: return PETSC_TRUE;
241: }
242: return PETSC_FALSE;
243: }
245: int Surgery_2D_22Flip(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, int * order, Mesh::point_type maxIndex) {
246: //if (m->getDimension() != 2) {
247: // throw Exception("Wrong Flip Performed - Wrong ear or dimension");
248: //}
249: Obj<Mesh::sieve_type> s = m->getSieve();
250: //get the triangles
251: s->removeBasePoint(cells[0]);
252: s->removeCapPoint(cells[0]);
253: s->removeBasePoint(cells[1]);
254: s->removeCapPoint(cells[1]);
255: s->addArrow(vertices[3], cells[0]);
256: if (order[0] < order[2]) {
257: s->addArrow(vertices[0], cells[0]);
258: s->addArrow(vertices[2], cells[0]);
259: } else {
260: s->addArrow(vertices[2], cells[0]);
261: s->addArrow(vertices[0], cells[0]);
262: }
263: s->addArrow(vertices[2], cells[1]);
264: if (order[4] < order[5]) {
265: s->addArrow(vertices[1], cells[1]);
266: s->addArrow(vertices[3], cells[1]);
267: } else {
268: s->addArrow(vertices[3], cells[1]);
269: s->addArrow(vertices[1], cells[1]);
270: }
271: if (1) {
272: //TEST the validity of the flip
273: if (s->cone(cells[0])->size() != 3 || s->cone(cells[1])->size() != 3) throw Exception("Flip Failed -> 2->2");
274:
275: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
276: line->insert(vertices[0]);
277: line->insert(vertices[2]);
278: Obj<Mesh::sieve_type::supportSet> join = s->nJoin1(line);
279: if (join->size() > 2) {
280: throw Exception("ERROR: Bad edge: a -- c in 2-2 flip");
281: }
282: line->clear();
283: line->insert(vertices[0]);
284: line->insert(vertices[3]);
285: join = s->nJoin1(line);
286: if (join->size() > 2) {
287: throw Exception("Bad edge: a -- d in 2-2 flip");
288: }
289: line->clear();
290: line->insert(vertices[1]);
291: line->insert(vertices[2]);
292: join = s->nJoin1(line);
293: if (join->size() > 2) {
294: throw Exception("Bad edge: b -- c in 2-2 flip");
295: }
296: line->clear();
297: line->insert(vertices[1]);
298: line->insert(vertices[3]);
299: join = s->nJoin1(line);
300: if (join->size() > 2) {
301: throw Exception("Bad edge: b -- d in 2-2 flip");
302: }
303: line->clear();
304: line->insert(vertices[2]);
305: line->insert(vertices[3]);
306: join = s->nJoin1(line);
307: if (join->size() != 2) {
308: PetscPrintf(m->comm(), "join size(%d, %d): %d\n", vertices[2], vertices[3], join->size());
309: throw Exception("Bad edge: c -- d in 2-2 flip");
310: }
311: }
312: return maxIndex;
313: }
315: void Surgery_2D_22Flip_FixBoundary(Obj<Mesh> b_m, Mesh::point_type * cells, Mesh::point_type * vertices) {
316: //fixes up a boundary mesh if it's flipped across -- just remove anything in the njoin1
317: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
318: line->clear();
319: line->insert(vertices[0]);
320: line->insert(vertices[1]);
321: Obj<Mesh::sieve_type::supportSet> ab_join = b_m->getSieve()->nJoin1(line);
322: Mesh::sieve_type::supportSet::iterator ab_iter = ab_join->begin();
323: Mesh::sieve_type::supportSet::iterator ab_iter_end = ab_join->end();
324: while (ab_iter != ab_iter_end) {
325: b_m->getSieve()->removeBasePoint(*ab_iter);
326: ab_iter++;
327: }
328: }
330: /*
331: a---------------b a---------------b
332: \\ // \ /
333: \ \ 1 / / \ /
334: \ \ / / \ 1 /
335: \ d / -> \ /
336: \2 | 3/ \ /
337: \ | / \ /
338: \|/ \ /
339: c c
340: */
343: void Surgery_2D_31Flip_Setup(Obj<Mesh> m, Mesh::point_type d, Mesh::point_type * cells, Mesh::point_type * vertices) {
344: vertices[3] = d;
345: Obj<Mesh::sieve_type> s = m->getSieve();
346: Obj<Mesh::sieve_type::supportSequence> cell_points = s->support(d);
347: Mesh::sieve_type::supportSequence::iterator cp_iter = cell_points->begin();
348: Mesh::sieve_type::supportSequence::iterator cp_iter_end = cell_points->end();
349: Obj<Mesh::sieve_type::coneSet> vertex_points = s->cone(cell_points);
350: if (vertex_points->size() != 4) throw Exception("Bad vertex set in 3-1 flip");
351: cells[0] = *cp_iter;
352: cp_iter++;
353: cells[1] = *cp_iter;
354: cp_iter++;
355: cells[2] = *cp_iter;
356: Mesh::sieve_type::coneSet::iterator v_iter = vertex_points->begin();
357: Mesh::sieve_type::coneSet::iterator v_iter_end = vertex_points->end();
358: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
359: while (v_iter != v_iter_end) {
360: if (*v_iter != vertices[3]) {
361: line->clear();
362: line->insert(*v_iter);
363: line->insert(d);
364: Obj<Mesh::sieve_type::supportSet> join = s->nJoin1(line);
365: bool j_1 = (join->find(cells[0]) != join->end());
366: bool j_2 = (join->find(cells[1]) != join->end());
367: bool j_3 = (join->find(cells[2]) != join->end());
368: if (j_1 && j_2) { vertices[0] = *v_iter;
369: } else if (j_1 && j_3) { vertices[1] = *v_iter;
370: } else if (j_2 && j_3) { vertices[2] = *v_iter;
371: }
372: }
373: v_iter++;
374: }
375: //check the validity of what we just did
376: //PetscPrintf(m->comm(), "3-1 Flip: %d %d %d %d, %d %d %d\n", vertices[0], vertices[1], vertices[2], vertices[3], cells[0], cells[1], cells[2]);
377: }
379: PetscTruth Surgery_2D_31Flip_Possible(Obj<Mesh> m, Mesh::point_type * vertices, Mesh::point_type * cells) {
380: //VALIDITY CONDITION FOR THIS FLIP: acd, dcb, and acb MUST be (much) less than 180.
381: // BUT this should be essentially guaranteed and we don't need to test it
382: return PETSC_TRUE;
383: }
385: //EDIT: SEE IF THIS NOW PRESERVES ORDERINGS
386: int Surgery_2D_31Flip(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, Mesh::point_type maxIndex) {
387: Obj<Mesh::sieve_type> s = m->getSieve();
388: //s->removeBasePoint(cells[0]);
389: s->removeBasePoint(cells[1]);
390: s->removeBasePoint(cells[2]);
391: s->removeCapPoint(vertices[3]);
392: //s->addArrow(vertices[0], cells[0]);
393: //s->addArrow(vertices[1], cells[0]);
394: s->addArrow(vertices[2], cells[0]);
395: return maxIndex;
396: }
398: /*
400: EDIT: not using really
401: = c = a
402: a-----------b a-----------b
403: |\ /| |\ |
404: | \ 1 / | | \ |
405: | \ =2/ | | \ 1 |
406: | \ / | | \ |
407: | \ / | | \ |
408: | 2 e 3 | -> | \ |
409: | =4/ \ =1| | \ |
410: | / \ | | 2 \ |
411: | / \ | | \ |
412: | / 4 \ | | \ |
413: |/ =3 \| | \|
414: c-----------d c-----------d
415: = d = b
416: */
419: void Surgery_2D_42Flip_Setup(Obj<Mesh> m, Mesh::point_type e, Mesh::point_type * cells, Mesh::point_type * vertices) {
420: Obj<Mesh::sieve_type> s = m->getSieve();
421: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
422: Obj<Mesh::sieve_type::supportSequence> cell_points = s->support(e);
423: if (cell_points->size() != 4) {
424: PetscPrintf(m->comm(), "%d\n", cell_points->size());
425: throw Exception("Bad Ear 4-2");
426: }
427: Obj<Mesh::sieve_type::coneSet> vertex_points = s->cone(cell_points);
428: Mesh::sieve_type::supportSequence::iterator cp_iter = cell_points->begin();
429: vertices[4] = e;
430: cells[0] = *cp_iter;
431: Obj<Mesh::sieve_type::coneSequence> c_corners = s->cone(cells[0]);
432: if (c_corners->size() != 3) throw Exception("Bad Mesh in 4-2 flip");
433: Mesh::sieve_type::coneSequence::iterator cc_iter = c_corners->begin();
434: Mesh::sieve_type::coneSequence::iterator cc_iter_end = c_corners->end();
435: bool first = true;
436: //find a and b
437: while (cc_iter != cc_iter_end) {
438: if ((*cc_iter != e) && first) {
439: vertices[0] = *cc_iter;
440: first = false;
441: } else if (*cc_iter != e) {
442: vertices[1] = *cc_iter;
443: }
444: cc_iter++;
445: }
446: line->clear();
447: line->insert(vertices[0]);
448: line->insert(vertices[4]);
449: //PetscPrintf(m->comm(), "current line: %d, %d\n", vertices[0], vertices[4]);
450: Obj<Mesh::sieve_type::supportSet> join = s->nJoin1(line);
451: if (join->size() != 2) throw Exception("bad join in 4-2 flip");
452: Mesh::sieve_type::supportSet::iterator j_iter = join->begin();
453: //find 2
454: while (j_iter != join->end()) {
455: if (*j_iter != cells[0]) cells[1] = *j_iter;
456: j_iter++;
457: }
458: c_corners = s->cone(cells[1]);
459: cc_iter = c_corners->begin();
460: cc_iter_end = c_corners->end();
461: //find c
462: while (cc_iter != cc_iter_end) {
463: if (*cc_iter != vertices[0] && *cc_iter != e)vertices[2] = *cc_iter;
464: cc_iter++;
465: }
466: line->clear();
467: line->insert(vertices[1]);
468: line->insert(vertices[4]);
469: join = s->nJoin1(line);
470: if (join->size() != 2) throw Exception("bad join in 4-2 flip");
471: j_iter = join->begin();
472: //find 3;
473: while (j_iter != join->end()) {
474: if (*j_iter != cells[0]) cells[2] = *j_iter;
475: j_iter++;
476: }
477: c_corners = s->cone(cells[2]);
478: cc_iter = c_corners->begin();
479: cc_iter_end = c_corners->end();
480: //find d
481: while (cc_iter != cc_iter_end) {
482: if (*cc_iter != vertices[1] && *cc_iter != vertices[4])vertices[3] = *cc_iter;
483: cc_iter++;
484: }
485: //find 4
486: line->clear();
487: line->insert(vertices[2]);
488: line->insert(vertices[4]);
489: join = s->nJoin1(line);
490: j_iter = join->begin();
491: while (j_iter != join->end()) {
492: if (*j_iter != cells[1]) cells[3] = *j_iter;
493: j_iter++;
494: }
495: //for some reason this screws up... cp_iter might be incoherent at this point.
496: //while (cp_iter != cell_points->end()) {
497: // if (*cp_iter != cells[0] && *cp_iter != cells[1] && *cp_iter != cells[2]) cells[3] = *cp_iter;
498: // cp_iter++;
499: //}
500: //PetscPrintf(m->comm(), "Completed Ear: %d %d %d %d %d, %d %d %d %d\n", vertices[0], vertices[1], vertices[2], vertices[3], vertices[4],cells[0], cells[1], cells[2], cells[3]);
501: return;
502: }
505: PetscTruth Surgery_2D_42Flip_Possible(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices) {
506: //criterion for this flip:
507: // 1. bac and bdc must be < 180 degrees
508: // if this isn't true, we can reorient the flip here and make it true. (a four-sided figure may have one concave vertex)
509: // a->c b->a d->b c->d, 1->3, 3->4, 4->2, 2->1
510: double pi = M_PI;
511: // double pi = 3.141592653589793238;
512: int dim = m->getDimension();
513: //if (dim != 2) throw ALE::Exception("Wrong dimension");
514: const int nDim = 3;
515: double a_coords[nDim], b_coords[nDim], c_coords[nDim], d_coords[nDim], e_coords[nDim];
516: const Obj<Mesh::real_section_type>& coordinates = m->getRealSection("coordinates");
517: PetscMemcpy(a_coords, coordinates->restrictPoint(vertices[0]), dim*sizeof(double));
518: PetscMemcpy(b_coords, coordinates->restrictPoint(vertices[1]), dim*sizeof(double));
519: PetscMemcpy(c_coords, coordinates->restrictPoint(vertices[2]), dim*sizeof(double));
520: PetscMemcpy(d_coords, coordinates->restrictPoint(vertices[3]), dim*sizeof(double));
521: PetscMemcpy(e_coords, coordinates->restrictPoint(vertices[4]), dim*sizeof(double));
522: if (corner_angle(dim, a_coords, b_coords, e_coords) + corner_angle(dim, a_coords, c_coords, e_coords) >= pi ||
523: corner_angle(dim, d_coords, b_coords, e_coords) + corner_angle(dim, d_coords, c_coords, e_coords) >= pi) {
524: //rotate the ear
525: //PetscPrintf(m->comm(), "rotating the ear.\n");
526: Mesh::point_type temp_point = cells[0];
527: cells[0] = cells[1];
528: cells[1] = cells[3];
529: cells[3] = cells[2];
530: cells[2] = temp_point;
531: temp_point = vertices[0];
532: vertices[0] = vertices[2];
533: vertices[2] = vertices[3];
534: vertices[3] = vertices[1];
535: vertices[1] = temp_point;
536: //check the rotation
537: Obj<Mesh::sieve_type> s = m->getSieve();
538: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
539: Obj<Mesh::sieve_type::supportSet> join;
540: line->clear();
541: line->insert(vertices[4]);
542: line->insert(vertices[0]);
543: join = s->nJoin1(line);
544: if (join->find(cells[0]) == join->end() || join->find(cells[1]) == join->end() || join->size() != 2) {
545: PetscPrintf(m->comm(), "join(%d, %d) size: %d\n", vertices[0], vertices[4], join->size());
546: throw Exception("rotation. BAD");
547: }
548: line->clear();
549: line->insert(vertices[4]);
550: line->insert(vertices[1]);
551: join = s->nJoin1(line);
552: if (join->find(cells[0]) == join->end() || join->find(cells[2]) == join->end() || join->size() != 2) {
553: PetscPrintf(m->comm(), "join(%d, %d) size: %d\n", vertices[1], vertices[4], join->size());
554: throw Exception("rotation. BAD");
555: }
556: line->clear();
557: line->insert(vertices[4]);
558: line->insert(vertices[2]);
559: join = s->nJoin1(line);
560: if (join->find(cells[3]) == join->end() && join->find(cells[1]) == join->end() || join->size() != 2) {
561: PetscPrintf(m->comm(), "join(%d, %d) size: %d\n", vertices[2], vertices[4], join->size());
562: throw Exception("rotation. BAD");
563: }
564: line->clear();
565: line->insert(vertices[4]);
566: line->insert(vertices[3]);
567: join = s->nJoin1(line);
568: if (join->find(cells[2]) == join->end() && join->find(cells[3]) == join->end() || join->size() != 2) {
569: PetscPrintf(m->comm(), "join(%d, %d) size: %d\n", vertices[0], vertices[4], join->size());
570: throw Exception("rotation. BAD");
571: }
572: }
573: return PETSC_TRUE;
574: }
578: Mesh::point_type Surgery_2D_42Flip(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, ALE::Mesh::point_type maxIndex) {
579: Obj<Mesh::sieve_type> s = m->getSieve();
580: s->removeBasePoint(vertices[4]);
581: s->removeCapPoint(vertices[4]);
582: s->removeBasePoint(cells[2]);
583: s->removeCapPoint(cells[2]);
584: s->removeBasePoint(cells[3]);
585: s->removeCapPoint(cells[3]);
586: s->removeBasePoint(cells[0]);
587: s->removeCapPoint(cells[0]);
588: s->removeBasePoint(cells[1]);
589: s->removeCapPoint(cells[1]);
590: if (s->hasPoint(cells[2]) || s->hasPoint(cells[3])) throw Exception("problem in 4-2 flip: not deleting points!");
591: s->addArrow(vertices[0], cells[0]);
592: s->addArrow(vertices[3], cells[0]);
593: s->addArrow(vertices[1], cells[0]);
595: s->addArrow(vertices[0], cells[1]);
596: s->addArrow(vertices[3], cells[1]);
597: s->addArrow(vertices[2], cells[1]);
599: //check the coherence of the modified mesh
600: if (m->debug()) {
601: //PetscPrintf(m->comm(), "cone sizes: %d, %d", s->cone(cells[0])->size(), s->cone(cells[1])->size());
602: if (s->cone(cells[0])->size() != 3 || s->cone(cells[1])->size() != 3) throw Exception("problem in 4-2 flip: incoherent resulting mesh");
604: //check edges of the resultant 2-ear for coherency
605: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
606: line->insert(vertices[0]);
607: line->insert(vertices[1]);
608: Obj<Mesh::sieve_type::supportSet> join = s->nJoin1(line);
609: if (join->size() > 2) {
610: PetscPrintf(m->comm(), "Join Size: %d, a: %d, b: %d\n", join->size(), vertices[0], vertices[1]);
611: Mesh::sieve_type::supportSet::iterator jerr_iter = join->begin();
612: while (jerr_iter != join->end()) {
613: PetscPrintf(m->comm(), "Join Component: %d\n", *jerr_iter);
614: jerr_iter++;
615: }
616: throw Exception("ERROR: Bad edge: a -- b in 4-2 flip");
617: }
618: line->clear();
619: line->insert(vertices[0]);
620: line->insert(vertices[2]);
621: join = s->nJoin1(line);
622: if (join->size() > 2) {
623: PetscPrintf(m->comm(), "Join Size: %d, a: %d, c: %d\n", join->size(), vertices[0], vertices[2]);
624: Mesh::sieve_type::supportSet::iterator jerr_iter = join->begin();
625: while (jerr_iter != join->end()) {
626: PetscPrintf(m->comm(), "Join Component: %d\n", *jerr_iter);
627: jerr_iter++;
628: }
629: throw Exception("Bad edge: a -- c in 4-2 flip");
630: }
631: line->clear();
632: line->insert(vertices[1]);
633: line->insert(vertices[3]);
634: join = s->nJoin1(line);
635: if (join->size() > 2) {
636: PetscPrintf(m->comm(), "Join Size: %d, b: %d, c: %d\n", join->size(), vertices[1], vertices[3]);
637: Mesh::sieve_type::supportSet::iterator jerr_iter = join->begin();
638: while (jerr_iter != join->end()) {
639: PetscPrintf(m->comm(), "Join Component: %d\n", *jerr_iter);
640: jerr_iter++;
641: }
642: throw Exception("Bad edge: b -- d in 4-2 flip");
643: }
644: line->clear();
645: line->insert(vertices[2]);
646: line->insert(vertices[3]);
647: join = s->nJoin1(line);
648: if (join->size() > 2) {
649: PetscPrintf(m->comm(), "Join Size: %d, c: %d, d: %d\n", join->size(), vertices[2], vertices[3]);
650: Mesh::sieve_type::supportSet::iterator jerr_iter = join->begin();
651: while (jerr_iter != join->end()) {
652: PetscPrintf(m->comm(), "Join Component: %d\n", *jerr_iter);
653: jerr_iter++;
654: }
655: throw Exception("Bad edge: c -- d in 4-2 flip");
656: }
657: line->clear();
658: line->insert(vertices[0]);
659: line->insert(vertices[3]);
660: join = s->nJoin1(line);
661: if (join->size() != 2) {
662: PetscPrintf(m->comm(), "Join Size: %d, a: %d, d: %d\n", join->size(), vertices[0], vertices[3]);
663: Mesh::sieve_type::supportSet::iterator jerr_iter = join->begin();
664: while (jerr_iter != join->end()) {
665: PetscPrintf(m->comm(), "Join Component: %d\n", *jerr_iter);
666: jerr_iter++;
667: }
668: throw Exception("Bad edge: a -- d in 4-2 flip");
669: }
670: }
671: return maxIndex;
673: }
675: /*
676: f-----g f-----g
677: /\ /\ / _-'\
678: / \ / \ / _-' \
679: / \ / \ /_-' \
680: b------a------c -> b-------------c
681: \ / \ / \'-_ /
682: \ / \ / \ '-_ /
683: \/ \/ \ '-_/
684: d-----e d-----e
687: */
689: void Surgery_2D_LineContract_Setup(Obj<Mesh> m, Mesh::point_type a, Mesh::point_type b, Mesh::point_type * cells, Mesh::point_type * vertices) {
690: //Line contract is there to make it easier to have internal edges expressedly represented in 2D or 3D boundary meshes. One can have an arbitrary number of
691: //facets "circling" the line, and if they all have convex joins with respect to b, then the line may be shrunk from bac to bc with interior edges shunted over
692: //order does NOT matter, as the legitimacy test is done on the joins of each of the vertices involved; the cells are not going to be filled in.
693:
694: //JUST record a and b. The cone(support) of a will be used for the rest
695: vertices[0] = a;
696: vertices[1] = b;
697: }
699: //in the case where we have an interior vertex, we may have it find b such that it can contract from a (nearest-neighbor). The criterion should be the LARGEST angle
700: void Surgery_2D_LineContract_Direction(Obj<Mesh> m, Mesh::point_type a, Mesh::point_type * cells, Mesh::point_type * vertices) {
701: Obj<Mesh::real_section_type> coordinates = m->getRealSection("coordinates");
702: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
703: vertices[0] = a;
704: int dim = m->getDimension();
705: //if (dim != 2) throw ALE::Exception("Wrong dimension");
706: const int nDim = 3;
707: double v_coords[nDim], n_coords[nDim], e1_coords[nDim], e2_coords[nDim];
708: PetscMemcpy(v_coords, coordinates->restrictPoint(a), dim*sizeof(double));
709: //go through the neighbors of the vertex and find the nearest one
710: Obj<Mesh::sieve_type> s = m->getSieve();
711: Obj<Mesh::sieve_type::coneSet> neighbors = s->cone(s->support(a));
712: Mesh::sieve_type::coneSet::iterator n_iter = neighbors->begin();
713: Mesh::sieve_type::coneSet::iterator n_iter_end = neighbors->end();
714: Mesh::point_type p;
715: // bool first = true;
716: double p_angle = 0.0;
717: while (n_iter != n_iter_end) {
718: /*
719: if (*n_iter != a) {
720: const double * tmpcoords = coordinates->restrictPoint(*n_iter);
721: double dist = 0;
722: for (int i = 0; i < dim; i++) {
723: dist += (tmpcoords[i] - coords[i])*(tmpcoords[i] - coords[i]);
724: }
725: dist = sqrt(dist);
726: if (first) {
727: first = false;
728: p_dist = dist;
729: p = *n_iter;
730: } else {
731: if (dist < p_dist) { p_dist = dist;
732: p = *n_iter;
733: }
734: }
735: }
736: */
737: //treat each like a doublet, and find the maximum angle
738: if (*n_iter != a) {
739: PetscMemcpy(n_coords, coordinates->restrictPoint(*n_iter), dim*sizeof(double));
740: line->clear();
741: line->insert(*n_iter);
742: line->insert(vertices[0]);
743: Obj<Mesh::sieve_type::supportSet> join = s->nJoin1(line);
744: Obj<Mesh::sieve_type::coneSet> corners = s->cone(join);
745: Mesh::sieve_type::coneSet::iterator c_iter = corners->begin();
746: Mesh::sieve_type::coneSet::iterator c_iter_end = corners->end();
747: Mesh::point_type earpoints[2];
748: int index = 0;
749: while (c_iter != c_iter_end) {
750: if (*c_iter != vertices[0] && *c_iter != *n_iter) {
751: earpoints[index] = *c_iter;
752: index++;
753: }
754: c_iter++;
755: }
756: PetscMemcpy(e1_coords, coordinates->restrictPoint(earpoints[0]), dim*sizeof(double));
757: PetscMemcpy(e2_coords, coordinates->restrictPoint(earpoints[1]), dim*sizeof(double));
758: double cur_angle = corner_angle(dim, n_coords, v_coords, e1_coords) +
759: corner_angle(dim, n_coords, v_coords, e2_coords);
760: if (cur_angle > p_angle) {
761: p = *n_iter;
762: p_angle = cur_angle;
763: }
764: }
765: n_iter++;
766: }
767: vertices[1] = p;
768: return;
769: }
771: PetscTruth Surgery_2D_LineContract_Possible(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices) {
772: //for now this is last-ditch for 3D... do this to form the exterior and let tetgen deal with collisions
773: //TODO: Tetgen flakes out; fix this
774: return PETSC_TRUE;
775: }
777: Mesh::point_type Surgery_2D_LineContract(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, Mesh::point_type maxIndex) {
778: Obj<Mesh::sieve_type> s = m->getSieve();
779: Obj<Mesh::sieve_type::supportSequence> a_support = s->support(vertices[0]);
780: Mesh::sieve_type::supportSequence::iterator as_iter = a_support->begin();
781: Mesh::sieve_type::supportSequence::iterator as_iter_end = a_support->end();
782: Mesh::sieve_type::supportSet remove_elements;
783: while (as_iter != as_iter_end) {
784: //shrink every element to b
785: s->addArrow(vertices[1], *as_iter, as_iter.color());
786: if (s->cone(*as_iter)->size() != 4) remove_elements.insert(*as_iter);
787: as_iter++;
788: }
789: Mesh::sieve_type::supportSet::iterator re_iter = remove_elements.begin();
790: Mesh::sieve_type::supportSet::iterator re_iter_end = remove_elements.end();
791: while (re_iter != re_iter_end) {
792: s->removeBasePoint(*re_iter);
793: s->removeCapPoint(*re_iter);
794: re_iter++;
795: }
796: s->removeBasePoint(vertices[0]);
797: s->removeCapPoint(vertices[0]);
798: return maxIndex;
799: }
801: /*
803: exterior exterior
805: a------d------c a-------------c
806: \ | / \ /
807: \ 1 | 2 / \ 1 /
808: \ | / -> \ /
809: \ | / \ /
810: \ | / \ /
811: \|/ \ /
812: b b
813: */
815: void Surgery_2D_21BoundFlip_Setup(Obj<Mesh> m, Mesh::point_type d, Mesh::point_type * cells, Mesh::point_type * vertices) {
816: Obj<Mesh::sieve_type> s = m->getSieve();
817: vertices[3] = d;
818: Obj<Mesh::sieve_type::supportSequence> cell_points = s->support(d);
819: if (cell_points->size() != 2) throw Exception("Wrong flip (2->1 boundary)");
820: Mesh::sieve_type::supportSequence::iterator cp_iter= cell_points->begin();
821: cells[0] = *cp_iter;
822: cp_iter++;
823: cells[1] = *cp_iter;
824: Obj<Mesh::sieve_type::coneSet> cell_vertices = s->cone(cell_points);
825: Mesh::sieve_type::coneSet::iterator cv_iter = cell_vertices->begin();
826: Mesh::sieve_type::coneSet::iterator cv_iter_end = cell_vertices->end();
827: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
828: Obj<Mesh::sieve_type::supportSet> join;
829: while (cv_iter != cv_iter_end) {
830: if (*cv_iter != vertices[3]) {
831: line->clear();
832: line->insert(vertices[3]);
833: line->insert(*cv_iter);
834: join = s->nJoin1(line);
835: if (join->size() == 2) {
836: vertices[1] = *cv_iter;
837: } else if (join->find(cells[0]) != join->end()) {
838: vertices[0] = *cv_iter;
839: } else {
840: vertices[2] = *cv_iter;
841: }
842: }
843: cv_iter++;
844: }
845: //PetscPrintf(m->comm(), "Completed 2-1 ear: %d %d %d %d, %d %d\n", vertices[0], vertices[1], vertices[2], vertices[3], cells[0], cells[1]);
846: return;
847: }
849: PetscTruth Surgery_2D_21BoundFlip_Possible(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices) {
850: //criterion for this flip: abc must be convex, otherwise the interior point would be exposed
851: double pi = M_PI;
852: // double pi = 3.14159265359;
853: const Obj<Mesh::real_section_type>& coordinates = m->getRealSection("coordinates");
854: int dim = m->getDimension();
855: //if (dim != 2) throw ALE::Exception("Wrong dimension");
856: const int nDim = 3;
857: double coords_a[nDim], coords_b[nDim], coords_c[nDim], coords_d[nDim];
858: PetscMemcpy(coords_a, coordinates->restrictPoint(vertices[0]), dim*sizeof(double));
859: PetscMemcpy(coords_b, coordinates->restrictPoint(vertices[1]), dim*sizeof(double));
860: PetscMemcpy(coords_c, coordinates->restrictPoint(vertices[2]), dim*sizeof(double));
861: PetscMemcpy(coords_d, coordinates->restrictPoint(vertices[3]), dim*sizeof(double));
862: if (corner_angle(dim, coords_b, coords_a, coords_d) +
863: corner_angle(dim, coords_b, coords_c, coords_d) >= pi) return PETSC_FALSE;
864: return PETSC_TRUE;
865: }
867: Mesh::point_type Surgery_2D_21BoundFlip(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, Mesh::point_type maxIndex) {
868: Obj<Mesh::sieve_type> s = m->getSieve();
869: s->removeBasePoint(cells[1]);
870: s->removeBasePoint(cells[0]);
871: s->removeCapPoint(vertices[3]);
872: s->addArrow(vertices[2], cells[0]);
873: s->addArrow(vertices[1], cells[0]);
874: s->addArrow(vertices[0], cells[0]);
875: return maxIndex;
876: }
878: /*
880: interior interior
882: b-------------c b-------------c
883: \ /
884: \ /
885: \ / ->
886: \ /
887: \ /
888: \ /
889: a
890: */
893: void Surgery_2D_10BoundFlip_Setup(Obj<Mesh> m, Mesh::point_type a, Mesh::point_type * cells, Mesh::point_type * vertices) {
894: Obj<Mesh::sieve_type> s = m->getSieve();
895: vertices[0] = a;
896: Obj<Mesh::sieve_type::supportSequence> cell_points = s->support(a);
897: if (cell_points->size() != 1) throw Exception("Wrong flip performed (1->0 Boundary)");
898: cells[0] = *cell_points->begin();
899: }
901: PetscTruth Surgery_2D_10BoundFlip_Possible(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices) {
902: //no degenerate cases;
903: return PETSC_TRUE;
904: }
906: Mesh::point_type Surgery_2D_10BoundFlip(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, Mesh::point_type maxIndex) {
907: Obj<Mesh::sieve_type> s = m->getSieve();
908: s->removeCapPoint(vertices[0]);
909: s->removeBasePoint(cells[0]);
910: return maxIndex;
911: }
913: //Two interior tets to three
915: /*
916: d d
917: / \ /|\
918: / 1 \ / | \
919: / | \ / | \
920: / | \ / 2 \
921: b----a----c -> b1---a---3c
922: \ | / \ | /
923: \ | / \ | /
924: \ 2 / \ | /
925: \|/ \|/
926: e e
927: */
929: void Surgery_3D_23Flip_Setup(Obj<Mesh> m, Mesh::point_type a, Mesh::point_type b, Mesh::point_type c, Mesh::point_type * cells, Mesh::point_type * vertices) {
930: Obj<Mesh::sieve_type> s = m->getSieve();
931: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
932: Obj<Mesh::sieve_type::supportSet> join;
933: line->clear();
934: vertices[0] = a;
935: vertices[1] = b;
936: vertices[2] = c;
937: line->insert(a);
938: line->insert(b);
939: line->insert(c);
940: join = s->nJoin1(line);
941: if (join->size() != 2) {
942: throw Exception("Incoherent mesh in 23 flip");
943: }
944: Mesh::sieve_type::supportSet::iterator j_iter = join->begin();
945: cells[0] = *j_iter;
946: j_iter++;
947: cells[1] = *j_iter;
948: Obj<Mesh::sieve_type::coneSequence> corners = s->cone(cells[0]);
949: Mesh::sieve_type::coneSequence::iterator c_iter = corners->begin();
950: Mesh::sieve_type::coneSequence::iterator c_iter_end = corners->end();
951: while (c_iter != c_iter_end) {
952: if (*c_iter != a && *c_iter != b && *c_iter != c) {
953: vertices[3] = *c_iter;
954: }
955: c_iter++;
956: }
957: corners = s->cone(cells[1]);
958: c_iter = corners->begin();
959: c_iter_end = corners->end();
960: while (c_iter != c_iter_end) {
961: if (*c_iter != a && *c_iter != b && *c_iter != c) {
962: vertices[4] = *c_iter;
963: }
964: c_iter++;
965: }
966: // PetscPrintf(m->comm(), "2-3 Flip: %d %d, %d %d %d %d %d\n", cells[0], cells[1], vertices[0], vertices[1], vertices[2], vertices[3], vertices[4]);
967: return;
969: }
971: PetscTruth Surgery_3D_23Flip_Possible (Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices){
972: //The 2-3 flip is only possible if the line between a and d lies inside the volume; this occurs when, for example,
973: //volume(abde + bcde + cade) <== volume(abcd + abce)
974:
975: int dim = m->getDimension();
976: if (dim != 3) throw ALE::Exception("Wrong dimension");
977: const int nDim = 3;
978: //kill this thing cheaply if possible:
979: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
980: line->insert(vertices[3]);
981: line->insert(vertices[4]);
982: if (m->getSieve()->nJoin1(line)->size() != 0) return PETSC_FALSE;
983: const Obj<Mesh::real_section_type> coordinates = m->getRealSection("coordinates");
984: double a_coords[nDim], b_coords[nDim], c_coords[nDim], d_coords[nDim], e_coords[nDim];
985: PetscMemcpy(a_coords, coordinates->restrictPoint(vertices[0]), dim*sizeof(double));
986: PetscMemcpy(b_coords, coordinates->restrictPoint(vertices[1]), dim*sizeof(double));
987: PetscMemcpy(c_coords, coordinates->restrictPoint(vertices[2]), dim*sizeof(double));
988: PetscMemcpy(d_coords, coordinates->restrictPoint(vertices[3]), dim*sizeof(double));
989: PetscMemcpy(e_coords, coordinates->restrictPoint(vertices[4]), dim*sizeof(double));
990: double volume_1 = tetrahedron_volume(dim, a_coords, b_coords, d_coords, e_coords);
991: double volume_2 = tetrahedron_volume(dim, b_coords, c_coords, d_coords, e_coords);
992: double volume_3 = tetrahedron_volume(dim, c_coords, a_coords, d_coords, e_coords);
993: double now_volume = tetrahedron_volume(dim, a_coords, b_coords, c_coords, d_coords)
994: + tetrahedron_volume(dim, a_coords, b_coords, c_coords, e_coords);
995: if ((volume_1 + volume_2 > now_volume)
996: || (volume_2 + volume_3 > now_volume)
997: || (volume_3 + volume_1 > now_volume)) return PETSC_FALSE;
998: return PETSC_TRUE;
999: }
1001: Mesh::point_type Surgery_3D_23Flip(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, Mesh::point_type maxIndex) {
1002: Mesh::point_type newCell = maxIndex+1;
1003: Obj<Mesh::sieve_type> s = m->getSieve();
1005: s->removeBasePoint(cells[0]);
1006: s->removeBasePoint(cells[1]);
1008: //check to make sure that there is currently not a join between the two endpoints of this;
1009: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
1010: line->insert(vertices[3]);
1011: line->insert(vertices[4]);
1012: if (s->nJoin1(line)->size() != 0) {
1013: throw Exception("line already exists for some reason!");
1014: }
1015: s->addArrow(vertices[0], cells[0]);
1016: s->addArrow(vertices[1], cells[0]);
1017: s->addArrow(vertices[3], cells[0]);
1018: s->addArrow(vertices[4], cells[0]);
1020: s->addArrow(vertices[1], cells[1]);
1021: s->addArrow(vertices[2], cells[1]);
1022: s->addArrow(vertices[3], cells[1]);
1023: s->addArrow(vertices[4], cells[1]);
1025: s->addArrow(vertices[2], newCell);
1026: s->addArrow(vertices[0], newCell);
1027: s->addArrow(vertices[3], newCell);
1028: s->addArrow(vertices[4], newCell);
1030: if (m->debug()) {
1031:
1032: //debug time
1033: int cone1_size = s->cone(cells[0])->size();
1034: int cone2_size = s->cone(cells[1])->size();
1035: int cone3_size = s->cone(newCell)->size();
1036: if (cone1_size != 4 || cone2_size != 4 || cone3_size != 4) {
1037: PetscPrintf(m->comm(), "involved vertices %d, %d, %d, %d, %d\n", vertices[0], vertices[1], vertices[2], vertices[3], vertices[4]);
1038: PetscPrintf(m->comm(), "cone sizes %d, %d, %d\n", cone1_size, cone2_size, cone3_size);
1039: throw Exception("Flip sizes screwed up");
1040: }
1041: Obj<Mesh::sieve_type::supportSet> lens;
1042: line->clear();
1043: line->insert(vertices[3]);
1044: line->insert(vertices[4]);
1045: lens = s->nJoin1(line);
1046: int lens_size = lens->size();
1047: if (lens_size != 3) {
1048: PetscPrintf(m->comm(), "Resulting Lens Size of line %d %d: %d\n", vertices[3], vertices[4], lens_size);
1049: Mesh::sieve_type::supportSet::iterator ls_iter = lens->begin();
1050: Mesh::sieve_type::supportSet::iterator ls_iter_end = lens->end();
1051: for (; ls_iter != ls_iter_end; ls_iter++) {
1052: PetscPrintf(m->comm(), "%d: ", *ls_iter);
1053: Obj<Mesh::sieve_type::coneSequence> error_cone = s->cone(*ls_iter);
1054: Mesh::sieve_type::coneSequence::iterator ec_iter = error_cone->begin();
1055: Mesh::sieve_type::coneSequence::iterator ec_iter_end = error_cone->end();
1056: while (ec_iter != ec_iter_end) {
1057: PetscPrintf(m->comm(), "%d ", *ec_iter);
1058: ec_iter++;
1059: }
1060: PetscPrintf(m->comm(), "\n");
1061: }
1062: PetscPrintf(m->comm(), "\n");
1063: throw Exception("Flip interior line screwed up");
1064: }
1065: //check interior edges
1066: line->clear();
1067: line->insert(vertices[3]);
1068: line->insert(vertices[4]);
1069: line->insert(vertices[1]);
1070: lens = s->nJoin1(line);
1071: if (lens->size() != 2) {
1072: PetscPrintf(m->comm(), "face: %d %d %d has %d sides\n", vertices[3], vertices[4], vertices[1], lens->size());
1073: throw Exception("2-3 flip: bad interior face");
1074: }
1075: line->clear();
1076: line->insert(vertices[3]);
1077: line->insert(vertices[4]);
1078: line->insert(vertices[2]);
1079: lens = s->nJoin1(line);
1080: if (lens->size() != 2) {
1081: PetscPrintf(m->comm(), "face: %d %d %d has %d sides\n", vertices[3], vertices[4], vertices[2], lens->size());
1082: throw Exception("2-3 flip: bad interior face");
1083: }
1084: line->clear();
1085: line->insert(vertices[3]);
1086: line->insert(vertices[4]);
1087: line->insert(vertices[0]);
1088: lens = s->nJoin1(line);
1089: if (lens->size() != 2) {
1090: PetscPrintf(m->comm(), "face: %d %d %d has %d sides\n", vertices[3], vertices[4], vertices[0], lens->size());
1091: throw Exception("2-3 flip: bad interior face");
1092: }
1093: line->clear();
1094: line->insert(vertices[3]);
1095: line->insert(vertices[0]);
1096: line->insert(vertices[1]);
1097: if (s->nJoin1(line)->size() > 2) {
1098: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[3], vertices[0], vertices[1], s->nJoin1(line)->size());
1099: throw Exception("Bad face Created in 2-3 flip");
1100: }
1101: line->clear();
1102: line->insert(vertices[3]);
1103: line->insert(vertices[1]);
1104: line->insert(vertices[2]);
1105: if (s->nJoin1(line)->size() > 2) {
1106: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[3], vertices[1], vertices[2], s->nJoin1(line)->size());
1107: throw Exception("Bad face Created in 2-3 flip");
1108: }
1109: line->clear();
1110: line->insert(vertices[3]);
1111: line->insert(vertices[2]);
1112: line->insert(vertices[0]);
1113: if (s->nJoin1(line)->size() > 2) {
1114: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[3], vertices[2], vertices[0], s->nJoin1(line)->size());
1115: throw Exception("Bad face Created in 2-3 flip");
1116: } line->clear();
1117: line->insert(vertices[4]);
1118: line->insert(vertices[0]);
1119: line->insert(vertices[1]);
1120: if (s->nJoin1(line)->size() > 2) {
1121: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[4], vertices[0], vertices[1], s->nJoin1(line)->size());
1122: throw Exception("Bad face Created in 2-3 flip");
1123: }
1124: line->clear();
1125: line->insert(vertices[4]);
1126: line->insert(vertices[1]);
1127: line->insert(vertices[2]);
1128: if (s->nJoin1(line)->size() > 2) {
1129: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[4], vertices[1], vertices[2], s->nJoin1(line)->size());
1130: throw Exception("Bad face Created in 2-3 flip");
1131: }
1132: line->clear();
1133: line->insert(vertices[4]);
1134: line->insert(vertices[2]);
1135: line->insert(vertices[0]);
1136: if (s->nJoin1(line)->size() > 2) {
1137: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[0], vertices[4], vertices[2], s->nJoin1(line)->size());
1138: throw Exception("Bad face Created in 2-3 flip");
1139: }
1140: }
1141: return newCell;
1142: }
1145: //Three interior tets to two
1147: /*
1148: a a
1149: /|\ /|\
1150: / | \ / | \
1151: / | \ / 1 \
1152: / d \ / | \
1153: c1---2---3e -> c----d----e
1154: \ | / \ | /
1155: \ | / \ 2 /
1156: \ | / \ | /
1157: \|/ \|/
1158: b b
1159: */
1162: void Surgery_3D_32Flip_Setup (Obj<Mesh> m, Mesh::point_type a, Mesh::point_type b, Mesh::point_type * cells, Mesh::point_type * vertices) {
1163: Obj<Mesh::sieve_type> s = m->getSieve();
1164: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
1165: vertices[0] = a;
1166: vertices[1] = b;
1167: line->clear();
1168: line->insert(a);
1169: line->insert(b);
1170: Obj<Mesh::sieve_type::supportSet> join = s->nJoin1(line);
1171: if (join->size() != 3) throw Exception("Wrong flip: 3-2");
1172: Mesh::sieve_type::supportSet::iterator j_iter = join->begin();
1173: cells[0] = *j_iter;
1174: j_iter++;
1175: cells[1] = *j_iter;
1176: j_iter++;
1177: cells[2] = *j_iter;
1178: Obj<Mesh::sieve_type::coneSequence> corners = s->cone(cells[0]);
1179: if (corners->size() != 4) throw Exception("bad element: 3-2");
1180: Mesh::sieve_type::coneSequence::iterator c_iter = corners->begin();
1181: Mesh::sieve_type::coneSequence::iterator c_iter_end = corners->end();
1182: bool first = true;
1183: Mesh::point_type p;
1184: while (c_iter != c_iter_end) {
1185: p = *c_iter;
1186: if (p != a && p != b) {
1187: if (first) {
1188: vertices[2] = p;
1189: first = false;
1190: } else {
1191: vertices[3] = p;
1192: }
1193: }
1194: c_iter++;
1195: }
1196: corners = s->cone(cells[1]);
1197: if (corners->size() != 4) throw Exception("bad element: 3-2");
1198: c_iter = corners->begin();
1199: c_iter_end = corners->end();
1200: while (c_iter != c_iter_end) {
1201: p = *c_iter;
1202: if (p == vertices[3]) { //we've got 2 instead of 1.
1203: Mesh::point_type swap = cells[1];
1204: cells[1] = cells[2];
1205: cells[2] = swap;
1206: }
1207: if (p != a && p != b && p != vertices[2] && p != vertices[3]) {
1208: vertices[4] = p;
1209: }
1210: c_iter++;
1211: }
1212: // PetscPrintf(m->comm(), "3-2 Flip: %d %d %d, %d %d %d %d %d\n", cells[0], cells[1], cells[2], vertices[0], vertices[1], vertices[2], vertices[3], vertices[4]);
1213: }
1214: PetscTruth Surgery_3D_32Flip_Possible (Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices){
1215: //The 3-2 flip is only possible if each new subvolume will have volume less than the previous three combined (convex)
1216: int dim = m->getDimension();
1217: if (dim != 3) throw ALE::Exception("Wrong dimension");
1218: const int nDim = 3;
1219: const Obj<Mesh::real_section_type> coordinates = m->getRealSection("coordinates");
1220: double a_coords[nDim], b_coords[nDim], c_coords[nDim], d_coords[nDim], e_coords[nDim];
1221: PetscMemcpy(a_coords, coordinates->restrictPoint(vertices[0]), dim*sizeof(double));
1222: PetscMemcpy(b_coords, coordinates->restrictPoint(vertices[1]), dim*sizeof(double));
1223: PetscMemcpy(c_coords, coordinates->restrictPoint(vertices[2]), dim*sizeof(double));
1224: PetscMemcpy(d_coords, coordinates->restrictPoint(vertices[3]), dim*sizeof(double));
1225: PetscMemcpy(e_coords, coordinates->restrictPoint(vertices[4]), dim*sizeof(double));
1226: double cur_volume = tetrahedron_volume(dim, a_coords, b_coords, c_coords, d_coords) +
1227: tetrahedron_volume(dim, a_coords, b_coords, d_coords, e_coords) +
1228: tetrahedron_volume(dim, a_coords, b_coords, e_coords, c_coords);
1229: double volume_1 = tetrahedron_volume(dim, a_coords, c_coords, d_coords, e_coords);
1230: double volume_2 = tetrahedron_volume(dim, b_coords, c_coords, d_coords, e_coords);
1231: if (volume_1 > cur_volume) return PETSC_FALSE;
1232: if (volume_2 > cur_volume) return PETSC_FALSE;
1233: return PETSC_TRUE;
1234: }
1236: Mesh::point_type Surgery_3D_32Flip(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, ALE::Mesh::point_type maxIndex) {
1237: Obj<Mesh::sieve_type> s = m->getSieve();
1238: s->removeBasePoint(cells[0]);
1239: s->removeBasePoint(cells[1]);
1240: s->removeBasePoint(cells[2]);
1242: Obj<Mesh::sieve_type::supportSet> line;
1244: if (m->debug()) {
1246: line = new Mesh::sieve_type::supportSet();
1247: line->clear();
1248: line->insert(vertices[2]);
1249: line->insert(vertices[3]);
1250: line->insert(vertices[4]);
1251: Obj<Mesh::sieve_type::supportSet> doublet = s->nJoin1(line);
1252: if (doublet->size() != 0) {
1253: PetscPrintf(m->comm(), "doublet size: %d\n", doublet->size());
1254: throw Exception("face already occupied in 3-2 flip");
1255: }
1257: }
1258:
1259: s->addArrow(vertices[0], cells[0]);
1260: s->addArrow(vertices[2], cells[0]);
1261: s->addArrow(vertices[3], cells[0]);
1262: s->addArrow(vertices[4], cells[0]);
1264: s->addArrow(vertices[1], cells[1]);
1265: s->addArrow(vertices[2], cells[1]);
1266: s->addArrow(vertices[3], cells[1]);
1267: s->addArrow(vertices[4], cells[1]);
1268: if (m->debug()) {
1269: //error checking;
1270: int cone1_size = s->cone(cells[0])->size();
1271: int cone2_size = s->cone(cells[1])->size();
1272: if (cone1_size != 4 || cone2_size != 4) {
1273: PetscPrintf(m->comm(), "Cone Sizes, %d, %d\n", cone1_size, cone2_size);
1274: throw Exception("Screwed up 3-2 flip");
1275: }
1276: line->clear();
1277: line->insert(vertices[2]);
1278: line->insert(vertices[3]);
1279: line->insert(vertices[4]);
1280: if (s->nJoin1(line)->size() != 2) {
1281: PetscPrintf(m->comm(), "Lens Size: %d\n", s->nJoin1(line)->size());
1282: throw Exception("Bad Lens Created in 3-2 flip");
1283: }
1284: //check the consistency of the resulting suspension exterior faces;
1285: line->clear();
1286: line->insert(vertices[0]);
1287: line->insert(vertices[2]);
1288: line->insert(vertices[3]);
1289: if (s->nJoin1(line)->size() > 2) {
1290: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[0], vertices[2], vertices[3], s->nJoin1(line)->size());
1291: throw Exception("Bad Lens Created in 3-2 flip");
1292: }
1293: line->clear();
1294: line->insert(vertices[0]);
1295: line->insert(vertices[3]);
1296: line->insert(vertices[4]);
1297: if (s->nJoin1(line)->size() > 2) {
1298: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[0], vertices[3], vertices[4], s->nJoin1(line)->size());
1299: throw Exception("Bad Lens Created in 3-2 flip");
1300: }
1301: line->clear();
1302: line->insert(vertices[0]);
1303: line->insert(vertices[4]);
1304: line->insert(vertices[2]);
1305: if (s->nJoin1(line)->size() > 2) {
1306: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[0], vertices[4], vertices[2], s->nJoin1(line)->size());
1307: throw Exception("Bad Lens Created in 3-2 flip");
1308: }
1309: line->clear();
1310: line->insert(vertices[1]);
1311: line->insert(vertices[2]);
1312: line->insert(vertices[3]);
1313: if (s->nJoin1(line)->size() > 2) {
1314: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[1], vertices[2], vertices[3], s->nJoin1(line)->size());
1315: throw Exception("Bad Lens Created in 3-2 flip");
1316: }
1317: line->clear();
1318: line->insert(vertices[1]);
1319: line->insert(vertices[3]);
1320: line->insert(vertices[4]);
1321: if (s->nJoin1(line)->size() > 2) {
1322: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[1], vertices[3], vertices[4], s->nJoin1(line)->size());
1323: throw Exception("Bad Lens Created in 3-2 flip");
1324: }
1325: line->clear();
1326: line->insert(vertices[1]);
1327: line->insert(vertices[4]);
1328: line->insert(vertices[2]);
1329: if (s->nJoin1(line)->size() > 2) {
1330: PetscPrintf(m->comm(), "Exterior doublet (%d %d %d) Size: %d\n", vertices[1], vertices[4], vertices[2], s->nJoin1(line)->size());
1331: throw Exception("Bad Lens Created in 3-2 flip");
1332: }
1333: }
1334: return maxIndex;
1335: }
1337: //Four interior tets to four, on the line
1340: /*
1341: a a
1342: /|\ /|\
1343: / | \ / | \
1344: /1 | 2\ / 1 \
1345: / |f \ / |f \
1346: b----e----d -> b----e----d
1347: \ | / \ | /
1348: \3 | 4/ \ | /
1349: \ | / \ 2 /
1350: \|/ \|/
1351: c c
1352: */
1354: int Surgery_3D_44Flip(Obj<Mesh>, Obj<Mesh::sieve_type> ear, ALE::Mesh::point_type maxIndex) {
1356: return 0;
1358: }
1360: //Four interior tets get collapsed into a single tet.
1362: /* d d
1363: a---------------b b---------------a
1364: \\ 2 // \ /
1365: \ \ / / \ /
1366: \ \ 1 / / \ 1 /
1367: \ 4 e 3 / -> \ /
1368: \ | / \ /
1369: \ | / \ /
1370: \|/ \ /
1371: c c
1372: */
1375: void Surgery_3D_41Flip_Setup(Obj<Mesh> m, Mesh::point_type e, Mesh::point_type * cells, Mesh::point_type * vertices) {
1376: Obj<Mesh::sieve_type> s = m->getSieve();
1377: Obj<Mesh::sieve_type::supportSequence> cell_points = s->support(e);
1378: vertices[4] = e;
1379: if (cell_points->size() != 4) throw Exception("Wrong flip: 4-1");
1380: cells[0] = *cell_points->begin();
1381: Obj<Mesh::sieve_type::coneSequence> corners = s->cone(cells[0]);
1382: Mesh::sieve_type::coneSequence::iterator c_iter = corners->begin();
1383: Mesh::sieve_type::coneSequence::iterator c_iter_end = corners->end();
1384: //name the first three vertices
1385: int index = 0;
1386: while (c_iter != c_iter_end) {
1387: if (*c_iter != e) {
1388: vertices[index] = *c_iter;
1389: index++;
1390: }
1391: c_iter++;
1392: }
1393: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
1394: line->clear();
1395: //build the face between
1396: line->insert(vertices[4]);
1397: line->insert(vertices[0]);
1398: line->insert(vertices[1]);
1399: Obj<Mesh::sieve_type::supportSet> join = s->nJoin1(line);
1400: Mesh::sieve_type::supportSet::iterator j_iter = join->begin();
1401: Mesh::sieve_type::supportSet::iterator j_iter_end = join->end();
1402: if (join->size() != 2) throw Exception("4-1 flip: bad join");
1403: while (j_iter != j_iter_end) {
1404: if (*j_iter != cells[0]) cells[1] = *j_iter;
1405: j_iter++;
1406: }
1407: line->clear();
1408: line->insert(vertices[4]);
1409: line->insert(vertices[1]);
1410: line->insert(vertices[2]);
1411: join = s->nJoin1(line);
1412: if (join->size() != 2) throw Exception("4-1 flip: bad join");
1413: j_iter = join->begin();
1414: j_iter_end = join->end();
1415: while (j_iter != j_iter_end) {
1416: if (*j_iter != cells[0]) cells[2] = *j_iter;
1417: j_iter++;
1418: }
1419: line->clear();
1420: line->insert(vertices[4]);
1421: line->insert(vertices[2]);
1422: line->insert(vertices[0]);
1423: join = s->nJoin1(line);
1424: if (join->size() != 2) throw Exception("4-1 flip: bad join");
1425: j_iter = join->begin();
1426: j_iter_end = join->end();
1427: while (j_iter != j_iter_end) {
1428: if (*j_iter != cells[0]) cells[3] = *j_iter;
1429: j_iter++;
1430: }
1431: //find d
1432: corners = s->cone(cells[1]);
1433: c_iter = corners->begin();
1434: c_iter_end = corners->end();
1435: while (c_iter != c_iter_end) {
1436: Mesh::point_type p = *c_iter;
1437: if (p != vertices[0] && p != vertices[1] && vertices[2] && p != vertices[4]) vertices[3] = p;
1438: c_iter++;
1439: }
1440: return;
1441: }
1443: PetscTruth Surgery_3D_41Flip_Possible(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices) {
1444: //criteria have to be true if we've gotten this far;
1445: return PETSC_TRUE;
1446: }
1448: Mesh::point_type Surgery_3D_41Flip(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, Mesh::point_type maxIndex) {
1450: Obj<Mesh::sieve_type> s = m->getSieve();
1451: s->removeBasePoint(cells[0]);
1452: s->removeBasePoint(cells[1]);
1453: s->removeBasePoint(cells[2]);
1454: s->removeBasePoint(cells[3]);
1455:
1456: s->addArrow(vertices[0], cells[0]);
1457: s->addArrow(vertices[1], cells[0]);
1458: s->addArrow(vertices[2], cells[0]);
1459: s->addArrow(vertices[3], cells[0]);
1460: return maxIndex;
1461: }
1465: //just like the 4-1 except one of the 4 is missing. (make the one of the four missing the one involving b, c, d)
1467: /* _e_ exterior
1468: _-' | '-_
1469: _-' | '-_
1470: b-------a-------c b-------a-------c
1471: \ | / \ | /
1472: \ 1| / \ | /
1473: \ | / \ 1 /
1474: \ 2 e 3 / -> \ | /
1475: \ | / \ | /
1476: \ | / \ | /
1477: \|/ \|/
1478: d d
1479: */
1481: void Surgery_3D_31BoundFlip_Setup(Obj<Mesh> m, Mesh::point_type e, Mesh::point_type * cells, Mesh::point_type * vertices) {
1482: vertices[4] = e;
1483: Obj<Mesh::sieve_type> s = m->getSieve();
1484: Obj<Mesh::sieve_type::supportSequence> cell_points = s->support(e);
1485: if (cell_points->size() != 3) throw Exception("wrong flip: 3-1 Boundary flip");
1486: Mesh::sieve_type::supportSequence::iterator cp_iter = cell_points->begin();
1487: cells[0] = *cp_iter;
1488: cp_iter++;
1489: cells[1] = *cp_iter;
1490: cp_iter++;
1491: cells[2] = *cp_iter;
1492: Obj<Mesh::sieve_type::coneSet> vertex_points = s->support(cell_points);
1493: if (vertex_points->size() != 5) throw Exception("Erroneous Flip: 3-1 Boundary flip");
1494: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
1495: Obj<Mesh::sieve_type::supportSet> link;
1496: Mesh::sieve_type::coneSet::iterator vp_iter = vertex_points->begin();
1497: Mesh::sieve_type::coneSet::iterator vp_iter_end = vertex_points->end();
1498: while (vp_iter != vp_iter_end) {
1499: if (*vp_iter != e) {
1500: line->clear();
1501: line->insert(e);
1502: line->insert(*vp_iter);
1503: link = s->nJoin1(line);
1504: if (link->size() == 3) {
1505: vertices[0] = *vp_iter;
1506: } else {
1507: Mesh::sieve_type::supportSet::iterator l_end = link->end();
1508: bool link_has_1 = (link->find(cells[0]) != l_end);
1509: bool link_has_2 = (link->find(cells[1]) != l_end);
1510: bool link_has_3 = (link->find(cells[3]) != l_end);
1511: if (link_has_1 && link_has_2) {
1512: vertices[1] = *vp_iter;
1513: } else if (link_has_2 && link_has_3) {
1514: vertices[2] = *vp_iter;
1515: } else if (link_has_3 && link_has_1) {
1516: vertices[3] = *vp_iter;
1517: } else {
1518: throw Exception("Flip Error: Boundflip 3-1");
1519: }
1520: }
1521: }
1522: vp_iter++;
1523: }
1524: return;
1525: }
1527: PetscTruth Surgery_3D_31BoundFlip_Possible(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices) {
1528: int dim = m->getDimension();
1529: if (dim != 3) throw ALE::Exception("Wrong dimension");
1530: const int nDim = 3;
1531: const Obj<Mesh::real_section_type>& coordinates = m->getRealSection("coordinates");
1532: double a_coords[nDim], b_coords[nDim], c_coords[nDim], d_coords[nDim], e_coords[nDim];
1533: PetscMemcpy(a_coords, coordinates->restrictPoint(vertices[0]), dim*sizeof(double));
1534: PetscMemcpy(b_coords, coordinates->restrictPoint(vertices[1]), dim*sizeof(double));
1535: PetscMemcpy(c_coords, coordinates->restrictPoint(vertices[2]), dim*sizeof(double));
1536: PetscMemcpy(d_coords, coordinates->restrictPoint(vertices[3]), dim*sizeof(double));
1537: PetscMemcpy(e_coords, coordinates->restrictPoint(vertices[4]), dim*sizeof(double));
1538: double new_volume = tetrahedron_volume(dim, a_coords, b_coords, c_coords, d_coords);
1539: double cap_volume = tetrahedron_volume(dim, a_coords, b_coords, d_coords, e_coords);
1540: double old_volume = tetrahedron_volume(dim, a_coords, b_coords, d_coords, e_coords) + tetrahedron_volume(dim, b_coords, c_coords, d_coords, e_coords) + tetrahedron_volume(dim, c_coords, a_coords, d_coords, e_coords);
1541: //CASE: e is concave, removing e increases the volume;
1542: if (cap_volume - old_volume > 0 && new_volume < cap_volume) return PETSC_FALSE;
1543: return PETSC_TRUE;
1544: }
1546: Mesh::point_type Surgery_3D_31BoundFlip(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, Mesh::point_type maxIndex) {
1547: Obj<Mesh::sieve_type> s = m->getSieve();
1548: s->removeBasePoint(cells[0]);
1549: s->removeBasePoint(cells[1]);
1550: s->removeBasePoint(cells[2]);
1551:
1552: s->addArrow(vertices[0], cells[0]);
1553: s->addArrow(vertices[1], cells[0]);
1554: s->addArrow(vertices[2], cells[0]);
1555: s->addArrow(vertices[3], cells[0]);
1556: return maxIndex;
1557: }
1559: /*
1561: 3D extension of the 2D 2-2 boundflip -- we've removed all internal subvolumes in our way on an edge; save for two
1563: a a
1564: /|\ /|\
1565: / | \ / | \
1566: / | \ / 1 \
1567: /_-'|e-_\ /_-'e'-_\
1568: c 1 | 2 d -> c---------d
1569: \ | / \ | /
1570: \ | / \ 2 /
1571: \ | / \ | /
1572: \|/ \|/
1573: b b
1575: a, b, c, and d are on the boundary in question
1577: */
1579: void Surgery_3D_22BoundFlip_Setup(Obj<Mesh> m, Mesh::point_type a, Mesh::point_type b, Mesh::point_type e, Mesh::point_type * cells, Mesh::point_type * vertices) {
1580: Obj<Mesh::sieve_type> s = m->getSieve();
1581: vertices[0] = a;
1582: vertices[1] = b;
1583: vertices[4] = e;
1584: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
1585: Obj<Mesh::sieve_type::supportSet> lens = s->nJoin1(line);
1586: if (lens->size() != 2) throw Exception("Wrong Flip: Boundary 2-2");
1587: Mesh::sieve_type::supportSet::iterator l_iter = lens->begin();
1588: cells[0] = *l_iter;
1589: l_iter++;
1590: cells[1] = *l_iter;
1591: Obj<Mesh::sieve_type::coneSet> corners = s->cone(lens);
1592: if (corners->size() != 5) throw Exception("Bad Corners on 2-2 Boundflip");
1593: Mesh::sieve_type::coneSet::iterator c_iter = corners->begin();
1594: Mesh::sieve_type::coneSet::iterator c_iter_end = corners->end();
1595: int index = 2;
1596: while (c_iter != c_iter_end) {
1597: if (*c_iter != a && *c_iter != b && *c_iter != e) {
1598: vertices[index] = *c_iter;
1599: index++;
1600: }
1601: c_iter++;
1602: }
1603: return;
1604: }
1606: PetscTruth Surgery_3D_22BoundFlip_Possible(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices) {
1608: //criterion for success: both new volumes are less than the old volume. (they don't overlap)
1609: int dim = m->getDimension();
1610: const double pi = M_PI;
1611: if (dim != 3) throw ALE::Exception("Wrong dimension");
1612: const int nDim = 3;
1613: // double pi = 3.141592653589793238;
1614: const Obj<Mesh::real_section_type> coordinates = m->getRealSection("coordinates");
1615: double a_coords[nDim], b_coords[nDim], c_coords[nDim], d_coords[nDim], e_coords[nDim];
1616: PetscMemcpy(a_coords, coordinates->restrictPoint(vertices[0]), dim*sizeof(double));
1617: PetscMemcpy(b_coords, coordinates->restrictPoint(vertices[1]), dim*sizeof(double));
1618: PetscMemcpy(c_coords, coordinates->restrictPoint(vertices[2]), dim*sizeof(double));
1619: PetscMemcpy(d_coords, coordinates->restrictPoint(vertices[3]), dim*sizeof(double));
1620: PetscMemcpy(e_coords, coordinates->restrictPoint(vertices[4]), dim*sizeof(double));
1621: //NAH! only consider surface angles adding to form the curvature... (which should work)... these are convex or a saddle (saddle = invalid)
1622: //double old_volume = tetrahedron_volume(dim, a_coords, b_coords, c_coords, e_coords) +
1623: // tetrahedron_volume(dim, a_coords, b_coords, d_coords, e_coords);
1624: //double volume_1 = tetrahedron_volume(dim, a_coords, c_coords, d_coords, e_coords);
1625: //double volume_2 = tetrahedron_volume(dim, b_coords, c_coords, d_coords, e_coords);
1626: //if (volume_1 < old_volume && volume_2 < old_volume) return PETSC_TRUE;
1627: double curvature_1 = corner_angle(dim, a_coords, c_coords, b_coords) + corner_angle(dim, a_coords, d_coords, b_coords) +
1628: corner_angle(dim, a_coords, c_coords, e_coords) + corner_angle(dim, a_coords, d_coords, e_coords);
1629: if (curvature_1 >= 2*pi) return PETSC_FALSE;
1630: double curvature_2 = corner_angle(dim, b_coords, c_coords, a_coords) + corner_angle(dim, b_coords, d_coords, a_coords) +
1631: corner_angle(dim, b_coords, c_coords, e_coords) + corner_angle(dim, b_coords, d_coords, e_coords);
1632: if (curvature_2 >= 2*pi) return PETSC_FALSE;
1633: return PETSC_TRUE;
1634: }
1636: Mesh::point_type Surgery_3D_22BoundFlip(Obj<Mesh> m, Mesh::point_type * cells, Mesh::point_type * vertices, Mesh::point_type maxIndex) {
1637: Obj<Mesh::sieve_type> s = m->getSieve();
1638: s->removeBasePoint(cells[0]);
1639: s->removeBasePoint(cells[1]);
1640:
1641: s->addArrow(vertices[0], cells[0]);
1642: s->addArrow(vertices[2], cells[0]);
1643: s->addArrow(vertices[3], cells[0]);
1644: s->addArrow(vertices[4], cells[0]);
1645:
1646: s->addArrow(vertices[1], cells[1]);
1647: s->addArrow(vertices[2], cells[1]);
1648: s->addArrow(vertices[3], cells[1]);
1649: s->addArrow(vertices[4], cells[1]);
1650:
1651: return maxIndex;
1652: }
1654: //remove a 1D point
1655: int Surgery_1D_Remove_Vertex(Obj<Mesh> m, Mesh::point_type vertex, ALE::Mesh::point_type maxIndex) {
1656: Obj<Mesh::sieve_type> s = m->getSieve();
1657: Mesh::sieve_type::supportSet edges_to_remove;
1658: Obj<Mesh::sieve_type::supportSequence> v_support = s->support(vertex);
1659: Mesh::sieve_type::supportSequence::iterator vs_iter = v_support->begin();
1660: Mesh::sieve_type::supportSequence::iterator vs_iter_end = v_support->end();
1661: //find a reasonable neighbor to contract to
1662: Mesh::point_type neighbor = vertex;
1663: Obj<Mesh::sieve_type::coneSet> neighbors = s->cone(v_support);
1664: if (neighbors->size() <= 1) {
1665: //leave this vertex alone
1666: } else {
1667: Mesh::sieve_type::coneSet::iterator n_iter = neighbors->begin();
1668: Mesh::sieve_type::coneSet::iterator n_iter_end = neighbors->end();
1669: while (n_iter != n_iter_end && neighbor == vertex) {
1670: neighbor = *n_iter;
1671: n_iter++;
1672: }
1673: //next, contract all edges to this neighbor
1674: edges_to_remove.clear();
1675: while (vs_iter != vs_iter_end) {
1676: s->addArrow(neighbor, *vs_iter);
1677: if(s->cone(*vs_iter)->size() < 3) edges_to_remove.insert(*vs_iter);
1678: vs_iter++;
1679: }
1680: //next, remove the vertex and the edges that should be removed
1681: s->removeBasePoint(vertex);
1682: s->removeCapPoint(vertex);
1683: Mesh::sieve_type::supportSet::iterator etr_iter = edges_to_remove.begin();
1684: Mesh::sieve_type::supportSet::iterator etr_iter_end = edges_to_remove.end();
1685: while (etr_iter != etr_iter_end) {
1686: s->removeBasePoint(*etr_iter);
1687: s->removeCapPoint(*etr_iter);
1688: etr_iter++;
1689: }
1690: }
1691: return maxIndex;
1692: }
1695: //remove a 2D point
1697: int Surgery_2D_Remove_Vertex(Obj<Mesh> m, Mesh::point_type vertex, Obj<Mesh> bound_m, ALE::Mesh::point_type maxIndex) {
1698: //get potential ears
1699: // int dim = m->getDimension(); //limits some of the operations we can do to 2D-centric and nD-centric
1700: Obj<Mesh::sieve_type> s = m->getSieve();
1701: //Obj<Mesh::label_type> boundary = m->getLabel("marker"); //this could be erroneously marked, unfortunately; it's used for other things.
1702: bool on_boundary = (bound_m->getSieve()->hasPoint(vertex));
1703: //if (on_boundary) PetscPrintf(m->comm(), "Boundary node.");
1704: Mesh::point_type cells[4];
1705: Mesh::point_type vertices[5];
1706: int order[9];
1707: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
1708: Obj<Mesh::sieve_type::coneSet> neighbors = s->cone(s->support(vertex));
1709: //go through neighbors seeing if they are legitimate two-ears; if so then flip and repeat.
1710: bool remove_finished = false;
1711: while (!remove_finished) {
1712: int neighbor_size = neighbors->size() - 1;
1713: //PetscPrintf(m->comm(), "Neighbor size = %d\n", neighbor_size);
1714: bool changed_neighbors = false;
1715: Mesh::sieve_type::coneSet::iterator n_iter = neighbors->begin();
1716: Mesh::sieve_type::coneSet::iterator n_iter_end = neighbors->end();
1717: if (changed_neighbors) neighbors = s->cone(s->support(vertex));
1719: if (neighbor_size == 3 && !on_boundary) {
1720:
1721: //PetscPrintf(m->comm(), "flip: 3-1\n");
1722: Surgery_2D_31Flip_Setup(m, vertex, cells, vertices);
1723: if (Surgery_2D_31Flip_Possible(m, cells, vertices)) {
1724: Surgery_2D_31Flip(m, cells, vertices, maxIndex);
1725: }
1726: /*
1727: } else if (neighbor_size == 3 && on_boundary) {
1728:
1729: //PetscPrintf(m->comm(), "2-1\n");
1730: Surgery_2D_21BoundFlip_Setup(m, vertex, cells, vertices);
1731: Surgery_2D_21BoundFlip(m, cells, vertices, maxIndex);
1732: */
1733: } else if (neighbor_size == 2 && on_boundary) {
1734:
1735: //PetscPrintf(m->comm(), "1-0\n");
1736: Surgery_2D_10BoundFlip_Setup(m, vertex, cells, vertices);
1737: Surgery_2D_10BoundFlip(m, cells, vertices, maxIndex);
1738:
1739: } else while (n_iter != n_iter_end && !changed_neighbors) {
1740: if (*n_iter != vertex) {
1741: //find the line, find the on-link link, and decimate it
1742: line->clear();
1743: line->insert(*n_iter);
1744: line->insert(vertex);
1745: if (s->nJoin1(line)->size() != 2 || bound_m->getSieve()->nJoin1(line)->size() != 0) {
1746: //do nothing
1747: } else {
1748: //2->2 flip
1749: //PetscPrintf(m->comm(), "2-2 attempt\n");
1750: Surgery_2D_22Flip_Setup(m, vertex, *n_iter, cells, vertices, order);
1751: if (Surgery_2D_22Flip_Possible(m, cells, vertices, order)) {
1752: Surgery_2D_22Flip(m, cells, vertices, order, maxIndex); //in 2D there are no cases where we have to take the maxIndex into account
1753: changed_neighbors = true;
1754: }
1755: }
1756: }
1757: n_iter++;
1758: }
1759: //SEEMS TO BE CAUSING PROBLEMS
1760: /*
1761: if (n_iter == n_iter_end && neighbor_size == 4 && !on_boundary) { //this is the ONLY safe time to use this
1762: Surgery_2D_LineContract_Direction(m, vertex, cells, vertices);
1763: if (Surgery_2D_LineContract_Possible(m, cells, vertices)) {
1764: Surgery_2D_LineContract(m, cells, vertices, maxIndex);
1765: }
1766: }
1767: */
1768: if (n_iter == n_iter_end && on_boundary) { //last-ditch, forced in edges exist.
1769: //PetscPrintf(m->comm(), "flip: Contract\n");
1770: Mesh::point_type other_line_end = *neighbors->begin(); //if it's an isolated vertex just contract along a single line
1771: Obj<Mesh::sieve_type::coneSet> bound_neighbors = bound_m->getSieve()->cone(bound_m->getSieve()->support(vertex));
1772: Mesh::sieve_type::coneSet::iterator bn_iter = bound_neighbors->begin();
1773: Mesh::sieve_type::coneSet::iterator bn_iter_end = bound_neighbors->end();
1774: while (bn_iter != bn_iter_end) {
1775: if (*bn_iter != vertex) other_line_end = *bn_iter; //find a line to contract along
1776: bn_iter++;
1777: }
1778: Surgery_2D_LineContract_Setup(m, vertex, other_line_end, cells, vertices);
1779: if (Surgery_2D_LineContract_Possible(m, cells, vertices)) {
1780: Surgery_2D_LineContract(m, cells, vertices, maxIndex);
1781: }
1782: } //last-ditch boundary contract: find another vertex on the boundary in the neighbor set and contract to it. NO GUARANTEES
1784: if (!changed_neighbors) {
1785: //we're done if the local topology hasn't changed
1786: remove_finished = true;
1787: } else {
1788: neighbors = s->cone(s->support(vertex));
1789: }
1790: }
1791: //PetscPrintf(m->comm(), "removed %d\n", vertex);
1792: if (bound_m)if (!s->hasPoint(vertex)) Surgery_1D_Remove_Vertex(bound_m, vertex, maxIndex);
1793: return maxIndex;
1794: }
1796: //remove a 3D point
1799: Mesh::point_type Surgery_3D_Remove_Vertex(Obj<Mesh> m, Mesh::point_type vertex, ALE::Mesh::point_type maxIndex) {
1800: //get potential ears
1801: Mesh::point_type cur_maxIndex = maxIndex;
1802: Obj<Mesh::sieve_type> s = m->getSieve();
1803: Obj<Mesh::label_type> boundary = m->getLabel("marker");
1804: //this could be erroneously marked, unfortunately; it's used for other things.
1805: //bool on_boundary = (m->getValue(boundary, vertex) == 1);
1806: //if (on_boundary) PetscPrintf(m->comm(), "Boundary node.");
1807: Mesh::point_type cells[4];
1808: Mesh::point_type vertices[7];
1809: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
1810: Obj<Mesh::sieve_type::supportSet> lens;
1812: //go through neighbors seeing if they are legitimate two-ears; if so then flip and repeat.
1813: // bool remove_finished = false;
1814: //Algorithm: Do 2-3 flips until the cardinality of the neighbors of n on the link is 3, then do a 3-2 flip to remove it
1815: //new idea: enqueue the link vertex we want to work on next; go until the queue is empty.
1816: //NEW IDEA: NESTED QUEUES
1817: Obj<Mesh::sieve_type::supportSet> neighbor_queue = new Mesh::sieve_type::supportSet();
1818: Obj<Mesh::sieve_type::supportSet> link_neighbor_queue = new Mesh::sieve_type::supportSet();
1820: //add the neighbors to the neighbor queue.
1821: Obj<Mesh::sieve_type::coneSet> neighbors = s->cone(s->support(vertex));
1822: Mesh::sieve_type::coneSet::iterator n_iter = neighbors->begin();
1823: Mesh::sieve_type::coneSet::iterator n_iter_end = neighbors->end();
1824: //loop doing 2-3 and 3-2 flips until there are no more legitimate flips; this will involve flipping on a given neighbor fan; reducing
1825: //its cardinality until we can put a cap on it, or it is concave.
1826: while (n_iter != n_iter_end) {
1827: bool reset_neighbors = false;
1828: if (*n_iter != vertex) {
1829: Mesh::point_type cur_link_vertex = *n_iter;
1830:
1831: line->clear();
1832: //REMOVE THIS LATER BECAUSE IT'S GROSSLY INEFFICIENT
1833: // PetscPrintf(m->comm(), "# neighbors: %d\n", s->cone(s->support(vertex))->size());
1834: // PetscPrintf(m->comm(), "processing the line: %d, %d\n", vertex, cur_link_vertex);
1835: line->insert(cur_link_vertex);
1836: line->insert(vertex);
1837: lens = s->nJoin1(line);
1838:
1839: //add the cone of the lens that isn't vertex or cur_link_vertex
1840: Obj<Mesh::sieve_type::coneSet> lens_vertices = s->cone(lens);
1841:
1842: Mesh::sieve_type::coneSet::iterator lv_iter = lens_vertices->begin();
1843: Mesh::sieve_type::coneSet::iterator lv_iter_end = lens_vertices->end();
1844: while (lv_iter != lv_iter_end) {
1845: bool reset_lens = false;
1846: Mesh::point_type cur_link_neighbor_vertex = *lv_iter;
1847: if (*lv_iter != vertex && *lv_iter != cur_link_vertex) {
1848: //REMOVE LATER BECAUSE THIS IS GROSSLY INEFFICIENT
1849: // PetscPrintf(m->comm(), "#link neighbors: %d\n", s->cone(s->nJoin1(line))->size() - 2);
1850: // PetscPrintf(m->comm(), "Processing the link line: %d, %d\n", cur_link_vertex, cur_link_neighbor_vertex);
1851: //do 2-3 flips until you can't anymore.
1852: Surgery_3D_23Flip_Setup(m, vertex, cur_link_vertex, cur_link_neighbor_vertex, cells, vertices);
1853: if (Surgery_3D_23Flip_Possible(m, cells, vertices)) {
1854: // PetscPrintf(m->comm(), "Flipping.\n");
1855: cur_maxIndex = Surgery_3D_23Flip(m, cells, vertices, cur_maxIndex);
1856: //reget the neighbors
1857: lens = s->nJoin1(line);
1858: lens_vertices = s->cone(lens);
1859: lv_iter = lens_vertices->begin();
1860: lv_iter_end = lens_vertices->end();
1861: reset_lens = true;
1862: }
1863: }
1864: if (!reset_lens)lv_iter++;
1865: }
1866: //cap the 3-ear if possible; otherwise go on;
1867: lens = s->nJoin1(line);
1868: lens_vertices = s->cone(lens);
1869: if (lens_vertices->size() == 5) {
1870: Surgery_3D_32Flip_Setup(m, vertex, cur_link_vertex, cells, vertices);
1871: if (Surgery_3D_32Flip_Possible(m, cells, vertices)) {
1872: // PetscPrintf(m->comm(), "Flipping.\n");
1873: cur_maxIndex = Surgery_3D_32Flip(m, cells, vertices, cur_maxIndex);
1874: neighbors = s->cone(s->support(vertex));
1875: n_iter = neighbors->begin();
1876: n_iter_end = neighbors->end();
1877: reset_neighbors = true;
1878: }
1879: }
1880: }
1881: if (!reset_neighbors) n_iter++;
1882: } //end of our link stuffing task; if we can now simply pop the point out, do it.
1883: Obj<Mesh::sieve_type::supportSequence> neighbor_cells = s->support(vertex);
1884: PetscPrintf(m->comm(), "Done with link decimation; # surrounding cells: %d\n", neighbor_cells->size());
1885: if (neighbor_cells->size() == 4) {
1886: Surgery_3D_41Flip_Setup(m, vertex, cells, vertices);
1887: if (Surgery_3D_41Flip_Possible(m, cells, vertices)) {
1888: cur_maxIndex = Surgery_3D_41Flip(m, cells, vertices, cur_maxIndex);
1889: }
1890: }
1891: return cur_maxIndex;
1892: }
1894: Mesh::point_type Surgery_Remove_Vertex(Obj<Mesh> m, Mesh::point_type vertex, Obj<Mesh> bound_m, Mesh::point_type maxIndex, int effectiveDimension = -1) {
1895: Mesh::point_type cur_maxIndex = maxIndex;
1896: int dim;
1897: if (effectiveDimension != -1) {
1898: dim = effectiveDimension;
1899: } else {
1900: dim = m->getDimension();
1901: }
1902: if (dim == 2) {
1903: cur_maxIndex = Surgery_2D_Remove_Vertex(m, vertex, bound_m, cur_maxIndex);
1904: } else if (dim == 3) {
1905: cur_maxIndex = Surgery_3D_Remove_Vertex(m, vertex, cur_maxIndex); //doesn't currently work; messy.
1906: }
1907: return cur_maxIndex;
1908: }
1910: Mesh::point_type Surgery_Remove_VertexSet(Obj<Mesh> m, Obj<Mesh::sieve_type::supportSet> vertices, Obj<Mesh> b_m, Mesh::point_type maxIndex, int effectiveDimension = -1) {
1911: Mesh::point_type cur_maxIndex = maxIndex;
1912: Mesh::sieve_type::supportSet::iterator v_iter = vertices->begin();
1913: Mesh::sieve_type::supportSet::iterator v_iter_end = vertices->end();
1914: while (v_iter != v_iter_end) {
1915: cur_maxIndex = Surgery_Remove_Vertex(m, *v_iter, b_m, cur_maxIndex, effectiveDimension);
1916: v_iter++;
1917: }
1918: return cur_maxIndex;
1919: }
1921: Mesh::point_type Surgery_Remove_AllButVertexSet(Obj<Mesh> m, Obj<Mesh::sieve_type::supportSet> kept_vertices, Obj<Mesh> b_m, Mesh::point_type maxIndex, int effectiveDimension = -1) {
1922: Obj<Mesh::label_sequence> vertices = m->depthStratum(0);
1923: Mesh::label_sequence::iterator v_iter = vertices->begin();
1924: Mesh::label_sequence::iterator v_iter_end = vertices->end();
1925: Mesh::sieve_type::supportSet::iterator k_iter_end = kept_vertices->end();
1926: Mesh::point_type cur_maxIndex = maxIndex;
1927: while (v_iter != v_iter_end) {
1928: if (kept_vertices->find(*v_iter) == kept_vertices->end()) {
1929: cur_maxIndex = Surgery_Remove_Vertex(m, *v_iter, b_m, maxIndex, effectiveDimension);
1930: }
1931: v_iter++;
1932: }
1933: m->stratify();
1934: //PetscPrintf(m->comm(), "%d vertices left\n", m->depthStratum(0)->size());
1935: return cur_maxIndex;
1936: }
1938: void Surgery_2D_Improve_Mesh(Obj<Mesh> m, Obj<Mesh> bound_m = PETSC_NULL) {
1939: //we SHOULD be traversing; starting from the BEST triangle in the mesh and moving outwards as we know we can improve angles.
1940: if (m->depth() != 1) throw Exception("uninterpolated meshes only");
1941: //improve the edges of a vertex and traverse outwards to its neighbors; do until all vertices are done.
1942: //DO NOT do edges that are in the boundary.
1943: Mesh::point_type cells_points[2], vertices_points[4];
1944: int order[6];
1945: Obj<Mesh::sieve_type> s = m->getSieve();
1946: Obj<Mesh::label_sequence> vertices = m->depthStratum(0);
1947: ALE::Mesh::label_sequence::iterator v_iter = vertices->begin();
1948: ALE::Mesh::label_sequence::iterator v_iter_end = vertices->end();
1949: Obj<Mesh::sieve_type::supportSet> line = new Mesh::sieve_type::supportSet();
1950: while (v_iter != v_iter_end) { //do the DUMBEST THING: give every mesh vertex a chance to have its link improved; potentially flipping each edge twice.
1951: //potential future change: traverse outwards from a reasonable triangle improving its bad neighbors.
1952: Obj<Mesh::sieve_type::coneSet> neighbors = s->cone(s->support(*v_iter));
1953: Mesh::sieve_type::coneSet::iterator n_iter = neighbors->begin();
1954: Mesh::sieve_type::coneSet::iterator n_iter_end = neighbors->end();
1955: while (n_iter != n_iter_end) {
1956: line->clear();
1957: line->insert(*n_iter);
1958: line->insert(*v_iter);
1959: if (bound_m) {
1960: //check if this line is in the boundary
1961: if (bound_m->getSieve()->nJoin1(line)->size() == 0) { //this line is NOT in the boundary mesh and therefore cool
1962: //now just check
1963: if (s->nJoin1(line)->size() == 2) {
1964: Surgery_2D_22Flip_Setup(m, *n_iter, *v_iter, cells_points, vertices_points, order);
1965: if (Surgery_2D_22Flip_Possible(m, cells_points, vertices_points, order))
1966: if (Surgery_2D_22Flip_Preferable(m, cells_points, vertices_points, order)) {
1967: Surgery_2D_22Flip(m, cells_points, vertices_points, order, 0);
1968: }
1969: }
1970: }
1971: } else if (s->nJoin1(line)->size() == 2) { //quick error check; njoin1 of this thing in the mesh-to-be-improved should be of cardinality 2
1972: if (s->nJoin1(line)->size() == 2) {
1973: Surgery_2D_22Flip_Setup(m, *n_iter, *v_iter, cells_points, vertices_points, order);
1974: if (Surgery_2D_22Flip_Possible(m, cells_points, vertices_points, order))
1975: if (Surgery_2D_22Flip_Preferable(m, cells_points, vertices_points, order)) {
1976: Surgery_2D_22Flip(m, cells_points, vertices_points, order, 0);
1977: }
1978: }
1979: }
1980: n_iter++;
1981: }
1982: v_iter++;
1983: }
1984: }
1986: void Surgery_3D_Improve_Mesh(Obj<Mesh> m, Obj<Mesh> bound_m) {
1987: //can be done much better than removal, but without removal its pointless
1988: //WHAT TO WRITE: for each doublet check if the average curvatures of its corners would be improved if it were flipped to a 3-lens
1989: throw Exception("3D Mesh Improvement not implemented.");
1990: }
1992: Obj<Mesh> Surgery_2D_Coarsen_Mesh(Obj<Mesh> m, Obj<Mesh::sieve_type::supportSet> kept_vertices, Obj<Mesh> b_m = PETSC_NULL) {
1993: //uninterpolate a new copy of the mesh
1994: int dim = m->getDimension();
1995: int depth = m->depth();
1996: Obj<Mesh> new_mesh = new Mesh(m->comm(), dim, m->debug());
1997: Obj<Mesh::sieve_type> new_sieve = new Mesh::sieve_type(m->comm(), m->debug());
1998: new_mesh->setSieve(new_sieve);
1999: Obj<Mesh::sieve_type> s = m->getSieve();
2000: Obj<Mesh::label_sequence> vertices = m->depthStratum(0);
2001: Mesh::label_sequence::iterator v_iter = vertices->begin();
2002: Mesh::label_sequence::iterator v_iter_end = vertices->end();
2003: while (v_iter != v_iter_end) {
2004: Obj<Mesh::sieve_type::supportArray> cells = s->nSupport(*v_iter, depth);
2005: Mesh::sieve_type::coneArray::iterator c_iter = cells->begin();
2006: Mesh::sieve_type::coneArray::iterator c_iter_end = cells->end();
2007: while (c_iter != c_iter_end) {
2008: new_sieve->addArrow(*v_iter, *c_iter);
2009: c_iter++;
2010: }
2011: v_iter++;
2012: }
2013: //coarsen the mesh
2014: new_mesh->setRealSection("coordinates", m->getRealSection("coordinates"));
2015: new_mesh->stratify();
2016: Surgery_Remove_AllButVertexSet(new_mesh, kept_vertices, b_m, 0, 2);
2017: //improve the mesh
2018: Surgery_2D_Improve_Mesh(new_mesh, b_m);
2019: return new_mesh;
2020: }
2022: Obj<Mesh> Surgery_1D_Coarsen_Mesh(Obj<Mesh> m, Obj<Mesh::sieve_type::supportSet> kept_vertices) {
2023: //simpler case; just remove all vertices not in kept_vertices through contraction to a neighbor
2024: Obj<Mesh::label_sequence> vertices = m->depthStratum(0);
2025: Mesh::sieve_type::supportSet vertices_to_remove;
2026: Obj<Mesh::sieve_type> s = m->getSieve();
2027: Obj<Mesh> new_mesh = new Mesh(m->comm(), m->getDimension(), m->debug());
2028: Obj<Mesh::sieve_type> new_sieve = new Mesh::sieve_type(m->comm(), m->debug());
2029: new_mesh->setSieve(new_sieve);
2030: Mesh::sieve_type::supportSet edges_to_remove;
2031: Mesh::label_sequence::iterator v_iter = vertices->begin();
2032: Mesh::label_sequence::iterator v_iter_end = vertices->end();
2033: Mesh::sieve_type::supportSet::iterator kv_end = kept_vertices->end();
2034: while (v_iter != v_iter_end) {
2035: //copy over the old mesh
2036: ALE::Obj<ALE::Mesh::sieve_type::supportSequence> lines = s->support(*v_iter);
2037: ALE::Mesh::sieve_type::supportSequence::iterator l_iter = lines->begin();
2038: ALE::Mesh::sieve_type::supportSequence::iterator l_iter_end = lines->end();
2039: while (l_iter != l_iter_end) {
2040: new_sieve->addArrow(*v_iter, *l_iter);
2041: l_iter++;
2042: }
2043: if (kept_vertices->find(*v_iter) == kv_end) { //invert the kept set
2044: vertices_to_remove.insert(*v_iter);
2045: }
2046: v_iter++;
2047: }
2048: Mesh::sieve_type::supportSet::iterator vtr_iter = vertices_to_remove.begin();
2049: Mesh::sieve_type::supportSet::iterator vtr_iter_end = vertices_to_remove.end();
2050: while (vtr_iter != vtr_iter_end) {
2051: Obj<Mesh::sieve_type::supportSequence> v_support = new_sieve->support(*vtr_iter);
2052: Mesh::sieve_type::supportSequence::iterator vs_iter = v_support->begin();
2053: Mesh::sieve_type::supportSequence::iterator vs_iter_end = v_support->end();
2054: if (v_support->size() != 2) {
2055: //leave this vertex alone
2056: } else {
2057: Mesh::point_type involved_edges[2];
2058: Mesh::point_type involved_vertices[2];
2059: int involved_index = 0;
2060: while (vs_iter != vs_iter_end) {
2061: involved_edges[involved_index] = *vs_iter;
2062: Obj<Mesh::sieve_type::coneSequence> s_cone = new_sieve->cone(*vs_iter);
2063: Mesh::sieve_type::coneSequence::iterator sc_iter = s_cone->begin();
2064: Mesh::sieve_type::coneSequence::iterator sc_iter_end = s_cone->end();
2065: if (s_cone->size() != 2) throw Exception("Bad edge in 1D Coarsen");
2066: while (sc_iter != sc_iter_end) {
2067: if (*sc_iter != *vtr_iter) involved_vertices[involved_index] = *sc_iter;
2068: sc_iter++;
2069: }
2070: involved_index++;
2071: vs_iter++;
2072: }
2073: new_sieve->removeBasePoint(involved_edges[0]);
2074: new_sieve->removeCapPoint(*vtr_iter);
2075: new_sieve->addArrow(involved_vertices[0], involved_edges[1]);
2076:
2077: /*
2078: Mesh::sieve_type::coneSet::iterator n_iter = neighbors->begin();
2079: Mesh::sieve_type::coneSet::iterator n_iter_end = neighbors->end();
2080: while (n_iter != n_iter_end && neighbor == *vtr_iter) {
2081: neighbor = *n_iter;
2082: n_iter++;
2083: }
2084: //next, contract all edges to this neighbor
2085: edges_to_remove.clear();
2086: while (vs_iter != vs_iter_end) {
2087: new_sieve->addArrow(neighbor, *vs_iter);
2088: if(new_sieve->cone(*vs_iter)->size() < 3) edges_to_remove.insert(*vs_iter);
2089: vs_iter++;
2090: }
2091: //next, remove the vertex and the edges that should be removed
2092: new_sieve->removeBasePoint(*vtr_iter);
2093: new_sieve->removeCapPoint(*vtr_iter);
2094: Mesh::sieve_type::supportSet::iterator etr_iter = edges_to_remove.begin();
2095: Mesh::sieve_type::supportSet::iterator etr_iter_end = edges_to_remove.end();
2096: while (etr_iter != etr_iter_end) {
2097: new_sieve->removeBasePoint(*etr_iter);
2098: new_sieve->removeCapPoint(*etr_iter);
2099: etr_iter++;
2100: }
2101: */
2102: }
2103: vtr_iter++;
2104: }
2105: new_mesh->stratify();
2106: new_mesh->setRealSection("coordinates", m->getRealSection("coordinates"));
2107: return new_mesh;
2108: }
2109: }
2111: PetscTruth Surgery_2D_CheckConsistency(Obj<Mesh> m) {
2113: //debugging function for all of this in order to allow
2114: return PETSC_FALSE;
2115: }