Actual source code: ISieve.hh

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

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

  8: #include <petscdmplex.h>

 10: #include <fstream>

 12: //#define IMESH_NEW_LABELS

 14: namespace ALE {
 15:   template<typename Point>
 16:   class OrientedPoint : public std::pair<Point, int> {
 17:   public:
 18:     OrientedPoint(const int o) : std::pair<Point, int>(o, o) {};
 19:     ~OrientedPoint() {};
 20:     friend std::ostream& operator<<(std::ostream& stream, const OrientedPoint& point) {
 21:       stream << "(" << point.first << ", " << point.second << ")";
 22:       return stream;
 23:     };
 24:   };

 26:   template<typename Point_, typename Alloc_ = malloc_allocator<Point_> >
 27:   class Interval {
 28:   public:
 29:     typedef Point_            point_type;
 30:     typedef Alloc_            alloc_type;
 31:   public:
 32:     class const_iterator {
 33:     protected:
 34:       point_type _p;
 35:     public:
 36:       const_iterator(const point_type p): _p(p) {};
 37:       ~const_iterator() {};
 38:     public:
 39:       const_iterator& operator=(const const_iterator& iter) {this->_p = iter._p; return *this;};
 40:       bool operator==(const const_iterator& iter) const {return this->_p == iter._p;};
 41:       bool operator!=(const const_iterator& iter) const {return this->_p != iter._p;};
 42:       const_iterator& operator++() {++this->_p; return *this;}
 43:       const_iterator& operator++(int) {
 44:         const_iterator tmp(*this);
 45:         ++(*this);
 46:         return tmp;
 47:       };
 48:       const_iterator& operator--() {--this->_p; return *this;}
 49:       const_iterator& operator--(int) {
 50:         const_iterator tmp(*this);
 51:         --(*this);
 52:         return tmp;
 53:       };
 54:       point_type operator*() const {return this->_p;};
 55:     };
 56:   protected:
 57:     point_type _min, _max;
 58:   public:
 59:     Interval(): _min(point_type()), _max(point_type()) {};
 60:     Interval(const point_type& min, const point_type& max): _min(min), _max(max) {};
 61:     Interval(const Interval& interval): _min(interval.min()), _max(interval.max()) {};
 62:     template<typename Iterator>
 63:     Interval(Iterator& iterator) {
 64:       this->_min = *std::min_element(iterator.begin(), iterator.end());
 65:       this->_max = (*std::max_element(iterator.begin(), iterator.end()))+1;
 66:     }
 67:   public:
 68:     Interval& operator=(const Interval& interval) {_min = interval.min(); _max = interval.max(); return *this;}
 69:     friend std::ostream& operator<<(std::ostream& stream, const Interval& interval) {
 70:       stream << "(" << interval.min() << ", " << interval.max() << ")";
 71:       return stream;
 72:     }
 73:   public:
 74:     const_iterator begin() const {return const_iterator(this->_min);};
 75:     const_iterator end() const {return const_iterator(this->_max);};
 76:     size_t size() const {return this->_max - this->_min;};
 77:     size_t count(const point_type& p) const {return ((p >= _min) && (p < _max)) ? 1 : 0;};
 78:     point_type min() const {return this->_min;};
 79:     point_type max() const {return this->_max;};
 80:     bool hasPoint(const point_type& point) const {
 81:       if (point < this->_min || point >= this->_max) return false;
 82:       return true;
 83:     };
 84:     void checkPoint(const point_type& point) const {
 85:       if (point < this->_min || point >= this->_max) {
 86:         ostringstream msg;
 87:         msg << "Invalid point " << point << " not in " << *this << std::endl;
 88:         throw ALE::Exception(msg.str().c_str());
 89:       }
 90:     };
 91:   };

 93:   template<typename Source_, typename Target_>
 94:   struct SimpleArrow {
 95:     typedef Source_ source_type;
 96:     typedef Target_ target_type;
 97:     const source_type source;
 98:     const target_type target;
 99:     SimpleArrow(const source_type& s, const target_type& t) : source(s), target(t) {};
100:     template<typename OtherSource_, typename OtherTarget_>
101:     struct rebind {
102:       typedef SimpleArrow<OtherSource_, OtherTarget_> other;
103:     };
104:     struct flip {
105:       typedef SimpleArrow<target_type, source_type> other;
106:       other arrow(const SimpleArrow& a) {return type(a.target, a.source);};
107:     };
108:     friend bool operator<(const SimpleArrow& x, const SimpleArrow& y) {
109:       return ((x.source < y.source) || ((x.source == y.source) && (x.target < y.target)));
110:     };
111:     friend std::ostream& operator<<(std::ostream& os, const SimpleArrow& a) {
112:       os << a.source << " ----> " << a.target;
113:       return os;
114:     }
115:   };

117:   namespace ISieveVisitor {
118:     template<typename Sieve>
119:     class NullVisitor {
120:     public:
121:       inline void visitArrow(const typename Sieve::arrow_type&) {};
122:       inline void visitPoint(const typename Sieve::point_type&) {};
123:       inline void visitArrow(const typename Sieve::arrow_type&, const int orientation) {};
124:       inline void visitPoint(const typename Sieve::point_type&, const int orientation) {};
125:     };
126:     class PrintVisitor {
127:     protected:
128:       ostringstream& os;
129:       const int      rank;
130:     public:
131:       PrintVisitor(ostringstream& s, const int rank = 0) : os(s), rank(rank) {};
132:       template<typename Arrow>
133:       inline void visitArrow(const Arrow& arrow) const {
134:         this->os << "["<<this->rank<<"]: " << arrow << std::endl;
135:       }
136:       template<typename Point>
137:       inline void visitPoint(const Point&) const {}
138:     };
139:     class ReversePrintVisitor : public PrintVisitor {
140:     public:
141:       ReversePrintVisitor(ostringstream& s, const int rank) : PrintVisitor(s, rank) {};
142:       template<typename Arrow>
143:       inline void visitArrow(const Arrow& arrow) const {
144:         this->os << "["<<this->rank<<"]: " << arrow.target << "<----" << arrow.source << std::endl;
145:       }
146:       template<typename Arrow>
147:       inline void visitArrow(const Arrow& arrow, const int orientation) const {
148:         this->os << "["<<this->rank<<"]: " << arrow.target << "<----" << arrow.source << ": " << orientation << std::endl;
149:       }
150:       template<typename Point>
151:       inline void visitPoint(const Point&) const {}
152:       template<typename Point>
153:       inline void visitPoint(const Point&, const int) const {}
154:     };
155:     template<typename Sieve, typename Visitor = NullVisitor<Sieve> >
156:     class PointRetriever {
157:     public:
158:       typedef typename Sieve::point_type point_type;
159:       typedef typename Sieve::arrow_type arrow_type;
160:       typedef std::pair<point_type,int>  oriented_point_type;
161:     protected:
162:       const bool           unique;
163:       size_t               i, o;
164:       size_t               skip, limit;
165:       Visitor             *visitor;
166:       size_t               size;
167:       point_type          *points;
168:       oriented_point_type *oPoints;
169:     protected:
170:       inline virtual bool accept(const point_type& point) {return true;};
171:     public:
172:       PointRetriever() : unique(false), i(0), o(0), skip(0), limit(0) {
173:         this->size    = 0;
174:         this->points  = NULL;
175:         this->oPoints = NULL;
176:       };
177:       PointRetriever(const size_t size, const bool unique = false) : unique(unique), i(0), o(0), skip(0), limit(0) {
178:         static Visitor nV;
179:         this->visitor = &nV;
180:         this->points  = NULL;
181:         this->oPoints = NULL;
182:         this->setSize(size);
183:       };
184:       PointRetriever(const size_t size, Visitor& v, const bool unique = false) : unique(unique), i(0), o(0), skip(0), limit(0), visitor(&v) {
185:         this->points  = NULL;
186:         this->oPoints = NULL;
187:         this->setSize(size);
188:       };
189:       void operator=(const PointRetriever& pr) {
190:         this->i = 0; this->o = 0; this->skip = 0; this->limit = 0; this->visitor = pr.visitor;
191:         this->points  = NULL;
192:         this->oPoints = NULL;
193:         this->setSize(pr.size);
194:       };
195:       virtual ~PointRetriever() {
196:         delete [] this->points;
197:         delete [] this->oPoints;
198:         this->points  = NULL;
199:         this->oPoints = NULL;
200:       };
201:       inline void visitArrow(const arrow_type& arrow) {
202:         this->visitor->visitArrow(arrow);
203:       };
204:       inline void visitArrow(const arrow_type& arrow, const int orientation) {
205:         this->visitor->visitArrow(arrow, orientation);
206:       };
207:       inline void visitPoint(const point_type& point) {
208:         if (i >= size) {
209:           ostringstream msg;
210:           msg << "Too many points (>" << size << ")for PointRetriever visitor";
211:           throw ALE::Exception(msg.str().c_str());
212:         }
213:         if (this->accept(point)) {
214:           if (this->unique) {
215:             size_t p;
216:             for(p = 0; p < i; ++p) {if (points[p] == point) break;}
217:             if (p != i) return;
218:           }
219:           if ((i < this->skip) || ((this->limit) && (i >= this->limit))) {--this->skip; return;}
220:           points[i++] = point;
221:           this->visitor->visitPoint(point);
222:         }
223:       };
224:       inline void visitPoint(const point_type& point, const int orientation) {
225:         if (o >= size) {
226:           ostringstream msg;
227:           msg << "Too many ordered points (>" << size << ")for PointRetriever visitor";
228:           throw ALE::Exception(msg.str().c_str());
229:         }
230:         if (this->accept(point)) {
231:           if (this->unique) {
232:             size_t p;
233:             for(p = 0; p < i; ++p) {if (points[p] == point) break;}
234:             if (p != i) return;
235:           }
236:           if ((i < this->skip) || ((this->limit) && (i >= this->limit))) {--this->skip; return;}
237:           points[i++]  = point;
238:           oPoints[o++] = oriented_point_type(point, orientation);
239:           this->visitor->visitPoint(point, orientation);
240:         }
241:       };
242:     public:
243:       size_t                     getSize() const {return this->i;}
244:       const point_type          *getPoints() const {return this->points;}
245:       size_t                     getOrientedSize() const {return this->o;}
246:       const oriented_point_type *getOrientedPoints() const {return this->oPoints;}
247:       void clear() {this->i = this->o = 0;}
248:       void setSize(const size_t s) {
249:         if (this->points) {
250:           delete [] this->points;
251:           delete [] this->oPoints;
252:         }
253:         this->size    = s;
254:         this->points  = new point_type[this->size];
255:         this->oPoints = new oriented_point_type[this->size];
256:       }
257:       void setSkip(size_t s) {this->skip = s;};
258:       void setLimit(size_t l) {this->limit = l;};
259:     };
260:     template<typename Sieve, typename Visitor = NullVisitor<Sieve> >
261:     class NConeRetriever : public PointRetriever<Sieve,Visitor> {
262:     public:
263:       typedef PointRetriever<Sieve,Visitor>           base_type;
264:       typedef typename Sieve::point_type              point_type;
265:       typedef typename Sieve::arrow_type              arrow_type;
266:       typedef typename base_type::oriented_point_type oriented_point_type;
267:     protected:
268:       const Sieve& sieve;
269:     protected:
270:       inline virtual bool accept(const point_type& point) {
271:         if (!this->sieve.getConeSize(point))
272:           return true;
273:         return false;
274:       };
275:     public:
276:       NConeRetriever(const Sieve& s, const size_t size) : PointRetriever<Sieve,Visitor>(size, true), sieve(s) {};
277:       NConeRetriever(const Sieve& s, const size_t size, Visitor& v) : PointRetriever<Sieve,Visitor>(size, v, true), sieve(s) {};
278:       void operator=(const NConeRetriever& ncr) {
279:         this->i = 0; this->o = 0; this->skip = 0; this->limit = 0; this->visitor = ncr.visitor;
280:         this->points  = NULL;
281:         this->oPoints = NULL;
282:         this->setSize(ncr.size);
283:       };
284:       virtual ~NConeRetriever() {};
285:     };
286:     template<typename Mesh, typename Visitor = NullVisitor<typename Mesh::sieve_type> >
287:     class MeshNConeRetriever : public PointRetriever<typename Mesh::sieve_type,Visitor> {
288:     public:
289:       typedef typename Mesh::Sieve                    Sieve;
290:       typedef PointRetriever<Sieve,Visitor>           base_type;
291:       typedef typename Sieve::point_type              point_type;
292:       typedef typename Sieve::arrow_type              arrow_type;
293:       typedef typename base_type::oriented_point_type oriented_point_type;
294:     protected:
295:       const Mesh& mesh;
296:       const int   depth;
297:     protected:
298:       inline virtual bool accept(const point_type& point) {
299:         if (this->mesh.depth(point) == this->depth)
300:           return true;
301:         return false;
302:       };
303:     public:
304:       MeshNConeRetriever(const Mesh& m, const int depth, const size_t size) : PointRetriever<typename Mesh::Sieve,Visitor>(size, true), mesh(m), depth(depth) {};
305:       MeshNConeRetriever(const Mesh& m, const int depth, const size_t size, Visitor& v) : PointRetriever<typename Mesh::Sieve,Visitor>(size, v, true), mesh(m), depth(depth) {};
306:       virtual ~MeshNConeRetriever() {};
307:     };
308:     template<typename Sieve, typename Set, typename Renumbering>
309:     class FilteredPointRetriever {
310:     public:
311:       typedef typename Sieve::point_type point_type;
312:       typedef typename Sieve::arrow_type arrow_type;
313:       typedef std::pair<point_type,int>  oriented_point_type;
314:     protected:
315:       const Set&   pointSet;
316:       Renumbering& renumbering;
317:       const size_t size;
318:       size_t       i, o;
319:       bool         renumber;
320:       point_type  *points;
321:       oriented_point_type *oPoints;
322:     public:
323:       FilteredPointRetriever(const Set& s, Renumbering& r, const size_t size) : pointSet(s), renumbering(r), size(size), i(0), o(0), renumber(true) {
324:         this->points  = new point_type[this->size];
325:         this->oPoints = new oriented_point_type[this->size];
326:       };
327:       ~FilteredPointRetriever() {
328:         delete [] this->points;
329:         delete [] this->oPoints;
330:       };
331:       inline void visitArrow(const arrow_type& arrow) {};
332:       inline void visitPoint(const point_type& point) {
333:         if (i >= size) throw ALE::Exception("Too many points for FilteredPointRetriever visitor");
334:         if (this->pointSet.find(point) == this->pointSet.end()) return;
335:         if (renumber) {
336:           points[i++] = this->renumbering[point];
337:         } else {
338:           points[i++] = point;
339:         }
340:       };
341:       inline void visitArrow(const arrow_type& arrow, const int orientation) {};
342:       inline void visitPoint(const point_type& point, const int orientation) {
343:         if (o >= size) throw ALE::Exception("Too many points for FilteredPointRetriever visitor");
344:         if (this->pointSet.find(point) == this->pointSet.end()) return;
345:         if (renumber) {
346:           points[i++]  = this->renumbering[point];
347:           oPoints[o++] = oriented_point_type(this->renumbering[point], orientation);
348:         } else {
349:           points[i++]  = point;
350:           oPoints[o++] = oriented_point_type(point, orientation);
351:         }
352:       };
353:     public:
354:       size_t            getSize() const {return this->i;}
355:       const point_type *getPoints() const {return this->points;}
356:       size_t            getOrientedSize() const {return this->o;}
357:       const oriented_point_type *getOrientedPoints() const {return this->oPoints;}
358:       void clear() {this->i = 0; this->o = 0;}
359:       void useRenumbering(const bool renumber) {this->renumber = renumber;}
360:     };
361:     template<typename Sieve, int size, typename Visitor = NullVisitor<Sieve> >
362:     class ArrowRetriever {
363:     public:
364:       typedef typename Sieve::point_type point_type;
365:       typedef typename Sieve::arrow_type arrow_type;
366:       typedef std::pair<arrow_type,int>  oriented_arrow_type;
367:     protected:
368:       arrow_type          arrows[size];
369:       oriented_arrow_type oArrows[size];
370:       size_t              i, o;
371:       Visitor            *visitor;
372:     public:
373:       ArrowRetriever() : i(0), o(0) {
374:         static Visitor nV;
375:         this->visitor = &nV;
376:       };
377:       ArrowRetriever(Visitor& v) : i(0), o(0), visitor(&v) {};
378:       inline void visitArrow(const typename Sieve::arrow_type& arrow) {
379:         if (i >= size) throw ALE::Exception("Too many arrows for visitor");
380:         arrows[i++] = arrow;
381:         this->visitor->visitArrow(arrow);
382:       };
383:       inline void visitArrow(const typename Sieve::arrow_type& arrow, const int orientation) {
384:         if (o >= size) throw ALE::Exception("Too many arrows for visitor");
385:         oArrows[o++] = oriented_arrow_type(arrow, orientation);
386:         this->visitor->visitArrow(arrow, orientation);
387:       };
388:       inline void visitPoint(const point_type& point) {
389:         this->visitor->visitPoint(point);
390:       };
391:       inline void visitPoint(const point_type& point, const int orientation) {
392:         this->visitor->visitPoint(point, orientation);
393:       };
394:     public:
395:       size_t                     getSize() const {return this->i;}
396:       const point_type          *getArrows() const {return this->arrows;}
397:       size_t                     getOrientedSize() const {return this->o;}
398:       const oriented_arrow_type *getOrientedArrows() const {return this->oArrows;}
399:       void clear() {this->i = this->o = 0;}
400:     };
401:     template<typename Sieve, typename Visitor>
402:     class ConeVisitor {
403:     protected:
404:       const Sieve& sieve;
405:       Visitor&     visitor;
406:       bool         useSource;
407:     public:
408:       ConeVisitor(const Sieve& s, Visitor& v, bool useSource = false) : sieve(s), visitor(v), useSource(useSource) {};
409:       inline void visitPoint(const typename Sieve::point_type& point) {
410:         this->sieve.cone(point, visitor);
411:       };
412:       inline void visitArrow(const typename Sieve::arrow_type& arrow) {};
413:     };
414:     template<typename Sieve, typename Visitor>
415:     class OrientedConeVisitor {
416:     protected:
417:       const Sieve& sieve;
418:       Visitor&     visitor;
419:       bool         useSource;
420:     public:
421:       OrientedConeVisitor(const Sieve& s, Visitor& v, bool useSource = false) : sieve(s), visitor(v), useSource(useSource) {};
422:       inline void visitPoint(const typename Sieve::point_type& point) {
423:         this->sieve.orientedCone(point, visitor);
424:       };
425:       inline void visitArrow(const typename Sieve::arrow_type& arrow) {};
426:     };
427:     template<typename Sieve, typename Visitor>
428:     class SupportVisitor {
429:     protected:
430:       const Sieve& sieve;
431:       Visitor&     visitor;
432:       bool         useSource;
433:     public:
434:       SupportVisitor(const Sieve& s, Visitor& v, bool useSource = true) : sieve(s), visitor(v), useSource(useSource) {};
435:       inline void visitPoint(const typename Sieve::point_type& point) {
436:         this->sieve.support(point, visitor);
437:       };
438:       inline void visitArrow(const typename Sieve::arrow_type& arrow) {};
439:     };
440:     template<typename Sieve, typename Visitor = NullVisitor<Sieve> >
441:     class TransitiveClosureVisitor {
442:     public:
443:       typedef Visitor visitor_type;
444:     protected:
445:       const Sieve& sieve;
446:       Visitor&     visitor;
447:       bool         isCone;
448:       std::set<typename Sieve::point_type> seen;
449:     public:
450:       TransitiveClosureVisitor(const Sieve& s, Visitor& v) : sieve(s), visitor(v), isCone(true) {};
451:       inline void visitPoint(const typename Sieve::point_type& point) const {};
452:       inline void visitArrow(const typename Sieve::arrow_type& arrow) {
453:         if (this->isCone) {
454:           if (this->seen.find(arrow.target) == this->seen.end()) {
455:             this->seen.insert(arrow.target);
456:             this->visitor.visitPoint(arrow.target);
457:           }
458:           this->visitor.visitArrow(arrow);
459:           if (this->seen.find(arrow.source) == this->seen.end()) {
460:             if (this->sieve.getConeSize(arrow.source)) {
461:               this->sieve.cone(arrow.source, *this);
462:             } else {
463:               this->seen.insert(arrow.source);
464:               this->visitor.visitPoint(arrow.source);
465:             }
466:           }
467:         } else {
468:           if (this->seen.find(arrow.source) == this->seen.end()) {
469:             this->seen.insert(arrow.source);
470:             this->visitor.visitPoint(arrow.source);
471:           }
472:           this->visitor.visitArrow(arrow);
473:           if (this->seen.find(arrow.target) == this->seen.end()) {
474:             if (this->sieve.getSupportSize(arrow.target)) {
475:               this->sieve.support(arrow.target, *this);
476:             } else {
477:               this->seen.insert(arrow.target);
478:               this->visitor.visitPoint(arrow.target);
479:             }
480:           }
481:         }
482:       };
483:     public:
484:       bool getIsCone() const {return this->isCone;};
485:       void setIsCone(const bool isCone) {this->isCone = isCone;};
486:       const std::set<typename Sieve::point_type>& getPoints() const {return this->seen;};
487:       void clear() {this->seen.clear();};
488:     };
489:     template<typename Sieve, typename Section>
490:     class SizeVisitor {
491:     protected:
492:       const Section& section;
493:       int            size;
494:     public:
495:       SizeVisitor(const Section& s) : section(s), size(0) {};
496:       inline void visitPoint(const typename Sieve::point_type& point) {
497:         this->size += section.getConstrainedFiberDimension(point);
498:       };
499:       inline void visitArrow(const typename Sieve::arrow_type&) {};
500:     public:
501:       int getSize() {return this->size;};
502:     };
503:     template<typename Sieve, typename Section>
504:     class SizeWithBCVisitor {
505:     protected:
506:       const Section& section;
507:       int            size;
508:     public:
509:       SizeWithBCVisitor(const Section& s) : section(s), size(0) {};
510:       inline void visitPoint(const typename Sieve::point_type& point) {
511:         this->size += section.getFiberDimension(point);
512:       };
513:       inline void visitArrow(const typename Sieve::arrow_type&) {};
514:     public:
515:       int getSize() {return this->size;};
516:     };
517:     template<typename Sieve>
518:     class SizeWithBCVisitor<Sieve,PetscSection> {
519:     protected:
520:       PetscSection section;
521:       int          size;
522:       PetscInt    *fieldSize;
523:       PetscInt     numFields;
524:     public:
525:       SizeWithBCVisitor(PetscSection s) : section(s), size(0), fieldSize(NULL), numFields(0) {};
526:       SizeWithBCVisitor(PetscSection s, PetscInt *fieldSize) : section(s), size(0), fieldSize(fieldSize) {
527:         PetscErrorCode PetscSectionGetNumFields(section, &numFields);CHKERRXX(ierr);
528:         for(PetscInt f = 0; f < numFields; ++f) {this->fieldSize[f] = 0;}
529:       };
530:       inline void visitPoint(const typename Sieve::point_type& point) {
531:         PetscInt dim;
533:         PetscSectionGetDof(section, point, &dim);CHKERRXX(ierr);
534:         this->size += dim;
535:         for(PetscInt f = 0; f < numFields; ++f) {
536:           PetscSectionGetFieldDof(section, point, f, &dim);CHKERRXX(ierr);
537:           this->fieldSize[f] += dim;
538:         }
539:       };
540:       inline void visitArrow(const typename Sieve::arrow_type&) {};
541:     public:
542:       int getSize() {return this->size;};
543:     };
544:     template<typename Section>
545:     class RestrictVisitor {
546:     public:
547:       typedef typename Section::value_type value_type;
548:     protected:
549:       const Section& section;
550:       int            size;
551:       int            i;
552:       value_type    *values;
553:       bool           allocated;
554:     public:
555:       RestrictVisitor(const Section& s, const int size) : section(s), size(size), i(0) {
556:         this->values    = new value_type[this->size];
557:         this->allocated = true;
558:       };
559:       RestrictVisitor(const Section& s, const int size, value_type *values) : section(s), size(size), i(0) {
560:         this->values    = values;
561:         this->allocated = false;
562:       };
563:       ~RestrictVisitor() {if (this->allocated) {delete [] this->values;}};
564:       template<typename Point>
565:       inline void visitPoint(const Point& point, const int orientation) {
566:         const int         dim = section.getFiberDimension(point);
567:         if (i+dim > size) {throw ALE::Exception("Too many values for RestrictVisitor.");}
568:         const value_type *v   = section.restrictPoint(point);

570:         if (orientation >= 0) {
571:           for(int d = 0; d < dim; ++d, ++i) {
572:             this->values[i] = v[d];
573:           }
574:         } else {
575:           for(int d = dim-1; d >= 0; --d, ++i) {
576:             this->values[i] = v[d];
577:           }
578:         }
579:       }
580:       template<typename Arrow>
581:       inline void visitArrow(const Arrow& arrow, const int orientation) {}
582:     public:
583:       const value_type *getValues() const {return this->values;};
584:       int  getSize() const {return this->i;};
585:       int  getMaxSize() const {return this->size;};
586:       void ensureSize(const int size) {
587:         this->clear();
588:         if (size > this->size) {
589:           this->size = size;
590:           if (this->allocated) {delete [] this->values;}
591:           this->values = new value_type[this->size];
592:           this->allocated = true;
593:         }
594:       };
595:       void clear() {this->i = 0;};
596:     };
597:     template<typename ValueType>
598:     class RestrictVecVisitor {
599:     public:
600:       typedef ValueType value_type;
601:     protected:
602:       const Vec          v;
603:       const PetscSection section;
604:       int                size;
605:       int                i;
606:       int                nF;
607:       int               *offsets;
608:       int               *indices;
609:       bool               processed;
610:       value_type        *values;
611:       bool               allocated;
612:       value_type        *array;
613:     protected:
614:       inline void swap(value_type& v, value_type& w) {
615:         value_type tmp = v;
616:         v = w;
617:         w = tmp;
618:       };
619:       void processArray() {
620:         for(PetscInt f = 1; f < nF; ++f) {
621:           offsets[f+1] += offsets[f];
622:         }
623:         for(PetscInt i = 0; i < offsets[nF]; ++i) {
624:           indices[i] = offsets[indices[i]]++;
625:         }
626:         assert(offsets[nF-1] == offsets[nF]);
627:         for(PetscInt i = 0; i < offsets[nF]; ++i) {
628:           if (indices[i] == -1) continue;
629:           PetscInt   startPos = indices[i];
630:           PetscInt   j        = startPos, k;
631:           value_type val      = values[i];

633:           do {
634:             swap(val, values[j]);
635:             k = indices[j];
636:             indices[j] = -1;
637:             j = k;
638:           } while(j != startPos);
639:         }
640:       };
641:     public:
642:       RestrictVecVisitor(const Vec v, const PetscSection s, const int size) : v(v), section(s), size(size), i(0), nF(0), processed(true) {
643:         this->values    = new value_type[this->size];
644:         this->allocated = true;
645:         PetscErrorCode VecGetArray(this->v, &this->array);CHKERRXX(ierr);
646:       };
647:       RestrictVecVisitor(const Vec v, const PetscSection s, const int size, value_type *values) : v(v), section(s), size(size), i(0), nF(0), processed(true) {
648:         this->values    = values;
649:         this->allocated = false;
650:         PetscErrorCode VecGetArray(this->v, &this->array);CHKERRXX(ierr);
651:       };
652:       RestrictVecVisitor(const Vec v, const PetscSection s, const int size, value_type *values, int *offsets, int *indices) : v(v), section(s), size(size), i(0), nF(0), offsets(offsets), indices(indices), processed(false) {

655:         this->values    = values;
656:         this->allocated = false;
657:         VecGetArray(this->v, &this->array);CHKERRXX(ierr);
658:         PetscSectionGetNumFields(section, &nF);CHKERRXX(ierr);
659:         for(PetscInt f = 0; f <= nF; ++f) {offsets[f] = 0;}
660:       };
661:       ~RestrictVecVisitor() {
662:         if (this->allocated) {delete [] this->values;}
663:         PetscErrorCode VecRestoreArray(this->v, &this->array);CHKERRXX(ierr);
664:       };
665:       template<typename Point>
666:       inline void visitPoint(const Point& point, const int orientation) {
667:         // Known:
668:         //   Nf: number of fields
669:         // Unknown:
670:         //   Np: number of points
671:         //   P:  points
672:         // Algorithm:
673:         //   Pass 1: Stack up values as before, but also
674:         //           count size of each field
675:         //   Comp 1: Sum up sizes to get field offsets
676:         //   Pass 2: Number each entry with its intended position
677:         //   Pass 3: Reorder entries
678:         // Algorithm if field sizes are known:
679:         //   Comp 1: Partition array into field components
680:         //   Pass 1: Stack up values at field offsets
681:         PetscInt       dim, off;

684:         PetscSectionGetDof(section, point, &dim);CHKERRXX(ierr);
685:         if (i+dim > size) {
686:           ostringstream msg;
687:           msg << "Too many values for RestrictVisitor "<<i+dim<<" > "<<size<< std::endl;
688:           throw ALE::Exception(msg.str().c_str());
689:         }
690:         PetscSectionGetOffset(section, point, &off);CHKERRXX(ierr);
691:         const value_type *v = &array[off];

693:         if (nF) {
694:           for(PetscInt f = 0, fOff = 0; f < nF; ++f) {
695:             PetscInt comp, fDim;

697:             PetscSectionGetFieldDof(section, point, f, &fDim);CHKERRXX(ierr);
698:             offsets[f+1] += fDim;
699:             for(PetscInt d = 0; d < fDim; ++d) {
700:               indices[i+d] = f;
701:             }
702:             if (orientation >= 0) {
703:               for(PetscInt d = 0; d < fDim; ++d, ++i) {
704:                 this->values[i] = v[fOff+d];
705:               }
706:             } else {
707:               PetscSectionGetFieldComponents(section, f, &comp);CHKERRXX(ierr);
708:               for(PetscInt d = fDim/comp-1; d >= 0; --d) {
709:                 for(PetscInt c = 0; c < comp; ++c, ++i) {
710:                   this->values[i] = v[fOff+d*comp+c];
711:                 }
712:               }
713:             }
714:             fOff += fDim;
715:           }
716:         } else {
717:           if (orientation >= 0) {
718:             for(PetscInt d = 0; d < dim; ++d, ++i) {
719:               this->values[i] = v[d];
720:             }
721:           } else {
722:             for(PetscInt d = dim-1; d >= 0; --d, ++i) {
723:               this->values[i] = v[d];
724:             }
725:           }
726:         }
727:       }
728:       template<typename Arrow>
729:       inline void visitArrow(const Arrow& arrow, const int orientation) {}
730:     public:
731:       const value_type *getValues() {
732:         if (!processed) {processArray(); processed = true;}
733:         return this->values;
734:       };
735:       int  getSize() const {return this->i;};
736:       int  getMaxSize() const {return this->size;};
737:       void ensureSize(const int size) {
738:         this->clear();
739:         if (size > this->size) {
740:           this->size = size;
741:           if (this->allocated) {delete [] this->values;}
742:           this->values = new value_type[this->size];
743:           this->allocated = true;
744:         }
745:       };
746:       void clear() {this->i = 0; if (processed) {processed = false;}};
747:     };
748:     template<typename Section>
749:     class UpdateVisitor {
750:     public:
751:       typedef typename Section::value_type value_type;
752:     protected:
753:       Section&          section;
754:       const value_type *values;
755:       int               i;
756:     public:
757:       UpdateVisitor(Section& s, const value_type *v) : section(s), values(v), i(0) {};
758:       template<typename Point>
759:       inline void visitPoint(const Point& point, const int orientation) {
760:         const int dim = section.getFiberDimension(point);
761:         this->section.updatePoint(point, &this->values[this->i], orientation);
762:         this->i += dim;
763:       }
764:       template<typename Arrow>
765:       inline void visitArrow(const Arrow& arrow, const int orientation) {}
766:       void clear() {this->i = 0;};
767:     };
768:     template<typename Section>
769:     class UpdateAllVisitor {
770:     public:
771:       typedef typename Section::value_type value_type;
772:     protected:
773:       Section&          section;
774:       const value_type *values;
775:       int               i;
776:     public:
777:       UpdateAllVisitor(Section& s, const value_type *v) : section(s), values(v), i(0) {};
778:       template<typename Point>
779:       inline void visitPoint(const Point& point, const int orientation) {
780:         const int dim = section.getFiberDimension(point);
781:         this->section.updatePointAll(point, &this->values[this->i], orientation);
782:         this->i += dim;
783:       }
784:       template<typename Arrow>
785:       inline void visitArrow(const Arrow& arrow, const int orientation) {}
786:       void clear() {this->i = 0;};
787:     };
788:     template<typename Section>
789:     class UpdateAddVisitor {
790:     public:
791:       typedef typename Section::value_type value_type;
792:     protected:
793:       Section&          section;
794:       const value_type *values;
795:       int               i;
796:     public:
797:       UpdateAddVisitor(Section& s, const value_type *v) : section(s), values(v), i(0) {};
798:       template<typename Point>
799:       inline void visitPoint(const Point& point, const int orientation) {
800:         const int dim = section.getFiberDimension(point);
801:         this->section.updateAddPoint(point, &this->values[this->i], orientation);
802:         this->i += dim;
803:       }
804:       template<typename Arrow>
805:       inline void visitArrow(const Arrow& arrow, const int orientation) {}
806:       void clear() {this->i = 0;};
807:     };
808:     template<typename ValueType>
809:     class UpdateVecVisitor {
810:     public:
811:       typedef ValueType value_type;
812:     protected:
813:       const Vec          v;
814:       const PetscSection section;
815:       const value_type  *values;
816:       const InsertMode   mode;
817:       PetscInt           nF;
818:       PetscInt           i;
819:       value_type        *array;
820:       PetscInt          *fieldSize;
821:       PetscInt          *j;
822:     protected:
823:       inline static void add   (value_type& x, value_type y) {x += y;}
824:       inline static void insert(value_type& x, value_type y) {x  = y;}
825:       template<typename Point>
826:       void updatePoint(const Point& point, void (*fuse)(value_type&, value_type), const bool setBC, const int orientation = 1) {
827:         PetscInt        dim;  // The number of dof on this point
828:         PetscInt        cDim; // The nubmer of constraints on this point
829:         const PetscInt *cDof; // The indices of the constrained dofs on this point
830:         value_type     *a;    // The values on this point
831:         PetscInt        offset, cInd = 0;
832:         PetscErrorCode  ierr;

834:         PetscSectionGetDof(section, point, &dim);CHKERRXX(ierr);
835:         PetscSectionGetConstraintDof(section, point, &cDim);CHKERRXX(ierr);
836:         PetscSectionGetOffset(section, point, &offset);CHKERRXX(ierr);
837:         a    = &array[offset];
838:         if (!cDim || setBC) {
839:           if (orientation >= 0) {
840:             for(PetscInt k = 0; k < dim; ++k) {
841:               fuse(a[k], values[i+k]);
842:             }
843:           } else {
844:             for(PetscInt k = 0; k < dim; ++k) {
845:               fuse(a[k], values[i+dim-k-1]);
846:             }
847:           }
848:         } else {
849:           PetscSectionGetConstraintIndices(section, point, &cDof);CHKERRXX(ierr);
850:           if (orientation >= 0) {
851:             for(PetscInt k = 0; k < dim; ++k) {
852:               if ((cInd < cDim) && (k == cDof[cInd])) {++cInd; continue;}
853:               fuse(a[k], values[i+k]);
854:             }
855:           } else {
856:             for(PetscInt k = 0; k < dim; ++k) {
857:               if ((cInd < cDim) && (k == cDof[cInd])) {++cInd; continue;}
858:               fuse(a[k], values[i+dim-k-1]);
859:             }
860:           }
861:         }
862:         i += dim;
863:       }
864:       template<typename Point>
865:       void updatePointFields(const Point& point, void (*fuse)(value_type&, value_type), const bool setBC, const int orientation = 1) {
866:         value_type    *a;
867:         PetscInt       offset;
868:         PetscInt       fOff = 0;

871:         PetscSectionGetOffset(section, point, &offset);CHKERRXX(ierr);
872:         a    = &array[offset];
873:         for(PetscInt f = 0; f < nF; ++f) {
874:           PetscInt    dim;  // The number of dof for field f on this point
875:           PetscInt    comp; // The number of components for field f on this point
876:           PetscInt    cDim; // The nubmer of constraints for field f on this point
877:           const PetscInt *cDof; // The indices of the constrained dofs for field f on this point
878:           PetscInt    cInd = 0;

880:           PetscSectionGetFieldComponents(section, f, &comp);CHKERRXX(ierr);
881:           PetscSectionGetFieldDof(section, point, f, &dim);CHKERRXX(ierr);
882:           PetscSectionGetFieldConstraintDof(section, point, f, &cDim);CHKERRXX(ierr);
883:           if (!cDim || setBC) {
884:             if (orientation >= 0) {
885:               for(PetscInt k = 0; k < dim; ++k) {
886:                 fuse(a[fOff+k], values[j[f]+k]);
887:               }
888:             } else {
889:               for(PetscInt k = dim/comp-1; k >= 0; --k) {
890:                 for(PetscInt c = 0; c < comp; ++c) {
891:                   fuse(a[fOff+(dim/comp-1-k)*comp+c], values[j[f]+k*comp+c]);
892:                 }
893:               }
894:             }
895:           } else {
896:             PetscSectionGetFieldConstraintIndices(section, point, f, &cDof);CHKERRXX(ierr);
897:             if (orientation >= 0) {
898:               for(PetscInt k = 0; k < dim; ++k) {
899:                 if ((cInd < cDim) && (k == cDof[cInd])) {++cInd; continue;}
900:                 fuse(a[fOff+k], values[j[f]+k]);
901:               }
902:             } else {
903:               for(PetscInt k = dim/comp-1; k >= 0; --k) {
904:                 for(PetscInt c = 0; c < comp; ++c) {
905:                   PetscInt ind = k*comp+c;
906:                   if ((cInd < cDim) && (ind == cDof[cInd])) {++cInd; continue;}
907:                   fuse(a[fOff+(dim/comp-1-k)*comp+c], values[j[f]+ind]);
908:                 }
909:               }
910:             }
911:           }
912:           fOff += dim;
913:           j[f] += dim;
914:         }
915:       }
916:     public:
917:       UpdateVecVisitor(const Vec v, const PetscSection s, const value_type *values, InsertMode mode) : v(v), section(s), values(values), mode(mode), nF(0), i(0) {};
918:       UpdateVecVisitor(const Vec v, const PetscSection s, const value_type *values, InsertMode mode, PetscInt numFields, PetscInt fieldSize[]) : v(v), section(s), values(values), mode(mode), nF(numFields), i(0) {

921:         VecGetArray(this->v, &this->array);CHKERRXX(ierr);
922:         PetscMalloc2(numFields,PetscInt,&this->fieldSize,numFields,PetscInt,&j);CHKERRXX(ierr);
923:         for(PetscInt f = 0; f < nF; ++f) {
924:           this->fieldSize[f] = fieldSize[f];
925:         }
926:         this->clear();
927:       };
928:       ~UpdateVecVisitor() {
930:         VecRestoreArray(this->v, &this->array);CHKERRXX(ierr);
931:         PetscFree2(fieldSize,j);CHKERRXX(ierr);
932:       };
933:       template<typename Point>
934:       inline void visitPoint(const Point& point, const int orientation) {
935:         if (nF) {
936:           switch(mode) {
937:           case INSERT_VALUES:
938:             updatePointFields(point, this->insert, false, orientation);break;
939:           case INSERT_ALL_VALUES:
940:             updatePointFields(point, this->insert, true,  orientation);break;
941:           case ADD_VALUES:
942:             updatePointFields(point, this->add, false, orientation);break;
943:           case ADD_ALL_VALUES:
944:             updatePointFields(point, this->add, true,  orientation);break;
945:           default:
946:             throw PETSc::Exception("Invalid mode");
947:           }
948:         } else {
949:           switch(mode) {
950:           case INSERT_VALUES:
951:             updatePoint(point, this->insert, false, orientation);break;
952:           case INSERT_ALL_VALUES:
953:             updatePoint(point, this->insert, true,  orientation);break;
954:           case ADD_VALUES:
955:             updatePoint(point, this->add, false, orientation);break;
956:           case ADD_ALL_VALUES:
957:             updatePoint(point, this->add, true,  orientation);break;
958:           default:
959:             throw PETSc::Exception("Invalid mode");
960:           }
961:         }
962:       }
963:       template<typename Arrow>
964:       inline void visitArrow(const Arrow& arrow, const int orientation) {}
965:     public:
966:       void clear() {
967:         this->i = 0;
968:         if (nF) {
969:           j[0] = 0;
970:           for(PetscInt f = 1; f < nF; ++f) {
971:             j[f] = j[f-1] + fieldSize[f-1];
972:           }
973:         }
974:       };
975:     };
976:     template<typename Section, typename Order, typename Value>
977:     class IndicesVisitor {
978:     public:
979:       typedef Value                        value_type;
980:       typedef typename Section::point_type point_type;
981:     protected:
982:       const Section& section;
983:       // This can't be const because UniformSection can't have a const restrict(), because of stupid map semantics
984:       Order&         order;
985:       int            size;
986:       int            i, p;
987:       // If false, constrained indices are returned as negative values. Otherwise, they are omitted
988:       bool           freeOnly;
989:       // If true, it allows space for constrained variables (even if the indices are not returned) Wierd
990:       bool           skipConstraints;
991:       value_type    *values;
992:       bool           allocated;
993:       point_type    *points;
994:       bool           allocatedPoints;
995:     protected:
996:       void getUnconstrainedIndices(const point_type& p, const int orientation) {
997:         if (i+section.getFiberDimension(p) > size) {throw ALE::Exception("Too many values for IndicesVisitor.");}
998:         if (orientation >= 0) {
999:           const int start = this->order.getIndex(p);
1000:           const int end   = start + section.getFiberDimension(p);

1002:           for(int j = start; j < end; ++j, ++i) {
1003:             this->values[i] = j;
1004:           }
1005:         } else if (!section.getNumSpaces()) {
1006:           const int start = this->order.getIndex(p);
1007:           const int end   = start + section.getFiberDimension(p);

1009:           for(int j = end-1; j >= start; --j, ++i) {
1010:             this->values[i] = j;
1011:           }
1012:         } else {
1013:           const int numSpaces = section.getNumSpaces();
1014:           int       start     = this->order.getIndex(p);

1016:           for(int space = 0; space < numSpaces; ++space) {
1017:             const int end = start + section.getFiberDimension(p, space);

1019:             for(int j = end-1; j >= start; --j, ++i) {
1020:               this->values[i] = j;
1021:             }
1022:             start = end;
1023:           }
1024:         }
1025:       };
1026:       void getConstrainedIndices(const point_type& p, const int orientation) {
1027:         const int cDim = this->section.getConstraintDimension(p);
1028:         if (i+cDim > size) {throw ALE::Exception("Too many values for IndicesVisitor.");}
1029:         typedef typename Section::bc_type::value_type index_type;
1030:         const index_type *cDof  = this->section.getConstraintDof(p);
1031:         const int         start = this->order.getIndex(p);

1033:         if (orientation >= 0) {
1034:           const int dim = this->section.getFiberDimension(p);

1036:           for(int j = start, cInd = 0, k = 0; k < dim; ++k) {
1037:             if ((cInd < cDim) && (k == cDof[cInd])) {
1038:               if (!freeOnly) values[i++] = -(k+1);
1039:               if (skipConstraints) ++j;
1040:               ++cInd;
1041:             } else {
1042:               values[i++] = j++;
1043:             }
1044:           }
1045:         } else {
1046:           int offset  = 0;
1047:           int cOffset = 0;
1048:           int k       = -1;

1050:           for(int space = 0; space < section.getNumSpaces(); ++space) {
1051:             const int  dim = this->section.getFiberDimension(p, space);
1052:             const int tDim = this->section.getConstrainedFiberDimension(p, space);
1053:             int       cInd = (dim - tDim)-1;

1055:             k += dim;
1056:             for(int l = 0, j = start+tDim+offset; l < dim; ++l, --k) {
1057:               if ((cInd >= 0) && (k == cDof[cInd+cOffset])) {
1058:                 if (!freeOnly) values[i++] = -(offset+l+1);
1059:                 if (skipConstraints) --j;
1060:                 --cInd;
1061:               } else {
1062:                 values[i++] = --j;
1063:               }
1064:             }
1065:             k       += dim;
1066:             offset  += dim;
1067:             cOffset += dim - tDim;
1068:           }
1069:         }
1070:       };
1071:     public:
1072:       IndicesVisitor(const Section& s, Order& o, const int size, const bool unique = false) : section(s), order(o), size(size), i(0), p(0), freeOnly(false), skipConstraints(false) {
1073:         this->values    = new value_type[this->size];
1074:         this->allocated = true;
1075:         if (unique) {
1076:           this->points          = new point_type[this->size];
1077:           this->allocatedPoints = true;
1078:         } else {
1079:           this->points          = NULL;
1080:           this->allocatedPoints = false;
1081:         }
1082:       };
1083:       IndicesVisitor(const Section& s, Order& o, const int size, value_type *values, const bool unique = false) : section(s), order(o), size(size), i(0), p(0), freeOnly(false), skipConstraints(false) {
1084:         this->values    = values;
1085:         this->allocated = false;
1086:         if (unique) {
1087:           this->points          = new point_type[this->size];
1088:           this->allocatedPoints = true;
1089:         } else {
1090:           this->points          = NULL;
1091:           this->allocatedPoints = false;
1092:         }
1093:       };
1094:       ~IndicesVisitor() {
1095:         if (this->allocated) {delete [] this->values;}
1096:         if (this->allocatedPoints) {delete [] this->points;}
1097:       };
1098:       inline void visitPoint(const point_type& point, const int orientation) {
1099:         if (p >= size) {
1100:           ostringstream msg;
1101:           msg << "Too many points (>" << size << ")for IndicesVisitor visitor";
1102:           throw ALE::Exception(msg.str().c_str());
1103:         }
1104:         if (points) {
1105:           int pp;
1106:           for(pp = 0; pp < p; ++pp) {if (points[pp] == point) break;}
1107:           if (pp != p) return;
1108:           points[p++] = point;
1109:         }
1110:         const int cDim = this->section.getConstraintDimension(point);

1112:         if (!cDim) {
1113:           this->getUnconstrainedIndices(point, orientation);
1114:         } else {
1115:           this->getConstrainedIndices(point, orientation);
1116:         }
1117:       }
1118:       template<typename Arrow>
1119:       inline void visitArrow(const Arrow& arrow, const int orientation) {}
1120:     public:
1121:       const value_type *getValues() const {return this->values;};
1122:       int  getSize() const {return this->i;};
1123:       int  getMaxSize() const {return this->size;};
1124:       void ensureSize(const int size) {
1125:         this->clear();
1126:         if (size > this->size) {
1127:           this->size = size;
1128:           if (this->allocated) {delete [] this->values;}
1129:           this->values = new value_type[this->size];
1130:           this->allocated = true;
1131:           if (this->allocatedPoints) {delete [] this->points;}
1132:           this->points = new point_type[this->size];
1133:           this->allocatedPoints = true;
1134:         }
1135:       };
1136:       void clear() {this->i = 0; this->p = 0;};
1137:     };
1138:     template<typename Order, typename Value>
1139:     class IndicesVisitor<PetscSection, Order, Value> {
1140:     public:
1141:       typedef Value                      value_type;
1142:       typedef typename Order::point_type point_type;
1143:     protected:
1144:       const PetscSection& section;
1145:       // This can't be const because UniformSection can't have a const restrict(), because of stupid map semantics
1146:       Order&              order;
1147:       int                 size;
1148:       int                 i, p;
1149:       bool                setBC;           // If true, returns indices for constrained dofs, otherwise negative values are returned
1150:       //bool                skipConstraints; // If true, do not return constrained indices at all
1151:       value_type         *values;
1152:       bool                allocated;
1153:       point_type         *points;
1154:       PetscInt            nF;
1155:       PetscInt           *fieldSize;
1156:       PetscInt           *j;
1157:     protected:
1158:       void updatePoint(const point_type& point, const bool setBC, const int orientation = 1) {
1159:         PetscInt        dim;  // The number of dof on this point
1160:         PetscInt        cDim; // The nubmer of constraints on this point
1161:         const PetscInt *cDof; // The indices of the constrained dofs on this point
1162:         PetscInt        offset = this->order.getIndex(point);
1163:         PetscInt        cInd   = 0;
1164:         PetscErrorCode  ierr;

1166:         PetscSectionGetDof(section, point, &dim);CHKERRXX(ierr);
1167:         PetscSectionGetConstraintDof(section, point, &cDim);CHKERRXX(ierr);
1168:         if (!cDim || setBC) {
1169:           if (orientation >= 0) {
1170:             for(PetscInt k = 0; k < dim; ++k) {
1171:               values[i+k] = offset+k;
1172:             }
1173:           } else {
1174:             for(PetscInt k = 0; k < dim; ++k) {
1175:               values[i+dim-k-1] = offset+k;
1176:             }
1177:           }
1178:         } else {
1179:           PetscSectionGetConstraintIndices(section, point, &cDof);CHKERRXX(ierr);
1180:           if (orientation >= 0) {
1181:             for(PetscInt k = 0; k < dim; ++k) {
1182:               if ((cInd < cDim) && (k == cDof[cInd])) {
1183:                 // Insert check for returning constrained indices
1184:                 values[i+k] = -(offset+k+1);
1185:                 ++cInd;
1186:               } else {
1187:                 values[i+k] = offset+k;
1188:               }
1189:             }
1190:           } else {
1191:             for(PetscInt k = 0; k < dim; ++k) {
1192:               if ((cInd < cDim) && (k == cDof[cInd])) {
1193:                 // Insert check for returning constrained indices
1194:                 values[i+dim-k-1] = -(offset+k+1);
1195:                 ++cInd;
1196:               } else {
1197:                 values[i+dim-k-1] = offset+k;
1198:               }
1199:             }
1200:           }
1201:         }
1202:         i += dim;
1203:       }
1204:       void updatePointFields(const point_type& point, const bool setBC, const int orientation = 1) {
1205:         PetscInt       offset = this->order.getIndex(point);
1206:         PetscInt       fOff   = 0;

1209:         for(PetscInt f = 0; f < nF; ++f) {
1210:           PetscInt  dim;  // The number of dof for field f on this point
1211:           PetscInt  comp; // The number of components for field f on this point
1212:           PetscInt  cDim; // The nubmer of constraints for field f on this point
1213:           const PetscInt *cDof; // The indices of the constrained dofs for field f on this point
1214:           PetscInt  cInd = 0;

1216:           PetscSectionGetFieldComponents(section, f, &comp);CHKERRXX(ierr);
1217:           PetscSectionGetFieldDof(section, point, f, &dim);CHKERRXX(ierr);
1218:           PetscSectionGetFieldConstraintDof(section, point, f, &cDim);CHKERRXX(ierr);
1219:           if (!cDim || setBC) {
1220:             if (orientation >= 0) {
1221:               for(PetscInt k = 0; k < dim; ++k) {
1222:                 values[j[f]+k] = offset+fOff+k;
1223:               }
1224:             } else {
1225:               for(PetscInt k = dim/comp-1; k >= 0; --k) {
1226:                 for(PetscInt c = 0; c < comp; ++c) {
1227:                   values[j[f]+(dim/comp-1-k)*comp+c] = offset+fOff+k*comp+c;
1228:                 }
1229:               }
1230:             }
1231:           } else {
1232:             PetscSectionGetFieldConstraintIndices(section, point, f, &cDof);CHKERRXX(ierr);
1233:             if (orientation >= 0) {
1234:               for(PetscInt k = 0; k < dim; ++k) {
1235:                 if ((cInd < cDim) && (k == cDof[cInd])) {
1236:                   values[j[f]+k] = -(offset+fOff+k+1);
1237:                   ++cInd;
1238:                 } else {
1239:                   values[j[f]+k] = offset+fOff+k;
1240:                 }
1241:               }
1242:             } else {
1243:               for(PetscInt k = dim/comp-1; k >= 0; --k) {
1244:                 for(PetscInt c = 0; c < comp; ++c) {
1245:                   PetscInt ind = k*comp+c;
1246:                   if ((cInd < cDim) && (ind == cDof[cInd])) {
1247:                     values[j[f]+(dim/comp-1-k)*comp+c] = -(offset+fOff+ind+1);
1248:                     ++cInd;
1249:                   } else {
1250:                     values[j[f]+(dim/comp-1-k)*comp+c] = offset+fOff+ind;
1251:                   }
1252:                 }
1253:               }
1254:             }
1255:           }
1256:           fOff += dim - cDim;
1257:           j[f] += dim;
1258:           i    += dim;
1259:         }
1260:       }
1261:     public:
1262:       IndicesVisitor(const PetscSection& s, Order& o, const int size, const bool unique = false, const PetscInt fieldSize[] = NULL) : section(s), order(o), size(size), i(0), p(0), setBC(false) {

1265:         PetscMalloc(this->size * sizeof(value_type), &this->values);CHKERRXX(ierr);
1266:         this->allocated = true;
1267:         this->points    = NULL;
1268:         if (unique) {
1269:           PetscMalloc(this->size * sizeof(point_type), &this->points);CHKERRXX(ierr);
1270:         }
1271:         nF = 0;
1272:         this->fieldSize = this->j = NULL;
1273:         if (fieldSize) {
1274:           PetscSectionGetNumFields(section, &nF);CHKERRXX(ierr);
1275:           PetscMalloc2(nF,PetscInt,&this->fieldSize,nF,PetscInt,&j);CHKERRXX(ierr);
1276:           for(PetscInt f = 0; f < nF; ++f) {
1277:             this->fieldSize[f] = fieldSize[f];
1278:           }
1279:         }
1280:         this->clear();
1281:       };
1282:       IndicesVisitor(const PetscSection& s, Order& o, const int size, value_type *values, const bool unique = false, const PetscInt fieldSize[] = NULL) : section(s), order(o), size(size), i(0), p(0), setBC(false) {

1285:         this->values    = values;
1286:         this->allocated = false;
1287:         this->points    = NULL;
1288:         if (unique) {
1289:           PetscMalloc(this->size * sizeof(point_type), &this->points);CHKERRXX(ierr);
1290:         }
1291:         nF = 0;
1292:         this->fieldSize = this->j = NULL;
1293:         if (fieldSize) {
1294:           PetscSectionGetNumFields(section, &nF);CHKERRXX(ierr);
1295:           PetscMalloc2(nF,PetscInt,&fieldSize,nF,PetscInt,&j);CHKERRXX(ierr);
1296:           for(PetscInt f = 0; f < nF; ++f) {
1297:             this->fieldSize[f] = fieldSize[f];
1298:           }
1299:         }
1300:         this->clear();
1301:       };
1302:       ~IndicesVisitor() {
1304:         if (this->allocated) {PetscFree(values);CHKERRXX(ierr);}
1305:         PetscFree(points);CHKERRXX(ierr);
1306:         PetscFree2(fieldSize,j);CHKERRXX(ierr);
1307:       };
1308:     public:
1309:       inline void visitPoint(const point_type& point, const int orientation) {
1310:         if (p >= size) {
1311:           ostringstream msg;
1312:           msg << "Too many points (>" << size << ")for IndicesVisitor visitor";
1313:           throw ALE::Exception(msg.str().c_str());
1314:         }
1315:         if (points) {
1316:           PetscInt pp;
1317:           for(pp = 0; pp < p; ++pp) {if (points[pp] == point) break;}
1318:           if (pp != p) return;
1319:           points[p++] = point;
1320:         }
1321:         if (nF) {
1322:           updatePointFields(point, setBC, orientation);
1323:         } else {
1324:           updatePoint(point, setBC, orientation);
1325:         }
1326:       }
1327:       template<typename Arrow>
1328:       inline void visitArrow(const Arrow& arrow, const int orientation) {}
1329:     public:
1330:       const value_type *getValues() const {return this->values;};
1331:       int  getSize() const {return this->i;};
1332:       int  getMaxSize() const {return this->size;};
1333:       void ensureSize(const int size) {
1334:         this->clear();
1335:         if (size > this->size) {

1338:           this->size = size;
1339:           if (this->allocated) {PetscFree(this->values);CHKERRXX(ierr);}
1340:           PetscMalloc(this->size * sizeof(value_type), &this->values);CHKERRXX(ierr);
1341:           this->allocated = true;
1342:           PetscFree(this->points);CHKERRXX(ierr);
1343:           PetscMalloc(this->size * sizeof(point_type), &this->points);CHKERRXX(ierr);
1344:         }
1345:       };
1346:       void clear() {
1347:         this->p = 0;
1348:         this->i = 0;
1349:         if (nF) {
1350:           j[0] = 0;
1351:           for(PetscInt f = 1; f < nF; ++f) {
1352:             j[f] = j[f-1] + fieldSize[f-1];
1353:           }
1354:         }
1355:       };
1356:     };
1357:     template<typename Sieve, typename Label>
1358:     class MarkVisitor {
1359:     protected:
1360:       Label& label;
1361:       int    marker;
1362:     public:
1363:       MarkVisitor(Label& l, const int marker) : label(l), marker(marker) {};
1364:       inline void visitPoint(const typename Sieve::point_type& point) {
1365:         this->label.setCone(this->marker, point);
1366:       };
1367:       inline void visitArrow(const typename Sieve::arrow_type&) {};
1368:     };
1369:   };

1371:   template<typename Sieve>
1372:   class ISieveTraversal {
1373:   public:
1374:     typedef typename Sieve::point_type point_type;
1375:   public:
1376:     template<typename Visitor>
1377:     static void orientedClosure(const Sieve& sieve, const point_type& p, Visitor& v) {
1378:       typedef ISieveVisitor::PointRetriever<Sieve,Visitor> Retriever;
1379:       typedef ISieveVisitor::PointRetriever<Sieve,Retriever> TmpRetriever;
1380:       Retriever    pV(200, v, true); // Correct estimate is pow(std::max(1, sieve->getMaxConeSize()), mesh->depth())
1381:       TmpRetriever cV[2] = {TmpRetriever(200,pV), TmpRetriever(200,pV)};
1382:       int          c     = 0;

1384:       v.visitPoint(p, 0);
1385:       // Cone is guarateed to be ordered correctly
1386:       sieve.orientedCone(p, cV[c]);

1388:       while(cV[c].getOrientedSize()) {
1389:         const typename Retriever::oriented_point_type *cone     = cV[c].getOrientedPoints();
1390:         const int                                      coneSize = cV[c].getOrientedSize();
1391:         c = 1 - c;

1393:         for(int p = 0; p < coneSize; ++p) {
1394:           const typename Retriever::point_type& point     = cone[p].first;
1395:           int                                   pO        = cone[p].second == 0 ? 1 : cone[p].second;
1396:           const int                             pConeSize = sieve.getConeSize(point);

1398:           if (pO < 0) {
1399:             if (pO == -pConeSize) {
1400:               sieve.orientedReverseCone(point, cV[c]);
1401:             } else {
1402:               const int numSkip = sieve.getConeSize(point) + pO;

1404:               cV[c].setSkip(cV[c].getSize()+numSkip);
1405:               cV[c].setLimit(cV[c].getSize()+pConeSize);
1406:               sieve.orientedReverseCone(point, cV[c]);
1407:               sieve.orientedReverseCone(point, cV[c]);
1408:               cV[c].setSkip(0);
1409:               cV[c].setLimit(0);
1410:             }
1411:           } else {
1412:             if (pO == 1) {
1413:               sieve.orientedCone(point, cV[c]);
1414:             } else {
1415:               const int numSkip = pO-1;

1417:               cV[c].setSkip(cV[c].getSize()+numSkip);
1418:               cV[c].setLimit(cV[c].getSize()+pConeSize);
1419:               sieve.orientedCone(point, cV[c]);
1420:               sieve.orientedCone(point, cV[c]);
1421:               cV[c].setSkip(0);
1422:               cV[c].setLimit(0);
1423:             }
1424:           }
1425:         }
1426:         cV[1-c].clear();
1427:       }
1428: #if 0
1429:       // These contain arrows paired with orientations from the \emph{previous} arrow
1430:       Obj<orientedArrowArray> cone    = new orientedArrowArray();
1431:       Obj<orientedArrowArray> base    = new orientedArrowArray();
1432:       coneSet                 seen;

1434:       for(typename sieve_type::traits::coneSequence::iterator c_iter = initCone->begin(); c_iter != initCone->end(); ++c_iter) {
1435:         const arrow_type arrow(*c_iter, p);

1437:         cone->push_back(oriented_arrow_type(arrow, 1)); // Notice the orientation of leaf cells is always 1
1438:         closure->push_back(oriented_point_type(*c_iter, orientation->restrictPoint(arrow)[0])); // However, we return the actual arrow orientation
1439:       }
1440:       for(int i = 1; i < depth; ++i) {
1441:         Obj<orientedArrowArray> tmp = cone; cone = base; base = tmp;

1443:         cone->clear();
1444:         for(typename orientedArrowArray::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
1445:           const arrow_type&                                     arrow = b_iter->first; // This is an arrow considered in the previous round
1446:           const Obj<typename sieve_type::traits::coneSequence>& pCone = sieve->cone(arrow.source); // We are going to get the cone of this guy
1447:           typename arrow_section_type::value_type               o     = orientation->restrictPoint(arrow)[0]; // The orientation of arrow, which is our pO

1449:           if (b_iter->second < 0) { // This is the problem. The second orientation is carried up, being from the previous round
1450:             o = -(o+1);
1451:           }
1452:           if (o < 0) {
1453:             const int size = pCone->size();

1455:             if (o == -size) {
1456:               for(typename sieve_type::traits::coneSequence::reverse_iterator c_iter = pCone->rbegin(); c_iter != pCone->rend(); ++c_iter) {
1457:                 if (seen.find(*c_iter) == seen.end()) {
1458:                   const arrow_type newArrow(*c_iter, arrow.source);
1459:                   int              pointO = orientation->restrictPoint(newArrow)[0];

1461:                   seen.insert(*c_iter);
1462:                   cone->push_back(oriented_arrow_type(newArrow, o));
1463:                   closure->push_back(oriented_point_type(*c_iter, pointO ? -(pointO+1): pointO));
1464:                 }
1465:               }
1466:             } else {
1467:               const int numSkip = size + o;
1468:               int       count   = 0;

1470:               for(typename sieve_type::traits::coneSequence::reverse_iterator c_iter = pCone->rbegin(); c_iter != pCone->rend(); ++c_iter, ++count) {
1471:                 if (count < numSkip) continue;
1472:                 if (seen.find(*c_iter) == seen.end()) {
1473:                   const arrow_type newArrow(*c_iter, arrow.source);
1474:                   int              pointO = orientation->restrictPoint(newArrow)[0];

1476:                   seen.insert(*c_iter);
1477:                   cone->push_back(oriented_arrow_type(newArrow, o));
1478:                   closure->push_back(oriented_point_type(*c_iter, pointO ? -(pointO+1): pointO));
1479:                 }
1480:               }
1481:               count = 0;
1482:               for(typename sieve_type::traits::coneSequence::reverse_iterator c_iter = pCone->rbegin(); c_iter != pCone->rend(); ++c_iter, ++count) {
1483:                 if (count >= numSkip) break;
1484:                 if (seen.find(*c_iter) == seen.end()) {
1485:                   const arrow_type newArrow(*c_iter, arrow.source);
1486:                   int              pointO = orientation->restrictPoint(newArrow)[0];

1488:                   seen.insert(*c_iter);
1489:                   cone->push_back(oriented_arrow_type(newArrow, o));
1490:                   closure->push_back(oriented_point_type(*c_iter, pointO ? -(pointO+1): pointO));
1491:                 }
1492:               }
1493:             }
1494:           } else {
1495:             if (o == 1) {
1496:               for(typename sieve_type::traits::coneSequence::iterator c_iter = pCone->begin(); c_iter != pCone->end(); ++c_iter) {
1497:                 if (seen.find(*c_iter) == seen.end()) {
1498:                   const arrow_type newArrow(*c_iter, arrow.source);

1500:                   seen.insert(*c_iter);
1501:                   cone->push_back(oriented_arrow_type(newArrow, o));
1502:                   closure->push_back(oriented_point_type(*c_iter, orientation->restrictPoint(newArrow)[0]));
1503:                 }
1504:               }
1505:             } else {
1506:               const int numSkip = o-1;
1507:               int       count   = 0;

1509:               for(typename sieve_type::traits::coneSequence::iterator c_iter = pCone->begin(); c_iter != pCone->end(); ++c_iter, ++count) {
1510:                 if (count < numSkip) continue;
1511:                 if (seen.find(*c_iter) == seen.end()) {
1512:                   const arrow_type newArrow(*c_iter, arrow.source);

1514:                   seen.insert(*c_iter);
1515:                   cone->push_back(oriented_arrow_type(newArrow, o));
1516:                   closure->push_back(oriented_point_type(*c_iter, orientation->restrictPoint(newArrow)[0]));
1517:                 }
1518:               }
1519:               count = 0;
1520:               for(typename sieve_type::traits::coneSequence::iterator c_iter = pCone->begin(); c_iter != pCone->end(); ++c_iter, ++count) {
1521:                 if (count >= numSkip) break;
1522:                 if (seen.find(*c_iter) == seen.end()) {
1523:                   const arrow_type newArrow(*c_iter, arrow.source);

1525:                   seen.insert(*c_iter);
1526:                   cone->push_back(oriented_arrow_type(newArrow, o));
1527:                   closure->push_back(oriented_point_type(*c_iter, orientation->restrictPoint(newArrow)[0]));
1528:                 }
1529:               }
1530:             }
1531:           }
1532:         }
1533:       }
1534: #endif
1535:     }
1536:     template<typename Visitor>
1537:     static void orientedStar(const Sieve& sieve, const point_type& p, Visitor& v) {
1538:       typedef ISieveVisitor::PointRetriever<Sieve,Visitor> Retriever;
1539:       Retriever sV[2] = {Retriever(200,v), Retriever(200,v)};
1540:       int       s     = 0;

1542:       v.visitPoint(p, 0);
1543:       // Support is guarateed to be ordered correctly
1544:       sieve.orientedSupport(p, sV[s]);

1546:       while(sV[s].getOrientedSize()) {
1547:         const typename Retriever::oriented_point_type *support     = sV[s].getOrientedPoints();
1548:         const int                                      supportSize = sV[s].getOrientedSize();
1549:         s = 1 - s;

1551:         for(int p = 0; p < supportSize; ++p) {
1552:           const typename Retriever::point_type& point        = support[p].first;
1553:           int                                   pO           = support[p].second == 0 ? 1 : support[p].second;
1554:           const int                             pSupportSize = sieve.getSupportSize(point);

1556:           if (pO < 0) {
1557:             if (pO == -pSupportSize) {
1558:               sieve.orientedReverseSupport(point, sV[s]);
1559:             } else {
1560:               const int numSkip = sieve.getSupportSize(point) + pO;

1562:               sV[s].setSkip(sV[s].getSize()+numSkip);
1563:               sV[s].setLimit(sV[s].getSize()+pSupportSize);
1564:               sieve.orientedReverseSupport(point, sV[s]);
1565:               sieve.orientedReverseSupport(point, sV[s]);
1566:               sV[s].setSkip(0);
1567:               sV[s].setLimit(0);
1568:             }
1569:           } else {
1570:             if (pO == 1) {
1571:               sieve.orientedSupport(point, sV[s]);
1572:             } else {
1573:               const int numSkip = pO-1;

1575:               sV[s].setSkip(sV[s].getSize()+numSkip);
1576:               sV[s].setLimit(sV[s].getSize()+pSupportSize);
1577:               sieve.orientedSupport(point, sV[s]);
1578:               sieve.orientedSupport(point, sV[s]);
1579:               sV[s].setSkip(0);
1580:               sV[s].setLimit(0);
1581:             }
1582:           }
1583:         }
1584:         sV[1-s].clear();
1585:       }
1586:     }
1587:   };

1589:   namespace IFSieveDef {
1590:     template<typename PointType_>
1591:     class Sequence {
1592:     public:
1593:       typedef PointType_ point_type;
1594:       class const_iterator {
1595:       public:
1596:         // Standard iterator typedefs
1597:         typedef std::input_iterator_tag iterator_category;
1598:         typedef PointType_              value_type;
1599:         typedef int                     difference_type;
1600:         typedef value_type*             pointer;
1601:         typedef value_type&             reference;
1602:       protected:
1603:         const point_type *_data;
1604:         int               _pos;
1605:       public:
1606:         const_iterator(const point_type data[], const int pos) : _data(data), _pos(pos) {};
1607:         virtual ~const_iterator() {};
1608:       public:
1609:         virtual bool              operator==(const const_iterator& iter) const {return this->_pos == iter._pos;};
1610:         virtual bool              operator!=(const const_iterator& iter) const {return this->_pos != iter._pos;};
1611:         virtual const value_type  operator*() const {return this->_data[this->_pos];};
1612:         virtual const_iterator&   operator++() {++this->_pos; return *this;};
1613:         virtual const_iterator    operator++(int n) {
1614:           const_iterator tmp(*this);
1615:           ++this->_pos;
1616:           return tmp;
1617:         };
1618:       };
1619:       typedef const_iterator iterator;
1620:     protected:
1621:       const point_type *_data;
1622:       int               _begin;
1623:       int               _end;
1624:     public:
1625:       Sequence(const point_type data[], const int begin, const int end) : _data(data), _begin(begin), _end(end) {};
1626:       virtual ~Sequence() {};
1627:     public:
1628:       virtual iterator begin() const {return iterator(_data, _begin);};
1629:       virtual iterator end()   const {return iterator(_data, _end);};
1630:       size_t size() const {return(_end - _begin);}
1631:       void reset(const point_type data[], const int begin, const int end) {_data = data; _begin = begin; _end = end;};
1632:     };
1633:   }

1635:   // Interval Final Sieve
1636:   // This is just two CSR matrices that give cones and supports
1637:   //   It is completely static and cannot be resized
1638:   //   It will operator on visitors, rather than sequences (which are messy)
1639:   template<typename Point_, typename Allocator_ = malloc_allocator<Point_> >
1640:   class IFSieve : public ParallelObject {
1641:   public:
1642:     // Types
1643:     typedef IFSieve<Point_,Allocator_>         this_type;
1644:     typedef Point_                             point_type;
1645:     typedef SimpleArrow<point_type,point_type> arrow_type;
1646:     typedef typename arrow_type::source_type   source_type;
1647:     typedef typename arrow_type::target_type   target_type;
1648:     typedef int                                index_type;
1649:     // Allocators
1650:     typedef Allocator_                                                        point_allocator_type;
1651:     typedef typename point_allocator_type::template rebind<index_type>::other index_allocator_type;
1652:     typedef typename point_allocator_type::template rebind<int>::other        int_allocator_type;
1653:     // Interval
1654:     typedef Interval<point_type, point_allocator_type> chart_type;
1655:     // Dynamic structure
1656:     typedef std::map<point_type, std::vector<point_type> > newpoints_type;
1657:     // Iterator interface
1658:     typedef typename IFSieveDef::Sequence<point_type> coneSequence;
1659:     typedef typename IFSieveDef::Sequence<point_type> supportSequence;
1660:     // Compatibility types for SieveAlgorithms (until we rewrite for visitors)
1661:     typedef std::set<point_type>   pointSet;
1662:     typedef ALE::array<point_type> pointArray;
1663:     typedef pointSet               coneSet;
1664:     typedef pointSet               supportSet;
1665:     typedef pointArray             coneArray;
1666:     typedef pointArray             supportArray;
1667:   protected:
1668:     // Arrow Containers
1669:     typedef index_type *offsets_type;
1670:     typedef point_type *cones_type;
1671:     typedef point_type *supports_type;
1672:     // Decorators
1673:     typedef int        *orientations_type;
1674:   protected:
1675:     // Data
1676:     bool                 indexAllocated;
1677:     offsets_type         coneOffsets;
1678:     offsets_type         supportOffsets;
1679:     bool                 pointAllocated;
1680:     index_type           maxConeSize;
1681:     index_type           maxSupportSize;
1682:     index_type           baseSize;
1683:     index_type           capSize;
1684:     cones_type           cones;
1685:     supports_type        supports;
1686:     bool                 orientCones;
1687:     orientations_type    coneOrientations;
1688:     chart_type           chart;
1689:     int_allocator_type   intAlloc;
1690:     index_allocator_type indexAlloc;
1691:     point_allocator_type pointAlloc;
1692:     newpoints_type       newCones;
1693:     newpoints_type       newSupports;
1694:     // Sequences
1695:     Obj<coneSequence>    coneSeq;
1696:     Obj<supportSequence> supportSeq;
1697:   protected: // Memory Management
1698:     void createIndices() {
1699:       this->coneOffsets = indexAlloc.allocate(this->chart.size()+1);
1700:       this->coneOffsets -= this->chart.min();
1701:       for(index_type i = this->chart.min(); i <= this->chart.max(); ++i) {indexAlloc.construct(this->coneOffsets+i, index_type(0));}
1702:       this->supportOffsets = indexAlloc.allocate(this->chart.size()+1);
1703:       this->supportOffsets -= this->chart.min();
1704:       for(index_type i = this->chart.min(); i <= this->chart.max(); ++i) {indexAlloc.construct(this->supportOffsets+i, index_type(0));}
1705:       this->indexAllocated = true;
1706:     };
1707:     void destroyIndices(const chart_type& chart, offsets_type *coneOffsets, offsets_type *supportOffsets) {
1708:       if (*coneOffsets) {
1709:         for(index_type i = chart.min(); i <= chart.max(); ++i) {indexAlloc.destroy((*coneOffsets)+i);}
1710:         *coneOffsets += chart.min();
1711:         indexAlloc.deallocate(*coneOffsets, chart.size()+1);
1712:         *coneOffsets = NULL;
1713:       }
1714:       if (*supportOffsets) {
1715:         for(index_type i = chart.min(); i <= chart.max(); ++i) {indexAlloc.destroy((*supportOffsets)+i);}
1716:         *supportOffsets += chart.min();
1717:         indexAlloc.deallocate(*supportOffsets, chart.size()+1);
1718:         *supportOffsets = NULL;
1719:       }
1720:     };
1721:     void destroyIndices() {
1722:       this->destroyIndices(this->chart, &this->coneOffsets, &this->supportOffsets);
1723:       this->indexAllocated = false;
1724:       this->maxConeSize    = 0;
1725:       this->maxSupportSize = 0;
1726:       this->baseSize       = -1;
1727:       this->capSize        = -1;
1728:     };
1729:     void createPoints() {
1730:       this->cones = pointAlloc.allocate(this->coneOffsets[this->chart.max()]-this->coneOffsets[this->chart.min()]);
1731:       for(index_type i = this->coneOffsets[this->chart.min()]; i < this->coneOffsets[this->chart.max()]; ++i) {pointAlloc.construct(this->cones+i, point_type(0));}
1732:       this->supports = pointAlloc.allocate(this->supportOffsets[this->chart.max()]-this->supportOffsets[this->chart.min()]);
1733:       for(index_type i = this->supportOffsets[this->chart.min()]; i < this->supportOffsets[this->chart.max()]; ++i) {pointAlloc.construct(this->supports+i, point_type(0));}
1734:       if (orientCones) {
1735:         this->coneOrientations = intAlloc.allocate(this->coneOffsets[this->chart.max()]-this->coneOffsets[this->chart.min()]);
1736:         for(index_type i = this->coneOffsets[this->chart.min()]; i < this->coneOffsets[this->chart.max()]; ++i) {intAlloc.construct(this->coneOrientations+i, 0);}
1737:       }
1738:       this->pointAllocated = true;
1739:     };
1740:     void destroyPoints(const chart_type& chart, const offsets_type coneOffsets, cones_type *cones, const offsets_type supportOffsets, supports_type *supports, orientations_type *coneOrientations) {
1741:       if (*cones) {
1742:         for(index_type i = coneOffsets[chart.min()]; i < coneOffsets[chart.max()]; ++i) {pointAlloc.destroy((*cones)+i);}
1743:         pointAlloc.deallocate(*cones, coneOffsets[chart.max()]-coneOffsets[chart.min()]);
1744:         *cones = NULL;
1745:       }
1746:       if (*supports) {
1747:         for(index_type i = supportOffsets[chart.min()]; i < supportOffsets[chart.max()]; ++i) {pointAlloc.destroy((*supports)+i);}
1748:         pointAlloc.deallocate(*supports, supportOffsets[chart.max()]-supportOffsets[chart.min()]);
1749:         *supports = NULL;
1750:       }
1751:       if (*coneOrientations) {
1752:         for(index_type i = coneOffsets[chart.min()]; i < coneOffsets[chart.max()]; ++i) {pointAlloc.destroy((*coneOrientations)+i);}
1753:         intAlloc.deallocate(*coneOrientations, coneOffsets[chart.max()]-coneOffsets[chart.min()]);
1754:         *coneOrientations = NULL;
1755:       }
1756:     };
1757:     void destroyPoints() {
1758:       this->destroyPoints(this->chart, this->coneOffsets, &this->cones, this->supportOffsets, &this->supports, &this->coneOrientations);
1759:       this->pointAllocated = false;
1760:     };
1761:     void prefixSum(const offsets_type array) {
1762:       for(index_type p = this->chart.min()+1; p <= this->chart.max(); ++p) {
1763:         array[p] = array[p] + array[p-1];
1764:       }
1765:     };
1766:     void calculateBaseAndCapSize() {
1767:       this->baseSize = 0;
1768:       for(point_type p = this->chart.min(); p < this->chart.max(); ++p) {
1769:         if (this->coneOffsets[p+1]-this->coneOffsets[p] > 0) {
1770:           ++this->baseSize;
1771:         }
1772:       }
1773:       this->capSize = 0;
1774:       for(point_type p = this->chart.min(); p < this->chart.max(); ++p) {
1775:         if (this->supportOffsets[p+1]-this->supportOffsets[p] > 0) {
1776:           ++this->capSize;
1777:         }
1778:       }
1779:     };
1780:   public:
1781:     IFSieve(const MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug), indexAllocated(false), coneOffsets(NULL), supportOffsets(NULL), pointAllocated(false), maxConeSize(-1), maxSupportSize(-1), baseSize(-1), capSize(-1), cones(NULL), supports(NULL), orientCones(true), coneOrientations(NULL) {
1782:       this->coneSeq    = new coneSequence(NULL, 0, 0);
1783:       this->supportSeq = new supportSequence(NULL, 0, 0);
1784:     };
1785:     IFSieve(const MPI_Comm comm, const point_type& min, const point_type& max, const int debug = 0) : ParallelObject(comm, debug), indexAllocated(false), coneOffsets(NULL), supportOffsets(NULL), pointAllocated(false), maxConeSize(-1), maxSupportSize(-1), baseSize(-1), capSize(-1), cones(NULL), supports(NULL), orientCones(true), coneOrientations(NULL) {
1786:       this->setChart(chart_type(min, max));
1787:       this->coneSeq    = new coneSequence(NULL, 0, 0);
1788:       this->supportSeq = new supportSequence(NULL, 0, 0);
1789:     };
1790:     ~IFSieve() {
1791:       this->destroyPoints();
1792:       this->destroyIndices();
1793:     };
1794:   public: // Accessors
1795:     const chart_type& getChart() const {return this->chart;};
1796:     void setChart(const chart_type& chart) {
1797:       this->destroyPoints();
1798:       this->destroyIndices();
1799:       this->chart = chart;
1800:       this->createIndices();
1801:     };
1802:     index_type getMaxConeSize() const {
1803:       return this->maxConeSize;
1804:     };
1805:     index_type getMaxSupportSize() const {
1806:       return this->maxSupportSize;
1807:     };
1808:     bool baseContains(const point_type& p) const {
1809:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
1810:       this->chart.checkPoint(p);

1812:       if (this->coneOffsets[p+1]-this->coneOffsets[p] > 0) {
1813:         return true;
1814:       }
1815:       return false;
1816:     };
1817:     bool orientedCones() const {return this->orientCones;};
1818:     // Raw array access
1819:     offsets_type      getConeOffsets() {return this->coneOffsets;};
1820:     offsets_type      getSupportOffsets() {return this->supportOffsets;};
1821:     cones_type        getCones() {return this->cones;};
1822:     supports_type     getSupports() {return this->supports;};
1823:     orientations_type getConeOrientations() {return this->coneOrientations;};
1824:   public: // Construction
1825:     index_type getConeSize(const point_type& p) const {
1826:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
1827:       this->chart.checkPoint(p);
1828:       return this->coneOffsets[p+1]-this->coneOffsets[p];
1829:     };
1830:     void setConeSize(const point_type& p, const index_type c) {
1831:       if (this->pointAllocated) {throw ALE::Exception("IFSieve points have already been allocated.");}
1832:       this->chart.checkPoint(p);
1833:       this->coneOffsets[p+1] = c;
1834:       this->maxConeSize = std::max(this->maxConeSize, c);
1835:     };
1836:     void addConeSize(const point_type& p, const index_type c) {
1837:       if (this->pointAllocated) {throw ALE::Exception("IFSieve points have already been allocated.");}
1838:       this->chart.checkPoint(p);
1839:       this->coneOffsets[p+1] += c;
1840:       this->maxConeSize = std::max(this->maxConeSize, this->coneOffsets[p+1]);
1841:     };
1842:     index_type getSupportSize(const point_type& p) const {
1843:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
1844:       this->chart.checkPoint(p);
1845:       return this->supportOffsets[p+1]-this->supportOffsets[p];
1846:     };
1847:     void setSupportSize(const point_type& p, const index_type s) {
1848:       if (this->pointAllocated) {throw ALE::Exception("IFSieve points have already been allocated.");}
1849:       this->chart.checkPoint(p);
1850:       this->supportOffsets[p+1] = s;
1851:       this->maxSupportSize = std::max(this->maxSupportSize, s);
1852:     };
1853:     void addSupportSize(const point_type& p, const index_type s) {
1854:       if (this->pointAllocated) {throw ALE::Exception("IFSieve points have already been allocated.");}
1855:       this->chart.checkPoint(p);
1856:       this->supportOffsets[p+1] += s;
1857:       this->maxSupportSize = std::max(this->maxSupportSize, this->supportOffsets[p+1]);
1858:     };
1859:     void allocate() {
1860:       if (this->pointAllocated) {throw ALE::Exception("IFSieve points have already been allocated.");}
1861:       this->prefixSum(this->coneOffsets);
1862:       this->prefixSum(this->supportOffsets);
1863:       this->createPoints();
1864:       this->calculateBaseAndCapSize();
1865:     }
1866:     // Purely for backwards compatibility
1867:     template<typename Color>
1868:     void addArrow(const point_type& p, const point_type& q, const Color c, const bool forceSupport = false) {
1869:       this->addArrow(p, q, forceSupport);
1870:     }
1871:     void addArrow(const point_type& p, const point_type& q, const bool forceSupport = false) {
1872:       if (!this->chart.hasPoint(q)) {
1873:         if (!this->newCones[q].size() && this->chart.hasPoint(q)) {
1874:           const index_type start = this->coneOffsets[q];
1875:           const index_type end   = this->coneOffsets[q+1];

1877:           for(int c = start; c < end; ++c) {
1878:             this->newCones[q].push_back(this->cones[c]);
1879:           }
1880:         }
1881:         this->newCones[q].push_back(p);
1882:       }
1883:       if (!this->chart.hasPoint(p) || forceSupport) {
1884:         if (!this->newSupports[p].size() && this->chart.hasPoint(p)) {
1885:           const index_type start = this->supportOffsets[p];
1886:           const index_type end   = this->supportOffsets[p+1];

1888:           for(int s = start; s < end; ++s) {
1889:             this->newSupports[p].push_back(this->supports[s]);
1890:           }
1891:         }
1892:         this->newSupports[p].push_back(q);
1893:       }
1894:     };
1895:     void reallocate() {
1896:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
1897:       if (!this->newCones.size() && !this->newSupports.size()) return;
1898:       const chart_type     oldChart            = this->chart;
1899:       offsets_type         oldConeOffsets      = this->coneOffsets;
1900:       offsets_type         oldSupportOffsets   = this->supportOffsets;
1901:       cones_type           oldCones            = this->cones;
1902:       supports_type        oldSupports         = this->supports;
1903:       orientations_type    oldConeOrientations = this->coneOrientations;
1904:       point_type           min                 = this->chart.min();
1905:       point_type           max                 = this->chart.max()-1;

1907:       for(typename newpoints_type::const_iterator c_iter = this->newCones.begin(); c_iter != this->newCones.end(); ++c_iter) {
1908:         min = std::min(min, c_iter->first);
1909:         max = std::max(max, c_iter->first);
1910:       }
1911:       for(typename newpoints_type::const_iterator s_iter = this->newSupports.begin(); s_iter != this->newSupports.end(); ++s_iter) {
1912:         min = std::min(min, s_iter->first);
1913:         max = std::max(max, s_iter->first);
1914:       }
1915:       this->chart = chart_type(min, max+1);
1916:       this->createIndices();
1917:       // Copy sizes (converted from offsets)
1918:       for(point_type p = oldChart.min(); p < oldChart.max(); ++p) {
1919:         this->coneOffsets[p+1]    = oldConeOffsets[p+1]-oldConeOffsets[p];
1920:         this->supportOffsets[p+1] = oldSupportOffsets[p+1]-oldSupportOffsets[p];
1921:       }
1922:       // Inject new sizes
1923:       for(typename newpoints_type::const_iterator c_iter = this->newCones.begin(); c_iter != this->newCones.end(); ++c_iter) {
1924:         this->coneOffsets[c_iter->first+1]    = c_iter->second.size();
1925:         this->maxConeSize                     = std::max(this->maxConeSize,    (int) c_iter->second.size());
1926:       }
1927:       for(typename newpoints_type::const_iterator s_iter = this->newSupports.begin(); s_iter != this->newSupports.end(); ++s_iter) {
1928:         this->supportOffsets[s_iter->first+1] = s_iter->second.size();
1929:         this->maxSupportSize                  = std::max(this->maxSupportSize, (int) s_iter->second.size());
1930:       }
1931:       this->prefixSum(this->coneOffsets);
1932:       this->prefixSum(this->supportOffsets);
1933:       this->createPoints();
1934:       this->calculateBaseAndCapSize();
1935:       // Copy cones and supports
1936:       for(point_type p = oldChart.min(); p < oldChart.max(); ++p) {
1937:         const index_type cStart  = this->coneOffsets[p];
1938:         const index_type cOStart = oldConeOffsets[p];
1939:         const index_type cOEnd   = oldConeOffsets[p+1];
1940:         const index_type sStart  = this->supportOffsets[p];
1941:         const index_type sOStart = oldSupportOffsets[p];
1942:         const index_type sOEnd   = oldSupportOffsets[p+1];

1944:         for(int cO = cOStart, c = cStart; cO < cOEnd; ++cO, ++c) {
1945:           this->cones[c] = oldCones[cO];
1946:         }
1947:         for(int sO = sOStart, s = sStart; sO < sOEnd; ++sO, ++s) {
1948:           this->supports[s] = oldSupports[sO];
1949:         }
1950:         if (this->orientCones) {
1951:           for(int cO = cOStart, c = cStart; cO < cOEnd; ++cO, ++c) {
1952:             this->coneOrientations[c] = oldConeOrientations[cO];
1953:           }
1954:         }
1955:       }
1956:       // Inject new cones and supports
1957:       for(typename newpoints_type::const_iterator c_iter = this->newCones.begin(); c_iter != this->newCones.end(); ++c_iter) {
1958:         index_type start = this->coneOffsets[c_iter->first];

1960:         for(typename std::vector<point_type>::const_iterator p_iter = c_iter->second.begin(); p_iter != c_iter->second.end(); ++p_iter) {
1961:           this->cones[start++] = *p_iter;
1962:         }
1963:         if (start != this->coneOffsets[c_iter->first+1]) throw ALE::Exception("Invalid size for new cone array");
1964:       }
1965:       for(typename newpoints_type::const_iterator s_iter = this->newSupports.begin(); s_iter != this->newSupports.end(); ++s_iter) {
1966:         index_type start = this->supportOffsets[s_iter->first];

1968:         for(typename std::vector<point_type>::const_iterator p_iter = s_iter->second.begin(); p_iter != s_iter->second.end(); ++p_iter) {
1969:           this->supports[start++] = *p_iter;
1970:         }
1971:         if (start != this->supportOffsets[s_iter->first+1]) throw ALE::Exception("Invalid size for new support array");
1972:       }
1973:       this->newCones.clear();
1974:       this->newSupports.clear();
1975:       this->destroyPoints(oldChart, oldConeOffsets, &oldCones, oldSupportOffsets, &oldSupports, &oldConeOrientations);
1976:       this->destroyIndices(oldChart, &oldConeOffsets, &oldSupportOffsets);
1977:     };
1978:     // Recalculate the support offsets and fill the supports
1979:     //   This is used when an IFSieve is being used as a label
1980:     void recalculateLabel() {
1981:       ISieveVisitor::PointRetriever<IFSieve> v(1);

1983:       for(point_type p = this->getChart().min(); p < this->getChart().max(); ++p) {
1984:         this->supportOffsets[p+1] = 0;
1985:       }
1986:       this->maxSupportSize = 0;
1987:       for(point_type p = this->getChart().min(); p < this->getChart().max(); ++p) {
1988:         this->cone(p, v);
1989:         if (v.getSize()) {
1990:           this->supportOffsets[v.getPoints()[0]+1]++;
1991:           this->maxSupportSize = std::max(this->maxSupportSize, this->supportOffsets[v.getPoints()[0]+1]);
1992:         }
1993:         v.clear();
1994:       }
1995:       this->prefixSum(this->supportOffsets);
1996:       this->calculateBaseAndCapSize();
1997:       this->symmetrize();
1998:     };
1999:     void setCone(const point_type cone[], const point_type& p) {
2000:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2001:       this->chart.checkPoint(p);
2002:       const index_type start = this->coneOffsets[p];
2003:       const index_type end   = this->coneOffsets[p+1];

2005:       for(index_type c = start, i = 0; c < end; ++c, ++i) {
2006:         this->cones[c] = cone[i];
2007:       }
2008:     };
2009:     void setCone(const point_type cone, const point_type& p) {
2010:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2011:       this->chart.checkPoint(p);
2012:       const index_type start = this->coneOffsets[p];
2013:       const index_type end   = this->coneOffsets[p+1];

2015:       if (end - start != 1) {throw ALE::Exception("IFSieve setCone() called with too few points.");}
2016:       this->cones[start] = cone;
2017:     };
2018: #if 0
2019:     template<typename PointSequence>
2020:     void setCone(const PointSequence& cone, const point_type& p) {
2021:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2022:       this->chart.checkPoint(p);
2023:       const index_type start = this->coneOffsets[p];
2024:       const index_type end   = this->coneOffsets[p+1];
2025:       if (cone.size() != end - start) {throw ALE::Exception("Invalid size for IFSieve cone.");}
2026:       typename PointSequence::iterator c_iter = cone.begin();

2028:       for(index_type c = start; c < end; ++c, ++c_iter) {
2029:         this->cones[c] = *c_iter;
2030:       }
2031:     };
2032: #endif
2033:     void setSupport(const point_type& p, const point_type support[]) {
2034:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2035:       this->chart.checkPoint(p);
2036:       const index_type start = this->supportOffsets[p];
2037:       const index_type end   = this->supportOffsets[p+1];

2039:       for(index_type s = start, i = 0; s < end; ++s, ++i) {
2040:         this->supports[s] = support[i];
2041:       }
2042:     };
2043: #if 0
2044:     template<typename PointSequence>
2045:     void setSupport(const point_type& p, const PointSequence& support) {
2046:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2047:       this->chart.checkPoint(p);
2048:       const index_type start = this->supportOffsets[p];
2049:       const index_type end   = this->supportOffsets[p+1];
2050:       if (support.size() != end - start) {throw ALE::Exception("Invalid size for IFSieve support.");}
2051:       typename PointSequence::iterator s_iter = support.begin();

2053:       for(index_type s = start; s < end; ++s, ++s_iter) {
2054:         this->supports[s] = *s_iter;
2055:       }
2056:     };
2057: #endif
2058:     void setConeOrientation(const int coneOrientation[], const point_type& p) {
2059:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2060:       this->chart.checkPoint(p);
2061:       const index_type start = this->coneOffsets[p];
2062:       const index_type end   = this->coneOffsets[p+1];

2064:       for(index_type c = start, i = 0; c < end; ++c, ++i) {
2065:         this->coneOrientations[c] = coneOrientation[i];
2066:       }
2067:     };
2068:     void symmetrizeSizes(const int numCells, const int numCorners, const int cones[], const int offset = 0) {
2069:       for(point_type p = 0; p < numCells; ++p) {
2070:         const index_type start = p*numCorners;
2071:         const index_type end   = (p+1)*numCorners;

2073:         for(index_type c = start; c < end; ++c) {
2074:           const point_type q = cones[c]+offset;

2076:           this->supportOffsets[q+1]++;
2077:         }
2078:       }
2079:       for(point_type p = numCells; p < this->chart.max(); ++p) {
2080:         this->maxSupportSize = std::max(this->maxSupportSize, this->supportOffsets[p+1]);
2081:       }
2082:     };
2083:     void symmetrize() {
2084:       index_type *offsets = indexAlloc.allocate(this->chart.size()+1);
2085:       offsets -= this->chart.min();
2086:       for(index_type i = this->chart.min(); i <= this->chart.max(); ++i) {indexAlloc.construct(offsets+i, index_type(0));}
2087:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}

2089:       for(point_type p = this->chart.min(); p < this->chart.max(); ++p) {
2090:         const index_type start = this->coneOffsets[p];
2091:         const index_type end   = this->coneOffsets[p+1];

2093:         for(index_type c = start; c < end; ++c) {
2094:           const point_type q = this->cones[c];

2096:           this->chart.checkPoint(q);
2097:           this->supports[this->supportOffsets[q]+offsets[q]] = p;
2098:           ++offsets[q];
2099:         }
2100:       }
2101:       for(index_type i = this->chart.min(); i <= this->chart.max(); ++i) {indexAlloc.destroy(offsets+i);}
2102:       indexAlloc.deallocate(offsets, this->chart.size()+1);
2103:     }
2104:     index_type getBaseSize() const {
2105:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2106:       return this->baseSize;
2107:     }
2108:     index_type getCapSize() const {
2109:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2110:       return this->capSize;
2111:     }
2112:     template<typename _Section>
2113:     void relabel(_Section& labeling) {

2116:       index_type *offsets = indexAlloc.allocate(this->chart.size()+1);
2117:       offsets -= this->chart.min();
2118:       for(index_type i = this->chart.min(); i <= this->chart.max(); ++i) {indexAlloc.construct(offsets+i, index_type(0));}
2119:       // Recalculate coneOffsets
2120:       for(index_type p = this->chart.min(); p < this->chart.max(); ++p) {
2121:         const point_type newP = labeling.restrictPoint(p)[0];

2123:         offsets[newP+1] = this->getConeSize(p);
2124:       }
2125:       this->prefixSum(offsets);
2126:       PetscMemcpy(this->coneOffsets, offsets, (this->chart.size()+1)*sizeof(index_type));CHKERRXX(ierr);
2127:       // Recalculate supportOffsets
2128:       for(index_type p = this->chart.min(); p < this->chart.max(); ++p) {
2129:         const point_type newP = labeling.restrictPoint(p)[0];

2131:         offsets[newP+1] = this->getSupportSize(p);
2132:       }
2133:       this->prefixSum(offsets);
2134:       PetscMemcpy(this->supportOffsets, offsets, (this->chart.size()+1)*sizeof(index_type));CHKERRXX(ierr);
2135:       for(index_type i = this->chart.min(); i <= this->chart.max(); ++i) {indexAlloc.destroy(offsets+i);}
2136:       indexAlloc.deallocate(offsets, this->chart.size()+1);
2137:       index_type  size = std::max(this->coneOffsets[this->chart.max()] - this->coneOffsets[this->chart.min()],
2138:                                   this->supportOffsets[this->chart.max()] - this->supportOffsets[this->chart.min()]);
2139:       index_type *orientations = offsets = indexAlloc.allocate(size);
2140:       for(index_type i = 0; i < size; ++i) {indexAlloc.construct(orientations+i, index_type(0));}
2141:       // Recalculate coneOrientations
2142:       for(index_type p = this->chart.min(), offset = 0; p < this->chart.max(); ++p) {
2143:         const point_type newP  = labeling.restrictPoint(p)[0];
2144:         const index_type start = this->coneOffsets[newP];
2145:         const index_type end   = this->coneOffsets[newP+1];

2147:         for(index_type c = start; c < end; ++c, ++offset) {
2148:           orientations[c] = this->coneOrientations[offset];
2149:         }
2150:       }
2151:       PetscMemcpy(this->coneOrientations, orientations, (this->coneOffsets[this->chart.max()] - this->coneOffsets[this->chart.min()])*sizeof(index_type));CHKERRXX(ierr);
2152:       for(index_type i = 0; i < size; ++i) {indexAlloc.destroy(orientations+i);}
2153:       indexAlloc.deallocate(orientations, size);
2154:       // Recalculate cones
2155:       point_type *array = pointAlloc.allocate(size);

2157:       for(index_type i = 0; i < size; ++i) {pointAlloc.construct(array+i, point_type(0));}
2158:       for(index_type p = this->chart.min(), offset = 0; p < this->chart.max(); ++p) {
2159:         const point_type newP  = labeling.restrictPoint(p)[0];
2160:         const index_type start = this->coneOffsets[newP];
2161:         const index_type end   = this->coneOffsets[newP+1];

2163:         for(index_type c = start; c < end; ++c, ++offset) {
2164:           const point_type newQ = labeling.restrictPoint(this->cones[offset])[0];

2166:           array[c] = newQ;
2167:         }
2168:       }
2169:       PetscMemcpy(this->cones, array, size*sizeof(point_type));CHKERRXX(ierr);
2170:       // Recalculate supports
2171:       for(index_type p = this->chart.min(), offset = 0; p < this->chart.max(); ++p) {
2172:         const point_type newP  = labeling.restrictPoint(p)[0];
2173:         const index_type start = this->supportOffsets[newP];
2174:         const index_type end   = this->supportOffsets[newP+1];

2176:         for(index_type c = start; c < end; ++c, ++offset) {
2177:           const point_type newQ = labeling.restrictPoint(this->supports[offset])[0];

2179:           array[c] = newQ;
2180:         }
2181:       }
2182:       PetscMemcpy(this->supports, array, size*sizeof(point_type));CHKERRXX(ierr);
2183:       for(index_type i = 0; i < size; ++i) {pointAlloc.destroy(array+i);}
2184:       pointAlloc.deallocate(array, size);
2185:     }
2186:   public: // Traversals
2187:     template<typename Visitor>
2188:     void roots(const Visitor& v) const {
2189:       this->roots(const_cast<Visitor&>(v));
2190:     }
2191:     template<typename Visitor>
2192:     void roots(Visitor& v) const {
2193:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}

2195:       for(point_type p = this->chart.min(); p < this->chart.max(); ++p) {
2196:         if (this->coneOffsets[p+1] == this->coneOffsets[p]) {
2197:           if (this->supportOffsets[p+1]-this->supportOffsets[p] > 0) {
2198:             v.visitPoint(p);
2199:           }
2200:         }
2201:       }
2202:     }
2203:     int numRoots() {
2204:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2205:       int n = 0;

2207:       for(point_type p = this->chart.min(); p < this->chart.max(); ++p) {
2208:         if (this->coneOffsets[p+1] == this->coneOffsets[p]) {
2209:           if (this->supportOffsets[p+1]-this->supportOffsets[p] > 0) {
2210:             ++n;
2211:           }
2212:         }
2213:       }
2214:       return n;
2215:     }
2216:     template<typename Visitor>
2217:     void leaves(const Visitor& v) const {
2218:       this->leaves(const_cast<Visitor&>(v));
2219:     }
2220:     template<typename Visitor>
2221:     void leaves(Visitor& v) const {
2222:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}

