Actual source code: Mesh.hh

  1: #ifndef included_ALE_Mesh_hh
  2: #define included_ALE_Mesh_hh

  4: #include <valarray>

  6: #ifndef  included_ALE_Numbering_hh
  7: #include <Numbering.hh>
  8: #endif

 10: #ifndef  included_ALE_Field_hh
 11: #include <Field.hh>
 12: #endif

 14: #ifndef  included_ALE_SieveBuilder_hh
 15: #include <SieveBuilder.hh>
 16: #endif

 18: #ifndef  included_ALE_LabelSifter_hh
 19: #include <LabelSifter.hh>
 20: #endif

 22: namespace ALE {
 23:   class indexSet : public std::valarray<int> {
 24:   public:
 25:     inline bool
 26:     operator<(const indexSet& __x) {
 27:       if (__x.size() != this->size()) return __x.size() < this->size();
 28:       for(unsigned int i = 0; i < __x.size(); ++i) {
 29:         if (__x[i] == (*this)[i]) continue;
 30:           return __x[i] < (*this)[i];
 31:       }
 32:       return false;
 33:     }
 34:   };
 35:   inline bool
 36:   operator<(const indexSet& __x, const indexSet& __y) {
 37:     if (__x.size() != __y.size()) return __x.size() < __y.size();
 38:     for(unsigned int i = 0; i < __x.size(); ++i) {
 39:       if (__x[i] == __y[i]) continue;
 40:       return __x[i] < __y[i];
 41:     }
 42:     return false;
 43:   };
 44:   inline bool
 45:   operator<=(const indexSet& __x, const indexSet& __y) {
 46:     if (__x.size() != __y.size()) return __x.size() < __y.size();
 47:     for(unsigned int i = 0; i < __x.size(); ++i) {
 48:       if (__x[i] == __y[i]) continue;
 49:       return __x[i] < __y[i];
 50:     }
 51:     return true;
 52:   };
 53:   inline bool
 54:   operator==(const indexSet& __x, const indexSet& __y) {
 55:     if (__x.size() != __y.size()) return false;
 56:     for(unsigned int i = 0; i < __x.size(); ++i) {
 57:       if (__x[i] != __y[i]) return false;
 58:     }
 59:     return true;
 60:   };
 61:   inline bool
 62:   operator!=(const indexSet& __x, const indexSet& __y) {
 63:     if (__x.size() != __y.size()) return true;
 64:     for(unsigned int i = 0; i < __x.size(); ++i) {
 65:       if (__x[i] != __y[i]) return true;
 66:     }
 67:     return false;
 68:   };

 70:   template<typename Sieve_,
 71:            typename RealSection_  = Section<typename Sieve_::point_type, double>,
 72:            typename IntSection_   = Section<typename Sieve_::point_type, int>,
 73:            typename ArrowSection_ = UniformSection<MinimalArrow<typename Sieve_::point_type, typename Sieve_::point_type>, int> >
 74:   class Bundle : public ALE::ParallelObject {
 75:   public:
 76:     typedef Sieve_                                                    sieve_type;
 77:     typedef RealSection_                                              real_section_type;
 78:     typedef IntSection_                                               int_section_type;
 79:     typedef ArrowSection_                                             arrow_section_type;
 80:     typedef Bundle<Sieve_,RealSection_,IntSection_,ArrowSection_>     this_type;
 81:     typedef typename sieve_type::point_type                           point_type;
 82: #define NEW_LABEL
 83: #ifdef NEW_LABEL
 84:     typedef typename ALE::LabelSifter<int, point_type>                label_type;
 85: #else
 86:     typedef typename ALE::Sifter<int, point_type, int>                label_type;
 87: #endif
 88:     typedef typename std::map<const std::string, Obj<label_type> >    labels_type;
 89:     typedef typename label_type::supportSequence                      label_sequence;
 90:     typedef std::map<std::string, Obj<arrow_section_type> >           arrow_sections_type;
 91:     typedef std::map<std::string, Obj<real_section_type> >            real_sections_type;
 92:     typedef std::map<std::string, Obj<int_section_type> >             int_sections_type;
 93:     typedef ALE::Point                                                index_type;
 94:     typedef std::pair<index_type, int>                                oIndex_type;
 95:     typedef std::vector<oIndex_type>                                  oIndexArray;
 96:     typedef std::pair<int *, int>                                     indices_type;
 97:     typedef NumberingFactory<this_type>                               NumberingFactory;
 98:     typedef typename NumberingFactory::numbering_type                 numbering_type;
 99:     typedef typename NumberingFactory::order_type                     order_type;
100:     typedef typename ALE::Sifter<int,point_type,point_type>           send_overlap_type;
101:     typedef typename ALE::Sifter<point_type,int,point_type>           recv_overlap_type;
102:     typedef typename ALE::SieveAlg<this_type>                         sieve_alg_type;
103:     typedef typename sieve_alg_type::coneArray                        coneArray;
104:     typedef typename sieve_alg_type::orientedConeArray                oConeArray;
105:     typedef typename sieve_alg_type::supportArray                     supportArray;
106:   protected:
107:     Obj<sieve_type>       _sieve;
108:     labels_type           _labels;
109:     int                   _maxHeight;
110:     int                   _maxDepth;
111:     arrow_sections_type   _arrowSections;
112:     real_sections_type    _realSections;
113:     int_sections_type     _intSections;
114:     Obj<oIndexArray>      _indexArray;
115:     Obj<NumberingFactory> _factory;
116:     bool                   _calculatedOverlap;
117:     Obj<send_overlap_type> _sendOverlap;
118:     Obj<recv_overlap_type> _recvOverlap;
119:     Obj<send_overlap_type> _distSendOverlap;
120:     Obj<recv_overlap_type> _distRecvOverlap;
121:     // Work space
122:     Obj<std::set<point_type> > _modifiedPoints;
123:   public:
124:     Bundle(MPI_Comm comm, int debug = 0) : ALE::ParallelObject(comm, debug), _maxHeight(-1), _maxDepth(-1) {
125:       this->_indexArray        = new oIndexArray();
126:       this->_modifiedPoints    = new std::set<point_type>();
127:       this->_factory           = NumberingFactory::singleton(this->comm(), this->debug());
128:       this->_calculatedOverlap = false;
129:       this->_sendOverlap       = new send_overlap_type(comm, debug);
130:       this->_recvOverlap       = new recv_overlap_type(comm, debug);
131:     };
132:     Bundle(const Obj<sieve_type>& sieve) : ALE::ParallelObject(sieve->comm(), sieve->debug()), _sieve(sieve), _maxHeight(-1), _maxDepth(-1) {
133:       this->_indexArray        = new oIndexArray();
134:       this->_modifiedPoints    = new std::set<point_type>();
135:       this->_factory           = NumberingFactory::singleton(this->comm(), this->debug());
136:       this->_calculatedOverlap = false;
137:       this->_sendOverlap       = new send_overlap_type(comm, debug);
138:       this->_recvOverlap       = new recv_overlap_type(comm, debug);
139:     };
140:     virtual ~Bundle() {};
141:   public: // Verifiers
142:     bool hasLabel(const std::string& name) {
143:       if (this->_labels.find(name) != this->_labels.end()) {
144:         return true;
145:       }
146:       return false;
147:     };
148:     void checkLabel(const std::string& name) {
149:       if (!this->hasLabel(name)) {
150:         ostringstream msg;
151:         msg << "Invalid label name: " << name << std::endl;
152:         throw ALE::Exception(msg.str().c_str());
153:       }
154:     };
155:   public: // Accessors
156:     const Obj<sieve_type>& getSieve() const {return this->_sieve;};
157:     void setSieve(const Obj<sieve_type>& sieve) {this->_sieve = sieve;};
158:     bool hasArrowSection(const std::string& name) const {
159:       return this->_arrowSections.find(name) != this->_arrowSections.end();
160:     };
161:     const Obj<arrow_section_type>& getArrowSection(const std::string& name) {
162:       if (!this->hasArrowSection(name)) {
163:         Obj<arrow_section_type> section = new arrow_section_type(this->comm(), this->debug());

165:         section->setName(name);
166:         if (this->_debug) {std::cout << "Creating new arrow section: " << name << std::endl;}
167:         this->_arrowSections[name] = section;
168:       }
169:       return this->_arrowSections[name];
170:     };
171:     void setArrowSection(const std::string& name, const Obj<arrow_section_type>& section) {
172:       this->_arrowSections[name] = section;
173:     };
174:     Obj<std::set<std::string> > getArrowSections() const {
175:       Obj<std::set<std::string> > names = std::set<std::string>();

177:       for(typename arrow_sections_type::const_iterator s_iter = this->_arrowSections.begin(); s_iter != this->_arrowSections.end(); ++s_iter) {
178:         names->insert(s_iter->first);
179:       }
180:       return names;
181:     };
182:     bool hasRealSection(const std::string& name) const {
183:       return this->_realSections.find(name) != this->_realSections.end();
184:     };
185:     const Obj<real_section_type>& getRealSection(const std::string& name) {
186:       if (!this->hasRealSection(name)) {
187:         Obj<real_section_type> section = new real_section_type(this->comm(), this->debug());

189:         section->setName(name);
190:         if (this->_debug) {std::cout << "Creating new real section: " << name << std::endl;}
191:         this->_realSections[name] = section;
192:       }
193:       return this->_realSections[name];
194:     };
195:     void setRealSection(const std::string& name, const Obj<real_section_type>& section) {
196:       this->_realSections[name] = section;
197:     };
198:     Obj<std::set<std::string> > getRealSections() const {
199:       Obj<std::set<std::string> > names = std::set<std::string>();

201:       for(typename real_sections_type::const_iterator s_iter = this->_realSections.begin(); s_iter != this->_realSections.end(); ++s_iter) {
202:         names->insert(s_iter->first);
203:       }
204:       return names;
205:     };
206:     bool hasIntSection(const std::string& name) const {
207:       return this->_intSections.find(name) != this->_intSections.end();
208:     };
209:     const Obj<int_section_type>& getIntSection(const std::string& name) {
210:       if (!this->hasIntSection(name)) {
211:         Obj<int_section_type> section = new int_section_type(this->comm(), this->debug());

213:         section->setName(name);
214:         if (this->_debug) {std::cout << "Creating new int section: " << name << std::endl;}
215:         this->_intSections[name] = section;
216:       }
217:       return this->_intSections[name];
218:     };
219:     void setIntSection(const std::string& name, const Obj<int_section_type>& section) {
220:       this->_intSections[name] = section;
221:     };
222:     Obj<std::set<std::string> > getIntSections() const {
223:       Obj<std::set<std::string> > names = std::set<std::string>();

225:       for(typename int_sections_type::const_iterator s_iter = this->_intSections.begin(); s_iter != this->_intSections.end(); ++s_iter) {
226:         names->insert(s_iter->first);
227:       }
228:       return names;
229:     };
230:     const Obj<NumberingFactory>& getFactory() const {return this->_factory;};
231:     const Obj<send_overlap_type>& getSendOverlap() const {return this->_sendOverlap;};
232:     void setSendOverlap(const Obj<send_overlap_type>& overlap) {this->_sendOverlap = overlap;};
233:     const Obj<recv_overlap_type>& getRecvOverlap() const {return this->_recvOverlap;};
234:     void setRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_recvOverlap = overlap;};
235:     const Obj<send_overlap_type>& getDistSendOverlap() const {return this->_distSendOverlap;};
236:     void setDistSendOverlap(const Obj<send_overlap_type>& overlap) {this->_distSendOverlap = overlap;};
237:     const Obj<recv_overlap_type>& getDistRecvOverlap() const {return this->_distRecvOverlap;};
238:     void setDistRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_distRecvOverlap = overlap;};
239:   public: // Labels
240:     int getValue (const Obj<label_type>& label, const point_type& point, const int defValue = 0) {
241:       const Obj<typename label_type::coneSequence>& cone = label->cone(point);

243:       if (cone->size() == 0) return defValue;
244:       return *cone->begin();
245:     };
246:     void setValue(const Obj<label_type>& label, const point_type& point, const int value) {
247:       label->setCone(value, point);
248:     };
249:     template<typename InputPoints>
250:     int getMaxValue (const Obj<label_type>& label, const Obj<InputPoints>& points, const int defValue = 0) {
251:       int maxValue = defValue;

253:       for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
254:         maxValue = std::max(maxValue, this->getValue(label, *p_iter, defValue));
255:       }
256:       return maxValue;
257:     };
258:     const Obj<label_type>& createLabel(const std::string& name) {
259:       this->_labels[name] = new label_type(this->comm(), this->debug());
260:       return this->_labels[name];
261:     };
262:     const Obj<label_type>& getLabel(const std::string& name) {
263:       this->checkLabel(name);
264:       return this->_labels[name];
265:     };
266:     void setLabel(const std::string& name, const Obj<label_type>& label) {
267:       this->_labels[name] = label;
268:     };
269:     const labels_type& getLabels() {
270:       return this->_labels;
271:     };
272:     virtual const Obj<label_sequence>& getLabelStratum(const std::string& name, int value) {
273:       this->checkLabel(name);
274:       return this->_labels[name]->support(value);
275:     };
276:   public: // Stratification
277:     template<class InputPoints>
278:     void computeHeight(const Obj<label_type>& height, const Obj<sieve_type>& sieve, const Obj<InputPoints>& points, int& maxHeight) {
279:       this->_modifiedPoints->clear();

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

286:         if(h1 != h0) {
287:           this->setValue(height, *p_iter, h1);
288:           if (h1 > maxHeight) maxHeight = h1;
289:           this->_modifiedPoints->insert(*p_iter);
290:         }
291:       }
292:       // FIX: We would like to avoid the copy here with cone()
293:       if(this->_modifiedPoints->size() > 0) {
294:         this->computeHeight(height, sieve, sieve->cone(this->_modifiedPoints), maxHeight);
295:       }
296:     };
297:     void computeHeights() {
298:       const Obj<label_type>& label = this->createLabel(std::string("height"));

300:       this->_maxHeight = -1;
301:       this->computeHeight(label, this->_sieve, this->_sieve->leaves(), this->_maxHeight);
302:     };
303:     virtual int height() const {return this->_maxHeight;};
304:     virtual int height(const point_type& point) {
305:       return this->getValue(this->_labels["height"], point, -1);
306:     };
307:     virtual const Obj<label_sequence>& heightStratum(int height) {
308:       return this->getLabelStratum("height", height);
309:     };
310:     template<class InputPoints>
311:     void computeDepth(const Obj<label_type>& depth, const Obj<sieve_type>& sieve, const Obj<InputPoints>& points, int& maxDepth) {
312:       this->_modifiedPoints->clear();

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

319:         if(d1 != d0) {
320:           this->setValue(depth, *p_iter, d1);
321:           if (d1 > maxDepth) maxDepth = d1;
322:           this->_modifiedPoints->insert(*p_iter);
323:         }
324:       }
325:       // FIX: We would like to avoid the copy here with support()
326:       if(this->_modifiedPoints->size() > 0) {
327:         this->computeDepth(depth, sieve, sieve->support(this->_modifiedPoints), maxDepth);
328:       }
329:     };
330:     void computeDepths() {
331:       const Obj<label_type>& label = this->createLabel(std::string("depth"));

333:       this->_maxDepth = -1;
334:       this->computeDepth(label, this->_sieve, this->_sieve->roots(), this->_maxDepth);
335:     };
336:     virtual int depth() const {return this->_maxDepth;};
337:     virtual int depth(const point_type& point) {
338:       return this->getValue(this->_labels["depth"], point, -1);
339:     };
340:     virtual const Obj<label_sequence>& depthStratum(int depth) {
341:       return this->getLabelStratum("depth", depth);
342:     };
345:     virtual void stratify() {
346:       ALE_LOG_EVENT_BEGIN;
347:       this->computeHeights();
348:       this->computeDepths();
349:       ALE_LOG_EVENT_END;
350:     };
351:   public: // Size traversal
352:     template<typename Section_>
353:     int size(const Obj<Section_>& section, const point_type& p) {
354:       const typename Section_::chart_type& chart = section->getChart();
355:       int                                  size  = 0;

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

361:         if (chart.count(p)) {
362:           size += section->getConstrainedFiberDimension(p);
363:         }
364:         for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
365:           if (chart.count(*c_iter)) {
366:             size += section->getConstrainedFiberDimension(*c_iter);
367:           }
368:         }
369:       } else {
370:         const Obj<coneArray>         closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), p);
371:         typename coneArray::iterator end     = closure->end();

