Actual source code: Mesh.hh

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

  4: #include <list>
  5: #include <valarray>

  7: #ifndef  included_ALE_Numbering_hh
  8: #include <sieve/Numbering.hh>
  9: #endif

 11: #ifndef  included_ALE_INumbering_hh
 12: #include <sieve/INumbering.hh>
 13: #endif

 15: #ifndef  included_ALE_Field_hh
 16: #include <sieve/Field.hh>
 17: #endif

 19: #ifndef  included_ALE_IField_hh
 20: #include <sieve/IField.hh>
 21: #endif

 23: #ifndef  included_ALE_SieveBuilder_hh
 24: #include <sieve/SieveBuilder.hh>
 25: #endif

 27: #ifndef  included_ALE_LabelSifter_hh
 28: #include <sieve/LabelSifter.hh>
 29: #endif

 31: #ifndef  included_ALE_Partitioner_hh
 32: #include <sieve/Partitioner.hh>
 33: #endif

 35: #ifndef  included_ALE_Ordering_hh
 36: #include <sieve/Ordering.hh>
 37: #endif

 39: #ifndef  included_PETSc_Overlap_hh
 40: #include <sieve/Overlap.hh>
 41: #endif

 43: namespace ALE {
 44:   class indexSet : public std::valarray<int> {
 45:   public:
 46:     inline bool
 47:     operator<(const indexSet& __x) {
 48:       if (__x.size() != this->size()) return __x.size() < this->size();
 49:       for(unsigned int i = 0; i < __x.size(); ++i) {
 50:         if (__x[i] == (*this)[i]) continue;
 51:           return __x[i] < (*this)[i];
 52:       }
 53:       return false;
 54:     }
 55:   };
 56:   inline bool
 57:   operator<(const indexSet& __x, const indexSet& __y) {
 58:     if (__x.size() != __y.size()) return __x.size() < __y.size();
 59:     for(unsigned int i = 0; i < __x.size(); ++i) {
 60:       if (__x[i] == __y[i]) continue;
 61:       return __x[i] < __y[i];
 62:     }
 63:     return false;
 64:   };
 65:   inline bool
 66:   operator<=(const indexSet& __x, const indexSet& __y) {
 67:     if (__x.size() != __y.size()) return __x.size() < __y.size();
 68:     for(unsigned int i = 0; i < __x.size(); ++i) {
 69:       if (__x[i] == __y[i]) continue;
 70:       return __x[i] < __y[i];
 71:     }
 72:     return true;
 73:   };
 74:   inline bool
 75:   operator==(const indexSet& __x, const indexSet& __y) {
 76:     if (__x.size() != __y.size()) return false;
 77:     for(unsigned int i = 0; i < __x.size(); ++i) {
 78:       if (__x[i] != __y[i]) return false;
 79:     }
 80:     return true;
 81:   };
 82:   inline bool
 83:   operator!=(const indexSet& __x, const indexSet& __y) {
 84:     if (__x.size() != __y.size()) return true;
 85:     for(unsigned int i = 0; i < __x.size(); ++i) {
 86:       if (__x[i] != __y[i]) return true;
 87:     }
 88:     return false;
 89:   };

 91:   template<typename Sieve_,
 92:            typename RealSection_  = Section<typename Sieve_::point_type, double>,
 93:            typename IntSection_   = Section<typename Sieve_::point_type, int>,
 94:            typename ArrowSection_ = UniformSection<MinimalArrow<typename Sieve_::point_type, typename Sieve_::point_type>, int> >
 95:   class Bundle : public ALE::ParallelObject {
 96:   public:
 97:     typedef Sieve_                                                    sieve_type;
 98:     typedef RealSection_                                              real_section_type;
 99:     typedef IntSection_                                               int_section_type;
100:     typedef ArrowSection_                                             arrow_section_type;
101:     typedef Bundle<Sieve_,RealSection_,IntSection_,ArrowSection_>     this_type;
102:     typedef typename sieve_type::point_type                           point_type;
103:     typedef malloc_allocator<point_type>                              alloc_type;
104:     typedef typename ALE::LabelSifter<int, point_type>                label_type;
105:     typedef typename std::map<const std::string, Obj<label_type> >    labels_type;
106:     typedef typename label_type::supportSequence                      label_sequence;
107:     typedef std::map<std::string, Obj<arrow_section_type> >           arrow_sections_type;
108:     typedef std::map<std::string, Obj<real_section_type> >            real_sections_type;
109:     typedef std::map<std::string, Obj<int_section_type> >             int_sections_type;
110:     typedef ALE::Point                                                index_type;
111:     typedef std::pair<index_type, int>                                oIndex_type;
112:     typedef std::vector<oIndex_type>                                  oIndexArray;
113:     typedef std::pair<int *, int>                                     indices_type;
114:     typedef NumberingFactory<this_type>                               MeshNumberingFactory;
115:     typedef typename ALE::Partitioner<>::part_type                    rank_type;
116:     typedef typename ALE::Sifter<point_type,rank_type,point_type>     send_overlap_type;
117:     typedef typename ALE::Sifter<rank_type,point_type,point_type>     recv_overlap_type;
118:     typedef typename MeshNumberingFactory::numbering_type             numbering_type;
119:     typedef typename MeshNumberingFactory::order_type                 order_type;
120:     typedef std::map<point_type, point_type>                          renumbering_type;
121:     typedef typename ALE::SieveAlg<this_type>                         sieve_alg_type;
122:     typedef typename sieve_alg_type::coneArray                        coneArray;
123:     typedef typename sieve_alg_type::orientedConeArray                oConeArray;
124:     typedef typename sieve_alg_type::supportArray                     supportArray;
125:   protected:
126:     Obj<sieve_type>       _sieve;
127:     labels_type           _labels;
128:     int                   _maxHeight;
129:     int                   _maxDepth;
130:     arrow_sections_type   _arrowSections;
131:     real_sections_type    _realSections;
132:     int_sections_type     _intSections;
133:     Obj<oIndexArray>      _indexArray;
134:     Obj<MeshNumberingFactory> _factory;
135:     bool                   _calculatedOverlap;
136:     Obj<send_overlap_type> _sendOverlap;
137:     Obj<recv_overlap_type> _recvOverlap;
138:     Obj<send_overlap_type> _distSendOverlap;
139:     Obj<recv_overlap_type> _distRecvOverlap;
140:     renumbering_type       _renumbering; // Maps global points to local points
141:     // Work space
142:     Obj<std::set<point_type> > _modifiedPoints;
143:   public:
144:     Bundle(MPI_Comm comm, int debug = 0) : ALE::ParallelObject(comm, debug), _maxHeight(-1), _maxDepth(-1) {
145:       this->_indexArray        = new oIndexArray();
146:       this->_modifiedPoints    = new std::set<point_type>();
147:       this->_factory           = MeshNumberingFactory::singleton(this->comm(), this->debug());
148:       this->_calculatedOverlap = false;
149:       this->_sendOverlap       = new send_overlap_type(comm, debug);
150:       this->_recvOverlap       = new recv_overlap_type(comm, debug);
151:     };
152:     Bundle(const Obj<sieve_type>& sieve) : ALE::ParallelObject(sieve->comm(), sieve->debug()), _sieve(sieve), _maxHeight(-1), _maxDepth(-1) {
153:       this->_indexArray        = new oIndexArray();
154:       this->_modifiedPoints    = new std::set<point_type>();
155:       this->_factory           = MeshNumberingFactory::singleton(this->comm(), this->debug());
156:       this->_calculatedOverlap = false;
157:       this->_sendOverlap       = new send_overlap_type(this->comm(), this->debug());
158:       this->_recvOverlap       = new recv_overlap_type(this->comm(), this->debug());
159:     };
160:     virtual ~Bundle() {};
161:   public: // Verifiers
162:     bool hasLabel(const std::string& name) {
163:       if (this->_labels.find(name) != this->_labels.end()) {
164:         return true;
165:       }
166:       return false;
167:     };
168:     void checkLabel(const std::string& name) {
169:       if (!this->hasLabel(name)) {
170:         ostringstream msg;
171:         msg << "Invalid label name: " << name << std::endl;
172:         throw ALE::Exception(msg.str().c_str());
173:       }
174:     };
175:   public: // Accessors
176:     const Obj<sieve_type>& getSieve() const {return this->_sieve;};
177:     void setSieve(const Obj<sieve_type>& sieve) {this->_sieve = sieve;};
178:     bool hasArrowSection(const std::string& name) const {
179:       return this->_arrowSections.find(name) != this->_arrowSections.end();
180:     };
181:     const Obj<arrow_section_type>& getArrowSection(const std::string& name) {
182:       if (!this->hasArrowSection(name)) {
183:         Obj<arrow_section_type> section = new arrow_section_type(this->comm(), this->debug());

185:         section->setName(name);
186:         if (this->_debug) {std::cout << "Creating new arrow section: " << name << std::endl;}
187:         this->_arrowSections[name] = section;
188:       }
189:       return this->_arrowSections[name];
190:     };
191:     void setArrowSection(const std::string& name, const Obj<arrow_section_type>& section) {
192:       this->_arrowSections[name] = section;
193:     };
194:     Obj<std::set<std::string> > getArrowSections() const {
195:       Obj<std::set<std::string> > names = std::set<std::string>();

197:       for(typename arrow_sections_type::const_iterator s_iter = this->_arrowSections.begin(); s_iter != this->_arrowSections.end(); ++s_iter) {
198:         names->insert(s_iter->first);
199:       }
200:       return names;
201:     };
202:     bool hasRealSection(const std::string& name) const {
203:       return this->_realSections.find(name) != this->_realSections.end();
204:     };
205:     const Obj<real_section_type>& getRealSection(const std::string& name) {
206:       if (!this->hasRealSection(name)) {
207:         Obj<real_section_type> section = new real_section_type(this->comm(), this->debug());

209:         section->setName(name);
210:         if (this->_debug) {std::cout << "Creating new real section: " << name << std::endl;}
211:         this->_realSections[name] = section;
212:       }
213:       return this->_realSections[name];
214:     };
215:     void setRealSection(const std::string& name, const Obj<real_section_type>& section) {
216:       this->_realSections[name] = section;
217:     };
218:     Obj<std::set<std::string> > getRealSections() const {
219:       Obj<std::set<std::string> > names = std::set<std::string>();

221:       for(typename real_sections_type::const_iterator s_iter = this->_realSections.begin(); s_iter != this->_realSections.end(); ++s_iter) {
222:         names->insert(s_iter->first);
223:       }
224:       return names;
225:     };
226:     bool hasIntSection(const std::string& name) const {
227:       return this->_intSections.find(name) != this->_intSections.end();
228:     };
229:     const Obj<int_section_type>& getIntSection(const std::string& name) {
230:       if (!this->hasIntSection(name)) {
231:         Obj<int_section_type> section = new int_section_type(this->comm(), this->debug());

233:         section->setName(name);
234:         if (this->_debug) {std::cout << "Creating new int section: " << name << std::endl;}
235:         this->_intSections[name] = section;
236:       }
237:       return this->_intSections[name];
238:     };
239:     void setIntSection(const std::string& name, const Obj<int_section_type>& section) {
240:       this->_intSections[name] = section;
241:     };
242:     Obj<std::set<std::string> > getIntSections() const {
243:       Obj<std::set<std::string> > names = std::set<std::string>();

245:       for(typename int_sections_type::const_iterator s_iter = this->_intSections.begin(); s_iter != this->_intSections.end(); ++s_iter) {
246:         names->insert(s_iter->first);
247:       }
248:       return names;
249:     };
250:     const Obj<MeshNumberingFactory>& getFactory() const {return this->_factory;};
251:     bool getCalculatedOverlap() const {return this->_calculatedOverlap;};
252:     void setCalculatedOverlap(const bool calc) {this->_calculatedOverlap = calc;};
253:     const Obj<send_overlap_type>& getSendOverlap() const {return this->_sendOverlap;};
254:     void setSendOverlap(const Obj<send_overlap_type>& overlap) {this->_sendOverlap = overlap;};
255:     const Obj<recv_overlap_type>& getRecvOverlap() const {return this->_recvOverlap;};
256:     void setRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_recvOverlap = overlap;};
257:     const Obj<send_overlap_type>& getDistSendOverlap() const {return this->_distSendOverlap;};
258:     void setDistSendOverlap(const Obj<send_overlap_type>& overlap) {this->_distSendOverlap = overlap;};
259:     const Obj<recv_overlap_type>& getDistRecvOverlap() const {return this->_distRecvOverlap;};
260:     void setDistRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_distRecvOverlap = overlap;};
261:     renumbering_type& getRenumbering() {return this->_renumbering;};
262:   public: // Labels
263:     int getValue (const Obj<label_type>& label, const point_type& point, const int defValue = 0) {
264:       const Obj<typename label_type::coneSequence>& cone = label->cone(point);

266:       if (cone->size() == 0) return defValue;
267:       return *cone->begin();
268:     };
269:     void setValue(const Obj<label_type>& label, const point_type& point, const int value) {
270:       label->setCone(value, point);
271:     };
272:     template<typename InputPoints>
273:     int getMaxValue (const Obj<label_type>& label, const Obj<InputPoints>& points, const int defValue = 0) {
274:       int maxValue = defValue;

276:       for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
277:         maxValue = std::max(maxValue, this->getValue(label, *p_iter, defValue));
278:       }
279:       return maxValue;
280:     }
281:     const Obj<label_type>& createLabel(const std::string& name) {
282:       this->_labels[name] = new label_type(this->comm(), this->debug());
283:       return this->_labels[name];
284:     };
285:     const Obj<label_type>& getLabel(const std::string& name) {
286:       this->checkLabel(name);
287:       return this->_labels[name];
288:     };
289:     void setLabel(const std::string& name, const Obj<label_type>& label) {
290:       this->_labels[name] = label;
291:     };
292:     const labels_type& getLabels() {
293:       return this->_labels;
294:     };
295:     virtual const Obj<label_sequence>& getLabelStratum(const std::string& name, int value) {
296:       this->checkLabel(name);
297:       return this->_labels[name]->support(value);
298:     };
299:   public: // Stratification
300:     template<class InputPoints>
301:     void computeHeight(const Obj<label_type>& height, const Obj<sieve_type>& sieve, const Obj<InputPoints>& points, int& maxHeight) {
302:       this->_modifiedPoints->clear();

304:       for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
305:         // Compute the max height of the points in the support of p, and add 1
306:         int h0 = this->getValue(height, *p_iter, -1);
307:         int h1 = this->getMaxValue(height, sieve->support(*p_iter), -1) + 1;

309:         if(h1 != h0) {
310:           this->setValue(height, *p_iter, h1);
311:           if (h1 > maxHeight) maxHeight = h1;
312:           this->_modifiedPoints->insert(*p_iter);
313:         }
314:       }
315:       // FIX: We would like to avoid the copy here with cone()
316:       if(this->_modifiedPoints->size() > 0) {
317:         this->computeHeight(height, sieve, sieve->cone(this->_modifiedPoints), maxHeight);
318:       }
319:     }
320:     void computeHeights() {
321:       const Obj<label_type>& label = this->createLabel(std::string("height"));

323:       this->_maxHeight = -1;
324:       this->computeHeight(label, this->_sieve, this->_sieve->leaves(), this->_maxHeight);
325:     };
326:     virtual int height() const {return this->_maxHeight;};
327:     virtual int height(const point_type& point) {
328:       return this->getValue(this->_labels["height"], point, -1);
329:     };
330:     virtual const Obj<label_sequence>& heightStratum(int height) {
331:       return this->getLabelStratum("height", height);
332:     };
333:     void setHeight(const Obj<label_type>& label) {
334:       this->_labels["height"] = label;
335:       const Obj<typename label_type::traits::capSequence> cap = label->cap();

337:       for(typename label_type::traits::capSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
338:         this->_maxHeight = std::max(this->_maxHeight, *c_iter);
339:       }
340:     };
341:     template<class InputPoints>
342:     void computeDepth(const Obj<label_type>& depth, const Obj<sieve_type>& sieve, const Obj<InputPoints>& points, int& maxDepth) {
343:       this->_modifiedPoints->clear();

345:       for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
346:         // Compute the max depth of the points in the cone of p, and add 1
347:         int d0 = this->getValue(depth, *p_iter, -1);
348:         int d1 = this->getMaxValue(depth, sieve->cone(*p_iter), -1) + 1;

350:         if(d1 != d0) {
351:           this->setValue(depth, *p_iter, d1);
352:           if (d1 > maxDepth) maxDepth = d1;
353:           this->_modifiedPoints->insert(*p_iter);
354:         }
355:       }
356:       // FIX: We would like to avoid the copy here with support()
357:       if(this->_modifiedPoints->size() > 0) {
358:         this->computeDepth(depth, sieve, sieve->support(this->_modifiedPoints), maxDepth);
359:       }
360:     }
361:     void computeDepths() {
362:       const Obj<label_type>& label = this->createLabel(std::string("depth"));

364:       this->_maxDepth = -1;
365:       this->computeDepth(label, this->_sieve, this->_sieve->roots(), this->_maxDepth);
366:     };
367:     virtual int depth() const {return this->_maxDepth;};
368:     virtual int depth(const point_type& point) {
369:       return this->getValue(this->_labels["depth"], point, -1);
370:     };
371:     virtual const Obj<label_sequence>& depthStratum(int depth) {
372:       return this->getLabelStratum("depth", depth);
373:     };
376:     virtual void stratify() {
377:       ALE_LOG_EVENT_BEGIN;
378:       this->computeHeights();
379:       this->computeDepths();
380:       ALE_LOG_EVENT_END;
381:     };
382:   public: // Size traversal
383:     template<typename Section_>
384:     int size(const Obj<Section_>& section, const point_type& p) {
385:       const typename Section_::chart_type& chart = section->getChart();
386:       int                                  size  = 0;

388:       if (this->height() < 2) {
389:         const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
390:         typename sieve_type::coneSequence::iterator   end  = cone->end();

392:         if (chart.count(p)) {
393:           size += section->getConstrainedFiberDimension(p);
394:         }
395:         for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
396:           if (chart.count(*c_iter)) {
397:             size += section->getConstrainedFiberDimension(*c_iter);
398:           }
399:         }
400:       } else {
401:         const Obj<coneArray>         closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), p);
402:         typename coneArray::iterator end     = closure->end();

404:         for(typename coneArray::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
405:           if (chart.count(*c_iter)) {
406:             size += section->getConstrainedFiberDimension(*c_iter);
407:           }
408:         }
409:       }
410:       return size;
411:     }
412:     template<typename Section_>
413:     int sizeWithBC(const Obj<Section_>& section, const point_type& p) {
414:       const typename Section_::chart_type& chart = section->getChart();
415:       int                                  size  = 0;

417:       if (this->height() < 2) {
418:         const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
419:         typename sieve_type::coneSequence::iterator   end  = cone->end();

421:         if (chart.count(p)) {
422:           size += section->getFiberDimension(p);
423:         }
424:         for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
425:           if (chart.count(*c_iter)) {
426:             size += section->getFiberDimension(*c_iter);
427:           }
428:         }
429:       } else {
430:         const Obj<coneArray>         closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), p);
431:         typename coneArray::iterator end     = closure->end();

433:         for(typename coneArray::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
434:           if (chart.count(*c_iter)) {
435:             size += section->getFiberDimension(*c_iter);
436:           }
437:         }
438:       }
439:       return size;
440:     }
441:   protected:
442:     int *getIndexArray(const int size) {
443:       static int *array   = NULL;
444:       static int  maxSize = 0;

446:       if (size > maxSize) {
447:         maxSize = size;
448:         if (array) delete [] array;
449:         array = new int[maxSize];
450:       };
451:       return array;
452:     };
453:   public: // Index traversal
454:     void expandInterval(const index_type& interval, PetscInt indices[], PetscInt *indx) {
455:       const int end = interval.prefix + interval.index;

457:       for(int i = interval.index; i < end; ++i) {
458:         indices[(*indx)++] = i;
459:       }
460:     };
461:     void expandInterval(const index_type& interval, const int orientation, PetscInt indices[], PetscInt *indx) {
462:       if (orientation >= 0) {
463:         for(int i = 0; i < interval.prefix; ++i) {
464:           indices[(*indx)++] = interval.index + i;
465:         }
466:       } else {
467:         for(int i = interval.prefix-1; i >= 0; --i) {
468:           indices[(*indx)++] = interval.index + i;
469:         }
470:       }
471:       for(int i = 0; i < -interval.prefix; ++i) {
472:         indices[(*indx)++] = -1;
473:       }
474:     };
475:     void expandIntervals(Obj<oIndexArray> intervals, PetscInt *indices) {
476:       int k = 0;

478:       for(typename oIndexArray::iterator i_iter = intervals->begin(); i_iter != intervals->end(); ++i_iter) {
479:         this->expandInterval(i_iter->first, i_iter->second, indices, &k);
480:       }
481:     }
482:     template<typename Section_>
483:     const indices_type getIndicesRaw(const Obj<Section_>& section, const point_type& p) {
484:       int *indexArray = NULL;
485:       int  size       = 0;

487:       const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
488:       typename oConeArray::iterator begin   = closure->begin();
489:       typename oConeArray::iterator end     = closure->end();

491:       for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
492:         size    += section->getFiberDimension(p_iter->first);
493:       }
494:       indexArray = this->getIndexArray(size);
495:       int  k     = 0;
496:       for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
497:         section->getIndicesRaw(p_iter->first, section->getIndex(p_iter->first), indexArray, &k, p_iter->second);
498:       }
499:       return indices_type(indexArray, size);
500:     }
501:     template<typename Section_>
502:     const indices_type getIndices(const Obj<Section_>& section, const point_type& p, const int level = -1) {
503:       int *indexArray = NULL;
504:       int  size       = 0;

506:       if (level == 0) {
507:         size      += section->getFiberDimension(p);
508:         indexArray = this->getIndexArray(size);
509:         int  k     = 0;

511:         section->getIndices(p, indexArray, &k);
512:       } else if ((level == 1) || (this->height() == 1)) {
513:         const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
514:         typename sieve_type::coneSequence::iterator   end  = cone->end();

516:         size      += section->getFiberDimension(p);
517:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
518:           size    += section->getFiberDimension(*p_iter);
519:         }
520:         indexArray = this->getIndexArray(size);
521:         int  k     = 0;

523:         section->getIndices(p, indexArray, &k);
524:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
525:           section->getIndices(*p_iter, indexArray, &k);
526:         }
527:       } else if (level == -1) {
528:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
529:         typename oConeArray::iterator begin   = closure->begin();
530:         typename oConeArray::iterator end     = closure->end();

532:         for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
533:           size    += section->getFiberDimension(p_iter->first);
534:         }
535:         indexArray = this->getIndexArray(size);
536:         int  k     = 0;
537:         for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
538:           section->getIndices(p_iter->first, indexArray, &k, p_iter->second);
539:         }
540:       } else {
541:         throw ALE::Exception("Bundle has not yet implemented getIndices() for an arbitrary level");
542:       }
543:       if (this->debug()) {
544:         for(int i = 0; i < size; ++i) {
545:           printf("[%d]index %d: %d\n", this->commRank(), i, indexArray[i]);
546:         }
547:       }
548:       return indices_type(indexArray, size);
549:     }
550:     template<typename Section_, typename Numbering>
551:     const indices_type getIndices(const Obj<Section_>& section, const point_type& p, const Obj<Numbering>& numbering, const int level = -1) {
552:       int *indexArray = NULL;
553:       int  size       = 0;

555:       if (level == 0) {
556:         size      += section->getFiberDimension(p);
557:         indexArray = this->getIndexArray(size);
558:         int  k     = 0;

560:         section->getIndices(p, numbering, indexArray, &k);
561:       } else if ((level == 1) || (this->height() == 1)) {
562:         const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
563:         typename sieve_type::coneSequence::iterator   end  = cone->end();

565:         size      += section->getFiberDimension(p);
566:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
567:           size    += section->getFiberDimension(*p_iter);
568:         }
569:         indexArray = this->getIndexArray(size);
570:         int  k     = 0;

572:         section->getIndices(p, numbering, indexArray, &k);
573:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
574:           section->getIndices(*p_iter, numbering, indexArray, &k);
575:         }
576:       } else if (level == -1) {
577:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
578:         typename oConeArray::iterator end     = closure->end();

580:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
581:           size    += section->getFiberDimension(p_iter->first);
582:         }
583:         indexArray = this->getIndexArray(size);
584:         int  k     = 0;
585:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
586:           section->getIndices(p_iter->first, numbering, indexArray, &k, p_iter->second);
587:         }
588:       } else {
589:         throw ALE::Exception("Bundle has not yet implemented getIndices() for an arbitrary level");
590:       }
591:       return indices_type(indexArray, size);
592:     }
593:   public: // Retrieval traversal
594:     // Return the values for the closure of this point
595:     //   use a smart pointer?
596:     template<typename Section_>
597:     const typename Section_::value_type *restrictClosure(const Obj<Section_>& section, const point_type& p) {
598:       const int size = this->sizeWithBC(section, p);
599:       return this->restrictClosure(section, p, section->getRawArray(size), size);
600:     }
601:     template<typename Section_>
602:     const typename Section_::value_type *restrictClosure(const Obj<Section_>& section, const point_type& p, typename Section_::value_type  *values, const int valuesSize) {
603:       const int size = this->sizeWithBC(section, p);
604:       int       j    = -1;
605:       if (valuesSize < size) throw ALE::Exception("Input array too small");

607:       // We could actually ask for the height of the individual point
608:       if (this->height() < 2) {
609:         const int& dim = section->getFiberDimension(p);
610:         const typename Section_::value_type *array = section->restrictPoint(p);

612:         for(int i = 0; i < dim; ++i) {
613:           values[++j] = array[i];
614:         }
615:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
616:         typename sieve_type::coneSequence::iterator   end  = cone->end();

618:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
619:           const int& dim = section->getFiberDimension(*p_iter);

621:           array = section->restrictPoint(*p_iter);
622:           for(int i = 0; i < dim; ++i) {
623:             values[++j] = array[i];
624:           }
625:         }
626:       } else {
627:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
628:         typename oConeArray::iterator end     = closure->end();

630:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
631:           const typename Section_::value_type *array = section->restrictPoint(p_iter->first);
632:           const int& dim = section->getFiberDimension(p_iter->first);

634:           if (p_iter->second >= 0) {
635:             for(int i = 0; i < dim; ++i) {
636:               values[++j] = array[i];
637:             }
638:           } else {
639:             for(int i = dim-1; i >= 0; --i) {
640:               values[++j] = array[i];
641:             }
642:           }
643:         }
644:       }
645:       if (j != size-1) {
646:         ostringstream txt;

648:         txt << "Invalid restrict to point " << p << std::endl;
649:         txt << "  j " << j << " should be " << (size-1) << std::endl;
650:         std::cout << txt.str();
651:         throw ALE::Exception(txt.str().c_str());
652:       }
653:       return values;
654:     }
655:     template<typename Section_>
656:     const typename Section_::value_type *restrictNew(const Obj<Section_>& section, const point_type& p) {
657:       const int size = this->sizeWithBC(section, p);
658:       return this->restrictNew(section, p, section->getRawArray(size), size);
659:     }
660:     template<typename Section_>
661:     const typename Section_::value_type *restrictNew(const Obj<Section_>& section, const point_type& p, typename Section_::value_type  *values, const int valuesSize) {
662:       const int                     size    = this->sizeWithBC(section, p);
663:       const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
664:       typename oConeArray::iterator end     = closure->end();
665:       int                           j       = -1;
666:       if (valuesSize < size) throw ALE::Exception("Input array too small");

668:       for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
669:         const typename Section_::value_type *array = section->restrictPoint(p_iter->first);

671:         if (p_iter->second >= 0) {
672:           const int& dim = section->getFiberDimension(p_iter->first);

674:           for(int i = 0; i < dim; ++i) {
675:             values[++j] = array[i];
676:           }
677:         } else {
678:           int offset = 0;

680:           for(int space = 0; space < section->getNumSpaces(); ++space) {
681:             const int& dim = section->getFiberDimension(p_iter->first, space);

683:             for(int i = dim-1; i >= 0; --i) {
684:               values[++j] = array[i+offset];
685:             }
686:             offset += dim;
687:           }
688:         }
689:       }
690:       if (j != size-1) {
691:         ostringstream txt;

693:         txt << "Invalid restrict to point " << p << std::endl;
694:         txt << "  j " << j << " should be " << (size-1) << std::endl;
695:         std::cout << txt.str();
696:         throw ALE::Exception(txt.str().c_str());
697:       }
698:       return values;
699:     }
700:     template<typename Section_>
701:     void update(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
702:       int j = 0;

704:       if (this->height() < 2) {
705:         section->updatePoint(p, &v[j]);
706:         j += section->getFiberDimension(p);
707:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);

709:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
710:           section->updatePoint(*p_iter, &v[j]);
711:           j += section->getFiberDimension(*p_iter);
712:         }
713:       } else {
714:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
715:         typename oConeArray::iterator end     = closure->end();

717:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
718:           section->updatePoint(p_iter->first, &v[j], p_iter->second);
719:           j += section->getFiberDimension(p_iter->first);
720:         }
721:       }
722:     }
723:     template<typename Section_>
724:     void updateAdd(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
725:       int j = 0;

727:       if (this->height() < 2) {
728:         section->updateAddPoint(p, &v[j]);
729:         j += section->getFiberDimension(p);
730:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);

732:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
733:           section->updateAddPoint(*p_iter, &v[j]);
734:           j += section->getFiberDimension(*p_iter);
735:         }
736:       } else {
737:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
738:         typename oConeArray::iterator end     = closure->end();

740:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
741:           section->updateAddPoint(p_iter->first, &v[j], p_iter->second);
742:           j += section->getFiberDimension(p_iter->first);
743:         }
744:       }
745:     }
746:     template<typename Section_>
747:     void updateBC(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
748:       int j = 0;

750:       if (this->height() < 2) {
751:         section->updatePointBC(p, &v[j]);
752:         j += section->getFiberDimension(p);
753:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);

755:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
756:           section->updatePointBC(*p_iter, &v[j]);
757:           j += section->getFiberDimension(*p_iter);
758:         }
759:       } else {
760:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
761:         typename oConeArray::iterator end     = closure->end();

763:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
764:           section->updatePointBC(p_iter->first, &v[j], p_iter->second);
765:           j += section->getFiberDimension(p_iter->first);
766:         }
767:       }
768:     }
769:     template<typename Section_>
770:     void updateAll(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
771:       int j = 0;

773:       if (this->height() < 2) {
774:         section->updatePointAll(p, &v[j]);
775:         j += section->getFiberDimension(p);
776:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);

778:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
779:           section->updatePointAll(*p_iter, &v[j]);
780:           j += section->getFiberDimension(*p_iter);
781:         }
782:       } else {
783:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
784:         typename oConeArray::iterator end     = closure->end();

786:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
787:           section->updatePointAll(p_iter->first, &v[j], p_iter->second);
788:           j += section->getFiberDimension(p_iter->first);
789:         }
790:       }
791:     }
792:     template<typename Section_>
793:     void updateAllAdd(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
794:       int j = 0;

796:       if (this->height() < 2) {
797:         section->updatePointAllAdd(p, &v[j]);
798:         j += section->getFiberDimension(p);
799:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);

801:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
802:           section->updatePointAllAdd(*p_iter, &v[j]);
803:           j += section->getFiberDimension(*p_iter);
804:         }
805:       } else {
806:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
807:         typename oConeArray::iterator end     = closure->end();

809:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
810:           section->updatePointAllAdd(p_iter->first, &v[j], p_iter->second);
811:           j += section->getFiberDimension(p_iter->first);
812:         }
813:       }
814:     }
815:   public: // Optimization
816:     // Calculate a custom atlas for the given traversal
817:     //   This returns the tag value assigned to the traversal
818:     template<typename Section_, typename Sequence_>
819:     int calculateCustomAtlas(const Obj<Section_>& section, const Obj<Sequence_>& points) {
820:       const typename Sequence_::iterator begin    = points->begin();
821:       const typename Sequence_::iterator end      = points->end();
822:       const int                          num      = points->size();
823:       int                               *rOffsets = new int[num+1];
824:       int                               *rIndices;
825:       int                               *uOffsets = new int[num+1];
826:       int                               *uIndices;
827:       int                                p;

829:       p = 0;
830:       rOffsets[p] = 0;
831:       uOffsets[p] = 0;
832:       for(typename Sequence_::iterator p_iter = begin; p_iter != end; ++p_iter, ++p) {
833:         rOffsets[p+1] = rOffsets[p] + this->sizeWithBC(section, *p_iter);
834:         uOffsets[p+1] = rOffsets[p+1];
835:         //uOffsets[p+1] = uOffsets[p] + this->size(section, *p_iter);
836:       }
837:       rIndices = new int[rOffsets[p]];
838:       uIndices = new int[uOffsets[p]];
839:       p = 0;
840:       for(typename Sequence_::iterator p_iter = begin; p_iter != end; ++p_iter, ++p) {
841:         const indices_type rIdx = this->getIndicesRaw(section, *p_iter);
842:         for(int i = 0, k = rOffsets[p]; k < rOffsets[p+1]; ++i, ++k) rIndices[k] = rIdx.first[i];

844:         const indices_type uIdx = this->getIndices(section, *p_iter);
845:         for(int i = 0, k = uOffsets[p]; k < uOffsets[p+1]; ++i, ++k) uIndices[k] = uIdx.first[i];
846:       }
847:       return section->setCustomAtlas(rOffsets, rIndices, uOffsets, uIndices);
848:     }
849:     template<typename Section_>
850:     const typename Section_::value_type *restrictClosure(const Obj<Section_>& section, const int tag, const int p) {
851:       const int *offsets, *indices;

853:       section->getCustomRestrictAtlas(tag, &offsets, &indices);
854:       const int size = offsets[p+1] - offsets[p];
855:       return this->restrictClosure(section, tag, p, section->getRawArray(size), offsets, indices);
856:     }
857:     template<typename Section_>
858:     const typename Section_::value_type *restrictClosure(const Obj<Section_>& section, const int tag, const int p, typename Section_::value_type  *values, const int valuesSize) {
859:       const int *offsets, *indices;

861:       section->getCustomRestrictAtlas(tag, &offsets, &indices);
862:       const int size = offsets[p+1] - offsets[p];
863:       if (valuesSize < size) {throw ALE::Exception("Input array too small");}
864:       return this->restrictClosure(section, tag, p, values, offsets, indices);
865:     }
866:     template<typename Section_>
867:     const typename Section_::value_type *restrictClosure(const Obj<Section_>& section, const int tag, const int p, typename Section_::value_type  *values, const int offsets[], const int indices[]) {
868:       const typename Section_::value_type *array = section->restrictSpace();

870:       const int size = offsets[p+1] - offsets[p];
871:       for(int j = 0, k = offsets[p]; j < size; ++j, ++k) {
872:         values[j] = array[indices[k]];
873:       }
874:       return values;
875:     }
876:     template<typename Section_>
877:     void updateAdd(const Obj<Section_>& section, const int tag, const int p, const typename Section_::value_type values[]) {
878:       typename Section_::value_type *array = (typename Section_::value_type *) section->restrictSpace();
879:       const int *offsets, *indices;

881:       section->getCustomUpdateAtlas(tag, &offsets, &indices);
882:       const int size = offsets[p+1] - offsets[p];
883:       for(int j = 0, k = offsets[p]; j < size; ++j, ++k) {
884:         if (indices[k] < 0) continue;
885:         array[indices[k]] += values[j];
886:       }
887:     }
888:   public: // Allocation
889:     template<typename Section_>
890:     void allocate(const Obj<Section_>& section, const Obj<send_overlap_type>& sendOverlap = NULL) {
891:       bool doGhosts = !sendOverlap.isNull();

893:       this->_factory->orderPatch(section, this->getSieve(), sendOverlap);
894:       if (doGhosts) {
895:         if (this->_debug > 1) {std::cout << "Ordering patch for ghosts" << std::endl;}
896:         const typename Section_::chart_type& points = section->getChart();
897:         typename Section_::index_type::index_type offset = 0;

899:         for(typename Section_::chart_type::const_iterator point = points.begin(); point != points.end(); ++point) {
900:           const typename Section_::index_type& idx = section->getIndex(*point);

902:           offset = std::max(offset, idx.index + std::abs(idx.prefix));
903:         }
904:         this->_factory->orderPatch(section, this->getSieve(), NULL, offset);
905:         if (offset != section->sizeWithBC()) throw ALE::Exception("Inconsistent array sizes in section");
906:       }
907:       section->allocateStorage();
908:     }
909:     template<typename Section_>
910:     void reallocate(const Obj<Section_>& section) {
911:       if (section->getNewAtlas().isNull()) return;
912:       // Since copy() preserves offsets, we must reinitialize them before ordering
913:       const Obj<typename Section_::atlas_type>         atlas    = section->getAtlas();
914:       const Obj<typename Section_::atlas_type>&        newAtlas = section->getNewAtlas();
915:       const typename Section_::atlas_type::chart_type& chart    = newAtlas->getChart();
916:       const typename Section_::atlas_type::chart_type& oldChart = atlas->getChart();
917:       int                                              newSize  = 0;
918:       typename Section_::index_type                    defaultIdx(0, -1);

920:       for(typename Section_::atlas_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
921:         defaultIdx.prefix = newAtlas->restrictPoint(*c_iter)[0].prefix;
922:         newAtlas->updatePoint(*c_iter, &defaultIdx);
923:         newSize += defaultIdx.prefix;
924:       }
925:       section->setAtlas(newAtlas);
926:       this->_factory->orderPatch(section, this->getSieve());
927:       // Copy over existing values
928:       typedef typename alloc_type::template rebind<typename Section_::value_type>::other value_alloc_type;
929:       value_alloc_type value_allocator;
930:       typename Section_::value_type                   *newArray = value_allocator.allocate(newSize);
931:       for(int i = 0; i < newSize; ++i) {value_allocator.construct(newArray+i, typename Section_::value_type());}
932:       ///typename Section_::value_type                   *newArray = new typename Section_::value_type[newSize];
933:       const typename Section_::value_type             *array    = section->restrictSpace();

935:       for(typename Section_::atlas_type::chart_type::const_iterator c_iter = oldChart.begin(); c_iter != oldChart.end(); ++c_iter) {
936:         const int& dim       = section->getFiberDimension(*c_iter);
937:         const int& offset    = atlas->restrictPoint(*c_iter)->index;
938:         const int& newOffset = newAtlas->restrictPoint(*c_iter)->index;

940:         for(int i = 0; i < dim; ++i) {
941:           newArray[newOffset+i] = array[offset+i];
942:         }
943:       }
944:       section->replaceStorage(newArray);
945:     }
946:   public: // Overlap
947:     template<typename Sequence>
948:     void constructOverlap(const Obj<Sequence>& points, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap) {
949:       point_type *sendBuf = new point_type[points->size()];
950:       int         size    = 0;
951:       for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
952:         sendBuf[size++] = *l_iter;
953:       }
954:       int *sizes   = new int[this->commSize()];   // The number of points coming from each process
955:       int *offsets = new int[this->commSize()+1]; // Prefix sums for sizes
956:       int *oldOffs = new int[this->commSize()+1]; // Temporary storage
957:       point_type *remotePoints = NULL;            // The points from each process
958:       int        *remoteRanks  = NULL;            // The rank and number of overlap points of each process that overlaps another

