Actual source code: Mesh.hh

petsc-3.3-p7 2013-05-11
  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:   public: // Sizes
1703:     template<typename Section>
1704:     int size(const Obj<Section>& section, const point_type& p) {
1705:       typedef ISieveVisitor::SizeVisitor<sieve_type,Section>                        size_visitor_type;
1706:       typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1707:       size_visitor_type    sV(*section);
1708:       closure_visitor_type cV(*this->getSieve(), sV);

1710:       this->getSieve()->cone(p, cV);
1711:       if (!sV.getSize()) sV.visitPoint(p);
1712:       return sV.getSize();
1713:     }
1714:     template<typename Section>
1715:     int sizeWithBC(const Obj<Section>& section, const point_type& p) {
1716:       typedef ISieveVisitor::SizeWithBCVisitor<sieve_type,Section>                  size_visitor_type;
1717:       typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1718:       size_visitor_type    sV(*section);
1719:       closure_visitor_type cV(*this->getSieve(), sV);

1721:       this->getSieve()->cone(p, cV);
1722:       if (!sV.getSize()) sV.visitPoint(p);
1723:       return sV.getSize();
1724:     }
1725:     int sizeWithBC(PetscSection section, const point_type& p) {
1726:       typedef ISieveVisitor::SizeWithBCVisitor<sieve_type,PetscSection>             size_visitor_type;
1727:       typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1728:       size_visitor_type    sV(section);
1729:       closure_visitor_type cV(*this->getSieve(), sV);

1731:       this->getSieve()->cone(p, cV);
1732:       if (!sV.getSize()) sV.visitPoint(p);
1733:       return sV.getSize();
1734:     }
1735:     void sizeWithBC(PetscSection section, const point_type& p, PetscInt fieldSize[]) {
1736:       typedef ISieveVisitor::SizeWithBCVisitor<sieve_type,PetscSection>             size_visitor_type;
1737:       typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1738:       size_visitor_type    sV(section, fieldSize);
1739:       closure_visitor_type cV(*this->getSieve(), sV);

1741:       this->getSieve()->cone(p, cV);
1742:       if (!sV.getSize()) sV.visitPoint(p);
1743:     }
1744:     template<typename Section>
1745:     void allocate(const Obj<Section>& section) {
1746:       section->allocatePoint();
1747:     }
1748:   public: // Restrict/Update closures
1749:     template<typename Sieve, typename Visitor>
1750:     void closure1(const Sieve& sieve, const point_type& p, Visitor& v)
1751:     {
1752:       v.visitPoint(p, 0);
1753:       // Cone is guarateed to be ordered correctly
1754:       sieve.orientedCone(p, v);
1755:     }
1756:     // Return the values for the closure of this point
1757:     template<typename Section>
1758:     const typename Section::value_type *restrictClosure(const Obj<Section>& section, const point_type& p) {
1759:       const int size = this->sizeWithBC(section, p);
1760:       ISieveVisitor::RestrictVisitor<Section> rV(*section, size, section->getRawArray(size));

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

1767:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1768:       }
1769:       return rV.getValues();
1770:     }
1771:     template<typename Section>
1772:     const typename Section::value_type *restrictClosure(const Obj<Section>& section, const point_type& p, typename Section::value_type *values, const int valuesSize) {
1773:       const int size = this->sizeWithBC(section, p);
1774:       if (valuesSize < size) {throw ALE::Exception("Input array to small for restrictClosure()");}
1775:       ISieveVisitor::RestrictVisitor<Section> rV(*section, size, values);

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

1782:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1783:       }
1784:       return rV.getValues();
1785:     }
1786:     template<typename Visitor>
1787:     void restrictClosure(const point_type& p, Visitor& v) {
1788:       if (this->depth() == 1) {
1789:         closure1(*this->getSieve(), p, v);
1790:       } else {
1791:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, v);
1792:       }
1793:     }
1794:     // Replace the values for the closure of this point
1795:     template<typename Section>
1796:     void update(const Obj<Section>& section, const point_type& p, const typename Section::value_type *v) {
1797:       ISieveVisitor::UpdateVisitor<Section> uV(*section, v);

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

1804:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1805:       }
1806:     }
1807:     // Replace the values for the closure of this point, including points constrained by BC
1808:     template<typename Section>
1809:     void updateAll(const Obj<Section>& section, const point_type& p, const typename Section::value_type *v) {
1810:       ISieveVisitor::UpdateAllVisitor<Section> uV(*section, v);

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

1817:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1818:       }
1819:     }
1820:     // Augment the values for the closure of this point
1821:     template<typename Section>
1822:     void updateAdd(const Obj<Section>& section, const point_type& p, const typename Section::value_type *v) {
1823:       ISieveVisitor::UpdateAddVisitor<Section> uV(*section, v);

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

1830:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1831:       }
1832:     }
1833:     // Augment the values for the closure of this point
1834:     template<typename Visitor>
1835:     void updateClosure(const point_type& p, Visitor& v) {
1836:       if (this->depth() == 1) {
1837:         closure1(*this->getSieve(), p, v);
1838:       } else {
1839:         ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, v);
1840:       }
1841:     }
1842:   public: // Overlap
1843:     void constructOverlap() {
1844:       if (!this->_calculatedOverlap && (this->commSize() > 1)) {throw ALE::Exception("Must calculate overlap during distribution");}
1845:     };
1846:   public: // Cell topology and geometry
1847:     int getNumCellCorners(const point_type& p, const int depth = -1) const {
1848:       const int d = depth < 0 ? this->depth() : depth;

1850:       if (d == 1) {
1851:         return this->_sieve->getConeSize(p);
1852:       } else if (d <= 0) {
1853:         return 0;
1854:       }
1855:       // Warning: this is slow
1856:       ISieveVisitor::NConeRetriever<sieve_type> ncV(*this->_sieve, (int) pow((double) this->_sieve->getMaxConeSize(), this->depth()));
1857:       ALE::ISieveTraversal<sieve_type>::orientedClosure(*this->_sieve, p, ncV);
1858:       return ncV.getOrientedSize();
1859:     };
1860:     int getNumCellCorners() {
1861:       return getNumCellCorners(*this->heightStratum(0)->begin());
1862:     };
1863:     void setupCoordinates(const Obj<real_section_type>& coordinates) {
1864:       const Obj<label_sequence>& vertices = this->depthStratum(0);

1866:       if (vertices->size() > 0) {
1867:         coordinates->setChart(typename real_section_type::chart_type(*std::min_element(vertices->begin(), vertices->end()),
1868:                                                                      *std::max_element(vertices->begin(), vertices->end())+1));
1869:       } else {
1870:         coordinates->setChart(typename real_section_type::chart_type(0, 0));
1871:       }
1872:     };
1873:     // Find the cell in which this point lies (stupid algorithm)
1874:     point_type locatePoint_Simplex_2D(const typename real_section_type::value_type point[]) {
1875:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1876:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
1877:       const int                     embedDim    = 2;
1878:       typename real_section_type::value_type v0[2], J[4], invJ[4], detJ;

1880:       for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1881:         //std::cout << "Checking cell " << *c_iter << std::endl;
1882:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
1883:         double xi   = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]);
1884:         double eta  = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]);

1886:         if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) {
1887:           return *c_iter;
1888:         }
1889:       }
1890:       {
1891:         ostringstream msg;
1892:         msg << "Could not locate point: (" << point[0] <<","<< point[1] << ")" << std::endl;
1893:         throw ALE::Exception(msg.str().c_str());
1894:       }
1895:     };
1896:     point_type locatePoint_General_2D(const typename real_section_type::value_type p[]) {
1897:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1898:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
1899:       const PetscInt                faces[8]    = {0, 1, 1, 2, 2, 3, 3, 0};

1901:       for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1902:         const PetscReal *coords    = this->restrictClosure(coordinates, *c_iter);
1903:         PetscInt         crossings = 0;

1905:         //std::cout << "Checking cell " << *c_iter << std::endl;
1906:         for(PetscInt f = 0; f < 4; f++) {
1907:           PetscReal x_i   = coords[faces[2*f+0]*2+0];
1908:           PetscReal y_i   = coords[faces[2*f+0]*2+1];
1909:           PetscReal x_j   = coords[faces[2*f+1]*2+0];
1910:           PetscReal y_j   = coords[faces[2*f+1]*2+1];
1911:           PetscReal slope = (y_j - y_i) / (x_j - x_i);
1912:           bool      cond1 = (x_i <= p[0]) && (p[0] < x_j);
1913:           bool      cond2 = (x_j <= p[0]) && (p[0] < x_i);
1914:           bool      above = (p[1] < slope * (p[0] - x_i) + y_i);
1915:           if ((cond1 || cond2)  && above) ++crossings;
1916:         }
1917:         if (crossings % 2) {return *c_iter;}
1918:       }
1919:       {
1920:         ostringstream msg;
1921:         msg << "Could not locate point: (" << p[0] <<","<< p[1] << ")" << std::endl;
1922:         throw ALE::Exception(msg.str().c_str());
1923:       }
1924:     };
1925:     //   Assume a simplex and 3D
1926:     point_type locatePoint_Simplex_3D(const typename real_section_type::value_type point[]) {
1927:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1928:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
1929:       const int                     embedDim    = 3;
1930:       typename real_section_type::value_type v0[3], J[9], invJ[9], detJ;

1932:       for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1933:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
1934:         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]);
1935:         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]);
1936:         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]);

1938:         if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) {
1939:           return *c_iter;
1940:         }
1941:       }
1942: #if 0
1943:       {
1944:         ostringstream msg;
1945:         msg << "Could not locate point: (" << point[0] <<","<< point[1] <<","<< point[2] << ")" << std::endl;
1946:         throw ALE::Exception(msg.str().c_str());
1947:       }
1948: #else
1949:       return -1;
1950: #endif
1951:     };
1952:     point_type locatePoint_General_3D(const typename real_section_type::value_type p[]) {
1953:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1954:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
1955:       const PetscInt                faces[24]   = {0, 1, 2, 3,  5, 4, 7, 6,  1, 0, 4, 5,
1956:                                                    3, 2, 6, 7,  1, 5, 6, 2,  0, 3, 7, 4};

1958:       for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1959:         const PetscReal *coords = this->restrictClosure(coordinates, *c_iter);
1960:         PetscBool        found  = PETSC_TRUE;

1962:         //std::cout << "Checking cell " << *c_iter << std::endl;
1963:         for(PetscInt f = 0; f < 6; f++) {
1964:           /* Check the point is under plane */
1965:           /*   Get face normal */
1966:           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]};
1967:           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]};
1968:           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]};
1969:           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]};
1970:           PetscReal dot       = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2];
1971:           /* Check that projected point is in face (2D location problem) */
1972:           if (dot < 0.0) {
1973:             found = PETSC_FALSE;
1974:             break;
1975:           }
1976:         }
1977:         if (found) {return *c_iter;}
1978:       }
1979: #if 0
1980:       {
1981:         ostringstream msg;
1982:         msg << "Could not locate point: (" << p[0] <<","<< p[1] <<","<< p[2] << ")" << std::endl;
1983:         throw ALE::Exception(msg.str().c_str());
1984:       }
1985: #else
1986:       return -1;
1987: #endif
1988:     };
1989:     point_type locatePoint(const typename real_section_type::value_type point[], point_type guess = -1) {
1990:       //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
1991:       if (guess != -1) {
1992:         return guess;
1993:       } else if (this->_dim == 2) {
1994:         const int e = *this->heightStratum(0)->begin();
1995:         switch(this->getSieve()->getConeSize(e)) {
1996:         case 3:
1997:           return locatePoint_Simplex_2D(point);
1998:         case 4:
1999:           return locatePoint_General_2D(point);
2000:         default:
2001:           throw ALE::Exception("No point location for cone size");
2002:         }
2003:       } else if (this->_dim == 3) {
2004:         const int e = *this->heightStratum(0)->begin();
2005:         switch(this->getSieve()->getConeSize(e)) {
2006:         case 4:
2007:           return locatePoint_Simplex_3D(point);
2008:         case 8:
2009:           return locatePoint_General_3D(point);
2010:         default:
2011:           throw ALE::Exception("No point location for cone size");
2012:         }
2013:       } else {
2014:         throw ALE::Exception("No point location for mesh dimension");
2015:       }
2016:     };
2017:     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) {
2018:       const PetscReal *coords = this->restrictClosure(coordinates, e);
2019:       const int        dim    = 2;
2020:       typename real_section_type::value_type           invDet;

2022:       if (v0) {
2023:         for(int d = 0; d < dim; d++) {
2024:           v0[d] = coords[d];
2025:         }
2026:       }
2027:       if (J) {
2028:         for(int d = 0; d < dim; d++) {
2029:           for(int f = 0; f < dim; f++) {
2030:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2031:           }
2032:         }
2033:         detJ = J[0]*J[3] - J[1]*J[2];
2034:         if (detJ < 0.0) {
2035:           const typename real_section_type::value_type  xLength = this->_periodicity[0];

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

2040:             if (v0x == 0.0) {
2041:               v0x = v0[0] = xLength;
2042:             }
2043:             for(int f = 0; f < dim; f++) {
2044:               const typename real_section_type::value_type px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];

2046:               J[0*dim+f] = 0.5*(px - v0x);
2047:             }
2048:           }
2049:           detJ = J[0]*J[3] - J[1]*J[2];
2050:         }
2051:         PetscLogFlopsNoError(8.0 + 3.0);
2052:       }
2053:       if (invJ) {
2054:         invDet  = 1.0/detJ;
2055:         invJ[0] =  invDet*J[3];
2056:         invJ[1] = -invDet*J[1];
2057:         invJ[2] = -invDet*J[2];
2058:         invJ[3] =  invDet*J[0];
2059:         PetscLogFlopsNoError(5.0);
2060:       }
2061:     };
2062:     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) {
2063:       const PetscReal *coords = this->restrictClosure(coordinates, e);
2064:       const int        dim    = 2;
2065:       typename real_section_type::value_type invDet;

2067:       if (v0) {
2068:         for(int d = 0; d < dim; d++) {
2069:           v0[d] = coords[d];
2070:         }
2071:       }
2072:       if (J) {
2073:         for(int d = 0; d < dim; d++) {
2074:           for(int f = 0; f < dim; f++) {
2075:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2076:           }
2077:         }
2078:         detJ = J[0]*J[3] - J[1]*J[2];
2079:         PetscLogFlopsNoError(8.0 + 3.0);
2080:       }
2081:       if (invJ) {
2082:         invDet  = 1.0/detJ;
2083:         invJ[0] =  invDet*J[3];
2084:         invJ[1] = -invDet*J[1];
2085:         invJ[2] = -invDet*J[2];
2086:         invJ[3] =  invDet*J[0];
2087:         PetscLogFlopsNoError(5.0);
2088:       }
2089:       detJ *= 2.0;
2090:     };
2091:     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) {
2092:       const PetscReal *coords = this->restrictClosure(coordinates, e);
2093:       const int        dim    = 3;
2094:       typename real_section_type::value_type           invDet;

2096:       if (v0) {
2097:         for(int d = 0; d < dim; d++) {
2098:           v0[d] = coords[d];
2099:         }
2100:       }
2101:       if (J) {
2102:         for(int d = 0; d < dim; d++) {
2103:           for(int f = 0; f < dim; f++) {
2104:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2105:           }
2106:         }
2107:         // The minus sign is here since I orient the first face to get the outward normal
2108:         detJ = -(J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2109:                  J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2110:                  J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
2111:         PetscLogFlopsNoError(18.0 + 12.0);
2112:       }
2113:       if (invJ) {
2114:         invDet  = -1.0/detJ;
2115:         invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2116:         invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
2117:         invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2118:         invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2119:         invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
2120:         invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2121:         invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2122:         invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
2123:         invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2124:         PetscLogFlopsNoError(37.0);
2125:       }
2126:     };
2127:     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) {
2128:       const PetscReal *coords = this->restrictClosure(coordinates, e);
2129:       const int        dim    = 3;
2130:       typename real_section_type::value_type invDet;

2132:       if (v0) {
2133:         for(int d = 0; d < dim; d++) {
2134:           v0[d] = coords[d];
2135:         }
2136:       }
2137:       if (J) {
2138:         for(int d = 0; d < dim; d++) {
2139:           J[d*dim+0] = 0.5*(coords[(0+1)*dim+d] - coords[0*dim+d]);
2140:           J[d*dim+1] = 0.5*(coords[(1+1)*dim+d] - coords[0*dim+d]);
2141:           J[d*dim+2] = 0.5*(coords[(3+1)*dim+d] - coords[0*dim+d]);
2142:         }
2143:         detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2144:                 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2145:                 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
2146:         PetscLogFlopsNoError(18.0 + 12.0);
2147:       }
2148:       if (invJ) {
2149:         invDet  = -1.0/detJ;
2150:         invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2151:         invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
2152:         invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2153:         invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2154:         invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
2155:         invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2156:         invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2157:         invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
2158:         invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2159:         PetscLogFlopsNoError(37.0);
2160:       }
2161:       detJ *= 8.0;
2162:     };
2163:     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) {
2164:       const int coneSize = this->getSieve()->getConeSize(e);

2166:       if (this->_dim == 2) {
2167:         if (coneSize == 3) {
2168:           computeTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
2169:         } else if (coneSize == 4) {
2170:           computeRectangleGeometry(coordinates, e, v0, J, invJ, detJ);
2171:         } else {
2172:           throw ALE::Exception("Unsupported coneSize for element geometry computation");
2173:         }
2174:       } else if (this->_dim == 3) {
2175:         if (coneSize == 4) {
2176:           computeTetrahedronGeometry(coordinates, e, v0, J, invJ, detJ);
2177:         } else if (coneSize == 8) {
2178:           computeHexahedronGeometry(coordinates, e, v0, J, invJ, detJ);
2179:         } else {
2180:           throw ALE::Exception("Unsupported coneSize for element geometry computation");
2181:         }
2182:       } else {
2183:         throw ALE::Exception("Unsupported dimension for element geometry computation");
2184:       }
2185:     };
2186:     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) {
2187:       const typename real_section_type::value_type *coords = this->restrictClosure(coordinates, e);
2188:       const int     dim    = 2;
2189:       typename real_section_type::value_type        invDet;

2191:       if (v0) {
2192:         for(int d = 0; d < dim; d++) {
2193:           v0[d] = coords[d];
2194:         }
2195:       }
2196:       if (J) {
2197:         //r2   = coords[1*dim+0]*coords[1*dim+0] + coords[1*dim+1]*coords[1*dim+1];
2198:         J[0] =  (coords[1*dim+0] - coords[0*dim+0])*0.5; J[1] = (-coords[1*dim+1] + coords[0*dim+1])*0.5;
2199:         J[2] =  (coords[1*dim+1] - coords[0*dim+1])*0.5; J[3] = ( coords[1*dim+0] - coords[0*dim+0])*0.5;
2200:         detJ = J[0]*J[3] - J[1]*J[2];
2201:         if (detJ < 0.0) {
2202:           const typename real_section_type::value_type  xLength = this->_periodicity[0];

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

2207:             if (v0x == 0.0) {
2208:               v0x = v0[0] = xLength;
2209:             }
2210:             for(int f = 0; f < dim; f++) {
2211:               const typename real_section_type::value_type px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];

2213:               J[0*dim+f] = 0.5*(px - v0x);
2214:             }
2215:           }
2216:           detJ = J[0]*J[3] - J[1]*J[2];
2217:         }
2218:         PetscLogFlopsNoError(8.0 + 3.0);
2219:       }
2220:       if (invJ) {
2221:         invDet  = 1.0/detJ;
2222:         invJ[0] =  invDet*J[3];
2223:         invJ[1] = -invDet*J[1];
2224:         invJ[2] = -invDet*J[2];
2225:         invJ[3] =  invDet*J[0];
2226:         PetscLogFlopsNoError(5.0);
2227:       }
2228:     };
2229:     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) {
2230:       if (this->_dim == 1) {
2231:         computeBdSegmentGeometry(coordinates, e, v0, J, invJ, detJ);
2232:         //      } else if (this->_dim == 2) {
2233:         //        computeBdTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
2234:       } else {
2235:         throw ALE::Exception("Unsupported dimension for element geometry computation");
2236:       }
2237:     };
2238:     typename real_section_type::value_type getMaxVolume() {
2239:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
2240:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
2241:       const int                     dim         = this->getDimension();
2242:       typename real_section_type::value_type v0[3], J[9], invJ[9], detJ, refVolume = 0.0, maxVolume = 0.0;

2244:       if (dim == 1) refVolume = 2.0;
2245:       if (dim == 2) refVolume = 2.0;
2246:       if (dim == 3) refVolume = 4.0/3.0;
2247:       for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
2248:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
2249:         maxVolume = std::max(maxVolume, detJ*refVolume);
2250:       }
2251:       return maxVolume;
2252:     };
2253:   public:
2254:     void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
2255:       if (comm == MPI_COMM_NULL) {
2256:         comm = this->comm();
2257:       }
2258:       if (name == "") {
2259:         PetscPrintf(comm, "viewing a Mesh\n");
2260:       } else {
2261:         PetscPrintf(comm, "viewing Mesh '%s'\n", name.c_str());
2262:       }
2263:       this->getSieve()->view("mesh sieve", comm);
2264:       Obj<names_type> sections = this->getRealSections();

2266:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2267:         this->getRealSection(*name)->view(*name);
2268:       }
2269:       sections = this->getIntSections();
2270:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2271:         this->getIntSection(*name)->view(*name);
2272:       }
2273:       sections = this->getArrowSections();
2274:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2275:         this->getArrowSection(*name)->view(*name);
2276:       }
2277:     };
2278:   public: // Discretization
2279:     void markBoundaryCells(const std::string& name, const int marker = 1, const int newMarker = 2, const bool onlyVertices = false) {
2280:       const Obj<label_type>&                  label    = this->getLabel(name);
2281:       const Obj<label_sequence>&              boundary = this->getLabelStratum(name, marker);
2282:       const typename label_sequence::iterator end      = boundary->end();
2283:       const Obj<sieve_type>&                  sieve    = this->getSieve();

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

2288:         for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != end; ++e_iter) {
2289:           if (this->height(*e_iter) == 1) {
2290:             sieve->support(*e_iter, mV);
2291:           }
2292:         }
2293:       } else {
2294: #if 1
2295:         throw ALE::Exception("Rewrite this to first mark boundary edges/faces.");
2296: #else
2297:         const int depth = this->depth();

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

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

2307:             for(typename sieve_type::traits::coneSequence::iterator e_iter = cone->begin(); e_iter != cEnd; ++e_iter) {
2308:               if (sieve->support(*e_iter)->size() == 1) {
2309:                 this->setValue(label, *c_iter, newMarker);
2310:                 break;
2311:               }
2312:             }
2313:           }
2314:         }
2315: #endif
2316:       }
2317:     };
2318:     int setFiberDimensions(const Obj<real_section_type>& s, const Obj<names_type>& discs, names_type& bcLabels) {
2319:       const int debug  = this->debug();
2320:       int       maxDof = 0;

2322:       for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter) {
2323:         s->addSpace();
2324:       }
2325:       for(int d = 0; d <= this->_dim; ++d) {
2326:         int numDof = 0;
2327:         int f      = 0;

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

2333:           numDof += sDof;
2334:           if (sDof) s->setFiberDimension(this->depthStratum(d), sDof, f);
2335:         }
2336:         if (numDof) s->setFiberDimension(this->depthStratum(d), numDof);
2337:         maxDof = std::max(maxDof, numDof);
2338:       }
2339:       // Process exclusions
2340:       typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2341:       int f = 0;

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