373:         for(typename coneArray::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
374:           if (chart.count(*c_iter)) {
375:             size += section->getConstrainedFiberDimension(*c_iter);
376:           }
377:         }
378:       }
379:       return size;
380:     };
381:     template<typename Section_>
382:     int sizeWithBC(const Obj<Section_>& section, const point_type& p) {
383:       const typename Section_::chart_type& chart = section->getChart();
384:       int                                  size  = 0;

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

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

402:         for(typename coneArray::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
403:           if (chart.count(*c_iter)) {
404:             size += section->getFiberDimension(*c_iter);
405:           }
406:         }
407:       }
408:       return size;
409:     };
410:   protected:
411:     int *getIndexArray(const int size) {
412:       static int *array   = NULL;
413:       static int  maxSize = 0;

415:       if (size > maxSize) {
416:         maxSize = size;
417:         if (array) delete [] array;
418:         array = new int[maxSize];
419:       };
420:       return array;
421:     };
422:   public: // Index traversal
423:     void expandInterval(const index_type& interval, PetscInt indices[], PetscInt *indx) {
424:       const int end = interval.prefix + interval.index;

426:       for(int i = interval.index; i < end; ++i) {
427:         indices[(*indx)++] = i;
428:       }
429:     };
430:     void expandInterval(const index_type& interval, const int orientation, PetscInt indices[], PetscInt *indx) {
431:       if (orientation >= 0) {
432:         for(int i = 0; i < interval.prefix; ++i) {
433:           indices[(*indx)++] = interval.index + i;
434:         }
435:       } else {
436:         for(int i = interval.prefix-1; i >= 0; --i) {
437:           indices[(*indx)++] = interval.index + i;
438:         }
439:       }
440:       for(int i = 0; i < -interval.prefix; ++i) {
441:         indices[(*indx)++] = -1;
442:       }
443:     };
444:     void expandIntervals(Obj<oIndexArray> intervals, PetscInt *indices) {
445:       int k = 0;

447:       for(typename oIndexArray::iterator i_iter = intervals->begin(); i_iter != intervals->end(); ++i_iter) {
448:         this->expandInterval(i_iter->first, i_iter->second, indices, &k);
449:       }
450:     }
451:     template<typename Section_>
452:     const indices_type getIndicesRaw(const Obj<Section_>& section, const point_type& p) {
453:       int *indexArray = NULL;
454:       int  size       = 0;

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

460:       for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
461:         size    += section->getFiberDimension(p_iter->first);
462:       }
463:       indexArray = this->getIndexArray(size);
464:       int  k     = 0;
465:       for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
466:         section->getIndicesRaw(p_iter->first, section->getIndex(p_iter->first), indexArray, &k, p_iter->second);
467:       }
468:       return indices_type(indexArray, size);
469:     };
470:     template<typename Section_>
471:     const indices_type getIndices(const Obj<Section_>& section, const point_type& p, const int level = -1) {
472:       int *indexArray = NULL;
473:       int  size       = 0;

475:       if (level == 0) {
476:         size      += section->getFiberDimension(p);
477:         indexArray = this->getIndexArray(size);
478:         int  k     = 0;

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

485:         size      += section->getFiberDimension(p);
486:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
487:           size    += section->getFiberDimension(*p_iter);
488:         }
489:         indexArray = this->getIndexArray(size);
490:         int  k     = 0;

492:         section->getIndices(p, indexArray, &k);
493:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
494:           section->getIndices(*p_iter, indexArray, &k);
495:         }
496:       } else if (level == -1) {
497:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
498:         typename oConeArray::iterator begin   = closure->begin();
499:         typename oConeArray::iterator end     = closure->end();

501:         for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
502:           size    += section->getFiberDimension(p_iter->first);
503:         }
504:         indexArray = this->getIndexArray(size);
505:         int  k     = 0;
506:         for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
507:           section->getIndices(p_iter->first, indexArray, &k, p_iter->second);
508:         }
509:       } else {
510:         throw ALE::Exception("Bundle has not yet implemented getIndices() for an arbitrary level");
511:       }
512:       if (this->debug()) {
513:         for(int i = 0; i < size; ++i) {
514:           printf("[%d]index %d: %d\n", this->commRank(), i, indexArray[i]);
515:         }
516:       }
517:       return indices_type(indexArray, size);
518:     };
519:     template<typename Section_, typename Numbering>
520:     const indices_type getIndices(const Obj<Section_>& section, const point_type& p, const Obj<Numbering>& numbering, const int level = -1) {
521:       int *indexArray = NULL;
522:       int  size       = 0;

524:       if (level == 0) {
525:         size      += section->getFiberDimension(p);
526:         indexArray = this->getIndexArray(size);
527:         int  k     = 0;

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

534:         size      += section->getFiberDimension(p);
535:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
536:           size    += section->getFiberDimension(*p_iter);
537:         }
538:         indexArray = this->getIndexArray(size);
539:         int  k     = 0;

541:         section->getIndices(p, numbering, indexArray, &k);
542:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
543:           section->getIndices(*p_iter, numbering, indexArray, &k);
544:         }
545:       } else if (level == -1) {
546:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
547:         typename oConeArray::iterator end     = closure->end();

549:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
550:           size    += section->getFiberDimension(p_iter->first);
551:         }
552:         indexArray = this->getIndexArray(size);
553:         int  k     = 0;
554:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
555:           section->getIndices(p_iter->first, numbering, indexArray, &k, p_iter->second);
556:         }
557:       } else {
558:         throw ALE::Exception("Bundle has not yet implemented getIndices() for an arbitrary level");
559:       }
560:       return indices_type(indexArray, size);
561:     };
562:   public: // Retrieval traversal
563:     // Return the values for the closure of this point
564:     //   use a smart pointer?
565:     template<typename Section_>
566:     const typename Section_::value_type *restrict(const Obj<Section_>& section, const point_type& p) {
567:       const int size = this->sizeWithBC(section, p);
568:       return this->restrict(section, p, section->getRawArray(size), size);
569:     };
570:     template<typename Section_>
571:     const typename Section_::value_type *restrict(const Obj<Section_>& section, const point_type& p, typename Section_::value_type  *values, const int valuesSize) {
572:       const int size = this->sizeWithBC(section, p);
573:       int       j    = -1;
574:       if (valuesSize < size) throw ALE::Exception("Input array too small");

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

581:         for(int i = 0; i < dim; ++i) {
582:           values[++j] = array[i];
583:         }
584:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
585:         typename sieve_type::coneSequence::iterator   end  = cone->end();

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

590:           array = section->restrictPoint(*p_iter);
591:           for(int i = 0; i < dim; ++i) {
592:             values[++j] = array[i];
593:           }
594:         }
595:       } else {
596:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
597:         typename oConeArray::iterator end     = closure->end();

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

603:           if (p_iter->second >= 0) {
604:             for(int i = 0; i < dim; ++i) {
605:               values[++j] = array[i];
606:             }
607:           } else {
608:             for(int i = dim-1; i >= 0; --i) {
609:               values[++j] = array[i];
610:             }
611:           }
612:         }
613:       }
614:       if (j != size-1) {
615:         ostringstream txt;

617:         txt << "Invalid restrict to point " << p << std::endl;
618:         txt << "  j " << j << " should be " << (size-1) << std::endl;
619:         std::cout << txt.str();
620:         throw ALE::Exception(txt.str().c_str());
621:       }
622:       return values;
623:     };
624:     template<typename Section_>
625:     const typename Section_::value_type *restrictNew(const Obj<Section_>& section, const point_type& p) {
626:       const int                       size    = this->sizeWithBC(section, p);
627:       typename Section_::value_type  *values  = section->getRawArray(size);
628:       const Obj<oConeArray>           closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
629:       typename oConeArray::iterator   end     = closure->end();
630:       int                             j       = -1;

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

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

638:           for(int i = 0; i < dim; ++i) {
639:             values[++j] = array[i];
640:           }
641:         } else {
642:           int offset = 0;

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

647:             for(int i = dim-1; i >= 0; --i) {
648:               values[++j] = array[i+offset];
649:             }
650:             offset += dim;
651:           }
652:         }
653:       }
654:       if (j != size-1) {
655:         ostringstream txt;

657:         txt << "Invalid restrict to point " << p << std::endl;
658:         txt << "  j " << j << " should be " << (size-1) << std::endl;
659:         std::cout << txt.str();
660:         throw ALE::Exception(txt.str().c_str());
661:       }
662:       return values;
663:     };
664:     template<typename Section_>
665:     void update(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
666:       int j = 0;

668:       if (this->height() < 2) {
669:         section->updatePoint(p, &v[j]);
670:         j += section->getFiberDimension(p);
671:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);

673:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
674:           section->updatePoint(*p_iter, &v[j]);
675:           j += section->getFiberDimension(*p_iter);
676:         }
677:       } else {
678:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
679:         typename oConeArray::iterator end     = closure->end();

681:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
682:           section->updatePoint(p_iter->first, &v[j], p_iter->second);
683:           j += section->getFiberDimension(p_iter->first);
684:         }
685:       }
686:     };
687:     template<typename Section_>
688:     void updateAdd(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
689:       int j = 0;

691:       if (this->height() < 2) {
692:         section->updateAddPoint(p, &v[j]);
693:         j += section->getFiberDimension(p);
694:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);

696:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
697:           section->updateAddPoint(*p_iter, &v[j]);
698:           j += section->getFiberDimension(*p_iter);
699:         }
700:       } else {
701:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
702:         typename oConeArray::iterator end     = closure->end();

704:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
705:           section->updateAddPoint(p_iter->first, &v[j], p_iter->second);
706:           j += section->getFiberDimension(p_iter->first);
707:         }
708:       }
709:     };
710:     template<typename Section_>
711:     void updateBC(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
712:       int j = 0;

714:       if (this->height() < 2) {
715:         section->updatePointBC(p, &v[j]);
716:         j += section->getFiberDimension(p);
717:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);

719:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
720:           section->updatePointBC(*p_iter, &v[j]);
721:           j += section->getFiberDimension(*p_iter);
722:         }
723:       } else {
724:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
725:         typename oConeArray::iterator end     = closure->end();

727:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
728:           section->updatePointBC(p_iter->first, &v[j], p_iter->second);
729:           j += section->getFiberDimension(p_iter->first);
730:         }
731:       }
732:     };
733:     template<typename Section_>
734:     void updateAll(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
735:       int j = 0;

737:       if (this->height() < 2) {
738:         section->updatePointAll(p, &v[j]);
739:         j += section->getFiberDimension(p);
740:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);

742:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
743:           section->updatePointAll(*p_iter, &v[j]);
744:           j += section->getFiberDimension(*p_iter);
745:         }
746:       } else {
747:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
748:         typename oConeArray::iterator end     = closure->end();

750:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
751:           section->updatePointAll(p_iter->first, &v[j], p_iter->second);
752:           j += section->getFiberDimension(p_iter->first);
753:         }
754:       }
755:     };
756:     template<typename Section_>
757:     void updateAllAdd(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
758:       int j = 0;

760:       if (this->height() < 2) {
761:         section->updatePointAllAdd(p, &v[j]);
762:         j += section->getFiberDimension(p);
763:         const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);

765:         for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
766:           section->updatePointAllAdd(*p_iter, &v[j]);
767:           j += section->getFiberDimension(*p_iter);
768:         }
769:       } else {
770:         const Obj<oConeArray>         closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
771:         typename oConeArray::iterator end     = closure->end();

773:         for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
774:           section->updatePointAllAdd(p_iter->first, &v[j], p_iter->second);
775:           j += section->getFiberDimension(p_iter->first);
776:         }
777:       }
778:     };
779:   public: // Optimization
780:     // Calculate a custom atlas for the given traversal
781:     //   This returns the tag value assigned to the traversal
782:     template<typename Section_, typename Sequence_>
783:     int calculateCustomAtlas(const Obj<Section_>& section, const Obj<Sequence_>& points) {
784:       const typename Sequence_::iterator begin    = points->begin();
785:       const typename Sequence_::iterator end      = points->end();
786:       const int                          num      = points->size();
787:       int                               *rOffsets = new int[num+1];
788:       int                               *rIndices;
789:       int                               *uOffsets = new int[num+1];
790:       int                               *uIndices;
791:       int                                p;

793:       p = 0;
794:       rOffsets[p] = 0;
795:       uOffsets[p] = 0;
796:       for(typename Sequence_::iterator p_iter = begin; p_iter != end; ++p_iter, ++p) {
797:         rOffsets[p+1] = rOffsets[p] + this->sizeWithBC(section, *p_iter);
798:         uOffsets[p+1] = rOffsets[p+1];
799:         //uOffsets[p+1] = uOffsets[p] + this->size(section, *p_iter);
800:       }
801:       rIndices = new int[rOffsets[p]];
802:       uIndices = new int[uOffsets[p]];
803:       p = 0;
804:       for(typename Sequence_::iterator p_iter = begin; p_iter != end; ++p_iter, ++p) {
805:         const indices_type rIdx = this->getIndicesRaw(section, *p_iter);
806:         for(int i = 0, k = rOffsets[p]; k < rOffsets[p+1]; ++i, ++k) rIndices[k] = rIdx.first[i];

808:         const indices_type uIdx = this->getIndices(section, *p_iter);
809:         for(int i = 0, k = uOffsets[p]; k < uOffsets[p+1]; ++i, ++k) uIndices[k] = uIdx.first[i];
810:       }
811:       return section->setCustomAtlas(rOffsets, rIndices, uOffsets, uIndices);
812:     };
813:     template<typename Section_>
814:     const typename Section_::value_type *restrict(const Obj<Section_>& section, const int tag, const int p) {
815:       const int *offsets, *indices;

817:       section->getCustomRestrictAtlas(tag, &offsets, &indices);
818:       const int size = offsets[p+1] - offsets[p];
819:       return this->restrict(section, tag, p, section->getRawArray(size), offsets, indices);
820:     };
821:     template<typename Section_>
822:     const typename Section_::value_type *restrict(const Obj<Section_>& section, const int tag, const int p, typename Section_::value_type  *values, const int valuesSize) {
823:       const int *offsets, *indices;

825:       section->getCustomRestrictAtlas(tag, &offsets, &indices);
826:       const int size = offsets[p+1] - offsets[p];
827:       if (valuesSize < size) {throw ALE::Exception("Input array too small");}
828:       return this->restrict(section, tag, p, values, offsets, indices);
829:     };
830:     template<typename Section_>
831:     const typename Section_::value_type *restrict(const Obj<Section_>& section, const int tag, const int p, typename Section_::value_type  *values, const int offsets[], const int indices[]) {
832:       const typename Section_::value_type *array = section->restrict();

834:       const int size = offsets[p+1] - offsets[p];
835:       for(int j = 0, k = offsets[p]; j < size; ++j, ++k) {
836:         values[j] = array[indices[k]];
837:       }
838:       return values;
839:     };
840:     template<typename Section_>
841:     void updateAdd(const Obj<Section_>& section, const int tag, const int p, const typename Section_::value_type values[]) {
842:       typename Section_::value_type *array = (typename Section_::value_type *) section->restrict();
843:       const int *offsets, *indices;

845:       section->getCustomUpdateAtlas(tag, &offsets, &indices);
846:       const int size = offsets[p+1] - offsets[p];
847:       for(int j = 0, k = offsets[p]; j < size; ++j, ++k) {
848:         if (indices[k] < 0) continue;
849:         array[indices[k]] += values[j];
850:       }
851:     };
852:   public: // Allocation
853:     template<typename Section_>
854:     void allocate(const Obj<Section_>& section, const Obj<send_overlap_type>& sendOverlap = NULL) {
855:       bool doGhosts = !sendOverlap.isNull();

857:       this->_factory->orderPatch(section, this->getSieve(), sendOverlap);
858:       if (doGhosts) {
859:         if (this->_debug > 1) {std::cout << "Ordering patch for ghosts" << std::endl;}
860:         const typename Section_::chart_type& points = section->getChart();
861:         typename Section_::index_type::index_type offset = 0;

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

866:           offset = std::max(offset, idx.index + std::abs(idx.prefix));
867:         }
868:         this->_factory->orderPatch(section, this->getSieve(), NULL, offset);
869:         if (offset != section->sizeWithBC()) throw ALE::Exception("Inconsistent array sizes in section");
870:       }
871:       section->allocateStorage();
872:     };
873:     template<typename Section_>
874:     void reallocate(const Obj<Section_>& section) {
875:       if (section->getNewAtlas().isNull()) return;
876:       // Since copy() preserves offsets, we must reinitialize them before ordering
877:       const Obj<typename Section_::atlas_type>         atlas    = section->getAtlas();
878:       const Obj<typename Section_::atlas_type>&        newAtlas = section->getNewAtlas();
879:       const typename Section_::atlas_type::chart_type& chart    = newAtlas->getChart();
880:       const typename Section_::atlas_type::chart_type& oldChart = atlas->getChart();
881:       int                                              newSize  = 0;
882:       typename Section_::index_type                    defaultIdx(0, -1);

884:       for(typename Section_::atlas_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
885:         defaultIdx.prefix = newAtlas->restrictPoint(*c_iter)[0].prefix;
886:         newAtlas->updatePoint(*c_iter, &defaultIdx);
887:         newSize += defaultIdx.prefix;
888:       }
889:       section->setAtlas(newAtlas);
890:       this->_factory->orderPatch(section, this->getSieve());
891:       // Copy over existing values
892:       typename Section_::value_type                   *newArray = new typename Section_::value_type[newSize];
893:       const typename Section_::value_type             *array    = section->restrict();

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

900:         for(int i = 0; i < dim; ++i) {
901:           newArray[newOffset+i] = array[offset+i];
902:         }
903:       }
904:       section->replaceStorage(newArray);
905:     };
906:   public: // Overlap
907:     template<typename Sequence>
908:     void constructOverlap(const Obj<Sequence>& points, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap) {
909:       point_type *sendBuf = new point_type[points->size()];
910:       int         size    = 0;
911:       for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
912:         sendBuf[size++] = *l_iter;
913:       }
914:       int *sizes   = new int[this->commSize()];   // The number of points coming from each process
915:       int *offsets = new int[this->commSize()+1]; // Prefix sums for sizes
916:       int *oldOffs = new int[this->commSize()+1]; // Temporary storage
917:       point_type *remotePoints = NULL;            // The points from each process
918:       int        *remoteRanks  = NULL;            // The rank and number of overlap points of each process that overlaps another

