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>
 23:   class Numbering : public UniformSection<Point_, Value_> {
 24:   public:
 25:     typedef UniformSection<Point_, Value_> 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_>(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>
111:   class NumberingFactory : ALE::ParallelObject {
112:   public:
113:     typedef Bundle_                                         bundle_type;
114:     typedef typename bundle_type::sieve_type                sieve_type;
115:     typedef typename sieve_type::point_type                 point_type;
116:     typedef Value_                                          value_type;
117:     typedef Numbering<point_type, value_type>               numbering_type;
118:     typedef std::map<bundle_type*, std::map<int, Obj<numbering_type> > >     numberings_type;
119:     typedef GlobalOrder<point_type>                         order_type;
120:     typedef typename order_type::value_type                 oValue_type;
121:     typedef std::map<bundle_type*, std::map<std::string, Obj<order_type> > > orders_type;
122:     typedef typename ALE::Sifter<int,point_type,point_type> send_overlap_type;
123:     typedef typename ALE::Sifter<point_type,int,point_type> recv_overlap_type;
124:   protected:
125:     numberings_type   _localNumberings;
126:     numberings_type   _numberings;
127:     orders_type       _orders;
128:     const value_type  _unknownNumber;
129:     const oValue_type _unknownOrder;
130:   protected:
131:     NumberingFactory(MPI_Comm comm, const int debug = 0) : ALE::ParallelObject(comm, debug), _unknownNumber(-1), _unknownOrder(-1, 0) {};
132:   public:
133:     ~NumberingFactory() {};
134:   public:
135:     static const Obj<NumberingFactory>& singleton(MPI_Comm comm, const int debug, bool cleanup = false) {
136:       static Obj<NumberingFactory> *_singleton = NULL;

138:       if (cleanup) {
139:         if (debug) {std::cout << "Destroying NumberingFactory" << std::endl;}
140:         if (_singleton) {delete _singleton;}
141:         _singleton = NULL;
142:       } else if (_singleton == NULL) {
143:         if (debug) {std::cout << "Creating new NumberingFactory" << std::endl;}
144:         _singleton  = new Obj<NumberingFactory>();
145:         *_singleton = new NumberingFactory(comm, debug);
146:       }
147:       return *_singleton;
148:     };
149:   public: // Dof ordering
150:     template<typename Section_>
151:     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) {
152:       const typename Section_::chart_type& chart = section->getChart();
153:       int&                                 idx   = section->getIndex(point);

155:       // If the point does not exist in the chart, throw an error
156:       if (chart.count(point) == 0) {
157:         throw ALE::Exception("Unknown point in ordering");
158:       }
159:       // If the point has not been ordered
160:       if (idx == -1) {
161:         // Recurse to its cover
162:         const Obj<typename sieve_type::coneSequence>& cone = sieve->cone(point);
163:         typename sieve_type::coneSequence::iterator   end  = cone->end();

165:         for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
166:           if (this->_debug > 1) {std::cout << "    Recursing to " << *c_iter << std::endl;}
167:           this->orderPoint(section, sieve, *c_iter, offset, bcOffset, sendOverlap);
168:         }
169:         const int dim  = section->getFiberDimension(point);
170:         const int cDim = section->getConstraintDimension(point);
171:         const int fDim = dim - cDim;

173:         // If the point has constrained variables
174:         if (cDim) {
175:           if (this->_debug > 1) {std::cout << "  Ordering boundary point " << point << " at " << bcOffset << std::endl;}
176:           section->setIndexBC(point, bcOffset);
177:           bcOffset += cDim;
178:         }
179:         // If the point has free variables
180:         if (fDim) {
181:           bool number = true;

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

187:             for(typename send_overlap_type::supportSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
188:               if (this->commRank() > *r_iter) {
189:                 number = false;
190:                 break;
191:               }
192:             }
193:           }
194:           if (number) {
195:             if (this->_debug > 1) {std::cout << "  Ordering point " << point << " at " << offset << std::endl;}
196:             section->setIndex(point, offset);
197:             offset += dim;
198:           } else {
199:             if (this->_debug > 1) {std::cout << "  Ignoring ghost point " << point << std::endl;}
200:           }
201:         }
202:       }
203:     };
204:     template<typename Section_>
205:     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) {
206:       const Obj<typename Section_::atlas_type>&     atlas = section->getAtlas();
207:       const Obj<typename sieve_type::coneSequence>& cone = sieve->cone(point);
208:       typename sieve_type::coneSequence::iterator   end  = cone->end();
209:       typename Section_::index_type                 idx  = section->getAtlas()->restrictPoint(point)[0];
210:       const value_type&                             dim  = idx.prefix;
211:       const typename Section_::index_type           defaultIdx(0, -1);

213:       if (atlas->getChart().count(point) == 0) {
214:         idx = defaultIdx;
215:       }
216:       if (idx.index == -1) {
217:         for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
218:           if (this->_debug > 1) {std::cout << "    Recursing to " << *c_iter << std::endl;}
219:           this->orderPoint(section, sieve, *c_iter, offset, bcOffset, sendOverlap);
220:         }
221:         if (dim > 0) {
222:           bool number = true;

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

228:             for(typename send_overlap_type::supportSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
229:               if (this->commRank() > *r_iter) {
230:                 number = false;
231:                 break;
232:               }
233:             }
234:           }
235:           if (number) {
236:             if (this->_debug > 1) {std::cout << "  Ordering point " << point << " at " << offset << std::endl;}
237:             idx.index = offset;
238:             atlas->updatePoint(point, &idx);
239:             offset += dim;
240:           } else {
241:             if (this->_debug > 1) {std::cout << "  Ignoring ghost point " << point << std::endl;}
242:           }
243:         } else if (dim < 0) {
244:           if (this->_debug > 1) {std::cout << "  Ordering boundary point " << point << " at " << bcOffset << std::endl;}
245:           idx.index = bcOffset;
246:           atlas->updatePoint(point, &idx);
247:           bcOffset += dim;
248:         }
249:       }
250:     };
251:     template<typename Section_>
252:     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) {
253:       const typename Section_::chart_type& chart = section->getChart();
254:       int off   = offset;
255:       int bcOff = bcOffset;

257:       if (this->_debug > 1) {std::cout << "Ordering patch" << std::endl;}
258:       for(typename Section_::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
259:         if (this->_debug > 1) {std::cout << "Ordering closure of point " << *p_iter << std::endl;}
260:         this->orderPoint(section, sieve, *p_iter, off, bcOff, sendOverlap);
261:       }
262:       for(typename Section_::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
263:         const int& idx  = section->getIndex(*p_iter);

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

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

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

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

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

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

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

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

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

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

369:       offsets[0] = 0;
370:       MPI_Allgather(&localSize, 1, MPI_INT, &(offsets[1]), 1, MPI_INT, numbering->comm());
371:       for(int p = 2; p <= numbering->commSize(); p++) {
372:         offsets[p] += offsets[p-1];
373:       }
374:       numbering->setGlobalOffsets(offsets);
375:       delete [] offsets;
376:     };
377:     // Update local offsets based upon process offsets
378:     template<typename Numbering, typename Sequence>
379:     void updateOrder(const Obj<Numbering>& numbering, const Obj<Sequence>& points) {
380:       const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());

382:       for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
383:         if (numbering->isLocal(*l_iter)) {
384:           numbering->updateAddPoint(*l_iter, &val);
385:         }
386:       }
387:     };
388:     template<typename Numbering, typename Point>
389:     void updateOrder(const Obj<Numbering>& numbering, const std::set<Point>& points) {
390:       const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());

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

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

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

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

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

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