2349:         if (this->hasLabel(labelName)) {
2350:           const Obj<label_type>&                  label     = this->getLabel(labelName);
2351:           const Obj<label_sequence>&              exclusion = this->getLabelStratum(labelName, 1);
2352:           const typename label_sequence::iterator end       = exclusion->end();
2353:           if (debug > 1) {label->view(labelName.c_str());}

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

2360:             for(int cl = 0; cl < oSize; ++cl) {
2361:               if (seen.find(oPoints[cl]) != seen.end()) continue;
2362:               if (this->getValue(label, oPoints[cl]) == 1) {
2363:                 seen.insert(oPoints[cl]);
2364:                 s->setFiberDimension(oPoints[cl], 0, f);
2365:                 s->addFiberDimension(oPoints[cl], -disc->getNumDof(this->depth(oPoints[cl])));
2366:                 if (debug > 1) {std::cout << "  point: " << oPoints[cl] << " dim: " << disc->getNumDof(this->depth(oPoints[cl])) << std::endl;}
2367:               }
2368:             }
2369:             pV.clear();
2370:           }
2371:         }
2372:       }
2373:       // Process constraints
2374:       f = 0;
2375:       for(std::set<std::string>::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2376:         const Obj<ALE::Discretization>&   disc        = this->getDiscretization(*f_iter);
2377:         const Obj<std::set<std::string> > bcs         = disc->getBoundaryConditions();
2378:         std::string                       excludeName = "exclude-"+*f_iter;

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

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

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

2392:                 if (numDof) s->addConstraintDimension(*e_iter, numDof);
2393:                 if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
2394:               }
2395:             }
2396:           } else {
2397:             for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
2398:               const int numDof = disc->getNumDof(this->depth(*e_iter));

2400:               if (numDof) s->addConstraintDimension(*e_iter, numDof);
2401:               if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
2402:             }
2403:           }
2404:         }
2405:       }
2406:       return maxDof;
2407:     };
2408:     void calculateIndices() {
2409:       typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2410:       // Should have an iterator over the whole tree
2411:       Obj<names_type> discs = this->getDiscretizations();
2412:       const int       debug = this->debug();
2413:       std::map<std::string, std::pair<int, int*> > indices;

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

2418:         indices[*d_iter] = std::pair<int, int*>(0, new int[disc->sizeV(*this)]);
2419:         disc->setIndices(indices[*d_iter].second);
2420:       }
2421:       const Obj<label_sequence>& cells   = this->heightStratum(0);
2422:       Visitor pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, true);
2423:       ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), *cells->begin(), pV);
2424:       const typename Visitor::point_type *oPoints = pV.getPoints();
2425:       const int                           oSize   = pV.getSize();
2426:       int                                 offset  = 0;

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

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

2437:           if (debug > 1) {std::cout << "    disc " << disc->getName() << " numDof " << num << std::endl;}
2438:           for(int o = 0; o < num; ++o) {
2439:             indices[*d_iter].second[indices[*d_iter].first++] = offset++;
2440:           }
2441:         }
2442:       }
2443:       pV.clear();
2444:       if (debug > 1) {
2445:         for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
2446:           const Obj<Discretization>& disc = this->getDiscretization(*d_iter);

2448:           std::cout << "Discretization " << disc->getName() << " indices:";
2449:           for(int i = 0; i < indices[*d_iter].first; ++i) {
2450:             std::cout << " " << indices[*d_iter].second[i];
2451:           }
2452:           std::cout << std::endl;
2453:         }
2454:       }
2455:     };
2456:     void calculateIndicesExcluded(const Obj<real_section_type>& s, const Obj<names_type>& discs) {
2457:       typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2458:       typedef std::map<std::string, std::pair<int, indexSet> > indices_type;
2459:       const Obj<label_type>& indexLabel = this->createLabel("cellExclusion");
2460:       const int debug  = this->debug();
2461:       int       marker = 0;
2462:       std::map<indices_type, int> indexMap;
2463:       indices_type                indices;
2464:       Visitor pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, true);

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

2470:         indices[*d_iter].second.resize(size);
2471:       }
2472:       const typename names_type::const_iterator dBegin = discs->begin();
2473:       const typename names_type::const_iterator dEnd   = discs->end();
2474:       std::set<point_type> seen;
2475:       int f = 0;

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

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

2484:           if (debug > 1) {std::cout << "Processing exclusion " << labelName << std::endl;}
2485:           for(typename label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
2486:             if (this->height(*e_iter)) continue;
2487:             ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), *e_iter, pV);
2488:             const typename Visitor::point_type *oPoints = pV.getPoints();
2489:             const int                           oSize   = pV.getSize();
2490:             int                                 offset  = 0;

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

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

2500:                 if (debug > 1) {std::cout << "      disc " << *g_iter << " numDof " << fDim << std::endl;}
2501:                 for(int d = 0; d < fDim; ++d) {
2502:                   indices[*g_iter].second[indices[*g_iter].first++] = offset++;
2503:                 }
2504:               }
2505:             }
2506:             pV.clear();
2507:             const std::map<indices_type, int>::iterator entry = indexMap.find(indices);

2509:             if (debug > 1) {
2510:               for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
2511:                 for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2512:                   std::cout << "Discretization (" << i_iter->second << ") " << *g_iter << " indices:";
2513:                   for(int i = 0; i < ((indices_type) i_iter->first)[*g_iter].first; ++i) {
2514:                     std::cout << " " << ((indices_type) i_iter->first)[*g_iter].second[i];
2515:                   }
2516:                   std::cout << std::endl;
2517:                 }
2518:                 std::cout << "Comparison: " << (indices == i_iter->first) << std::endl;
2519:               }
2520:               for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2521:                 std::cout << "Discretization " << *g_iter << " indices:";
2522:                 for(int i = 0; i < indices[*g_iter].first; ++i) {
2523:                   std::cout << " " << indices[*g_iter].second[i];
2524:                 }
2525:                 std::cout << std::endl;
2526:               }
2527:             }
2528:             if (entry != indexMap.end()) {
2529:               this->setValue(indexLabel, *e_iter, entry->second);
2530:               if (debug > 1) {std::cout << "  Found existing indices with marker " << entry->second << std::endl;}
2531:             } else {
2532:               indexMap[indices] = ++marker;
2533:               this->setValue(indexLabel, *e_iter, marker);
2534:               if (debug > 1) {std::cout << "  Created new indices with marker " << marker << std::endl;}
2535:             }
2536:             for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2537:               indices[*g_iter].first  = 0;
2538:               for(unsigned int i = 0; i < indices[*g_iter].second.size(); ++i) indices[*g_iter].second[i] = 0;
2539:             }
2540:           }
2541:         }
2542:       }
2543:       if (debug > 1) {indexLabel->view("cellExclusion");}
2544:       for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
2545:         if (debug > 1) {std::cout << "Setting indices for marker " << i_iter->second << std::endl;}
2546:         for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2547:           const Obj<Discretization>& disc = this->getDiscretization(*g_iter);
2548:           const indexSet  indSet   = ((indices_type) i_iter->first)[*g_iter].second;
2549:           const int       size     = indSet.size();
2550:           int            *_indices = new int[size];

2552:           if (debug > 1) {std::cout << "  field " << *g_iter << std::endl;}
2553:           for(int i = 0; i < size; ++i) {
2554:             _indices[i] = indSet[i];
2555:             if (debug > 1) {std::cout << "    indices["<<i<<"] = " << _indices[i] << std::endl;}
2556:           }
2557:           disc->setIndices(_indices, i_iter->second);
2558:         }
2559:       }
2560:     };
2561:     void setupField(const Obj<real_section_type>& s, const int cellMarker = 2, const bool noUpdate = false) {
2562:       typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2563:       const Obj<names_type>& discs  = this->getDiscretizations();
2564:       const int              debug  = s->debug();
2565:       names_type             bcLabels;

2567:       s->setChart(this->getSieve()->getChart());
2568:       this->_maxDof = this->setFiberDimensions(s, discs, bcLabels);
2569:       this->calculateIndices();
2570:       this->calculateIndicesExcluded(s, discs);
2571:       this->allocate(s);
2572:       s->defaultConstraintDof();
2573:       const Obj<label_type>& cellExclusion = this->getLabel("cellExclusion");

2575:       if (debug > 1) {std::cout << "Setting boundary values" << std::endl;}
2576:       for(typename names_type::const_iterator n_iter = bcLabels.begin(); n_iter != bcLabels.end(); ++n_iter) {
2577:         const Obj<label_sequence>&              boundaryCells = this->getLabelStratum(*n_iter, cellMarker);
2578:         const Obj<real_section_type>&           coordinates   = this->getRealSection("coordinates");
2579:         const Obj<names_type>&                  discs         = this->getDiscretizations();
2580:         const point_type                        firstCell     = *boundaryCells->begin();
2581:         const int                               numFields     = discs->size();
2582:         typename real_section_type::value_type *values        = new typename real_section_type::value_type[this->sizeWithBC(s, firstCell)];
2583:         int                                    *dofs          = new int[this->_maxDof];
2584:         int                                    *v             = new int[numFields];
2585:         typename real_section_type::value_type *v0            = new typename real_section_type::value_type[this->getDimension()];
2586:         typename real_section_type::value_type *J             = new typename real_section_type::value_type[this->getDimension()*this->getDimension()];
2587:         typename real_section_type::value_type  detJ;
2588:         Visitor pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, true);

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

2595:           if (debug > 1) {std::cout << "  Boundary cell " << *c_iter << std::endl;}
2596:           this->computeElementGeometry(coordinates, *c_iter, v0, J, PETSC_NULL, detJ);
2597:           for(int f = 0; f < numFields; ++f) v[f] = 0;
2598:           for(int cl = 0; cl < oSize; ++cl) {
2599:             const int cDim = s->getConstraintDimension(oPoints[cl]);
2600:             int       off  = 0;
2601:             int       f    = 0;
2602:             int       i    = -1;

2604:             if (debug > 1) {std::cout << "    point " << oPoints[cl] << std::endl;}
2605:             if (cDim) {
2606:               if (debug > 1) {std::cout << "      constrained excMarker: " << this->getValue(cellExclusion, *c_iter) << std::endl;}
2607:               for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2608:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
2609:                 const Obj<names_type>           bcs     = disc->getBoundaryConditions();
2610:                 const int                       fDim    = s->getFiberDimension(oPoints[cl], f);//disc->getNumDof(this->depth(oPoints[cl]));
2611:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
2612:                 int                             b       = 0;

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

2618:                   if (b > 0) v[f] -= fDim;
2619:                   if (value == bc->getMarker()) {
2620:                     if (debug > 1) {std::cout << "      field " << *f_iter << " marker " << value << std::endl;}
2621:                     for(int d = 0; d < fDim; ++d, ++v[f]) {
2622:                       dofs[++i] = off+d;
2623:                       if (!noUpdate) values[indices[v[f]]] = (*bc->getDualIntegrator())(v0, J, v[f], bc->getFunction());
2624:                       if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2625:                     }
2626:                     // Allow only one condition per point
2627:                     ++b;
2628:                     break;
2629:                   } else {
2630:                     if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
2631:                     for(int d = 0; d < fDim; ++d, ++v[f]) {
2632:                       values[indices[v[f]]] = 0.0;
2633:                       if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2634:                     }
2635:                   }
2636:                 }
2637:                 if (b == 0) {
2638:                   if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
2639:                   for(int d = 0; d < fDim; ++d, ++v[f]) {
2640:                     values[indices[v[f]]] = 0.0;
2641:                     if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2642:                   }
2643:                 }
2644:                 off += fDim;
2645:               }
2646:               if (i != cDim-1) {throw ALE::Exception("Invalid constraint initialization");}
2647:               s->setConstraintDof(oPoints[cl], dofs);
2648:             } else {
2649:               if (debug > 1) {std::cout << "      unconstrained" << std::endl;}
2650:               for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2651:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
2652:                 const int                       fDim    = s->getFiberDimension(oPoints[cl], f);//disc->getNumDof(this->depth(oPoints[cl]));
2653:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));

2655:                 if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
2656:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
2657:                   values[indices[v[f]]] = 0.0;
2658:                   if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2659:                 }
2660:               }
2661:             }
2662:           }
2663:           if (debug > 1) {
2664:             for(int f = 0; f < numFields; ++f) v[f] = 0;
2665:             for(int cl = 0; cl < oSize; ++cl) {
2666:               int f = 0;
2667:               for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2668:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
2669:                 const int                       fDim    = s->getFiberDimension(oPoints[cl], f);
2670:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));

2672:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
2673:                   std::cout << "    "<<*f_iter<<"-value["<<indices[v[f]]<<"] " << values[indices[v[f]]] << std::endl;
2674:                 }
2675:               }
2676:             }
2677:           }
2678:           if (!noUpdate) {
2679:             this->updateAll(s, *c_iter, values);
2680:           }
2681:           pV.clear();
2682:         }
2683:         delete [] dofs;
2684:         delete [] values;
2685:         delete [] v0;
2686:         delete [] J;
2687:       }
2688:       if (debug > 1) {s->view("");}
2689:     };
2690:   public:
2691:     // Take in a map for the cells labels
2692:     template<typename Section_>
2693:     void relabel(Section_& labeling) {
2694:       this->getSieve()->relabel(labeling);
2695:       // Relabel sections
2696:       Obj<std::set<std::string> > realNames = this->getRealSections();

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

2701:         section->setName(*n_iter);
2702:         ALE::Ordering<>::relabelSection(*this->getRealSection(*n_iter), labeling, *section);
2703:         this->setRealSection(*n_iter, section);
2704:       }
2705:       Obj<std::set<std::string> > intNames = this->getIntSections();

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

2710:         section->setName(*n_iter);
2711:         ALE::Ordering<>::relabelSection(*this->getIntSection(*n_iter), labeling, *section);
2712:         this->setIntSection(*n_iter, section);
2713:       }
2714:       // Relabel labels
2715:       const labels_type& labels = this->getLabels();

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

2720:         l_iter->second->relabel(labeling, *label);
2721:         this->setLabel(l_iter->first, label);
2722:       }
2723:       // Relabel overlap
2724:       Obj<send_overlap_type> sendOverlap = new send_overlap_type(this->comm(), this->debug());
2725:       Obj<recv_overlap_type> recvOverlap = new recv_overlap_type(this->comm(), this->debug());

2727:       this->getSendOverlap()->relabel(labeling, *sendOverlap);
2728:       this->setSendOverlap(sendOverlap);
2729:       this->getRecvOverlap()->relabel(labeling, *recvOverlap);
2730:       this->setRecvOverlap(recvOverlap);
2731:       // Relabel distribution overlap ???
2732:       // Relabel renumbering
2733:     }
2734:   };
2735: }

2737: namespace ALE {
2738:   template<typename IndexType, typename ScalarType>
2739:   class Mesh : public Bundle<ALE::Sieve<IndexType,IndexType,IndexType>, GeneralSection<IndexType,ScalarType> > {
2740:   public:
2741:     typedef Bundle<ALE::Sieve<IndexType,IndexType,IndexType>, GeneralSection<IndexType,ScalarType> > base_type;
2742:     typedef typename base_type::sieve_type            sieve_type;
2743:     typedef typename sieve_type::point_type           point_type;
2744:     typedef typename base_type::alloc_type            alloc_type;
2745:     typedef typename base_type::label_type            label_type;
2746:     typedef typename base_type::label_sequence        label_sequence;
2747:     typedef typename base_type::coneArray             coneArray;
2748:     typedef typename base_type::supportArray          supportArray;
2749:     typedef typename base_type::arrow_section_type    arrow_section_type;
2750:     typedef typename base_type::real_section_type     real_section_type;
2751:     typedef typename base_type::numbering_type        numbering_type;
2752:     typedef typename base_type::order_type            order_type;
2753:     typedef typename base_type::send_overlap_type     send_overlap_type;
2754:     typedef typename base_type::recv_overlap_type     recv_overlap_type;
2755:     typedef typename base_type::sieve_alg_type        sieve_alg_type;
2756:     typedef std::set<std::string>            names_type;
2757:     typedef std::map<std::string, Obj<Discretization> > discretizations_type;
2758:     typedef std::vector<PETSc::Point<3> >    holes_type;
2759:   protected:
2760:     int                  _dim;
2761:     discretizations_type _discretizations;
2762:     std::map<int,double> _periodicity;
2763:     holes_type           _holes;
2764:   public:
2765:     Mesh(MPI_Comm comm, int dim, int debug = 0) : base_type(comm, debug), _dim(dim) {
2766:       ///this->_factory = MeshNumberingFactory::singleton(debug);
2767:       //std::cout << "["<<this->commRank()<<"]: Creating an ALE::Mesh" << std::endl;
2768:     };
2769:     ~Mesh() {
2770:       //std::cout << "["<<this->commRank()<<"]: Destroying an ALE::Mesh" << std::endl;
2771:     };
2772:   public: // Accessors
2773:     int getDimension() const {return this->_dim;};
2774:     void setDimension(const int dim) {this->_dim = dim;};
2775:     const Obj<Discretization>& getDiscretization() {return this->getDiscretization("default");};
2776:     const Obj<Discretization>& getDiscretization(const std::string& name) {return this->_discretizations[name];};
2777:     void setDiscretization(const Obj<Discretization>& disc) {this->setDiscretization("default", disc);};
2778:     void setDiscretization(const std::string& name, const Obj<Discretization>& disc) {this->_discretizations[name] = disc;};
2779:     Obj<names_type> getDiscretizations() const {
2780:       Obj<names_type> names = names_type();

2782:       for(discretizations_type::const_iterator d_iter = this->_discretizations.begin(); d_iter != this->_discretizations.end(); ++d_iter) {
2783:         names->insert(d_iter->first);
2784:       }
2785:       return names;
2786:     };
2787:     bool getPeriodicity(const int d) {return this->_periodicity[d];};
2788:     void setPeriodicity(const int d, const double length) {this->_periodicity[d] = length;};
2789:     const holes_type& getHoles() const {return this->_holes;};
2790:     void addHole(const double hole[]) {
2791:       this->_holes.push_back(hole);
2792:     };
2793:     void copyHoles(const Obj<Mesh>& m) {
2794:       const holes_type& holes = m->getHoles();

2796:       for(holes_type::const_iterator h_iter = holes.begin(); h_iter != holes.end(); ++h_iter) {
2797:         this->_holes.push_back(*h_iter);
2798:       }
2799:     };
2800:     void copy(const Obj<Mesh>& m) {
2801:       this->setSieve(m->getSieve());
2802:       this->setLabel("height", m->getLabel("height"));
2803:       this->_maxHeight = m->height();
2804:       this->setLabel("depth", m->getLabel("depth"));
2805:       this->_maxDepth  = m->depth();
2806:       this->setLabel("marker", m->getLabel("marker"));
2807:       this->setRealSection("coordinates", m->getRealSection("coordinates"));
2808:       this->setArrowSection("orientation", m->getArrowSection("orientation"));
2809:     };
2810:   public: // Cell topology and geometry
2811:     int getNumCellCorners(const point_type& p, const int depth = -1) const {
2812:       return (this->getDimension() > 0) ? this->_sieve->nCone(p, depth < 0 ? this->depth() : depth)->size() : 1;
2813:     };
2814:     int getNumCellCorners() {
2815:       return getNumCellCorners(*(this->heightStratum(0)->begin()));
2816:     };
2817:     void setupCoordinates(const Obj<real_section_type>& coordinates) {};
2818:     void computeTriangleGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2819:       const double *coords = this->restrictClosure(coordinates, e);
2820:       const int     dim    = 2;
2821:       double        invDet;

2823:       if (v0) {
2824:         for(int d = 0; d < dim; d++) {
2825:           v0[d] = coords[d];
2826:         }
2827:       }
2828:       if (J) {
2829:         for(int d = 0; d < dim; d++) {
2830:           for(int f = 0; f < dim; f++) {
2831:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2832:           }
2833:         }
2834:         detJ = J[0]*J[3] - J[1]*J[2];
2835:         if (detJ < 0.0) {
2836:           const double  xLength = this->_periodicity[0];

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

2841:             if (v0x == 0.0) {
2842:               v0x = v0[0] = xLength;
2843:             }
2844:             for(int f = 0; f < dim; f++) {
2845:               const double px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];

2847:               J[0*dim+f] = 0.5*(px - v0x);
2848:             }
2849:           }
2850:           detJ = J[0]*J[3] - J[1]*J[2];
2851:         }
2852:         PetscLogFlopsNoError(8.0 + 3.0);
2853:       }
2854:       if (invJ) {
2855:         invDet  = 1.0/detJ;
2856:         invJ[0] =  invDet*J[3];
2857:         invJ[1] = -invDet*J[1];
2858:         invJ[2] = -invDet*J[2];
2859:         invJ[3] =  invDet*J[0];
2860:         PetscLogFlopsNoError(5.0);
2861:       }
2862:     };
2863:     void computeQuadrilateralGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double point[], double v0[], double J[], double invJ[], double& detJ) {
2864:       const double *coords = this->restrictClosure(coordinates, e);
2865:       const int     dim    = 2;
2866:       double        invDet;

2868:       if (v0) {
2869:         for(int d = 0; d < dim; d++) {
2870:           v0[d] = coords[d];
2871:         }
2872:       }
2873:       if (J) {
2874:         double x_1 = coords[2] - coords[0];
2875:         double y_1 = coords[3] - coords[1];
2876:         double x_2 = coords[6] - coords[0];
2877:         double y_2 = coords[7] - coords[1];
2878:         double x_3 = coords[4] - coords[0];
2879:         double y_3 = coords[5] - coords[1];

2881:         J[0] = x_1 + (x_3 - x_1 - x_2)*point[1];
2882:         J[1] = x_2 + (x_3 - x_1 - x_2)*point[0];
2883:         J[2] = y_1 + (y_3 - y_1 - y_2)*point[1];
2884:         J[3] = y_1 + (y_3 - y_1 - y_2)*point[0];
2885:         detJ = J[0]*J[3] - J[1]*J[2];
2886:         PetscLogFlopsNoError(6.0 + 16.0 + 3.0);
2887:       }
2888:       if (invJ) {
2889:         invDet  = 1.0/detJ;
2890:         invJ[0] =  invDet*J[3];
2891:         invJ[1] = -invDet*J[1];
2892:         invJ[2] = -invDet*J[2];
2893:         invJ[3] =  invDet*J[0];
2894:         PetscLogFlopsNoError(5.0);
2895:       }
2896:     };
2897:     void computeTetrahedronGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2898:       const double *coords = this->restrictClosure(coordinates, e);
2899:       const int     dim    = 3;
2900:       double        invDet;