2224:       for(point_type p = this->chart.min(); p < this->chart.max(); ++p) {
2225:         if (this->supportOffsets[p+1] == this->supportOffsets[p]) {
2226:           if (this->coneOffsets[p+1]-this->coneOffsets[p] > 0) {
2227:             v.visitPoint(p);
2228:           }
2229:         }
2230:       }
2231:     }
2232:     int numLeaves() {
2233:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2234:       int n = 0;

2236:       for(point_type p = this->chart.min(); p < this->chart.max(); ++p) {
2237:         if (this->supportOffsets[p+1] == this->supportOffsets[p]) {
2238:           if (this->coneOffsets[p+1]-this->coneOffsets[p] > 0) {
2239:             ++n;
2240:           }
2241:         }
2242:       }
2243:       return n;
2244:     }
2245:     template<typename Visitor>
2246:     void base(const Visitor& v) const {
2247:       this->base(const_cast<Visitor&>(v));
2248:     }
2249:     template<typename Visitor>
2250:     void base(Visitor& v) const {
2251:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}

2253:       for(point_type p = this->chart.min(); p < this->chart.max(); ++p) {
2254:         if (this->coneOffsets[p+1]-this->coneOffsets[p] > 0) {
2255:           v.visitPoint(p);
2256:         }
2257:       }
2258:     }
2259:     template<typename Visitor>
2260:     void cap(const Visitor& v) const {
2261:       this->cap(const_cast<Visitor&>(v));
2262:     }
2263:     template<typename Visitor>
2264:     void cap(Visitor& v) const {
2265:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}