960:       // Change to Allgather() for the correct binning algorithm
961:       MPI_Gather(&size, 1, MPI_INT, sizes, 1, MPI_INT, 0, this->comm());
962:       if (this->commRank() == 0) {
963:         offsets[0] = 0;
964:         for(int p = 1; p <= this->commSize(); p++) {
965:           offsets[p] = offsets[p-1] + sizes[p-1];
966:         }
967:         remotePoints = new point_type[offsets[this->commSize()]];
968:       }
969:       MPI_Gatherv(sendBuf, size, MPI_INT, remotePoints, sizes, offsets, MPI_INT, 0, this->comm());
970:       delete [] sendBuf;
971:       std::map<int, std::map<int, std::set<point_type> > > overlapInfo; // Maps (p,q) to their set of overlap points

973:       if (this->commRank() == 0) {
974:         for(int p = 0; p < this->commSize(); p++) {
975:           std::sort(&remotePoints[offsets[p]], &remotePoints[offsets[p+1]]);
976:         }
977:         for(int p = 0; p <= this->commSize(); p++) {
978:           oldOffs[p] = offsets[p];
979:         }
980:         for(int p = 0; p < this->commSize(); p++) {
981:           for(int q = p+1; q < this->commSize(); q++) {
982:             std::set_intersection(&remotePoints[oldOffs[p]], &remotePoints[oldOffs[p+1]],
983:                                   &remotePoints[oldOffs[q]], &remotePoints[oldOffs[q+1]],
984:                                   std::insert_iterator<std::set<point_type> >(overlapInfo[p][q], overlapInfo[p][q].begin()));
985:             overlapInfo[q][p] = overlapInfo[p][q];
986:           }
987:           sizes[p]     = overlapInfo[p].size()*2;
988:           offsets[p+1] = offsets[p] + sizes[p];
989:         }
990:         remoteRanks = new int[offsets[this->commSize()]];
991:         int       k = 0;
992:         for(int p = 0; p < this->commSize(); p++) {
993:           for(typename std::map<int, std::set<point_type> >::iterator r_iter = overlapInfo[p].begin(); r_iter != overlapInfo[p].end(); ++r_iter) {
994:             remoteRanks[k*2]   = r_iter->first;
995:             remoteRanks[k*2+1] = r_iter->second.size();
996:             k++;
997:           }
998:         }
999:       }
1000:       int numOverlaps;                          // The number of processes overlapping this process
1001:       MPI_Scatter(sizes, 1, MPI_INT, &numOverlaps, 1, MPI_INT, 0, this->comm());
1002:       int *overlapRanks = new int[numOverlaps]; // The rank and overlap size for each overlapping process
1003:       MPI_Scatterv(remoteRanks, sizes, offsets, MPI_INT, overlapRanks, numOverlaps, MPI_INT, 0, this->comm());
1004:       point_type *sendPoints = NULL;            // The points to send to each process
1005:       if (this->commRank() == 0) {
1006:         for(int p = 0, k = 0; p < this->commSize(); p++) {
1007:           sizes[p] = 0;
1008:           for(int r = 0; r < (int) overlapInfo[p].size(); r++) {
1009:             sizes[p] += remoteRanks[k*2+1];
1010:             k++;
1011:           }
1012:           offsets[p+1] = offsets[p] + sizes[p];
1013:         }
1014:         sendPoints = new point_type[offsets[this->commSize()]];
1015:         for(int p = 0, k = 0; p < this->commSize(); p++) {
1016:           for(typename std::map<int, std::set<point_type> >::iterator r_iter = overlapInfo[p].begin(); r_iter != overlapInfo[p].end(); ++r_iter) {
1017:             int rank = r_iter->first;
1018:             for(typename std::set<point_type>::iterator p_iter = (overlapInfo[p][rank]).begin(); p_iter != (overlapInfo[p][rank]).end(); ++p_iter) {
1019:               sendPoints[k++] = *p_iter;
1020:             }
1021:           }
1022:         }
1023:       }
1024:       int numOverlapPoints = 0;
1025:       for(int r = 0; r < numOverlaps/2; r++) {
1026:         numOverlapPoints += overlapRanks[r*2+1];
1027:       }
1028:       point_type *overlapPoints = new point_type[numOverlapPoints];
1029:       MPI_Scatterv(sendPoints, sizes, offsets, MPI_INT, overlapPoints, numOverlapPoints, MPI_INT, 0, this->comm());

1031:       for(int r = 0, k = 0; r < numOverlaps/2; r++) {
1032:         int rank = overlapRanks[r*2];

1034:         for(int p = 0; p < overlapRanks[r*2+1]; p++) {
1035:           point_type point = overlapPoints[k++];

1037:           sendOverlap->addArrow(point, rank, point);
1038:           recvOverlap->addArrow(rank, point, point);
1039:         }
1040:       }

1042:       delete [] overlapPoints;
1043:       delete [] overlapRanks;
1044:       delete [] sizes;
1045:       delete [] offsets;
1046:       delete [] oldOffs;
1047:       if (this->commRank() == 0) {
1048:         delete [] remoteRanks;
1049:         delete [] remotePoints;
1050:         delete [] sendPoints;
1051:       }
1052:     }
1053:     void constructOverlap() {
1054:       if (this->_calculatedOverlap) return;
1055:       this->constructOverlap(this->getSieve()->base(), this->getSendOverlap(), this->getRecvOverlap());
1056:       this->constructOverlap(this->getSieve()->cap(),  this->getSendOverlap(), this->getRecvOverlap());
1057:       if (this->debug()) {
1058:         this->_sendOverlap->view("Send overlap");
1059:         this->_recvOverlap->view("Receive overlap");
1060:       }
1061:       this->_calculatedOverlap = true;
1062:     }
1063:   };
1064:   class BoundaryCondition : public ALE::ParallelObject {
1065:   public:
1066:     typedef double (*function_type)(const PetscReal []);
1067:     typedef double (*integrator_type)(const PetscReal [], const PetscReal [], const int, function_type);
1068:   protected:
1069:     std::string     _labelName;
1070:     int             _marker;
1071:     function_type   _func;
1072:     integrator_type _integrator;
1073:   public:
1074:     BoundaryCondition(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {};
1075:     ~BoundaryCondition() {};
1076:   public:
1077:     const std::string& getLabelName() const {return this->_labelName;};
1078:     void setLabelName(const std::string& name) {this->_labelName = name;};
1079:     int getMarker() const {return this->_marker;};
1080:     void setMarker(const int marker) {this->_marker = marker;};
1081:     function_type getFunction() const {return this->_func;};
1082:     void setFunction(function_type func) {this->_func = func;};
1083:     integrator_type getDualIntegrator() const {return this->_integrator;};
1084:     void setDualIntegrator(integrator_type integrator) {this->_integrator = integrator;};
1085:   public:
1086:     PetscReal evaluate(const PetscReal coords[]) const {return this->_func(coords);};
1087:     PetscReal integrateDual(const PetscReal v0[], const PetscReal J[], const int dualIndex) const {return this->_integrator(v0, J, dualIndex, this->_func);};
1088:   };
1089:   class Discretization : public ALE::ParallelObject {
1090:     typedef std::map<std::string, Obj<BoundaryCondition> > boundaryConditions_type;
1091:   protected:
1092:     boundaryConditions_type _boundaryConditions;
1093:     Obj<BoundaryCondition> _exactSolution;
1094:     std::map<int,int> _dim2dof;
1095:     std::map<int,int> _dim2class;
1096:     int           _quadSize;
1097:     const PetscReal *_points;
1098:     const PetscReal *_weights;
1099:     int           _basisSize;
1100:     const PetscReal *_basis;
1101:     const PetscReal *_basisDer;
1102:     const int    *_indices;
1103:     std::map<int, const int *> _exclusionIndices;
1104:   public:
1105:     Discretization(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug), _quadSize(0), _points(NULL), _weights(NULL), _basisSize(0), _basis(NULL), _basisDer(NULL), _indices(NULL) {};
1106:     virtual ~Discretization() {
1107:       if (this->_indices) {delete [] this->_indices;}
1108:       for(std::map<int, const int *>::iterator i_iter = _exclusionIndices.begin(); i_iter != _exclusionIndices.end(); ++i_iter) {
1109:         delete [] i_iter->second;
1110:       }
1111:     };
1112:   public:
1113:     bool hasBoundaryCondition() {return (this->_boundaryConditions.find("default") != this->_boundaryConditions.end());};
1114:     const Obj<BoundaryCondition>& getBoundaryCondition() {return this->getBoundaryCondition("default");};
1115:     void setBoundaryCondition(const Obj<BoundaryCondition>& boundaryCondition) {this->setBoundaryCondition("default", boundaryCondition);};
1116:     const Obj<BoundaryCondition>& getBoundaryCondition(const std::string& name) {return this->_boundaryConditions[name];};
1117:     void setBoundaryCondition(const std::string& name, const Obj<BoundaryCondition>& boundaryCondition) {this->_boundaryConditions[name] = boundaryCondition;};
1118:     Obj<std::set<std::string> > getBoundaryConditions() const {
1119:       Obj<std::set<std::string> > names = std::set<std::string>();

1121:       for(boundaryConditions_type::const_iterator d_iter = this->_boundaryConditions.begin(); d_iter != this->_boundaryConditions.end(); ++d_iter) {
1122:         names->insert(d_iter->first);
1123:       }
1124:       return names;
1125:     };
1126:     const Obj<BoundaryCondition>& getExactSolution() {return this->_exactSolution;};
1127:     void setExactSolution(const Obj<BoundaryCondition>& exactSolution) {this->_exactSolution = exactSolution;};
1128:     int           getQuadratureSize() {return this->_quadSize;};
1129:     void          setQuadratureSize(const int size) {this->_quadSize = size;};
1130:     const PetscReal *getQuadraturePoints() {return this->_points;};
1131:     void          setQuadraturePoints(const PetscReal *points) {this->_points = points;};
1132:     const PetscReal *getQuadratureWeights() {return this->_weights;};
1133:     void          setQuadratureWeights(const PetscReal *weights) {this->_weights = weights;};
1134:     int           getBasisSize() {return this->_basisSize;};
1135:     void          setBasisSize(const int size) {this->_basisSize = size;};
1136:     const PetscReal *getBasis() {return this->_basis;};
1137:     void          setBasis(const PetscReal *basis) {this->_basis = basis;};
1138:     const PetscReal *getBasisDerivatives() {return this->_basisDer;};
1139:     void          setBasisDerivatives(const PetscReal *basisDer) {this->_basisDer = basisDer;};
1140:     int  getNumDof(const int dim) {return this->_dim2dof[dim];};
1141:     void setNumDof(const int dim, const int numDof) {this->_dim2dof[dim] = numDof;};
1142:     int  getDofClass(const int dim) {return this->_dim2class[dim];};
1143:     void setDofClass(const int dim, const int dofClass) {this->_dim2class[dim] = dofClass;};
1144:   public:
1145:     const int *getIndices() {return this->_indices;};
1146:     const int *getIndices(const int marker) {
1147:       if (!marker) return this->getIndices();
1148:       return this->_exclusionIndices[marker];
1149:     };
1150:     void       setIndices(const int *indices) {this->_indices = indices;};
1151:     void       setIndices(const int *indices, const int marker) {
1152:       if (!marker) this->_indices = indices;
1153:       this->_exclusionIndices[marker] = indices;
1154:     };
1155:     template<typename Bundle>
1156:     int sizeV(Bundle& mesh) {
1157:       typedef typename ISieveVisitor::PointRetriever<typename Bundle::sieve_type> Visitor;
1158:       Visitor pV((int) pow((double) mesh.getSieve()->getMaxConeSize(), mesh.depth())+1, true);
1159:       ISieveTraversal<typename Bundle::sieve_type>::orientedClosure(*mesh.getSieve(), *mesh.heightStratum(0)->begin(), pV);
1160:       const typename Visitor::point_type *oPoints = pV.getPoints();
1161:       const int                           oSize   = pV.getSize();
1162:       int                                 size    = 0;

1164:       for(int cl = 0; cl < oSize; ++cl) {
1165:         size += this->_dim2dof[mesh.depth(oPoints[cl])];
1166:       }
1167:       return size;
1168:     }
1169:     template<typename Bundle>
1170:     int size(const Obj<Bundle>& mesh) {
1171:       const Obj<typename Bundle::label_sequence>& cells   = mesh->heightStratum(0);
1172:       const Obj<typename Bundle::coneArray>       closure = ALE::SieveAlg<Bundle>::closure(mesh, *cells->begin());
1173:       const typename Bundle::coneArray::iterator  end     = closure->end();
1174:       int                                         size    = 0;

1176:       for(typename Bundle::coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
1177:         size += this->_dim2dof[mesh->depth(*cl_iter)];
1178:       }
1179:       return size;
1180:     }
1181:   };
1182: }