2902:       if (v0) {
2903:         for(int d = 0; d < dim; d++) {
2904:           v0[d] = coords[d];
2905:         }
2906:       }
2907:       if (J) {
2908:         for(int d = 0; d < dim; d++) {
2909:           for(int f = 0; f < dim; f++) {
2910:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2911:           }
2912:         }
2913:         // The minus sign is here since I orient the first face to get the outward normal
2914:         detJ = -(J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2915:                  J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2916:                  J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
2917:         PetscLogFlopsNoError(18.0 + 12.0);
2918:       }
2919:       if (invJ) {
2920:         invDet  = -1.0/detJ;
2921:         invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2922:         invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
2923:         invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2924:         invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2925:         invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
2926:         invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2927:         invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2928:         invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
2929:         invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2930:         PetscLogFlopsNoError(37.0);
2931:       }
2932:     };
2933:     void computeHexahedralGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double point[], double v0[], double J[], double invJ[], double& detJ) {
2934:       const double *coords = this->restrictClosure(coordinates, e);
2935:       const int     dim    = 3;
2936:       double        invDet;

2938:       if (v0) {
2939:         for(int d = 0; d < dim; d++) {
2940:           v0[d] = coords[d];
2941:         }
2942:       }
2943:       if (J) {
2944:         double x_1 = coords[3]  - coords[0];
2945:         double y_1 = coords[4]  - coords[1];
2946:         double z_1 = coords[5]  - coords[2];
2947:         double x_2 = coords[6]  - coords[0];
2948:         double y_2 = coords[7]  - coords[1];
2949:         double z_2 = coords[8]  - coords[2];
2950:         double x_3 = coords[9]  - coords[0];
2951:         double y_3 = coords[10] - coords[1];
2952:         double z_3 = coords[11] - coords[2];
2953:         double x_4 = coords[12] - coords[0];
2954:         double y_4 = coords[13] - coords[1];
2955:         double z_4 = coords[14] - coords[2];
2956:         double x_5 = coords[15] - coords[0];
2957:         double y_5 = coords[16] - coords[1];
2958:         double z_5 = coords[17] - coords[2];
2959:         double x_6 = coords[18] - coords[0];
2960:         double y_6 = coords[19] - coords[1];
2961:         double z_6 = coords[20] - coords[2];
2962:         double x_7 = coords[21] - coords[0];
2963:         double y_7 = coords[22] - coords[1];
2964:         double z_7 = coords[23] - coords[2];
2965:         double g_x = x_1 - x_2 + x_3 + x_4 - x_5 + x_6 - x_7;
2966:         double g_y = y_1 - y_2 + y_3 + y_4 - y_5 + y_6 - y_7;
2967:         double g_z = z_1 - z_2 + z_3 + z_4 - z_5 + z_6 - z_7;

2969:         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];
2970:         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];
2971:         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];
2972:         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];
2973:         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];
2974:         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];
2975:         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];
2976:         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];
2977:         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];
2978:         detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2979:                 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2980:                 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
2981:         PetscLogFlopsNoError(39.0 + 81.0 + 12.0);
2982:       }
2983:       if (invJ) {
2984:         invDet  = 1.0/detJ;
2985:         invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2986:         invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
2987:         invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2988:         invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2989:         invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
2990:         invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2991:         invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2992:         invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
2993:         invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2994:         PetscLogFlopsNoError(37.0);
2995:       }
2996:     };
2997:     void computeElementGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2998:       if (this->_dim == 2) {
2999:         computeTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
3000:       } else if (this->_dim == 3) {
3001:         computeTetrahedronGeometry(coordinates, e, v0, J, invJ, detJ);
3002:       } else {
3003:         throw ALE::Exception("Unsupported dimension for element geometry computation");
3004:       }
3005:     };
3006:     void computeLineFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
3007:       const typename arrow_section_type::point_type arrow(cell, face);
3008:       const bool reversed = (this->getArrowSection("orientation")->restrictPoint(arrow)[0] == -2);
3009:       const int  dim      = this->getDimension();
3010:       double     norm     = 0.0;
3011:       double    *vec      = tangent;

3013:       if (f == 0) {
3014:         vec[0] = 0.0;        vec[1] = -1.0;
3015:       } else if (f == 1) {
3016:         vec[0] = 0.70710678; vec[1] = 0.70710678;
3017:       } else if (f == 2) {
3018:         vec[0] = -1.0;       vec[1] = 0.0;
3019:       }
3020:       for(int d = 0; d < dim; ++d) {
3021:         normal[d] = 0.0;
3022:         for(int e = 0; e < dim; ++e) normal[d] += cellInvJ[e*dim+d]*vec[e];
3023:         if (reversed) normal[d] = -normal[d];
3024:         norm += normal[d]*normal[d];
3025:       }
3026:       norm = std::sqrt(norm);
3027:       for(int d = 0; d < dim; ++d) {
3028:         normal[d] /= norm;
3029:       }
3030:       tangent[0] =  normal[1];
3031:       tangent[1] = -normal[0];
3032:       if (this->debug()) {
3033:         std::cout << "Cell: " << cell << " Face: " << face << "("<<f<<")" << std::endl;
3034:         for(int d = 0; d < dim; ++d) {
3035:           std::cout << "Normal["<<d<<"]: " << normal[d] << " Tangent["<<d<<"]: " << tangent[d] << std::endl;
3036:         }
3037:       }
3038:       // Now get 1D Jacobian info
3039:       //   Should be a way to get this directly
3040:       const double *coords = this->restrictClosure(this->getRealSection("coordinates"), face);
3041:       detJ    = std::sqrt(PetscSqr(coords[1*2+0] - coords[0*2+0]) + PetscSqr(coords[1*2+1] - coords[0*2+1]))/2.0;
3042:       invJ[0] = 1.0/detJ;
3043:     };
3044:     void computeTriangleFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
3045:       const typename arrow_section_type::point_type arrow(cell, face);
3046:       const bool reversed = this->getArrowSection("orientation")->restrictPoint(arrow)[0] < 0;
3047:       const int  dim      = this->getDimension();
3048:       const int  faceDim  = dim-1;
3049:       double     norm     = 0.0;
3050:       double    *vec      = tangent;

3052:       if (f == 0) {
3053:         vec[0] = 0.0;        vec[1] = 0.0;        vec[2] = -1.0;
3054:       } else if (f == 1) {
3055:         vec[0] = 0.0;        vec[1] = -1.0;       vec[2] = 0.0;
3056:       } else if (f == 2) {
3057:         vec[0] = 0.57735027; vec[1] = 0.57735027; vec[2] = 0.57735027;
3058:       } else if (f == 3) {
3059:         vec[0] = -1.0;       vec[1] = 0.0;        vec[2] = 0.0;
3060:       }
3061:       for(int d = 0; d < dim; ++d) {
3062:         normal[d] = 0.0;
3063:         for(int e = 0; e < dim; ++e) normal[d] += cellInvJ[e*dim+d]*vec[e];
3064:         if (reversed) normal[d] = -normal[d];
3065:         norm += normal[d]*normal[d];
3066:       }
3067:       norm = std::sqrt(norm);
3068:       for(int d = 0; d < dim; ++d) {
3069:         normal[d] /= norm;
3070:       }
3071:       // Get tangents
3072:       tangent[0] = normal[1] - normal[2];
3073:       tangent[1] = normal[2] - normal[0];
3074:       tangent[2] = normal[0] - normal[1];
3075:       norm = 0.0;
3076:       for(int d = 0; d < dim; ++d) {
3077:         norm += tangent[d]*tangent[d];
3078:       }
3079:       norm = std::sqrt(norm);
3080:       for(int d = 0; d < dim; ++d) {
3081:         tangent[d] /= norm;
3082:       }
3083:       tangent[3] = normal[1]*tangent[2] - normal[2]*tangent[1];
3084:       tangent[4] = normal[2]*tangent[0] - normal[0]*tangent[2];
3085:       tangent[5] = normal[0]*tangent[1] - normal[1]*tangent[0];
3086:       if (this->debug()) {
3087:         std::cout << "Cell: " << cell << " Face: " << face << "("<<f<<")" << std::endl;
3088:         for(int d = 0; d < dim; ++d) {
3089:           std::cout << "Normal["<<d<<"]: " << normal[d] << " TangentA["<<d<<"]: " << tangent[d] << " TangentB["<<d<<"]: " << tangent[dim+d] << std::endl;
3090:         }
3091:       }
3092:       // Now get 2D Jacobian info
3093:       //   Should be a way to get this directly
3094:       const double *coords = this->restrictClosure(this->getRealSection("coordinates"), face);
3095:       // Rotate so that normal in z
3096:       double invR[9], R[9];
3097:       double detR, invDetR;
3098:       for(int d = 0; d < dim; d++) {
3099:         invR[d*dim+0] = tangent[d];
3100:         invR[d*dim+1] = tangent[dim+d];
3101:         invR[d*dim+2] = normal[d];
3102:       }
3103:       invDetR = (invR[0*3+0]*(invR[1*3+1]*invR[2*3+2] - invR[1*3+2]*invR[2*3+1]) +
3104:                  invR[0*3+1]*(invR[1*3+2]*invR[2*3+0] - invR[1*3+0]*invR[2*3+2]) +
3105:                  invR[0*3+2]*(invR[1*3+0]*invR[2*3+1] - invR[1*3+1]*invR[2*3+0]));
3106:       detR  = 1.0/invDetR;
3107:       R[0*3+0] = detR*(invR[1*3+1]*invR[2*3+2] - invR[1*3+2]*invR[2*3+1]);
3108:       R[0*3+1] = detR*(invR[0*3+2]*invR[2*3+1] - invR[0*3+1]*invR[2*3+2]);
3109:       R[0*3+2] = detR*(invR[0*3+1]*invR[1*3+2] - invR[0*3+2]*invR[1*3+1]);
3110:       R[1*3+0] = detR*(invR[1*3+2]*invR[2*3+0] - invR[1*3+0]*invR[2*3+2]);
3111:       R[1*3+1] = detR*(invR[0*3+0]*invR[2*3+2] - invR[0*3+2]*invR[2*3+0]);
3112:       R[1*3+2] = detR*(invR[0*3+2]*invR[1*3+0] - invR[0*3+0]*invR[1*3+2]);
3113:       R[2*3+0] = detR*(invR[1*3+0]*invR[2*3+1] - invR[1*3+1]*invR[2*3+0]);
3114:       R[2*3+1] = detR*(invR[0*3+1]*invR[2*3+0] - invR[0*3+0]*invR[2*3+1]);
3115:       R[2*3+2] = detR*(invR[0*3+0]*invR[1*3+1] - invR[0*3+1]*invR[1*3+0]);
3116:       for(int d = 0; d < dim; d++) {
3117:         for(int e = 0; e < dim; e++) {
3118:           invR[d*dim+e] = 0.0;
3119:           for(int g = 0; g < dim; g++) {
3120:             invR[d*dim+e] += R[e*dim+g]*coords[d*dim+g];
3121:           }
3122:         }
3123:       }
3124:       for(int d = dim-1; d >= 0; --d) {
3125:         invR[d*dim+2] -= invR[0*dim+2];
3126:         if (this->debug() && (d == dim-1)) {
3127:           double ref[9];
3128:           for(int q = 0; q < dim; q++) {
3129:             for(int e = 0; e < dim; e++) {
3130:               ref[q*dim+e] = 0.0;
3131:               for(int g = 0; g < dim; g++) {
3132:                 ref[q*dim+e] += cellInvJ[e*dim+g]*coords[q*dim+g];
3133:               }
3134:             }
3135:           }
3136:           std::cout << "f: " << f << std::endl;
3137:           std::cout << this->printMatrix(std::string("coords"), dim, dim, coords) << std::endl;
3138:           std::cout << this->printMatrix(std::string("ref coords"), dim, dim, ref) << std::endl;
3139:           std::cout << this->printMatrix(std::string("R"), dim, dim, R) << std::endl;
3140:           std::cout << this->printMatrix(std::string("invR"), dim, dim, invR) << std::endl;
3141:         }
3142:         if (fabs(invR[d*dim+2]) > 1.0e-8) {
3143:           throw ALE::Exception("Invalid rotation");
3144:         }
3145:       }
3146:       double J[4];
3147:       for(int d = 0; d < faceDim; d++) {
3148:         for(int e = 0; e < faceDim; e++) {
3149:           J[d*faceDim+e] = 0.5*(invR[(e+1)*dim+d] - invR[0*dim+d]);
3150:         }
3151:       }
3152:       detJ = fabs(J[0]*J[3] - J[1]*J[2]);
3153:       // Probably need something here if detJ < 0
3154:       const double invDet = 1.0/detJ;
3155:       invJ[0] =  invDet*J[3];
3156:       invJ[1] = -invDet*J[1];
3157:       invJ[2] = -invDet*J[2];
3158:       invJ[3] =  invDet*J[0];
3159:     };
3160:     void computeFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
3161:       if (this->_dim == 2) {
3162:         computeLineFaceGeometry(cell, face, f, cellInvJ, invJ, detJ, normal, tangent);
3163:       } else if (this->_dim == 3) {
3164:         computeTriangleFaceGeometry(cell, face, f, cellInvJ, invJ, detJ, normal, tangent);
3165:       } else {
3166:         throw ALE::Exception("Unsupported dimension for element geometry computation");
3167:       }
3168:     };
3169:     double getMaxVolume() {
3170:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3171:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
3172:       const int                     dim         = this->getDimension();
3173:       double v0[3], J[9], invJ[9], detJ, refVolume = 0.0, maxVolume = 0.0;

3175:       if (dim == 1) refVolume = 2.0;
3176:       if (dim == 2) refVolume = 2.0;
3177:       if (dim == 3) refVolume = 4.0/3.0;
3178:       for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
3179:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
3180:         maxVolume = std::max(maxVolume, detJ*refVolume);
3181:       }
3182:       return maxVolume;
3183:     };
3184:     // Find the cell in which this point lies (stupid algorithm)
3185:     point_type locatePoint_2D(const typename real_section_type::value_type point[]) {
3186:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3187:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
3188:       const int                     embedDim    = 2;
3189:       double v0[2], J[4], invJ[4], detJ;

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

3196:         if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) {
3197:           return *c_iter;
3198:         }
3199:       }
3200:       throw ALE::Exception("Could not locate point");
3201:     };
3202:     //   Assume a simplex and 3D
3203:     point_type locatePoint_3D(const typename real_section_type::value_type point[]) {
3204:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3205:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
3206:       const int                     embedDim    = 3;
3207:       double v0[3], J[9], invJ[9], detJ;

3209:       for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
3210:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
3211:         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]);
3212:         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]);
3213:         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]);

3215:         if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) {
3216:           return *c_iter;
3217:         }
3218:       }
3219:       throw ALE::Exception("Could not locate point");
3220:     };
3221:     point_type locatePoint(const typename real_section_type::value_type point[], point_type guess = -1) {
3222:       //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
3223:       if (guess != -1) {
3224:         return guess;
3225:       }else if (this->_dim == 2) {
3226:         return locatePoint_2D(point);
3227:       } else if (this->_dim == 3) {
3228:         return locatePoint_3D(point);
3229:       } else {
3230:         throw ALE::Exception("No point location for mesh dimension");
3231:       }
3232:     };
3233:   public: // Discretization
3234:     void markBoundaryCells(const std::string& name, const int marker = 1, const int newMarker = 2, const bool onlyVertices = false) {
3235:       const Obj<label_type>&     label    = this->getLabel(name);
3236:       const Obj<label_sequence>& boundary = this->getLabelStratum(name, marker);
3237:       const Obj<sieve_type>&     sieve    = this->getSieve();

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

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

3246:             this->setValue(label, cell, newMarker);
3247:           }
3248:         }
3249:       } else {
3250:         const typename label_sequence::iterator end   = boundary->end();
3251:         const int                      depth = this->depth();

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

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

3261:             for(typename sieve_type::traits::coneSequence::iterator e_iter = cone->begin(); e_iter != cEnd; ++e_iter) {
3262:               if (sieve->support(*e_iter)->size() == 1) {
3263:                 this->setValue(label, *c_iter, newMarker);
3264:                 break;
3265:               }
3266:             }
3267:           }
3268:         }
3269:       }
3270:     };
3271:     int setFiberDimensions(const Obj<real_section_type>& s, const Obj<names_type>& discs, names_type& bcLabels) {
3272:       const int debug  = this->debug();
3273:       int       maxDof = 0;

3275:       for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter) {
3276:         s->addSpace();
3277:       }
3278:       for(int d = 0; d <= this->_dim; ++d) {
3279:         int numDof = 0;
3280:         int f      = 0;

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

3286:           numDof += sDof;
3287:           if (sDof) s->setFiberDimension(this->depthStratum(d), sDof, f);
3288:         }
3289:         if (numDof) s->setFiberDimension(this->depthStratum(d), numDof);
3290:         maxDof = std::max(maxDof, numDof);
3291:       }
3292:       // Process exclusions
3293:       int f = 0;

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

3300:         if (this->hasLabel(labelName)) {
3301:           const Obj<label_type>&         label     = this->getLabel(labelName);
3302:           const Obj<label_sequence>&     exclusion = this->getLabelStratum(labelName, 1);
3303:           const typename label_sequence::iterator end       = exclusion->end();
3304:           if (debug > 1) {label->view(labelName.c_str());}

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

3310:             for(typename coneArray::iterator c_iter = closure->begin(); c_iter != cEnd; ++c_iter) {
3311:               if (seen.find(*c_iter) != seen.end()) continue;
3312:               if (this->getValue(label, *c_iter) == 1) {
3313:                 seen.insert(*c_iter);
3314:                 s->setFiberDimension(*c_iter, 0, f);
3315:                 s->addFiberDimension(*c_iter, -disc->getNumDof(this->depth(*c_iter)));
3316:                 if (debug > 1) {std::cout << "  cell: " << *c_iter << " dim: " << disc->getNumDof(this->depth(*c_iter)) << std::endl;}
3317:               }
3318:             }
3319:           }
3320:         }
3321:       }
3322:       // Process constraints
3323:       f = 0;
3324:       for(typename std::set<std::string>::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3325:         const Obj<ALE::Discretization>&    disc        = this->getDiscretization(*f_iter);
3326:         const Obj<std::set<std::string> >  bcs         = disc->getBoundaryConditions();
3327:         std::string                        excludeName = "exclude-"+*f_iter;

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

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

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

3341:                 if (numDof) s->addConstraintDimension(*e_iter, numDof);
3342:                 if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
3343:               }
3344:             }
3345:           } else {
3346:             for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
3347:               const int numDof = disc->getNumDof(this->depth(*e_iter));

3349:               if (numDof) s->addConstraintDimension(*e_iter, numDof);
3350:               if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
3351:             }
3352:           }
3353:         }
3354:       }
3355:       return maxDof;
3356:     };
3357:     void calculateIndices() {
3358:       // Should have an iterator over the whole tree
3359:       Obj<names_type> discs = this->getDiscretizations();
3360:       Obj<Mesh>       mesh  = this;
3361:       const int       debug = this->debug();
3362:       std::map<std::string, std::pair<int, int*> > indices;

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

3368:         indices[*d_iter] = std::pair<int, int*>(0, new int[disc->size(mesh)]);
3369:         disc->setIndices(indices[*d_iter].second);
3370:       }
3371:       const Obj<label_sequence>& cells   = this->heightStratum(0);
3372:       const Obj<coneArray>       closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *cells->begin());
3373:       const typename coneArray::iterator  end     = closure->end();
3374:       int                        offset  = 0;

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

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

3385:           if (debug > 1) {std::cout << "    disc " << disc->getName() << " numDof " << num << std::endl;}
3386:           for(int o = 0; o < num; ++o) {
3387:             indices[*d_iter].second[indices[*d_iter].first++] = offset++;
3388:           }
3389:         }
3390:       }
3391:       if (debug > 1) {
3392:         for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
3393:           const Obj<Discretization>& disc = this->getDiscretization(*d_iter);

3395:           std::cout << "Discretization " << disc->getName() << " indices:";
3396:           for(int i = 0; i < indices[*d_iter].first; ++i) {
3397:             std::cout << " " << indices[*d_iter].second[i];
3398:           }
3399:           std::cout << std::endl;
3400:         }
3401:       }
3402:     };
3403:     void calculateIndicesExcluded(const Obj<real_section_type>& s, const Obj<names_type>& discs) {
3404:       typedef std::map<std::string, std::pair<int, indexSet> > indices_type;
3405:       const Obj<label_type>& indexLabel = this->createLabel("cellExclusion");
3406:       const int debug  = this->debug();
3407:       int       marker = 0;
3408:       Obj<Mesh> mesh   = this;
3409:       std::map<indices_type, int> indexMap;
3410:       indices_type                indices;

3412:       mesh.addRef();
3413:       for(names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
3414:         const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
3415:         const int                  size = disc->size(mesh);

3417:         indices[*d_iter].second.resize(size);
3418:       }
3419:       const names_type::const_iterator dBegin = discs->begin();
3420:       const names_type::const_iterator dEnd   = discs->end();
3421:       std::set<point_type> seen;
3422:       int f = 0;

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

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

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

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

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

3446:                 if (debug > 1) {std::cout << "      disc " << *g_iter << " numDof " << fDim << std::endl;}
3447:                 for(int d = 0; d < fDim; ++d) {
3448:                   indices[*g_iter].second[indices[*g_iter].first++] = offset++;
3449:                 }
3450:               }
3451:             }
3452:             const typename std::map<indices_type, int>::iterator entry = indexMap.find(indices);

