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