1184: namespace ALE {
1185:   template<typename Sieve_,
1186:            typename RealSection_  = Section<typename Sieve_::point_type, double>,
1187:            typename IntSection_   = Section<typename Sieve_::point_type, int>,
1188:            typename Label_        = LabelSifter<int, typename Sieve_::point_type>,
1189:            typename ArrowSection_ = UniformSection<MinimalArrow<typename Sieve_::point_type, typename Sieve_::point_type>, int> >
1190:   class IBundle : public ALE::ParallelObject {
1191:   public:
1192:     typedef Sieve_                                                    sieve_type;
1193:     typedef RealSection_                                              real_section_type;
1194:     typedef IntSection_                                               int_section_type;
1195:     typedef ArrowSection_                                             arrow_section_type;
1196:     typedef IBundle<Sieve_,RealSection_,IntSection_,Label_,ArrowSection_> this_type;
1197:     typedef typename sieve_type::point_type                           point_type;
1198:     typedef malloc_allocator<point_type>                              alloc_type;
1199:     typedef Label_                                                    label_type;
1200:     typedef typename std::map<const std::string, Obj<label_type> >    labels_type;
1201:     typedef typename label_type::supportSequence                      label_sequence;
1202:     typedef std::map<std::string, Obj<arrow_section_type> >           arrow_sections_type;
1203:     typedef std::map<std::string, Obj<real_section_type> >            real_sections_type;
1204:     typedef std::map<std::string, Obj<int_section_type> >             int_sections_type;
1205:     typedef ALE::Point                                                index_type;
1206:     typedef std::pair<index_type, int>                                oIndex_type;
1207:     typedef std::vector<oIndex_type>                                  oIndexArray;
1208:     typedef std::pair<int *, int>                                     indices_type;
1209:     typedef NumberingFactory<this_type>                               MeshNumberingFactory;
1210:     typedef typename ALE::Partitioner<>::part_type                    rank_type;
1211: #define USE_NEW_OVERLAP
1212: #ifdef USE_NEW_OVERLAP
1213:     typedef typename PETSc::SendOverlap<point_type,rank_type>         send_overlap_type;
1214:     typedef typename PETSc::RecvOverlap<point_type,rank_type>         recv_overlap_type;
1215: #else
1216:     typedef typename ALE::Sifter<point_type,rank_type,point_type>     send_overlap_type;
1217:     typedef typename ALE::Sifter<rank_type,point_type,point_type>     recv_overlap_type;
1218: #endif
1219:     typedef typename MeshNumberingFactory::numbering_type             numbering_type;
1220:     typedef typename MeshNumberingFactory::order_type                 order_type;
1221:     typedef std::map<point_type, point_type>                          renumbering_type;
1222:     // These should go away
1223:     typedef typename ALE::SieveAlg<this_type>                         sieve_alg_type;
1224:     typedef typename sieve_alg_type::coneArray                        coneArray;
1225:     typedef typename sieve_alg_type::orientedConeArray                oConeArray;
1226:     typedef typename sieve_alg_type::supportArray                     supportArray;
1227:   public:
1228:     class LabelVisitor {
1229:     protected:
1230:       label_type& label;
1231:       int         defaultValue;
1232:       int         value;
1233:     public:
1234:       LabelVisitor(label_type& l, const int defValue) : label(l), defaultValue(defValue), value(defValue) {};
1235:       int getLabelValue(const point_type& point) const {
1236:         const Obj<typename label_type::coneSequence>& cone = this->label.cone(point);

1238:         if (cone->size() == 0) return this->defaultValue;
1239:         return *cone->begin();
1240:       };
1241:       void setLabelValue(const point_type& point, const int value) {
1242:         this->label.setCone(value, point);
1243:       };
1244:       int getValue() const {return this->value;};
1245:     };
1246:     class MaxConeVisitor : public LabelVisitor {
1247:     public:
1248:       MaxConeVisitor(label_type& l, const int defValue) : LabelVisitor(l, defValue) {};
1249:       void visitPoint(const typename sieve_type::point_type& point) {};
1250:       void visitArrow(const typename sieve_type::arrow_type& arrow) {
1251:         this->value = std::max(this->value, this->getLabelValue(arrow.source));
1252:       };
1253:     };
1254:     class MaxSupportVisitor : public LabelVisitor {
1255:     public:
1256:       MaxSupportVisitor(label_type& l, const int defValue) : LabelVisitor(l, defValue) {};
1257:       void visitPoint(const typename sieve_type::point_type& point) {};
1258:       void visitArrow(const typename sieve_type::arrow_type& arrow) {
1259:         this->value = std::max(this->value, this->getLabelValue(arrow.target));
1260:       };
1261:     };
1262:     class BinaryStratifyVisitor {
1263:     protected:
1264:       label_type& height;
1265:       label_type& depth;
1266:       bool        isLeaf;
1267:     public:
1268:       BinaryStratifyVisitor(label_type& h, label_type& d, bool isLeaf) : height(h), depth(d), isLeaf(isLeaf) {};
1269:       void visitPoint(const typename sieve_type::point_type& point) {
1270:         if (isLeaf) {
1271:           height.setCone(0, point);
1272:           depth.setCone(1, point);
1273:         } else {
1274:           height.setCone(1, point);
1275:           depth.setCone(0, point);
1276:         }
1277:       };
1278:     };
1279:     class HeightVisitor {
1280:     protected:
1281:       const sieve_type& sieve;
1282:       label_type&       height;
1283:       int               maxHeight;
1284:       std::set<typename sieve_type::point_type> modifiedPoints;
1285:     public:
1286:       HeightVisitor(const sieve_type& s, label_type& h) : sieve(s), height(h), maxHeight(0) {};
1287:       void visitPoint(const typename sieve_type::point_type& point) {
1288:         MaxSupportVisitor v(height, -1);

1290:         // Compute the max height of the points in the support of p, and add 1
1291:         this->sieve.support(point, v);
1292:         const int h0 = v.getLabelValue(point);
1293:         const int h1 = v.getValue() + 1;

1295:         if(h1 != h0) {
1296:           v.setLabelValue(point, h1);
1297:           if (h1 > this->maxHeight) this->maxHeight = h1;
1298:           this->modifiedPoints.insert(point);
1299:         }
1300:       };
1301:       void visitArrow(const typename sieve_type::arrow_type& arrow) {
1302:         this->visitPoint(arrow.source);
1303:       };
1304:       int getMaxHeight() const {return this->maxHeight;};
1305:       bool isModified() const {return this->modifiedPoints.size() > 0;};
1306:       const std::set<typename sieve_type::point_type>& getModifiedPoints() const {return this->modifiedPoints;};
1307:       void clear() {this->modifiedPoints.clear();};
1308:     };
1309:     class DepthVisitor {
1310:     public:
1311:       typedef typename sieve_type::point_type point_type;
1312:     protected:
1313:       const sieve_type& sieve;
1314:       label_type&       depth;
1315:       int               maxDepth;
1316:       const point_type  limitPoint;
1317:       std::set<point_type> modifiedPoints;
1318:     public:
1319:       DepthVisitor(const sieve_type& s, label_type& d) : sieve(s), depth(d), maxDepth(0), limitPoint(sieve.getChart().max()+1) {};
1320:       DepthVisitor(const sieve_type& s, const point_type& limit, label_type& d) : sieve(s), depth(d), maxDepth(-1), limitPoint(limit) {};
1321:       void visitPoint(const point_type& point) {
1322:         if (point >= this->limitPoint) return;
1323:         MaxConeVisitor v(depth, -1);

1325:         // Compute the max height of the points in the support of p, and add 1
1326:         this->sieve.cone(point, v);
1327:         const int d0 = v.getLabelValue(point);
1328:         const int d1 = v.getValue() + 1;

1330:         if(d1 != d0) {
1331:           v.setLabelValue(point, d1);
1332:           if (d1 > this->maxDepth) this->maxDepth = d1;
1333:           this->modifiedPoints.insert(point);
1334:         }
1335:       };
1336:       void visitArrow(const typename sieve_type::arrow_type& arrow) {
1337:         this->visitPoint(arrow.target);
1338:       };
1339:       int getMaxDepth() const {return this->maxDepth;};
1340:       bool isModified() const {return this->modifiedPoints.size() > 0;};
1341:       const std::set<typename sieve_type::point_type>& getModifiedPoints() const {return this->modifiedPoints;};
1342:       void clear() {this->modifiedPoints.clear();};
1343:     };
1344:   protected:
1345:     Obj<sieve_type>       _sieve;
1346:     labels_type           _labels;
1347:     int                   _maxHeight;
1348:     int                   _maxDepth;
1349:     arrow_sections_type   _arrowSections;
1350:     real_sections_type    _realSections;
1351:     int_sections_type     _intSections;
1352:     Obj<oIndexArray>      _indexArray;
1353:     Obj<MeshNumberingFactory> _factory;
1354:     bool                   _calculatedOverlap;
1355:     Obj<send_overlap_type> _sendOverlap;
1356:     Obj<recv_overlap_type> _recvOverlap;
1357:     Obj<send_overlap_type> _distSendOverlap;
1358:     Obj<recv_overlap_type> _distRecvOverlap;
1359:     renumbering_type       _renumbering;
1360:     // Work space
1361:     Obj<std::set<point_type> > _modifiedPoints;
1362:   public:
1363:     IBundle(MPI_Comm comm, int debug = 0) : ALE::ParallelObject(comm, debug), _maxHeight(-1), _maxDepth(-1) {
1364:       this->_indexArray        = new oIndexArray();
1365:       this->_modifiedPoints    = new std::set<point_type>();
1366:       this->_factory           = MeshNumberingFactory::singleton(this->comm(), this->debug());
1367:       this->_calculatedOverlap = false;
1368:       this->_sendOverlap       = new send_overlap_type(this->comm(), this->debug());
1369:       this->_recvOverlap       = new recv_overlap_type(this->comm(), this->debug());
1370:     };
1371:     IBundle(const Obj<sieve_type>& sieve) : ALE::ParallelObject(sieve->comm(), sieve->debug()), _sieve(sieve), _maxHeight(-1), _maxDepth(-1) {
1372:       this->_indexArray        = new oIndexArray();
1373:       this->_modifiedPoints    = new std::set<point_type>();
1374:       this->_factory           = MeshNumberingFactory::singleton(this->comm(), this->debug());
1375:       this->_calculatedOverlap = false;
1376:       this->_sendOverlap       = new send_overlap_type(this->comm(), this->debug());
1377:       this->_recvOverlap       = new recv_overlap_type(this->comm(), this->debug());
1378:     };
1379:     virtual ~IBundle() {};
1380:   public: // Verifiers
1381:     bool hasLabel(const std::string& name) {
1382:       if (this->_labels.find(name) != this->_labels.end()) {
1383:         return true;
1384:       }
1385:       return false;
1386:     };
1387:     void checkLabel(const std::string& name) {
1388:       if (!this->hasLabel(name)) {
1389:         ostringstream msg;
1390:         msg << "Invalid label name: " << name << std::endl;
1391:         throw ALE::Exception(msg.str().c_str());
1392:       }
1393:     };
1394:   public: // Accessors
1395:     const Obj<sieve_type>& getSieve() const {return this->_sieve;};
1396:     void setSieve(const Obj<sieve_type>& sieve) {this->_sieve = sieve;};
1397:     bool hasArrowSection(const std::string& name) const {
1398:       return this->_arrowSections.find(name) != this->_arrowSections.end();
1399:     };
1400:     const Obj<arrow_section_type>& getArrowSection(const std::string& name) {
1401:       if (!this->hasArrowSection(name)) {
1402:         Obj<arrow_section_type> section = new arrow_section_type(this->comm(), this->debug());

1404:         section->setName(name);
1405:         if (this->_debug) {std::cout << "Creating new arrow section: " << name << std::endl;}
1406:         this->_arrowSections[name] = section;
1407:       }
1408:       return this->_arrowSections[name];
1409:     };
1410:     void setArrowSection(const std::string& name, const Obj<arrow_section_type>& section) {
1411:       this->_arrowSections[name] = section;
1412:     };
1413:     Obj<std::set<std::string> > getArrowSections() const {
1414:       Obj<std::set<std::string> > names = std::set<std::string>();

1416:       for(typename arrow_sections_type::const_iterator s_iter = this->_arrowSections.begin(); s_iter != this->_arrowSections.end(); ++s_iter) {
1417:         names->insert(s_iter->first);
1418:       }
1419:       return names;
1420:     };
1421:     bool hasRealSection(const std::string& name) const {
1422:       return this->_realSections.find(name) != this->_realSections.end();
1423:     };
1424:     const Obj<real_section_type>& getRealSection(const std::string& name) {
1425:       if (!this->hasRealSection(name)) {
1426:         Obj<real_section_type> section = new real_section_type(this->comm(), this->debug());

1428:         section->setName(name);
1429:         if (this->_debug) {std::cout << "Creating new real section: " << name << std::endl;}
1430:         this->_realSections[name] = section;
1431:       }
1432:       return this->_realSections[name];
1433:     };
1434:     void setRealSection(const std::string& name, const Obj<real_section_type>& section) {
1435:       this->_realSections[name] = section;
1436:     };
1437:     Obj<std::set<std::string> > getRealSections() const {
1438:       Obj<std::set<std::string> > names = std::set<std::string>();

1440:       for(typename real_sections_type::const_iterator s_iter = this->_realSections.begin(); s_iter != this->_realSections.end(); ++s_iter) {
1441:         names->insert(s_iter->first);
1442:       }
1443:       return names;
1444:     };
1445:     bool hasIntSection(const std::string& name) const {
1446:       return this->_intSections.find(name) != this->_intSections.end();
1447:     };
1448:     const Obj<int_section_type>& getIntSection(const std::string& name) {
1449:       if (!this->hasIntSection(name)) {
1450:         Obj<int_section_type> section = new int_section_type(this->comm(), this->debug());

1452:         section->setName(name);
1453:         if (this->_debug) {std::cout << "Creating new int section: " << name << std::endl;}
1454:         this->_intSections[name] = section;
1455:       }
1456:       return this->_intSections[name];
1457:     };
1458:     void setIntSection(const std::string& name, const Obj<int_section_type>& section) {
1459:       this->_intSections[name] = section;
1460:     };
1461:     Obj<std::set<std::string> > getIntSections() const {
1462:       Obj<std::set<std::string> > names = std::set<std::string>();

1464:       for(typename int_sections_type::const_iterator s_iter = this->_intSections.begin(); s_iter != this->_intSections.end(); ++s_iter) {
1465:         names->insert(s_iter->first);
1466:       }
1467:       return names;
1468:     };
1469:     const Obj<MeshNumberingFactory>& getFactory() const {return this->_factory;};
1470:     renumbering_type& getRenumbering() {return this->_renumbering;};
1471:   public: // Labels
1472:     int getValue (const Obj<label_type>& label, const point_type& point, const int defValue = 0) {
1473:       const Obj<typename label_type::coneSequence>& cone = label->cone(point);

1475:       if (cone->size() == 0) return defValue;
1476:       return *cone->begin();
1477:     };
1478:     void setValue(const Obj<label_type>& label, const point_type& point, const int value) {
1479:       label->setCone(value, point);
1480:     };
1481:     void addValue(const Obj<label_type>& label, const point_type& point, const int value) {
1482:       label->addCone(value, point);
1483:     };
1484:     template<typename InputPoints>
1485:     int getMaxValue (const Obj<label_type>& label, const Obj<InputPoints>& points, const int defValue = 0) {
1486:       int maxValue = defValue;

1488:       for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
1489:         maxValue = std::max(maxValue, this->getValue(label, *p_iter, defValue));
1490:       }
1491:       return maxValue;
1492:     }
1493:     const Obj<label_type>& createLabel(const std::string& name) {
1494:       this->_labels[name] = new label_type(this->comm(), this->debug());
1495:       return this->_labels[name];
1496:     };
1497:     const Obj<label_type>& getLabel(const std::string& name) {
1498:       this->checkLabel(name);
1499:       return this->_labels[name];
1500:     };
1501:     void setLabel(const std::string& name, const Obj<label_type>& label) {
1502:       this->_labels[name] = label;
1503:     };
1504:     const labels_type& getLabels() {
1505:       return this->_labels;
1506:     };
1507:     virtual const Obj<label_sequence>& getLabelStratum(const std::string& name, int value) {
1508:       this->checkLabel(name);
1509:       return this->_labels[name]->support(value);
1510:     };
1511:   public: // Stratification
1512:     void computeBinaryStratification() {
1513:       const Obj<label_type>& height = this->createLabel("height");
1514:       const Obj<label_type>& depth  = this->createLabel("depth");
1515:       BinaryStratifyVisitor  l(*height, *depth, true);
1516:       BinaryStratifyVisitor  r(*height, *depth, false);

1518:       this->_sieve->leaves(l);
1519:       this->_sieve->roots(r);
1520:       if (this->_sieve->numRoots()) {
1521:         this->setHeight(1);
1522:         this->setDepth(1);
1523:       } else {
1524:         this->setHeight(0);
1525:         this->setDepth(0);
1526:       }
1527:     };
1528:     void computeHeights() {
1529:       const Obj<label_type>& label = this->createLabel(std::string("height"));
1530:       HeightVisitor          h(*this->_sieve, *label);

1532: #ifdef IMESH_NEW_LABELS
1533:       label->setChart(this->getSieve()->getChart());
1534:       for(point_type p = label->getChart().min(); p < label->getChart().max(); ++p) {label->setConeSize(p, 1);}
1535:       if (label->getChart().size()) {label->setSupportSize(0, label->getChart().size());}
1536:       label->allocate();
1537:       for(point_type p = label->getChart().min(); p < label->getChart().max(); ++p) {label->setCone(-1, p);}
1538: #endif
1539:       this->_sieve->leaves(h);
1540:       while(h.isModified()) {
1541:         // FIX: Avoid the copy here somehow by fixing the traversal
1542:         std::vector<point_type> modifiedPoints(h.getModifiedPoints().begin(), h.getModifiedPoints().end());

1544:         h.clear();
1545:         this->_sieve->cone(modifiedPoints, h);
1546:       }
1547: #ifdef IMESH_NEW_LABELS
1548:       // Recalculate supportOffsets and populate support
1549:       label->recalculateLabel();
1550: #endif
1551:       this->_maxHeight = h.getMaxHeight();
1552:     };
1553:     virtual int height() const {return this->_maxHeight;};
1554:     virtual void setHeight(const int height) {this->_maxHeight = height;};
1555:     virtual int height(const point_type& point) {
1556:       return this->getValue(this->_labels["height"], point, -1);
1557:     };
1558:     virtual void setHeight(const point_type& point, const int height) {
1559:       return this->setValue(this->_labels["height"], point, height);
1560:     };
1561:     virtual const Obj<label_sequence>& heightStratum(int height) {
1562:       return this->getLabelStratum("height", height);
1563:     };
1564:     void computeDepths() {
1565:       const Obj<label_type>& label = this->createLabel(std::string("depth"));
1566:       DepthVisitor           d(*this->_sieve, *label);

1568: #ifdef IMESH_NEW_LABELS
1569:       label->setChart(this->getSieve()->getChart());
1570:       for(point_type p = label->getChart().min(); p < label->getChart().max(); ++p) {label->setConeSize(p, 1);}
1571:       if (label->getChart().size()) {label->setSupportSize(0, label->getChart().size());}
1572:       label->allocate();
1573:       for(point_type p = label->getChart().min(); p < label->getChart().max(); ++p) {label->setCone(-1, p);}
1574: #endif
1575:       this->_sieve->roots(d);
1576:       while(d.isModified()) {
1577:         // FIX: Avoid the copy here somehow by fixing the traversal
1578:         std::vector<point_type> modifiedPoints(d.getModifiedPoints().begin(), d.getModifiedPoints().end());

1580:         d.clear();
1581:         this->_sieve->support(modifiedPoints, d);
1582:       }
1583: #ifdef IMESH_NEW_LABELS
1584:       // Recalculate supportOffsets and populate support
1585:       label->recalculateLabel();
1586: #endif
1587:       this->_maxDepth = d.getMaxDepth();
1588:     };
1589:     virtual int depth() const {return this->_maxDepth;};
1590:     virtual void setDepth(const int depth) {this->_maxDepth = depth;};
1591:     virtual int depth(const point_type& point) {
1592:       return this->getValue(this->_labels["depth"], point, -1);
1593:     };
1594:     virtual void setDepth(const point_type& point, const int depth) {
1595:       return this->setValue(this->_labels["depth"], point, depth);
1596:     };
1597:     virtual const Obj<label_sequence>& depthStratum(int depth) {
1598:       return this->getLabelStratum("depth", depth);
1599:     };
1602:     void stratify() {
1603:       ALE::LogEvent event = ALE::LogEventRegister(__FUNCT__);
1604:       ALE::LogEventBegin(event);
1605:       if (this->_sieve->numRoots() + this->_sieve->numLeaves() == (int) this->_sieve->getChart().size()) {
1606:         this->computeBinaryStratification();
1607:       } else {
1608:         this->computeHeights();
1609:         this->computeDepths();
1610:       }
1611:       ALE::LogEventEnd(event);
1612:     };
1613:   protected:
1614:     template<typename Value>
1615:     static bool lt1(const Value& a, const Value& b) {
1616:       return a.first < b.first;
1617:     }
1618:   public: // Allocation
1619:     template<typename Section_>
1620:     void reallocate(const Obj<Section_>& section) {
1621:       if (!section->hasNewPoints()) return;
1622:       typename Section_::chart_type newChart(std::min(std::min_element(section->getNewPoints().begin(), section->getNewPoints().end(), lt1<typename Section_::newpoint_type>)->first, section->getChart().min()),
1623:                                              std::max(std::max_element(section->getNewPoints().begin(), section->getNewPoints().end(), lt1<typename Section_::newpoint_type>)->first, section->getChart().max()-1)+1);
1624:       section->reallocatePoint(newChart);
1625:     }
1626:   };
1627: #ifdef IMESH_NEW_LABELS
1628:   template<typename Label_ = IFSieve<int> >
1629: #else
1630:   template<typename IndexType, typename ScalarType, typename Label_ = LabelSifter<IndexType, IndexType> >
1631: #endif
1632:   class IMesh : public IBundle<IFSieve<IndexType>, IGeneralSection<IndexType, ScalarType>, IGeneralSection<IndexType, IndexType>,  Label_> {
1633:   public:
1634:     typedef IBundle<IFSieve<IndexType>, IGeneralSection<IndexType, ScalarType>, IGeneralSection<IndexType, IndexType>, Label_> base_type;
1635:     typedef typename base_type::sieve_type            sieve_type;
1636:     typedef typename sieve_type::point_type           point_type;
1637:     typedef typename base_type::alloc_type            alloc_type;
1638:     typedef typename base_type::label_type            label_type;
1639:     typedef typename base_type::labels_type           labels_type;
1640:     typedef typename base_type::label_sequence        label_sequence;
1641:     typedef typename base_type::real_section_type     real_section_type;
1642:     typedef typename base_type::int_section_type      int_section_type;
1643:     typedef typename base_type::numbering_type        numbering_type;
1644:     typedef typename base_type::order_type            order_type;
1645:     typedef typename base_type::send_overlap_type     send_overlap_type;
1646:     typedef typename base_type::recv_overlap_type     recv_overlap_type;
1647:     typedef std::set<std::string>                     names_type;
1648:     typedef std::vector<typename PETSc::Point<3> >    holes_type;
1649:     typedef std::map<std::string, Obj<Discretization> > discretizations_type;
1650:   protected:
1651:     int _dim;
1652:     bool                   _calculatedOverlap;
1653:     Obj<send_overlap_type> _sendOverlap;
1654:     Obj<recv_overlap_type> _recvOverlap;
1655:     std::map<int,double>   _periodicity;
1656:     holes_type             _holes;
1657:     discretizations_type   _discretizations;
1658:     int                    _maxDof;
1659:   public:
1660:     IMesh(MPI_Comm comm, int dim, int debug = 0) : base_type(comm, debug), _dim(dim) {
1661:       this->_calculatedOverlap = false;
1662:       this->_sendOverlap       = new send_overlap_type(comm, debug);
1663:       this->_recvOverlap       = new recv_overlap_type(comm, debug);
1664:       this->_maxDof            = -1;
1665:     };
1666:   public: // Accessors
1667:     int getDimension() const {return this->_dim;};
1668:     void setDimension(const int dim) {this->_dim = dim;};
1669:     bool getCalculatedOverlap() const {return this->_calculatedOverlap;};
1670:     void setCalculatedOverlap(const bool calc) {this->_calculatedOverlap = calc;};
1671:     const Obj<send_overlap_type>& getSendOverlap() const {return this->_sendOverlap;};
1672:     void setSendOverlap(const Obj<send_overlap_type>& overlap) {this->_sendOverlap = overlap;};
1673:     const Obj<recv_overlap_type>& getRecvOverlap() const {return this->_recvOverlap;};
1674:     void setRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_recvOverlap = overlap;};
1675:     bool getPeriodicity(const int d) {return this->_periodicity[d];};
1676:     void setPeriodicity(const int d, const double length) {this->_periodicity[d] = length;};
1677:     const holes_type& getHoles() const {return this->_holes;};
1678:     void addHole(const double hole[]) {
1679:       this->_holes.push_back(hole);
1680:     };
1681:     void copyHoles(const Obj<IMesh>& m) {
1682:       const holes_type& holes = m->getHoles();

1684:       for(holes_type::const_iterator h_iter = holes.begin(); h_iter != holes.end(); ++h_iter) {
1685:         this->_holes.push_back(*h_iter);
1686:       }
1687:     };
1688:     const Obj<Discretization>& getDiscretization() {return this->getDiscretization("default");};
1689:     const Obj<Discretization>& getDiscretization(const std::string& name) {return this->_discretizations[name];};
1690:     void setDiscretization(const Obj<Discretization>& disc) {this->setDiscretization("default", disc);};
1691:     void setDiscretization(const std::string& name, const Obj<Discretization>& disc) {this->_discretizations[name] = disc;};
1692:     Obj<names_type> getDiscretizations() const {
1693:       Obj<names_type> names = names_type();

1695:       for(discretizations_type::const_iterator d_iter = this->_discretizations.begin(); d_iter != this->_discretizations.end(); ++d_iter) {
1696:         names->insert(d_iter->first);
1697:       }
1698:       return names;
1699:     };
1700:     int getMaxDof() const {return this->_maxDof;};
1701:     void setMaxDof(const int maxDof) {this->_maxDof = maxDof;};
1702:     void copy(const Obj<IMesh>& m) {
1703:       this->setSieve(m->getSieve());
1704:       this->_calculatedOverlap = m->_calculatedOverlap;
1705:       this->_sendOverlap       = m->_sendOverlap;
1706:       this->_recvOverlap       = m->_recvOverlap;
1707:       this->_renumbering       = m->_renumbering;
1708:       const labels_type& labels = m->getLabels();

1710:       for(typename labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
1711:         this->setLabel(l_iter->first, l_iter->second);
1712:       }
1713:       this->_maxHeight = m->height();
1714:       this->_maxDepth  = m->depth();
1715:       this->setRealSection("coordinates", m->getRealSection("coordinates"));
1716:       this->setArrowSection("orientation", m->getArrowSection("orientation"));
1717:     };
1718:   public: // Sizes
1719:     template<typename Section>
1720:     int size(const Obj<Section>& section, const point_type& p) {
1721:       typedef ISieveVisitor::SizeVisitor<sieve_type,Section>                        size_visitor_type;
1722:       typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1723:       size_visitor_type    sV(*section);
1724:       closure_visitor_type cV(*this->getSieve(), sV);

1726:       this->getSieve()->cone(p, cV);
1727:       if (!sV.getSize()) sV.visitPoint(p);
1728:       return sV.getSize();
1729:     }
1730:     template<typename Section>
1731:     int sizeWithBC(const Obj<Section>& section, const point_type& p) {
1732:       typedef ISieveVisitor::SizeWithBCVisitor<sieve_type,Section>                  size_visitor_type;
1733:       typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1734:       size_visitor_type    sV(*section);
1735:       closure_visitor_type cV(*this->getSieve(), sV);

1737:       this->getSieve()->cone(p, cV);
1738:       if (!sV.getSize()) sV.visitPoint(p);
1739:       return sV.getSize();
1740:     }
1741:     int sizeWithBC(PetscSection section, const point_type& p) {
1742:       typedef ISieveVisitor::SizeWithBCVisitor<sieve_type,PetscSection>             size_visitor_type;
1743:       typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1744:       size_visitor_type    sV(section);
1745:       closure_visitor_type cV(*this->getSieve(), sV);

1747:       this->getSieve()->cone(p, cV);
1748:       if (!sV.getSize()) sV.visitPoint(p);
1749:       return sV.getSize();
1750:     }
1751:     void sizeWithBC(PetscSection section, const point_type& p, PetscInt fieldSize[]) {
1752:       typedef ISieveVisitor::SizeWithBCVisitor<sieve_type,PetscSection>             size_visitor_type;
1753:       typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1754:       size_visitor_type    sV(section, fieldSize);
1755:       closure_visitor_type cV(*this->getSieve(), sV);

1757:       this->getSieve()->cone(p, cV);
1758:       if (!sV.getSize()) sV.visitPoint(p);
1759:     }
1760:     template<typename Section>
1761:     void allocate(const Obj<Section>& section) {
1762:       section->allocatePoint();
1763:     }
1764:   public: // Restrict/Update closures
1765:     template<typename Sieve, typename Visitor>
1766:     void closure1(const Sieve& sieve, const point_type& p, Visitor& v)
1767:     {
1768:       v.visitPoint(p, 0);
1769:       // Cone is guarateed to be ordered correctly
1770:       sieve.orientedCone(p, v);
1771:     }
1772:     // Return the values for the closure of this point
1773:     template<typename Section>
1774:     const typename Section::value_type *restrictClosure(const Obj<Section>& section, const point_type& p) {
1775:       const int size = this->sizeWithBC(section, p);
1776:       ISieveVisitor::RestrictVisitor<Section> rV(*section, size, section->getRawArray(size));

1778:       if (this->depth() == 1) {
1779:         closure1(*this->getSieve(), p, rV);
1780:       } else {
1781:         ISieveVisitor::PointRetriever<sieve_type,ISieveVisitor::RestrictVisitor<Section> > pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, rV, true);

1783:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1784:       }
1785:       return rV.getValues();
1786:     }
1787:     template<typename Section>
1788:     const typename Section::value_type *restrictClosure(const Obj<Section>& section, const point_type& p, typename Section::value_type *values, const int valuesSize) {
1789:       const int size = this->sizeWithBC(section, p);
1790:       if (valuesSize < size) {throw ALE::Exception("Input array to small for restrictClosure()");}
1791:       ISieveVisitor::RestrictVisitor<Section> rV(*section, size, values);

1793:       if (this->depth() == 1) {
1794:         closure1(*this->getSieve(), p, rV);
1795:       } else {
1796:         ISieveVisitor::PointRetriever<sieve_type,ISieveVisitor::RestrictVisitor<Section> > pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, rV, true);

1798:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1799:       }
1800:       return rV.getValues();
1801:     }
1802:     template<typename Visitor>
1803:     void restrictClosure(const point_type& p, Visitor& v) {
1804:       if (this->depth() == 1) {
1805:         closure1(*this->getSieve(), p, v);
1806:       } else {
1807:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, v);
1808:       }
1809:     }
1810:     // Replace the values for the closure of this point
1811:     template<typename Section>
1812:     void update(const Obj<Section>& section, const point_type& p, const typename Section::value_type *v) {
1813:       ISieveVisitor::UpdateVisitor<Section> uV(*section, v);

1815:       if (this->depth() == 1) {
1816:         closure1(*this->getSieve(), p, uV);
1817:       } else {
1818:         ISieveVisitor::PointRetriever<sieve_type,ISieveVisitor::UpdateVisitor<Section> > pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, uV, true);

1820:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1821:       }
1822:     }
1823:     // Replace the values for the closure of this point, including points constrained by BC
1824:     template<typename Section>
1825:     void updateAll(const Obj<Section>& section, const point_type& p, const typename Section::value_type *v) {
1826:       ISieveVisitor::UpdateAllVisitor<Section> uV(*section, v);

1828:       if (this->depth() == 1) {
1829:         closure1(*this->getSieve(), p, uV);
1830:       } else {
1831:         ISieveVisitor::PointRetriever<sieve_type,ISieveVisitor::UpdateAllVisitor<Section> > pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, uV, true);

1833:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1834:       }
1835:     }
1836:     // Augment the values for the closure of this point
1837:     template<typename Section>
1838:     void updateAdd(const Obj<Section>& section, const point_type& p, const typename Section::value_type *v) {
1839:       ISieveVisitor::UpdateAddVisitor<Section> uV(*section, v);

1841:       if (this->depth() == 1) {
1842:         closure1(*this->getSieve(), p, uV);
1843:       } else {
1844:         ISieveVisitor::PointRetriever<sieve_type,ISieveVisitor::UpdateAddVisitor<Section> > pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, uV, true);

1846:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1847:       }
1848:     }
1849:     // Augment the values for the closure of this point
1850:     template<typename Visitor>
1851:     void updateClosure(const point_type& p, Visitor& v) {
1852:       if (this->depth() == 1) {
1853:         closure1(*this->getSieve(), p, v);
1854:       } else {
1855:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, v);
1856:       }
1857:     }
1858:   public: // Overlap
1859:     void constructOverlap() {
1860:       if (!this->_calculatedOverlap && (this->commSize() > 1)) {throw ALE::Exception("Must calculate overlap during distribution");}
1861:     };
1862:   public: // Cell topology and geometry
1863:     int getNumCellCorners(const point_type& p, const int depth = -1) const {
1864:       const int d = depth < 0 ? this->depth() : depth;

1866:       if (d == 1) {
1867:         return this->_sieve->getConeSize(p);
1868:       } else if (d <= 0) {
1869:         return 0;
1870:       }
1871:       // Warning: this is slow
1872:       ISieveVisitor::NConeRetriever<sieve_type> ncV(*this->_sieve, (int) pow((double) this->_sieve->getMaxConeSize(), this->depth()));
1873:       ALE::ISieveTraversal<sieve_type>::orientedClosure(*this->_sieve, p, ncV);
1874:       return ncV.getOrientedSize();
1875:     };
1876:     int getNumCellCorners() {
1877:       return getNumCellCorners(*this->heightStratum(0)->begin());
1878:     };
1879:     void setupCoordinates(const Obj<real_section_type>& coordinates) {
1880:       const Obj<label_sequence>& vertices = this->depthStratum(0);

1882:       if (vertices->size() > 0) {
1883:         coordinates->setChart(typename real_section_type::chart_type(*std::min_element(vertices->begin(), vertices->end()),
1884:                                                                      *std::max_element(vertices->begin(), vertices->end())+1));
1885:       } else {
1886:         coordinates->setChart(typename real_section_type::chart_type(0, 0));
1887:       }
1888:     };
1889:     // Find the cell in which this point lies (stupid algorithm)
1890:     point_type locatePoint_Simplex_2D(const typename real_section_type::value_type point[], const point_type cell) {
1891:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1892:       const int                     embedDim    = 2;
1893:       typename real_section_type::value_type v0[2], J[4], invJ[4], detJ;

1895:       //std::cout << "Checking cell " << cell << std::endl;
1896:       this->computeElementGeometry(coordinates, cell, v0, J, invJ, detJ);
1897:       double xi   = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]);
1898:       double eta  = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]);

1900:       if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) {
1901:         return cell;
1902:       }
1903: #if 0
1904:       {
1905:         ostringstream msg;
1906:         msg << "Could not locate point: (" << point[0] <<","<< point[1] << ")" << std::endl;
1907:         throw ALE::Exception(msg.str().c_str());
1908:       }
1909: #endif
1910:       return -1;
1911:     };
1912:     point_type locatePoint_General_2D(const typename real_section_type::value_type p[], const point_type cell) {
1913:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1914:       const PetscInt                faces[8]    = {0, 1, 1, 2, 2, 3, 3, 0};

1916:       const PetscReal *coords    = this->restrictClosure(coordinates, cell);
1917:       PetscInt         crossings = 0;

1919:       //std::cout << "Checking cell " << cell << std::endl;
1920:       for(PetscInt f = 0; f < 4; f++) {
1921:         PetscReal x_i   = coords[faces[2*f+0]*2+0];
1922:         PetscReal y_i   = coords[faces[2*f+0]*2+1];
1923:         PetscReal x_j   = coords[faces[2*f+1]*2+0];
1924:         PetscReal y_j   = coords[faces[2*f+1]*2+1];
1925:         PetscReal slope = (y_j - y_i) / (x_j - x_i);
1926:         bool      cond1 = (x_i <= p[0]) && (p[0] < x_j);
1927:         bool      cond2 = (x_j <= p[0]) && (p[0] < x_i);
1928:         bool      above = (p[1] < slope * (p[0] - x_i) + y_i);
1929:         if ((cond1 || cond2)  && above) ++crossings;
1930:       }
1931:       if (crossings % 2) {return cell;}
1932: #if 0
1933:       {
1934:         ostringstream msg;
1935:         msg << "Could not locate point: (" << p[0] <<","<< p[1] << ")" << std::endl;
1936:         throw ALE::Exception(msg.str().c_str());
1937:       }
1938: #endif
1939:       return -1;
1940:     };
1941:     //   Assume a simplex and 3D
1942:     point_type locatePoint_Simplex_3D(const typename real_section_type::value_type point[], const point_type cell) {
1943:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1944:       const int                     embedDim    = 3;
1945:       typename real_section_type::value_type v0[3], J[9], invJ[9], detJ;

1947:       this->computeElementGeometry(coordinates, cell, v0, J, invJ, detJ);
1948:       double xi   = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]) + invJ[0*embedDim+2]*(point[2] - v0[2]);
1949:       double eta  = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]) + invJ[1*embedDim+2]*(point[2] - v0[2]);
1950:       double zeta = invJ[2*embedDim+0]*(point[0] - v0[0]) + invJ[2*embedDim+1]*(point[1] - v0[1]) + invJ[2*embedDim+2]*(point[2] - v0[2]);

1952:       if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) {
1953:         return cell;
1954:         }
1955: #if 0
1956:       {
1957:         ostringstream msg;
1958:         msg << "Could not locate point: (" << point[0] <<","<< point[1] <<","<< point[2] << ")" << std::endl;
1959:         throw ALE::Exception(msg.str().c_str());
1960:       }
1961: #else
1962:       return -1;
1963: #endif
1964:     };
1965:     point_type locatePoint_General_3D(const typename real_section_type::value_type p[], const point_type cell) {
1966:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1967:       const PetscInt                faces[24]   = {0, 1, 2, 3,  5, 4, 7, 6,  1, 0, 4, 5,
1968:                                                    3, 2, 6, 7,  1, 5, 6, 2,  0, 3, 7, 4};

1970:       const PetscReal *coords = this->restrictClosure(coordinates, cell);
1971:       PetscBool        found  = PETSC_TRUE;

1973:       //std::cout << "Checking cell " << cell << std::endl;
1974:       for(PetscInt f = 0; f < 6; f++) {
1975:         /* Check the point is under plane */
1976:         /*   Get face normal */
1977:         PetscReal v_i[3]    = {coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0],coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1],coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]};
1978:         PetscReal v_j[3]    = {coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0],coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1],coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]};
1979:         PetscReal normal[3] = {v_i[1]*v_j[2] - v_i[2]*v_j[1], v_i[2]*v_j[0] - v_i[0]*v_j[2], v_i[0]*v_j[1] - v_i[1]*v_j[0]};
1980:         PetscReal pp[3]     = {coords[faces[f*4+0]*3+0] - p[0],coords[faces[f*4+0]*3+1] - p[1],coords[faces[f*4+0]*3+2] - p[2]};
1981:         PetscReal dot       = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2];
1982:         /* Check that projected point is in face (2D location problem) */
1983:         if (dot < 0.0) {
1984:           found = PETSC_FALSE;
1985:           break;
1986:         }
1987:       }
1988:       if (found) {return cell;}
1989: #if 0
1990:       {
1991:         ostringstream msg;
1992:         msg << "Could not locate point: (" << p[0] <<","<< p[1] <<","<< p[2] << ")" << std::endl;
1993:         throw ALE::Exception(msg.str().c_str());
1994:       }
1995: #else
1996:       return -1;
1997: #endif
1998:     };
1999:     point_type locatePoint(const typename real_section_type::value_type point[], point_type guess = -1) {
2000:       //guess overrides this by saying that we already know the relation of this point to this mesh.  We will need to make it a more robust "guess" later for more than P1

2002:       int cellDepthLocal = (this->depth() == -1) ? -1 : 1;
2003:       int cellDepth = 0;
2004:       PetscErrorCode err = MPI_Allreduce(&cellDepthLocal, &cellDepth, 1, MPI_INT, MPI_MAX, this->comm());CHKERRXX(err);
2005:       const std::string labelName = (this->hasLabel("censored depth")) ? "censored depth" : "depth";
2006:       const ALE::Obj<label_sequence>& cells = this->getLabelStratum(labelName, cellDepth);

2008:       point_type cell = -1;
2009:       if (guess != -1) {
2010:         return guess;
2011:       } else if (this->_dim == 2) {
2012:         for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
2013:           switch(this->getSieve()->getConeSize(*c_iter)) {
2014:           case 3:
2015:             cell = locatePoint_Simplex_2D(point, *c_iter);
2016:             break;
2017:           case 4:
2018:             cell = locatePoint_General_2D(point, *c_iter);
2019:             break;
2020:           default:
2021:             // MATT: Add warning?
2022:             cell = -1;
2023:           } // switch
2024:           if (cell >= 0)
2025:             break;
2026:         } // for
2027:       } else if (this->_dim == 3) {
2028:         for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
2029:           switch(this->getSieve()->getConeSize(*c_iter)) {
2030:           case 4:
2031:             cell = locatePoint_Simplex_3D(point, *c_iter);
2032:             break;
2033:           case 8:
2034:             cell = locatePoint_General_3D(point, *c_iter);
2035:             break;
2036:           default:
2037:             // MATT: Add warning?
2038:             cell = -1;
2039:           } // switch
2040:           if (cell >= 0)
2041:             break;
2042:         } // for
2043:       } else {
2044:         throw ALE::Exception("No point location for mesh dimension");
2045:       }
2046:       return cell;
2047:     };
2048:     void computeTriangleGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2049:       const PetscReal *coords = this->restrictClosure(coordinates, e);
2050:       const int        dim    = 2;
2051:       typename real_section_type::value_type           invDet;

2053:       if (v0) {
2054:         for(int d = 0; d < dim; d++) {
2055:           v0[d] = coords[d];
2056:         }
2057:       }
2058:       if (J) {
2059:         for(int d = 0; d < dim; d++) {
2060:           for(int f = 0; f < dim; f++) {
2061:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2062:           }
2063:         }
2064:         detJ = J[0]*J[3] - J[1]*J[2];
2065:         if (detJ < 0.0) {
2066:           const typename real_section_type::value_type  xLength = this->_periodicity[0];

2068:           if (xLength != 0.0) {
2069:             typename real_section_type::value_type v0x = coords[0*dim+0];

2071:             if (v0x == 0.0) {
2072:               v0x = v0[0] = xLength;
2073:             }
2074:             for(int f = 0; f < dim; f++) {
2075:               const typename real_section_type::value_type px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];

2077:               J[0*dim+f] = 0.5*(px - v0x);
2078:             }
2079:           }
2080:           detJ = J[0]*J[3] - J[1]*J[2];
2081:         }
2082:         PetscLogFlops(8.0 + 3.0);
2083:       }
2084:       if (invJ) {
2085:         invDet  = 1.0/detJ;
2086:         invJ[0] =  invDet*J[3];
2087:         invJ[1] = -invDet*J[1];
2088:         invJ[2] = -invDet*J[2];
2089:         invJ[3] =  invDet*J[0];
2090:         PetscLogFlops(5.0);
2091:       }
2092:     };
2093:     void computeRectangleGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2094:       const PetscReal *coords = this->restrictClosure(coordinates, e);
2095:       const int        dim    = 2;
2096:       typename real_section_type::value_type invDet;

2098:       if (v0) {
2099:         for(int d = 0; d < dim; d++) {
2100:           v0[d] = coords[d];
2101:         }
2102:       }
2103:       if (J) {
2104:         for(int d = 0; d < dim; d++) {
2105:           for(int f = 0; f < dim; f++) {
2106:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2107:           }
2108:         }
2109:         detJ = J[0]*J[3] - J[1]*J[2];
2110:         PetscLogFlops(8.0 + 3.0);
2111:       }
2112:       if (invJ) {
2113:         invDet  = 1.0/detJ;
2114:         invJ[0] =  invDet*J[3];
2115:         invJ[1] = -invDet*J[1];
2116:         invJ[2] = -invDet*J[2];
2117:         invJ[3] =  invDet*J[0];
2118:         PetscLogFlops(5.0);
2119:       }
2120:       detJ *= 2.0;
2121:     };
2122:     void computeTetrahedronGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2123:       const PetscReal *coords = this->restrictClosure(coordinates, e);
2124:       const int        dim    = 3;
2125:       typename real_section_type::value_type           invDet;

2127:       if (v0) {
2128:         for(int d = 0; d < dim; d++) {
2129:           v0[d] = coords[d];
2130:         }
2131:       }
2132:       if (J) {
2133:         for(int d = 0; d < dim; d++) {
2134:           for(int f = 0; f < dim; f++) {
2135:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2136:           }
2137:         }
2138:         // The minus sign is here since I orient the first face to get the outward normal
2139:         detJ = -(J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2140:                  J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2141:                  J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
2142:         PetscLogFlops(18.0 + 12.0);
2143:       }
2144:       if (invJ) {
2145:         invDet  = -1.0/detJ;
2146:         invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2147:         invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
2148:         invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2149:         invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2150:         invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
2151:         invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2152:         invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2153:         invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
2154:         invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2155:         PetscLogFlops(37.0);
2156:       }
2157:     };
2158:     void computeHexahedronGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2159:       const PetscReal *coords = this->restrictClosure(coordinates, e);
2160:       const int        dim    = 3;
2161:       typename real_section_type::value_type invDet;

2163:       if (v0) {
2164:         for(int d = 0; d < dim; d++) {
2165:           v0[d] = coords[d];
2166:         }
2167:       }
2168:       if (J) {
2169:         for(int d = 0; d < dim; d++) {
2170:           J[d*dim+0] = 0.5*(coords[(0+1)*dim+d] - coords[0*dim+d]);
2171:           J[d*dim+1] = 0.5*(coords[(1+1)*dim+d] - coords[0*dim+d]);
2172:           J[d*dim+2] = 0.5*(coords[(3+1)*dim+d] - coords[0*dim+d]);
2173:         }
2174:         detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2175:                 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2176:                 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
2177:         PetscLogFlops(18.0 + 12.0);
2178:       }
2179:       if (invJ) {
2180:         invDet  = -1.0/detJ;
2181:         invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2182:         invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
2183:         invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2184:         invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2185:         invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
2186:         invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2187:         invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2188:         invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
2189:         invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2190:         PetscLogFlops(37.0);
2191:       }
2192:       detJ *= 8.0;
2193:     };
2194:     void computeElementGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2195:       const int coneSize = this->getSieve()->getConeSize(e);

2197:       if (this->_dim == 2) {
2198:         if (coneSize == 3) {
2199:           computeTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
2200:         } else if (coneSize == 4) {
2201:           computeRectangleGeometry(coordinates, e, v0, J, invJ, detJ);
2202:         } else {
2203:           throw ALE::Exception("Unsupported coneSize for element geometry computation");
2204:         }
2205:       } else if (this->_dim == 3) {
2206:         if (coneSize == 4) {
2207:           computeTetrahedronGeometry(coordinates, e, v0, J, invJ, detJ);
2208:         } else if (coneSize == 8) {
2209:           computeHexahedronGeometry(coordinates, e, v0, J, invJ, detJ);
2210:         } else {
2211:           throw ALE::Exception("Unsupported coneSize for element geometry computation");
2212:         }
2213:       } else {
2214:         throw ALE::Exception("Unsupported dimension for element geometry computation");
2215:       }
2216:     };
2217:     void computeBdSegmentGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2218:       const typename real_section_type::value_type *coords = this->restrictClosure(coordinates, e);
2219:       const int     dim    = 2;
2220:       typename real_section_type::value_type        invDet;

2222:       if (v0) {
2223:         for(int d = 0; d < dim; d++) {
2224:           v0[d] = coords[d];
2225:         }
2226:       }
2227:       if (J) {
2228:         //r2   = coords[1*dim+0]*coords[1*dim+0] + coords[1*dim+1]*coords[1*dim+1];
2229:         J[0] =  (coords[1*dim+0] - coords[0*dim+0])*0.5; J[1] = (-coords[1*dim+1] + coords[0*dim+1])*0.5;
2230:         J[2] =  (coords[1*dim+1] - coords[0*dim+1])*0.5; J[3] = ( coords[1*dim+0] - coords[0*dim+0])*0.5;
2231:         detJ = J[0]*J[3] - J[1]*J[2];
2232:         if (detJ < 0.0) {
2233:           const typename real_section_type::value_type  xLength = this->_periodicity[0];

2235:           if (xLength != 0.0) {
2236:             typename real_section_type::value_type v0x = coords[0*dim+0];

2238:             if (v0x == 0.0) {
2239:               v0x = v0[0] = xLength;
2240:             }
2241:             for(int f = 0; f < dim; f++) {
2242:               const typename real_section_type::value_type px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];

2244:               J[0*dim+f] = 0.5*(px - v0x);
2245:             }
2246:           }
2247:           detJ = J[0]*J[3] - J[1]*J[2];
2248:         }
2249:         PetscLogFlops(8.0 + 3.0);
2250:       }
2251:       if (invJ) {
2252:         invDet  = 1.0/detJ;
2253:         invJ[0] =  invDet*J[3];
2254:         invJ[1] = -invDet*J[1];
2255:         invJ[2] = -invDet*J[2];
2256:         invJ[3] =  invDet*J[0];
2257:         PetscLogFlops(5.0);
2258:       }
2259:     };
2260:     void computeBdElementGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2261:       if (this->_dim == 1) {
2262:         computeBdSegmentGeometry(coordinates, e, v0, J, invJ, detJ);
2263:         //      } else if (this->_dim == 2) {
2264:         //        computeBdTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
2265:       } else {
2266:         throw ALE::Exception("Unsupported dimension for element geometry computation");
2267:       }
2268:     };
2269:     typename real_section_type::value_type getMaxVolume() {
2270:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
2271:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
2272:       const int                     dim         = this->getDimension();
2273:       typename real_section_type::value_type v0[3], J[9], invJ[9], detJ, refVolume = 0.0, maxVolume = 0.0;

2275:       if (dim == 1) refVolume = 2.0;
2276:       if (dim == 2) refVolume = 2.0;
2277:       if (dim == 3) refVolume = 4.0/3.0;
2278:       for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
2279:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
2280:         maxVolume = std::max(maxVolume, detJ*refVolume);
2281:       }
2282:       return maxVolume;
2283:     };
2284:   public:
2285:     void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
2286:       if (comm == MPI_COMM_NULL) {
2287:         comm = this->comm();
2288:       }
2289:       if (name == "") {
2290:         PetscPrintf(comm, "viewing a Mesh\n");
2291:       } else {
2292:         PetscPrintf(comm, "viewing Mesh '%s'\n", name.c_str());
2293:       }
2294:       this->getSieve()->view("mesh sieve", comm);
2295:       Obj<names_type> sections = this->getRealSections();