2267:       for(point_type p = this->chart.min(); p < this->chart.max(); ++p) {
2268:         if (this->supportOffsets[p+1]-this->supportOffsets[p] > 0) {
2269:           v.visitPoint(p);
2270:         }
2271:       }
2272:     }
2273:     template<typename PointSequence, typename Visitor>
2274:     void cone(const PointSequence& points, Visitor& v) const {
2275:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2276:       for(typename PointSequence::const_iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
2277:         const point_type p = *p_iter;
2278:         this->chart.checkPoint(p);
2279:         const index_type start = this->coneOffsets[p];
2280:         const index_type end   = this->coneOffsets[p+1];

2282:         for(index_type c = start; c < end; ++c) {
2283:           v.visitArrow(arrow_type(this->cones[c], p));
2284:           v.visitPoint(this->cones[c]);
2285:         }
2286:       }
2287:     }
2288:     template<typename Visitor>
2289:     void cone(const point_type& p, Visitor& v) const {
2290:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2291:       this->chart.checkPoint(p);
2292:       const index_type start = this->coneOffsets[p];
2293:       const index_type end   = this->coneOffsets[p+1];

2295:       for(index_type c = start; c < end; ++c) {
2296:         v.visitArrow(arrow_type(this->cones[c], p));
2297:         v.visitPoint(this->cones[c]);
2298:       }
2299:     }
2300:     const Obj<coneSequence>& cone(const point_type& p) const {
2301:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2302:       if (!this->chart.hasPoint(p)) {
2303:         this->coneSeq->reset(this->cones, 0, 0);
2304:       } else {
2305:         this->coneSeq->reset(this->cones, this->coneOffsets[p], this->coneOffsets[p+1]);
2306:       }
2307:       return this->coneSeq;
2308:     }
2309:     template<typename PointSequence, typename Visitor>
2310:     void support(const PointSequence& points, Visitor& v) const {
2311:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2312:       for(typename PointSequence::const_iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
2313:         const point_type p = *p_iter;
2314:         this->chart.checkPoint(p);
2315:         const index_type start = this->supportOffsets[p];
2316:         const index_type end   = this->supportOffsets[p+1];

2318:         for(index_type s = start; s < end; ++s) {
2319:           v.visitArrow(arrow_type(p, this->supports[s]));
2320:           v.visitPoint(this->supports[s]);
2321:         }
2322:       }
2323:     }
2324:     template<typename Visitor>
2325:     void support(const point_type& p, Visitor& v) const {
2326:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2327:       this->chart.checkPoint(p);
2328:       const index_type start = this->supportOffsets[p];
2329:       const index_type end   = this->supportOffsets[p+1];

2331:       for(index_type s = start; s < end; ++s) {
2332:         v.visitArrow(arrow_type(p, this->supports[s]));
2333:         v.visitPoint(this->supports[s]);
2334:       }
2335:     }
2336:     const Obj<supportSequence>& support(const point_type& p) const {
2337:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2338:       if (!this->chart.hasPoint(p)) {
2339:         this->supportSeq->reset(this->supports, 0, 0);
2340:       } else {
2341:         this->supportSeq->reset(this->supports, this->supportOffsets[p], this->supportOffsets[p+1]);
2342:       }
2343:       return this->supportSeq;
2344:     }
2345:     template<typename Visitor>
2346:     void orientedCone(const point_type& p, Visitor& v) const {
2347:       if (!this->orientCones) {throw ALE::Exception("IFSieve cones have not been oriented.");}
2348:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2349:       this->chart.checkPoint(p);
2350:       const index_type start = this->coneOffsets[p];
2351:       const index_type end   = this->coneOffsets[p+1];

2353:       for(index_type c = start; c < end; ++c) {
2354:         v.visitArrow(arrow_type(this->cones[c], p), this->coneOrientations[c]);
2355:         v.visitPoint(this->cones[c], this->coneOrientations[c]);
2356:       }
2357:     }
2358:     template<typename Visitor>
2359:     void orientedReverseCone(const point_type& p, Visitor& v) const {
2360:       if (!this->orientCones) {throw ALE::Exception("IFSieve cones have not been oriented.");}
2361:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2362:       this->chart.checkPoint(p);
2363:       const index_type start = this->coneOffsets[p];
2364:       const index_type end   = this->coneOffsets[p+1];

2366:       for(index_type c = end-1; c >= start; --c) {
2367:         v.visitArrow(arrow_type(this->cones[c], p), this->coneOrientations[c]);
2368:         v.visitPoint(this->cones[c], this->coneOrientations[c] ? -(this->coneOrientations[c]+1): 0);
2369:       }
2370:     }
2371:     template<typename Visitor>
2372:     void orientedSupport(const point_type& p, Visitor& v) const {
2373:       //if (!this->orientCones) {throw ALE::Exception("IFSieve cones have not been oriented.");}
2374:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2375:       this->chart.checkPoint(p);
2376:       const index_type start = this->supportOffsets[p];
2377:       const index_type end   = this->supportOffsets[p+1];

2379:       for(index_type s = start; s < end; ++s) {
2380:         //v.visitArrow(arrow_type(this->supports[s], p), this->supportOrientations[s]);
2381:         //v.visitPoint(this->supports[s], this->supportOrientations[s]);
2382:         v.visitArrow(arrow_type(this->supports[s], p), 0);
2383:         v.visitPoint(this->supports[s], 0);
2384:       }
2385:     }
2386:     template<typename Visitor>
2387:     void orientedReverseSupport(const point_type& p, Visitor& v) const {
2388:       //if (!this->orientCones) {throw ALE::Exception("IFSieve cones have not been oriented.");}
2389:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2390:       this->chart.checkPoint(p);
2391:       const index_type start = this->supportOffsets[p];
2392:       const index_type end   = this->supportOffsets[p+1];

2394:       for(index_type s = end-1; s >= start; --s) {
2395:         //v.visitArrow(arrow_type(this->supports[s], p), this->supportOrientations[s]);
2396:         //v.visitPoint(this->supports[s], this->supportOrientations[s] ? -(this->supportOrientations[s]+1): 0);
2397:         v.visitArrow(arrow_type(this->supports[s], p), 0);
2398:         v.visitPoint(this->supports[s], 0);
2399:       }
2400:     }
2401:     // Currently does only 1 level
2402:     //   Does not check for uniqueness
2403:     template<typename Visitor>
2404:     void meet(const point_type& p, const point_type& q, Visitor& v) const {
2405:       if (!this->pointAllocated) {throw ALE::Exception("IFSieve points have not been allocated.");}
2406:       this->chart.checkPoint(p);
2407:       this->chart.checkPoint(q);
2408:       const index_type startP = this->coneOffsets[p];
2409:       const index_type endP   = this->coneOffsets[p+1];
2410:       const index_type startQ = this->coneOffsets[q];
2411:       const index_type endQ   = this->coneOffsets[q+1];

2413:       for(index_type cP = startP; cP < endP; ++cP) {
2414:         const point_type& c1 = this->cones[cP];

2416:         for(index_type cQ = startQ; cQ < endQ; ++cQ) {
2417:           if (c1 == this->cones[cQ]) v.visitPoint(c1);
2418:         }
2419:         if (this->coneOffsets[c1+1] > this->coneOffsets[c1]) {throw ALE::Exception("Cannot handle multiple level meet()");}
2420:       }
2421:     }
2422:     // Currently does only 1 level
2423:     template<typename Sequence, typename Visitor>
2424:     void join(const Sequence& points, Visitor& v) const {
2425:       typedef std::set<point_type> pointSet;
2426:       pointSet intersect[2] = {pointSet(), pointSet()};
2427:       pointSet tmp;
2428:       int      p = 0;
2429:       int      c = 0;

2431:       for(typename Sequence::const_iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
2432:         this->chart.checkPoint(*p_iter);
2433:         tmp.insert(&this->supports[this->supportOffsets[*p_iter]], &this->supports[this->supportOffsets[(*p_iter)+1]]);
2434:         if (p == 0) {
2435:           intersect[1-c].insert(tmp.begin(), tmp.end());
2436:           p++;
2437:         } else {
2438:           std::set_intersection(intersect[c].begin(), intersect[c].end(), tmp.begin(), tmp.end(),
2439:                                 std::insert_iterator<pointSet>(intersect[1-c], intersect[1-c].begin()));
2440:           intersect[c].clear();
2441:         }
2442:         c = 1 - c;
2443:         tmp.clear();
2444:       }
2445:       for(typename pointSet::const_iterator p_iter = intersect[c].begin(); p_iter != intersect[c].end(); ++p_iter) {
2446:         v.visitPoint(*p_iter);
2447:       }
2448:     }
2449:     // Helper function
2450:     void insertNSupport(point_type p, pointSet& set, const int depth) {
2451:       const index_type start = this->supportOffsets[p];
2452:       const index_type end   = this->supportOffsets[p+1];

2454:       if (depth == 1) {
2455:         set.insert(&this->supports[start], &this->supports[end]);
2456:       } else {
2457:         for(index_type s = start; s < end; ++s) {
2458:           this->insertNSupport(this->supports[s], set, depth-1);
2459:         }
2460:       }
2461:     }
2462:     // Gives only the join of depth n
2463:     template<typename SequenceIterator, typename Visitor>
2464:     void nJoin(const SequenceIterator& pointsBegin, const SequenceIterator& pointsEnd, const int depth, Visitor& v) {
2465:       typedef std::set<point_type> pointSet;
2466:       pointSet intersect[2] = {pointSet(), pointSet()};
2467:       pointSet tmp;
2468:       int      p = 0;
2469:       int      c = 0;

2471:       for(SequenceIterator p_iter = pointsBegin; p_iter != pointsEnd; ++p_iter) {
2472:         this->chart.checkPoint(*p_iter);
2473:         // Put points in the nSupport into tmp (duplicates are fine since it is a set)
2474:         this->insertNSupport(*p_iter, tmp, depth);
2475:         if (p == 0) {
2476:           intersect[1-c].insert(tmp.begin(), tmp.end());
2477:           p++;
2478:         } else {
2479:           std::set_intersection(intersect[c].begin(), intersect[c].end(), tmp.begin(), tmp.end(),
2480:                                 std::insert_iterator<pointSet>(intersect[1-c], intersect[1-c].begin()));
2481:           intersect[c].clear();
2482:         }
2483:         c = 1 - c;
2484:         tmp.clear();
2485:       }
2486:       for(typename pointSet::const_iterator p_iter = intersect[c].begin(); p_iter != intersect[c].end(); ++p_iter) {
2487:         v.visitPoint(*p_iter);
2488:       }
2489:     }
2490:   public: // Viewing
2491:     void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
2492:       ostringstream txt;
2493:       int rank;