3454:             if (debug > 1) {
3455:               for(typename std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
3456:                 for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3457:                   std::cout << "Discretization (" << i_iter->second << ") " << *g_iter << " indices:";
3458:                   for(int i = 0; i < ((indices_type) i_iter->first)[*g_iter].first; ++i) {
3459:                     std::cout << " " << ((indices_type) i_iter->first)[*g_iter].second[i];
3460:                   }
3461:                   std::cout << std::endl;
3462:                 }
3463:                 std::cout << "Comparison: " << (indices == i_iter->first) << std::endl;
3464:               }
3465:               for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3466:                 std::cout << "Discretization " << *g_iter << " indices:";
3467:                 for(int i = 0; i < indices[*g_iter].first; ++i) {
3468:                   std::cout << " " << indices[*g_iter].second[i];
3469:                 }
3470:                 std::cout << std::endl;
3471:               }
3472:             }
3473:             if (entry != indexMap.end()) {
3474:               this->setValue(indexLabel, *e_iter, entry->second);
3475:               if (debug > 1) {std::cout << "  Found existing indices with marker " << entry->second << std::endl;}
3476:             } else {
3477:               indexMap[indices] = ++marker;
3478:               this->setValue(indexLabel, *e_iter, marker);
3479:               if (debug > 1) {std::cout << "  Created new indices with marker " << marker << std::endl;}
3480:             }
3481:             for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3482:               indices[*g_iter].first  = 0;
3483:               for(unsigned int i = 0; i < indices[*g_iter].second.size(); ++i) indices[*g_iter].second[i] = 0;
3484:             }
3485:           }
3486:         }
3487:       }
3488:       if (debug > 1) {indexLabel->view("cellExclusion");}
3489:       for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
3490:         if (debug > 1) {std::cout << "Setting indices for marker " << i_iter->second << std::endl;}
3491:         for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3492:           const Obj<Discretization>& disc = this->getDiscretization(*g_iter);
3493:           const indexSet  indSet   = ((indices_type) i_iter->first)[*g_iter].second;
3494:           const int       size     = indSet.size();
3495:           int            *_indices = new int[size];

3497:           if (debug > 1) {std::cout << "  field " << *g_iter << std::endl;}
3498:           for(int i = 0; i < size; ++i) {
3499:             _indices[i] = indSet[i];
3500:             if (debug > 1) {std::cout << "    indices["<<i<<"] = " << _indices[i] << std::endl;}
3501:           }
3502:           disc->setIndices(_indices, i_iter->second);
3503:         }
3504:       }
3505:     };
3506:     void setupField(const Obj<real_section_type>& s, const int cellMarker = 2, const bool noUpdate = false) {
3507:       const Obj<names_type>& discs  = this->getDiscretizations();
3508:       const int              debug  = s->debug();
3509:       names_type             bcLabels;
3510:       int                    maxDof;

3512:       maxDof = this->setFiberDimensions(s, discs, bcLabels);
3513:       this->calculateIndices();
3514:       this->calculateIndicesExcluded(s, discs);
3515:       this->allocate(s);
3516:       s->defaultConstraintDof();
3517:       const Obj<label_type>& cellExclusion = this->getLabel("cellExclusion");

3519:       if (debug > 1) {std::cout << "Setting boundary values" << std::endl;}
3520:       for(names_type::const_iterator n_iter = bcLabels.begin(); n_iter != bcLabels.end(); ++n_iter) {
3521:         const Obj<label_sequence>&     boundaryCells = this->getLabelStratum(*n_iter, cellMarker);
3522:         const Obj<real_section_type>&  coordinates   = this->getRealSection("coordinates");
3523:         const Obj<names_type>&         discs         = this->getDiscretizations();
3524:         const point_type               firstCell     = *boundaryCells->begin();
3525:         const int                      numFields     = discs->size();
3526:         typename real_section_type::value_type *values = new typename real_section_type::value_type[this->sizeWithBC(s, firstCell)];
3527:         int                           *dofs          = new int[maxDof];
3528:         int                           *v             = new int[numFields];
3529:         typename real_section_type::value_type *v0   = new typename real_section_type::value_type[this->getDimension()];
3530:         typename real_section_type::value_type *J    = new typename real_section_type::value_type[this->getDimension()*this->getDimension()];
3531:         typename real_section_type::value_type  detJ;

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

3537:           if (debug > 1) {std::cout << "  Boundary cell " << *c_iter << std::endl;}
3538:           this->computeElementGeometry(coordinates, *c_iter, v0, J, PETSC_NULL, detJ);
3539:           for(int f = 0; f < numFields; ++f) v[f] = 0;
3540:           for(typename coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
3541:             const int cDim = s->getConstraintDimension(*cl_iter);
3542:             int       off  = 0;
3543:             int       f    = 0;
3544:             int       i    = -1;

3546:             if (debug > 1) {std::cout << "    point " << *cl_iter << std::endl;}
3547:             if (cDim) {
3548:               if (debug > 1) {std::cout << "      constrained excMarker: " << this->getValue(cellExclusion, *c_iter) << std::endl;}
3549:               for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3550:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
3551:                 const Obj<names_type>           bcs     = disc->getBoundaryConditions();
3552:                 const int                       fDim    = s->getFiberDimension(*cl_iter, f);//disc->getNumDof(this->depth(*cl_iter));
3553:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
3554:                 int                             b       = 0;

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

3560:                   if (b > 0) v[f] -= fDim;
3561:                   if (value == bc->getMarker()) {
3562:                     if (debug > 1) {std::cout << "      field " << *f_iter << " marker " << value << std::endl;}
3563:                     for(int d = 0; d < fDim; ++d, ++v[f]) {
3564:                       dofs[++i] = off+d;
3565:                       if (!noUpdate) values[indices[v[f]]] = (*bc->getDualIntegrator())(v0, J, v[f], bc->getFunction());
3566:                       if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3567:                     }
3568:                     // Allow only one condition per point
3569:                     ++b;
3570:                     break;
3571:                   } else {
3572:                     if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
3573:                     for(int d = 0; d < fDim; ++d, ++v[f]) {
3574:                       values[indices[v[f]]] = 0.0;
3575:                       if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3576:                     }
3577:                   }
3578:                 }
3579:                 if (b == 0) {
3580:                   if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
3581:                   for(int d = 0; d < fDim; ++d, ++v[f]) {
3582:                     values[indices[v[f]]] = 0.0;
3583:                     if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3584:                   }
3585:                 }
3586:                 off += fDim;
3587:               }
3588:               if (i != cDim-1) {throw ALE::Exception("Invalid constraint initialization");}
3589:               s->setConstraintDof(*cl_iter, dofs);
3590:             } else {
3591:               if (debug > 1) {std::cout << "      unconstrained" << std::endl;}
3592:               for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3593:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
3594:                 const int                       fDim    = s->getFiberDimension(*cl_iter, f);//disc->getNumDof(this->depth(*cl_iter));
3595:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));

3597:                 if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
3598:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
3599:                   values[indices[v[f]]] = 0.0;
3600:                   if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3601:                 }
3602:               }
3603:             }
3604:           }
3605:           if (debug > 1) {
3606:             const Obj<coneArray>      closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *c_iter);
3607:             const typename coneArray::iterator end     = closure->end();

3609:             for(int f = 0; f < numFields; ++f) v[f] = 0;
3610:             for(typename coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
3611:               int f = 0;
3612:               for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3613:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
3614:                 const int                       fDim    = s->getFiberDimension(*cl_iter, f);
3615:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));

3617:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
3618:                   std::cout << "    "<<*f_iter<<"-value["<<indices[v[f]]<<"] " << values[indices[v[f]]] << std::endl;
3619:                 }
3620:               }
3621:             }
3622:           }
3623:           if (!noUpdate) {
3624:             this->updateAll(s, *c_iter, values);
3625:           }
3626:         }
3627:         delete [] dofs;
3628:         delete [] values;
3629:         delete [] v0;
3630:         delete [] J;
3631:       }
3632:       if (debug > 1) {s->view("");}
3633:     };
3634:   public:
3635:     void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
3636:       if (comm == MPI_COMM_NULL) {
3637:         comm = this->comm();
3638:       }
3639:       if (name == "") {
3640:         PetscPrintf(comm, "viewing a Mesh\n");
3641:       } else {
3642:         PetscPrintf(comm, "viewing Mesh '%s'\n", name.c_str());
3643:       }
3644:       this->getSieve()->view("mesh sieve", comm);
3645:       Obj<names_type> sections = this->getRealSections();

3647:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
3648:         this->getRealSection(*name)->view(*name);
3649:       }
3650:       sections = this->getIntSections();
3651:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
3652:         this->getIntSection(*name)->view(*name);
3653:       }
3654:       sections = this->getArrowSections();
3655:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
3656:         this->getArrowSection(*name)->view(*name);
3657:       }
3658:     };
3659:     template<typename value_type>
3660:     static std::string printMatrix(const std::string& name, const int rows, const int cols, const value_type matrix[], const int rank = -1)
3661:     {
3662:       ostringstream output;
3663:       ostringstream rankStr;

3665:       if (rank >= 0) {
3666:         rankStr << "[" << rank << "]";
3667:       }
3668:       output << rankStr.str() << name << " = " << std::endl;
3669:       for(int r = 0; r < rows; r++) {
3670:         if (r == 0) {
3671:           output << rankStr.str() << " /";
3672:         } else if (r == rows-1) {
3673:           output << rankStr.str() << " \\";
3674:         } else {
3675:           output << rankStr.str() << " |";
3676:         }
3677:         for(int c = 0; c < cols; c++) {
3678:           output << " " << matrix[r*cols+c];
3679:         }
3680:         if (r == 0) {
3681:           output << " \\" << std::endl;
3682:         } else if (r == rows-1) {
3683:           output << " /" << std::endl;
3684:         } else {
3685:           output << " |" << std::endl;
3686:         }
3687:       }
3688:       return output.str();
3689:     }
3690:   };
3691:   template<typename Mesh>
3692:   class MeshBuilder {
3693:   public:
3694:     typedef typename Mesh::real_section_type::value_type real;
3695:   public:
3698:     /*
3699:       Simple square boundary:

3701:      18--5-17--4--16
3702:       |     |     |
3703:       6    10     3
3704:       |     |     |
3705:      19-11-20--9--15
3706:       |     |     |
3707:       7     8     2
3708:       |     |     |
3709:      12--0-13--1--14
3710:     */
3711:     static Obj<Mesh> createSquareBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int edges[], const int debug = 0) {
3712:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
3713:       int       numVertices = (edges[0]+1)*(edges[1]+1);
3714:       int       numEdges    = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
3715:       real     *coords      = new real[numVertices*2];
3716:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
3717:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];
3718:       int                         order    = 0;

3720:       mesh->setSieve(sieve);
3721:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
3722:       if (mesh->commRank() == 0) {
3723:         /* Create sieve and ordering */
3724:         for(int v = numEdges; v < numEdges+numVertices; v++) {
3725:           vertices[v-numEdges] = typename Mesh::point_type(v);
3726:         }
3727:         for(int vy = 0; vy <= edges[1]; vy++) {
3728:           for(int ex = 0; ex < edges[0]; ex++) {
3729:             typename Mesh::point_type edge(vy*edges[0] + ex);
3730:             int vertex = vy*(edges[0]+1) + ex;

3732:             sieve->addArrow(vertices[vertex+0], edge, order++);
3733:             sieve->addArrow(vertices[vertex+1], edge, order++);
3734:             if ((vy == 0) || (vy == edges[1])) {
3735:               mesh->setValue(markers, edge, 1);
3736:               mesh->setValue(markers, vertices[vertex], 1);
3737:               if (ex == edges[0]-1) {
3738:                 mesh->setValue(markers, vertices[vertex+1], 1);
3739:               }
3740:             }
3741:           }
3742:         }
3743:         for(int vx = 0; vx <= edges[0]; vx++) {
3744:           for(int ey = 0; ey < edges[1]; ey++) {
3745:             typename Mesh::point_type edge(vx*edges[1] + ey + edges[0]*(edges[1]+1));
3746:             int vertex = ey*(edges[0]+1) + vx;

3748:             sieve->addArrow(vertices[vertex],            edge, order++);
3749:             sieve->addArrow(vertices[vertex+edges[0]+1], edge, order++);
3750:             if ((vx == 0) || (vx == edges[0])) {
3751:               mesh->setValue(markers, edge, 1);
3752:               mesh->setValue(markers, vertices[vertex], 1);
3753:               if (ey == edges[1]-1) {
3754:                 mesh->setValue(markers, vertices[vertex+edges[0]+1], 1);
3755:               }
3756:             }
3757:           }
3758:         }
3759:       }
3760:       mesh->stratify();
3761:       for(int vy = 0; vy <= edges[1]; ++vy) {
3762:         for(int vx = 0; vx <= edges[0]; ++vx) {
3763:           coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
3764:           coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
3765:         }
3766:       }
3767:       delete [] vertices;
3768:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
3769:       return mesh;
3770:     };
3773:     /*
3774:       Simple square boundary:

3776:      14--5-13--4--12
3777:       |           |
3778:       6           3
3779:       |           |
3780:      15           11
3781:       |           |
3782:       7           2
3783:       |           |
3784:       8--0--9--1--10
3785:     */
3786:     static Obj<Mesh> createSquareBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int edges, const int debug = 0) {
3787:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
3788:       int       numVertices = edges*4;
3789:       int       numEdges    = edges*4;
3790:       real     *coords      = new real[numVertices*2];
3791:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
3792:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];

3794:       mesh->setSieve(sieve);
3795:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
3796:       if (mesh->commRank() == 0) {
3797:         /* Create sieve and ordering */
3798:         for(int v = numEdges; v < numEdges+numVertices; v++) {
3799:           vertices[v-numEdges] = typename Mesh::point_type(v);
3800:         }
3801:         for(int e = 0; e < numEdges; ++e) {
3802:           typename Mesh::point_type edge(e);
3803:           int order = 0;

3805:           sieve->addArrow(vertices[e],                 edge, order++);
3806:           sieve->addArrow(vertices[(e+1)%numVertices], edge, order++);
3807:           mesh->setValue(markers, edge, 2);
3808:           mesh->setValue(markers, vertices[e], 1);
3809:           mesh->setValue(markers, vertices[(e+1)%numVertices], 1);
3810:         }
3811:       }
3812:       mesh->stratify();
3813:       for(int v = 0; v < edges; ++v) {
3814:         coords[(v+edges*0)*2+0] = lower[0] + ((upper[0] - lower[0])/edges)*v;
3815:         coords[(v+edges*0)*2+1] = lower[1];
3816:       }
3817:       for(int v = 0; v < edges; ++v) {
3818:         coords[(v+edges*1)*2+0] = upper[0];
3819:         coords[(v+edges*1)*2+1] = lower[1] + ((upper[1] - lower[1])/edges)*v;
3820:       }
3821:       for(int v = 0; v < edges; ++v) {
3822:         coords[(v+edges*2)*2+0] = upper[0] - ((upper[0] - lower[0])/edges)*v;
3823:         coords[(v+edges*2)*2+1] = upper[1];
3824:       }
3825:       for(int v = 0; v < edges; ++v) {
3826:         coords[(v+edges*3)*2+0] = lower[0];
3827:         coords[(v+edges*3)*2+1] = upper[1] - ((upper[1] - lower[1])/edges)*v;
3828:       }
3829:       delete [] vertices;
3830:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
3831:       // Build normals for cells
3832:       const Obj<typename Mesh::real_section_type>& normals = mesh->getRealSection("normals");
3833:       const Obj<typename Mesh::label_sequence>&    cells   = mesh->heightStratum(0);

3835:       //normals->setChart(typename Mesh::real_section_type::chart_type(*std::min_element(cells->begin(), cells->end()),
3836:       //                                                               *std::max_element(cells->begin(), cells->end())+1));
3837:       normals->setFiberDimension(cells, mesh->getDimension()+1);
3838:       mesh->allocate(normals);
3839:       for(int e = 0; e < edges; ++e) {
3840:         real normal[2] = {0.0, -1.0};
3841:         normals->updatePoint(e+edges*0, normal);
3842:       }
3843:       for(int e = 0; e < edges; ++e) {
3844:         real normal[2] = {1.0, 0.0};
3845:         normals->updatePoint(e+edges*1, normal);
3846:       }
3847:       for(int e = 0; e < edges; ++e) {
3848:         real normal[2] = {0.0, 1.0};
3849:         normals->updatePoint(e+edges*2, normal);
3850:       }
3851:       for(int e = 0; e < edges; ++e) {
3852:         real normal[2] = {-1.0, 0.0};
3853:         normals->updatePoint(e+edges*3, normal);
3854:       }
3855:       return mesh;
3856:     };
3859:     /*
3860:       Simple square boundary:

3862:      18--5-17--4--16
3863:       |     |     |
3864:       6    10     3
3865:       |     |     |
3866:      19-11-20--9--15
3867:       |     |     |
3868:       7     8     2
3869:       |     |     |
3870:      12--0-13--1--14
3871:     */
3872:     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) {
3873:       Obj<Mesh> mesh              = new Mesh(comm, 1, debug);
3874:       const int numSquareVertices = (edges[0]+1)*(edges[1]+1);
3875:       const int numVertices       = numSquareVertices + partEdges;
3876:       const int numSquareEdges    = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
3877:       const int numEdges          = numSquareEdges + partEdges;
3878:       real   *coords            = new real[numVertices*2];
3879:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
3880:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];
3881:       int                         order    = 0;

3883:       mesh->setSieve(sieve);
3884:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
3885:       if (mesh->commRank() == 0) {
3886:         /* Create sieve and ordering */
3887:         for(int v = numEdges; v < numEdges+numVertices; v++) {
3888:           vertices[v-numEdges] = typename Mesh::point_type(v);
3889:         }
3890:         // Make square
3891:         for(int vy = 0; vy <= edges[1]; vy++) {
3892:           for(int ex = 0; ex < edges[0]; ex++) {
3893:             typename Mesh::point_type edge(vy*edges[0] + ex);
3894:             int vertex = vy*(edges[0]+1) + ex;

3896:             sieve->addArrow(vertices[vertex+0], edge, order++);
3897:             sieve->addArrow(vertices[vertex+1], edge, order++);
3898:             if ((vy == 0) || (vy == edges[1])) {
3899:               mesh->setValue(markers, edge, 1);
3900:               mesh->setValue(markers, vertices[vertex], 1);
3901:               if (ex == edges[0]-1) {
3902:                 mesh->setValue(markers, vertices[vertex+1], 1);
3903:               }
3904:             }
3905:           }
3906:         }
3907:         for(int vx = 0; vx <= edges[0]; vx++) {
3908:           for(int ey = 0; ey < edges[1]; ey++) {
3909:             typename Mesh::point_type edge(vx*edges[1] + ey + edges[0]*(edges[1]+1));
3910:             int vertex = ey*(edges[0]+1) + vx;

3912:             sieve->addArrow(vertices[vertex],            edge, order++);
3913:             sieve->addArrow(vertices[vertex+edges[0]+1], edge, order++);
3914:             if ((vx == 0) || (vx == edges[0])) {
3915:               mesh->setValue(markers, edge, 1);
3916:               mesh->setValue(markers, vertices[vertex], 1);
3917:               if (ey == edges[1]-1) {
3918:                 mesh->setValue(markers, vertices[vertex+edges[0]+1], 1);
3919:               }
3920:             }
3921:           }
3922:         }
3923:         // Make particle
3924:         for(int ep = 0; ep < partEdges; ++ep) {
3925:           typename Mesh::point_type edge(numSquareEdges + ep);
3926:           const int vertexA = numSquareVertices + ep;
3927:           const int vertexB = numSquareVertices + (ep+1)%partEdges;

3929:           sieve->addArrow(vertices[vertexA], edge, order++);
3930:           sieve->addArrow(vertices[vertexB], edge, order++);
3931:           mesh->setValue(markers, edge, 2);
3932:           mesh->setValue(markers, vertices[vertexA], 2);
3933:           mesh->setValue(markers, vertices[vertexB], 2);
3934:         }
3935:       }
3936:       mesh->stratify();
3937:       for(int vy = 0; vy <= edges[1]; ++vy) {
3938:         for(int vx = 0; vx <= edges[0]; ++vx) {
3939:           coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
3940:           coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
3941:         }
3942:       }
3943:       const real centroidX = 0.5*(upper[0] + lower[0]);
3944:       const real centroidY = 0.5*(upper[1] + lower[1]);
3945:       for(int vp = 0; vp < partEdges; ++vp) {
3946:         const real rad = 2.0*PETSC_PI*vp/partEdges;
3947:         coords[(numSquareVertices+vp)*2+0] = centroidX + radius*cos(rad);
3948:         coords[(numSquareVertices+vp)*2+1] = centroidY + radius*sin(rad);
3949:       }
3950:       delete [] vertices;
3951:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
3952:       return mesh;
3953:     };
3956:     /*
3957:       Simple boundary with reentrant singularity:

3959:      12--5-11
3960:       |     |
3961:       |     4
3962:       |     |
3963:       6    10--3--9
3964:       |           |
3965:       |           2
3966:       |           |
3967:       7-----1-----8
3968:     */
3969:     static Obj<Mesh> createReentrantBoundary(const MPI_Comm comm, const real lower[], const real upper[], real notchpercent[], const int debug = 0) {
3970:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
3971:       int       numVertices = 6;
3972:       int       numEdges    = numVertices;
3973:       real   *coords      = new real[numVertices*2];
3974:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
3975:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];

3977:       mesh->setSieve(sieve);
3978:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
3979:       if (mesh->commRank() == 0) {
3980:         /* Create sieve and ordering */
3981:         for (int b = 0; b < numVertices; b++) {
3982:           sieve->addArrow(numEdges+b, b);
3983:           sieve->addArrow(numEdges+b, (b+1)%numVertices);
3984:           mesh->setValue(markers, b, 1);
3985:           mesh->setValue(markers, b+numVertices, 1);
3986:         }
3987:         coords[0] = upper[0];
3988:         coords[1] = lower[1];

3990:         coords[2] = lower[0];
3991:         coords[3] = lower[1];
3992: 
3993:         coords[4] = lower[0];
3994:         coords[5] = notchpercent[1]*lower[1] + (1 - notchpercent[1])*upper[1];
3995: 
3996:         coords[6] = notchpercent[0]*upper[0] + (1 - notchpercent[0])*lower[0];
3997:         coords[7] = notchpercent[1]*lower[1] + (1 - notchpercent[1])*upper[1];
3998: 
3999: 
4000:         coords[8] = notchpercent[0]*upper[0] + (1 - notchpercent[0])*lower[0];
4001:         coords[9] = upper[1];

4003:         coords[10] = upper[0];
4004:         coords[11] = upper[1];
4005:         mesh->stratify();
4006:       }
4007:       delete [] vertices;
4008:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4009:       return mesh;
4010:     }