2297:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2298:         this->getRealSection(*name)->view(*name);
2299:       }
2300:       sections = this->getIntSections();
2301:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2302:         this->getIntSection(*name)->view(*name);
2303:       }
2304:       sections = this->getArrowSections();
2305:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2306:         this->getArrowSection(*name)->view(*name);
2307:       }
2308:     };
2309:   public: // Discretization
2310:     void markBoundaryCells(const std::string& name, const int marker = 1, const int newMarker = 2, const bool onlyVertices = false) {
2311:       const Obj<label_type>&                  label    = this->getLabel(name);
2312:       const Obj<label_sequence>&              boundary = this->getLabelStratum(name, marker);
2313:       const typename label_sequence::iterator end      = boundary->end();
2314:       const Obj<sieve_type>&                  sieve    = this->getSieve();

2316:       if (!onlyVertices) {
2317:         typename ISieveVisitor::MarkVisitor<sieve_type,label_type> mV(*label, newMarker);

2319:         for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != end; ++e_iter) {
2320:           if (this->height(*e_iter) == 1) {
2321:             sieve->support(*e_iter, mV);
2322:           }
2323:         }
2324:       } else {
2325: #if 1
2326:         throw ALE::Exception("Rewrite this to first mark boundary edges/faces.");
2327: #else
2328:         const int depth = this->depth();

2330:         for(typename label_sequence::iterator v_iter = boundary->begin(); v_iter != end; ++v_iter) {
2331:           const Obj<supportArray>               support = sieve->nSupport(*v_iter, depth);
2332:           const typename supportArray::iterator sEnd    = support->end();

2334:           for(typename supportArray::iterator c_iter = support->begin(); c_iter != sEnd; ++c_iter) {
2335:             const Obj<typename sieve_type::traits::coneSequence>&     cone = sieve->cone(*c_iter);
2336:             const typename sieve_type::traits::coneSequence::iterator cEnd = cone->end();

2338:             for(typename sieve_type::traits::coneSequence::iterator e_iter = cone->begin(); e_iter != cEnd; ++e_iter) {
2339:               if (sieve->support(*e_iter)->size() == 1) {
2340:                 this->setValue(label, *c_iter, newMarker);
2341:                 break;
2342:               }
2343:             }
2344:           }
2345:         }
2346: #endif
2347:       }
2348:     };
2349:     int setFiberDimensions(const Obj<real_section_type>& s, const Obj<names_type>& discs, names_type& bcLabels) {
2350:       const int debug  = this->debug();
2351:       int       maxDof = 0;

2353:       for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter) {
2354:         s->addSpace();
2355:       }
2356:       for(int d = 0; d <= this->_dim; ++d) {
2357:         int numDof = 0;
2358:         int f      = 0;

2360:         for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2361:           const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
2362:           const int                       sDof = disc->getNumDof(d);

2364:           numDof += sDof;
2365:           if (sDof) s->setFiberDimension(this->depthStratum(d), sDof, f);
2366:         }
2367:         if (numDof) s->setFiberDimension(this->depthStratum(d), numDof);
2368:         maxDof = std::max(maxDof, numDof);
2369:       }
2370:       // Process exclusions
2371:       typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2372:       int f = 0;

2374:       for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2375:         const Obj<ALE::Discretization>& disc      = this->getDiscretization(*f_iter);
2376:         std::string                     labelName = "exclude-"+*f_iter;
2377:         std::set<point_type>            seen;
2378:         Visitor pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth()), true);

2380:         if (this->hasLabel(labelName)) {
2381:           const Obj<label_type>&                  label     = this->getLabel(labelName);
2382:           const Obj<label_sequence>&              exclusion = this->getLabelStratum(labelName, 1);
2383:           const typename label_sequence::iterator end       = exclusion->end();
2384:           if (debug > 1) {label->view(labelName.c_str());}

2386:           for(typename label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
2387:             ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), *e_iter, pV);
2388:             const typename Visitor::point_type *oPoints = pV.getPoints();
2389:             const int                           oSize   = pV.getSize();

2391:             for(int cl = 0; cl < oSize; ++cl) {
2392:               if (seen.find(oPoints[cl]) != seen.end()) continue;
2393:               if (this->getValue(label, oPoints[cl]) == 1) {
2394:                 seen.insert(oPoints[cl]);
2395:                 s->setFiberDimension(oPoints[cl], 0, f);
2396:                 s->addFiberDimension(oPoints[cl], -disc->getNumDof(this->depth(oPoints[cl])));
2397:                 if (debug > 1) {std::cout << "  point: " << oPoints[cl] << " dim: " << disc->getNumDof(this->depth(oPoints[cl])) << std::endl;}
2398:               }
2399:             }
2400:             pV.clear();
2401:           }
2402:         }
2403:       }
2404:       // Process constraints
2405:       f = 0;
2406:       for(std::set<std::string>::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2407:         const Obj<ALE::Discretization>&   disc        = this->getDiscretization(*f_iter);
2408:         const Obj<std::set<std::string> > bcs         = disc->getBoundaryConditions();
2409:         std::string                       excludeName = "exclude-"+*f_iter;

2411:         for(std::set<std::string>::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter) {
2412:           const Obj<ALE::BoundaryCondition>& bc       = disc->getBoundaryCondition(*bc_iter);
2413:           const Obj<label_sequence>&         boundary = this->getLabelStratum(bc->getLabelName(), bc->getMarker());

2415:           bcLabels.insert(bc->getLabelName());
2416:           if (this->hasLabel(excludeName)) {
2417:             const Obj<label_type>& label = this->getLabel(excludeName);

2419:             for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
2420:               if (!this->getValue(label, *e_iter)) {
2421:                 const int numDof = disc->getNumDof(this->depth(*e_iter));

2423:                 if (numDof) s->addConstraintDimension(*e_iter, numDof);
2424:                 if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
2425:               }
2426:             }
2427:           } else {
2428:             for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
2429:               const int numDof = disc->getNumDof(this->depth(*e_iter));

2431:               if (numDof) s->addConstraintDimension(*e_iter, numDof);
2432:               if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
2433:             }
2434:           }
2435:         }
2436:       }
2437:       return maxDof;
2438:     };
2439:     void calculateIndices() {
2440:       typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2441:       // Should have an iterator over the whole tree
2442:       Obj<names_type> discs = this->getDiscretizations();
2443:       const int       debug = this->debug();
2444:       std::map<std::string, std::pair<int, int*> > indices;

2446:       for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
2447:         const Obj<Discretization>& disc = this->getDiscretization(*d_iter);

2449:         indices[*d_iter] = std::pair<int, int*>(0, new int[disc->sizeV(*this)]);
2450:         disc->setIndices(indices[*d_iter].second);
2451:       }
2452:       const Obj<label_sequence>& cells   = this->heightStratum(0);
2453:       Visitor pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, true);
2454:       ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), *cells->begin(), pV);
2455:       const typename Visitor::point_type *oPoints = pV.getPoints();
2456:       const int                           oSize   = pV.getSize();
2457:       int                                 offset  = 0;

2459:       if (debug > 1) {std::cout << "Closure for first element" << std::endl;}
2460:       for(int cl = 0; cl < oSize; ++cl) {
2461:         const int dim = this->depth(oPoints[cl]);

2463:         if (debug > 1) {std::cout << "  point " << oPoints[cl] << " depth " << dim << std::endl;}
2464:         for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
2465:           const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
2466:           const int                  num  = disc->getNumDof(dim);

2468:           if (debug > 1) {std::cout << "    disc " << disc->getName() << " numDof " << num << std::endl;}
2469:           for(int o = 0; o < num; ++o) {
2470:             indices[*d_iter].second[indices[*d_iter].first++] = offset++;
2471:           }
2472:         }
2473:       }
2474:       pV.clear();
2475:       if (debug > 1) {
2476:         for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
2477:           const Obj<Discretization>& disc = this->getDiscretization(*d_iter);

2479:           std::cout << "Discretization " << disc->getName() << " indices:";
2480:           for(int i = 0; i < indices[*d_iter].first; ++i) {
2481:             std::cout << " " << indices[*d_iter].second[i];
2482:           }
2483:           std::cout << std::endl;
2484:         }
2485:       }
2486:     };
2487:     void calculateIndicesExcluded(const Obj<real_section_type>& s, const Obj<names_type>& discs) {
2488:       typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2489:       typedef std::map<std::string, std::pair<int, indexSet> > indices_type;
2490:       const Obj<label_type>& indexLabel = this->createLabel("cellExclusion");
2491:       const int debug  = this->debug();
2492:       int       marker = 0;
2493:       std::map<indices_type, int> indexMap;
2494:       indices_type                indices;
2495:       Visitor pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, true);

2497:       for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
2498:         const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
2499:         const int                  size = disc->sizeV(*this);

2501:         indices[*d_iter].second.resize(size);
2502:       }
2503:       const typename names_type::const_iterator dBegin = discs->begin();
2504:       const typename names_type::const_iterator dEnd   = discs->end();
2505:       std::set<point_type> seen;
2506:       int f = 0;

2508:       for(typename names_type::const_iterator f_iter = dBegin; f_iter != dEnd; ++f_iter, ++f) {
2509:         std::string labelName = "exclude-"+*f_iter;

2511:         if (this->hasLabel(labelName)) {
2512:           const Obj<label_sequence>&              exclusion = this->getLabelStratum(labelName, 1);
2513:           const typename label_sequence::iterator end       = exclusion->end();

2515:           if (debug > 1) {std::cout << "Processing exclusion " << labelName << std::endl;}
2516:           for(typename label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
2517:             if (this->height(*e_iter)) continue;
2518:             ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), *e_iter, pV);
2519:             const typename Visitor::point_type *oPoints = pV.getPoints();
2520:             const int                           oSize   = pV.getSize();
2521:             int                                 offset  = 0;

2523:             if (debug > 1) {std::cout << "  Closure for cell " << *e_iter << std::endl;}
2524:             for(int cl = 0; cl < oSize; ++cl) {
2525:               int g = 0;

2527:               if (debug > 1) {std::cout << "    point " << oPoints[cl] << std::endl;}
2528:               for(typename names_type::const_iterator g_iter = dBegin; g_iter != dEnd; ++g_iter, ++g) {
2529:                 const int fDim = s->getFiberDimension(oPoints[cl], g);

2531:                 if (debug > 1) {std::cout << "      disc " << *g_iter << " numDof " << fDim << std::endl;}
2532:                 for(int d = 0; d < fDim; ++d) {
2533:                   indices[*g_iter].second[indices[*g_iter].first++] = offset++;
2534:                 }
2535:               }
2536:             }
2537:             pV.clear();
2538:             const std::map<indices_type, int>::iterator entry = indexMap.find(indices);

2540:             if (debug > 1) {
2541:               for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
2542:                 for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2543:                   std::cout << "Discretization (" << i_iter->second << ") " << *g_iter << " indices:";
2544:                   for(int i = 0; i < ((indices_type) i_iter->first)[*g_iter].first; ++i) {
2545:                     std::cout << " " << ((indices_type) i_iter->first)[*g_iter].second[i];
2546:                   }
2547:                   std::cout << std::endl;
2548:                 }
2549:                 std::cout << "Comparison: " << (indices == i_iter->first) << std::endl;
2550:               }
2551:               for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2552:                 std::cout << "Discretization " << *g_iter << " indices:";
2553:                 for(int i = 0; i < indices[*g_iter].first; ++i) {
2554:                   std::cout << " " << indices[*g_iter].second[i];
2555:                 }
2556:                 std::cout << std::endl;
2557:               }
2558:             }
2559:             if (entry != indexMap.end()) {
2560:               this->setValue(indexLabel, *e_iter, entry->second);
2561:               if (debug > 1) {std::cout << "  Found existing indices with marker " << entry->second << std::endl;}
2562:             } else {
2563:               indexMap[indices] = ++marker;
2564:               this->setValue(indexLabel, *e_iter, marker);
2565:               if (debug > 1) {std::cout << "  Created new indices with marker " << marker << std::endl;}
2566:             }
2567:             for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2568:               indices[*g_iter].first  = 0;
2569:               for(unsigned int i = 0; i < indices[*g_iter].second.size(); ++i) indices[*g_iter].second[i] = 0;
2570:             }
2571:           }
2572:         }
2573:       }
2574:       if (debug > 1) {indexLabel->view("cellExclusion");}
2575:       for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
2576:         if (debug > 1) {std::cout << "Setting indices for marker " << i_iter->second << std::endl;}
2577:         for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2578:           const Obj<Discretization>& disc = this->getDiscretization(*g_iter);
2579:           const indexSet  indSet   = ((indices_type) i_iter->first)[*g_iter].second;
2580:           const int       size     = indSet.size();
2581:           int            *_indices = new int[size];

2583:           if (debug > 1) {std::cout << "  field " << *g_iter << std::endl;}
2584:           for(int i = 0; i < size; ++i) {
2585:             _indices[i] = indSet[i];
2586:             if (debug > 1) {std::cout << "    indices["<<i<<"] = " << _indices[i] << std::endl;}
2587:           }
2588:           disc->setIndices(_indices, i_iter->second);
2589:         }
2590:       }
2591:     };
2592:     void setupField(const Obj<real_section_type>& s, const int cellMarker = 2, const bool noUpdate = false) {
2593:       typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2594:       const Obj<names_type>& discs  = this->getDiscretizations();
2595:       const int              debug  = s->debug();
2596:       names_type             bcLabels;

2598:       s->setChart(this->getSieve()->getChart());
2599:       this->_maxDof = this->setFiberDimensions(s, discs, bcLabels);
2600:       this->calculateIndices();
2601:       this->calculateIndicesExcluded(s, discs);
2602:       this->allocate(s);
2603:       s->defaultConstraintDof();
2604:       const Obj<label_type>& cellExclusion = this->getLabel("cellExclusion");

2606:       if (debug > 1) {std::cout << "Setting boundary values" << std::endl;}
2607:       for(typename names_type::const_iterator n_iter = bcLabels.begin(); n_iter != bcLabels.end(); ++n_iter) {
2608:         const Obj<label_sequence>&              boundaryCells = this->getLabelStratum(*n_iter, cellMarker);
2609:         const Obj<real_section_type>&           coordinates   = this->getRealSection("coordinates");
2610:         const Obj<names_type>&                  discs         = this->getDiscretizations();
2611:         const point_type                        firstCell     = *boundaryCells->begin();
2612:         const int                               numFields     = discs->size();
2613:         typename real_section_type::value_type *values        = new typename real_section_type::value_type[this->sizeWithBC(s, firstCell)];
2614:         int                                    *dofs          = new int[this->_maxDof];
2615:         int                                    *v             = new int[numFields];
2616:         typename real_section_type::value_type *v0            = new typename real_section_type::value_type[this->getDimension()];
2617:         typename real_section_type::value_type *J             = new typename real_section_type::value_type[this->getDimension()*this->getDimension()];
2618:         typename real_section_type::value_type  detJ;
2619:         Visitor pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, true);

2621:         for(typename label_sequence::iterator c_iter = boundaryCells->begin(); c_iter != boundaryCells->end(); ++c_iter) {
2622:           ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), *c_iter, pV);
2623:           const typename Visitor::point_type *oPoints = pV.getPoints();
2624:           const int                           oSize   = pV.getSize();

2626:           if (debug > 1) {std::cout << "  Boundary cell " << *c_iter << std::endl;}
2627:           this->computeElementGeometry(coordinates, *c_iter, v0, J, NULL, detJ);
2628:           for(int f = 0; f < numFields; ++f) v[f] = 0;
2629:           for(int cl = 0; cl < oSize; ++cl) {
2630:             const int cDim = s->getConstraintDimension(oPoints[cl]);
2631:             int       off  = 0;
2632:             int       f    = 0;
2633:             int       i    = -1;

2635:             if (debug > 1) {std::cout << "    point " << oPoints[cl] << std::endl;}
2636:             if (cDim) {
2637:               if (debug > 1) {std::cout << "      constrained excMarker: " << this->getValue(cellExclusion, *c_iter) << std::endl;}
2638:               for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2639:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
2640:                 const Obj<names_type>           bcs     = disc->getBoundaryConditions();
2641:                 const int                       fDim    = s->getFiberDimension(oPoints[cl], f);//disc->getNumDof(this->depth(oPoints[cl]));
2642:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
2643:                 int                             b       = 0;

2645:                 for(typename names_type::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter, ++b) {
2646:                   const Obj<ALE::BoundaryCondition>& bc    = disc->getBoundaryCondition(*bc_iter);
2647:                   const int                          value = this->getValue(this->getLabel(bc->getLabelName()), oPoints[cl]);

2649:                   if (b > 0) v[f] -= fDim;
2650:                   if (value == bc->getMarker()) {
2651:                     if (debug > 1) {std::cout << "      field " << *f_iter << " marker " << value << std::endl;}
2652:                     for(int d = 0; d < fDim; ++d, ++v[f]) {
2653:                       dofs[++i] = off+d;
2654:                       if (!noUpdate) values[indices[v[f]]] = (*bc->getDualIntegrator())(v0, J, v[f], bc->getFunction());
2655:                       if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2656:                     }
2657:                     // Allow only one condition per point
2658:                     ++b;
2659:                     break;
2660:                   } else {
2661:                     if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
2662:                     for(int d = 0; d < fDim; ++d, ++v[f]) {
2663:                       values[indices[v[f]]] = 0.0;
2664:                       if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2665:                     }
2666:                   }
2667:                 }
2668:                 if (b == 0) {
2669:                   if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
2670:                   for(int d = 0; d < fDim; ++d, ++v[f]) {
2671:                     values[indices[v[f]]] = 0.0;
2672:                     if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2673:                   }
2674:                 }
2675:                 off += fDim;
2676:               }
2677:               if (i != cDim-1) {throw ALE::Exception("Invalid constraint initialization");}
2678:               s->setConstraintDof(oPoints[cl], dofs);
2679:             } else {
2680:               if (debug > 1) {std::cout << "      unconstrained" << std::endl;}
2681:               for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2682:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
2683:                 const int                       fDim    = s->getFiberDimension(oPoints[cl], f);//disc->getNumDof(this->depth(oPoints[cl]));
2684:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));

2686:                 if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
2687:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
2688:                   values[indices[v[f]]] = 0.0;
2689:                   if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2690:                 }
2691:               }
2692:             }
2693:           }
2694:           if (debug > 1) {
2695:             for(int f = 0; f < numFields; ++f) v[f] = 0;
2696:             for(int cl = 0; cl < oSize; ++cl) {
2697:               int f = 0;
2698:               for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2699:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
2700:                 const int                       fDim    = s->getFiberDimension(oPoints[cl], f);
2701:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));

2703:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
2704:                   std::cout << "    "<<*f_iter<<"-value["<<indices[v[f]]<<"] " << values[indices[v[f]]] << std::endl;
2705:                 }
2706:               }
2707:             }
2708:           }
2709:           if (!noUpdate) {
2710:             this->updateAll(s, *c_iter, values);
2711:           }
2712:           pV.clear();
2713:         }
2714:         delete [] dofs;
2715:         delete [] values;
2716:         delete [] v0;
2717:         delete [] J;
2718:       }
2719:       if (debug > 1) {s->view("");}
2720:     };
2721:   public:
2722:     // Take in a map for the cells labels
2723:     template<typename Section_>
2724:     void relabel(Section_& labeling) {
2725:       this->getSieve()->relabel(labeling);
2726:       // Relabel sections
2727:       Obj<std::set<std::string> > realNames = this->getRealSections();

2729:       for(std::set<std::string>::const_iterator n_iter = realNames->begin(); n_iter != realNames->end(); ++n_iter) {
2730:         Obj<real_section_type> section = new real_section_type(this->comm(), this->debug());

2732:         section->setName(*n_iter);
2733:         ALE::Ordering<>::relabelSection(*this->getRealSection(*n_iter), labeling, *section);
2734:         this->setRealSection(*n_iter, section);
2735:       }
2736:       Obj<std::set<std::string> > intNames = this->getIntSections();

2738:       for(std::set<std::string>::const_iterator n_iter = intNames->begin(); n_iter != intNames->end(); ++n_iter) {
2739:         Obj<int_section_type> section = new int_section_type(this->comm(), this->debug());

2741:         section->setName(*n_iter);
2742:         ALE::Ordering<>::relabelSection(*this->getIntSection(*n_iter), labeling, *section);
2743:         this->setIntSection(*n_iter, section);
2744:       }
2745:       // Relabel labels
2746:       const labels_type& labels = this->getLabels();

2748:       for(typename labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
2749:         Obj<label_type> label = new label_type(this->comm(), this->debug());

2751:         l_iter->second->relabel(labeling, *label);
2752:         this->setLabel(l_iter->first, label);
2753:       }
2754:       // Relabel overlap
2755:       Obj<send_overlap_type> sendOverlap = new send_overlap_type(this->comm(), this->debug());
2756:       Obj<recv_overlap_type> recvOverlap = new recv_overlap_type(this->comm(), this->debug());

2758:       this->getSendOverlap()->relabel(labeling, *sendOverlap);
2759:       this->setSendOverlap(sendOverlap);
2760:       this->getRecvOverlap()->relabel(labeling, *recvOverlap);
2761:       this->setRecvOverlap(recvOverlap);
2762:       // Relabel distribution overlap ???
2763:       // Relabel renumbering
2764:     }
2765:   };
2766: }

2768: namespace ALE {
2769:   template<typename IndexType, typename ScalarType>
2770:   class Mesh : public Bundle<ALE::Sieve<IndexType,IndexType,IndexType>, GeneralSection<IndexType,ScalarType> > {
2771:   public:
2772:     typedef Bundle<ALE::Sieve<IndexType,IndexType,IndexType>, GeneralSection<IndexType,ScalarType> > base_type;
2773:     typedef typename base_type::sieve_type            sieve_type;
2774:     typedef typename sieve_type::point_type           point_type;
2775:     typedef typename base_type::alloc_type            alloc_type;
2776:     typedef typename base_type::label_type            label_type;
2777:     typedef typename base_type::label_sequence        label_sequence;
2778:     typedef typename base_type::coneArray             coneArray;
2779:     typedef typename base_type::supportArray          supportArray;
2780:     typedef typename base_type::arrow_section_type    arrow_section_type;
2781:     typedef typename base_type::real_section_type     real_section_type;
2782:     typedef typename base_type::numbering_type        numbering_type;
2783:     typedef typename base_type::order_type            order_type;
2784:     typedef typename base_type::send_overlap_type     send_overlap_type;
2785:     typedef typename base_type::recv_overlap_type     recv_overlap_type;
2786:     typedef typename base_type::sieve_alg_type        sieve_alg_type;
2787:     typedef std::set<std::string>            names_type;
2788:     typedef std::map<std::string, Obj<Discretization> > discretizations_type;
2789:     typedef std::vector<PETSc::Point<3> >    holes_type;
2790:   protected:
2791:     int                  _dim;
2792:     discretizations_type _discretizations;
2793:     std::map<int,double> _periodicity;
2794:     holes_type           _holes;
2795:   public:
2796:     Mesh(MPI_Comm comm, int dim, int debug = 0) : base_type(comm, debug), _dim(dim) {
2797:       ///this->_factory = MeshNumberingFactory::singleton(debug);
2798:       //std::cout << "["<<this->commRank()<<"]: Creating an ALE::Mesh" << std::endl;
2799:     };
2800:     ~Mesh() {
2801:       //std::cout << "["<<this->commRank()<<"]: Destroying an ALE::Mesh" << std::endl;
2802:     };
2803:   public: // Accessors
2804:     int getDimension() const {return this->_dim;};
2805:     void setDimension(const int dim) {this->_dim = dim;};
2806:     const Obj<Discretization>& getDiscretization() {return this->getDiscretization("default");};
2807:     const Obj<Discretization>& getDiscretization(const std::string& name) {return this->_discretizations[name];};
2808:     void setDiscretization(const Obj<Discretization>& disc) {this->setDiscretization("default", disc);};
2809:     void setDiscretization(const std::string& name, const Obj<Discretization>& disc) {this->_discretizations[name] = disc;};
2810:     Obj<names_type> getDiscretizations() const {
2811:       Obj<names_type> names = names_type();

2813:       for(discretizations_type::const_iterator d_iter = this->_discretizations.begin(); d_iter != this->_discretizations.end(); ++d_iter) {
2814:         names->insert(d_iter->first);
2815:       }
2816:       return names;
2817:     };
2818:     bool getPeriodicity(const int d) {return this->_periodicity[d];};
2819:     void setPeriodicity(const int d, const double length) {this->_periodicity[d] = length;};
2820:     const holes_type& getHoles() const {return this->_holes;};
2821:     void addHole(const double hole[]) {
2822:       this->_holes.push_back(hole);
2823:     };
2824:     void copyHoles(const Obj<Mesh>& m) {
2825:       const holes_type& holes = m->getHoles();

2827:       for(holes_type::const_iterator h_iter = holes.begin(); h_iter != holes.end(); ++h_iter) {
2828:         this->_holes.push_back(*h_iter);
2829:       }
2830:     };
2831:     void copy(const Obj<Mesh>& m) {
2832:       this->setSieve(m->getSieve());
2833:       this->setLabel("height", m->getLabel("height"));
2834:       this->_maxHeight = m->height();
2835:       this->setLabel("depth", m->getLabel("depth"));
2836:       this->_maxDepth  = m->depth();
2837:       if (m->hasLabel("marker")) {
2838:         this->setLabel("marker", m->getLabel("marker"));
2839:       }
2840:       this->setRealSection("coordinates", m->getRealSection("coordinates"));
2841:       this->setArrowSection("orientation", m->getArrowSection("orientation"));
2842:     };
2843:   public: // Cell topology and geometry
2844:     int getNumCellCorners(const point_type& p, const int depth = -1) const {
2845:       return (this->getDimension() > 0) ? this->_sieve->nCone(p, depth < 0 ? this->depth() : depth)->size() : 1;
2846:     };
2847:     int getNumCellCorners() {
2848:       return getNumCellCorners(*(this->heightStratum(0)->begin()));
2849:     };
2850:     void setupCoordinates(const Obj<real_section_type>& coordinates) {};
2851:     void computeTriangleGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2852:       const double *coords = this->restrictClosure(coordinates, e);
2853:       const int     dim    = 2;
2854:       double        invDet;

2856:       if (v0) {
2857:         for(int d = 0; d < dim; d++) {
2858:           v0[d] = coords[d];
2859:         }
2860:       }
2861:       if (J) {
2862:         for(int d = 0; d < dim; d++) {
2863:           for(int f = 0; f < dim; f++) {
2864:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2865:           }
2866:         }
2867:         detJ = J[0]*J[3] - J[1]*J[2];
2868:         if (detJ < 0.0) {
2869:           const double  xLength = this->_periodicity[0];

2871:           if (xLength != 0.0) {
2872:             double v0x = coords[0*dim+0];

2874:             if (v0x == 0.0) {
2875:               v0x = v0[0] = xLength;
2876:             }
2877:             for(int f = 0; f < dim; f++) {
2878:               const double px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];

2880:               J[0*dim+f] = 0.5*(px - v0x);
2881:             }
2882:           }
2883:           detJ = J[0]*J[3] - J[1]*J[2];
2884:         }
2885:         PetscLogFlops(8.0 + 3.0);
2886:       }
2887:       if (invJ) {
2888:         invDet  = 1.0/detJ;
2889:         invJ[0] =  invDet*J[3];
2890:         invJ[1] = -invDet*J[1];
2891:         invJ[2] = -invDet*J[2];
2892:         invJ[3] =  invDet*J[0];
2893:         PetscLogFlops(5.0);
2894:       }
2895:     };
2896:     void computeQuadrilateralGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double point[], double v0[], double J[], double invJ[], double& detJ) {
2897:       const double *coords = this->restrictClosure(coordinates, e);
2898:       const int     dim    = 2;
2899:       double        invDet;

2901:       if (v0) {
2902:         for(int d = 0; d < dim; d++) {
2903:           v0[d] = coords[d];
2904:         }
2905:       }
2906:       if (J) {
2907:         double x_1 = coords[2] - coords[0];
2908:         double y_1 = coords[3] - coords[1];
2909:         double x_2 = coords[6] - coords[0];
2910:         double y_2 = coords[7] - coords[1];
2911:         double x_3 = coords[4] - coords[0];
2912:         double y_3 = coords[5] - coords[1];

2914:         J[0] = x_1 + (x_3 - x_1 - x_2)*point[1];
2915:         J[1] = x_2 + (x_3 - x_1 - x_2)*point[0];
2916:         J[2] = y_1 + (y_3 - y_1 - y_2)*point[1];
2917:         J[3] = y_1 + (y_3 - y_1 - y_2)*point[0];
2918:         detJ = J[0]*J[3] - J[1]*J[2];
2919:         PetscLogFlops(6.0 + 16.0 + 3.0);
2920:       }
2921:       if (invJ) {
2922:         invDet  = 1.0/detJ;
2923:         invJ[0] =  invDet*J[3];
2924:         invJ[1] = -invDet*J[1];
2925:         invJ[2] = -invDet*J[2];
2926:         invJ[3] =  invDet*J[0];
2927:         PetscLogFlops(5.0);
2928:       }
2929:     };
2930:     void computeTetrahedronGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2931:       const double *coords = this->restrictClosure(coordinates, e);
2932:       const int     dim    = 3;
2933:       double        invDet;

2935:       if (v0) {
2936:         for(int d = 0; d < dim; d++) {
2937:           v0[d] = coords[d];
2938:         }
2939:       }
2940:       if (J) {
2941:         for(int d = 0; d < dim; d++) {
2942:           for(int f = 0; f < dim; f++) {
2943:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2944:           }
2945:         }
2946:         // The minus sign is here since I orient the first face to get the outward normal
2947:         detJ = -(J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2948:                  J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2949:                  J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
2950:         PetscLogFlops(18.0 + 12.0);
2951:       }
2952:       if (invJ) {
2953:         invDet  = -1.0/detJ;
2954:         invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2955:         invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
2956:         invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2957:         invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2958:         invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
2959:         invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2960:         invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2961:         invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
2962:         invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2963:         PetscLogFlops(37.0);
2964:       }
2965:     };
2966:     void computeHexahedralGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double point[], double v0[], double J[], double invJ[], double& detJ) {
2967:       const double *coords = this->restrictClosure(coordinates, e);
2968:       const int     dim    = 3;
2969:       double        invDet;

2971:       if (v0) {
2972:         for(int d = 0; d < dim; d++) {
2973:           v0[d] = coords[d];
2974:         }
2975:       }
2976:       if (J) {
2977:         double x_1 = coords[3]  - coords[0];
2978:         double y_1 = coords[4]  - coords[1];
2979:         double z_1 = coords[5]  - coords[2];
2980:         double x_2 = coords[6]  - coords[0];
2981:         double y_2 = coords[7]  - coords[1];
2982:         double z_2 = coords[8]  - coords[2];
2983:         double x_3 = coords[9]  - coords[0];
2984:         double y_3 = coords[10] - coords[1];
2985:         double z_3 = coords[11] - coords[2];
2986:         double x_4 = coords[12] - coords[0];
2987:         double y_4 = coords[13] - coords[1];
2988:         double z_4 = coords[14] - coords[2];
2989:         double x_5 = coords[15] - coords[0];
2990:         double y_5 = coords[16] - coords[1];
2991:         double z_5 = coords[17] - coords[2];
2992:         double x_6 = coords[18] - coords[0];
2993:         double y_6 = coords[19] - coords[1];
2994:         double z_6 = coords[20] - coords[2];
2995:         double x_7 = coords[21] - coords[0];
2996:         double y_7 = coords[22] - coords[1];
2997:         double z_7 = coords[23] - coords[2];
2998:         double g_x = x_1 - x_2 + x_3 + x_4 - x_5 + x_6 - x_7;
2999:         double g_y = y_1 - y_2 + y_3 + y_4 - y_5 + y_6 - y_7;
3000:         double g_z = z_1 - z_2 + z_3 + z_4 - z_5 + z_6 - z_7;

3002:         J[0] = x_1 + (x_2 - x_1 - x_3)*point[1] + (x_5 - x_1 - x_4)*point[2] + g_x*point[1]*point[2];
3003:         J[1] = x_3 + (x_2 - x_1 - x_3)*point[0] + (x_7 - x_3 - x_4)*point[2] + g_x*point[2]*point[0];
3004:         J[2] = x_4 + (x_7 - x_3 - x_4)*point[1] + (x_5 - x_1 - x_4)*point[0] + g_x*point[0]*point[1];
3005:         J[3] = y_1 + (y_2 - y_1 - y_3)*point[1] + (y_5 - y_1 - y_4)*point[2] + g_y*point[1]*point[2];
3006:         J[4] = y_3 + (y_2 - y_1 - y_3)*point[0] + (y_7 - y_3 - y_4)*point[2] + g_y*point[2]*point[0];
3007:         J[5] = y_4 + (y_7 - y_3 - y_4)*point[1] + (y_5 - y_1 - y_4)*point[0] + g_y*point[0]*point[1];
3008:         J[6] = z_1 + (z_2 - z_1 - z_3)*point[1] + (z_5 - z_1 - z_4)*point[2] + g_z*point[1]*point[2];
3009:         J[7] = z_3 + (z_2 - z_1 - z_3)*point[0] + (z_7 - z_3 - z_4)*point[2] + g_z*point[2]*point[0];
3010:         J[8] = z_4 + (z_7 - z_3 - z_4)*point[1] + (z_5 - z_1 - z_4)*point[0] + g_z*point[0]*point[1];
3011:         detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
3012:                 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
3013:                 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
3014:         PetscLogFlops(39.0 + 81.0 + 12.0);
3015:       }
3016:       if (invJ) {
3017:         invDet  = 1.0/detJ;
3018:         invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
3019:         invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
3020:         invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
3021:         invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
3022:         invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
3023:         invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
3024:         invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
3025:         invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
3026:         invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
3027:         PetscLogFlops(37.0);
3028:       }
3029:     };
3030:     void computeElementGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
3031:       if (this->_dim == 2) {
3032:         computeTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
3033:       } else if (this->_dim == 3) {
3034:         computeTetrahedronGeometry(coordinates, e, v0, J, invJ, detJ);
3035:       } else {
3036:         throw ALE::Exception("Unsupported dimension for element geometry computation");
3037:       }
3038:     };
3039:     void computeLineFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
3040:       const typename arrow_section_type::point_type arrow(cell, face);
3041:       const bool reversed = (this->getArrowSection("orientation")->restrictPoint(arrow)[0] == -2);
3042:       const int  dim      = this->getDimension();
3043:       double     norm     = 0.0;
3044:       double    *vec      = tangent;

3046:       if (f == 0) {
3047:         vec[0] = 0.0;        vec[1] = -1.0;
3048:       } else if (f == 1) {
3049:         vec[0] = 0.70710678; vec[1] = 0.70710678;
3050:       } else if (f == 2) {
3051:         vec[0] = -1.0;       vec[1] = 0.0;
3052:       }
3053:       for(int d = 0; d < dim; ++d) {
3054:         normal[d] = 0.0;
3055:         for(int e = 0; e < dim; ++e) normal[d] += cellInvJ[e*dim+d]*vec[e];
3056:         if (reversed) normal[d] = -normal[d];
3057:         norm += normal[d]*normal[d];
3058:       }
3059:       norm = std::sqrt(norm);
3060:       for(int d = 0; d < dim; ++d) {
3061:         normal[d] /= norm;
3062:       }
3063:       tangent[0] =  normal[1];
3064:       tangent[1] = -normal[0];
3065:       if (this->debug()) {
3066:         std::cout << "Cell: " << cell << " Face: " << face << "("<<f<<")" << std::endl;
3067:         for(int d = 0; d < dim; ++d) {
3068:           std::cout << "Normal["<<d<<"]: " << normal[d] << " Tangent["<<d<<"]: " << tangent[d] << std::endl;
3069:         }
3070:       }
3071:       // Now get 1D Jacobian info
3072:       //   Should be a way to get this directly
3073:       const double *coords = this->restrictClosure(this->getRealSection("coordinates"), face);
3074:       detJ    = std::sqrt(PetscSqr(coords[1*2+0] - coords[0*2+0]) + PetscSqr(coords[1*2+1] - coords[0*2+1]))/2.0;
3075:       invJ[0] = 1.0/detJ;
3076:     };
3077:     void computeTriangleFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
3078:       const typename arrow_section_type::point_type arrow(cell, face);
3079:       const bool reversed = this->getArrowSection("orientation")->restrictPoint(arrow)[0] < 0;
3080:       const int  dim      = this->getDimension();
3081:       const int  faceDim  = dim-1;
3082:       double     norm     = 0.0;
3083:       double    *vec      = tangent;

