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