2495:       if (comm == MPI_COMM_NULL) {
2496:         comm = this->comm();
2497:         rank = this->commRank();
2498:       } else {
2499:         MPI_Comm_rank(comm, &rank);
2500:       }
2501:       if (name == "") {
2502:         if(rank == 0) {
2503:           txt << "viewing an IFSieve" << std::endl;
2504:         }
2505:       } else {
2506:         if(rank == 0) {
2507:           txt << "viewing IFSieve '" << name << "'" << std::endl;
2508:         }
2509:       }
2510:       PetscSynchronizedPrintf(comm, "Max sizes cone: %d support: %d\n", this->getMaxConeSize(), this->getMaxSupportSize());
2511:       if(rank == 0) {
2512:         txt << "cap --> base:" << std::endl;
2513:       }
2514:       ISieveVisitor::PrintVisitor pV(txt, rank);
2515:       this->cap(ISieveVisitor::SupportVisitor<IFSieve,ISieveVisitor::PrintVisitor>(*this, pV));
2516:       PetscSynchronizedPrintf(comm, txt.str().c_str());
2517:       PetscSynchronizedFlush(comm);
2518:       ostringstream txt2;

2520:       if(rank == 0) {
2521:         txt2 << "base <-- cap:" << std::endl;
2522:       }
2523:       ISieveVisitor::ReversePrintVisitor rV(txt2, rank);
2524:       this->base(ISieveVisitor::ConeVisitor<IFSieve,ISieveVisitor::ReversePrintVisitor>(*this, rV));
2525:       PetscSynchronizedPrintf(comm, txt2.str().c_str());
2526:       PetscSynchronizedFlush(comm);
2527:       if (orientCones) {
2528:         ostringstream txt3;

2530:         if(rank == 0) {
2531:           txt3 << "Orientation:" << std::endl;
2532:         }
2533:         ISieveVisitor::ReversePrintVisitor rV2(txt3, rank);
2534:         this->base(ISieveVisitor::OrientedConeVisitor<IFSieve,ISieveVisitor::ReversePrintVisitor>(*this, rV2));
2535:         PetscSynchronizedPrintf(comm, txt3.str().c_str());
2536:         PetscSynchronizedFlush(comm);
2537:       }
2538:     };
2539:   };