3085:       if (f == 0) {
3086:         vec[0] = 0.0;        vec[1] = 0.0;        vec[2] = -1.0;
3087:       } else if (f == 1) {
3088:         vec[0] = 0.0;        vec[1] = -1.0;       vec[2] = 0.0;
3089:       } else if (f == 2) {
3090:         vec[0] = 0.57735027; vec[1] = 0.57735027; vec[2] = 0.57735027;
3091:       } else if (f == 3) {
3092:         vec[0] = -1.0;       vec[1] = 0.0;        vec[2] = 0.0;
3093:       }
3094:       for(int d = 0; d < dim; ++d) {
3095:         normal[d] = 0.0;
3096:         for(int e = 0; e < dim; ++e) normal[d] += cellInvJ[e*dim+d]*vec[e];
3097:         if (reversed) normal[d] = -normal[d];
3098:         norm += normal[d]*normal[d];
3099:       }
3100:       norm = std::sqrt(norm);
3101:       for(int d = 0; d < dim; ++d) {
3102:         normal[d] /= norm;
3103:       }
3104:       // Get tangents
3105:       tangent[0] = normal[1] - normal[2];
3106:       tangent[1] = normal[2] - normal[0];
3107:       tangent[2] = normal[0] - normal[1];
3108:       norm = 0.0;
3109:       for(int d = 0; d < dim; ++d) {
3110:         norm += tangent[d]*tangent[d];
3111:       }
3112:       norm = std::sqrt(norm);
3113:       for(int d = 0; d < dim; ++d) {
3114:         tangent[d] /= norm;
3115:       }
3116:       tangent[3] = normal[1]*tangent[2] - normal[2]*tangent[1];
3117:       tangent[4] = normal[2]*tangent[0] - normal[0]*tangent[2];
3118:       tangent[5] = normal[0]*tangent[1] - normal[1]*tangent[0];
3119:       if (this->debug()) {
3120:         std::cout << "Cell: " << cell << " Face: " << face << "("<<f<<")" << std::endl;
3121:         for(int d = 0; d < dim; ++d) {
3122:           std::cout << "Normal["<<d<<"]: " << normal[d] << " TangentA["<<d<<"]: " << tangent[d] << " TangentB["<<d<<"]: " << tangent[dim+d] << std::endl;
3123:         }
3124:       }
3125:       // Now get 2D Jacobian info
3126:       //   Should be a way to get this directly
3127:       const double *coords = this->restrictClosure(this->getRealSection("coordinates"), face);
3128:       // Rotate so that normal in z
3129:       double invR[9], R[9];
3130:       double detR, invDetR;
3131:       for(int d = 0; d < dim; d++) {
3132:         invR[d*dim+0] = tangent[d];
3133:         invR[d*dim+1] = tangent[dim+d];
3134:         invR[d*dim+2] = normal[d];
3135:       }
3136:       invDetR = (invR[0*3+0]*(invR[1*3+1]*invR[2*3+2] - invR[1*3+2]*invR[2*3+1]) +
3137:                  invR[0*3+1]*(invR[1*3+2]*invR[2*3+0] - invR[1*3+0]*invR[2*3+2]) +
3138:                  invR[0*3+2]*(invR[1*3+0]*invR[2*3+1] - invR[1*3+1]*invR[2*3+0]));
3139:       detR  = 1.0/invDetR;
3140:       R[0*3+0] = detR*(invR[1*3+1]*invR[2*3+2] - invR[1*3+2]*invR[2*3+1]);
3141:       R[0*3+1] = detR*(invR[0*3+2]*invR[2*3+1] - invR[0*3+1]*invR[2*3+2]);
3142:       R[0*3+2] = detR*(invR[0*3+1]*invR[1*3+2] - invR[0*3+2]*invR[1*3+1]);
3143:       R[1*3+0] = detR*(invR[1*3+2]*invR[2*3+0] - invR[1*3+0]*invR[2*3+2]);
3144:       R[1*3+1] = detR*(invR[0*3+0]*invR[2*3+2] - invR[0*3+2]*invR[2*3+0]);
3145:       R[1*3+2] = detR*(invR[0*3+2]*invR[1*3+0] - invR[0*3+0]*invR[1*3+2]);
3146:       R[2*3+0] = detR*(invR[1*3+0]*invR[2*3+1] - invR[1*3+1]*invR[2*3+0]);
3147:       R[2*3+1] = detR*(invR[0*3+1]*invR[2*3+0] - invR[0*3+0]*invR[2*3+1]);
3148:       R[2*3+2] = detR*(invR[0*3+0]*invR[1*3+1] - invR[0*3+1]*invR[1*3+0]);
3149:       for(int d = 0; d < dim; d++) {
3150:         for(int e = 0; e < dim; e++) {
3151:           invR[d*dim+e] = 0.0;
3152:           for(int g = 0; g < dim; g++) {
3153:             invR[d*dim+e] += R[e*dim+g]*coords[d*dim+g];
3154:           }
3155:         }
3156:       }
3157:       for(int d = dim-1; d >= 0; --d) {
3158:         invR[d*dim+2] -= invR[0*dim+2];
3159:         if (this->debug() && (d == dim-1)) {
3160:           double ref[9];
3161:           for(int q = 0; q < dim; q++) {
3162:             for(int e = 0; e < dim; e++) {
3163:               ref[q*dim+e] = 0.0;
3164:               for(int g = 0; g < dim; g++) {
3165:                 ref[q*dim+e] += cellInvJ[e*dim+g]*coords[q*dim+g];
3166:               }
3167:             }
3168:           }
3169:           std::cout << "f: " << f << std::endl;
3170:           std::cout << this->printMatrix(std::string("coords"), dim, dim, coords) << std::endl;
3171:           std::cout << this->printMatrix(std::string("ref coords"), dim, dim, ref) << std::endl;
3172:           std::cout << this->printMatrix(std::string("R"), dim, dim, R) << std::endl;
3173:           std::cout << this->printMatrix(std::string("invR"), dim, dim, invR) << std::endl;
3174:         }
3175:         if (fabs(invR[d*dim+2]) > 1.0e-8) {
3176:           throw ALE::Exception("Invalid rotation");
3177:         }
3178:       }
3179:       double J[4];
3180:       for(int d = 0; d < faceDim; d++) {
3181:         for(int e = 0; e < faceDim; e++) {
3182:           J[d*faceDim+e] = 0.5*(invR[(e+1)*dim+d] - invR[0*dim+d]);
3183:         }
3184:       }
3185:       detJ = fabs(J[0]*J[3] - J[1]*J[2]);
3186:       // Probably need something here if detJ < 0
3187:       const double invDet = 1.0/detJ;
3188:       invJ[0] =  invDet*J[3];
3189:       invJ[1] = -invDet*J[1];
3190:       invJ[2] = -invDet*J[2];
3191:       invJ[3] =  invDet*J[0];
3192:     };
3193:     void computeFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
3194:       if (this->_dim == 2) {
3195:         computeLineFaceGeometry(cell, face, f, cellInvJ, invJ, detJ, normal, tangent);
3196:       } else if (this->_dim == 3) {
3197:         computeTriangleFaceGeometry(cell, face, f, cellInvJ, invJ, detJ, normal, tangent);
3198:       } else {
3199:         throw ALE::Exception("Unsupported dimension for element geometry computation");
3200:       }
3201:     };
3202:     double getMaxVolume() {
3203:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3204:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
3205:       const int                     dim         = this->getDimension();
3206:       double v0[3], J[9], invJ[9], detJ, refVolume = 0.0, maxVolume = 0.0;

3208:       if (dim == 1) refVolume = 2.0;
3209:       if (dim == 2) refVolume = 2.0;
3210:       if (dim == 3) refVolume = 4.0/3.0;
3211:       for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
3212:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
3213:         maxVolume = std::max(maxVolume, detJ*refVolume);
3214:       }
3215:       return maxVolume;
3216:     };
3217:     // Find the cell in which this point lies (stupid algorithm)
3218:     point_type locatePoint_2D(const typename real_section_type::value_type point[]) {
3219:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3220:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
3221:       const int                     embedDim    = 2;
3222:       double v0[2], J[4], invJ[4], detJ;

3224:       for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
3225:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
3226:         double xi   = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]);
3227:         double eta  = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]);

3229:         if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) {
3230:           return *c_iter;
3231:         }
3232:       }
3233:       throw ALE::Exception("Could not locate point");
3234:     };
3235:     //   Assume a simplex and 3D
3236:     point_type locatePoint_3D(const typename real_section_type::value_type point[]) {
3237:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3238:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
3239:       const int                     embedDim    = 3;
3240:       double v0[3], J[9], invJ[9], detJ;

3242:       for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
3243:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
3244:         double xi   = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]) + invJ[0*embedDim+2]*(point[2] - v0[2]);
3245:         double eta  = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]) + invJ[1*embedDim+2]*(point[2] - v0[2]);
3246:         double zeta = invJ[2*embedDim+0]*(point[0] - v0[0]) + invJ[2*embedDim+1]*(point[1] - v0[1]) + invJ[2*embedDim+2]*(point[2] - v0[2]);

3248:         if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) {
3249:           return *c_iter;
3250:         }
3251:       }
3252:       throw ALE::Exception("Could not locate point");
3253:     };
3254:     point_type locatePoint(const typename real_section_type::value_type point[], point_type guess = -1) {
3255:       //guess overrides this by saying that we already know the relation of this point to this mesh.  We will need to make it a more robust "guess" later for more than P1
3256:       if (guess != -1) {
3257:         return guess;
3258:       }else if (this->_dim == 2) {
3259:         return locatePoint_2D(point);
3260:       } else if (this->_dim == 3) {
3261:         return locatePoint_3D(point);
3262:       } else {
3263:         throw ALE::Exception("No point location for mesh dimension");
3264:       }
3265:     };
3266:   public: // Discretization
3267:     void markBoundaryCells(const std::string& name, const int marker = 1, const int newMarker = 2, const bool onlyVertices = false) {
3268:       const Obj<label_type>&     label    = this->getLabel(name);
3269:       const Obj<label_sequence>& boundary = this->getLabelStratum(name, marker);
3270:       const Obj<sieve_type>&     sieve    = this->getSieve();

3272:       if (!onlyVertices) {
3273:         const typename label_sequence::iterator end = boundary->end();

3275:         for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != end; ++e_iter) {
3276:           if (this->height(*e_iter) == 1) {
3277:             const point_type cell = *sieve->support(*e_iter)->begin();

3279:             this->setValue(label, cell, newMarker);
3280:           }
3281:         }
3282:       } else {
3283:         const typename label_sequence::iterator end   = boundary->end();
3284:         const int                      depth = this->depth();

3286:         for(typename label_sequence::iterator v_iter = boundary->begin(); v_iter != end; ++v_iter) {
3287:           const Obj<supportArray>      support = sieve->nSupport(*v_iter, depth);
3288:           const typename supportArray::iterator sEnd    = support->end();

3290:           for(typename supportArray::iterator c_iter = support->begin(); c_iter != sEnd; ++c_iter) {
3291:             const Obj<typename sieve_type::traits::coneSequence>&     cone = sieve->cone(*c_iter);
3292:             const typename sieve_type::traits::coneSequence::iterator cEnd = cone->end();

3294:             for(typename sieve_type::traits::coneSequence::iterator e_iter = cone->begin(); e_iter != cEnd; ++e_iter) {
3295:               if (sieve->support(*e_iter)->size() == 1) {
3296:                 this->setValue(label, *c_iter, newMarker);
3297:                 break;
3298:               }
3299:             }
3300:           }
3301:         }
3302:       }
3303:     };
3304:     int setFiberDimensions(const Obj<real_section_type>& s, const Obj<names_type>& discs, names_type& bcLabels) {
3305:       const int debug  = this->debug();
3306:       int       maxDof = 0;

3308:       for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter) {
3309:         s->addSpace();
3310:       }
3311:       for(int d = 0; d <= this->_dim; ++d) {
3312:         int numDof = 0;
3313:         int f      = 0;

3315:         for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3316:           const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
3317:           const int                       sDof = disc->getNumDof(d);

3319:           numDof += sDof;
3320:           if (sDof) s->setFiberDimension(this->depthStratum(d), sDof, f);
3321:         }
3322:         if (numDof) s->setFiberDimension(this->depthStratum(d), numDof);
3323:         maxDof = std::max(maxDof, numDof);
3324:       }
3325:       // Process exclusions
3326:       int f = 0;

3328:       for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3329:         const Obj<ALE::Discretization>& disc      = this->getDiscretization(*f_iter);
3330:         std::string                     labelName = "exclude-"+*f_iter;
3331:         std::set<point_type>            seen;

3333:         if (this->hasLabel(labelName)) {
3334:           const Obj<label_type>&         label     = this->getLabel(labelName);
3335:           const Obj<label_sequence>&     exclusion = this->getLabelStratum(labelName, 1);
3336:           const typename label_sequence::iterator end       = exclusion->end();
3337:           if (debug > 1) {label->view(labelName.c_str());}

3339:           for(typename label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
3340:             const Obj<coneArray>      closure = ALE::SieveAlg<ALE::Mesh<IndexType,ScalarType> >::closure(this, this->getArrowSection("orientation"), *e_iter);
3341:             const typename coneArray::iterator cEnd    = closure->end();

3343:             for(typename coneArray::iterator c_iter = closure->begin(); c_iter != cEnd; ++c_iter) {
3344:               if (seen.find(*c_iter) != seen.end()) continue;
3345:               if (this->getValue(label, *c_iter) == 1) {
3346:                 seen.insert(*c_iter);
3347:                 s->setFiberDimension(*c_iter, 0, f);
3348:                 s->addFiberDimension(*c_iter, -disc->getNumDof(this->depth(*c_iter)));
3349:                 if (debug > 1) {std::cout << "  cell: " << *c_iter << " dim: " << disc->getNumDof(this->depth(*c_iter)) << std::endl;}
3350:               }
3351:             }
3352:           }
3353:         }
3354:       }
3355:       // Process constraints
3356:       f = 0;
3357:       for(typename std::set<std::string>::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3358:         const Obj<ALE::Discretization>&    disc        = this->getDiscretization(*f_iter);
3359:         const Obj<std::set<std::string> >  bcs         = disc->getBoundaryConditions();
3360:         std::string                        excludeName = "exclude-"+*f_iter;

3362:         for(typename std::set<std::string>::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter) {
3363:           const Obj<ALE::BoundaryCondition>& bc       = disc->getBoundaryCondition(*bc_iter);
3364:           const Obj<label_sequence>&         boundary = this->getLabelStratum(bc->getLabelName(), bc->getMarker());

3366:           bcLabels.insert(bc->getLabelName());
3367:           if (this->hasLabel(excludeName)) {
3368:             const Obj<label_type>& label = this->getLabel(excludeName);

3370:             for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
3371:               if (!this->getValue(label, *e_iter)) {
3372:                 const int numDof = disc->getNumDof(this->depth(*e_iter));

3374:                 if (numDof) s->addConstraintDimension(*e_iter, numDof);
3375:                 if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
3376:               }
3377:             }
3378:           } else {
3379:             for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
3380:               const int numDof = disc->getNumDof(this->depth(*e_iter));

3382:               if (numDof) s->addConstraintDimension(*e_iter, numDof);
3383:               if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
3384:             }
3385:           }
3386:         }
3387:       }
3388:       return maxDof;
3389:     };
3390:     void calculateIndices() {
3391:       // Should have an iterator over the whole tree
3392:       Obj<names_type> discs = this->getDiscretizations();
3393:       Obj<Mesh>       mesh  = this;
3394:       const int       debug = this->debug();
3395:       std::map<std::string, std::pair<int, int*> > indices;

3397:       mesh.addRef();
3398:       for(names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
3399:         const Obj<Discretization>& disc = this->getDiscretization(*d_iter);

3401:         indices[*d_iter] = std::pair<int, int*>(0, new int[disc->size(mesh)]);
3402:         disc->setIndices(indices[*d_iter].second);
3403:       }
3404:       const Obj<label_sequence>& cells   = this->heightStratum(0);
3405:       const Obj<coneArray>       closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *cells->begin());
3406:       const typename coneArray::iterator  end     = closure->end();
3407:       int                        offset  = 0;

3409:       if (debug > 1) {std::cout << "Closure for first element" << std::endl;}
3410:       for(typename coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
3411:         const int dim = this->depth(*cl_iter);

3413:         if (debug > 1) {std::cout << "  point " << *cl_iter << " depth " << dim << std::endl;}
3414:         for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
3415:           const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
3416:           const int                  num  = disc->getNumDof(dim);

3418:           if (debug > 1) {std::cout << "    disc " << disc->getName() << " numDof " << num << std::endl;}
3419:           for(int o = 0; o < num; ++o) {
3420:             indices[*d_iter].second[indices[*d_iter].first++] = offset++;
3421:           }
3422:         }
3423:       }
3424:       if (debug > 1) {
3425:         for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
3426:           const Obj<Discretization>& disc = this->getDiscretization(*d_iter);

3428:           std::cout << "Discretization " << disc->getName() << " indices:";
3429:           for(int i = 0; i < indices[*d_iter].first; ++i) {
3430:             std::cout << " " << indices[*d_iter].second[i];
3431:           }
3432:           std::cout << std::endl;
3433:         }
3434:       }
3435:     };
3436:     void calculateIndicesExcluded(const Obj<real_section_type>& s, const Obj<names_type>& discs) {
3437:       typedef std::map<std::string, std::pair<int, indexSet> > indices_type;
3438:       const Obj<label_type>& indexLabel = this->createLabel("cellExclusion");
3439:       const int debug  = this->debug();
3440:       int       marker = 0;
3441:       Obj<Mesh> mesh   = this;
3442:       std::map<indices_type, int> indexMap;
3443:       indices_type                indices;

3445:       mesh.addRef();
3446:       for(names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
3447:         const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
3448:         const int                  size = disc->size(mesh);

3450:         indices[*d_iter].second.resize(size);
3451:       }
3452:       const names_type::const_iterator dBegin = discs->begin();
3453:       const names_type::const_iterator dEnd   = discs->end();
3454:       std::set<point_type> seen;
3455:       int f = 0;

3457:       for(names_type::const_iterator f_iter = dBegin; f_iter != dEnd; ++f_iter, ++f) {
3458:         std::string labelName = "exclude-"+*f_iter;

3460:         if (this->hasLabel(labelName)) {
3461:           const Obj<label_sequence>&     exclusion = this->getLabelStratum(labelName, 1);
3462:           const typename label_sequence::iterator end       = exclusion->end();

3464:           if (debug > 1) {std::cout << "Processing exclusion " << labelName << std::endl;}
3465:           for(typename label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
3466:             if (this->height(*e_iter)) continue;
3467:             const Obj<coneArray>      closure = ALE::SieveAlg<ALE::Mesh<IndexType,ScalarType> >::closure(this, this->getArrowSection("orientation"), *e_iter);
3468:             const typename coneArray::iterator clEnd   = closure->end();
3469:             int                       offset  = 0;

3471:             if (debug > 1) {std::cout << "  Closure for cell " << *e_iter << std::endl;}
3472:             for(typename coneArray::iterator cl_iter = closure->begin(); cl_iter != clEnd; ++cl_iter) {
3473:               int g = 0;

3475:               if (debug > 1) {std::cout << "    point " << *cl_iter << std::endl;}
3476:               for(typename names_type::const_iterator g_iter = dBegin; g_iter != dEnd; ++g_iter, ++g) {
3477:                 const int fDim = s->getFiberDimension(*cl_iter, g);

3479:                 if (debug > 1) {std::cout << "      disc " << *g_iter << " numDof " << fDim << std::endl;}
3480:                 for(int d = 0; d < fDim; ++d) {
3481:                   indices[*g_iter].second[indices[*g_iter].first++] = offset++;
3482:                 }
3483:               }
3484:             }
3485:             const typename std::map<indices_type, int>::iterator entry = indexMap.find(indices);

3487:             if (debug > 1) {
3488:               for(typename std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
3489:                 for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3490:                   std::cout << "Discretization (" << i_iter->second << ") " << *g_iter << " indices:";
3491:                   for(int i = 0; i < ((indices_type) i_iter->first)[*g_iter].first; ++i) {
3492:                     std::cout << " " << ((indices_type) i_iter->first)[*g_iter].second[i];
3493:                   }
3494:                   std::cout << std::endl;
3495:                 }
3496:                 std::cout << "Comparison: " << (indices == i_iter->first) << std::endl;
3497:               }
3498:               for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3499:                 std::cout << "Discretization " << *g_iter << " indices:";
3500:                 for(int i = 0; i < indices[*g_iter].first; ++i) {
3501:                   std::cout << " " << indices[*g_iter].second[i];
3502:                 }
3503:                 std::cout << std::endl;
3504:               }
3505:             }
3506:             if (entry != indexMap.end()) {
3507:               this->setValue(indexLabel, *e_iter, entry->second);
3508:               if (debug > 1) {std::cout << "  Found existing indices with marker " << entry->second << std::endl;}
3509:             } else {
3510:               indexMap[indices] = ++marker;
3511:               this->setValue(indexLabel, *e_iter, marker);
3512:               if (debug > 1) {std::cout << "  Created new indices with marker " << marker << std::endl;}
3513:             }
3514:             for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3515:               indices[*g_iter].first  = 0;
3516:               for(unsigned int i = 0; i < indices[*g_iter].second.size(); ++i) indices[*g_iter].second[i] = 0;
3517:             }
3518:           }
3519:         }
3520:       }
3521:       if (debug > 1) {indexLabel->view("cellExclusion");}
3522:       for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
3523:         if (debug > 1) {std::cout << "Setting indices for marker " << i_iter->second << std::endl;}
3524:         for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3525:           const Obj<Discretization>& disc = this->getDiscretization(*g_iter);
3526:           const indexSet  indSet   = ((indices_type) i_iter->first)[*g_iter].second;
3527:           const int       size     = indSet.size();
3528:           int            *_indices = new int[size];

3530:           if (debug > 1) {std::cout << "  field " << *g_iter << std::endl;}
3531:           for(int i = 0; i < size; ++i) {
3532:             _indices[i] = indSet[i];
3533:             if (debug > 1) {std::cout << "    indices["<<i<<"] = " << _indices[i] << std::endl;}
3534:           }
3535:           disc->setIndices(_indices, i_iter->second);
3536:         }
3537:       }
3538:     };
3539:     void setupField(const Obj<real_section_type>& s, const int cellMarker = 2, const bool noUpdate = false) {
3540:       const Obj<names_type>& discs  = this->getDiscretizations();
3541:       const int              debug  = s->debug();
3542:       names_type             bcLabels;
3543:       int                    maxDof;

3545:       maxDof = this->setFiberDimensions(s, discs, bcLabels);
3546:       this->calculateIndices();
3547:       this->calculateIndicesExcluded(s, discs);
3548:       this->allocate(s);
3549:       s->defaultConstraintDof();
3550:       const Obj<label_type>& cellExclusion = this->getLabel("cellExclusion");

3552:       if (debug > 1) {std::cout << "Setting boundary values" << std::endl;}
3553:       for(names_type::const_iterator n_iter = bcLabels.begin(); n_iter != bcLabels.end(); ++n_iter) {
3554:         const Obj<label_sequence>&     boundaryCells = this->getLabelStratum(*n_iter, cellMarker);
3555:         const Obj<real_section_type>&  coordinates   = this->getRealSection("coordinates");
3556:         const Obj<names_type>&         discs         = this->getDiscretizations();
3557:         const point_type               firstCell     = *boundaryCells->begin();
3558:         const int                      numFields     = discs->size();
3559:         typename real_section_type::value_type *values = new typename real_section_type::value_type[this->sizeWithBC(s, firstCell)];
3560:         int                           *dofs          = new int[maxDof];
3561:         int                           *v             = new int[numFields];
3562:         typename real_section_type::value_type *v0   = new typename real_section_type::value_type[this->getDimension()];
3563:         typename real_section_type::value_type *J    = new typename real_section_type::value_type[this->getDimension()*this->getDimension()];
3564:         typename real_section_type::value_type  detJ;

3566:         for(typename label_sequence::iterator c_iter = boundaryCells->begin(); c_iter != boundaryCells->end(); ++c_iter) {
3567:           const Obj<coneArray>      closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *c_iter);
3568:           const typename coneArray::iterator end     = closure->end();

3570:           if (debug > 1) {std::cout << "  Boundary cell " << *c_iter << std::endl;}
3571:           this->computeElementGeometry(coordinates, *c_iter, v0, J, NULL, detJ);
3572:           for(int f = 0; f < numFields; ++f) v[f] = 0;
3573:           for(typename coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
3574:             const int cDim = s->getConstraintDimension(*cl_iter);
3575:             int       off  = 0;
3576:             int       f    = 0;
3577:             int       i    = -1;

3579:             if (debug > 1) {std::cout << "    point " << *cl_iter << std::endl;}
3580:             if (cDim) {
3581:               if (debug > 1) {std::cout << "      constrained excMarker: " << this->getValue(cellExclusion, *c_iter) << std::endl;}
3582:               for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3583:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
3584:                 const Obj<names_type>           bcs     = disc->getBoundaryConditions();
3585:                 const int                       fDim    = s->getFiberDimension(*cl_iter, f);//disc->getNumDof(this->depth(*cl_iter));
3586:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
3587:                 int                             b       = 0;

3589:                 for(names_type::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter, ++b) {
3590:                   const Obj<ALE::BoundaryCondition>& bc    = disc->getBoundaryCondition(*bc_iter);
3591:                   const int                          value = this->getValue(this->getLabel(bc->getLabelName()), *cl_iter);

3593:                   if (b > 0) v[f] -= fDim;
3594:                   if (value == bc->getMarker()) {
3595:                     if (debug > 1) {std::cout << "      field " << *f_iter << " marker " << value << std::endl;}
3596:                     for(int d = 0; d < fDim; ++d, ++v[f]) {
3597:                       dofs[++i] = off+d;
3598:                       if (!noUpdate) values[indices[v[f]]] = (*bc->getDualIntegrator())(v0, J, v[f], bc->getFunction());
3599:                       if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3600:                     }
3601:                     // Allow only one condition per point
3602:                     ++b;
3603:                     break;
3604:                   } else {
3605:                     if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
3606:                     for(int d = 0; d < fDim; ++d, ++v[f]) {
3607:                       values[indices[v[f]]] = 0.0;
3608:                       if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3609:                     }
3610:                   }
3611:                 }
3612:                 if (b == 0) {
3613:                   if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
3614:                   for(int d = 0; d < fDim; ++d, ++v[f]) {
3615:                     values[indices[v[f]]] = 0.0;
3616:                     if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3617:                   }
3618:                 }
3619:                 off += fDim;
3620:               }
3621:               if (i != cDim-1) {throw ALE::Exception("Invalid constraint initialization");}
3622:               s->setConstraintDof(*cl_iter, dofs);
3623:             } else {
3624:               if (debug > 1) {std::cout << "      unconstrained" << std::endl;}
3625:               for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3626:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
3627:                 const int                       fDim    = s->getFiberDimension(*cl_iter, f);//disc->getNumDof(this->depth(*cl_iter));
3628:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));

3630:                 if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
3631:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
3632:                   values[indices[v[f]]] = 0.0;
3633:                   if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3634:                 }
3635:               }
3636:             }
3637:           }
3638:           if (debug > 1) {
3639:             const Obj<coneArray>      closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *c_iter);
3640:             const typename coneArray::iterator end     = closure->end();

3642:             for(int f = 0; f < numFields; ++f) v[f] = 0;
3643:             for(typename coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
3644:               int f = 0;
3645:               for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3646:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
3647:                 const int                       fDim    = s->getFiberDimension(*cl_iter, f);
3648:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));

3650:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
3651:                   std::cout << "    "<<*f_iter<<"-value["<<indices[v[f]]<<"] " << values[indices[v[f]]] << std::endl;
3652:                 }
3653:               }
3654:             }
3655:           }
3656:           if (!noUpdate) {
3657:             this->updateAll(s, *c_iter, values);
3658:           }
3659:         }
3660:         delete [] dofs;
3661:         delete [] values;
3662:         delete [] v0;
3663:         delete [] J;
3664:       }
3665:       if (debug > 1) {s->view("");}
3666:     };
3667:   public:
3668:     void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
3669:       if (comm == MPI_COMM_NULL) {
3670:         comm = this->comm();
3671:       }
3672:       if (name == "") {
3673:         PetscPrintf(comm, "viewing a Mesh\n");
3674:       } else {
3675:         PetscPrintf(comm, "viewing Mesh '%s'\n", name.c_str());
3676:       }
3677:       this->getSieve()->view("mesh sieve", comm);
3678:       Obj<names_type> sections = this->getRealSections();

3680:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
3681:         this->getRealSection(*name)->view(*name);
3682:       }
3683:       sections = this->getIntSections();
3684:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
3685:         this->getIntSection(*name)->view(*name);
3686:       }
3687:       sections = this->getArrowSections();
3688:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
3689:         this->getArrowSection(*name)->view(*name);
3690:       }
3691:     };
3692:     template<typename value_type>
3693:     static std::string printMatrix(const std::string& name, const int rows, const int cols, const value_type matrix[], const int rank = -1)
3694:     {
3695:       ostringstream output;
3696:       ostringstream rankStr;

3698:       if (rank >= 0) {
3699:         rankStr << "[" << rank << "]";
3700:       }
3701:       output << rankStr.str() << name << " = " << std::endl;
3702:       for(int r = 0; r < rows; r++) {
3703:         if (r == 0) {
3704:           output << rankStr.str() << " /";
3705:         } else if (r == rows-1) {
3706:           output << rankStr.str() << " \\";
3707:         } else {
3708:           output << rankStr.str() << " |";
3709:         }
3710:         for(int c = 0; c < cols; c++) {
3711:           output << " " << matrix[r*cols+c];
3712:         }
3713:         if (r == 0) {
3714:           output << " \\" << std::endl;
3715:         } else if (r == rows-1) {
3716:           output << " /" << std::endl;
3717:         } else {
3718:           output << " |" << std::endl;
3719:         }
3720:       }
3721:       return output.str();
3722:     }
3723:   };
3724:   template<typename Mesh>
3725:   class MeshBuilder {
3726:   public:
3727:     typedef typename Mesh::real_section_type::value_type real;
3728:   public:
3731:     /*
3732:       Simple square boundary:

3734:      18--5-17--4--16
3735:       |     |     |
3736:       6    10     3
3737:       |     |     |
3738:      19-11-20--9--15
3739:       |     |     |
3740:       7     8     2
3741:       |     |     |
3742:      12--0-13--1--14
3743:     */
3744:     static Obj<Mesh> createSquareBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int edges[], const int debug = 0) {
3745:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
3746:       int       numVertices = (edges[0]+1)*(edges[1]+1);
3747:       int       numEdges    = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
3748:       real     *coords      = new real[numVertices*2];
3749:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
3750:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];
3751:       int                         order    = 0;

3753:       mesh->setSieve(sieve);
3754:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
3755:       if (mesh->commRank() == 0) {
3756:         /* Create sieve and ordering */
3757:         for(int v = numEdges; v < numEdges+numVertices; v++) {
3758:           vertices[v-numEdges] = typename Mesh::point_type(v);
3759:         }
3760:         for(int vy = 0; vy <= edges[1]; vy++) {
3761:           for(int ex = 0; ex < edges[0]; ex++) {
3762:             typename Mesh::point_type edge(vy*edges[0] + ex);
3763:             int vertex = vy*(edges[0]+1) + ex;

3765:             sieve->addArrow(vertices[vertex+0], edge, order++);
3766:             sieve->addArrow(vertices[vertex+1], edge, order++);
3767:             if ((vy == 0) || (vy == edges[1])) {
3768:               mesh->setValue(markers, edge, 1);
3769:               mesh->setValue(markers, vertices[vertex], 1);
3770:               if (ex == edges[0]-1) {
3771:                 mesh->setValue(markers, vertices[vertex+1], 1);
3772:               }
3773:             }
3774:           }
3775:         }
3776:         for(int vx = 0; vx <= edges[0]; vx++) {
3777:           for(int ey = 0; ey < edges[1]; ey++) {
3778:             typename Mesh::point_type edge(vx*edges[1] + ey + edges[0]*(edges[1]+1));
3779:             int vertex = ey*(edges[0]+1) + vx;

3781:             sieve->addArrow(vertices[vertex],            edge, order++);
3782:             sieve->addArrow(vertices[vertex+edges[0]+1], edge, order++);
3783:             if ((vx == 0) || (vx == edges[0])) {
3784:               mesh->setValue(markers, edge, 1);
3785:               mesh->setValue(markers, vertices[vertex], 1);
3786:               if (ey == edges[1]-1) {
3787:                 mesh->setValue(markers, vertices[vertex+edges[0]+1], 1);
3788:               }
3789:             }
3790:           }
3791:         }
3792:       }
3793:       mesh->stratify();
3794:       for(int vy = 0; vy <= edges[1]; ++vy) {
3795:         for(int vx = 0; vx <= edges[0]; ++vx) {
3796:           coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
3797:           coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
3798:         }
3799:       }
3800:       delete [] vertices;
3801:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
3802:       return mesh;
3803:     };
3806:     /*
3807:       Simple square boundary:

3809:      14--5-13--4--12
3810:       |           |
3811:       6           3
3812:       |           |
3813:      15           11
3814:       |           |
3815:       7           2
3816:       |           |
3817:       8--0--9--1--10
3818:     */
3819:     static Obj<Mesh> createSquareBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int edges, const int debug = 0) {
3820:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
3821:       int       numVertices = edges*4;
3822:       int       numEdges    = edges*4;
3823:       real     *coords      = new real[numVertices*2];
3824:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
3825:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];