920:       // Change to Allgather() for the correct binning algorithm
921:       MPI_Gather(&size, 1, MPI_INT, sizes, 1, MPI_INT, 0, this->comm());
922:       if (this->commRank() == 0) {
923:         offsets[0] = 0;
924:         for(int p = 1; p <= this->commSize(); p++) {
925:           offsets[p] = offsets[p-1] + sizes[p-1];
926:         }
927:         remotePoints = new point_type[offsets[this->commSize()]];
928:       }
929:       MPI_Gatherv(sendBuf, size, MPI_INT, remotePoints, sizes, offsets, MPI_INT, 0, this->comm());
930:       delete [] sendBuf;
931:       std::map<int, std::map<int, std::set<point_type> > > overlapInfo; // Maps (p,q) to their set of overlap points

933:       if (this->commRank() == 0) {
934:         for(int p = 0; p < this->commSize(); p++) {
935:           std::sort(&remotePoints[offsets[p]], &remotePoints[offsets[p+1]]);
936:         }
937:         for(int p = 0; p <= this->commSize(); p++) {
938:           oldOffs[p] = offsets[p];
939:         }
940:         for(int p = 0; p < this->commSize(); p++) {
941:           for(int q = p+1; q < this->commSize(); q++) {
942:             std::set_intersection(&remotePoints[oldOffs[p]], &remotePoints[oldOffs[p+1]],
943:                                   &remotePoints[oldOffs[q]], &remotePoints[oldOffs[q+1]],
944:                                   std::insert_iterator<std::set<point_type> >(overlapInfo[p][q], overlapInfo[p][q].begin()));
945:             overlapInfo[q][p] = overlapInfo[p][q];
946:           }
947:           sizes[p]     = overlapInfo[p].size()*2;
948:           offsets[p+1] = offsets[p] + sizes[p];
949:         }
950:         remoteRanks = new int[offsets[this->commSize()]];
951:         int       k = 0;
952:         for(int p = 0; p < this->commSize(); p++) {
953:           for(typename std::map<int, std::set<point_type> >::iterator r_iter = overlapInfo[p].begin(); r_iter != overlapInfo[p].end(); ++r_iter) {
954:             remoteRanks[k*2]   = r_iter->first;
955:             remoteRanks[k*2+1] = r_iter->second.size();
956:             k++;
957:           }
958:         }
959:       }
960:       int numOverlaps;                          // The number of processes overlapping this process
961:       MPI_Scatter(sizes, 1, MPI_INT, &numOverlaps, 1, MPI_INT, 0, this->comm());
962:       int *overlapRanks = new int[numOverlaps]; // The rank and overlap size for each overlapping process
963:       MPI_Scatterv(remoteRanks, sizes, offsets, MPI_INT, overlapRanks, numOverlaps, MPI_INT, 0, this->comm());
964:       point_type *sendPoints = NULL;            // The points to send to each process
965:       if (this->commRank() == 0) {
966:         for(int p = 0, k = 0; p < this->commSize(); p++) {
967:           sizes[p] = 0;
968:           for(int r = 0; r < (int) overlapInfo[p].size(); r++) {
969:             sizes[p] += remoteRanks[k*2+1];
970:             k++;
971:           }
972:           offsets[p+1] = offsets[p] + sizes[p];
973:         }
974:         sendPoints = new point_type[offsets[this->commSize()]];
975:         for(int p = 0, k = 0; p < this->commSize(); p++) {
976:           for(typename std::map<int, std::set<point_type> >::iterator r_iter = overlapInfo[p].begin(); r_iter != overlapInfo[p].end(); ++r_iter) {
977:             int rank = r_iter->first;
978:             for(typename std::set<point_type>::iterator p_iter = (overlapInfo[p][rank]).begin(); p_iter != (overlapInfo[p][rank]).end(); ++p_iter) {
979:               sendPoints[k++] = *p_iter;
980:             }
981:           }
982:         }
983:       }
984:       int numOverlapPoints = 0;
985:       for(int r = 0; r < numOverlaps/2; r++) {
986:         numOverlapPoints += overlapRanks[r*2+1];
987:       }
988:       point_type *overlapPoints = new point_type[numOverlapPoints];
989:       MPI_Scatterv(sendPoints, sizes, offsets, MPI_INT, overlapPoints, numOverlapPoints, MPI_INT, 0, this->comm());

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

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

997:           sendOverlap->addArrow(point, rank, point);
998:           recvOverlap->addArrow(rank, point, point);
999:         }
1000:       }

1002:       delete [] overlapPoints;
1003:       delete [] overlapRanks;
1004:       delete [] sizes;
1005:       delete [] offsets;
1006:       delete [] oldOffs;
1007:       if (this->commRank() == 0) {
1008:         delete [] remoteRanks;
1009:         delete [] remotePoints;
1010:         delete [] sendPoints;
1011:       }
1012:     };
1013:     void constructOverlap() {
1014:       if (this->_calculatedOverlap) return;
1015:       this->constructOverlap(this->getSieve()->base(), this->getSendOverlap(), this->getRecvOverlap());
1016:       this->constructOverlap(this->getSieve()->cap(),  this->getSendOverlap(), this->getRecvOverlap());
1017:       if (this->debug()) {
1018:         this->_sendOverlap->view("Send overlap");
1019:         this->_recvOverlap->view("Receive overlap");
1020:       }
1021:       this->_calculatedOverlap = true;
1022:     };
1023:   };
1024:   class BoundaryCondition : public ALE::ParallelObject {
1025:   public:
1026:     typedef double (*function_type)(const double []);
1027:     typedef double (*integrator_type)(const double [], const double [], const int, function_type);
1028:   protected:
1029:     std::string     _labelName;
1030:     int             _marker;
1031:     function_type   _func;
1032:     integrator_type _integrator;
1033:   public:
1034:     BoundaryCondition(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {};
1035:     ~BoundaryCondition() {};
1036:   public:
1037:     const std::string& getLabelName() const {return this->_labelName;};
1038:     void setLabelName(const std::string& name) {this->_labelName = name;};
1039:     int getMarker() const {return this->_marker;};
1040:     void setMarker(const int marker) {this->_marker = marker;};
1041:     function_type getFunction() const {return this->_func;};
1042:     void setFunction(function_type func) {this->_func = func;};
1043:     integrator_type getDualIntegrator() const {return this->_integrator;};
1044:     void setDualIntegrator(integrator_type integrator) {this->_integrator = integrator;};
1045:   public:
1046:     double evaluate(const double coords[]) const {return this->_func(coords);};
1047:     double integrateDual(const double v0[], const double J[], const int dualIndex) const {return this->_integrator(v0, J, dualIndex, this->_func);};
1048:   };
1049:   class Discretization : public ALE::ParallelObject {
1050:     typedef std::map<std::string, Obj<BoundaryCondition> > boundaryConditions_type;
1051:   protected:
1052:     boundaryConditions_type _boundaryConditions;
1053:     Obj<BoundaryCondition> _exactSolution;
1054:     std::map<int,int> _dim2dof;
1055:     std::map<int,int> _dim2class;
1056:     int           _quadSize;
1057:     const double *_points;
1058:     const double *_weights;
1059:     int           _basisSize;
1060:     const double *_basis;
1061:     const double *_basisDer;
1062:     const int    *_indices;
1063:     std::map<int, const int *> _exclusionIndices;
1064:   public:
1065:     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) {};
1066:     virtual ~Discretization() {
1067:       if (this->_indices) {delete [] this->_indices;}
1068:       for(std::map<int, const int *>::iterator i_iter = _exclusionIndices.begin(); i_iter != _exclusionIndices.end(); ++i_iter) {
1069:         delete [] i_iter->second;
1070:       }
1071:     };
1072:   public:
1073:     const bool hasBoundaryCondition() {return (this->_boundaryConditions.find("default") != this->_boundaryConditions.end());};
1074:     const Obj<BoundaryCondition>& getBoundaryCondition() {return this->getBoundaryCondition("default");};
1075:     void setBoundaryCondition(const Obj<BoundaryCondition>& boundaryCondition) {this->setBoundaryCondition("default", boundaryCondition);};
1076:     const Obj<BoundaryCondition>& getBoundaryCondition(const std::string& name) {return this->_boundaryConditions[name];};
1077:     void setBoundaryCondition(const std::string& name, const Obj<BoundaryCondition>& boundaryCondition) {this->_boundaryConditions[name] = boundaryCondition;};
1078:     Obj<std::set<std::string> > getBoundaryConditions() const {
1079:       Obj<std::set<std::string> > names = std::set<std::string>();

1081:       for(boundaryConditions_type::const_iterator d_iter = this->_boundaryConditions.begin(); d_iter != this->_boundaryConditions.end(); ++d_iter) {
1082:         names->insert(d_iter->first);
1083:       }
1084:       return names;
1085:     };
1086:     const Obj<BoundaryCondition>& getExactSolution() {return this->_exactSolution;};
1087:     void setExactSolution(const Obj<BoundaryCondition>& exactSolution) {this->_exactSolution = exactSolution;};
1088:     const int     getQuadratureSize() {return this->_quadSize;};
1089:     void          setQuadratureSize(const int size) {this->_quadSize = size;};
1090:     const double *getQuadraturePoints() {return this->_points;};
1091:     void          setQuadraturePoints(const double *points) {this->_points = points;};
1092:     const double *getQuadratureWeights() {return this->_weights;};
1093:     void          setQuadratureWeights(const double *weights) {this->_weights = weights;};
1094:     const int     getBasisSize() {return this->_basisSize;};
1095:     void          setBasisSize(const int size) {this->_basisSize = size;};
1096:     const double *getBasis() {return this->_basis;};
1097:     void          setBasis(const double *basis) {this->_basis = basis;};
1098:     const double *getBasisDerivatives() {return this->_basisDer;};
1099:     void          setBasisDerivatives(const double *basisDer) {this->_basisDer = basisDer;};
1100:     int  getNumDof(const int dim) {return this->_dim2dof[dim];};
1101:     void setNumDof(const int dim, const int numDof) {this->_dim2dof[dim] = numDof;};
1102:     int  getDofClass(const int dim) {return this->_dim2class[dim];};
1103:     void setDofClass(const int dim, const int dofClass) {this->_dim2class[dim] = dofClass;};
1104:   public:
1105:     const int *getIndices() {return this->_indices;};
1106:     const int *getIndices(const int marker) {
1107:       if (!marker) return this->getIndices();
1108:       return this->_exclusionIndices[marker];
1109:     };
1110:     void       setIndices(const int *indices) {this->_indices = indices;};
1111:     void       setIndices(const int *indices, const int marker) {
1112:       if (!marker) this->_indices = indices;
1113:       this->_exclusionIndices[marker] = indices;
1114:     };
1115:     template<typename Bundle>
1116:     int size(const Obj<Bundle>& mesh) {
1117:       const Obj<typename Bundle::label_sequence>& cells   = mesh->heightStratum(0);
1118:       const Obj<typename Bundle::coneArray>       closure = ALE::SieveAlg<Bundle>::closure(mesh, *cells->begin());
1119:       const typename Bundle::coneArray::iterator  end     = closure->end();
1120:       int                                         size    = 0;

1122:       for(typename Bundle::coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
1123:         size += this->_dim2dof[mesh->depth(*cl_iter)];
1124:       }
1125:       return size;
1126:     };
1127:   };
1128: }

1130: namespace ALE {
1131: #ifdef NEW_SECTION
1132:   class Mesh : public Bundle<ALE::Sieve<int,int,int>, GeneralSection<int, double> > {
1133: #else
1134:   class Mesh : public Bundle<ALE::Sieve<int,int,int> > {
1135: #endif
1136:   public:
1137: #ifdef NEW_SECTION
1138:     typedef Bundle<ALE::Sieve<int,int,int>, GeneralSection<int, double> > base_type;
1139: #else
1140:     typedef Bundle<ALE::Sieve<int,int,int> > base_type;
1141: #endif
1142:     typedef base_type::sieve_type            sieve_type;
1143:     typedef sieve_type::point_type           point_type;
1144:     typedef base_type::label_sequence        label_sequence;
1145:     typedef base_type::real_section_type     real_section_type;
1146:     typedef base_type::numbering_type        numbering_type;
1147:     typedef base_type::order_type            order_type;
1148:     typedef base_type::send_overlap_type     send_overlap_type;
1149:     typedef base_type::recv_overlap_type     recv_overlap_type;
1150:     typedef base_type::sieve_alg_type        sieve_alg_type;
1151:     typedef std::set<std::string>            names_type;
1152:     typedef std::map<std::string, Obj<Discretization> > discretizations_type;
1153:   protected:
1154:     int                  _dim;
1155:     discretizations_type _discretizations;
1156:     std::map<int,double> _periodicity;
1157:   public:
1158:     Mesh(MPI_Comm comm, int dim, int debug = 0) : base_type(comm, debug), _dim(dim) {
1159:       ///this->_factory = NumberingFactory::singleton(debug);
1160:     };
1161:   public: // Accessors
1162:     int getDimension() const {return this->_dim;};
1163:     void setDimension(const int dim) {this->_dim = dim;};
1164:     const Obj<Discretization>& getDiscretization() {return this->getDiscretization("default");};
1165:     const Obj<Discretization>& getDiscretization(const std::string& name) {return this->_discretizations[name];};
1166:     void setDiscretization(const Obj<Discretization>& disc) {this->setDiscretization("default", disc);};
1167:     void setDiscretization(const std::string& name, const Obj<Discretization>& disc) {this->_discretizations[name] = disc;};
1168:     Obj<names_type> getDiscretizations() const {
1169:       Obj<names_type> names = names_type();

1171:       for(discretizations_type::const_iterator d_iter = this->_discretizations.begin(); d_iter != this->_discretizations.end(); ++d_iter) {
1172:         names->insert(d_iter->first);
1173:       }
1174:       return names;
1175:     };
1176:     bool getPeriodicity(const int d) {return this->_periodicity[d];};
1177:     void setPeriodicity(const int d, const double length) {this->_periodicity[d] = length;};
1178:   public: // Mesh geometry
1179:     void computeTriangleGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
1180:       const double *coords = this->restrict(coordinates, e);
1181:       const int     dim    = 2;
1182:       double        invDet;

1184:       if (v0) {
1185:         for(int d = 0; d < dim; d++) {
1186:           v0[d] = coords[d];
1187:         }
1188:       }
1189:       if (J) {
1190:         for(int d = 0; d < dim; d++) {
1191:           for(int f = 0; f < dim; f++) {
1192:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
1193:           }
1194:         }
1195:         detJ = J[0]*J[3] - J[1]*J[2];
1196:         if (detJ < 0.0) {
1197:           const double  xLength = this->_periodicity[0];

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

1202:             if (v0x == 0.0) {
1203:               v0x = v0[0] = xLength;
1204:             }
1205:             for(int f = 0; f < dim; f++) {
1206:               const double px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];

1208:               J[0*dim+f] = 0.5*(px - v0x);
1209:             }
1210:           }
1211:           detJ = J[0]*J[3] - J[1]*J[2];
1212:         }
1213:         PetscLogFlopsNoCheck(8 + 3);
1214:       }
1215:       if (invJ) {
1216:         invDet  = 1.0/detJ;
1217:         invJ[0] =  invDet*J[3];
1218:         invJ[1] = -invDet*J[1];
1219:         invJ[2] = -invDet*J[2];
1220:         invJ[3] =  invDet*J[0];
1221:         PetscLogFlopsNoCheck(5);
1222:       }
1223:     };
1224:     void computeQuadrilateralGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double point[], double v0[], double J[], double invJ[], double& detJ) {
1225:       const double *coords = this->restrict(coordinates, e);
1226:       const int     dim    = 2;
1227:       double        invDet;

1229:       if (v0) {
1230:         for(int d = 0; d < dim; d++) {
1231:           v0[d] = coords[d];
1232:         }
1233:       }
1234:       if (J) {
1235:         double x_1 = coords[2] - coords[0];
1236:         double y_1 = coords[3] - coords[1];
1237:         double x_2 = coords[6] - coords[0];
1238:         double y_2 = coords[7] - coords[1];
1239:         double x_3 = coords[4] - coords[0];
1240:         double y_3 = coords[5] - coords[1];

1242:         J[0] = x_1 + (x_3 - x_1 - x_2)*point[1];
1243:         J[1] = x_2 + (x_3 - x_1 - x_2)*point[0];
1244:         J[2] = y_1 + (y_3 - y_1 - y_2)*point[1];
1245:         J[3] = y_1 + (y_3 - y_1 - y_2)*point[0];
1246:         detJ = J[0]*J[3] - J[1]*J[2];
1247:         PetscLogFlopsNoCheck(6 + 16 + 3);
1248:       }
1249:       if (invJ) {
1250:         invDet  = 1.0/detJ;
1251:         invJ[0] =  invDet*J[3];
1252:         invJ[1] = -invDet*J[1];
1253:         invJ[2] = -invDet*J[2];
1254:         invJ[3] =  invDet*J[0];
1255:         PetscLogFlopsNoCheck(5);
1256:       }
1257:     };
1258:     void computeTetrahedronGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
1259:       const double *coords = this->restrict(coordinates, e);
1260:       const int     dim    = 3;
1261:       double        invDet;

