Actual source code: Numbering.hh

  1: #ifndef included_ALE_Numbering_hh
  2: #define included_ALE_Numbering_hh

  4: #ifndef  included_ALE_SectionCompletion_hh
  5: #include <SectionCompletion.hh>
  6: #endif


  9: namespace ALE {
 10:     // We have a dichotomy between \emph{types}, describing the structure of objects,
 11:     //   and \emph{concepts}, describing the role these objects play in the algorithm.
 12:     //   Below we identify concepts with potential implementing types.
 13:     //
 14:     //   Concept           Type
 15:     //   -------           ----
 16:     //   Overlap           Sifter
 17:     //   Atlas             ConstantSection, UniformSection
 18:     //   Numbering         UniformSection
 19:     //   GlobalOrder       UniformSection
 20:     //
 21:     // We will use factory types to create objects which satisfy a given concept.
 22:   template<typename Point_, typename Value_ = int, typename Alloc_ = std::allocator<Point_> >
 23:   class Numbering : public UniformSection<Point_, Value_, 1, Alloc_> {
 24:   public:
 25:     typedef UniformSection<Point_, Value_, 1, Alloc_> base_type;
 26:     typedef typename base_type::point_type point_type;
 27:     typedef typename base_type::value_type value_type;
 28:     typedef typename base_type::atlas_type atlas_type;
 29:   protected:
 30:     int                       _localSize;
 31:     int                      *_offsets;
 32:     std::map<int, point_type> _invOrder;
 33:   public:
 34:     Numbering(MPI_Comm comm, const int debug = 0) : UniformSection<Point_, Value_, 1, Alloc_>(comm, debug), _localSize(0) {
 35:       this->_offsets    = new int[this->commSize()+1];
 36:       this->_offsets[0] = 0;
 37:     };
 38:     virtual ~Numbering() {
 39:       delete [] this->_offsets;
 40:     };
 41:   public: // Sizes
 42:     int        getLocalSize() const {return this->_localSize;};
 43:     void       setLocalSize(const int size) {this->_localSize = size;};
 44:     int        getGlobalSize() const {return this->_offsets[this->commSize()];};
 45:     int        getGlobalOffset(const int p) const {return this->_offsets[p];};
 46:     const int *getGlobalOffsets() const {return this->_offsets;};
 47:     void       setGlobalOffsets(const int offsets[]) {
 48:       for(int p = 0; p <= this->commSize(); ++p) {
 49:         this->_offsets[p] = offsets[p];
 50:       }
 51:     };
 52:   public: // Indices
 53:     virtual int getIndex(const point_type& point) {
 54:       const value_type& idx = this->restrictPoint(point)[0];
 55:       if (idx >= 0) {
 56:         return idx;
 57:       }
 58:       return -(idx+1);
 59:     };
 60:     virtual void setIndex(const point_type& point, const int index) {this->updatePoint(point, &index);};
 61:     virtual bool isLocal(const point_type& point) {return this->restrictPoint(point)[0] >= 0;};
 62:     virtual bool isRemote(const point_type& point) {return this->restrictPoint(point)[0] < 0;};
 63:     point_type getPoint(const int& index) {return this->_invOrder[index];};
 64:     void setPoint(const int& index, const point_type& point) {this->_invOrder[index] = point;};
 65:   };
 66:   template<typename Point_, typename Value_ = ALE::Point>
 67:   class GlobalOrder : public UniformSection<Point_, Value_> {
 68:   public:
 69:     typedef UniformSection<Point_, Value_> base_type;
 70:     typedef typename base_type::point_type point_type;
 71:     typedef typename base_type::value_type value_type;
 72:     typedef typename base_type::atlas_type atlas_type;
 73:   protected:
 74:     int  _localSize;
 75:     int *_offsets;
 76:   public:
 77:     GlobalOrder(MPI_Comm comm, const int debug = 0) : UniformSection<Point_, Value_>(comm, debug), _localSize(0) {
 78:       this->_offsets    = new int[this->commSize()+1];
 79:       this->_offsets[0] = 0;
 80:     };
 81:     ~GlobalOrder() {
 82:       delete [] this->_offsets;
 83:     };
 84:   public: // Sizes
 85:     int        getLocalSize() const {return this->_localSize;};
 86:     void       setLocalSize(const int size) {this->_localSize = size;};
 87:     int        getGlobalSize() const {return this->_offsets[this->commSize()];};
 88:     int        getGlobalOffset(const int p) const {return this->_offsets[p];};
 89:     const int *getGlobalOffsets() const {return this->_offsets;};
 90:     void       setGlobalOffsets(const int offsets[]) {
 91:       for(int p = 0; p <= this->commSize(); ++p) {
 92:         this->_offsets[p] = offsets[p];
 93:       }
 94:     };
 95:   public: // Indices
 96:     virtual int getIndex(const point_type& p) {
 97:       const int idx = this->restrictPoint(p)[0].prefix;
 98:       if (idx >= 0) {
 99:         return idx;
100:       }
101:       return -(idx+1);
102:     };
103:     virtual void setIndex(const point_type& p, const int index) {
104:       const value_type idx(index, this->restrictPoint(p)[0].index);
105:       this->updatePoint(p, &idx);
106:     };
107:     virtual bool isLocal(const point_type& p) {return this->restrictPoint(p)[0].prefix >= 0;};
108:     virtual bool isRemote(const point_type& p) {return this->restrictPoint(p)[0].prefix < 0;};
109:   };
110:   template<typename Bundle_, typename Value_ = int, typename Alloc_ = typename Bundle_::alloc_type>
111:   class NumberingFactory : ALE::ParallelObject {
112:   public:
113:     typedef Bundle_                                         bundle_type;
114:     typedef Alloc_                                          alloc_type;
115:     typedef typename bundle_type::sieve_type                sieve_type;
116:     typedef typename sieve_type::point_type                 point_type;
117:     typedef Value_                                          value_type;
118:     typedef typename alloc_type::template rebind<value_type>::other value_alloc_type;
119:     typedef Numbering<point_type, value_type, alloc_type>   numbering_type;
120:     typedef std::map<bundle_type*, std::map<int, Obj<numbering_type> > >     numberings_type;
121:     typedef GlobalOrder<point_type>                         order_type;
122:     typedef typename order_type::value_type                 oValue_type;
123:     typedef typename alloc_type::template rebind<oValue_type>::other oValue_alloc_type;
124:     typedef std::map<bundle_type*, std::map<std::string, Obj<order_type> > > orders_type;
125:     typedef typename ALE::Sifter<int,point_type,point_type> send_overlap_type;
126:     typedef typename ALE::Sifter<point_type,int,point_type> recv_overlap_type;
127:   protected:
128:     numberings_type   _localNumberings;
129:     numberings_type   _numberings;
130:     orders_type       _orders;
131:     const value_type  _unknownNumber;
132:     const oValue_type _unknownOrder;
133:   protected:
134:     NumberingFactory(MPI_Comm comm, const int debug = 0) : ALE::ParallelObject(comm, debug), _unknownNumber(-1), _unknownOrder(-1, 0) {};
135:   public:
136:     ~NumberingFactory() {};
137:   public:
138:     static const Obj<NumberingFactory>& singleton(MPI_Comm comm, const int debug, bool cleanup = false) {
139:       static Obj<NumberingFactory> *_singleton = NULL;

141:       if (cleanup) {
142:         if (debug) {std::cout << "Destroying NumberingFactory" << std::endl;}
143:         if (_singleton) {delete _singleton;}
144:         _singleton = NULL;
145:       } else if (_singleton == NULL) {
146:         if (debug) {std::cout << "Creating new NumberingFactory" << std::endl;}
147:         _singleton  = new Obj<NumberingFactory>();
148:         *_singleton = new NumberingFactory(comm, debug);
149:       }
150:       return *_singleton;
151:     };
152:     void clear() {
153:       this->_localNumberings.clear();
154:       this->_numberings.clear();
155:       this->_orders.clear();
156:     };
157:   public: // Dof ordering
158:     template<typename Section_>
159:     void orderPointNew(const Obj<Section_>& section, const Obj<sieve_type>& sieve, const typename Section_::point_type& point, value_type& offset, value_type& bcOffset, const Obj<send_overlap_type>& sendOverlap = NULL) {
160:       const typename Section_::chart_type& chart = section->getChart();
161:       int&                                 idx   = section->getIndex(point);

163:       // If the point does not exist in the chart, throw an error
164:       if (chart.count(point) == 0) {
165:         throw ALE::Exception("Unknown point in ordering");
166:       }
167:       // If the point has not been ordered
168:       if (idx == -1) {
169:         // Recurse to its cover
170:         const Obj<typename sieve_type::coneSequence>& cone = sieve->cone(point);
171:         typename sieve_type::coneSequence::iterator   end  = cone->end();

173:         for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
174:           if (this->_debug > 1) {std::cout << "    Recursing to " << *c_iter << std::endl;}
175:           this->orderPoint(section, sieve, *c_iter, offset, bcOffset, sendOverlap);
176:         }
177:         const int dim  = section->getFiberDimension(point);
178:         const int cDim = section->getConstraintDimension(point);
179:         const int fDim = dim - cDim;

181:         // If the point has constrained variables
182:         if (cDim) {
183:           if (this->_debug > 1) {std::cout << "  Ordering boundary point " << point << " at " << bcOffset << std::endl;}
184:           section->setIndexBC(point, bcOffset);
185:           bcOffset += cDim;
186:         }
187:         // If the point has free variables
188:         if (fDim) {
189:           bool number = true;

191:           // Maybe use template specialization here
192:           if (!sendOverlap.isNull() && sendOverlap->capContains(point)) {
193:             const Obj<typename send_overlap_type::supportSequence>& ranks = sendOverlap->support(point);

195:             for(typename send_overlap_type::supportSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
196:               if (this->commRank() > *r_iter) {
197:                 number = false;
198:                 break;
199:               }
200:             }
201:           }
202:           if (number) {
203:             if (this->_debug > 1) {std::cout << "  Ordering point " << point << " at " << offset << std::endl;}
204:             section->setIndex(point, offset);
205:             offset += dim;
206:           } else {
207:             if (this->_debug > 1) {std::cout << "  Ignoring ghost point " << point << std::endl;}
208:           }
209:         }
210:       }
211:     };
212:     template<typename Section_>
213:     void orderPoint(const Obj<Section_>& section, const Obj<sieve_type>& sieve, const typename Section_::point_type& point, value_type& offset, value_type& bcOffset, const Obj<send_overlap_type>& sendOverlap = NULL) {
214:       const Obj<typename Section_::atlas_type>&     atlas = section->getAtlas();
215:       const Obj<typename sieve_type::coneSequence>& cone = sieve->cone(point);
216:       typename sieve_type::coneSequence::iterator   end  = cone->end();
217:       typename Section_::index_type                 idx  = section->getAtlas()->restrictPoint(point)[0];
218:       const value_type&                             dim  = idx.prefix;
219:       const typename Section_::index_type           defaultIdx(0, -1);

221:       if (atlas->getChart().count(point) == 0) {
222:         idx = defaultIdx;
223:       }
224:       if (idx.index == -1) {
225:         for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
226:           if (this->_debug > 1) {std::cout << "    Recursing to " << *c_iter << std::endl;}
227:           this->orderPoint(section, sieve, *c_iter, offset, bcOffset, sendOverlap);
228:         }
229:         if (dim > 0) {
230:           bool number = true;

232:           // Maybe use template specialization here
233:           if (!sendOverlap.isNull() && sendOverlap->capContains(point)) {
234:             const Obj<typename send_overlap_type::supportSequence>& ranks = sendOverlap->support(point);

236:             for(typename send_overlap_type::supportSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
237:               if (this->commRank() > *r_iter) {
238:                 number = false;
239:                 break;
240:               }
241:             }
242:           }
243:           if (number) {
244:             if (this->_debug > 1) {std::cout << "  Ordering point " << point << " at " << offset << std::endl;}
245:             idx.index = offset;
246:             atlas->updatePoint(point, &idx);
247:             offset += dim;
248:           } else {
249:             if (this->_debug > 1) {std::cout << "  Ignoring ghost point " << point << std::endl;}
250:           }
251:         } else if (dim < 0) {
252:           if (this->_debug > 1) {std::cout << "  Ordering boundary point " << point << " at " << bcOffset << std::endl;}
253:           idx.index = bcOffset;
254:           atlas->updatePoint(point, &idx);
255:           bcOffset += dim;
256:         }
257:       }
258:     };
259:     template<typename Section_>
260:     void orderPatch(const Obj<Section_>& section, const Obj<sieve_type>& sieve, const Obj<send_overlap_type>& sendOverlap = NULL, const value_type offset = 0, const value_type bcOffset = -2) {
261:       const typename Section_::chart_type& chart = section->getChart();
262:       int off   = offset;
263:       int bcOff = bcOffset;

265:       if (this->_debug > 1) {std::cout << "Ordering patch" << std::endl;}
266:       for(typename Section_::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
267:         if (this->_debug > 1) {std::cout << "Ordering closure of point " << *p_iter << std::endl;}
268:         this->orderPoint(section, sieve, *p_iter, off, bcOff, sendOverlap);
269:       }
270:       for(typename Section_::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
271:         const int& idx  = section->getIndex(*p_iter);

273:         if (idx < 0) {
274:           if (this->_debug > 1) {std::cout << "Correcting boundary offset of point " << *p_iter << std::endl;}
275:           section->setIndex(*p_iter, off - (idx + 2));
276:         }
277:       }
278:     };
279:   public: // Numbering
280:     // Number all local points
281:     //   points in the overlap are only numbered by the owner with the lowest rank
282:     template<typename Sequence_>
283:     void constructLocalNumbering(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const Obj<Sequence_>& points) {
284:       int localSize = 0;

286:       numbering->setFiberDimension(points, 1);
287:       for(typename Sequence_::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
288:         value_type val;

290:         if (sendOverlap->capContains(*l_iter)) {
291:           const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
292:           int minRank = sendOverlap->commSize();

294:           for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
295:             if (*p_iter < minRank) minRank = *p_iter;
296:           }
297:           if (minRank < sendOverlap->commRank()) {
298:             val = this->_unknownNumber;
299:           } else {
300:             val = localSize++;
301:           }
302:         } else {
303:           val = localSize++;
304:         }
305:         numbering->updatePoint(*l_iter, &val);
306:       }
307:       numbering->setLocalSize(localSize);
308:     };
309:     // Order all local points
310:     //   points in the overlap are only ordered by the owner with the lowest rank
311:     template<typename Sequence_, typename Section_>
312:     void constructLocalOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<Sequence_>& points, const Obj<Section_>& section) {
313:       int localSize = 0;

315:       order->setFiberDimension(points, 1);
316:       for(typename Sequence_::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
317:         oValue_type val;

319:         if (sendOverlap->capContains(*l_iter)) {
320:           const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
321:           int minRank = sendOverlap->commSize();

323:           for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
324:             if (*p_iter < minRank) minRank = *p_iter;
325:           }
326:           if (minRank < sendOverlap->commRank()) {
327:             val = this->_unknownOrder;
328:           } else {
329:             val.prefix = localSize;
330:             val.index  = section->getConstrainedFiberDimension(*l_iter);
331:           }
332:         } else {
333:           val.prefix = localSize;
334:           val.index  = section->getConstrainedFiberDimension(*l_iter);
335:         }
336:         localSize += val.index;
337:         order->updatePoint(*l_iter, &val);
338:       }
339:       order->setLocalSize(localSize);
340:     };
341:     template<typename Point_, typename Section_>
342:     void constructLocalOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const std::set<Point_>& points, const Obj<Section_>& section) {
343:       int localSize = 0;

345:       order->setFiberDimension(points, 1);
346:       for(typename std::set<Point_>::iterator l_iter = points.begin(); l_iter != points.end(); ++l_iter) {
347:         oValue_type val;

349:         if (sendOverlap->capContains(*l_iter)) {
350:           const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
351:           int minRank = sendOverlap->commSize();

353:           for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
354:             if (*p_iter < minRank) minRank = *p_iter;
355:           }
356:           if (minRank < sendOverlap->commRank()) {
357:             val = this->_unknownOrder;
358:           } else {
359:             val.prefix = localSize;
360:             val.index  = section->getConstrainedFiberDimension(*l_iter);
361:           }
362:         } else {
363:           val.prefix = localSize;
364:           val.index  = section->getConstrainedFiberDimension(*l_iter);
365:         }
366:         localSize += val.index;
367:         order->updatePoint(*l_iter, &val);
368:       }
369:       order->setLocalSize(localSize);
370:     };
371:     // Calculate process offsets
372:     template<typename Numbering>
373:     void calculateOffsets(const Obj<Numbering>& numbering) {
374:       int  localSize = numbering->getLocalSize();
375:       int *offsets   = new int[numbering->commSize()+1];

377:       offsets[0] = 0;
378:       MPI_Allgather(&localSize, 1, MPI_INT, &(offsets[1]), 1, MPI_INT, numbering->comm());
379:       for(int p = 2; p <= numbering->commSize(); p++) {
380:         offsets[p] += offsets[p-1];
381:       }
382:       numbering->setGlobalOffsets(offsets);
383:       delete [] offsets;
384:     };
385:     // Update local offsets based upon process offsets
386:     template<typename Numbering, typename Sequence>
387:     void updateOrder(const Obj<Numbering>& numbering, const Obj<Sequence>& points) {
388:       const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());