2541:   class ISieveConverter {
2542:   public:
2543:     template<typename Sieve, typename ISieve, typename Renumbering>
2544:     static void convertSieve(Sieve& sieve, ISieve& isieve, Renumbering& renumbering, bool renumber = true) {
2545:       // First construct a renumbering of the sieve points
2546:       const Obj<typename Sieve::baseSequence>& base = sieve.base();
2547:       const Obj<typename Sieve::capSequence>&  cap  = sieve.cap();
2548:       typename ISieve::point_type              min  = 0;
2549:       typename ISieve::point_type              max  = 0;

2551:       if (renumber) {
2552:         /* Roots/Leaves from Sieve do not seem to work */

2554:         for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2555:           if (sieve.support(*b_iter)->size() == 0) {
2556:             renumbering[*b_iter] = max++;
2557:           }
2558:         }
2559:         for(typename Sieve::baseSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
2560:           if (sieve.cone(*c_iter)->size() == 0) {
2561:             renumbering[*c_iter] = max++;
2562:           }
2563:         }
2564:         for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2565:           if (sieve.support(*b_iter)->size() == 0) {
2566:             const typename Sieve::coneSequence::iterator coneBegin = sieve.coneBegin(*b_iter);
2567:             const typename Sieve::coneSequence::iterator coneEnd   = sieve.coneEnd(*b_iter);

2569:             for(typename Sieve::coneSequence::iterator c_iter = coneBegin; c_iter != coneEnd; ++c_iter) {
2570:               if (renumbering.find(*c_iter) == renumbering.end()) {
2571:                 renumbering[*c_iter] = max++;
2572:               }
2573:             }
2574:           }
2575:         }
2576:         for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2577:           if (renumbering.find(*b_iter) == renumbering.end()) {
2578:             renumbering[*b_iter] = max++;
2579:           }
2580:         }
2581:         for(typename Sieve::baseSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
2582:           if (renumbering.find(*c_iter) == renumbering.end()) {
2583:             renumbering[*c_iter] = max++;
2584:           }
2585:         }
2586:       } else {
2587:         if (base->size()) {
2588:           min = *base->begin();
2589:           max = *base->begin();
2590:         } else if (cap->size()) {
2591:           min = *cap->begin();
2592:           max = *cap->begin();
2593:         }
2594:         for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2595:           min = std::min(min, *b_iter);
2596:           max = std::max(max, *b_iter);
2597:         }
2598:         for(typename Sieve::baseSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
2599:           min = std::min(min, *c_iter);
2600:           max = std::max(max, *c_iter);
2601:         }
2602:         if (base->size() || cap->size()) {
2603:           ++max;
2604:         }
2605:         for(typename ISieve::point_type p = min; p < max; ++p) {
2606:           renumbering[p] = p;
2607:         }
2608:       }
2609:       // Create the ISieve
2610:       isieve.setChart(typename ISieve::chart_type(min, max));
2611:       // Set cone and support sizes
2612:       size_t maxSize = 0;