1263:       if (v0) {
1264:         for(int d = 0; d < dim; d++) {
1265:           v0[d] = coords[d];
1266:         }
1267:       }
1268:       if (J) {
1269:         for(int d = 0; d < dim; d++) {
1270:           for(int f = 0; f < dim; f++) {
1271:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
1272:           }
1273:         }
1274:         // The minus sign is here since I orient the first face to get the outward normal
1275:         detJ = -(J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
1276:                  J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
1277:                  J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
1278:         PetscLogFlopsNoCheck(18 + 12);
1279:       }
1280:       if (invJ) {
1281:         invDet  = -1.0/detJ;
1282:         invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
1283:         invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
1284:         invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
1285:         invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
1286:         invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
1287:         invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
1288:         invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
1289:         invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
1290:         invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
1291:         PetscLogFlopsNoCheck(37);
1292:       }
1293:     };
1294:     void computeHexahedralGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double point[], double v0[], double J[], double invJ[], double& detJ) {
1295:       const double *coords = this->restrict(coordinates, e);
1296:       const int     dim    = 3;
1297:       double        invDet;

1299:       if (v0) {
1300:         for(int d = 0; d < dim; d++) {
1301:           v0[d] = coords[d];
1302:         }
1303:       }
1304:       if (J) {
1305:         double x_1 = coords[3]  - coords[0];
1306:         double y_1 = coords[4]  - coords[1];
1307:         double z_1 = coords[5]  - coords[2];
1308:         double x_2 = coords[6]  - coords[0];
1309:         double y_2 = coords[7]  - coords[1];
1310:         double z_2 = coords[8]  - coords[2];
1311:         double x_3 = coords[9]  - coords[0];
1312:         double y_3 = coords[10] - coords[1];
1313:         double z_3 = coords[11] - coords[2];
1314:         double x_4 = coords[12] - coords[0];
1315:         double y_4 = coords[13] - coords[1];
1316:         double z_4 = coords[14] - coords[2];
1317:         double x_5 = coords[15] - coords[0];
1318:         double y_5 = coords[16] - coords[1];
1319:         double z_5 = coords[17] - coords[2];
1320:         double x_6 = coords[18] - coords[0];
1321:         double y_6 = coords[19] - coords[1];
1322:         double z_6 = coords[20] - coords[2];
1323:         double x_7 = coords[21] - coords[0];
1324:         double y_7 = coords[22] - coords[1];
1325:         double z_7 = coords[23] - coords[2];
1326:         double g_x = x_1 - x_2 + x_3 + x_4 - x_5 + x_6 - x_7;
1327:         double g_y = y_1 - y_2 + y_3 + y_4 - y_5 + y_6 - y_7;
1328:         double g_z = z_1 - z_2 + z_3 + z_4 - z_5 + z_6 - z_7;

1330:         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];
1331:         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];
1332:         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];
1333:         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];
1334:         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];
1335:         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];
1336:         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];
1337:         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];
1338:         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];
1339:         detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
1340:                 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
1341:                 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
1342:         PetscLogFlopsNoCheck(39 + 81 + 12);
1343:       }
1344:       if (invJ) {
1345:         invDet  = 1.0/detJ;
1346:         invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
1347:         invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
1348:         invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
1349:         invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
1350:         invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
1351:         invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
1352:         invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
1353:         invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
1354:         invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
1355:         PetscLogFlopsNoCheck(37);
1356:       }
1357:     };
1358:     void computeElementGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
1359:       if (this->_dim == 2) {
1360:         computeTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
1361:       } else if (this->_dim == 3) {
1362:         computeTetrahedronGeometry(coordinates, e, v0, J, invJ, detJ);
1363:       } else {
1364:         throw ALE::Exception("Unsupport dimension for element geometry computation");
1365:       }
1366:     };
1367:     void computeLineFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
1368:       const arrow_section_type::point_type arrow(cell, face);
1369:       const bool reversed = (this->getArrowSection("orientation")->restrictPoint(arrow)[0] == -2);
1370:       const int  dim      = this->getDimension();
1371:       double     norm     = 0.0;
1372:       double    *vec      = tangent;

1374:       if (f == 0) {
1375:         vec[0] = 0.0;        vec[1] = -1.0;
1376:       } else if (f == 1) {
1377:         vec[0] = 0.70710678; vec[1] = 0.70710678;
1378:       } else if (f == 2) {
1379:         vec[0] = -1.0;       vec[1] = 0.0;
1380:       }
1381:       for(int d = 0; d < dim; ++d) {
1382:         normal[d] = 0.0;
1383:         for(int e = 0; e < dim; ++e) normal[d] += cellInvJ[e*dim+d]*vec[e];
1384:         if (reversed) normal[d] = -normal[d];
1385:         norm += normal[d]*normal[d];
1386:       }
1387:       norm = std::sqrt(norm);
1388:       for(int d = 0; d < dim; ++d) {
1389:         normal[d] /= norm;
1390:       }
1391:       tangent[0] =  normal[1];
1392:       tangent[1] = -normal[0];
1393:       if (this->debug()) {
1394:         std::cout << "Cell: " << cell << " Face: " << face << "("<<f<<")" << std::endl;
1395:         for(int d = 0; d < dim; ++d) {
1396:           std::cout << "Normal["<<d<<"]: " << normal[d] << " Tangent["<<d<<"]: " << tangent[d] << std::endl;
1397:         }
1398:       }
1399:       // Now get 1D Jacobian info
1400:       //   Should be a way to get this directly
1401:       const double *coords = this->restrict(this->getRealSection("coordinates"), face);
1402:       detJ    = std::sqrt(PetscSqr(coords[1*2+0] - coords[0*2+0]) + PetscSqr(coords[1*2+1] - coords[0*2+1]))/2.0;
1403:       invJ[0] = 1.0/detJ;
1404:     };
1405:     void computeTriangleFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
1406:       const arrow_section_type::point_type arrow(cell, face);
1407:       const bool reversed = this->getArrowSection("orientation")->restrictPoint(arrow)[0] < 0;
1408:       const int  dim      = this->getDimension();
1409:       const int  faceDim  = dim-1;
1410:       double     norm     = 0.0;
1411:       double    *vec      = tangent;

1413:       if (f == 0) {
1414:         vec[0] = 0.0;        vec[1] = 0.0;        vec[2] = -1.0;
1415:       } else if (f == 1) {
1416:         vec[0] = 0.0;        vec[1] = -1.0;       vec[2] = 0.0;
1417:       } else if (f == 2) {
1418:         vec[0] = 0.57735027; vec[1] = 0.57735027; vec[2] = 0.57735027;
1419:       } else if (f == 3) {
1420:         vec[0] = -1.0;       vec[1] = 0.0;        vec[2] = 0.0;
1421:       }
1422:       for(int d = 0; d < dim; ++d) {
1423:         normal[d] = 0.0;
1424:         for(int e = 0; e < dim; ++e) normal[d] += cellInvJ[e*dim+d]*vec[e];
1425:         if (reversed) normal[d] = -normal[d];
1426:         norm += normal[d]*normal[d];
1427:       }
1428:       norm = std::sqrt(norm);
1429:       for(int d = 0; d < dim; ++d) {
1430:         normal[d] /= norm;
1431:       }
1432:       // Get tangents
1433:       tangent[0] = normal[1] - normal[2];
1434:       tangent[1] = normal[2] - normal[0];
1435:       tangent[2] = normal[0] - normal[1];
1436:       norm = 0.0;
1437:       for(int d = 0; d < dim; ++d) {
1438:         norm += tangent[d]*tangent[d];
1439:       }
1440:       norm = std::sqrt(norm);
1441:       for(int d = 0; d < dim; ++d) {
1442:         tangent[d] /= norm;
1443:       }
1444:       tangent[3] = normal[1]*tangent[2] - normal[2]*tangent[1];
1445:       tangent[4] = normal[2]*tangent[0] - normal[0]*tangent[2];
1446:       tangent[5] = normal[0]*tangent[1] - normal[1]*tangent[0];
1447:       if (this->debug()) {
1448:         std::cout << "Cell: " << cell << " Face: " << face << "("<<f<<")" << std::endl;
1449:         for(int d = 0; d < dim; ++d) {
1450:           std::cout << "Normal["<<d<<"]: " << normal[d] << " TangentA["<<d<<"]: " << tangent[d] << " TangentB["<<d<<"]: " << tangent[dim+d] << std::endl;
1451:         }
1452:       }
1453:       // Now get 2D Jacobian info
1454:       //   Should be a way to get this directly
1455:       const double *coords = this->restrict(this->getRealSection("coordinates"), face);
1456:       // Rotate so that normal in z
1457:       double invR[9], R[9];
1458:       double detR, invDetR;
1459:       for(int d = 0; d < dim; d++) {
1460:         invR[d*dim+0] = tangent[d];
1461:         invR[d*dim+1] = tangent[dim+d];
1462:         invR[d*dim+2] = normal[d];
1463:       }
1464:       invDetR = (invR[0*3+0]*(invR[1*3+1]*invR[2*3+2] - invR[1*3+2]*invR[2*3+1]) +
1465:                  invR[0*3+1]*(invR[1*3+2]*invR[2*3+0] - invR[1*3+0]*invR[2*3+2]) +
1466:                  invR[0*3+2]*(invR[1*3+0]*invR[2*3+1] - invR[1*3+1]*invR[2*3+0]));
1467:       detR  = 1.0/invDetR;
1468:       R[0*3+0] = detR*(invR[1*3+1]*invR[2*3+2] - invR[1*3+2]*invR[2*3+1]);
1469:       R[0*3+1] = detR*(invR[0*3+2]*invR[2*3+1] - invR[0*3+1]*invR[2*3+2]);
1470:       R[0*3+2] = detR*(invR[0*3+1]*invR[1*3+2] - invR[0*3+2]*invR[1*3+1]);
1471:       R[1*3+0] = detR*(invR[1*3+2]*invR[2*3+0] - invR[1*3+0]*invR[2*3+2]);
1472:       R[1*3+1] = detR*(invR[0*3+0]*invR[2*3+2] - invR[0*3+2]*invR[2*3+0]);
1473:       R[1*3+2] = detR*(invR[0*3+2]*invR[1*3+0] - invR[0*3+0]*invR[1*3+2]);
1474:       R[2*3+0] = detR*(invR[1*3+0]*invR[2*3+1] - invR[1*3+1]*invR[2*3+0]);
1475:       R[2*3+1] = detR*(invR[0*3+1]*invR[2*3+0] - invR[0*3+0]*invR[2*3+1]);
1476:       R[2*3+2] = detR*(invR[0*3+0]*invR[1*3+1] - invR[0*3+1]*invR[1*3+0]);
1477:       for(int d = 0; d < dim; d++) {
1478:         for(int e = 0; e < dim; e++) {
1479:           invR[d*dim+e] = 0.0;
1480:           for(int g = 0; g < dim; g++) {
1481:             invR[d*dim+e] += R[e*dim+g]*coords[d*dim+g];
1482:           }
1483:         }
1484:       }
1485:       for(int d = dim-1; d >= 0; --d) {
1486:         invR[d*dim+2] -= invR[0*dim+2];
1487:         if (this->debug() && (d == dim-1)) {
1488:           double ref[9];
1489:           for(int q = 0; q < dim; q++) {
1490:             for(int e = 0; e < dim; e++) {
1491:               ref[q*dim+e] = 0.0;
1492:               for(int g = 0; g < dim; g++) {
1493:                 ref[q*dim+e] += cellInvJ[e*dim+g]*coords[q*dim+g];
1494:               }
1495:             }
1496:           }
1497:           std::cout << "f: " << f << std::endl;
1498:           std::cout << this->printMatrix(std::string("coords"), dim, dim, coords) << std::endl;
1499:           std::cout << this->printMatrix(std::string("ref coords"), dim, dim, ref) << std::endl;
1500:           std::cout << this->printMatrix(std::string("R"), dim, dim, R) << std::endl;
1501:           std::cout << this->printMatrix(std::string("invR"), dim, dim, invR) << std::endl;
1502:         }
1503:         if (fabs(invR[d*dim+2]) > 1.0e-8) {
1504:           throw ALE::Exception("Invalid rotation");
1505:         }
1506:       }
1507:       double J[4];
1508:       for(int d = 0; d < faceDim; d++) {
1509:         for(int e = 0; e < faceDim; e++) {
1510:           J[d*faceDim+e] = 0.5*(invR[(e+1)*dim+d] - invR[0*dim+d]);
1511:         }
1512:       }
1513:       detJ = fabs(J[0]*J[3] - J[1]*J[2]);
1514:       // Probably need something here if detJ < 0
1515:       const double invDet = 1.0/detJ;
1516:       invJ[0] =  invDet*J[3];
1517:       invJ[1] = -invDet*J[1];
1518:       invJ[2] = -invDet*J[2];
1519:       invJ[3] =  invDet*J[0];
1520:     };
1521:     void computeFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
1522:       if (this->_dim == 2) {
1523:         computeLineFaceGeometry(cell, face, f, cellInvJ, invJ, detJ, normal, tangent);
1524:       } else if (this->_dim == 3) {
1525:         computeTriangleFaceGeometry(cell, face, f, cellInvJ, invJ, detJ, normal, tangent);
1526:       } else {
1527:         throw ALE::Exception("Unsupport dimension for element geometry computation");
1528:       }
1529:     };
1530:     double getMaxVolume() {
1531:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1532:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
1533:       const int                     dim         = this->getDimension();
1534:       double v0[3], J[9], invJ[9], detJ, refVolume = 0.0, maxVolume = 0.0;

1536:       if (dim == 1) refVolume = 2.0;
1537:       if (dim == 2) refVolume = 2.0;
1538:       if (dim == 3) refVolume = 4.0/3.0;
1539:       for(label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1540:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
1541:         maxVolume = std::max(maxVolume, detJ*refVolume);
1542:       }
1543:       return maxVolume;
1544:     };
1545:     // Find the cell in which this point lies (stupid algorithm)
1546:     point_type locatePoint_2D(const real_section_type::value_type point[]) {
1547:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1548:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
1549:       const int                     embedDim    = 2;
1550:       double v0[2], J[4], invJ[4], detJ;

1552:       for(label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1553:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
1554:         double xi   = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]);
1555:         double eta  = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]);

1557:         if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) {
1558:           return *c_iter;
1559:         }
1560:       }
1561:       throw ALE::Exception("Could not locate point");
1562:     };
1563:     //   Assume a simplex and 3D
1564:     point_type locatePoint_3D(const real_section_type::value_type point[]) {
1565:       const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1566:       const Obj<label_sequence>&    cells       = this->heightStratum(0);
1567:       const int                     embedDim    = 3;
1568:       double v0[3], J[9], invJ[9], detJ;

1570:       for(label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1571:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
1572:         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]);
1573:         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]);
1574:         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]);