4014:     /*
4015:       Circular boundary with reentrant singularity:

4017:          ---1
4018:       --    |
4019:      -      |
4020:      |      |
4021:      |      0-----n
4022:      |            |
4023:      -           -
4024:       --       --
4025:         -------
4026:     */
4027:     static Obj<Mesh> createCircularReentrantBoundary(const MPI_Comm comm, const int segments, const real radius, const real arc_percent, const int debug = 0) {
4028:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
4029:       int       numVertices = segments+2;
4030:       int       numEdges    = numVertices;
4031:       real   *coords      = new real[numVertices*2];
4032:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4033:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];

4035:       mesh->setSieve(sieve);
4036:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4037:       if (mesh->commRank() == 0) {
4038:         /* Create sieve and ordering */

4040:         int startvertex = 1;
4041:         if (arc_percent < 1.) {
4042:           coords[0] = 0.;
4043:           coords[1] = 0.;
4044:         } else {
4045:           numVertices = segments;
4046:           numEdges = numVertices;
4047:           startvertex = 0;
4048:         }

4050:         for (int b = 0; b < numVertices; b++) {
4051:           sieve->addArrow(numEdges+b, b);
4052:           sieve->addArrow(numEdges+b, (b+1)%numVertices);
4053:           mesh->setValue(markers, b, 1);
4054:           mesh->setValue(markers, b+numVertices, 1);
4055:         }

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

4059:         for (int i = startvertex; i < numVertices; i++) {
4060:           coords[2*i] = radius * sin(anglestep*(i-startvertex));
4061:           coords[2*i+1] = radius*cos(anglestep*(i-startvertex));
4062:         }
4063:         mesh->stratify();
4064:       }
4065:       delete [] vertices;
4066:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4067:       return mesh;
4068:     };
4071:     static Obj<Mesh> createAnnularBoundary(const MPI_Comm comm, const int segments, const real centers[4], const real radii[2], const int debug = 0) {
4072:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
4073:       int       numVertices = segments*2;
4074:       int       numEdges    = numVertices;
4075:       real   *coords      = new real[numVertices*2];
4076:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4077:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];

4079:       mesh->setSieve(sieve);
4080:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4081:       if (mesh->commRank() == 0) {
4082:         for (int e = 0; e < segments; ++e) {
4083:           sieve->addArrow(numEdges+e,              e);
4084:           sieve->addArrow(numEdges+(e+1)%segments, e);
4085:           sieve->addArrow(numEdges+segments+e,              e+segments);
4086:           sieve->addArrow(numEdges+segments+(e+1)%segments, e+segments);
4087:           mesh->setValue(markers, e,          1);
4088:           mesh->setValue(markers, e+segments, 1);
4089:           mesh->setValue(markers, e+numEdges,          1);
4090:           mesh->setValue(markers, e+numEdges+segments, 1);
4091:         }
4092:         const real anglestep = 2.0*M_PI/segments;

4094:         for (int v = 0; v < segments; ++v) {
4095:           coords[v*2]              = centers[0] + radii[0]*cos(anglestep*v);
4096:           coords[v*2+1]            = centers[1] + radii[0]*sin(anglestep*v);
4097:           coords[(v+segments)*2]   = centers[2] + radii[1]*cos(anglestep*v);
4098:           coords[(v+segments)*2+1] = centers[3] + radii[1]*sin(anglestep*v);
4099:         }
4100:         mesh->addHole(&centers[2]);
4101:       }
4102:       mesh->stratify();
4103:       delete [] vertices;
4104:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4105:       return mesh;
4106:     };
4109:     /*
4110:       Simple cubic boundary:

4112:      30----31-----32
4113:       |     |     |
4114:       |  3  |  2  |
4115:       |     |     |
4116:      27----28-----29
4117:       |     |     |
4118:       |  0  |  1  |
4119:       |     |     |
4120:      24----25-----26
4121:     */
4122:     static Obj<Mesh> createCubeBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int faces[], const int debug = 0) {
4123:       Obj<Mesh> mesh        = new Mesh(comm, 2, debug);
4124:       int       numVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
4125:       int       numFaces    = 6;
4126:       real   *coords      = new real[numVertices*3];
4127:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4128:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];
4129:       int                         order    = 0;

4131:       mesh->setSieve(sieve);
4132:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4133:       if (mesh->commRank() == 0) {
4134:         /* Create sieve and ordering */
4135:         for(int v = numFaces; v < numFaces+numVertices; v++) {
4136:           vertices[v-numFaces] = typename Mesh::point_type(v);
4137:           mesh->setValue(markers, vertices[v-numFaces], 1);
4138:         }
4139:         {
4140:           // Side 0 (Front)
4141:           typename Mesh::point_type face(0);
4142:           sieve->addArrow(vertices[0], face, order++);
4143:           sieve->addArrow(vertices[1], face, order++);
4144:           sieve->addArrow(vertices[2], face, order++);
4145:           sieve->addArrow(vertices[3], face, order++);
4146:           mesh->setValue(markers, face, 1);
4147:         }
4148:         {
4149:           // Side 1 (Back)
4150:           typename Mesh::point_type face(1);
4151:           sieve->addArrow(vertices[5], face, order++);
4152:           sieve->addArrow(vertices[4], face, order++);
4153:           sieve->addArrow(vertices[7], face, order++);
4154:           sieve->addArrow(vertices[6], face, order++);
4155:           mesh->setValue(markers, face, 1);
4156:         }
4157:         {
4158:           // Side 2 (Bottom)
4159:           typename Mesh::point_type face(2);
4160:           sieve->addArrow(vertices[4], face, order++);
4161:           sieve->addArrow(vertices[5], face, order++);
4162:           sieve->addArrow(vertices[1], face, order++);
4163:           sieve->addArrow(vertices[0], face, order++);
4164:           mesh->setValue(markers, face, 1);
4165:         }
4166:         {
4167:           // Side 3 (Top)
4168:           typename Mesh::point_type face(3);
4169:           sieve->addArrow(vertices[3], face, order++);
4170:           sieve->addArrow(vertices[2], face, order++);
4171:           sieve->addArrow(vertices[6], face, order++);
4172:           sieve->addArrow(vertices[7], face, order++);
4173:           mesh->setValue(markers, face, 1);
4174:         }
4175:         {
4176:           // Side 4 (Left)
4177:           typename Mesh::point_type face(4);
4178:           sieve->addArrow(vertices[4], face, order++);
4179:           sieve->addArrow(vertices[0], face, order++);
4180:           sieve->addArrow(vertices[3], face, order++);
4181:           sieve->addArrow(vertices[7], face, order++);
4182:           mesh->setValue(markers, face, 1);
4183:         }
4184:         {
4185:           // Side 5 (Right)
4186:           typename Mesh::point_type face(5);
4187:           sieve->addArrow(vertices[1], face, order++);
4188:           sieve->addArrow(vertices[5], face, order++);
4189:           sieve->addArrow(vertices[6], face, order++);
4190:           sieve->addArrow(vertices[2], face, order++);
4191:           mesh->setValue(markers, face, 1);
4192:         }
4193:       }
4194:       mesh->stratify();
4195: #if 0
4196:       for(int vz = 0; vz <= edges[2]; ++vz) {
4197:         for(int vy = 0; vy <= edges[1]; ++vy) {
4198:           for(int vx = 0; vx <= edges[0]; ++vx) {
4199:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
4200:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
4201:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
4202:           }
4203:         }
4204:       }
4205: #else
4206:       coords[0*3+0] = lower[0];
4207:       coords[0*3+1] = lower[1];
4208:       coords[0*3+2] = upper[2];
4209:       coords[1*3+0] = upper[0];
4210:       coords[1*3+1] = lower[1];
4211:       coords[1*3+2] = upper[2];
4212:       coords[2*3+0] = upper[0];
4213:       coords[2*3+1] = upper[1];
4214:       coords[2*3+2] = upper[2];
4215:       coords[3*3+0] = lower[0];
4216:       coords[3*3+1] = upper[1];
4217:       coords[3*3+2] = upper[2];
4218:       coords[4*3+0] = lower[0];
4219:       coords[4*3+1] = lower[1];
4220:       coords[4*3+2] = lower[2];
4221:       coords[5*3+0] = upper[0];
4222:       coords[5*3+1] = lower[1];
4223:       coords[5*3+2] = lower[2];
4224:       coords[6*3+0] = upper[0];
4225:       coords[6*3+1] = upper[1];
4226:       coords[6*3+2] = lower[2];
4227:       coords[7*3+0] = lower[0];
4228:       coords[7*3+1] = upper[1];
4229:       coords[7*3+2] = lower[2];
4230: #endif
4231:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4232:       return mesh;
4233:     };

4235:     // Creates a triangular prism boundary
4236:     static Obj<Mesh> createPrismBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int debug = 0) {
4237:       Obj<Mesh> mesh        = new Mesh(comm, 2, debug);
4238:       int       numVertices = 6;
4239:       int       numFaces    = 5;
4240:       real   *coords      = new real[numVertices*3];
4241:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4242:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];
4243:       int                         order    = 0;

4245:       mesh->setSieve(sieve);
4246:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4247:       if (mesh->commRank() == 0) {
4248:         /* Create sieve and ordering */
4249:         for(int v = numFaces; v < numFaces+numVertices; v++) {
4250:           vertices[v-numFaces] = typename Mesh::point_type(v);
4251:           mesh->setValue(markers, vertices[v-numFaces], 1);
4252:         }
4253:         {
4254:           // Side 0 (Top)
4255:           typename Mesh::point_type face(0);
4256:           sieve->addArrow(vertices[0], face, order++);
4257:           sieve->addArrow(vertices[1], face, order++);
4258:           sieve->addArrow(vertices[2], face, order++);
4259:           mesh->setValue(markers, face, 1);
4260:         }
4261:         {
4262:           // Side 1 (Bottom)
4263:           typename Mesh::point_type face(1);
4264:           sieve->addArrow(vertices[3], face, order++);
4265:           sieve->addArrow(vertices[5], face, order++);
4266:           sieve->addArrow(vertices[4], face, order++);
4267:           mesh->setValue(markers, face, 1);
4268:         }
4269:         {
4270:           // Side 2 (Front)
4271:           typename Mesh::point_type face(2);
4272:           sieve->addArrow(vertices[0], face, order++);
4273:           sieve->addArrow(vertices[3], face, order++);
4274:           sieve->addArrow(vertices[4], face, order++);
4275:           sieve->addArrow(vertices[1], face, order++);
4276:           mesh->setValue(markers, face, 1);
4277:         }
4278:         {
4279:           // Side 3 (Left)
4280:           typename Mesh::point_type face(3);
4281:           sieve->addArrow(vertices[1], face, order++);
4282:           sieve->addArrow(vertices[4], face, order++);
4283:           sieve->addArrow(vertices[5], face, order++);
4284:           sieve->addArrow(vertices[2], face, order++);
4285:           mesh->setValue(markers, face, 1);
4286:         }
4287:         {
4288:           // Side 4 (Right)
4289:           typename Mesh::point_type face(4);
4290:           sieve->addArrow(vertices[2], face, order++);
4291:           sieve->addArrow(vertices[5], face, order++);
4292:           sieve->addArrow(vertices[3], face, order++);
4293:           sieve->addArrow(vertices[0], face, order++);
4294:           mesh->setValue(markers, face, 1);
4295:         }
4296:       }
4297:       mesh->stratify();
4298:       coords[0*3+0] = lower[0];
4299:       coords[0*3+1] = lower[1];
4300:       coords[0*3+2] = upper[2];
4301:       coords[1*3+0] = upper[0];
4302:       coords[1*3+1] = lower[1];
4303:       coords[1*3+2] = upper[2];
4304:       coords[2*3+0] = upper[0];
4305:       coords[2*3+1] = upper[1];
4306:       coords[2*3+2] = upper[2];
4307:       coords[3*3+0] = lower[0];
4308:       coords[3*3+1] = upper[1];
4309:       coords[3*3+2] = upper[2];
4310:       coords[4*3+0] = lower[0];
4311:       coords[4*3+1] = lower[1];
4312:       coords[4*3+2] = lower[2];
4313:       coords[5*3+0] = upper[0];
4314:       coords[5*3+1] = lower[1];
4315:       coords[5*3+2] = lower[2];
4316:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4317:       return mesh;
4318:     };

4322:     /*    v0
4323:          / \
4324:         /   \
4325:     2  /  4  \  1
4326:       /       \
4327:      /   v12   \
4328:   v6|\   /|\   /|v5
4329:     | \v8 | v7/ |          z  
4330:     |  |7 |8 |  |          | 
4331:     |  |v13\ |  |  <-v4   / \
4332:     | v9/ 9 \v10|        x   y
4333:  v1 | 5 \   / 6 |v2
4334:      \   \ /   /
4335:       \  v11  /
4336:        \  |  /
4337:      3  \ | /
4338:          \|/
4339:           v3
4340:     */
4341:     static Obj<Mesh> createFicheraCornerBoundary(const MPI_Comm comm, const real lower[], const real upper[], const real offset[], const int debug = 0) {
4342:       Obj<Mesh> mesh            = new Mesh(comm, 2, debug);
4343:       const int nVertices = 14;
4344:       const int nFaces = 12;
4345:       real ilower[3];
4346:       ilower[0] = lower[0]*(1. - offset[0]) + upper[0]*offset[0];
4347:       ilower[1] = lower[1]*(1. - offset[1]) + upper[1]*offset[1];
4348:       ilower[2] = lower[2]*(1. - offset[2]) + upper[2]*offset[2];
4349:       real coords[nVertices*3];
4350:       //outer square-triplet
4351:       coords[0*3+0] = lower[0];
4352:       coords[0*3+1] = lower[1];
4353:       coords[0*3+2] = upper[2];
4354:       coords[1*3+0] = upper[0];
4355:       coords[1*3+1] = lower[1];
4356:       coords[1*3+2] = lower[2];
4357:       coords[2*3+0] = lower[0];
4358:       coords[2*3+1] = upper[1];
4359:       coords[2*3+2] = lower[2];
4360:       coords[3*3+0] = upper[0];
4361:       coords[3*3+1] = upper[1];
4362:       coords[3*3+2] = lower[2];
4363:       coords[4*3+0] = lower[0];
4364:       coords[4*3+1] = lower[1];
4365:       coords[4*3+2] = lower[2];
4366:       coords[5*3+0] = lower[0];
4367:       coords[5*3+1] = upper[1];
4368:       coords[5*3+2] = upper[2];
4369:       coords[6*3+0] = upper[0];
4370:       coords[6*3+1] = lower[1];
4371:       coords[6*3+2] = upper[2];

4373:       //inner square-triplet
4374:       coords[7*3+0] = ilower[0];
4375:       coords[7*3+1] = upper[1];
4376:       coords[7*3+2] = upper[2];
4377:       coords[8*3+0] = upper[0];
4378:       coords[8*3+1] = ilower[1];
4379:       coords[8*3+2] = upper[2];
4380:       coords[9*3+0] = upper[0];
4381:       coords[9*3+1] = ilower[1];
4382:       coords[9*3+2] = ilower[2];
4383:       coords[10*3+0] = ilower[0];
4384:       coords[10*3+1] = upper[1];
4385:       coords[10*3+2] = ilower[2];
4386:       coords[11*3+0] = upper[0];
4387:       coords[11*3+1] = upper[1];
4388:       coords[11*3+2] = ilower[2];
4389:       coords[12*3+0] = ilower[0];
4390:       coords[12*3+1] = ilower[1];
4391:       coords[12*3+2] = upper[2];
4392:       coords[13*3+0] = ilower[0];
4393:       coords[13*3+1] = ilower[1];
4394:       coords[13*3+2] = ilower[2];

4396: 
4397:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4398:       mesh->setSieve(sieve);
4399:       typename Mesh::point_type p[nVertices];
4400:       typename Mesh::point_type f[nFaces];
4401:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4402:       for (int i = 0; i < nVertices; i++) {
4403:         p[i] = typename Mesh::point_type(i+nFaces);
4404:         mesh->setValue(markers, p[i], 1);
4405:       }
4406:       for (int i = 0; i < nFaces; i++) {
4407:         f[i] = typename Mesh::point_type(i);
4408:       }
4409:       int order = 0;
4410:      //assemble the larger square sides
4411:       sieve->addArrow(p[0], f[0], order++);
4412:       sieve->addArrow(p[5], f[0], order++);
4413:       sieve->addArrow(p[2], f[0], order++);
4414:       sieve->addArrow(p[4], f[0], order++);
4415:       mesh->setValue(markers, f[0], 1);

4417:       sieve->addArrow(p[0], f[1], order++);
4418:       sieve->addArrow(p[4], f[1], order++);
4419:       sieve->addArrow(p[1], f[1], order++);
4420:       sieve->addArrow(p[6], f[1], order++);
4421:       mesh->setValue(markers, f[1], 1);

4423:       sieve->addArrow(p[4], f[2], order++);
4424:       sieve->addArrow(p[1], f[2], order++);
4425:       sieve->addArrow(p[3], f[2], order++);
4426:       sieve->addArrow(p[2], f[2], order++);
4427:       mesh->setValue(markers, f[2], 1);
4428: 
4429:       //assemble the L-shaped sides

4431:       sieve->addArrow(p[0], f[3], order++);
4432:       sieve->addArrow(p[12], f[3], order++);
4433:       sieve->addArrow(p[7], f[3], order++);
4434:       sieve->addArrow(p[5], f[3], order++);
4435:       mesh->setValue(markers, f[3], 1);

4437:       sieve->addArrow(p[0], f[4], order++);
4438:       sieve->addArrow(p[12],f[4], order++);
4439:       sieve->addArrow(p[8], f[4], order++);
4440:       sieve->addArrow(p[6], f[4], order++);
4441:       mesh->setValue(markers, f[4], 1);

4443:       sieve->addArrow(p[9], f[5], order++);
4444:       sieve->addArrow(p[1], f[5], order++);
4445:       sieve->addArrow(p[3], f[5], order++);
4446:       sieve->addArrow(p[11], f[5], order++);
4447:       mesh->setValue(markers, f[5], 1);

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

4455:       sieve->addArrow(p[10], f[7], order++);
4456:       sieve->addArrow(p[2], f[7], order++);
4457:       sieve->addArrow(p[5], f[7], order++);
4458:       sieve->addArrow(p[7], f[7], order++);
4459:       mesh->setValue(markers, f[7], 1);

4461:       sieve->addArrow(p[10], f[8], order++);
4462:       sieve->addArrow(p[2], f[8], order++);
4463:       sieve->addArrow(p[3], f[8], order++);
4464:       sieve->addArrow(p[11], f[8], order++);
4465:       mesh->setValue(markers, f[8], 1);

4467:       //assemble the smaller square sides

4469:       sieve->addArrow(p[13], f[9], order++);
4470:       sieve->addArrow(p[10], f[9], order++);
4471:       sieve->addArrow(p[11], f[9], order++);
4472:       sieve->addArrow(p[9], f[9], order++);
4473:       mesh->setValue(markers, f[9], 1);

4475:       sieve->addArrow(p[12], f[10], order++);
4476:       sieve->addArrow(p[7], f[10], order++);
4477:       sieve->addArrow(p[10], f[10], order++);
4478:       sieve->addArrow(p[13], f[10], order++);
4479:       mesh->setValue(markers, f[10], 1);

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

4487:       mesh->stratify();
4488:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4489:       Obj<typename Mesh::real_section_type> coordinates = mesh->getRealSection("coordinates");
4490:       //coordinates->view("coordinates");
4491:       return mesh;

4493:     }

