Actual source code: Field.hh
1: #ifndef included_ALE_Field_hh
2: #define included_ALE_Field_hh
4: #ifndef included_ALE_SieveAlgorithms_hh
5: #include <SieveAlgorithms.hh>
6: #endif
10: // Sieve need point_type
11: // Section need point_type and value_type
12: // size(), restrict(), update() need orientation which is a Bundle (circular)
13: // Bundle is Sieve+Section
15: // An AbstractSection is a mapping from Sieve points to sets of values
16: // This is our presentation of a section of a fibre bundle,
17: // in which the Topology is the base space, and
18: // the value sets are vectors in the fiber spaces
19: // The main interface to values is through restrict() and update()
20: // This retrieval uses Sieve closure()
21: // We should call these rawRestrict/rawUpdate
22: // The Section must also be able to set/report the dimension of each fiber
23: // for which we use another section we call an \emph{Atlas}
24: // For some storage schemes, we also want offsets to go with these dimensions
25: // We must have some way of limiting the points associated with values
26: // so each section must support a getPatch() call returning the points with associated fibers
27: // I was using the Chart for this
28: // The Section must be able to participate in \emph{completion}
29: // This means restrict to a provided overlap, and exchange in the restricted sections
30: // Completion does not use hierarchy, so we see the Topology as a DiscreteTopology
31: namespace ALE {
32: template<typename Point_, typename Alloc_ = std::allocator<Point_> >
33: class DiscreteSieve {
34: public:
35: typedef Point_ point_type;
36: typedef Alloc_ alloc_type;
37: typedef std::vector<point_type, alloc_type> coneSequence;
38: typedef std::vector<point_type, alloc_type> coneSet;
39: typedef std::vector<point_type, alloc_type> coneArray;
40: typedef std::vector<point_type, alloc_type> supportSequence;
41: typedef std::vector<point_type, alloc_type> supportSet;
42: typedef std::vector<point_type, alloc_type> supportArray;
43: typedef std::set<point_type, std::less<point_type>, alloc_type> points_type;
44: typedef points_type baseSequence;
45: typedef points_type capSequence;
46: typedef typename alloc_type::template rebind<points_type>::other points_alloc_type;
47: typedef typename points_alloc_type::pointer points_ptr;
48: typedef typename alloc_type::template rebind<coneSequence>::other coneSequence_alloc_type;
49: typedef typename coneSequence_alloc_type::pointer coneSequence_ptr;
50: protected:
51: Obj<points_type> _points;
52: Obj<coneSequence> _empty;
53: Obj<coneSequence> _return;
54: alloc_type _allocator;
55: void _init() {
56: points_ptr pPoints = points_alloc_type(this->_allocator).allocate(1);
57: points_alloc_type(this->_allocator).construct(pPoints, points_type());
58: this->_points = Obj<points_type>(pPoints, sizeof(points_type));
59: ///this->_points = new points_type();
60: coneSequence_ptr pEmpty = coneSequence_alloc_type(this->_allocator).allocate(1);
61: coneSequence_alloc_type(this->_allocator).construct(pEmpty, coneSequence());
62: this->_empty = Obj<coneSequence>(pEmpty, sizeof(coneSequence));
63: ///this->_empty = new coneSequence();
64: coneSequence_ptr pReturn = coneSequence_alloc_type(this->_allocator).allocate(1);
65: coneSequence_alloc_type(this->_allocator).construct(pReturn, coneSequence());
66: this->_return = Obj<coneSequence>(pReturn, sizeof(coneSequence));
67: ///this->_return = new coneSequence();
68: };
69: public:
70: DiscreteSieve() {
71: this->_init();
72: };
73: template<typename Input>
74: DiscreteSieve(const Obj<Input>& points) {
75: this->_init();
76: this->_points->insert(points->begin(), points->end());
77: };
78: virtual ~DiscreteSieve() {};
79: public:
80: void addPoint(const point_type& point) {
81: this->_points->insert(point);
82: };
83: template<typename Input>
84: void addPoints(const Obj<Input>& points) {
85: this->_points->insert(points->begin(), points->end());
86: };
87: const Obj<coneSequence>& cone(const point_type& p) {return this->_empty;};
88: template<typename Input>
89: const Obj<coneSequence>& cone(const Input& p) {return this->_empty;};
90: const Obj<coneSet>& nCone(const point_type& p, const int level) {
91: if (level == 0) {
92: return this->closure(p);
93: } else {
94: return this->_empty;
95: }
96: };
97: const Obj<coneArray>& closure(const point_type& p) {
98: this->_return->clear();
99: this->_return->push_back(p);
100: return this->_return;
101: };
102: const Obj<supportSequence>& support(const point_type& p) {return this->_empty;};
103: template<typename Input>
104: const Obj<supportSequence>& support(const Input& p) {return this->_empty;};
105: const Obj<supportSet>& nSupport(const point_type& p, const int level) {
106: if (level == 0) {
107: return this->star(p);
108: } else {
109: return this->_empty;
110: }
111: };
112: const Obj<supportArray>& star(const point_type& p) {
113: this->_return->clear();
114: this->_return->push_back(p);
115: return this->_return;
116: };
117: const Obj<capSequence>& roots() {return this->_points;};
118: const Obj<capSequence>& cap() {return this->_points;};
119: const Obj<baseSequence>& leaves() {return this->_points;};
120: const Obj<baseSequence>& base() {return this->_points;};
121: template<typename Color>
122: void addArrow(const point_type& p, const point_type& q, const Color& color) {
123: throw ALE::Exception("Cannot add an arrow to a DiscreteSieve");
124: };
125: void stratify() {};
126: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
127: ostringstream txt;
128: int rank;
130: if (comm == MPI_COMM_NULL) {
131: comm = MPI_COMM_SELF;
132: rank = 0;
133: } else {
134: MPI_Comm_rank(comm, &rank);
135: }
136: if (name == "") {
137: if(rank == 0) {
138: txt << "viewing a DiscreteSieve" << std::endl;
139: }
140: } else {
141: if(rank == 0) {
142: txt << "viewing DiscreteSieve '" << name << "'" << std::endl;
143: }
144: }
145: for(typename points_type::const_iterator p_iter = this->_points->begin(); p_iter != this->_points->end(); ++p_iter) {
146: txt << " Point " << *p_iter << std::endl;
147: }
148: PetscSynchronizedPrintf(comm, txt.str().c_str());
149: PetscSynchronizedFlush(comm);
150: };
151: };
152: // A ConstantSection is the simplest Section
153: // All fibers are dimension 1
154: // All values are equal to a constant
155: // We need no value storage and no communication for completion
156: template<typename Point_, typename Value_, typename Alloc_ = std::allocator<Point_> >
157: class ConstantSection : public ALE::ParallelObject {
158: public:
159: typedef Point_ point_type;
160: typedef Value_ value_type;
161: typedef Alloc_ alloc_type;
162: typedef std::set<point_type, std::less<point_type>, alloc_type> chart_type;
163: protected:
164: chart_type _chart;
165: value_type _value;
166: value_type _defaultValue;
167: public:
168: ConstantSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug), _defaultValue(0) {};
169: ConstantSection(MPI_Comm comm, const value_type& value, const int debug) : ParallelObject(comm, debug), _value(value), _defaultValue(value) {};
170: ConstantSection(MPI_Comm comm, const value_type& value, const value_type& defaultValue, const int debug) : ParallelObject(comm, debug), _value(value), _defaultValue(defaultValue) {};
171: public: // Verifiers
172: void checkPoint(const point_type& point) const {
173: if (this->_chart.find(point) == this->_chart.end()) {
174: ostringstream msg;
175: msg << "Invalid section point " << point << std::endl;
176: throw ALE::Exception(msg.str().c_str());
177: }
178: };
179: void checkDimension(const int& dim) {
180: if (dim != 1) {
181: ostringstream msg;
182: msg << "Invalid fiber dimension " << dim << " must be 1" << std::endl;
183: throw ALE::Exception(msg.str().c_str());
184: }
185: };
186: bool hasPoint(const point_type& point) const {
187: return this->_chart.count(point) > 0;
188: };
189: public: // Accessors
190: const chart_type& getChart() {return this->_chart;};
191: void addPoint(const point_type& point) {
192: this->_chart.insert(point);
193: };
194: template<typename Points>
195: void addPoint(const Obj<Points>& points) {
196: this->_chart.insert(points->begin(), points->end());
197: };
198: template<typename Points>
199: void addPoint(const Points& points) {
200: this->_chart.insert(points.begin(), points.end());
201: };
202: // void addPoint(const std::set<point_type>& points) {
203: // this->_chart.insert(points.begin(), points.end());
204: // };
205: value_type getDefaultValue() {return this->_defaultValue;};
206: void setDefaultValue(const value_type value) {this->_defaultValue = value;};
207: void copy(const Obj<ConstantSection>& section) {
208: const chart_type& chart = section->getChart();
210: this->addPoint(chart);
211: this->_value = section->restrict(*chart.begin())[0];
212: };
213: public: // Sizes
214: void clear() {
215: this->_chart.clear();
216: };
217: int getFiberDimension(const point_type& p) const {
218: if (this->hasPoint(p)) return 1;
219: return 0;
220: };
221: void setFiberDimension(const point_type& p, int dim) {
222: this->checkDimension(dim);
223: this->addPoint(p);
224: };
225: template<typename Sequence>
226: void setFiberDimension(const Obj<Sequence>& points, int dim) {
227: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
228: this->setFiberDimension(*p_iter, dim);
229: }
230: };
231: void addFiberDimension(const point_type& p, int dim) {
232: if (this->_chart.find(p) != this->_chart.end()) {
233: ostringstream msg;
234: msg << "Invalid addition to fiber dimension " << dim << " cannot exceed 1" << std::endl;
235: throw ALE::Exception(msg.str().c_str());
236: } else {
237: this->setFiberDimension(p, dim);
238: }
239: };
240: int size(const point_type& p) {return this->getFiberDimension(p);};
241: public: // Restriction
242: const value_type *restrict(const point_type& p) const {
243: if (this->hasPoint(p)) {
244: return &this->_value;
245: }
246: return &this->_defaultValue;
247: };
248: const value_type *restrictPoint(const point_type& p) const {return this->restrict(p);};
249: void update(const point_type& p, const value_type v[]) {
250: this->_value = v[0];
251: };
252: void updatePoint(const point_type& p, const value_type v[]) {return this->update(p, v);};
253: void updateAdd(const point_type& p, const value_type v[]) {
254: this->_value += v[0];
255: };
256: void updateAddPoint(const point_type& p, const value_type v[]) {return this->updateAdd(p, v);};
257: public:
258: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
259: ostringstream txt;
260: int rank;
262: if (comm == MPI_COMM_NULL) {
263: comm = this->comm();
264: rank = this->commRank();
265: } else {
266: MPI_Comm_rank(comm, &rank);
267: }
268: if (name == "") {
269: if(rank == 0) {
270: txt << "viewing a ConstantSection" << std::endl;
271: }
272: } else {
273: if(rank == 0) {
274: txt << "viewing ConstantSection '" << name << "'" << std::endl;
275: }
276: }
277: txt <<"["<<this->commRank()<<"]: Value " << this->_value << std::endl;
278: PetscSynchronizedPrintf(comm, txt.str().c_str());
279: PetscSynchronizedFlush(comm);
280: };
281: };
282: // A UniformSection often acts as an Atlas
283: // All fibers are the same dimension
284: // Note we can use a ConstantSection for this Atlas
285: // Each point may have a different vector
286: // Thus we need storage for values, and hence must implement completion
287: template<typename Point_, typename Value_, int fiberDim = 1, typename Alloc_ = std::allocator<Value_> >
288: class UniformSection : public ALE::ParallelObject {
289: public:
290: typedef Point_ point_type;
291: typedef Value_ value_type;
292: typedef Alloc_ alloc_type;
293: typedef typename alloc_type::template rebind<point_type>::other point_alloc_type;
294: typedef ConstantSection<point_type, int, point_alloc_type> atlas_type;
295: typedef typename atlas_type::chart_type chart_type;
296: typedef struct {value_type v[fiberDim];} fiber_type;
297: typedef typename alloc_type::template rebind<std::pair<const point_type, fiber_type> >::other pair_alloc_type;
298: typedef std::map<point_type, fiber_type, std::less<point_type>, pair_alloc_type> values_type;
299: typedef typename alloc_type::template rebind<atlas_type>::other atlas_alloc_type;
300: typedef typename atlas_alloc_type::pointer atlas_ptr;
301: protected:
302: size_t _contiguous_array_size;
303: value_type *_contiguous_array;
304: Obj<atlas_type> _atlas;
305: values_type _array;
306: fiber_type _emptyValue;
307: alloc_type _allocator;
308: public:
309: UniformSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug), _contiguous_array_size(0), _contiguous_array(NULL) {
310: atlas_ptr pAtlas = atlas_alloc_type(this->_allocator).allocate(1);
311: atlas_alloc_type(this->_allocator).construct(pAtlas, atlas_type(comm, debug));
312: this->_atlas = Obj<atlas_type>(pAtlas, sizeof(atlas_type));
313: int dim = fiberDim;
314: this->_atlas->update(*this->_atlas->getChart().begin(), &dim);
315: for(int i = 0; i < fiberDim; ++i) this->_emptyValue.v[i] = value_type();
316: };
317: UniformSection(const Obj<atlas_type>& atlas) : ParallelObject(atlas->comm(), atlas->debug()), _contiguous_array_size(0), _contiguous_array(NULL), _atlas(atlas) {
318: int dim = fiberDim;
319: this->_atlas->update(*this->_atlas->getChart().begin(), &dim);
320: for(int i = 0; i < fiberDim; ++i) this->_emptyValue.v[i] = value_type();
321: };
322: virtual ~UniformSection() {
323: this->_atlas = NULL;
324: if (this->_contiguous_array) {
325: for(size_t i = 0; i < this->_contiguous_array_size; ++i) {this->_allocator.destroy(this->_contiguous_array+i);}
326: this->_allocator.deallocate(this->_contiguous_array, this->_contiguous_array_size);
327: }
328: };
329: public:
330: value_type *getRawArray(const int size) {
331: static value_type *array = NULL;
332: static int maxSize = 0;
334: if (size > maxSize) {
335: const value_type dummy(0);
337: if (array) {
338: for(int i = 0; i < maxSize; ++i) {this->_allocator.destroy(array+i);}
339: this->_allocator.deallocate(array, maxSize);
340: ///delete [] array;
341: }
342: maxSize = size;
343: array = this->_allocator.allocate(maxSize);
344: for(int i = 0; i < maxSize; ++i) {this->_allocator.construct(array+i, dummy);}
345: ///array = new value_type[maxSize];
346: };
347: return array;
348: };
349: public: // Verifiers
350: bool hasPoint(const point_type& point) {
351: return this->_atlas->hasPoint(point);
352: };
353: void checkDimension(const int& dim) {
354: if (dim != fiberDim) {
355: ostringstream msg;
356: msg << "Invalid fiber dimension " << dim << " must be " << fiberDim << std::endl;
357: throw ALE::Exception(msg.str().c_str());
358: }
359: };
360: public: // Accessors
361: const chart_type& getChart() {return this->_atlas->getChart();};
362: const Obj<atlas_type>& getAtlas() {return this->_atlas;};
363: void setAtlas(const Obj<atlas_type>& atlas) {this->_atlas = atlas;};
364: void addPoint(const point_type& point) {
365: this->setFiberDimension(point, fiberDim);
366: };
367: template<typename Points>
368: void addPoint(const Obj<Points>& points) {
369: for(typename Points::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
370: this->setFiberDimension(*p_iter, fiberDim);
371: }
372: };
373: void copy(const Obj<UniformSection>& section) {
374: this->getAtlas()->copy(section->getAtlas());
375: const chart_type& chart = section->getChart();
377: for(typename chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
378: this->updatePoint(*c_iter, section->restrictPoint(*c_iter));
379: }
380: };
381: public: // Sizes
382: void clear() {
383: this->_atlas->clear();
384: this->_array.clear();
385: };
386: int getFiberDimension(const point_type& p) const {
387: return this->_atlas->restrictPoint(p)[0];
388: };
389: void setFiberDimension(const point_type& p, int dim) {
390: this->update();
391: this->checkDimension(dim);
392: this->_atlas->addPoint(p);
393: this->_atlas->updatePoint(p, &dim);
394: };
395: template<typename Sequence>
396: void setFiberDimension(const Obj<Sequence>& points, int dim) {
397: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
398: this->setFiberDimension(*p_iter, dim);
399: }
400: };
401: void setFiberDimension(const std::set<point_type>& points, int dim) {
402: for(typename std::set<point_type>::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
403: this->setFiberDimension(*p_iter, dim);
404: }
405: };
406: void addFiberDimension(const point_type& p, int dim) {
407: if (this->hasPoint(p)) {
408: ostringstream msg;
409: msg << "Invalid addition to fiber dimension " << dim << " cannot exceed " << fiberDim << std::endl;
410: throw ALE::Exception(msg.str().c_str());
411: } else {
412: this->setFiberDimension(p, dim);
413: }
414: };
415: int size() const {
416: const chart_type& points = this->_atlas->getChart();
417: int size = 0;
419: for(typename chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
420: size += this->getFiberDimension(*p_iter);
421: }
422: return size;
423: };
424: int sizeWithBC() const {
425: return this->size();
426: };
427: void allocatePoint() {};
428: public: // Restriction
429: const value_type *restrict() {
430: const chart_type& chart = this->getChart();
431: const value_type dummy = 0;
432: int k = 0;
434: if (chart.size() > this->_contiguous_array_size*fiberDim) {
435: if (this->_contiguous_array) {
436: for(size_t i = 0; i < this->_contiguous_array_size; ++i) {this->_allocator.destroy(this->_contiguous_array+i);}
437: this->_allocator.deallocate(this->_contiguous_array, this->_contiguous_array_size);
438: }
439: this->_contiguous_array_size = chart.size()*fiberDim;
440: this->_contiguous_array = this->_allocator.allocate(this->_contiguous_array_size*fiberDim);
441: for(size_t i = 0; i < this->_contiguous_array_size; ++i) {this->_allocator.construct(this->_contiguous_array+i, dummy);}
442: }
443: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
444: const value_type *a = this->_array[*p_iter].v;
446: for(int i = 0; i < fiberDim; ++i, ++k) {
447: this->_contiguous_array[k] = a[i];
448: }
449: }
450: return this->_contiguous_array;
451: };
452: void update() {
453: if (this->_contiguous_array) {
454: const chart_type& chart = this->getChart();
455: int k = 0;
457: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
458: value_type *a = this->_array[*p_iter].v;
460: for(int i = 0; i < fiberDim; ++i, ++k) {
461: a[i] = this->_contiguous_array[k];
462: }
463: }
464: for(size_t i = 0; i < this->_contiguous_array_size; ++i) {this->_allocator.destroy(this->_contiguous_array+i);}
465: this->_allocator.deallocate(this->_contiguous_array, this->_contiguous_array_size);
466: this->_contiguous_array_size = 0;
467: this->_contiguous_array = NULL;
468: }
469: };
470: // Return only the values associated to this point, not its closure
471: const value_type *restrictPoint(const point_type& p) {
472: if (this->_array.find(p) == this->_array.end()) return this->_emptyValue.v;
473: this->update();
474: return this->_array[p].v;
475: };
476: // Update only the values associated to this point, not its closure
477: void updatePoint(const point_type& p, const value_type v[]) {
478: this->update();
479: for(int i = 0; i < fiberDim; ++i) {
480: this->_array[p].v[i] = v[i];
481: }
482: };
483: // Update only the values associated to this point, not its closure
484: void updateAddPoint(const point_type& p, const value_type v[]) {
485: this->update();
486: for(int i = 0; i < fiberDim; ++i) {
487: this->_array[p].v[i] += v[i];
488: }
489: };
490: void updatePointAll(const point_type& p, const value_type v[]) {
491: this->updatePoint(p, v);
492: };
493: public:
494: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
495: ostringstream txt;
496: int rank;
498: this->update();
499: if (comm == MPI_COMM_NULL) {
500: comm = this->comm();
501: rank = this->commRank();
502: } else {
503: MPI_Comm_rank(comm, &rank);
504: }
505: if (name == "") {
506: if(rank == 0) {
507: txt << "viewing a UniformSection" << std::endl;
508: }
509: } else {
510: if(rank == 0) {
511: txt << "viewing UniformSection '" << name << "'" << std::endl;
512: }
513: }
514: const typename atlas_type::chart_type& chart = this->_atlas->getChart();
515: values_type& array = this->_array;
517: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
518: const point_type& point = *p_iter;
519: const typename atlas_type::value_type dim = this->_atlas->restrict(point)[0];
521: if (dim != 0) {
522: txt << "[" << this->commRank() << "]: " << point << " dim " << dim << " ";
523: for(int i = 0; i < dim; i++) {
524: txt << " " << array[point].v[i];
525: }
526: txt << std::endl;
527: }
528: }
529: if (chart.size() == 0) {
530: txt << "[" << this->commRank() << "]: empty" << std::endl;
531: }
532: PetscSynchronizedPrintf(comm, txt.str().c_str());
533: PetscSynchronizedFlush(comm);
534: };
535: };
537: // A FauxConstantSection is the simplest Section
538: // All fibers are dimension 1
539: // All values are equal to a constant
540: // We need no value storage and no communication for completion
541: template<typename Point_, typename Value_, typename Alloc_ = std::allocator<Point_> >
542: class FauxConstantSection : public ALE::ParallelObject {
543: public:
544: typedef Point_ point_type;
545: typedef Value_ value_type;
546: typedef Alloc_ alloc_type;
547: protected:
548: value_type _value;
549: public:
550: FauxConstantSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {};
551: FauxConstantSection(MPI_Comm comm, const value_type& value, const int debug) : ParallelObject(comm, debug), _value(value) {};
552: public: // Verifiers
553: void checkDimension(const int& dim) {
554: if (dim != 1) {
555: ostringstream msg;
556: msg << "Invalid fiber dimension " << dim << " must be 1" << std::endl;
557: throw ALE::Exception(msg.str().c_str());
558: }
559: };
560: public: // Accessors
561: void addPoint(const point_type& point) {
562: };
563: template<typename Points>
564: void addPoint(const Obj<Points>& points) {
565: };
566: template<typename Points>
567: void addPoint(const Points& points) {
568: };
569: void copy(const Obj<FauxConstantSection>& section) {
570: this->_value = section->restrict(point_type())[0];
571: };
572: public: // Sizes
573: void clear() {
574: };
575: int getFiberDimension(const point_type& p) const {
576: return 1;
577: };
578: void setFiberDimension(const point_type& p, int dim) {
579: this->checkDimension(dim);
580: this->addPoint(p);
581: };
582: template<typename Sequence>
583: void setFiberDimension(const Obj<Sequence>& points, int dim) {
584: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
585: this->setFiberDimension(*p_iter, dim);
586: }
587: };
588: void addFiberDimension(const point_type& p, int dim) {
589: this->setFiberDimension(p, dim);
590: };
591: int size(const point_type& p) {return this->getFiberDimension(p);};
592: public: // Restriction
593: const value_type *restrict(const point_type& p) const {
594: return &this->_value;
595: };
596: const value_type *restrictPoint(const point_type& p) const {return this->restrict(p);};
597: void update(const point_type& p, const value_type v[]) {
598: this->_value = v[0];
599: };
600: void updatePoint(const point_type& p, const value_type v[]) {return this->update(p, v);};
601: void updateAdd(const point_type& p, const value_type v[]) {
602: this->_value += v[0];
603: };
604: void updateAddPoint(const point_type& p, const value_type v[]) {return this->updateAdd(p, v);};
605: public:
606: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
607: ostringstream txt;
608: int rank;
610: if (comm == MPI_COMM_NULL) {
611: comm = this->comm();
612: rank = this->commRank();
613: } else {
614: MPI_Comm_rank(comm, &rank);
615: }
616: if (name == "") {
617: if(rank == 0) {
618: txt << "viewing a FauxConstantSection" << std::endl;
619: }
620: } else {
621: if(rank == 0) {
622: txt << "viewing FauxConstantSection '" << name << "'" << std::endl;
623: }
624: }
625: txt <<"["<<this->commRank()<<"]: Value " << this->_value << std::endl;
626: PetscSynchronizedPrintf(comm, txt.str().c_str());
627: PetscSynchronizedFlush(comm);
628: };
629: };
630: // Make a simple set from the keys of a map
631: template<typename Map>
632: class SetFromMap {
633: public:
634: typedef typename Map::size_type size_type;
635: class const_iterator {
636: public:
637: typedef typename Map::key_type value_type;
638: typedef typename Map::size_type size_type;
639: protected:
640: typename Map::const_iterator _iter;
641: public:
642: const_iterator(const typename Map::const_iterator& iter): _iter(iter) {};
643: ~const_iterator() {};
644: public:
645: const_iterator& operator=(const const_iterator& iter) {this->_iter = iter._iter;};
646: bool operator==(const const_iterator& iter) const {return this->_iter == iter._iter;};
647: bool operator!=(const const_iterator& iter) const {return this->_iter != iter._iter;};
648: const_iterator& operator++() {++this->_iter; return *this;}
649: const_iterator& operator++(int) {
650: const_iterator tmp(*this);
651: ++(*this);
652: return tmp;
653: };
654: const_iterator& operator--() {--this->_iter; return *this;}
655: const_iterator& operator--(int) {
656: const_iterator tmp(*this);
657: --(*this);
658: return tmp;
659: };
660: value_type operator*() const {return this->_iter->first;};
661: size_type size() const {return this->_iter->size();};
662: };
663: protected:
664: const Map& _map;
665: public:
666: SetFromMap(const Map& map): _map(map) {};
667: public:
668: const_iterator begin() const {return const_iterator(this->_map.begin());};
669: const_iterator end() const {return const_iterator(this->_map.end());};
670: size_type size() const {return this->_map.size();};
671: };
672: // A NewUniformSection often acts as an Atlas
673: // All fibers are the same dimension
674: // Note we can use a ConstantSection for this Atlas
675: // Each point may have a different vector
676: // Thus we need storage for values, and hence must implement completion
677: template<typename Point_, typename Value_, int fiberDim = 1, typename Alloc_ = std::allocator<Value_> >
678: class NewUniformSection : public ALE::ParallelObject {
679: public:
680: typedef Point_ point_type;
681: typedef Value_ value_type;
682: typedef Alloc_ alloc_type;
683: typedef typename alloc_type::template rebind<point_type>::other point_alloc_type;
684: typedef FauxConstantSection<point_type, int, point_alloc_type> atlas_type;
685: typedef struct {value_type v[fiberDim];} fiber_type;
686: typedef typename alloc_type::template rebind<std::pair<const point_type, fiber_type> >::other pair_alloc_type;
687: typedef std::map<point_type, fiber_type, std::less<point_type>, pair_alloc_type> values_type;
688: typedef SetFromMap<values_type> chart_type;
689: typedef typename alloc_type::template rebind<atlas_type>::other atlas_alloc_type;
690: typedef typename atlas_alloc_type::pointer atlas_ptr;
691: protected:
692: values_type _array;
693: chart_type _chart;
694: size_t _contiguous_array_size;
695: value_type *_contiguous_array;
696: Obj<atlas_type> _atlas;
697: fiber_type _emptyValue;
698: alloc_type _allocator;
699: public:
700: NewUniformSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug), _chart(_array), _contiguous_array_size(0), _contiguous_array(NULL) {
701: atlas_ptr pAtlas = atlas_alloc_type(this->_allocator).allocate(1);
702: atlas_alloc_type(this->_allocator).construct(pAtlas, atlas_type(comm, debug));
703: this->_atlas = Obj<atlas_type>(pAtlas, sizeof(atlas_type));
704: int dim = fiberDim;
705: this->_atlas->update(point_type(), &dim);
706: for(int i = 0; i < fiberDim; ++i) this->_emptyValue.v[i] = value_type();
707: };
708: NewUniformSection(const Obj<atlas_type>& atlas) : ParallelObject(atlas->comm(), atlas->debug()), _chart(_array), _contiguous_array_size(0), _contiguous_array(NULL), _atlas(atlas) {
709: int dim = fiberDim;
710: this->_atlas->update(point_type(), &dim);
711: for(int i = 0; i < fiberDim; ++i) this->_emptyValue.v[i] = value_type();
712: };
713: ~NewUniformSection() {
714: this->_atlas = NULL;
715: if (this->_contiguous_array) {
716: for(size_t i = 0; i < this->_contiguous_array_size; ++i) {this->_allocator.destroy(this->_contiguous_array+i);}
717: this->_allocator.deallocate(this->_contiguous_array, this->_contiguous_array_size);
718: }
719: };
720: public:
721: value_type *getRawArray(const int size) {
722: static value_type *array = NULL;
723: static int maxSize = 0;
725: if (size > maxSize) {
726: const value_type dummy(0);
728: if (array) {
729: for(int i = 0; i < maxSize; ++i) {this->_allocator.destroy(array+i);}
730: this->_allocator.deallocate(array, maxSize);
731: ///delete [] array;
732: }
733: maxSize = size;
734: array = this->_allocator.allocate(maxSize);
735: for(int i = 0; i < maxSize; ++i) {this->_allocator.construct(array+i, dummy);}
736: ///array = new value_type[maxSize];
737: };
738: return array;
739: };
740: public: // Verifiers
741: bool hasPoint(const point_type& point) {
742: return (this->_values.find(point) != this->_values.end());
743: ///return this->_atlas->hasPoint(point);
744: };
745: void checkDimension(const int& dim) {
746: if (dim != fiberDim) {
747: ostringstream msg;
748: msg << "Invalid fiber dimension " << dim << " must be " << fiberDim << std::endl;
749: throw ALE::Exception(msg.str().c_str());
750: }
751: };
752: public: // Accessors
753: const chart_type& getChart() {return this->_chart;};
754: const Obj<atlas_type>& getAtlas() {return this->_atlas;};
755: void setAtlas(const Obj<atlas_type>& atlas) {this->_atlas = atlas;};
756: void addPoint(const point_type& point) {
757: this->setFiberDimension(point, fiberDim);
758: };
759: template<typename Points>
760: void addPoint(const Obj<Points>& points) {
761: for(typename Points::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
762: this->setFiberDimension(*p_iter, fiberDim);
763: }
764: };
765: void copy(const Obj<NewUniformSection>& section) {
766: this->getAtlas()->copy(section->getAtlas());
767: const chart_type& chart = section->getChart();
769: for(typename chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
770: this->updatePoint(*c_iter, section->restrictPoint(*c_iter));
771: }
772: };
773: public: // Sizes
774: void clear() {
775: this->_atlas->clear();
776: this->_array.clear();
777: };
778: int getFiberDimension(const point_type& p) const {
779: return fiberDim;
780: };
781: void setFiberDimension(const point_type& p, int dim) {
782: this->update();
783: this->checkDimension(dim);
784: this->_atlas->addPoint(p);
785: this->_atlas->updatePoint(p, &dim);
786: this->_array[p] = fiber_type();
787: };
788: template<typename Sequence>
789: void setFiberDimension(const Obj<Sequence>& points, int dim) {
790: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
791: this->setFiberDimension(*p_iter, dim);
792: }
793: };
794: void setFiberDimension(const std::set<point_type>& points, int dim) {
795: for(typename std::set<point_type>::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
796: this->setFiberDimension(*p_iter, dim);
797: }
798: };
799: void addFiberDimension(const point_type& p, int dim) {
800: if (this->hasPoint(p)) {
801: ostringstream msg;
802: msg << "Invalid addition to fiber dimension " << dim << " cannot exceed " << fiberDim << std::endl;
803: throw ALE::Exception(msg.str().c_str());
804: } else {
805: this->setFiberDimension(p, dim);
806: }
807: };
808: int size() const {
809: const chart_type& points = this->getChart();
810: int size = 0;
812: for(typename chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
813: size += this->getFiberDimension(*p_iter);
814: }
815: return size;
816: };
817: int sizeWithBC() const {
818: return this->size();
819: };
820: void allocatePoint() {};
821: public: // Restriction
822: // Return a pointer to the entire contiguous storage array
823: const value_type *restrict() {
824: const chart_type& chart = this->getChart();
825: const value_type dummy = 0;
826: int k = 0;
828: if (chart.size() > this->_contiguous_array_size*fiberDim) {
829: if (this->_contiguous_array) {
830: for(size_t i = 0; i < this->_contiguous_array_size; ++i) {this->_allocator.destroy(this->_contiguous_array+i);}
831: this->_allocator.deallocate(this->_contiguous_array, this->_contiguous_array_size);
832: }
833: this->_contiguous_array_size = chart.size()*fiberDim;
834: this->_contiguous_array = this->_allocator.allocate(this->_contiguous_array_size*fiberDim);
835: for(size_t i = 0; i < this->_contiguous_array_size; ++i) {this->_allocator.construct(this->_contiguous_array+i, dummy);}
836: }
837: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
838: const value_type *a = this->_array[*p_iter].v;
840: for(int i = 0; i < fiberDim; ++i, ++k) {
841: this->_contiguous_array[k] = a[i];
842: }
843: }
844: return this->_contiguous_array;
845: };
846: void update() {
847: if (this->_contiguous_array) {
848: const chart_type& chart = this->getChart();
849: int k = 0;
851: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
852: value_type *a = this->_array[*p_iter].v;
854: for(int i = 0; i < fiberDim; ++i, ++k) {
855: a[i] = this->_contiguous_array[k];
856: }
857: }
858: for(size_t i = 0; i < this->_contiguous_array_size; ++i) {this->_allocator.destroy(this->_contiguous_array+i);}
859: this->_allocator.deallocate(this->_contiguous_array, this->_contiguous_array_size);
860: this->_contiguous_array_size = 0;
861: this->_contiguous_array = NULL;
862: }
863: };
864: // Return only the values associated to this point, not its closure
865: const value_type *restrictPoint(const point_type& p) {
866: if (this->_array.find(p) == this->_array.end()) return this->_emptyValue.v;
867: this->update();
868: return this->_array[p].v;
869: };
870: // Update only the values associated to this point, not its closure
871: void updatePoint(const point_type& p, const value_type v[]) {
872: this->update();
873: for(int i = 0; i < fiberDim; ++i) {
874: this->_array[p].v[i] = v[i];
875: }
876: };
877: // Update only the values associated to this point, not its closure
878: void updateAddPoint(const point_type& p, const value_type v[]) {
879: this->update();
880: for(int i = 0; i < fiberDim; ++i) {
881: this->_array[p].v[i] += v[i];
882: }
883: };
884: void updatePointAll(const point_type& p, const value_type v[]) {
885: this->updatePoint(p, v);
886: };
887: public:
888: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
889: ostringstream txt;
890: int rank;
892: this->update();
893: if (comm == MPI_COMM_NULL) {
894: comm = this->comm();
895: rank = this->commRank();
896: } else {
897: MPI_Comm_rank(comm, &rank);
898: }
899: if (name == "") {
900: if(rank == 0) {
901: txt << "viewing a NewUniformSection" << std::endl;
902: }
903: } else {
904: if(rank == 0) {
905: txt << "viewing NewUniformSection '" << name << "'" << std::endl;
906: }
907: }
908: const chart_type& chart = this->getChart();
909: values_type& array = this->_array;
911: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
912: const point_type& point = *p_iter;
914: if (fiberDim != 0) {
915: txt << "[" << this->commRank() << "]: " << point << " dim " << fiberDim << " ";
916: for(int i = 0; i < fiberDim; i++) {
917: txt << " " << array[point].v[i];
918: }
919: txt << std::endl;
920: }
921: }
922: if (chart.size() == 0) {
923: txt << "[" << this->commRank() << "]: empty" << std::endl;
924: }
925: PetscSynchronizedPrintf(comm, txt.str().c_str());
926: PetscSynchronizedFlush(comm);
927: };
928: };
929: // A Section is our most general construct (more general ones could be envisioned)
930: // The Atlas is a UniformSection of dimension 1 and value type Point
931: // to hold each fiber dimension and offsets into a contiguous patch array
932: template<typename Point_, typename Value_, typename Alloc_ = std::allocator<Value_>,
933: typename Atlas_ = UniformSection<Point_, Point, 1, typename Alloc_::template rebind<Point>::other> >
934: class Section : public ALE::ParallelObject {
935: public:
936: typedef Point_ point_type;
937: typedef Value_ value_type;
938: typedef Alloc_ alloc_type;
939: typedef Atlas_ atlas_type;
940: typedef Point index_type;
941: typedef typename atlas_type::chart_type chart_type;
942: typedef value_type * values_type;
943: typedef typename alloc_type::template rebind<atlas_type>::other atlas_alloc_type;
944: typedef typename atlas_alloc_type::pointer atlas_ptr;
945: protected:
946: Obj<atlas_type> _atlas;
947: Obj<atlas_type> _atlasNew;
948: values_type _array;
949: alloc_type _allocator;
950: public:
951: Section(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {
952: atlas_ptr pAtlas = atlas_alloc_type(this->_allocator).allocate(1);
953: atlas_alloc_type(this->_allocator).construct(pAtlas, atlas_type(comm, debug));
954: this->_atlas = Obj<atlas_type>(pAtlas, sizeof(atlas_type));
955: this->_atlasNew = NULL;
956: this->_array = NULL;
957: };
958: Section(const Obj<atlas_type>& atlas) : ParallelObject(atlas->comm(), atlas->debug()), _atlas(atlas), _atlasNew(NULL), _array(NULL) {};
959: virtual ~Section() {
960: if (this->_array) {
961: const int totalSize = this->sizeWithBC();
963: for(int i = 0; i < totalSize; ++i) {this->_allocator.destroy(this->_array+i);}
964: this->_allocator.deallocate(this->_array, totalSize);
965: ///delete [] this->_array;
966: this->_array = NULL;
967: }
968: };
969: public:
970: value_type *getRawArray(const int size) {
971: static value_type *array = NULL;
972: static int maxSize = 0;
974: if (size > maxSize) {
975: const value_type dummy(0);
977: if (array) {
978: for(int i = 0; i < maxSize; ++i) {this->_allocator.destroy(array+i);}
979: this->_allocator.deallocate(array, maxSize);
980: ///delete [] array;
981: }
982: maxSize = size;
983: array = this->_allocator.allocate(maxSize);
984: for(int i = 0; i < maxSize; ++i) {this->_allocator.construct(array+i, dummy);}
985: ///array = new value_type[maxSize];
986: };
987: return array;
988: };
989: int getStorageSize() const {
990: return this->sizeWithBC();
991: };
992: public: // Verifiers
993: bool hasPoint(const point_type& point) {
994: return this->_atlas->hasPoint(point);
995: };
996: public: // Accessors
997: const Obj<atlas_type>& getAtlas() {return this->_atlas;};
998: void setAtlas(const Obj<atlas_type>& atlas) {this->_atlas = atlas;};
999: const Obj<atlas_type>& getNewAtlas() {return this->_atlasNew;};
1000: void setNewAtlas(const Obj<atlas_type>& atlas) {this->_atlasNew = atlas;};
1001: const chart_type& getChart() const {return this->_atlas->getChart();};
1002: public: // BC
1003: // Returns the number of constraints on a point
1004: const int getConstraintDimension(const point_type& p) const {
1005: return std::max(0, -this->_atlas->restrictPoint(p)->prefix);
1006: };
1007: // Set the number of constraints on a point
1008: // We only allow the entire point to be constrained, so these will be the
1009: // only dofs on the point
1010: void setConstraintDimension(const point_type& p, const int numConstraints) {
1011: this->setFiberDimension(p, -numConstraints);
1012: };
1013: void addConstraintDimension(const point_type& p, const int numConstraints) {
1014: throw ALE::Exception("Variable constraint dimensions not available for this Section type");
1015: };
1016: void copyBC(const Obj<Section>& section) {
1017: const chart_type& chart = this->getChart();
1019: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
1020: if (this->getConstraintDimension(*p_iter)) {
1021: this->updatePointBC(*p_iter, section->restrictPoint(*p_iter));
1022: }
1023: }
1024: };
1025: void defaultConstraintDof() {};
1026: public: // Sizes
1027: void clear() {
1028: const int totalSize = this->sizeWithBC();
1030: this->_atlas->clear();
1031: for(int i = 0; i < totalSize; ++i) {this->_allocator.destroy(this->_array+i);}
1032: this->_allocator.deallocate(this->_array, totalSize);
1033: ///delete [] this->_array;
1034: this->_array = NULL;
1035: };
1036: // Return the total number of dofs on the point (free and constrained)
1037: int getFiberDimension(const point_type& p) const {
1038: return std::abs(this->_atlas->restrictPoint(p)->prefix);
1039: };
1040: int getFiberDimension(const Obj<atlas_type>& atlas, const point_type& p) const {
1041: return std::abs(atlas->restrictPoint(p)->prefix);
1042: };
1043: // Set the total number of dofs on the point (free and constrained)
1044: void setFiberDimension(const point_type& p, int dim) {
1045: const index_type idx(dim, -1);
1046: this->_atlas->addPoint(p);
1047: this->_atlas->updatePoint(p, &idx);
1048: };
1049: template<typename Sequence>
1050: void setFiberDimension(const Obj<Sequence>& points, int dim) {
1051: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
1052: this->setFiberDimension(*p_iter, dim);
1053: }
1054: };
1055: void addFiberDimension(const point_type& p, int dim) {
1056: if (this->_atlas->hasPoint(p)) {
1057: const index_type values(dim, 0);
1058: this->_atlas->updateAddPoint(p, &values);
1059: } else {
1060: this->setFiberDimension(p, dim);
1061: }
1062: };
1063: // Return the number of constrained dofs on this point
1064: // If constrained, this is equal to the fiber dimension
1065: // Otherwise, 0
1066: int getConstrainedFiberDimension(const point_type& p) const {
1067: return std::max(0, this->_atlas->restrictPoint(p)->prefix);
1068: };
1069: // Return the total number of free dofs
1070: int size() const {
1071: const chart_type& points = this->getChart();
1072: int size = 0;
1074: for(typename chart_type::const_iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
1075: size += this->getConstrainedFiberDimension(*p_iter);
1076: }
1077: return size;
1078: };
1079: // Return the total number of dofs (free and constrained)
1080: int sizeWithBC() const {
1081: const chart_type& points = this->getChart();
1082: int size = 0;
1084: for(typename chart_type::const_iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
1085: size += this->getFiberDimension(*p_iter);
1086: }
1087: return size;
1088: };
1089: public: // Index retrieval
1090: const typename index_type::index_type& getIndex(const point_type& p) {
1091: return this->_atlas->restrictPoint(p)->index;
1092: };
1093: void setIndex(const point_type& p, const typename index_type::index_type& index) {
1094: ((typename atlas_type::value_type *) this->_atlas->restrictPoint(p))->index = index;
1095: };
1096: void setIndexBC(const point_type& p, const typename index_type::index_type& index) {
1097: this->setIndex(p, index);
1098: };
1099: void getIndices(const point_type& p, PetscInt indices[], PetscInt *indx, const int orientation = 1, const bool freeOnly = false, const bool skipConstraints = false) {
1100: this->getIndices(p, this->getIndex(p), indices, indx, orientation, freeOnly, skipConstraints);
1101: };
1102: template<typename Order_>
1103: void getIndices(const point_type& p, const Obj<Order_>& order, PetscInt indices[], PetscInt *indx, const int orientation = 1, const bool freeOnly = false, const bool skipConstraints = false) {
1104: this->getIndices(p, order->getIndex(p), indices, indx, orientation, freeOnly, skipConstraints);
1105: };
1106: void getIndices(const point_type& p, const int start, PetscInt indices[], PetscInt *indx, const int orientation = 1, const bool freeOnly = false, const bool skipConstraints = false) {
1107: const int& dim = this->getFiberDimension(p);
1108: const int& cDim = this->getConstraintDimension(p);
1109: const int end = start + dim;
1111: if (!cDim) {
1112: if (orientation >= 0) {
1113: for(int i = start; i < end; ++i) {
1114: indices[(*indx)++] = i;
1115: }
1116: } else {
1117: for(int i = end-1; i >= start; --i) {
1118: indices[(*indx)++] = i;
1119: }
1120: }
1121: } else {
1122: if (!freeOnly) {
1123: for(int i = start; i < end; ++i) {
1124: indices[(*indx)++] = -1;
1125: }
1126: }
1127: }
1128: };
1129: public: // Allocation
1130: void allocateStorage() {
1131: const int totalSize = this->sizeWithBC();
1132: const value_type dummy(0);
1134: this->_array = this->_allocator.allocate(totalSize);
1135: ///this->_array = new value_type[totalSize];
1136: for(int i = 0; i < totalSize; ++i) {this->_allocator.construct(this->_array+i, dummy);}
1137: ///PetscMemzero(this->_array, totalSize * sizeof(value_type));
1138: };
1139: void replaceStorage(value_type *newArray) {
1140: delete [] this->_array;
1141: this->_array = newArray;
1142: this->_atlasNew = NULL;
1143: };
1144: void addPoint(const point_type& point, const int dim) {
1145: if (dim == 0) return;
1146: if (this->_atlasNew.isNull()) {
1147: this->_atlasNew = new atlas_type(this->comm(), this->debug());
1148: this->_atlasNew->copy(this->_atlas);
1149: }
1150: const index_type idx(dim, -1);
1151: this->_atlasNew->addPoint(point);
1152: this->_atlasNew->updatePoint(point, &idx);
1153: };
1154: template<typename Sequence>
1155: void addPoints(const Obj<Sequence>& points, const int dim) {
1156: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
1157: this->addPoint(*p_iter, dim);
1158: }
1159: };
1160: void orderPoints(const Obj<atlas_type>& atlas){
1161: const chart_type& chart = this->getChart();
1162: int offset = 0;
1163: int bcOffset = this->size();
1165: for(typename chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1166: typename atlas_type::value_type idx = atlas->restrictPoint(*c_iter)[0];
1167: const int& dim = idx.prefix;
1169: if (dim >= 0) {
1170: idx.index = offset;
1171: atlas->updatePoint(*c_iter, &idx);
1172: offset += dim;
1173: } else {
1174: idx.index = bcOffset;
1175: atlas->updatePoint(*c_iter, &idx);
1176: bcOffset -= dim;
1177: }
1178: }
1179: };
1180: void allocatePoint() {
1181: this->orderPoints(this->_atlas);
1182: this->allocateStorage();
1183: };
1184: public: // Restriction and Update
1185: // Zero entries
1186: void zero() {
1187: memset(this->_array, 0, this->size()* sizeof(value_type));
1188: };
1189: // Return a pointer to the entire contiguous storage array
1190: const value_type *restrict() {
1191: return this->_array;
1192: };
1193: // Update the entire contiguous storage array
1194: void update(const value_type v[]) {
1195: const value_type *array = this->_array;
1196: const int size = this->size();
1198: for(int i = 0; i < size; i++) {
1199: array[i] = v[i];
1200: }
1201: };
1202: // Return the free values on a point
1203: const value_type *restrictPoint(const point_type& p) {
1204: return &(this->_array[this->_atlas->restrictPoint(p)[0].index]);
1205: };
1206: // Update the free values on a point
1207: void updatePoint(const point_type& p, const value_type v[], const int orientation = 1) {
1208: const index_type& idx = this->_atlas->restrictPoint(p)[0];
1209: value_type *a = &(this->_array[idx.index]);
1211: if (orientation >= 0) {
1212: for(int i = 0; i < idx.prefix; ++i) {
1213: a[i] = v[i];
1214: }
1215: } else {
1216: const int last = idx.prefix-1;
1218: for(int i = 0; i < idx.prefix; ++i) {
1219: a[i] = v[last-i];
1220: }
1221: }
1222: };
1223: // Update the free values on a point
1224: void updateAddPoint(const point_type& p, const value_type v[], const int orientation = 1) {
1225: const index_type& idx = this->_atlas->restrictPoint(p)[0];
1226: value_type *a = &(this->_array[idx.index]);
1228: if (orientation >= 0) {
1229: for(int i = 0; i < idx.prefix; ++i) {
1230: a[i] += v[i];
1231: }
1232: } else {
1233: const int last = idx.prefix-1;
1235: for(int i = 0; i < idx.prefix; ++i) {
1236: a[i] += v[last-i];
1237: }
1238: }
1239: };
1240: // Update only the constrained dofs on a point
1241: void updatePointBC(const point_type& p, const value_type v[], const int orientation = 1) {
1242: const index_type& idx = this->_atlas->restrictPoint(p)[0];
1243: const int dim = -idx.prefix;
1244: value_type *a = &(this->_array[idx.index]);
1246: if (orientation >= 0) {
1247: for(int i = 0; i < dim; ++i) {
1248: a[i] = v[i];
1249: }
1250: } else {
1251: const int last = dim-1;
1253: for(int i = 0; i < dim; ++i) {
1254: a[i] = v[last-i];
1255: }
1256: }
1257: };
1258: // Update all dofs on a point (free and constrained)
1259: void updatePointAll(const point_type& p, const value_type v[], const int orientation = 1) {
1260: const index_type& idx = this->_atlas->restrictPoint(p)[0];
1261: const int dim = std::abs(idx.prefix);
1262: value_type *a = &(this->_array[idx.index]);
1264: if (orientation >= 0) {
1265: for(int i = 0; i < dim; ++i) {
1266: a[i] = v[i];
1267: }
1268: } else {
1269: const int last = dim-1;
1271: for(int i = 0; i < dim; ++i) {
1272: a[i] = v[last-i];
1273: }
1274: }
1275: };
1276: public:
1277: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
1278: ostringstream txt;
1279: int rank;
1281: if (comm == MPI_COMM_NULL) {
1282: comm = this->comm();
1283: rank = this->commRank();
1284: } else {
1285: MPI_Comm_rank(comm, &rank);
1286: }
1287: if(rank == 0) {
1288: txt << "viewing Section " << this->getName() << std::endl;
1289: if (name != "") {
1290: txt << ": " << name << "'";
1291: }
1292: txt << std::endl;
1293: }
1294: const typename atlas_type::chart_type& chart = this->_atlas->getChart();
1295: const value_type *array = this->_array;
1297: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
1298: const point_type& point = *p_iter;
1299: const index_type& idx = this->_atlas->restrictPoint(point)[0];
1300: const int dim = this->getFiberDimension(point);
1302: if (idx.prefix != 0) {
1303: txt << "[" << this->commRank() << "]: " << point << " dim " << idx.prefix << " offset " << idx.index << " ";
1304: for(int i = 0; i < dim; i++) {
1305: txt << " " << array[idx.index+i];
1306: }
1307: txt << std::endl;
1308: }
1309: }
1310: if (chart.size() == 0) {
1311: txt << "[" << this->commRank() << "]: empty" << std::endl;
1312: }
1313: PetscSynchronizedPrintf(comm, txt.str().c_str());
1314: PetscSynchronizedFlush(comm);
1315: };
1316: public: // Fibrations
1317: void setConstraintDof(const point_type& p, const int dofs[]) {};
1318: int getNumSpaces() const {return 1;};
1319: void addSpace() {};
1320: int getFiberDimension(const point_type& p, const int space) {return this->getFiberDimension(p);};
1321: void setFiberDimension(const point_type& p, int dim, const int space) {this->setFiberDimension(p, dim);};
1322: template<typename Sequence>
1323: void setFiberDimension(const Obj<Sequence>& points, int dim, const int space) {
1324: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
1325: this->setFiberDimension(*p_iter, dim, space);
1326: }
1327: };
1328: void setConstraintDimension(const point_type& p, const int numConstraints, const int space) {
1329: this->setConstraintDimension(p, numConstraints);
1330: };
1331: };
1332: // GeneralSection will support BC on a subset of unknowns on a point
1333: // We make a separate constraint Atlas to mark constrained dofs on a point
1334: // Storage will be contiguous by node, just as in Section
1335: // This allows fast restrict(p)
1336: // Then update() is accomplished by skipping constrained unknowns
1337: // We must eliminate restrict() since it does not correspond to the constrained system
1338: // Numbering will have to be rewritten to calculate correct mappings
1339: // I think we can just generate multiple tuples per point
1340: template<typename Point_, typename Value_, typename Alloc_ = std::allocator<Value_>,
1341: typename Atlas_ = UniformSection<Point_, Point, 1, typename Alloc_::template rebind<Point>::other>,
1342: typename BCAtlas_ = Section<Point_, int, typename Alloc_::template rebind<int>::other> >
1343: class GeneralSection : public ALE::ParallelObject {
1344: public:
1345: typedef Point_ point_type;
1346: typedef Value_ value_type;
1347: typedef Alloc_ alloc_type;
1348: typedef Atlas_ atlas_type;
1349: typedef BCAtlas_ bc_type;
1350: typedef Point index_type;
1351: typedef typename atlas_type::chart_type chart_type;
1352: typedef value_type * values_type;
1353: typedef std::pair<const int *, const int *> customAtlasInd_type;
1354: typedef std::pair<customAtlasInd_type, bool> customAtlas_type;
1355: typedef typename alloc_type::template rebind<atlas_type>::other atlas_alloc_type;
1356: typedef typename atlas_alloc_type::pointer atlas_ptr;
1357: typedef typename alloc_type::template rebind<bc_type>::other bc_alloc_type;
1358: typedef typename bc_alloc_type::pointer bc_ptr;
1359: protected:
1360: Obj<atlas_type> _atlas;
1361: Obj<atlas_type> _atlasNew;
1362: values_type _array;
1363: bool _sharedStorage;
1364: int _sharedStorageSize;
1365: Obj<bc_type> _bc;
1366: alloc_type _allocator;
1367: std::vector<Obj<atlas_type> > _spaces;
1368: std::vector<Obj<bc_type> > _bcs;
1369: // Optimization
1370: std::vector<customAtlas_type> _customRestrictAtlas;
1371: std::vector<customAtlas_type> _customUpdateAtlas;
1372: public:
1373: GeneralSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {
1374: atlas_ptr pAtlas = atlas_alloc_type(this->_allocator).allocate(1);
1375: atlas_alloc_type(this->_allocator).construct(pAtlas, atlas_type(comm, debug));
1376: this->_atlas = Obj<atlas_type>(pAtlas, sizeof(atlas_type));
1377: bc_ptr pBC = bc_alloc_type(this->_allocator).allocate(1);
1378: bc_alloc_type(this->_allocator).construct(pBC, bc_type(comm, debug));
1379: this->_bc = Obj<bc_type>(pBC, sizeof(bc_type));
1380: this->_atlasNew = NULL;
1381: this->_array = NULL;
1382: this->_sharedStorage = false;
1383: };
1384: GeneralSection(const Obj<atlas_type>& atlas) : ParallelObject(atlas->comm(), atlas->debug()), _atlas(atlas), _atlasNew(NULL), _array(NULL), _sharedStorage(false), _sharedStorageSize(0) {
1385: bc_ptr pBC = bc_alloc_type(this->_allocator).allocate(1);
1386: bc_alloc_type(this->_allocator).construct(pBC, bc_type(comm, debug));
1387: this->_bc = Obj<bc_type>(pBC, sizeof(bc_type));
1388: };
1389: ~GeneralSection() {
1390: if (this->_array && !this->_sharedStorage) {
1391: const int totalSize = this->sizeWithBC();
1393: for(int i = 0; i < totalSize; ++i) {this->_allocator.destroy(this->_array+i);}
1394: this->_allocator.deallocate(this->_array, totalSize);
1395: ///delete [] this->_array;
1396: this->_array = NULL;
1397: }
1398: for(std::vector<customAtlas_type>::iterator a_iter = this->_customRestrictAtlas.begin(); a_iter != this->_customRestrictAtlas.end(); ++a_iter) {
1399: if (a_iter->second) {
1400: delete [] a_iter->first.first;
1401: delete [] a_iter->first.second;
1402: }
1403: }
1404: for(std::vector<customAtlas_type>::iterator a_iter = this->_customUpdateAtlas.begin(); a_iter != this->_customUpdateAtlas.end(); ++a_iter) {
1405: if (a_iter->second) {
1406: delete [] a_iter->first.first;
1407: delete [] a_iter->first.second;
1408: }
1409: }
1410: };
1411: public:
1412: value_type *getRawArray(const int size) {
1413: // Put in a sentinel value that deallocates the array
1414: static value_type *array = NULL;
1415: static int maxSize = 0;
1417: if (size > maxSize) {
1418: const value_type dummy(0);
1420: if (array) {
1421: for(int i = 0; i < maxSize; ++i) {this->_allocator.destroy(array+i);}
1422: this->_allocator.deallocate(array, maxSize);
1423: ///delete [] array;
1424: }
1425: maxSize = size;
1426: array = this->_allocator.allocate(maxSize);
1427: for(int i = 0; i < maxSize; ++i) {this->_allocator.construct(array+i, dummy);}
1428: ///array = new value_type[maxSize];
1429: };
1430: return array;
1431: };
1432: int getStorageSize() const {
1433: if (this->_sharedStorage) {
1434: return this->_sharedStorageSize;
1435: }
1436: return this->sizeWithBC();
1437: };
1438: public: // Verifiers
1439: bool hasPoint(const point_type& point) {
1440: return this->_atlas->hasPoint(point);
1441: };
1442: public: // Accessors
1443: const Obj<atlas_type>& getAtlas() const {return this->_atlas;};
1444: void setAtlas(const Obj<atlas_type>& atlas) {this->_atlas = atlas;};
1445: const Obj<atlas_type>& getNewAtlas() const {return this->_atlasNew;};
1446: void setNewAtlas(const Obj<atlas_type>& atlas) {this->_atlasNew = atlas;};
1447: const Obj<bc_type>& getBC() const {return this->_bc;};
1448: void setBC(const Obj<bc_type>& bc) {this->_bc = bc;};
1449: const chart_type& getChart() const {return this->_atlas->getChart();};
1450: public: // BC
1451: // Returns the number of constraints on a point
1452: const int getConstraintDimension(const point_type& p) const {
1453: if (!this->_bc->hasPoint(p)) return 0;
1454: return this->_bc->getFiberDimension(p);
1455: };
1456: // Set the number of constraints on a point
1457: void setConstraintDimension(const point_type& p, const int numConstraints) {
1458: this->_bc->setFiberDimension(p, numConstraints);
1459: };
1460: // Increment the number of constraints on a point
1461: void addConstraintDimension(const point_type& p, const int numConstraints) {
1462: this->_bc->addFiberDimension(p, numConstraints);
1463: };
1464: // Return the local dofs which are constrained on a point
1465: const int *getConstraintDof(const point_type& p) {
1466: return this->_bc->restrictPoint(p);
1467: };
1468: // Set the local dofs which are constrained on a point
1469: void setConstraintDof(const point_type& p, const int dofs[]) {
1470: this->_bc->updatePoint(p, dofs);
1471: };
1472: void copyBC(const Obj<GeneralSection>& section) {
1473: this->setBC(section->getBC());
1474: const chart_type& chart = this->getChart();
1476: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
1477: if (this->getConstraintDimension(*p_iter)) {
1478: this->updatePointBCFull(*p_iter, section->restrictPoint(*p_iter));
1479: }
1480: }
1481: this->copyFibration(section);
1482: };
1483: void defaultConstraintDof() {
1484: const chart_type& chart = this->getChart();
1485: int size = 0;
1487: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
1488: size = std::max(size, this->getConstraintDimension(*p_iter));
1489: }
1490: int *dofs = new int[size];
1491: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
1492: const int cDim = this->getConstraintDimension(*p_iter);
1494: if (cDim) {
1495: for(int d = 0; d < cDim; ++d) {
1496: dofs[d] = d;
1497: }
1498: this->_bc->updatePoint(*p_iter, dofs);
1499: }
1500: }
1501: delete [] dofs;
1502: };
1503: public: // Sizes
1504: void clear() {
1505: this->_atlas->clear();
1506: if (!this->_sharedStorage) {
1507: const int totalSize = this->sizeWithBC();
1509: for(int i = 0; i < totalSize; ++i) {this->_allocator.destroy(this->_array+i);}
1510: this->_allocator.deallocate(this->_array, totalSize);
1511: ///delete [] this->_array;
1512: }
1513: this->_array = NULL;
1514: this->_bc->clear();
1515: };
1516: // Return the total number of dofs on the point (free and constrained)
1517: int getFiberDimension(const point_type& p) const {
1518: return this->_atlas->restrictPoint(p)->prefix;
1519: };
1520: int getFiberDimension(const Obj<atlas_type>& atlas, const point_type& p) const {
1521: return atlas->restrictPoint(p)->prefix;
1522: };
1523: // Set the total number of dofs on the point (free and constrained)
1524: void setFiberDimension(const point_type& p, int dim) {
1525: const index_type idx(dim, -1);
1526: this->_atlas->addPoint(p);
1527: this->_atlas->updatePoint(p, &idx);
1528: };
1529: template<typename Sequence>
1530: void setFiberDimension(const Obj<Sequence>& points, int dim) {
1531: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
1532: this->setFiberDimension(*p_iter, dim);
1533: }
1534: };
1535: void addFiberDimension(const point_type& p, int dim) {
1536: if (this->_atlas->hasPoint(p)) {
1537: const index_type values(dim, 0);
1538: this->_atlas->updateAddPoint(p, &values);
1539: } else {
1540: this->setFiberDimension(p, dim);
1541: }
1542: };
1543: // Return the number of constrained dofs on this point
1544: int getConstrainedFiberDimension(const point_type& p) const {
1545: return this->getFiberDimension(p) - this->getConstraintDimension(p);
1546: };
1547: // Return the total number of free dofs
1548: int size() const {
1549: const chart_type& points = this->getChart();
1550: int size = 0;
1552: for(typename chart_type::const_iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
1553: size += this->getConstrainedFiberDimension(*p_iter);
1554: }
1555: return size;
1556: };
1557: // Return the total number of dofs (free and constrained)
1558: int sizeWithBC() const {
1559: const chart_type& points = this->getChart();
1560: int size = 0;
1562: for(typename chart_type::const_iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
1563: size += this->getFiberDimension(*p_iter);
1564: }
1565: return size;
1566: };
1567: public: // Index retrieval
1568: const typename index_type::index_type& getIndex(const point_type& p) {
1569: return this->_atlas->restrictPoint(p)->index;
1570: };
1571: void setIndex(const point_type& p, const typename index_type::index_type& index) {
1572: ((typename atlas_type::value_type *) this->_atlas->restrictPoint(p))->index = index;
1573: };
1574: void setIndexBC(const point_type& p, const typename index_type::index_type& index) {};
1575: void getIndices(const point_type& p, PetscInt indices[], PetscInt *indx, const int orientation = 1, const bool freeOnly = false, const bool skipConstraints = true) {
1576: this->getIndices(p, this->getIndex(p), indices, indx, orientation, freeOnly, skipConstraints);
1577: };
1578: template<typename Order_>
1579: void getIndices(const point_type& p, const Obj<Order_>& order, PetscInt indices[], PetscInt *indx, const int orientation = 1, const bool freeOnly = false, const bool skipConstraints = false) {
1580: this->getIndices(p, order->getIndex(p), indices, indx, orientation, freeOnly, skipConstraints);
1581: };
1582: void getIndicesRaw(const point_type& p, const int start, PetscInt indices[], PetscInt *indx, const int orientation) {
1583: if (orientation >= 0) {
1584: const int& dim = this->getFiberDimension(p);
1585: const int end = start + dim;
1587: for(int i = start; i < end; ++i) {
1588: indices[(*indx)++] = i;
1589: }
1590: } else {
1591: const int numSpaces = this->getNumSpaces();
1592: int offset = start;
1594: for(int space = 0; space < numSpaces; ++space) {
1595: const int& dim = this->getFiberDimension(p, space);
1597: for(int i = offset+dim-1; i >= offset; --i) {
1598: indices[(*indx)++] = i;
1599: }
1600: offset += dim;
1601: }
1602: if (!numSpaces) {
1603: const int& dim = this->getFiberDimension(p);
1605: for(int i = offset+dim-1; i >= offset; --i) {
1606: indices[(*indx)++] = i;
1607: }
1608: offset += dim;
1609: }
1610: }
1611: }
1612: void getIndices(const point_type& p, const int start, PetscInt indices[], PetscInt *indx, const int orientation = 1, const bool freeOnly = false, const bool skipConstraints = false) {
1613: const int& cDim = this->getConstraintDimension(p);
1615: if (!cDim) {
1616: this->getIndicesRaw(p, start, indices, indx, orientation);
1617: } else {
1618: if (orientation >= 0) {
1619: const int& dim = this->getFiberDimension(p);
1620: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1621: int cInd = 0;
1623: for(int i = start, k = 0; k < dim; ++k) {
1624: if ((cInd < cDim) && (k == cDof[cInd])) {
1625: if (!freeOnly) indices[(*indx)++] = -(k+1);
1626: if (skipConstraints) ++i;
1627: ++cInd;
1628: } else {
1629: indices[(*indx)++] = i++;
1630: }
1631: }
1632: } else {
1633: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1634: int offset = 0;
1635: int cOffset = 0;
1636: int j = -1;
1638: for(int space = 0; space < this->getNumSpaces(); ++space) {
1639: const int dim = this->getFiberDimension(p, space);
1640: const int tDim = this->getConstrainedFiberDimension(p, space);
1641: int cInd = (dim - tDim)-1;
1643: j += dim;
1644: for(int i = 0, k = start+tDim+offset; i < dim; ++i, --j) {
1645: if ((cInd >= 0) && (j == cDof[cInd+cOffset])) {
1646: if (!freeOnly) indices[(*indx)++] = -(offset+i+1);
1647: if (skipConstraints) --k;
1648: --cInd;
1649: } else {
1650: indices[(*indx)++] = --k;
1651: }
1652: }
1653: j += dim;
1654: offset += dim;
1655: cOffset += dim - tDim;
1656: }
1657: }
1658: }
1659: };
1660: public: // Allocation
1661: void allocateStorage() {
1662: const int totalSize = this->sizeWithBC();
1663: const value_type dummy(0) ;
1665: this->_array = this->_allocator.allocate(totalSize);
1666: ///this->_array = new value_type[totalSize];
1667: this->_sharedStorage = false;
1668: this->_sharedStorageSize = 0;
1669: for(int i = 0; i < totalSize; ++i) {this->_allocator.construct(this->_array+i, dummy);}
1670: ///PetscMemzero(this->_array, totalSize * sizeof(value_type));
1671: this->_bc->allocatePoint();
1672: };
1673: void replaceStorage(value_type *newArray, const bool sharedStorage = false, const int sharedStorageSize = 0) {
1674: if (this->_array && !this->_sharedStorage) {
1675: const int totalSize = this->sizeWithBC();
1677: for(int i = 0; i < totalSize; ++i) {this->_allocator.destroy(this->_array+i);}
1678: this->_allocator.deallocate(this->_array, totalSize);
1679: ///delete [] this->_array;
1680: }
1681: this->_array = newArray;
1682: this->_sharedStorage = sharedStorage;
1683: this->_sharedStorageSize = sharedStorageSize;
1684: this->_atlas = this->_atlasNew;
1685: this->_atlasNew = NULL;
1686: };
1687: void addPoint(const point_type& point, const int dim) {
1688: if (dim == 0) return;
1689: if (this->_atlasNew.isNull()) {
1690: this->_atlasNew = new atlas_type(this->comm(), this->debug());
1691: this->_atlasNew->copy(this->_atlas);
1692: }
1693: const index_type idx(dim, -1);
1694: this->_atlasNew->addPoint(point);
1695: this->_atlasNew->updatePoint(point, &idx);
1696: };
1697: void orderPoints(const Obj<atlas_type>& atlas){
1698: const chart_type& chart = this->getChart();
1699: int offset = 0;
1701: for(typename chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1702: typename atlas_type::value_type idx = atlas->restrictPoint(*c_iter)[0];
1703: const int& dim = idx.prefix;
1705: idx.index = offset;
1706: atlas->updatePoint(*c_iter, &idx);
1707: offset += dim;
1708: }
1709: };
1710: void allocatePoint() {
1711: this->orderPoints(this->_atlas);
1712: this->allocateStorage();
1713: };
1714: public: // Restriction and Update
1715: // Zero entries
1716: void zero() {
1717: this->set(0.0);
1718: };
1719: void set(const value_type value) {
1720: //memset(this->_array, 0, this->sizeWithBC()* sizeof(value_type));
1721: const chart_type& chart = this->getChart();
1723: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1724: value_type *array = (value_type *) this->restrictPoint(*c_iter);
1725: const int& dim = this->getFiberDimension(*c_iter);
1726: const int& cDim = this->getConstraintDimension(*c_iter);
1728: if (!cDim) {
1729: for(int i = 0; i < dim; ++i) {
1730: array[i] = value;
1731: }
1732: } else {
1733: const typename bc_type::value_type *cDof = this->getConstraintDof(*c_iter);
1734: int cInd = 0;
1736: for(int i = 0; i < dim; ++i) {
1737: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1738: array[i] = value;
1739: }
1740: }
1741: }
1742: };
1743: // Add two sections and put the result in a third
1744: void add(const Obj<GeneralSection>& x, const Obj<GeneralSection>& y) {
1745: // Check atlases
1746: const chart_type& chart = this->getChart();
1748: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1749: value_type *array = (value_type *) this->restrictPoint(*c_iter);
1750: const value_type *xArray = x->restrictPoint(*c_iter);
1751: const value_type *yArray = y->restrictPoint(*c_iter);
1752: const int& dim = this->getFiberDimension(*c_iter);
1753: const int& cDim = this->getConstraintDimension(*c_iter);
1755: if (!cDim) {
1756: for(int i = 0; i < dim; ++i) {
1757: array[i] = xArray[i] + yArray[i];
1758: }
1759: } else {
1760: const typename bc_type::value_type *cDof = this->getConstraintDof(*c_iter);
1761: int cInd = 0;
1763: for(int i = 0; i < dim; ++i) {
1764: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1765: array[i] = xArray[i] + yArray[i];
1766: }
1767: }
1768: }
1769: };
1770: // this = this + alpha * x
1771: void axpy(const value_type alpha, const Obj<GeneralSection>& x) {
1772: // Check atlases
1773: const chart_type& chart = this->getChart();
1775: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1776: value_type *array = (value_type *) this->restrictPoint(*c_iter);
1777: const value_type *xArray = x->restrictPoint(*c_iter);
1778: const int& dim = this->getFiberDimension(*c_iter);
1779: const int& cDim = this->getConstraintDimension(*c_iter);
1781: if (!cDim) {
1782: for(int i = 0; i < dim; ++i) {
1783: array[i] += alpha*xArray[i];
1784: }
1785: } else {
1786: const typename bc_type::value_type *cDof = this->getConstraintDof(*c_iter);
1787: int cInd = 0;
1789: for(int i = 0; i < dim; ++i) {
1790: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1791: array[i] += alpha*xArray[i];
1792: }
1793: }
1794: }
1795: };
1796: // Return the free values on a point
1797: const value_type *restrict() const {
1798: return this->_array;
1799: };
1800: // Return the free values on a point
1801: const value_type *restrictPoint(const point_type& p) const {
1802: return &(this->_array[this->_atlas->restrictPoint(p)[0].index]);
1803: };
1804: // Update the free values on a point
1805: // Takes a full array and ignores constrained values
1806: void updatePoint(const point_type& p, const value_type v[], const int orientation = 1) {
1807: value_type *array = (value_type *) this->restrictPoint(p);
1808: const int& cDim = this->getConstraintDimension(p);
1810: if (!cDim) {
1811: if (orientation >= 0) {
1812: const int& dim = this->getFiberDimension(p);
1814: for(int i = 0; i < dim; ++i) {
1815: array[i] = v[i];
1816: }
1817: } else {
1818: int offset = 0;
1819: int j = -1;
1821: for(int space = 0; space < this->getNumSpaces(); ++space) {
1822: const int& dim = this->getFiberDimension(p, space);
1824: for(int i = dim-1; i >= 0; --i) {
1825: array[++j] = v[i+offset];
1826: }
1827: offset += dim;
1828: }
1829: }
1830: } else {
1831: if (orientation >= 0) {
1832: const int& dim = this->getFiberDimension(p);
1833: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1834: int cInd = 0;
1836: for(int i = 0; i < dim; ++i) {
1837: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1838: array[i] = v[i];
1839: }
1840: } else {
1841: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1842: int offset = 0;
1843: int cOffset = 0;
1844: int j = 0;
1846: for(int space = 0; space < this->getNumSpaces(); ++space) {
1847: const int dim = this->getFiberDimension(p, space);
1848: const int tDim = this->getConstrainedFiberDimension(p, space);
1849: const int sDim = dim - tDim;
1850: int cInd = 0;
1852: for(int i = 0, k = dim+offset-1; i < dim; ++i, ++j, --k) {
1853: if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;}
1854: array[j] = v[k];
1855: }
1856: offset += dim;
1857: cOffset += dim - tDim;
1858: }
1859: }
1860: }
1861: };
1862: // Update the free values on a point
1863: // Takes a full array and ignores constrained values
1864: void updateAddPoint(const point_type& p, const value_type v[], const int orientation = 1) {
1865: value_type *array = (value_type *) this->restrictPoint(p);
1866: const int& cDim = this->getConstraintDimension(p);
1868: if (!cDim) {
1869: if (orientation >= 0) {
1870: const int& dim = this->getFiberDimension(p);
1872: for(int i = 0; i < dim; ++i) {
1873: array[i] += v[i];
1874: }
1875: } else {
1876: int offset = 0;
1877: int j = -1;
1879: for(int space = 0; space < this->getNumSpaces(); ++space) {
1880: const int& dim = this->getFiberDimension(p, space);
1882: for(int i = dim-1; i >= 0; --i) {
1883: array[++j] += v[i+offset];
1884: }
1885: offset += dim;
1886: }
1887: }
1888: } else {
1889: if (orientation >= 0) {
1890: const int& dim = this->getFiberDimension(p);
1891: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1892: int cInd = 0;
1894: for(int i = 0; i < dim; ++i) {
1895: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1896: array[i] += v[i];
1897: }
1898: } else {
1899: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1900: int offset = 0;
1901: int cOffset = 0;
1902: int j = 0;
1904: for(int space = 0; space < this->getNumSpaces(); ++space) {
1905: const int dim = this->getFiberDimension(p, space);
1906: const int tDim = this->getConstrainedFiberDimension(p, space);
1907: const int sDim = dim - tDim;
1908: int cInd = 0;
1910: for(int i = 0, k = dim+offset-1; i < dim; ++i, ++j, --k) {
1911: if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;}
1912: array[j] += v[k];
1913: }
1914: offset += dim;
1915: cOffset += dim - tDim;
1916: }
1917: }
1918: }
1919: };
1920: // Update the free values on a point
1921: // Takes ONLY unconstrained values
1922: void updateFreePoint(const point_type& p, const value_type v[], const int orientation = 1) {
1923: value_type *array = (value_type *) this->restrictPoint(p);
1924: const int& cDim = this->getConstraintDimension(p);
1926: if (!cDim) {
1927: if (orientation >= 0) {
1928: const int& dim = this->getFiberDimension(p);
1930: for(int i = 0; i < dim; ++i) {
1931: array[i] = v[i];
1932: }
1933: } else {
1934: int offset = 0;
1935: int j = -1;
1937: for(int space = 0; space < this->getNumSpaces(); ++space) {
1938: const int& dim = this->getFiberDimension(p, space);
1940: for(int i = dim-1; i >= 0; --i) {
1941: array[++j] = v[i+offset];
1942: }
1943: offset += dim;
1944: }
1945: }
1946: } else {
1947: if (orientation >= 0) {
1948: const int& dim = this->getFiberDimension(p);
1949: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1950: int cInd = 0;
1952: for(int i = 0, k = -1; i < dim; ++i) {
1953: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1954: array[i] = v[++k];
1955: }
1956: } else {
1957: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1958: int offset = 0;
1959: int cOffset = 0;
1960: int j = 0;
1962: for(int space = 0; space < this->getNumSpaces(); ++space) {
1963: const int dim = this->getFiberDimension(p, space);
1964: const int tDim = this->getConstrainedFiberDimension(p, space);
1965: const int sDim = dim - tDim;
1966: int cInd = 0;
1968: for(int i = 0, k = tDim+offset-1; i < dim; ++i, ++j) {
1969: if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;}
1970: array[j] = v[--k];
1971: }
1972: offset += dim;
1973: cOffset += dim - tDim;
1974: }
1975: }
1976: }
1977: };
1978: // Update the free values on a point
1979: // Takes ONLY unconstrained values
1980: void updateFreeAddPoint(const point_type& p, const value_type v[], const int orientation = 1) {
1981: value_type *array = (value_type *) this->restrictPoint(p);
1982: const int& cDim = this->getConstraintDimension(p);
1984: if (!cDim) {
1985: if (orientation >= 0) {
1986: const int& dim = this->getFiberDimension(p);
1988: for(int i = 0; i < dim; ++i) {
1989: array[i] += v[i];
1990: }
1991: } else {
1992: int offset = 0;
1993: int j = -1;
1995: for(int space = 0; space < this->getNumSpaces(); ++space) {
1996: const int& dim = this->getFiberDimension(p, space);
1998: for(int i = dim-1; i >= 0; --i) {
1999: array[++j] += v[i+offset];
2000: }
2001: offset += dim;
2002: }
2003: }
2004: } else {
2005: if (orientation >= 0) {
2006: const int& dim = this->getFiberDimension(p);
2007: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
2008: int cInd = 0;
2010: for(int i = 0, k = -1; i < dim; ++i) {
2011: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
2012: array[i] += v[++k];
2013: }
2014: } else {
2015: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
2016: int offset = 0;
2017: int cOffset = 0;
2018: int j = 0;
2020: for(int space = 0; space < this->getNumSpaces(); ++space) {
2021: const int dim = this->getFiberDimension(p, space);
2022: const int tDim = this->getConstrainedFiberDimension(p, space);
2023: const int sDim = dim - tDim;
2024: int cInd = 0;
2026: for(int i = 0, k = tDim+offset-1; i < dim; ++i, ++j) {
2027: if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;}
2028: array[j] += v[--k];
2029: }
2030: offset += dim;
2031: cOffset += dim - tDim;
2032: }
2033: }
2034: }
2035: };
2036: // Update only the constrained dofs on a point
2037: // This takes an array with ONLY bc values
2038: void updatePointBC(const point_type& p, const value_type v[], const int orientation = 1) {
2039: value_type *array = (value_type *) this->restrictPoint(p);
2040: const int& cDim = this->getConstraintDimension(p);
2042: if (cDim) {
2043: if (orientation >= 0) {
2044: const int& dim = this->getFiberDimension(p);
2045: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
2046: int cInd = 0;
2048: for(int i = 0; i < dim; ++i) {
2049: if (cInd == cDim) break;
2050: if (i == cDof[cInd]) {
2051: array[i] = v[cInd];
2052: ++cInd;
2053: }
2054: }
2055: } else {
2056: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
2057: int cOffset = 0;
2058: int j = 0;
2060: for(int space = 0; space < this->getNumSpaces(); ++space) {
2061: const int dim = this->getFiberDimension(p, space);
2062: const int tDim = this->getConstrainedFiberDimension(p, space);
2063: int cInd = 0;
2065: for(int i = 0; i < dim; ++i, ++j) {
2066: if (cInd < 0) break;
2067: if (j == cDof[cInd+cOffset]) {
2068: array[j] = v[cInd+cOffset];
2069: ++cInd;
2070: }
2071: }
2072: cOffset += dim - tDim;
2073: }
2074: }
2075: }
2076: };
2077: // Update only the constrained dofs on a point
2078: // This takes an array with ALL values, not just BC
2079: void updatePointBCFull(const point_type& p, const value_type v[], const int orientation = 1) {
2080: value_type *array = (value_type *) this->restrictPoint(p);
2081: const int& cDim = this->getConstraintDimension(p);
2083: if (cDim) {
2084: if (orientation >= 0) {
2085: const int& dim = this->getFiberDimension(p);
2086: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
2087: int cInd = 0;
2089: for(int i = 0; i < dim; ++i) {
2090: if (cInd == cDim) break;
2091: if (i == cDof[cInd]) {
2092: array[i] = v[i];
2093: ++cInd;
2094: }
2095: }
2096: } else {
2097: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
2098: int offset = 0;
2099: int cOffset = 0;
2100: int j = 0;
2102: for(int space = 0; space < this->getNumSpaces(); ++space) {
2103: const int dim = this->getFiberDimension(p, space);
2104: const int tDim = this->getConstrainedFiberDimension(p, space);
2105: int cInd = 0;
2107: for(int i = 0, k = dim+offset-1; i < dim; ++i, ++j, --k) {
2108: if (cInd < 0) break;
2109: if (j == cDof[cInd+cOffset]) {
2110: array[j] = v[k];
2111: ++cInd;
2112: }
2113: }
2114: offset += dim;
2115: cOffset += dim - tDim;
2116: }
2117: }
2118: }
2119: };
2120: // Update all dofs on a point (free and constrained)
2121: void updatePointAll(const point_type& p, const value_type v[], const int orientation = 1) {
2122: value_type *array = (value_type *) this->restrictPoint(p);
2124: if (orientation >= 0) {
2125: const int& dim = this->getFiberDimension(p);
2127: for(int i = 0; i < dim; ++i) {
2128: array[i] = v[i];
2129: }
2130: } else {
2131: int offset = 0;
2132: int j = -1;
2134: for(int space = 0; space < this->getNumSpaces(); ++space) {
2135: const int& dim = this->getFiberDimension(p, space);
2137: for(int i = dim-1; i >= 0; --i) {
2138: array[++j] = v[i+offset];
2139: }
2140: offset += dim;
2141: }
2142: }
2143: };
2144: // Update all dofs on a point (free and constrained)
2145: void updatePointAllAdd(const point_type& p, const value_type v[], const int orientation = 1) {
2146: value_type *array = (value_type *) this->restrictPoint(p);
2148: if (orientation >= 0) {
2149: const int& dim = this->getFiberDimension(p);
2151: for(int i = 0; i < dim; ++i) {
2152: array[i] += v[i];
2153: }
2154: } else {
2155: int offset = 0;
2156: int j = -1;
2158: for(int space = 0; space < this->getNumSpaces(); ++space) {
2159: const int& dim = this->getFiberDimension(p, space);
2161: for(int i = dim-1; i >= 0; --i) {
2162: array[++j] += v[i+offset];
2163: }
2164: offset += dim;
2165: }
2166: }
2167: };
2168: public: // Fibrations
2169: int getNumSpaces() const {return this->_spaces.size();};
2170: const std::vector<Obj<atlas_type> >& getSpaces() {return this->_spaces;};
2171: const std::vector<Obj<bc_type> >& getBCs() {return this->_bcs;};
2172: void addSpace() {
2173: Obj<atlas_type> space = new atlas_type(this->comm(), this->debug());
2174: Obj<bc_type> bc = new bc_type(this->comm(), this->debug());
2175: this->_spaces.push_back(space);
2176: this->_bcs.push_back(bc);
2177: };
2178: int getFiberDimension(const point_type& p, const int space) const {
2179: return this->_spaces[space]->restrictPoint(p)->prefix;
2180: };
2181: void setFiberDimension(const point_type& p, int dim, const int space) {
2182: const index_type idx(dim, -1);
2183: this->_spaces[space]->addPoint(p);
2184: this->_spaces[space]->updatePoint(p, &idx);
2185: };
2186: template<typename Sequence>
2187: void setFiberDimension(const Obj<Sequence>& points, int dim, const int space) {
2188: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
2189: this->setFiberDimension(*p_iter, dim, space);
2190: }
2191: };
2192: const int getConstraintDimension(const point_type& p, const int space) const {
2193: if (!this->_bcs[space]->hasPoint(p)) return 0;
2194: return this->_bcs[space]->getFiberDimension(p);
2195: };
2196: void setConstraintDimension(const point_type& p, const int numConstraints, const int space) {
2197: this->_bcs[space]->setFiberDimension(p, numConstraints);
2198: };
2199: int getConstrainedFiberDimension(const point_type& p, const int space) const {
2200: return this->getFiberDimension(p, space) - this->getConstraintDimension(p, space);
2201: };
2202: void copyFibration(const Obj<GeneralSection>& section) {
2203: const std::vector<Obj<atlas_type> >& spaces = section->getSpaces();
2204: const std::vector<Obj<bc_type> >& bcs = section->getBCs();
2206: this->_spaces.clear();
2207: for(typename std::vector<Obj<atlas_type> >::const_iterator s_iter = spaces.begin(); s_iter != spaces.end(); ++s_iter) {
2208: this->_spaces.push_back(*s_iter);
2209: }
2210: this->_bcs.clear();
2211: for(typename std::vector<Obj<bc_type> >::const_iterator b_iter = bcs.begin(); b_iter != bcs.end(); ++b_iter) {
2212: this->_bcs.push_back(*b_iter);
2213: }
2214: };
2215: Obj<GeneralSection> getFibration(const int space) const {
2216: Obj<GeneralSection> field = new GeneralSection(this->comm(), this->debug());
2217: // Obj<atlas_type> _atlas;
2218: // std::vector<Obj<atlas_type> > _spaces;
2219: // Obj<bc_type> _bc;
2220: // std::vector<Obj<bc_type> > _bcs;
2221: field->addSpace();
2222: const chart_type& chart = this->getChart();
2224: // Copy sizes
2225: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
2226: const int fDim = this->getFiberDimension(*c_iter, space);
2227: const int cDim = this->getConstraintDimension(*c_iter, space);
2229: if (fDim) {
2230: field->setFiberDimension(*c_iter, fDim);
2231: field->setFiberDimension(*c_iter, fDim, 0);
2232: }
2233: if (cDim) {
2234: field->setConstraintDimension(*c_iter, cDim);
2235: field->setConstraintDimension(*c_iter, cDim, 0);
2236: }
2237: }
2238: field->allocateStorage();
2239: Obj<atlas_type> newAtlas = new atlas_type(this->comm(), this->debug());
2240: const chart_type& newChart = field->getChart();
2242: for(typename chart_type::iterator c_iter = newChart.begin(); c_iter != newChart.end(); ++c_iter) {
2243: const int cDim = field->getConstraintDimension(*c_iter);
2244: const int dof[1] = {0};
2246: if (cDim) {
2247: field->setConstraintDof(*c_iter, dof);
2248: }
2249: }
2250: // Copy offsets
2251: for(typename chart_type::iterator c_iter = newChart.begin(); c_iter != newChart.end(); ++c_iter) {
2252: index_type idx;
2254: idx.prefix = field->getFiberDimension(*c_iter);
2255: idx.index = this->_atlas->restrictPoint(*c_iter)[0].index;
2256: for(int s = 0; s < space; ++s) {
2257: idx.index += this->getFiberDimension(*c_iter, s);
2258: }
2259: newAtlas->addPoint(*c_iter);
2260: newAtlas->updatePoint(*c_iter, &idx);
2261: }
2262: field->replaceStorage(this->_array, true, this->getStorageSize());
2263: field->setAtlas(newAtlas);
2264: return field;
2265: };
2266: public: // Optimization
2267: void getCustomRestrictAtlas(const int tag, const int *offsets[], const int *indices[]) {
2268: *offsets = this->_customRestrictAtlas[tag].first.first;
2269: *indices = this->_customRestrictAtlas[tag].first.second;
2270: };
2271: void getCustomUpdateAtlas(const int tag, const int *offsets[], const int *indices[]) {
2272: *offsets = this->_customUpdateAtlas[tag].first.first;
2273: *indices = this->_customUpdateAtlas[tag].first.second;
2274: };
2275: // This returns the tag assigned to the atlas
2276: int setCustomAtlas(const int restrictOffsets[], const int restrictIndices[], const int updateOffsets[], const int updateIndices[], bool autoFree = true) {
2277: this->_customRestrictAtlas.push_back(customAtlas_type(customAtlasInd_type(restrictOffsets, restrictIndices), autoFree));
2278: this->_customUpdateAtlas.push_back(customAtlas_type(customAtlasInd_type(updateOffsets, updateIndices), autoFree));
2279: return this->_customUpdateAtlas.size()-1;
2280: };
2281: int copyCustomAtlas(const Obj<GeneralSection>& section, const int tag) {
2282: const int *rOffsets, *rIndices, *uOffsets, *uIndices;
2284: section->getCustomRestrictAtlas(tag, &rOffsets, &rIndices);
2285: section->getCustomUpdateAtlas(tag, &uOffsets, &uIndices);
2286: return this->setCustomAtlas(rOffsets, rIndices, uOffsets, uIndices, false);
2287: };
2288: public:
2289: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
2290: ostringstream txt;
2291: int rank;
2293: if (comm == MPI_COMM_NULL) {
2294: comm = this->comm();
2295: rank = this->commRank();
2296: } else {
2297: MPI_Comm_rank(comm, &rank);
2298: }
2299: if (name == "") {
2300: if(rank == 0) {
2301: txt << "viewing a GeneralSection" << std::endl;
2302: }
2303: } else {
2304: if (rank == 0) {
2305: txt << "viewing GeneralSection '" << name << "'" << std::endl;
2306: }
2307: }
2308: if (rank == 0) {
2309: txt << " Fields: " << this->getNumSpaces() << std::endl;
2310: }
2311: const chart_type& chart = this->getChart();
2313: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
2314: const value_type *array = this->restrictPoint(*p_iter);
2315: const int& dim = this->getFiberDimension(*p_iter);
2317: if (dim != 0) {
2318: txt << "[" << this->commRank() << "]: " << *p_iter << " dim " << dim << " offset " << this->_atlas->restrictPoint(*p_iter)->index << " ";
2319: for(int i = 0; i < dim; i++) {
2320: txt << " " << array[i];
2321: }
2322: const int& dim = this->getConstraintDimension(*p_iter);
2324: if (dim) {
2325: const typename bc_type::value_type *bcArray = this->_bc->restrictPoint(*p_iter);
2327: txt << " constrained";
2328: for(int i = 0; i < dim; ++i) {
2329: txt << " " << bcArray[i];
2330: }
2331: }
2332: txt << std::endl;
2333: }
2334: }
2335: if (chart.size() == 0) {
2336: txt << "[" << this->commRank() << "]: empty" << std::endl;
2337: }
2338: PetscSynchronizedPrintf(comm, txt.str().c_str());
2339: PetscSynchronizedFlush(comm);
2340: };
2341: };
2342: // A Field combines several sections
2343: template<typename Overlap_, typename Patch_, typename Section_>
2344: class Field : public ALE::ParallelObject {
2345: public:
2346: typedef Overlap_ overlap_type;
2347: typedef Patch_ patch_type;
2348: typedef Section_ section_type;
2349: typedef typename section_type::point_type point_type;
2350: typedef typename section_type::chart_type chart_type;
2351: typedef typename section_type::value_type value_type;
2352: typedef std::map<patch_type, Obj<section_type> > sheaf_type;
2353: typedef enum {SEND, RECEIVE} request_type;
2354: typedef std::map<patch_type, MPI_Request> requests_type;
2355: protected:
2356: sheaf_type _sheaf;
2357: int _tag;
2358: MPI_Datatype _datatype;
2359: requests_type _requests;
2360: public:
2361: Field(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {
2362: this->_tag = this->getNewTag();
2363: this->_datatype = this->getMPIDatatype();
2364: };
2365: Field(MPI_Comm comm, const int tag, const int debug) : ParallelObject(comm, debug), _tag(tag) {
2366: this->_datatype = this->getMPIDatatype();
2367: };
2368: virtual ~Field() {};
2369: protected:
2370: MPI_Datatype getMPIDatatype() {
2371: if (sizeof(value_type) == 4) {
2372: return MPI_INT;
2373: } else if (sizeof(value_type) == 8) {
2374: return MPI_DOUBLE;
2375: } else if (sizeof(value_type) == 28) {
2376: int blen[2];
2377: MPI_Aint indices[2];
2378: MPI_Datatype oldtypes[2], newtype;
2379: blen[0] = 1; indices[0] = 0; oldtypes[0] = MPI_INT;
2380: blen[1] = 3; indices[1] = sizeof(int); oldtypes[1] = MPI_DOUBLE;
2381: MPI_Type_struct(2, blen, indices, oldtypes, &newtype);
2382: MPI_Type_commit(&newtype);
2383: return newtype;
2384: } else if (sizeof(value_type) == 32) {
2385: int blen[2];
2386: MPI_Aint indices[2];
2387: MPI_Datatype oldtypes[2], newtype;
2388: blen[0] = 1; indices[0] = 0; oldtypes[0] = MPI_DOUBLE;
2389: blen[1] = 3; indices[1] = sizeof(int); oldtypes[1] = MPI_DOUBLE;
2390: MPI_Type_struct(2, blen, indices, oldtypes, &newtype);
2391: MPI_Type_commit(&newtype);
2392: return newtype;
2393: }
2394: throw ALE::Exception("Cannot determine MPI type for value type");
2395: };
2396: int getNewTag() {
2397: static int tagKeyval = MPI_KEYVAL_INVALID;
2398: int *tagvalp = NULL, *maxval, flg;
2400: if (tagKeyval == MPI_KEYVAL_INVALID) {
2401: tagvalp = (int *) malloc(sizeof(int));
2402: MPI_Keyval_create(MPI_NULL_COPY_FN, Mesh_DelTag, &tagKeyval, (void *) NULL);
2403: MPI_Attr_put(this->_comm, tagKeyval, tagvalp);
2404: tagvalp[0] = 0;
2405: }
2406: MPI_Attr_get(this->_comm, tagKeyval, (void **) &tagvalp, &flg);
2407: if (tagvalp[0] < 1) {
2408: MPI_Attr_get(MPI_COMM_WORLD, MPI_TAG_UB, (void **) &maxval, &flg);
2409: tagvalp[0] = *maxval - 128; // hope that any still active tags were issued right at the beginning of the run
2410: }
2411: if (this->debug()) {
2412: std::cout << "[" << this->commRank() << "]Got new tag " << tagvalp[0] << std::endl;
2413: }
2414: return tagvalp[0]--;
2415: };
2416: public: // Verifiers
2417: void checkPatch(const patch_type& patch) const {
2418: if (this->_sheaf.find(patch) == this->_sheaf.end()) {
2419: ostringstream msg;
2420: msg << "Invalid field patch " << patch << std::endl;
2421: throw ALE::Exception(msg.str().c_str());
2422: }
2423: };
2424: bool hasPatch(const patch_type& patch) {
2425: if (this->_sheaf.find(patch) == this->_sheaf.end()) {
2426: return false;
2427: }
2428: return true;
2429: };
2430: public: // Accessors
2431: int getTag() const {return this->_tag;};
2432: void setTag(const int tag) {this->_tag = tag;};
2433: Obj<section_type>& getSection(const patch_type& patch) {
2434: if (this->_sheaf.find(patch) == this->_sheaf.end()) {
2435: this->_sheaf[patch] = new section_type(this->comm(), this->debug());
2436: }
2437: return this->_sheaf[patch];
2438: };
2439: void setSection(const patch_type& patch, const Obj<section_type>& section) {this->_sheaf[patch] = section;};
2440: const sheaf_type& getPatches() {
2441: return this->_sheaf;
2442: };
2443: void clear() {
2444: for(typename sheaf_type::const_iterator p_iter = this->_sheaf.begin(); p_iter != this->_sheaf.end(); ++p_iter) {
2445: p_iter->second->clear();
2446: }
2447: };
2448: public: // Adapter
2449: template<typename Topology_>
2450: void setTopology(const Obj<Topology_>& topology) {
2451: const typename Topology_::sheaf_type& patches = topology->getPatches();
2453: for(typename Topology_::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2454: int rank = p_iter->first;
2455: const Obj<section_type>& section = this->getSection(rank);
2456: const Obj<typename Topology_::sieve_type::baseSequence>& base = p_iter->second->base();
2458: for(typename Topology_::sieve_type::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
2459: section->setFiberDimension(*b_iter, 1);
2460: }
2461: }
2462: };
2463: void allocate() {
2464: for(typename sheaf_type::const_iterator p_iter = this->_sheaf.begin(); p_iter != this->_sheaf.end(); ++p_iter) {
2465: p_iter->second->allocatePoint();
2466: }
2467: };
2468: public: // Communication
2469: void construct(const int size) {
2470: const sheaf_type& patches = this->getPatches();
2472: for(typename sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2473: const patch_type rank = p_iter->first;
2474: const Obj<section_type>& section = this->getSection(rank);
2475: const chart_type& chart = section->getChart();
2477: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
2478: section->setFiberDimension(*c_iter, size);
2479: }
2480: }
2481: };
2482: template<typename Sizer>
2483: void construct(const Obj<Sizer>& sizer) {
2484: const sheaf_type& patches = this->getPatches();
2486: for(typename sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2487: const patch_type rank = p_iter->first;
2488: const Obj<section_type>& section = this->getSection(rank);
2489: const chart_type& chart = section->getChart();
2490:
2491: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
2492: section->setFiberDimension(*c_iter, *(sizer->getSection(rank)->restrictPoint(*c_iter)));
2493: }
2494: }
2495: };
2496: void constructCommunication(const request_type& requestType) {
2497: const sheaf_type& patches = this->getPatches();
2499: for(typename sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2500: const patch_type patch = p_iter->first;
2501: const Obj<section_type>& section = this->getSection(patch);
2502: MPI_Request request;
2504: if (requestType == RECEIVE) {
2505: if (this->_debug) {std::cout <<"["<<this->commRank()<<"] Receiving data(" << section->size() << ") from " << patch << " tag " << this->_tag << std::endl;}
2506: MPI_Recv_init((void *) section->restrict(), section->size(), this->_datatype, patch, this->_tag, this->comm(), &request);
2507: } else {
2508: if (this->_debug) {std::cout <<"["<<this->commRank()<<"] Sending data (" << section->size() << ") to " << patch << " tag " << this->_tag << std::endl;}
2509: MPI_Send_init((void *) section->restrict(), section->size(), this->_datatype, patch, this->_tag, this->comm(), &request);
2510: }
2511: this->_requests[patch] = request;
2512: }
2513: };
2514: void startCommunication() {
2515: const sheaf_type& patches = this->getPatches();
2517: for(typename sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2518: MPI_Request request = this->_requests[p_iter->first];
2520: MPI_Start(&request);
2521: }
2522: };
2523: void endCommunication() {
2524: const sheaf_type& patches = this->getPatches();
2525: MPI_Status status;
2527: for(typename sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2528: MPI_Request request = this->_requests[p_iter->first];
2530: MPI_Wait(&request, &status);
2531: }
2532: };
2533: public:
2534: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
2535: ostringstream txt;
2536: int rank;
2538: if (comm == MPI_COMM_NULL) {
2539: comm = this->comm();
2540: rank = this->commRank();
2541: } else {
2542: MPI_Comm_rank(comm, &rank);
2543: }
2544: if (name == "") {
2545: if(rank == 0) {
2546: txt << "viewing a Field" << std::endl;
2547: }
2548: } else {
2549: if(rank == 0) {
2550: txt << "viewing Field '" << name << "'" << std::endl;
2551: }
2552: }
2553: PetscSynchronizedPrintf(comm, txt.str().c_str());
2554: PetscSynchronizedFlush(comm);
2555: for(typename sheaf_type::const_iterator p_iter = this->_sheaf.begin(); p_iter != this->_sheaf.end(); ++p_iter) {
2556: ostringstream txt1;
2558: txt1 << "[" << this->commRank() << "]: Patch " << p_iter->first << std::endl;
2559: PetscSynchronizedPrintf(comm, txt1.str().c_str());
2560: PetscSynchronizedFlush(comm);
2561: p_iter->second->view("field section", comm);
2562: }
2563: };
2564: };
2565: }
2567: namespace ALECompat {
2568: namespace New {
2569: using ALE::Obj;
2570: // A ConstantSection is the simplest Section
2571: // All fibers are dimension 1
2572: // All values are equal to a constant
2573: // We need no value storage and no communication for completion
2574: template<typename Topology_, typename Value_>
2575: class NewConstantSection : public ALE::ParallelObject {
2576: public:
2577: typedef Topology_ topology_type;
2578: typedef typename topology_type::patch_type patch_type;
2579: typedef typename topology_type::sieve_type sieve_type;
2580: typedef typename topology_type::point_type point_type;
2581: typedef std::set<point_type> chart_type;
2582: typedef std::map<patch_type, chart_type> atlas_type;
2583: typedef Value_ value_type;
2584: protected:
2585: Obj<topology_type> _topology;
2586: atlas_type _atlas;
2587: chart_type _emptyChart;
2588: value_type _value;
2589: value_type _defaultValue;
2590: public:
2591: NewConstantSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug), _defaultValue(0) {
2592: this->_topology = new topology_type(comm, debug);
2593: };
2594: NewConstantSection(const Obj<topology_type>& topology) : ParallelObject(topology->comm(), topology->debug()), _topology(topology) {};
2595: NewConstantSection(const Obj<topology_type>& topology, const value_type& value) : ParallelObject(topology->comm(), topology->debug()), _topology(topology), _value(value), _defaultValue(value) {};
2596: NewConstantSection(const Obj<topology_type>& topology, const value_type& value, const value_type& defaultValue) : ParallelObject(topology->comm(), topology->debug()), _topology(topology), _value(value), _defaultValue(defaultValue) {};
2597: public: // Verifiers
2598: void checkPatch(const patch_type& patch) const {
2599: this->_topology->checkPatch(patch);
2600: if (this->_atlas.find(patch) == this->_atlas.end()) {
2601: ostringstream msg;
2602: msg << "Invalid atlas patch " << patch << std::endl;
2603: throw ALE::Exception(msg.str().c_str());
2604: }
2605: };
2606: void checkPoint(const patch_type& patch, const point_type& point) const {
2607: this->checkPatch(patch);
2608: if (this->_atlas.find(patch)->second.find(point) == this->_atlas.find(patch)->second.end()) {
2609: ostringstream msg;
2610: msg << "Invalid section point " << point << std::endl;
2611: throw ALE::Exception(msg.str().c_str());
2612: }
2613: };
2614: void checkDimension(const int& dim) {
2615: if (dim != 1) {
2616: ostringstream msg;
2617: msg << "Invalid fiber dimension " << dim << " must be 1" << std::endl;
2618: throw ALE::Exception(msg.str().c_str());
2619: }
2620: };
2621: bool hasPatch(const patch_type& patch) {
2622: if (this->_atlas.find(patch) == this->_atlas.end()) {
2623: return false;
2624: }
2625: return true;
2626: };
2627: bool hasPoint(const patch_type& patch, const point_type& point) const {
2628: this->checkPatch(patch);
2629: return this->_atlas.find(patch)->second.count(point) > 0;
2630: };
2631: bool hasPoint(const point_type& point) const {
2632: this->checkPatch(0);
2633: return this->_atlas.find(0)->second.count(point) > 0;
2634: };
2635: public: // Accessors
2636: const Obj<topology_type>& getTopology() const {return this->_topology;};
2637: void setTopology(const Obj<topology_type>& topology) {this->_topology = topology;};
2638: const chart_type& getPatch(const patch_type& patch) {
2639: if (this->hasPatch(patch)) {
2640: return this->_atlas[patch];
2641: }
2642: return this->_emptyChart;
2643: };
2644: void updatePatch(const patch_type& patch, const point_type& point) {
2645: this->_atlas[patch].insert(point);
2646: };
2647: template<typename Points>
2648: void updatePatch(const patch_type& patch, const Obj<Points>& points) {
2649: this->_atlas[patch].insert(points->begin(), points->end());
2650: };
2651: value_type getDefaultValue() {return this->_defaultValue;};
2652: void setDefaultValue(const value_type value) {this->_defaultValue = value;};
2653: public: // Sizes
2654: void clear() {
2655: this->_atlas.clear();
2656: };
2657: int getFiberDimension(const patch_type& patch, const point_type& p) const {
2658: if (this->hasPoint(patch, p)) return 1;
2659: return 0;
2660: };
2661: void setFiberDimension(const patch_type& patch, const point_type& p, int dim) {
2662: this->checkDimension(dim);
2663: this->updatePatch(patch, p);
2664: };
2665: template<typename Sequence>
2666: void setFiberDimension(const patch_type& patch, const Obj<Sequence>& points, int dim) {
2667: for(typename topology_type::label_sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
2668: this->setFiberDimension(patch, *p_iter, dim);
2669: }
2670: };
2671: void addFiberDimension(const patch_type& patch, const point_type& p, int dim) {
2672: if (this->hasPatch(patch) && (this->_atlas[patch].find(p) != this->_atlas[patch].end())) {
2673: ostringstream msg;
2674: msg << "Invalid addition to fiber dimension " << dim << " cannot exceed 1" << std::endl;
2675: throw ALE::Exception(msg.str().c_str());
2676: } else {
2677: this->setFiberDimension(patch, p, dim);
2678: }
2679: };
2680: void setFiberDimensionByDepth(const patch_type& patch, int depth, int dim) {
2681: this->setFiberDimension(patch, this->_topology->getLabelStratum(patch, "depth", depth), dim);
2682: };
2683: void setFiberDimensionByHeight(const patch_type& patch, int height, int dim) {
2684: this->setFiberDimension(patch, this->_topology->getLabelStratum(patch, "height", height), dim);
2685: };
2686: int size(const patch_type& patch) {return this->_atlas[patch].size();};
2687: int size(const patch_type& patch, const point_type& p) {return this->getFiberDimension(patch, p);};
2688: public: // Restriction
2689: const value_type *restrict(const patch_type& patch, const point_type& p) const {
2690: //std::cout <<"["<<this->commRank()<<"]: Constant restrict ("<<patch<<","<<p<<") from " << std::endl;
2691: //for(typename chart_type::iterator c_iter = this->_atlas.find(patch)->second.begin(); c_iter != this->_atlas.find(patch)->second.end(); ++c_iter) {
2692: // std::cout <<"["<<this->commRank()<<"]: point " << *c_iter << std::endl;
2693: //}
2694: if (this->hasPoint(patch, p)) {
2695: return &this->_value;
2696: }
2697: return &this->_defaultValue;
2698: };
2699: const value_type *restrictPoint(const patch_type& patch, const point_type& p) const {return this->restrict(patch, p);};
2700: const value_type *restrictPoint(const point_type& p) const {return this->restrict(0, p);};
2701: void update(const patch_type& patch, const point_type& p, const value_type v[]) {
2702: this->checkPatch(patch);
2703: this->_value = v[0];
2704: };
2705: void updatePoint(const patch_type& patch, const point_type& p, const value_type v[]) {return this->update(patch, p, v);};
2706: void updateAdd(const patch_type& patch, const point_type& p, const value_type v[]) {
2707: this->checkPatch(patch);
2708: this->_value += v[0];
2709: };
2710: void updateAddPoint(const patch_type& patch, const point_type& p, const value_type v[]) {return this->updateAdd(patch, p, v);};
2711: public:
2712: void copy(const Obj<NewConstantSection>& section) {
2713: const typename topology_type::sheaf_type& patches = this->_topology->getPatches();
2715: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2716: const patch_type& patch = p_iter->first;
2717: if (!section->hasPatch(patch)) continue;
2718: const chart_type& chart = section->getPatch(patch);
2720: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
2721: this->updatePatch(patch, *c_iter);
2722: }
2723: this->_value = section->restrict(patch, *chart.begin())[0];
2724: }
2725: };
2726: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
2727: ostringstream txt;
2728: int rank;
2730: if (comm == MPI_COMM_NULL) {
2731: comm = this->comm();
2732: rank = this->commRank();
2733: } else {
2734: MPI_Comm_rank(comm, &rank);
2735: }
2736: if (name == "") {
2737: if(rank == 0) {
2738: txt << "viewing a NewConstantSection" << std::endl;
2739: }
2740: } else {
2741: if(rank == 0) {
2742: txt << "viewing NewConstantSection '" << name << "'" << std::endl;
2743: }
2744: }
2745: const typename topology_type::sheaf_type& sheaf = this->_topology->getPatches();
2747: for(typename topology_type::sheaf_type::const_iterator p_iter = sheaf.begin(); p_iter != sheaf.end(); ++p_iter) {
2748: txt <<"["<<this->commRank()<<"]: Patch " << p_iter->first << std::endl;
2749: txt <<"["<<this->commRank()<<"]: Value " << this->_value << std::endl;
2750: }
2751: PetscSynchronizedPrintf(comm, txt.str().c_str());
2752: PetscSynchronizedFlush(comm);
2753: };
2754: };
2756: // A UniformSection often acts as an Atlas
2757: // All fibers are the same dimension
2758: // Note we can use a ConstantSection for this Atlas
2759: // Each point may have a different vector
2760: // Thus we need storage for values, and hence must implement completion
2761: template<typename Topology_, typename Value_, int fiberDim = 1>
2762: class UniformSection : public ALE::ParallelObject {
2763: public:
2764: typedef Topology_ topology_type;
2765: typedef typename topology_type::patch_type patch_type;
2766: typedef typename topology_type::sieve_type sieve_type;
2767: typedef typename topology_type::point_type point_type;
2768: typedef NewConstantSection<topology_type, int> atlas_type;
2769: typedef typename atlas_type::chart_type chart_type;
2770: typedef Value_ value_type;
2771: typedef struct {value_type v[fiberDim];} fiber_type;
2772: typedef std::map<point_type, fiber_type> array_type;
2773: typedef std::map<patch_type, array_type> values_type;
2774: protected:
2775: Obj<atlas_type> _atlas;
2776: values_type _arrays;
2777: public:
2778: UniformSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {
2779: this->_atlas = new atlas_type(comm, debug);
2780: };
2781: UniformSection(const Obj<topology_type>& topology) : ParallelObject(topology->comm(), topology->debug()) {
2782: this->_atlas = new atlas_type(topology, fiberDim, 0);
2783: };
2784: UniformSection(const Obj<atlas_type>& atlas) : ParallelObject(atlas->comm(), atlas->debug()), _atlas(atlas) {};
2785: protected:
2786: value_type *getRawArray(const int size) {
2787: static value_type *array = NULL;
2788: static int maxSize = 0;
2790: if (size > maxSize) {
2791: maxSize = size;
2792: if (array) delete [] array;
2793: array = new value_type[maxSize];
2794: };
2795: return array;
2796: };
2797: public: // Verifiers
2798: void checkPatch(const patch_type& patch) {
2799: this->_atlas->checkPatch(patch);
2800: if (this->_arrays.find(patch) == this->_arrays.end()) {
2801: ostringstream msg;
2802: msg << "Invalid section patch: " << patch << std::endl;
2803: throw ALE::Exception(msg.str().c_str());
2804: }
2805: };
2806: bool hasPatch(const patch_type& patch) {
2807: return this->_atlas->hasPatch(patch);
2808: };
2809: bool hasPoint(const patch_type& patch, const point_type& point) {
2810: return this->_atlas->hasPoint(patch, point);
2811: };
2812: bool hasPoint(const point_type& point) {
2813: return this->_atlas->hasPoint(0, point);
2814: };
2815: void checkDimension(const int& dim) {
2816: if (dim != fiberDim) {
2817: ostringstream msg;
2818: msg << "Invalid fiber dimension " << dim << " must be " << fiberDim << std::endl;
2819: throw ALE::Exception(msg.str().c_str());
2820: }
2821: };
2822: public: // Accessors
2823: const Obj<atlas_type>& getAtlas() {return this->_atlas;};
2824: void setAtlas(const Obj<atlas_type>& atlas) {this->_atlas = atlas;};
2825: const Obj<topology_type>& getTopology() {return this->_atlas->getTopology();};
2826: void setTopology(const Obj<topology_type>& topology) {this->_atlas->setTopology(topology);};
2827: const chart_type& getPatch(const patch_type& patch) {
2828: return this->_atlas->getPatch(patch);
2829: };
2830: void updatePatch(const patch_type& patch, const point_type& point) {
2831: this->setFiberDimension(patch, point, 1);
2832: };
2833: template<typename Points>
2834: void updatePatch(const patch_type& patch, const Obj<Points>& points) {
2835: for(typename Points::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
2836: this->setFiberDimension(patch, *p_iter, 1);
2837: }
2838: };
2839: void copy(const Obj<UniformSection<Topology_, Value_, fiberDim> >& section) {
2840: this->getAtlas()->copy(section->getAtlas());
2841: const typename topology_type::sheaf_type& sheaf = section->getTopology()->getPatches();
2843: for(typename topology_type::sheaf_type::const_iterator s_iter = sheaf.begin(); s_iter != sheaf.end(); ++s_iter) {
2844: const patch_type& patch = s_iter->first;
2845: if (!section->hasPatch(patch)) continue;
2846: const chart_type& chart = section->getPatch(patch);
2848: for(typename chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
2849: this->updatePoint(s_iter->first, *c_iter, section->restrictPoint(s_iter->first, *c_iter));
2850: }
2851: }
2852: };
2853: public: // Sizes
2854: void clear() {
2855: this->_atlas->clear();
2856: this->_arrays.clear();
2857: };
2858: int getFiberDimension(const patch_type& patch, const point_type& p) const {
2859: // Could check for non-existence here
2860: return this->_atlas->restrictPoint(patch, p)[0];
2861: };
2862: void setFiberDimension(const patch_type& patch, const point_type& p, int dim) {
2863: this->checkDimension(dim);
2864: this->_atlas->updatePatch(patch, p);
2865: this->_atlas->updatePoint(patch, p, &dim);
2866: };
2867: template<typename Sequence>
2868: void setFiberDimension(const patch_type& patch, const Obj<Sequence>& points, int dim) {
2869: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
2870: this->setFiberDimension(patch, *p_iter, dim);
2871: }
2872: };
2873: void setFiberDimension(const patch_type& patch, const std::set<point_type>& points, int dim) {
2874: for(typename std::set<point_type>::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
2875: this->setFiberDimension(patch, *p_iter, dim);
2876: }
2877: };
2878: void addFiberDimension(const patch_type& patch, const point_type& p, int dim) {
2879: if (this->hasPatch(patch) && (this->_atlas[patch].find(p) != this->_atlas[patch].end())) {
2880: ostringstream msg;
2881: msg << "Invalid addition to fiber dimension " << dim << " cannot exceed " << fiberDim << std::endl;
2882: throw ALE::Exception(msg.str().c_str());
2883: } else {
2884: this->setFiberDimension(patch, p, dim);
2885: }
2886: };
2887: void setFiberDimensionByDepth(const patch_type& patch, int depth, int dim) {
2888: this->setFiberDimension(patch, this->getTopology()->getLabelStratum(patch, "depth", depth), dim);
2889: };
2890: void setFiberDimensionByHeight(const patch_type& patch, int height, int dim) {
2891: this->setFiberDimension(patch, this->getTopology()->getLabelStratum(patch, "height", height), dim);
2892: };
2893: int size(const patch_type& patch) {
2894: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
2895: int size = 0;
2897: for(typename atlas_type::chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
2898: size += this->getFiberDimension(patch, *p_iter);
2899: }
2900: return size;
2901: };
2902: int size(const patch_type& patch, const point_type& p) {
2903: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
2904: const Obj<typename sieve_type::coneSet> closure = this->getTopology()->getPatch(patch)->closure(p);
2905: typename sieve_type::coneSet::iterator end = closure->end();
2906: int size = 0;
2908: for(typename sieve_type::coneSet::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
2909: if (points.count(*c_iter)) {
2910: size += this->getFiberDimension(patch, *c_iter);
2911: }
2912: }
2913: return size;
2914: };
2915: void orderPatches() {};
2916: public: // Restriction
2917: // Return a pointer to the entire contiguous storage array
2918: const array_type& restrict(const patch_type& patch) {
2919: this->checkPatch(patch);
2920: return this->_arrays[patch];
2921: };
2922: // Return the values for the closure of this point
2923: // use a smart pointer?
2924: const value_type *restrict(const patch_type& patch, const point_type& p) {
2925: this->checkPatch(patch);
2926: const chart_type& chart = this->getPatch(patch);
2927: array_type& array = this->_arrays[patch];
2928: const int size = this->size(patch, p);
2929: value_type *values = this->getRawArray(size);
2930: int j = -1;
2932: // We could actually ask for the height of the individual point
2933: if (this->getTopology()->height(patch) < 2) {
2934: // Avoids only the copy of closure()
2935: const int& dim = this->_atlas->restrictPoint(patch, p)[0];
2937: if (chart.count(p)) {
2938: for(int i = 0; i < dim; ++i) {
2939: values[++j] = array[p].v[i];
2940: }
2941: }
2942: // Need only the cone
2943: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
2944: typename sieve_type::coneSequence::iterator end = cone->end();
2946: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
2947: if (chart.count(*p_iter)) {
2948: const int& dim = this->_atlas->restrictPoint(patch, *p_iter)[0];
2950: for(int i = 0; i < dim; ++i) {
2951: values[++j] = array[*p_iter].v[i];
2952: }
2953: }
2954: }
2955: } else {
2956: // Right now, we have no way of consistently ordering the closure()
2957: const Obj<typename sieve_type::coneSet>& closure = this->getTopology()->getPatch(patch)->closure(p);
2958: typename sieve_type::coneSet::iterator end = closure->end();
2960: for(typename sieve_type::coneSet::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
2961: if (chart.count(*p_iter)) {
2962: const int& dim = this->_atlas->restrictPoint(patch, *p_iter)[0];
2964: for(int i = 0; i < dim; ++i) {
2965: values[++j] = array[*p_iter].v[i];
2966: }
2967: }
2968: }
2969: }
2970: if (j != size-1) {
2971: ostringstream txt;
2973: txt << "Invalid restrict to point " << p << std::endl;
2974: txt << " j " << j << " should be " << (size-1) << std::endl;
2975: std::cout << txt.str();
2976: throw ALE::Exception(txt.str().c_str());
2977: }
2978: return values;
2979: };
2980: void update(const patch_type& patch, const point_type& p, const value_type v[]) {
2981: this->_atlas->checkPatch(patch);
2982: const chart_type& chart = this->getPatch(patch);
2983: array_type& array = this->_arrays[patch];
2984: int j = -1;
2986: if (this->getTopology()->height(patch) < 2) {
2987: // Only avoids the copy of closure()
2988: const int& dim = this->_atlas->restrict(patch, p)[0];
2990: if (chart.count(p)) {
2991: for(int i = 0; i < dim; ++i) {
2992: array[p].v[i] = v[++j];
2993: }
2994: }
2995: // Should be closure()
2996: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
2998: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
2999: if (chart.count(*p_iter)) {
3000: const int& dim = this->_atlas->restrict(patch, *p_iter)[0];
3002: for(int i = 0; i < dim; ++i) {
3003: array[*p_iter].v[i] = v[++j];
3004: }
3005: }
3006: }
3007: } else {
3008: throw ALE::Exception("Update is not yet implemented for interpolated sieves");
3009: }
3010: };
3011: void updateAdd(const patch_type& patch, const point_type& p, const value_type v[]) {
3012: this->_atlas->checkPatch(patch);
3013: const chart_type& chart = this->getPatch(patch);
3014: array_type& array = this->_arrays[patch];
3015: int j = -1;
3017: if (this->getTopology()->height(patch) < 2) {
3018: // Only avoids the copy of closure()
3019: const int& dim = this->_atlas->restrict(patch, p)[0];
3021: if (chart.count(p)) {
3022: for(int i = 0; i < dim; ++i) {
3023: array[p].v[i] += v[++j];
3024: }
3025: }
3026: // Should be closure()
3027: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3029: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
3030: if (chart.count(*p_iter)) {
3031: const int& dim = this->_atlas->restrict(patch, *p_iter)[0];
3033: for(int i = 0; i < dim; ++i) {
3034: array[*p_iter].v[i] += v[++j];
3035: }
3036: }
3037: }
3038: } else {
3039: throw ALE::Exception("Not yet implemented for interpolated sieves");
3040: }
3041: };
3042: // Return only the values associated to this point, not its closure
3043: const value_type *restrictPoint(const patch_type& patch, const point_type& p) {
3044: this->checkPatch(patch);
3045: return this->_arrays[patch][p].v;
3046: };
3047: const value_type *restrictPoint(const point_type& p) {
3048: this->checkPatch(0);
3049: return this->_arrays[0][p].v;
3050: };
3051: // Update only the values associated to this point, not its closure
3052: void updatePoint(const patch_type& patch, const point_type& p, const value_type v[]) {
3053: this->_atlas->checkPatch(patch);
3054: for(int i = 0; i < fiberDim; ++i) {
3055: this->_arrays[patch][p].v[i] = v[i];
3056: }
3057: };
3058: // Update only the values associated to this point, not its closure
3059: void updateAddPoint(const patch_type& patch, const point_type& p, const value_type v[]) {
3060: this->_atlas->checkPatch(patch);
3061: for(int i = 0; i < fiberDim; ++i) {
3062: this->_arrays[patch][p].v[i] += v[i];
3063: }
3064: };
3065: public:
3066: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
3067: ostringstream txt;
3068: int rank;
3070: if (comm == MPI_COMM_NULL) {
3071: comm = this->comm();
3072: rank = this->commRank();
3073: } else {
3074: MPI_Comm_rank(comm, &rank);
3075: }
3076: if (name == "") {
3077: if(rank == 0) {
3078: txt << "viewing a UniformSection" << std::endl;
3079: }
3080: } else {
3081: if(rank == 0) {
3082: txt << "viewing UniformSection '" << name << "'" << std::endl;
3083: }
3084: }
3085: for(typename values_type::const_iterator a_iter = this->_arrays.begin(); a_iter != this->_arrays.end(); ++a_iter) {
3086: const patch_type& patch = a_iter->first;
3087: array_type& array = this->_arrays[patch];
3089: txt << "[" << this->commRank() << "]: Patch " << patch << std::endl;
3090: const typename atlas_type::chart_type& chart = this->_atlas->getPatch(patch);
3092: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
3093: const point_type& point = *p_iter;
3094: const typename atlas_type::value_type dim = this->_atlas->restrict(patch, point)[0];
3096: if (dim != 0) {
3097: txt << "[" << this->commRank() << "]: " << point << " dim " << dim << " ";
3098: for(int i = 0; i < dim; i++) {
3099: txt << " " << array[point].v[i];
3100: }
3101: txt << std::endl;
3102: }
3103: }
3104: }
3105: PetscSynchronizedPrintf(comm, txt.str().c_str());
3106: PetscSynchronizedFlush(comm);
3107: };
3108: };
3110: // A Section is our most general construct (more general ones could be envisioned)
3111: // The Atlas is a UniformSection of dimension 1 and value type Point
3112: // to hold each fiber dimension and offsets into a contiguous patch array
3113: template<typename Topology_, typename Value_>
3114: class Section : public ALE::ParallelObject {
3115: public:
3116: typedef Topology_ topology_type;
3117: typedef typename topology_type::patch_type patch_type;
3118: typedef typename topology_type::sieve_type sieve_type;
3119: typedef typename topology_type::point_type point_type;
3120: typedef ALE::Point index_type;
3121: typedef UniformSection<topology_type, index_type> atlas_type;
3122: typedef typename atlas_type::chart_type chart_type;
3123: typedef Value_ value_type;
3124: typedef value_type * array_type;
3125: typedef std::map<patch_type, array_type> values_type;
3126: typedef std::vector<index_type> IndexArray;
3127: protected:
3128: Obj<atlas_type> _atlas;
3129: Obj<atlas_type> _atlasNew;
3130: values_type _arrays;
3131: Obj<IndexArray> _indexArray;
3132: public:
3133: Section(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {
3134: this->_atlas = new atlas_type(comm, debug);
3135: this->_atlasNew = NULL;
3136: this->_indexArray = new IndexArray();
3137: };
3138: Section(const Obj<topology_type>& topology) : ParallelObject(topology->comm(), topology->debug()), _atlasNew(NULL) {
3139: this->_atlas = new atlas_type(topology);
3140: this->_indexArray = new IndexArray();
3141: };
3142: Section(const Obj<atlas_type>& atlas) : ParallelObject(atlas->comm(), atlas->debug()), _atlas(atlas), _atlasNew(NULL) {
3143: this->_indexArray = new IndexArray();
3144: };
3145: virtual ~Section() {
3146: for(typename values_type::iterator a_iter = this->_arrays.begin(); a_iter != this->_arrays.end(); ++a_iter) {
3147: delete [] a_iter->second;
3148: a_iter->second = NULL;
3149: }
3150: };
3151: protected:
3152: value_type *getRawArray(const int size) {
3153: static value_type *array = NULL;
3154: static int maxSize = 0;
3156: if (size > maxSize) {
3157: maxSize = size;
3158: if (array) delete [] array;
3159: array = new value_type[maxSize];
3160: };
3161: return array;
3162: };
3163: public: // Verifiers
3164: void checkPatch(const patch_type& patch) {
3165: this->_atlas->checkPatch(patch);
3166: if (this->_arrays.find(patch) == this->_arrays.end()) {
3167: ostringstream msg;
3168: msg << "Invalid section patch: " << patch << std::endl;
3169: throw ALE::Exception(msg.str().c_str());
3170: }
3171: };
3172: bool hasPatch(const patch_type& patch) {
3173: return this->_atlas->hasPatch(patch);
3174: };
3175: public: // Accessors
3176: const Obj<atlas_type>& getAtlas() {return this->_atlas;};
3177: void setAtlas(const Obj<atlas_type>& atlas) {this->_atlas = atlas;};
3178: const Obj<topology_type>& getTopology() {return this->_atlas->getTopology();};
3179: void setTopology(const Obj<topology_type>& topology) {this->_atlas->setTopology(topology);};
3180: const chart_type& getPatch(const patch_type& patch) {
3181: return this->_atlas->getPatch(patch);
3182: };
3183: bool hasPoint(const patch_type& patch, const point_type& point) {
3184: return this->_atlas->hasPoint(patch, point);
3185: };
3186: public: // Sizes
3187: void clear() {
3188: this->_atlas->clear();
3189: this->_arrays.clear();
3190: };
3191: int getFiberDimension(const patch_type& patch, const point_type& p) const {
3192: // Could check for non-existence here
3193: return this->_atlas->restrictPoint(patch, p)->prefix;
3194: };
3195: int getFiberDimension(const Obj<atlas_type>& atlas, const patch_type& patch, const point_type& p) const {
3196: // Could check for non-existence here
3197: return atlas->restrictPoint(patch, p)->prefix;
3198: };
3199: void setFiberDimension(const patch_type& patch, const point_type& p, int dim) {
3200: const index_type idx(dim, -1);
3201: this->_atlas->updatePatch(patch, p);
3202: this->_atlas->updatePoint(patch, p, &idx);
3203: };
3204: template<typename Sequence>
3205: void setFiberDimension(const patch_type& patch, const Obj<Sequence>& points, int dim) {
3206: for(typename topology_type::label_sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
3207: this->setFiberDimension(patch, *p_iter, dim);
3208: }
3209: };
3210: void addFiberDimension(const patch_type& patch, const point_type& p, int dim) {
3211: if (this->_atlas->hasPatch(patch) && this->_atlas->hasPoint(patch, p)) {
3212: const index_type values(dim, 0);
3213: this->_atlas->updateAddPoint(patch, p, &values);
3214: } else {
3215: this->setFiberDimension(patch, p, dim);
3216: }
3217: };
3218: void setFiberDimensionByDepth(const patch_type& patch, int depth, int dim) {
3219: this->setFiberDimension(patch, this->getTopology()->getLabelStratum(patch, "depth", depth), dim);
3220: };
3221: void setFiberDimensionByHeight(const patch_type& patch, int height, int dim) {
3222: this->setFiberDimension(patch, this->getTopology()->getLabelStratum(patch, "height", height), dim);
3223: };
3224: int size(const patch_type& patch) {
3225: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
3226: int size = 0;
3228: for(typename atlas_type::chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
3229: size += std::max(0, this->getFiberDimension(patch, *p_iter));
3230: }
3231: return size;
3232: };
3233: int sizeWithBC(const patch_type& patch) {
3234: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
3235: int size = 0;
3237: for(typename atlas_type::chart_type::const_iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
3238: size += std::abs(this->getFiberDimension(patch, *p_iter));
3239: }
3240: return size;
3241: };
3242: int size(const patch_type& patch, const point_type& p) {
3243: if (this->getTopology()->depth() > 1) throw ALE::Exception("Compatibility layer is not for interpolated meshes");
3244: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
3245: const Obj<typename sieve_type::coneSequence> closure = this->getTopology()->getPatch(patch)->cone(p);
3246: typename sieve_type::coneSequence::iterator end = closure->end();
3247: int size = 0;
3249: size += std::max(0, this->getFiberDimension(patch, p));
3250: for(typename sieve_type::coneSequence::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
3251: if (points.count(*c_iter)) {
3252: size += std::max(0, this->getFiberDimension(patch, *c_iter));
3253: }
3254: }
3255: return size;
3256: };
3257: int sizeWithBC(const patch_type& patch, const point_type& p) {
3258: if (this->getTopology()->depth() > 1) throw ALE::Exception("Compatibility layer is not for interpolated meshes");
3259: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
3260: const Obj<typename sieve_type::coneSequence> closure = this->getTopology()->getPatch(patch)->cone(p);
3261: typename sieve_type::coneSequence::iterator end = closure->end();
3262: int size = 0;
3264: size += std::abs(this->getFiberDimension(patch, p));
3265: for(typename sieve_type::coneSequence::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
3266: if (points.count(*c_iter)) {
3267: size += std::abs(this->getFiberDimension(patch, *c_iter));
3268: }
3269: }
3270: return size;
3271: };
3272: int size(const Obj<atlas_type>& atlas, const patch_type& patch) {
3273: const typename atlas_type::chart_type& points = atlas->getPatch(patch);
3274: int size = 0;
3276: for(typename atlas_type::chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
3277: size += std::max(0, this->getFiberDimension(atlas, patch, *p_iter));
3278: }
3279: return size;
3280: };
3281: public: // Index retrieval
3282: const index_type& getIndex(const patch_type& patch, const point_type& p) {
3283: this->checkPatch(patch);
3284: return this->_atlas->restrictPoint(patch, p)[0];
3285: };
3286: template<typename Numbering>
3287: const index_type getIndex(const patch_type& patch, const point_type& p, const Obj<Numbering>& numbering) {
3288: this->checkPatch(patch);
3289: return index_type(this->getFiberDimension(patch, p), numbering->getIndex(p));
3290: };
3291: const Obj<IndexArray>& getIndices(const patch_type& patch, const point_type& p, const int level = -1) {
3292: this->_indexArray->clear();
3294: if (level == 0) {
3295: this->_indexArray->push_back(this->getIndex(patch, p));
3296: } else if ((level == 1) || (this->getTopology()->height(patch) == 1)) {
3297: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3298: typename sieve_type::coneSequence::iterator end = cone->end();
3300: this->_indexArray->push_back(this->getIndex(patch, p));
3301: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3302: this->_indexArray->push_back(this->getIndex(patch, *p_iter));
3303: }
3304: } else if (level == -1) {
3305: #if 1
3306: throw ALE::Exception("Call should be moved to Bundle");
3307: #else
3308: const Obj<typename sieve_type::coneSet> closure = this->getTopology()->getPatch(patch)->closure(p);
3309: typename sieve_type::coneSet::iterator end = closure->end();
3311: for(typename sieve_type::coneSet::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
3312: this->_indexArray->push_back(this->getIndex(patch, *p_iter));
3313: }
3314: #endif
3315: } else {
3316: const Obj<typename sieve_type::coneArray> cone = this->getTopology()->getPatch(patch)->nCone(p, level);
3317: typename sieve_type::coneArray::iterator end = cone->end();
3319: for(typename sieve_type::coneArray::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3320: this->_indexArray->push_back(this->getIndex(patch, *p_iter));
3321: }
3322: }
3323: return this->_indexArray;
3324: };
3325: template<typename Numbering>
3326: const Obj<IndexArray>& getIndices(const patch_type& patch, const point_type& p, const Obj<Numbering>& numbering, const int level = -1) {
3327: this->_indexArray->clear();
3329: if (level == 0) {
3330: this->_indexArray->push_back(this->getIndex(patch, p, numbering));
3331: } else if ((level == 1) || (this->getTopology()->height(patch) == 1)) {
3332: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3333: typename sieve_type::coneSequence::iterator end = cone->end();
3335: this->_indexArray->push_back(this->getIndex(patch, p, numbering));
3336: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3337: this->_indexArray->push_back(this->getIndex(patch, *p_iter, numbering));
3338: }
3339: } else if (level == -1) {
3340: #if 1
3341: throw ALE::Exception("Call should be moved to Bundle");
3342: #else
3343: const Obj<typename sieve_type::coneSet> closure = this->getTopology()->getPatch(patch)->closure(p);
3344: typename sieve_type::coneSet::iterator end = closure->end();
3346: for(typename sieve_type::coneSet::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
3347: this->_indexArray->push_back(this->getIndex(patch, *p_iter, numbering));
3348: }
3349: #endif
3350: } else {
3351: const Obj<typename sieve_type::coneArray> cone = this->getTopology()->getPatch(patch)->nCone(p, level);
3352: typename sieve_type::coneArray::iterator end = cone->end();
3354: for(typename sieve_type::coneArray::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3355: this->_indexArray->push_back(this->getIndex(patch, *p_iter, numbering));
3356: }
3357: }
3358: return this->_indexArray;
3359: };
3360: public: // Allocation
3361: void orderPoint(const Obj<atlas_type>& atlas, const Obj<sieve_type>& sieve, const patch_type& patch, const point_type& point, typename atlas_type::value_type::index_type& offset, typename atlas_type::value_type::index_type& bcOffset, const bool postponeGhosts = false) {
3362: const Obj<typename sieve_type::coneSequence>& cone = sieve->cone(point);
3363: typename sieve_type::coneSequence::iterator end = cone->end();
3364: index_type idx = atlas->restrictPoint(patch, point)[0];
3365: const int& dim = idx.prefix;
3366: const index_type defaultIdx(0, -1);
3368: if (atlas->getPatch(patch).count(point) == 0) {
3369: idx = defaultIdx;
3370: }
3371: if (idx.index == -1) {
3372: for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
3373: if (this->_debug > 1) {std::cout << " Recursing to " << *c_iter << std::endl;}
3374: this->orderPoint(atlas, sieve, patch, *c_iter, offset, bcOffset);
3375: }
3376: if (dim > 0) {
3377: bool number = true;
3379: // Maybe use template specialization here
3380: if (postponeGhosts && this->getTopology()->getSendOverlap()->capContains(point)) {
3381: const Obj<typename topology_type::send_overlap_type::supportSequence>& ranks = this->getTopology()->getSendOverlap()->support(point);
3383: for(typename topology_type::send_overlap_type::supportSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
3384: if (this->commRank() > *r_iter) {
3385: number = false;
3386: break;
3387: }
3388: }
3389: }
3390: if (number) {
3391: if (this->_debug > 1) {std::cout << " Ordering point " << point << " at " << offset << std::endl;}
3392: idx.index = offset;
3393: atlas->updatePoint(patch, point, &idx);
3394: offset += dim;
3395: } else {
3396: if (this->_debug > 1) {std::cout << " Ignoring ghost point " << point << std::endl;}
3397: }
3398: } else if (dim < 0) {
3399: if (this->_debug > 1) {std::cout << " Ordering boundary point " << point << " at " << bcOffset << std::endl;}
3400: idx.index = bcOffset;
3401: atlas->updatePoint(patch, point, &idx);
3402: bcOffset += dim;
3403: }
3404: }
3405: }
3406: void orderPatch(const Obj<atlas_type>& atlas, const patch_type& patch, typename atlas_type::value_type::index_type& offset, typename atlas_type::value_type::index_type& bcOffset, const bool postponeGhosts = false) {
3407: const typename atlas_type::chart_type& chart = atlas->getPatch(patch);
3409: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
3410: if (this->_debug > 1) {std::cout << "Ordering closure of point " << *p_iter << std::endl;}
3411: this->orderPoint(atlas, this->getTopology()->getPatch(patch), patch, *p_iter, offset, bcOffset, postponeGhosts);
3412: }
3413: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
3414: index_type idx = atlas->restrictPoint(patch, *p_iter)[0];
3415: const int& dim = idx.prefix;
3417: if (dim < 0) {
3418: if (this->_debug > 1) {std::cout << "Correcting boundary offset of point " << *p_iter << std::endl;}
3419: idx.index = offset - (idx.index+2);
3420: atlas->updatePoint(patch, *p_iter, &idx);
3421: }
3422: }
3423: };
3424: void orderPatches(const Obj<atlas_type>& atlas, const bool postponeGhosts = false) {
3425: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
3427: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
3428: if (this->_debug > 1) {std::cout << "Ordering patch " << p_iter->first << std::endl;}
3429: typename atlas_type::value_type::index_type offset = 0, bcOffset = -2;
3431: if (!atlas->hasPatch(p_iter->first)) continue;
3432: this->orderPatch(atlas, p_iter->first, offset, bcOffset, postponeGhosts);
3433: }
3434: };
3435: void orderPatches(const bool postponeGhosts = false) {
3436: this->orderPatches(this->_atlas, postponeGhosts);
3437: };
3438: void allocateStorage() {
3439: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
3441: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
3442: if (!this->_atlas->hasPatch(p_iter->first)) continue;
3443: this->_arrays[p_iter->first] = new value_type[this->sizeWithBC(p_iter->first)];
3444: PetscMemzero(this->_arrays[p_iter->first], this->sizeWithBC(p_iter->first) * sizeof(value_type));
3445: }
3446: };
3447: void allocate(const bool postponeGhosts = false) {
3448: bool doGhosts = false;
3450: if (postponeGhosts && !this->getTopology()->getSendOverlap().isNull()) {
3451: doGhosts = true;
3452: }
3453: this->orderPatches(doGhosts);
3454: if (doGhosts) {
3455: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
3457: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
3458: if (this->_debug > 1) {std::cout << "Ordering patch " << p_iter->first << " for ghosts" << std::endl;}
3459: const typename atlas_type::chart_type& points = this->_atlas->getPatch(p_iter->first);
3460: typename atlas_type::value_type::index_type offset = 0, bcOffset = -2;
3462: for(typename atlas_type::chart_type::const_iterator point = points.begin(); point != points.end(); ++point) {
3463: const index_type& idx = this->_atlas->restrictPoint(p_iter->first, *point)[0];
3465: offset = std::max(offset, idx.index + std::abs(idx.prefix));
3466: }
3467: if (!this->_atlas->hasPatch(p_iter->first)) continue;
3468: this->orderPatch(this->_atlas, p_iter->first, offset, bcOffset);
3469: if (offset != this->sizeWithBC(p_iter->first)) throw ALE::Exception("Inconsistent array sizes in section");
3470: }
3471: }
3472: this->allocateStorage();
3473: };
3474: void addPoint(const patch_type& patch, const point_type& point, const int dim) {
3475: if (dim == 0) return;
3476: //const typename atlas_type::chart_type& chart = this->_atlas->getPatch(patch);
3478: //if (chart.find(point) == chart.end()) {
3479: if (this->_atlasNew.isNull()) {
3480: this->_atlasNew = new atlas_type(this->getTopology());
3481: this->_atlasNew->copy(this->_atlas);
3482: }
3483: const index_type idx(dim, -1);
3484: this->_atlasNew->updatePatch(patch, point);
3485: this->_atlasNew->updatePoint(patch, point, &idx);
3486: };
3487: void reallocate() {
3488: if (this->_atlasNew.isNull()) return;
3489: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
3491: // Since copy() preserves offsets, we must reinitialize them before ordering
3492: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
3493: const patch_type& patch = p_iter->first;
3494: const typename atlas_type::chart_type& chart = this->_atlasNew->getPatch(patch);
3495: index_type defaultIdx(0, -1);
3497: for(typename atlas_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
3498: defaultIdx.prefix = this->_atlasNew->restrictPoint(patch, *c_iter)[0].prefix;
3499: this->_atlasNew->updatePoint(patch, *c_iter, &defaultIdx);
3500: }
3501: }
3502: this->orderPatches(this->_atlasNew);
3503: // Copy over existing values
3504: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
3505: const patch_type& patch = p_iter->first;
3506: value_type *newArray = new value_type[this->size(this->_atlasNew, patch)];
3508: if (!this->_atlas->hasPatch(patch)) {
3509: this->_arrays[patch] = newArray;
3510: continue;
3511: }
3512: const typename atlas_type::chart_type& chart = this->_atlas->getPatch(patch);
3513: const value_type *array = this->_arrays[patch];
3515: for(typename atlas_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
3516: const index_type& idx = this->_atlas->restrictPoint(patch, *c_iter)[0];
3517: const int size = idx.prefix;
3518: const int offset = idx.index;
3519: const int& newOffset = this->_atlasNew->restrictPoint(patch, *c_iter)[0].index;
3521: for(int i = 0; i < size; ++i) {
3522: newArray[newOffset+i] = array[offset+i];
3523: }
3524: }
3525: delete [] this->_arrays[patch];
3526: this->_arrays[patch] = newArray;
3527: }
3528: this->_atlas = this->_atlasNew;
3529: this->_atlasNew = NULL;
3530: };
3531: public: // Restriction and Update
3532: // Zero entries
3533: void zero(const patch_type& patch) {
3534: this->checkPatch(patch);
3535: memset(this->_arrays[patch], 0, this->size(patch)* sizeof(value_type));
3536: };
3537: // Return a pointer to the entire contiguous storage array
3538: const value_type *restrict(const patch_type& patch) {
3539: this->checkPatch(patch);
3540: return this->_arrays[patch];
3541: };
3542: // Update the entire contiguous storage array
3543: void update(const patch_type& patch, const value_type v[]) {
3544: const value_type *array = this->_arrays[patch];
3545: const int size = this->size(patch);
3547: for(int i = 0; i < size; i++) {
3548: array[i] = v[i];
3549: }
3550: };
3551: // Return the values for the closure of this point
3552: // use a smart pointer?
3553: const value_type *restrict(const patch_type& patch, const point_type& p) {
3554: this->checkPatch(patch);
3555: const value_type *a = this->_arrays[patch];
3556: const int size = this->sizeWithBC(patch, p);
3557: value_type *values = this->getRawArray(size);
3558: int j = -1;
3560: if (this->getTopology()->height(patch) < 2) {
3561: // Avoids the copy of both
3562: // points in topology->closure()
3563: // indices in _atlas->restrict()
3564: const index_type& pInd = this->_atlas->restrictPoint(patch, p)[0];
3566: for(int i = pInd.index; i < std::abs(pInd.prefix) + pInd.index; ++i) {
3567: values[++j] = a[i];
3568: }
3569: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3570: typename sieve_type::coneSequence::iterator end = cone->end();
3572: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3573: const index_type& ind = this->_atlas->restrictPoint(patch, *p_iter)[0];
3574: const int& start = ind.index;
3575: const int& length = std::abs(ind.prefix);
3577: for(int i = start; i < start + length; ++i) {
3578: values[++j] = a[i];
3579: }
3580: }
3581: } else {
3582: const Obj<IndexArray>& ind = this->getIndices(patch, p);
3584: for(typename IndexArray::iterator i_iter = ind->begin(); i_iter != ind->end(); ++i_iter) {
3585: const int& start = i_iter->index;
3586: const int& length = std::abs(i_iter->prefix);
3588: for(int i = start; i < start + length; ++i) {
3589: values[++j] = a[i];
3590: }
3591: }
3592: }
3593: if (j != size-1) {
3594: ostringstream txt;
3596: txt << "Invalid restrict to point " << p << std::endl;
3597: txt << " j " << j << " should be " << (size-1) << std::endl;
3598: std::cout << txt.str();
3599: throw ALE::Exception(txt.str().c_str());
3600: }
3601: return values;
3602: };
3603: // Update the values for the closure of this point
3604: void update(const patch_type& patch, const point_type& p, const value_type v[]) {
3605: this->checkPatch(patch);
3606: value_type *a = this->_arrays[patch];
3607: int j = -1;
3609: if (this->getTopology()->height(patch) < 2) {
3610: // Avoids the copy of both
3611: // points in topology->closure()
3612: // indices in _atlas->restrict()
3613: const index_type& pInd = this->_atlas->restrictPoint(patch, p)[0];
3615: for(int i = pInd.index; i < pInd.prefix + pInd.index; ++i) {
3616: a[i] = v[++j];
3617: }
3618: j += std::max(0, -pInd.prefix);
3619: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3620: typename sieve_type::coneSequence::iterator end = cone->end();
3622: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3623: const index_type& ind = this->_atlas->restrictPoint(patch, *p_iter)[0];
3624: const int& start = ind.index;
3625: const int& length = ind.prefix;
3627: for(int i = start; i < start + length; ++i) {
3628: a[i] = v[++j];
3629: }
3630: j += std::max(0, -length);
3631: }
3632: } else {
3633: const Obj<IndexArray>& ind = this->getIndices(patch, p);
3635: for(typename IndexArray::iterator i_iter = ind->begin(); i_iter != ind->end(); ++i_iter) {
3636: const int& start = i_iter->index;
3637: const int& length = i_iter->prefix;
3639: for(int i = start; i < start + length; ++i) {
3640: a[i] = v[++j];
3641: }
3642: j += std::max(0, -length);
3643: }
3644: }
3645: };
3646: // Update the values for the closure of this point
3647: void updateAdd(const patch_type& patch, const point_type& p, const value_type v[]) {
3648: this->checkPatch(patch);
3649: value_type *a = this->_arrays[patch];
3650: int j = -1;
3652: if (this->getTopology()->height(patch) < 2) {
3653: // Avoids the copy of both
3654: // points in topology->closure()
3655: // indices in _atlas->restrict()
3656: const index_type& pInd = this->_atlas->restrictPoint(patch, p)[0];
3658: for(int i = pInd.index; i < pInd.prefix + pInd.index; ++i) {
3659: a[i] += v[++j];
3660: }
3661: j += std::max(0, -pInd.prefix);
3662: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3663: typename sieve_type::coneSequence::iterator end = cone->end();
3665: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3666: const index_type& ind = this->_atlas->restrictPoint(patch, *p_iter)[0];
3667: const int& start = ind.index;
3668: const int& length = ind.prefix;
3670: for(int i = start; i < start + length; ++i) {
3671: a[i] += v[++j];
3672: }
3673: j += std::max(0, -length);
3674: }
3675: } else {
3676: const Obj<IndexArray>& ind = this->getIndices(patch, p);
3678: for(typename IndexArray::iterator i_iter = ind->begin(); i_iter != ind->end(); ++i_iter) {
3679: const int& start = i_iter->index;
3680: const int& length = i_iter->prefix;
3682: for(int i = start; i < start + length; ++i) {
3683: a[i] += v[++j];
3684: }
3685: j += std::max(0, -length);
3686: }
3687: }
3688: };
3689: // Update the values for the closure of this point
3690: template<typename Input>
3691: void update(const patch_type& patch, const point_type& p, const Obj<Input>& v) {
3692: this->checkPatch(patch);
3693: value_type *a = this->_arrays[patch];
3695: if (this->getTopology()->height(patch) == 1) {
3696: // Only avoids the copy
3697: const index_type& pInd = this->_atlas->restrictPoint(patch, p)[0];
3698: typename Input::iterator v_iter = v->begin();
3699: typename Input::iterator v_end = v->end();
3701: for(int i = pInd.index; i < pInd.prefix + pInd.index; ++i) {
3702: a[i] = *v_iter;
3703: ++v_iter;
3704: }
3705: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3706: typename sieve_type::coneSequence::iterator end = cone->end();
3708: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3709: const index_type& ind = this->_atlas->restrictPoint(patch, *p_iter)[0];
3710: const int& start = ind.index;
3711: const int& length = ind.prefix;
3713: for(int i = start; i < start + length; ++i) {
3714: a[i] = *v_iter;
3715: ++v_iter;
3716: }
3717: }
3718: } else {
3719: const Obj<IndexArray>& ind = this->getIndices(patch, p);
3720: typename Input::iterator v_iter = v->begin();
3721: typename Input::iterator v_end = v->end();
3723: for(typename IndexArray::iterator i_iter = ind->begin(); i_iter != ind->end(); ++i_iter) {
3724: const int& start = i_iter->index;
3725: const int& length = i_iter->prefix;
3727: for(int i = start; i < start + length; ++i) {
3728: a[i] = *v_iter;
3729: ++v_iter;
3730: }
3731: }
3732: }
3733: };
3734: void updateBC(const patch_type& patch, const point_type& p, const value_type v[]) {
3735: this->checkPatch(patch);
3736: value_type *a = this->_arrays[patch];
3737: int j = -1;
3739: if (this->getTopology()->height(patch) < 2) {
3740: // Avoids the copy of both
3741: // points in topology->closure()
3742: // indices in _atlas->restrict()
3743: const index_type& pInd = this->_atlas->restrictPoint(patch, p)[0];
3745: for(int i = pInd.index; i < std::abs(pInd.prefix) + pInd.index; ++i) {
3746: a[i] = v[++j];
3747: }
3748: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3749: typename sieve_type::coneSequence::iterator end = cone->end();
3751: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3752: const index_type& ind = this->_atlas->restrictPoint(patch, *p_iter)[0];
3753: const int& start = ind.index;
3754: const int& length = std::abs(ind.prefix);
3756: for(int i = start; i < start + length; ++i) {
3757: a[i] = v[++j];
3758: }
3759: }
3760: } else {
3761: const Obj<IndexArray>& ind = this->getIndices(patch, p);
3763: for(typename IndexArray::iterator i_iter = ind->begin(); i_iter != ind->end(); ++i_iter) {
3764: const int& start = i_iter->index;
3765: const int& length = std::abs(i_iter->prefix);
3767: for(int i = start; i < start + length; ++i) {
3768: a[i] = v[++j];
3769: }
3770: }
3771: }
3772: };
3773: // Return only the values associated to this point, not its closure
3774: const value_type *restrictPoint(const patch_type& patch, const point_type& p) {
3775: this->checkPatch(patch);
3776: return &(this->_arrays[patch][this->_atlas->restrictPoint(patch, p)[0].index]);
3777: };
3778: // Update only the values associated to this point, not its closure
3779: void updatePoint(const patch_type& patch, const point_type& p, const value_type v[]) {
3780: this->checkPatch(patch);
3781: const index_type& idx = this->_atlas->restrictPoint(patch, p)[0];
3782: value_type *a = &(this->_arrays[patch][idx.index]);
3784: for(int i = 0; i < idx.prefix; ++i) {
3785: a[i] = v[i];
3786: }
3787: };
3788: // Update only the values associated to this point, not its closure
3789: void updateAddPoint(const patch_type& patch, const point_type& p, const value_type v[]) {
3790: this->checkPatch(patch);
3791: const index_type& idx = this->_atlas->restrictPoint(patch, p)[0];
3792: value_type *a = &(this->_arrays[patch][idx.index]);
3794: for(int i = 0; i < idx.prefix; ++i) {
3795: a[i] += v[i];
3796: }
3797: };
3798: void updatePointBC(const patch_type& patch, const point_type& p, const value_type v[]) {
3799: this->checkPatch(patch);
3800: const index_type& idx = this->_atlas->restrictPoint(patch, p)[0];
3801: value_type *a = &(this->_arrays[patch][idx.index]);
3803: for(int i = 0; i < std::abs(idx.prefix); ++i) {
3804: a[i] = v[i];
3805: }
3806: };
3807: public: // BC
3808: void copyBC(const Obj<Section>& section) {
3809: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
3811: for(typename topology_type::sheaf_type::const_iterator patch_iter = patches.begin(); patch_iter != patches.end(); ++patch_iter) {
3812: const typename atlas_type::chart_type& chart = this->_atlas->getPatch(patch_iter->first);
3814: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
3815: const index_type& idx = this->_atlas->restrictPoint(patch_iter->first, *p_iter)[0];
3817: if (idx.prefix < 0) {
3818: this->updatePointBC(patch_iter->first, *p_iter, section->restrictPoint(patch_iter->first, *p_iter));
3819: }
3820: }
3821: }
3822: };
3823: public:
3824: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
3825: ostringstream txt;
3826: int rank;
3828: if (comm == MPI_COMM_NULL) {
3829: comm = this->comm();
3830: rank = this->commRank();
3831: } else {
3832: MPI_Comm_rank(comm, &rank);
3833: }
3834: if (name == "") {
3835: if(rank == 0) {
3836: txt << "viewing a Section" << std::endl;
3837: }
3838: } else {
3839: if(rank == 0) {
3840: txt << "viewing Section '" << name << "'" << std::endl;
3841: }
3842: }
3843: for(typename values_type::const_iterator a_iter = this->_arrays.begin(); a_iter != this->_arrays.end(); ++a_iter) {
3844: const patch_type& patch = a_iter->first;
3845: const value_type *array = a_iter->second;
3847: txt << "[" << this->commRank() << "]: Patch " << patch << std::endl;
3848: const typename atlas_type::chart_type& chart = this->_atlas->getPatch(patch);
3850: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
3851: const point_type& point = *p_iter;
3852: const index_type& idx = this->_atlas->restrictPoint(patch, point)[0];
3854: if (idx.prefix != 0) {
3855: txt << "[" << this->commRank() << "]: " << point << " dim " << idx.prefix << " offset " << idx.index << " ";
3856: for(int i = 0; i < std::abs(idx.prefix); i++) {
3857: txt << " " << array[idx.index+i];
3858: }
3859: txt << std::endl;
3860: }
3861: }
3862: }
3863: if (this->_arrays.empty()) {
3864: txt << "[" << this->commRank() << "]: empty" << std::endl;
3865: }
3866: PetscSynchronizedPrintf(comm, txt.str().c_str());
3867: PetscSynchronizedFlush(comm);
3868: };
3869: };
3871: // An Overlap is a Sifter describing the overlap of two Sieves
3872: // Each arrow is local point ---(remote point)---> remote rank right now
3873: // For XSifter, this should change to (local patch, local point) ---> (remote rank, remote patch, remote point)
3875: template<typename Topology_, typename Value_>
3876: class OldConstantSection : public ALE::ParallelObject {
3877: public:
3878: typedef OldConstantSection<Topology_, Value_> section_type;
3879: typedef Topology_ topology_type;
3880: typedef typename topology_type::patch_type patch_type;
3881: typedef typename topology_type::sieve_type sieve_type;
3882: typedef typename topology_type::point_type point_type;
3883: typedef Value_ value_type;
3884: protected:
3885: Obj<topology_type> _topology;
3886: const value_type _value;
3887: Obj<section_type> _section;
3888: public:
3889: OldConstantSection(MPI_Comm comm, const value_type value, const int debug = 0) : ParallelObject(comm, debug), _value(value) {
3890: this->_topology = new topology_type(comm, debug);
3891: this->_section = this;
3892: this->_section.addRef();
3893: };
3894: OldConstantSection(const Obj<topology_type>& topology, const value_type value) : ParallelObject(topology->comm(), topology->debug()), _topology(topology), _value(value) {
3895: this->_section = this;
3896: this->_section.addRef();
3897: };
3898: virtual ~OldConstantSection() {};
3899: public: // Verifiers
3900: bool hasPoint(const patch_type& patch, const point_type& point) const {return true;};
3901: public: // Restriction
3902: const value_type *restrict(const patch_type& patch) {return &this->_value;};
3903: const value_type *restrictPoint(const patch_type& patch, const point_type& p) {return &this->_value;};
3904: public: // Adapter
3905: const Obj<section_type>& getSection(const patch_type& patch) {return this->_section;};
3906: const value_type *restrictPoint(const point_type& p) {return &this->_value;};
3907: public:
3908: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
3909: ostringstream txt;
3910: int rank;
3912: if (comm == MPI_COMM_NULL) {
3913: comm = this->comm();
3914: rank = this->commRank();
3915: } else {
3916: MPI_Comm_rank(comm, &rank);
3917: }
3918: if (name == "") {
3919: if(rank == 0) {
3920: txt << "viewing a OldConstantSection with value " << this->_value << std::endl;
3921: }
3922: } else {
3923: if(rank == 0) {
3924: txt << "viewing OldConstantSection '" << name << "' with value " << this->_value << std::endl;
3925: }
3926: }
3927: PetscSynchronizedPrintf(comm, txt.str().c_str());
3928: PetscSynchronizedFlush(comm);
3929: };
3930: };
3932: template<typename Overlap_, typename Topology_, typename Value_>
3933: class OverlapValues : public Section<Topology_, Value_> {
3934: public:
3935: typedef Overlap_ overlap_type;
3936: typedef Section<Topology_, Value_> base_type;
3937: typedef typename base_type::topology_type topology_type;
3938: typedef typename base_type::patch_type patch_type;
3939: typedef typename base_type::chart_type chart_type;
3940: typedef typename base_type::atlas_type atlas_type;
3941: typedef typename base_type::value_type value_type;
3942: typedef enum {SEND, RECEIVE} request_type;
3943: typedef std::map<patch_type, MPI_Request> requests_type;
3944: protected:
3945: int _tag;
3946: MPI_Datatype _datatype;
3947: requests_type _requests;
3948: public:
3949: OverlapValues(MPI_Comm comm, const int debug = 0) : Section<Topology_, Value_>(comm, debug) {
3950: this->_tag = this->getNewTag();
3951: this->_datatype = this->getMPIDatatype();
3952: };
3953: OverlapValues(MPI_Comm comm, const int tag, const int debug) : Section<Topology_, Value_>(comm, debug), _tag(tag) {
3954: this->_datatype = this->getMPIDatatype();
3955: };
3956: virtual ~OverlapValues() {};
3957: protected:
3958: MPI_Datatype getMPIDatatype() {
3959: if (sizeof(value_type) == 4) {
3960: return MPI_INT;
3961: } else if (sizeof(value_type) == 8) {
3962: return MPI_DOUBLE;
3963: } else if (sizeof(value_type) == 28) {
3964: int blen[2];
3965: MPI_Aint indices[2];
3966: MPI_Datatype oldtypes[2], newtype;
3967: blen[0] = 1; indices[0] = 0; oldtypes[0] = MPI_INT;
3968: blen[1] = 3; indices[1] = sizeof(int); oldtypes[1] = MPI_DOUBLE;
3969: MPI_Type_struct(2, blen, indices, oldtypes, &newtype);
3970: MPI_Type_commit(&newtype);
3971: return newtype;
3972: } else if (sizeof(value_type) == 32) {
3973: int blen[2];
3974: MPI_Aint indices[2];
3975: MPI_Datatype oldtypes[2], newtype;
3976: blen[0] = 1; indices[0] = 0; oldtypes[0] = MPI_DOUBLE;
3977: blen[1] = 3; indices[1] = sizeof(int); oldtypes[1] = MPI_DOUBLE;
3978: MPI_Type_struct(2, blen, indices, oldtypes, &newtype);
3979: MPI_Type_commit(&newtype);
3980: return newtype;
3981: }
3982: throw ALE::Exception("Cannot determine MPI type for value type");
3983: };
3984: int getNewTag() {
3985: static int tagKeyval = MPI_KEYVAL_INVALID;
3986: int *tagvalp = NULL, *maxval, flg;
3988: if (tagKeyval == MPI_KEYVAL_INVALID) {
3989: tagvalp = (int *) malloc(sizeof(int));
3990: MPI_Keyval_create(MPI_NULL_COPY_FN, Mesh_DelTag, &tagKeyval, (void *) NULL);
3991: MPI_Attr_put(this->_comm, tagKeyval, tagvalp);
3992: tagvalp[0] = 0;
3993: }
3994: MPI_Attr_get(this->_comm, tagKeyval, (void **) &tagvalp, &flg);
3995: if (tagvalp[0] < 1) {
3996: MPI_Attr_get(MPI_COMM_WORLD, MPI_TAG_UB, (void **) &maxval, &flg);
3997: tagvalp[0] = *maxval - 128; // hope that any still active tags were issued right at the beginning of the run
3998: }
3999: if (this->debug()) {
4000: std::cout << "[" << this->commRank() << "]Got new tag " << tagvalp[0] << std::endl;
4001: }
4002: return tagvalp[0]--;
4003: };
4004: public: // Accessors
4005: int getTag() const {return this->_tag;};
4006: void setTag(const int tag) {this->_tag = tag;};
4007: public:
4008: void construct(const int size) {
4009: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
4011: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
4012: const Obj<typename topology_type::sieve_type::baseSequence>& base = p_iter->second->base();
4013: int rank = p_iter->first;
4015: for(typename topology_type::sieve_type::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
4016: this->setFiberDimension(rank, *b_iter, size);
4017: }
4018: }
4019: };
4020: template<typename Sizer>
4021: void construct(const Obj<Sizer>& sizer) {
4022: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
4024: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
4025: const Obj<typename topology_type::sieve_type::baseSequence>& base = p_iter->second->base();
4026: int rank = p_iter->first;
4028: for(typename topology_type::sieve_type::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
4029: this->setFiberDimension(rank, *b_iter, *(sizer->restrictPoint(rank, *b_iter)));
4030: }
4031: }
4032: };
4033: void constructCommunication(const request_type& requestType) {
4034: const typename topology_type::sheaf_type& patches = this->getAtlas()->getTopology()->getPatches();
4036: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
4037: const patch_type patch = p_iter->first;
4038: MPI_Request request;
4040: if (requestType == RECEIVE) {
4041: if (this->_debug) {std::cout <<"["<<this->commRank()<<"] Receiving data(" << this->size(patch) << ") from " << patch << " tag " << this->_tag << std::endl;}
4042: MPI_Recv_init(this->_arrays[patch], this->size(patch), this->_datatype, patch, this->_tag, this->_comm, &request);
4043: } else {
4044: if (this->_debug) {std::cout <<"["<<this->commRank()<<"] Sending data (" << this->size(patch) << ") to " << patch << " tag " << this->_tag << std::endl;}
4045: MPI_Send_init(this->_arrays[patch], this->size(patch), this->_datatype, patch, this->_tag, this->_comm, &request);
4046: }
4047: this->_requests[patch] = request;
4048: }
4049: };
4050: void startCommunication() {
4051: const typename topology_type::sheaf_type& patches = this->getAtlas()->getTopology()->getPatches();
4053: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
4054: MPI_Request request = this->_requests[p_iter->first];
4056: MPI_Start(&request);
4057: }
4058: };
4059: void endCommunication() {
4060: const typename topology_type::sheaf_type& patches = this->getAtlas()->getTopology()->getPatches();
4061: MPI_Status status;
4063: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
4064: MPI_Request request = this->_requests[p_iter->first];
4066: MPI_Wait(&request, &status);
4067: }
4068: };
4069: };
4070: }
4071: }
4072: #endif