454:       for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
455:         if (!order->hasPoint(*r_iter)) {
456:           order->setFiberDimension(*r_iter, 1);
457:           order->updatePoint(*r_iter, &this->_unknownOrder);
458:         }
459:       }
460:       for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
461:         const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
462: 
463:         for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != recvPatches->end(); ++p_iter) {
464:           const typename recv_section_type::value_type *values = recvSection->getSection(*p_iter)->restrictPoint(*r_iter);

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

515:       for(typename numbering_type::chart_type::iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
516:         numbering->setPoint(numbering->getIndex(*p_iter), *p_iter);
517:       }
518:     };
519:   public: // Real interface
520:     template<typename ABundle_>
521:     const Obj<numbering_type>& getLocalNumbering(const Obj<ABundle_>& bundle, const int depth) {
522:       if ((this->_localNumberings.find(bundle.ptr()) == this->_localNumberings.end()) ||
523:           (this->_localNumberings[bundle.ptr()].find(depth) == this->_localNumberings[bundle.ptr()].end())) {
524:         Obj<numbering_type>    numbering   = new numbering_type(bundle->comm(), bundle->debug());
525:         Obj<send_overlap_type> sendOverlap = new send_overlap_type(bundle->comm(), bundle->debug());

527:         this->constructLocalNumbering(numbering, sendOverlap, bundle->depthStratum(depth));
528:         if (this->_debug) {std::cout << "Creating new local numbering: depth " << depth << std::endl;}
529:         this->_localNumberings[bundle.ptr()][depth] = numbering;
530:       }
531:       return this->_localNumberings[bundle.ptr()][depth];
532:     };
533:     template<typename ABundle_>
534:     const Obj<numbering_type>& getNumbering(const Obj<ABundle_>& bundle, const int depth) {
535:       if ((this->_numberings.find(bundle.ptr()) == this->_numberings.end()) ||
536:           (this->_numberings[bundle.ptr()].find(depth) == this->_numberings[bundle.ptr()].end())) {
537:         bundle->constructOverlap();
538:         Obj<numbering_type>    numbering   = new numbering_type(bundle->comm(), bundle->debug());
539:         Obj<send_overlap_type> sendOverlap = bundle->getSendOverlap();
540:         Obj<recv_overlap_type> recvOverlap = bundle->getRecvOverlap();

542:         this->constructNumbering(numbering, sendOverlap, recvOverlap, bundle->depthStratum(depth));
543:         if (this->_debug) {std::cout << "Creating new numbering: depth " << depth << std::endl;}
544:         this->_numberings[bundle.ptr()][depth] = numbering;
545:       }
546:       return this->_numberings[bundle.ptr()][depth];
547:     };
548:     template<typename ABundle_, typename Section_>
549:     const Obj<order_type>& getGlobalOrder(const Obj<ABundle_>& bundle, const std::string& name, const Obj<Section_>& section) {
550:       if ((this->_orders.find(bundle.ptr()) == this->_orders.end()) ||
551:           (this->_orders[bundle.ptr()].find(name) == this->_orders[bundle.ptr()].end())) {
552:         bundle->constructOverlap();
553:         Obj<order_type>        order       = new order_type(bundle->comm(), bundle->debug());
554:         Obj<send_overlap_type> sendOverlap = bundle->getSendOverlap();
555:         Obj<recv_overlap_type> recvOverlap = bundle->getRecvOverlap();

557:         this->constructOrder(order, sendOverlap, recvOverlap, section->getChart(), section);
558:         if (this->_debug) {std::cout << "Creating new global order: name " << name << std::endl;}
559:         this->_orders[bundle.ptr()][name] = order;
560:       }
561:       return this->_orders[bundle.ptr()][name];
562:     };
563:   };
564: }