3827:       mesh->setSieve(sieve);
3828:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
3829:       if (mesh->commRank() == 0) {
3830:         /* Create sieve and ordering */
3831:         for(int v = numEdges; v < numEdges+numVertices; v++) {
3832:           vertices[v-numEdges] = typename Mesh::point_type(v);
3833:         }
3834:         for(int e = 0; e < numEdges; ++e) {
3835:           typename Mesh::point_type edge(e);
3836:           int order = 0;

3838:           sieve->addArrow(vertices[e],                 edge, order++);
3839:           sieve->addArrow(vertices[(e+1)%numVertices], edge, order++);
3840:           mesh->setValue(markers, edge, 2);
3841:           mesh->setValue(markers, vertices[e], 1);
3842:           mesh->setValue(markers, vertices[(e+1)%numVertices], 1);
3843:         }
3844:       }
3845:       mesh->stratify();
3846:       for(int v = 0; v < edges; ++v) {
3847:         coords[(v+edges*0)*2+0] = lower[0] + ((upper[0] - lower[0])/edges)*v;
3848:         coords[(v+edges*0)*2+1] = lower[1];
3849:       }
3850:       for(int v = 0; v < edges; ++v) {
3851:         coords[(v+edges*1)*2+0] = upper[0];
3852:         coords[(v+edges*1)*2+1] = lower[1] + ((upper[1] - lower[1])/edges)*v;
3853:       }
3854:       for(int v = 0; v < edges; ++v) {
3855:         coords[(v+edges*2)*2+0] = upper[0] - ((upper[0] - lower[0])/edges)*v;
3856:         coords[(v+edges*2)*2+1] = upper[1];
3857:       }
3858:       for(int v = 0; v < edges; ++v) {
3859:         coords[(v+edges*3)*2+0] = lower[0];
3860:         coords[(v+edges*3)*2+1] = upper[1] - ((upper[1] - lower[1])/edges)*v;
3861:       }
3862:       delete [] vertices;
3863:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
3864:       // Build normals for cells
3865:       const Obj<typename Mesh::real_section_type>& normals = mesh->getRealSection("normals");
3866:       const Obj<typename Mesh::label_sequence>&    cells   = mesh->heightStratum(0);

3868:       //normals->setChart(typename Mesh::real_section_type::chart_type(*std::min_element(cells->begin(), cells->end()),
3869:       //                                                               *std::max_element(cells->begin(), cells->end())+1));
3870:       normals->setFiberDimension(cells, mesh->getDimension()+1);
3871:       mesh->allocate(normals);
3872:       for(int e = 0; e < edges; ++e) {
3873:         real normal[2] = {0.0, -1.0};
3874:         normals->updatePoint(e+edges*0, normal);
3875:       }
3876:       for(int e = 0; e < edges; ++e) {
3877:         real normal[2] = {1.0, 0.0};
3878:         normals->updatePoint(e+edges*1, normal);
3879:       }
3880:       for(int e = 0; e < edges; ++e) {
3881:         real normal[2] = {0.0, 1.0};
3882:         normals->updatePoint(e+edges*2, normal);
3883:       }
3884:       for(int e = 0; e < edges; ++e) {
3885:         real normal[2] = {-1.0, 0.0};
3886:         normals->updatePoint(e+edges*3, normal);
3887:       }
3888:       return mesh;
3889:     };
3892:     /*
3893:       Simple square boundary:

3895:      18--5-17--4--16
3896:       |     |     |
3897:       6    10     3
3898:       |     |     |
3899:      19-11-20--9--15
3900:       |     |     |
3901:       7     8     2
3902:       |     |     |
3903:      12--0-13--1--14
3904:     */
3905:     static Obj<Mesh> createParticleInSquareBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int edges[], const real radius, const int partEdges, const int debug = 0) {
3906:       Obj<Mesh> mesh              = new Mesh(comm, 1, debug);
3907:       const int numSquareVertices = (edges[0]+1)*(edges[1]+1);
3908:       const int numVertices       = numSquareVertices + partEdges;
3909:       const int numSquareEdges    = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
3910:       const int numEdges          = numSquareEdges + partEdges;
3911:       real   *coords            = new real[numVertices*2];
3912:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
3913:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];
3914:       int                         order    = 0;

3916:       mesh->setSieve(sieve);
3917:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
3918:       if (mesh->commRank() == 0) {
3919:         /* Create sieve and ordering */
3920:         for(int v = numEdges; v < numEdges+numVertices; v++) {
3921:           vertices[v-numEdges] = typename Mesh::point_type(v);
3922:         }
3923:         // Make square
3924:         for(int vy = 0; vy <= edges[1]; vy++) {
3925:           for(int ex = 0; ex < edges[0]; ex++) {
3926:             typename Mesh::point_type edge(vy*edges[0] + ex);
3927:             int vertex = vy*(edges[0]+1) + ex;

3929:             sieve->addArrow(vertices[vertex+0], edge, order++);
3930:             sieve->addArrow(vertices[vertex+1], edge, order++);
3931:             if ((vy == 0) || (vy == edges[1])) {
3932:               mesh->setValue(markers, edge, 1);
3933:               mesh->setValue(markers, vertices[vertex], 1);
3934:               if (ex == edges[0]-1) {
3935:                 mesh->setValue(markers, vertices[vertex+1], 1);
3936:               }
3937:             }
3938:           }
3939:         }
3940:         for(int vx = 0; vx <= edges[0]; vx++) {
3941:           for(int ey = 0; ey < edges[1]; ey++) {
3942:             typename Mesh::point_type edge(vx*edges[1] + ey + edges[0]*(edges[1]+1));
3943:             int vertex = ey*(edges[0]+1) + vx;

3945:             sieve->addArrow(vertices[vertex],            edge, order++);
3946:             sieve->addArrow(vertices[vertex+edges[0]+1], edge, order++);
3947:             if ((vx == 0) || (vx == edges[0])) {
3948:               mesh->setValue(markers, edge, 1);
3949:               mesh->setValue(markers, vertices[vertex], 1);
3950:               if (ey == edges[1]-1) {
3951:                 mesh->setValue(markers, vertices[vertex+edges[0]+1], 1);
3952:               }
3953:             }
3954:           }
3955:         }
3956:         // Make particle
3957:         for(int ep = 0; ep < partEdges; ++ep) {
3958:           typename Mesh::point_type edge(numSquareEdges + ep);
3959:           const int vertexA = numSquareVertices + ep;
3960:           const int vertexB = numSquareVertices + (ep+1)%partEdges;

3962:           sieve->addArrow(vertices[vertexA], edge, order++);
3963:           sieve->addArrow(vertices[vertexB], edge, order++);
3964:           mesh->setValue(markers, edge, 2);
3965:           mesh->setValue(markers, vertices[vertexA], 2);
3966:           mesh->setValue(markers, vertices[vertexB], 2);
3967:         }
3968:       }
3969:       mesh->stratify();
3970:       for(int vy = 0; vy <= edges[1]; ++vy) {
3971:         for(int vx = 0; vx <= edges[0]; ++vx) {
3972:           coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
3973:           coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
3974:         }
3975:       }
3976:       const real centroidX = 0.5*(upper[0] + lower[0]);
3977:       const real centroidY = 0.5*(upper[1] + lower[1]);
3978:       for(int vp = 0; vp < partEdges; ++vp) {
3979:         const real rad = 2.0*PETSC_PI*vp/partEdges;
3980:         coords[(numSquareVertices+vp)*2+0] = centroidX + radius*cos(rad);
3981:         coords[(numSquareVertices+vp)*2+1] = centroidY + radius*sin(rad);
3982:       }
3983:       delete [] vertices;
3984:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
3985:       return mesh;
3986:     };
3989:     /*
3990:       Simple boundary with reentrant singularity:

3992:      12--5-11
3993:       |     |
3994:       |     4
3995:       |     |
3996:       6    10--3--9
3997:       |           |
3998:       |           2
3999:       |           |
4000:       7-----1-----8
4001:     */
4002:     static Obj<Mesh> createReentrantBoundary(const MPI_Comm comm, const real lower[], const real upper[], real notchpercent[], const int debug = 0) {
4003:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
4004:       int       numVertices = 6;
4005:       int       numEdges    = numVertices;
4006:       real   *coords      = new real[numVertices*2];
4007:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4008:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];

4010:       mesh->setSieve(sieve);
4011:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4012:       if (mesh->commRank() == 0) {
4013:         /* Create sieve and ordering */
4014:         for (int b = 0; b < numVertices; b++) {
4015:           sieve->addArrow(numEdges+b, b);
4016:           sieve->addArrow(numEdges+b, (b+1)%numVertices);
4017:           mesh->setValue(markers, b, 1);
4018:           mesh->setValue(markers, b+numVertices, 1);
4019:         }
4020:         coords[0] = upper[0];
4021:         coords[1] = lower[1];

4023:         coords[2] = lower[0];
4024:         coords[3] = lower[1];

4026:         coords[4] = lower[0];
4027:         coords[5] = notchpercent[1]*lower[1] + (1 - notchpercent[1])*upper[1];

4029:         coords[6] = notchpercent[0]*upper[0] + (1 - notchpercent[0])*lower[0];
4030:         coords[7] = notchpercent[1]*lower[1] + (1 - notchpercent[1])*upper[1];


4033:         coords[8] = notchpercent[0]*upper[0] + (1 - notchpercent[0])*lower[0];
4034:         coords[9] = upper[1];

4036:         coords[10] = upper[0];
4037:         coords[11] = upper[1];
4038:         mesh->stratify();
4039:       }
4040:       delete [] vertices;
4041:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4042:       return mesh;
4043:     }

4047:     /*
4048:       Circular boundary with reentrant singularity:

4050:          ---1
4051:       --    |
4052:      -      |
4053:      |      |
4054:      |      0-----n
4055:      |            |
4056:      -           -
4057:       --       --
4058:         -------
4059:     */
4060:     static Obj<Mesh> createCircularReentrantBoundary(const MPI_Comm comm, const int segments, const real radius, const real arc_percent, const int debug = 0) {
4061:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
4062:       int       numVertices = segments+2;
4063:       int       numEdges    = numVertices;
4064:       real   *coords      = new real[numVertices*2];
4065:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4066:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];

4068:       mesh->setSieve(sieve);
4069:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4070:       if (mesh->commRank() == 0) {
4071:         /* Create sieve and ordering */

4073:         int startvertex = 1;
4074:         if (arc_percent < 1.) {
4075:           coords[0] = 0.;
4076:           coords[1] = 0.;
4077:         } else {
4078:           numVertices = segments;
4079:           numEdges = numVertices;
4080:           startvertex = 0;
4081:         }

4083:         for (int b = 0; b < numVertices; b++) {
4084:           sieve->addArrow(numEdges+b, b);
4085:           sieve->addArrow(numEdges+b, (b+1)%numVertices);
4086:           mesh->setValue(markers, b, 1);
4087:           mesh->setValue(markers, b+numVertices, 1);
4088:         }

4090:         real anglestep = arc_percent*2.*3.14159265/((float)segments);

4092:         for (int i = startvertex; i < numVertices; i++) {
4093:           coords[2*i] = radius * sin(anglestep*(i-startvertex));
4094:           coords[2*i+1] = radius*cos(anglestep*(i-startvertex));
4095:         }
4096:         mesh->stratify();
4097:       }
4098:       delete [] vertices;
4099:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4100:       return mesh;
4101:     };
4104:     static Obj<Mesh> createAnnularBoundary(const MPI_Comm comm, const int segments, const real centers[4], const real radii[2], const int debug = 0) {
4105:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
4106:       int       numVertices = segments*2;
4107:       int       numEdges    = numVertices;
4108:       real   *coords      = new real[numVertices*2];
4109:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4110:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];

4112:       mesh->setSieve(sieve);
4113:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4114:       if (mesh->commRank() == 0) {
4115:         for (int e = 0; e < segments; ++e) {
4116:           sieve->addArrow(numEdges+e,              e);
4117:           sieve->addArrow(numEdges+(e+1)%segments, e);
4118:           sieve->addArrow(numEdges+segments+e,              e+segments);
4119:           sieve->addArrow(numEdges+segments+(e+1)%segments, e+segments);
4120:           mesh->setValue(markers, e,          1);
4121:           mesh->setValue(markers, e+segments, 1);
4122:           mesh->setValue(markers, e+numEdges,          1);
4123:           mesh->setValue(markers, e+numEdges+segments, 1);
4124:         }
4125:         const real anglestep = 2.0*M_PI/segments;

4127:         for (int v = 0; v < segments; ++v) {
4128:           coords[v*2]              = centers[0] + radii[0]*cos(anglestep*v);
4129:           coords[v*2+1]            = centers[1] + radii[0]*sin(anglestep*v);
4130:           coords[(v+segments)*2]   = centers[2] + radii[1]*cos(anglestep*v);
4131:           coords[(v+segments)*2+1] = centers[3] + radii[1]*sin(anglestep*v);
4132:         }
4133:         mesh->addHole(&centers[2]);
4134:       }
4135:       mesh->stratify();
4136:       delete [] vertices;
4137:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4138:       return mesh;
4139:     };
4142:     /*
4143:       Simple cubic boundary:

4145:      30----31-----32
4146:       |     |     |
4147:       |  3  |  2  |
4148:       |     |     |
4149:      27----28-----29
4150:       |     |     |
4151:       |  0  |  1  |
4152:       |     |     |
4153:      24----25-----26
4154:     */
4155:     static Obj<Mesh> createCubeBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int faces[], const int debug = 0) {
4156:       Obj<Mesh> mesh        = new Mesh(comm, 2, debug);
4157:       int       numVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
4158:       int       numFaces    = 6;
4159:       real   *coords      = new real[numVertices*3];
4160:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4161:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];
4162:       int                         order    = 0;

4164:       mesh->setSieve(sieve);
4165:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4166:       if (mesh->commRank() == 0) {
4167:         /* Create sieve and ordering */
4168:         for(int v = numFaces; v < numFaces+numVertices; v++) {
4169:           vertices[v-numFaces] = typename Mesh::point_type(v);
4170:           mesh->setValue(markers, vertices[v-numFaces], 1);
4171:         }
4172:         {
4173:           // Side 0 (Front)
4174:           typename Mesh::point_type face(0);
4175:           sieve->addArrow(vertices[0], face, order++);
4176:           sieve->addArrow(vertices[1], face, order++);
4177:           sieve->addArrow(vertices[2], face, order++);
4178:           sieve->addArrow(vertices[3], face, order++);
4179:           mesh->setValue(markers, face, 1);
4180:         }
4181:         {
4182:           // Side 1 (Back)
4183:           typename Mesh::point_type face(1);
4184:           sieve->addArrow(vertices[5], face, order++);
4185:           sieve->addArrow(vertices[4], face, order++);
4186:           sieve->addArrow(vertices[7], face, order++);
4187:           sieve->addArrow(vertices[6], face, order++);
4188:           mesh->setValue(markers, face, 1);
4189:         }
4190:         {
4191:           // Side 2 (Bottom)
4192:           typename Mesh::point_type face(2);
4193:           sieve->addArrow(vertices[4], face, order++);
4194:           sieve->addArrow(vertices[5], face, order++);
4195:           sieve->addArrow(vertices[1], face, order++);
4196:           sieve->addArrow(vertices[0], face, order++);
4197:           mesh->setValue(markers, face, 1);
4198:         }
4199:         {
4200:           // Side 3 (Top)
4201:           typename Mesh::point_type face(3);
4202:           sieve->addArrow(vertices[3], face, order++);
4203:           sieve->addArrow(vertices[2], face, order++);
4204:           sieve->addArrow(vertices[6], face, order++);
4205:           sieve->addArrow(vertices[7], face, order++);
4206:           mesh->setValue(markers, face, 1);
4207:         }
4208:         {
4209:           // Side 4 (Left)
4210:           typename Mesh::point_type face(4);
4211:           sieve->addArrow(vertices[4], face, order++);
4212:           sieve->addArrow(vertices[0], face, order++);
4213:           sieve->addArrow(vertices[3], face, order++);
4214:           sieve->addArrow(vertices[7], face, order++);
4215:           mesh->setValue(markers, face, 1);
4216:         }
4217:         {
4218:           // Side 5 (Right)
4219:           typename Mesh::point_type face(5);
4220:           sieve->addArrow(vertices[1], face, order++);
4221:           sieve->addArrow(vertices[5], face, order++);
4222:           sieve->addArrow(vertices[6], face, order++);
4223:           sieve->addArrow(vertices[2], face, order++);
4224:           mesh->setValue(markers, face, 1);
4225:         }
4226:       }
4227:       mesh->stratify();
4228: #if 0
4229:       for(int vz = 0; vz <= edges[2]; ++vz) {
4230:         for(int vy = 0; vy <= edges[1]; ++vy) {
4231:           for(int vx = 0; vx <= edges[0]; ++vx) {
4232:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
4233:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
4234:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
4235:           }
4236:         }
4237:       }
4238: #else
4239:       coords[0*3+0] = lower[0];
4240:       coords[0*3+1] = lower[1];
4241:       coords[0*3+2] = upper[2];
4242:       coords[1*3+0] = upper[0];
4243:       coords[1*3+1] = lower[1];
4244:       coords[1*3+2] = upper[2];
4245:       coords[2*3+0] = upper[0];
4246:       coords[2*3+1] = upper[1];
4247:       coords[2*3+2] = upper[2];
4248:       coords[3*3+0] = lower[0];
4249:       coords[3*3+1] = upper[1];
4250:       coords[3*3+2] = upper[2];
4251:       coords[4*3+0] = lower[0];
4252:       coords[4*3+1] = lower[1];
4253:       coords[4*3+2] = lower[2];
4254:       coords[5*3+0] = upper[0];
4255:       coords[5*3+1] = lower[1];
4256:       coords[5*3+2] = lower[2];
4257:       coords[6*3+0] = upper[0];
4258:       coords[6*3+1] = upper[1];
4259:       coords[6*3+2] = lower[2];
4260:       coords[7*3+0] = lower[0];
4261:       coords[7*3+1] = upper[1];
4262:       coords[7*3+2] = lower[2];
4263: #endif
4264:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4265:       return mesh;
4266:     };

4268:     // Creates a triangular prism boundary
4269:     static Obj<Mesh> createPrismBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int debug = 0) {
4270:       Obj<Mesh> mesh        = new Mesh(comm, 2, debug);
4271:       int       numVertices = 6;
4272:       int       numFaces    = 5;
4273:       real   *coords      = new real[numVertices*3];
4274:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4275:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];
4276:       int                         order    = 0;

4278:       mesh->setSieve(sieve);
4279:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4280:       if (mesh->commRank() == 0) {
4281:         /* Create sieve and ordering */
4282:         for(int v = numFaces; v < numFaces+numVertices; v++) {
4283:           vertices[v-numFaces] = typename Mesh::point_type(v);
4284:           mesh->setValue(markers, vertices[v-numFaces], 1);
4285:         }
4286:         {
4287:           // Side 0 (Top)
4288:           typename Mesh::point_type face(0);
4289:           sieve->addArrow(vertices[0], face, order++);
4290:           sieve->addArrow(vertices[1], face, order++);
4291:           sieve->addArrow(vertices[2], face, order++);
4292:           mesh->setValue(markers, face, 1);
4293:         }
4294:         {
4295:           // Side 1 (Bottom)
4296:           typename Mesh::point_type face(1);
4297:           sieve->addArrow(vertices[3], face, order++);
4298:           sieve->addArrow(vertices[5], face, order++);
4299:           sieve->addArrow(vertices[4], face, order++);
4300:           mesh->setValue(markers, face, 1);
4301:         }
4302:         {
4303:           // Side 2 (Front)
4304:           typename Mesh::point_type face(2);
4305:           sieve->addArrow(vertices[0], face, order++);
4306:           sieve->addArrow(vertices[3], face, order++);
4307:           sieve->addArrow(vertices[4], face, order++);
4308:           sieve->addArrow(vertices[1], face, order++);
4309:           mesh->setValue(markers, face, 1);
4310:         }
4311:         {
4312:           // Side 3 (Left)
4313:           typename Mesh::point_type face(3);
4314:           sieve->addArrow(vertices[1], face, order++);
4315:           sieve->addArrow(vertices[4], face, order++);
4316:           sieve->addArrow(vertices[5], face, order++);
4317:           sieve->addArrow(vertices[2], face, order++);
4318:           mesh->setValue(markers, face, 1);
4319:         }
4320:         {
4321:           // Side 4 (Right)
4322:           typename Mesh::point_type face(4);
4323:           sieve->addArrow(vertices[2], face, order++);
4324:           sieve->addArrow(vertices[5], face, order++);
4325:           sieve->addArrow(vertices[3], face, order++);
4326:           sieve->addArrow(vertices[0], face, order++);
4327:           mesh->setValue(markers, face, 1);
4328:         }
4329:       }
4330:       mesh->stratify();
4331:       coords[0*3+0] = lower[0];
4332:       coords[0*3+1] = lower[1];
4333:       coords[0*3+2] = upper[2];
4334:       coords[1*3+0] = upper[0];
4335:       coords[1*3+1] = lower[1];
4336:       coords[1*3+2] = upper[2];
4337:       coords[2*3+0] = upper[0];
4338:       coords[2*3+1] = upper[1];
4339:       coords[2*3+2] = upper[2];
4340:       coords[3*3+0] = lower[0];
4341:       coords[3*3+1] = upper[1];
4342:       coords[3*3+2] = upper[2];
4343:       coords[4*3+0] = lower[0];
4344:       coords[4*3+1] = lower[1];
4345:       coords[4*3+2] = lower[2];
4346:       coords[5*3+0] = upper[0];
4347:       coords[5*3+1] = lower[1];
4348:       coords[5*3+2] = lower[2];
4349:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4350:       return mesh;
4351:     };

4355:     /*    v0
4356:          / \
4357:         /   \
4358:     2  /  4  \  1
4359:       /       \
4360:      /   v12   \
4361:   v6|\   /|\   /|v5
4362:     | \v8 | v7/ |          z
4363:     |  |7 |8 |  |          |
4364:     |  |v13\ |  |  <-v4   / \
4365:     | v9/ 9 \v10|        x   y
4366:  v1 | 5 \   / 6 |v2
4367:      \   \ /   /
4368:       \  v11  /
4369:        \  |  /
4370:      3  \ | /
4371:          \|/
4372:           v3
4373:     */
4374:     static Obj<Mesh> createFicheraCornerBoundary(const MPI_Comm comm, const real lower[], const real upper[], const real offset[], const int debug = 0) {
4375:       Obj<Mesh> mesh            = new Mesh(comm, 2, debug);
4376:       const int nVertices = 14;
4377:       const int nFaces = 12;
4378:       real ilower[3];
4379:       ilower[0] = lower[0]*(1. - offset[0]) + upper[0]*offset[0];
4380:       ilower[1] = lower[1]*(1. - offset[1]) + upper[1]*offset[1];
4381:       ilower[2] = lower[2]*(1. - offset[2]) + upper[2]*offset[2];
4382:       real coords[nVertices*3];
4383:       //outer square-triplet
4384:       coords[0*3+0] = lower[0];
4385:       coords[0*3+1] = lower[1];
4386:       coords[0*3+2] = upper[2];
4387:       coords[1*3+0] = upper[0];
4388:       coords[1*3+1] = lower[1];
4389:       coords[1*3+2] = lower[2];
4390:       coords[2*3+0] = lower[0];
4391:       coords[2*3+1] = upper[1];
4392:       coords[2*3+2] = lower[2];
4393:       coords[3*3+0] = upper[0];
4394:       coords[3*3+1] = upper[1];
4395:       coords[3*3+2] = lower[2];
4396:       coords[4*3+0] = lower[0];
4397:       coords[4*3+1] = lower[1];
4398:       coords[4*3+2] = lower[2];
4399:       coords[5*3+0] = lower[0];
4400:       coords[5*3+1] = upper[1];
4401:       coords[5*3+2] = upper[2];
4402:       coords[6*3+0] = upper[0];
4403:       coords[6*3+1] = lower[1];
4404:       coords[6*3+2] = upper[2];

4406:       //inner square-triplet
4407:       coords[7*3+0] = ilower[0];
4408:       coords[7*3+1] = upper[1];
4409:       coords[7*3+2] = upper[2];
4410:       coords[8*3+0] = upper[0];
4411:       coords[8*3+1] = ilower[1];
4412:       coords[8*3+2] = upper[2];
4413:       coords[9*3+0] = upper[0];
4414:       coords[9*3+1] = ilower[1];
4415:       coords[9*3+2] = ilower[2];
4416:       coords[10*3+0] = ilower[0];
4417:       coords[10*3+1] = upper[1];
4418:       coords[10*3+2] = ilower[2];
4419:       coords[11*3+0] = upper[0];
4420:       coords[11*3+1] = upper[1];
4421:       coords[11*3+2] = ilower[2];
4422:       coords[12*3+0] = ilower[0];
4423:       coords[12*3+1] = ilower[1];
4424:       coords[12*3+2] = upper[2];
4425:       coords[13*3+0] = ilower[0];
4426:       coords[13*3+1] = ilower[1];
4427:       coords[13*3+2] = ilower[2];


4430:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4431:       mesh->setSieve(sieve);
4432:       typename Mesh::point_type p[nVertices];
4433:       typename Mesh::point_type f[nFaces];
4434:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4435:       for (int i = 0; i < nVertices; i++) {
4436:         p[i] = typename Mesh::point_type(i+nFaces);
4437:         mesh->setValue(markers, p[i], 1);
4438:       }
4439:       for (int i = 0; i < nFaces; i++) {
4440:         f[i] = typename Mesh::point_type(i);
4441:       }
4442:       int order = 0;
4443:      //assemble the larger square sides
4444:       sieve->addArrow(p[0], f[0], order++);
4445:       sieve->addArrow(p[5], f[0], order++);
4446:       sieve->addArrow(p[2], f[0], order++);
4447:       sieve->addArrow(p[4], f[0], order++);
4448:       mesh->setValue(markers, f[0], 1);

4450:       sieve->addArrow(p[0], f[1], order++);
4451:       sieve->addArrow(p[4], f[1], order++);
4452:       sieve->addArrow(p[1], f[1], order++);
4453:       sieve->addArrow(p[6], f[1], order++);
4454:       mesh->setValue(markers, f[1], 1);

4456:       sieve->addArrow(p[4], f[2], order++);
4457:       sieve->addArrow(p[1], f[2], order++);
4458:       sieve->addArrow(p[3], f[2], order++);
4459:       sieve->addArrow(p[2], f[2], order++);
4460:       mesh->setValue(markers, f[2], 1);

4462:       //assemble the L-shaped sides

4464:       sieve->addArrow(p[0], f[3], order++);
4465:       sieve->addArrow(p[12], f[3], order++);
4466:       sieve->addArrow(p[7], f[3], order++);
4467:       sieve->addArrow(p[5], f[3], order++);
4468:       mesh->setValue(markers, f[3], 1);

4470:       sieve->addArrow(p[0], f[4], order++);
4471:       sieve->addArrow(p[12],f[4], order++);
4472:       sieve->addArrow(p[8], f[4], order++);
4473:       sieve->addArrow(p[6], f[4], order++);
4474:       mesh->setValue(markers, f[4], 1);

4476:       sieve->addArrow(p[9], f[5], order++);
4477:       sieve->addArrow(p[1], f[5], order++);
4478:       sieve->addArrow(p[3], f[5], order++);
4479:       sieve->addArrow(p[11], f[5], order++);
4480:       mesh->setValue(markers, f[5], 1);

4482:       sieve->addArrow(p[9], f[6], order++);
4483:       sieve->addArrow(p[1], f[6], order++);
4484:       sieve->addArrow(p[6], f[6], order++);
4485:       sieve->addArrow(p[8], f[6], order++);
4486:       mesh->setValue(markers, f[6], 1);

4488:       sieve->addArrow(p[10], f[7], order++);
4489:       sieve->addArrow(p[2], f[7], order++);
4490:       sieve->addArrow(p[5], f[7], order++);
4491:       sieve->addArrow(p[7], f[7], order++);
4492:       mesh->setValue(markers, f[7], 1);

4494:       sieve->addArrow(p[10], f[8], order++);
4495:       sieve->addArrow(p[2], f[8], order++);
4496:       sieve->addArrow(p[3], f[8], order++);
4497:       sieve->addArrow(p[11], f[8], order++);
4498:       mesh->setValue(markers, f[8], 1);

4500:       //assemble the smaller square sides

4502:       sieve->addArrow(p[13], f[9], order++);
4503:       sieve->addArrow(p[10], f[9], order++);
4504:       sieve->addArrow(p[11], f[9], order++);
4505:       sieve->addArrow(p[9], f[9], order++);
4506:       mesh->setValue(markers, f[9], 1);

4508:       sieve->addArrow(p[12], f[10], order++);
4509:       sieve->addArrow(p[7], f[10], order++);
4510:       sieve->addArrow(p[10], f[10], order++);
4511:       sieve->addArrow(p[13], f[10], order++);
4512:       mesh->setValue(markers, f[10], 1);

4514:       sieve->addArrow(p[8], f[11], order++);
4515:       sieve->addArrow(p[12], f[11], order++);
4516:       sieve->addArrow(p[13], f[11], order++);
4517:       sieve->addArrow(p[9], f[11], order++);
4518:       mesh->setValue(markers, f[11], 1);

4520:       mesh->stratify();
4521:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4522:       Obj<typename Mesh::real_section_type> coordinates = mesh->getRealSection("coordinates");
4523:       //coordinates->view("coordinates");
4524:       return mesh;

4526:     }