4497:     /*
4498:       //"sphere" out a cube 

4500:     */
4501: #if 0
4502:     static Obj<Mesh> createSphereBoundary(const MPI_Comm comm, const real radius, const int refinement, const int debug = 0) {
4503:       Obj<Mesh> m = new Mesh(comm, 2, debug);
4504:       Obj<Mesh::sieve_type> s = new Mesh::sieve_type(comm, debug);
4505:       m->setSieve(s);
4506:       Mesh::point_type p = 0;
4507:       int nVertices = 8+12*(refinement)+6*(refinement)*(refinement);
4508:       Mesh::point_type vertices[nVertices];
4509:       real coords[3*nVertices];
4510:       int nCells = 6*2*(refinement+1)*(refinement+1);
4511:       real delta = 2./((real)(refinement+1));
4512:       Mesh::point_type cells[nCells];
4513:       for (int i = 0; i < nCells; i++) {
4514:         cells[i] = p;
4515:         p++;
4516:       }
4517:       for (int i = 0; i < nVertices; i++) {
4518:         vertices[i] = p;
4519:         p++;
4520:       }
4521:       //set up the corners;
4522:       //lll
4523:       coords[0*3+0] = -1.;
4524:       coords[0*3+1] = -1.;
4525:       coords[0*3+2] = -1.;
4526:       //llh
4527:       coords[1*3+0] = -1.;
4528:       coords[1*3+1] = -1.;
4529:       coords[1*3+2] = 1.;
4530:       //lhh
4531:       coords[2*3+0] = -1.;
4532:       coords[2*3+1] = 1.;
4533:       coords[2*3+2] = 1.;
4534:       //lhl
4535:       coords[3*3+0] = -1.;
4536:       coords[3*3+1] = 1.;
4537:       coords[3*3+2] = -1.;
4538:       //hhl
4539:       coords[4*3+0] = 1.;
4540:       coords[4*3+1] = 1.;
4541:       coords[4*3+2] = -1.;
4542:       //hhh
4543:       coords[5*3+0] = 1.;
4544:       coords[5*3+1] = 1.;
4545:       coords[5*3+2] = 1.;
4546:       //hlh
4547:       coords[6*3+0] = 1.;
4548:       coords[6*3+1] = -1.;
4549:       coords[6*3+2] = 1.;
4550:       //hll
4551:       coords[7*3+0] = 1.;
4552:       coords[7*3+1] = -1.;
4553:       coords[7*3+2] = -1.;
4554:       //set up the edges (always go low to high)
4555:       //xll
4556:       for (int i = 0; i < refinement; i++) {
4557:         coords[3*(8+0*refinement+i)+0] = -1. + delta*i;
4558:         coords[3*(8+0*refinement+i)+1] = -1.;
4559:         coords[3*(8+0*refinement+i)+2] = -1.;
4560:       }
4561:       //xlh
4562:       for (int i = 0; i < refinement; i++) {
4563:         coords[3*(8+1*refinement+i)+0] = -1. + delta*i;
4564:         coords[3*(8+1*refinement+i)+1] = -1.;
4565:         coords[3*(8+1*refinement+i)+2] = 1.;
4566:       }
4567:       //xhh
4568:       for (int i = 0; i < refinement; i++) {
4569:         coords[3*(8+2*refinement+i)+0] = -1. + delta*i;
4570:         coords[3*(8+2*refinement+i)+1] = 1.;
4571:         coords[3*(8+2*refinement+i)+2] = 1.;
4572:       }
4573:       //xhl
4574:       for (int i = 0; i < refinement; i++) {
4575:         coords[3*(8+3*refinement+i)+0] = -1. + delta*i;
4576:         coords[3*(8+3*refinement+i)+1] = 1.;
4577:         coords[3*(8+3*refinement+i)+2] = -1.;
4578:       }
4579:       //lxl
4580:       for (int i = 0; i < refinement; i++) {
4581:         coords[3*(8+4*refinement+i)+0] = -1.;
4582:         coords[3*(8+4*refinement+i)+1] = -1. + delta*i;
4583:         coords[3*(8+4*refinement+i)+2] = -1.;
4584:       }
4585:       //lxh
4586:       for (int i = 0; i < refinement; i++) {
4587:         coords[3*(8+5*refinement+i)+0] = -1.;
4588:         coords[3*(8+5*refinement+i)+1] = -1. + delta*i;
4589:         coords[3*(8+5*refinement+i)+2] = 1.;
4590:       }
4591:       //hxh
4592:       for (int i = 0; i < refinement; i++) {
4593:         coords[3*(8+6*refinement+i)+0] = 1.;
4594:         coords[3*(8+6*refinement+i)+1] = -1. + delta*i;
4595:         coords[3*(8+6*refinement+i)+2] = 1.;
4596:       }
4597:       //hxl
4598:       for (int i = 0; i < refinement; i++) {
4599:         coords[3*(8+7*refinement+i)+0] = 1.;
4600:         coords[3*(8+7*refinement+i)+1] = -1. + delta*i;
4601:         coords[3*(8+7*refinement+i)+2] = -1.;
4602:       }
4603:       //llx
4604:       for (int i = 0; i < refinement; i++) {
4605:         coords[3*(8+8*refinement+i)+0] = -1.;
4606:         coords[3*(8+8*refinement+i)+1] = -1.;
4607:         coords[3*(8+8*refinement+i)+2] = -1. + delta*i;
4608:       }
4609:       //lhx
4610:       for (int i = 0; i < refinement; i++) {
4611:         coords[3*(8+9*refinement+i)+0] = -1.;
4612:         coords[3*(8+9*refinement+i)+1] = 1.;
4613:         coords[3*(8+9*refinement+i)+2] = -1. + delta*i;
4614:       }
4615:       //hhx
4616:       for (int i = 0; i < refinement; i++) {
4617:         coords[3*(8+10*refinement+i)+0] = 1.;
4618:         coords[3*(8+10*refinement+i)+1] = 1.;
4619:         coords[3*(8+10*refinement+i)+2] = -1. + delta*i;
4620:       }
4621:       //hlx
4622:       for (int i = 0; i < refinement; i++) {
4623:         coords[3*(8+11*refinement+i)+0] = 1.;
4624:         coords[3*(8+11*refinement+i)+1] = -1.;
4625:         coords[3*(8+11*refinement+i)+2] = -1. + delta*i;
4626:       }
4627:       //set up the faces
4628:       //lxx
4629:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4630:         coords[3*(8+12*refinement+0*refinement*refinement+i*refinement+j)+0] = -1.;
4631:         coords[3*(8+12*refinement+0*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4632:         coords[3*(8+12*refinement+0*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4633:       }
4634:       //hxx
4635:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4636:         coords[3*(8+12*refinement+1*refinement*refinement+i*refinement+j)+0] = 1.;
4637:         coords[3*(8+12*refinement+1*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4638:         coords[3*(8+12*refinement+1*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4639:       }
4640:       //xlx
4641:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4642:         coords[3*(8+12*refinement+2*refinement*refinement+i*refinement+j)+0] = -1. + delta*j;
4643:         coords[3*(8+12*refinement+2*refinement*refinement+i*refinement+j)+1] = -1.;
4644:         coords[3*(8+12*refinement+2*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4645:       }
4646:       //xhx
4647:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4648:         coords[3*(8+12*refinement+3*refinement*refinement+i*refinement+j)+0] = -1. + delta*j;
4649:         coords[3*(8+12*refinement+3*refinement*refinement+i*refinement+j)+1] = 1.;
4650:         coords[3*(8+12*refinement+3*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4651:       }
4652:       //xxl
4653:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4654:         coords[3*(8+12*refinement+4*refinement*refinement+i*refinement+j)+0] = -1.;
4655:         coords[3*(8+12*refinement+4*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4656:         coords[3*(8+12*refinement+4*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4657:       }
4658:       //xxh
4659:       for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4660:         coords[3*(8+12*refinement+5*refinement*refinement+i*refinement+j)+0] = 1.;
4661:         coords[3*(8+12*refinement+5*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4662:         coords[3*(8+12*refinement+5*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4663:       }
4664:       //stitch the corners up with the edges and the faces
4665: 
4666:       //stitch the edges to the faces
4667:       //fill in the faces
4668:       int face_offset = 8 + 12*refinement;
4669:       for (int i = 0; i < 6; i++) for (int j = 0; j < refinement; j++) for (int k = 0; k < refinement; k++) {
4670:         //build each square doublet
4671:       }
4672:     }

4674: #endif

4678:     /*
4679:       Simple cubic boundary:

4681:      30----31-----32
4682:       |     |     |
4683:       |  3  |  2  |
4684:       |     |     |
4685:      27----28-----29
4686:       |     |     |
4687:       |  0  |  1  |
4688:       |     |     |
4689:      24----25-----26
4690:     */
4691:     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) {
4692:       Obj<Mesh> mesh            = new Mesh(comm, 2, debug);
4693:       const int numCubeVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
4694:       const int numPartVertices = (thetaEdges - 1)*phiSlices + 2;
4695:       const int numVertices     = numCubeVertices + numPartVertices;
4696:       const int numCubeFaces    = 6;
4697:       const int numFaces        = numCubeFaces + thetaEdges*phiSlices;
4698:       real   *coords          = new real[numVertices*3];
4699:       const Obj<typename Mesh::sieve_type> sieve    = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4700:       typename Mesh::point_type           *vertices = new typename Mesh::point_type[numVertices];
4701:       int                         order    = 0;

4703:       mesh->setSieve(sieve);
4704:       const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4705:       if (mesh->commRank() == 0) {
4706:         // Make cube
4707:         for(int v = numFaces; v < numFaces+numVertices; v++) {
4708:           vertices[v-numFaces] = typename Mesh::point_type(v);
4709:           mesh->setValue(markers, vertices[v-numFaces], 1);
4710:         }
4711:         {
4712:           // Side 0 (Front)
4713:           typename Mesh::point_type face(0);
4714:           sieve->addArrow(vertices[0], face, order++);
4715:           sieve->addArrow(vertices[1], face, order++);
4716:           sieve->addArrow(vertices[2], face, order++);
4717:           sieve->addArrow(vertices[3], face, order++);
4718:           mesh->setValue(markers, face, 1);
4719:         }
4720:         {
4721:           // Side 1 (Back)
4722:           typename Mesh::point_type face(1);
4723:           sieve->addArrow(vertices[5], face, order++);
4724:           sieve->addArrow(vertices[4], face, order++);
4725:           sieve->addArrow(vertices[7], face, order++);
4726:           sieve->addArrow(vertices[6], face, order++);
4727:           mesh->setValue(markers, face, 1);
4728:         }
4729:         {
4730:           // Side 2 (Bottom)
4731:           typename Mesh::point_type face(2);
4732:           sieve->addArrow(vertices[4], face, order++);
4733:           sieve->addArrow(vertices[5], face, order++);
4734:           sieve->addArrow(vertices[1], face, order++);
4735:           sieve->addArrow(vertices[0], face, order++);
4736:           mesh->setValue(markers, face, 1);
4737:         }
4738:         {
4739:           // Side 3 (Top)
4740:           typename Mesh::point_type face(3);
4741:           sieve->addArrow(vertices[3], face, order++);
4742:           sieve->addArrow(vertices[2], face, order++);
4743:           sieve->addArrow(vertices[6], face, order++);
4744:           sieve->addArrow(vertices[7], face, order++);
4745:           mesh->setValue(markers, face, 1);
4746:         }
4747:         {
4748:           // Side 4 (Left)
4749:           typename Mesh::point_type face(4);
4750:           sieve->addArrow(vertices[4], face, order++);
4751:           sieve->addArrow(vertices[0], face, order++);
4752:           sieve->addArrow(vertices[3], face, order++);
4753:           sieve->addArrow(vertices[7], face, order++);
4754:           mesh->setValue(markers, face, 1);
4755:         }
4756:         {
4757:           // Side 5 (Right)
4758:           typename Mesh::point_type face(5);
4759:           sieve->addArrow(vertices[1], face, order++);
4760:           sieve->addArrow(vertices[5], face, order++);
4761:           sieve->addArrow(vertices[6], face, order++);
4762:           sieve->addArrow(vertices[2], face, order++);
4763:           mesh->setValue(markers, face, 1);
4764:         }
4765:         // Make particle
4766:         for(int s = 0; s < phiSlices; ++s) {
4767:           for(int ep = 0; ep < thetaEdges; ++ep) {
4768:             // Vertices on each slice are 0..thetaEdges
4769:             typename Mesh::point_type face(numCubeFaces + s*thetaEdges + ep);
4770:             int vertexA = numCubeVertices + ep + 0 +     s*(thetaEdges+1);
4771:             int vertexB = numCubeVertices + ep + 1 +     s*(thetaEdges+1);
4772:             int vertexC = numCubeVertices + (ep + 1 + (s+1)*(thetaEdges+1))%((thetaEdges+1)*phiSlices);
4773:             int vertexD = numCubeVertices + (ep + 0 + (s+1)*(thetaEdges+1))%((thetaEdges+1)*phiSlices);
4774:             const int correction1 = (s > 0)*((s-1)*2 + 1);
4775:             const int correction2 = (s < phiSlices-1)*(s*2 + 1);

4777:             if ((vertexA - numCubeVertices)%(thetaEdges+1) == 0) {
4778:               vertexA = vertexD = numCubeVertices;
4779:               vertexB -= correction1;
4780:               vertexC -= correction2;
4781:             } else if ((vertexB - numCubeVertices)%(thetaEdges+1) == thetaEdges) {
4782:               vertexA -= correction1;
4783:               vertexD -= correction2;
4784:               vertexB = vertexC = numCubeVertices + thetaEdges;
4785:             } else {
4786:               vertexA -= correction1;
4787:               vertexB -= correction1;
4788:               vertexC -= correction2;
4789:               vertexD -= correction2;
4790:             }
4791:             if ((vertexA >= numVertices) || (vertexB >= numVertices) || (vertexC >= numVertices) || (vertexD >= numVertices)) {
4792:               throw ALE::Exception("Bad vertex");
4793:             }
4794:             sieve->addArrow(vertices[vertexA], face, order++);
4795:             sieve->addArrow(vertices[vertexB], face, order++);
4796:             if (vertexB != vertexC) sieve->addArrow(vertices[vertexC], face, order++);
4797:             if (vertexA != vertexD) sieve->addArrow(vertices[vertexD], face, order++);
4798:             mesh->setValue(markers, face, 2);
4799:             mesh->setValue(markers, vertices[vertexA], 2);
4800:             mesh->setValue(markers, vertices[vertexB], 2);
4801:             if (vertexB != vertexC) mesh->setValue(markers, vertices[vertexC], 2);
4802:             if (vertexA != vertexD) mesh->setValue(markers, vertices[vertexD], 2);
4803:           }
4804:         }
4805:       }
4806:       mesh->stratify();
4807: #if 0
4808:       for(int vz = 0; vz <= edges[2]; ++vz) {
4809:         for(int vy = 0; vy <= edges[1]; ++vy) {
4810:           for(int vx = 0; vx <= edges[0]; ++vx) {
4811:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
4812:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
4813:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
4814:           }
4815:         }
4816:       }
4817: #else
4818:       coords[0*3+0] = lower[0];
4819:       coords[0*3+1] = lower[1];
4820:       coords[0*3+2] = upper[2];
4821:       coords[1*3+0] = upper[0];
4822:       coords[1*3+1] = lower[1];
4823:       coords[1*3+2] = upper[2];
4824:       coords[2*3+0] = upper[0];
4825:       coords[2*3+1] = upper[1];
4826:       coords[2*3+2] = upper[2];
4827:       coords[3*3+0] = lower[0];
4828:       coords[3*3+1] = upper[1];
4829:       coords[3*3+2] = upper[2];
4830:       coords[4*3+0] = lower[0];
4831:       coords[4*3+1] = lower[1];
4832:       coords[4*3+2] = lower[2];
4833:       coords[5*3+0] = upper[0];
4834:       coords[5*3+1] = lower[1];
4835:       coords[5*3+2] = lower[2];
4836:       coords[6*3+0] = upper[0];
4837:       coords[6*3+1] = upper[1];
4838:       coords[6*3+2] = lower[2];
4839:       coords[7*3+0] = lower[0];
4840:       coords[7*3+1] = upper[1];
4841:       coords[7*3+2] = lower[2];
4842: #endif
4843:       const real centroidX = 0.5*(upper[0] + lower[0]);
4844:       const real centroidY = 0.5*(upper[1] + lower[1]);
4845:       const real centroidZ = 0.5*(upper[2] + lower[2]);
4846:       for(int s = 0; s < phiSlices; ++s) {
4847:         for(int v = 0; v <= thetaEdges; ++v) {
4848:           int          vertex  = numCubeVertices + v + s*(thetaEdges+1);
4849:           const real theta   = v*(PETSC_PI/thetaEdges);
4850:           const real phi     = s*(2.0*PETSC_PI/phiSlices);
4851:           const int correction = (s > 0)*((s-1)*2 + 1);

4853:           if ((vertex- numCubeVertices)%(thetaEdges+1) == 0) {
4854:             vertex = numCubeVertices;
4855:           } else if ((vertex - numCubeVertices)%(thetaEdges+1) == thetaEdges) {
4856:             vertex = numCubeVertices + thetaEdges;
4857:           } else {
4858:             vertex -= correction;
4859:           }
4860:           coords[vertex*3+0] = centroidX + radius*sin(theta)*cos(phi);
4861:           coords[vertex*3+1] = centroidY + radius*sin(theta)*sin(phi);
4862:           coords[vertex*3+2] = centroidZ + radius*cos(theta);
4863:         }
4864:       }
4865:       delete [] vertices;
4866:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4867:       return mesh;
4868:     };

4870: #if 0 // WORKING ON REDESIGN WITHIN PYLITH SOURCE TREE
4871:     template<typename MeshType, typename EdgeType>
4872:     class CellRefiner {
4873:     public:
4874:       typedef typename MeshType::point_type point_type;
4875:       typedef EdgeType                      edge_type;
4876:       typedef typename std::map<edge_type, point_type> edge_map_type;
4877:       typedef enum {LINE, LINE_LAGRANGE, TRIANGLE, QUADRILATERAL, TETRAHEDRON, HEXAHEDRON, TRIANGULAR_PRISM, TRIANGULAR_PRISM_LAGRANGE, HEXAHEDRON_LAGRANGE} CellType;
4878:     protected:
4879:       const MeshType&     _mesh;
4880:       int           _dim;
4881:       point_type    _vertexOffset;
4882:       edge_map_type _edge2vertex;
4883:     public:
4884:       CellRefiner(MeshType& mesh) : _mesh(mesh) {
4885:         _dim = _mesh.getDimension();
4886:       };
4887:       ~CellRefiner() {};
4888:     protected:
4889:       CellType getCellType(const point_type cell) {
4890:         const int corners = _mesh.getSieve()->getConeSize(cell);
4891:         switch (_dim) {
4892:           return LINE;
4893:         case 2:
4894:           switch (corners) {
4895:           case 3:
4896:             return TRIANGLE;
4897:           case 4:
4898:             throw ALE::Exception("Not implemented.");
4899:             return QUADRILATERAL;
4900:           case 6:
4901:             return LINE_LAGRANGE;
4902:           case 0: {
4903:             std::ostringstream msg;
4904:             std::cerr << "Internal error. Cone size for mesh point " << cell << " is zero. May be a vertex.";
4905:             assert(0);
4906:             throw ALE::Exception("Could not determine 2-D cell type.");
4907:           } // case 0
4908:           default : {
4909:             std::ostringstream msg;
4910:             std::cerr << "Internal error. Unknown cone size for mesh point " << cell << ". Unknown cell type.";
4911:             assert(0);
4912:             throw ALE::Exception("Could not determine 2-D cell type.");
4913:           } // default
4914:           } // switch
4915:         case 3:
4916:           switch (corners) {
4917:           case 4:
4918:             return TETRAHEDRON;
4919:           case 6:
4920:             return TRIANGULAR_PRISM;
4921:           case 9:
4922:             return TRIANGULAR_PRISM_LAGRANGE;
4923:           case 12:
4924:             throw ALE::Exception("Not implemented.");
4925:             return HEXAHEDRON_LAGRANGE;
4926:           case 0: {
4927:             std::ostringstream msg;
4928:             std::cerr << "Internal error. Cone size for mesh point " << cell << " is zero. May be a vertex.";
4929:             assert(0);
4930:             throw ALE::Exception("Could not determine 3-D cell type.");
4931:           } // case 0
4932:           default : {
4933:             std::ostringstream msg;
4934:             std::cerr << "Internal error. Unknown cone size for mesh point " << cell << ". Unknown cell type.";
4935:             assert(0);
4936:             throw ALE::Exception("Could not determine 3-D cell type.");
4937:           } // default
4938:           } // switch
4939:         } // switch
4940:       };
4941:       void getEdges_TRIANGLE(const int coneSize, const point_type cone[],  int *numEdges, const edge_type **edges) {
4942:         static edge_type triEdges[3];

4944:         assert(coneSize == 3);
4945:         triEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4946:         triEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
4947:         triEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
4948:         *numEdges = 3;
4949:         *edges    = triEdges;
4950:       };
4951:       void getEdges_LINE_LAGRANGE(const int coneSize, const point_type cone[],  int *numEdges, const edge_type **edges) {
4952:         static edge_type lineEdges[6];

4954:         assert(coneSize == 6);
4955:         lineEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4956:         lineEdges[1] = edge_type(std::min(cone[2], cone[3]), std::max(cone[2], cone[3]));
4957:         lineEdges[2] = edge_type(std::min(cone[4], cone[5]), std::max(cone[4], cone[5]));
4958:         *numEdges = 3;
4959:         *edges    = lineEdges;
4960:       };
4961:       void getEdges_TETRAHEDRON(const int coneSize, const point_type cone[],  int *numEdges, const edge_type **edges) {
4962:         static edge_type tetEdges[6];

4964:         assert(coneSize == 4);
4965:         // As per Brad's diagram
4966:         tetEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4967:         tetEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
4968:         tetEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
4969:         tetEdges[3] = edge_type(std::min(cone[0], cone[3]), std::max(cone[0], cone[3]));
4970:         tetEdges[4] = edge_type(std::min(cone[1], cone[3]), std::max(cone[1], cone[3]));
4971:         tetEdges[5] = edge_type(std::min(cone[2], cone[3]), std::max(cone[2], cone[3]));
4972:         *numEdges = 6;
4973:         *edges    = tetEdges;
4974:       };
4975:       void getEdges_TRIANGULAR_PRISM(const int coneSize, const point_type cone[],  int *numEdges, const edge_type **edges) {
4976:         static edge_type triPrismEdges[6];

4978:         assert(coneSize == 6);
4979:         triPrismEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4980:         triPrismEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
4981:         triPrismEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
4982:         triPrismEdges[3] = edge_type(std::min(cone[3], cone[4]), std::max(cone[3], cone[4]));
4983:         triPrismEdges[4] = edge_type(std::min(cone[4], cone[5]), std::max(cone[4], cone[5]));
4984:         triPrismEdges[5] = edge_type(std::min(cone[5], cone[3]), std::max(cone[5], cone[3]));
4985:         *numEdges = 6;
4986:         *edges    = triPrismEdges;
4987:       };
4988:       void getEdges_TRIANGULAR_PRISM_LAGRANGE(const int coneSize, const point_type cone[],  int *numEdges, const edge_type **edges) {
4989:         static edge_type triPrismLEdges[9];

4991:         assert(coneSize == 9);
4992:         triPrismLEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4993:         triPrismLEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
4994:         triPrismLEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
4995:         triPrismLEdges[3] = edge_type(std::min(cone[3], cone[4]), std::max(cone[3], cone[4]));
4996:         triPrismLEdges[4] = edge_type(std::min(cone[4], cone[5]), std::max(cone[4], cone[5]));
4997:         triPrismLEdges[5] = edge_type(std::min(cone[5], cone[3]), std::max(cone[5], cone[3]));
4998:         triPrismLEdges[6] = edge_type(std::min(cone[6], cone[7]), std::max(cone[6], cone[7]));
4999:         triPrismLEdges[7] = edge_type(std::min(cone[7], cone[8]), std::max(cone[7], cone[8]));
5000:         triPrismLEdges[8] = edge_type(std::min(cone[8], cone[6]), std::max(cone[8], cone[6]));
5001:         *numEdges = 9;
5002:         *edges    = triPrismLEdges;
5003:       };
5004:       void getNewCells_TRIANGLE(const int coneSize, const point_type cone[],  int *numCells, const point_type **cells) {
5005:         int               numEdges;
5006:         const edge_type  *edges;
5007:         static point_type triCells[4*3];
5008:         point_type        newVertices[3];

5010:         getEdges_TRIANGLE(coneSize, cone, &numEdges, &edges);
5011:         assert(numEdges == 3);
5012:         for(int e = 0; e < numEdges; ++e) {
5013:           if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5014:             throw ALE::Exception("Missing edge in refined mesh");
5015:           }
5016:           newVertices[e] = _edge2vertex[edges[e]];
5017:         }
5018:         triCells[0*3+0] = cone[0]+_vertexOffset; triCells[0*3+1] = newVertices[0]; triCells[0*3+2] = newVertices[2];
5019:         triCells[1*3+0] = newVertices[0];       triCells[1*3+1] = newVertices[1]; triCells[1*3+2] = newVertices[2];
5020:         triCells[2*3+0] = cone[1]+_vertexOffset; triCells[2*3+1] = newVertices[1]; triCells[2*3+2] = newVertices[0];
5021:         triCells[3*3+0] = cone[2]+_vertexOffset; triCells[3*3+1] = newVertices[2]; triCells[3*3+2] = newVertices[1];
5022:         *numCells = 4;
5023:         *cells    = triCells;
5024:       };
5025:       void getNewCells_LINE_LAGRANGE(const int coneSize, const point_type cone[],  int *numCells, const point_type **cells) {
5026:         int               numEdges;
5027:         const edge_type  *edges;
5028:         static point_type lineCells[2*6];
5029:         point_type        newVertices[3];

5031:         getEdges_LINE_LAGRANGE(coneSize, cone, &numEdges, &edges);
5032:         assert(numEdges == 3);
5033:         for(int e = 0; e < numEdges; ++e) {
5034:           if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5035:             throw ALE::Exception("Missing edge in refined mesh");
5036:           }
5037:           newVertices[e] = _edge2vertex[edges[e]];
5038:         }
5039:         lineCells[0*6+0] = cone[0]+_vertexOffset; // new cell 0
5040:         lineCells[0*6+1] = newVertices[0];
5041:         lineCells[0*6+2] = cone[2]+_vertexOffset;
5042:         lineCells[0*6+3] = newVertices[1];
5043:         lineCells[0*6+4] = cone[4]+_vertexOffset;
5044:         lineCells[0*6+5] = newVertices[2];

5046:         lineCells[1*6+0] = newVertices[0]; // new cell 1
5047:         lineCells[1*6+1] = cone[1]+_vertexOffset;
5048:         lineCells[1*6+2] = newVertices[1];
5049:         lineCells[1*6+3] = cone[3]+_vertexOffset;
5050:         lineCells[1*6+4] = newVertices[2];
5051:         lineCells[1*6+5] = cone[5]+_vertexOffset;

5053:         *numCells = 2;
5054:         *cells    = lineCells;
5055:       };
5056:       void getNewCells_TETRAHEDRON(const int coneSize, const point_type cone[],  int *numCells, const point_type **cells) {
5057:         int               numEdges;
5058:         const edge_type  *edges;
5059:         static point_type tetCells[8*4];
5060:         point_type        newVertices[6];

5062:         getEdges_TETRAHEDRON(coneSize, cone, &numEdges, &edges);
5063:         assert(numEdges == 6);
5064:         for(int e = 0; e < numEdges; ++e) {
5065:           if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5066:             throw ALE::Exception("Missing edge in refined mesh");
5067:           }
5068:           newVertices[e] = _edge2vertex[edges[e]];
5069:         }
5070:         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];
5071:         tetCells[1*4+0] = newVertices[0];       tetCells[1*4+1] = newVertices[1]; tetCells[1*4+2] = newVertices[2]; tetCells[1*4+3] = newVertices[3];
5072:         tetCells[2*4+0] = newVertices[0];       tetCells[2*4+1] = newVertices[3]; tetCells[2*4+2] = newVertices[4]; tetCells[2*4+3] = newVertices[1];
5073:         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];
5074:         tetCells[4*4+0] = newVertices[2];       tetCells[4*4+1] = newVertices[5]; tetCells[4*4+2] = newVertices[3]; tetCells[4*4+3] = newVertices[1];
5075:         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];
5076:         tetCells[6*4+0] = newVertices[1];       tetCells[6*4+1] = newVertices[4]; tetCells[6*4+2] = newVertices[5]; tetCells[6*4+3] = newVertices[3];
5077:         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];
5078:         *numCells = 8;
5079:         *cells    = tetCells;
5080:       };
5081:       void getNewCells_TRIANGULAR_PRISM_LAGRANGE(const int coneSize, const point_type cone[],  int *numCells, const point_type **cells) {
5082:         int               numEdges;
5083:         const edge_type  *edges;
5084:         static point_type tcells[4*9];
5085:         point_type        newVertices[9];

5087:         getEdges_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone, &numEdges, &edges);
5088:         assert(numEdges == 9);
5089:         for(int e = 0; e < numEdges; ++e) {
5090:           if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5091:             throw ALE::Exception("Missing edge in refined mesh");
5092:           }
5093:           newVertices[e] = _edge2vertex[edges[e]];
5094:         }
5095:         tcells[0*9+0] = cone[0]+_vertexOffset; // New cell 0
5096:         tcells[0*9+1] = newVertices[0];
5097:         tcells[0*9+2] = newVertices[2];
5098:         tcells[0*9+3] = cone[3]+_vertexOffset;
5099:         tcells[0*9+4] = newVertices[3];
5100:         tcells[0*9+5] = newVertices[5];
5101:         tcells[0*9+6] = cone[6]+_vertexOffset;
5102:         tcells[0*9+7] = newVertices[6];
5103:         tcells[0*9+8] = newVertices[8];

5105:         tcells[1*9+0] = newVertices[0]; // New cell 1
5106:         tcells[1*9+1] = newVertices[1];
5107:         tcells[1*9+2] = newVertices[2];
5108:         tcells[1*9+3] = newVertices[3];
5109:         tcells[1*9+4] = newVertices[4];
5110:         tcells[1*9+5] = newVertices[5];
5111:         tcells[1*9+6] = newVertices[6];
5112:         tcells[1*9+7] = newVertices[7];
5113:         tcells[1*9+8] = newVertices[8];

5115:         tcells[2*9+0] = cone[1]+_vertexOffset; // New cell 2
5116:         tcells[2*9+1] = newVertices[1];
5117:         tcells[2*9+2] = newVertices[0];
5118:         tcells[2*9+3] = cone[4]+_vertexOffset;
5119:         tcells[2*9+4] = newVertices[4];
5120:         tcells[2*9+5] = newVertices[3];
5121:         tcells[2*9+6] = cone[7]+_vertexOffset;
5122:         tcells[2*9+7] = newVertices[7];
5123:         tcells[2*9+8] = newVertices[6];

5125:         tcells[3*9+0] = cone[2]+_vertexOffset; // New cell 3
5126:         tcells[3*9+1] = newVertices[2];
5127:         tcells[3*9+2] = newVertices[1];
5128:         tcells[3*9+3] = cone[5]+_vertexOffset;
5129:         tcells[3*9+4] = newVertices[5];
5130:         tcells[3*9+5] = newVertices[4];
5131:         tcells[3*9+6] = cone[8]+_vertexOffset;
5132:         tcells[3*9+7] = newVertices[8];
5133:         tcells[3*9+8] = newVertices[7];

5135:         *numCells = 4;
5136:         *cells    = tcells;
5137:       };
5138:     public:
5139:       point_type getVertexRelativeOffset()                        {return _vertexOffset;};
5140:       void       setVertexRelativeOffset(const point_type offset) {_vertexOffset = offset;};
5141:       edge_map_type& getEdgeToVertex() {return _edge2vertex;};
5142:       int numNewCells(const point_type cell) {
5143:         switch(this->getCellType(cell)) {
5144:         case TRIANGLE:
5145:           return 4;
5146:         case LINE_LAGRANGE:
5147:           return 2;
5148:         case TETRAHEDRON:
5149:           return 8;
5150:         case TRIANGULAR_PRISM:
5151:         case TRIANGULAR_PRISM_LAGRANGE:
5152:           return 4;
5153:         }
5154:         throw ALE::Exception("Could not determine number of new cells for this cell type");
5155:       };
5156:       void splitEdge(const point_type cell, const int coneSize, const point_type cone[], point_type& curNewVertex) {
5157:         const CellType   t = this->getCellType(cell);
5158:         int              numEdges;
5159:         const edge_type *edges;

5161:         switch(t) {
5162:         case TRIANGLE:
5163:           getEdges_TRIANGLE(coneSize, cone, &numEdges, &edges);
5164:           break;
5165:         case LINE_LAGRANGE:
5166:           getEdges_LINE_LAGRANGE(coneSize, cone, &numEdges, &edges);
5167:           break;
5168:         case TETRAHEDRON:
5169:           getEdges_TETRAHEDRON(coneSize, cone, &numEdges, &edges);
5170:           break;
5171:         case TRIANGULAR_PRISM:
5172:           getEdges_TRIANGULAR_PRISM(coneSize, cone, &numEdges, &edges);
5173:           break;
5174:         case TRIANGULAR_PRISM_LAGRANGE:
5175:           getEdges_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone, &numEdges, &edges);
5176:           break;
5177:         default:
5178:           throw ALE::Exception("Could not determine number of new cells for this cell type");
5179:         }
5180:         // Check that vertex does not yet exist
5181:         for(int v = 0; v < numEdges; ++v) {
5182:           if (_edge2vertex.find(edges[v]) == _edge2vertex.end()) {
5183:             std::cout << "Edge: " << edges[v] << ", new vertex: " << curNewVertex << std::endl;
5184:             _edge2vertex[edges[v]] = curNewVertex++;
5185:           }
5186:         }
5187:       };
5188:       void getNewCell(const point_type cell, const int coneSize, const point_type cone[], int newCellNumber, int *newConeSize, const point_type **newCone) {
5189:         const CellType    t = this->getCellType(cell);
5190:         int               numCells;
5191:         const point_type *cells;

5193:         switch(t) {
5194:         case TRIANGLE:
5195:           getNewCells_TRIANGLE(coneSize, cone,  &numCells, &cells);
5196:           *newConeSize = 3;
5197:           *newCone     = &cells[newCellNumber*3];
5198:           break;
5199:         case LINE_LAGRANGE:
5200:           getNewCells_LINE_LAGRANGE(coneSize, cone,  &numCells, &cells);
5201:           *newConeSize = 6;
5202:           *newCone     = &cells[newCellNumber*6];
5203:           break;
5204:         case TETRAHEDRON:
5205:           getNewCells_TETRAHEDRON(coneSize, cone,  &numCells, &cells);
5206:           *newConeSize = 4;
5207:           *newCone     = &cells[newCellNumber*4];
5208:           break;
5209:         case TRIANGULAR_PRISM_LAGRANGE:
5210:           getNewCells_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone,  &numCells, &cells);
5211:           *newConeSize = 9;
5212:           *newCone     = &cells[newCellNumber*9];
5213:           break;
5214:         default:
5215:           throw ALE::Exception("Could not create new cell for this cell type");
5216:         }
5217:       };
5218:       void getNeighboringVertices(const point_type cell, const int coneSize, const point_type cone[], const point_type firstNewVertex, point_type vertex2edge[]) {
5219:         const CellType   t = this->getCellType(cell);
5220:         int              numEdges;
5221:         const edge_type *edges;

5223:         switch(t) {
5224:         case TRIANGLE:
5225:           getEdges_TRIANGLE(coneSize, cone, &numEdges, &edges);
5226:           break;
5227:         case LINE_LAGRANGE:
5228:           getEdges_LINE_LAGRANGE(coneSize, cone, &numEdges, &edges);
5229:           break;
5230:         case TETRAHEDRON:
5231:           getEdges_TETRAHEDRON(coneSize, cone, &numEdges, &edges);
5232:           break;
5233:         case TRIANGULAR_PRISM:
5234:           getEdges_TRIANGULAR_PRISM(coneSize, cone, &numEdges, &edges);
5235:           break;
5236:         case TRIANGULAR_PRISM_LAGRANGE:
5237:           getEdges_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone, &numEdges, &edges);
5238:           break;
5239:         default:
5240:           throw ALE::Exception("Could not determine number of new cells for this cell type");
5241:         }
5242:         for(int v = 0; v < numEdges; ++v) {
5243:           point_type newVertex = _edge2vertex[edges[v]];

5245:           std::cout << "VERTEX2EDGE index: " << newVertex-firstNewVertex << ", first: " << edges[v].first << ", second: " << edges[v].second << std::endl;
5246:           vertex2edge[(newVertex-firstNewVertex)*2+0] = edges[v].first;
5247:           vertex2edge[(newVertex-firstNewVertex)*2+1] = edges[v].second;
5248:         }
5249:       };
5250:     };
5251:     // This method takes a mesh and performs a refinement of each cell
5252:     //
5253:     //   triangle: 1 --> 4 refinement, adding a new vertex at the midpoint of each edge
5254:     //   tetrahedra:        1 --> 8 refinement,  adding a new vertex at the midpoint of each edge
5255:     //
5256:     // :WARNING: This method currently only works for uninterpolated meshes with tri and tet cells.
5257:     template<typename MeshType, typename Refiner>
5258:     static void refineGeneral(const Obj<MeshType>& mesh, const Obj<MeshType>& newMesh, Refiner& refiner) {
5259:       typedef typename MeshType::sieve_type sieve_type;
5260:       typedef typename MeshType::point_type point_type;
5261:       typedef typename Refiner::edge_type   edge_type;

5263:       // :WARNING: Assumed order of mesh points (cells and vertices):
5264:       //
5265:       // normal cells (in censored depth)
5266:       // normal vertices (in censored depth)
5267:       // other vertices
5268:       // other cells
5269:       //
5270:       // This permits omitting in output the other vertices (e.g.,
5271:       // Lagrange multipliers) and other cells (e.g., cohesive cells)
5272:       // which have a custom reference cell that is not recognized.

5274:       assert(!mesh.isNull());
5275:       assert(!newMesh.isNull());

5277:       // Get original mesh stuff.
5278:       const Obj<typename MeshType::label_sequence>& cells = mesh->heightStratum(0);
5279:       assert(!cells.isNull());
5280:       const typename MeshType::label_sequence::iterator cellsEnd = cells->end();

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

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

5289:       if (mesh->hasLabel("censored depth")) {
5290:         // :WARNING: Assume all cells in the censored depth come before
5291:         // any other cells. This guarantees that we add vertices in the
5292:         // censored depth before adding other vertices.

5294:         int counterBegin = 0;

5296:         int oldNumCellsNormal = 0;
5297:         int oldNumCellsOther = 0;
5298:         int oldNumVerticesNormal = 0;
5299:         int oldNumVerticesOther = 0;

5301:         int newNumCellsNormal = 0;
5302:         int newNumCellsOther = 0;
5303:         int newNumVerticesNormal = 0;
5304:         int newNumVerticesOther = 0;

5306:         // Count number of cells in censored depth (normal cells).
5307:         const Obj<typename MeshType::label_sequence>& cellsNormal = mesh->getLabelStratum("censored depth", mesh->depth());
5308:         assert(!cellsNormal.isNull());
5309:         const typename MeshType::label_sequence::iterator cellsNormalEnd = cellsNormal->end();
5310:         oldNumCellsNormal = cellsNormal->size();
5311:         for(typename MeshType::label_sequence::iterator c_iter = cellsNormal->begin(); c_iter != cellsNormalEnd; ++c_iter)
5312:           newNumCellsNormal += refiner.numNewCells(*c_iter);

5314:         // Count number of remaining cells (other cells).
5315:         const int numSkip = oldNumCellsNormal;
5316:         oldNumCellsOther = cells->size() - oldNumCellsNormal;
5317:         typename MeshType::label_sequence::iterator c_iter = cells->begin();
5318:         for (int i=0; i < numSkip; ++i)
5319:           ++c_iter;
5320:         for (; c_iter != cellsEnd; ++c_iter)
5321:           newNumCellsOther += refiner.numNewCells(*c_iter);

5323:         // Get number of old normal vertices.
5324:         assert(!mesh->getFactory.isNull());
5325:         Obj<typename Mesh::numbering_type> vNumbering = mesh->getFactory()->getNumbering(mesh, "censored depth", 0);
5326:         assert(!vNumbering.isNull());
5327:         oldNumVerticesNormal = vNumbering->size();

5329:         // Count number of new normal vertices.
5330:         int counterBegin = newNumCellsNormal + vertices->size();
5331:         const point_type curNewVertex = counterBegin;
5332:         for(typename MeshType::label_sequence::iterator c_iter = cellsNormal->begin(); c_iter != cellsNormalEnd; ++c_iter) {
5333:           cV.clear();
5334:           sieve->cone(*c_iter, cV);
5335:           refiner.splitEdge(*c_iter, cV.getSize(), cV.getPoints(), curNewVertex);
5336:         } // for
5337:         newNumVerticesNormal = curNewVertex - counterBegin;

5339:         // Count number of remaining vertices (other vertices).
5340:         oldNumVerticesOther = vertices->size() - oldNumVerticessNormal;
5341:         counterBegin = curNewVertex + oldNumVerticesOther;
5342:         curNewVertex = counterBegin;
5343:         c_iter = cells->begin();
5344:         for (int i=0; i < numSkip; ++i)
5345:           ++c_iter;
5346:         for (; c_iter != cellsEnd; ++c_iter) {
5347:           cV.clear();
5348:           sieve->cone(*c_iter, cV);
5349:           refiner.splitEdge(*c_iter, cV.getSize(), cV.getPoints(), curNewVertex);
5350:         } // for
5351:         newNumVerticesOther = curNewVertex - counterBegin;

5353:         Interval<point_type> oldCellsNormalRange(0, oldNumCellsNormal);
5354:         Interval<point_type> newCellsNormalRange(0, newNumCellsNormal);

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

5359:         Interval<point_type> oldVerticesOtherRange(oldNumCellsNormal+oldNumVerticesNormal ,
5360:                                                    oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesOther);
5361:         Interval<point_type> newVerticesOtherRange(newNumCellsNormal+newNumVerticesNormal ,
5362:                                                    newNumCellsNormal+newNumVerticesNormal+newNumVerticesOther);

5364:         Interval<point_type> oldCellssOtherRange(oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesOther,
5365:                                                  oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesOther+oldNumCellsOther);
5366:         Interval<point_type> newCellssOtherRange(newNumCellsNormal+newNumVerticesNormal+newNumVerticesOther,
5367:                                                  newNumCellsNormal+newNumVerticesNormal+newNumVerticesOther+newNumCellsOther);


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

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

5378:         // Start with normal cells.
5379:         point_type curNewCell = newCellsNormalRange.begin();
5380:         const typename Interval<point_type>::const_iterator oldCellsNormalRangeEnd = oldCellsNormalRange.end();
5381:         for (typename Interval<point_type>::const_iterator c_iter=oldCellsNormalRange.begin();
5382:              c_iter != oldCellsNormalRangeEnd;
5383:              ++c_iter) {
5384:           // Set new cone and support sizes
5385:           cV.clear();
5386:           sieve->cone(*c_iter, cV);
5387:           const point_type *cone = cV.getPoints();
5388:           const int coneSize = cV.getSize();
5389:           const int newCells = refiner.numNewCells(*c_iter);

5391:           for(int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5392:             const point_type *newCone;
5393:             int newConeSize;

5395:             newSieve->setConeSize(curNewCell, sieve->getConeSize(*c_iter));
5396:             // OPTIMIZE THIS
5397:             refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5398:             for(int v = 0; v < newConeSize; ++v)
5399:               newSieve->addSupportSize(newCone[v], 1);
5400:           } // for
5401:         } // for

5403:         // Continue with other cells.
5404:         point_type curNewCell = newCellsOtherRange.begin();
5405:         const typename Interval<point_type>::const_iterator oldCellsOtherRangeEnd = oldCellsOtherRange.end();
5406:         for (typename Interval<point_type>::const_iterator c_iter=oldCellOtherRange.begin();
5407:              c_iter != oldCellsOtherRangeEnd;
5408:              ++c_iter) {
5409:           // Set new cone and support sizes
5410:           cV.clear();
5411:           sieve->cone(*c_iter, cV);
5412:           const point_type *cone = cV.getPoints();
5413:           const int coneSize = cV.getSize();
5414:           const int newCells = refiner.numNewCells(*c_iter);

5416:           for(int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5417:             const point_type *newCone;
5418:             int newConeSize;

5420:             newSieve->setConeSize(curNewCell, sieve->getConeSize(*c_iter));
5421:             // OPTIMIZE THIS
5422:             refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5423:             for(int v = 0; v < newConeSize; ++v)
5424:               newSieve->addSupportSize(newCone[v], 1);
5425:           } // for
5426:         } // for
5427:         newSieve->allocate();
5428:         point_type* vertex2edge = new point_type[(newNumVerticesNormal+newNumVerticesOther)*2];
5429:         typename Refiner::edge_map_type& edge2vertex = refiner.getEdgeToVertex();


5432:         // Create refined normal cells in new sieve.
5433:         curNewCell = newCellsNormalRange.begin();
5434:         for (typename Interval<point_type>::const_iterator c_iter=oldCellsNormalRange.begin();
5435:              c_iter != oldCellsNormalRangeEnd;
5436:              ++c_iter) {
5437:           cV.clear();
5438:           sieve->cone(*c_iter, cV);
5439:           const point_type *cone = cV.getPoints();
5440:           const int coneSize = cV.getSize();
5441:           const int newCells = refiner.numNewCells(*c_iter);

5443:           for (int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5444:             const point_type *newCone;
5445:             int newConeSize;

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

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

5454:         // Create refined other cells in new sieve.
5455:         curNewCell = newCellsOtherRange.begin();
5456:         for (typename Interval<point_type>::const_iterator c_iter=oldCellsOtherRange.begin();
5457:              c_iter != oldCellsOtherRangeEnd;
5458:              ++c_iter) {
5459:           cV.clear();
5460:           sieve->cone(*c_iter, cV);
5461:           const point_type *cone = cV.getPoints();
5462:           const int coneSize = cV.getSize();
5463:           const int newCells = refiner.numNewCells(*c_iter);

5465:           for (int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5466:             const point_type *newCone;
5467:             int newConeSize;

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

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

5478:         // Set coordinates in refined mesh.
5479:         const Obj<typename MeshType::real_section_type>& coordinates = mesh->getRealSection("coordinates");
5480:         assert(!coordinates.isNull());
5481:         const Obj<typename MeshType::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates");
5482:         assert(!newCoordinates.isNull());

5484:         const typename MeshType::label_sequence::const_iterator verticesEnd = vertices->end();
5485:         assert(vertices->size() > 0);
5486:         const int spaceDim = coordinates->getFiberDimension(*vertices->begin());
5487:         assert(spaceDim > 0);
5488:         newCoordinates->setChart(typename sieve_type::chart_type(newNumCellsNormal, newNumCellsNormal+newNumVertices));

5490:         for (int iVertex=0, offset=newNumCellsNormal; iVertex < newNumVertices; ++iVertex) {
5491:           const point_type vNew = iVertex + offset;
5492:           newCoordinates->setFiberDimension(vNew, spaceDim);
5493:         } // for
5494:         newCoordinates->allocatePoint();

5496:         for (int iVertex=0, oldOffset=oldNumCellsNormal, newOffset=newNumCellsNormal; iVertex < oldNumVertices; ++iVertex) {
5497:           const point_type vOld = iVertex + oldOffset;
5498:           const point_type vNew = iVertex + newOffset;
5499:           newCoordinates->updatePoint(vNew, coordinates->restrictPoint(vOld));
5500:         } // for
5501:         for(int v=0, iVertex=oldNumVertices, newOffset=newNumCellsNormal; iVertex < newNumVertices; ++v, ++iVertex) {
5502:           const point_type vNew = iVertex + newOffset;
5503:           const point_type endpointA = vertex2edge[v*2+0];
5504:           const point_type endpointB = vertex2edge[v*2+1];
5505:           std::cout << "Setting coordinates of vertex " << vNew << " between vertices "
5506:                     << endpointA << " and " << endpointB << std::endl;
5507:           const real *coordsA   = coordinates->restrictPoint(endpointA);
5508:           real coords[3];

5510:           for(int d = 0; d < 3; ++d)
5511:             coords[d]  = coordsA[d];
5512:           const real *coordsB = coordinates->restrictPoint(endpointB);
5513:           for(int d = 0; d < 3; ++d) {
5514:             coords[d] += coordsB[d];
5515:             coords[d] *= 0.5;
5516:           } // for
5517:           newCoordinates->updatePoint(vNew, coords);
5518:         } // for
5519:         delete [] vertex2edge;
5520:         // Fast stratification
5521:         const Obj<typename MeshType::label_type>& height = newMesh->createLabel("height");
5522:         const Obj<typename MeshType::label_type>& depth  = newMesh->createLabel("depth");

5524:         for (int iCell=0; iCell < newNumCellsNormal; ++iCell) {
5525:           const point_type cNew = iCell;
5526:           height->setCone(0, cNew);
5527:           depth->setCone(1, cNew);
5528:         } // for
5529:         for (int iCell=newNumCellsNormal, offset=newNumVertices; iCell < newNumCells; ++iCell) {
5530:           const point_type cNew = iCell + offset;
5531:           height->setCone(0, cNew);
5532:           depth->setCone(1, cNew);
5533:         } // for
5534:         for (int iVertex=0, newOffset=newNumCellsNormal; iVertex < newNumVertices; ++iVertex) {
5535:           const point_type vNew = iVertex + newOffset;
5536:           height->setCone(1, vNew);
5537:           depth->setCone(0, vNew);
5538:         } // for
5539:         newMesh->setHeight(1);
5540:         newMesh->setDepth(1);

5542:       } else {
5543:         int counterBegin = 0;

5545:         int oldNumCells = 0;
5546:         int oldNumVertices = 0;

5548:         int newNumCells = 0;
5549:         int newNumVertices = 0;

5551:         // Count number of cells.
5552:         oldNumCells = cells->size();
5553:         for (typename MeshType::label_sequence::iterator c_iter = cells->begin(); c_iter != cellsEnd; ++c_iter)
5554:           newNumCells += refiner.numNewCells(*c_iter);

5556:         // Count number of vertices (normal vertices).
5557:         oldNumVertices = vertices->size();
5558:         int counterBegin = newNumCells + oldNumVertices;
5559:         const point_type curNewVertex = counterBegin;
5560:         for(typename MeshType::label_sequence::iterator c_iter = cells->begin(); c_iter != cellsEnd; ++c_iter) {
5561:           cV.clear();
5562:           sieve->cone(*c_iter, cV);
5563:           refiner.splitEdge(*c_iter, cV.getSize(), cV.getPoints(), curNewVertex);
5564:         } // for
5565:         newNumVertices = curNewVertex - counterBegin;

5567:         Interval<point_type> oldCellsRange(0, oldNumCells);
5568:         Interval<point_type> newCellsRange(0, newNumCells);

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

5573:         // Allocate chart for new sieve.
5574:         const Obj<sieve_type>& newSieve = newMesh->getSieve();
5575:         assert(!newSieve.isNull());
5576:         newSieve->setChart(typename sieve_type::chart_type(0, newCellsOtherRange.end()));
5577:         refiner.setVertexRelativeOffset(newNumCells-oldNumCells);

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

5581:         // Start with normal cells.
5582:         point_type curNewCell = newCellsRange.begin();
5583:         const typename Interval<point_type>::const_iterator oldCellsRangeEnd = oldCellsRange.end();
5584:         for (typename Interval<point_type>::const_iterator c_iter=oldCellsRange.begin();
5585:              c_iter != oldCellsRangeEnd;
5586:              ++c_iter) {
5587:           // Set new cone and support sizes
5588:           cV.clear();
5589:           sieve->cone(*c_iter, cV);
5590:           const point_type *cone = cV.getPoints();
5591:           const int coneSize = cV.getSize();
5592:           const int newCells = refiner.numNewCells(*c_iter);

5594:           for(int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5595:             const point_type *newCone;
5596:             int newConeSize;

5598:             newSieve->setConeSize(curNewCell, sieve->getConeSize(*c_iter));
5599:             // OPTIMIZE THIS
5600:             refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5601:             for(int v = 0; v < newConeSize; ++v)
5602:               newSieve->addSupportSize(newCone[v], 1);
5603:           } // for
5604:         } // for

5606:         // Create refined normal cells in new sieve.
5607:         curNewCell = newCellsRange.begin();
5608:         for (typename Interval<point_type>::const_iterator c_iter=oldCellsRange.begin();
5609:              c_iter != oldCellsRangeEnd;
5610:              ++c_iter) {
5611:           cV.clear();
5612:           sieve->cone(*c_iter, cV);
5613:           const point_type *cone = cV.getPoints();
5614:           const int coneSize = cV.getSize();
5615:           const int newCells = refiner.numNewCells(*c_iter);

5617:           for (int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5618:             const point_type *newCone;
5619:             int newConeSize;

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

5625:           refiner.getNeighboringVertices(*c_iter, coneSize, cone, firstNewVertex, vertex2edge);
5626:         } // for
5627:         newSieve->symmetrize();

5629:         // Set coordinates in refined mesh.
5630:         const Obj<typename MeshType::real_section_type>& coordinates = mesh->getRealSection("coordinates");
5631:         assert(!coordinates.isNull());
5632:         const Obj<typename MeshType::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates");
5633:         assert(!newCoordinates.isNull());

5635:         const typename MeshType::label_sequence::const_iterator verticesEnd = vertices->end();
5636:         assert(vertices->size() > 0);
5637:         const int spaceDim = coordinates->getFiberDimension(*vertices->begin());
5638:         assert(spaceDim > 0);
5639:         newCoordinates->setChart(typename sieve_type::chart_type(newVerticesRange.begin(), newVerticesRange.end()));

5641:         const typename Interval<point_type>::const_iterator newVerticesRangeEnd = newVerticesRange.end();
5642:         for (typename Interval<point_type>::const_iterator v_iter=newVerticesRange.begin(); v_iter != newVerticesRangeEnd; ++v_iter)
5643:           newCoordinates->setFiberDimension(v_iter, spaceDim);
5644:         newCoordinates->allocatePoint();

5646:         const typename Interval<point_type>::const_iterator oldVerticesRangeEnd = oldVerticesRange.end();
5647:         for (typename Interval<point_type>::const_iterator vOld_iter=oldVerticesRange.begin(), vNew_iter=newVerticesRange.begin(); vOld_iter != oldVerticesRangeEnd; ++vOld_iter)
5648:           newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter));
5649:         for(int v=0, iVertex=oldNumVertices; iVertex < newNumVertices; ++v, ++iVertex) {
5650:           const point_type vNew = newVerticesRange.begin() + iVertex;
5651:           const point_type endpointA = vertex2edge[v*2+0];
5652:           const point_type endpointB = vertex2edge[v*2+1];
5653:           std::cout << "Setting coordinates of vertex " << vNew << " between vertices "
5654:                     << endpointA << " and " << endpointB << std::endl;
5655:           const real *coordsA   = coordinates->restrictPoint(endpointA);
5656:           real coords[3];

5658:           for(int d = 0; d < 3; ++d)
5659:             coords[d]  = coordsA[d];
5660:           const real *coordsB = coordinates->restrictPoint(endpointB);
5661:           for(int d = 0; d < 3; ++d) {
5662:             coords[d] += coordsB[d];
5663:             coords[d] *= 0.5;
5664:           } // for
5665:           newCoordinates->updatePoint(vNew, coords);
5666:         } // for
5667:         delete [] vertex2edge;

5669:         // Fast stratification
5670:         const Obj<typename MeshType::label_type>& height = newMesh->createLabel("height");
5671:         const Obj<typename MeshType::label_type>& depth  = newMesh->createLabel("depth");
5672:         for (int iCell=0; iCell < newNumCells; ++iCell) {
5673:           const point_type cNew = iCell;
5674:           height->setCone(0, cNew);
5675:           depth->setCone(1, cNew);
5676:         } // for
5677:         for (int iVertex=0, newOffset=newNumCellsNormal; iVertex < newNumVertices; ++iVertex) {
5678:           const point_type vNew = iVertex + newOffset;
5679:           height->setCone(1, vNew);
5680:           depth->setCone(0, vNew);
5681:         } // for
5682:         newMesh->setHeight(1);
5683:         newMesh->setDepth(1);
5684:       } // if/else

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


5694:       // Create the parallel overlap
5695:       int *oldNumCellsP    = new int[mesh->commSize()];
5696:       int *newNumCellsP = new int[newMesh->commSize()];
5697:       int  ierr;

5699:       MPI_Allgather((void *) &oldNumCells, 1, MPI_INT, oldNumCellsP, 1, MPI_INT, mesh->comm());CHKERRXX(ierr);
5700:       MPI_Allgather((void *) &newNumCells, 1, MPI_INT, newNumCellsP, 1, MPI_INT, newMesh->comm());CHKERRXX(ierr);
5701:       Obj<typename MeshType::send_overlap_type> newSendOverlap = newMesh->getSendOverlap();
5702:       Obj<typename MeshType::recv_overlap_type> newRecvOverlap = newMesh->getRecvOverlap();
5703:       const Obj<typename MeshType::send_overlap_type>& sendOverlap = mesh->getSendOverlap();
5704:       const Obj<typename MeshType::recv_overlap_type>& recvOverlap = mesh->getRecvOverlap();
5705:       Obj<typename MeshType::send_overlap_type::traits::capSequence> sendPoints  = sendOverlap->cap();
5706:       const typename MeshType::send_overlap_type::source_type        localOffset = newNumCellsP[newMesh->commRank()] - oldNumCellsP[mesh->commRank()];

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

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

5717:           newSendOverlap->addArrow(localPoint+localOffset, rank, remotePoint+remoteOffset);
5718:         }
5719:       }
5720:       Obj<typename MeshType::recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();

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

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

5731:           newRecvOverlap->addArrow(rank, localPoint+localOffset, remotePoint+remoteOffset);
5732:         }
5733:       }
5734:       newMesh->setCalculatedOverlap(true);
5735:       delete [] oldNumCellsP;
5736:       delete [] newNumCellsP;
5737:       // Check edges in edge2vertex for both endpoints sent to same process
5738:       //   Put it in section with point being the lowest numbered vertex and value (other endpoint, new vertex)
5739:       Obj<ALE::Section<point_type, edge_type> > newVerticesSection = new ALE::Section<point_type, edge_type>(mesh->comm());
5740:       std::map<edge_type, std::vector<int> > bdedge2rank;

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

5746:         if (sendOverlap->capContains(left) && sendOverlap->capContains(right)) {
5747:           const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& leftRanksSeq  = sendOverlap->support(left);
5748:           std::set<int> leftRanks(leftRanksSeq->begin(), leftRanksSeq->end());
5749:           const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& rightRanksSeq = sendOverlap->support(right);
5750:           std::set<int> rightRanks(rightRanksSeq->begin(), rightRanksSeq->end());
5751:           std::set<int> ranks;
5752:           std::set_intersection(leftRanks.begin(), leftRanks.end(), rightRanks->begin(), rightRanks->end(),
5753:                                 std::insert_iterator<std::list<int> >(ranks, ranks.begin()));

5755:           if(ranks.size()) {
5756:             newVerticesSection->addFiberDimension(std::min(e_iter->first.first, e_iter->first.second)+localOffset, 1);
5757:             for(typename std::list<int>::const_iterator r_iter = ranks.begin(); r_iter != ranks.end(); ++r_iter) {
5758:               bdedge2rank[e_iter->first].push_back(*r_iter);
5759:             }
5760:           }
5761:         }
5762:       }
5763:       newVerticesSection->allocatePoint();
5764:       const typename ALE::Section<point_type, edge_type>::chart_type& chart = newVerticesSection->getChart();