1576:         if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) {
1577:           return *c_iter;
1578:         }
1579:       }
1580:       throw ALE::Exception("Could not locate point");
1581:     };
1582:     point_type locatePoint(const real_section_type::value_type point[], point_type guess = -1) {
1583:       //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
1584:       if (guess != -1) {
1585:         return guess;
1586:       }else if (this->_dim == 2) {
1587:         return locatePoint_2D(point);
1588:       } else if (this->_dim == 3) {
1589:         return locatePoint_3D(point);
1590:       } else {
1591:         throw ALE::Exception("No point location for mesh dimension");
1592:       }
1593:     };
1594:   public: // Discretization
1595:     void markBoundaryCells(const std::string& name, const int marker = 1, const int newMarker = 2, const bool onlyVertices = false) {
1596:       const Obj<label_type>&     label    = this->getLabel(name);
1597:       const Obj<label_sequence>& boundary = this->getLabelStratum(name, marker);
1598:       const Obj<sieve_type>&     sieve    = this->getSieve();

1600:       if (!onlyVertices) {
1601:         const label_sequence::iterator end = boundary->end();

1603:         for(label_sequence::iterator e_iter = boundary->begin(); e_iter != end; ++e_iter) {
1604:           if (this->height(*e_iter) == 1) {
1605:             const point_type cell = *sieve->support(*e_iter)->begin();

1607:             this->setValue(label, cell, newMarker);
1608:           }
1609:         }
1610:       } else {
1611:         const label_sequence::iterator end   = boundary->end();
1612:         const int                      depth = this->depth();

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

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

1622:             for(sieve_type::traits::coneSequence::iterator e_iter = cone->begin(); e_iter != cEnd; ++e_iter) {
1623:               if (sieve->support(*e_iter)->size() == 1) {
1624:                 this->setValue(label, *c_iter, newMarker);
1625:                 break;
1626:               }
1627:             }
1628:           }
1629:         }
1630:       }
1631:     };
1632:     int setFiberDimensions(const Obj<real_section_type>& s, const Obj<names_type>& discs, names_type& bcLabels) {
1633:       const int debug  = this->debug();
1634:       int       maxDof = 0;

1636:       for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter) {
1637:         s->addSpace();
1638:       }
1639:       for(int d = 0; d <= this->_dim; ++d) {
1640:         int numDof = 0;
1641:         int f      = 0;

1643:         for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
1644:           const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);

1646:           numDof += disc->getNumDof(d);
1647:           s->setFiberDimension(this->depthStratum(d), disc->getNumDof(d), f);
1648:         }
1649:         s->setFiberDimension(this->depthStratum(d), numDof);
1650:         maxDof = std::max(maxDof, numDof);
1651:       }
1652:       // Process exclusions
1653:       int f = 0;

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

1660:         if (this->hasLabel(labelName)) {
1661:           const Obj<label_type>&         label     = this->getLabel(labelName);
1662:           const Obj<label_sequence>&     exclusion = this->getLabelStratum(labelName, 1);
1663:           const label_sequence::iterator end       = exclusion->end();
1664:           if (debug) {label->view(labelName.c_str());}

1666:           for(label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
1667:             const Obj<coneArray>      closure = ALE::SieveAlg<ALE::Mesh>::closure(this, this->getArrowSection("orientation"), *e_iter);
1668:             const coneArray::iterator cEnd    = closure->end();

1670:             for(coneArray::iterator c_iter = closure->begin(); c_iter != cEnd; ++c_iter) {
1671:               if (seen.find(*c_iter) != seen.end()) continue;
1672:               if (this->getValue(label, *c_iter) == 1) {
1673:                 seen.insert(*c_iter);
1674:                 s->setFiberDimension(*c_iter, 0, f);
1675:                 s->addFiberDimension(*c_iter, -disc->getNumDof(this->depth(*c_iter)));
1676:                 if (debug) {std::cout << "  cell: " << *c_iter << " dim: " << disc->getNumDof(this->depth(*c_iter)) << std::endl;}
1677:               }
1678:             }
1679:           }
1680:         }
1681:       }
1682:       // Process constraints
1683:       f = 0;
1684:       for(std::set<std::string>::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
1685:         const Obj<ALE::Discretization>&    disc        = this->getDiscretization(*f_iter);
1686:         const Obj<std::set<std::string> >  bcs         = disc->getBoundaryConditions();
1687:         std::string                        excludeName = "exclude-"+*f_iter;

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

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

1697:             for(label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
1698:               if (!this->getValue(label, *e_iter)) {
1699:                 s->addConstraintDimension(*e_iter, disc->getNumDof(this->depth(*e_iter)));
1700:                 s->setConstraintDimension(*e_iter, disc->getNumDof(this->depth(*e_iter)), f);
1701:               }
1702:             }
1703:           } else {
1704:             for(label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
1705:               s->addConstraintDimension(*e_iter, disc->getNumDof(this->depth(*e_iter)));
1706:               s->setConstraintDimension(*e_iter, disc->getNumDof(this->depth(*e_iter)), f);
1707:             }
1708:           }
1709:         }
1710:       }
1711:       return maxDof;
1712:     };
1713:     void calculateIndices() {
1714:       // Should have an iterator over the whole tree
1715:       Obj<names_type> discs = this->getDiscretizations();
1716:       Obj<Mesh>       mesh  = this;
1717:       const int       debug = this->debug();
1718:       std::map<std::string, std::pair<int, int*> > indices;

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

1724:         indices[*d_iter] = std::pair<int, int*>(0, new int[disc->size(mesh)]);
1725:         disc->setIndices(indices[*d_iter].second);
1726:       }
1727:       const Obj<label_sequence>& cells   = this->heightStratum(0);
1728:       const Obj<coneArray>       closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *cells->begin());
1729:       const coneArray::iterator  end     = closure->end();
1730:       int                        offset  = 0;

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

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

1741:           if (debug) {std::cout << "    disc " << disc->getName() << " numDof " << num << std::endl;}
1742:           for(int o = 0; o < num; ++o) {
1743:             indices[*d_iter].second[indices[*d_iter].first++] = offset++;
1744:           }
1745:         }
1746:       }
1747:       if (debug) {
1748:         for(names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
1749:           const Obj<Discretization>& disc = this->getDiscretization(*d_iter);

1751:           std::cout << "Discretization " << disc->getName() << " indices:";
1752:           for(int i = 0; i < indices[*d_iter].first; ++i) {
1753:             std::cout << " " << indices[*d_iter].second[i];
1754:           }
1755:           std::cout << std::endl;
1756:         }
1757:       }
1758:     };
1759:     void calculateIndicesExcluded(const Obj<real_section_type>& s, const Obj<names_type>& discs) {
1760:       typedef std::map<std::string, std::pair<int, indexSet> > indices_type;
1761:       const Obj<label_type>& indexLabel = this->createLabel("cellExclusion");
1762:       Obj<Mesh> mesh   = this;
1763:       const int debug  = this->debug();
1764:       int       marker = 0;
1765:       std::map<indices_type, int> indexMap;
1766:       indices_type                indices;

1768:       mesh.addRef();
1769:       for(names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
1770:         const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
1771:         const int                  size = disc->size(mesh);

1773:         indices[*d_iter].second.resize(size);
1774:       }
1775:       const names_type::const_iterator dBegin = discs->begin();
1776:       const names_type::const_iterator dEnd   = discs->end();
1777:       std::set<point_type> seen;
1778:       int f = 0;

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

1783:         if (this->hasLabel(labelName)) {
1784:           const Obj<label_sequence>&     exclusion = this->getLabelStratum(labelName, 1);
1785:           const label_sequence::iterator end       = exclusion->end();

1787:           if (debug) {std::cout << "Processing exclusion " << labelName << std::endl;}
1788:           for(label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
1789:             if (this->height(*e_iter)) continue;
1790:             const Obj<coneArray>      closure = ALE::SieveAlg<ALE::Mesh>::closure(this, this->getArrowSection("orientation"), *e_iter);
1791:             const coneArray::iterator clEnd   = closure->end();
1792:             int                       offset  = 0;

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

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

1802:                 if (debug) {std::cout << "      disc " << *g_iter << " numDof " << fDim << std::endl;}
1803:                 for(int d = 0; d < fDim; ++d) {
1804:                   indices[*g_iter].second[indices[*g_iter].first++] = offset++;
1805:                 }
1806:               }
1807:             }
1808:             const std::map<indices_type, int>::iterator entry = indexMap.find(indices);

1810:             if (debug) {
1811:               for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
1812:                 for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
1813:                   std::cout << "Discretization (" << i_iter->second << ") " << *g_iter << " indices:";
1814:                   for(int i = 0; i < ((indices_type) i_iter->first)[*g_iter].first; ++i) {
1815:                     std::cout << " " << ((indices_type) i_iter->first)[*g_iter].second[i];
1816:                   }
1817:                   std::cout << std::endl;
1818:                 }
1819:                 std::cout << "Comparison: " << (indices == i_iter->first) << std::endl;
1820:               }
1821:               for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
1822:                 std::cout << "Discretization " << *g_iter << " indices:";
1823:                 for(int i = 0; i < indices[*g_iter].first; ++i) {
1824:                   std::cout << " " << indices[*g_iter].second[i];
1825:                 }
1826:                 std::cout << std::endl;
1827:               }
1828:             }
1829:             if (entry != indexMap.end()) {
1830:               this->setValue(indexLabel, *e_iter, entry->second);
1831:               if (debug) {std::cout << "  Found existing indices with marker " << entry->second << std::endl;}
1832:             } else {
1833:               indexMap[indices] = ++marker;
1834:               this->setValue(indexLabel, *e_iter, marker);
1835:               if (debug) {std::cout << "  Created new indices with marker " << marker << std::endl;}
1836:             }
1837:             for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
1838:               indices[*g_iter].first  = 0;
1839:               for(unsigned int i = 0; i < indices[*g_iter].second.size(); ++i) indices[*g_iter].second[i] = 0;
1840:             }
1841:           }
1842:         }
1843:       }
1844:       if (debug) {indexLabel->view("cellExclusion");}
1845:       for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
1846:         if (debug) {std::cout << "Setting indices for marker " << i_iter->second << std::endl;}
1847:         for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
1848:           const Obj<Discretization>& disc = this->getDiscretization(*g_iter);
1849:           const indexSet  indSet   = ((indices_type) i_iter->first)[*g_iter].second;
1850:           const int       size     = indSet.size();
1851:           int            *_indices = new int[size];

1853:           if (debug) {std::cout << "  field " << *g_iter << std::endl;}
1854:           for(int i = 0; i < size; ++i) {
1855:             _indices[i] = indSet[i];
1856:             if (debug) {std::cout << "    indices["<<i<<"] = " << _indices[i] << std::endl;}
1857:           }
1858:           disc->setIndices(_indices, i_iter->second);
1859:         }
1860:       }
1861:     };
1862:     void setupField(const Obj<real_section_type>& s, const int cellMarker = 2, const bool noUpdate = false) {
1863:       const Obj<names_type>& discs  = this->getDiscretizations();
1864:       const int              debug  = s->debug();
1865:       names_type             bcLabels;
1866:       int                    maxDof;

1868:       maxDof = this->setFiberDimensions(s, discs, bcLabels);
1869:       this->calculateIndices();
1870:       this->calculateIndicesExcluded(s, discs);
1871:       this->allocate(s);
1872:       s->defaultConstraintDof();
1873:       const Obj<label_type>& cellExclusion = this->getLabel("cellExclusion");

1875:       if (debug) {std::cout << "Setting boundary values" << std::endl;}
1876:       for(names_type::const_iterator n_iter = bcLabels.begin(); n_iter != bcLabels.end(); ++n_iter) {
1877:         const Obj<label_sequence>&     boundaryCells = this->getLabelStratum(*n_iter, cellMarker);
1878:         const Obj<real_section_type>&  coordinates   = this->getRealSection("coordinates");
1879:         const Obj<names_type>&         discs         = this->getDiscretizations();
1880:         const point_type               firstCell     = *boundaryCells->begin();
1881:         const int                      numFields     = discs->size();
1882:         real_section_type::value_type *values        = new real_section_type::value_type[this->sizeWithBC(s, firstCell)];
1883:         int                           *dofs          = new int[maxDof];
1884:         int                           *v             = new int[numFields];
1885:         double                        *v0            = new double[this->getDimension()];
1886:         double                        *J             = new double[this->getDimension()*this->getDimension()];
1887:         double                         detJ;

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

1893:           if (debug) {std::cout << "  Boundary cell " << *c_iter << std::endl;}
1894:           this->computeElementGeometry(coordinates, *c_iter, v0, J, PETSC_NULL, detJ);
1895:           for(int f = 0; f < numFields; ++f) v[f] = 0;
1896:           for(coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
1897:             const int cDim = s->getConstraintDimension(*cl_iter);
1898:             int       off  = 0;
1899:             int       f    = 0;
1900:             int       i    = -1;

1902:             if (debug) {std::cout << "    point " << *cl_iter << std::endl;}
1903:             if (cDim) {
1904:               if (debug) {std::cout << "      constrained excMarker: " << this->getValue(cellExclusion, *c_iter) << std::endl;}
1905:               for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
1906:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
1907:                 const Obj<names_type>           bcs     = disc->getBoundaryConditions();
1908:                 const int                       fDim    = s->getFiberDimension(*cl_iter, f);//disc->getNumDof(this->depth(*cl_iter));
1909:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
1910:                 int                             b       = 0;

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

1916:                   if (b > 0) v[f] -= fDim;
1917:                   if (value == bc->getMarker()) {
1918:                     if (debug) {std::cout << "      field " << *f_iter << " marker " << value << std::endl;}
1919:                     for(int d = 0; d < fDim; ++d, ++v[f]) {
1920:                       dofs[++i] = off+d;
1921:                       if (!noUpdate) values[indices[v[f]]] = (*bc->getDualIntegrator())(v0, J, v[f], bc->getFunction());
1922:                       if (debug) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
1923:                     }
1924:                     // Allow only one condition per point
1925:                     ++b;
1926:                     break;
1927:                   } else {
1928:                     if (debug) {std::cout << "      field " << *f_iter << std::endl;}
1929:                     for(int d = 0; d < fDim; ++d, ++v[f]) {
1930:                       values[indices[v[f]]] = 0.0;
1931:                       if (debug) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
1932:                     }
1933:                   }
1934:                 }
1935:                 if (b == 0) {
1936:                   if (debug) {std::cout << "      field " << *f_iter << std::endl;}
1937:                   for(int d = 0; d < fDim; ++d, ++v[f]) {
1938:                     values[indices[v[f]]] = 0.0;
1939:                     if (debug) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
1940:                   }
1941:                 }
1942:                 off += fDim;
1943:               }
1944:               if (i != cDim-1) {throw ALE::Exception("Invalid constraint initialization");}
1945:               s->setConstraintDof(*cl_iter, dofs);
1946:             } else {
1947:               if (debug) {std::cout << "      unconstrained" << std::endl;}
1948:               for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
1949:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
1950:                 const int                       fDim    = s->getFiberDimension(*cl_iter, f);//disc->getNumDof(this->depth(*cl_iter));
1951:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));

1953:                 if (debug) {std::cout << "      field " << *f_iter << std::endl;}
1954:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
1955:                   values[indices[v[f]]] = 0.0;
1956:                   if (debug) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
1957:                 }
1958:               }
1959:             }
1960:           }
1961:           if (debug) {
1962:             const Obj<coneArray>      closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *c_iter);
1963:             const coneArray::iterator end     = closure->end();

1965:             for(int f = 0; f < numFields; ++f) v[f] = 0;
1966:             for(coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
1967:               int f = 0;
1968:               for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
1969:                 const Obj<ALE::Discretization>& disc    = this->getDiscretization(*f_iter);
1970:                 const int                       fDim    = s->getFiberDimension(*cl_iter, f);
1971:                 const int                      *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));

1973:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
1974:                   std::cout << "    "<<*f_iter<<"-value["<<indices[v[f]]<<"] " << values[indices[v[f]]] << std::endl;
1975:                 }
1976:               }
1977:             }
1978:           }
1979:           if (!noUpdate) {
1980:             this->updateAll(s, *c_iter, values);
1981:           }
1982:         }
1983:         delete [] dofs;
1984:         delete [] values;
1985:         delete [] v0;
1986:         delete [] J;
1987:       }
1988:       if (debug) {s->view("");}
1989:     };
1990:   public:
1991:     void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
1992:       if (comm == MPI_COMM_NULL) {
1993:         comm = this->comm();
1994:       }
1995:       if (name == "") {
1996:         PetscPrintf(comm, "viewing a Mesh\n");
1997:       } else {
1998:         PetscPrintf(comm, "viewing Mesh '%s'\n", name.c_str());
1999:       }
2000:       this->getSieve()->view("mesh sieve", comm);
2001:       Obj<names_type> sections = this->getRealSections();