2614:       for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2615:         const Obj<typename Sieve::coneSequence>& cone = sieve.cone(*b_iter);

2617:         isieve.setConeSize(renumbering[*b_iter], cone->size());
2618:         maxSize = std::max(maxSize, cone->size());
2619:       }
2620:       for(typename Sieve::capSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
2621:         const Obj<typename Sieve::supportSequence>& support = sieve.support(*c_iter);

2623:         isieve.setSupportSize(renumbering[*c_iter], support->size());
2624:         maxSize = std::max(maxSize, support->size());
2625:       }
2626:       isieve.allocate();
2627:       // Fill up cones and supports
2628:       typename Sieve::point_type *points = new typename Sieve::point_type[maxSize];

2630:       for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2631:         const Obj<typename Sieve::coneSequence>& cone = sieve.cone(*b_iter);
2632:         int i = 0;

2634:         for(typename Sieve::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter, ++i) {
2635:           points[i] = renumbering[*c_iter];
2636:         }
2637:         isieve.setCone(points, renumbering[*b_iter]);
2638:       }
2639:       for(typename Sieve::capSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
2640:         const Obj<typename Sieve::supportSequence>& support = sieve.support(*c_iter);
2641:         int i = 0;

2643:         for(typename Sieve::supportSequence::iterator s_iter = support->begin(); s_iter != support->end(); ++s_iter, ++i) {
2644:           points[i] = renumbering[*s_iter];
2645:         }
2646:         isieve.setSupport(renumbering[*c_iter], points);
2647:       }
2648:       delete [] points;
2649:     }
2650:     template<typename Sieve, typename Renumbering>
2651:     static void convertSieve(Sieve& sieve, DM dm, Renumbering& renumbering, bool renumber = true) {
2652:       // First construct a renumbering of the sieve points
2653:       const Obj<typename Sieve::baseSequence>& base = sieve.base();
2654:       const Obj<typename Sieve::capSequence>&  cap  = sieve.cap();
2655:       PetscInt                                 min  = 0;
2656:       PetscInt                                 max  = 0;
2657:       PetscErrorCode                           ierr;

2659:       if (renumber) {
2660:         /* Roots/Leaves from Sieve do not seem to work */

2662:         for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2663:           if (sieve.support(*b_iter)->size() == 0) {
2664:             renumbering[*b_iter] = max++;
2665:           }
2666:         }
2667:         for(typename Sieve::baseSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
2668:           if (sieve.cone(*c_iter)->size() == 0) {
2669:             renumbering[*c_iter] = max++;
2670:           }
2671:         }
2672: #if 0
2673:         for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2674:           if (sieve.support(*b_iter)->size() == 0) {
2675:             const typename Sieve::coneSequence::iterator coneBegin = sieve.coneBegin(*b_iter);
2676:             const typename Sieve::coneSequence::iterator coneEnd   = sieve.coneEnd(*b_iter);

2678:             for(typename Sieve::coneSequence::iterator c_iter = coneBegin; c_iter != coneEnd; ++c_iter) {
2679:               if (renumbering.find(*c_iter) == renumbering.end()) {
2680:                 renumbering[*c_iter] = max++;
2681:               }
2682:             }
2683:           }
2684:         }
2685: #else
2686:         std::vector<typename Sieve::point_type> faces;
2687:         for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2688:           if (sieve.support(*b_iter)->size() == 0) {
2689:             const typename Sieve::coneSequence::iterator coneBegin = sieve.coneBegin(*b_iter);
2690:             const typename Sieve::coneSequence::iterator coneEnd   = sieve.coneEnd(*b_iter);

2692:             for(typename Sieve::coneSequence::iterator c_iter = coneBegin; c_iter != coneEnd; ++c_iter) {
2693:               if (renumbering.find(*c_iter) == renumbering.end()) {
2694:                 faces.push_back(*c_iter);
2695:               }
2696:             }
2697:           }
2698:         }
2699:         std::sort(faces.begin(), faces.end());
2700:         typename std::vector<typename Sieve::point_type>::const_iterator fEnd = std::unique(faces.begin(), faces.end());
2701:         for(typename std::vector<typename Sieve::point_type>::const_iterator c_iter = faces.begin(); c_iter != fEnd; ++c_iter) {
2702:           renumbering[*c_iter] = max++;
2703:         }
2704:         faces.clear();
2705: #endif
2706:         for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2707:           if (renumbering.find(*b_iter) == renumbering.end()) {
2708:             renumbering[*b_iter] = max++;
2709:           }
2710:         }
2711:         for(typename Sieve::baseSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
2712:           if (renumbering.find(*c_iter) == renumbering.end()) {
2713:             renumbering[*c_iter] = max++;
2714:           }
2715:         }
2716:       } else {
2717:         if (base->size()) {
2718:           min = *base->begin();
2719:           max = *base->begin();
2720:         } else if (cap->size()) {
2721:           min = *cap->begin();
2722:           max = *cap->begin();
2723:         }
2724:         for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2725:           min = std::min(min, *b_iter);
2726:           max = std::max(max, *b_iter);
2727:         }
2728:         for(typename Sieve::baseSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
2729:           min = std::min(min, *c_iter);
2730:           max = std::max(max, *c_iter);
2731:         }
2732:         if (base->size() || cap->size()) {
2733:           ++max;
2734:         }
2735:         for(PetscInt p = min; p < max; ++p) {
2736:           renumbering[p] = p;
2737:         }
2738:       }
2739:       // Create the ISieve
2740:       DMPlexSetChart(dm, min, max);CHKERRXX(ierr);
2741:       // Set cone and support sizes
2742:       size_t maxSize = 0;

