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:     void clear() {
150:       this->_localNumberings.clear();
151:       this->_numberings.clear();
152:       this->_orders.clear();
153:     };
154:   public: // Dof ordering
155:     template<typename Section_>
156:     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) {
157:       const typename Section_::chart_type& chart = section->getChart();
158:       int&                                 idx   = section->getIndex(point);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

794:             for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
795:               if (*p_iter < minRank) minRank = *p_iter;
796:             }
797:             if (minRank < sendOverlap->commRank()) {
798:               val = this->_unknownOrder;
799:             } else {
800:               val.prefix = localSize;
801:               val.index  = atlas->restrict(patch, *l_iter)[0].prefix;
802:             }
803:           } else {
804:             val.prefix = localSize;
805:             val.index  = atlas->restrict(patch, *l_iter)[0].prefix;
806:           }
807:           localSize += std::max(0, val.index);
808:           order->updatePoint(patch, *l_iter, &val);
809:         }
810:         order->setLocalSize(localSize);
811:       };
812:       template<typename PointType, typename Atlas>
813:       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) {
814:         int localSize = 0;

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

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

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

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

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

871:         for(typename std::set<PointType>::iterator l_iter = points.begin(); l_iter != points.end(); ++l_iter) {
872:           if (numbering->isLocal(*l_iter)) {
873:             numbering->updateAddPoint(patch, *l_iter, &val);
874:           }
875:         }
876:       };
877:       // Communicate numbers in the overlap
878:       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) {
879:         typedef dtopology_type topo_type;
880:         typedef typename ALE::Field<send_overlap_type, int, ALE::Section<point_type, value_type> > send_section_type;
881:         typedef typename ALE::Field<recv_overlap_type, int, ALE::Section<point_type, value_type> > recv_section_type;
882:         typedef typename ALECompat::New::OldConstantSection<topology_type, int> constant_sizer;
883:         const Obj<send_section_type> sendSection = new send_section_type(numbering->comm(), this->debug());
884:         const Obj<recv_section_type> recvSection = new recv_section_type(numbering->comm(), sendSection->getTag(), this->debug());
885:         //const Obj<constant_sizer>    sizer       = new constant_sizer(numbering->comm(), 1, this->debug());

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

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

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

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

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

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

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

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

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

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

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

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

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