2003:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2004:         this->getRealSection(*name)->view(*name);
2005:       }
2006:       sections = this->getIntSections();
2007:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2008:         this->getIntSection(*name)->view(*name);
2009:       }
2010:       sections = this->getArrowSections();
2011:       for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2012:         this->getArrowSection(*name)->view(*name);
2013:       }
2014:     };
2015:     template<typename value_type>
2016:     static std::string printMatrix(const std::string& name, const int rows, const int cols, const value_type matrix[], const int rank = -1)
2017:     {
2018:       ostringstream output;
2019:       ostringstream rankStr;

2021:       if (rank >= 0) {
2022:         rankStr << "[" << rank << "]";
2023:       }
2024:       output << rankStr.str() << name << " = " << std::endl;
2025:       for(int r = 0; r < rows; r++) {
2026:         if (r == 0) {
2027:           output << rankStr.str() << " /";
2028:         } else if (r == rows-1) {
2029:           output << rankStr.str() << " \\";
2030:         } else {
2031:           output << rankStr.str() << " |";
2032:         }
2033:         for(int c = 0; c < cols; c++) {
2034:           output << " " << matrix[r*cols+c];
2035:         }
2036:         if (r == 0) {
2037:           output << " \\" << std::endl;
2038:         } else if (r == rows-1) {
2039:           output << " /" << std::endl;
2040:         } else {
2041:           output << " |" << std::endl;
2042:         }
2043:       }
2044:       return output.str();
2045:     };
2046:   };
2047:   class MeshBuilder {
2048:     typedef ALE::Mesh Mesh;
2049:   public:
2052:     /*
2053:       Simple square boundary:

2055:      18--5-17--4--16
2056:       |     |     |
2057:       6    10     3
2058:       |     |     |
2059:      19-11-20--9--15
2060:       |     |     |
2061:       7     8     2
2062:       |     |     |
2063:      12--0-13--1--14
2064:     */
2065:     static Obj<ALE::Mesh> createSquareBoundary(const MPI_Comm comm, const double lower[], const double upper[], const int edges[], const int debug = 0) {
2066:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
2067:       int       numVertices = (edges[0]+1)*(edges[1]+1);
2068:       int       numEdges    = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
2069:       double   *coords      = new double[numVertices*2];
2070:       const Obj<Mesh::sieve_type> sieve    = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2071:       Mesh::point_type           *vertices = new Mesh::point_type[numVertices];
2072:       int                         order    = 0;

2074:       mesh->setSieve(sieve);
2075:       const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2076:       if (mesh->commRank() == 0) {
2077:         /* Create sieve and ordering */
2078:         for(int v = numEdges; v < numEdges+numVertices; v++) {
2079:           vertices[v-numEdges] = Mesh::point_type(v);
2080:         }
2081:         for(int vy = 0; vy <= edges[1]; vy++) {
2082:           for(int ex = 0; ex < edges[0]; ex++) {
2083:             Mesh::point_type edge(vy*edges[0] + ex);
2084:             int vertex = vy*(edges[0]+1) + ex;

2086:             sieve->addArrow(vertices[vertex+0], edge, order++);
2087:             sieve->addArrow(vertices[vertex+1], edge, order++);
2088:             if ((vy == 0) || (vy == edges[1])) {
2089:               mesh->setValue(markers, edge, 1);
2090:               mesh->setValue(markers, vertices[vertex], 1);
2091:               if (ex == edges[0]-1) {
2092:                 mesh->setValue(markers, vertices[vertex+1], 1);
2093:               }
2094:             }
2095:           }
2096:         }
2097:         for(int vx = 0; vx <= edges[0]; vx++) {
2098:           for(int ey = 0; ey < edges[1]; ey++) {
2099:             Mesh::point_type edge(vx*edges[1] + ey + edges[0]*(edges[1]+1));
2100:             int vertex = ey*(edges[0]+1) + vx;

2102:             sieve->addArrow(vertices[vertex],            edge, order++);
2103:             sieve->addArrow(vertices[vertex+edges[0]+1], edge, order++);
2104:             if ((vx == 0) || (vx == edges[0])) {
2105:               mesh->setValue(markers, edge, 1);
2106:               mesh->setValue(markers, vertices[vertex], 1);
2107:               if (ey == edges[1]-1) {
2108:                 mesh->setValue(markers, vertices[vertex+edges[0]+1], 1);
2109:               }
2110:             }
2111:           }
2112:         }
2113:       }
2114:       mesh->stratify();
2115:       for(int vy = 0; vy <= edges[1]; ++vy) {
2116:         for(int vx = 0; vx <= edges[0]; ++vx) {
2117:           coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
2118:           coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
2119:         }
2120:       }
2121:       delete [] vertices;
2122:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2123:       return mesh;
2124:     };
2127:     /*
2128:       Simple square boundary:

2130:      18--5-17--4--16
2131:       |     |     |
2132:       6    10     3
2133:       |     |     |
2134:      19-11-20--9--15
2135:       |     |     |
2136:       7     8     2
2137:       |     |     |
2138:      12--0-13--1--14
2139:     */
2140:     static Obj<ALE::Mesh> createParticleInSquareBoundary(const MPI_Comm comm, const double lower[], const double upper[], const int edges[], const double radius, const int partEdges, const int debug = 0) {
2141:       Obj<Mesh> mesh              = new Mesh(comm, 1, debug);
2142:       const int numSquareVertices = (edges[0]+1)*(edges[1]+1);
2143:       const int numVertices       = numSquareVertices + partEdges;
2144:       const int numSquareEdges    = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
2145:       const int numEdges          = numSquareEdges + partEdges;
2146:       double   *coords            = new double[numVertices*2];
2147:       const Obj<Mesh::sieve_type> sieve    = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2148:       Mesh::point_type           *vertices = new Mesh::point_type[numVertices];
2149:       int                         order    = 0;

2151:       mesh->setSieve(sieve);
2152:       const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2153:       if (mesh->commRank() == 0) {
2154:         /* Create sieve and ordering */
2155:         for(int v = numEdges; v < numEdges+numVertices; v++) {
2156:           vertices[v-numEdges] = Mesh::point_type(v);
2157:         }
2158:         // Make square
2159:         for(int vy = 0; vy <= edges[1]; vy++) {
2160:           for(int ex = 0; ex < edges[0]; ex++) {
2161:             Mesh::point_type edge(vy*edges[0] + ex);
2162:             int vertex = vy*(edges[0]+1) + ex;

2164:             sieve->addArrow(vertices[vertex+0], edge, order++);
2165:             sieve->addArrow(vertices[vertex+1], edge, order++);
2166:             if ((vy == 0) || (vy == edges[1])) {
2167:               mesh->setValue(markers, edge, 1);
2168:               mesh->setValue(markers, vertices[vertex], 1);
2169:               if (ex == edges[0]-1) {
2170:                 mesh->setValue(markers, vertices[vertex+1], 1);
2171:               }
2172:             }
2173:           }
2174:         }
2175:         for(int vx = 0; vx <= edges[0]; vx++) {
2176:           for(int ey = 0; ey < edges[1]; ey++) {
2177:             Mesh::point_type edge(vx*edges[1] + ey + edges[0]*(edges[1]+1));
2178:             int vertex = ey*(edges[0]+1) + vx;

2180:             sieve->addArrow(vertices[vertex],            edge, order++);
2181:             sieve->addArrow(vertices[vertex+edges[0]+1], edge, order++);
2182:             if ((vx == 0) || (vx == edges[0])) {
2183:               mesh->setValue(markers, edge, 1);
2184:               mesh->setValue(markers, vertices[vertex], 1);
2185:               if (ey == edges[1]-1) {
2186:                 mesh->setValue(markers, vertices[vertex+edges[0]+1], 1);
2187:               }
2188:             }
2189:           }
2190:         }
2191:         // Make particle
2192:         for(int ep = 0; ep < partEdges; ++ep) {
2193:           Mesh::point_type edge(numSquareEdges + ep);
2194:           const int vertexA = numSquareVertices + ep;
2195:           const int vertexB = numSquareVertices + (ep+1)%partEdges;

2197:           sieve->addArrow(vertices[vertexA], edge, order++);
2198:           sieve->addArrow(vertices[vertexB], edge, order++);
2199:           mesh->setValue(markers, edge, 2);
2200:           mesh->setValue(markers, vertices[vertexA], 2);
2201:           mesh->setValue(markers, vertices[vertexB], 2);
2202:         }
2203:       }
2204:       mesh->stratify();
2205:       for(int vy = 0; vy <= edges[1]; ++vy) {
2206:         for(int vx = 0; vx <= edges[0]; ++vx) {
2207:           coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
2208:           coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
2209:         }
2210:       }
2211:       const double centroidX = 0.5*(upper[0] + lower[0]);
2212:       const double centroidY = 0.5*(upper[1] + lower[1]);
2213:       for(int vp = 0; vp < partEdges; ++vp) {
2214:         const double rad = 2.0*PETSC_PI*vp/partEdges;
2215:         coords[(numSquareVertices+vp)*2+0] = centroidX + radius*cos(rad);
2216:         coords[(numSquareVertices+vp)*2+1] = centroidY + radius*sin(rad);
2217:       }
2218:       delete [] vertices;
2219:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2220:       return mesh;
2221:     };
2224:     /*
2225:       Simple boundary with reentrant singularity:

2227:      12--5-11
2228:       |     |
2229:       |     4
2230:       |     |
2231:       6    10--3--9
2232:       |           |
2233:       |           2
2234:       |           |
2235:       7-----1-----8
2236:     */
2237:     static Obj<ALE::Mesh> createReentrantBoundary(const MPI_Comm comm, const double lower[], const double upper[], double notchpercent[], const int debug = 0) {
2238:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
2239:       int       numVertices = 6;
2240:       int       numEdges    = numVertices;
2241:       double   *coords      = new double[numVertices*2];
2242:       const Obj<Mesh::sieve_type> sieve    = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2243:       Mesh::point_type           *vertices = new Mesh::point_type[numVertices];

2245:       mesh->setSieve(sieve);
2246:       const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2247:       if (mesh->commRank() == 0) {
2248:         /* Create sieve and ordering */
2249:         for (int b = 0; b < numVertices; b++) {
2250:           sieve->addArrow(numEdges+b, b);
2251:           sieve->addArrow(numEdges+b, (b+1)%numVertices);
2252:           mesh->setValue(markers, b, 1);
2253:           mesh->setValue(markers, b+numVertices, 1);
2254:         }
2255:         coords[0] = upper[0];
2256:         coords[1] = lower[1];

2258:         coords[2] = lower[0];
2259:         coords[3] = lower[1];
2260: 
2261:         coords[4] = lower[0];
2262:         coords[5] = notchpercent[1]*lower[1] + (1 - notchpercent[1])*upper[1];
2263: 
2264:         coords[6] = notchpercent[0]*upper[0] + (1 - notchpercent[0])*lower[0];
2265:         coords[7] = notchpercent[1]*lower[1] + (1 - notchpercent[1])*upper[1];
2266: 
2267: 
2268:         coords[8] = notchpercent[0]*upper[0] + (1 - notchpercent[0])*lower[0];
2269:         coords[9] = upper[1];

2271:         coords[10] = upper[0];
2272:         coords[11] = upper[1];
2273:         mesh->stratify();
2274:       }
2275:       delete [] vertices;
2276:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2277:       return mesh;
2278:     }

2282:     /*
2283:       Circular boundary with reentrant singularity:

2285:        ___--1
2286:       |     |
2287:       |     |
2288:       |     |
2289:       -     0-----n
2290:        -          |
2291:         -         |
2292:          -___  _|
2293:              --
2294:     */
2295:     static Obj<ALE::Mesh> createCircularReentrantBoundary(const MPI_Comm comm, const int segments, const double radius, const double arc_percent, const int debug = 0) {
2296:       Obj<Mesh> mesh        = new Mesh(comm, 1, debug);
2297:       int       numVertices = segments+2;
2298:       int       numEdges    = numVertices;
2299:       double   *coords      = new double[numVertices*2];
2300:       const Obj<Mesh::sieve_type> sieve    = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2301:       Mesh::point_type           *vertices = new Mesh::point_type[numVertices];

2303:       mesh->setSieve(sieve);
2304:       const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2305:       if (mesh->commRank() == 0) {
2306:         /* Create sieve and ordering */

2308:         int startvertex = 1;
2309:         if (arc_percent < 1.) {
2310:           coords[0] = 0.;
2311:           coords[1] = 0.;
2312:         } else {
2313:           numVertices = segments;
2314:           numEdges = numVertices;
2315:           startvertex = 0;
2316:         }

2318:         for (int b = 0; b < numVertices; b++) {
2319:           sieve->addArrow(numEdges+b, b);
2320:           sieve->addArrow(numEdges+b, (b+1)%numVertices);
2321:           mesh->setValue(markers, b, 1);
2322:           mesh->setValue(markers, b+numVertices, 1);
2323:         }

2325:         double anglestep = arc_percent*2.*3.14159265/((float)segments);

2327:         for (int i = startvertex; i < numVertices; i++) {
2328:           coords[2*i] = radius * sin(anglestep*(i-startvertex));
2329:           coords[2*i+1] = radius*cos(anglestep*(i-startvertex));
2330:         }
2331:         mesh->stratify();
2332:       }
2333:       delete [] vertices;
2334:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2335:       return mesh;
2336:     };
2339:     /*
2340:       Simple cubic boundary:

2342:      30----31-----32
2343:       |     |     |
2344:       |  3  |  2  |
2345:       |     |     |
2346:      27----28-----29
2347:       |     |     |
2348:       |  0  |  1  |
2349:       |     |     |
2350:      24----25-----26
2351:     */
2352:     static Obj<Mesh> createCubeBoundary(const MPI_Comm comm, const double lower[], const double upper[], const int faces[], const int debug = 0) {
2353:       Obj<Mesh> mesh        = new Mesh(comm, 2, debug);
2354:       int       numVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
2355:       int       numFaces    = 6;
2356:       double   *coords      = new double[numVertices*3];
2357:       const Obj<Mesh::sieve_type> sieve    = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2358:       Mesh::point_type           *vertices = new Mesh::point_type[numVertices];
2359:       int                         order    = 0;

2361:       mesh->setSieve(sieve);
2362:       const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2363:       if (mesh->commRank() == 0) {
2364:         /* Create sieve and ordering */
2365:         for(int v = numFaces; v < numFaces+numVertices; v++) {
2366:           vertices[v-numFaces] = Mesh::point_type(v);
2367:           mesh->setValue(markers, vertices[v-numFaces], 1);
2368:         }
2369:         {
2370:           // Side 0 (Front)
2371:           Mesh::point_type face(0);
2372:           sieve->addArrow(vertices[0], face, order++);
2373:           sieve->addArrow(vertices[1], face, order++);
2374:           sieve->addArrow(vertices[2], face, order++);
2375:           sieve->addArrow(vertices[3], face, order++);
2376:           mesh->setValue(markers, face, 1);
2377:         }
2378:         {
2379:           // Side 1 (Back)
2380:           Mesh::point_type face(1);
2381:           sieve->addArrow(vertices[5], face, order++);
2382:           sieve->addArrow(vertices[4], face, order++);
2383:           sieve->addArrow(vertices[7], face, order++);
2384:           sieve->addArrow(vertices[6], face, order++);
2385:           mesh->setValue(markers, face, 1);
2386:         }
2387:         {
2388:           // Side 2 (Bottom)
2389:           Mesh::point_type face(2);
2390:           sieve->addArrow(vertices[4], face, order++);
2391:           sieve->addArrow(vertices[5], face, order++);
2392:           sieve->addArrow(vertices[1], face, order++);
2393:           sieve->addArrow(vertices[0], face, order++);
2394:           mesh->setValue(markers, face, 1);
2395:         }
2396:         {
2397:           // Side 3 (Top)
2398:           Mesh::point_type face(3);
2399:           sieve->addArrow(vertices[3], face, order++);
2400:           sieve->addArrow(vertices[2], face, order++);
2401:           sieve->addArrow(vertices[6], face, order++);
2402:           sieve->addArrow(vertices[7], face, order++);
2403:           mesh->setValue(markers, face, 1);
2404:         }
2405:         {
2406:           // Side 4 (Left)
2407:           Mesh::point_type face(4);
2408:           sieve->addArrow(vertices[4], face, order++);
2409:           sieve->addArrow(vertices[0], face, order++);
2410:           sieve->addArrow(vertices[3], face, order++);
2411:           sieve->addArrow(vertices[7], face, order++);
2412:           mesh->setValue(markers, face, 1);
2413:         }
2414:         {
2415:           // Side 5 (Right)
2416:           Mesh::point_type face(5);
2417:           sieve->addArrow(vertices[1], face, order++);
2418:           sieve->addArrow(vertices[5], face, order++);
2419:           sieve->addArrow(vertices[6], face, order++);
2420:           sieve->addArrow(vertices[2], face, order++);
2421:           mesh->setValue(markers, face, 1);
2422:         }
2423:       }
2424:       mesh->stratify();
2425: #if 0
2426:       for(int vz = 0; vz <= edges[2]; ++vz) {
2427:         for(int vy = 0; vy <= edges[1]; ++vy) {
2428:           for(int vx = 0; vx <= edges[0]; ++vx) {
2429:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
2430:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
2431:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
2432:           }
2433:         }
2434:       }
2435: #else
2436:       coords[0*3+0] = lower[0];
2437:       coords[0*3+1] = lower[1];
2438:       coords[0*3+2] = upper[2];
2439:       coords[1*3+0] = upper[0];
2440:       coords[1*3+1] = lower[1];
2441:       coords[1*3+2] = upper[2];
2442:       coords[2*3+0] = upper[0];
2443:       coords[2*3+1] = upper[1];
2444:       coords[2*3+2] = upper[2];
2445:       coords[3*3+0] = lower[0];
2446:       coords[3*3+1] = upper[1];
2447:       coords[3*3+2] = upper[2];
2448:       coords[4*3+0] = lower[0];
2449:       coords[4*3+1] = lower[1];
2450:       coords[4*3+2] = lower[2];
2451:       coords[5*3+0] = upper[0];
2452:       coords[5*3+1] = lower[1];
2453:       coords[5*3+2] = lower[2];
2454:       coords[6*3+0] = upper[0];
2455:       coords[6*3+1] = upper[1];
2456:       coords[6*3+2] = lower[2];
2457:       coords[7*3+0] = lower[0];
2458:       coords[7*3+1] = upper[1];
2459:       coords[7*3+2] = lower[2];
2460: #endif
2461:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2462:       return mesh;
2463:     };
2466:     /*
2467:       Simple cubic boundary:

2469:      30----31-----32
2470:       |     |     |
2471:       |  3  |  2  |
2472:       |     |     |
2473:      27----28-----29
2474:       |     |     |
2475:       |  0  |  1  |
2476:       |     |     |
2477:      24----25-----26
2478:     */
2479:     static Obj<Mesh> createParticleInCubeBoundary(const MPI_Comm comm, const double lower[], const double upper[], const int faces[], const double radius, const int thetaEdges, const int phiSlices, const int debug = 0) {
2480:       Obj<Mesh> mesh            = new Mesh(comm, 2, debug);
2481:       const int numCubeVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
2482:       const int numPartVertices = (thetaEdges - 1)*phiSlices + 2;
2483:       const int numVertices     = numCubeVertices + numPartVertices;
2484:       const int numCubeFaces    = 6;
2485:       const int numFaces        = numCubeFaces + thetaEdges*phiSlices;
2486:       double   *coords          = new double[numVertices*3];
2487:       const Obj<Mesh::sieve_type> sieve    = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2488:       Mesh::point_type           *vertices = new Mesh::point_type[numVertices];
2489:       int                         order    = 0;

2491:       mesh->setSieve(sieve);
2492:       const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2493:       if (mesh->commRank() == 0) {
2494:         // Make cube
2495:         for(int v = numFaces; v < numFaces+numVertices; v++) {
2496:           vertices[v-numFaces] = Mesh::point_type(v);
2497:           mesh->setValue(markers, vertices[v-numFaces], 1);
2498:         }
2499:         {
2500:           // Side 0 (Front)
2501:           Mesh::point_type face(0);
2502:           sieve->addArrow(vertices[0], face, order++);
2503:           sieve->addArrow(vertices[1], face, order++);
2504:           sieve->addArrow(vertices[2], face, order++);
2505:           sieve->addArrow(vertices[3], face, order++);
2506:           mesh->setValue(markers, face, 1);
2507:         }
2508:         {
2509:           // Side 1 (Back)
2510:           Mesh::point_type face(1);
2511:           sieve->addArrow(vertices[5], face, order++);
2512:           sieve->addArrow(vertices[4], face, order++);
2513:           sieve->addArrow(vertices[7], face, order++);
2514:           sieve->addArrow(vertices[6], face, order++);
2515:           mesh->setValue(markers, face, 1);
2516:         }
2517:         {
2518:           // Side 2 (Bottom)
2519:           Mesh::point_type face(2);
2520:           sieve->addArrow(vertices[4], face, order++);
2521:           sieve->addArrow(vertices[5], face, order++);
2522:           sieve->addArrow(vertices[1], face, order++);
2523:           sieve->addArrow(vertices[0], face, order++);
2524:           mesh->setValue(markers, face, 1);
2525:         }
2526:         {
2527:           // Side 3 (Top)
2528:           Mesh::point_type face(3);
2529:           sieve->addArrow(vertices[3], face, order++);
2530:           sieve->addArrow(vertices[2], face, order++);
2531:           sieve->addArrow(vertices[6], face, order++);
2532:           sieve->addArrow(vertices[7], face, order++);
2533:           mesh->setValue(markers, face, 1);
2534:         }
2535:         {
2536:           // Side 4 (Left)
2537:           Mesh::point_type face(4);
2538:           sieve->addArrow(vertices[4], face, order++);
2539:           sieve->addArrow(vertices[0], face, order++);
2540:           sieve->addArrow(vertices[3], face, order++);
2541:           sieve->addArrow(vertices[7], face, order++);
2542:           mesh->setValue(markers, face, 1);
2543:         }
2544:         {
2545:           // Side 5 (Right)
2546:           Mesh::point_type face(5);
2547:           sieve->addArrow(vertices[1], face, order++);
2548:           sieve->addArrow(vertices[5], face, order++);
2549:           sieve->addArrow(vertices[6], face, order++);
2550:           sieve->addArrow(vertices[2], face, order++);
2551:           mesh->setValue(markers, face, 1);
2552:         }
2553:         // Make particle
2554:         for(int s = 0; s < phiSlices; ++s) {
2555:           for(int ep = 0; ep < thetaEdges; ++ep) {
2556:             // Vertices on each slice are 0..thetaEdges
2557:             Mesh::point_type face(numCubeFaces + s*thetaEdges + ep);
2558:             int vertexA = numCubeVertices + ep + 0 +     s*(thetaEdges+1);
2559:             int vertexB = numCubeVertices + ep + 1 +     s*(thetaEdges+1);
2560:             int vertexC = numCubeVertices + (ep + 1 + (s+1)*(thetaEdges+1))%((thetaEdges+1)*phiSlices);
2561:             int vertexD = numCubeVertices + (ep + 0 + (s+1)*(thetaEdges+1))%((thetaEdges+1)*phiSlices);
2562:             const int correction1 = (s > 0)*((s-1)*2 + 1);
2563:             const int correction2 = (s < phiSlices-1)*(s*2 + 1);

2565:             if ((vertexA - numCubeVertices)%(thetaEdges+1) == 0) {
2566:               vertexA = vertexD = numCubeVertices;
2567:               vertexB -= correction1;
2568:               vertexC -= correction2;
2569:             } else if ((vertexB - numCubeVertices)%(thetaEdges+1) == thetaEdges) {
2570:               vertexA -= correction1;
2571:               vertexD -= correction2;
2572:               vertexB = vertexC = numCubeVertices + thetaEdges;
2573:             } else {
2574:               vertexA -= correction1;
2575:               vertexB -= correction1;
2576:               vertexC -= correction2;
2577:               vertexD -= correction2;
2578:             }
2579:             if ((vertexA >= numVertices) || (vertexB >= numVertices) || (vertexC >= numVertices) || (vertexD >= numVertices)) {
2580:               throw ALE::Exception("Bad vertex");
2581:             }
2582:             sieve->addArrow(vertices[vertexA], face, order++);
2583:             sieve->addArrow(vertices[vertexB], face, order++);
2584:             if (vertexB != vertexC) sieve->addArrow(vertices[vertexC], face, order++);
2585:             if (vertexA != vertexD) sieve->addArrow(vertices[vertexD], face, order++);
2586:             mesh->setValue(markers, face, 2);
2587:             mesh->setValue(markers, vertices[vertexA], 2);
2588:             mesh->setValue(markers, vertices[vertexB], 2);
2589:             if (vertexB != vertexC) mesh->setValue(markers, vertices[vertexC], 2);
2590:             if (vertexA != vertexD) mesh->setValue(markers, vertices[vertexD], 2);
2591:           }
2592:         }
2593:       }
2594:       mesh->stratify();
2595: #if 0
2596:       for(int vz = 0; vz <= edges[2]; ++vz) {
2597:         for(int vy = 0; vy <= edges[1]; ++vy) {
2598:           for(int vx = 0; vx <= edges[0]; ++vx) {
2599:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
2600:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
2601:             coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
2602:           }
2603:         }
2604:       }
2605: #else
2606:       coords[0*3+0] = lower[0];
2607:       coords[0*3+1] = lower[1];
2608:       coords[0*3+2] = upper[2];
2609:       coords[1*3+0] = upper[0];
2610:       coords[1*3+1] = lower[1];
2611:       coords[1*3+2] = upper[2];
2612:       coords[2*3+0] = upper[0];
2613:       coords[2*3+1] = upper[1];
2614:       coords[2*3+2] = upper[2];
2615:       coords[3*3+0] = lower[0];
2616:       coords[3*3+1] = upper[1];
2617:       coords[3*3+2] = upper[2];
2618:       coords[4*3+0] = lower[0];
2619:       coords[4*3+1] = lower[1];
2620:       coords[4*3+2] = lower[2];
2621:       coords[5*3+0] = upper[0];
2622:       coords[5*3+1] = lower[1];
2623:       coords[5*3+2] = lower[2];
2624:       coords[6*3+0] = upper[0];
2625:       coords[6*3+1] = upper[1];
2626:       coords[6*3+2] = lower[2];
2627:       coords[7*3+0] = lower[0];
2628:       coords[7*3+1] = upper[1];
2629:       coords[7*3+2] = lower[2];
2630: #endif
2631:       const double centroidX = 0.5*(upper[0] + lower[0]);
2632:       const double centroidY = 0.5*(upper[1] + lower[1]);
2633:       const double centroidZ = 0.5*(upper[2] + lower[2]);
2634:       for(int s = 0; s < phiSlices; ++s) {
2635:         for(int v = 0; v <= thetaEdges; ++v) {
2636:           int          vertex  = numCubeVertices + v + s*(thetaEdges+1);
2637:           const double theta   = v*(PETSC_PI/thetaEdges);
2638:           const double phi     = s*(2.0*PETSC_PI/phiSlices);
2639:           const int correction = (s > 0)*((s-1)*2 + 1);

2641:           if ((vertex- numCubeVertices)%(thetaEdges+1) == 0) {
2642:             vertex = numCubeVertices;
2643:           } else if ((vertex - numCubeVertices)%(thetaEdges+1) == thetaEdges) {
2644:             vertex = numCubeVertices + thetaEdges;
2645:           } else {
2646:             vertex -= correction;
2647:           }
2648:           coords[vertex*3+0] = centroidX + radius*sin(theta)*cos(phi);
2649:           coords[vertex*3+1] = centroidY + radius*sin(theta)*sin(phi);
2650:           coords[vertex*3+2] = centroidZ + radius*cos(theta);
2651:         }
2652:       }
2653:       delete [] vertices;
2654:       ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2655:       return mesh;
2656:     };
2657:   };
2658: } // namespace ALE