2744:       for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2745:         const Obj<typename Sieve::coneSequence>& cone = sieve.cone(*b_iter);

2747:         DMPlexSetConeSize(dm, renumbering[*b_iter], cone->size());CHKERRXX(ierr);
2748:         maxSize = std::max(maxSize, cone->size());
2749:       }
2750:       for(typename Sieve::capSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
2751:         const Obj<typename Sieve::supportSequence>& support = sieve.support(*c_iter);

2753:         DMPlexSetSupportSize(dm, renumbering[*c_iter], support->size());CHKERRXX(ierr);
2754:         maxSize = std::max(maxSize, support->size());
2755:       }
2756:       DMSetUp(dm);CHKERRXX(ierr);
2757:       // Fill up cones and supports
2758:       typename Sieve::point_type *points = new typename Sieve::point_type[maxSize];

2760:       for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2761:         const Obj<typename Sieve::coneSequence>& cone = sieve.cone(*b_iter);
2762:         int i = 0;

2764:         for(typename Sieve::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter, ++i) {
2765:           points[i] = renumbering[*c_iter];
2766:         }
2767:         DMPlexSetCone(dm, renumbering[*b_iter], points);CHKERRXX(ierr);
2768:       }
2769:       for(typename Sieve::capSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
2770:         const Obj<typename Sieve::supportSequence>& support = sieve.support(*c_iter);
2771:         int i = 0;

2773:         for(typename Sieve::supportSequence::iterator s_iter = support->begin(); s_iter != support->end(); ++s_iter, ++i) {
2774:           points[i] = renumbering[*s_iter];
2775:         }
2776:         DMPlexSetSupport(dm, renumbering[*c_iter], points);CHKERRXX(ierr);
2777:       }
2778:       delete [] points;
2779:     }
2780:     template<typename Sieve, typename ISieve, typename Renumbering, typename ArrowSection>
2781:     static void convertOrientation(Sieve& sieve, ISieve& isieve, Renumbering& renumbering, ArrowSection *orientation) {
2782:       if (isieve.getMaxConeSize() < 0) return;
2783:       const Obj<typename Sieve::baseSequence>& base = sieve.base();
2784:       int *orientations = new int[isieve.getMaxConeSize()];

2786:       for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2787:         const Obj<typename Sieve::coneSequence>& cone = sieve.cone(*b_iter);
2788:         int i = 0;

2790:         for(typename Sieve::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter, ++i) {
2791:           typename ArrowSection::point_type arrow(*c_iter, *b_iter);

2793:           orientations[i] = orientation->restrictPoint(arrow)[0];
2794:         }
2795:         isieve.setConeOrientation(orientations, renumbering[*b_iter]);
2796:       }
2797:       delete [] orientations;
2798:     }
2799:     template<typename Sieve, typename Renumbering, typename ArrowSection>
2800:     static void convertOrientation(Sieve& sieve, DM dm, Renumbering& renumbering, ArrowSection *orientation) {
2801:       PetscInt       maxConeSize;

2804:       DMPlexGetMaxSizes(dm, &maxConeSize, NULL);CHKERRXX(ierr);
2805:       if (maxConeSize < 0) return;
2806:       const Obj<typename Sieve::baseSequence>& base = sieve.base();
2807:       int *orientations = new int[maxConeSize];

2809:       for(typename Sieve::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2810:         const Obj<typename Sieve::coneSequence>& cone = sieve.cone(*b_iter);
2811:         int i = 0;

2813:         for(typename Sieve::coneSequence::iterator c_iter = cone->begin(); c_iter != cone->end(); ++c_iter, ++i) {
2814:           typename ArrowSection::point_type arrow(*c_iter, *b_iter);
2815:           const int o = orientation->restrictPoint(arrow)[0];

2817:           orientations[i] = o == 1 ? 0 : o;
2818:         }
2819:         DMPlexSetConeOrientation(dm, renumbering[*b_iter], orientations);
2820:       }
2821:       delete [] orientations;
2822:     }
2823:     template<typename Section, typename ISection, typename Renumbering>
2824:     static void convertCoordinates(Section& coordinates, ISection& icoordinates, Renumbering& renumbering) {
2825:       const typename Section::chart_type& chart = coordinates.getChart();
2826:       typename ISection::point_type       min   = *chart.begin();
2827:       typename ISection::point_type       max   = *chart.begin();

2829:       for(typename Section::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
2830:         min = std::min(min, renumbering[*p_iter]);
2831:         max = std::max(max, renumbering[*p_iter]);
2832:       }
2833:       icoordinates.setChart(typename ISection::chart_type(min, max+1));
2834:       for(typename Section::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
2835:         icoordinates.setFiberDimension(renumbering[*p_iter], coordinates.getFiberDimension(*p_iter));
2836:       }
2837:       icoordinates.allocatePoint();
2838:       for(typename Section::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
2839:         icoordinates.updatePoint(renumbering[*p_iter], coordinates.restrictPoint(*p_iter));
2840:       }
2841:     }
2842:     template<typename Section, typename Renumbering>
2843:     static void convertCoordinates(Section& coordinates, PetscSection coordSection, Vec coords, Renumbering& renumbering) {
2844:       const typename Section::chart_type& chart = coordinates.getChart();
2845:       PetscInt                            min   = *chart.begin();
2846:       PetscInt                            max   = *chart.begin();
2847:       PetscScalar                        *a;
2848:       PetscInt                            n;
2849:       PetscErrorCode                      ierr;

2851:       PetscSectionSetNumFields(coordSection, 1);CHKERRXX(ierr);
2852:       if (!chart.size()) {
2853:         PetscSectionSetFieldComponents(coordSection, 0, 1);CHKERRXX(ierr);
2854:         return;
2855:       }
2856:       for(typename Section::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
2857:         min = std::min(min, renumbering[*p_iter]);
2858:         max = std::max(max, renumbering[*p_iter]);
2859:       }
2860:       PetscSectionSetFieldComponents(coordSection, 0, coordinates.getFiberDimension(*chart.begin()));CHKERRXX(ierr);
2861:       PetscSectionSetChart(coordSection, min, max+1);CHKERRXX(ierr);
2862:       for(typename Section::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
2863:         PetscSectionSetDof(coordSection, renumbering[*p_iter], coordinates.getFiberDimension(*p_iter));CHKERRXX(ierr);
2864:         PetscSectionSetFieldDof(coordSection, renumbering[*p_iter], 0, coordinates.getFiberDimension(*p_iter));CHKERRXX(ierr);
2865:       }
2866:       PetscSectionSetUp(coordSection);CHKERRXX(ierr);
2867:       PetscSectionGetStorageSize(coordSection, &n);CHKERRXX(ierr);
2868:       VecSetSizes(coords, n, PETSC_DETERMINE);CHKERRXX(ierr);
2869:       VecSetFromOptions(coords);CHKERRXX(ierr);
2870:       VecGetArray(coords, &a);CHKERRXX(ierr);
2871:       for(typename Section::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
2872:         const typename Section::value_type *values = coordinates.restrictPoint(*p_iter);
2873:         PetscInt dof, off;

2875:         PetscSectionGetDof(coordSection, renumbering[*p_iter], &dof);CHKERRXX(ierr);
2876:         PetscSectionGetOffset(coordSection, renumbering[*p_iter], &off);CHKERRXX(ierr);
2877:         for(int d = 0; d < dof; ++d) {
2878:           a[off+d] = values[d];
2879:         }
2880:       }
2881:       VecRestoreArray(coords, &a);CHKERRXX(ierr);
2882:     }
2883:     template<typename Label, typename Renumbering>
2884:     static void convertLabel(const Obj<Label>& newLabel, const Obj<Label>& oldLabel, Renumbering& renumbering) {
2885:       for(typename Renumbering::const_iterator p = renumbering.begin(); p != renumbering.end(); ++p) {
2886:         if (oldLabel->getConeSize(p->first)) {
2887:           newLabel->setCone(*oldLabel->cone(p->first)->begin(), p->second);
2888:         }
2889:       }
2890:     }
2891:     template<typename Label, typename Renumbering>
2892:     static void convertLabel(DM dm, const char name[], const Obj<Label>& label, Renumbering& renumbering) {

2895:       for(typename Renumbering::const_iterator p = renumbering.begin(); p != renumbering.end(); ++p) {
2896:         if (label->getConeSize(p->first)) {
2897:           DMPlexSetLabelValue(dm, name, p->second, *label->cone(p->first)->begin());CHKERRXX(ierr);
2898:         }
2899:       }
2900:     }
2901:     template<typename Mesh, typename IMesh, typename Renumbering>
2902:     static void convertMesh(Mesh& mesh, IMesh& imesh, Renumbering& renumbering, bool renumber = true) {
2903:       convertSieve(*mesh.getSieve(), *imesh.getSieve(), renumbering, renumber);
2904:       imesh.stratify();
2905:       convertOrientation(*mesh.getSieve(), *imesh.getSieve(), renumbering, mesh.getArrowSection("orientation").ptr());
2906:       convertCoordinates(*mesh.getRealSection("coordinates"), *imesh.getRealSection("coordinates"), renumbering);
2907:       if (mesh.hasRealSection("normals")) {
2908:         convertCoordinates(*mesh.getRealSection("normals"), *imesh.getRealSection("normals"), renumbering);
2909:       }
2910:       const typename Mesh::labels_type& labels = mesh.getLabels();
2911:       std::string heightName("height");
2912:       std::string depthName("depth");

2914:       for(typename Mesh::labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
2915: #ifdef IMESH_NEW_LABELS
2916:         if ((l_iter->first != heightName) && (l_iter->first != depthName)) {
2917:           convertLabel(imesh, l_iter->first, l_iter->second);
2918:         }
2919: #else
2920:         if (renumber) {
2921:           convertLabel(imesh.createLabel(l_iter->first), l_iter->second, renumbering);
2922:         } else {
2923:           imesh.setLabel(l_iter->first, l_iter->second);
2924:         }
2925: #endif
2926:       }
2927:     }
2928:     template<typename Mesh, typename Renumbering>
2929:     static void convertMesh(Mesh& mesh, DM *dm, Renumbering& renumbering, bool renumber = true) {
2930:       PetscSection   coordSection;
2931:       Vec            coordinates;

2934:       DMCreate(mesh.comm(), dm);CHKERRXX(ierr);
2935:       DMSetType(*dm, DMPLEX);CHKERRXX(ierr);
2936:       DMPlexSetDimension(*dm, mesh.getDimension());CHKERRXX(ierr);
2937:       convertSieve(*mesh.getSieve(), *dm, renumbering, renumber);
2938:       DMPlexStratify(*dm);CHKERRXX(ierr);
2939:       convertOrientation(*mesh.getSieve(), *dm, renumbering, mesh.getArrowSection("orientation").ptr());
2940:       DMPlexGetCoordinateSection(*dm, &coordSection);CHKERRXX(ierr);
2941:       VecCreate(mesh.comm(), &coordinates);CHKERRXX(ierr);
2942:       convertCoordinates(*mesh.getRealSection("coordinates"), coordSection, coordinates, renumbering);
2943:       DMSetCoordinatesLocal(*dm, coordinates);CHKERRXX(ierr);
2944:       VecDestroy(&coordinates);CHKERRXX(ierr);
2945:       const typename Mesh::labels_type& labels = mesh.getLabels();

2947:       for(typename Mesh::labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
2948:         convertLabel(*dm, l_iter->first.c_str(), l_iter->second, renumbering);
2949:       }
2950:     }
2951:   };