5766:       for(typename ALE::Section<point_type, edge_type>::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
5767:         typedef typename ALE::Section<point_type, edge_type>::value_type value_type;
5768:         const point_type p      = *c_iter;
5769:         const int        dim    = newVerticesSection->getFiberDimension(p);
5770:         int              v      = 0;
5771:         value_type      *values = new value_type[dim];

5773:         for(typename std::map<edge_type, std::vector<int> >::const_iterator e_iter = bdedge2rank.begin(); e_iter != bdedge2rank.end() && v < dim; ++e_iter) {
5774:           if (std::min(e_iter->first.first, e_iter->first.second)+localOffset == p) {
5775:             values[v++] = edge_type(std::max(e_iter->first.first, e_iter->first.second)+localOffset, edge2vertex[e_iter->first]);
5776:           }
5777:         }
5778:         newVerticesSection->updatePoint(p, values);
5779:         delete [] values;
5780:       }
5781:       // Copy across overlap
5782:       typedef ALE::Pair<int, point_type> overlap_point_type;
5783:       Obj<ALE::Section<overlap_point_type, edge_type> > overlapVertices = new ALE::Section<overlap_point_type, edge_type>(mesh->comm());

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

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

5794:           const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& leftRanks = newSendOverlap->support(e_iter->first.first+localOffset);
5795:           for(typename MeshType::send_overlap_type::traits::supportSequence::iterator lr_iter = leftRanks->begin(); lr_iter != leftRanks->end(); ++lr_iter) {
5796:             if (rank == *lr_iter) {
5797:               remoteLeft = lr_iter.color();
5798:               break;
5799:             }
5800:           }
5801:           const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& rightRanks = newSendOverlap->support(e_iter->first.second+localOffset);
5802:           for(typename MeshType::send_overlap_type::traits::supportSequence::iterator rr_iter = rightRanks->begin(); rr_iter != rightRanks->end(); ++rr_iter) {
5803:             if (rank == *rr_iter) {
5804:               remoteRight = rr_iter.color();
5805:               break;
5806:             }
5807:           }
5808:           const point_type remoteMin   = std::min(remoteLeft, remoteRight);
5809:           const point_type remoteMax   = std::max(remoteLeft, remoteRight);
5810:           const int        remoteSize  = overlapVertices->getFiberDimension(overlap_point_type(rank, remoteMin));
5811:           const edge_type *remoteVals  = overlapVertices->restrictPoint(overlap_point_type(rank, remoteMin));
5812:           point_type       remotePoint = -1;