566: namespace ALECompat {
567:   namespace New {
568:     template<typename Topology_, typename Value_ = int>
569:     class NewNumbering : public UniformSection<Topology_, Value_> {
570:     public:
571:       typedef UniformSection<Topology_, Value_>  base_type;
572:       typedef Topology_                          topology_type;
573:       typedef Value_                             value_type;
574:       typedef typename topology_type::patch_type patch_type;
575:       typedef typename topology_type::point_type point_type;
576:       typedef typename base_type::atlas_type     atlas_type;
577:     protected:
578:       int                       _localSize;
579:       int                      *_offsets;
580:       std::map<int, point_type> _invOrder;
581:     public:
582:       NewNumbering(const Obj<topology_type>& topology) : UniformSection<Topology_, Value_>(topology), _localSize(0) {
583:         this->_offsets    = new int[this->commSize()+1];
584:         this->_offsets[0] = 0;
585:       };
586:       ~NewNumbering() {
587:         delete [] this->_offsets;
588:       };
589:     public: // Sizes
590:       int        getLocalSize() const {return this->_localSize;};
591:       void       setLocalSize(const int size) {this->_localSize = size;};
592:       int        getGlobalSize() const {return this->_offsets[this->commSize()];};
593:       int        getGlobalOffset(const int p) const {return this->_offsets[p];};
594:       const int *getGlobalOffsets() const {return this->_offsets;};
595:       void       setGlobalOffsets(const int offsets[]) {
596:         for(int p = 0; p <= this->commSize(); ++p) {
597:           this->_offsets[p] = offsets[p];
598:         }
599:       };
600:     public: // Indices
601:       virtual int getIndex(const point_type& point) {
602:         return getIndex(0, point);
603:       };
604:       virtual int getIndex(const patch_type& patch, const point_type& point) {
605:         const value_type& idx = this->restrictPoint(patch, point)[0];
606:         if (idx >= 0) {
607:           return idx;
608:         }
609:         return -(idx+1);
610:       };
611:       virtual void setIndex(const point_type& point, const int index) {this->updatePoint(0, point, &index);};
612:       virtual bool isLocal(const point_type& point) {return this->restrictPoint(0, point)[0] >= 0;};
613:       virtual bool isRemote(const point_type& point) {return this->restrictPoint(0, point)[0] < 0;};
614:       point_type getPoint(const int& index) {return this->_invOrder[index];};
615:       void setPoint(const int& index, const point_type& point) {this->_invOrder[index] = point;};
616:     };

618:     template<typename Topology_>
619:     class NewGlobalOrder : public UniformSection<Topology_, ALE::Point> {
620:     public:
621:       typedef UniformSection<Topology_, ALE::Point> base_type;
622:       typedef Topology_                          topology_type;
623:       typedef ALE::Point                         value_type;
624:       typedef typename topology_type::patch_type patch_type;
625:       typedef typename topology_type::point_type point_type;
626:       typedef typename base_type::atlas_type     atlas_type;
627:     protected:
628:       int                       _localSize;
629:       int                      *_offsets;
630:       //std::map<int, point_type> _invOrder;
631:     public:
632:       NewGlobalOrder(const Obj<topology_type>& topology) : UniformSection<Topology_, ALE::Point>(topology), _localSize(0) {
633:         this->_offsets    = new int[this->commSize()+1];
634:         this->_offsets[0] = 0;
635:       };
636:       ~NewGlobalOrder() {
637:         delete [] this->_offsets;
638:       };
639:     public: // Sizes
640:       int        getLocalSize() const {return this->_localSize;};
641:       void       setLocalSize(const int size) {this->_localSize = size;};
642:       int        getGlobalSize() const {return this->_offsets[this->commSize()];};
643:       int        getGlobalOffset(const int p) const {return this->_offsets[p];};
644:       const int *getGlobalOffsets() const {return this->_offsets;};
645:       void       setGlobalOffsets(const int offsets[]) {
646:         for(int p = 0; p <= this->commSize(); ++p) {
647:           this->_offsets[p] = offsets[p];
648:         }
649:       };
650:     public: // Indices
651:       virtual int getIndex(const point_type& point) {
652:         return getIndex(0, point);
653:       };
654:       virtual int getIndex(const patch_type& patch, const point_type& point) {
655:         if (this->restrictPoint(0, point)[0].prefix >= 0) {
656:           return this->restrictPoint(0, point)[0].prefix;
657:         }
658:         return -(this->restrictPoint(0, point)[0].prefix+1);
659:       };
660:       virtual void setIndex(const point_type& point, const int index) {
661:         const value_type idx(index, this->restrictPoint(0, point)[0].index);
662:         this->updatePoint(0, point, &idx);
663:       };
664:       virtual bool isLocal(const point_type& point) {return this->restrictPoint(0, point)[0].prefix >= 0;};
665:       virtual bool isRemote(const point_type& point) {return this->restrictPoint(0, point)[0].prefix < 0;};
666:     };

668:     // We have a dichotomy between \emph{types}, describing the structure of objects,
669:     //   and \emph{concepts}, describing the role these objects play in the algorithm.
670:     //   Below we identify concepts with potential implementing types.
671:     //
672:     //   Concept           Type
673:     //   -------           ----
674:     //   Overlap           Sifter
675:     //   Atlas             ConstantSection, UniformSection
676:     //   Numbering         UniformSection
677:     //   GlobalOrder       UniformSection
678:     //
679:     // We will use factory types to create objects which satisfy a given concept.
680:     template<typename Topology_, typename Value_ = int>
681:     class NumberingFactory {
682:     public:
683:       typedef Topology_                                                           topology_type;
684:       typedef Value_                                                              value_type;
685:       typedef typename topology_type::point_type                                  point_type;
686:       typedef typename ALE::DiscreteSieve<point_type>                             dsieve_type;
687:       typedef typename ALE::Topology<int, dsieve_type>                            dtopology_type;
688:       typedef typename topology_type::patch_type                                  patch_type;
689:       typedef typename topology_type::send_overlap_type                           send_overlap_type;
690:       typedef typename topology_type::recv_overlap_type                           recv_overlap_type;
691:       typedef typename ALECompat::New::NewNumbering<topology_type, value_type>          numbering_type;
692:       typedef std::map<int, Obj<numbering_type> >                                 depthMap_type;
693:       typedef std::map<patch_type, depthMap_type>                                 patchMap_type;
694:       typedef std::map<topology_type*, patchMap_type>                             numberings_type;
695:       typedef typename ALECompat::New::NewGlobalOrder<topology_type>                    order_type;
696:       typedef std::map<std::string, Obj<order_type> >                             sectionMap_type;
697:       typedef std::map<patch_type, sectionMap_type>                               oPatchMap_type;
698:       typedef std::map<topology_type*, oPatchMap_type>                            orders_type;
699:       typedef typename order_type::value_type                                     oValue_type;
700:       typedef typename ALECompat::New::SectionCompletion<topology_type, int>            completion;
701:     protected:
702:       int             _debug;
703:       numberings_type _localNumberings;
704:       numberings_type _numberings;
705:       orders_type     _orders;
706:       value_type      _unknownNumber;
707:       ALE::Point      _unknownOrder;
708:     protected:
709:       NumberingFactory(const int debug) : _debug(debug), _unknownNumber(-1), _unknownOrder(-1, 0) {};
710:     public:
711:       ~NumberingFactory() {};
712:     public:
713:       static const Obj<NumberingFactory>& singleton(const int debug, bool cleanup = false) {
714:         static Obj<NumberingFactory> *_singleton = NULL;

716:         if (cleanup) {
717:           if (debug) {std::cout << "Destroying NumberingFactory" << std::endl;}
718:           if (_singleton) {delete _singleton;}
719:           _singleton = NULL;
720:         } else if (_singleton == NULL) {
721:           if (debug) {std::cout << "Creating new NumberingFactory" << std::endl;}
722:           _singleton  = new Obj<NumberingFactory>();
723:           *_singleton = new NumberingFactory(debug);
724:         }
725:         return *_singleton;
726:       };
727:     public:
728:       const int debug() {return this->_debug;};
729:       const int setDebug(const int debug) {return this->_debug = debug;};
730:     public:
731:       // Number all local points
732:       //   points in the overlap are only numbered by the owner with the lowest rank
733:       template<typename Sequence>
734:       void constructLocalNumbering(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const patch_type& patch, const Obj<Sequence>& points) {
735:         int localSize = 0;

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

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

745:             for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
746:               if (*p_iter < minRank) minRank = *p_iter;
747:             }
748:             if (minRank < sendOverlap->commRank()) {
749:               val = this->_unknownNumber;
750:             } else {
751:               val = localSize++;
752:             }
753:           } else {
754:             val = localSize++;
755:           }
756:           numbering->updatePoint(patch, *l_iter, &val);
757:         }
758:         numbering->setLocalSize(localSize);
759:       };
760:       // Order all local points
761:       //   points in the overlap are only ordered by the owner with the lowest rank
762:       template<typename Sequence, typename Atlas>
763:       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) {
764:         int localSize = 0;

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

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

774:             for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
775:               if (*p_iter < minRank) minRank = *p_iter;
776:             }
777:             if (minRank < sendOverlap->commRank()) {
778:               val = this->_unknownOrder;
779:             } else {
780:               val.prefix = localSize;
781:               val.index  = atlas->restrict(patch, *l_iter)[0].prefix;
782:             }
783:           } else {
784:             val.prefix = localSize;
785:             val.index  = atlas->restrict(patch, *l_iter)[0].prefix;
786:           }
787:           localSize += std::max(0, val.index);
788:           order->updatePoint(patch, *l_iter, &val);
789:         }
790:         order->setLocalSize(localSize);
791:       };
792:       template<typename PointType, typename Atlas>
793:       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) {
794:         int localSize = 0;

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

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

804:             for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
805:               if (*p_iter < minRank) minRank = *p_iter;
806:             }
807:             if (minRank < sendOverlap->commRank()) {
808:               val = this->_unknownOrder;
809:             } else {
810:               val.prefix = localSize;
811:               val.index  = atlas->restrictPoint(patch, *l_iter)[0].prefix;
812:             }
813:           } else {
814:             val.prefix = localSize;
815:             val.index  = atlas->restrictPoint(patch, *l_iter)[0].prefix;
816:           }
817:           localSize += std::max(0, val.index);
818:           order->updatePoint(patch, *l_iter, &val);
819:         }
820:         order->setLocalSize(localSize);
821:       };
822:       // Calculate process offsets
823:       template<typename Numbering>
824:       void calculateOffsets(const Obj<Numbering>& numbering) {
825:         int  localSize = numbering->getLocalSize();
826:         int *offsets   = new int[numbering->commSize()+1];

828:         offsets[0] = 0;
829:         MPI_Allgather(&localSize, 1, MPI_INT, &(offsets[1]), 1, MPI_INT, numbering->comm());
830:         for(int p = 2; p <= numbering->commSize(); p++) {
831:           offsets[p] += offsets[p-1];
832:         }
833:         numbering->setGlobalOffsets(offsets);
834:         delete [] offsets;
835:       };
836:       // Update local offsets based upon process offsets
837:       template<typename Numbering, typename Sequence>
838:       void updateOrder(const Obj<Numbering>& numbering, const patch_type& patch, const Obj<Sequence>& points) {
839:         const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());

