Actual source code: Mesh.hh
petsc-3.4.2 2013-07-02

      1: #ifndef included_ALE_Mesh_hh
      2: #define included_ALE_Mesh_hh

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    4462:       //assemble the L-shaped sides

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

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

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

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

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

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

    4500:       //assemble the smaller square sides

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

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

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

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

    4526:     }

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

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

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

    4707: #endif

    4711:     /*
    4712:       Simple cubic boundary:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    5327:         int counterBegin = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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