Actual source code: SieveBuilder.hh

petsc-3.4.5 2014-06-29
  1: #ifndef included_ALE_SieveBuilder_hh
  2: #define included_ALE_SieveBuilder_hh

  4: #ifndef  included_ALE_ALE_hh
  5: #include <sieve/ALE.hh>
  6: #endif

  8: namespace ALE {
  9:   template<typename Bundle_>
 10:   class SieveBuilder {
 11:   public:
 12:     typedef Bundle_                                      bundle_type;
 13:     typedef typename bundle_type::sieve_type             sieve_type;
 14:     typedef typename bundle_type::arrow_section_type     arrow_section_type;
 15:     typedef std::vector<typename sieve_type::point_type> PointArray;
 16:     typedef std::pair<typename sieve_type::point_type, int> oPoint_type;
 17:     typedef std::vector<oPoint_type>                        oPointArray;
 18:   public:
 19:     static void buildHexFaces(Obj<sieve_type> sieve, Obj<arrow_section_type> orientation, int dim, std::map<int, int*>& curElement, std::map<int,PointArray>& bdVertices, std::map<int,oPointArray>& faces, typename sieve_type::point_type& cell, int& cellOrientation) {
 20:       int debug = sieve->debug();

 22:       if (debug > 1) {std::cout << "  Building hex faces for boundary of " << cell << " (size " << bdVertices[dim].size() << "), dim " << dim << std::endl;}
 23:       faces[dim].clear();
 24:       if (dim > 3) {
 25:         throw ALE::Exception("Cannot do hexes of dimension greater than three");
 26:       } else if (dim > 2) {
 27:         int nodes[24] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 5, 4,
 28:                          1, 2, 6, 5, 2, 3, 7, 6, 3, 0, 4, 7};

 30:         for(int b = 0; b < 6; b++) {
 31:           typename sieve_type::point_type face;
 32:           int o = 1;

 34:           bdVertices[dim-1].clear();
 35:           for(int c = 0; c < 4; c++) {
 36:             bdVertices[dim-1].push_back(bdVertices[dim][nodes[b*4+c]]);
 37:           }
 38:           if (debug > 1) {std::cout << "    boundary hex face " << b << std::endl;}
 39:           buildHexFaces(sieve, orientation, dim-1, curElement, bdVertices, faces, face, o);
 40:           if (debug > 1) {std::cout << "    added face " << face << std::endl;}
 41:           faces[dim].push_back(oPoint_type(face, o));
 42:         }
 43:       } else if (dim > 1) {
 44:         int boundarySize = bdVertices[dim].size();

 46:         for(int b = 0; b < boundarySize; b++) {
 47:           typename sieve_type::point_type face;
 48:           int o = 1;

 50:           bdVertices[dim-1].clear();
 51:           for(int c = 0; c < 2; c++) {
 52:             bdVertices[dim-1].push_back(bdVertices[dim][(b+c)%boundarySize]);
 53:           }
 54:           if (debug > 1) {
 55:             std::cout << "    boundary point " << bdVertices[dim][b] << std::endl;
 56:             std::cout << "      boundary vertices";
 57:             for(int c = 0; c < (int) bdVertices[dim-1].size(); c++) {
 58:               std::cout << " " << bdVertices[dim-1][c];
 59:             }
 60:             std::cout << std::endl;
 61:           }
 62:           buildHexFaces(sieve, orientation, dim-1, curElement, bdVertices, faces, face, o);
 63:           if (debug > 1) {std::cout << "    added face " << face << std::endl;}
 64:           faces[dim].push_back(oPoint_type(face, o));
 65:         }
 66:       } else {
 67:         if (debug > 1) {std::cout << "  Just set faces to boundary in 1d" << std::endl;}
 68:         typename PointArray::iterator bd_iter = bdVertices[dim].begin();
 69:         faces[dim].push_back(oPoint_type(*bd_iter, 0));++bd_iter;
 70:         faces[dim].push_back(oPoint_type(*bd_iter, 0));
 71:         //faces[dim].insert(faces[dim].end(), bdVertices[dim].begin(), bdVertices[dim].end());
 72:       }
 73:       if (debug > 1) {
 74:         for(typename oPointArray::iterator f_iter = faces[dim].begin(); f_iter != faces[dim].end(); ++f_iter) {
 75:           std::cout << "  face point " << f_iter->first << " orientation " << f_iter->second << std::endl;
 76:         }
 77:       }
 78:       // We always create the toplevel, so we could short circuit somehow
 79:       // Should not have to loop here since the meet of just 2 boundary elements is an element
 80:       typename oPointArray::iterator         f_itor = faces[dim].begin();
 81:       const typename sieve_type::point_type& start  = f_itor->first;
 82:       const typename sieve_type::point_type& next   = (++f_itor)->first;
 83:       Obj<typename sieve_type::supportSet> preElement = sieve->nJoin(start, next, 1);

 85:       if (preElement->size() > 0) {
 86:         cell = *preElement->begin();

 88:         const int size = faces[dim].size();
 89:         const Obj<typename sieve_type::traits::coneSequence>& cone = sieve->cone(cell);
 90:         int       wrap = size > 2 ? size-1 : 0;
 91:         int       indA = 0, indB = 0;

 93:         for(typename sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter, ++indA) {
 94:           if (start == *c_iter) break;
 95:         }
 96:         if (debug > 1) {std::cout << "    pointA " << start << " indA " << indA << std::endl;}
 97:         for(typename sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter, ++indB) {
 98:           if (next  == *c_iter) break;
 99:         }
100:         if (debug > 1) {std::cout << "    pointB " << next  << " indB " << indB << std::endl;}
101:         if ((indB - indA == 1) || (indA - indB == wrap)) {
102:           if (cellOrientation > 0) {
103:             cellOrientation = indA+1;
104:           } else {
105:             if (dim == 1) {
106:               cellOrientation = -2;
107:             } else {
108:               cellOrientation = -(indA+1);
109:             }
110:           }
111:         } else if ((indA - indB == 1) || (indB - indA == wrap)) {
112:           if (debug > 1) {std::cout << "      reversing cell orientation" << std::endl;}
113:           if (cellOrientation > 0) {
114:             cellOrientation = -(indA+1);
115:           } else {
116:             if (dim == 1) {
117:               cellOrientation = 1;
118:             } else {
119:               cellOrientation = indA+1;
120:             }
121:           }
122:         } else {
123:           throw ALE::Exception("Inconsistent orientation");
124:         }
125:         if (debug > 1) {std::cout << "  Found old cell " << cell << " orientation " << cellOrientation << std::endl;}
126:       } else {
127:         int color = 0;

129:         cell = typename sieve_type::point_type((*curElement[dim])++);
130:         for(typename oPointArray::iterator f_iter = faces[dim].begin(); f_iter != faces[dim].end(); ++f_iter) {
131:           MinimalArrow<typename sieve_type::point_type,typename sieve_type::point_type> arrow(f_iter->first, cell);

133:           sieve->addArrow(f_iter->first, cell, color++);
134:           if (f_iter->second) {
135:             orientation->addPoint(arrow);
136:             orientation->updatePoint(arrow, &(f_iter->second));
137:             if (debug > 1) {std::cout << "    Orienting arrow (" << f_iter->first << ", " << cell << ") to " << f_iter->second << std::endl;}
138:           }
139:         }
140:         if (cellOrientation > 0) {
141:           cellOrientation = 1;
142:         } else {
143:           cellOrientation = -(dim+1);
144:         }
145:         if (debug > 1) {std::cout << "  Added cell " << cell << " dim " << dim << std::endl;}
146:       }
147:     };
148:     static void buildQuadraticHexFaces(Obj<sieve_type> sieve, Obj<arrow_section_type> orientation, int dim, std::map<int, int*>& curElement, std::map<int,PointArray>& bdVertices, std::map<int,oPointArray>& faces, typename sieve_type::point_type& cell, int& cellOrientation) {
149:       int debug = sieve->debug();

151:       if (debug > 1) {std::cout << "  Building hex faces for boundary of " << cell << " (size " << bdVertices[dim].size() << "), dim " << dim << std::endl;}
152:       faces[dim].clear();
153:       if (dim > 3) {
154:         throw ALE::Exception("Cannot do hexes of dimension greater than three");
155:       } else if (dim > 2) {
156:         const int faceSizeQuadHex = 9;
157:         const int numFacesQuadHex = 6;
158:         int nodes[54] = {
159:           3, 2, 1, 0,  10, 9, 8, 11,  24, // bottom
160:           4, 5, 6, 7,  12, 13, 14, 15,  25, // top
161:           0, 1, 5, 4,  8, 17, 12, 16,  22, // front
162:           1, 2, 6, 5,  9, 18, 13, 17,  21, // right
163:           2, 3, 7, 6,  10, 19, 14, 18,  23, // back
164:           3, 0, 4, 7,  11, 16, 15, 19,  20 // left
165:         };

167:         for(int b = 0; b < numFacesQuadHex; b++) {
168:           typename sieve_type::point_type face;
169:           int o = 1;

171:           bdVertices[dim-1].clear();
172:           for(int c = 0; c < faceSizeQuadHex; c++) {
173:             bdVertices[dim-1].push_back(bdVertices[dim][nodes[b*faceSizeQuadHex+c]]);
174:           }
175:           if (debug > 1) {std::cout << "    boundary hex face " << b << std::endl;}
176:           buildQuadraticHexFaces(sieve, orientation, dim-1, curElement, bdVertices, faces, face, o);
177:           if (debug > 1) {std::cout << "    added face " << face << std::endl;}
178:           faces[dim].push_back(oPoint_type(face, o));
179:         }
180:       } else if (dim > 1) {
181:         const int edgeSizeQuadHex = 3;
182:         const int numEdgesQuadHex = 4;
183:         int nodes[12] = {
184:           0, 1,  4, // bottom
185:           1, 2,  5, // right
186:           2, 3,  6, // top
187:           3, 0,  7, // left
188:         };
189:         for(int b = 0; b < numEdgesQuadHex; b++) {
190:           typename sieve_type::point_type face;
191:           int o = 1;

193:           bdVertices[dim-1].clear();
194:           for(int c = 0; c < edgeSizeQuadHex; c++) {
195:             bdVertices[dim-1].push_back(bdVertices[dim][nodes[b*edgeSizeQuadHex+c]]);
196:           }
197:           if (debug > 1) {
198:             std::cout << "    boundary point " << bdVertices[dim][b] << std::endl;
199:             std::cout << "      boundary vertices";
200:             for(int c = 0; c < (int) bdVertices[dim-1].size(); c++) {
201:               std::cout << " " << bdVertices[dim-1][c];
202:             }
203:             std::cout << std::endl;
204:           }
205:           buildQuadraticHexFaces(sieve, orientation, dim-1, curElement, bdVertices, faces, face, o);
206:           if (debug > 1) {std::cout << "    added face " << face << std::endl;}
207:           faces[dim].push_back(oPoint_type(face, o));
208:         }
209:       } else {
210:         if (debug > 1) {std::cout << "  Just set faces to boundary in 1d" << std::endl;}
211:         typename PointArray::iterator bdEnd = bdVertices[dim].end();
212:         for (typename PointArray::iterator bd_iter = bdVertices[dim].begin(); bd_iter != bdEnd; ++bd_iter)
213:           faces[dim].push_back(oPoint_type(*bd_iter, 0));
214:         //faces[dim].insert(faces[dim].end(), bdVertices[dim].begin(), bdVertices[dim].end());
215:       }
216:       if (debug > 1) {
217:         for(typename oPointArray::iterator f_iter = faces[dim].begin(); f_iter != faces[dim].end(); ++f_iter) {
218:           std::cout << "  face point " << f_iter->first << " orientation " << f_iter->second << std::endl;
219:         }
220:       }
221:       // We always create the toplevel, so we could short circuit somehow
222:       // Should not have to loop here since the meet of just 2 boundary elements is an element
223:       typename oPointArray::iterator         f_itor = faces[dim].begin();
224:       const typename sieve_type::point_type& start  = f_itor->first;
225:       const typename sieve_type::point_type& next   = (++f_itor)->first;
226:       Obj<typename sieve_type::supportSet> preElement = sieve->nJoin(start, next, 1);

228:       if (preElement->size() > 0) {
229:         cell = *preElement->begin();

231:         const int size = faces[dim].size();
232:         const Obj<typename sieve_type::traits::coneSequence>& cone = sieve->cone(cell);
233:         int       wrap = size > 2 ? size-1 : 0;
234:         int       indA = 0, indB = 0;

236:         for(typename sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter, ++indA) {
237:           if (start == *c_iter) break;
238:         }
239:         if (debug > 1) {std::cout << "    pointA " << start << " indA " << indA << std::endl;}
240:         for(typename sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter, ++indB) {
241:           if (next  == *c_iter) break;
242:         }
243:         if (debug > 1) {std::cout << "    pointB " << next  << " indB " << indB << std::endl;}
244:         if ((indB - indA == 1) || (indA - indB == wrap)) {
245:           if (cellOrientation > 0) {
246:             cellOrientation = indA+1;
247:           } else {
248:             if (dim == 1) {
249:               cellOrientation = -2;
250:             } else {
251:               cellOrientation = -(indA+1);
252:             }
253:           }
254:         } else if ((indA - indB == 1) || (indB - indA == wrap)) {
255:           if (debug > 1) {std::cout << "      reversing cell orientation" << std::endl;}
256:           if (cellOrientation > 0) {
257:             cellOrientation = -(indA+1);
258:           } else {
259:             if (dim == 1) {
260:               cellOrientation = 1;
261:             } else {
262:               cellOrientation = indA+1;
263:             }
264:           }
265:         } else {
266:           throw ALE::Exception("Inconsistent orientation");
267:         }
268:         if (debug > 1) {std::cout << "  Found old cell " << cell << " orientation " << cellOrientation << std::endl;}
269:       } else {
270:         int color = 0;

272:         cell = typename sieve_type::point_type((*curElement[dim])++);
273:         for(typename oPointArray::iterator f_iter = faces[dim].begin(); f_iter != faces[dim].end(); ++f_iter) {
274:           MinimalArrow<typename sieve_type::point_type,typename sieve_type::point_type> arrow(f_iter->first, cell);

276:           sieve->addArrow(f_iter->first, cell, color++);
277:           if (f_iter->second) {
278:             orientation->addPoint(arrow);
279:             orientation->updatePoint(arrow, &(f_iter->second));
280:             if (debug > 1) {std::cout << "    Orienting arrow (" << f_iter->first << ", " << cell << ") to " << f_iter->second << std::endl;}
281:           }
282:         }
283:         if (cellOrientation > 0) {
284:           cellOrientation = 1;
285:         } else {
286:           cellOrientation = -(dim+1);
287:         }
288:         if (debug > 1) {std::cout << "  Added cell " << cell << " dim " << dim << std::endl;}
289:       }
290:     };
291:     static void buildQuadraticTetFaces(Obj<sieve_type> sieve, Obj<arrow_section_type> orientation,
292:                                        int dim,
293:                                        std::map<int, int*>& curElement,
294:                                        std::map<int,PointArray>& bdVertices,
295:                                        std::map<int,oPointArray>& faces,
296:                                        typename sieve_type::point_type& cell,
297:                                        int& cellOrientation) {
298:       int debug = sieve->debug();

300:       if (debug > 1)
301:         std::cout << "  Building tet faces for cell " << cell << " (size " << bdVertices[dim].size() << "), dim " << dim << std::endl;

303:       switch (dim) {
304:       case 1: {
305:         break;
306:       } // case 1
307:       case 2: {
308:         assert(6 == bdVertices[dim].size());

310:         // Edges on face
311:         int color = 0;
312:         int faceOrientation = 1;

314:         // Bottom edge
315:         typename sieve_type::point_type edge = bdVertices[dim][0];
316:         MinimalArrow<typename sieve_type::point_type,typename sieve_type::point_type> arrow(edge, cell);
317:         sieve->addArrow(edge, cell, color++);
318:         orientation->addPoint(arrow);
319:         if (bdVertices[dim][3] < bdVertices[dim][4])
320:           faceOrientation = 1;
321:         else
322:           faceOrientation = -dim;
323:         orientation->updatePoint(arrow, &faceOrientation);
324:         if (debug > 1)
325:           std::cout << "    Adding bottom edge " << edge << " with orientation " << faceOrientation << std::endl;

327:         // Right edge
328:         faceOrientation = 1;
329:         edge = bdVertices[dim][1];
330:         arrow.source = edge;
331:         sieve->addArrow(edge, cell, color++);
332:         orientation->addPoint(arrow);
333:         if (bdVertices[dim][4] < bdVertices[dim][5])
334:           faceOrientation = 1;
335:         else
336:           faceOrientation = -dim;
337:         orientation->updatePoint(arrow, &faceOrientation);
338:         if (debug > 1)
339:           std::cout << "    Adding right edge " << edge << " with orientation " << faceOrientation << std::endl;
340: 
341:         // Left edge
342:         faceOrientation = 1;
343:         edge = bdVertices[dim][2];
344:         arrow.source = edge;
345:         sieve->addArrow(edge, cell, color++);
346:         orientation->addPoint(arrow);
347:         if (bdVertices[dim][5] < bdVertices[dim][3])
348:           faceOrientation = 1;
349:         else
350:           faceOrientation = -dim;
351:         orientation->updatePoint(arrow, &faceOrientation);
352:         if (debug > 1)
353:           std::cout << "    Adding left edge " << edge << " with orientation " << faceOrientation << std::endl;
354: 
355:         // Vertices on edges

357:         // Vertices on bottom edge
358:         color = 0;
359:         edge = bdVertices[dim][0];
360:         typename sieve_type::point_type vertexA = bdVertices[dim][3];
361:         typename sieve_type::point_type vertexB = bdVertices[dim][4];
362:         sieve->addArrow(vertexA, edge, color++);
363:         sieve->addArrow(vertexB, edge, color++);
364:         if (debug > 1)
365:           std::cout << "    Adding vertices " << vertexA << " and " << vertexB << std::endl;
366: 
367:         // Vertices on right edge
368:         color = 0;
369:         edge = bdVertices[dim][1];
370:         vertexA = bdVertices[dim][4];
371:         vertexB = bdVertices[dim][5];
372:         sieve->addArrow(vertexA, edge, color++);
373:         sieve->addArrow(vertexB, edge, color++);
374:         if (debug > 1)
375:           std::cout << "    Adding vertices " << vertexA << " and " << vertexB << std::endl;
376: 
377:         // Vertices on left edge
378:         color = 0;
379:         edge = bdVertices[dim][2];
380:         vertexA = bdVertices[dim][5];
381:         vertexB = bdVertices[dim][3];
382:         sieve->addArrow(vertexA, edge, color++);
383:         sieve->addArrow(vertexB, edge, color++);
384:         if (debug > 1)
385:           std::cout << "    Adding vertices " << vertexA << " and " << vertexB << std::endl;
386: 
387:         break;
388:       } // case 2
389:       case 3: {
390:         break;
391:       } // case 3
392:       default:
393:         std::cerr << "Unknown dimension " << dim << std::endl;
394:         assert(0);
395:         throw ALE::Exception("Unknown dimension");
396:       } // switch

398:     };
399:     static void buildFaces(Obj<sieve_type> sieve, Obj<arrow_section_type> orientation, int dim, std::map<int, int*>& curElement, std::map<int,PointArray>& bdVertices, std::map<int,oPointArray>& faces, typename sieve_type::point_type& cell, int& cellOrientation) {
400:       int debug = sieve->debug();

402:       if (debug > 1) {
403:         if (cell >= 0) {
404:           std::cout << "  Building faces for boundary of " << cell << " (size " << bdVertices[dim].size() << "), dim " << dim << std::endl;
405:         } else {
406:           std::cout << "  Building faces for boundary of undetermined cell (size " << bdVertices[dim].size() << "), dim " << dim << std::endl;
407:         }
408:       }
409:       if (dim == 0) return;
410:       faces[dim].clear();
411:       if (dim > 1) {
412:         int b = 0;
413:         // Use the cone construction
414:         for(typename PointArray::iterator b_itor = bdVertices[dim].begin(); b_itor != bdVertices[dim].end(); ++b_itor, ++b) {
415:           typename sieve_type::point_type face = -1;
416:           int                             o    = b%2 ? -bdVertices[dim].size() : 1;

418:           bdVertices[dim-1].clear();
419:           for(typename PointArray::iterator i_itor = bdVertices[dim].begin(); i_itor != bdVertices[dim].end(); ++i_itor) {
420:             if (i_itor != b_itor) {
421:               bdVertices[dim-1].push_back(*i_itor);
422:             }
423:           }
424:           if (debug > 1) {std::cout << "    boundary point " << *b_itor << std::endl;}
425:           buildFaces(sieve, orientation, dim-1, curElement, bdVertices, faces, face, o);
426:           if (debug > 1) {std::cout << "    added face " << face << std::endl;}
427:           faces[dim].push_back(oPoint_type(face, o));
428:         }
429:       } else {
430:         if (debug > 1) {std::cout << "  Just set faces to boundary in 1d" << std::endl;}
431:         typename PointArray::iterator bd_iter = bdVertices[dim].begin();
432:         faces[dim].push_back(oPoint_type(*bd_iter, 0));++bd_iter;
433:         faces[dim].push_back(oPoint_type(*bd_iter, 0));
434:         //faces[dim].insert(faces[dim].end(), bdVertices[dim].begin(), bdVertices[dim].end());
435:       }
436:       if (debug > 1) {
437:         for(typename oPointArray::iterator f_iter = faces[dim].begin(); f_iter != faces[dim].end(); ++f_iter) {
438:           std::cout << "  face point " << f_iter->first << " orientation " << f_iter->second << std::endl;
439:         }
440:       }
441:       // We always create the toplevel, so we could short circuit somehow
442:       // Should not have to loop here since the meet of just 2 boundary elements is an element
443:       typename oPointArray::iterator         f_itor = faces[dim].begin();
444:       const typename sieve_type::point_type& start  = f_itor->first;
445:       const typename sieve_type::point_type& next   = (++f_itor)->first;
446:       Obj<typename sieve_type::supportSet> preElement = sieve->nJoin(start, next, 1);

448:       if (preElement->size() > 0) {
449:         cell = *preElement->begin();

451:         const int size = faces[dim].size();
452:         const Obj<typename sieve_type::traits::coneSequence>& cone = sieve->cone(cell);
453:         int       wrap = size > 2 ? size-1 : 0;
454:         int       indA = 0, indB = 0;

456:         for(typename sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter, ++indA) {
457:           if (start == *c_iter) break;
458:         }
459:         if (debug > 1) {std::cout << "    pointA " << start << " indA " << indA << std::endl;}
460:         for(typename sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter, ++indB) {
461:           if (next  == *c_iter) break;
462:         }
463:         if (debug > 1) {std::cout << "    pointB " << next  << " indB " << indB << std::endl;}
464:         if ((indB - indA == 1) || (indA - indB == wrap)) {
465:           if (cellOrientation > 0) {
466:             cellOrientation = indA+1;
467:           } else {
468:             if (dim == 1) {
469:               cellOrientation = -2;
470:             } else {
471:               cellOrientation = -(indA+1);
472:             }
473:           }
474:         } else if ((indA - indB == 1) || (indB - indA == wrap)) {
475:           if (debug > 1) {std::cout << "      reversing cell orientation" << std::endl;}
476:           if (cellOrientation > 0) {
477:             cellOrientation = -(indA+1);
478:           } else {
479:             if (dim == 1) {
480:               cellOrientation = 1;
481:             } else {
482:               cellOrientation = indA+1;
483:             }
484:           }
485:         } else {
486:           throw ALE::Exception("Inconsistent orientation");
487:         }
488:         if (debug > 1) {std::cout << "  Found old cell " << cell << " orientation " << cellOrientation << std::endl;}
489:       } else {
490:         int color = 0;

492:         cell = typename sieve_type::point_type((*curElement[dim])++);
493:         for(typename oPointArray::iterator f_iter = faces[dim].begin(); f_iter != faces[dim].end(); ++f_iter) {
494:           MinimalArrow<typename sieve_type::point_type,typename sieve_type::point_type> arrow(f_iter->first, cell);

496:           sieve->addArrow(f_iter->first, cell, color++);
497:           if (f_iter->second) {
498:             orientation->addPoint(arrow);
499:             orientation->updatePoint(arrow, &(f_iter->second));
500:             if (debug > 1) {std::cout << "    Orienting arrow (" << f_iter->first << ", " << cell << ") to " << f_iter->second << std::endl;}
501:           }
502:         }
503:         if (cellOrientation > 0) {
504:           cellOrientation = 1;
505:         } else {
506:           cellOrientation = -(dim+1);
507:         }
508:         if (debug > 1) {std::cout << "  Added cell " << cell << " dim " << dim << " orientation " << cellOrientation << std::endl;}
509:       }
510:     };
511: #if 0
512:     static void orientTriangle(const typename sieve_type::point_type cell, const int vertices[], const Obj<sieve_type>& sieve, const Obj<arrow_section_type>& orientation, int firstVertex[]) {
513:       const Obj<typename sieve_type::traits::coneSequence>&     cone = sieve->cone(cell);
514:       const typename sieve_type::traits::coneSequence::iterator end  = cone->end();
515:       int debug   = sieve->debug();
516:       int corners = 3;
517:       int e       = 0;

519:       if (debug > 1) {std::cout << "Orienting triangle " << cell << std::endl;}
520:       for(typename sieve_type::traits::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter, ++e) {
521:         if (debug > 1) {std::cout << "  edge " << *p_iter << std::endl;}
522:         const Obj<typename sieve_type::traits::coneSequence>& endpoints = sieve->cone(*p_iter);
523:         typename sieve_type::traits::coneSequence::iterator   vertex    = endpoints->begin();
524:         MinimalArrow<typename sieve_type::point_type,typename sieve_type::point_type> arrow(*p_iter, cell);
525:         int                                                                           indA, indB, value;

527:         orientation->addPoint(arrow);
528:         for(indA = 0; indA < corners; indA++) {if (*vertex == vertices[indA]) break;}
529:         if (debug > 1) {std::cout << "    vertexA " << *vertex << " indA " << indA <<std::endl;}
530:         firstVertex[e] = *vertex;
531:         ++vertex;
532:         for(indB = 0; indB < corners; indB++) {if (*vertex == vertices[indB]) break;}
533:         if (debug > 1) {std::cout << "    vertexB " << *vertex << " indB " << indB <<std::endl;}
534:         if ((indA == corners) || (indB == corners) || (indA == indB)) {throw ALE::Exception("Invalid edge endpoints");}
535:         if ((indB - indA == 1) || (indA - indB == 2)) {
536:           value =  1;
537:         } else {
538:           value = -1;
539:           firstVertex[e] = *vertex;
540:         }
541:         if (debug > 1) {std::cout << "  value " << value <<std::endl;}
542:         orientation->updatePoint(arrow, &value);
543:       }
544:     };
545: #endif
548:     // Build a topology from a connectivity description
549:     //   (0, 0)        ... (0, numCells-1):  dim-dimensional cells
550:     //   (0, numCells) ... (0, numVertices): vertices
551:     // The other cells are numbered as they are requested
552:     static void buildTopology(Obj<sieve_type> sieve, int dim, int numCells, int cells[], int numVertices, bool interpolate = true, int corners = -1, int firstVertex = -1, Obj<arrow_section_type> orientation = NULL, int firstCell = 0) {
553:       if (interpolate && orientation.isNull()) {
554:         throw ALE::Exception("Cannot interpolate mesh without providing an orientation Section");
555:       }
556:       ALE_LOG_EVENT_BEGIN;
557:       if (sieve->commRank() != 0) {
558:         ALE_LOG_EVENT_END;
559:         return;
560:       }
561:       buildTopology_private(sieve, dim, numCells, cells, numVertices, interpolate, corners, firstVertex, orientation, firstCell);
562:       ALE_LOG_EVENT_END;
563:     };
564:     static void buildTopology_private(Obj<sieve_type> sieve, int dim, int numCells, int cells[], int numVertices, bool interpolate = true, int corners = -1, int firstVertex = -1, Obj<arrow_section_type> orientation = NULL, int firstCell = 0) {
565:       int debug = sieve->debug();

567:       if (firstVertex < 0) firstVertex = numCells;
568:       // Create a map from dimension to the current element number for that dimension
569:       std::map<int,int*>       curElement;
570:       std::map<int,PointArray> bdVertices;
571:       std::map<int,PointArray> faces;
572:       std::map<int,oPointArray> oFaces;
573:       int                      curCell    = firstCell;
574:       int                      curVertex  = firstVertex;
575:       int                      newElement = firstVertex > firstCell ? firstVertex + numVertices : firstCell + numCells;
576:       int                      o          = 1;

578:       if (corners < 0) corners = dim+1;
579:       curElement[0]   = &curVertex;
580:       curElement[dim] = &curCell;
581:       for(int d = 1; d < dim; d++) {
582:         curElement[d] = &newElement;
583:       }
584:       for(int c = 0; c < numCells; c++) {
585:         typename sieve_type::point_type cell(c);

587:         // Build the cell
588:         if (interpolate) {
589:           bdVertices[dim].clear();
590:           for(int b = 0; b < corners; b++) {
591:             // This ordering produces the same vertex order as the uninterpolated mesh
592:             //typename sieve_type::point_type vertex(cells[c*corners+(b+corners-1)%corners]+firstVertex);
593:             typename sieve_type::point_type vertex(cells[c*corners+b]+firstVertex);

595:             if (debug > 1) {std::cout << "Adding boundary vertex " << vertex << std::endl;}
596:             bdVertices[dim].push_back(vertex);
597:           }
598:           if (debug) {std::cout << "cell " << cell << " num boundary vertices " << bdVertices[dim].size() << std::endl;}

600:           if ((2 == dim && 4 == corners) || (3 == dim && 8 == corners)) {
601:             buildHexFaces(sieve, orientation, dim, curElement, bdVertices, oFaces, cell, o);
602:           } else if ((2 == dim && 9 == corners) || (3 == dim && 27 == corners)) {
603:             buildQuadraticHexFaces(sieve, orientation, dim, curElement, bdVertices, oFaces, cell, o);
604:           } else if ((2 == dim && 6 == corners) || (3 == dim && 10 == corners)) {
605:             buildQuadraticTetFaces(sieve, orientation, dim, curElement, bdVertices, oFaces, cell, o);
606:           } else {
607:             buildFaces(sieve, orientation, dim, curElement, bdVertices, oFaces, cell, o);
608:           }
609: #if 0
610:           if ((dim == 2) && (!orientation.isNull())) {
611:             typename sieve_type::point_type eVertices[3];
612:             typename sieve_type::point_type fVertices[3];

614:             for(int v = 0; v < 3; ++v) {
615:               fVertices[v] = cells[c*corners+v]+numCells;
616:             }
617:             orientTriangle(cell, fVertices, sieve, orientation, eVertices);
618:           } else if ((dim == 3) && (!orientation.isNull())) {
619:             // The order of vertices in cells[] orients the cell itself
620:             if (debug > 1) {std::cout << "Orienting tetrahedron " << cell << std::endl;}
621:             const Obj<typename sieve_type::traits::coneSequence>&     cone = sieve->cone(cell);
622:             const typename sieve_type::traits::coneSequence::iterator end  = cone->end();
623:             int f = 0;

625:             for(typename sieve_type::traits::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter, ++f) {
626:               if (debug > 1) {std::cout << "  face " << *p_iter << std::endl;}
627:               const Obj<typename sieve_type::traits::coneSequence>&     fCone = sieve->cone(*p_iter);
628:               const typename sieve_type::traits::coneSequence::iterator fEnd  = fCone->end();
629:               typename sieve_type::point_type fVertices[3];
630:               typename sieve_type::point_type eVertices[3];

632:               // We will choose the orientation such that the normals are outward
633:               for(int v = 0, i = 0; v < corners; ++v) {
634:                 if (v == f) continue;
635:                 fVertices[i++] = cells[c*corners+v]+numCells;
636:               }
637:               if (f%2) {
638:                 int tmp      = fVertices[0];
639:                 fVertices[0] = fVertices[1];
640:                 fVertices[1] = tmp;
641:               }
642:               orientTriangle(*p_iter, fVertices, sieve, orientation, eVertices);
643:               MinimalArrow<typename sieve_type::point_type,typename sieve_type::point_type> fArrow(*p_iter, cell);
644:               int                                                                           indC, indD, indE, value;

646:               orientation->addPoint(fArrow);
647:               for(indC = 0; indC < corners; indC++) {if (eVertices[0] == fVertices[indC]) break;}
648:               if (debug > 1) {std::cout << "    vertexC " << eVertices[0] << " indC " << indC <<std::endl;}
649:               for(indD = 0; indD < corners; indD++) {if (eVertices[1] == fVertices[indD]) break;}
650:               if (debug > 1) {std::cout << "    vertexD " << eVertices[1] << " indD " << indD <<std::endl;}
651:               for(indE = 0; indE < corners; indE++) {if (eVertices[2] == fVertices[indE]) break;}
652:               if (debug > 1) {std::cout << "    vertexE " << eVertices[2] << " indE " << indE <<std::endl;}
653:               if ((indC == corners) || (indD == corners) || (indE == corners) ||
654:                   (indC == indD) || (indD == indE) || (indE == indC)) {throw ALE::Exception("Invalid face corners");}
655:               if ((indD - indC == 1) || (indC - indD == 2)) {
656:                 if (!((indE - indD == 1) || (indD - indE == 2)) ||
657:                     !((indC - indE == 1) || (indE - indC == 2))) {throw ALE::Exception("Invalid order");}
658:                 value =  1;
659:               } else {
660:                 value = -1;
661:               }
662:               if (debug > 1) {std::cout << "  value " << value <<std::endl;}
663:               orientation->updatePoint(fArrow, &value);
664:               orientation->view("Intermediate orientation");
665:             }
666:           }
667: #endif
668:         } else {
669:           for(int b = 0; b < corners; b++) {
670:             sieve->addArrow(typename sieve_type::point_type(cells[c*corners+b]+firstVertex), cell, b);
671:           }
672:           if (debug) {
673:             if (debug > 1) {
674:               for(int b = 0; b < corners; b++) {
675:                 std::cout << "  Adding vertex " << typename sieve_type::point_type(cells[c*corners+b]+firstVertex) << std::endl;
676:               }
677:             }
678:             if ((numCells < 10000) || (c%1000 == 0)) {
679:               std::cout << "Adding cell " << cell << " dim " << dim << std::endl;
680:             }
681:           }
682:         }
683:       }
684:     };
685:     static void buildCoordinates(const Obj<Bundle_>& bundle, const int embedDim, const PetscReal coords[], int numCells = -1) {
686:       const Obj<typename Bundle_::real_section_type>& coordinates = bundle->getRealSection("coordinates");
687:       const Obj<typename Bundle_::label_sequence>&    vertices    = bundle->depthStratum(0);
688:       const int                                       debug       = bundle->debug();

690:       if (numCells < 0) {
691:         numCells = bundle->heightStratum(0)->size();
692:       }
693:       bundle->setupCoordinates(coordinates);
694:       coordinates->setFiberDimension(vertices, embedDim);
695:       bundle->allocate(coordinates);
696:       for(typename Bundle_::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
697:         coordinates->updatePoint(*v_iter, &(coords[(*v_iter - numCells)*embedDim]));
698:         if (debug) {
699:           if ((numCells < 10000) || ((*v_iter)%1000 == 0)) {
700:             std::cout << "Adding coordinates for vertex " << *v_iter << std::endl;
701:           }
702:         }
703:       }
704:     };
707:     // Build a topology from a connectivity description
708:     //   (0, 0)        ... (0, numCells-1):  dim-dimensional cells
709:     //   (0, numCells) ... (0, numVertices): vertices
710:     // The other cells are numbered as they are requested
711:     static void buildTopologyMultiple(Obj<sieve_type> sieve, int dim, int numCells, int cells[], int numVertices, bool interpolate = true, int corners = -1, int firstVertex = -1, Obj<arrow_section_type> orientation = NULL) {
712:       int debug = sieve->debug();

714:       ALE_LOG_EVENT_BEGIN;
715:       int *cellOffset = new int[sieve->commSize()+1];
716:       cellOffset[0] = 0;
717:       MPI_Allgather(&numCells, 1, MPI_INT, &cellOffset[1], 1, MPI_INT, sieve->comm());
718:       for(int p = 1; p <= sieve->commSize(); ++p) cellOffset[p] += cellOffset[p-1];
719:       int *vertexOffset = new int[sieve->commSize()+1];
720:       vertexOffset[0] = 0;
721:       MPI_Allgather(&numVertices, 1, MPI_INT, &vertexOffset[1], 1, MPI_INT, sieve->comm());
722:       for(int p = 1; p <= sieve->commSize(); ++p) vertexOffset[p] += vertexOffset[p-1];
723:       if (firstVertex < 0) firstVertex = cellOffset[sieve->commSize()] + vertexOffset[sieve->commRank()];
724:       // Estimate the number of intermediates as (V+C)*(dim-1)
725:       //   Should include a check for running over the namespace
726:       // Create a map from dimension to the current element number for that dimension
727:       std::map<int,int*>       curElement;
728:       std::map<int,PointArray> bdVertices;
729:       std::map<int,PointArray> faces;
730:       std::map<int,oPointArray> oFaces;
731:       int                      curCell    = cellOffset[sieve->commRank()];
732:       int                      curVertex  = firstVertex;
733:       int                      newElement = firstVertex+vertexOffset[sieve->commSize()] + (cellOffset[sieve->commRank()] + vertexOffset[sieve->commRank()])*(dim-1);
734:       int                      o          = 1;

736:       if (corners < 0) corners = dim+1;
737:       curElement[0]   = &curVertex;
738:       curElement[dim] = &curCell;
739:       for(int d = 1; d < dim; d++) {
740:         curElement[d] = &newElement;
741:       }
742:       for(int c = 0; c < numCells; c++) {
743:         typename sieve_type::point_type cell(c);

745:         // Build the cell
746:         if (interpolate) {
747:           bdVertices[dim].clear();
748:           for(int b = 0; b < corners; b++) {
749:             // This ordering produces the same vertex order as the uninterpolated mesh
750:             //typename sieve_type::point_type vertex(cells[c*corners+(b+corners-1)%corners]+firstVertex);
751:             typename sieve_type::point_type vertex(cells[c*corners+b]+firstVertex);

753:             if (debug > 1) {std::cout << "Adding boundary vertex " << vertex << std::endl;}
754:             bdVertices[dim].push_back(vertex);
755:           }
756:           if (debug) {std::cout << "cell " << cell << " num boundary vertices " << bdVertices[dim].size() << std::endl;}

758:           if ((2 == dim && 4 == corners) || (3 == dim && 8 == corners)) {
759:             buildHexFaces(sieve, orientation, dim, curElement, bdVertices, oFaces, cell, o);
760:           } else if ((2 == dim && 9 == corners) || (3 == dim && 27 == corners)) {
761:             buildQuadraticHexFaces(sieve, orientation, dim, curElement, bdVertices, oFaces, cell, o);
762:           } else if ((2 == dim && 6 == corners) || (3 == dim && 10 == corners)) {
763:             buildQuadraticTetFaces(sieve, orientation, dim, curElement, bdVertices, oFaces, cell, o);
764:           } else {
765:             buildFaces(sieve, orientation, dim, curElement, bdVertices, oFaces, cell, o);
766:           }
767:         } else {
768:           for(int b = 0; b < corners; b++) {
769:             sieve->addArrow(typename sieve_type::point_type(cells[c*corners+b]+firstVertex), cell, b);
770:           }
771:           if (debug) {
772:             if (debug > 1) {
773:               for(int b = 0; b < corners; b++) {
774:                 std::cout << "  Adding vertex " << typename sieve_type::point_type(cells[c*corners+b]+firstVertex) << std::endl;
775:               }
776:             }
777:             if ((numCells < 10000) || (c%1000 == 0)) {
778:               std::cout << "Adding cell " << cell << " dim " << dim << std::endl;
779:             }
780:           }
781:         }
782:       }

784:       if (newElement >= firstVertex+vertexOffset[sieve->commSize()] + (cellOffset[sieve->commRank()+1] + vertexOffset[sieve->commRank()+1])*(dim-1)) {
785:         throw ALE::Exception("Namespace violation during intermediate element construction");
786:       }
787:       delete [] cellOffset;
788:       delete [] vertexOffset;
789:       ALE_LOG_EVENT_END;
790:     };
791:     static void buildCoordinatesMultiple(const Obj<Bundle_>& bundle, const int embedDim, const double coords[], int numGlobalCells = -1) {
792:       const Obj<typename Bundle_::real_section_type>& coordinates = bundle->getRealSection("coordinates");
793:       const Obj<typename Bundle_::label_sequence>&    vertices    = bundle->depthStratum(0);
794:       const int numCells = bundle->heightStratum(0)->size(), numVertices = vertices->size();
795:       const int debug    = bundle->debug();
796:       int       offset;

798:       if (numGlobalCells < 0) {
799:         MPI_Allreduce((void *) &numCells, &numGlobalCells, 1, MPI_INT, MPI_SUM, bundle->comm());
800:       }
801:       MPI_Scan((void *) &numVertices, &offset, 1, MPI_INT, MPI_SUM, bundle->comm());
802:       offset += numGlobalCells - numVertices;
803:       coordinates->setFiberDimension(vertices, embedDim);
804:       bundle->allocate(coordinates);
805:       for(typename Bundle_::label_sequence::iterator v_iter = vertices->begin(); v_iter != vertices->end(); ++v_iter) {
806:         coordinates->updatePoint(*v_iter, &(coords[(*v_iter - offset)*embedDim]));
807:         if (debug) {
808:           if ((numCells < 10000) || ((*v_iter)%1000 == 0)) {
809:             std::cout << "Adding coordinates for vertex " << *v_iter << std::endl;
810:           }
811:         }
812:       }
813:     };
814:   };
815: }
816: #endif