390:       for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
391:         if (numbering->isLocal(*l_iter)) {
392:           numbering->updateAddPoint(*l_iter, &val);
393:         }
394:       }
395:     };
396:     template<typename Numbering, typename Point>
397:     void updateOrder(const Obj<Numbering>& numbering, const std::set<Point>& points) {
398:       const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());

400:       for(typename std::set<Point>::iterator l_iter = points.begin(); l_iter != points.end(); ++l_iter) {
401:         if (numbering->isLocal(*l_iter)) {
402:           numbering->updateAddPoint(*l_iter, &val);
403:         }
404:       }
405:     };
406:     // Communicate numbers in the overlap
407:     void completeNumbering(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, bool allowDuplicates = false) {
408:       typedef Field<send_overlap_type, int, Section<point_type, value_type, value_alloc_type> > send_section_type;
409:       typedef Field<recv_overlap_type, int, Section<point_type, value_type, value_alloc_type> > recv_section_type;
410:       typedef typename ALE::DiscreteSieve<point_type, alloc_type>                   dsieve_type;
411:       typedef typename ALE::Topology<int, dsieve_type, alloc_type>                  dtopology_type;
412:       typedef typename ALE::New::SectionCompletion<dtopology_type, int, alloc_type> completion;
413:       const Obj<send_section_type> sendSection = new send_section_type(numbering->comm(), this->debug());
414:       const Obj<recv_section_type> recvSection = new recv_section_type(numbering->comm(), sendSection->getTag(), this->debug());

416:       completion::completeSection(sendOverlap, recvOverlap, numbering->getAtlas(), numbering, sendSection, recvSection);
417:       const typename recv_section_type::sheaf_type& patches = recvSection->getPatches();

419:       for(typename recv_section_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
420:         const typename recv_section_type::patch_type&        rPatch  = p_iter->first;
421:         const Obj<typename recv_section_type::section_type>& section = recvSection->getSection(rPatch);
422:         const typename recv_section_type::chart_type&        points  = section->getChart();

424:         for(typename recv_section_type::chart_type::iterator r_iter = points.begin(); r_iter != points.end(); ++r_iter) {
425:           const typename recv_section_type::point_type& point  = *r_iter;
426:           const typename recv_section_type::value_type *values = section->restrictPoint(point);

428:           if (section->getFiberDimension(point) == 0) continue;
429:           if (values[0] >= 0) {
430:             if (numbering->isLocal(point) && !allowDuplicates) {
431:               ostringstream msg;
432:               msg << "["<<numbering->commRank()<<"]Multiple indices for point " << point << " from " << rPatch << " with index " << values[0];
433:               throw ALE::Exception(msg.str().c_str());
434:             }
435:             if (numbering->getAtlas()->getFiberDimension(point) == 0) {
436:               ostringstream msg;
437:               msg << "["<<numbering->commRank()<<"]Unexpected point " << point << " from " << rPatch << " with index " << values[0];
438:               throw ALE::Exception(msg.str().c_str());
439:             }
440:             int val = -(values[0]+1);
441:             numbering->updatePoint(point, &val);
442:           }
443:         }
444:       }
445:     };
446:     // Communicate (size,offset)s in the overlap
447:     void completeOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, bool allowDuplicates = false) {
448:       typedef Field<send_overlap_type, int, Section<point_type, oValue_type, oValue_alloc_type> > send_section_type;
449:       typedef Field<recv_overlap_type, int, Section<point_type, oValue_type, oValue_alloc_type> > recv_section_type;
450:       typedef ConstantSection<point_type, int, alloc_type>                          constant_sizer;
451:       typedef typename ALE::DiscreteSieve<point_type, alloc_type>                   dsieve_type;
452:       typedef typename ALE::Topology<int, dsieve_type, alloc_type>                  dtopology_type;
453:       typedef typename ALE::New::SectionCompletion<dtopology_type, int, alloc_type> completion;
454:       const Obj<send_section_type> sendSection = new send_section_type(order->comm(), this->debug());
455:       const Obj<recv_section_type> recvSection = new recv_section_type(order->comm(), sendSection->getTag(), this->debug());
456:       //const Obj<constant_sizer>    sizer       = new constant_sizer(order->comm(), 1, this->debug());

458:       //completion::completeSection(sendOverlap, recvOverlap, sizer, order, sendSection, recvSection);
459:       completion::completeSection(sendOverlap, recvOverlap, order->getAtlas(), order, sendSection, recvSection);
460:       Obj<typename recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();

462:       for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
463:         if (!order->hasPoint(*r_iter)) {
464:           order->setFiberDimension(*r_iter, 1);
465:           order->updatePoint(*r_iter, &this->_unknownOrder);
466:         }
467:       }
468:       for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
469:         const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
470: 
471:         for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != recvPatches->end(); ++p_iter) {
472:           const typename recv_section_type::value_type *values = recvSection->getSection(*p_iter)->restrictPoint(*r_iter);

474:           if (recvSection->getSection(*p_iter)->getFiberDimension(*r_iter) == 0) continue;
475:           if (values[0].index == 0) continue;
476:           if (values[0].prefix >= 0) {
477:             if (order->isLocal(*r_iter)) {
478:               if (!allowDuplicates) {
479:                 ostringstream msg;
480:                 msg << "["<<order->commRank()<<"]Multiple indices for point " << *r_iter << " from " << *p_iter << " with index " << values[0];
481:                 throw ALE::Exception(msg.str().c_str());
482:               }
483:               continue;
484:             }
485:             const oValue_type val(-(values[0].prefix+1), values[0].index);
486:             order->updatePoint(*r_iter, &val);
487:           } else {
488:             if (order->isLocal(*r_iter)) continue;
489:             order->updatePoint(*r_iter, values);
490:           }
491:         }
492:       }
493:     };
494:     // Construct a full global numbering
495:     template<typename Sequence>
496:     void constructNumbering(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const Obj<Sequence>& points) {
497:       this->constructLocalNumbering(numbering, sendOverlap, points);
498:       this->calculateOffsets(numbering);
499:       this->updateOrder(numbering, points);
500:       this->completeNumbering(numbering, sendOverlap, recvOverlap);
501:     };
502:     // Construct a full global order
503:     template<typename Sequence, typename Section>
504:     void constructOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const Obj<Sequence>& points, const Obj<Section>& section) {
505:       this->constructLocalOrder(order, sendOverlap, points, section);
506:       this->calculateOffsets(order);
507:       this->updateOrder(order, points);
508:       this->completeOrder(order, sendOverlap, recvOverlap);
509:     };
510:     template<typename PointType, typename Section>
511:     void constructOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const std::set<PointType>& points, const Obj<Section>& section) {
512:       this->constructLocalOrder(order, sendOverlap, points, section);
513:       this->calculateOffsets(order);
514:       this->updateOrder(order, points);
515:       this->completeOrder(order, sendOverlap, recvOverlap);
516:     };
517:   public:
518:     // Construct the inverse map from numbers to points
519:     //   If we really need this, then we should consider using a label
520:     void constructInverseOrder(const Obj<numbering_type>& numbering) {
521:       const typename numbering_type::chart_type& chart = numbering->getChart();

523:       for(typename numbering_type::chart_type::iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
524:         numbering->setPoint(numbering->getIndex(*p_iter), *p_iter);
525:       }
526:     };
527:   public: // Real interface
528:     template<typename ABundle_>
529:     const Obj<numbering_type>& getLocalNumbering(const Obj<ABundle_>& bundle, const int depth) {
530:       if ((this->_localNumberings.find(bundle.ptr()) == this->_localNumberings.end()) ||
531:           (this->_localNumberings[bundle.ptr()].find(depth) == this->_localNumberings[bundle.ptr()].end())) {
532:         Obj<numbering_type>    numbering   = new numbering_type(bundle->comm(), bundle->debug());
533:         Obj<send_overlap_type> sendOverlap = new send_overlap_type(bundle->comm(), bundle->debug());

535:         this->constructLocalNumbering(numbering, sendOverlap, bundle->depthStratum(depth));
536:         if (this->_debug) {std::cout << "Creating new local numbering: depth " << depth << std::endl;}
537:         this->_localNumberings[bundle.ptr()][depth] = numbering;
538:       }
539:       return this->_localNumberings[bundle.ptr()][depth];
540:     };
541:     template<typename ABundle_>
542:     const Obj<numbering_type>& getNumbering(const Obj<ABundle_>& bundle, const int depth) {
543:       if ((this->_numberings.find(bundle.ptr()) == this->_numberings.end()) ||
544:           (this->_numberings[bundle.ptr()].find(depth) == this->_numberings[bundle.ptr()].end())) {
545:         bundle->constructOverlap();
546:         Obj<numbering_type>    numbering   = new numbering_type(bundle->comm(), bundle->debug());
547:         Obj<send_overlap_type> sendOverlap = bundle->getSendOverlap();
548:         Obj<recv_overlap_type> recvOverlap = bundle->getRecvOverlap();

550:         this->constructNumbering(numbering, sendOverlap, recvOverlap, bundle->depthStratum(depth));
551:         if (this->_debug) {std::cout << "Creating new numbering: depth " << depth << std::endl;}
552:         this->_numberings[bundle.ptr()][depth] = numbering;
553:       }
554:       return this->_numberings[bundle.ptr()][depth];
555:     };
556:     template<typename ABundle_>
557:     const Obj<numbering_type>& getNumbering(const Obj<ABundle_>& bundle, const std::string& labelname, const int value) {
558:       if ((this->_numberings.find(bundle.ptr()) == this->_numberings.end()) ||
559:           (this->_numberings[bundle.ptr()].find(value) == this->_numberings[bundle.ptr()].end())) {
560:         bundle->constructOverlap();
561:         Obj<numbering_type>    numbering   = new numbering_type(bundle->comm(), bundle->debug());
562:         Obj<send_overlap_type> sendOverlap = bundle->getSendOverlap();
563:         Obj<recv_overlap_type> recvOverlap = bundle->getRecvOverlap();

565:         this->constructNumbering(numbering, sendOverlap, recvOverlap, bundle->getLabelStratum(labelname, value));
566:         if (this->_debug) {std::cout << "Creating new numbering: labelname " << labelname << " value " << value << std::endl;}
567:         this->_numberings[bundle.ptr()][value] = numbering;
568:       }
569:       return this->_numberings[bundle.ptr()][value];
570:     };
571:     template<typename ABundle_, typename Section_>
572:     const Obj<order_type>& getGlobalOrder(const Obj<ABundle_>& bundle, const std::string& name, const Obj<Section_>& section) {
573:       if ((this->_orders.find(bundle.ptr()) == this->_orders.end()) ||
574:           (this->_orders[bundle.ptr()].find(name) == this->_orders[bundle.ptr()].end())) {
575:         bundle->constructOverlap();
576:         Obj<order_type>        order       = new order_type(bundle->comm(), bundle->debug());
577:         Obj<send_overlap_type> sendOverlap = bundle->getSendOverlap();
578:         Obj<recv_overlap_type> recvOverlap = bundle->getRecvOverlap();

580:         this->constructOrder(order, sendOverlap, recvOverlap, section->getChart(), section);
581:         if (this->_debug) {std::cout << "Creating new global order: name " << name << std::endl;}
582:         this->_orders[bundle.ptr()][name] = order;
583:       }
584:       return this->_orders[bundle.ptr()][name];
585:     };
586:   };
587: }

