Actual source code: Numbering.hh
1: #ifndef included_ALE_Numbering_hh
2: #define included_ALE_Numbering_hh
4: #ifndef included_ALE_SectionCompletion_hh
5: #include <SectionCompletion.hh>
6: #endif
9: namespace ALE {
10: // We have a dichotomy between \emph{types}, describing the structure of objects,
11: // and \emph{concepts}, describing the role these objects play in the algorithm.
12: // Below we identify concepts with potential implementing types.
13: //
14: // Concept Type
15: // ------- ----
16: // Overlap Sifter
17: // Atlas ConstantSection, UniformSection
18: // Numbering UniformSection
19: // GlobalOrder UniformSection
20: //
21: // We will use factory types to create objects which satisfy a given concept.
22: template<typename Point_, typename Value_ = int, typename Alloc_ = std::allocator<Point_> >
23: class Numbering : public UniformSection<Point_, Value_, 1, Alloc_> {
24: public:
25: typedef UniformSection<Point_, Value_, 1, Alloc_> base_type;
26: typedef typename base_type::point_type point_type;
27: typedef typename base_type::value_type value_type;
28: typedef typename base_type::atlas_type atlas_type;
29: protected:
30: int _localSize;
31: int *_offsets;
32: std::map<int, point_type> _invOrder;
33: public:
34: Numbering(MPI_Comm comm, const int debug = 0) : UniformSection<Point_, Value_, 1, Alloc_>(comm, debug), _localSize(0) {
35: this->_offsets = new int[this->commSize()+1];
36: this->_offsets[0] = 0;
37: };
38: virtual ~Numbering() {
39: delete [] this->_offsets;
40: };
41: public: // Sizes
42: int getLocalSize() const {return this->_localSize;};
43: void setLocalSize(const int size) {this->_localSize = size;};
44: int getGlobalSize() const {return this->_offsets[this->commSize()];};
45: int getGlobalOffset(const int p) const {return this->_offsets[p];};
46: const int *getGlobalOffsets() const {return this->_offsets;};
47: void setGlobalOffsets(const int offsets[]) {
48: for(int p = 0; p <= this->commSize(); ++p) {
49: this->_offsets[p] = offsets[p];
50: }
51: };
52: public: // Indices
53: virtual int getIndex(const point_type& point) {
54: const value_type& idx = this->restrictPoint(point)[0];
55: if (idx >= 0) {
56: return idx;
57: }
58: return -(idx+1);
59: };
60: virtual void setIndex(const point_type& point, const int index) {this->updatePoint(point, &index);};
61: virtual bool isLocal(const point_type& point) {return this->restrictPoint(point)[0] >= 0;};
62: virtual bool isRemote(const point_type& point) {return this->restrictPoint(point)[0] < 0;};
63: point_type getPoint(const int& index) {return this->_invOrder[index];};
64: void setPoint(const int& index, const point_type& point) {this->_invOrder[index] = point;};
65: };
66: template<typename Point_, typename Value_ = ALE::Point>
67: class GlobalOrder : public UniformSection<Point_, Value_> {
68: public:
69: typedef UniformSection<Point_, Value_> base_type;
70: typedef typename base_type::point_type point_type;
71: typedef typename base_type::value_type value_type;
72: typedef typename base_type::atlas_type atlas_type;
73: protected:
74: int _localSize;
75: int *_offsets;
76: public:
77: GlobalOrder(MPI_Comm comm, const int debug = 0) : UniformSection<Point_, Value_>(comm, debug), _localSize(0) {
78: this->_offsets = new int[this->commSize()+1];
79: this->_offsets[0] = 0;
80: };
81: ~GlobalOrder() {
82: delete [] this->_offsets;
83: };
84: public: // Sizes
85: int getLocalSize() const {return this->_localSize;};
86: void setLocalSize(const int size) {this->_localSize = size;};
87: int getGlobalSize() const {return this->_offsets[this->commSize()];};
88: int getGlobalOffset(const int p) const {return this->_offsets[p];};
89: const int *getGlobalOffsets() const {return this->_offsets;};
90: void setGlobalOffsets(const int offsets[]) {
91: for(int p = 0; p <= this->commSize(); ++p) {
92: this->_offsets[p] = offsets[p];
93: }
94: };
95: public: // Indices
96: virtual int getIndex(const point_type& p) {
97: const int idx = this->restrictPoint(p)[0].prefix;
98: if (idx >= 0) {
99: return idx;
100: }
101: return -(idx+1);
102: };
103: virtual void setIndex(const point_type& p, const int index) {
104: const value_type idx(index, this->restrictPoint(p)[0].index);
105: this->updatePoint(p, &idx);
106: };
107: virtual bool isLocal(const point_type& p) {return this->restrictPoint(p)[0].prefix >= 0;};
108: virtual bool isRemote(const point_type& p) {return this->restrictPoint(p)[0].prefix < 0;};
109: };
110: template<typename Bundle_, typename Value_ = int, typename Alloc_ = typename Bundle_::alloc_type>
111: class NumberingFactory : ALE::ParallelObject {
112: public:
113: typedef Bundle_ bundle_type;
114: typedef Alloc_ alloc_type;
115: typedef typename bundle_type::sieve_type sieve_type;
116: typedef typename sieve_type::point_type point_type;
117: typedef Value_ value_type;
118: typedef typename alloc_type::template rebind<value_type>::other value_alloc_type;
119: typedef Numbering<point_type, value_type, alloc_type> numbering_type;
120: typedef std::map<bundle_type*, std::map<int, Obj<numbering_type> > > numberings_type;
121: typedef GlobalOrder<point_type> order_type;
122: typedef typename order_type::value_type oValue_type;
123: typedef typename alloc_type::template rebind<oValue_type>::other oValue_alloc_type;
124: typedef std::map<bundle_type*, std::map<std::string, Obj<order_type> > > orders_type;
125: typedef typename ALE::Sifter<int,point_type,point_type> send_overlap_type;
126: typedef typename ALE::Sifter<point_type,int,point_type> recv_overlap_type;
127: protected:
128: numberings_type _localNumberings;
129: numberings_type _numberings;
130: orders_type _orders;
131: const value_type _unknownNumber;
132: const oValue_type _unknownOrder;
133: protected:
134: NumberingFactory(MPI_Comm comm, const int debug = 0) : ALE::ParallelObject(comm, debug), _unknownNumber(-1), _unknownOrder(-1, 0) {};
135: public:
136: ~NumberingFactory() {};
137: public:
138: static const Obj<NumberingFactory>& singleton(MPI_Comm comm, const int debug, bool cleanup = false) {
139: static Obj<NumberingFactory> *_singleton = NULL;
141: if (cleanup) {
142: if (debug) {std::cout << "Destroying NumberingFactory" << std::endl;}
143: if (_singleton) {delete _singleton;}
144: _singleton = NULL;
145: } else if (_singleton == NULL) {
146: if (debug) {std::cout << "Creating new NumberingFactory" << std::endl;}
147: _singleton = new Obj<NumberingFactory>();
148: *_singleton = new NumberingFactory(comm, debug);
149: }
150: return *_singleton;
151: };
152: void clear() {
153: this->_localNumberings.clear();
154: this->_numberings.clear();
155: this->_orders.clear();
156: };
157: public: // Dof ordering
158: template<typename Section_>
159: void orderPointNew(const Obj<Section_>& section, const Obj<sieve_type>& sieve, const typename Section_::point_type& point, value_type& offset, value_type& bcOffset, const Obj<send_overlap_type>& sendOverlap = NULL) {
160: const typename Section_::chart_type& chart = section->getChart();
161: int& idx = section->getIndex(point);
163: // If the point does not exist in the chart, throw an error
164: if (chart.count(point) == 0) {
165: throw ALE::Exception("Unknown point in ordering");
166: }
167: // If the point has not been ordered
168: if (idx == -1) {
169: // Recurse to its cover
170: const Obj<typename sieve_type::coneSequence>& cone = sieve->cone(point);
171: typename sieve_type::coneSequence::iterator end = cone->end();
173: for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
174: if (this->_debug > 1) {std::cout << " Recursing to " << *c_iter << std::endl;}
175: this->orderPoint(section, sieve, *c_iter, offset, bcOffset, sendOverlap);
176: }
177: const int dim = section->getFiberDimension(point);
178: const int cDim = section->getConstraintDimension(point);
179: const int fDim = dim - cDim;
181: // If the point has constrained variables
182: if (cDim) {
183: if (this->_debug > 1) {std::cout << " Ordering boundary point " << point << " at " << bcOffset << std::endl;}
184: section->setIndexBC(point, bcOffset);
185: bcOffset += cDim;
186: }
187: // If the point has free variables
188: if (fDim) {
189: bool number = true;
191: // Maybe use template specialization here
192: if (!sendOverlap.isNull() && sendOverlap->capContains(point)) {
193: const Obj<typename send_overlap_type::supportSequence>& ranks = sendOverlap->support(point);
195: for(typename send_overlap_type::supportSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
196: if (this->commRank() > *r_iter) {
197: number = false;
198: break;
199: }
200: }
201: }
202: if (number) {
203: if (this->_debug > 1) {std::cout << " Ordering point " << point << " at " << offset << std::endl;}
204: section->setIndex(point, offset);
205: offset += dim;
206: } else {
207: if (this->_debug > 1) {std::cout << " Ignoring ghost point " << point << std::endl;}
208: }
209: }
210: }
211: };
212: template<typename Section_>
213: void orderPoint(const Obj<Section_>& section, const Obj<sieve_type>& sieve, const typename Section_::point_type& point, value_type& offset, value_type& bcOffset, const Obj<send_overlap_type>& sendOverlap = NULL) {
214: const Obj<typename Section_::atlas_type>& atlas = section->getAtlas();
215: const Obj<typename sieve_type::coneSequence>& cone = sieve->cone(point);
216: typename sieve_type::coneSequence::iterator end = cone->end();
217: typename Section_::index_type idx = section->getAtlas()->restrictPoint(point)[0];
218: const value_type& dim = idx.prefix;
219: const typename Section_::index_type defaultIdx(0, -1);
221: if (atlas->getChart().count(point) == 0) {
222: idx = defaultIdx;
223: }
224: if (idx.index == -1) {
225: for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
226: if (this->_debug > 1) {std::cout << " Recursing to " << *c_iter << std::endl;}
227: this->orderPoint(section, sieve, *c_iter, offset, bcOffset, sendOverlap);
228: }
229: if (dim > 0) {
230: bool number = true;
232: // Maybe use template specialization here
233: if (!sendOverlap.isNull() && sendOverlap->capContains(point)) {
234: const Obj<typename send_overlap_type::supportSequence>& ranks = sendOverlap->support(point);
236: for(typename send_overlap_type::supportSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
237: if (this->commRank() > *r_iter) {
238: number = false;
239: break;
240: }
241: }
242: }
243: if (number) {
244: if (this->_debug > 1) {std::cout << " Ordering point " << point << " at " << offset << std::endl;}
245: idx.index = offset;
246: atlas->updatePoint(point, &idx);
247: offset += dim;
248: } else {
249: if (this->_debug > 1) {std::cout << " Ignoring ghost point " << point << std::endl;}
250: }
251: } else if (dim < 0) {
252: if (this->_debug > 1) {std::cout << " Ordering boundary point " << point << " at " << bcOffset << std::endl;}
253: idx.index = bcOffset;
254: atlas->updatePoint(point, &idx);
255: bcOffset += dim;
256: }
257: }
258: };
259: template<typename Section_>
260: void orderPatch(const Obj<Section_>& section, const Obj<sieve_type>& sieve, const Obj<send_overlap_type>& sendOverlap = NULL, const value_type offset = 0, const value_type bcOffset = -2) {
261: const typename Section_::chart_type& chart = section->getChart();
262: int off = offset;
263: int bcOff = bcOffset;
265: if (this->_debug > 1) {std::cout << "Ordering patch" << std::endl;}
266: for(typename Section_::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
267: if (this->_debug > 1) {std::cout << "Ordering closure of point " << *p_iter << std::endl;}
268: this->orderPoint(section, sieve, *p_iter, off, bcOff, sendOverlap);
269: }
270: for(typename Section_::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
271: const int& idx = section->getIndex(*p_iter);
273: if (idx < 0) {
274: if (this->_debug > 1) {std::cout << "Correcting boundary offset of point " << *p_iter << std::endl;}
275: section->setIndex(*p_iter, off - (idx + 2));
276: }
277: }
278: };
279: public: // Numbering
280: // Number all local points
281: // points in the overlap are only numbered by the owner with the lowest rank
282: template<typename Sequence_>
283: void constructLocalNumbering(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const Obj<Sequence_>& points) {
284: int localSize = 0;
286: numbering->setFiberDimension(points, 1);
287: for(typename Sequence_::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
288: value_type val;
290: if (sendOverlap->capContains(*l_iter)) {
291: const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
292: int minRank = sendOverlap->commSize();
294: for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
295: if (*p_iter < minRank) minRank = *p_iter;
296: }
297: if (minRank < sendOverlap->commRank()) {
298: val = this->_unknownNumber;
299: } else {
300: val = localSize++;
301: }
302: } else {
303: val = localSize++;
304: }
305: numbering->updatePoint(*l_iter, &val);
306: }
307: numbering->setLocalSize(localSize);
308: };
309: // Order all local points
310: // points in the overlap are only ordered by the owner with the lowest rank
311: template<typename Sequence_, typename Section_>
312: void constructLocalOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<Sequence_>& points, const Obj<Section_>& section) {
313: int localSize = 0;
315: order->setFiberDimension(points, 1);
316: for(typename Sequence_::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
317: oValue_type val;
319: if (sendOverlap->capContains(*l_iter)) {
320: const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
321: int minRank = sendOverlap->commSize();
323: for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
324: if (*p_iter < minRank) minRank = *p_iter;
325: }
326: if (minRank < sendOverlap->commRank()) {
327: val = this->_unknownOrder;
328: } else {
329: val.prefix = localSize;
330: val.index = section->getConstrainedFiberDimension(*l_iter);
331: }
332: } else {
333: val.prefix = localSize;
334: val.index = section->getConstrainedFiberDimension(*l_iter);
335: }
336: localSize += val.index;
337: order->updatePoint(*l_iter, &val);
338: }
339: order->setLocalSize(localSize);
340: };
341: template<typename Point_, typename Section_>
342: void constructLocalOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const std::set<Point_>& points, const Obj<Section_>& section) {
343: int localSize = 0;
345: order->setFiberDimension(points, 1);
346: for(typename std::set<Point_>::iterator l_iter = points.begin(); l_iter != points.end(); ++l_iter) {
347: oValue_type val;
349: if (sendOverlap->capContains(*l_iter)) {
350: const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
351: int minRank = sendOverlap->commSize();
353: for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
354: if (*p_iter < minRank) minRank = *p_iter;
355: }
356: if (minRank < sendOverlap->commRank()) {
357: val = this->_unknownOrder;
358: } else {
359: val.prefix = localSize;
360: val.index = section->getConstrainedFiberDimension(*l_iter);
361: }
362: } else {
363: val.prefix = localSize;
364: val.index = section->getConstrainedFiberDimension(*l_iter);
365: }
366: localSize += val.index;
367: order->updatePoint(*l_iter, &val);
368: }
369: order->setLocalSize(localSize);
370: };
371: // Calculate process offsets
372: template<typename Numbering>
373: void calculateOffsets(const Obj<Numbering>& numbering) {
374: int localSize = numbering->getLocalSize();
375: int *offsets = new int[numbering->commSize()+1];
377: offsets[0] = 0;
378: MPI_Allgather(&localSize, 1, MPI_INT, &(offsets[1]), 1, MPI_INT, numbering->comm());
379: for(int p = 2; p <= numbering->commSize(); p++) {
380: offsets[p] += offsets[p-1];
381: }
382: numbering->setGlobalOffsets(offsets);
383: delete [] offsets;
384: };
385: // Update local offsets based upon process offsets
386: template<typename Numbering, typename Sequence>
387: void updateOrder(const Obj<Numbering>& numbering, const Obj<Sequence>& points) {
388: const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());
390: for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
391: if (numbering->isLocal(*l_iter)) {
392: numbering->updateAddPoint(*l_iter, &val);
393: }
394: }
395: };
396: template<typename Numbering, typename Point>
397: void updateOrder(const Obj<Numbering>& numbering, const std::set<Point>& points) {
398: const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());
400: for(typename std::set<Point>::iterator l_iter = points.begin(); l_iter != points.end(); ++l_iter) {
401: if (numbering->isLocal(*l_iter)) {
402: numbering->updateAddPoint(*l_iter, &val);
403: }
404: }
405: };
406: // Communicate numbers in the overlap
407: void completeNumbering(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, bool allowDuplicates = false) {
408: typedef Field<send_overlap_type, int, Section<point_type, value_type, value_alloc_type> > send_section_type;
409: typedef Field<recv_overlap_type, int, Section<point_type, value_type, value_alloc_type> > recv_section_type;
410: typedef typename ALE::DiscreteSieve<point_type, alloc_type> dsieve_type;
411: typedef typename ALE::Topology<int, dsieve_type, alloc_type> dtopology_type;
412: typedef typename ALE::New::SectionCompletion<dtopology_type, int, alloc_type> completion;
413: const Obj<send_section_type> sendSection = new send_section_type(numbering->comm(), this->debug());
414: const Obj<recv_section_type> recvSection = new recv_section_type(numbering->comm(), sendSection->getTag(), this->debug());
416: completion::completeSection(sendOverlap, recvOverlap, numbering->getAtlas(), numbering, sendSection, recvSection);
417: const typename recv_section_type::sheaf_type& patches = recvSection->getPatches();
419: for(typename recv_section_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
420: const typename recv_section_type::patch_type& rPatch = p_iter->first;
421: const Obj<typename recv_section_type::section_type>& section = recvSection->getSection(rPatch);
422: const typename recv_section_type::chart_type& points = section->getChart();
424: for(typename recv_section_type::chart_type::iterator r_iter = points.begin(); r_iter != points.end(); ++r_iter) {
425: const typename recv_section_type::point_type& point = *r_iter;
426: const typename recv_section_type::value_type *values = section->restrictPoint(point);
428: if (section->getFiberDimension(point) == 0) continue;
429: if (values[0] >= 0) {
430: if (numbering->isLocal(point) && !allowDuplicates) {
431: ostringstream msg;
432: msg << "["<<numbering->commRank()<<"]Multiple indices for point " << point << " from " << rPatch << " with index " << values[0];
433: throw ALE::Exception(msg.str().c_str());
434: }
435: if (numbering->getAtlas()->getFiberDimension(point) == 0) {
436: ostringstream msg;
437: msg << "["<<numbering->commRank()<<"]Unexpected point " << point << " from " << rPatch << " with index " << values[0];
438: throw ALE::Exception(msg.str().c_str());
439: }
440: int val = -(values[0]+1);
441: numbering->updatePoint(point, &val);
442: }
443: }
444: }
445: };
446: // Communicate (size,offset)s in the overlap
447: void completeOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, bool allowDuplicates = false) {
448: typedef Field<send_overlap_type, int, Section<point_type, oValue_type, oValue_alloc_type> > send_section_type;
449: typedef Field<recv_overlap_type, int, Section<point_type, oValue_type, oValue_alloc_type> > recv_section_type;
450: typedef ConstantSection<point_type, int, alloc_type> constant_sizer;
451: typedef typename ALE::DiscreteSieve<point_type, alloc_type> dsieve_type;
452: typedef typename ALE::Topology<int, dsieve_type, alloc_type> dtopology_type;
453: typedef typename ALE::New::SectionCompletion<dtopology_type, int, alloc_type> completion;
454: const Obj<send_section_type> sendSection = new send_section_type(order->comm(), this->debug());
455: const Obj<recv_section_type> recvSection = new recv_section_type(order->comm(), sendSection->getTag(), this->debug());
456: //const Obj<constant_sizer> sizer = new constant_sizer(order->comm(), 1, this->debug());
458: //completion::completeSection(sendOverlap, recvOverlap, sizer, order, sendSection, recvSection);
459: completion::completeSection(sendOverlap, recvOverlap, order->getAtlas(), order, sendSection, recvSection);
460: Obj<typename recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();
462: for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
463: if (!order->hasPoint(*r_iter)) {
464: order->setFiberDimension(*r_iter, 1);
465: order->updatePoint(*r_iter, &this->_unknownOrder);
466: }
467: }
468: for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
469: const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
470:
471: for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != recvPatches->end(); ++p_iter) {
472: const typename recv_section_type::value_type *values = recvSection->getSection(*p_iter)->restrictPoint(*r_iter);
474: if (recvSection->getSection(*p_iter)->getFiberDimension(*r_iter) == 0) continue;
475: if (values[0].index == 0) continue;
476: if (values[0].prefix >= 0) {
477: if (order->isLocal(*r_iter)) {
478: if (!allowDuplicates) {
479: ostringstream msg;
480: msg << "["<<order->commRank()<<"]Multiple indices for point " << *r_iter << " from " << *p_iter << " with index " << values[0];
481: throw ALE::Exception(msg.str().c_str());
482: }
483: continue;
484: }
485: const oValue_type val(-(values[0].prefix+1), values[0].index);
486: order->updatePoint(*r_iter, &val);
487: } else {
488: if (order->isLocal(*r_iter)) continue;
489: order->updatePoint(*r_iter, values);
490: }
491: }
492: }
493: };
494: // Construct a full global numbering
495: template<typename Sequence>
496: void constructNumbering(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const Obj<Sequence>& points) {
497: this->constructLocalNumbering(numbering, sendOverlap, points);
498: this->calculateOffsets(numbering);
499: this->updateOrder(numbering, points);
500: this->completeNumbering(numbering, sendOverlap, recvOverlap);
501: };
502: // Construct a full global order
503: template<typename Sequence, typename Section>
504: void constructOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const Obj<Sequence>& points, const Obj<Section>& section) {
505: this->constructLocalOrder(order, sendOverlap, points, section);
506: this->calculateOffsets(order);
507: this->updateOrder(order, points);
508: this->completeOrder(order, sendOverlap, recvOverlap);
509: };
510: template<typename PointType, typename Section>
511: void constructOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const std::set<PointType>& points, const Obj<Section>& section) {
512: this->constructLocalOrder(order, sendOverlap, points, section);
513: this->calculateOffsets(order);
514: this->updateOrder(order, points);
515: this->completeOrder(order, sendOverlap, recvOverlap);
516: };
517: public:
518: // Construct the inverse map from numbers to points
519: // If we really need this, then we should consider using a label
520: void constructInverseOrder(const Obj<numbering_type>& numbering) {
521: const typename numbering_type::chart_type& chart = numbering->getChart();
523: for(typename numbering_type::chart_type::iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
524: numbering->setPoint(numbering->getIndex(*p_iter), *p_iter);
525: }
526: };
527: public: // Real interface
528: template<typename ABundle_>
529: const Obj<numbering_type>& getLocalNumbering(const Obj<ABundle_>& bundle, const int depth) {
530: if ((this->_localNumberings.find(bundle.ptr()) == this->_localNumberings.end()) ||
531: (this->_localNumberings[bundle.ptr()].find(depth) == this->_localNumberings[bundle.ptr()].end())) {
532: Obj<numbering_type> numbering = new numbering_type(bundle->comm(), bundle->debug());
533: Obj<send_overlap_type> sendOverlap = new send_overlap_type(bundle->comm(), bundle->debug());
535: this->constructLocalNumbering(numbering, sendOverlap, bundle->depthStratum(depth));
536: if (this->_debug) {std::cout << "Creating new local numbering: depth " << depth << std::endl;}
537: this->_localNumberings[bundle.ptr()][depth] = numbering;
538: }
539: return this->_localNumberings[bundle.ptr()][depth];
540: };
541: template<typename ABundle_>
542: const Obj<numbering_type>& getNumbering(const Obj<ABundle_>& bundle, const int depth) {
543: if ((this->_numberings.find(bundle.ptr()) == this->_numberings.end()) ||
544: (this->_numberings[bundle.ptr()].find(depth) == this->_numberings[bundle.ptr()].end())) {
545: bundle->constructOverlap();
546: Obj<numbering_type> numbering = new numbering_type(bundle->comm(), bundle->debug());
547: Obj<send_overlap_type> sendOverlap = bundle->getSendOverlap();
548: Obj<recv_overlap_type> recvOverlap = bundle->getRecvOverlap();
550: this->constructNumbering(numbering, sendOverlap, recvOverlap, bundle->depthStratum(depth));
551: if (this->_debug) {std::cout << "Creating new numbering: depth " << depth << std::endl;}
552: this->_numberings[bundle.ptr()][depth] = numbering;
553: }
554: return this->_numberings[bundle.ptr()][depth];
555: };
556: template<typename ABundle_>
557: const Obj<numbering_type>& getNumbering(const Obj<ABundle_>& bundle, const std::string& labelname, const int value) {
558: if ((this->_numberings.find(bundle.ptr()) == this->_numberings.end()) ||
559: (this->_numberings[bundle.ptr()].find(value) == this->_numberings[bundle.ptr()].end())) {
560: bundle->constructOverlap();
561: Obj<numbering_type> numbering = new numbering_type(bundle->comm(), bundle->debug());
562: Obj<send_overlap_type> sendOverlap = bundle->getSendOverlap();
563: Obj<recv_overlap_type> recvOverlap = bundle->getRecvOverlap();
565: this->constructNumbering(numbering, sendOverlap, recvOverlap, bundle->getLabelStratum(labelname, value));
566: if (this->_debug) {std::cout << "Creating new numbering: labelname " << labelname << " value " << value << std::endl;}
567: this->_numberings[bundle.ptr()][value] = numbering;
568: }
569: return this->_numberings[bundle.ptr()][value];
570: };
571: template<typename ABundle_, typename Section_>
572: const Obj<order_type>& getGlobalOrder(const Obj<ABundle_>& bundle, const std::string& name, const Obj<Section_>& section) {
573: if ((this->_orders.find(bundle.ptr()) == this->_orders.end()) ||
574: (this->_orders[bundle.ptr()].find(name) == this->_orders[bundle.ptr()].end())) {
575: bundle->constructOverlap();
576: Obj<order_type> order = new order_type(bundle->comm(), bundle->debug());
577: Obj<send_overlap_type> sendOverlap = bundle->getSendOverlap();
578: Obj<recv_overlap_type> recvOverlap = bundle->getRecvOverlap();
580: this->constructOrder(order, sendOverlap, recvOverlap, section->getChart(), section);
581: if (this->_debug) {std::cout << "Creating new global order: name " << name << std::endl;}
582: this->_orders[bundle.ptr()][name] = order;
583: }
584: return this->_orders[bundle.ptr()][name];
585: };
586: };
587: }
589: namespace ALECompat {
590: namespace New {
591: template<typename Topology_, typename Value_ = int>
592: class NewNumbering : public UniformSection<Topology_, Value_> {
593: public:
594: typedef UniformSection<Topology_, Value_> base_type;
595: typedef Topology_ topology_type;
596: typedef Value_ value_type;
597: typedef typename topology_type::patch_type patch_type;
598: typedef typename topology_type::point_type point_type;
599: typedef typename base_type::atlas_type atlas_type;
600: protected:
601: int _localSize;
602: int *_offsets;
603: std::map<int, point_type> _invOrder;
604: public:
605: NewNumbering(const Obj<topology_type>& topology) : UniformSection<Topology_, Value_>(topology), _localSize(0) {
606: this->_offsets = new int[this->commSize()+1];
607: this->_offsets[0] = 0;
608: };
609: ~NewNumbering() {
610: delete [] this->_offsets;
611: };
612: public: // Sizes
613: int getLocalSize() const {return this->_localSize;};
614: void setLocalSize(const int size) {this->_localSize = size;};
615: int getGlobalSize() const {return this->_offsets[this->commSize()];};
616: int getGlobalOffset(const int p) const {return this->_offsets[p];};
617: const int *getGlobalOffsets() const {return this->_offsets;};
618: void setGlobalOffsets(const int offsets[]) {
619: for(int p = 0; p <= this->commSize(); ++p) {
620: this->_offsets[p] = offsets[p];
621: }
622: };
623: public: // Indices
624: virtual int getIndex(const point_type& point) {
625: return getIndex(0, point);
626: };
627: virtual int getIndex(const patch_type& patch, const point_type& point) {
628: const value_type& idx = this->restrictPoint(patch, point)[0];
629: if (idx >= 0) {
630: return idx;
631: }
632: return -(idx+1);
633: };
634: virtual void setIndex(const point_type& point, const int index) {this->updatePoint(0, point, &index);};
635: virtual bool isLocal(const point_type& point) {return this->restrictPoint(0, point)[0] >= 0;};
636: virtual bool isRemote(const point_type& point) {return this->restrictPoint(0, point)[0] < 0;};
637: point_type getPoint(const int& index) {return this->_invOrder[index];};
638: void setPoint(const int& index, const point_type& point) {this->_invOrder[index] = point;};
639: };
641: template<typename Topology_>
642: class NewGlobalOrder : public UniformSection<Topology_, ALE::Point> {
643: public:
644: typedef UniformSection<Topology_, ALE::Point> base_type;
645: typedef Topology_ topology_type;
646: typedef ALE::Point value_type;
647: typedef typename topology_type::patch_type patch_type;
648: typedef typename topology_type::point_type point_type;
649: typedef typename base_type::atlas_type atlas_type;
650: protected:
651: int _localSize;
652: int *_offsets;
653: //std::map<int, point_type> _invOrder;
654: public:
655: NewGlobalOrder(const Obj<topology_type>& topology) : UniformSection<Topology_, ALE::Point>(topology), _localSize(0) {
656: this->_offsets = new int[this->commSize()+1];
657: this->_offsets[0] = 0;
658: };
659: ~NewGlobalOrder() {
660: delete [] this->_offsets;
661: };
662: public: // Sizes
663: int getLocalSize() const {return this->_localSize;};
664: void setLocalSize(const int size) {this->_localSize = size;};
665: int getGlobalSize() const {return this->_offsets[this->commSize()];};
666: int getGlobalOffset(const int p) const {return this->_offsets[p];};
667: const int *getGlobalOffsets() const {return this->_offsets;};
668: void setGlobalOffsets(const int offsets[]) {
669: for(int p = 0; p <= this->commSize(); ++p) {
670: this->_offsets[p] = offsets[p];
671: }
672: };
673: public: // Indices
674: virtual int getIndex(const point_type& point) {
675: return getIndex(0, point);
676: };
677: virtual int getIndex(const patch_type& patch, const point_type& point) {
678: if (this->restrictPoint(0, point)[0].prefix >= 0) {
679: return this->restrictPoint(0, point)[0].prefix;
680: }
681: return -(this->restrictPoint(0, point)[0].prefix+1);
682: };
683: virtual void setIndex(const point_type& point, const int index) {
684: const value_type idx(index, this->restrictPoint(0, point)[0].index);
685: this->updatePoint(0, point, &idx);
686: };
687: virtual bool isLocal(const point_type& point) {return this->restrictPoint(0, point)[0].prefix >= 0;};
688: virtual bool isRemote(const point_type& point) {return this->restrictPoint(0, point)[0].prefix < 0;};
689: };
691: // We have a dichotomy between \emph{types}, describing the structure of objects,
692: // and \emph{concepts}, describing the role these objects play in the algorithm.
693: // Below we identify concepts with potential implementing types.
694: //
695: // Concept Type
696: // ------- ----
697: // Overlap Sifter
698: // Atlas ConstantSection, UniformSection
699: // Numbering UniformSection
700: // GlobalOrder UniformSection
701: //
702: // We will use factory types to create objects which satisfy a given concept.
703: template<typename Topology_, typename Value_ = int>
704: class NumberingFactory {
705: public:
706: typedef Topology_ topology_type;
707: typedef Value_ value_type;
708: typedef typename topology_type::point_type point_type;
709: typedef typename ALE::DiscreteSieve<point_type> dsieve_type;
710: typedef typename ALE::Topology<int, dsieve_type> dtopology_type;
711: typedef typename topology_type::patch_type patch_type;
712: typedef typename topology_type::send_overlap_type send_overlap_type;
713: typedef typename topology_type::recv_overlap_type recv_overlap_type;
714: typedef typename ALECompat::New::NewNumbering<topology_type, value_type> numbering_type;
715: typedef std::map<int, Obj<numbering_type> > depthMap_type;
716: typedef std::map<patch_type, depthMap_type> patchMap_type;
717: typedef std::map<topology_type*, patchMap_type> numberings_type;
718: typedef typename ALECompat::New::NewGlobalOrder<topology_type> order_type;
719: typedef std::map<std::string, Obj<order_type> > sectionMap_type;
720: typedef std::map<patch_type, sectionMap_type> oPatchMap_type;
721: typedef std::map<topology_type*, oPatchMap_type> orders_type;
722: typedef typename order_type::value_type oValue_type;
723: typedef typename ALECompat::New::SectionCompletion<topology_type, int> completion;
724: protected:
725: int _debug;
726: numberings_type _localNumberings;
727: numberings_type _numberings;
728: orders_type _orders;
729: value_type _unknownNumber;
730: ALE::Point _unknownOrder;
731: protected:
732: NumberingFactory(const int debug) : _debug(debug), _unknownNumber(-1), _unknownOrder(-1, 0) {};
733: public:
734: ~NumberingFactory() {};
735: public:
736: static const Obj<NumberingFactory>& singleton(const int debug, bool cleanup = false) {
737: static Obj<NumberingFactory> *_singleton = NULL;
739: if (cleanup) {
740: if (debug) {std::cout << "Destroying NumberingFactory" << std::endl;}
741: if (_singleton) {delete _singleton;}
742: _singleton = NULL;
743: } else if (_singleton == NULL) {
744: if (debug) {std::cout << "Creating new NumberingFactory" << std::endl;}
745: _singleton = new Obj<NumberingFactory>();
746: *_singleton = new NumberingFactory(debug);
747: }
748: return *_singleton;
749: };
750: public:
751: const int debug() {return this->_debug;};
752: const int setDebug(const int debug) {return this->_debug = debug;};
753: public:
754: // Number all local points
755: // points in the overlap are only numbered by the owner with the lowest rank
756: template<typename Sequence>
757: void constructLocalNumbering(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const patch_type& patch, const Obj<Sequence>& points) {
758: int localSize = 0;
760: numbering->setFiberDimension(patch, points, 1);
761: for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
762: value_type val;
764: if (sendOverlap->capContains(*l_iter)) {
765: const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
766: int minRank = sendOverlap->commSize();
768: for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
769: if (*p_iter < minRank) minRank = *p_iter;
770: }
771: if (minRank < sendOverlap->commRank()) {
772: val = this->_unknownNumber;
773: } else {
774: val = localSize++;
775: }
776: } else {
777: val = localSize++;
778: }
779: numbering->updatePoint(patch, *l_iter, &val);
780: }
781: numbering->setLocalSize(localSize);
782: };
783: // Order all local points
784: // points in the overlap are only ordered by the owner with the lowest rank
785: template<typename Sequence, typename Atlas>
786: void constructLocalOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const patch_type& patch, const Obj<Sequence>& points, const Obj<Atlas>& atlas) {
787: int localSize = 0;
789: order->setFiberDimension(patch, points, 1);
790: for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
791: oValue_type val;
793: if (sendOverlap->capContains(*l_iter)) {
794: const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
795: int minRank = sendOverlap->commSize();
797: for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
798: if (*p_iter < minRank) minRank = *p_iter;
799: }
800: if (minRank < sendOverlap->commRank()) {
801: val = this->_unknownOrder;
802: } else {
803: val.prefix = localSize;
804: val.index = atlas->restrict(patch, *l_iter)[0].prefix;
805: }
806: } else {
807: val.prefix = localSize;
808: val.index = atlas->restrict(patch, *l_iter)[0].prefix;
809: }
810: localSize += std::max(0, val.index);
811: order->updatePoint(patch, *l_iter, &val);
812: }
813: order->setLocalSize(localSize);
814: };
815: template<typename PointType, typename Atlas>
816: void constructLocalOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const patch_type& patch, const std::set<PointType>& points, const Obj<Atlas>& atlas) {
817: int localSize = 0;
819: order->setFiberDimension(patch, points, 1);
820: for(typename std::set<PointType>::iterator l_iter = points.begin(); l_iter != points.end(); ++l_iter) {
821: oValue_type val;
823: if (sendOverlap->capContains(*l_iter)) {
824: const Obj<typename send_overlap_type::traits::supportSequence>& sendPatches = sendOverlap->support(*l_iter);
825: int minRank = sendOverlap->commSize();
827: for(typename send_overlap_type::traits::supportSequence::iterator p_iter = sendPatches->begin(); p_iter != sendPatches->end(); ++p_iter) {
828: if (*p_iter < minRank) minRank = *p_iter;
829: }
830: if (minRank < sendOverlap->commRank()) {
831: val = this->_unknownOrder;
832: } else {
833: val.prefix = localSize;
834: val.index = atlas->restrictPoint(patch, *l_iter)[0].prefix;
835: }
836: } else {
837: val.prefix = localSize;
838: val.index = atlas->restrictPoint(patch, *l_iter)[0].prefix;
839: }
840: localSize += std::max(0, val.index);
841: order->updatePoint(patch, *l_iter, &val);
842: }
843: order->setLocalSize(localSize);
844: };
845: // Calculate process offsets
846: template<typename Numbering>
847: void calculateOffsets(const Obj<Numbering>& numbering) {
848: int localSize = numbering->getLocalSize();
849: int *offsets = new int[numbering->commSize()+1];
851: offsets[0] = 0;
852: MPI_Allgather(&localSize, 1, MPI_INT, &(offsets[1]), 1, MPI_INT, numbering->comm());
853: for(int p = 2; p <= numbering->commSize(); p++) {
854: offsets[p] += offsets[p-1];
855: }
856: numbering->setGlobalOffsets(offsets);
857: delete [] offsets;
858: };
859: // Update local offsets based upon process offsets
860: template<typename Numbering, typename Sequence>
861: void updateOrder(const Obj<Numbering>& numbering, const patch_type& patch, const Obj<Sequence>& points) {
862: const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());
864: for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
865: if (numbering->isLocal(*l_iter)) {
866: numbering->updateAddPoint(patch, *l_iter, &val);
867: }
868: }
869: };
870: template<typename Numbering, typename PointType>
871: void updateOrder(const Obj<Numbering>& numbering, const patch_type& patch, const std::set<PointType>& points) {
872: const typename Numbering::value_type val = numbering->getGlobalOffset(numbering->commRank());
874: for(typename std::set<PointType>::iterator l_iter = points.begin(); l_iter != points.end(); ++l_iter) {
875: if (numbering->isLocal(*l_iter)) {
876: numbering->updateAddPoint(patch, *l_iter, &val);
877: }
878: }
879: };
880: // Communicate numbers in the overlap
881: void complete(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const patch_type& patch, bool allowDuplicates = false) {
882: typedef dtopology_type topo_type;
883: typedef typename ALE::Field<send_overlap_type, int, ALE::Section<point_type, value_type> > send_section_type;
884: typedef typename ALE::Field<recv_overlap_type, int, ALE::Section<point_type, value_type> > recv_section_type;
885: typedef typename ALECompat::New::OldConstantSection<topology_type, int> constant_sizer;
886: const Obj<send_section_type> sendSection = new send_section_type(numbering->comm(), this->debug());
887: const Obj<recv_section_type> recvSection = new recv_section_type(numbering->comm(), sendSection->getTag(), this->debug());
888: //const Obj<constant_sizer> sizer = new constant_sizer(numbering->comm(), 1, this->debug());
890: completion::completeSection(sendOverlap, recvOverlap, numbering->getAtlas(), numbering, sendSection, recvSection);
891: const typename recv_section_type::topology_type::sheaf_type& patches = recvSection->getTopology()->getPatches();
893: for(typename recv_section_type::topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
894: const typename recv_section_type::patch_type& rPatch = p_iter->first;
895: const typename recv_section_type::chart_type& points = recvSection->getPatch(rPatch);
897: for(typename recv_section_type::chart_type::iterator r_iter = points.begin(); r_iter != points.end(); ++r_iter) {
898: const typename recv_section_type::point_type& point = *r_iter;
899: const typename recv_section_type::value_type *values = recvSection->restrictPoint(rPatch, point);
901: if (recvSection->getFiberDimension(rPatch, point) == 0) continue;
902: if (values[0] >= 0) {
903: if (numbering->isLocal(point) && !allowDuplicates) {
904: ostringstream msg;
905: msg << "["<<numbering->commRank()<<"]Multiple indices for point " << point << " from " << rPatch << " with index " << values[0];
906: throw ALE::Exception(msg.str().c_str());
907: }
908: if (numbering->getAtlas()->getFiberDimension(0, point) == 0) {
909: ostringstream msg;
910: msg << "["<<numbering->commRank()<<"]Unexpected point " << point << " from " << rPatch << " with index " << values[0];
911: throw ALE::Exception(msg.str().c_str());
912: }
913: int val = -(values[0]+1);
914: numbering->updatePoint(patch, point, &val);
915: }
916: }
917: }
918: #if 0
919: Obj<typename recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();
921: for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
922: numbering->setFiberDimension(0, *r_iter, 1);
923: }
924: for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
925: const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
926:
927: for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != recvPatches->end(); ++p_iter) {
928: const typename recv_section_type::value_type *values = recvSection->restrict(*p_iter, *r_iter);
930: if (values[0] >= 0) {
931: if (numbering->isLocal(*r_iter) && !allowDuplicates) {
932: ostringstream msg;
933: msg << "["<<numbering->commRank()<<"]Multiple indices for point " << *r_iter << " from " << *p_iter << " with index " << values[0];
934: throw ALE::Exception(msg.str().c_str());
935: }
936: if (numbering->getAtlas()->getFiberDimension(0, *r_iter) == 0) {
937: ostringstream msg;
938: msg << "["<<numbering->commRank()<<"]Unexpected point " << *r_iter << " from " << *p_iter << " with index " << values[0];
939: throw ALE::Exception(msg.str().c_str());
940: }
941: int val = -(values[0]+1);
942: numbering->updatePoint(patch, *r_iter, &val);
943: }
944: }
945: }
946: #endif
947: };
948: // Communicate (size,offset)s in the overlap
949: void completeOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const patch_type& patch, bool allowDuplicates = false) {
950: typedef dtopology_type topo_type;
951: typedef typename ALECompat::New::OverlapValues<send_overlap_type, topo_type, oValue_type> send_section_type;
952: typedef typename ALECompat::New::OverlapValues<recv_overlap_type, topo_type, oValue_type> recv_section_type;
953: typedef typename ALECompat::New::OldConstantSection<topology_type, int> constant_sizer;
954: const Obj<send_section_type> sendSection = new send_section_type(order->comm(), this->debug());
955: const Obj<recv_section_type> recvSection = new recv_section_type(order->comm(), sendSection->getTag(), this->debug());
956: const Obj<constant_sizer> sizer = new constant_sizer(order->comm(), 1, this->debug());
958: completion::completeSection(sendOverlap, recvOverlap, sizer, order, sendSection, recvSection);
959: Obj<typename recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();
961: for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
962: if (!order->hasPoint(patch, *r_iter)) {
963: order->setFiberDimension(patch, *r_iter, 1);
964: order->updatePoint(patch, *r_iter, &this->_unknownOrder);
965: }
966: }
967: for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
968: const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
969:
970: for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != recvPatches->end(); ++p_iter) {
971: const typename recv_section_type::value_type *values = recvSection->restrict(*p_iter, *r_iter);
973: if (values[0].index == 0) continue;
974: if (values[0].prefix >= 0) {
975: if (order->isLocal(*r_iter)) {
976: if (!allowDuplicates) {
977: ostringstream msg;
978: msg << "["<<order->commRank()<<"]Multiple indices for point " << *r_iter << " from " << *p_iter << " with index " << values[0];
979: throw ALE::Exception(msg.str().c_str());
980: }
981: continue;
982: }
983: const oValue_type val(-(values[0].prefix+1), values[0].index);
984: order->updatePoint(patch, *r_iter, &val);
985: } else {
986: if (order->isLocal(*r_iter)) continue;
987: order->updatePoint(patch, *r_iter, values);
988: }
989: }
990: }
991: };
992: // Construct a full global numbering
993: template<typename Sequence>
994: void construct(const Obj<numbering_type>& numbering, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const patch_type& patch, const Obj<Sequence>& points) {
995: this->constructLocalNumbering(numbering, sendOverlap, patch, points);
996: this->calculateOffsets(numbering);
997: this->updateOrder(numbering, patch, points);
998: this->complete(numbering, sendOverlap, recvOverlap, patch);
999: };
1000: // Construct a full global order
1001: template<typename Sequence, typename Atlas>
1002: void constructOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const patch_type& patch, const Obj<Sequence>& points, const Obj<Atlas>& atlas) {
1003: this->constructLocalOrder(order, sendOverlap, patch, points, atlas);
1004: this->calculateOffsets(order);
1005: this->updateOrder(order, patch, points);
1006: this->completeOrder(order, sendOverlap, recvOverlap, patch);
1007: };
1008: template<typename PointType, typename Atlas>
1009: void constructOrder(const Obj<order_type>& order, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const patch_type& patch, const std::set<PointType>& points, const Obj<Atlas>& atlas) {
1010: this->constructLocalOrder(order, sendOverlap, patch, points, atlas);
1011: this->calculateOffsets(order);
1012: this->updateOrder(order, patch, points);
1013: this->completeOrder(order, sendOverlap, recvOverlap, patch);
1014: };
1015: // Construct the inverse map from numbers to points
1016: // If we really need this, then we should consider using a label
1017: void constructInverseOrder(const Obj<numbering_type>& numbering) {
1018: const typename numbering_type::chart_type& patch = numbering->getAtlas()->getPatch(0);
1020: for(typename numbering_type::chart_type::iterator p_iter = patch.begin(); p_iter != patch.end(); ++p_iter) {
1021: numbering->setPoint(numbering->getIndex(*p_iter), *p_iter);
1022: }
1023: };
1024: public:
1025: const Obj<numbering_type>& getLocalNumbering(const Obj<topology_type>& topology, const patch_type& patch, const int depth) {
1026: if ((this->_localNumberings.find(topology.ptr()) == this->_localNumberings.end()) ||
1027: (this->_localNumberings[topology.ptr()].find(patch) == this->_localNumberings[topology.ptr()].end()) ||
1028: (this->_localNumberings[topology.ptr()][patch].find(depth) == this->_localNumberings[topology.ptr()][patch].end())) {
1029: Obj<numbering_type> numbering = new numbering_type(topology);
1030: // These go in the Topology soon
1031: Obj<send_overlap_type> sendOverlap = new send_overlap_type(topology->comm(), topology->debug());
1032: //Obj<recv_overlap_type> recvOverlap = new recv_overlap_type(this->comm(), this->debug());
1034: this->constructLocalNumbering(numbering, sendOverlap, patch, topology->getLabelStratum(patch, "depth", depth));
1035: if (this->_debug) {std::cout << "Creating new local numbering: patch " << patch << " depth " << depth << std::endl;}
1036: this->_localNumberings[topology.ptr()][patch][depth] = numbering;
1037: }
1038: return this->_localNumberings[topology.ptr()][patch][depth];
1039: };
1040: const Obj<numbering_type>& getNumbering(const Obj<topology_type>& topology, const patch_type& patch, const int depth) {
1041: if ((this->_numberings.find(topology.ptr()) == this->_numberings.end()) ||
1042: (this->_numberings[topology.ptr()].find(patch) == this->_numberings[topology.ptr()].end()) ||
1043: (this->_numberings[topology.ptr()][patch].find(depth) == this->_numberings[topology.ptr()][patch].end())) {
1044: topology->constructOverlap(patch);
1045: Obj<numbering_type> numbering = new numbering_type(topology);
1046: Obj<send_overlap_type> sendOverlap = topology->getSendOverlap();
1047: Obj<recv_overlap_type> recvOverlap = topology->getRecvOverlap();
1049: this->construct(numbering, sendOverlap, recvOverlap, patch, topology->getLabelStratum(patch, "depth", depth));
1050: if (this->_debug) {std::cout << "Creating new numbering: patch " << patch << " depth " << depth << std::endl;}
1051: this->_numberings[topology.ptr()][patch][depth] = numbering;
1052: }
1053: return this->_numberings[topology.ptr()][patch][depth];
1054: };
1055: template<typename Atlas>
1056: const Obj<order_type>& getGlobalOrder(const Obj<topology_type>& topology, const patch_type& patch, const std::string& name, const Obj<Atlas>& atlas) {
1057: if ((this->_orders.find(topology.ptr()) == this->_orders.end()) ||
1058: (this->_orders[topology.ptr()].find(patch) == this->_orders[topology.ptr()].end()) ||
1059: (this->_orders[topology.ptr()][patch].find(name) == this->_orders[topology.ptr()][patch].end())) {
1060: topology->constructOverlap(patch);
1061: Obj<order_type> order = new order_type(topology);
1062: Obj<send_overlap_type> sendOverlap = topology->getSendOverlap();
1063: Obj<recv_overlap_type> recvOverlap = topology->getRecvOverlap();
1065: this->constructOrder(order, sendOverlap, recvOverlap, patch, atlas->getPatch(patch), atlas);
1066: //this->constructOrder(order, sendOverlap, recvOverlap, patch, topology->depthStratum(patch, 0), atlas);
1067: if (this->_debug) {std::cout << "Creating new global order: patch " << patch << " name " << name << std::endl;}
1068: this->_orders[topology.ptr()][patch][name] = order;
1069: }
1070: return this->_orders[topology.ptr()][patch][name];
1071: };
1072: };
1073: }
1074: }
1075: #endif