4530:     /*
4531:       //"sphere" out a cube

4533:     */
4534: #if 0
4535:     static Obj<Mesh> createSphereBoundary(const MPI_Comm comm, const real radius, const int refinement, const int debug = 0) {
4536:       Obj<Mesh> m = new Mesh(comm, 2, debug);
4537:       Obj<Mesh::sieve_type> s = new Mesh::sieve_type(comm, debug);
4538:       m->setSieve(s);
4539:       Mesh::point_type p = 0;
4540:       int nVertices = 8+12*(refinement)+6*(refinement)*(refinement);
4541:       Mesh::point_type vertices[nVertices];
4542:       real coords[3*nVertices];
4543:       int nCells = 6*2*(refinement+1)*(refinement+1);
4544:       real delta = 2./((real)(refinement+1));
4545:       Mesh::point_type cells[nCells];
4546:       for (int i = 0; i < nCells; i++) {
4547:         cells[i] = p;
4548:         p++;
4549:       }
4550:       for (int i = 0; i < nVertices; i++) {
4551:         vertices[i] = p;
4552:         p++;
4553:       }
4554:       //set up the corners;
4555:       //lll
4556:       coords[0*3+0] = -1.;
4557:       coords[0*3+1] = -1.;
4558:       coords[0*3+2] = -1.;
4559:       //llh
4560:       coords[1*3+0] = -1.;
4561:       coords[1*3+1] = -1.;
4562:       coords[1*3+2] = 1.;
4563:       //lhh
4564:       coords[2*3+0] = -1.;
4565:       coords[2*3+1] = 1.;
4566:       coords[2*3+2] = 1.;
4567:       //lhl
4568:       coords[3*3+0] = -1.;
4569:       coords[3*3+1] = 1.;
4570:       coords[3*3+2] = -1.;
4571:       //hhl
4572:       coords[4*3+0] = 1.;
4573:       coords[4*3+1] = 1.;
4574:       coords[4*3+2] = -1.;
4575:       //hhh
4576:       coords[5*3+0] = 1.;
4577:       coords[5*3+1] = 1.;
4578:       coords[5*3+2] = 1.;
4579:       //hlh
4580:       coords[6*3+0] = 1.;
4581:       coords[6*3+1] = -1.;
4582:       coords[6*3+2] = 1.;
4583:       //hll
4584:       coords[7*3+0] = 1.;
4585:       coords[7*3+1] = -1.;
4586:       coords[7*3+2] = -1.;
4587:       //set up the edges (always go low to high)
4588:       //xll
4589:       for (int i = 0; i < refinement; i++) {
4590:         coords[3*(8+0*refinement+i)+0] = -1. + delta*i;
4591:         coords[3*(8+0*refinement+i)+1] = -1.;
4592:         coords[3*(8+0*refinement+i)+2] = -1.;
4593:       }
4594:       //xlh
4595:       for (int i = 0; i < refinement; i++) {
4596:         coords[3*(8+1*refinement+i)+0] = -1. + delta*i;
4597:         coords[3*(8+1*refinement+i)+1] = -1.;
4598:         coords[3*(8+1*refinement+i)+2] = 1.;
4599:       }
4600:       //xhh
4601:       for (int i = 0; i < refinement; i++) {
4602:         coords[3*(8+2*refinement+i)+0] = -1. + delta*i;
4603:         coords[3*(8+2*refinement+i)+1] = 1.;
4604:         coords[3*(8+2*refinement+i)+2] = 1.;
4605:       }
4606:       //xhl
4607:       for (int i = 0; i < refinement; i++) {
4608:         coords[3*(8+3*refinement+i)+0] = -1. + delta*i;
4609:         coords[3*(8+3*refinement+i)+1] = 1.;
4610:         coords[3*(8+3*refinement+i)+2] = -1.;
4611:       }
4612:       //lxl
4613:       for (int i = 0; i < refinement; i++) {
4614:         coords[3*(8+4*refinement+i)+0] = -1.;
4615:         coords[3*(8+4*refinement+i)+1] = -1. + delta*i;
4616:         coords[3*(8+4*refinement+i)+2] = -1.;
4617:       }
4618:       //lxh
4619:       for (int i = 0; i < refinement; i++) {
4620:         coords[3*(8+5*refinement+i)+0] = -1.;
4621:         coords[3*(8+5*refinement+i)+1] = -1. + delta*i;
4622:         coords[3*(8+5*refinement+i)+2] = 1.;
4623:       }
4624:       //hxh
4625:       for (int i = 0; i < refinement; i++) {
4626:         coords[3*(8+6*refinement+i)+0] = 1.;
4627:         coords[3*(8+6*refinement+i)+1] = -1. + delta*i;
4628:         coords[3*(8+6*refinement+i)+2] = 1.;
4629:       }
4630:       //hxl
4631:       for (int i = 0; i < refinement; i++) {
4632:         coords[3*(8+7*refinement+i)+0] = 1.;
4633:         coords[3*(8+7*refinement+i)+1] = -1. + delta*i;
4634:         coords[3*(8+7*refinement+i)+2] = -1.;
4635:       }
4636:       //llx
4637:       for (int i = 0; i < refinement; i++) {
4638:         coords[3*(8+8*refinement+i)+0] = -1.;
4639:         coords[3*(8+8*refinement+i)+1] = -1.;
4640:         coords[3*(8+8*refinement+i)+2] = -1. + delta*i;
4641:       }
4642:       //lhx
4643:       for (int i = 0; i < refinement; i++) {
4644:         coords[3*(8+9*refinement+i)+0] = -1.;
4645:         coords[3*(8+9*refinement+i)+1] = 1.;
4646:         coords[3*(8+9*refinement+i)+2] = -1. + delta*i;
4647:       }
4648:       //hhx
4649:       for (int i = 0; i < refinement; i++) {
4650:         coords[3*(8+10*refinement+i)+0] = 1.;
4651:         coords[3*(8+10*refinement+i)+1] = 1.;
4652:         coords[3*(8+10*refinement+i)+2] = -1. + delta*i;
4653:       }
4654:       //hlx
4655:       for (int i = 0; i < refinement; i++) {
4656:         coords[3*(8+11*refinement+i)+0] = 1.;
4657:         coords[3*(8+11*refinement+i)+1] = -1.;
4658:         coords[3*(8+11*refinement+i)+2] = -1. + delta*i;
4659:       }
4660:       //set up the faces
4661:       //lxx
4662:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4663:         coords[3*(8+12*refinement+0*refinement*refinement+i*refinement+j)+0] = -1.;
4664:         coords[3*(8+12*refinement+0*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4665:         coords[3*(8+12*refinement+0*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4666:       }
4667:       //hxx
4668:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4669:         coords[3*(8+12*refinement+1*refinement*refinement+i*refinement+j)+0] = 1.;
4670:         coords[3*(8+12*refinement+1*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4671:         coords[3*(8+12*refinement+1*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4672:       }
4673:       //xlx
4674:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4675:         coords[3*(8+12*refinement+2*refinement*refinement+i*refinement+j)+0] = -1. + delta*j;
4676:         coords[3*(8+12*refinement+2*refinement*refinement+i*refinement+j)+1] = -1.;
4677:         coords[3*(8+12*refinement+2*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4678:       }
4679:       //xhx
4680:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4681:         coords[3*(8+12*refinement+3*refinement*refinement+i*refinement+j)+0] = -1. + delta*j;
4682:         coords[3*(8+12*refinement+3*refinement*refinement+i*refinement+j)+1] = 1.;
4683:         coords[3*(8+12*refinement+3*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4684:       }
4685:       //xxl
4686:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4687:         coords[3*(8+12*refinement+4*refinement*refinement+i*refinement+j)+0] = -1.;
4688:         coords[3*(8+12*refinement+4*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4689:         coords[3*(8+12*refinement+4*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4690:       }
4691:       //xxh
4692:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4693:         coords[3*(8+12*refinement+5*refinement*refinement+i*refinement+j)+0] = 1.;
4694:         coords[3*(8+12*refinement+5*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4695:         coords[3*(8+12*refinement+5*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4696:       }
4697:       //stitch the corners up with the edges and the faces

4699:       //stitch the edges to the faces
4700:       //fill in the faces
4701:       int face_offset = 8 + 12*refinement;
4702:       for (int i = 0; i < 6; i++) for (int j = 0; j < refinement; j++) for (int k = 0; k < refinement; k++) {
4703:         //build each square doublet
4704:       }
4705:     }

4707: #endif

4711:     /*
4712:       Simple cubic boundary:

4714:      30----31-----32
4715:       |     |     |
4716:       |  3  |  2  |
4717:       |     |     |
4718:      27----28-----29
4719:       |     |     |
4720:       |  0  |  1  |
4721:       |     |     |
4722:      24----25-----26
4723:     */
4724:     static Obj<Mesh> createParticleInCubeBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int faces[], const real radius, const int thetaEdges, const int phiSlices, const int debug = 0) {
4725:       Obj<Mesh> mesh            = new Mesh(comm, 2, debug);
4726:       const int numCubeVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
4727:       const int numPartVertices = (thetaEdges - 1)*phiSlices + 2;
4728:       const int numVertices     = numCubeVertices + numPartVertices;
4729:       const int numCubeFaces    = 6;
4730:       const int numFaces        = numCubeFaces + thetaEdges*phiSlices;
4731:       real   *coords          = new real[numVertices*3];
4732:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4733:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];
4734:       int                         order    = 0;

4736:       mesh->setSieve(sieve);
4737:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4738:       if (mesh->commRank() == 0) {
4739:         // Make cube
4740:         for(int v = numFaces; v < numFaces+numVertices; v++) {
4741:           vertices[v-numFaces] = typename Mesh::point_type(v);
4742:           mesh->setValue(markers, vertices[v-numFaces], 1);
4743:         }
4744:         {
4745:           // Side 0 (Front)
4746:           typename Mesh::point_type face(0);
4747:           sieve->addArrow(vertices[0], face, order++);
4748:           sieve->addArrow(vertices[1], face, order++);
4749:           sieve->addArrow(vertices[2], face, order++);
4750:           sieve->addArrow(vertices[3], face, order++);
4751:           mesh->setValue(markers, face, 1);
4752:         }
4753:         {
4754:           // Side 1 (Back)
4755:           typename Mesh::point_type face(1);
4756:           sieve->addArrow(vertices[5], face, order++);
4757:           sieve->addArrow(vertices[4], face, order++);
4758:           sieve->addArrow(vertices[7], face, order++);
4759:           sieve->addArrow(vertices[6], face, order++);
4760:           mesh->setValue(markers, face, 1);
4761:         }
4762:         {
4763:           // Side 2 (Bottom)
4764:           typename Mesh::point_type face(2);
4765:           sieve->addArrow(vertices[4], face, order++);
4766:           sieve->addArrow(vertices[5], face, order++);
4767:           sieve->addArrow(vertices[1], face, order++);
4768:           sieve->addArrow(vertices[0], face, order++);
4769:           mesh->setValue(markers, face, 1);
4770:         }
4771:         {
4772:           // Side 3 (Top)
4773:           typename Mesh::point_type face(3);
4774:           sieve->addArrow(vertices[3], face, order++);
4775:           sieve->addArrow(vertices[2], face, order++);
4776:           sieve->addArrow(vertices[6], face, order++);
4777:           sieve->addArrow(vertices[7], face, order++);
4778:           mesh->setValue(markers, face, 1);
4779:         }
4780:         {
4781:           // Side 4 (Left)
4782:           typename Mesh::point_type face(4);
4783:           sieve->addArrow(vertices[4], face, order++);
4784:           sieve->addArrow(vertices[0], face, order++);
4785:           sieve->addArrow(vertices[3], face, order++);
4786:           sieve->addArrow(vertices[7], face, order++);
4787:           mesh->setValue(markers, face, 1);
4788:         }
4789:         {
4790:           // Side 5 (Right)
4791:           typename Mesh::point_type face(5);
4792:           sieve->addArrow(vertices[1], face, order++);
4793:           sieve->addArrow(vertices[5], face, order++);
4794:           sieve->addArrow(vertices[6], face, order++);
4795:           sieve->addArrow(vertices[2], face, order++);
4796:           mesh->setValue(markers, face, 1);
4797:         }
4798:         // Make particle
4799:         for(int s = 0; s < phiSlices; ++s) {
4800:           for(int ep = 0; ep < thetaEdges; ++ep) {
4801:             // Vertices on each slice are 0..thetaEdges
4802:             typename Mesh::point_type face(numCubeFaces + s*thetaEdges + ep);
4803:             int vertexA = numCubeVertices + ep + 0 +     s*(thetaEdges+1);
4804:             int vertexB = numCubeVertices + ep + 1 +     s*(thetaEdges+1);
4805:             int vertexC = numCubeVertices + (ep + 1 + (s+1)*(thetaEdges+1))%((thetaEdges+1)*phiSlices);
4806:             int vertexD = numCubeVertices + (ep + 0 + (s+1)*(thetaEdges+1))%((thetaEdges+1)*phiSlices);
4807:             const int correction1 = (s > 0)*((s-1)*2 + 1);
4808:             const int correction2 = (s < phiSlices-1)*(s*2 + 1);

4810:             if ((vertexA - numCubeVertices)%(thetaEdges+1) == 0) {
4811:               vertexA = vertexD = numCubeVertices;
4812:               vertexB -= correction1;
4813:               vertexC -= correction2;
4814:             } else if ((vertexB - numCubeVertices)%(thetaEdges+1) == thetaEdges) {
4815:               vertexA -= correction1;
4816:               vertexD -= correction2;
4817:               vertexB = vertexC = numCubeVertices + thetaEdges;
4818:             } else {
4819:               vertexA -= correction1;
4820:               vertexB -= correction1;
4821:               vertexC -= correction2;
4822:               vertexD -= correction2;
4823:             }
4824:             if ((vertexA >= numVertices) || (vertexB >= numVertices) || (vertexC >= numVertices) || (vertexD >= numVertices)) {
4825:               throw ALE::Exception("Bad vertex");
4826:             }
4827:             sieve->addArrow(vertices[vertexA], face, order++);
4828:             sieve->addArrow(vertices[vertexB], face, order++);
4829:             if (vertexB != vertexC) sieve->addArrow(vertices[vertexC], face, order++);
4830:             if (vertexA != vertexD) sieve->addArrow(vertices[vertexD], face, order++);
4831:             mesh->setValue(markers, face, 2);
4832:             mesh->setValue(markers, vertices[vertexA], 2);
4833:             mesh->setValue(markers, vertices[vertexB], 2);
4834:             if (vertexB != vertexC) mesh->setValue(markers, vertices[vertexC], 2);
4835:             if (vertexA != vertexD) mesh->setValue(markers, vertices[vertexD], 2);
4836:           }
4837:         }
4838:       }
4839:       mesh->stratify();
4840: #if 0
4841:       for(int vz = 0; vz <= edges[2]; ++vz) {
4842:         for(int vy = 0; vy <= edges[1]; ++vy) {
4843:           for(int vx = 0; vx <= edges[0]; ++vx) {
4844:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
4845:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
4846:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
4847:           }
4848:         }
4849:       }
4850: #else
4851:       coords[0*3+0] = lower[0];
4852:       coords[0*3+1] = lower[1];
4853:       coords[0*3+2] = upper[2];
4854:       coords[1*3+0] = upper[0];
4855:       coords[1*3+1] = lower[1];
4856:       coords[1*3+2] = upper[2];
4857:       coords[2*3+0] = upper[0];
4858:       coords[2*3+1] = upper[1];
4859:       coords[2*3+2] = upper[2];
4860:       coords[3*3+0] = lower[0];
4861:       coords[3*3+1] = upper[1];
4862:       coords[3*3+2] = upper[2];
4863:       coords[4*3+0] = lower[0];
4864:       coords[4*3+1] = lower[1];
4865:       coords[4*3+2] = lower[2];
4866:       coords[5*3+0] = upper[0];
4867:       coords[5*3+1] = lower[1];
4868:       coords[5*3+2] = lower[2];
4869:       coords[6*3+0] = upper[0];
4870:       coords[6*3+1] = upper[1];
4871:       coords[6*3+2] = lower[2];
4872:       coords[7*3+0] = lower[0];
4873:       coords[7*3+1] = upper[1];
4874:       coords[7*3+2] = lower[2];
4875: #endif
4876:       const real centroidX = 0.5*(upper[0] + lower[0]);
4877:       const real centroidY = 0.5*(upper[1] + lower[1]);
4878:       const real centroidZ = 0.5*(upper[2] + lower[2]);
4879:       for(int s = 0; s < phiSlices; ++s) {
4880:         for(int v = 0; v <= thetaEdges; ++v) {
4881:           int          vertex  = numCubeVertices + v + s*(thetaEdges+1);
4882:           const real theta   = v*(PETSC_PI/thetaEdges);
4883:           const real phi     = s*(2.0*PETSC_PI/phiSlices);
4884:           const int correction = (s > 0)*((s-1)*2 + 1);

4886:           if ((vertex- numCubeVertices)%(thetaEdges+1) == 0) {
4887:             vertex = numCubeVertices;
4888:           } else if ((vertex - numCubeVertices)%(thetaEdges+1) == thetaEdges) {
4889:             vertex = numCubeVertices + thetaEdges;
4890:           } else {
4891:             vertex -= correction;
4892:           }
4893:           coords[vertex*3+0] = centroidX + radius*sin(theta)*cos(phi);
4894:           coords[vertex*3+1] = centroidY + radius*sin(theta)*sin(phi);
4895:           coords[vertex*3+2] = centroidZ + radius*cos(theta);
4896:         }
4897:       }
4898:       delete [] vertices;
4899:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4900:       return mesh;
4901:     };

4903: #if 0 // WORKING ON REDESIGN WITHIN PYLITH SOURCE TREE
4904:     template<typename MeshType, typename EdgeType>
4905:     class CellRefiner {
4906:     public:
4907:       typedef typename MeshType::point_type point_type;
4908:       typedef EdgeType                      edge_type;
4909:       typedef typename std::map<edge_type, point_type> edge_map_type;
4910:       typedef enum {LINE, LINE_LAGRANGE, TRIANGLE, QUADRILATERAL, TETRAHEDRON, HEXAHEDRON, TRIANGULAR_PRISM, TRIANGULAR_PRISM_LAGRANGE, HEXAHEDRON_LAGRANGE} CellType;
4911:     protected:
4912:       MeshType&     _mesh;
4913:       int           _dim;
4914:       point_type    _vertexOffset;
4915:       edge_map_type _edge2vertex;
4916:     public:
4917:       CellRefiner(MeshType& mesh) : _mesh(mesh) {
4918:         _dim = _mesh.getDimension();
4919:       };
4920:       ~CellRefiner() {};
4921:     protected:
4922:       CellType getCellType(const point_type cell) {
4923:         const int corners = _mesh.getSieve()->getConeSize(cell);
4924:         switch (_dim) {
4925:           return LINE;
4926:         case 2:
4927:           switch (corners) {
4928:           case 3:
4929:             return TRIANGLE;
4930:           case 4:
4931:             throw ALE::Exception("Not implemented.");
4932:             return QUADRILATERAL;
4933:           case 6:
4934:             return LINE_LAGRANGE;
4935:           case 0: {
4936:             std::ostringstream msg;
4937:             std::cerr << "Internal error. Cone size for mesh point " << cell << " is zero. May be a vertex.";
4938:             assert(0);
4939:             throw ALE::Exception("Could not determine 2-D cell type.");
4940:           } // case 0
4941:           default : {
4942:             std::ostringstream msg;
4943:             std::cerr << "Internal error. Unknown cone size for mesh point " << cell << ". Unknown cell type.";
4944:             assert(0);
4945:             throw ALE::Exception("Could not determine 2-D cell type.");
4946:           } // default
4947:           } // switch
4948:         case 3:
4949:           switch (corners) {
4950:           case 4:
4951:             return TETRAHEDRON;
4952:           case 6:
4953:             return TRIANGULAR_PRISM;
4954:           case 9:
4955:             return TRIANGULAR_PRISM_LAGRANGE;
4956:           case 12:
4957:             throw ALE::Exception("Not implemented.");
4958:             return HEXAHEDRON_LAGRANGE;
4959:           case 0: {
4960:             std::ostringstream msg;
4961:             std::cerr << "Internal error. Cone size for mesh point " << cell << " is zero. May be a vertex.";
4962:             assert(0);
4963:             throw ALE::Exception("Could not determine 3-D cell type.");
4964:           } // case 0
4965:           default : {
4966:             std::ostringstream msg;
4967:             std::cerr << "Internal error. Unknown cone size for mesh point " << cell << ". Unknown cell type.";
4968:             assert(0);
4969:             throw ALE::Exception("Could not determine 3-D cell type.");
4970:           } // default
4971:           } // switch
4972:         } // switch
4973:       };
4974:       void getEdges_TRIANGLE(const int coneSize, const point_type cone[],  int *numEdges, const edge_type **edges) {
4975:         static edge_type triEdges[3];

4977:         assert(coneSize == 3);
4978:         triEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4979:         triEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
4980:         triEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
4981:         *numEdges = 3;
4982:         *edges    = triEdges;
4983:       };
4984:       void getEdges_LINE_LAGRANGE(const int coneSize, const point_type cone[],  int *numEdges, const edge_type **edges) {
4985:         static edge_type lineEdges[6];

4987:         assert(coneSize == 6);
4988:         lineEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4989:         lineEdges[1] = edge_type(std::min(cone[2], cone[3]), std::max(cone[2], cone[3]));
4990:         lineEdges[2] = edge_type(std::min(cone[4], cone[5]), std::max(cone[4], cone[5]));
4991:         *numEdges = 3;
4992:         *edges    = lineEdges;
4993:       };
4994:       void getEdges_TETRAHEDRON(const int coneSize, const point_type cone[],  int *numEdges, const edge_type **edges) {
4995:         static edge_type tetEdges[6];

4997:         assert(coneSize == 4);
4998:         // As per Brad's diagram
4999:         tetEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
5000:         tetEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
5001:         tetEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
5002:         tetEdges[3] = edge_type(std::min(cone[0], cone[3]), std::max(cone[0], cone[3]));
5003:         tetEdges[4] = edge_type(std::min(cone[1], cone[3]), std::max(cone[1], cone[3]));
5004:         tetEdges[5] = edge_type(std::min(cone[2], cone[3]), std::max(cone[2], cone[3]));
5005:         *numEdges = 6;
5006:         *edges    = tetEdges;
5007:       };
5008:       void getEdges_TRIANGULAR_PRISM(const int coneSize, const point_type cone[],  int *numEdges, const edge_type **edges) {
5009:         static edge_type triPrismEdges[6];

5011:         assert(coneSize == 6);
5012:         triPrismEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
5013:         triPrismEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
5014:         triPrismEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
5015:         triPrismEdges[3] = edge_type(std::min(cone[3], cone[4]), std::max(cone[3], cone[4]));
5016:         triPrismEdges[4] = edge_type(std::min(cone[4], cone[5]), std::max(cone[4], cone[5]));
5017:         triPrismEdges[5] = edge_type(std::min(cone[5], cone[3]), std::max(cone[5], cone[3]));
5018:         *numEdges = 6;
5019:         *edges    = triPrismEdges;
5020:       };
5021:       void getEdges_TRIANGULAR_PRISM_LAGRANGE(const int coneSize, const point_type cone[],  int *numEdges, const edge_type **edges) {
5022:         static edge_type triPrismLEdges[9];

5024:         assert(coneSize == 9);
5025:         triPrismLEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
5026:         triPrismLEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
5027:         triPrismLEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
5028:         triPrismLEdges[3] = edge_type(std::min(cone[3], cone[4]), std::max(cone[3], cone[4]));
5029:         triPrismLEdges[4] = edge_type(std::min(cone[4], cone[5]), std::max(cone[4], cone[5]));
5030:         triPrismLEdges[5] = edge_type(std::min(cone[5], cone[3]), std::max(cone[5], cone[3]));
5031:         triPrismLEdges[6] = edge_type(std::min(cone[6], cone[7]), std::max(cone[6], cone[7]));
5032:         triPrismLEdges[7] = edge_type(std::min(cone[7], cone[8]), std::max(cone[7], cone[8]));
5033:         triPrismLEdges[8] = edge_type(std::min(cone[8], cone[6]), std::max(cone[8], cone[6]));
5034:         *numEdges = 9;
5035:         *edges    = triPrismLEdges;
5036:       };
5037:       void getNewCells_TRIANGLE(const int coneSize, const point_type cone[],  int *numCells, const point_type **cells) {
5038:         int               numEdges;
5039:         const edge_type  *edges;
5040:         static point_type triCells[4*3];
5041:         point_type        newVertices[3];

5043:         getEdges_TRIANGLE(coneSize, cone, &numEdges, &edges);
5044:         assert(numEdges == 3);
5045:         for(int e = 0; e < numEdges; ++e) {
5046:           if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5047:             throw ALE::Exception("Missing edge in refined mesh");
5048:           }
5049:           newVertices[e] = _edge2vertex[edges[e]];
5050:         }
5051:         triCells[0*3+0] = cone[0]+_vertexOffset; triCells[0*3+1] = newVertices[0]; triCells[0*3+2] = newVertices[2];
5052:         triCells[1*3+0] = newVertices[0];       triCells[1*3+1] = newVertices[1]; triCells[1*3+2] = newVertices[2];
5053:         triCells[2*3+0] = cone[1]+_vertexOffset; triCells[2*3+1] = newVertices[1]; triCells[2*3+2] = newVertices[0];
5054:         triCells[3*3+0] = cone[2]+_vertexOffset; triCells[3*3+1] = newVertices[2]; triCells[3*3+2] = newVertices[1];
5055:         *numCells = 4;
5056:         *cells    = triCells;
5057:       };
5058:       void getNewCells_LINE_LAGRANGE(const int coneSize, const point_type cone[],  int *numCells, const point_type **cells) {
5059:         int               numEdges;
5060:         const edge_type  *edges;
5061:         static point_type lineCells[2*6];
5062:         point_type        newVertices[3];

5064:         getEdges_LINE_LAGRANGE(coneSize, cone, &numEdges, &edges);
5065:         assert(numEdges == 3);
5066:         for(int e = 0; e < numEdges; ++e) {
5067:           if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5068:             throw ALE::Exception("Missing edge in refined mesh");
5069:           }
5070:           newVertices[e] = _edge2vertex[edges[e]];
5071:         }
5072:         lineCells[0*6+0] = cone[0]+_vertexOffset; // new cell 0
5073:         lineCells[0*6+1] = newVertices[0];
5074:         lineCells[0*6+2] = cone[2]+_vertexOffset;
5075:         lineCells[0*6+3] = newVertices[1];
5076:         lineCells[0*6+4] = cone[4]+_vertexOffset;
5077:         lineCells[0*6+5] = newVertices[2];

5079:         lineCells[1*6+0] = newVertices[0]; // new cell 1
5080:         lineCells[1*6+1] = cone[1]+_vertexOffset;
5081:         lineCells[1*6+2] = newVertices[1];
5082:         lineCells[1*6+3] = cone[3]+_vertexOffset;
5083:         lineCells[1*6+4] = newVertices[2];
5084:         lineCells[1*6+5] = cone[5]+_vertexOffset;

5086:         *numCells = 2;
5087:         *cells    = lineCells;
5088:       };
5089:       void getNewCells_TETRAHEDRON(const int coneSize, const point_type cone[],  int *numCells, const point_type **cells) {
5090:         int               numEdges;
5091:         const edge_type  *edges;
5092:         static point_type tetCells[8*4];
5093:         point_type        newVertices[6];

5095:         getEdges_TETRAHEDRON(coneSize, cone, &numEdges, &edges);
5096:         assert(numEdges == 6);
5097:         for(int e = 0; e < numEdges; ++e) {
5098:           if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5099:             throw ALE::Exception("Missing edge in refined mesh");
5100:           }
5101:           newVertices[e] = _edge2vertex[edges[e]];
5102:         }
5103:         tetCells[0*4+0] = cone[0]+_vertexOffset; tetCells[0*4+1] = newVertices[3]; tetCells[0*4+2] = newVertices[0]; tetCells[0*4+3] = newVertices[2];
5104:         tetCells[1*4+0] = newVertices[0];       tetCells[1*4+1] = newVertices[1]; tetCells[1*4+2] = newVertices[2]; tetCells[1*4+3] = newVertices[3];
5105:         tetCells[2*4+0] = newVertices[0];       tetCells[2*4+1] = newVertices[3]; tetCells[2*4+2] = newVertices[4]; tetCells[2*4+3] = newVertices[1];
5106:         tetCells[3*4+0] = cone[1]+_vertexOffset; tetCells[3*4+1] = newVertices[4]; tetCells[3*4+2] = newVertices[1]; tetCells[3*4+3] = newVertices[0];
5107:         tetCells[4*4+0] = newVertices[2];       tetCells[4*4+1] = newVertices[5]; tetCells[4*4+2] = newVertices[3]; tetCells[4*4+3] = newVertices[1];
5108:         tetCells[5*4+0] = cone[2]+_vertexOffset; tetCells[5*4+1] = newVertices[5]; tetCells[5*4+2] = newVertices[2]; tetCells[5*4+3] = newVertices[1];
5109:         tetCells[6*4+0] = newVertices[1];       tetCells[6*4+1] = newVertices[4]; tetCells[6*4+2] = newVertices[5]; tetCells[6*4+3] = newVertices[3];
5110:         tetCells[7*4+0] = cone[3]+_vertexOffset; tetCells[7*4+1] = newVertices[3]; tetCells[7*4+2] = newVertices[5]; tetCells[7*4+3] = newVertices[4];
5111:         *numCells = 8;
5112:         *cells    = tetCells;
5113:       };
5114:       void getNewCells_TRIANGULAR_PRISM_LAGRANGE(const int coneSize, const point_type cone[],  int *numCells, const point_type **cells) {
5115:         int               numEdges;
5116:         const edge_type  *edges;
5117:         static point_type tcells[4*9];
5118:         point_type        newVertices[9];

5120:         getEdges_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone, &numEdges, &edges);
5121:         assert(numEdges == 9);
5122:         for(int e = 0; e < numEdges; ++e) {
5123:           if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5124:             throw ALE::Exception("Missing edge in refined mesh");
5125:           }
5126:           newVertices[e] = _edge2vertex[edges[e]];
5127:         }
5128:         tcells[0*9+0] = cone[0]+_vertexOffset; // New cell 0
5129:         tcells[0*9+1] = newVertices[0];
5130:         tcells[0*9+2] = newVertices[2];
5131:         tcells[0*9+3] = cone[3]+_vertexOffset;
5132:         tcells[0*9+4] = newVertices[3];
5133:         tcells[0*9+5] = newVertices[5];
5134:         tcells[0*9+6] = cone[6]+_vertexOffset;
5135:         tcells[0*9+7] = newVertices[6];
5136:         tcells[0*9+8] = newVertices[8];

5138:         tcells[1*9+0] = newVertices[0]; // New cell 1
5139:         tcells[1*9+1] = newVertices[1];
5140:         tcells[1*9+2] = newVertices[2];
5141:         tcells[1*9+3] = newVertices[3];
5142:         tcells[1*9+4] = newVertices[4];
5143:         tcells[1*9+5] = newVertices[5];
5144:         tcells[1*9+6] = newVertices[6];
5145:         tcells[1*9+7] = newVertices[7];
5146:         tcells[1*9+8] = newVertices[8];

5148:         tcells[2*9+0] = cone[1]+_vertexOffset; // New cell 2
5149:         tcells[2*9+1] = newVertices[1];
5150:         tcells[2*9+2] = newVertices[0];
5151:         tcells[2*9+3] = cone[4]+_vertexOffset;
5152:         tcells[2*9+4] = newVertices[4];
5153:         tcells[2*9+5] = newVertices[3];
5154:         tcells[2*9+6] = cone[7]+_vertexOffset;
5155:         tcells[2*9+7] = newVertices[7];
5156:         tcells[2*9+8] = newVertices[6];

5158:         tcells[3*9+0] = cone[2]+_vertexOffset; // New cell 3
5159:         tcells[3*9+1] = newVertices[2];
5160:         tcells[3*9+2] = newVertices[1];
5161:         tcells[3*9+3] = cone[5]+_vertexOffset;
5162:         tcells[3*9+4] = newVertices[5];
5163:         tcells[3*9+5] = newVertices[4];
5164:         tcells[3*9+6] = cone[8]+_vertexOffset;
5165:         tcells[3*9+7] = newVertices[8];
5166:         tcells[3*9+8] = newVertices[7];

5168:         *numCells = 4;
5169:         *cells    = tcells;
5170:       };
5171:     public:
5172:       point_type getVertexRelativeOffset()                        {return _vertexOffset;};
5173:       void       setVertexRelativeOffset(const point_type offset) {_vertexOffset = offset;};
5174:       edge_map_type& getEdgeToVertex() {return _edge2vertex;};
5175:       int numNewCells(const point_type cell) {
5176:         switch(this->getCellType(cell)) {
5177:         case TRIANGLE:
5178:           return 4;
5179:         case LINE_LAGRANGE:
5180:           return 2;
5181:         case TETRAHEDRON:
5182:           return 8;
5183:         case TRIANGULAR_PRISM:
5184:         case TRIANGULAR_PRISM_LAGRANGE:
5185:           return 4;
5186:         }
5187:         throw ALE::Exception("Could not determine number of new cells for this cell type");
5188:       };
5189:       void splitEdge(const point_type cell, const int coneSize, const point_type cone[], point_type& curNewVertex) {
5190:         CellType   t = this->getCellType(cell);
5191:         int              numEdges;
5192:         const edge_type *edges;

5194:         switch(t) {
5195:         case TRIANGLE:
5196:           getEdges_TRIANGLE(coneSize, cone, &numEdges, &edges);
5197:           break;
5198:         case LINE_LAGRANGE:
5199:           getEdges_LINE_LAGRANGE(coneSize, cone, &numEdges, &edges);
5200:           break;
5201:         case TETRAHEDRON:
5202:           getEdges_TETRAHEDRON(coneSize, cone, &numEdges, &edges);
5203:           break;
5204:         case TRIANGULAR_PRISM:
5205:           getEdges_TRIANGULAR_PRISM(coneSize, cone, &numEdges, &edges);
5206:           break;
5207:         case TRIANGULAR_PRISM_LAGRANGE:
5208:           getEdges_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone, &numEdges, &edges);
5209:           break;
5210:         default:
5211:           throw ALE::Exception("Could not determine number of new cells for this cell type");
5212:         }
5213:         // Check that vertex does not yet exist
5214:         for(int v = 0; v < numEdges; ++v) {
5215:           if (_edge2vertex.find(edges[v]) == _edge2vertex.end()) {
5216:             std::cout << "Edge: " << edges[v] << ", new vertex: " << curNewVertex << std::endl;
5217:             _edge2vertex[edges[v]] = curNewVertex++;
5218:           }
5219:         }
5220:       };
5221:       void getNewCell(const point_type cell, const int coneSize, const point_type cone[], int newCellNumber, int *newConeSize, const point_type **newCone) {
5222:         CellType    t = this->getCellType(cell);
5223:         int               numCells;
5224:         const point_type *cells;

5226:         switch(t) {
5227:         case TRIANGLE:
5228:           getNewCells_TRIANGLE(coneSize, cone,  &numCells, &cells);
5229:           *newConeSize = 3;
5230:           *newCone     = &cells[newCellNumber*3];
5231:           break;
5232:         case LINE_LAGRANGE:
5233:           getNewCells_LINE_LAGRANGE(coneSize, cone,  &numCells, &cells);
5234:           *newConeSize = 6;
5235:           *newCone     = &cells[newCellNumber*6];
5236:           break;
5237:         case TETRAHEDRON:
5238:           getNewCells_TETRAHEDRON(coneSize, cone,  &numCells, &cells);
5239:           *newConeSize = 4;
5240:           *newCone     = &cells[newCellNumber*4];
5241:           break;
5242:         case TRIANGULAR_PRISM_LAGRANGE:
5243:           getNewCells_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone,  &numCells, &cells);
5244:           *newConeSize = 9;
5245:           *newCone     = &cells[newCellNumber*9];
5246:           break;
5247:         default:
5248:           throw ALE::Exception("Could not create new cell for this cell type");
5249:         }
5250:       };
5251:       void getNeighboringVertices(const point_type cell, const int coneSize, const point_type cone[], const point_type firstNewVertex, point_type vertex2edge[]) {
5252:         CellType   t = this->getCellType(cell);
5253:         int              numEdges;
5254:         const edge_type *edges;

5256:         switch(t) {
5257:         case TRIANGLE:
5258:           getEdges_TRIANGLE(coneSize, cone, &numEdges, &edges);
5259:           break;
5260:         case LINE_LAGRANGE:
5261:           getEdges_LINE_LAGRANGE(coneSize, cone, &numEdges, &edges);
5262:           break;
5263:         case TETRAHEDRON:
5264:           getEdges_TETRAHEDRON(coneSize, cone, &numEdges, &edges);
5265:           break;
5266:         case TRIANGULAR_PRISM:
5267:           getEdges_TRIANGULAR_PRISM(coneSize, cone, &numEdges, &edges);
5268:           break;
5269:         case TRIANGULAR_PRISM_LAGRANGE:
5270:           getEdges_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone, &numEdges, &edges);
5271:           break;
5272:         default:
5273:           throw ALE::Exception("Could not determine number of new cells for this cell type");
5274:         }
5275:         for(int v = 0; v < numEdges; ++v) {
5276:           point_type newVertex = _edge2vertex[edges[v]];

5278:           std::cout << "VERTEX2EDGE index: " << newVertex-firstNewVertex << ", first: " << edges[v].first << ", second: " << edges[v].second << std::endl;
5279:           vertex2edge[(newVertex-firstNewVertex)*2+0] = edges[v].first;
5280:           vertex2edge[(newVertex-firstNewVertex)*2+1] = edges[v].second;
5281:         }
5282:       };
5283:     };
5284:     // This method takes a mesh and performs a refinement of each cell
5285:     //
5286:     //   triangle: 1 --> 4 refinement, adding a new vertex at the midpoint of each edge
5287:     //   tetrahedra:        1 --> 8 refinement,  adding a new vertex at the midpoint of each edge
5288:     //
5289:     // :WARNING: This method currently only works for uninterpolated meshes with tri and tet cells.
5290:     template<typename MeshType, typename Refiner>
5291:     static void refineGeneral(const Obj<MeshType>& mesh, const Obj<MeshType>& newMesh, Refiner& refiner) {
5292:       typedef typename MeshType::sieve_type sieve_type;
5293:       typedef typename MeshType::point_type point_type;
5294:       typedef typename Refiner::edge_type   edge_type;

5296:       // :WARNING: Assumed order of mesh points (cells and vertices):
5297:       //
5298:       // normal cells (in censored depth)
5299:       // normal vertices (in censored depth)
5300:       // other vertices
5301:       // other cells
5302:       //
5303:       // This permits omitting in output the other vertices (e.g.,
5304:       // Lagrange multipliers) and other cells (e.g., cohesive cells)
5305:       // which have a custom reference cell that is not recognized.

5307:       assert(!mesh.isNull());
5308:       assert(!newMesh.isNull());

5310:       // Get original mesh stuff.
5311:       const Obj<typename MeshType::label_sequence>& cells = mesh->heightStratum(0);
5312:       assert(!cells.isNull());
5313:       const typename MeshType::label_sequence::iterator cellsEnd = cells->end();

5315:       const Obj<typename MeshType::label_sequence>& vertices = mesh->depthStratum(0);
5316:       assert(!vertices.isNull());

5318:       const Obj<sieve_type>& sieve = mesh->getSieve();
5319:       assert(!sieve.isNull());
5320:       ALE::ISieveVisitor::PointRetriever<sieve_type> cV(std::max(1, sieve->getMaxConeSize()));

5322:       if (mesh->hasLabel("censored depth")) {
5323:         // :WARNING: Assume all cells in the censored depth come before
5324:         // any other cells. This guarantees that we add vertices in the
5325:         // censored depth before adding other vertices.

5327:         int counterBegin = 0;

5329:         int oldNumCellsNormal = 0;
5330:         int oldNumCellsOther = 0;
5331:         int oldNumVerticesNormal = 0;
5332:         int oldNumVerticesOther = 0;

5334:         int newNumCellsNormal = 0;
5335:         int newNumCellsOther = 0;
5336:         int newNumVerticesNormal = 0;
5337:         int newNumVerticesOther = 0;

5339:         // Count number of cells in censored depth (normal cells).
5340:         const Obj<typename MeshType::label_sequence>& cellsNormal = mesh->getLabelStratum("censored depth", mesh->depth());
5341:         assert(!cellsNormal.isNull());
5342:         const typename MeshType::label_sequence::iterator cellsNormalEnd = cellsNormal->end();
5343:         oldNumCellsNormal = cellsNormal->size();
5344:         for(typename MeshType::label_sequence::iterator c_iter = cellsNormal->begin(); c_iter != cellsNormalEnd; ++c_iter)
5345:           newNumCellsNormal += refiner.numNewCells(*c_iter);

5347:         // Count number of remaining cells (other cells).
5348:         const int numSkip = oldNumCellsNormal;
5349:         oldNumCellsOther = cells->size() - oldNumCellsNormal;
5350:         typename MeshType::label_sequence::iterator c_iter = cells->begin();
5351:         for (int i=0; i < numSkip; ++i)
5352:           ++c_iter;
5353:         for (; c_iter != cellsEnd; ++c_iter)
5354:           newNumCellsOther += refiner.numNewCells(*c_iter);

5356:         // Get number of old normal vertices.
5357:         assert(!mesh->getFactory.isNull());
5358:         Obj<typename Mesh::numbering_type> vNumbering = mesh->getFactory()->getNumbering(mesh, "censored depth", 0);
5359:         assert(!vNumbering.isNull());
5360:         oldNumVerticesNormal = vNumbering->size();

5362:         // Count number of new normal vertices.
5363:         int counterBegin = newNumCellsNormal + vertices->size();
5364:         const point_type curNewVertex = counterBegin;
5365:         for(typename MeshType::label_sequence::iterator c_iter = cellsNormal->begin(); c_iter != cellsNormalEnd; ++c_iter) {
5366:           cV.clear();
5367:           sieve->cone(*c_iter, cV);
5368:           refiner.splitEdge(*c_iter, cV.getSize(), cV.getPoints(), curNewVertex);
5369:         } // for
5370:         newNumVerticesNormal = curNewVertex - counterBegin;

5372:         // Count number of remaining vertices (other vertices).
5373:         oldNumVerticesOther = vertices->size() - oldNumVerticessNormal;
5374:         counterBegin = curNewVertex + oldNumVerticesOther;
5375:         curNewVertex = counterBegin;
5376:         c_iter = cells->begin();
5377:         for (int i=0; i < numSkip; ++i)
5378:           ++c_iter;
5379:         for (; c_iter != cellsEnd; ++c_iter) {
5380:           cV.clear();
5381:           sieve->cone(*c_iter, cV);
5382:           refiner.splitEdge(*c_iter, cV.getSize(), cV.getPoints(), curNewVertex);
5383:         } // for
5384:         newNumVerticesOther = curNewVertex - counterBegin;

5386:         Interval<point_type> oldCellsNormalRange(0, oldNumCellsNormal);
5387:         Interval<point_type> newCellsNormalRange(0, newNumCellsNormal);

5389:         Interval<point_type> oldVerticesNormalRange(oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal);
5390:         Interval<point_type> newVerticesNormalRange(newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal);

5392:         Interval<point_type> oldVerticesOtherRange(oldNumCellsNormal+oldNumVerticesNormal ,
5393:                                                    oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesOther);
5394:         Interval<point_type> newVerticesOtherRange(newNumCellsNormal+newNumVerticesNormal ,
5395:                                                    newNumCellsNormal+newNumVerticesNormal+newNumVerticesOther);

5397:         Interval<point_type> oldCellssOtherRange(oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesOther,
5398:                                                  oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesOther+oldNumCellsOther);
5399:         Interval<point_type> newCellssOtherRange(newNumCellsNormal+newNumVerticesNormal+newNumVerticesOther,
5400:                                                  newNumCellsNormal+newNumVerticesNormal+newNumVerticesOther+newNumCellsOther);


5403:         // Allocate chart for new sieve.
5404:         const Obj<sieve_type>& newSieve = newMesh->getSieve();
5405:         assert(!newSieve.isNull());
5406:         newSieve->setChart(typename sieve_type::chart_type(0, newCellsOtherRange.end()));
5407:         refiner.setVertexRelativeOffset(newNumCellsNormal-oldNumCellsNormal); // THIS DOES NOT WORK FOR COHESIVE CELLS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

5409:         // Create new sieve with correct sizes for refined cells

5411:         // Start with normal cells.
5412:         point_type curNewCell = newCellsNormalRange.begin();
5413:         const typename Interval<point_type>::const_iterator oldCellsNormalRangeEnd = oldCellsNormalRange.end();
5414:         for (typename Interval<point_type>::const_iterator c_iter=oldCellsNormalRange.begin();
5415:              c_iter != oldCellsNormalRangeEnd;
5416:              ++c_iter) {
5417:           // Set new cone and support sizes
5418:           cV.clear();
5419:           sieve->cone(*c_iter, cV);
5420:           const point_type *cone = cV.getPoints();
5421:           const int coneSize = cV.getSize();
5422:           const int newCells = refiner.numNewCells(*c_iter);

5424:           for(int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5425:             const point_type *newCone;
5426:             int newConeSize;

5428:             newSieve->setConeSize(curNewCell, sieve->getConeSize(*c_iter));
5429:             // OPTIMIZE THIS
5430:             refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5431:             for(int v = 0; v < newConeSize; ++v)
5432:               newSieve->addSupportSize(newCone[v], 1);
5433:           } // for
5434:         } // for

5436:         // Continue with other cells.
5437:         point_type curNewCell = newCellsOtherRange.begin();
5438:         const typename Interval<point_type>::const_iterator oldCellsOtherRangeEnd = oldCellsOtherRange.end();
5439:         for (typename Interval<point_type>::const_iterator c_iter=oldCellOtherRange.begin();
5440:              c_iter != oldCellsOtherRangeEnd;
5441:              ++c_iter) {
5442:           // Set new cone and support sizes
5443:           cV.clear();
5444:           sieve->cone(*c_iter, cV);
5445:           const point_type *cone = cV.getPoints();
5446:           const int coneSize = cV.getSize();
5447:           const int newCells = refiner.numNewCells(*c_iter);

5449:           for(int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5450:             const point_type *newCone;
5451:             int newConeSize;

5453:             newSieve->setConeSize(curNewCell, sieve->getConeSize(*c_iter));
5454:             // OPTIMIZE THIS
5455:             refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5456:             for(int v = 0; v < newConeSize; ++v)
5457:               newSieve->addSupportSize(newCone[v], 1);
5458:           } // for
5459:         } // for
5460:         newSieve->allocate();
5461:         point_type* vertex2edge = new point_type[(newNumVerticesNormal+newNumVerticesOther)*2];
5462:         typename Refiner::edge_map_type& edge2vertex = refiner.getEdgeToVertex();


5465:         // Create refined normal cells in new sieve.
5466:         curNewCell = newCellsNormalRange.begin();
5467:         for (typename Interval<point_type>::const_iterator c_iter=oldCellsNormalRange.begin();
5468:              c_iter != oldCellsNormalRangeEnd;
5469:              ++c_iter) {
5470:           cV.clear();
5471:           sieve->cone(*c_iter, cV);
5472:           const point_type *cone = cV.getPoints();
5473:           const int coneSize = cV.getSize();
5474:           const int newCells = refiner.numNewCells(*c_iter);

5476:           for (int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5477:             const point_type *newCone;
5478:             int newConeSize;

5480:             refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5481:             newSieve->setCone(newCone, curNewCell);
5482:           } // for

5484:           refiner.getNeighboringVertices(*c_iter, coneSize, cone, firstNewVertex, vertex2edge);
5485:         } // for

5487:         // Create refined other cells in new sieve.
5488:         curNewCell = newCellsOtherRange.begin();
5489:         for (typename Interval<point_type>::const_iterator c_iter=oldCellsOtherRange.begin();
5490:              c_iter != oldCellsOtherRangeEnd;
5491:              ++c_iter) {
5492:           cV.clear();
5493:           sieve->cone(*c_iter, cV);
5494:           const point_type *cone = cV.getPoints();
5495:           const int coneSize = cV.getSize();
5496:           const int newCells = refiner.numNewCells(*c_iter);

5498:           for (int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5499:             const point_type *newCone;
5500:             int newConeSize;

5502:             refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5503:             newSieve->setCone(newCone, curNewCell);
5504:           } // for

5506:           // FIX THIS!!! LAGRANGE VERTICES MUST BE AFTER ALL OTHER VERTICES (INCLUDING OLD LAGRANGE VERTICES)
5507:           refiner.getNeighboringVertices(*c_iter, coneSize, cone, firstNewVertex, vertex2edge);
5508:         } // for
5509:         newSieve->symmetrize();

5511:         // Set coordinates in refined mesh.
5512:         const Obj<typename MeshType::real_section_type>& coordinates = mesh->getRealSection("coordinates");
5513:         assert(!coordinates.isNull());
5514:         const Obj<typename MeshType::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates");
5515:         assert(!newCoordinates.isNull());

5517:         const typename MeshType::label_sequence::const_iterator verticesEnd = vertices->end();
5518:         assert(vertices->size() > 0);
5519:         const int spaceDim = coordinates->getFiberDimension(*vertices->begin());
5520:         assert(spaceDim > 0);
5521:         newCoordinates->setChart(typename sieve_type::chart_type(newNumCellsNormal, newNumCellsNormal+newNumVertices));

5523:         for (int iVertex=0, offset=newNumCellsNormal; iVertex < newNumVertices; ++iVertex) {
5524:           const point_type vNew = iVertex + offset;
5525:           newCoordinates->setFiberDimension(vNew, spaceDim);
5526:         } // for
5527:         newCoordinates->allocatePoint();

5529:         for (int iVertex=0, oldOffset=oldNumCellsNormal, newOffset=newNumCellsNormal; iVertex < oldNumVertices; ++iVertex) {
5530:           const point_type vOld = iVertex + oldOffset;
5531:           const point_type vNew = iVertex + newOffset;
5532:           newCoordinates->updatePoint(vNew, coordinates->restrictPoint(vOld));
5533:         } // for
5534:         for(int v=0, iVertex=oldNumVertices, newOffset=newNumCellsNormal; iVertex < newNumVertices; ++v, ++iVertex) {
5535:           const point_type vNew = iVertex + newOffset;
5536:           const point_type endpointA = vertex2edge[v*2+0];
5537:           const point_type endpointB = vertex2edge[v*2+1];
5538:           std::cout << "Setting coordinates of vertex " << vNew << " between vertices "
5539:                     << endpointA << " and " << endpointB << std::endl;
5540:           const real *coordsA   = coordinates->restrictPoint(endpointA);
5541:           real coords[3];

5543:           for(int d = 0; d < 3; ++d)
5544:             coords[d]  = coordsA[d];
5545:           const real *coordsB = coordinates->restrictPoint(endpointB);
5546:           for(int d = 0; d < 3; ++d) {
5547:             coords[d] += coordsB[d];
5548:             coords[d] *= 0.5;
5549:           } // for
5550:           newCoordinates->updatePoint(vNew, coords);
5551:         } // for
5552:         delete [] vertex2edge;
5553:         // Fast stratification
5554:         const Obj<typename MeshType::label_type>& height = newMesh->createLabel("height");
5555:         const Obj<typename MeshType::label_type>& depth  = newMesh->createLabel("depth");

5557:         for (int iCell=0; iCell < newNumCellsNormal; ++iCell) {
5558:           const point_type cNew = iCell;
5559:           height->setCone(0, cNew);
5560:           depth->setCone(1, cNew);
5561:         } // for
5562:         for (int iCell=newNumCellsNormal, offset=newNumVertices; iCell < newNumCells; ++iCell) {
5563:           const point_type cNew = iCell + offset;
5564:           height->setCone(0, cNew);
5565:           depth->setCone(1, cNew);
5566:         } // for
5567:         for (int iVertex=0, newOffset=newNumCellsNormal; iVertex < newNumVertices; ++iVertex) {
5568:           const point_type vNew = iVertex + newOffset;
5569:           height->setCone(1, vNew);
5570:           depth->setCone(0, vNew);
5571:         } // for
5572:         newMesh->setHeight(1);
5573:         newMesh->setDepth(1);

5575:       } else {
5576:         int counterBegin = 0;

5578:         int oldNumCells = 0;
5579:         int oldNumVertices = 0;

5581:         int newNumCells = 0;
5582:         int newNumVertices = 0;

5584:         // Count number of cells.
5585:         oldNumCells = cells->size();
5586:         for (typename MeshType::label_sequence::iterator c_iter = cells->begin(); c_iter != cellsEnd; ++c_iter)
5587:           newNumCells += refiner.numNewCells(*c_iter);

5589:         // Count number of vertices (normal vertices).
5590:         oldNumVertices = vertices->size();
5591:         int counterBegin = newNumCells + oldNumVertices;
5592:         const point_type curNewVertex = counterBegin;
5593:         for(typename MeshType::label_sequence::iterator c_iter = cells->begin(); c_iter != cellsEnd; ++c_iter) {
5594:           cV.clear();
5595:           sieve->cone(*c_iter, cV);
5596:           refiner.splitEdge(*c_iter, cV.getSize(), cV.getPoints(), curNewVertex);
5597:         } // for
5598:         newNumVertices = curNewVertex - counterBegin;

5600:         Interval<point_type> oldCellsRange(0, oldNumCells);
5601:         Interval<point_type> newCellsRange(0, newNumCells);

5603:         Interval<point_type> oldVerticesRange(oldNumCells, oldNumCells+oldNumVertices);
5604:         Interval<point_type> newVerticesRange(newNumCells, newNumCells+newNumVertices);

5606:         // Allocate chart for new sieve.
5607:         const Obj<sieve_type>& newSieve = newMesh->getSieve();
5608:         assert(!newSieve.isNull());
5609:         newSieve->setChart(typename sieve_type::chart_type(0, newCellsOtherRange.end()));
5610:         refiner.setVertexRelativeOffset(newNumCells-oldNumCells);

5612:         // Create new sieve with correct sizes for refined cells

5614:         // Start with normal cells.
5615:         point_type curNewCell = newCellsRange.begin();
5616:         const typename Interval<point_type>::const_iterator oldCellsRangeEnd = oldCellsRange.end();
5617:         for (typename Interval<point_type>::const_iterator c_iter=oldCellsRange.begin();
5618:              c_iter != oldCellsRangeEnd;
5619:              ++c_iter) {
5620:           // Set new cone and support sizes
5621:           cV.clear();
5622:           sieve->cone(*c_iter, cV);
5623:           const point_type *cone = cV.getPoints();
5624:           const int coneSize = cV.getSize();
5625:           const int newCells = refiner.numNewCells(*c_iter);

5627:           for(int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5628:             const point_type *newCone;
5629:             int newConeSize;

5631:             newSieve->setConeSize(curNewCell, sieve->getConeSize(*c_iter));
5632:             // OPTIMIZE THIS
5633:             refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5634:             for(int v = 0; v < newConeSize; ++v)
5635:               newSieve->addSupportSize(newCone[v], 1);
5636:           } // for
5637:         } // for

5639:         // Create refined normal cells in new sieve.
5640:         curNewCell = newCellsRange.begin();
5641:         for (typename Interval<point_type>::const_iterator c_iter=oldCellsRange.begin();
5642:              c_iter != oldCellsRangeEnd;
5643:              ++c_iter) {
5644:           cV.clear();
5645:           sieve->cone(*c_iter, cV);
5646:           const point_type *cone = cV.getPoints();
5647:           const int coneSize = cV.getSize();
5648:           const int newCells = refiner.numNewCells(*c_iter);

5650:           for (int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5651:             const point_type *newCone;
5652:             int newConeSize;

5654:             refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5655:             newSieve->setCone(newCone, curNewCell);
5656:           } // for

5658:           refiner.getNeighboringVertices(*c_iter, coneSize, cone, firstNewVertex, vertex2edge);
5659:         } // for
5660:         newSieve->symmetrize();

5662:         // Set coordinates in refined mesh.
5663:         const Obj<typename MeshType::real_section_type>& coordinates = mesh->getRealSection("coordinates");
5664:         assert(!coordinates.isNull());
5665:         const Obj<typename MeshType::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates");
5666:         assert(!newCoordinates.isNull());

5668:         const typename MeshType::label_sequence::const_iterator verticesEnd = vertices->end();
5669:         assert(vertices->size() > 0);
5670:         const int spaceDim = coordinates->getFiberDimension(*vertices->begin());
5671:         assert(spaceDim > 0);
5672:         newCoordinates->setChart(typename sieve_type::chart_type(newVerticesRange.begin(), newVerticesRange.end()));

5674:         const typename Interval<point_type>::const_iterator newVerticesRangeEnd = newVerticesRange.end();
5675:         for (typename Interval<point_type>::const_iterator v_iter=newVerticesRange.begin(); v_iter != newVerticesRangeEnd; ++v_iter)
5676:           newCoordinates->setFiberDimension(v_iter, spaceDim);
5677:         newCoordinates->allocatePoint();

5679:         const typename Interval<point_type>::const_iterator oldVerticesRangeEnd = oldVerticesRange.end();
5680:         for (typename Interval<point_type>::const_iterator vOld_iter=oldVerticesRange.begin(), vNew_iter=newVerticesRange.begin(); vOld_iter != oldVerticesRangeEnd; ++vOld_iter)
5681:           newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter));
5682:         for(int v=0, iVertex=oldNumVertices; iVertex < newNumVertices; ++v, ++iVertex) {
5683:           const point_type vNew = newVerticesRange.begin() + iVertex;
5684:           const point_type endpointA = vertex2edge[v*2+0];
5685:           const point_type endpointB = vertex2edge[v*2+1];
5686:           std::cout << "Setting coordinates of vertex " << vNew << " between vertices "
5687:                     << endpointA << " and " << endpointB << std::endl;
5688:           const real *coordsA   = coordinates->restrictPoint(endpointA);
5689:           real coords[3];

5691:           for(int d = 0; d < 3; ++d)
5692:             coords[d]  = coordsA[d];
5693:           const real *coordsB = coordinates->restrictPoint(endpointB);
5694:           for(int d = 0; d < 3; ++d) {
5695:             coords[d] += coordsB[d];
5696:             coords[d] *= 0.5;
5697:           } // for
5698:           newCoordinates->updatePoint(vNew, coords);
5699:         } // for
5700:         delete [] vertex2edge;

5702:         // Fast stratification
5703:         const Obj<typename MeshType::label_type>& height = newMesh->createLabel("height");
5704:         const Obj<typename MeshType::label_type>& depth  = newMesh->createLabel("depth");
5705:         for (int iCell=0; iCell < newNumCells; ++iCell) {
5706:           const point_type cNew = iCell;
5707:           height->setCone(0, cNew);
5708:           depth->setCone(1, cNew);
5709:         } // for
5710:         for (int iVertex=0, newOffset=newNumCellsNormal; iVertex < newNumVertices; ++iVertex) {
5711:           const point_type vNew = iVertex + newOffset;
5712:           height->setCone(1, vNew);
5713:           depth->setCone(0, vNew);
5714:         } // for
5715:         newMesh->setHeight(1);
5716:         newMesh->setDepth(1);
5717:       } // if/else

5719:       // Exchange new boundary vertices
5720:       //   We can convert endpoints, and then just match to new vertex on this side
5721:       //   1) Create the overlap of edges which are vertex pairs (do not need for interpolated meshes)
5722:       //   2) Create a section of overlap edge --> new vertex (this will generalize to other split points in interpolated meshes)
5723:       //   3) Copy across new overlap
5724:       //   4) Fuse matches new vertex pairs and inserts them into the old overlap


5727:       // Create the parallel overlap
5728:       int *oldNumCellsP    = new int[mesh->commSize()];
5729:       int *newNumCellsP = new int[newMesh->commSize()];
5730:       int  ierr;

5732:       MPI_Allgather((void *) &oldNumCells, 1, MPI_INT, oldNumCellsP, 1, MPI_INT, mesh->comm());CHKERRXX(ierr);
5733:       MPI_Allgather((void *) &newNumCells, 1, MPI_INT, newNumCellsP, 1, MPI_INT, newMesh->comm());CHKERRXX(ierr);
5734:       Obj<typename MeshType::send_overlap_type> newSendOverlap = newMesh->getSendOverlap();
5735:       Obj<typename MeshType::recv_overlap_type> newRecvOverlap = newMesh->getRecvOverlap();
5736:       const Obj<typename MeshType::send_overlap_type>& sendOverlap = mesh->getSendOverlap();
5737:       const Obj<typename MeshType::recv_overlap_type>& recvOverlap = mesh->getRecvOverlap();
5738:       Obj<typename MeshType::send_overlap_type::traits::capSequence> sendPoints  = sendOverlap->cap();
5739:       const typename MeshType::send_overlap_type::source_type        localOffset = newNumCellsP[newMesh->commRank()] - oldNumCellsP[mesh->commRank()];

5741:       for(typename MeshType::send_overlap_type::traits::capSequence::iterator p_iter = sendPoints->begin(); p_iter != sendPoints->end(); ++p_iter) {
5742:         const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& ranks      = sendOverlap->support(*p_iter);
5743:         const typename MeshType::send_overlap_type::source_type&                  localPoint = *p_iter;

5745:         for(typename MeshType::send_overlap_type::traits::supportSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
5746:           const int                                   rank         = *r_iter;
5747:           const typename MeshType::send_overlap_type::source_type& remotePoint  = r_iter.color();
5748:           const typename MeshType::send_overlap_type::source_type  remoteOffset = newNumCellsP[rank] - oldNumCellsP[rank];

5750:           newSendOverlap->addArrow(localPoint+localOffset, rank, remotePoint+remoteOffset);
5751:         }
5752:       }
5753:       Obj<typename MeshType::recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();

5755:       for(typename MeshType::recv_overlap_type::traits::baseSequence::iterator p_iter = recvPoints->begin(); p_iter != recvPoints->end(); ++p_iter) {
5756:         const Obj<typename MeshType::recv_overlap_type::traits::coneSequence>& ranks      = recvOverlap->cone(*p_iter);
5757:         const typename MeshType::recv_overlap_type::target_type&               localPoint = *p_iter;

5759:         for(typename MeshType::recv_overlap_type::traits::coneSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
5760:           const int                                        rank         = *r_iter;
5761:           const typename MeshType::recv_overlap_type::target_type& remotePoint  = r_iter.color();
5762:           const typename MeshType::recv_overlap_type::target_type  remoteOffset = newNumCellsP[rank] - oldNumCellsP[rank];

5764:           newRecvOverlap->addArrow(rank, localPoint+localOffset, remotePoint+remoteOffset);
5765:         }
5766:       }
5767:       newMesh->setCalculatedOverlap(true);
5768:       delete [] oldNumCellsP;
5769:       delete [] newNumCellsP;
5770:       // Check edges in edge2vertex for both endpoints sent to same process
5771:       //   Put it in section with point being the lowest numbered vertex and value (other endpoint, new vertex)
5772:       Obj<ALE::Section<point_type, edge_type> > newVerticesSection = new ALE::Section<point_type, edge_type>(mesh->comm());
5773:       std::map<edge_type, std::vector<int> > bdedge2rank;

5775:       for(typename std::map<edge_type, point_type>::const_iterator e_iter = edge2vertex.begin(); e_iter != edge2vertex.end(); ++e_iter) {
5776:         const point_type left  = e_iter->first.first;
5777:         const point_type right = e_iter->first.second;

5779:         if (sendOverlap->capContains(left) && sendOverlap->capContains(right)) {
5780:           const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& leftRanksSeq  = sendOverlap->support(left);
5781:           std::set<int> leftRanks(leftRanksSeq->begin(), leftRanksSeq->end());
5782:           const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& rightRanksSeq = sendOverlap->support(right);
5783:           std::set<int> rightRanks(rightRanksSeq->begin(), rightRanksSeq->end());
5784:           std::set<int> ranks;
5785:           std::set_intersection(leftRanks.begin(), leftRanks.end(), rightRanks->begin(), rightRanks->end(),
5786:                                 std::insert_iterator<std::list<int> >(ranks, ranks.begin()));

5788:           if(ranks.size()) {
5789:             newVerticesSection->addFiberDimension(std::min(e_iter->first.first, e_iter->first.second)+localOffset, 1);
5790:             for(typename std::list<int>::const_iterator r_iter = ranks.begin(); r_iter != ranks.end(); ++r_iter) {
5791:               bdedge2rank[e_iter->first].push_back(*r_iter);
5792:             }
5793:           }
5794:         }
5795:       }
5796:       newVerticesSection->allocatePoint();
5797:       const typename ALE::Section<point_type, edge_type>::chart_type& chart = newVerticesSection->getChart();

5799:       for(typename ALE::Section<point_type, edge_type>::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
5800:         typedef typename ALE::Section<point_type, edge_type>::value_type value_type;
5801:         const point_type p      = *c_iter;
5802:         const int        dim    = newVerticesSection->getFiberDimension(p);
5803:         int              v      = 0;
5804:         value_type      *values = new value_type[dim];

5806:         for(typename std::map<edge_type, std::vector<int> >::const_iterator e_iter = bdedge2rank.begin(); e_iter != bdedge2rank.end() && v < dim; ++e_iter) {
5807:           if (std::min(e_iter->first.first, e_iter->first.second)+localOffset == p) {
5808:             values[v++] = edge_type(std::max(e_iter->first.first, e_iter->first.second)+localOffset, edge2vertex[e_iter->first]);
5809:           }
5810:         }
5811:         newVerticesSection->updatePoint(p, values);
5812:         delete [] values;
5813:       }
5814:       // Copy across overlap
5815:       typedef ALE::Pair<int, point_type> overlap_point_type;
5816:       Obj<ALE::Section<overlap_point_type, edge_type> > overlapVertices = new ALE::Section<overlap_point_type, edge_type>(mesh->comm());

5818:       ALE::Pullback::SimpleCopy::copy(newSendOverlap, newRecvOverlap, newVerticesSection, overlapVertices);
5819:       // Merge by translating edge to local points, finding edge in edge2vertex, and adding (local new vetex, remote new vertex) to overlap
5820:       for(typename std::map<edge_type, std::vector<int> >::const_iterator e_iter = bdedge2rank.begin(); e_iter != bdedge2rank.end(); ++e_iter) {
5821:         const point_type localPoint = edge2vertex[e_iter->first];

5823:         for(typename std::vector<int>::const_iterator r_iter = e_iter->second.begin(); r_iter != e_iter->second.end(); ++r_iter) {
5824:           point_type remoteLeft = -1, remoteRight = -1;
5825:           const int  rank       = *r_iter;

5827:           const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& leftRanks = newSendOverlap->support(e_iter->first.first+localOffset);
5828:           for(typename MeshType::send_overlap_type::traits::supportSequence::iterator lr_iter = leftRanks->begin(); lr_iter != leftRanks->end(); ++lr_iter) {
5829:             if (rank == *lr_iter) {
5830:               remoteLeft = lr_iter.color();
5831:               break;
5832:             }
5833:           }
5834:           const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& rightRanks = newSendOverlap->support(e_iter->first.second+localOffset);
5835:           for(typename MeshType::send_overlap_type::traits::supportSequence::iterator rr_iter = rightRanks->begin(); rr_iter != rightRanks->end(); ++rr_iter) {
5836:             if (rank == *rr_iter) {
5837:               remoteRight = rr_iter.color();
5838:               break;
5839:             }
5840:           }
5841:           const point_type remoteMin   = std::min(remoteLeft, remoteRight);
5842:           const point_type remoteMax   = std::max(remoteLeft, remoteRight);
5843:           const int        remoteSize  = overlapVertices->getFiberDimension(overlap_point_type(rank, remoteMin));
5844:           const edge_type *remoteVals  = overlapVertices->restrictPoint(overlap_point_type(rank, remoteMin));
5845:           point_type       remotePoint = -1;

5847:           for(int d = 0; d < remoteSize; ++d) {
5848:             if (remoteVals[d].first == remoteMax) {
5849:               remotePoint = remoteVals[d].second;
5850:               break;
5851:             }
5852:           }
5853:           newSendOverlap->addArrow(localPoint, rank, remotePoint);
5854:           newRecvOverlap->addArrow(rank, localPoint, remotePoint);
5855:         }
5856:       }
5857:     };
5858: #endif
5859:   };

5861:   class MeshSerializer {
5862:   public:
5863:     template<typename Mesh>
5864:     static void writeMesh(const std::string& filename, Mesh& mesh) {
5865:       std::ofstream fs;

5867:       if (mesh.commRank() == 0) {
5868:         fs.open(filename.c_str());
5869:       }
5870:       writeMesh(fs, mesh);
5871:       if (mesh.commRank() == 0) {
5872:         fs.close();
5873:       }
5874:     }
5875:     template<typename Mesh>
5876:     static void writeMesh(std::ofstream& fs, Mesh& mesh) {
5877:       ISieveSerializer::writeSieve(fs, *mesh.getSieve());
5878:       // Write labels
5879:       const typename Mesh::labels_type& labels = mesh.getLabels();

5881:       if (!mesh.commRank()) {fs << labels.size() << std::endl;}
5882:       for(typename Mesh::labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
5883:         if (!mesh.commRank()) {fs << l_iter->first << std::endl;}
5884:         LabelSifterSerializer::writeLabel(fs, *l_iter->second);
5885:       }
5886:       // Write sections
5887:       Obj<std::set<std::string> > realNames = mesh.getRealSections();

5889:       if (!mesh.commRank()) {fs << realNames->size() << std::endl;}
5890:       for(std::set<std::string>::const_iterator n_iter = realNames->begin(); n_iter != realNames->end(); ++n_iter) {
5891:         if (!mesh.commRank()) {fs << *n_iter << std::endl;}
5892:         SectionSerializer::writeSection(fs, *mesh.getRealSection(*n_iter));
5893:       }
5894:       Obj<std::set<std::string> > intNames = mesh.getIntSections();

5896:       if (!mesh.commRank()) {fs << intNames->size() << std::endl;}
5897:       for(std::set<std::string>::const_iterator n_iter = intNames->begin(); n_iter != intNames->end(); ++n_iter) {
5898:         if (!mesh.commRank()) {fs << *n_iter << std::endl;}
5899:         SectionSerializer::writeSection(fs, *mesh.getIntSection(*n_iter));
5900:       }
5901:       // Write overlap
5902: #ifdef USE_NEW_OVERLAP
5903:       PETSc::OverlapSerializer::writeOverlap(fs, *mesh.getSendOverlap());
5904:       PETSc::OverlapSerializer::writeOverlap(fs, *mesh.getRecvOverlap());
5905: #else
5906:       SifterSerializer::writeSifter(fs, *mesh.getSendOverlap());
5907:       SifterSerializer::writeSifter(fs, *mesh.getRecvOverlap());
5908: #endif
5909:       // Write distribution overlap
5910:       // Write renumbering
5911:     }
5912:     template<typename Mesh>
5913:     static void loadMesh(const std::string& filename, Mesh& mesh) {
5914:       std::ifstream fs;

5916:       if (mesh.commRank() == 0) {
5917:         fs.open(filename.c_str());
5918:       }
5919:       loadMesh(fs, mesh);
5920:       if (mesh.commRank() == 0) {
5921:         fs.close();
5922:       }
5923:     }
5924:     template<typename Mesh>
5925:     static void loadMesh(std::ifstream& fs, Mesh& mesh) {
5926:       ALE::Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh.comm(), mesh.debug());
5927:       PetscErrorCode                      ierr;

5929:       ISieveSerializer::loadSieve(fs, *sieve);
5930:       mesh.setSieve(sieve);
5931:       // Load labels
5932:       int numLabels;

5934:       if (!mesh.commRank()) {fs >> numLabels;}
5935:       MPI_Bcast(&numLabels, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5936:       for(int l = 0; l < numLabels; ++l) {
5937:         ALE::Obj<typename Mesh::label_type> label = new typename Mesh::label_type(mesh.comm(), mesh.debug());
5938:         std::string                         name;
5939:         int                                 len;

5941:         if (!mesh.commRank()) {
5942:           fs >> name;
5943:           len = name.size();
5944:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5945:           MPI_Bcast((void *) name.c_str(), len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5946:         } else {
5947:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5948:           char *n = new char[len+1];
5949:           MPI_Bcast(n, len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5950:           name = n;
5951:           delete [] n;
5952:         }
5953:         LabelSifterSerializer::loadLabel(fs, *label);
5954:         mesh.setLabel(name, label);
5955:       }
5956:       // Load sections
5957:       int numRealSections;

5959:       if (!mesh.commRank()) {fs >> numRealSections;}
5960:       MPI_Bcast(&numRealSections, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5961:       for(int s = 0; s < numRealSections; ++s) {
5962:         ALE::Obj<typename Mesh::real_section_type> section = new typename Mesh::real_section_type(mesh.comm(), mesh.debug());
5963:         std::string                                name;
5964:         int                                        len;

5966:         if (!mesh.commRank()) {
5967:           fs >> name;
5968:           len = name.size();
5969:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5970:           MPI_Bcast((void *) name.c_str(), len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5971:         } else {
5972:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5973:           char *n = new char[len+1];
5974:           MPI_Bcast(n, len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5975:           name = n;
5976:           delete [] n;
5977:         }
5978:         SectionSerializer::loadSection(fs, *section);
5979:         mesh.setRealSection(name, section);
5980:       }
5981:       int numIntSections;

5983:       if (!mesh.commRank()) {fs >> numIntSections;}
5984:       MPI_Bcast(&numIntSections, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5985:       for(int s = 0; s < numIntSections; ++s) {
5986:         ALE::Obj<typename Mesh::int_section_type> section = new typename Mesh::int_section_type(mesh.comm(), mesh.debug());
5987:         std::string                               name;
5988:         int                                       len;

5990:         if (!mesh.commRank()) {
5991:           fs >> name;
5992:           len = name.size();
5993:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5994:           MPI_Bcast((void *) name.c_str(), len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5995:         } else {
5996:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5997:           char *n = new char[len+1];
5998:           MPI_Bcast(n, len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5999:           name = n;
6000:           delete [] n;
6001:         }
6002:         SectionSerializer::loadSection(fs, *section);
6003:         mesh.setIntSection(name, section);
6004:       }
6005:       // Load overlap
6006: #ifdef USE_NEW_OVERLAP
6007:       PETSc::OverlapSerializer::loadOverlap(fs, *mesh.getSendOverlap());
6008:       PETSc::OverlapSerializer::loadOverlap(fs, *mesh.getRecvOverlap());
6009: #else
6010:       SifterSerializer::loadSifter(fs, *mesh.getSendOverlap());
6011:       SifterSerializer::loadSifter(fs, *mesh.getRecvOverlap());
6012: #endif
6013:       // Load distribution overlap
6014:       // Load renumbering
6015:     }
6016:   };
6017: } // namespace ALE
6018: #endif