2660: namespace ALECompat {
2661:   using ALE::Obj;
2662:   template<typename Topology_>
2663:   class Bundle : public ALE::ParallelObject {
2664:   public:
2665:     typedef Topology_                                      topology_type;
2666:     typedef typename topology_type::patch_type             patch_type;
2667:     typedef typename topology_type::point_type             point_type;
2668:     typedef typename topology_type::sieve_type             sieve_type;
2669:     typedef typename sieve_type::coneArray                 coneArray;
2670:     typedef ALECompat::New::Section<topology_type, double> real_section_type;
2671:     typedef ALECompat::New::Section<topology_type, int>    int_section_type;
2672:     typedef ALE::MinimalArrow<point_type, point_type>      arrow_type;
2673:     typedef ALE::UniformSection<arrow_type, int>           arrow_section_type;
2674:     typedef struct {double x, y, z;}                       split_value;
2675:     typedef ALE::pair<point_type, split_value>             pair_type;
2676:     typedef ALECompat::New::Section<topology_type, pair_type>    pair_section_type;
2677:     typedef std::map<std::string, Obj<real_section_type> > real_sections_type;
2678:     typedef std::map<std::string, Obj<int_section_type> >  int_sections_type;
2679:     typedef std::map<std::string, Obj<pair_section_type> > pair_sections_type;
2680:     typedef std::map<std::string, Obj<arrow_section_type> > arrow_sections_type;
2681:     typedef typename topology_type::send_overlap_type      send_overlap_type;
2682:     typedef typename topology_type::recv_overlap_type      recv_overlap_type;
2683:     typedef typename ALECompat::New::SectionCompletion<topology_type, point_type>::topology_type      comp_topology_type;
2684:     typedef typename ALECompat::New::OverlapValues<send_overlap_type, comp_topology_type, point_type> send_section_type;
2685:     typedef typename ALECompat::New::OverlapValues<recv_overlap_type, comp_topology_type, point_type> recv_section_type;
2686:   protected:
2687:     Obj<topology_type> _topology;
2688:     bool               _distributed;
2689:     real_sections_type _realSections;
2690:     int_sections_type  _intSections;
2691:     pair_sections_type _pairSections;
2692:     arrow_sections_type _arrowSections;
2693:   public:
2694:     Bundle(MPI_Comm comm, int debug = 0) : ALE::ParallelObject(comm, debug), _distributed(false) {
2695:       this->_topology = new topology_type(comm, debug);
2696:     };
2697:     Bundle(const Obj<topology_type>& topology) : ALE::ParallelObject(topology->comm(), topology->debug()), _topology(topology), _distributed(false) {};
2698:   public: // Accessors
2699:     bool getDistributed() const {return this->_distributed;};
2700:     void setDistributed(const bool distributed) {this->_distributed = distributed;};
2701:     const Obj<topology_type>& getTopology() const {return this->_topology;};
2702:     void setTopology(const Obj<topology_type>& topology) {this->_topology = topology;};
2703:   public:
2704:     bool hasRealSection(const std::string& name) {
2705:       return this->_realSections.find(name) != this->_realSections.end();
2706:     };
2707:     const Obj<real_section_type>& getRealSection(const std::string& name) {
2708:       if (this->_realSections.find(name) == this->_realSections.end()) {
2709:         Obj<real_section_type> section = new real_section_type(this->_topology);

2711:         if (this->_debug) {std::cout << "Creating new real section: " << name << std::endl;}
2712:         this->_realSections[name] = section;
2713:       }
2714:       return this->_realSections[name];
2715:     };
2716:     void setRealSection(const std::string& name, const Obj<real_section_type>& section) {
2717:       this->_realSections[name] = section;
2718:     };
2719:     Obj<std::set<std::string> > getRealSections() const {
2720:       Obj<std::set<std::string> > names = std::set<std::string>();

2722:       for(typename real_sections_type::const_iterator s_iter = this->_realSections.begin(); s_iter != this->_realSections.end(); ++s_iter) {
2723:         names->insert(s_iter->first);
2724:       }
2725:       return names;
2726:     };
2727:     bool hasIntSection(const std::string& name) {
2728:       return this->_intSections.find(name) != this->_intSections.end();
2729:     };
2730:     const Obj<int_section_type>& getIntSection(const std::string& name) {
2731:       if (this->_intSections.find(name) == this->_intSections.end()) {
2732:         Obj<int_section_type> section = new int_section_type(this->_topology);

2734:         if (this->_debug) {std::cout << "Creating new int section: " << name << std::endl;}
2735:         this->_intSections[name] = section;
2736:       }
2737:       return this->_intSections[name];
2738:     };
2739:     void setIntSection(const std::string& name, const Obj<int_section_type>& section) {
2740:       this->_intSections[name] = section;
2741:     };
2742:     Obj<std::set<std::string> > getIntSections() const {
2743:       Obj<std::set<std::string> > names = std::set<std::string>();

2745:       for(typename int_sections_type::const_iterator s_iter = this->_intSections.begin(); s_iter != this->_intSections.end(); ++s_iter) {
2746:         names->insert(s_iter->first);
2747:       }
2748:       return names;
2749:     };
2750:     bool hasPairSection(const std::string& name) {
2751:       return this->_pairSections.find(name) != this->_pairSections.end();
2752:     };
2753:     const Obj<pair_section_type>& getPairSection(const std::string& name) {
2754:       if (this->_pairSections.find(name) == this->_pairSections.end()) {
2755:         Obj<pair_section_type> section = new pair_section_type(this->_topology);

2757:         if (this->_debug) {std::cout << "Creating new pair section: " << name << std::endl;}
2758:         this->_pairSections[name] = section;
2759:       }
2760:       return this->_pairSections[name];
2761:     };
2762:     void setPairSection(const std::string& name, const Obj<pair_section_type>& section) {
2763:       this->_pairSections[name] = section;
2764:     };
2765:     Obj<std::set<std::string> > getPairSections() const {
2766:       Obj<std::set<std::string> > names = std::set<std::string>();

2768:       for(typename pair_sections_type::const_iterator s_iter = this->_pairSections.begin(); s_iter != this->_pairSections.end(); ++s_iter) {
2769:         names->insert(s_iter->first);
2770:       }
2771:       return names;
2772:     };
2773:     bool hasArrowSection(const std::string& name) {
2774:       return this->_arrowSections.find(name) != this->_arrowSections.end();
2775:     };
2776:     const Obj<arrow_section_type>& getArrowSection(const std::string& name) {
2777:       if (this->_arrowSections.find(name) == this->_arrowSections.end()) {
2778:         Obj<arrow_section_type> section = new arrow_section_type(this->comm(), this->debug());

2780:         if (this->_debug) {std::cout << "Creating new arrow section: " << name << std::endl;}
2781:         this->_arrowSections[name] = section;
2782:       }
2783:       return this->_arrowSections[name];
2784:     };
2785:     void setArrowSection(const std::string& name, const Obj<arrow_section_type>& section) {
2786:       this->_arrowSections[name] = section;
2787:     };
2788:     Obj<std::set<std::string> > getArrowSections() const {
2789:       Obj<std::set<std::string> > names = std::set<std::string>();

2791:       for(typename arrow_sections_type::const_iterator s_iter = this->_arrowSections.begin(); s_iter != this->_arrowSections.end(); ++s_iter) {
2792:         names->insert(s_iter->first);
2793:       }
2794:       return names;
2795:     };
2796:   public: // Printing
2797:     friend std::ostream& operator<<(std::ostream& os, const split_value& s) {
2798:       os << "(" << s.x << ", "<< s.y << ", "<< s.z << ")";
2799:       return os;
2800:     };
2801:   public: // Adapter
2802:     const Obj<sieve_type>& getSieve() {return this->_topology->getPatch(0);};
2803:     int height() {return 2;};
2804:     int depth() {return 2;};
2805:   };

2807:   class Discretization : public ALE::ParallelObject {
2808:   protected:
2809:     std::map<int,int> _dim2dof;
2810:     std::map<int,int> _dim2class;
2811:   public:
2812:     Discretization(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {};
2813:     ~Discretization() {};
2814:   public:
2815:     const double *getQuadraturePoints() {return NULL;};
2816:     const double *getQuadratureWeights() {return NULL;};
2817:     const double *getBasis() {return NULL;};
2818:     const double *getBasisDerivatives() {return NULL;};
2819:     int  getNumDof(const int dim) {return this->_dim2dof[dim];};
2820:     void setNumDof(const int dim, const int numDof) {this->_dim2dof[dim] = numDof;};
2821:     int  getDofClass(const int dim) {return this->_dim2class[dim];};
2822:     void setDofClass(const int dim, const int dofClass) {this->_dim2class[dim] = dofClass;};
2823:   };

2825:   class BoundaryCondition : public ALE::ParallelObject {
2826:   protected:
2827:     std::string _labelName;
2828:     double    (*_func)(const double []);
2829:   public:
2830:     BoundaryCondition(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {};
2831:     ~BoundaryCondition() {};
2832:   public:
2833:     const std::string& getLabelName() {return this->_labelName;};
2834:     void setLabelName(const std::string& name) {this->_labelName = name;};
2835:     void setFunction(double (*func)(const double [])) {this->_func = func;};
2836:   public:
2837:     double evaluate(const double coords[]) {return this->_func(coords);};
2838:   };

2840:   class Mesh : public Bundle<ALE::Topology<int, ALE::Sieve<int,int,int> > > {
2841:   public:
2842:     typedef int                                       point_type;
2843:     typedef ALE::Sieve<point_type,int,int>            sieve_type;
2844:     typedef ALE::Topology<int, sieve_type>            topology_type;
2845:     typedef topology_type::patch_type                 patch_type;
2846:     typedef Bundle<topology_type>                     base_type;
2847:     typedef ALECompat::New::NumberingFactory<topology_type> NumberingFactory;
2848:     typedef NumberingFactory::numbering_type          numbering_type;
2849:     typedef NumberingFactory::order_type              order_type;
2850:     typedef base_type::send_overlap_type              send_overlap_type;
2851:     typedef base_type::recv_overlap_type              recv_overlap_type;
2852:     typedef base_type::send_section_type              send_section_type;
2853:     typedef base_type::recv_section_type              recv_section_type;
2854:     typedef base_type::real_sections_type             real_sections_type;
2855:     // PCICE BC
2856:     typedef struct {double rho,u,v,p;}                bc_value_type;
2857:     typedef std::map<int, bc_value_type>              bc_values_type;
2858:     // PyLith BC
2859:     typedef ALECompat::New::Section<topology_type, ALE::pair<int,double> > foliated_section_type;
2860:   protected:
2861:     int                   _dim;
2862:     Obj<NumberingFactory> _factory;
2863:     // PCICE BC
2864:     bc_values_type        _bcValues;
2865:     // PyLith BC
2866:     Obj<foliated_section_type> _boundaries;
2867:     // Discretization
2868:     Obj<Discretization>    _discretization;
2869:     Obj<BoundaryCondition> _boundaryCondition;
2870:   public:
2871:     Mesh(MPI_Comm comm, int dim, int debug = 0) : Bundle<ALE::Topology<int, ALE::Sieve<int,int,int> > >(comm, debug), _dim(dim) {
2872:       this->_factory = NumberingFactory::singleton(debug);
2873:       this->_boundaries = NULL;
2874:       this->_discretization = new Discretization(comm, debug);
2875:       this->_boundaryCondition = new BoundaryCondition(comm, debug);
2876:     };
2877:     Mesh(const Obj<topology_type>& topology, int dim) : Bundle<ALE::Topology<int, ALE::Sieve<int,int,int> > >(topology), _dim(dim) {
2878:       this->_factory = NumberingFactory::singleton(topology->debug());
2879:       this->_boundaries = NULL;
2880:     };
2881:   public: // Accessors
2882:     int getDimension() const {return this->_dim;};
2883:     void setDimension(const int dim) {this->_dim = dim;};
2884:     const Obj<NumberingFactory>& getFactory() {return this->_factory;};
2885:     const Obj<Discretization>&    getDiscretization() {return this->_discretization;};
2886:     void setDiscretization(const Obj<Discretization>& discretization) {this->_discretization = discretization;};
2887:     const Obj<BoundaryCondition>& getBoundaryCondition() {return this->_boundaryCondition;};
2888:     void setBoundaryCondition(const Obj<BoundaryCondition>& boundaryCondition) {this->_boundaryCondition = boundaryCondition;};
2889:   public: // Mesh geometry
2890: #if 0
2891:     void computeTriangleGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2892:       const double *coords = this->restrict(coordinates, e);
2893:       const int     dim    = 2;
2894:       double        invDet;

2896:       if (v0) {
2897:         for(int d = 0; d < dim; d++) {
2898:           v0[d] = coords[d];
2899:         }
2900:       }
2901:       if (J) {
2902:         for(int d = 0; d < dim; d++) {
2903:           for(int f = 0; f < dim; f++) {
2904:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2905:           }
2906:         }
2907:         detJ = J[0]*J[3] - J[1]*J[2];
2908:       }
2909:       if (invJ) {
2910:         invDet  = 1.0/detJ;
2911:         invJ[0] =  invDet*J[3];
2912:         invJ[1] = -invDet*J[1];
2913:         invJ[2] = -invDet*J[2];
2914:         invJ[3] =  invDet*J[0];
2915:       }
2916:     };
2917:     static void computeTetrahedronGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2918:       const patch_type patch  = 0;
2919:       const double    *coords = coordinates->restrict(patch, e);
2920:       const int        dim    = 3;
2921:       double           invDet;

2923:       if (v0) {
2924:         for(int d = 0; d < dim; d++) {
2925:           v0[d] = coords[d];
2926:         }
2927:       }
2928:       if (J) {
2929:         for(int d = 0; d < dim; d++) {
2930:           for(int f = 0; f < dim; f++) {
2931:             J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2932:           }
2933:         }
2934:         detJ = J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2935:           J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2936:           J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2937:       }
2938:       if (invJ) {
2939:         invDet  = 1.0/detJ;
2940:         invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2941:         invJ[0*3+1] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2942:         invJ[0*3+2] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2943:         invJ[1*3+0] = invDet*(J[0*3+1]*J[2*3+2] - J[0*3+2]*J[2*3+1]);
2944:         invJ[1*3+1] = invDet*(J[0*3+2]*J[2*3+0] - J[0*3+0]*J[2*3+2]);
2945:         invJ[1*3+2] = invDet*(J[0*3+0]*J[2*3+1] - J[0*3+1]*J[2*3+0]);
2946:         invJ[2*3+0] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2947:         invJ[2*3+1] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2948:         invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2949:       }
2950:     };
2951:     void computeElementGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2952:       if (this->_dim == 2) {
2953:         computeTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
2954:       } else if (this->_dim == 3) {
2955:         computeTetrahedronGeometry(coordinates, e, v0, J, invJ, detJ);
2956:       } else {
2957:         throw ALE::Exception("Unsupport dimension for element geometry computation");
2958:       }
2959:     };
2960:     double getMaxVolume() {
2961:       const topology_type::sheaf_type& patches = this->getTopology()->getPatches();
2962:       double v0[3], J[9], invJ[9], detJ, maxVolume = 0.0;

2964:       for(topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2965:         const Obj<real_section_type>&             coordinates = this->getRealSection("coordinates");
2966:         const Obj<topology_type::label_sequence>& cells       = this->getTopology()->heightStratum(p_iter->first, 0);

2968:         for(topology_type::label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
2969:           this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
2970:           maxVolume = std::max(maxVolume, detJ);
2971:         }
2972:       }
2973:       return maxVolume;
2974:     };
2975:     // Find the cell in which this point lies (stupid algorithm)
2976:     point_type locatePoint_2D(const patch_type& patch, const real_section_type::value_type point[]) {
2977:       const Obj<real_section_type>&             coordinates = this->getRealSection("coordinates");
2978:       const Obj<topology_type::label_sequence>& cells       = this->getTopology()->heightStratum(patch, 0);
2979:       const int                                 embedDim    = 2;
2980:       double v0[2], J[4], invJ[4], detJ;

2982:       for(topology_type::label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
2983:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
2984:         double xi   = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]);
2985:         double eta  = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]);