841:         for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
842:           if (numbering->isLocal(*l_iter)) {
843:             numbering->updateAddPoint(patch, *l_iter, &val);
844:           }
845:         }
846:       };
847:       template<typename Numbering, typename PointType>
848:       void updateOrder(const Obj<Numbering>& numbering, const patch_type& patch, const std::set<PointType>& points) {
849:         const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());

851:         for(typename std::set<PointType>::iterator l_iter = points.begin(); l_iter != points.end(); ++l_iter) {
852:           if (numbering->isLocal(*l_iter)) {
853:             numbering->updateAddPoint(patch, *l_iter, &val);
854:           }
855:         }
856:       };
857:       // Communicate numbers in the overlap
858:       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) {
859:         typedef dtopology_type topo_type;
860:         typedef typename ALE::Field<send_overlap_type, int, ALE::Section<point_type, value_type> > send_section_type;
861:         typedef typename ALE::Field<recv_overlap_type, int, ALE::Section<point_type, value_type> > recv_section_type;
862:         typedef typename ALECompat::New::OldConstantSection<topology_type, int> constant_sizer;
863:         const Obj<send_section_type> sendSection = new send_section_type(numbering->comm(), this->debug());
864:         const Obj<recv_section_type> recvSection = new recv_section_type(numbering->comm(), sendSection->getTag(), this->debug());
865:         //const Obj<constant_sizer>    sizer       = new constant_sizer(numbering->comm(), 1, this->debug());

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

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

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

878:             if (recvSection->getFiberDimension(rPatch, point) == 0) continue;
879:             if (values[0] >= 0) {
880:               if (numbering->isLocal(point) && !allowDuplicates) {
881:                 ostringstream msg;
882:                 msg << "["<<numbering->commRank()<<"]Multiple indices for point " << point << " from " << rPatch << " with index " << values[0];
883:                 throw ALE::Exception(msg.str().c_str());
884:               }
885:               if (numbering->getAtlas()->getFiberDimension(0, point) == 0) {
886:                 ostringstream msg;
887:                 msg << "["<<numbering->commRank()<<"]Unexpected point " << point << " from " << rPatch << " with index " << values[0];
888:                 throw ALE::Exception(msg.str().c_str());
889:               }
890:               int val = -(values[0]+1);
891:               numbering->updatePoint(patch, point, &val);
892:             }
893:           }
894:         }
895: #if 0
896:         Obj<typename recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();

