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_>
33: class DiscreteSieve {
34: public:
35: typedef Point_ point_type;
36: typedef std::vector<point_type> coneSequence;
37: typedef std::vector<point_type> coneSet;
38: typedef std::vector<point_type> coneArray;
39: typedef std::vector<point_type> supportSequence;
40: typedef std::vector<point_type> supportSet;
41: typedef std::vector<point_type> supportArray;
42: typedef std::set<point_type> points_type;
43: typedef points_type baseSequence;
44: typedef points_type capSequence;
45: protected:
46: Obj<points_type> _points;
47: Obj<coneSequence> _empty;
48: Obj<coneSequence> _return;
49: void _init() {
50: this->_points = new points_type();
51: this->_empty = new coneSequence();
52: this->_return = new coneSequence();
53: };
54: public:
55: DiscreteSieve() {
56: this->_init();
57: };
58: template<typename Input>
59: DiscreteSieve(const Obj<Input>& points) {
60: this->_init();
61: this->_points->insert(points->begin(), points->end());
62: };
63: virtual ~DiscreteSieve() {};
64: public:
65: void addPoint(const point_type& point) {
66: this->_points->insert(point);
67: };
68: template<typename Input>
69: void addPoints(const Obj<Input>& points) {
70: this->_points->insert(points->begin(), points->end());
71: };
72: const Obj<coneSequence>& cone(const point_type& p) {return this->_empty;};
73: template<typename Input>
74: const Obj<coneSequence>& cone(const Input& p) {return this->_empty;};
75: const Obj<coneSet>& nCone(const point_type& p, const int level) {
76: if (level == 0) {
77: return this->closure(p);
78: } else {
79: return this->_empty;
80: }
81: };
82: const Obj<coneArray>& closure(const point_type& p) {
83: this->_return->clear();
84: this->_return->push_back(p);
85: return this->_return;
86: };
87: const Obj<supportSequence>& support(const point_type& p) {return this->_empty;};
88: template<typename Input>
89: const Obj<supportSequence>& support(const Input& p) {return this->_empty;};
90: const Obj<supportSet>& nSupport(const point_type& p, const int level) {
91: if (level == 0) {
92: return this->star(p);
93: } else {
94: return this->_empty;
95: }
96: };
97: const Obj<supportArray>& star(const point_type& p) {
98: this->_return->clear();
99: this->_return->push_back(p);
100: return this->_return;
101: };
102: const Obj<capSequence>& roots() {return this->_points;};
103: const Obj<capSequence>& cap() {return this->_points;};
104: const Obj<baseSequence>& leaves() {return this->_points;};
105: const Obj<baseSequence>& base() {return this->_points;};
106: template<typename Color>
107: void addArrow(const point_type& p, const point_type& q, const Color& color) {
108: throw ALE::Exception("Cannot add an arrow to a DiscreteSieve");
109: };
110: void stratify() {};
111: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
112: ostringstream txt;
113: int rank;
115: if (comm == MPI_COMM_NULL) {
116: comm = MPI_COMM_SELF;
117: rank = 0;
118: } else {
119: MPI_Comm_rank(comm, &rank);
120: }
121: if (name == "") {
122: if(rank == 0) {
123: txt << "viewing a DiscreteSieve" << std::endl;
124: }
125: } else {
126: if(rank == 0) {
127: txt << "viewing DiscreteSieve '" << name << "'" << std::endl;
128: }
129: }
130: for(typename points_type::const_iterator p_iter = this->_points->begin(); p_iter != this->_points->end(); ++p_iter) {
131: txt << " Point " << *p_iter << std::endl;
132: }
133: PetscSynchronizedPrintf(comm, txt.str().c_str());
134: PetscSynchronizedFlush(comm);
135: };
136: };
137: // A ConstantSection is the simplest Section
138: // All fibers are dimension 1
139: // All values are equal to a constant
140: // We need no value storage and no communication for completion
141: template<typename Point_, typename Value_>
142: class ConstantSection : public ALE::ParallelObject {
143: public:
144: typedef Point_ point_type;
145: typedef std::set<point_type> chart_type;
146: typedef Value_ value_type;
147: protected:
148: chart_type _chart;
149: value_type _value;
150: value_type _defaultValue;
151: public:
152: ConstantSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug), _defaultValue(0) {};
153: ConstantSection(MPI_Comm comm, const value_type& value, const int debug) : ParallelObject(comm, debug), _value(value), _defaultValue(value) {};
154: ConstantSection(MPI_Comm comm, const value_type& value, const value_type& defaultValue, const int debug) : ParallelObject(comm, debug), _value(value), _defaultValue(defaultValue) {};
155: public: // Verifiers
156: void checkPoint(const point_type& point) const {
157: if (this->_chart.find(point) == this->_chart.end()) {
158: ostringstream msg;
159: msg << "Invalid section point " << point << std::endl;
160: throw ALE::Exception(msg.str().c_str());
161: }
162: };
163: void checkDimension(const int& dim) {
164: if (dim != 1) {
165: ostringstream msg;
166: msg << "Invalid fiber dimension " << dim << " must be 1" << std::endl;
167: throw ALE::Exception(msg.str().c_str());
168: }
169: };
170: bool hasPoint(const point_type& point) const {
171: return this->_chart.count(point) > 0;
172: };
173: public: // Accessors
174: const chart_type& getChart() {return this->_chart;};
175: void addPoint(const point_type& point) {
176: this->_chart.insert(point);
177: };
178: template<typename Points>
179: void addPoint(const Obj<Points>& points) {
180: this->_chart.insert(points->begin(), points->end());
181: };
182: void addPoint(const std::set<point_type>& points) {
183: this->_chart.insert(points.begin(), points.end());
184: };
185: value_type getDefaultValue() {return this->_defaultValue;};
186: void setDefaultValue(const value_type value) {this->_defaultValue = value;};
187: void copy(const Obj<ConstantSection>& section) {
188: const chart_type& chart = section->getChart();
190: this->addPoint(chart);
191: this->_value = section->restrict(*chart.begin())[0];
192: };
193: public: // Sizes
194: void clear() {
195: this->_chart.clear();
196: };
197: int getFiberDimension(const point_type& p) const {
198: if (this->hasPoint(p)) return 1;
199: return 0;
200: };
201: void setFiberDimension(const point_type& p, int dim) {
202: this->checkDimension(dim);
203: this->addPoint(p);
204: };
205: template<typename Sequence>
206: void setFiberDimension(const Obj<Sequence>& points, int dim) {
207: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
208: this->setFiberDimension(*p_iter, dim);
209: }
210: };
211: void addFiberDimension(const point_type& p, int dim) {
212: if (this->_chart.find(p) != this->_chart.end()) {
213: ostringstream msg;
214: msg << "Invalid addition to fiber dimension " << dim << " cannot exceed 1" << std::endl;
215: throw ALE::Exception(msg.str().c_str());
216: } else {
217: this->setFiberDimension(p, dim);
218: }
219: };
220: int size() {return this->_sheaf.size();};
221: int size(const point_type& p) {return this->getFiberDimension(p);};
222: public: // Restriction
223: const value_type *restrict(const point_type& p) const {
224: if (this->hasPoint(p)) {
225: return &this->_value;
226: }
227: return &this->_defaultValue;
228: };
229: const value_type *restrictPoint(const point_type& p) const {return this->restrict(p);};
230: void update(const point_type& p, const value_type v[]) {
231: this->_value = v[0];
232: };
233: void updatePoint(const point_type& p, const value_type v[]) {return this->update(p, v);};
234: void updateAdd(const point_type& p, const value_type v[]) {
235: this->_value += v[0];
236: };
237: void updateAddPoint(const point_type& p, const value_type v[]) {return this->updateAdd(p, v);};
238: public:
239: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
240: ostringstream txt;
241: int rank;
243: if (comm == MPI_COMM_NULL) {
244: comm = this->comm();
245: rank = this->commRank();
246: } else {
247: MPI_Comm_rank(comm, &rank);
248: }
249: if (name == "") {
250: if(rank == 0) {
251: txt << "viewing a ConstantSection" << std::endl;
252: }
253: } else {
254: if(rank == 0) {
255: txt << "viewing ConstantSection '" << name << "'" << std::endl;
256: }
257: }
258: txt <<"["<<this->commRank()<<"]: Value " << this->_value << std::endl;
259: PetscSynchronizedPrintf(comm, txt.str().c_str());
260: PetscSynchronizedFlush(comm);
261: };
262: };
264: // A UniformSection often acts as an Atlas
265: // All fibers are the same dimension
266: // Note we can use a ConstantSection for this Atlas
267: // Each point may have a different vector
268: // Thus we need storage for values, and hence must implement completion
269: template<typename Point_, typename Value_, int fiberDim = 1>
270: class UniformSection : public ALE::ParallelObject {
271: public:
272: typedef Point_ point_type;
273: typedef ConstantSection<point_type, int> atlas_type;
274: typedef typename atlas_type::chart_type chart_type;
275: typedef Value_ value_type;
276: typedef struct {value_type v[fiberDim];} fiber_type;
277: typedef std::map<point_type, fiber_type> values_type;
278: protected:
279: Obj<atlas_type> _atlas;
280: values_type _array;
281: fiber_type _emptyValue;
282: public:
283: UniformSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {
284: this->_atlas = new atlas_type(comm, fiberDim, 0, debug);
285: for(int i = 0; i < fiberDim; ++i) this->_emptyValue.v[i] = value_type();
286: };
287: UniformSection(const Obj<atlas_type>& atlas) : ParallelObject(atlas->comm(), atlas->debug()), _atlas(atlas) {
288: int dim = fiberDim;
289: this->_atlas->update(*this->_atlas->getChart().begin(), &dim);
290: for(int i = 0; i < fiberDim; ++i) this->_emptyValue.v[i] = value_type();
291: };
292: virtual ~UniformSection() {
293: this->_atlas = NULL;
294: };
295: public:
296: value_type *getRawArray(const int size) {
297: static value_type *array = NULL;
298: static int maxSize = 0;
300: if (size > maxSize) {
301: maxSize = size;
302: if (array) delete [] array;
303: array = new value_type[maxSize];
304: };
305: return array;
306: };
307: public: // Verifiers
308: bool hasPoint(const point_type& point) {
309: return this->_atlas->hasPoint(point);
310: };
311: void checkDimension(const int& dim) {
312: if (dim != fiberDim) {
313: ostringstream msg;
314: msg << "Invalid fiber dimension " << dim << " must be " << fiberDim << std::endl;
315: throw ALE::Exception(msg.str().c_str());
316: }
317: };
318: public: // Accessors
319: const chart_type& getChart() {return this->_atlas->getChart();};
320: const Obj<atlas_type>& getAtlas() {return this->_atlas;};
321: void setAtlas(const Obj<atlas_type>& atlas) {this->_atlas = atlas;};
322: void addPoint(const point_type& point) {
323: this->setFiberDimension(point, fiberDim);
324: };
325: template<typename Points>
326: void addPoint(const Obj<Points>& points) {
327: for(typename Points::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
328: this->setFiberDimension(*p_iter, fiberDim);
329: }
330: };
331: void copy(const Obj<UniformSection>& section) {
332: this->getAtlas()->copy(section->getAtlas());
333: const chart_type& chart = section->getChart();
335: for(typename chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
336: this->updatePoint(*c_iter, section->restrictPoint(*c_iter));
337: }
338: };
339: public: // Sizes
340: void clear() {
341: this->_atlas->clear();
342: this->_array.clear();
343: };
344: int getFiberDimension(const point_type& p) const {
345: return this->_atlas->restrictPoint(p)[0];
346: };
347: void setFiberDimension(const point_type& p, int dim) {
348: this->checkDimension(dim);
349: this->_atlas->addPoint(p);
350: this->_atlas->updatePoint(p, &dim);
351: };
352: template<typename Sequence>
353: void setFiberDimension(const Obj<Sequence>& points, int dim) {
354: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
355: this->setFiberDimension(*p_iter, dim);
356: }
357: };
358: void setFiberDimension(const std::set<point_type>& points, int dim) {
359: for(typename std::set<point_type>::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
360: this->setFiberDimension(*p_iter, dim);
361: }
362: };
363: void addFiberDimension(const point_type& p, int dim) {
364: if (this->hasPoint(p)) {
365: ostringstream msg;
366: msg << "Invalid addition to fiber dimension " << dim << " cannot exceed " << fiberDim << std::endl;
367: throw ALE::Exception(msg.str().c_str());
368: } else {
369: this->setFiberDimension(p, dim);
370: }
371: };
372: int size() const {
373: const chart_type& points = this->_atlas->getChart();
374: int size = 0;
376: for(typename chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
377: size += this->getFiberDimension(*p_iter);
378: }
379: return size;
380: };
381: int sizeWithBC() const {
382: return this->size();
383: };
384: public: // Restriction
385: // Return a pointer to the entire contiguous storage array
386: const values_type& restrict() {
387: return this->_array;
388: };
389: // Return only the values associated to this point, not its closure
390: const value_type *restrictPoint(const point_type& p) {
391: if (this->_array.find(p) == this->_array.end()) return this->_emptyValue.v;
392: return this->_array[p].v;
393: };
394: // Update only the values associated to this point, not its closure
395: void updatePoint(const point_type& p, const value_type v[]) {
396: for(int i = 0; i < fiberDim; ++i) {
397: this->_array[p].v[i] = v[i];
398: }
399: };
400: // Update only the values associated to this point, not its closure
401: void updateAddPoint(const point_type& p, const value_type v[]) {
402: for(int i = 0; i < fiberDim; ++i) {
403: this->_array[p].v[i] += v[i];
404: }
405: };
406: void updatePointAll(const point_type& p, const value_type v[]) {
407: this->updatePoint(p, v);
408: };
409: public:
410: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
411: ostringstream txt;
412: int rank;
414: if (comm == MPI_COMM_NULL) {
415: comm = this->comm();
416: rank = this->commRank();
417: } else {
418: MPI_Comm_rank(comm, &rank);
419: }
420: if (name == "") {
421: if(rank == 0) {
422: txt << "viewing a UniformSection" << std::endl;
423: }
424: } else {
425: if(rank == 0) {
426: txt << "viewing UniformSection '" << name << "'" << std::endl;
427: }
428: }
429: const typename atlas_type::chart_type& chart = this->_atlas->getChart();
430: values_type& array = this->_array;
432: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
433: const point_type& point = *p_iter;
434: const typename atlas_type::value_type dim = this->_atlas->restrict(point)[0];
436: if (dim != 0) {
437: txt << "[" << this->commRank() << "]: " << point << " dim " << dim << " ";
438: for(int i = 0; i < dim; i++) {
439: txt << " " << array[point].v[i];
440: }
441: txt << std::endl;
442: }
443: }
444: if (chart.size() == 0) {
445: txt << "[" << this->commRank() << "]: empty" << std::endl;
446: }
447: PetscSynchronizedPrintf(comm, txt.str().c_str());
448: PetscSynchronizedFlush(comm);
449: };
450: };
451: // A Section is our most general construct (more general ones could be envisioned)
452: // The Atlas is a UniformSection of dimension 1 and value type Point
453: // to hold each fiber dimension and offsets into a contiguous patch array
454: template<typename Point_, typename Value_>
455: class Section : public ALE::ParallelObject {
456: public:
457: typedef Point_ point_type;
458: typedef ALE::Point index_type;
459: typedef UniformSection<point_type, index_type> atlas_type;
460: typedef typename atlas_type::chart_type chart_type;
461: typedef Value_ value_type;
462: typedef value_type * values_type;
463: protected:
464: Obj<atlas_type> _atlas;
465: Obj<atlas_type> _atlasNew;
466: values_type _array;
467: public:
468: Section(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {
469: this->_atlas = new atlas_type(comm, debug);
470: this->_atlasNew = NULL;
471: this->_array = NULL;
472: };
473: Section(const Obj<atlas_type>& atlas) : ParallelObject(atlas->comm(), atlas->debug()), _atlas(atlas), _atlasNew(NULL), _array(NULL) {};
474: virtual ~Section() {
475: if (this->_array) {
476: delete [] this->_array;
477: this->_array = NULL;
478: }
479: };
480: public:
481: value_type *getRawArray(const int size) {
482: static value_type *array = NULL;
483: static int maxSize = 0;
485: if (size > maxSize) {
486: maxSize = size;
487: if (array) delete [] array;
488: array = new value_type[maxSize];
489: };
490: return array;
491: };
492: int getStorageSize() const {
493: return this->sizeWithBC();
494: };
495: public: // Verifiers
496: bool hasPoint(const point_type& point) {
497: return this->_atlas->hasPoint(point);
498: };
499: public: // Accessors
500: const Obj<atlas_type>& getAtlas() {return this->_atlas;};
501: void setAtlas(const Obj<atlas_type>& atlas) {this->_atlas = atlas;};
502: const Obj<atlas_type>& getNewAtlas() {return this->_atlasNew;};
503: void setNewAtlas(const Obj<atlas_type>& atlas) {this->_atlasNew = atlas;};
504: const chart_type& getChart() const {return this->_atlas->getChart();};
505: public: // BC
506: // Returns the number of constraints on a point
507: const int getConstraintDimension(const point_type& p) const {
508: return std::max(0, -this->_atlas->restrictPoint(p)->prefix);
509: };
510: // Set the number of constraints on a point
511: // We only allow the entire point to be constrained, so these will be the
512: // only dofs on the point
513: void setConstraintDimension(const point_type& p, const int numConstraints) {
514: this->setFiberDimension(p, -numConstraints);
515: };
516: void addConstraintDimension(const point_type& p, const int numConstraints) {
517: throw ALE::Exception("Variable constraint dimensions not available for this Section type");
518: };
519: void copyBC(const Obj<Section>& section) {
520: const chart_type& chart = this->getChart();
522: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
523: if (this->getConstraintDimension(*p_iter)) {
524: this->updatePointBC(*p_iter, section->restrictPoint(*p_iter));
525: }
526: }
527: };
528: void defaultConstraintDof() {};
529: public: // Sizes
530: void clear() {
531: this->_atlas->clear();
532: delete [] this->_array;
533: this->_array = NULL;
534: };
535: // Return the total number of dofs on the point (free and constrained)
536: int getFiberDimension(const point_type& p) const {
537: return std::abs(this->_atlas->restrictPoint(p)->prefix);
538: };
539: int getFiberDimension(const Obj<atlas_type>& atlas, const point_type& p) const {
540: return std::abs(atlas->restrictPoint(p)->prefix);
541: };
542: // Set the total number of dofs on the point (free and constrained)
543: void setFiberDimension(const point_type& p, int dim) {
544: const index_type idx(dim, -1);
545: this->_atlas->addPoint(p);
546: this->_atlas->updatePoint(p, &idx);
547: };
548: template<typename Sequence>
549: void setFiberDimension(const Obj<Sequence>& points, int dim) {
550: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
551: this->setFiberDimension(*p_iter, dim);
552: }
553: };
554: void addFiberDimension(const point_type& p, int dim) {
555: if (this->_atlas->hasPoint(p)) {
556: const index_type values(dim, 0);
557: this->_atlas->updateAddPoint(p, &values);
558: } else {
559: this->setFiberDimension(p, dim);
560: }
561: };
562: // Return the number of constrained dofs on this point
563: // If constrained, this is equal to the fiber dimension
564: // Otherwise, 0
565: int getConstrainedFiberDimension(const point_type& p) const {
566: return std::max(0, this->_atlas->restrictPoint(p)->prefix);
567: };
568: // Return the total number of free dofs
569: int size() const {
570: const chart_type& points = this->getChart();
571: int size = 0;
573: for(typename chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
574: size += this->getConstrainedFiberDimension(*p_iter);
575: }
576: return size;
577: };
578: // Return the total number of dofs (free and constrained)
579: int sizeWithBC() const {
580: const chart_type& points = this->getChart();
581: int size = 0;
583: for(typename chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
584: size += this->getFiberDimension(*p_iter);
585: }
586: return size;
587: };
588: public: // Index retrieval
589: const typename index_type::index_type& getIndex(const point_type& p) {
590: return this->_atlas->restrictPoint(p)->index;
591: };
592: void setIndex(const point_type& p, const typename index_type::index_type& index) {
593: ((typename atlas_type::value_type *) this->_atlas->restrictPoint(p))->index = index;
594: };
595: void setIndexBC(const point_type& p, const typename index_type::index_type& index) {
596: this->setIndex(p, index);
597: };
598: void getIndices(const point_type& p, PetscInt indices[], PetscInt *indx, const int orientation = 1, const bool freeOnly = false, const bool skipConstraints = false) {
599: this->getIndices(p, this->getIndex(p), indices, indx, orientation, freeOnly, skipConstraints);
600: };
601: template<typename Order_>
602: 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) {
603: this->getIndices(p, order->getIndex(p), indices, indx, orientation, freeOnly, skipConstraints);
604: };
605: 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) {
606: const int& dim = this->getFiberDimension(p);
607: const int& cDim = this->getConstraintDimension(p);
608: const int end = start + dim;
610: if (!cDim) {
611: if (orientation >= 0) {
612: for(int i = start; i < end; ++i) {
613: indices[(*indx)++] = i;
614: }
615: } else {
616: for(int i = end-1; i >= start; --i) {
617: indices[(*indx)++] = i;
618: }
619: }
620: } else {
621: if (!freeOnly) {
622: for(int i = start; i < end; ++i) {
623: indices[(*indx)++] = -1;
624: }
625: }
626: }
627: };
628: public: // Allocation
629: void allocateStorage() {
630: const int totalSize = this->sizeWithBC();
632: this->_array = new value_type[totalSize];
633: PetscMemzero(this->_array, totalSize * sizeof(value_type));
634: };
635: void replaceStorage(value_type *newArray) {
636: delete [] this->_array;
637: this->_array = newArray;
638: this->_atlasNew = NULL;
639: };
640: void addPoint(const point_type& point, const int dim) {
641: if (dim == 0) return;
642: if (this->_atlasNew.isNull()) {
643: this->_atlasNew = new atlas_type(this->comm(), this->debug());
644: this->_atlasNew->copy(this->_atlas);
645: }
646: const index_type idx(dim, -1);
647: this->_atlasNew->addPoint(point);
648: this->_atlasNew->updatePoint(point, &idx);
649: };
650: template<typename Sequence>
651: void addPoints(const Obj<Sequence>& points, const int dim) {
652: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
653: this->addPoint(*p_iter, dim);
654: }
655: };
656: void orderPoints(const Obj<atlas_type>& atlas){
657: const chart_type& chart = this->getChart();
658: int offset = 0;
659: int bcOffset = this->size();
661: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
662: typename atlas_type::value_type idx = atlas->restrictPoint(*c_iter)[0];
663: const int& dim = idx.prefix;
665: if (dim >= 0) {
666: idx.index = offset;
667: atlas->updatePoint(*c_iter, &idx);
668: offset += dim;
669: } else {
670: idx.index = bcOffset;
671: atlas->updatePoint(*c_iter, &idx);
672: bcOffset -= dim;
673: }
674: }
675: };
676: void allocatePoint() {
677: this->orderPoints(this->_atlas);
678: this->allocateStorage();
679: };
680: public: // Restriction and Update
681: // Zero entries
682: void zero() {
683: memset(this->_array, 0, this->size()* sizeof(value_type));
684: };
685: // Return a pointer to the entire contiguous storage array
686: const value_type *restrict() {
687: return this->_array;
688: };
689: // Update the entire contiguous storage array
690: void update(const value_type v[]) {
691: const value_type *array = this->_array;
692: const int size = this->size();
694: for(int i = 0; i < size; i++) {
695: array[i] = v[i];
696: }
697: };
698: // Return the free values on a point
699: const value_type *restrictPoint(const point_type& p) {
700: return &(this->_array[this->_atlas->restrictPoint(p)[0].index]);
701: };
702: // Update the free values on a point
703: void updatePoint(const point_type& p, const value_type v[], const int orientation = 1) {
704: const index_type& idx = this->_atlas->restrictPoint(p)[0];
705: value_type *a = &(this->_array[idx.index]);
707: if (orientation >= 0) {
708: for(int i = 0; i < idx.prefix; ++i) {
709: a[i] = v[i];
710: }
711: } else {
712: const int last = idx.prefix-1;
714: for(int i = 0; i < idx.prefix; ++i) {
715: a[i] = v[last-i];
716: }
717: }
718: };
719: // Update the free values on a point
720: void updateAddPoint(const point_type& p, const value_type v[], const int orientation = 1) {
721: const index_type& idx = this->_atlas->restrictPoint(p)[0];
722: value_type *a = &(this->_array[idx.index]);
724: if (orientation >= 0) {
725: for(int i = 0; i < idx.prefix; ++i) {
726: a[i] += v[i];
727: }
728: } else {
729: const int last = idx.prefix-1;
731: for(int i = 0; i < idx.prefix; ++i) {
732: a[i] += v[last-i];
733: }
734: }
735: };
736: // Update only the constrained dofs on a point
737: void updatePointBC(const point_type& p, const value_type v[], const int orientation = 1) {
738: const index_type& idx = this->_atlas->restrictPoint(p)[0];
739: const int dim = -idx.prefix;
740: value_type *a = &(this->_array[idx.index]);
742: if (orientation >= 0) {
743: for(int i = 0; i < dim; ++i) {
744: a[i] = v[i];
745: }
746: } else {
747: const int last = dim-1;
749: for(int i = 0; i < dim; ++i) {
750: a[i] = v[last-i];
751: }
752: }
753: };
754: // Update all dofs on a point (free and constrained)
755: void updatePointAll(const point_type& p, const value_type v[], const int orientation = 1) {
756: const index_type& idx = this->_atlas->restrictPoint(p)[0];
757: const int dim = std::abs(idx.prefix);
758: value_type *a = &(this->_array[idx.index]);
760: if (orientation >= 0) {
761: for(int i = 0; i < dim; ++i) {
762: a[i] = v[i];
763: }
764: } else {
765: const int last = dim-1;
767: for(int i = 0; i < dim; ++i) {
768: a[i] = v[last-i];
769: }
770: }
771: };
772: public:
773: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
774: ostringstream txt;
775: int rank;
777: if (comm == MPI_COMM_NULL) {
778: comm = this->comm();
779: rank = this->commRank();
780: } else {
781: MPI_Comm_rank(comm, &rank);
782: }
783: if(rank == 0) {
784: txt << "viewing Section " << this->getName() << std::endl;
785: if (name != "") {
786: txt << ": " << name << "'";
787: }
788: txt << std::endl;
789: }
790: const typename atlas_type::chart_type& chart = this->_atlas->getChart();
791: const value_type *array = this->_array;
793: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
794: const point_type& point = *p_iter;
795: const index_type& idx = this->_atlas->restrictPoint(point)[0];
796: const int dim = this->getFiberDimension(point);
798: if (idx.prefix != 0) {
799: txt << "[" << this->commRank() << "]: " << point << " dim " << idx.prefix << " offset " << idx.index << " ";
800: for(int i = 0; i < dim; i++) {
801: txt << " " << array[idx.index+i];
802: }
803: txt << std::endl;
804: }
805: }
806: if (chart.size() == 0) {
807: txt << "[" << this->commRank() << "]: empty" << std::endl;
808: }
809: PetscSynchronizedPrintf(comm, txt.str().c_str());
810: PetscSynchronizedFlush(comm);
811: };
812: public: // Fibrations
813: void setConstraintDof(const point_type& p, const int dofs[]) {};
814: int getNumSpaces() const {return 1;};
815: void addSpace() {};
816: int getFiberDimension(const point_type& p, const int space) {return this->getFiberDimension(p);};
817: void setFiberDimension(const point_type& p, int dim, const int space) {this->setFiberDimension(p, dim);};
818: template<typename Sequence>
819: void setFiberDimension(const Obj<Sequence>& points, int dim, const int space) {
820: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
821: this->setFiberDimension(*p_iter, dim, space);
822: }
823: };
824: void setConstraintDimension(const point_type& p, const int numConstraints, const int space) {
825: this->setConstraintDimension(p, numConstraints);
826: };
827: };
828: // GeneralSection will support BC on a subset of unknowns on a point
829: // We make a separate constraint Atlas to mark constrained dofs on a point
830: // Storage will be contiguous by node, just as in Section
831: // This allows fast restrict(p)
832: // Then update() is accomplished by skipping constrained unknowns
833: // We must eliminate restrict() since it does not correspond to the constrained system
834: // Numbering will have to be rewritten to calculate correct mappings
835: // I think we can just generate multiple tuples per point
836: template<typename Point_, typename Value_>
837: class GeneralSection : public ALE::ParallelObject {
838: public:
839: typedef Point_ point_type;
840: typedef ALE::Point index_type;
841: typedef UniformSection<point_type, index_type> atlas_type;
842: typedef Section<point_type, int> bc_type;
843: typedef typename atlas_type::chart_type chart_type;
844: typedef Value_ value_type;
845: typedef value_type * values_type;
846: typedef std::pair<const int *, const int *> customAtlasInd_type;
847: typedef std::pair<customAtlasInd_type, bool> customAtlas_type;
848: protected:
849: Obj<atlas_type> _atlas;
850: Obj<atlas_type> _atlasNew;
851: values_type _array;
852: bool _sharedStorage;
853: int _sharedStorageSize;
854: Obj<bc_type> _bc;
855: std::vector<Obj<atlas_type> > _spaces;
856: std::vector<Obj<bc_type> > _bcs;
857: // Optimization
858: std::vector<customAtlas_type> _customRestrictAtlas;
859: std::vector<customAtlas_type> _customUpdateAtlas;
860: public:
861: GeneralSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {
862: this->_atlas = new atlas_type(comm, debug);
863: this->_atlasNew = NULL;
864: this->_array = NULL;
865: this->_sharedStorage = false;
866: this->_bc = new bc_type(comm, debug);
867: };
868: GeneralSection(const Obj<atlas_type>& atlas) : ParallelObject(atlas->comm(), atlas->debug()), _atlas(atlas), _atlasNew(NULL), _array(NULL), _sharedStorage(false), _sharedStorageSize(0) {
869: this->_bc = new bc_type(comm, debug);
870: };
871: virtual ~GeneralSection() {
872: if (this->_array && !this->_sharedStorage) {
873: delete [] this->_array;
874: this->_array = NULL;
875: }
876: for(std::vector<customAtlas_type>::iterator a_iter = this->_customRestrictAtlas.begin(); a_iter != this->_customRestrictAtlas.end(); ++a_iter) {
877: if (a_iter->second) {
878: delete [] a_iter->first.first;
879: delete [] a_iter->first.second;
880: }
881: }
882: for(std::vector<customAtlas_type>::iterator a_iter = this->_customUpdateAtlas.begin(); a_iter != this->_customUpdateAtlas.end(); ++a_iter) {
883: if (a_iter->second) {
884: delete [] a_iter->first.first;
885: delete [] a_iter->first.second;
886: }
887: }
888: };
889: public:
890: value_type *getRawArray(const int size) {
891: // Put in a sentinel value that deallocates the array
892: static value_type *array = NULL;
893: static int maxSize = 0;
895: if (size > maxSize) {
896: maxSize = size;
897: if (array) delete [] array;
898: array = new value_type[maxSize];
899: };
900: return array;
901: };
902: int getStorageSize() const {
903: if (this->_sharedStorage) {
904: return this->_sharedStorageSize;
905: }
906: return this->sizeWithBC();
907: };
908: public: // Verifiers
909: bool hasPoint(const point_type& point) {
910: return this->_atlas->hasPoint(point);
911: };
912: public: // Accessors
913: const Obj<atlas_type>& getAtlas() const {return this->_atlas;};
914: void setAtlas(const Obj<atlas_type>& atlas) {this->_atlas = atlas;};
915: const Obj<atlas_type>& getNewAtlas() const {return this->_atlasNew;};
916: void setNewAtlas(const Obj<atlas_type>& atlas) {this->_atlasNew = atlas;};
917: const Obj<bc_type>& getBC() const {return this->_bc;};
918: void setBC(const Obj<bc_type>& bc) {this->_bc = bc;};
919: const chart_type& getChart() const {return this->_atlas->getChart();};
920: public: // BC
921: // Returns the number of constraints on a point
922: const int getConstraintDimension(const point_type& p) const {
923: if (!this->_bc->hasPoint(p)) return 0;
924: return this->_bc->getFiberDimension(p);
925: };
926: // Set the number of constraints on a point
927: void setConstraintDimension(const point_type& p, const int numConstraints) {
928: this->_bc->setFiberDimension(p, numConstraints);
929: };
930: // Increment the number of constraints on a point
931: void addConstraintDimension(const point_type& p, const int numConstraints) {
932: this->_bc->addFiberDimension(p, numConstraints);
933: };
934: // Return the local dofs which are constrained on a point
935: const int *getConstraintDof(const point_type& p) {
936: return this->_bc->restrictPoint(p);
937: };
938: // Set the local dofs which are constrained on a point
939: void setConstraintDof(const point_type& p, const int dofs[]) {
940: this->_bc->updatePoint(p, dofs);
941: };
942: void copyBC(const Obj<GeneralSection>& section) {
943: this->setBC(section->getBC());
944: const chart_type& chart = this->getChart();
946: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
947: if (this->getConstraintDimension(*p_iter)) {
948: this->updatePointBCFull(*p_iter, section->restrictPoint(*p_iter));
949: }
950: }
951: this->copyFibration(section);
952: };
953: void defaultConstraintDof() {
954: const chart_type& chart = this->getChart();
955: int size = 0;
957: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
958: size = std::max(size, this->getConstraintDimension(*p_iter));
959: }
960: int *dofs = new int[size];
961: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
962: const int cDim = this->getConstraintDimension(*p_iter);
964: if (cDim) {
965: for(int d = 0; d < cDim; ++d) {
966: dofs[d] = d;
967: }
968: this->_bc->updatePoint(*p_iter, dofs);
969: }
970: }
971: };
972: public: // Sizes
973: void clear() {
974: this->_atlas->clear();
975: if (!this->_sharedStorage) delete [] this->_array;
976: this->_array = NULL;
977: this->_bc->clear();
978: };
979: // Return the total number of dofs on the point (free and constrained)
980: int getFiberDimension(const point_type& p) const {
981: return this->_atlas->restrictPoint(p)->prefix;
982: };
983: int getFiberDimension(const Obj<atlas_type>& atlas, const point_type& p) const {
984: return atlas->restrictPoint(p)->prefix;
985: };
986: // Set the total number of dofs on the point (free and constrained)
987: void setFiberDimension(const point_type& p, int dim) {
988: const index_type idx(dim, -1);
989: this->_atlas->addPoint(p);
990: this->_atlas->updatePoint(p, &idx);
991: };
992: template<typename Sequence>
993: void setFiberDimension(const Obj<Sequence>& points, int dim) {
994: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
995: this->setFiberDimension(*p_iter, dim);
996: }
997: };
998: void addFiberDimension(const point_type& p, int dim) {
999: if (this->_atlas->hasPoint(p)) {
1000: const index_type values(dim, 0);
1001: this->_atlas->updateAddPoint(p, &values);
1002: } else {
1003: this->setFiberDimension(p, dim);
1004: }
1005: };
1006: // Return the number of constrained dofs on this point
1007: int getConstrainedFiberDimension(const point_type& p) const {
1008: return this->getFiberDimension(p) - this->getConstraintDimension(p);
1009: };
1010: // Return the total number of free dofs
1011: int size() const {
1012: const chart_type& points = this->getChart();
1013: int size = 0;
1015: for(typename chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
1016: size += this->getConstrainedFiberDimension(*p_iter);
1017: }
1018: return size;
1019: };
1020: // Return the total number of dofs (free and constrained)
1021: int sizeWithBC() const {
1022: const chart_type& points = this->getChart();
1023: int size = 0;
1025: for(typename chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
1026: size += this->getFiberDimension(*p_iter);
1027: }
1028: return size;
1029: };
1030: public: // Index retrieval
1031: const typename index_type::index_type& getIndex(const point_type& p) {
1032: return this->_atlas->restrictPoint(p)->index;
1033: };
1034: void setIndex(const point_type& p, const typename index_type::index_type& index) {
1035: ((typename atlas_type::value_type *) this->_atlas->restrictPoint(p))->index = index;
1036: };
1037: void setIndexBC(const point_type& p, const typename index_type::index_type& index) {};
1038: void getIndices(const point_type& p, PetscInt indices[], PetscInt *indx, const int orientation = 1, const bool freeOnly = false, const bool skipConstraints = false) {
1039: this->getIndices(p, this->getIndex(p), indices, indx, orientation, freeOnly, skipConstraints);
1040: };
1041: template<typename Order_>
1042: 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) {
1043: this->getIndices(p, order->getIndex(p), indices, indx, orientation, freeOnly, skipConstraints);
1044: };
1045: void getIndicesRaw(const point_type& p, const int start, PetscInt indices[], PetscInt *indx, const int orientation) {
1046: if (orientation >= 0) {
1047: const int& dim = this->getFiberDimension(p);
1048: const int end = start + dim;
1050: for(int i = start; i < end; ++i) {
1051: indices[(*indx)++] = i;
1052: }
1053: } else {
1054: const int numSpaces = this->getNumSpaces();
1055: int offset = start;
1057: for(int space = 0; space < numSpaces; ++space) {
1058: const int& dim = this->getFiberDimension(p, space);
1060: for(int i = offset+dim-1; i >= offset; --i) {
1061: indices[(*indx)++] = i;
1062: }
1063: offset += dim;
1064: }
1065: if (!numSpaces) {
1066: const int& dim = this->getFiberDimension(p);
1068: for(int i = offset+dim-1; i >= offset; --i) {
1069: indices[(*indx)++] = i;
1070: }
1071: offset += dim;
1072: }
1073: }
1074: }
1075: 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) {
1076: const int& cDim = this->getConstraintDimension(p);
1078: if (!cDim) {
1079: this->getIndicesRaw(p, start, indices, indx, orientation);
1080: } else {
1081: if (orientation >= 0) {
1082: const int& dim = this->getFiberDimension(p);
1083: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1084: int cInd = 0;
1086: for(int i = start, k = 0; k < dim; ++k) {
1087: if ((cInd < cDim) && (k == cDof[cInd])) {
1088: if (!freeOnly) indices[(*indx)++] = -(k+1);
1089: if (skipConstraints) ++i;
1090: ++cInd;
1091: } else {
1092: indices[(*indx)++] = i++;
1093: }
1094: }
1095: } else {
1096: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1097: int offset = 0;
1098: int cOffset = 0;
1099: int j = -1;
1101: for(int space = 0; space < this->getNumSpaces(); ++space) {
1102: const int dim = this->getFiberDimension(p, space);
1103: const int tDim = this->getConstrainedFiberDimension(p, space);
1104: int cInd = (dim - tDim)-1;
1106: j += dim;
1107: for(int i = 0, k = start+tDim+offset; i < dim; ++i, --j) {
1108: if ((cInd >= 0) && (j == cDof[cInd+cOffset])) {
1109: if (!freeOnly) indices[(*indx)++] = -(offset+i+1);
1110: if (skipConstraints) --k;
1111: --cInd;
1112: } else {
1113: indices[(*indx)++] = --k;
1114: }
1115: }
1116: j += dim;
1117: offset += dim;
1118: cOffset += dim - tDim;
1119: }
1120: }
1121: }
1122: };
1123: public: // Allocation
1124: void allocateStorage() {
1125: const int totalSize = this->sizeWithBC();
1127: this->_array = new value_type[totalSize];
1128: this->_sharedStorage = false;
1129: this->_sharedStorageSize = 0;
1130: PetscMemzero(this->_array, totalSize * sizeof(value_type));
1131: this->_bc->allocatePoint();
1132: };
1133: void replaceStorage(value_type *newArray, const bool sharedStorage = false, const int sharedStorageSize = 0) {
1134: if (this->_array && !this->_sharedStorage) {delete [] this->_array;}
1135: this->_array = newArray;
1136: this->_sharedStorage = sharedStorage;
1137: this->_sharedStorageSize = sharedStorageSize;
1138: this->_atlas = this->_atlasNew;
1139: this->_atlasNew = NULL;
1140: };
1141: void addPoint(const point_type& point, const int dim) {
1142: if (dim == 0) return;
1143: if (this->_atlasNew.isNull()) {
1144: this->_atlasNew = new atlas_type(this->comm(), this->debug());
1145: this->_atlasNew->copy(this->_atlas);
1146: }
1147: const index_type idx(dim, -1);
1148: this->_atlasNew->addPoint(point);
1149: this->_atlasNew->updatePoint(point, &idx);
1150: };
1151: void orderPoints(const Obj<atlas_type>& atlas){
1152: const chart_type& chart = this->getChart();
1153: int offset = 0;
1155: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1156: typename atlas_type::value_type idx = atlas->restrictPoint(*c_iter)[0];
1157: const int& dim = idx.prefix;
1159: idx.index = offset;
1160: atlas->updatePoint(*c_iter, &idx);
1161: offset += dim;
1162: }
1163: };
1164: void allocatePoint() {
1165: this->orderPoints(this->_atlas);
1166: this->allocateStorage();
1167: };
1168: public: // Restriction and Update
1169: // Zero entries
1170: void zero() {
1171: this->set(0.0);
1172: };
1173: void set(const value_type value) {
1174: //memset(this->_array, 0, this->sizeWithBC()* sizeof(value_type));
1175: const chart_type& chart = this->getChart();
1177: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1178: value_type *array = (value_type *) this->restrictPoint(*c_iter);
1179: const int& dim = this->getFiberDimension(*c_iter);
1180: const int& cDim = this->getConstraintDimension(*c_iter);
1182: if (!cDim) {
1183: for(int i = 0; i < dim; ++i) {
1184: array[i] = value;
1185: }
1186: } else {
1187: const typename bc_type::value_type *cDof = this->getConstraintDof(*c_iter);
1188: int cInd = 0;
1190: for(int i = 0; i < dim; ++i) {
1191: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1192: array[i] = value;
1193: }
1194: }
1195: }
1196: };
1197: // Add two sections and put the result in a third
1198: void add(const Obj<GeneralSection>& x, const Obj<GeneralSection>& y) {
1199: // Check atlases
1200: const chart_type& chart = this->getChart();
1202: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1203: value_type *array = (value_type *) this->restrictPoint(*c_iter);
1204: const value_type *xArray = x->restrictPoint(*c_iter);
1205: const value_type *yArray = y->restrictPoint(*c_iter);
1206: const int& dim = this->getFiberDimension(*c_iter);
1207: const int& cDim = this->getConstraintDimension(*c_iter);
1209: if (!cDim) {
1210: for(int i = 0; i < dim; ++i) {
1211: array[i] = xArray[i] + yArray[i];
1212: }
1213: } else {
1214: const typename bc_type::value_type *cDof = this->getConstraintDof(*c_iter);
1215: int cInd = 0;
1217: for(int i = 0; i < dim; ++i) {
1218: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1219: array[i] = xArray[i] + yArray[i];
1220: }
1221: }
1222: }
1223: };
1224: // this = this + alpha * x
1225: void axpy(const value_type alpha, const Obj<GeneralSection>& x) {
1226: // Check atlases
1227: const chart_type& chart = this->getChart();
1229: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1230: value_type *array = (value_type *) this->restrictPoint(*c_iter);
1231: const value_type *xArray = x->restrictPoint(*c_iter);
1232: const int& dim = this->getFiberDimension(*c_iter);
1233: const int& cDim = this->getConstraintDimension(*c_iter);
1235: if (!cDim) {
1236: for(int i = 0; i < dim; ++i) {
1237: array[i] += alpha*xArray[i];
1238: }
1239: } else {
1240: const typename bc_type::value_type *cDof = this->getConstraintDof(*c_iter);
1241: int cInd = 0;
1243: for(int i = 0; i < dim; ++i) {
1244: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1245: array[i] += alpha*xArray[i];
1246: }
1247: }
1248: }
1249: };
1250: // Return the free values on a point
1251: const value_type *restrict() const {
1252: return this->_array;
1253: };
1254: // Return the free values on a point
1255: const value_type *restrictPoint(const point_type& p) const {
1256: return &(this->_array[this->_atlas->restrictPoint(p)[0].index]);
1257: };
1258: // Update the free values on a point
1259: // Takes a full array and ignores constrained values
1260: void updatePoint(const point_type& p, const value_type v[], const int orientation = 1) {
1261: value_type *array = (value_type *) this->restrictPoint(p);
1262: const int& cDim = this->getConstraintDimension(p);
1264: if (!cDim) {
1265: if (orientation >= 0) {
1266: const int& dim = this->getFiberDimension(p);
1268: for(int i = 0; i < dim; ++i) {
1269: array[i] = v[i];
1270: }
1271: } else {
1272: int offset = 0;
1273: int j = -1;
1275: for(int space = 0; space < this->getNumSpaces(); ++space) {
1276: const int& dim = this->getFiberDimension(p, space);
1278: for(int i = dim-1; i >= 0; --i) {
1279: array[++j] = v[i+offset];
1280: }
1281: offset += dim;
1282: }
1283: }
1284: } else {
1285: if (orientation >= 0) {
1286: const int& dim = this->getFiberDimension(p);
1287: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1288: int cInd = 0;
1290: for(int i = 0; i < dim; ++i) {
1291: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1292: array[i] = v[i];
1293: }
1294: } else {
1295: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1296: int offset = 0;
1297: int cOffset = 0;
1298: int j = 0;
1300: for(int space = 0; space < this->getNumSpaces(); ++space) {
1301: const int dim = this->getFiberDimension(p, space);
1302: const int tDim = this->getConstrainedFiberDimension(p, space);
1303: const int sDim = dim - tDim;
1304: int cInd = 0;
1306: for(int i = 0, k = dim+offset-1; i < dim; ++i, ++j, --k) {
1307: if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;}
1308: array[j] = v[k];
1309: }
1310: offset += dim;
1311: cOffset += dim - tDim;
1312: }
1313: }
1314: }
1315: };
1316: // Update the free values on a point
1317: // Takes a full array and ignores constrained values
1318: void updateAddPoint(const point_type& p, const value_type v[], const int orientation = 1) {
1319: value_type *array = (value_type *) this->restrictPoint(p);
1320: const int& cDim = this->getConstraintDimension(p);
1322: if (!cDim) {
1323: if (orientation >= 0) {
1324: const int& dim = this->getFiberDimension(p);
1326: for(int i = 0; i < dim; ++i) {
1327: array[i] += v[i];
1328: }
1329: } else {
1330: int offset = 0;
1331: int j = -1;
1333: for(int space = 0; space < this->getNumSpaces(); ++space) {
1334: const int& dim = this->getFiberDimension(p, space);
1336: for(int i = dim-1; i >= 0; --i) {
1337: array[++j] += v[i+offset];
1338: }
1339: offset += dim;
1340: }
1341: }
1342: } else {
1343: if (orientation >= 0) {
1344: const int& dim = this->getFiberDimension(p);
1345: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1346: int cInd = 0;
1348: for(int i = 0; i < dim; ++i) {
1349: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1350: array[i] += v[i];
1351: }
1352: } else {
1353: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1354: int offset = 0;
1355: int cOffset = 0;
1356: int j = 0;
1358: for(int space = 0; space < this->getNumSpaces(); ++space) {
1359: const int dim = this->getFiberDimension(p, space);
1360: const int tDim = this->getConstrainedFiberDimension(p, space);
1361: const int sDim = dim - tDim;
1362: int cInd = 0;
1364: for(int i = 0, k = dim+offset-1; i < dim; ++i, ++j, --k) {
1365: if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;}
1366: array[j] += v[k];
1367: }
1368: offset += dim;
1369: cOffset += dim - tDim;
1370: }
1371: }
1372: }
1373: };
1374: // Update the free values on a point
1375: // Takes ONLY unconstrained values
1376: void updateFreePoint(const point_type& p, const value_type v[], const int orientation = 1) {
1377: value_type *array = (value_type *) this->restrictPoint(p);
1378: const int& cDim = this->getConstraintDimension(p);
1380: if (!cDim) {
1381: if (orientation >= 0) {
1382: const int& dim = this->getFiberDimension(p);
1384: for(int i = 0; i < dim; ++i) {
1385: array[i] = v[i];
1386: }
1387: } else {
1388: int offset = 0;
1389: int j = -1;
1391: for(int space = 0; space < this->getNumSpaces(); ++space) {
1392: const int& dim = this->getFiberDimension(p, space);
1394: for(int i = dim-1; i >= 0; --i) {
1395: array[++j] = v[i+offset];
1396: }
1397: offset += dim;
1398: }
1399: }
1400: } else {
1401: if (orientation >= 0) {
1402: const int& dim = this->getFiberDimension(p);
1403: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1404: int cInd = 0;
1406: for(int i = 0, k = -1; i < dim; ++i) {
1407: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1408: array[i] = v[++k];
1409: }
1410: } else {
1411: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1412: int offset = 0;
1413: int cOffset = 0;
1414: int j = 0;
1416: for(int space = 0; space < this->getNumSpaces(); ++space) {
1417: const int dim = this->getFiberDimension(p, space);
1418: const int tDim = this->getConstrainedFiberDimension(p, space);
1419: const int sDim = dim - tDim;
1420: int cInd = 0;
1422: for(int i = 0, k = tDim+offset-1; i < dim; ++i, ++j) {
1423: if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;}
1424: array[j] = v[--k];
1425: }
1426: offset += dim;
1427: cOffset += dim - tDim;
1428: }
1429: }
1430: }
1431: };
1432: // Update the free values on a point
1433: // Takes ONLY unconstrained values
1434: void updateFreeAddPoint(const point_type& p, const value_type v[], const int orientation = 1) {
1435: value_type *array = (value_type *) this->restrictPoint(p);
1436: const int& cDim = this->getConstraintDimension(p);
1438: if (!cDim) {
1439: if (orientation >= 0) {
1440: const int& dim = this->getFiberDimension(p);
1442: for(int i = 0; i < dim; ++i) {
1443: array[i] += v[i];
1444: }
1445: } else {
1446: int offset = 0;
1447: int j = -1;
1449: for(int space = 0; space < this->getNumSpaces(); ++space) {
1450: const int& dim = this->getFiberDimension(p, space);
1452: for(int i = dim-1; i >= 0; --i) {
1453: array[++j] += v[i+offset];
1454: }
1455: offset += dim;
1456: }
1457: }
1458: } else {
1459: if (orientation >= 0) {
1460: const int& dim = this->getFiberDimension(p);
1461: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1462: int cInd = 0;
1464: for(int i = 0, k = -1; i < dim; ++i) {
1465: if ((cInd < cDim) && (i == cDof[cInd])) {++cInd; continue;}
1466: array[i] += v[++k];
1467: }
1468: } else {
1469: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1470: int offset = 0;
1471: int cOffset = 0;
1472: int j = 0;
1474: for(int space = 0; space < this->getNumSpaces(); ++space) {
1475: const int dim = this->getFiberDimension(p, space);
1476: const int tDim = this->getConstrainedFiberDimension(p, space);
1477: const int sDim = dim - tDim;
1478: int cInd = 0;
1480: for(int i = 0, k = tDim+offset-1; i < dim; ++i, ++j) {
1481: if ((cInd < sDim) && (j == cDof[cInd+cOffset])) {++cInd; continue;}
1482: array[j] += v[--k];
1483: }
1484: offset += dim;
1485: cOffset += dim - tDim;
1486: }
1487: }
1488: }
1489: };
1490: // Update only the constrained dofs on a point
1491: // This takes an array with ONLY bc values
1492: void updatePointBC(const point_type& p, const value_type v[], const int orientation = 1) {
1493: value_type *array = (value_type *) this->restrictPoint(p);
1494: const int& cDim = this->getConstraintDimension(p);
1496: if (cDim) {
1497: if (orientation >= 0) {
1498: const int& dim = this->getFiberDimension(p);
1499: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1500: int cInd = 0;
1502: for(int i = 0; i < dim; ++i) {
1503: if (cInd == cDim) break;
1504: if (i == cDof[cInd]) {
1505: array[i] = v[cInd];
1506: ++cInd;
1507: }
1508: }
1509: } else {
1510: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1511: int cOffset = 0;
1512: int j = 0;
1514: for(int space = 0; space < this->getNumSpaces(); ++space) {
1515: const int dim = this->getFiberDimension(p, space);
1516: const int tDim = this->getConstrainedFiberDimension(p, space);
1517: int cInd = 0;
1519: for(int i = 0; i < dim; ++i, ++j) {
1520: if (cInd < 0) break;
1521: if (j == cDof[cInd+cOffset]) {
1522: array[j] = v[cInd+cOffset];
1523: ++cInd;
1524: }
1525: }
1526: cOffset += dim - tDim;
1527: }
1528: }
1529: }
1530: };
1531: // Update only the constrained dofs on a point
1532: // This takes an array with ALL values, not just BC
1533: void updatePointBCFull(const point_type& p, const value_type v[], const int orientation = 1) {
1534: value_type *array = (value_type *) this->restrictPoint(p);
1535: const int& cDim = this->getConstraintDimension(p);
1537: if (cDim) {
1538: if (orientation >= 0) {
1539: const int& dim = this->getFiberDimension(p);
1540: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1541: int cInd = 0;
1543: for(int i = 0; i < dim; ++i) {
1544: if (cInd == cDim) break;
1545: if (i == cDof[cInd]) {
1546: array[i] = v[i];
1547: ++cInd;
1548: }
1549: }
1550: } else {
1551: const typename bc_type::value_type *cDof = this->getConstraintDof(p);
1552: int offset = 0;
1553: int cOffset = 0;
1554: int j = 0;
1556: for(int space = 0; space < this->getNumSpaces(); ++space) {
1557: const int dim = this->getFiberDimension(p, space);
1558: const int tDim = this->getConstrainedFiberDimension(p, space);
1559: int cInd = 0;
1561: for(int i = 0, k = dim+offset-1; i < dim; ++i, ++j, --k) {
1562: if (cInd < 0) break;
1563: if (j == cDof[cInd+cOffset]) {
1564: array[j] = v[k];
1565: ++cInd;
1566: }
1567: }
1568: offset += dim;
1569: cOffset += dim - tDim;
1570: }
1571: }
1572: }
1573: };
1574: // Update all dofs on a point (free and constrained)
1575: void updatePointAll(const point_type& p, const value_type v[], const int orientation = 1) {
1576: value_type *array = (value_type *) this->restrictPoint(p);
1578: if (orientation >= 0) {
1579: const int& dim = this->getFiberDimension(p);
1581: for(int i = 0; i < dim; ++i) {
1582: array[i] = v[i];
1583: }
1584: } else {
1585: int offset = 0;
1586: int j = -1;
1588: for(int space = 0; space < this->getNumSpaces(); ++space) {
1589: const int& dim = this->getFiberDimension(p, space);
1591: for(int i = dim-1; i >= 0; --i) {
1592: array[++j] = v[i+offset];
1593: }
1594: offset += dim;
1595: }
1596: }
1597: };
1598: // Update all dofs on a point (free and constrained)
1599: void updatePointAllAdd(const point_type& p, const value_type v[], const int orientation = 1) {
1600: value_type *array = (value_type *) this->restrictPoint(p);
1602: if (orientation >= 0) {
1603: const int& dim = this->getFiberDimension(p);
1605: for(int i = 0; i < dim; ++i) {
1606: array[i] += v[i];
1607: }
1608: } else {
1609: int offset = 0;
1610: int j = -1;
1612: for(int space = 0; space < this->getNumSpaces(); ++space) {
1613: const int& dim = this->getFiberDimension(p, space);
1615: for(int i = dim-1; i >= 0; --i) {
1616: array[++j] += v[i+offset];
1617: }
1618: offset += dim;
1619: }
1620: }
1621: };
1622: public: // Fibrations
1623: int getNumSpaces() const {return this->_spaces.size();};
1624: const std::vector<Obj<atlas_type> >& getSpaces() {return this->_spaces;};
1625: const std::vector<Obj<bc_type> >& getBCs() {return this->_bcs;};
1626: void addSpace() {
1627: Obj<atlas_type> space = new atlas_type(this->comm(), this->debug());
1628: Obj<bc_type> bc = new bc_type(this->comm(), this->debug());
1629: this->_spaces.push_back(space);
1630: this->_bcs.push_back(bc);
1631: };
1632: int getFiberDimension(const point_type& p, const int space) const {
1633: return this->_spaces[space]->restrictPoint(p)->prefix;
1634: };
1635: void setFiberDimension(const point_type& p, int dim, const int space) {
1636: const index_type idx(dim, -1);
1637: this->_spaces[space]->addPoint(p);
1638: this->_spaces[space]->updatePoint(p, &idx);
1639: };
1640: template<typename Sequence>
1641: void setFiberDimension(const Obj<Sequence>& points, int dim, const int space) {
1642: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
1643: this->setFiberDimension(*p_iter, dim, space);
1644: }
1645: };
1646: const int getConstraintDimension(const point_type& p, const int space) const {
1647: if (!this->_bcs[space]->hasPoint(p)) return 0;
1648: return this->_bcs[space]->getFiberDimension(p);
1649: };
1650: void setConstraintDimension(const point_type& p, const int numConstraints, const int space) {
1651: this->_bcs[space]->setFiberDimension(p, numConstraints);
1652: };
1653: int getConstrainedFiberDimension(const point_type& p, const int space) const {
1654: return this->getFiberDimension(p, space) - this->getConstraintDimension(p, space);
1655: };
1656: void copyFibration(const Obj<GeneralSection>& section) {
1657: const std::vector<Obj<atlas_type> >& spaces = section->getSpaces();
1658: const std::vector<Obj<bc_type> >& bcs = section->getBCs();
1660: this->_spaces.clear();
1661: for(typename std::vector<Obj<atlas_type> >::const_iterator s_iter = spaces.begin(); s_iter != spaces.end(); ++s_iter) {
1662: this->_spaces.push_back(*s_iter);
1663: }
1664: this->_bcs.clear();
1665: for(typename std::vector<Obj<bc_type> >::const_iterator b_iter = bcs.begin(); b_iter != bcs.end(); ++b_iter) {
1666: this->_bcs.push_back(*b_iter);
1667: }
1668: };
1669: Obj<GeneralSection> getFibration(const int space) const {
1670: Obj<GeneralSection> field = new GeneralSection(this->comm(), this->debug());
1671: // Obj<atlas_type> _atlas;
1672: // std::vector<Obj<atlas_type> > _spaces;
1673: // Obj<bc_type> _bc;
1674: // std::vector<Obj<bc_type> > _bcs;
1675: field->addSpace();
1676: const chart_type& chart = this->getChart();
1678: // Copy sizes
1679: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1680: const int fDim = this->getFiberDimension(*c_iter, space);
1681: const int cDim = this->getConstraintDimension(*c_iter, space);
1683: if (fDim) {
1684: field->setFiberDimension(*c_iter, fDim);
1685: field->setFiberDimension(*c_iter, fDim, 0);
1686: }
1687: if (cDim) {
1688: field->setConstraintDimension(*c_iter, cDim);
1689: field->setConstraintDimension(*c_iter, cDim, 0);
1690: }
1691: }
1692: field->allocateStorage();
1693: Obj<atlas_type> newAtlas = new atlas_type(this->comm(), this->debug());
1694: const chart_type& newChart = field->getChart();
1696: for(typename chart_type::iterator c_iter = newChart.begin(); c_iter != newChart.end(); ++c_iter) {
1697: const int cDim = field->getConstraintDimension(*c_iter);
1698: const int dof[1] = {0};
1700: if (cDim) {
1701: field->setConstraintDof(*c_iter, dof);
1702: }
1703: }
1704: // Copy offsets
1705: for(typename chart_type::iterator c_iter = newChart.begin(); c_iter != newChart.end(); ++c_iter) {
1706: index_type idx;
1708: idx.prefix = field->getFiberDimension(*c_iter);
1709: idx.index = this->_atlas->restrictPoint(*c_iter)[0].index;
1710: for(int s = 0; s < space; ++s) {
1711: idx.index += this->getFiberDimension(*c_iter, s);
1712: }
1713: newAtlas->addPoint(*c_iter);
1714: newAtlas->updatePoint(*c_iter, &idx);
1715: }
1716: field->replaceStorage(this->_array, true, this->getStorageSize());
1717: field->setAtlas(newAtlas);
1718: return field;
1719: };
1720: public: // Optimization
1721: void getCustomRestrictAtlas(const int tag, const int *offsets[], const int *indices[]) {
1722: *offsets = this->_customRestrictAtlas[tag].first.first;
1723: *indices = this->_customRestrictAtlas[tag].first.second;
1724: };
1725: void getCustomUpdateAtlas(const int tag, const int *offsets[], const int *indices[]) {
1726: *offsets = this->_customUpdateAtlas[tag].first.first;
1727: *indices = this->_customUpdateAtlas[tag].first.second;
1728: };
1729: // This returns the tag assigned to the atlas
1730: int setCustomAtlas(const int restrictOffsets[], const int restrictIndices[], const int updateOffsets[], const int updateIndices[], bool autoFree = true) {
1731: this->_customRestrictAtlas.push_back(customAtlas_type(customAtlasInd_type(restrictOffsets, restrictIndices), autoFree));
1732: this->_customUpdateAtlas.push_back(customAtlas_type(customAtlasInd_type(updateOffsets, updateIndices), autoFree));
1733: return this->_customUpdateAtlas.size()-1;
1734: };
1735: int copyCustomAtlas(const Obj<GeneralSection>& section, const int tag) {
1736: const int *rOffsets, *rIndices, *uOffsets, *uIndices;
1738: section->getCustomRestrictAtlas(tag, &rOffsets, &rIndices);
1739: section->getCustomUpdateAtlas(tag, &uOffsets, &uIndices);
1740: return this->setCustomAtlas(rOffsets, rIndices, uOffsets, uIndices, false);
1741: };
1742: public:
1743: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
1744: ostringstream txt;
1745: int rank;
1747: if (comm == MPI_COMM_NULL) {
1748: comm = this->comm();
1749: rank = this->commRank();
1750: } else {
1751: MPI_Comm_rank(comm, &rank);
1752: }
1753: if (name == "") {
1754: if(rank == 0) {
1755: txt << "viewing a GeneralSection" << std::endl;
1756: }
1757: } else {
1758: if (rank == 0) {
1759: txt << "viewing GeneralSection '" << name << "'" << std::endl;
1760: }
1761: }
1762: if (rank == 0) {
1763: txt << " Fields: " << this->getNumSpaces() << std::endl;
1764: }
1765: const chart_type& chart = this->getChart();
1767: for(typename chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
1768: const value_type *array = this->restrictPoint(*p_iter);
1769: const int& dim = this->getFiberDimension(*p_iter);
1771: if (dim != 0) {
1772: txt << "[" << this->commRank() << "]: " << *p_iter << " dim " << dim << " offset " << this->_atlas->restrictPoint(*p_iter)->index << " ";
1773: for(int i = 0; i < dim; i++) {
1774: txt << " " << array[i];
1775: }
1776: const int& dim = this->getConstraintDimension(*p_iter);
1778: if (dim) {
1779: const typename bc_type::value_type *bcArray = this->_bc->restrictPoint(*p_iter);
1781: txt << " constrained";
1782: for(int i = 0; i < dim; ++i) {
1783: txt << " " << bcArray[i];
1784: }
1785: }
1786: txt << std::endl;
1787: }
1788: }
1789: if (chart.size() == 0) {
1790: txt << "[" << this->commRank() << "]: empty" << std::endl;
1791: }
1792: PetscSynchronizedPrintf(comm, txt.str().c_str());
1793: PetscSynchronizedFlush(comm);
1794: };
1795: };
1796: // A Field combines several sections
1797: template<typename Overlap_, typename Patch_, typename Section_>
1798: class Field : public ALE::ParallelObject {
1799: public:
1800: typedef Overlap_ overlap_type;
1801: typedef Patch_ patch_type;
1802: typedef Section_ section_type;
1803: typedef typename section_type::point_type point_type;
1804: typedef typename section_type::chart_type chart_type;
1805: typedef typename section_type::value_type value_type;
1806: typedef std::map<patch_type, Obj<section_type> > sheaf_type;
1807: typedef enum {SEND, RECEIVE} request_type;
1808: typedef std::map<patch_type, MPI_Request> requests_type;
1809: protected:
1810: sheaf_type _sheaf;
1811: int _tag;
1812: MPI_Datatype _datatype;
1813: requests_type _requests;
1814: public:
1815: Field(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {
1816: this->_tag = this->getNewTag();
1817: this->_datatype = this->getMPIDatatype();
1818: };
1819: Field(MPI_Comm comm, const int tag, const int debug) : ParallelObject(comm, debug), _tag(tag) {
1820: this->_datatype = this->getMPIDatatype();
1821: };
1822: virtual ~Field() {};
1823: protected:
1824: MPI_Datatype getMPIDatatype() {
1825: if (sizeof(value_type) == 4) {
1826: return MPI_INT;
1827: } else if (sizeof(value_type) == 8) {
1828: return MPI_DOUBLE;
1829: } else if (sizeof(value_type) == 28) {
1830: int blen[2];
1831: MPI_Aint indices[2];
1832: MPI_Datatype oldtypes[2], newtype;
1833: blen[0] = 1; indices[0] = 0; oldtypes[0] = MPI_INT;
1834: blen[1] = 3; indices[1] = sizeof(int); oldtypes[1] = MPI_DOUBLE;
1835: MPI_Type_struct(2, blen, indices, oldtypes, &newtype);
1836: MPI_Type_commit(&newtype);
1837: return newtype;
1838: } else if (sizeof(value_type) == 32) {
1839: int blen[2];
1840: MPI_Aint indices[2];
1841: MPI_Datatype oldtypes[2], newtype;
1842: blen[0] = 1; indices[0] = 0; oldtypes[0] = MPI_DOUBLE;
1843: blen[1] = 3; indices[1] = sizeof(int); oldtypes[1] = MPI_DOUBLE;
1844: MPI_Type_struct(2, blen, indices, oldtypes, &newtype);
1845: MPI_Type_commit(&newtype);
1846: return newtype;
1847: }
1848: throw ALE::Exception("Cannot determine MPI type for value type");
1849: };
1850: int getNewTag() {
1851: static int tagKeyval = MPI_KEYVAL_INVALID;
1852: int *tagvalp = NULL, *maxval, flg;
1854: if (tagKeyval == MPI_KEYVAL_INVALID) {
1855: tagvalp = (int *) malloc(sizeof(int));
1856: MPI_Keyval_create(MPI_NULL_COPY_FN, Mesh_DelTag, &tagKeyval, (void *) NULL);
1857: MPI_Attr_put(this->_comm, tagKeyval, tagvalp);
1858: tagvalp[0] = 0;
1859: }
1860: MPI_Attr_get(this->_comm, tagKeyval, (void **) &tagvalp, &flg);
1861: if (tagvalp[0] < 1) {
1862: MPI_Attr_get(MPI_COMM_WORLD, MPI_TAG_UB, (void **) &maxval, &flg);
1863: tagvalp[0] = *maxval - 128; // hope that any still active tags were issued right at the beginning of the run
1864: }
1865: if (this->debug()) {
1866: std::cout << "[" << this->commRank() << "]Got new tag " << tagvalp[0] << std::endl;
1867: }
1868: return tagvalp[0]--;
1869: };
1870: public: // Verifiers
1871: void checkPatch(const patch_type& patch) const {
1872: if (this->_sheaf.find(patch) == this->_sheaf.end()) {
1873: ostringstream msg;
1874: msg << "Invalid field patch " << patch << std::endl;
1875: throw ALE::Exception(msg.str().c_str());
1876: }
1877: };
1878: bool hasPatch(const patch_type& patch) {
1879: if (this->_sheaf.find(patch) == this->_sheaf.end()) {
1880: return false;
1881: }
1882: return true;
1883: };
1884: public: // Accessors
1885: int getTag() const {return this->_tag;};
1886: void setTag(const int tag) {this->_tag = tag;};
1887: Obj<section_type>& getSection(const patch_type& patch) {
1888: if (this->_sheaf.find(patch) == this->_sheaf.end()) {
1889: this->_sheaf[patch] = new section_type(this->comm(), this->debug());
1890: }
1891: return this->_sheaf[patch];
1892: };
1893: void setSection(const patch_type& patch, const Obj<section_type>& section) {this->_sheaf[patch] = section;};
1894: const sheaf_type& getPatches() {
1895: return this->_sheaf;
1896: };
1897: void clear() {
1898: for(typename sheaf_type::const_iterator p_iter = this->_sheaf.begin(); p_iter != this->_sheaf.end(); ++p_iter) {
1899: p_iter->second->clear();
1900: }
1901: };
1902: public: // Adapter
1903: template<typename Topology_>
1904: void setTopology(const Obj<Topology_>& topology) {
1905: const typename Topology_::sheaf_type& patches = topology->getPatches();
1907: for(typename Topology_::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
1908: int rank = p_iter->first;
1909: const Obj<section_type>& section = this->getSection(rank);
1910: const Obj<typename Topology_::sieve_type::baseSequence>& base = p_iter->second->base();
1912: for(typename Topology_::sieve_type::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
1913: section->setFiberDimension(*b_iter, 1);
1914: }
1915: }
1916: };
1917: void allocate() {
1918: for(typename sheaf_type::const_iterator p_iter = this->_sheaf.begin(); p_iter != this->_sheaf.end(); ++p_iter) {
1919: p_iter->second->allocatePoint();
1920: }
1921: };
1922: public: // Communication
1923: void construct(const int size) {
1924: const sheaf_type& patches = this->getPatches();
1926: for(typename sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
1927: const patch_type rank = p_iter->first;
1928: const Obj<section_type>& section = this->getSection(rank);
1929: const chart_type& chart = section->getChart();
1931: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1932: section->setFiberDimension(*c_iter, size);
1933: }
1934: }
1935: };
1936: template<typename Sizer>
1937: void construct(const Obj<Sizer>& sizer) {
1938: const sheaf_type& patches = this->getPatches();
1940: for(typename sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
1941: const patch_type rank = p_iter->first;
1942: const Obj<section_type>& section = this->getSection(rank);
1943: const chart_type& chart = section->getChart();
1944:
1945: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
1946: section->setFiberDimension(*c_iter, *(sizer->getSection(rank)->restrictPoint(*c_iter)));
1947: }
1948: }
1949: };
1950: void constructCommunication(const request_type& requestType) {
1951: const sheaf_type& patches = this->getPatches();
1953: for(typename sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
1954: const patch_type patch = p_iter->first;
1955: const Obj<section_type>& section = this->getSection(patch);
1956: MPI_Request request;
1958: if (requestType == RECEIVE) {
1959: if (this->_debug) {std::cout <<"["<<this->commRank()<<"] Receiving data(" << section->size() << ") from " << patch << " tag " << this->_tag << std::endl;}
1960: MPI_Recv_init((void *) section->restrict(), section->size(), this->_datatype, patch, this->_tag, this->comm(), &request);
1961: } else {
1962: if (this->_debug) {std::cout <<"["<<this->commRank()<<"] Sending data (" << section->size() << ") to " << patch << " tag " << this->_tag << std::endl;}
1963: MPI_Send_init((void *) section->restrict(), section->size(), this->_datatype, patch, this->_tag, this->comm(), &request);
1964: }
1965: this->_requests[patch] = request;
1966: }
1967: };
1968: void startCommunication() {
1969: const sheaf_type& patches = this->getPatches();
1971: for(typename sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
1972: MPI_Request request = this->_requests[p_iter->first];
1974: MPI_Start(&request);
1975: }
1976: };
1977: void endCommunication() {
1978: const sheaf_type& patches = this->getPatches();
1979: MPI_Status status;
1981: for(typename sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
1982: MPI_Request request = this->_requests[p_iter->first];
1984: MPI_Wait(&request, &status);
1985: }
1986: };
1987: public:
1988: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
1989: ostringstream txt;
1990: int rank;
1992: if (comm == MPI_COMM_NULL) {
1993: comm = this->comm();
1994: rank = this->commRank();
1995: } else {
1996: MPI_Comm_rank(comm, &rank);
1997: }
1998: if (name == "") {
1999: if(rank == 0) {
2000: txt << "viewing a Field" << std::endl;
2001: }
2002: } else {
2003: if(rank == 0) {
2004: txt << "viewing Field '" << name << "'" << std::endl;
2005: }
2006: }
2007: PetscSynchronizedPrintf(comm, txt.str().c_str());
2008: PetscSynchronizedFlush(comm);
2009: for(typename sheaf_type::const_iterator p_iter = this->_sheaf.begin(); p_iter != this->_sheaf.end(); ++p_iter) {
2010: ostringstream txt1;
2012: txt1 << "[" << this->commRank() << "]: Patch " << p_iter->first << std::endl;
2013: PetscSynchronizedPrintf(comm, txt1.str().c_str());
2014: PetscSynchronizedFlush(comm);
2015: p_iter->second->view("field section", comm);
2016: }
2017: };
2018: };
2019: }
2021: namespace ALECompat {
2022: namespace New {
2023: using ALE::Obj;
2024: // A ConstantSection is the simplest Section
2025: // All fibers are dimension 1
2026: // All values are equal to a constant
2027: // We need no value storage and no communication for completion
2028: template<typename Topology_, typename Value_>
2029: class NewConstantSection : public ALE::ParallelObject {
2030: public:
2031: typedef Topology_ topology_type;
2032: typedef typename topology_type::patch_type patch_type;
2033: typedef typename topology_type::sieve_type sieve_type;
2034: typedef typename topology_type::point_type point_type;
2035: typedef std::set<point_type> chart_type;
2036: typedef std::map<patch_type, chart_type> atlas_type;
2037: typedef Value_ value_type;
2038: protected:
2039: Obj<topology_type> _topology;
2040: atlas_type _atlas;
2041: chart_type _emptyChart;
2042: value_type _value;
2043: value_type _defaultValue;
2044: public:
2045: NewConstantSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug), _defaultValue(0) {
2046: this->_topology = new topology_type(comm, debug);
2047: };
2048: NewConstantSection(const Obj<topology_type>& topology) : ParallelObject(topology->comm(), topology->debug()), _topology(topology) {};
2049: NewConstantSection(const Obj<topology_type>& topology, const value_type& value) : ParallelObject(topology->comm(), topology->debug()), _topology(topology), _value(value), _defaultValue(value) {};
2050: 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) {};
2051: public: // Verifiers
2052: void checkPatch(const patch_type& patch) const {
2053: this->_topology->checkPatch(patch);
2054: if (this->_atlas.find(patch) == this->_atlas.end()) {
2055: ostringstream msg;
2056: msg << "Invalid atlas patch " << patch << std::endl;
2057: throw ALE::Exception(msg.str().c_str());
2058: }
2059: };
2060: void checkPoint(const patch_type& patch, const point_type& point) const {
2061: this->checkPatch(patch);
2062: if (this->_atlas.find(patch)->second.find(point) == this->_atlas.find(patch)->second.end()) {
2063: ostringstream msg;
2064: msg << "Invalid section point " << point << std::endl;
2065: throw ALE::Exception(msg.str().c_str());
2066: }
2067: };
2068: void checkDimension(const int& dim) {
2069: if (dim != 1) {
2070: ostringstream msg;
2071: msg << "Invalid fiber dimension " << dim << " must be 1" << std::endl;
2072: throw ALE::Exception(msg.str().c_str());
2073: }
2074: };
2075: bool hasPatch(const patch_type& patch) {
2076: if (this->_atlas.find(patch) == this->_atlas.end()) {
2077: return false;
2078: }
2079: return true;
2080: };
2081: bool hasPoint(const patch_type& patch, const point_type& point) const {
2082: this->checkPatch(patch);
2083: return this->_atlas.find(patch)->second.count(point) > 0;
2084: };
2085: bool hasPoint(const point_type& point) const {
2086: this->checkPatch(0);
2087: return this->_atlas.find(0)->second.count(point) > 0;
2088: };
2089: public: // Accessors
2090: const Obj<topology_type>& getTopology() const {return this->_topology;};
2091: void setTopology(const Obj<topology_type>& topology) {this->_topology = topology;};
2092: const chart_type& getPatch(const patch_type& patch) {
2093: if (this->hasPatch(patch)) {
2094: return this->_atlas[patch];
2095: }
2096: return this->_emptyChart;
2097: };
2098: void updatePatch(const patch_type& patch, const point_type& point) {
2099: this->_atlas[patch].insert(point);
2100: };
2101: template<typename Points>
2102: void updatePatch(const patch_type& patch, const Obj<Points>& points) {
2103: this->_atlas[patch].insert(points->begin(), points->end());
2104: };
2105: value_type getDefaultValue() {return this->_defaultValue;};
2106: void setDefaultValue(const value_type value) {this->_defaultValue = value;};
2107: public: // Sizes
2108: void clear() {
2109: this->_atlas.clear();
2110: };
2111: int getFiberDimension(const patch_type& patch, const point_type& p) const {
2112: if (this->hasPoint(patch, p)) return 1;
2113: return 0;
2114: };
2115: void setFiberDimension(const patch_type& patch, const point_type& p, int dim) {
2116: this->checkDimension(dim);
2117: this->updatePatch(patch, p);
2118: };
2119: template<typename Sequence>
2120: void setFiberDimension(const patch_type& patch, const Obj<Sequence>& points, int dim) {
2121: for(typename topology_type::label_sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
2122: this->setFiberDimension(patch, *p_iter, dim);
2123: }
2124: };
2125: void addFiberDimension(const patch_type& patch, const point_type& p, int dim) {
2126: if (this->hasPatch(patch) && (this->_atlas[patch].find(p) != this->_atlas[patch].end())) {
2127: ostringstream msg;
2128: msg << "Invalid addition to fiber dimension " << dim << " cannot exceed 1" << std::endl;
2129: throw ALE::Exception(msg.str().c_str());
2130: } else {
2131: this->setFiberDimension(patch, p, dim);
2132: }
2133: };
2134: void setFiberDimensionByDepth(const patch_type& patch, int depth, int dim) {
2135: this->setFiberDimension(patch, this->_topology->getLabelStratum(patch, "depth", depth), dim);
2136: };
2137: void setFiberDimensionByHeight(const patch_type& patch, int height, int dim) {
2138: this->setFiberDimension(patch, this->_topology->getLabelStratum(patch, "height", height), dim);
2139: };
2140: int size(const patch_type& patch) {return this->_atlas[patch].size();};
2141: int size(const patch_type& patch, const point_type& p) {return this->getFiberDimension(patch, p);};
2142: public: // Restriction
2143: const value_type *restrict(const patch_type& patch, const point_type& p) const {
2144: //std::cout <<"["<<this->commRank()<<"]: Constant restrict ("<<patch<<","<<p<<") from " << std::endl;
2145: //for(typename chart_type::iterator c_iter = this->_atlas.find(patch)->second.begin(); c_iter != this->_atlas.find(patch)->second.end(); ++c_iter) {
2146: // std::cout <<"["<<this->commRank()<<"]: point " << *c_iter << std::endl;
2147: //}
2148: if (this->hasPoint(patch, p)) {
2149: return &this->_value;
2150: }
2151: return &this->_defaultValue;
2152: };
2153: const value_type *restrictPoint(const patch_type& patch, const point_type& p) const {return this->restrict(patch, p);};
2154: const value_type *restrictPoint(const point_type& p) const {return this->restrict(0, p);};
2155: void update(const patch_type& patch, const point_type& p, const value_type v[]) {
2156: this->checkPatch(patch);
2157: this->_value = v[0];
2158: };
2159: void updatePoint(const patch_type& patch, const point_type& p, const value_type v[]) {return this->update(patch, p, v);};
2160: void updateAdd(const patch_type& patch, const point_type& p, const value_type v[]) {
2161: this->checkPatch(patch);
2162: this->_value += v[0];
2163: };
2164: void updateAddPoint(const patch_type& patch, const point_type& p, const value_type v[]) {return this->updateAdd(patch, p, v);};
2165: public:
2166: void copy(const Obj<NewConstantSection>& section) {
2167: const typename topology_type::sheaf_type& patches = this->_topology->getPatches();
2169: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2170: const patch_type& patch = p_iter->first;
2171: if (!section->hasPatch(patch)) continue;
2172: const chart_type& chart = section->getPatch(patch);
2174: for(typename chart_type::iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
2175: this->updatePatch(patch, *c_iter);
2176: }
2177: this->_value = section->restrict(patch, *chart.begin())[0];
2178: }
2179: };
2180: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
2181: ostringstream txt;
2182: int rank;
2184: if (comm == MPI_COMM_NULL) {
2185: comm = this->comm();
2186: rank = this->commRank();
2187: } else {
2188: MPI_Comm_rank(comm, &rank);
2189: }
2190: if (name == "") {
2191: if(rank == 0) {
2192: txt << "viewing a NewConstantSection" << std::endl;
2193: }
2194: } else {
2195: if(rank == 0) {
2196: txt << "viewing NewConstantSection '" << name << "'" << std::endl;
2197: }
2198: }
2199: const typename topology_type::sheaf_type& sheaf = this->_topology->getPatches();
2201: for(typename topology_type::sheaf_type::const_iterator p_iter = sheaf.begin(); p_iter != sheaf.end(); ++p_iter) {
2202: txt <<"["<<this->commRank()<<"]: Patch " << p_iter->first << std::endl;
2203: txt <<"["<<this->commRank()<<"]: Value " << this->_value << std::endl;
2204: }
2205: PetscSynchronizedPrintf(comm, txt.str().c_str());
2206: PetscSynchronizedFlush(comm);
2207: };
2208: };
2210: // A UniformSection often acts as an Atlas
2211: // All fibers are the same dimension
2212: // Note we can use a ConstantSection for this Atlas
2213: // Each point may have a different vector
2214: // Thus we need storage for values, and hence must implement completion
2215: template<typename Topology_, typename Value_, int fiberDim = 1>
2216: class UniformSection : public ALE::ParallelObject {
2217: public:
2218: typedef Topology_ topology_type;
2219: typedef typename topology_type::patch_type patch_type;
2220: typedef typename topology_type::sieve_type sieve_type;
2221: typedef typename topology_type::point_type point_type;
2222: typedef NewConstantSection<topology_type, int> atlas_type;
2223: typedef typename atlas_type::chart_type chart_type;
2224: typedef Value_ value_type;
2225: typedef struct {value_type v[fiberDim];} fiber_type;
2226: typedef std::map<point_type, fiber_type> array_type;
2227: typedef std::map<patch_type, array_type> values_type;
2228: protected:
2229: Obj<atlas_type> _atlas;
2230: values_type _arrays;
2231: public:
2232: UniformSection(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {
2233: this->_atlas = new atlas_type(comm, debug);
2234: };
2235: UniformSection(const Obj<topology_type>& topology) : ParallelObject(topology->comm(), topology->debug()) {
2236: this->_atlas = new atlas_type(topology, fiberDim, 0);
2237: };
2238: UniformSection(const Obj<atlas_type>& atlas) : ParallelObject(atlas->comm(), atlas->debug()), _atlas(atlas) {};
2239: protected:
2240: value_type *getRawArray(const int size) {
2241: static value_type *array = NULL;
2242: static int maxSize = 0;
2244: if (size > maxSize) {
2245: maxSize = size;
2246: if (array) delete [] array;
2247: array = new value_type[maxSize];
2248: };
2249: return array;
2250: };
2251: public: // Verifiers
2252: void checkPatch(const patch_type& patch) {
2253: this->_atlas->checkPatch(patch);
2254: if (this->_arrays.find(patch) == this->_arrays.end()) {
2255: ostringstream msg;
2256: msg << "Invalid section patch: " << patch << std::endl;
2257: throw ALE::Exception(msg.str().c_str());
2258: }
2259: };
2260: bool hasPatch(const patch_type& patch) {
2261: return this->_atlas->hasPatch(patch);
2262: };
2263: bool hasPoint(const patch_type& patch, const point_type& point) {
2264: return this->_atlas->hasPoint(patch, point);
2265: };
2266: bool hasPoint(const point_type& point) {
2267: return this->_atlas->hasPoint(0, point);
2268: };
2269: void checkDimension(const int& dim) {
2270: if (dim != fiberDim) {
2271: ostringstream msg;
2272: msg << "Invalid fiber dimension " << dim << " must be " << fiberDim << std::endl;
2273: throw ALE::Exception(msg.str().c_str());
2274: }
2275: };
2276: public: // Accessors
2277: const Obj<atlas_type>& getAtlas() {return this->_atlas;};
2278: void setAtlas(const Obj<atlas_type>& atlas) {this->_atlas = atlas;};
2279: const Obj<topology_type>& getTopology() {return this->_atlas->getTopology();};
2280: void setTopology(const Obj<topology_type>& topology) {this->_atlas->setTopology(topology);};
2281: const chart_type& getPatch(const patch_type& patch) {
2282: return this->_atlas->getPatch(patch);
2283: };
2284: void updatePatch(const patch_type& patch, const point_type& point) {
2285: this->setFiberDimension(patch, point, 1);
2286: };
2287: template<typename Points>
2288: void updatePatch(const patch_type& patch, const Obj<Points>& points) {
2289: for(typename Points::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
2290: this->setFiberDimension(patch, *p_iter, 1);
2291: }
2292: };
2293: void copy(const Obj<UniformSection<Topology_, Value_, fiberDim> >& section) {
2294: this->getAtlas()->copy(section->getAtlas());
2295: const typename topology_type::sheaf_type& sheaf = section->getTopology()->getPatches();
2297: for(typename topology_type::sheaf_type::const_iterator s_iter = sheaf.begin(); s_iter != sheaf.end(); ++s_iter) {
2298: const patch_type& patch = s_iter->first;
2299: if (!section->hasPatch(patch)) continue;
2300: const chart_type& chart = section->getPatch(patch);
2302: for(typename chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
2303: this->updatePoint(s_iter->first, *c_iter, section->restrictPoint(s_iter->first, *c_iter));
2304: }
2305: }
2306: };
2307: public: // Sizes
2308: void clear() {
2309: this->_atlas->clear();
2310: this->_arrays.clear();
2311: };
2312: int getFiberDimension(const patch_type& patch, const point_type& p) const {
2313: // Could check for non-existence here
2314: return this->_atlas->restrictPoint(patch, p)[0];
2315: };
2316: void setFiberDimension(const patch_type& patch, const point_type& p, int dim) {
2317: this->checkDimension(dim);
2318: this->_atlas->updatePatch(patch, p);
2319: this->_atlas->updatePoint(patch, p, &dim);
2320: };
2321: template<typename Sequence>
2322: void setFiberDimension(const patch_type& patch, const Obj<Sequence>& points, int dim) {
2323: for(typename Sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
2324: this->setFiberDimension(patch, *p_iter, dim);
2325: }
2326: };
2327: void setFiberDimension(const patch_type& patch, const std::set<point_type>& points, int dim) {
2328: for(typename std::set<point_type>::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
2329: this->setFiberDimension(patch, *p_iter, dim);
2330: }
2331: };
2332: void addFiberDimension(const patch_type& patch, const point_type& p, int dim) {
2333: if (this->hasPatch(patch) && (this->_atlas[patch].find(p) != this->_atlas[patch].end())) {
2334: ostringstream msg;
2335: msg << "Invalid addition to fiber dimension " << dim << " cannot exceed " << fiberDim << std::endl;
2336: throw ALE::Exception(msg.str().c_str());
2337: } else {
2338: this->setFiberDimension(patch, p, dim);
2339: }
2340: };
2341: void setFiberDimensionByDepth(const patch_type& patch, int depth, int dim) {
2342: this->setFiberDimension(patch, this->getTopology()->getLabelStratum(patch, "depth", depth), dim);
2343: };
2344: void setFiberDimensionByHeight(const patch_type& patch, int height, int dim) {
2345: this->setFiberDimension(patch, this->getTopology()->getLabelStratum(patch, "height", height), dim);
2346: };
2347: int size(const patch_type& patch) {
2348: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
2349: int size = 0;
2351: for(typename atlas_type::chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
2352: size += this->getFiberDimension(patch, *p_iter);
2353: }
2354: return size;
2355: };
2356: int size(const patch_type& patch, const point_type& p) {
2357: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
2358: const Obj<typename sieve_type::coneSet> closure = this->getTopology()->getPatch(patch)->closure(p);
2359: typename sieve_type::coneSet::iterator end = closure->end();
2360: int size = 0;
2362: for(typename sieve_type::coneSet::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
2363: if (points.count(*c_iter)) {
2364: size += this->getFiberDimension(patch, *c_iter);
2365: }
2366: }
2367: return size;
2368: };
2369: void orderPatches() {};
2370: public: // Restriction
2371: // Return a pointer to the entire contiguous storage array
2372: const array_type& restrict(const patch_type& patch) {
2373: this->checkPatch(patch);
2374: return this->_arrays[patch];
2375: };
2376: // Return the values for the closure of this point
2377: // use a smart pointer?
2378: const value_type *restrict(const patch_type& patch, const point_type& p) {
2379: this->checkPatch(patch);
2380: const chart_type& chart = this->getPatch(patch);
2381: array_type& array = this->_arrays[patch];
2382: const int size = this->size(patch, p);
2383: value_type *values = this->getRawArray(size);
2384: int j = -1;
2386: // We could actually ask for the height of the individual point
2387: if (this->getTopology()->height(patch) < 2) {
2388: // Avoids only the copy of closure()
2389: const int& dim = this->_atlas->restrictPoint(patch, p)[0];
2391: if (chart.count(p)) {
2392: for(int i = 0; i < dim; ++i) {
2393: values[++j] = array[p].v[i];
2394: }
2395: }
2396: // Need only the cone
2397: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
2398: typename sieve_type::coneSequence::iterator end = cone->end();
2400: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
2401: if (chart.count(*p_iter)) {
2402: const int& dim = this->_atlas->restrictPoint(patch, *p_iter)[0];
2404: for(int i = 0; i < dim; ++i) {
2405: values[++j] = array[*p_iter].v[i];
2406: }
2407: }
2408: }
2409: } else {
2410: // Right now, we have no way of consistently ordering the closure()
2411: const Obj<typename sieve_type::coneSet>& closure = this->getTopology()->getPatch(patch)->closure(p);
2412: typename sieve_type::coneSet::iterator end = closure->end();
2414: for(typename sieve_type::coneSet::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
2415: if (chart.count(*p_iter)) {
2416: const int& dim = this->_atlas->restrictPoint(patch, *p_iter)[0];
2418: for(int i = 0; i < dim; ++i) {
2419: values[++j] = array[*p_iter].v[i];
2420: }
2421: }
2422: }
2423: }
2424: if (j != size-1) {
2425: ostringstream txt;
2427: txt << "Invalid restrict to point " << p << std::endl;
2428: txt << " j " << j << " should be " << (size-1) << std::endl;
2429: std::cout << txt.str();
2430: throw ALE::Exception(txt.str().c_str());
2431: }
2432: return values;
2433: };
2434: void update(const patch_type& patch, const point_type& p, const value_type v[]) {
2435: this->_atlas->checkPatch(patch);
2436: const chart_type& chart = this->getPatch(patch);
2437: array_type& array = this->_arrays[patch];
2438: int j = -1;
2440: if (this->getTopology()->height(patch) < 2) {
2441: // Only avoids the copy of closure()
2442: const int& dim = this->_atlas->restrict(patch, p)[0];
2444: if (chart.count(p)) {
2445: for(int i = 0; i < dim; ++i) {
2446: array[p].v[i] = v[++j];
2447: }
2448: }
2449: // Should be closure()
2450: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
2452: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
2453: if (chart.count(*p_iter)) {
2454: const int& dim = this->_atlas->restrict(patch, *p_iter)[0];
2456: for(int i = 0; i < dim; ++i) {
2457: array[*p_iter].v[i] = v[++j];
2458: }
2459: }
2460: }
2461: } else {
2462: throw ALE::Exception("Update is not yet implemented for interpolated sieves");
2463: }
2464: };
2465: void updateAdd(const patch_type& patch, const point_type& p, const value_type v[]) {
2466: this->_atlas->checkPatch(patch);
2467: const chart_type& chart = this->getPatch(patch);
2468: array_type& array = this->_arrays[patch];
2469: int j = -1;
2471: if (this->getTopology()->height(patch) < 2) {
2472: // Only avoids the copy of closure()
2473: const int& dim = this->_atlas->restrict(patch, p)[0];
2475: if (chart.count(p)) {
2476: for(int i = 0; i < dim; ++i) {
2477: array[p].v[i] += v[++j];
2478: }
2479: }
2480: // Should be closure()
2481: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
2483: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
2484: if (chart.count(*p_iter)) {
2485: const int& dim = this->_atlas->restrict(patch, *p_iter)[0];
2487: for(int i = 0; i < dim; ++i) {
2488: array[*p_iter].v[i] += v[++j];
2489: }
2490: }
2491: }
2492: } else {
2493: throw ALE::Exception("Not yet implemented for interpolated sieves");
2494: }
2495: };
2496: // Return only the values associated to this point, not its closure
2497: const value_type *restrictPoint(const patch_type& patch, const point_type& p) {
2498: this->checkPatch(patch);
2499: return this->_arrays[patch][p].v;
2500: };
2501: const value_type *restrictPoint(const point_type& p) {
2502: this->checkPatch(0);
2503: return this->_arrays[0][p].v;
2504: };
2505: // Update only the values associated to this point, not its closure
2506: void updatePoint(const patch_type& patch, const point_type& p, const value_type v[]) {
2507: this->_atlas->checkPatch(patch);
2508: for(int i = 0; i < fiberDim; ++i) {
2509: this->_arrays[patch][p].v[i] = v[i];
2510: }
2511: };
2512: // Update only the values associated to this point, not its closure
2513: void updateAddPoint(const patch_type& patch, const point_type& p, const value_type v[]) {
2514: this->_atlas->checkPatch(patch);
2515: for(int i = 0; i < fiberDim; ++i) {
2516: this->_arrays[patch][p].v[i] += v[i];
2517: }
2518: };
2519: public:
2520: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
2521: ostringstream txt;
2522: int rank;
2524: if (comm == MPI_COMM_NULL) {
2525: comm = this->comm();
2526: rank = this->commRank();
2527: } else {
2528: MPI_Comm_rank(comm, &rank);
2529: }
2530: if (name == "") {
2531: if(rank == 0) {
2532: txt << "viewing a UniformSection" << std::endl;
2533: }
2534: } else {
2535: if(rank == 0) {
2536: txt << "viewing UniformSection '" << name << "'" << std::endl;
2537: }
2538: }
2539: for(typename values_type::const_iterator a_iter = this->_arrays.begin(); a_iter != this->_arrays.end(); ++a_iter) {
2540: const patch_type& patch = a_iter->first;
2541: array_type& array = this->_arrays[patch];
2543: txt << "[" << this->commRank() << "]: Patch " << patch << std::endl;
2544: const typename atlas_type::chart_type& chart = this->_atlas->getPatch(patch);
2546: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
2547: const point_type& point = *p_iter;
2548: const typename atlas_type::value_type dim = this->_atlas->restrict(patch, point)[0];
2550: if (dim != 0) {
2551: txt << "[" << this->commRank() << "]: " << point << " dim " << dim << " ";
2552: for(int i = 0; i < dim; i++) {
2553: txt << " " << array[point].v[i];
2554: }
2555: txt << std::endl;
2556: }
2557: }
2558: }
2559: PetscSynchronizedPrintf(comm, txt.str().c_str());
2560: PetscSynchronizedFlush(comm);
2561: };
2562: };
2564: // A Section is our most general construct (more general ones could be envisioned)
2565: // The Atlas is a UniformSection of dimension 1 and value type Point
2566: // to hold each fiber dimension and offsets into a contiguous patch array
2567: template<typename Topology_, typename Value_>
2568: class Section : public ALE::ParallelObject {
2569: public:
2570: typedef Topology_ topology_type;
2571: typedef typename topology_type::patch_type patch_type;
2572: typedef typename topology_type::sieve_type sieve_type;
2573: typedef typename topology_type::point_type point_type;
2574: typedef ALE::Point index_type;
2575: typedef UniformSection<topology_type, index_type> atlas_type;
2576: typedef typename atlas_type::chart_type chart_type;
2577: typedef Value_ value_type;
2578: typedef value_type * array_type;
2579: typedef std::map<patch_type, array_type> values_type;
2580: typedef std::vector<index_type> IndexArray;
2581: protected:
2582: Obj<atlas_type> _atlas;
2583: Obj<atlas_type> _atlasNew;
2584: values_type _arrays;
2585: Obj<IndexArray> _indexArray;
2586: public:
2587: Section(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {
2588: this->_atlas = new atlas_type(comm, debug);
2589: this->_atlasNew = NULL;
2590: this->_indexArray = new IndexArray();
2591: };
2592: Section(const Obj<topology_type>& topology) : ParallelObject(topology->comm(), topology->debug()), _atlasNew(NULL) {
2593: this->_atlas = new atlas_type(topology);
2594: this->_indexArray = new IndexArray();
2595: };
2596: Section(const Obj<atlas_type>& atlas) : ParallelObject(atlas->comm(), atlas->debug()), _atlas(atlas), _atlasNew(NULL) {
2597: this->_indexArray = new IndexArray();
2598: };
2599: virtual ~Section() {
2600: for(typename values_type::iterator a_iter = this->_arrays.begin(); a_iter != this->_arrays.end(); ++a_iter) {
2601: delete [] a_iter->second;
2602: a_iter->second = NULL;
2603: }
2604: };
2605: protected:
2606: value_type *getRawArray(const int size) {
2607: static value_type *array = NULL;
2608: static int maxSize = 0;
2610: if (size > maxSize) {
2611: maxSize = size;
2612: if (array) delete [] array;
2613: array = new value_type[maxSize];
2614: };
2615: return array;
2616: };
2617: public: // Verifiers
2618: void checkPatch(const patch_type& patch) {
2619: this->_atlas->checkPatch(patch);
2620: if (this->_arrays.find(patch) == this->_arrays.end()) {
2621: ostringstream msg;
2622: msg << "Invalid section patch: " << patch << std::endl;
2623: throw ALE::Exception(msg.str().c_str());
2624: }
2625: };
2626: bool hasPatch(const patch_type& patch) {
2627: return this->_atlas->hasPatch(patch);
2628: };
2629: public: // Accessors
2630: const Obj<atlas_type>& getAtlas() {return this->_atlas;};
2631: void setAtlas(const Obj<atlas_type>& atlas) {this->_atlas = atlas;};
2632: const Obj<topology_type>& getTopology() {return this->_atlas->getTopology();};
2633: void setTopology(const Obj<topology_type>& topology) {this->_atlas->setTopology(topology);};
2634: const chart_type& getPatch(const patch_type& patch) {
2635: return this->_atlas->getPatch(patch);
2636: };
2637: bool hasPoint(const patch_type& patch, const point_type& point) {
2638: return this->_atlas->hasPoint(patch, point);
2639: };
2640: public: // Sizes
2641: void clear() {
2642: this->_atlas->clear();
2643: this->_arrays.clear();
2644: };
2645: int getFiberDimension(const patch_type& patch, const point_type& p) const {
2646: // Could check for non-existence here
2647: return this->_atlas->restrictPoint(patch, p)->prefix;
2648: };
2649: int getFiberDimension(const Obj<atlas_type>& atlas, const patch_type& patch, const point_type& p) const {
2650: // Could check for non-existence here
2651: return atlas->restrictPoint(patch, p)->prefix;
2652: };
2653: void setFiberDimension(const patch_type& patch, const point_type& p, int dim) {
2654: const index_type idx(dim, -1);
2655: this->_atlas->updatePatch(patch, p);
2656: this->_atlas->updatePoint(patch, p, &idx);
2657: };
2658: template<typename Sequence>
2659: void setFiberDimension(const patch_type& patch, const Obj<Sequence>& points, int dim) {
2660: for(typename topology_type::label_sequence::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
2661: this->setFiberDimension(patch, *p_iter, dim);
2662: }
2663: };
2664: void addFiberDimension(const patch_type& patch, const point_type& p, int dim) {
2665: if (this->_atlas->hasPatch(patch) && this->_atlas->hasPoint(patch, p)) {
2666: const index_type values(dim, 0);
2667: this->_atlas->updateAddPoint(patch, p, &values);
2668: } else {
2669: this->setFiberDimension(patch, p, dim);
2670: }
2671: };
2672: void setFiberDimensionByDepth(const patch_type& patch, int depth, int dim) {
2673: this->setFiberDimension(patch, this->getTopology()->getLabelStratum(patch, "depth", depth), dim);
2674: };
2675: void setFiberDimensionByHeight(const patch_type& patch, int height, int dim) {
2676: this->setFiberDimension(patch, this->getTopology()->getLabelStratum(patch, "height", height), dim);
2677: };
2678: int size(const patch_type& patch) {
2679: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
2680: int size = 0;
2682: for(typename atlas_type::chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
2683: size += std::max(0, this->getFiberDimension(patch, *p_iter));
2684: }
2685: return size;
2686: };
2687: int sizeWithBC(const patch_type& patch) {
2688: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
2689: int size = 0;
2691: for(typename atlas_type::chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
2692: size += std::abs(this->getFiberDimension(patch, *p_iter));
2693: }
2694: return size;
2695: };
2696: int size(const patch_type& patch, const point_type& p) {
2697: if (this->getTopology()->depth() > 1) throw ALE::Exception("Compatibility layer is not for interpolated meshes");
2698: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
2699: const Obj<typename sieve_type::coneSequence> closure = this->getTopology()->getPatch(patch)->cone(p);
2700: typename sieve_type::coneSequence::iterator end = closure->end();
2701: int size = 0;
2703: size += std::max(0, this->getFiberDimension(patch, p));
2704: for(typename sieve_type::coneSequence::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
2705: if (points.count(*c_iter)) {
2706: size += std::max(0, this->getFiberDimension(patch, *c_iter));
2707: }
2708: }
2709: return size;
2710: };
2711: int sizeWithBC(const patch_type& patch, const point_type& p) {
2712: if (this->getTopology()->depth() > 1) throw ALE::Exception("Compatibility layer is not for interpolated meshes");
2713: const typename atlas_type::chart_type& points = this->_atlas->getPatch(patch);
2714: const Obj<typename sieve_type::coneSequence> closure = this->getTopology()->getPatch(patch)->cone(p);
2715: typename sieve_type::coneSequence::iterator end = closure->end();
2716: int size = 0;
2718: size += std::abs(this->getFiberDimension(patch, p));
2719: for(typename sieve_type::coneSequence::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
2720: if (points.count(*c_iter)) {
2721: size += std::abs(this->getFiberDimension(patch, *c_iter));
2722: }
2723: }
2724: return size;
2725: };
2726: int size(const Obj<atlas_type>& atlas, const patch_type& patch) {
2727: const typename atlas_type::chart_type& points = atlas->getPatch(patch);
2728: int size = 0;
2730: for(typename atlas_type::chart_type::iterator p_iter = points.begin(); p_iter != points.end(); ++p_iter) {
2731: size += std::max(0, this->getFiberDimension(atlas, patch, *p_iter));
2732: }
2733: return size;
2734: };
2735: public: // Index retrieval
2736: const index_type& getIndex(const patch_type& patch, const point_type& p) {
2737: this->checkPatch(patch);
2738: return this->_atlas->restrictPoint(patch, p)[0];
2739: };
2740: template<typename Numbering>
2741: const index_type getIndex(const patch_type& patch, const point_type& p, const Obj<Numbering>& numbering) {
2742: this->checkPatch(patch);
2743: return index_type(this->getFiberDimension(patch, p), numbering->getIndex(p));
2744: };
2745: const Obj<IndexArray>& getIndices(const patch_type& patch, const point_type& p, const int level = -1) {
2746: this->_indexArray->clear();
2748: if (level == 0) {
2749: this->_indexArray->push_back(this->getIndex(patch, p));
2750: } else if ((level == 1) || (this->getTopology()->height(patch) == 1)) {
2751: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
2752: typename sieve_type::coneSequence::iterator end = cone->end();
2754: this->_indexArray->push_back(this->getIndex(patch, p));
2755: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
2756: this->_indexArray->push_back(this->getIndex(patch, *p_iter));
2757: }
2758: } else if (level == -1) {
2759: #if 1
2760: throw ALE::Exception("Call should be moved to Bundle");
2761: #else
2762: const Obj<typename sieve_type::coneSet> closure = this->getTopology()->getPatch(patch)->closure(p);
2763: typename sieve_type::coneSet::iterator end = closure->end();
2765: for(typename sieve_type::coneSet::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
2766: this->_indexArray->push_back(this->getIndex(patch, *p_iter));
2767: }
2768: #endif
2769: } else {
2770: const Obj<typename sieve_type::coneArray> cone = this->getTopology()->getPatch(patch)->nCone(p, level);
2771: typename sieve_type::coneArray::iterator end = cone->end();
2773: for(typename sieve_type::coneArray::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
2774: this->_indexArray->push_back(this->getIndex(patch, *p_iter));
2775: }
2776: }
2777: return this->_indexArray;
2778: };
2779: template<typename Numbering>
2780: const Obj<IndexArray>& getIndices(const patch_type& patch, const point_type& p, const Obj<Numbering>& numbering, const int level = -1) {
2781: this->_indexArray->clear();
2783: if (level == 0) {
2784: this->_indexArray->push_back(this->getIndex(patch, p, numbering));
2785: } else if ((level == 1) || (this->getTopology()->height(patch) == 1)) {
2786: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
2787: typename sieve_type::coneSequence::iterator end = cone->end();
2789: this->_indexArray->push_back(this->getIndex(patch, p, numbering));
2790: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
2791: this->_indexArray->push_back(this->getIndex(patch, *p_iter, numbering));
2792: }
2793: } else if (level == -1) {
2794: #if 1
2795: throw ALE::Exception("Call should be moved to Bundle");
2796: #else
2797: const Obj<typename sieve_type::coneSet> closure = this->getTopology()->getPatch(patch)->closure(p);
2798: typename sieve_type::coneSet::iterator end = closure->end();
2800: for(typename sieve_type::coneSet::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
2801: this->_indexArray->push_back(this->getIndex(patch, *p_iter, numbering));
2802: }
2803: #endif
2804: } else {
2805: const Obj<typename sieve_type::coneArray> cone = this->getTopology()->getPatch(patch)->nCone(p, level);
2806: typename sieve_type::coneArray::iterator end = cone->end();
2808: for(typename sieve_type::coneArray::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
2809: this->_indexArray->push_back(this->getIndex(patch, *p_iter, numbering));
2810: }
2811: }
2812: return this->_indexArray;
2813: };
2814: public: // Allocation
2815: 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) {
2816: const Obj<typename sieve_type::coneSequence>& cone = sieve->cone(point);
2817: typename sieve_type::coneSequence::iterator end = cone->end();
2818: index_type idx = atlas->restrictPoint(patch, point)[0];
2819: const int& dim = idx.prefix;
2820: const index_type defaultIdx(0, -1);
2822: if (atlas->getPatch(patch).count(point) == 0) {
2823: idx = defaultIdx;
2824: }
2825: if (idx.index == -1) {
2826: for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
2827: if (this->_debug > 1) {std::cout << " Recursing to " << *c_iter << std::endl;}
2828: this->orderPoint(atlas, sieve, patch, *c_iter, offset, bcOffset);
2829: }
2830: if (dim > 0) {
2831: bool number = true;
2833: // Maybe use template specialization here
2834: if (postponeGhosts && this->getTopology()->getSendOverlap()->capContains(point)) {
2835: const Obj<typename topology_type::send_overlap_type::supportSequence>& ranks = this->getTopology()->getSendOverlap()->support(point);
2837: for(typename topology_type::send_overlap_type::supportSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
2838: if (this->commRank() > *r_iter) {
2839: number = false;
2840: break;
2841: }
2842: }
2843: }
2844: if (number) {
2845: if (this->_debug > 1) {std::cout << " Ordering point " << point << " at " << offset << std::endl;}
2846: idx.index = offset;
2847: atlas->updatePoint(patch, point, &idx);
2848: offset += dim;
2849: } else {
2850: if (this->_debug > 1) {std::cout << " Ignoring ghost point " << point << std::endl;}
2851: }
2852: } else if (dim < 0) {
2853: if (this->_debug > 1) {std::cout << " Ordering boundary point " << point << " at " << bcOffset << std::endl;}
2854: idx.index = bcOffset;
2855: atlas->updatePoint(patch, point, &idx);
2856: bcOffset += dim;
2857: }
2858: }
2859: }
2860: 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) {
2861: const typename atlas_type::chart_type& chart = atlas->getPatch(patch);
2863: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
2864: if (this->_debug > 1) {std::cout << "Ordering closure of point " << *p_iter << std::endl;}
2865: this->orderPoint(atlas, this->getTopology()->getPatch(patch), patch, *p_iter, offset, bcOffset, postponeGhosts);
2866: }
2867: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
2868: index_type idx = atlas->restrictPoint(patch, *p_iter)[0];
2869: const int& dim = idx.prefix;
2871: if (dim < 0) {
2872: if (this->_debug > 1) {std::cout << "Correcting boundary offset of point " << *p_iter << std::endl;}
2873: idx.index = offset - (idx.index+2);
2874: atlas->updatePoint(patch, *p_iter, &idx);
2875: }
2876: }
2877: };
2878: void orderPatches(const Obj<atlas_type>& atlas, const bool postponeGhosts = false) {
2879: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
2881: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2882: if (this->_debug > 1) {std::cout << "Ordering patch " << p_iter->first << std::endl;}
2883: typename atlas_type::value_type::index_type offset = 0, bcOffset = -2;
2885: if (!atlas->hasPatch(p_iter->first)) continue;
2886: this->orderPatch(atlas, p_iter->first, offset, bcOffset, postponeGhosts);
2887: }
2888: };
2889: void orderPatches(const bool postponeGhosts = false) {
2890: this->orderPatches(this->_atlas, postponeGhosts);
2891: };
2892: void allocateStorage() {
2893: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
2895: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2896: if (!this->_atlas->hasPatch(p_iter->first)) continue;
2897: this->_arrays[p_iter->first] = new value_type[this->sizeWithBC(p_iter->first)];
2898: PetscMemzero(this->_arrays[p_iter->first], this->sizeWithBC(p_iter->first) * sizeof(value_type));
2899: }
2900: };
2901: void allocate(const bool postponeGhosts = false) {
2902: bool doGhosts = false;
2904: if (postponeGhosts && !this->getTopology()->getSendOverlap().isNull()) {
2905: doGhosts = true;
2906: }
2907: this->orderPatches(doGhosts);
2908: if (doGhosts) {
2909: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
2911: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2912: if (this->_debug > 1) {std::cout << "Ordering patch " << p_iter->first << " for ghosts" << std::endl;}
2913: const typename atlas_type::chart_type& points = this->_atlas->getPatch(p_iter->first);
2914: typename atlas_type::value_type::index_type offset = 0, bcOffset = -2;
2916: for(typename atlas_type::chart_type::iterator point = points.begin(); point != points.end(); ++point) {
2917: const index_type& idx = this->_atlas->restrictPoint(p_iter->first, *point)[0];
2919: offset = std::max(offset, idx.index + std::abs(idx.prefix));
2920: }
2921: if (!this->_atlas->hasPatch(p_iter->first)) continue;
2922: this->orderPatch(this->_atlas, p_iter->first, offset, bcOffset);
2923: if (offset != this->sizeWithBC(p_iter->first)) throw ALE::Exception("Inconsistent array sizes in section");
2924: }
2925: }
2926: this->allocateStorage();
2927: };
2928: void addPoint(const patch_type& patch, const point_type& point, const int dim) {
2929: if (dim == 0) return;
2930: //const typename atlas_type::chart_type& chart = this->_atlas->getPatch(patch);
2932: //if (chart.find(point) == chart.end()) {
2933: if (this->_atlasNew.isNull()) {
2934: this->_atlasNew = new atlas_type(this->getTopology());
2935: this->_atlasNew->copy(this->_atlas);
2936: }
2937: const index_type idx(dim, -1);
2938: this->_atlasNew->updatePatch(patch, point);
2939: this->_atlasNew->updatePoint(patch, point, &idx);
2940: };
2941: void reallocate() {
2942: if (this->_atlasNew.isNull()) return;
2943: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
2945: // Since copy() preserves offsets, we must reinitialize them before ordering
2946: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2947: const patch_type& patch = p_iter->first;
2948: const typename atlas_type::chart_type& chart = this->_atlasNew->getPatch(patch);
2949: index_type defaultIdx(0, -1);
2951: for(typename atlas_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
2952: defaultIdx.prefix = this->_atlasNew->restrictPoint(patch, *c_iter)[0].prefix;
2953: this->_atlasNew->updatePoint(patch, *c_iter, &defaultIdx);
2954: }
2955: }
2956: this->orderPatches(this->_atlasNew);
2957: // Copy over existing values
2958: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2959: const patch_type& patch = p_iter->first;
2960: value_type *newArray = new value_type[this->size(this->_atlasNew, patch)];
2962: if (!this->_atlas->hasPatch(patch)) {
2963: this->_arrays[patch] = newArray;
2964: continue;
2965: }
2966: const typename atlas_type::chart_type& chart = this->_atlas->getPatch(patch);
2967: const value_type *array = this->_arrays[patch];
2969: for(typename atlas_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
2970: const index_type& idx = this->_atlas->restrictPoint(patch, *c_iter)[0];
2971: const int size = idx.prefix;
2972: const int offset = idx.index;
2973: const int& newOffset = this->_atlasNew->restrictPoint(patch, *c_iter)[0].index;
2975: for(int i = 0; i < size; ++i) {
2976: newArray[newOffset+i] = array[offset+i];
2977: }
2978: }
2979: delete [] this->_arrays[patch];
2980: this->_arrays[patch] = newArray;
2981: }
2982: this->_atlas = this->_atlasNew;
2983: this->_atlasNew = NULL;
2984: };
2985: public: // Restriction and Update
2986: // Zero entries
2987: void zero(const patch_type& patch) {
2988: this->checkPatch(patch);
2989: memset(this->_arrays[patch], 0, this->size(patch)* sizeof(value_type));
2990: };
2991: // Return a pointer to the entire contiguous storage array
2992: const value_type *restrict(const patch_type& patch) {
2993: this->checkPatch(patch);
2994: return this->_arrays[patch];
2995: };
2996: // Update the entire contiguous storage array
2997: void update(const patch_type& patch, const value_type v[]) {
2998: const value_type *array = this->_arrays[patch];
2999: const int size = this->size(patch);
3001: for(int i = 0; i < size; i++) {
3002: array[i] = v[i];
3003: }
3004: };
3005: // Return the values for the closure of this point
3006: // use a smart pointer?
3007: const value_type *restrict(const patch_type& patch, const point_type& p) {
3008: this->checkPatch(patch);
3009: const value_type *a = this->_arrays[patch];
3010: const int size = this->sizeWithBC(patch, p);
3011: value_type *values = this->getRawArray(size);
3012: int j = -1;
3014: if (this->getTopology()->height(patch) < 2) {
3015: // Avoids the copy of both
3016: // points in topology->closure()
3017: // indices in _atlas->restrict()
3018: const index_type& pInd = this->_atlas->restrictPoint(patch, p)[0];
3020: for(int i = pInd.index; i < std::abs(pInd.prefix) + pInd.index; ++i) {
3021: values[++j] = a[i];
3022: }
3023: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3024: typename sieve_type::coneSequence::iterator end = cone->end();
3026: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3027: const index_type& ind = this->_atlas->restrictPoint(patch, *p_iter)[0];
3028: const int& start = ind.index;
3029: const int& length = std::abs(ind.prefix);
3031: for(int i = start; i < start + length; ++i) {
3032: values[++j] = a[i];
3033: }
3034: }
3035: } else {
3036: const Obj<IndexArray>& ind = this->getIndices(patch, p);
3038: for(typename IndexArray::iterator i_iter = ind->begin(); i_iter != ind->end(); ++i_iter) {
3039: const int& start = i_iter->index;
3040: const int& length = std::abs(i_iter->prefix);
3042: for(int i = start; i < start + length; ++i) {
3043: values[++j] = a[i];
3044: }
3045: }
3046: }
3047: if (j != size-1) {
3048: ostringstream txt;
3050: txt << "Invalid restrict to point " << p << std::endl;
3051: txt << " j " << j << " should be " << (size-1) << std::endl;
3052: std::cout << txt.str();
3053: throw ALE::Exception(txt.str().c_str());
3054: }
3055: return values;
3056: };
3057: // Update the values for the closure of this point
3058: void update(const patch_type& patch, const point_type& p, const value_type v[]) {
3059: this->checkPatch(patch);
3060: value_type *a = this->_arrays[patch];
3061: int j = -1;
3063: if (this->getTopology()->height(patch) < 2) {
3064: // Avoids the copy of both
3065: // points in topology->closure()
3066: // indices in _atlas->restrict()
3067: const index_type& pInd = this->_atlas->restrictPoint(patch, p)[0];
3069: for(int i = pInd.index; i < pInd.prefix + pInd.index; ++i) {
3070: a[i] = v[++j];
3071: }
3072: j += std::max(0, -pInd.prefix);
3073: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3074: typename sieve_type::coneSequence::iterator end = cone->end();
3076: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3077: const index_type& ind = this->_atlas->restrictPoint(patch, *p_iter)[0];
3078: const int& start = ind.index;
3079: const int& length = ind.prefix;
3081: for(int i = start; i < start + length; ++i) {
3082: a[i] = v[++j];
3083: }
3084: j += std::max(0, -length);
3085: }
3086: } else {
3087: const Obj<IndexArray>& ind = this->getIndices(patch, p);
3089: for(typename IndexArray::iterator i_iter = ind->begin(); i_iter != ind->end(); ++i_iter) {
3090: const int& start = i_iter->index;
3091: const int& length = i_iter->prefix;
3093: for(int i = start; i < start + length; ++i) {
3094: a[i] = v[++j];
3095: }
3096: j += std::max(0, -length);
3097: }
3098: }
3099: };
3100: // Update the values for the closure of this point
3101: void updateAdd(const patch_type& patch, const point_type& p, const value_type v[]) {
3102: this->checkPatch(patch);
3103: value_type *a = this->_arrays[patch];
3104: int j = -1;
3106: if (this->getTopology()->height(patch) < 2) {
3107: // Avoids the copy of both
3108: // points in topology->closure()
3109: // indices in _atlas->restrict()
3110: const index_type& pInd = this->_atlas->restrictPoint(patch, p)[0];
3112: for(int i = pInd.index; i < pInd.prefix + pInd.index; ++i) {
3113: a[i] += v[++j];
3114: }
3115: j += std::max(0, -pInd.prefix);
3116: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3117: typename sieve_type::coneSequence::iterator end = cone->end();
3119: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3120: const index_type& ind = this->_atlas->restrictPoint(patch, *p_iter)[0];
3121: const int& start = ind.index;
3122: const int& length = ind.prefix;
3124: for(int i = start; i < start + length; ++i) {
3125: a[i] += v[++j];
3126: }
3127: j += std::max(0, -length);
3128: }
3129: } else {
3130: const Obj<IndexArray>& ind = this->getIndices(patch, p);
3132: for(typename IndexArray::iterator i_iter = ind->begin(); i_iter != ind->end(); ++i_iter) {
3133: const int& start = i_iter->index;
3134: const int& length = i_iter->prefix;
3136: for(int i = start; i < start + length; ++i) {
3137: a[i] += v[++j];
3138: }
3139: j += std::max(0, -length);
3140: }
3141: }
3142: };
3143: // Update the values for the closure of this point
3144: template<typename Input>
3145: void update(const patch_type& patch, const point_type& p, const Obj<Input>& v) {
3146: this->checkPatch(patch);
3147: value_type *a = this->_arrays[patch];
3149: if (this->getTopology()->height(patch) == 1) {
3150: // Only avoids the copy
3151: const index_type& pInd = this->_atlas->restrictPoint(patch, p)[0];
3152: typename Input::iterator v_iter = v->begin();
3153: typename Input::iterator v_end = v->end();
3155: for(int i = pInd.index; i < pInd.prefix + pInd.index; ++i) {
3156: a[i] = *v_iter;
3157: ++v_iter;
3158: }
3159: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3160: typename sieve_type::coneSequence::iterator end = cone->end();
3162: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3163: const index_type& ind = this->_atlas->restrictPoint(patch, *p_iter)[0];
3164: const int& start = ind.index;
3165: const int& length = ind.prefix;
3167: for(int i = start; i < start + length; ++i) {
3168: a[i] = *v_iter;
3169: ++v_iter;
3170: }
3171: }
3172: } else {
3173: const Obj<IndexArray>& ind = this->getIndices(patch, p);
3174: typename Input::iterator v_iter = v->begin();
3175: typename Input::iterator v_end = v->end();
3177: for(typename IndexArray::iterator i_iter = ind->begin(); i_iter != ind->end(); ++i_iter) {
3178: const int& start = i_iter->index;
3179: const int& length = i_iter->prefix;
3181: for(int i = start; i < start + length; ++i) {
3182: a[i] = *v_iter;
3183: ++v_iter;
3184: }
3185: }
3186: }
3187: };
3188: void updateBC(const patch_type& patch, const point_type& p, const value_type v[]) {
3189: this->checkPatch(patch);
3190: value_type *a = this->_arrays[patch];
3191: int j = -1;
3193: if (this->getTopology()->height(patch) < 2) {
3194: // Avoids the copy of both
3195: // points in topology->closure()
3196: // indices in _atlas->restrict()
3197: const index_type& pInd = this->_atlas->restrictPoint(patch, p)[0];
3199: for(int i = pInd.index; i < std::abs(pInd.prefix) + pInd.index; ++i) {
3200: a[i] = v[++j];
3201: }
3202: const Obj<typename sieve_type::coneSequence>& cone = this->getTopology()->getPatch(patch)->cone(p);
3203: typename sieve_type::coneSequence::iterator end = cone->end();
3205: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
3206: const index_type& ind = this->_atlas->restrictPoint(patch, *p_iter)[0];
3207: const int& start = ind.index;
3208: const int& length = std::abs(ind.prefix);
3210: for(int i = start; i < start + length; ++i) {
3211: a[i] = v[++j];
3212: }
3213: }
3214: } else {
3215: const Obj<IndexArray>& ind = this->getIndices(patch, p);
3217: for(typename IndexArray::iterator i_iter = ind->begin(); i_iter != ind->end(); ++i_iter) {
3218: const int& start = i_iter->index;
3219: const int& length = std::abs(i_iter->prefix);
3221: for(int i = start; i < start + length; ++i) {
3222: a[i] = v[++j];
3223: }
3224: }
3225: }
3226: };
3227: // Return only the values associated to this point, not its closure
3228: const value_type *restrictPoint(const patch_type& patch, const point_type& p) {
3229: this->checkPatch(patch);
3230: return &(this->_arrays[patch][this->_atlas->restrictPoint(patch, p)[0].index]);
3231: };
3232: // Update only the values associated to this point, not its closure
3233: void updatePoint(const patch_type& patch, const point_type& p, const value_type v[]) {
3234: this->checkPatch(patch);
3235: const index_type& idx = this->_atlas->restrictPoint(patch, p)[0];
3236: value_type *a = &(this->_arrays[patch][idx.index]);
3238: for(int i = 0; i < idx.prefix; ++i) {
3239: a[i] = v[i];
3240: }
3241: };
3242: // Update only the values associated to this point, not its closure
3243: void updateAddPoint(const patch_type& patch, const point_type& p, const value_type v[]) {
3244: this->checkPatch(patch);
3245: const index_type& idx = this->_atlas->restrictPoint(patch, p)[0];
3246: value_type *a = &(this->_arrays[patch][idx.index]);
3248: for(int i = 0; i < idx.prefix; ++i) {
3249: a[i] += v[i];
3250: }
3251: };
3252: void updatePointBC(const patch_type& patch, const point_type& p, const value_type v[]) {
3253: this->checkPatch(patch);
3254: const index_type& idx = this->_atlas->restrictPoint(patch, p)[0];
3255: value_type *a = &(this->_arrays[patch][idx.index]);
3257: for(int i = 0; i < std::abs(idx.prefix); ++i) {
3258: a[i] = v[i];
3259: }
3260: };
3261: public: // BC
3262: void copyBC(const Obj<Section>& section) {
3263: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
3265: for(typename topology_type::sheaf_type::const_iterator patch_iter = patches.begin(); patch_iter != patches.end(); ++patch_iter) {
3266: const typename atlas_type::chart_type& chart = this->_atlas->getPatch(patch_iter->first);
3268: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
3269: const index_type& idx = this->_atlas->restrictPoint(patch_iter->first, *p_iter)[0];
3271: if (idx.prefix < 0) {
3272: this->updatePointBC(patch_iter->first, *p_iter, section->restrictPoint(patch_iter->first, *p_iter));
3273: }
3274: }
3275: }
3276: };
3277: public:
3278: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
3279: ostringstream txt;
3280: int rank;
3282: if (comm == MPI_COMM_NULL) {
3283: comm = this->comm();
3284: rank = this->commRank();
3285: } else {
3286: MPI_Comm_rank(comm, &rank);
3287: }
3288: if (name == "") {
3289: if(rank == 0) {
3290: txt << "viewing a Section" << std::endl;
3291: }
3292: } else {
3293: if(rank == 0) {
3294: txt << "viewing Section '" << name << "'" << std::endl;
3295: }
3296: }
3297: for(typename values_type::const_iterator a_iter = this->_arrays.begin(); a_iter != this->_arrays.end(); ++a_iter) {
3298: const patch_type& patch = a_iter->first;
3299: const value_type *array = a_iter->second;
3301: txt << "[" << this->commRank() << "]: Patch " << patch << std::endl;
3302: const typename atlas_type::chart_type& chart = this->_atlas->getPatch(patch);
3304: for(typename atlas_type::chart_type::const_iterator p_iter = chart.begin(); p_iter != chart.end(); ++p_iter) {
3305: const point_type& point = *p_iter;
3306: const index_type& idx = this->_atlas->restrictPoint(patch, point)[0];
3308: if (idx.prefix != 0) {
3309: txt << "[" << this->commRank() << "]: " << point << " dim " << idx.prefix << " offset " << idx.index << " ";
3310: for(int i = 0; i < std::abs(idx.prefix); i++) {
3311: txt << " " << array[idx.index+i];
3312: }
3313: txt << std::endl;
3314: }
3315: }
3316: }
3317: if (this->_arrays.empty()) {
3318: txt << "[" << this->commRank() << "]: empty" << std::endl;
3319: }
3320: PetscSynchronizedPrintf(comm, txt.str().c_str());
3321: PetscSynchronizedFlush(comm);
3322: };
3323: };
3325: // An Overlap is a Sifter describing the overlap of two Sieves
3326: // Each arrow is local point ---(remote point)---> remote rank right now
3327: // For XSifter, this should change to (local patch, local point) ---> (remote rank, remote patch, remote point)
3329: template<typename Topology_, typename Value_>
3330: class OldConstantSection : public ALE::ParallelObject {
3331: public:
3332: typedef OldConstantSection<Topology_, Value_> section_type;
3333: typedef Topology_ topology_type;
3334: typedef typename topology_type::patch_type patch_type;
3335: typedef typename topology_type::sieve_type sieve_type;
3336: typedef typename topology_type::point_type point_type;
3337: typedef Value_ value_type;
3338: protected:
3339: Obj<topology_type> _topology;
3340: const value_type _value;
3341: Obj<section_type> _section;
3342: public:
3343: OldConstantSection(MPI_Comm comm, const value_type value, const int debug = 0) : ParallelObject(comm, debug), _value(value) {
3344: this->_topology = new topology_type(comm, debug);
3345: this->_section = this;
3346: this->_section.addRef();
3347: };
3348: OldConstantSection(const Obj<topology_type>& topology, const value_type value) : ParallelObject(topology->comm(), topology->debug()), _topology(topology), _value(value) {
3349: this->_section = this;
3350: this->_section.addRef();
3351: };
3352: virtual ~OldConstantSection() {};
3353: public: // Verifiers
3354: bool hasPoint(const patch_type& patch, const point_type& point) const {return true;};
3355: public: // Restriction
3356: const value_type *restrict(const patch_type& patch) {return &this->_value;};
3357: const value_type *restrictPoint(const patch_type& patch, const point_type& p) {return &this->_value;};
3358: public: // Adapter
3359: const Obj<section_type>& getSection(const patch_type& patch) {return this->_section;};
3360: const value_type *restrictPoint(const point_type& p) {return &this->_value;};
3361: public:
3362: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) const {
3363: ostringstream txt;
3364: int rank;
3366: if (comm == MPI_COMM_NULL) {
3367: comm = this->comm();
3368: rank = this->commRank();
3369: } else {
3370: MPI_Comm_rank(comm, &rank);
3371: }
3372: if (name == "") {
3373: if(rank == 0) {
3374: txt << "viewing a OldConstantSection with value " << this->_value << std::endl;
3375: }
3376: } else {
3377: if(rank == 0) {
3378: txt << "viewing OldConstantSection '" << name << "' with value " << this->_value << std::endl;
3379: }
3380: }
3381: PetscSynchronizedPrintf(comm, txt.str().c_str());
3382: PetscSynchronizedFlush(comm);
3383: };
3384: };
3386: template<typename Overlap_, typename Topology_, typename Value_>
3387: class OverlapValues : public Section<Topology_, Value_> {
3388: public:
3389: typedef Overlap_ overlap_type;
3390: typedef Section<Topology_, Value_> base_type;
3391: typedef typename base_type::topology_type topology_type;
3392: typedef typename base_type::patch_type patch_type;
3393: typedef typename base_type::chart_type chart_type;
3394: typedef typename base_type::atlas_type atlas_type;
3395: typedef typename base_type::value_type value_type;
3396: typedef enum {SEND, RECEIVE} request_type;
3397: typedef std::map<patch_type, MPI_Request> requests_type;
3398: protected:
3399: int _tag;
3400: MPI_Datatype _datatype;
3401: requests_type _requests;
3402: public:
3403: OverlapValues(MPI_Comm comm, const int debug = 0) : Section<Topology_, Value_>(comm, debug) {
3404: this->_tag = this->getNewTag();
3405: this->_datatype = this->getMPIDatatype();
3406: };
3407: OverlapValues(MPI_Comm comm, const int tag, const int debug) : Section<Topology_, Value_>(comm, debug), _tag(tag) {
3408: this->_datatype = this->getMPIDatatype();
3409: };
3410: virtual ~OverlapValues() {};
3411: protected:
3412: MPI_Datatype getMPIDatatype() {
3413: if (sizeof(value_type) == 4) {
3414: return MPI_INT;
3415: } else if (sizeof(value_type) == 8) {
3416: return MPI_DOUBLE;
3417: } else if (sizeof(value_type) == 28) {
3418: int blen[2];
3419: MPI_Aint indices[2];
3420: MPI_Datatype oldtypes[2], newtype;
3421: blen[0] = 1; indices[0] = 0; oldtypes[0] = MPI_INT;
3422: blen[1] = 3; indices[1] = sizeof(int); oldtypes[1] = MPI_DOUBLE;
3423: MPI_Type_struct(2, blen, indices, oldtypes, &newtype);
3424: MPI_Type_commit(&newtype);
3425: return newtype;
3426: } else if (sizeof(value_type) == 32) {
3427: int blen[2];
3428: MPI_Aint indices[2];
3429: MPI_Datatype oldtypes[2], newtype;
3430: blen[0] = 1; indices[0] = 0; oldtypes[0] = MPI_DOUBLE;
3431: blen[1] = 3; indices[1] = sizeof(int); oldtypes[1] = MPI_DOUBLE;
3432: MPI_Type_struct(2, blen, indices, oldtypes, &newtype);
3433: MPI_Type_commit(&newtype);
3434: return newtype;
3435: }
3436: throw ALE::Exception("Cannot determine MPI type for value type");
3437: };
3438: int getNewTag() {
3439: static int tagKeyval = MPI_KEYVAL_INVALID;
3440: int *tagvalp = NULL, *maxval, flg;
3442: if (tagKeyval == MPI_KEYVAL_INVALID) {
3443: tagvalp = (int *) malloc(sizeof(int));
3444: MPI_Keyval_create(MPI_NULL_COPY_FN, Mesh_DelTag, &tagKeyval, (void *) NULL);
3445: MPI_Attr_put(this->_comm, tagKeyval, tagvalp);
3446: tagvalp[0] = 0;
3447: }
3448: MPI_Attr_get(this->_comm, tagKeyval, (void **) &tagvalp, &flg);
3449: if (tagvalp[0] < 1) {
3450: MPI_Attr_get(MPI_COMM_WORLD, MPI_TAG_UB, (void **) &maxval, &flg);
3451: tagvalp[0] = *maxval - 128; // hope that any still active tags were issued right at the beginning of the run
3452: }
3453: if (this->debug()) {
3454: std::cout << "[" << this->commRank() << "]Got new tag " << tagvalp[0] << std::endl;
3455: }
3456: return tagvalp[0]--;
3457: };
3458: public: // Accessors
3459: int getTag() const {return this->_tag;};
3460: void setTag(const int tag) {this->_tag = tag;};
3461: public:
3462: void construct(const int size) {
3463: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
3465: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
3466: const Obj<typename topology_type::sieve_type::baseSequence>& base = p_iter->second->base();
3467: int rank = p_iter->first;
3469: for(typename topology_type::sieve_type::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
3470: this->setFiberDimension(rank, *b_iter, size);
3471: }
3472: }
3473: };
3474: template<typename Sizer>
3475: void construct(const Obj<Sizer>& sizer) {
3476: const typename topology_type::sheaf_type& patches = this->getTopology()->getPatches();
3478: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
3479: const Obj<typename topology_type::sieve_type::baseSequence>& base = p_iter->second->base();
3480: int rank = p_iter->first;
3482: for(typename topology_type::sieve_type::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
3483: this->setFiberDimension(rank, *b_iter, *(sizer->restrictPoint(rank, *b_iter)));
3484: }
3485: }
3486: };
3487: void constructCommunication(const request_type& requestType) {
3488: const typename topology_type::sheaf_type& patches = this->getAtlas()->getTopology()->getPatches();
3490: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
3491: const patch_type patch = p_iter->first;
3492: MPI_Request request;
3494: if (requestType == RECEIVE) {
3495: if (this->_debug) {std::cout <<"["<<this->commRank()<<"] Receiving data(" << this->size(patch) << ") from " << patch << " tag " << this->_tag << std::endl;}
3496: MPI_Recv_init(this->_arrays[patch], this->size(patch), this->_datatype, patch, this->_tag, this->_comm, &request);
3497: } else {
3498: if (this->_debug) {std::cout <<"["<<this->commRank()<<"] Sending data (" << this->size(patch) << ") to " << patch << " tag " << this->_tag << std::endl;}
3499: MPI_Send_init(this->_arrays[patch], this->size(patch), this->_datatype, patch, this->_tag, this->_comm, &request);
3500: }
3501: this->_requests[patch] = request;
3502: }
3503: };
3504: void startCommunication() {
3505: const typename topology_type::sheaf_type& patches = this->getAtlas()->getTopology()->getPatches();
3507: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
3508: MPI_Request request = this->_requests[p_iter->first];
3510: MPI_Start(&request);
3511: }
3512: };
3513: void endCommunication() {
3514: const typename topology_type::sheaf_type& patches = this->getAtlas()->getTopology()->getPatches();
3515: MPI_Status status;
3517: for(typename topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
3518: MPI_Request request = this->_requests[p_iter->first];
3520: MPI_Wait(&request, &status);
3521: }
3522: };
3523: };
3524: }
3525: }
3526: #endif