589: namespace ALECompat {
590:   namespace New {
591:     template<typename Topology_, typename Value_ = int>
592:     class NewNumbering : public UniformSection<Topology_, Value_> {
593:     public:
594:       typedef UniformSection<Topology_, Value_>  base_type;
595:       typedef Topology_                          topology_type;
596:       typedef Value_                             value_type;
597:       typedef typename topology_type::patch_type patch_type;
598:       typedef typename topology_type::point_type point_type;
599:       typedef typename base_type::atlas_type     atlas_type;
600:     protected:
601:       int                       _localSize;
602:       int                      *_offsets;
603:       std::map<int, point_type> _invOrder;
604:     public:
605:       NewNumbering(const Obj<topology_type>& topology) : UniformSection<Topology_, Value_>(topology), _localSize(0) {
606:         this->_offsets    = new int[this->commSize()+1];
607:         this->_offsets[0] = 0;
608:       };
609:       ~NewNumbering() {
610:         delete [] this->_offsets;
611:       };
612:     public: // Sizes
613:       int        getLocalSize() const {return this->_localSize;};
614:       void       setLocalSize(const int size) {this->_localSize = size;};
615:       int        getGlobalSize() const {return this->_offsets[this->commSize()];};
616:       int        getGlobalOffset(const int p) const {return this->_offsets[p];};
617:       const int *getGlobalOffsets() const {return this->_offsets;};
618:       void       setGlobalOffsets(const int offsets[]) {
619:         for(int p = 0; p <= this->commSize(); ++p) {
620:           this->_offsets[p] = offsets[p];
621:         }
622:       };
623:     public: // Indices
624:       virtual int getIndex(const point_type& point) {
625:         return getIndex(0, point);
626:       };
627:       virtual int getIndex(const patch_type& patch, const point_type& point) {
628:         const value_type& idx = this->restrictPoint(patch, point)[0];
629:         if (idx >= 0) {
630:           return idx;
631:         }
632:         return -(idx+1);
633:       };
634:       virtual void setIndex(const point_type& point, const int index) {this->updatePoint(0, point, &index);};
635:       virtual bool isLocal(const point_type& point) {return this->restrictPoint(0, point)[0] >= 0;};
636:       virtual bool isRemote(const point_type& point) {return this->restrictPoint(0, point)[0] < 0;};
637:       point_type getPoint(const int& index) {return this->_invOrder[index];};
638:       void setPoint(const int& index, const point_type& point) {this->_invOrder[index] = point;};
639:     };

641:     template<typename Topology_>
642:     class NewGlobalOrder : public UniformSection<Topology_, ALE::Point> {
643:     public:
644:       typedef UniformSection<Topology_, ALE::Point> base_type;
645:       typedef Topology_                          topology_type;
646:       typedef ALE::Point                         value_type;
647:       typedef typename topology_type::patch_type patch_type;
648:       typedef typename topology_type::point_type point_type;
649:       typedef typename base_type::atlas_type     atlas_type;
650:     protected:
651:       int                       _localSize;
652:       int                      *_offsets;
653:       //std::map<int, point_type> _invOrder;
654:     public:
655:       NewGlobalOrder(const Obj<topology_type>& topology) : UniformSection<Topology_, ALE::Point>(topology), _localSize(0) {
656:         this->_offsets    = new int[this->commSize()+1];
657:         this->_offsets[0] = 0;
658:       };
659:       ~NewGlobalOrder() {
660:         delete [] this->_offsets;
661:       };
662:     public: // Sizes
663:       int        getLocalSize() const {return this->_localSize;};
664:       void       setLocalSize(const int size) {this->_localSize = size;};
665:       int        getGlobalSize() const {return this->_offsets[this->commSize()];};
666:       int        getGlobalOffset(const int p) const {return this->_offsets[p];};
667:       const int *getGlobalOffsets() const {return this->_offsets;};
668:       void       setGlobalOffsets(const int offsets[]) {
669:         for(int p = 0; p <= this->commSize(); ++p) {
670:           this->_offsets[p] = offsets[p];
671:         }
672:       };
673:     public: // Indices
674:       virtual int getIndex(const point_type& point) {
675:         return getIndex(0, point);
676:       };
677:       virtual int getIndex(const patch_type& patch, const point_type& point) {
678:         if (this->restrictPoint(0, point)[0].prefix >= 0) {
679:           return this->restrictPoint(0, point)[0].prefix;
680:         }
681:         return -(this->restrictPoint(0, point)[0].prefix+1);
682:       };
683:       virtual void setIndex(const point_type& point, const int index) {
684:         const value_type idx(index, this->restrictPoint(0, point)[0].index);
685:         this->updatePoint(0, point, &idx);
686:       };
687:       virtual bool isLocal(const point_type& point) {return this->restrictPoint(0, point)[0].prefix >= 0;};
688:       virtual bool isRemote(const point_type& point) {return this->restrictPoint(0, point)[0].prefix < 0;};
689:     };

691:     // We have a dichotomy between \emph{types}, describing the structure of objects,
692:     //   and \emph{concepts}, describing the role these objects play in the algorithm.
693:     //   Below we identify concepts with potential implementing types.
694:     //
695:     //   Concept           Type
696:     //   -------           ----
697:     //   Overlap           Sifter
698:     //   Atlas             ConstantSection, UniformSection
699:     //   Numbering         UniformSection
700:     //   GlobalOrder       UniformSection
701:     //
702:     // We will use factory types to create objects which satisfy a given concept.
703:     template<typename Topology_, typename Value_ = int>
704:     class NumberingFactory {
705:     public:
706:       typedef Topology_                                                           topology_type;
707:       typedef Value_                                                              value_type;
708:       typedef typename topology_type::point_type                                  point_type;
709:       typedef typename ALE::DiscreteSieve<point_type>                             dsieve_type;
710:       typedef typename ALE::Topology<int, dsieve_type>                            dtopology_type;
711:       typedef typename topology_type::patch_type                                  patch_type;
712:       typedef typename topology_type::send_overlap_type                           send_overlap_type;
713:       typedef typename topology_type::recv_overlap_type                           recv_overlap_type;
714:       typedef typename ALECompat::New::NewNumbering<topology_type, value_type>          numbering_type;
715:       typedef std::map<int, Obj<numbering_type> >                                 depthMap_type;
716:       typedef std::map<patch_type, depthMap_type>                                 patchMap_type;
717:       typedef std::map<topology_type*, patchMap_type>                             numberings_type;
718:       typedef typename ALECompat::New::NewGlobalOrder<topology_type>                    order_type;
719:       typedef std::map<std::string, Obj<order_type> >                             sectionMap_type;
720:       typedef std::map<patch_type, sectionMap_type>                               oPatchMap_type;
721:       typedef std::map<topology_type*, oPatchMap_type>                            orders_type;
722:       typedef typename order_type::value_type                                     oValue_type;
723:       typedef typename ALECompat::New::SectionCompletion<topology_type, int>            completion;
724:     protected:
725:       int             _debug;
726:       numberings_type _localNumberings;
727:       numberings_type _numberings;
728:       orders_type     _orders;
729:       value_type      _unknownNumber;
730:       ALE::Point      _unknownOrder;
731:     protected:
732:       NumberingFactory(const int debug) : _debug(debug), _unknownNumber(-1), _unknownOrder(-1, 0) {};
733:     public:
734:       ~NumberingFactory() {};
735:     public:
736:       static const Obj<NumberingFactory>& singleton(const int debug, bool cleanup = false) {
737:         static Obj<NumberingFactory> *_singleton = NULL;

739:         if (cleanup) {
740:           if (debug) {std::cout << "Destroying NumberingFactory" << std::endl;}
741:           if (_singleton) {delete _singleton;}
742:           _singleton = NULL;
743:         } else if (_singleton == NULL) {
744:           if (debug) {std::cout << "Creating new NumberingFactory" << std::endl;}
745:           _singleton  = new Obj<NumberingFactory>();
746:           *_singleton = new NumberingFactory(debug);
747:         }
748:         return *_singleton;
749:       };
750:     public:
751:       const int debug() {return this->_debug;};
752:       const int setDebug(const int debug) {return this->_debug = debug;};
753:     public:
754:       // Number all local points
755:       //   points in the overlap are only numbered by the owner with the lowest rank
756:       template<typename Sequence>
757:       void constructLocalNumbering(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const patch_type& patch, const Obj<Sequence>& points) {
758:         int localSize = 0;

760:         numbering->setFiberDimension(patch, points, 1);
761:         for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
762:           value_type val;

764:           if (sendOverlap->capContains(*l_iter)) {
765:             const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
766:             int minRank = sendOverlap->commSize();

768:             for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
769:               if (*p_iter < minRank) minRank = *p_iter;
770:             }
771:             if (minRank < sendOverlap->commRank()) {
772:               val = this->_unknownNumber;
773:             } else {
774:               val = localSize++;
775:             }
776:           } else {
777:             val = localSize++;
778:           }
779:           numbering->updatePoint(patch, *l_iter, &val);
780:         }
781:         numbering->setLocalSize(localSize);
782:       };
783:       // Order all local points
784:       //   points in the overlap are only ordered by the owner with the lowest rank
785:       template<typename Sequence, typename Atlas>
786:       void constructLocalOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const patch_type& patch, const Obj<Sequence>& points, const Obj<Atlas>& atlas) {
787:         int localSize = 0;

789:         order->setFiberDimension(patch, points, 1);
790:         for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
791:           oValue_type val;

793:           if (sendOverlap->capContains(*l_iter)) {
794:             const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
795:             int minRank = sendOverlap->commSize();

797:             for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
798:               if (*p_iter < minRank) minRank = *p_iter;
799:             }
800:             if (minRank < sendOverlap->commRank()) {
801:               val = this->_unknownOrder;
802:             } else {
803:               val.prefix = localSize;
804:               val.index  = atlas->restrict(patch, *l_iter)[0].prefix;
805:             }
806:           } else {
807:             val.prefix = localSize;
808:             val.index  = atlas->restrict(patch, *l_iter)[0].prefix;
809:           }
810:           localSize += std::max(0, val.index);
811:           order->updatePoint(patch, *l_iter, &val);
812:         }
813:         order->setLocalSize(localSize);
814:       };
815:       template<typename PointType, typename Atlas>
816:       void constructLocalOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const patch_type& patch, const std::set<PointType>& points, const Obj<Atlas>& atlas) {
817:         int localSize = 0;

819:         order->setFiberDimension(patch, points, 1);
820:         for(typename std::set<PointType>::iterator l_iter = points.begin(); l_iter != points.end(); ++l_iter) {
821:           oValue_type val;

823:           if (sendOverlap->capContains(*l_iter)) {
824:             const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
825:             int minRank = sendOverlap->commSize();

827:             for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
828:               if (*p_iter < minRank) minRank = *p_iter;
829:             }
830:             if (minRank < sendOverlap->commRank()) {
831:               val = this->_unknownOrder;
832:             } else {
833:               val.prefix = localSize;
834:               val.index  = atlas->restrictPoint(patch, *l_iter)[0].prefix;
835:             }
836:           } else {
837:             val.prefix = localSize;
838:             val.index  = atlas->restrictPoint(patch, *l_iter)[0].prefix;
839:           }
840:           localSize += std::max(0, val.index);
841:           order->updatePoint(patch, *l_iter, &val);
842:         }
843:         order->setLocalSize(localSize);
844:       };
845:       // Calculate process offsets
846:       template<typename Numbering>
847:       void calculateOffsets(const Obj<Numbering>& numbering) {
848:         int  localSize = numbering->getLocalSize();
849:         int *offsets   = new int[numbering->commSize()+1];

851:         offsets[0] = 0;
852:         MPI_Allgather(&localSize, 1, MPI_INT, &(offsets[1]), 1, MPI_INT, numbering->comm());
853:         for(int p = 2; p <= numbering->commSize(); p++) {
854:           offsets[p] += offsets[p-1];
855:         }
856:         numbering->setGlobalOffsets(offsets);
857:         delete [] offsets;
858:       };
859:       // Update local offsets based upon process offsets
860:       template<typename Numbering, typename Sequence>
861:       void updateOrder(const Obj<Numbering>& numbering, const patch_type& patch, const Obj<Sequence>& points) {
862:         const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());