2987:         if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 1.0)) {
2988:           return *c_iter;
2989:         }
2990:       }
2991:       throw ALE::Exception("Could not locate point");
2992:     };
2993:     //   Assume a simplex and 3D
2994:     point_type locatePoint_3D(const patch_type& patch, const real_section_type::value_type point[]) {
2995:       const Obj<real_section_type>&             coordinates = this->getRealSection("coordinates");
2996:       const Obj<topology_type::label_sequence>& cells       = this->getTopology()->heightStratum(patch, 0);
2997:       const int                                 embedDim    = 3;
2998:       double v0[3], J[9], invJ[9], detJ;

3000:       for(topology_type::label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
3001:         this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
3002:         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]);
3003:         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]);
3004:         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]);

3006:         if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 1.0)) {
3007:           return *c_iter;
3008:         }
3009:       }
3010:       throw ALE::Exception("Could not locate point");
3011:     };
3012:     point_type locatePoint(const patch_type& patch, const real_section_type::value_type point[]) {
3013:       if (this->_dim == 2) {
3014:         return locatePoint_2D(patch, point);
3015:       } else if (this->_dim == 3) {
3016:         return locatePoint_3D(patch, point);
3017:       } else {
3018:         throw ALE::Exception("No point location for mesh dimension");
3019:       }
3020:     };
3021: #endif
3022:     // Only works in 2D
3023:     int orientation(const patch_type& patch, const point_type& cell) {
3024:       const Obj<real_section_type>&     coordinates = this->getRealSection("coordinates");
3025:       const Obj<topology_type>&         topology    = this->getTopology();
3026:       const Obj<sieve_type>&            sieve       = topology->getPatch(patch);
3027:       const Obj<sieve_type::coneArray>& cone        = sieve->nCone(cell, topology->depth());
3028:       sieve_type::coneArray::iterator   cBegin      = cone->begin();
3029:       real_section_type::value_type     root[2];
3030:       real_section_type::value_type     vA[2];
3031:       real_section_type::value_type     vB[2];

3033:       const real_section_type::value_type *coords = coordinates->restrictPoint(patch, *cBegin);
3034:       root[0] = coords[0];
3035:       root[1] = coords[1];
3036:       ++cBegin;
3037:       coords = coordinates->restrictPoint(patch, *cBegin);
3038:       vA[0] = coords[0] - root[0];
3039:       vA[1] = coords[1] - root[1];
3040:       ++cBegin;
3041:       coords = coordinates->restrictPoint(patch, *cBegin);
3042:       vB[0] = coords[0] - root[0];
3043:       vB[1] = coords[1] - root[1];
3044:       double det = vA[0]*vB[1] - vA[1]*vB[0];
3045:       if (det > 0.0) return  1;
3046:       if (det < 0.0) return -1;
3047:       return 0;
3048:     };
3049:   public: // BC values for PCICE
3050:     const bc_value_type& getBCValue(const int bcFunc) {
3051:       return this->_bcValues[bcFunc];
3052:     };
3053:     void setBCValue(const int bcFunc, const bc_value_type& value) {
3054:       this->_bcValues[bcFunc] = value;
3055:     };
3056:     bc_values_type& getBCValues() {
3057:       return this->_bcValues;
3058:     };
3059:     void distributeBCValues() {
3060:       int size = this->_bcValues.size();

3062:       MPI_Bcast(&size, 1, MPI_INT, 0, this->comm());
3063:       if (this->commRank()) {
3064:         for(int bc = 0; bc < size; ++bc) {
3065:           int           funcNum;
3066:           bc_value_type funcVal;

3068:           MPI_Bcast((void *) &funcNum, 1, MPI_INT,    0, this->comm());
3069:           MPI_Bcast((void *) &funcVal, 4, MPI_DOUBLE, 0, this->comm());
3070:           this->_bcValues[funcNum] = funcVal;
3071:         }
3072:       } else {
3073:         for(bc_values_type::iterator bc_iter = this->_bcValues.begin(); bc_iter != this->_bcValues.end(); ++bc_iter) {
3074:           const int&           funcNum = bc_iter->first;
3075:           const bc_value_type& funcVal = bc_iter->second;
3076:           MPI_Bcast((void *) &funcNum, 1, MPI_INT,    0, this->comm());
3077:           MPI_Bcast((void *) &funcVal, 4, MPI_DOUBLE, 0, this->comm());
3078:         }
3079:       }
3080:     };
3081:   public: // BC values for PyLith
3082:     const Obj<foliated_section_type>& getBoundariesNew() {
3083:       if (this->_boundaries.isNull()) {
3084:         this->_boundaries = new foliated_section_type(this->getTopology());
3085:       }
3086:       return this->_boundaries;
3087:     };
3088:   public: // Discretization
3089:     void setupField(const Obj<real_section_type>& s, const bool postponeGhosts = false) {
3090:       const std::string& name  = this->_boundaryCondition->getLabelName();
3091:       const patch_type   patch = 0;

3093:       for(int d = 0; d <= this->_dim; ++d) {
3094:         s->setFiberDimensionByDepth(patch, d, this->_discretization->getNumDof(d));
3095:       }
3096:       if (!name.empty()) {
3097:         const Obj<topology_type::label_sequence>& boundary = this->_topology->getLabelStratum(patch, name, 1);

3099:         for(topology_type::label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
3100:           s->setFiberDimension(patch, *e_iter, -this->_discretization->getNumDof(this->_topology->depth(patch, *e_iter)));
3101:         }
3102:       }
3103:       s->allocate(postponeGhosts);
3104:       if (!name.empty()) {
3105:         const Obj<real_section_type>&             coordinates = this->getRealSection("coordinates");
3106:         const Obj<topology_type::label_sequence>& boundary    = this->_topology->getLabelStratum(patch, name, 1);

3108:         for(topology_type::label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
3109:           const real_section_type::value_type *coords = coordinates->restrictPoint(patch, *e_iter);
3110:           const PetscScalar                    value  = this->_boundaryCondition->evaluate(coords);

3112:           s->updatePointBC(patch, *e_iter, &value);
3113:         }
3114:       }
3115:     };
3116:   public:
3117:     void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
3118:       if (comm == MPI_COMM_NULL) {
3119:         comm = this->comm();
3120:       }
3121:       if (name == "") {
3122:         PetscPrintf(comm, "viewing a Mesh\n");
3123:       } else {
3124:         PetscPrintf(comm, "viewing Mesh '%s'\n", name.c_str());
3125:       }
3126:       this->getTopology()->view("mesh topology", comm);
3127:       Obj<std::set<std::string> > sections = this->getRealSections();

3129:       for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
3130:         this->getRealSection(*name)->view(*name);
3131:       }
3132:       sections = this->getIntSections();
3133:       for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
3134:         this->getIntSection(*name)->view(*name);
3135:       }
3136:       sections = this->getPairSections();
3137:       for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
3138:         this->getPairSection(*name)->view(*name);
3139:       }
3140:     };
3141:     template<typename value_type>
3142:     static std::string printMatrix(const std::string& name, const int rows, const int cols, const value_type matrix[], const int rank = -1)
3143:     {
3144:       ostringstream output;
3145:       ostringstream rankStr;

3147:       if (rank >= 0) {
3148:         rankStr << "[" << rank << "]";
3149:       }
3150:       output << rankStr.str() << name << " = " << std::endl;
3151:       for(int r = 0; r < rows; r++) {
3152:         if (r == 0) {
3153:           output << rankStr.str() << " /";
3154:         } else if (r == rows-1) {
3155:           output << rankStr.str() << " \\";
3156:         } else {
3157:           output << rankStr.str() << " |";
3158:         }
3159:         for(int c = 0; c < cols; c++) {
3160:           output << " " << matrix[r*cols+c];
3161:         }
3162:         if (r == 0) {
3163:           output << " \\" << std::endl;
3164:         } else if (r == rows-1) {
3165:           output << " /" << std::endl;
3166:         } else {
3167:           output << " |" << std::endl;
3168:         }
3169:       }
3170:       return output.str();
3171:     };
3172:   };
3173: } // namespace ALECompat
3174: #endif