2953:   class ISieveSerializer {
2954:   public:
2955:     template<typename ISieve>
2956:     static void writeSieve(const std::string& filename, ISieve& sieve) {
2957:       std::ofstream fs;

2959:       if (sieve.commRank() == 0) {
2960:         fs.open(filename.c_str());
2961:       }
2962:       writeSieve(fs, sieve);
2963:       if (sieve.commRank() == 0) {
2964:         fs.close();
2965:       }
2966:     }
2967:     template<typename ISieve>
2968:     static void writeSieve(std::ofstream& fs, ISieve& sieve) {
2969:       typedef ISieveVisitor::PointRetriever<ISieve> Visitor;
2970:       const Obj<typename ISieve::chart_type>& chart = sieve.getChart();
2971:       typename ISieve::point_type             min   = chart->min();
2972:       typename ISieve::point_type             max   = chart->max();
2973:       PetscInt                               *mins  = new PetscInt[sieve.commSize()];
2974:       PetscInt                               *maxs  = new PetscInt[sieve.commSize()];

2976:       // Write sizes
2977:       if (sieve.commRank() == 0) {
2978:         // Write local
2979:         fs << min <<" "<< max << std::endl;
2980:         for(typename ISieve::point_type p = min; p < max; ++p) {
2981:           fs << sieve.getConeSize(p) << " " << sieve.getSupportSize(p) << std::endl;
2982:         }
2983:         // Receive and write remote
2984:         for(int pr = 1; pr < sieve.commSize(); ++pr) {
2985:           PetscInt       minp, maxp;
2986:           PetscInt      *sizes;
2987:           MPI_Status     status;

2990:           MPI_Recv(&minp, 1, MPIU_INT, pr, 1, sieve.comm(), &status);CHKERRXX(ierr);
2991:           MPI_Recv(&maxp, 1, MPIU_INT, pr, 1, sieve.comm(), &status);CHKERRXX(ierr);
2992:           PetscMalloc(2*(maxp - minp) * sizeof(PetscInt), &sizes);CHKERRXX(ierr);
2993:           MPI_Recv(sizes, (maxp - minp)*2, MPIU_INT, pr, 1, sieve.comm(), &status);CHKERRXX(ierr);
2994:           fs << minp <<" "<< maxp << std::endl;
2995:           for(PetscInt s = 0; s < maxp - minp; ++s) {
2996:             fs << sizes[s*2+0] << " " << sizes[s*2+1] << std::endl;
2997:           }
2998:           PetscFree(sizes);CHKERRXX(ierr);
2999:           mins[pr] = minp;
3000:           maxs[pr] = maxp;
3001:         }
3002:       } else {
3003:         // Send remote
3004:         //PetscInt       min = chart->min();
3005:         //PetscInt       max = chart->max();
3006:         PetscInt       s   = 0;
3007:         PetscInt      *sizes;

3010:         MPI_Send(&min, 1, MPIU_INT, 0, 1, sieve.comm());CHKERRXX(ierr);
3011:         MPI_Send(&max, 1, MPIU_INT, 0, 1, sieve.comm());CHKERRXX(ierr);
3012:         PetscMalloc((max - min)*2 * sizeof(PetscInt) + 1, &sizes);CHKERRXX(ierr);
3013:         for(typename ISieve::point_type p = min; p < max; ++p, ++s) {
3014:           sizes[s*2+0] = sieve.getConeSize(p);
3015:           sizes[s*2+1] = sieve.getSupportSize(p);
3016:         }
3017:         MPI_Send(sizes, (max - min)*2, MPIU_INT, 0, 1, sieve.comm());CHKERRXX(ierr);
3018:         PetscFree(sizes);CHKERRXX(ierr);
3019:       }
3020:       // Write covering
3021:       if (sieve.commRank() == 0) {
3022:         // Write local
3023:         Visitor pV(std::max(sieve.getMaxConeSize(), sieve.getMaxSupportSize())+1);

3025:         for(typename ISieve::point_type p = min; p < max; ++p) {
3026:           sieve.cone(p, pV);
3027:           const typename Visitor::point_type *cone  = pV.getPoints();
3028:           const int                           cSize = pV.getSize();

3030:           if (cSize > 0) {
3031:             for(int c = 0; c < cSize; ++c) {
3032:               if (c) {fs << " ";}
3033:               fs << cone[c];
3034:             }
3035:             fs << std::endl;
3036:           }
3037:           pV.clear();

3039:           sieve.orientedCone(p, pV);
3040:           const typename Visitor::oriented_point_type *oCone = pV.getOrientedPoints();
3041:           const int                                    oSize = pV.getOrientedSize();

3043:           if (oSize > 0) {
3044:             for(int c = 0; c < oSize; ++c) {
3045:               if (c) {fs << " ";}
3046:               fs << oCone[c].second;
3047:             }
3048:             fs << std::endl;
3049:           }
3050:           pV.clear();

3052:           sieve.support(p, pV);
3053:           const typename Visitor::point_type *support = pV.getPoints();
3054:           const int                           sSize   = pV.getSize();

3056:           if (sSize > 0) {
3057:             for(int s = 0; s < sSize; ++s) {
3058:               if (s) {fs << " ";}
3059:               fs << support[s];
3060:             }
3061:             fs << std::endl;
3062:           }
3063:           pV.clear();
3064:         }
3065:         // Receive and write remote
3066:         for(int pr = 1; pr < sieve.commSize(); ++pr) {
3067:           PetscInt       size;
3068:           PetscInt      *data;
3069:           PetscInt       off = 0;
3070:           MPI_Status     status;

3073:           MPI_Recv(&size, 1, MPIU_INT, pr, 1, sieve.comm(), &status);CHKERRXX(ierr);
3074:           PetscMalloc(size*sizeof(PetscInt), &data);CHKERRXX(ierr);
3075:           MPI_Recv(data, size, MPIU_INT, pr, 1, sieve.comm(), &status);CHKERRXX(ierr);
3076:           for(typename ISieve::point_type p = mins[pr]; p < maxs[pr]; ++p) {
3077:             PetscInt cSize = data[off++];

3079:             fs << cSize << std::endl;
3080:             if (cSize > 0) {
3081:               for(int c = 0; c < cSize; ++c) {
3082:                 if (c) {fs << " ";}
3083:                 fs << data[off++];
3084:               }
3085:               fs << std::endl;
3086:             }
3087:             PetscInt oSize = data[off++];

3089:             if (oSize > 0) {
3090:               for(int c = 0; c < oSize; ++c) {
3091:                 if (c) {fs << " ";}
3092:                 fs << data[off++];
3093:               }
3094:               fs << std::endl;
3095:             }
3096:             PetscInt sSize = data[off++];

3098:             fs << sSize << std::endl;
3099:             if (sSize > 0) {
3100:               for(int s = 0; s < sSize; ++s) {
3101:                 if (s) {fs << " ";}
3102:                 fs << data[off++];
3103:               }
3104:               fs << std::endl;
3105:             }
3106:           }
3107:           assert(off == size);
3108:           PetscFree(data);CHKERRXX(ierr);
3109:         }
3110:       } else {
3111:         // Send remote
3112:         Visitor pV(std::max(sieve.getMaxConeSize(), sieve.getMaxSupportSize())+1);
3113:         PetscInt totalConeSize    = 0;
3114:         PetscInt totalSupportSize = 0;

3116:         for(typename ISieve::point_type p = min; p < max; ++p) {
3117:           totalConeSize    += sieve.getConeSize(p);
3118:           totalSupportSize += sieve.getSupportSize(p);
3119:         }
3120:         PetscInt       size = (sieve.getChart().size()+totalConeSize)*2 + sieve.getChart().size()+totalSupportSize;
3121:         PetscInt       off  = 0;
3122:         PetscInt      *data;

3125:         MPI_Send(&size, 1, MPIU_INT, 0, 1, sieve.comm());CHKERRXX(ierr);
3126:         // There is no nice way to make a generic MPI type here. Really sucky
3127:         PetscMalloc(size * sizeof(PetscInt), &data);CHKERRXX(ierr);
3128:         for(typename ISieve::point_type p = min; p < max; ++p) {
3129:           sieve.cone(p, pV);
3130:           const typename Visitor::point_type *cone  = pV.getPoints();
3131:           const int                           cSize = pV.getSize();

3133:           data[off++] = cSize;
3134:           for(int c = 0; c < cSize; ++c) {
3135:             data[off++] = cone[c];
3136:           }
3137:           pV.clear();

3139:           sieve.orientedCone(p, pV);
3140:           const typename Visitor::oriented_point_type *oCone = pV.getOrientedPoints();
3141:           const int                                    oSize = pV.getOrientedSize();

3143:           data[off++] = oSize;
3144:           for(int c = 0; c < oSize; ++c) {
3145:             data[off++] = oCone[c].second;
3146:           }
3147:           pV.clear();

3149:           sieve.support(p, pV);
3150:           const typename Visitor::point_type *support = pV.getPoints();
3151:           const int                           sSize   = pV.getSize();

3153:           data[off++] = sSize;
3154:           for(int s = 0; s < sSize; ++s) {
3155:             data[off++] = support[s];
3156:           }
3157:           pV.clear();
3158:         }
3159:         MPI_Send(data, size, MPIU_INT, 0, 1, sieve.comm());CHKERRXX(ierr);
3160:         PetscFree(data);CHKERRXX(ierr);
3161:       }
3162:       delete [] mins;
3163:       delete [] maxs;
3164:       // Output renumbering
3165:     }
3166:     template<typename ISieve>
3167:     static void loadSieve(const std::string& filename, ISieve& sieve) {
3168:       std::ifstream fs;

3170:       if (sieve.commRank() == 0) {
3171:         fs.open(filename.c_str());
3172:       }
3173:       loadSieve(fs, sieve);
3174:       if (sieve.commRank() == 0) {
3175:         fs.close();
3176:       }
3177:     }
3178:     template<typename ISieve>
3179:     static void loadSieve(std::ifstream& fs, ISieve& sieve) {
3180:       typename ISieve::point_type min, max;
3181:       PetscInt                   *mins = new PetscInt[sieve.commSize()];
3182:       PetscInt                   *maxs = new PetscInt[sieve.commSize()];
3183:       PetscInt                   *totalConeSizes    = new PetscInt[sieve.commSize()];
3184:       PetscInt                   *totalSupportSizes = new PetscInt[sieve.commSize()];

3186:       // Load sizes
3187:       if (sieve.commRank() == 0) {
3188:         // Load local
3189:         fs >> min;
3190:         fs >> max;
3191:         sieve.setChart(typename ISieve::chart_type(min, max));
3192:         for(typename ISieve::point_type p = min; p < max; ++p) {
3193:           typename ISieve::index_type coneSize, supportSize;

3195:           fs >> coneSize;
3196:           fs >> supportSize;
3197:           sieve.setConeSize(p, coneSize);
3198:           sieve.setSupportSize(p, supportSize);
3199:         }
3200:         // Load and send remote
3201:         for(int pr = 1; pr < sieve.commSize(); ++pr) {
3202:           PetscInt       minp, maxp;
3203:           PetscInt      *sizes;

3206:           fs >> minp;
3207:           fs >> maxp;
3208:           MPI_Send(&minp, 1, MPIU_INT, pr, 1, sieve.comm());CHKERRXX(ierr);
3209:           MPI_Send(&maxp, 1, MPIU_INT, pr, 1, sieve.comm());CHKERRXX(ierr);
3210:           PetscMalloc((maxp - minp)*2 * sizeof(PetscInt), &sizes);CHKERRXX(ierr);
3211:           totalConeSizes[pr]    = 0;
3212:           totalSupportSizes[pr] = 0;
3213:           for(PetscInt s = 0; s < maxp - minp; ++s) {
3214:             fs >> sizes[s*2+0];
3215:             fs >> sizes[s*2+1];
3216:             totalConeSizes[pr]    += sizes[s*2+0];
3217:             totalSupportSizes[pr] += sizes[s*2+1];
3218:           }
3219:           MPI_Send(sizes, (maxp - minp)*2, MPIU_INT, pr, 1, sieve.comm());CHKERRXX(ierr);
3220:           PetscFree(sizes);CHKERRXX(ierr);
3221:           mins[pr] = minp;
3222:           maxs[pr] = maxp;
3223:         }
3224:       } else {
3225:         // Load remote
3226:         PetscInt       s   = 0;
3227:         PetscInt      *sizes;
3228:         MPI_Status     status;

3231:         MPI_Recv(&min, 1, MPIU_INT, 0, 1, sieve.comm(), &status);CHKERRXX(ierr);
3232:         MPI_Recv(&max, 1, MPIU_INT, 0, 1, sieve.comm(), &status);CHKERRXX(ierr);
3233:         sieve.setChart(typename ISieve::chart_type(min, max));
3234:         PetscMalloc((max - min)*2 * sizeof(PetscInt), &sizes);CHKERRXX(ierr);
3235:         MPI_Recv(sizes, (max - min)*2, MPIU_INT, 0, 1, sieve.comm(), &status);CHKERRXX(ierr);
3236:         for(typename ISieve::point_type p = min; p < max; ++p, ++s) {
3237:           sieve.setConeSize(p, sizes[s*2+0]);
3238:           sieve.setSupportSize(p, sizes[s*2+1]);
3239:         }
3240:         PetscFree(sizes);CHKERRXX(ierr);
3241:       }
3242:       sieve.allocate();
3243:       // Load covering
3244:       if (sieve.commRank() == 0) {
3245:         // Load local
3246:         typename ISieve::index_type  maxSize = std::max(sieve.getMaxConeSize(), sieve.getMaxSupportSize());
3247:         typename ISieve::point_type *points  = new typename ISieve::point_type[maxSize];

3249:         for(typename ISieve::point_type p = min; p < max; ++p) {
3250:           typename ISieve::index_type coneSize    = sieve.getConeSize(p);
3251:           typename ISieve::index_type supportSize = sieve.getSupportSize(p);

3253:           if (coneSize > 0) {
3254:             for(int c = 0; c < coneSize; ++c) {
3255:               fs >> points[c];
3256:             }
3257:             sieve.setCone(points, p);
3258:             if (sieve.orientedCones()) {
3259:               for(int c = 0; c < coneSize; ++c) {
3260:                 fs >> points[c];
3261:               }
3262:               sieve.setConeOrientation(points, p);
3263:             }
3264:           }
3265:           if (supportSize > 0) {
3266:             for(int s = 0; s < supportSize; ++s) {
3267:               fs >> points[s];
3268:             }
3269:             sieve.setSupport(p, points);
3270:           }
3271:         }
3272:         delete [] points;
3273:         // Load and send remote
3274:         for(int pr = 1; pr < sieve.commSize(); ++pr) {
3275:           PetscInt       size = (maxs[pr] - mins[pr])+totalConeSizes[pr]*2 + (maxs[pr] - mins[pr])+totalSupportSizes[pr];
3276:           PetscInt       off  = 0;
3277:           PetscInt      *data;

3280:           MPI_Send(&size, 1, MPIU_INT, pr, 1, sieve.comm());CHKERRXX(ierr);
3281:           // There is no nice way to make a generic MPI type here. Really sucky
3282:           PetscMalloc(size * sizeof(PetscInt), &data);CHKERRXX(ierr);
3283:           for(typename ISieve::point_type p = mins[pr]; p < maxs[pr]; ++p) {
3284:             PetscInt coneSize, supportSize;

3286:             fs >> coneSize;
3287:             data[off++] = coneSize;
3288:             if (coneSize > 0) {
3289:               for(int c = 0; c < coneSize; ++c) {
3290:                 fs >> data[off++];
3291:               }
3292:               for(int c = 0; c < coneSize; ++c) {
3293:                 fs >> data[off++];
3294:               }
3295:             }
3296:             fs >> supportSize;
3297:             data[off++] = supportSize;
3298:             if (supportSize > 0) {
3299:               for(int s = 0; s < supportSize; ++s) {
3300:                 fs >> data[off++];
3301:               }
3302:             }
3303:           }
3304:           assert(off == size);
3305:           MPI_Send(data, size, MPIU_INT, pr, 1, sieve.comm());CHKERRXX(ierr);
3306:           PetscFree(data);CHKERRXX(ierr);
3307:         }
3308:         delete [] mins;
3309:         delete [] maxs;
3310:       } else {
3311:         // Load remote
3312:         PetscInt       size;
3313:         PetscInt      *data;
3314:         PetscInt       off = 0;
3315:         MPI_Status     status;

3318:         MPI_Recv(&size, 1, MPIU_INT, 0, 1, sieve.comm(), &status);CHKERRXX(ierr);
3319:         PetscMalloc(size*sizeof(PetscInt), &data);CHKERRXX(ierr);
3320:         MPI_Recv(data, size, MPIU_INT, 0, 1, sieve.comm(), &status);CHKERRXX(ierr);
3321:         for(typename ISieve::point_type p = min; p < max; ++p) {
3322:           typename ISieve::index_type coneSize    = sieve.getConeSize(p);
3323:           typename ISieve::index_type supportSize = sieve.getSupportSize(p);
3324:           PetscInt cs = data[off++];

3326:           assert(cs == coneSize);
3327:           if (coneSize > 0) {
3328:             sieve.setCone(&data[off], p);
3329:             off += coneSize;
3330:             if (sieve.orientedCones()) {
3331:               sieve.setConeOrientation(&data[off], p);
3332:               off += coneSize;
3333:             }
3334:           }
3335:           PetscInt ss = data[off++];

3337:           assert(ss == supportSize);
3338:           if (supportSize > 0) {
3339:             sieve.setSupport(p, &data[off]);
3340:             off += supportSize;
3341:           }
3342:         }
3343:         assert(off == size);
3344:       }
3345:       // Load renumbering
3346:     }
3347:   };
3348: }

3350: #endif