864:         for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
865:           if (numbering->isLocal(*l_iter)) {
866:             numbering->updateAddPoint(patch, *l_iter, &val);
867:           }
868:         }
869:       };
870:       template<typename Numbering, typename PointType>
871:       void updateOrder(const Obj<Numbering>& numbering, const patch_type& patch, const std::set<PointType>& points) {
872:         const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());

874:         for(typename std::set<PointType>::iterator l_iter = points.begin(); l_iter != points.end(); ++l_iter) {
875:           if (numbering->isLocal(*l_iter)) {
876:             numbering->updateAddPoint(patch, *l_iter, &val);
877:           }
878:         }
879:       };
880:       // Communicate numbers in the overlap
881:       void complete(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const patch_type& patch, bool allowDuplicates = false) {
882:         typedef dtopology_type topo_type;
883:         typedef typename ALE::Field<send_overlap_type, int, ALE::Section<point_type, value_type> > send_section_type;
884:         typedef typename ALE::Field<recv_overlap_type, int, ALE::Section<point_type, value_type> > recv_section_type;
885:         typedef typename ALECompat::New::OldConstantSection<topology_type, int> constant_sizer;
886:         const Obj<send_section_type> sendSection = new send_section_type(numbering->comm(), this->debug());
887:         const Obj<recv_section_type> recvSection = new recv_section_type(numbering->comm(), sendSection->getTag(), this->debug());
888:         //const Obj<constant_sizer>    sizer       = new constant_sizer(numbering->comm(), 1, this->debug());

890:         completion::completeSection(sendOverlap, recvOverlap, numbering->getAtlas(), numbering, sendSection, recvSection);
891:         const typename recv_section_type::topology_type::sheaf_type& patches = recvSection->getTopology()->getPatches();

893:         for(typename recv_section_type::topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
894:           const typename recv_section_type::patch_type& rPatch = p_iter->first;
895:           const typename recv_section_type::chart_type& points = recvSection->getPatch(rPatch);

897:           for(typename recv_section_type::chart_type::iterator r_iter = points.begin(); r_iter != points.end(); ++r_iter) {
898:             const typename recv_section_type::point_type& point  = *r_iter;
899:             const typename recv_section_type::value_type *values = recvSection->restrictPoint(rPatch, point);

901:             if (recvSection->getFiberDimension(rPatch, point) == 0) continue;
902:             if (values[0] >= 0) {
903:               if (numbering->isLocal(point) && !allowDuplicates) {
904:                 ostringstream msg;
905:                 msg << "["<<numbering->commRank()<<"]Multiple indices for point " << point << " from " << rPatch << " with index " << values[0];
906:                 throw ALE::Exception(msg.str().c_str());
907:               }
908:               if (numbering->getAtlas()->getFiberDimension(0, point) == 0) {
909:                 ostringstream msg;
910:                 msg << "["<<numbering->commRank()<<"]Unexpected point " << point << " from " << rPatch << " with index " << values[0];
911:                 throw ALE::Exception(msg.str().c_str());
912:               }
913:               int val = -(values[0]+1);
914:               numbering->updatePoint(patch, point, &val);
915:             }
916:           }
917:         }
918: #if 0
919:         Obj<typename recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();

921:         for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
922:           numbering->setFiberDimension(0, *r_iter, 1);
923:         }
924:         for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
925:           const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
926: 
927:           for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != recvPatches->end(); ++p_iter) {
928:             const typename recv_section_type::value_type *values = recvSection->restrict(*p_iter, *r_iter);

930:             if (values[0] >= 0) {
931:               if (numbering->isLocal(*r_iter) && !allowDuplicates) {
932:                 ostringstream msg;
933:                 msg << "["<<numbering->commRank()<<"]Multiple indices for point " << *r_iter << " from " << *p_iter << " with index " << values[0];
934:                 throw ALE::Exception(msg.str().c_str());
935:               }
936:               if (numbering->getAtlas()->getFiberDimension(0, *r_iter) == 0) {
937:                 ostringstream msg;
938:                 msg << "["<<numbering->commRank()<<"]Unexpected point " << *r_iter << " from " << *p_iter << " with index " << values[0];
939:                 throw ALE::Exception(msg.str().c_str());
940:               }
941:               int val = -(values[0]+1);
942:               numbering->updatePoint(patch, *r_iter, &val);
943:             }
944:           }
945:         }
946: #endif
947:       };
948:       // Communicate (size,offset)s in the overlap
949:       void completeOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const patch_type& patch, bool allowDuplicates = false) {
950:         typedef dtopology_type topo_type;
951:         typedef typename ALECompat::New::OverlapValues<send_overlap_type, topo_type, oValue_type> send_section_type;
952:         typedef typename ALECompat::New::OverlapValues<recv_overlap_type, topo_type, oValue_type> recv_section_type;
953:         typedef typename ALECompat::New::OldConstantSection<topology_type, int> constant_sizer;
954:         const Obj<send_section_type> sendSection = new send_section_type(order->comm(), this->debug());
955:         const Obj<recv_section_type> recvSection = new recv_section_type(order->comm(), sendSection->getTag(), this->debug());
956:         const Obj<constant_sizer>    sizer       = new constant_sizer(order->comm(), 1, this->debug());

958:         completion::completeSection(sendOverlap, recvOverlap, sizer, order, sendSection, recvSection);
959:         Obj<typename recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();

961:         for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
962:           if (!order->hasPoint(patch, *r_iter)) {
963:             order->setFiberDimension(patch, *r_iter, 1);
964:             order->updatePoint(patch, *r_iter, &this->_unknownOrder);
965:           }
966:         }
967:         for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
968:           const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
969: 
970:           for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != recvPatches->end(); ++p_iter) {
971:             const typename recv_section_type::value_type *values = recvSection->restrict(*p_iter, *r_iter);

973:             if (values[0].index == 0) continue;
974:             if (values[0].prefix >= 0) {
975:               if (order->isLocal(*r_iter)) {
976:                 if (!allowDuplicates) {
977:                   ostringstream msg;
978:                   msg << "["<<order->commRank()<<"]Multiple indices for point " << *r_iter << " from " << *p_iter << " with index " << values[0];
979:                   throw ALE::Exception(msg.str().c_str());
980:                 }
981:                 continue;
982:               }
983:               const oValue_type val(-(values[0].prefix+1), values[0].index);
984:               order->updatePoint(patch, *r_iter, &val);
985:             } else {
986:               if (order->isLocal(*r_iter)) continue;
987:               order->updatePoint(patch, *r_iter, values);
988:             }
989:           }
990:         }
991:       };
992:       // Construct a full global numbering
993:       template<typename Sequence>
994:       void construct(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const patch_type& patch, const Obj<Sequence>& points) {
995:         this->constructLocalNumbering(numbering, sendOverlap, patch, points);
996:         this->calculateOffsets(numbering);
997:         this->updateOrder(numbering, patch, points);
998:         this->complete(numbering, sendOverlap, recvOverlap, patch);
999:       };
1000:       // Construct a full global order
1001:       template<typename Sequence, typename Atlas>
1002:       void constructOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const patch_type& patch, const Obj<Sequence>& points, const Obj<Atlas>& atlas) {
1003:         this->constructLocalOrder(order, sendOverlap, patch, points, atlas);
1004:         this->calculateOffsets(order);
1005:         this->updateOrder(order, patch, points);
1006:         this->completeOrder(order, sendOverlap, recvOverlap, patch);
1007:       };
1008:       template<typename PointType, typename Atlas>
1009:       void constructOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const patch_type& patch, const std::set<PointType>& points, const Obj<Atlas>& atlas) {
1010:         this->constructLocalOrder(order, sendOverlap, patch, points, atlas);
1011:         this->calculateOffsets(order);
1012:         this->updateOrder(order, patch, points);
1013:         this->completeOrder(order, sendOverlap, recvOverlap, patch);
1014:       };
1015:       // Construct the inverse map from numbers to points
1016:       //   If we really need this, then we should consider using a label
1017:       void constructInverseOrder(const Obj<numbering_type>& numbering) {
1018:         const typename numbering_type::chart_type& patch = numbering->getAtlas()->getPatch(0);

1020:         for(typename numbering_type::chart_type::iterator p_iter = patch.begin(); p_iter != patch.end(); ++p_iter) {
1021:           numbering->setPoint(numbering->getIndex(*p_iter), *p_iter);
1022:         }
1023:       };
1024:     public:
1025:       const Obj<numbering_type>& getLocalNumbering(const Obj<topology_type>& topology, const patch_type& patch, const int depth) {
1026:         if ((this->_localNumberings.find(topology.ptr()) == this->_localNumberings.end()) ||
1027:             (this->_localNumberings[topology.ptr()].find(patch) == this->_localNumberings[topology.ptr()].end()) ||
1028:             (this->_localNumberings[topology.ptr()][patch].find(depth) == this->_localNumberings[topology.ptr()][patch].end())) {
1029:           Obj<numbering_type>    numbering   = new numbering_type(topology);
1030:           // These go in the Topology soon
1031:           Obj<send_overlap_type> sendOverlap = new send_overlap_type(topology->comm(), topology->debug());
1032:           //Obj<recv_overlap_type> recvOverlap = new recv_overlap_type(this->comm(), this->debug());

1034:           this->constructLocalNumbering(numbering, sendOverlap, patch, topology->getLabelStratum(patch, "depth", depth));
1035:           if (this->_debug) {std::cout << "Creating new local numbering: patch " << patch << " depth " << depth << std::endl;}
1036:           this->_localNumberings[topology.ptr()][patch][depth] = numbering;
1037:         }
1038:         return this->_localNumberings[topology.ptr()][patch][depth];
1039:       };
1040:       const Obj<numbering_type>& getNumbering(const Obj<topology_type>& topology, const patch_type& patch, const int depth) {
1041:         if ((this->_numberings.find(topology.ptr()) == this->_numberings.end()) ||
1042:             (this->_numberings[topology.ptr()].find(patch) == this->_numberings[topology.ptr()].end()) ||
1043:             (this->_numberings[topology.ptr()][patch].find(depth) == this->_numberings[topology.ptr()][patch].end())) {
1044:           topology->constructOverlap(patch);
1045:           Obj<numbering_type>    numbering   = new numbering_type(topology);
1046:           Obj<send_overlap_type> sendOverlap = topology->getSendOverlap();
1047:           Obj<recv_overlap_type> recvOverlap = topology->getRecvOverlap();

1049:           this->construct(numbering, sendOverlap, recvOverlap, patch, topology->getLabelStratum(patch, "depth", depth));
1050:           if (this->_debug) {std::cout << "Creating new numbering: patch " << patch << " depth " << depth << std::endl;}
1051:           this->_numberings[topology.ptr()][patch][depth] = numbering;
1052:         }
1053:         return this->_numberings[topology.ptr()][patch][depth];
1054:       };
1055:       template<typename Atlas>
1056:       const Obj<order_type>& getGlobalOrder(const Obj<topology_type>& topology, const patch_type& patch, const std::string& name, const Obj<Atlas>& atlas) {
1057:         if ((this->_orders.find(topology.ptr()) == this->_orders.end()) ||
1058:             (this->_orders[topology.ptr()].find(patch) == this->_orders[topology.ptr()].end()) ||
1059:             (this->_orders[topology.ptr()][patch].find(name) == this->_orders[topology.ptr()][patch].end())) {
1060:           topology->constructOverlap(patch);
1061:           Obj<order_type>        order       = new order_type(topology);
1062:           Obj<send_overlap_type> sendOverlap = topology->getSendOverlap();
1063:           Obj<recv_overlap_type> recvOverlap = topology->getRecvOverlap();

1065:           this->constructOrder(order, sendOverlap, recvOverlap, patch, atlas->getPatch(patch), atlas);
1066:           //this->constructOrder(order, sendOverlap, recvOverlap, patch, topology->depthStratum(patch, 0), atlas);
1067:           if (this->_debug) {std::cout << "Creating new global order: patch " << patch << " name " << name << std::endl;}
1068:           this->_orders[topology.ptr()][patch][name] = order;
1069:         }
1070:         return this->_orders[topology.ptr()][patch][name];
1071:       };
1072:     };
1073:   }
1074: }
1075: #endif