898:         for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
899:           numbering->setFiberDimension(0, *r_iter, 1);
900:         }
901:         for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
902:           const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
903: 
904:           for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != recvPatches->end(); ++p_iter) {
905:             const typename recv_section_type::value_type *values = recvSection->restrict(*p_iter, *r_iter);

907:             if (values[0] >= 0) {
908:               if (numbering->isLocal(*r_iter) && !allowDuplicates) {
909:                 ostringstream msg;
910:                 msg << "["<<numbering->commRank()<<"]Multiple indices for point " << *r_iter << " from " << *p_iter << " with index " << values[0];
911:                 throw ALE::Exception(msg.str().c_str());
912:               }
913:               if (numbering->getAtlas()->getFiberDimension(0, *r_iter) == 0) {
914:                 ostringstream msg;
915:                 msg << "["<<numbering->commRank()<<"]Unexpected point " << *r_iter << " from " << *p_iter << " with index " << values[0];
916:                 throw ALE::Exception(msg.str().c_str());
917:               }
918:               int val = -(values[0]+1);
919:               numbering->updatePoint(patch, *r_iter, &val);
920:             }
921:           }
922:         }
923: #endif
924:       };
925:       // Communicate (size,offset)s in the overlap
926:       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) {
927:         typedef dtopology_type topo_type;
928:         typedef typename ALECompat::New::OverlapValues<send_overlap_type, topo_type, oValue_type> send_section_type;
929:         typedef typename ALECompat::New::OverlapValues<recv_overlap_type, topo_type, oValue_type> recv_section_type;
930:         typedef typename ALECompat::New::OldConstantSection<topology_type, int> constant_sizer;
931:         const Obj<send_section_type> sendSection = new send_section_type(order->comm(), this->debug());
932:         const Obj<recv_section_type> recvSection = new recv_section_type(order->comm(), sendSection->getTag(), this->debug());
933:         const Obj<constant_sizer>    sizer       = new constant_sizer(order->comm(), 1, this->debug());

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

938:         for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
939:           if (!order->hasPoint(patch, *r_iter)) {
940:             order->setFiberDimension(patch, *r_iter, 1);
941:             order->updatePoint(patch, *r_iter, &this->_unknownOrder);
942:           }
943:         }
944:         for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
945:           const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
946: 
947:           for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != recvPatches->end(); ++p_iter) {
948:             const typename recv_section_type::value_type *values = recvSection->restrict(*p_iter, *r_iter);

950:             if (values[0].index == 0) continue;
951:             if (values[0].prefix >= 0) {
952:               if (order->isLocal(*r_iter)) {
953:                 if (!allowDuplicates) {
954:                   ostringstream msg;
955:                   msg << "["<<order->commRank()<<"]Multiple indices for point " << *r_iter << " from " << *p_iter << " with index " << values[0];
956:                   throw ALE::Exception(msg.str().c_str());
957:                 }
958:                 continue;
959:               }
960:               const oValue_type val(-(values[0].prefix+1), values[0].index);
961:               order->updatePoint(patch, *r_iter, &val);
962:             } else {
963:               if (order->isLocal(*r_iter)) continue;
964:               order->updatePoint(patch, *r_iter, values);
965:             }
966:           }
967:         }
968:       };
969:       // Construct a full global numbering
970:       template<typename Sequence>
971:       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) {
972:         this->constructLocalNumbering(numbering, sendOverlap, patch, points);
973:         this->calculateOffsets(numbering);
974:         this->updateOrder(numbering, patch, points);
975:         this->complete(numbering, sendOverlap, recvOverlap, patch);
976:       };
977:       // Construct a full global order
978:       template<typename Sequence, typename Atlas>
979:       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) {
980:         this->constructLocalOrder(order, sendOverlap, patch, points, atlas);
981:         this->calculateOffsets(order);
982:         this->updateOrder(order, patch, points);
983:         this->completeOrder(order, sendOverlap, recvOverlap, patch);
984:       };
985:       template<typename PointType, typename Atlas>
986:       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) {
987:         this->constructLocalOrder(order, sendOverlap, patch, points, atlas);
988:         this->calculateOffsets(order);
989:         this->updateOrder(order, patch, points);
990:         this->completeOrder(order, sendOverlap, recvOverlap, patch);
991:       };
992:       // Construct the inverse map from numbers to points
993:       //   If we really need this, then we should consider using a label
994:       void constructInverseOrder(const Obj<numbering_type>& numbering) {
995:         const typename numbering_type::chart_type& patch = numbering->getAtlas()->getPatch(0);

997:         for(typename numbering_type::chart_type::iterator p_iter = patch.begin(); p_iter != patch.end(); ++p_iter) {
998:           numbering->setPoint(numbering->getIndex(*p_iter), *p_iter);
999:         }
1000:       };
1001:     public:
1002:       const Obj<numbering_type>& getLocalNumbering(const Obj<topology_type>& topology, const patch_type& patch, const int depth) {
1003:         if ((this->_localNumberings.find(topology.ptr()) == this->_localNumberings.end()) ||
1004:             (this->_localNumberings[topology.ptr()].find(patch) == this->_localNumberings[topology.ptr()].end()) ||
1005:             (this->_localNumberings[topology.ptr()][patch].find(depth) == this->_localNumberings[topology.ptr()][patch].end())) {
1006:           Obj<numbering_type>    numbering   = new numbering_type(topology);
1007:           // These go in the Topology soon
1008:           Obj<send_overlap_type> sendOverlap = new send_overlap_type(topology->comm(), topology->debug());
1009:           //Obj<recv_overlap_type> recvOverlap = new recv_overlap_type(this->comm(), this->debug());

1011:           this->constructLocalNumbering(numbering, sendOverlap, patch, topology->getLabelStratum(patch, "depth", depth));
1012:           if (this->_debug) {std::cout << "Creating new local numbering: patch " << patch << " depth " << depth << std::endl;}
1013:           this->_localNumberings[topology.ptr()][patch][depth] = numbering;
1014:         }
1015:         return this->_localNumberings[topology.ptr()][patch][depth];
1016:       };
1017:       const Obj<numbering_type>& getNumbering(const Obj<topology_type>& topology, const patch_type& patch, const int depth) {
1018:         if ((this->_numberings.find(topology.ptr()) == this->_numberings.end()) ||
1019:             (this->_numberings[topology.ptr()].find(patch) == this->_numberings[topology.ptr()].end()) ||
1020:             (this->_numberings[topology.ptr()][patch].find(depth) == this->_numberings[topology.ptr()][patch].end())) {
1021:           topology->constructOverlap(patch);
1022:           Obj<numbering_type>    numbering   = new numbering_type(topology);
1023:           Obj<send_overlap_type> sendOverlap = topology->getSendOverlap();
1024:           Obj<recv_overlap_type> recvOverlap = topology->getRecvOverlap();

1026:           this->construct(numbering, sendOverlap, recvOverlap, patch, topology->getLabelStratum(patch, "depth", depth));
1027:           if (this->_debug) {std::cout << "Creating new numbering: patch " << patch << " depth " << depth << std::endl;}
1028:           this->_numberings[topology.ptr()][patch][depth] = numbering;
1029:         }
1030:         return this->_numberings[topology.ptr()][patch][depth];
1031:       };
1032:       template<typename Atlas>
1033:       const Obj<order_type>& getGlobalOrder(const Obj<topology_type>& topology, const patch_type& patch, const std::string& name, const Obj<Atlas>& atlas) {
1034:         if ((this->_orders.find(topology.ptr()) == this->_orders.end()) ||
1035:             (this->_orders[topology.ptr()].find(patch) == this->_orders[topology.ptr()].end()) ||
1036:             (this->_orders[topology.ptr()][patch].find(name) == this->_orders[topology.ptr()][patch].end())) {
1037:           topology->constructOverlap(patch);
1038:           Obj<order_type>        order       = new order_type(topology);
1039:           Obj<send_overlap_type> sendOverlap = topology->getSendOverlap();
1040:           Obj<recv_overlap_type> recvOverlap = topology->getRecvOverlap();

1042:           this->constructOrder(order, sendOverlap, recvOverlap, patch, atlas->getPatch(patch), atlas);
1043:           //this->constructOrder(order, sendOverlap, recvOverlap, patch, topology->depthStratum(patch, 0), atlas);
1044:           if (this->_debug) {std::cout << "Creating new global order: patch " << patch << " name " << name << std::endl;}
1045:           this->_orders[topology.ptr()][patch][name] = order;
1046:         }
1047:         return this->_orders[topology.ptr()][patch][name];
1048:       };
1049:     };
1050:   }
1051: }
1052: #endif