5814:           for(int d = 0; d < remoteSize; ++d) {
5815:             if (remoteVals[d].first == remoteMax) {
5816:               remotePoint = remoteVals[d].second;
5817:               break;
5818:             }
5819:           }
5820:           newSendOverlap->addArrow(localPoint, rank, remotePoint);
5821:           newRecvOverlap->addArrow(rank, localPoint, remotePoint);
5822:         }
5823:       }
5824:     };
5825: #endif
5826:   };

5828:   class MeshSerializer {
5829:   public:
5830:     template<typename Mesh>
5831:     static void writeMesh(const std::string& filename, Mesh& mesh) {
5832:       std::ofstream fs;

5834:       if (mesh.commRank() == 0) {
5835:         fs.open(filename.c_str());
5836:       }
5837:       writeMesh(fs, mesh);
5838:       if (mesh.commRank() == 0) {
5839:         fs.close();
5840:       }
5841:     }
5842:     template<typename Mesh>
5843:     static void writeMesh(std::ofstream& fs, Mesh& mesh) {
5844:       ISieveSerializer::writeSieve(fs, *mesh.getSieve());
5845:       // Write labels
5846:       const typename Mesh::labels_type& labels = mesh.getLabels();

5848:       if (!mesh.commRank()) {fs << labels.size() << std::endl;}
5849:       for(typename Mesh::labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
5850:         if (!mesh.commRank()) {fs << l_iter->first << std::endl;}
5851:         LabelSifterSerializer::writeLabel(fs, *l_iter->second);
5852:       }
5853:       // Write sections
5854:       Obj<std::set<std::string> > realNames = mesh.getRealSections();

5856:       if (!mesh.commRank()) {fs << realNames->size() << std::endl;}
5857:       for(std::set<std::string>::const_iterator n_iter = realNames->begin(); n_iter != realNames->end(); ++n_iter) {
5858:         if (!mesh.commRank()) {fs << *n_iter << std::endl;}
5859:         SectionSerializer::writeSection(fs, *mesh.getRealSection(*n_iter));
5860:       }
5861:       Obj<std::set<std::string> > intNames = mesh.getIntSections();

5863:       if (!mesh.commRank()) {fs << intNames->size() << std::endl;}
5864:       for(std::set<std::string>::const_iterator n_iter = intNames->begin(); n_iter != intNames->end(); ++n_iter) {
5865:         if (!mesh.commRank()) {fs << *n_iter << std::endl;}
5866:         SectionSerializer::writeSection(fs, *mesh.getIntSection(*n_iter));
5867:       }
5868:       // Write overlap
5869: #ifdef USE_NEW_OVERLAP
5870:       PETSc::OverlapSerializer::writeOverlap(fs, *mesh.getSendOverlap());
5871:       PETSc::OverlapSerializer::writeOverlap(fs, *mesh.getRecvOverlap());
5872: #else
5873:       SifterSerializer::writeSifter(fs, *mesh.getSendOverlap());
5874:       SifterSerializer::writeSifter(fs, *mesh.getRecvOverlap());
5875: #endif
5876:       // Write distribution overlap
5877:       // Write renumbering
5878:     }
5879:     template<typename Mesh>
5880:     static void loadMesh(const std::string& filename, Mesh& mesh) {
5881:       std::ifstream fs;

5883:       if (mesh.commRank() == 0) {
5884:         fs.open(filename.c_str());
5885:       }
5886:       loadMesh(fs, mesh);
5887:       if (mesh.commRank() == 0) {
5888:         fs.close();
5889:       }
5890:     }
5891:     template<typename Mesh>
5892:     static void loadMesh(std::ifstream& fs, Mesh& mesh) {
5893:       ALE::Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh.comm(), mesh.debug());
5894:       PetscErrorCode                      ierr;

5896:       ISieveSerializer::loadSieve(fs, *sieve);
5897:       mesh.setSieve(sieve);
5898:       // Load labels
5899:       int numLabels;

5901:       if (!mesh.commRank()) {fs >> numLabels;}
5902:       MPI_Bcast(&numLabels, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5903:       for(int l = 0; l < numLabels; ++l) {
5904:         ALE::Obj<typename Mesh::label_type> label = new typename Mesh::label_type(mesh.comm(), mesh.debug());
5905:         std::string                         name;
5906:         int                                 len;

5908:         if (!mesh.commRank()) {
5909:           fs >> name;
5910:           len = name.size();
5911:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5912:           MPI_Bcast((void *) name.c_str(), len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5913:         } else {
5914:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5915:           char *n = new char[len+1];
5916:           MPI_Bcast(n, len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5917:           name = n;
5918:           delete [] n;
5919:         }
5920:         LabelSifterSerializer::loadLabel(fs, *label);
5921:         mesh.setLabel(name, label);
5922:       }
5923:       // Load sections
5924:       int numRealSections;

5926:       if (!mesh.commRank()) {fs >> numRealSections;}
5927:       MPI_Bcast(&numRealSections, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5928:       for(int s = 0; s < numRealSections; ++s) {
5929:         ALE::Obj<typename Mesh::real_section_type> section = new typename Mesh::real_section_type(mesh.comm(), mesh.debug());
5930:         std::string                                name;
5931:         int                                        len;

5933:         if (!mesh.commRank()) {
5934:           fs >> name;
5935:           len = name.size();
5936:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5937:           MPI_Bcast((void *) name.c_str(), len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5938:         } else {
5939:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5940:           char *n = new char[len+1];
5941:           MPI_Bcast(n, len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5942:           name = n;
5943:           delete [] n;
5944:         }
5945:         SectionSerializer::loadSection(fs, *section);
5946:         mesh.setRealSection(name, section);
5947:       }
5948:       int numIntSections;

5950:       if (!mesh.commRank()) {fs >> numIntSections;}
5951:       MPI_Bcast(&numIntSections, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5952:       for(int s = 0; s < numIntSections; ++s) {
5953:         ALE::Obj<typename Mesh::int_section_type> section = new typename Mesh::int_section_type(mesh.comm(), mesh.debug());
5954:         std::string                               name;
5955:         int                                       len;

5957:         if (!mesh.commRank()) {
5958:           fs >> name;
5959:           len = name.size();
5960:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5961:           MPI_Bcast((void *) name.c_str(), len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5962:         } else {
5963:           MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5964:           char *n = new char[len+1];
5965:           MPI_Bcast(n, len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5966:           name = n;
5967:           delete [] n;
5968:         }
5969:         SectionSerializer::loadSection(fs, *section);
5970:         mesh.setIntSection(name, section);
5971:       }
5972:       // Load overlap
5973: #ifdef USE_NEW_OVERLAP
5974:       PETSc::OverlapSerializer::loadOverlap(fs, *mesh.getSendOverlap());
5975:       PETSc::OverlapSerializer::loadOverlap(fs, *mesh.getRecvOverlap());
5976: #else
5977:       SifterSerializer::loadSifter(fs, *mesh.getSendOverlap());
5978:       SifterSerializer::loadSifter(fs, *mesh.getRecvOverlap());
5979: #endif
5980:       // Load distribution overlap
5981:       // Load renumbering
5982:     }
5983:   };
5984: } // namespace ALE
5985: #endif