Actual source code: Mesh.hh
petsc-3.3-p7 2013-05-11
1: #ifndef included_ALE_Mesh_hh
2: #define included_ALE_Mesh_hh
4: #include <list>
5: #include <valarray>
7: #ifndef included_ALE_Numbering_hh
8: #include <sieve/Numbering.hh>
9: #endif
11: #ifndef included_ALE_INumbering_hh
12: #include <sieve/INumbering.hh>
13: #endif
15: #ifndef included_ALE_Field_hh
16: #include <sieve/Field.hh>
17: #endif
19: #ifndef included_ALE_IField_hh
20: #include <sieve/IField.hh>
21: #endif
23: #ifndef included_ALE_SieveBuilder_hh
24: #include <sieve/SieveBuilder.hh>
25: #endif
27: #ifndef included_ALE_LabelSifter_hh
28: #include <sieve/LabelSifter.hh>
29: #endif
31: #ifndef included_ALE_Partitioner_hh
32: #include <sieve/Partitioner.hh>
33: #endif
35: #ifndef included_ALE_Ordering_hh
36: #include <sieve/Ordering.hh>
37: #endif
39: #ifndef included_PETSc_Overlap_hh
40: #include <sieve/Overlap.hh>
41: #endif
43: namespace ALE {
44: class indexSet : public std::valarray<int> {
45: public:
46: inline bool
47: operator<(const indexSet& __x) {
48: if (__x.size() != this->size()) return __x.size() < this->size();
49: for(unsigned int i = 0; i < __x.size(); ++i) {
50: if (__x[i] == (*this)[i]) continue;
51: return __x[i] < (*this)[i];
52: }
53: return false;
54: }
55: };
56: inline bool
57: operator<(const indexSet& __x, const indexSet& __y) {
58: if (__x.size() != __y.size()) return __x.size() < __y.size();
59: for(unsigned int i = 0; i < __x.size(); ++i) {
60: if (__x[i] == __y[i]) continue;
61: return __x[i] < __y[i];
62: }
63: return false;
64: };
65: inline bool
66: operator<=(const indexSet& __x, const indexSet& __y) {
67: if (__x.size() != __y.size()) return __x.size() < __y.size();
68: for(unsigned int i = 0; i < __x.size(); ++i) {
69: if (__x[i] == __y[i]) continue;
70: return __x[i] < __y[i];
71: }
72: return true;
73: };
74: inline bool
75: operator==(const indexSet& __x, const indexSet& __y) {
76: if (__x.size() != __y.size()) return false;
77: for(unsigned int i = 0; i < __x.size(); ++i) {
78: if (__x[i] != __y[i]) return false;
79: }
80: return true;
81: };
82: inline bool
83: operator!=(const indexSet& __x, const indexSet& __y) {
84: if (__x.size() != __y.size()) return true;
85: for(unsigned int i = 0; i < __x.size(); ++i) {
86: if (__x[i] != __y[i]) return true;
87: }
88: return false;
89: };
91: template<typename Sieve_,
92: typename RealSection_ = Section<typename Sieve_::point_type, double>,
93: typename IntSection_ = Section<typename Sieve_::point_type, int>,
94: typename ArrowSection_ = UniformSection<MinimalArrow<typename Sieve_::point_type, typename Sieve_::point_type>, int> >
95: class Bundle : public ALE::ParallelObject {
96: public:
97: typedef Sieve_ sieve_type;
98: typedef RealSection_ real_section_type;
99: typedef IntSection_ int_section_type;
100: typedef ArrowSection_ arrow_section_type;
101: typedef Bundle<Sieve_,RealSection_,IntSection_,ArrowSection_> this_type;
102: typedef typename sieve_type::point_type point_type;
103: typedef malloc_allocator<point_type> alloc_type;
104: typedef typename ALE::LabelSifter<int, point_type> label_type;
105: typedef typename std::map<const std::string, Obj<label_type> > labels_type;
106: typedef typename label_type::supportSequence label_sequence;
107: typedef std::map<std::string, Obj<arrow_section_type> > arrow_sections_type;
108: typedef std::map<std::string, Obj<real_section_type> > real_sections_type;
109: typedef std::map<std::string, Obj<int_section_type> > int_sections_type;
110: typedef ALE::Point index_type;
111: typedef std::pair<index_type, int> oIndex_type;
112: typedef std::vector<oIndex_type> oIndexArray;
113: typedef std::pair<int *, int> indices_type;
114: typedef NumberingFactory<this_type> MeshNumberingFactory;
115: typedef typename ALE::Partitioner<>::part_type rank_type;
116: typedef typename ALE::Sifter<point_type,rank_type,point_type> send_overlap_type;
117: typedef typename ALE::Sifter<rank_type,point_type,point_type> recv_overlap_type;
118: typedef typename MeshNumberingFactory::numbering_type numbering_type;
119: typedef typename MeshNumberingFactory::order_type order_type;
120: typedef std::map<point_type, point_type> renumbering_type;
121: typedef typename ALE::SieveAlg<this_type> sieve_alg_type;
122: typedef typename sieve_alg_type::coneArray coneArray;
123: typedef typename sieve_alg_type::orientedConeArray oConeArray;
124: typedef typename sieve_alg_type::supportArray supportArray;
125: protected:
126: Obj<sieve_type> _sieve;
127: labels_type _labels;
128: int _maxHeight;
129: int _maxDepth;
130: arrow_sections_type _arrowSections;
131: real_sections_type _realSections;
132: int_sections_type _intSections;
133: Obj<oIndexArray> _indexArray;
134: Obj<MeshNumberingFactory> _factory;
135: bool _calculatedOverlap;
136: Obj<send_overlap_type> _sendOverlap;
137: Obj<recv_overlap_type> _recvOverlap;
138: Obj<send_overlap_type> _distSendOverlap;
139: Obj<recv_overlap_type> _distRecvOverlap;
140: renumbering_type _renumbering; // Maps global points to local points
141: // Work space
142: Obj<std::set<point_type> > _modifiedPoints;
143: public:
144: Bundle(MPI_Comm comm, int debug = 0) : ALE::ParallelObject(comm, debug), _maxHeight(-1), _maxDepth(-1) {
145: this->_indexArray = new oIndexArray();
146: this->_modifiedPoints = new std::set<point_type>();
147: this->_factory = MeshNumberingFactory::singleton(this->comm(), this->debug());
148: this->_calculatedOverlap = false;
149: this->_sendOverlap = new send_overlap_type(comm, debug);
150: this->_recvOverlap = new recv_overlap_type(comm, debug);
151: };
152: Bundle(const Obj<sieve_type>& sieve) : ALE::ParallelObject(sieve->comm(), sieve->debug()), _sieve(sieve), _maxHeight(-1), _maxDepth(-1) {
153: this->_indexArray = new oIndexArray();
154: this->_modifiedPoints = new std::set<point_type>();
155: this->_factory = MeshNumberingFactory::singleton(this->comm(), this->debug());
156: this->_calculatedOverlap = false;
157: this->_sendOverlap = new send_overlap_type(this->comm(), this->debug());
158: this->_recvOverlap = new recv_overlap_type(this->comm(), this->debug());
159: };
160: virtual ~Bundle() {};
161: public: // Verifiers
162: bool hasLabel(const std::string& name) {
163: if (this->_labels.find(name) != this->_labels.end()) {
164: return true;
165: }
166: return false;
167: };
168: void checkLabel(const std::string& name) {
169: if (!this->hasLabel(name)) {
170: ostringstream msg;
171: msg << "Invalid label name: " << name << std::endl;
172: throw ALE::Exception(msg.str().c_str());
173: }
174: };
175: public: // Accessors
176: const Obj<sieve_type>& getSieve() const {return this->_sieve;};
177: void setSieve(const Obj<sieve_type>& sieve) {this->_sieve = sieve;};
178: bool hasArrowSection(const std::string& name) const {
179: return this->_arrowSections.find(name) != this->_arrowSections.end();
180: };
181: const Obj<arrow_section_type>& getArrowSection(const std::string& name) {
182: if (!this->hasArrowSection(name)) {
183: Obj<arrow_section_type> section = new arrow_section_type(this->comm(), this->debug());
185: section->setName(name);
186: if (this->_debug) {std::cout << "Creating new arrow section: " << name << std::endl;}
187: this->_arrowSections[name] = section;
188: }
189: return this->_arrowSections[name];
190: };
191: void setArrowSection(const std::string& name, const Obj<arrow_section_type>& section) {
192: this->_arrowSections[name] = section;
193: };
194: Obj<std::set<std::string> > getArrowSections() const {
195: Obj<std::set<std::string> > names = std::set<std::string>();
197: for(typename arrow_sections_type::const_iterator s_iter = this->_arrowSections.begin(); s_iter != this->_arrowSections.end(); ++s_iter) {
198: names->insert(s_iter->first);
199: }
200: return names;
201: };
202: bool hasRealSection(const std::string& name) const {
203: return this->_realSections.find(name) != this->_realSections.end();
204: };
205: const Obj<real_section_type>& getRealSection(const std::string& name) {
206: if (!this->hasRealSection(name)) {
207: Obj<real_section_type> section = new real_section_type(this->comm(), this->debug());
209: section->setName(name);
210: if (this->_debug) {std::cout << "Creating new real section: " << name << std::endl;}
211: this->_realSections[name] = section;
212: }
213: return this->_realSections[name];
214: };
215: void setRealSection(const std::string& name, const Obj<real_section_type>& section) {
216: this->_realSections[name] = section;
217: };
218: Obj<std::set<std::string> > getRealSections() const {
219: Obj<std::set<std::string> > names = std::set<std::string>();
221: for(typename real_sections_type::const_iterator s_iter = this->_realSections.begin(); s_iter != this->_realSections.end(); ++s_iter) {
222: names->insert(s_iter->first);
223: }
224: return names;
225: };
226: bool hasIntSection(const std::string& name) const {
227: return this->_intSections.find(name) != this->_intSections.end();
228: };
229: const Obj<int_section_type>& getIntSection(const std::string& name) {
230: if (!this->hasIntSection(name)) {
231: Obj<int_section_type> section = new int_section_type(this->comm(), this->debug());
233: section->setName(name);
234: if (this->_debug) {std::cout << "Creating new int section: " << name << std::endl;}
235: this->_intSections[name] = section;
236: }
237: return this->_intSections[name];
238: };
239: void setIntSection(const std::string& name, const Obj<int_section_type>& section) {
240: this->_intSections[name] = section;
241: };
242: Obj<std::set<std::string> > getIntSections() const {
243: Obj<std::set<std::string> > names = std::set<std::string>();
245: for(typename int_sections_type::const_iterator s_iter = this->_intSections.begin(); s_iter != this->_intSections.end(); ++s_iter) {
246: names->insert(s_iter->first);
247: }
248: return names;
249: };
250: const Obj<MeshNumberingFactory>& getFactory() const {return this->_factory;};
251: bool getCalculatedOverlap() const {return this->_calculatedOverlap;};
252: void setCalculatedOverlap(const bool calc) {this->_calculatedOverlap = calc;};
253: const Obj<send_overlap_type>& getSendOverlap() const {return this->_sendOverlap;};
254: void setSendOverlap(const Obj<send_overlap_type>& overlap) {this->_sendOverlap = overlap;};
255: const Obj<recv_overlap_type>& getRecvOverlap() const {return this->_recvOverlap;};
256: void setRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_recvOverlap = overlap;};
257: const Obj<send_overlap_type>& getDistSendOverlap() const {return this->_distSendOverlap;};
258: void setDistSendOverlap(const Obj<send_overlap_type>& overlap) {this->_distSendOverlap = overlap;};
259: const Obj<recv_overlap_type>& getDistRecvOverlap() const {return this->_distRecvOverlap;};
260: void setDistRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_distRecvOverlap = overlap;};
261: renumbering_type& getRenumbering() {return this->_renumbering;};
262: public: // Labels
263: int getValue (const Obj<label_type>& label, const point_type& point, const int defValue = 0) {
264: const Obj<typename label_type::coneSequence>& cone = label->cone(point);
266: if (cone->size() == 0) return defValue;
267: return *cone->begin();
268: };
269: void setValue(const Obj<label_type>& label, const point_type& point, const int value) {
270: label->setCone(value, point);
271: };
272: template<typename InputPoints>
273: int getMaxValue (const Obj<label_type>& label, const Obj<InputPoints>& points, const int defValue = 0) {
274: int maxValue = defValue;
276: for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
277: maxValue = std::max(maxValue, this->getValue(label, *p_iter, defValue));
278: }
279: return maxValue;
280: }
281: const Obj<label_type>& createLabel(const std::string& name) {
282: this->_labels[name] = new label_type(this->comm(), this->debug());
283: return this->_labels[name];
284: };
285: const Obj<label_type>& getLabel(const std::string& name) {
286: this->checkLabel(name);
287: return this->_labels[name];
288: };
289: void setLabel(const std::string& name, const Obj<label_type>& label) {
290: this->_labels[name] = label;
291: };
292: const labels_type& getLabels() {
293: return this->_labels;
294: };
295: virtual const Obj<label_sequence>& getLabelStratum(const std::string& name, int value) {
296: this->checkLabel(name);
297: return this->_labels[name]->support(value);
298: };
299: public: // Stratification
300: template<class InputPoints>
301: void computeHeight(const Obj<label_type>& height, const Obj<sieve_type>& sieve, const Obj<InputPoints>& points, int& maxHeight) {
302: this->_modifiedPoints->clear();
304: for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
305: // Compute the max height of the points in the support of p, and add 1
306: int h0 = this->getValue(height, *p_iter, -1);
307: int h1 = this->getMaxValue(height, sieve->support(*p_iter), -1) + 1;
309: if(h1 != h0) {
310: this->setValue(height, *p_iter, h1);
311: if (h1 > maxHeight) maxHeight = h1;
312: this->_modifiedPoints->insert(*p_iter);
313: }
314: }
315: // FIX: We would like to avoid the copy here with cone()
316: if(this->_modifiedPoints->size() > 0) {
317: this->computeHeight(height, sieve, sieve->cone(this->_modifiedPoints), maxHeight);
318: }
319: }
320: void computeHeights() {
321: const Obj<label_type>& label = this->createLabel(std::string("height"));
323: this->_maxHeight = -1;
324: this->computeHeight(label, this->_sieve, this->_sieve->leaves(), this->_maxHeight);
325: };
326: virtual int height() const {return this->_maxHeight;};
327: virtual int height(const point_type& point) {
328: return this->getValue(this->_labels["height"], point, -1);
329: };
330: virtual const Obj<label_sequence>& heightStratum(int height) {
331: return this->getLabelStratum("height", height);
332: };
333: void setHeight(const Obj<label_type>& label) {
334: this->_labels["height"] = label;
335: const Obj<typename label_type::traits::capSequence> cap = label->cap();
337: for(typename label_type::traits::capSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
338: this->_maxHeight = std::max(this->_maxHeight, *c_iter);
339: }
340: };
341: template<class InputPoints>
342: void computeDepth(const Obj<label_type>& depth, const Obj<sieve_type>& sieve, const Obj<InputPoints>& points, int& maxDepth) {
343: this->_modifiedPoints->clear();
345: for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
346: // Compute the max depth of the points in the cone of p, and add 1
347: int d0 = this->getValue(depth, *p_iter, -1);
348: int d1 = this->getMaxValue(depth, sieve->cone(*p_iter), -1) + 1;
350: if(d1 != d0) {
351: this->setValue(depth, *p_iter, d1);
352: if (d1 > maxDepth) maxDepth = d1;
353: this->_modifiedPoints->insert(*p_iter);
354: }
355: }
356: // FIX: We would like to avoid the copy here with support()
357: if(this->_modifiedPoints->size() > 0) {
358: this->computeDepth(depth, sieve, sieve->support(this->_modifiedPoints), maxDepth);
359: }
360: }
361: void computeDepths() {
362: const Obj<label_type>& label = this->createLabel(std::string("depth"));
364: this->_maxDepth = -1;
365: this->computeDepth(label, this->_sieve, this->_sieve->roots(), this->_maxDepth);
366: };
367: virtual int depth() const {return this->_maxDepth;};
368: virtual int depth(const point_type& point) {
369: return this->getValue(this->_labels["depth"], point, -1);
370: };
371: virtual const Obj<label_sequence>& depthStratum(int depth) {
372: return this->getLabelStratum("depth", depth);
373: };
376: virtual void stratify() {
377: ALE_LOG_EVENT_BEGIN;
378: this->computeHeights();
379: this->computeDepths();
380: ALE_LOG_EVENT_END;
381: };
382: public: // Size traversal
383: template<typename Section_>
384: int size(const Obj<Section_>& section, const point_type& p) {
385: const typename Section_::chart_type& chart = section->getChart();
386: int size = 0;
388: if (this->height() < 2) {
389: const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
390: typename sieve_type::coneSequence::iterator end = cone->end();
392: if (chart.count(p)) {
393: size += section->getConstrainedFiberDimension(p);
394: }
395: for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
396: if (chart.count(*c_iter)) {
397: size += section->getConstrainedFiberDimension(*c_iter);
398: }
399: }
400: } else {
401: const Obj<coneArray> closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), p);
402: typename coneArray::iterator end = closure->end();
404: for(typename coneArray::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
405: if (chart.count(*c_iter)) {
406: size += section->getConstrainedFiberDimension(*c_iter);
407: }
408: }
409: }
410: return size;
411: }
412: template<typename Section_>
413: int sizeWithBC(const Obj<Section_>& section, const point_type& p) {
414: const typename Section_::chart_type& chart = section->getChart();
415: int size = 0;
417: if (this->height() < 2) {
418: const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
419: typename sieve_type::coneSequence::iterator end = cone->end();
421: if (chart.count(p)) {
422: size += section->getFiberDimension(p);
423: }
424: for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
425: if (chart.count(*c_iter)) {
426: size += section->getFiberDimension(*c_iter);
427: }
428: }
429: } else {
430: const Obj<coneArray> closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), p);
431: typename coneArray::iterator end = closure->end();
433: for(typename coneArray::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
434: if (chart.count(*c_iter)) {
435: size += section->getFiberDimension(*c_iter);
436: }
437: }
438: }
439: return size;
440: }
441: protected:
442: int *getIndexArray(const int size) {
443: static int *array = NULL;
444: static int maxSize = 0;
446: if (size > maxSize) {
447: maxSize = size;
448: if (array) delete [] array;
449: array = new int[maxSize];
450: };
451: return array;
452: };
453: public: // Index traversal
454: void expandInterval(const index_type& interval, PetscInt indices[], PetscInt *indx) {
455: const int end = interval.prefix + interval.index;
457: for(int i = interval.index; i < end; ++i) {
458: indices[(*indx)++] = i;
459: }
460: };
461: void expandInterval(const index_type& interval, const int orientation, PetscInt indices[], PetscInt *indx) {
462: if (orientation >= 0) {
463: for(int i = 0; i < interval.prefix; ++i) {
464: indices[(*indx)++] = interval.index + i;
465: }
466: } else {
467: for(int i = interval.prefix-1; i >= 0; --i) {
468: indices[(*indx)++] = interval.index + i;
469: }
470: }
471: for(int i = 0; i < -interval.prefix; ++i) {
472: indices[(*indx)++] = -1;
473: }
474: };
475: void expandIntervals(Obj<oIndexArray> intervals, PetscInt *indices) {
476: int k = 0;
478: for(typename oIndexArray::iterator i_iter = intervals->begin(); i_iter != intervals->end(); ++i_iter) {
479: this->expandInterval(i_iter->first, i_iter->second, indices, &k);
480: }
481: }
482: template<typename Section_>
483: const indices_type getIndicesRaw(const Obj<Section_>& section, const point_type& p) {
484: int *indexArray = NULL;
485: int size = 0;
487: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
488: typename oConeArray::iterator begin = closure->begin();
489: typename oConeArray::iterator end = closure->end();
491: for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
492: size += section->getFiberDimension(p_iter->first);
493: }
494: indexArray = this->getIndexArray(size);
495: int k = 0;
496: for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
497: section->getIndicesRaw(p_iter->first, section->getIndex(p_iter->first), indexArray, &k, p_iter->second);
498: }
499: return indices_type(indexArray, size);
500: }
501: template<typename Section_>
502: const indices_type getIndices(const Obj<Section_>& section, const point_type& p, const int level = -1) {
503: int *indexArray = NULL;
504: int size = 0;
506: if (level == 0) {
507: size += section->getFiberDimension(p);
508: indexArray = this->getIndexArray(size);
509: int k = 0;
511: section->getIndices(p, indexArray, &k);
512: } else if ((level == 1) || (this->height() == 1)) {
513: const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
514: typename sieve_type::coneSequence::iterator end = cone->end();
516: size += section->getFiberDimension(p);
517: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
518: size += section->getFiberDimension(*p_iter);
519: }
520: indexArray = this->getIndexArray(size);
521: int k = 0;
523: section->getIndices(p, indexArray, &k);
524: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
525: section->getIndices(*p_iter, indexArray, &k);
526: }
527: } else if (level == -1) {
528: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
529: typename oConeArray::iterator begin = closure->begin();
530: typename oConeArray::iterator end = closure->end();
532: for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
533: size += section->getFiberDimension(p_iter->first);
534: }
535: indexArray = this->getIndexArray(size);
536: int k = 0;
537: for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
538: section->getIndices(p_iter->first, indexArray, &k, p_iter->second);
539: }
540: } else {
541: throw ALE::Exception("Bundle has not yet implemented getIndices() for an arbitrary level");
542: }
543: if (this->debug()) {
544: for(int i = 0; i < size; ++i) {
545: printf("[%d]index %d: %d\n", this->commRank(), i, indexArray[i]);
546: }
547: }
548: return indices_type(indexArray, size);
549: }
550: template<typename Section_, typename Numbering>
551: const indices_type getIndices(const Obj<Section_>& section, const point_type& p, const Obj<Numbering>& numbering, const int level = -1) {
552: int *indexArray = NULL;
553: int size = 0;
555: if (level == 0) {
556: size += section->getFiberDimension(p);
557: indexArray = this->getIndexArray(size);
558: int k = 0;
560: section->getIndices(p, numbering, indexArray, &k);
561: } else if ((level == 1) || (this->height() == 1)) {
562: const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
563: typename sieve_type::coneSequence::iterator end = cone->end();
565: size += section->getFiberDimension(p);
566: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
567: size += section->getFiberDimension(*p_iter);
568: }
569: indexArray = this->getIndexArray(size);
570: int k = 0;
572: section->getIndices(p, numbering, indexArray, &k);
573: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
574: section->getIndices(*p_iter, numbering, indexArray, &k);
575: }
576: } else if (level == -1) {
577: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
578: typename oConeArray::iterator end = closure->end();
580: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
581: size += section->getFiberDimension(p_iter->first);
582: }
583: indexArray = this->getIndexArray(size);
584: int k = 0;
585: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
586: section->getIndices(p_iter->first, numbering, indexArray, &k, p_iter->second);
587: }
588: } else {
589: throw ALE::Exception("Bundle has not yet implemented getIndices() for an arbitrary level");
590: }
591: return indices_type(indexArray, size);
592: }
593: public: // Retrieval traversal
594: // Return the values for the closure of this point
595: // use a smart pointer?
596: template<typename Section_>
597: const typename Section_::value_type *restrictClosure(const Obj<Section_>& section, const point_type& p) {
598: const int size = this->sizeWithBC(section, p);
599: return this->restrictClosure(section, p, section->getRawArray(size), size);
600: }
601: template<typename Section_>
602: const typename Section_::value_type *restrictClosure(const Obj<Section_>& section, const point_type& p, typename Section_::value_type *values, const int valuesSize) {
603: const int size = this->sizeWithBC(section, p);
604: int j = -1;
605: if (valuesSize < size) throw ALE::Exception("Input array too small");
607: // We could actually ask for the height of the individual point
608: if (this->height() < 2) {
609: const int& dim = section->getFiberDimension(p);
610: const typename Section_::value_type *array = section->restrictPoint(p);
612: for(int i = 0; i < dim; ++i) {
613: values[++j] = array[i];
614: }
615: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
616: typename sieve_type::coneSequence::iterator end = cone->end();
618: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
619: const int& dim = section->getFiberDimension(*p_iter);
621: array = section->restrictPoint(*p_iter);
622: for(int i = 0; i < dim; ++i) {
623: values[++j] = array[i];
624: }
625: }
626: } else {
627: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
628: typename oConeArray::iterator end = closure->end();
630: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
631: const typename Section_::value_type *array = section->restrictPoint(p_iter->first);
632: const int& dim = section->getFiberDimension(p_iter->first);
634: if (p_iter->second >= 0) {
635: for(int i = 0; i < dim; ++i) {
636: values[++j] = array[i];
637: }
638: } else {
639: for(int i = dim-1; i >= 0; --i) {
640: values[++j] = array[i];
641: }
642: }
643: }
644: }
645: if (j != size-1) {
646: ostringstream txt;
648: txt << "Invalid restrict to point " << p << std::endl;
649: txt << " j " << j << " should be " << (size-1) << std::endl;
650: std::cout << txt.str();
651: throw ALE::Exception(txt.str().c_str());
652: }
653: return values;
654: }
655: template<typename Section_>
656: const typename Section_::value_type *restrictNew(const Obj<Section_>& section, const point_type& p) {
657: const int size = this->sizeWithBC(section, p);
658: return this->restrictNew(section, p, section->getRawArray(size), size);
659: }
660: template<typename Section_>
661: const typename Section_::value_type *restrictNew(const Obj<Section_>& section, const point_type& p, typename Section_::value_type *values, const int valuesSize) {
662: const int size = this->sizeWithBC(section, p);
663: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
664: typename oConeArray::iterator end = closure->end();
665: int j = -1;
666: if (valuesSize < size) throw ALE::Exception("Input array too small");
668: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
669: const typename Section_::value_type *array = section->restrictPoint(p_iter->first);
671: if (p_iter->second >= 0) {
672: const int& dim = section->getFiberDimension(p_iter->first);
674: for(int i = 0; i < dim; ++i) {
675: values[++j] = array[i];
676: }
677: } else {
678: int offset = 0;
680: for(int space = 0; space < section->getNumSpaces(); ++space) {
681: const int& dim = section->getFiberDimension(p_iter->first, space);
683: for(int i = dim-1; i >= 0; --i) {
684: values[++j] = array[i+offset];
685: }
686: offset += dim;
687: }
688: }
689: }
690: if (j != size-1) {
691: ostringstream txt;
693: txt << "Invalid restrict to point " << p << std::endl;
694: txt << " j " << j << " should be " << (size-1) << std::endl;
695: std::cout << txt.str();
696: throw ALE::Exception(txt.str().c_str());
697: }
698: return values;
699: }
700: template<typename Section_>
701: void update(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
702: int j = 0;
704: if (this->height() < 2) {
705: section->updatePoint(p, &v[j]);
706: j += section->getFiberDimension(p);
707: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
709: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
710: section->updatePoint(*p_iter, &v[j]);
711: j += section->getFiberDimension(*p_iter);
712: }
713: } else {
714: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
715: typename oConeArray::iterator end = closure->end();
717: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
718: section->updatePoint(p_iter->first, &v[j], p_iter->second);
719: j += section->getFiberDimension(p_iter->first);
720: }
721: }
722: }
723: template<typename Section_>
724: void updateAdd(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
725: int j = 0;
727: if (this->height() < 2) {
728: section->updateAddPoint(p, &v[j]);
729: j += section->getFiberDimension(p);
730: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
732: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
733: section->updateAddPoint(*p_iter, &v[j]);
734: j += section->getFiberDimension(*p_iter);
735: }
736: } else {
737: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
738: typename oConeArray::iterator end = closure->end();
740: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
741: section->updateAddPoint(p_iter->first, &v[j], p_iter->second);
742: j += section->getFiberDimension(p_iter->first);
743: }
744: }
745: }
746: template<typename Section_>
747: void updateBC(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
748: int j = 0;
750: if (this->height() < 2) {
751: section->updatePointBC(p, &v[j]);
752: j += section->getFiberDimension(p);
753: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
755: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
756: section->updatePointBC(*p_iter, &v[j]);
757: j += section->getFiberDimension(*p_iter);
758: }
759: } else {
760: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
761: typename oConeArray::iterator end = closure->end();
763: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
764: section->updatePointBC(p_iter->first, &v[j], p_iter->second);
765: j += section->getFiberDimension(p_iter->first);
766: }
767: }
768: }
769: template<typename Section_>
770: void updateAll(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
771: int j = 0;
773: if (this->height() < 2) {
774: section->updatePointAll(p, &v[j]);
775: j += section->getFiberDimension(p);
776: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
778: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
779: section->updatePointAll(*p_iter, &v[j]);
780: j += section->getFiberDimension(*p_iter);
781: }
782: } else {
783: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
784: typename oConeArray::iterator end = closure->end();
786: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
787: section->updatePointAll(p_iter->first, &v[j], p_iter->second);
788: j += section->getFiberDimension(p_iter->first);
789: }
790: }
791: }
792: template<typename Section_>
793: void updateAllAdd(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
794: int j = 0;
796: if (this->height() < 2) {
797: section->updatePointAllAdd(p, &v[j]);
798: j += section->getFiberDimension(p);
799: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
801: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
802: section->updatePointAllAdd(*p_iter, &v[j]);
803: j += section->getFiberDimension(*p_iter);
804: }
805: } else {
806: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
807: typename oConeArray::iterator end = closure->end();
809: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
810: section->updatePointAllAdd(p_iter->first, &v[j], p_iter->second);
811: j += section->getFiberDimension(p_iter->first);
812: }
813: }
814: }
815: public: // Optimization
816: // Calculate a custom atlas for the given traversal
817: // This returns the tag value assigned to the traversal
818: template<typename Section_, typename Sequence_>
819: int calculateCustomAtlas(const Obj<Section_>& section, const Obj<Sequence_>& points) {
820: const typename Sequence_::iterator begin = points->begin();
821: const typename Sequence_::iterator end = points->end();
822: const int num = points->size();
823: int *rOffsets = new int[num+1];
824: int *rIndices;
825: int *uOffsets = new int[num+1];
826: int *uIndices;
827: int p;
829: p = 0;
830: rOffsets[p] = 0;
831: uOffsets[p] = 0;
832: for(typename Sequence_::iterator p_iter = begin; p_iter != end; ++p_iter, ++p) {
833: rOffsets[p+1] = rOffsets[p] + this->sizeWithBC(section, *p_iter);
834: uOffsets[p+1] = rOffsets[p+1];
835: //uOffsets[p+1] = uOffsets[p] + this->size(section, *p_iter);
836: }
837: rIndices = new int[rOffsets[p]];
838: uIndices = new int[uOffsets[p]];
839: p = 0;
840: for(typename Sequence_::iterator p_iter = begin; p_iter != end; ++p_iter, ++p) {
841: const indices_type rIdx = this->getIndicesRaw(section, *p_iter);
842: for(int i = 0, k = rOffsets[p]; k < rOffsets[p+1]; ++i, ++k) rIndices[k] = rIdx.first[i];
844: const indices_type uIdx = this->getIndices(section, *p_iter);
845: for(int i = 0, k = uOffsets[p]; k < uOffsets[p+1]; ++i, ++k) uIndices[k] = uIdx.first[i];
846: }
847: return section->setCustomAtlas(rOffsets, rIndices, uOffsets, uIndices);
848: }
849: template<typename Section_>
850: const typename Section_::value_type *restrictClosure(const Obj<Section_>& section, const int tag, const int p) {
851: const int *offsets, *indices;
853: section->getCustomRestrictAtlas(tag, &offsets, &indices);
854: const int size = offsets[p+1] - offsets[p];
855: return this->restrictClosure(section, tag, p, section->getRawArray(size), offsets, indices);
856: }
857: template<typename Section_>
858: const typename Section_::value_type *restrictClosure(const Obj<Section_>& section, const int tag, const int p, typename Section_::value_type *values, const int valuesSize) {
859: const int *offsets, *indices;
861: section->getCustomRestrictAtlas(tag, &offsets, &indices);
862: const int size = offsets[p+1] - offsets[p];
863: if (valuesSize < size) {throw ALE::Exception("Input array too small");}
864: return this->restrictClosure(section, tag, p, values, offsets, indices);
865: }
866: template<typename Section_>
867: const typename Section_::value_type *restrictClosure(const Obj<Section_>& section, const int tag, const int p, typename Section_::value_type *values, const int offsets[], const int indices[]) {
868: const typename Section_::value_type *array = section->restrictSpace();
870: const int size = offsets[p+1] - offsets[p];
871: for(int j = 0, k = offsets[p]; j < size; ++j, ++k) {
872: values[j] = array[indices[k]];
873: }
874: return values;
875: }
876: template<typename Section_>
877: void updateAdd(const Obj<Section_>& section, const int tag, const int p, const typename Section_::value_type values[]) {
878: typename Section_::value_type *array = (typename Section_::value_type *) section->restrictSpace();
879: const int *offsets, *indices;
881: section->getCustomUpdateAtlas(tag, &offsets, &indices);
882: const int size = offsets[p+1] - offsets[p];
883: for(int j = 0, k = offsets[p]; j < size; ++j, ++k) {
884: if (indices[k] < 0) continue;
885: array[indices[k]] += values[j];
886: }
887: }
888: public: // Allocation
889: template<typename Section_>
890: void allocate(const Obj<Section_>& section, const Obj<send_overlap_type>& sendOverlap = NULL) {
891: bool doGhosts = !sendOverlap.isNull();
893: this->_factory->orderPatch(section, this->getSieve(), sendOverlap);
894: if (doGhosts) {
895: if (this->_debug > 1) {std::cout << "Ordering patch for ghosts" << std::endl;}
896: const typename Section_::chart_type& points = section->getChart();
897: typename Section_::index_type::index_type offset = 0;
899: for(typename Section_::chart_type::const_iterator point = points.begin(); point != points.end(); ++point) {
900: const typename Section_::index_type& idx = section->getIndex(*point);
902: offset = std::max(offset, idx.index + std::abs(idx.prefix));
903: }
904: this->_factory->orderPatch(section, this->getSieve(), NULL, offset);
905: if (offset != section->sizeWithBC()) throw ALE::Exception("Inconsistent array sizes in section");
906: }
907: section->allocateStorage();
908: }
909: template<typename Section_>
910: void reallocate(const Obj<Section_>& section) {
911: if (section->getNewAtlas().isNull()) return;
912: // Since copy() preserves offsets, we must reinitialize them before ordering
913: const Obj<typename Section_::atlas_type> atlas = section->getAtlas();
914: const Obj<typename Section_::atlas_type>& newAtlas = section->getNewAtlas();
915: const typename Section_::atlas_type::chart_type& chart = newAtlas->getChart();
916: const typename Section_::atlas_type::chart_type& oldChart = atlas->getChart();
917: int newSize = 0;
918: typename Section_::index_type defaultIdx(0, -1);
920: for(typename Section_::atlas_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
921: defaultIdx.prefix = newAtlas->restrictPoint(*c_iter)[0].prefix;
922: newAtlas->updatePoint(*c_iter, &defaultIdx);
923: newSize += defaultIdx.prefix;
924: }
925: section->setAtlas(newAtlas);
926: this->_factory->orderPatch(section, this->getSieve());
927: // Copy over existing values
928: typedef typename alloc_type::template rebind<typename Section_::value_type>::other value_alloc_type;
929: value_alloc_type value_allocator;
930: typename Section_::value_type *newArray = value_allocator.allocate(newSize);
931: for(int i = 0; i < newSize; ++i) {value_allocator.construct(newArray+i, typename Section_::value_type());}
932: ///typename Section_::value_type *newArray = new typename Section_::value_type[newSize];
933: const typename Section_::value_type *array = section->restrictSpace();
935: for(typename Section_::atlas_type::chart_type::const_iterator c_iter = oldChart.begin(); c_iter != oldChart.end(); ++c_iter) {
936: const int& dim = section->getFiberDimension(*c_iter);
937: const int& offset = atlas->restrictPoint(*c_iter)->index;
938: const int& newOffset = newAtlas->restrictPoint(*c_iter)->index;
940: for(int i = 0; i < dim; ++i) {
941: newArray[newOffset+i] = array[offset+i];
942: }
943: }
944: section->replaceStorage(newArray);
945: }
946: public: // Overlap
947: template<typename Sequence>
948: void constructOverlap(const Obj<Sequence>& points, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap) {
949: point_type *sendBuf = new point_type[points->size()];
950: int size = 0;
951: for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
952: sendBuf[size++] = *l_iter;
953: }
954: int *sizes = new int[this->commSize()]; // The number of points coming from each process
955: int *offsets = new int[this->commSize()+1]; // Prefix sums for sizes
956: int *oldOffs = new int[this->commSize()+1]; // Temporary storage
957: point_type *remotePoints = NULL; // The points from each process
958: int *remoteRanks = NULL; // The rank and number of overlap points of each process that overlaps another
960: // Change to Allgather() for the correct binning algorithm
961: MPI_Gather(&size, 1, MPI_INT, sizes, 1, MPI_INT, 0, this->comm());
962: if (this->commRank() == 0) {
963: offsets[0] = 0;
964: for(int p = 1; p <= this->commSize(); p++) {
965: offsets[p] = offsets[p-1] + sizes[p-1];
966: }
967: remotePoints = new point_type[offsets[this->commSize()]];
968: }
969: MPI_Gatherv(sendBuf, size, MPI_INT, remotePoints, sizes, offsets, MPI_INT, 0, this->comm());
970: delete [] sendBuf;
971: std::map<int, std::map<int, std::set<point_type> > > overlapInfo; // Maps (p,q) to their set of overlap points
973: if (this->commRank() == 0) {
974: for(int p = 0; p < this->commSize(); p++) {
975: std::sort(&remotePoints[offsets[p]], &remotePoints[offsets[p+1]]);
976: }
977: for(int p = 0; p <= this->commSize(); p++) {
978: oldOffs[p] = offsets[p];
979: }
980: for(int p = 0; p < this->commSize(); p++) {
981: for(int q = p+1; q < this->commSize(); q++) {
982: std::set_intersection(&remotePoints[oldOffs[p]], &remotePoints[oldOffs[p+1]],
983: &remotePoints[oldOffs[q]], &remotePoints[oldOffs[q+1]],
984: std::insert_iterator<std::set<point_type> >(overlapInfo[p][q], overlapInfo[p][q].begin()));
985: overlapInfo[q][p] = overlapInfo[p][q];
986: }
987: sizes[p] = overlapInfo[p].size()*2;
988: offsets[p+1] = offsets[p] + sizes[p];
989: }
990: remoteRanks = new int[offsets[this->commSize()]];
991: int k = 0;
992: for(int p = 0; p < this->commSize(); p++) {
993: for(typename std::map<int, std::set<point_type> >::iterator r_iter = overlapInfo[p].begin(); r_iter != overlapInfo[p].end(); ++r_iter) {
994: remoteRanks[k*2] = r_iter->first;
995: remoteRanks[k*2+1] = r_iter->second.size();
996: k++;
997: }
998: }
999: }
1000: int numOverlaps; // The number of processes overlapping this process
1001: MPI_Scatter(sizes, 1, MPI_INT, &numOverlaps, 1, MPI_INT, 0, this->comm());
1002: int *overlapRanks = new int[numOverlaps]; // The rank and overlap size for each overlapping process
1003: MPI_Scatterv(remoteRanks, sizes, offsets, MPI_INT, overlapRanks, numOverlaps, MPI_INT, 0, this->comm());
1004: point_type *sendPoints = NULL; // The points to send to each process
1005: if (this->commRank() == 0) {
1006: for(int p = 0, k = 0; p < this->commSize(); p++) {
1007: sizes[p] = 0;
1008: for(int r = 0; r < (int) overlapInfo[p].size(); r++) {
1009: sizes[p] += remoteRanks[k*2+1];
1010: k++;
1011: }
1012: offsets[p+1] = offsets[p] + sizes[p];
1013: }
1014: sendPoints = new point_type[offsets[this->commSize()]];
1015: for(int p = 0, k = 0; p < this->commSize(); p++) {
1016: for(typename std::map<int, std::set<point_type> >::iterator r_iter = overlapInfo[p].begin(); r_iter != overlapInfo[p].end(); ++r_iter) {
1017: int rank = r_iter->first;
1018: for(typename std::set<point_type>::iterator p_iter = (overlapInfo[p][rank]).begin(); p_iter != (overlapInfo[p][rank]).end(); ++p_iter) {
1019: sendPoints[k++] = *p_iter;
1020: }
1021: }
1022: }
1023: }
1024: int numOverlapPoints = 0;
1025: for(int r = 0; r < numOverlaps/2; r++) {
1026: numOverlapPoints += overlapRanks[r*2+1];
1027: }
1028: point_type *overlapPoints = new point_type[numOverlapPoints];
1029: MPI_Scatterv(sendPoints, sizes, offsets, MPI_INT, overlapPoints, numOverlapPoints, MPI_INT, 0, this->comm());
1031: for(int r = 0, k = 0; r < numOverlaps/2; r++) {
1032: int rank = overlapRanks[r*2];
1034: for(int p = 0; p < overlapRanks[r*2+1]; p++) {
1035: point_type point = overlapPoints[k++];
1037: sendOverlap->addArrow(point, rank, point);
1038: recvOverlap->addArrow(rank, point, point);
1039: }
1040: }
1042: delete [] overlapPoints;
1043: delete [] overlapRanks;
1044: delete [] sizes;
1045: delete [] offsets;
1046: delete [] oldOffs;
1047: if (this->commRank() == 0) {
1048: delete [] remoteRanks;
1049: delete [] remotePoints;
1050: delete [] sendPoints;
1051: }
1052: }
1053: void constructOverlap() {
1054: if (this->_calculatedOverlap) return;
1055: this->constructOverlap(this->getSieve()->base(), this->getSendOverlap(), this->getRecvOverlap());
1056: this->constructOverlap(this->getSieve()->cap(), this->getSendOverlap(), this->getRecvOverlap());
1057: if (this->debug()) {
1058: this->_sendOverlap->view("Send overlap");
1059: this->_recvOverlap->view("Receive overlap");
1060: }
1061: this->_calculatedOverlap = true;
1062: }
1063: };
1064: class BoundaryCondition : public ALE::ParallelObject {
1065: public:
1066: typedef double (*function_type)(const PetscReal []);
1067: typedef double (*integrator_type)(const PetscReal [], const PetscReal [], const int, function_type);
1068: protected:
1069: std::string _labelName;
1070: int _marker;
1071: function_type _func;
1072: integrator_type _integrator;
1073: public:
1074: BoundaryCondition(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {};
1075: ~BoundaryCondition() {};
1076: public:
1077: const std::string& getLabelName() const {return this->_labelName;};
1078: void setLabelName(const std::string& name) {this->_labelName = name;};
1079: int getMarker() const {return this->_marker;};
1080: void setMarker(const int marker) {this->_marker = marker;};
1081: function_type getFunction() const {return this->_func;};
1082: void setFunction(function_type func) {this->_func = func;};
1083: integrator_type getDualIntegrator() const {return this->_integrator;};
1084: void setDualIntegrator(integrator_type integrator) {this->_integrator = integrator;};
1085: public:
1086: PetscReal evaluate(const PetscReal coords[]) const {return this->_func(coords);};
1087: PetscReal integrateDual(const PetscReal v0[], const PetscReal J[], const int dualIndex) const {return this->_integrator(v0, J, dualIndex, this->_func);};
1088: };
1089: class Discretization : public ALE::ParallelObject {
1090: typedef std::map<std::string, Obj<BoundaryCondition> > boundaryConditions_type;
1091: protected:
1092: boundaryConditions_type _boundaryConditions;
1093: Obj<BoundaryCondition> _exactSolution;
1094: std::map<int,int> _dim2dof;
1095: std::map<int,int> _dim2class;
1096: int _quadSize;
1097: const PetscReal *_points;
1098: const PetscReal *_weights;
1099: int _basisSize;
1100: const PetscReal *_basis;
1101: const PetscReal *_basisDer;
1102: const int *_indices;
1103: std::map<int, const int *> _exclusionIndices;
1104: public:
1105: Discretization(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug), _quadSize(0), _points(NULL), _weights(NULL), _basisSize(0), _basis(NULL), _basisDer(NULL), _indices(NULL) {};
1106: virtual ~Discretization() {
1107: if (this->_indices) {delete [] this->_indices;}
1108: for(std::map<int, const int *>::iterator i_iter = _exclusionIndices.begin(); i_iter != _exclusionIndices.end(); ++i_iter) {
1109: delete [] i_iter->second;
1110: }
1111: };
1112: public:
1113: bool hasBoundaryCondition() {return (this->_boundaryConditions.find("default") != this->_boundaryConditions.end());};
1114: const Obj<BoundaryCondition>& getBoundaryCondition() {return this->getBoundaryCondition("default");};
1115: void setBoundaryCondition(const Obj<BoundaryCondition>& boundaryCondition) {this->setBoundaryCondition("default", boundaryCondition);};
1116: const Obj<BoundaryCondition>& getBoundaryCondition(const std::string& name) {return this->_boundaryConditions[name];};
1117: void setBoundaryCondition(const std::string& name, const Obj<BoundaryCondition>& boundaryCondition) {this->_boundaryConditions[name] = boundaryCondition;};
1118: Obj<std::set<std::string> > getBoundaryConditions() const {
1119: Obj<std::set<std::string> > names = std::set<std::string>();
1121: for(boundaryConditions_type::const_iterator d_iter = this->_boundaryConditions.begin(); d_iter != this->_boundaryConditions.end(); ++d_iter) {
1122: names->insert(d_iter->first);
1123: }
1124: return names;
1125: };
1126: const Obj<BoundaryCondition>& getExactSolution() {return this->_exactSolution;};
1127: void setExactSolution(const Obj<BoundaryCondition>& exactSolution) {this->_exactSolution = exactSolution;};
1128: int getQuadratureSize() {return this->_quadSize;};
1129: void setQuadratureSize(const int size) {this->_quadSize = size;};
1130: const PetscReal *getQuadraturePoints() {return this->_points;};
1131: void setQuadraturePoints(const PetscReal *points) {this->_points = points;};
1132: const PetscReal *getQuadratureWeights() {return this->_weights;};
1133: void setQuadratureWeights(const PetscReal *weights) {this->_weights = weights;};
1134: int getBasisSize() {return this->_basisSize;};
1135: void setBasisSize(const int size) {this->_basisSize = size;};
1136: const PetscReal *getBasis() {return this->_basis;};
1137: void setBasis(const PetscReal *basis) {this->_basis = basis;};
1138: const PetscReal *getBasisDerivatives() {return this->_basisDer;};
1139: void setBasisDerivatives(const PetscReal *basisDer) {this->_basisDer = basisDer;};
1140: int getNumDof(const int dim) {return this->_dim2dof[dim];};
1141: void setNumDof(const int dim, const int numDof) {this->_dim2dof[dim] = numDof;};
1142: int getDofClass(const int dim) {return this->_dim2class[dim];};
1143: void setDofClass(const int dim, const int dofClass) {this->_dim2class[dim] = dofClass;};
1144: public:
1145: const int *getIndices() {return this->_indices;};
1146: const int *getIndices(const int marker) {
1147: if (!marker) return this->getIndices();
1148: return this->_exclusionIndices[marker];
1149: };
1150: void setIndices(const int *indices) {this->_indices = indices;};
1151: void setIndices(const int *indices, const int marker) {
1152: if (!marker) this->_indices = indices;
1153: this->_exclusionIndices[marker] = indices;
1154: };
1155: template<typename Bundle>
1156: int sizeV(Bundle& mesh) {
1157: typedef typename ISieveVisitor::PointRetriever<typename Bundle::sieve_type> Visitor;
1158: Visitor pV((int) pow((double) mesh.getSieve()->getMaxConeSize(), mesh.depth())+1, true);
1159: ISieveTraversal<typename Bundle::sieve_type>::orientedClosure(*mesh.getSieve(), *mesh.heightStratum(0)->begin(), pV);
1160: const typename Visitor::point_type *oPoints = pV.getPoints();
1161: const int oSize = pV.getSize();
1162: int size = 0;
1164: for(int cl = 0; cl < oSize; ++cl) {
1165: size += this->_dim2dof[mesh.depth(oPoints[cl])];
1166: }
1167: return size;
1168: }
1169: template<typename Bundle>
1170: int size(const Obj<Bundle>& mesh) {
1171: const Obj<typename Bundle::label_sequence>& cells = mesh->heightStratum(0);
1172: const Obj<typename Bundle::coneArray> closure = ALE::SieveAlg<Bundle>::closure(mesh, *cells->begin());
1173: const typename Bundle::coneArray::iterator end = closure->end();
1174: int size = 0;
1176: for(typename Bundle::coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
1177: size += this->_dim2dof[mesh->depth(*cl_iter)];
1178: }
1179: return size;
1180: }
1181: };
1182: }
1184: namespace ALE {
1185: template<typename Sieve_,
1186: typename RealSection_ = Section<typename Sieve_::point_type, double>,
1187: typename IntSection_ = Section<typename Sieve_::point_type, int>,
1188: typename Label_ = LabelSifter<int, typename Sieve_::point_type>,
1189: typename ArrowSection_ = UniformSection<MinimalArrow<typename Sieve_::point_type, typename Sieve_::point_type>, int> >
1190: class IBundle : public ALE::ParallelObject {
1191: public:
1192: typedef Sieve_ sieve_type;
1193: typedef RealSection_ real_section_type;
1194: typedef IntSection_ int_section_type;
1195: typedef ArrowSection_ arrow_section_type;
1196: typedef IBundle<Sieve_,RealSection_,IntSection_,Label_,ArrowSection_> this_type;
1197: typedef typename sieve_type::point_type point_type;
1198: typedef malloc_allocator<point_type> alloc_type;
1199: typedef Label_ label_type;
1200: typedef typename std::map<const std::string, Obj<label_type> > labels_type;
1201: typedef typename label_type::supportSequence label_sequence;
1202: typedef std::map<std::string, Obj<arrow_section_type> > arrow_sections_type;
1203: typedef std::map<std::string, Obj<real_section_type> > real_sections_type;
1204: typedef std::map<std::string, Obj<int_section_type> > int_sections_type;
1205: typedef ALE::Point index_type;
1206: typedef std::pair<index_type, int> oIndex_type;
1207: typedef std::vector<oIndex_type> oIndexArray;
1208: typedef std::pair<int *, int> indices_type;
1209: typedef NumberingFactory<this_type> MeshNumberingFactory;
1210: typedef typename ALE::Partitioner<>::part_type rank_type;
1211: #define USE_NEW_OVERLAP
1212: #ifdef USE_NEW_OVERLAP
1213: typedef typename PETSc::SendOverlap<point_type,rank_type> send_overlap_type;
1214: typedef typename PETSc::RecvOverlap<point_type,rank_type> recv_overlap_type;
1215: #else
1216: typedef typename ALE::Sifter<point_type,rank_type,point_type> send_overlap_type;
1217: typedef typename ALE::Sifter<rank_type,point_type,point_type> recv_overlap_type;
1218: #endif
1219: typedef typename MeshNumberingFactory::numbering_type numbering_type;
1220: typedef typename MeshNumberingFactory::order_type order_type;
1221: typedef std::map<point_type, point_type> renumbering_type;
1222: // These should go away
1223: typedef typename ALE::SieveAlg<this_type> sieve_alg_type;
1224: typedef typename sieve_alg_type::coneArray coneArray;
1225: typedef typename sieve_alg_type::orientedConeArray oConeArray;
1226: typedef typename sieve_alg_type::supportArray supportArray;
1227: public:
1228: class LabelVisitor {
1229: protected:
1230: label_type& label;
1231: int defaultValue;
1232: int value;
1233: public:
1234: LabelVisitor(label_type& l, const int defValue) : label(l), defaultValue(defValue), value(defValue) {};
1235: int getLabelValue(const point_type& point) const {
1236: const Obj<typename label_type::coneSequence>& cone = this->label.cone(point);
1238: if (cone->size() == 0) return this->defaultValue;
1239: return *cone->begin();
1240: };
1241: void setLabelValue(const point_type& point, const int value) {
1242: this->label.setCone(value, point);
1243: };
1244: int getValue() const {return this->value;};
1245: };
1246: class MaxConeVisitor : public LabelVisitor {
1247: public:
1248: MaxConeVisitor(label_type& l, const int defValue) : LabelVisitor(l, defValue) {};
1249: void visitPoint(const typename sieve_type::point_type& point) {};
1250: void visitArrow(const typename sieve_type::arrow_type& arrow) {
1251: this->value = std::max(this->value, this->getLabelValue(arrow.source));
1252: };
1253: };
1254: class MaxSupportVisitor : public LabelVisitor {
1255: public:
1256: MaxSupportVisitor(label_type& l, const int defValue) : LabelVisitor(l, defValue) {};
1257: void visitPoint(const typename sieve_type::point_type& point) {};
1258: void visitArrow(const typename sieve_type::arrow_type& arrow) {
1259: this->value = std::max(this->value, this->getLabelValue(arrow.target));
1260: };
1261: };
1262: class BinaryStratifyVisitor {
1263: protected:
1264: label_type& height;
1265: label_type& depth;
1266: bool isLeaf;
1267: public:
1268: BinaryStratifyVisitor(label_type& h, label_type& d, bool isLeaf) : height(h), depth(d), isLeaf(isLeaf) {};
1269: void visitPoint(const typename sieve_type::point_type& point) {
1270: if (isLeaf) {
1271: height.setCone(0, point);
1272: depth.setCone(1, point);
1273: } else {
1274: height.setCone(1, point);
1275: depth.setCone(0, point);
1276: }
1277: };
1278: };
1279: class HeightVisitor {
1280: protected:
1281: const sieve_type& sieve;
1282: label_type& height;
1283: int maxHeight;
1284: std::set<typename sieve_type::point_type> modifiedPoints;
1285: public:
1286: HeightVisitor(const sieve_type& s, label_type& h) : sieve(s), height(h), maxHeight(0) {};
1287: void visitPoint(const typename sieve_type::point_type& point) {
1288: MaxSupportVisitor v(height, -1);
1290: // Compute the max height of the points in the support of p, and add 1
1291: this->sieve.support(point, v);
1292: const int h0 = v.getLabelValue(point);
1293: const int h1 = v.getValue() + 1;
1295: if(h1 != h0) {
1296: v.setLabelValue(point, h1);
1297: if (h1 > this->maxHeight) this->maxHeight = h1;
1298: this->modifiedPoints.insert(point);
1299: }
1300: };
1301: void visitArrow(const typename sieve_type::arrow_type& arrow) {
1302: this->visitPoint(arrow.source);
1303: };
1304: int getMaxHeight() const {return this->maxHeight;};
1305: bool isModified() const {return this->modifiedPoints.size() > 0;};
1306: const std::set<typename sieve_type::point_type>& getModifiedPoints() const {return this->modifiedPoints;};
1307: void clear() {this->modifiedPoints.clear();};
1308: };
1309: class DepthVisitor {
1310: public:
1311: typedef typename sieve_type::point_type point_type;
1312: protected:
1313: const sieve_type& sieve;
1314: label_type& depth;
1315: int maxDepth;
1316: const point_type limitPoint;
1317: std::set<point_type> modifiedPoints;
1318: public:
1319: DepthVisitor(const sieve_type& s, label_type& d) : sieve(s), depth(d), maxDepth(0), limitPoint(sieve.getChart().max()+1) {};
1320: DepthVisitor(const sieve_type& s, const point_type& limit, label_type& d) : sieve(s), depth(d), maxDepth(-1), limitPoint(limit) {};
1321: void visitPoint(const point_type& point) {
1322: if (point >= this->limitPoint) return;
1323: MaxConeVisitor v(depth, -1);
1325: // Compute the max height of the points in the support of p, and add 1
1326: this->sieve.cone(point, v);
1327: const int d0 = v.getLabelValue(point);
1328: const int d1 = v.getValue() + 1;
1330: if(d1 != d0) {
1331: v.setLabelValue(point, d1);
1332: if (d1 > this->maxDepth) this->maxDepth = d1;
1333: this->modifiedPoints.insert(point);
1334: }
1335: };
1336: void visitArrow(const typename sieve_type::arrow_type& arrow) {
1337: this->visitPoint(arrow.target);
1338: };
1339: int getMaxDepth() const {return this->maxDepth;};
1340: bool isModified() const {return this->modifiedPoints.size() > 0;};
1341: const std::set<typename sieve_type::point_type>& getModifiedPoints() const {return this->modifiedPoints;};
1342: void clear() {this->modifiedPoints.clear();};
1343: };
1344: protected:
1345: Obj<sieve_type> _sieve;
1346: labels_type _labels;
1347: int _maxHeight;
1348: int _maxDepth;
1349: arrow_sections_type _arrowSections;
1350: real_sections_type _realSections;
1351: int_sections_type _intSections;
1352: Obj<oIndexArray> _indexArray;
1353: Obj<MeshNumberingFactory> _factory;
1354: bool _calculatedOverlap;
1355: Obj<send_overlap_type> _sendOverlap;
1356: Obj<recv_overlap_type> _recvOverlap;
1357: Obj<send_overlap_type> _distSendOverlap;
1358: Obj<recv_overlap_type> _distRecvOverlap;
1359: renumbering_type _renumbering;
1360: // Work space
1361: Obj<std::set<point_type> > _modifiedPoints;
1362: public:
1363: IBundle(MPI_Comm comm, int debug = 0) : ALE::ParallelObject(comm, debug), _maxHeight(-1), _maxDepth(-1) {
1364: this->_indexArray = new oIndexArray();
1365: this->_modifiedPoints = new std::set<point_type>();
1366: this->_factory = MeshNumberingFactory::singleton(this->comm(), this->debug());
1367: this->_calculatedOverlap = false;
1368: this->_sendOverlap = new send_overlap_type(this->comm(), this->debug());
1369: this->_recvOverlap = new recv_overlap_type(this->comm(), this->debug());
1370: };
1371: IBundle(const Obj<sieve_type>& sieve) : ALE::ParallelObject(sieve->comm(), sieve->debug()), _sieve(sieve), _maxHeight(-1), _maxDepth(-1) {
1372: this->_indexArray = new oIndexArray();
1373: this->_modifiedPoints = new std::set<point_type>();
1374: this->_factory = MeshNumberingFactory::singleton(this->comm(), this->debug());
1375: this->_calculatedOverlap = false;
1376: this->_sendOverlap = new send_overlap_type(this->comm(), this->debug());
1377: this->_recvOverlap = new recv_overlap_type(this->comm(), this->debug());
1378: };
1379: virtual ~IBundle() {};
1380: public: // Verifiers
1381: bool hasLabel(const std::string& name) {
1382: if (this->_labels.find(name) != this->_labels.end()) {
1383: return true;
1384: }
1385: return false;
1386: };
1387: void checkLabel(const std::string& name) {
1388: if (!this->hasLabel(name)) {
1389: ostringstream msg;
1390: msg << "Invalid label name: " << name << std::endl;
1391: throw ALE::Exception(msg.str().c_str());
1392: }
1393: };
1394: public: // Accessors
1395: const Obj<sieve_type>& getSieve() const {return this->_sieve;};
1396: void setSieve(const Obj<sieve_type>& sieve) {this->_sieve = sieve;};
1397: bool hasArrowSection(const std::string& name) const {
1398: return this->_arrowSections.find(name) != this->_arrowSections.end();
1399: };
1400: const Obj<arrow_section_type>& getArrowSection(const std::string& name) {
1401: if (!this->hasArrowSection(name)) {
1402: Obj<arrow_section_type> section = new arrow_section_type(this->comm(), this->debug());
1404: section->setName(name);
1405: if (this->_debug) {std::cout << "Creating new arrow section: " << name << std::endl;}
1406: this->_arrowSections[name] = section;
1407: }
1408: return this->_arrowSections[name];
1409: };
1410: void setArrowSection(const std::string& name, const Obj<arrow_section_type>& section) {
1411: this->_arrowSections[name] = section;
1412: };
1413: Obj<std::set<std::string> > getArrowSections() const {
1414: Obj<std::set<std::string> > names = std::set<std::string>();
1416: for(typename arrow_sections_type::const_iterator s_iter = this->_arrowSections.begin(); s_iter != this->_arrowSections.end(); ++s_iter) {
1417: names->insert(s_iter->first);
1418: }
1419: return names;
1420: };
1421: bool hasRealSection(const std::string& name) const {
1422: return this->_realSections.find(name) != this->_realSections.end();
1423: };
1424: const Obj<real_section_type>& getRealSection(const std::string& name) {
1425: if (!this->hasRealSection(name)) {
1426: Obj<real_section_type> section = new real_section_type(this->comm(), this->debug());
1428: section->setName(name);
1429: if (this->_debug) {std::cout << "Creating new real section: " << name << std::endl;}
1430: this->_realSections[name] = section;
1431: }
1432: return this->_realSections[name];
1433: };
1434: void setRealSection(const std::string& name, const Obj<real_section_type>& section) {
1435: this->_realSections[name] = section;
1436: };
1437: Obj<std::set<std::string> > getRealSections() const {
1438: Obj<std::set<std::string> > names = std::set<std::string>();
1440: for(typename real_sections_type::const_iterator s_iter = this->_realSections.begin(); s_iter != this->_realSections.end(); ++s_iter) {
1441: names->insert(s_iter->first);
1442: }
1443: return names;
1444: };
1445: bool hasIntSection(const std::string& name) const {
1446: return this->_intSections.find(name) != this->_intSections.end();
1447: };
1448: const Obj<int_section_type>& getIntSection(const std::string& name) {
1449: if (!this->hasIntSection(name)) {
1450: Obj<int_section_type> section = new int_section_type(this->comm(), this->debug());
1452: section->setName(name);
1453: if (this->_debug) {std::cout << "Creating new int section: " << name << std::endl;}
1454: this->_intSections[name] = section;
1455: }
1456: return this->_intSections[name];
1457: };
1458: void setIntSection(const std::string& name, const Obj<int_section_type>& section) {
1459: this->_intSections[name] = section;
1460: };
1461: Obj<std::set<std::string> > getIntSections() const {
1462: Obj<std::set<std::string> > names = std::set<std::string>();
1464: for(typename int_sections_type::const_iterator s_iter = this->_intSections.begin(); s_iter != this->_intSections.end(); ++s_iter) {
1465: names->insert(s_iter->first);
1466: }
1467: return names;
1468: };
1469: const Obj<MeshNumberingFactory>& getFactory() const {return this->_factory;};
1470: renumbering_type& getRenumbering() {return this->_renumbering;};
1471: public: // Labels
1472: int getValue (const Obj<label_type>& label, const point_type& point, const int defValue = 0) {
1473: const Obj<typename label_type::coneSequence>& cone = label->cone(point);
1475: if (cone->size() == 0) return defValue;
1476: return *cone->begin();
1477: };
1478: void setValue(const Obj<label_type>& label, const point_type& point, const int value) {
1479: label->setCone(value, point);
1480: };
1481: void addValue(const Obj<label_type>& label, const point_type& point, const int value) {
1482: label->addCone(value, point);
1483: };
1484: template<typename InputPoints>
1485: int getMaxValue (const Obj<label_type>& label, const Obj<InputPoints>& points, const int defValue = 0) {
1486: int maxValue = defValue;
1488: for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
1489: maxValue = std::max(maxValue, this->getValue(label, *p_iter, defValue));
1490: }
1491: return maxValue;
1492: }
1493: const Obj<label_type>& createLabel(const std::string& name) {
1494: this->_labels[name] = new label_type(this->comm(), this->debug());
1495: return this->_labels[name];
1496: };
1497: const Obj<label_type>& getLabel(const std::string& name) {
1498: this->checkLabel(name);
1499: return this->_labels[name];
1500: };
1501: void setLabel(const std::string& name, const Obj<label_type>& label) {
1502: this->_labels[name] = label;
1503: };
1504: const labels_type& getLabels() {
1505: return this->_labels;
1506: };
1507: virtual const Obj<label_sequence>& getLabelStratum(const std::string& name, int value) {
1508: this->checkLabel(name);
1509: return this->_labels[name]->support(value);
1510: };
1511: public: // Stratification
1512: void computeBinaryStratification() {
1513: const Obj<label_type>& height = this->createLabel("height");
1514: const Obj<label_type>& depth = this->createLabel("depth");
1515: BinaryStratifyVisitor l(*height, *depth, true);
1516: BinaryStratifyVisitor r(*height, *depth, false);
1518: this->_sieve->leaves(l);
1519: this->_sieve->roots(r);
1520: if (this->_sieve->numRoots()) {
1521: this->setHeight(1);
1522: this->setDepth(1);
1523: } else {
1524: this->setHeight(0);
1525: this->setDepth(0);
1526: }
1527: };
1528: void computeHeights() {
1529: const Obj<label_type>& label = this->createLabel(std::string("height"));
1530: HeightVisitor h(*this->_sieve, *label);
1532: #ifdef IMESH_NEW_LABELS
1533: label->setChart(this->getSieve()->getChart());
1534: for(point_type p = label->getChart().min(); p < label->getChart().max(); ++p) {label->setConeSize(p, 1);}
1535: if (label->getChart().size()) {label->setSupportSize(0, label->getChart().size());}
1536: label->allocate();
1537: for(point_type p = label->getChart().min(); p < label->getChart().max(); ++p) {label->setCone(-1, p);}
1538: #endif
1539: this->_sieve->leaves(h);
1540: while(h.isModified()) {
1541: // FIX: Avoid the copy here somehow by fixing the traversal
1542: std::vector<point_type> modifiedPoints(h.getModifiedPoints().begin(), h.getModifiedPoints().end());
1544: h.clear();
1545: this->_sieve->cone(modifiedPoints, h);
1546: }
1547: #ifdef IMESH_NEW_LABELS
1548: // Recalculate supportOffsets and populate support
1549: label->recalculateLabel();
1550: #endif
1551: this->_maxHeight = h.getMaxHeight();
1552: };
1553: virtual int height() const {return this->_maxHeight;};
1554: virtual void setHeight(const int height) {this->_maxHeight = height;};
1555: virtual int height(const point_type& point) {
1556: return this->getValue(this->_labels["height"], point, -1);
1557: };
1558: virtual void setHeight(const point_type& point, const int height) {
1559: return this->setValue(this->_labels["height"], point, height);
1560: };
1561: virtual const Obj<label_sequence>& heightStratum(int height) {
1562: return this->getLabelStratum("height", height);
1563: };
1564: void computeDepths() {
1565: const Obj<label_type>& label = this->createLabel(std::string("depth"));
1566: DepthVisitor d(*this->_sieve, *label);
1568: #ifdef IMESH_NEW_LABELS
1569: label->setChart(this->getSieve()->getChart());
1570: for(point_type p = label->getChart().min(); p < label->getChart().max(); ++p) {label->setConeSize(p, 1);}
1571: if (label->getChart().size()) {label->setSupportSize(0, label->getChart().size());}
1572: label->allocate();
1573: for(point_type p = label->getChart().min(); p < label->getChart().max(); ++p) {label->setCone(-1, p);}
1574: #endif
1575: this->_sieve->roots(d);
1576: while(d.isModified()) {
1577: // FIX: Avoid the copy here somehow by fixing the traversal
1578: std::vector<point_type> modifiedPoints(d.getModifiedPoints().begin(), d.getModifiedPoints().end());
1580: d.clear();
1581: this->_sieve->support(modifiedPoints, d);
1582: }
1583: #ifdef IMESH_NEW_LABELS
1584: // Recalculate supportOffsets and populate support
1585: label->recalculateLabel();
1586: #endif
1587: this->_maxDepth = d.getMaxDepth();
1588: };
1589: virtual int depth() const {return this->_maxDepth;};
1590: virtual void setDepth(const int depth) {this->_maxDepth = depth;};
1591: virtual int depth(const point_type& point) {
1592: return this->getValue(this->_labels["depth"], point, -1);
1593: };
1594: virtual void setDepth(const point_type& point, const int depth) {
1595: return this->setValue(this->_labels["depth"], point, depth);
1596: };
1597: virtual const Obj<label_sequence>& depthStratum(int depth) {
1598: return this->getLabelStratum("depth", depth);
1599: };
1602: void stratify() {
1603: ALE::LogEvent event = ALE::LogEventRegister(__FUNCT__);
1604: ALE::LogEventBegin(event);
1605: if (this->_sieve->numRoots() + this->_sieve->numLeaves() == (int) this->_sieve->getChart().size()) {
1606: this->computeBinaryStratification();
1607: } else {
1608: this->computeHeights();
1609: this->computeDepths();
1610: }
1611: ALE::LogEventEnd(event);
1612: };
1613: protected:
1614: template<typename Value>
1615: static bool lt1(const Value& a, const Value& b) {
1616: return a.first < b.first;
1617: }
1618: public: // Allocation
1619: template<typename Section_>
1620: void reallocate(const Obj<Section_>& section) {
1621: if (!section->hasNewPoints()) return;
1622: typename Section_::chart_type newChart(std::min(std::min_element(section->getNewPoints().begin(), section->getNewPoints().end(), lt1<typename Section_::newpoint_type>)->first, section->getChart().min()),
1623: std::max(std::max_element(section->getNewPoints().begin(), section->getNewPoints().end(), lt1<typename Section_::newpoint_type>)->first, section->getChart().max()-1)+1);
1624: section->reallocatePoint(newChart);
1625: }
1626: };
1627: #ifdef IMESH_NEW_LABELS
1628: template<typename Label_ = IFSieve<int> >
1629: #else
1630: template<typename IndexType, typename ScalarType, typename Label_ = LabelSifter<IndexType, IndexType> >
1631: #endif
1632: class IMesh : public IBundle<IFSieve<IndexType>, IGeneralSection<IndexType, ScalarType>, IGeneralSection<IndexType, IndexType>, Label_> {
1633: public:
1634: typedef IBundle<IFSieve<IndexType>, IGeneralSection<IndexType, ScalarType>, IGeneralSection<IndexType, IndexType>, Label_> base_type;
1635: typedef typename base_type::sieve_type sieve_type;
1636: typedef typename sieve_type::point_type point_type;
1637: typedef typename base_type::alloc_type alloc_type;
1638: typedef typename base_type::label_type label_type;
1639: typedef typename base_type::labels_type labels_type;
1640: typedef typename base_type::label_sequence label_sequence;
1641: typedef typename base_type::real_section_type real_section_type;
1642: typedef typename base_type::int_section_type int_section_type;
1643: typedef typename base_type::numbering_type numbering_type;
1644: typedef typename base_type::order_type order_type;
1645: typedef typename base_type::send_overlap_type send_overlap_type;
1646: typedef typename base_type::recv_overlap_type recv_overlap_type;
1647: typedef std::set<std::string> names_type;
1648: typedef std::vector<typename PETSc::Point<3> > holes_type;
1649: typedef std::map<std::string, Obj<Discretization> > discretizations_type;
1650: protected:
1651: int _dim;
1652: bool _calculatedOverlap;
1653: Obj<send_overlap_type> _sendOverlap;
1654: Obj<recv_overlap_type> _recvOverlap;
1655: std::map<int,double> _periodicity;
1656: holes_type _holes;
1657: discretizations_type _discretizations;
1658: int _maxDof;
1659: public:
1660: IMesh(MPI_Comm comm, int dim, int debug = 0) : base_type(comm, debug), _dim(dim) {
1661: this->_calculatedOverlap = false;
1662: this->_sendOverlap = new send_overlap_type(comm, debug);
1663: this->_recvOverlap = new recv_overlap_type(comm, debug);
1664: this->_maxDof = -1;
1665: };
1666: public: // Accessors
1667: int getDimension() const {return this->_dim;};
1668: void setDimension(const int dim) {this->_dim = dim;};
1669: bool getCalculatedOverlap() const {return this->_calculatedOverlap;};
1670: void setCalculatedOverlap(const bool calc) {this->_calculatedOverlap = calc;};
1671: const Obj<send_overlap_type>& getSendOverlap() const {return this->_sendOverlap;};
1672: void setSendOverlap(const Obj<send_overlap_type>& overlap) {this->_sendOverlap = overlap;};
1673: const Obj<recv_overlap_type>& getRecvOverlap() const {return this->_recvOverlap;};
1674: void setRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_recvOverlap = overlap;};
1675: bool getPeriodicity(const int d) {return this->_periodicity[d];};
1676: void setPeriodicity(const int d, const double length) {this->_periodicity[d] = length;};
1677: const holes_type& getHoles() const {return this->_holes;};
1678: void addHole(const double hole[]) {
1679: this->_holes.push_back(hole);
1680: };
1681: void copyHoles(const Obj<IMesh>& m) {
1682: const holes_type& holes = m->getHoles();
1684: for(holes_type::const_iterator h_iter = holes.begin(); h_iter != holes.end(); ++h_iter) {
1685: this->_holes.push_back(*h_iter);
1686: }
1687: };
1688: const Obj<Discretization>& getDiscretization() {return this->getDiscretization("default");};
1689: const Obj<Discretization>& getDiscretization(const std::string& name) {return this->_discretizations[name];};
1690: void setDiscretization(const Obj<Discretization>& disc) {this->setDiscretization("default", disc);};
1691: void setDiscretization(const std::string& name, const Obj<Discretization>& disc) {this->_discretizations[name] = disc;};
1692: Obj<names_type> getDiscretizations() const {
1693: Obj<names_type> names = names_type();
1695: for(discretizations_type::const_iterator d_iter = this->_discretizations.begin(); d_iter != this->_discretizations.end(); ++d_iter) {
1696: names->insert(d_iter->first);
1697: }
1698: return names;
1699: };
1700: int getMaxDof() const {return this->_maxDof;};
1701: void setMaxDof(const int maxDof) {this->_maxDof = maxDof;};
1702: public: // Sizes
1703: template<typename Section>
1704: int size(const Obj<Section>& section, const point_type& p) {
1705: typedef ISieveVisitor::SizeVisitor<sieve_type,Section> size_visitor_type;
1706: typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1707: size_visitor_type sV(*section);
1708: closure_visitor_type cV(*this->getSieve(), sV);
1710: this->getSieve()->cone(p, cV);
1711: if (!sV.getSize()) sV.visitPoint(p);
1712: return sV.getSize();
1713: }
1714: template<typename Section>
1715: int sizeWithBC(const Obj<Section>& section, const point_type& p) {
1716: typedef ISieveVisitor::SizeWithBCVisitor<sieve_type,Section> size_visitor_type;
1717: typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1718: size_visitor_type sV(*section);
1719: closure_visitor_type cV(*this->getSieve(), sV);
1721: this->getSieve()->cone(p, cV);
1722: if (!sV.getSize()) sV.visitPoint(p);
1723: return sV.getSize();
1724: }
1725: int sizeWithBC(PetscSection section, const point_type& p) {
1726: typedef ISieveVisitor::SizeWithBCVisitor<sieve_type,PetscSection> size_visitor_type;
1727: typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1728: size_visitor_type sV(section);
1729: closure_visitor_type cV(*this->getSieve(), sV);
1731: this->getSieve()->cone(p, cV);
1732: if (!sV.getSize()) sV.visitPoint(p);
1733: return sV.getSize();
1734: }
1735: void sizeWithBC(PetscSection section, const point_type& p, PetscInt fieldSize[]) {
1736: typedef ISieveVisitor::SizeWithBCVisitor<sieve_type,PetscSection> size_visitor_type;
1737: typedef ISieveVisitor::TransitiveClosureVisitor<sieve_type,size_visitor_type> closure_visitor_type;
1738: size_visitor_type sV(section, fieldSize);
1739: closure_visitor_type cV(*this->getSieve(), sV);
1741: this->getSieve()->cone(p, cV);
1742: if (!sV.getSize()) sV.visitPoint(p);
1743: }
1744: template<typename Section>
1745: void allocate(const Obj<Section>& section) {
1746: section->allocatePoint();
1747: }
1748: public: // Restrict/Update closures
1749: template<typename Sieve, typename Visitor>
1750: void closure1(const Sieve& sieve, const point_type& p, Visitor& v)
1751: {
1752: v.visitPoint(p, 0);
1753: // Cone is guarateed to be ordered correctly
1754: sieve.orientedCone(p, v);
1755: }
1756: // Return the values for the closure of this point
1757: template<typename Section>
1758: const typename Section::value_type *restrictClosure(const Obj<Section>& section, const point_type& p) {
1759: const int size = this->sizeWithBC(section, p);
1760: ISieveVisitor::RestrictVisitor<Section> rV(*section, size, section->getRawArray(size));
1762: if (this->depth() == 1) {
1763: closure1(*this->getSieve(), p, rV);
1764: } else {
1765: ISieveVisitor::PointRetriever<sieve_type,ISieveVisitor::RestrictVisitor<Section> > pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, rV, true);
1767: ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1768: }
1769: return rV.getValues();
1770: }
1771: template<typename Section>
1772: const typename Section::value_type *restrictClosure(const Obj<Section>& section, const point_type& p, typename Section::value_type *values, const int valuesSize) {
1773: const int size = this->sizeWithBC(section, p);
1774: if (valuesSize < size) {throw ALE::Exception("Input array to small for restrictClosure()");}
1775: ISieveVisitor::RestrictVisitor<Section> rV(*section, size, values);
1777: if (this->depth() == 1) {
1778: closure1(*this->getSieve(), p, rV);
1779: } else {
1780: ISieveVisitor::PointRetriever<sieve_type,ISieveVisitor::RestrictVisitor<Section> > pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, rV, true);
1782: ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1783: }
1784: return rV.getValues();
1785: }
1786: template<typename Visitor>
1787: void restrictClosure(const point_type& p, Visitor& v) {
1788: if (this->depth() == 1) {
1789: closure1(*this->getSieve(), p, v);
1790: } else {
1791: ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, v);
1792: }
1793: }
1794: // Replace the values for the closure of this point
1795: template<typename Section>
1796: void update(const Obj<Section>& section, const point_type& p, const typename Section::value_type *v) {
1797: ISieveVisitor::UpdateVisitor<Section> uV(*section, v);
1799: if (this->depth() == 1) {
1800: closure1(*this->getSieve(), p, uV);
1801: } else {
1802: ISieveVisitor::PointRetriever<sieve_type,ISieveVisitor::UpdateVisitor<Section> > pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, uV, true);
1804: ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1805: }
1806: }
1807: // Replace the values for the closure of this point, including points constrained by BC
1808: template<typename Section>
1809: void updateAll(const Obj<Section>& section, const point_type& p, const typename Section::value_type *v) {
1810: ISieveVisitor::UpdateAllVisitor<Section> uV(*section, v);
1812: if (this->depth() == 1) {
1813: closure1(*this->getSieve(), p, uV);
1814: } else {
1815: ISieveVisitor::PointRetriever<sieve_type,ISieveVisitor::UpdateAllVisitor<Section> > pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, uV, true);
1817: ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1818: }
1819: }
1820: // Augment the values for the closure of this point
1821: template<typename Section>
1822: void updateAdd(const Obj<Section>& section, const point_type& p, const typename Section::value_type *v) {
1823: ISieveVisitor::UpdateAddVisitor<Section> uV(*section, v);
1825: if (this->depth() == 1) {
1826: closure1(*this->getSieve(), p, uV);
1827: } else {
1828: ISieveVisitor::PointRetriever<sieve_type,ISieveVisitor::UpdateAddVisitor<Section> > pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, uV, true);
1830: ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, pV);
1831: }
1832: }
1833: // Augment the values for the closure of this point
1834: template<typename Visitor>
1835: void updateClosure(const point_type& p, Visitor& v) {
1836: if (this->depth() == 1) {
1837: closure1(*this->getSieve(), p, v);
1838: } else {
1839: ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), p, v);
1840: }
1841: }
1842: public: // Overlap
1843: void constructOverlap() {
1844: if (!this->_calculatedOverlap && (this->commSize() > 1)) {throw ALE::Exception("Must calculate overlap during distribution");}
1845: };
1846: public: // Cell topology and geometry
1847: int getNumCellCorners(const point_type& p, const int depth = -1) const {
1848: const int d = depth < 0 ? this->depth() : depth;
1850: if (d == 1) {
1851: return this->_sieve->getConeSize(p);
1852: } else if (d <= 0) {
1853: return 0;
1854: }
1855: // Warning: this is slow
1856: ISieveVisitor::NConeRetriever<sieve_type> ncV(*this->_sieve, (int) pow((double) this->_sieve->getMaxConeSize(), this->depth()));
1857: ALE::ISieveTraversal<sieve_type>::orientedClosure(*this->_sieve, p, ncV);
1858: return ncV.getOrientedSize();
1859: };
1860: int getNumCellCorners() {
1861: return getNumCellCorners(*this->heightStratum(0)->begin());
1862: };
1863: void setupCoordinates(const Obj<real_section_type>& coordinates) {
1864: const Obj<label_sequence>& vertices = this->depthStratum(0);
1866: if (vertices->size() > 0) {
1867: coordinates->setChart(typename real_section_type::chart_type(*std::min_element(vertices->begin(), vertices->end()),
1868: *std::max_element(vertices->begin(), vertices->end())+1));
1869: } else {
1870: coordinates->setChart(typename real_section_type::chart_type(0, 0));
1871: }
1872: };
1873: // Find the cell in which this point lies (stupid algorithm)
1874: point_type locatePoint_Simplex_2D(const typename real_section_type::value_type point[]) {
1875: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1876: const Obj<label_sequence>& cells = this->heightStratum(0);
1877: const int embedDim = 2;
1878: typename real_section_type::value_type v0[2], J[4], invJ[4], detJ;
1880: for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1881: //std::cout << "Checking cell " << *c_iter << std::endl;
1882: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
1883: double xi = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]);
1884: double eta = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]);
1886: if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) {
1887: return *c_iter;
1888: }
1889: }
1890: {
1891: ostringstream msg;
1892: msg << "Could not locate point: (" << point[0] <<","<< point[1] << ")" << std::endl;
1893: throw ALE::Exception(msg.str().c_str());
1894: }
1895: };
1896: point_type locatePoint_General_2D(const typename real_section_type::value_type p[]) {
1897: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1898: const Obj<label_sequence>& cells = this->heightStratum(0);
1899: const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0};
1901: for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1902: const PetscReal *coords = this->restrictClosure(coordinates, *c_iter);
1903: PetscInt crossings = 0;
1905: //std::cout << "Checking cell " << *c_iter << std::endl;
1906: for(PetscInt f = 0; f < 4; f++) {
1907: PetscReal x_i = coords[faces[2*f+0]*2+0];
1908: PetscReal y_i = coords[faces[2*f+0]*2+1];
1909: PetscReal x_j = coords[faces[2*f+1]*2+0];
1910: PetscReal y_j = coords[faces[2*f+1]*2+1];
1911: PetscReal slope = (y_j - y_i) / (x_j - x_i);
1912: bool cond1 = (x_i <= p[0]) && (p[0] < x_j);
1913: bool cond2 = (x_j <= p[0]) && (p[0] < x_i);
1914: bool above = (p[1] < slope * (p[0] - x_i) + y_i);
1915: if ((cond1 || cond2) && above) ++crossings;
1916: }
1917: if (crossings % 2) {return *c_iter;}
1918: }
1919: {
1920: ostringstream msg;
1921: msg << "Could not locate point: (" << p[0] <<","<< p[1] << ")" << std::endl;
1922: throw ALE::Exception(msg.str().c_str());
1923: }
1924: };
1925: // Assume a simplex and 3D
1926: point_type locatePoint_Simplex_3D(const typename real_section_type::value_type point[]) {
1927: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1928: const Obj<label_sequence>& cells = this->heightStratum(0);
1929: const int embedDim = 3;
1930: typename real_section_type::value_type v0[3], J[9], invJ[9], detJ;
1932: for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1933: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
1934: double xi = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]) + invJ[0*embedDim+2]*(point[2] - v0[2]);
1935: double eta = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]) + invJ[1*embedDim+2]*(point[2] - v0[2]);
1936: double zeta = invJ[2*embedDim+0]*(point[0] - v0[0]) + invJ[2*embedDim+1]*(point[1] - v0[1]) + invJ[2*embedDim+2]*(point[2] - v0[2]);
1938: if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) {
1939: return *c_iter;
1940: }
1941: }
1942: #if 0
1943: {
1944: ostringstream msg;
1945: msg << "Could not locate point: (" << point[0] <<","<< point[1] <<","<< point[2] << ")" << std::endl;
1946: throw ALE::Exception(msg.str().c_str());
1947: }
1948: #else
1949: return -1;
1950: #endif
1951: };
1952: point_type locatePoint_General_3D(const typename real_section_type::value_type p[]) {
1953: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1954: const Obj<label_sequence>& cells = this->heightStratum(0);
1955: const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5,
1956: 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4};
1958: for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1959: const PetscReal *coords = this->restrictClosure(coordinates, *c_iter);
1960: PetscBool found = PETSC_TRUE;
1962: //std::cout << "Checking cell " << *c_iter << std::endl;
1963: for(PetscInt f = 0; f < 6; f++) {
1964: /* Check the point is under plane */
1965: /* Get face normal */
1966: PetscReal v_i[3] = {coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0],coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1],coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]};
1967: PetscReal v_j[3] = {coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0],coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1],coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]};
1968: PetscReal normal[3] = {v_i[1]*v_j[2] - v_i[2]*v_j[1], v_i[2]*v_j[0] - v_i[0]*v_j[2], v_i[0]*v_j[1] - v_i[1]*v_j[0]};
1969: PetscReal pp[3] = {coords[faces[f*4+0]*3+0] - p[0],coords[faces[f*4+0]*3+1] - p[1],coords[faces[f*4+0]*3+2] - p[2]};
1970: PetscReal dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2];
1971: /* Check that projected point is in face (2D location problem) */
1972: if (dot < 0.0) {
1973: found = PETSC_FALSE;
1974: break;
1975: }
1976: }
1977: if (found) {return *c_iter;}
1978: }
1979: #if 0
1980: {
1981: ostringstream msg;
1982: msg << "Could not locate point: (" << p[0] <<","<< p[1] <<","<< p[2] << ")" << std::endl;
1983: throw ALE::Exception(msg.str().c_str());
1984: }
1985: #else
1986: return -1;
1987: #endif
1988: };
1989: point_type locatePoint(const typename real_section_type::value_type point[], point_type guess = -1) {
1990: //guess overrides this by saying that we already know the relation of this point to this mesh. We will need to make it a more robust "guess" later for more than P1
1991: if (guess != -1) {
1992: return guess;
1993: } else if (this->_dim == 2) {
1994: const int e = *this->heightStratum(0)->begin();
1995: switch(this->getSieve()->getConeSize(e)) {
1996: case 3:
1997: return locatePoint_Simplex_2D(point);
1998: case 4:
1999: return locatePoint_General_2D(point);
2000: default:
2001: throw ALE::Exception("No point location for cone size");
2002: }
2003: } else if (this->_dim == 3) {
2004: const int e = *this->heightStratum(0)->begin();
2005: switch(this->getSieve()->getConeSize(e)) {
2006: case 4:
2007: return locatePoint_Simplex_3D(point);
2008: case 8:
2009: return locatePoint_General_3D(point);
2010: default:
2011: throw ALE::Exception("No point location for cone size");
2012: }
2013: } else {
2014: throw ALE::Exception("No point location for mesh dimension");
2015: }
2016: };
2017: void computeTriangleGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2018: const PetscReal *coords = this->restrictClosure(coordinates, e);
2019: const int dim = 2;
2020: typename real_section_type::value_type invDet;
2022: if (v0) {
2023: for(int d = 0; d < dim; d++) {
2024: v0[d] = coords[d];
2025: }
2026: }
2027: if (J) {
2028: for(int d = 0; d < dim; d++) {
2029: for(int f = 0; f < dim; f++) {
2030: J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2031: }
2032: }
2033: detJ = J[0]*J[3] - J[1]*J[2];
2034: if (detJ < 0.0) {
2035: const typename real_section_type::value_type xLength = this->_periodicity[0];
2037: if (xLength != 0.0) {
2038: typename real_section_type::value_type v0x = coords[0*dim+0];
2040: if (v0x == 0.0) {
2041: v0x = v0[0] = xLength;
2042: }
2043: for(int f = 0; f < dim; f++) {
2044: const typename real_section_type::value_type px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];
2046: J[0*dim+f] = 0.5*(px - v0x);
2047: }
2048: }
2049: detJ = J[0]*J[3] - J[1]*J[2];
2050: }
2051: PetscLogFlopsNoError(8.0 + 3.0);
2052: }
2053: if (invJ) {
2054: invDet = 1.0/detJ;
2055: invJ[0] = invDet*J[3];
2056: invJ[1] = -invDet*J[1];
2057: invJ[2] = -invDet*J[2];
2058: invJ[3] = invDet*J[0];
2059: PetscLogFlopsNoError(5.0);
2060: }
2061: };
2062: void computeRectangleGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2063: const PetscReal *coords = this->restrictClosure(coordinates, e);
2064: const int dim = 2;
2065: typename real_section_type::value_type invDet;
2067: if (v0) {
2068: for(int d = 0; d < dim; d++) {
2069: v0[d] = coords[d];
2070: }
2071: }
2072: if (J) {
2073: for(int d = 0; d < dim; d++) {
2074: for(int f = 0; f < dim; f++) {
2075: J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2076: }
2077: }
2078: detJ = J[0]*J[3] - J[1]*J[2];
2079: PetscLogFlopsNoError(8.0 + 3.0);
2080: }
2081: if (invJ) {
2082: invDet = 1.0/detJ;
2083: invJ[0] = invDet*J[3];
2084: invJ[1] = -invDet*J[1];
2085: invJ[2] = -invDet*J[2];
2086: invJ[3] = invDet*J[0];
2087: PetscLogFlopsNoError(5.0);
2088: }
2089: detJ *= 2.0;
2090: };
2091: void computeTetrahedronGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2092: const PetscReal *coords = this->restrictClosure(coordinates, e);
2093: const int dim = 3;
2094: typename real_section_type::value_type invDet;
2096: if (v0) {
2097: for(int d = 0; d < dim; d++) {
2098: v0[d] = coords[d];
2099: }
2100: }
2101: if (J) {
2102: for(int d = 0; d < dim; d++) {
2103: for(int f = 0; f < dim; f++) {
2104: J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2105: }
2106: }
2107: // The minus sign is here since I orient the first face to get the outward normal
2108: detJ = -(J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2109: J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2110: J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
2111: PetscLogFlopsNoError(18.0 + 12.0);
2112: }
2113: if (invJ) {
2114: invDet = -1.0/detJ;
2115: invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2116: invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
2117: invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2118: invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2119: invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
2120: invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2121: invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2122: invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
2123: invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2124: PetscLogFlopsNoError(37.0);
2125: }
2126: };
2127: void computeHexahedronGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2128: const PetscReal *coords = this->restrictClosure(coordinates, e);
2129: const int dim = 3;
2130: typename real_section_type::value_type invDet;
2132: if (v0) {
2133: for(int d = 0; d < dim; d++) {
2134: v0[d] = coords[d];
2135: }
2136: }
2137: if (J) {
2138: for(int d = 0; d < dim; d++) {
2139: J[d*dim+0] = 0.5*(coords[(0+1)*dim+d] - coords[0*dim+d]);
2140: J[d*dim+1] = 0.5*(coords[(1+1)*dim+d] - coords[0*dim+d]);
2141: J[d*dim+2] = 0.5*(coords[(3+1)*dim+d] - coords[0*dim+d]);
2142: }
2143: detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2144: J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2145: J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
2146: PetscLogFlopsNoError(18.0 + 12.0);
2147: }
2148: if (invJ) {
2149: invDet = -1.0/detJ;
2150: invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2151: invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
2152: invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2153: invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2154: invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
2155: invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2156: invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2157: invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
2158: invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2159: PetscLogFlopsNoError(37.0);
2160: }
2161: detJ *= 8.0;
2162: };
2163: void computeElementGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2164: const int coneSize = this->getSieve()->getConeSize(e);
2166: if (this->_dim == 2) {
2167: if (coneSize == 3) {
2168: computeTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
2169: } else if (coneSize == 4) {
2170: computeRectangleGeometry(coordinates, e, v0, J, invJ, detJ);
2171: } else {
2172: throw ALE::Exception("Unsupported coneSize for element geometry computation");
2173: }
2174: } else if (this->_dim == 3) {
2175: if (coneSize == 4) {
2176: computeTetrahedronGeometry(coordinates, e, v0, J, invJ, detJ);
2177: } else if (coneSize == 8) {
2178: computeHexahedronGeometry(coordinates, e, v0, J, invJ, detJ);
2179: } else {
2180: throw ALE::Exception("Unsupported coneSize for element geometry computation");
2181: }
2182: } else {
2183: throw ALE::Exception("Unsupported dimension for element geometry computation");
2184: }
2185: };
2186: void computeBdSegmentGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2187: const typename real_section_type::value_type *coords = this->restrictClosure(coordinates, e);
2188: const int dim = 2;
2189: typename real_section_type::value_type invDet;
2191: if (v0) {
2192: for(int d = 0; d < dim; d++) {
2193: v0[d] = coords[d];
2194: }
2195: }
2196: if (J) {
2197: //r2 = coords[1*dim+0]*coords[1*dim+0] + coords[1*dim+1]*coords[1*dim+1];
2198: J[0] = (coords[1*dim+0] - coords[0*dim+0])*0.5; J[1] = (-coords[1*dim+1] + coords[0*dim+1])*0.5;
2199: J[2] = (coords[1*dim+1] - coords[0*dim+1])*0.5; J[3] = ( coords[1*dim+0] - coords[0*dim+0])*0.5;
2200: detJ = J[0]*J[3] - J[1]*J[2];
2201: if (detJ < 0.0) {
2202: const typename real_section_type::value_type xLength = this->_periodicity[0];
2204: if (xLength != 0.0) {
2205: typename real_section_type::value_type v0x = coords[0*dim+0];
2207: if (v0x == 0.0) {
2208: v0x = v0[0] = xLength;
2209: }
2210: for(int f = 0; f < dim; f++) {
2211: const typename real_section_type::value_type px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];
2213: J[0*dim+f] = 0.5*(px - v0x);
2214: }
2215: }
2216: detJ = J[0]*J[3] - J[1]*J[2];
2217: }
2218: PetscLogFlopsNoError(8.0 + 3.0);
2219: }
2220: if (invJ) {
2221: invDet = 1.0/detJ;
2222: invJ[0] = invDet*J[3];
2223: invJ[1] = -invDet*J[1];
2224: invJ[2] = -invDet*J[2];
2225: invJ[3] = invDet*J[0];
2226: PetscLogFlopsNoError(5.0);
2227: }
2228: };
2229: void computeBdElementGeometry(const Obj<real_section_type>& coordinates, const point_type& e, typename real_section_type::value_type v0[], typename real_section_type::value_type J[], typename real_section_type::value_type invJ[], typename real_section_type::value_type& detJ) {
2230: if (this->_dim == 1) {
2231: computeBdSegmentGeometry(coordinates, e, v0, J, invJ, detJ);
2232: // } else if (this->_dim == 2) {
2233: // computeBdTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
2234: } else {
2235: throw ALE::Exception("Unsupported dimension for element geometry computation");
2236: }
2237: };
2238: typename real_section_type::value_type getMaxVolume() {
2239: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
2240: const Obj<label_sequence>& cells = this->heightStratum(0);
2241: const int dim = this->getDimension();
2242: typename real_section_type::value_type v0[3], J[9], invJ[9], detJ, refVolume = 0.0, maxVolume = 0.0;
2244: if (dim == 1) refVolume = 2.0;
2245: if (dim == 2) refVolume = 2.0;
2246: if (dim == 3) refVolume = 4.0/3.0;
2247: for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
2248: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
2249: maxVolume = std::max(maxVolume, detJ*refVolume);
2250: }
2251: return maxVolume;
2252: };
2253: public:
2254: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
2255: if (comm == MPI_COMM_NULL) {
2256: comm = this->comm();
2257: }
2258: if (name == "") {
2259: PetscPrintf(comm, "viewing a Mesh\n");
2260: } else {
2261: PetscPrintf(comm, "viewing Mesh '%s'\n", name.c_str());
2262: }
2263: this->getSieve()->view("mesh sieve", comm);
2264: Obj<names_type> sections = this->getRealSections();
2266: for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2267: this->getRealSection(*name)->view(*name);
2268: }
2269: sections = this->getIntSections();
2270: for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2271: this->getIntSection(*name)->view(*name);
2272: }
2273: sections = this->getArrowSections();
2274: for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2275: this->getArrowSection(*name)->view(*name);
2276: }
2277: };
2278: public: // Discretization
2279: void markBoundaryCells(const std::string& name, const int marker = 1, const int newMarker = 2, const bool onlyVertices = false) {
2280: const Obj<label_type>& label = this->getLabel(name);
2281: const Obj<label_sequence>& boundary = this->getLabelStratum(name, marker);
2282: const typename label_sequence::iterator end = boundary->end();
2283: const Obj<sieve_type>& sieve = this->getSieve();
2285: if (!onlyVertices) {
2286: typename ISieveVisitor::MarkVisitor<sieve_type,label_type> mV(*label, newMarker);
2288: for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != end; ++e_iter) {
2289: if (this->height(*e_iter) == 1) {
2290: sieve->support(*e_iter, mV);
2291: }
2292: }
2293: } else {
2294: #if 1
2295: throw ALE::Exception("Rewrite this to first mark boundary edges/faces.");
2296: #else
2297: const int depth = this->depth();
2299: for(typename label_sequence::iterator v_iter = boundary->begin(); v_iter != end; ++v_iter) {
2300: const Obj<supportArray> support = sieve->nSupport(*v_iter, depth);
2301: const typename supportArray::iterator sEnd = support->end();
2303: for(typename supportArray::iterator c_iter = support->begin(); c_iter != sEnd; ++c_iter) {
2304: const Obj<typename sieve_type::traits::coneSequence>& cone = sieve->cone(*c_iter);
2305: const typename sieve_type::traits::coneSequence::iterator cEnd = cone->end();
2307: for(typename sieve_type::traits::coneSequence::iterator e_iter = cone->begin(); e_iter != cEnd; ++e_iter) {
2308: if (sieve->support(*e_iter)->size() == 1) {
2309: this->setValue(label, *c_iter, newMarker);
2310: break;
2311: }
2312: }
2313: }
2314: }
2315: #endif
2316: }
2317: };
2318: int setFiberDimensions(const Obj<real_section_type>& s, const Obj<names_type>& discs, names_type& bcLabels) {
2319: const int debug = this->debug();
2320: int maxDof = 0;
2322: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter) {
2323: s->addSpace();
2324: }
2325: for(int d = 0; d <= this->_dim; ++d) {
2326: int numDof = 0;
2327: int f = 0;
2329: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2330: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
2331: const int sDof = disc->getNumDof(d);
2333: numDof += sDof;
2334: if (sDof) s->setFiberDimension(this->depthStratum(d), sDof, f);
2335: }
2336: if (numDof) s->setFiberDimension(this->depthStratum(d), numDof);
2337: maxDof = std::max(maxDof, numDof);
2338: }
2339: // Process exclusions
2340: typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2341: int f = 0;
2343: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2344: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
2345: std::string labelName = "exclude-"+*f_iter;
2346: std::set<point_type> seen;
2347: Visitor pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth()), true);
2349: if (this->hasLabel(labelName)) {
2350: const Obj<label_type>& label = this->getLabel(labelName);
2351: const Obj<label_sequence>& exclusion = this->getLabelStratum(labelName, 1);
2352: const typename label_sequence::iterator end = exclusion->end();
2353: if (debug > 1) {label->view(labelName.c_str());}
2355: for(typename label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
2356: ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), *e_iter, pV);
2357: const typename Visitor::point_type *oPoints = pV.getPoints();
2358: const int oSize = pV.getSize();
2360: for(int cl = 0; cl < oSize; ++cl) {
2361: if (seen.find(oPoints[cl]) != seen.end()) continue;
2362: if (this->getValue(label, oPoints[cl]) == 1) {
2363: seen.insert(oPoints[cl]);
2364: s->setFiberDimension(oPoints[cl], 0, f);
2365: s->addFiberDimension(oPoints[cl], -disc->getNumDof(this->depth(oPoints[cl])));
2366: if (debug > 1) {std::cout << " point: " << oPoints[cl] << " dim: " << disc->getNumDof(this->depth(oPoints[cl])) << std::endl;}
2367: }
2368: }
2369: pV.clear();
2370: }
2371: }
2372: }
2373: // Process constraints
2374: f = 0;
2375: for(std::set<std::string>::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2376: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
2377: const Obj<std::set<std::string> > bcs = disc->getBoundaryConditions();
2378: std::string excludeName = "exclude-"+*f_iter;
2380: for(std::set<std::string>::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter) {
2381: const Obj<ALE::BoundaryCondition>& bc = disc->getBoundaryCondition(*bc_iter);
2382: const Obj<label_sequence>& boundary = this->getLabelStratum(bc->getLabelName(), bc->getMarker());
2384: bcLabels.insert(bc->getLabelName());
2385: if (this->hasLabel(excludeName)) {
2386: const Obj<label_type>& label = this->getLabel(excludeName);
2388: for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
2389: if (!this->getValue(label, *e_iter)) {
2390: const int numDof = disc->getNumDof(this->depth(*e_iter));
2392: if (numDof) s->addConstraintDimension(*e_iter, numDof);
2393: if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
2394: }
2395: }
2396: } else {
2397: for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
2398: const int numDof = disc->getNumDof(this->depth(*e_iter));
2400: if (numDof) s->addConstraintDimension(*e_iter, numDof);
2401: if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
2402: }
2403: }
2404: }
2405: }
2406: return maxDof;
2407: };
2408: void calculateIndices() {
2409: typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2410: // Should have an iterator over the whole tree
2411: Obj<names_type> discs = this->getDiscretizations();
2412: const int debug = this->debug();
2413: std::map<std::string, std::pair<int, int*> > indices;
2415: for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
2416: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
2418: indices[*d_iter] = std::pair<int, int*>(0, new int[disc->sizeV(*this)]);
2419: disc->setIndices(indices[*d_iter].second);
2420: }
2421: const Obj<label_sequence>& cells = this->heightStratum(0);
2422: Visitor pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, true);
2423: ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), *cells->begin(), pV);
2424: const typename Visitor::point_type *oPoints = pV.getPoints();
2425: const int oSize = pV.getSize();
2426: int offset = 0;
2428: if (debug > 1) {std::cout << "Closure for first element" << std::endl;}
2429: for(int cl = 0; cl < oSize; ++cl) {
2430: const int dim = this->depth(oPoints[cl]);
2432: if (debug > 1) {std::cout << " point " << oPoints[cl] << " depth " << dim << std::endl;}
2433: for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
2434: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
2435: const int num = disc->getNumDof(dim);
2437: if (debug > 1) {std::cout << " disc " << disc->getName() << " numDof " << num << std::endl;}
2438: for(int o = 0; o < num; ++o) {
2439: indices[*d_iter].second[indices[*d_iter].first++] = offset++;
2440: }
2441: }
2442: }
2443: pV.clear();
2444: if (debug > 1) {
2445: for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
2446: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
2448: std::cout << "Discretization " << disc->getName() << " indices:";
2449: for(int i = 0; i < indices[*d_iter].first; ++i) {
2450: std::cout << " " << indices[*d_iter].second[i];
2451: }
2452: std::cout << std::endl;
2453: }
2454: }
2455: };
2456: void calculateIndicesExcluded(const Obj<real_section_type>& s, const Obj<names_type>& discs) {
2457: typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2458: typedef std::map<std::string, std::pair<int, indexSet> > indices_type;
2459: const Obj<label_type>& indexLabel = this->createLabel("cellExclusion");
2460: const int debug = this->debug();
2461: int marker = 0;
2462: std::map<indices_type, int> indexMap;
2463: indices_type indices;
2464: Visitor pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, true);
2466: for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
2467: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
2468: const int size = disc->sizeV(*this);
2470: indices[*d_iter].second.resize(size);
2471: }
2472: const typename names_type::const_iterator dBegin = discs->begin();
2473: const typename names_type::const_iterator dEnd = discs->end();
2474: std::set<point_type> seen;
2475: int f = 0;
2477: for(typename names_type::const_iterator f_iter = dBegin; f_iter != dEnd; ++f_iter, ++f) {
2478: std::string labelName = "exclude-"+*f_iter;
2480: if (this->hasLabel(labelName)) {
2481: const Obj<label_sequence>& exclusion = this->getLabelStratum(labelName, 1);
2482: const typename label_sequence::iterator end = exclusion->end();
2484: if (debug > 1) {std::cout << "Processing exclusion " << labelName << std::endl;}
2485: for(typename label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
2486: if (this->height(*e_iter)) continue;
2487: ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), *e_iter, pV);
2488: const typename Visitor::point_type *oPoints = pV.getPoints();
2489: const int oSize = pV.getSize();
2490: int offset = 0;
2492: if (debug > 1) {std::cout << " Closure for cell " << *e_iter << std::endl;}
2493: for(int cl = 0; cl < oSize; ++cl) {
2494: int g = 0;
2496: if (debug > 1) {std::cout << " point " << oPoints[cl] << std::endl;}
2497: for(typename names_type::const_iterator g_iter = dBegin; g_iter != dEnd; ++g_iter, ++g) {
2498: const int fDim = s->getFiberDimension(oPoints[cl], g);
2500: if (debug > 1) {std::cout << " disc " << *g_iter << " numDof " << fDim << std::endl;}
2501: for(int d = 0; d < fDim; ++d) {
2502: indices[*g_iter].second[indices[*g_iter].first++] = offset++;
2503: }
2504: }
2505: }
2506: pV.clear();
2507: const std::map<indices_type, int>::iterator entry = indexMap.find(indices);
2509: if (debug > 1) {
2510: for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
2511: for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2512: std::cout << "Discretization (" << i_iter->second << ") " << *g_iter << " indices:";
2513: for(int i = 0; i < ((indices_type) i_iter->first)[*g_iter].first; ++i) {
2514: std::cout << " " << ((indices_type) i_iter->first)[*g_iter].second[i];
2515: }
2516: std::cout << std::endl;
2517: }
2518: std::cout << "Comparison: " << (indices == i_iter->first) << std::endl;
2519: }
2520: for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2521: std::cout << "Discretization " << *g_iter << " indices:";
2522: for(int i = 0; i < indices[*g_iter].first; ++i) {
2523: std::cout << " " << indices[*g_iter].second[i];
2524: }
2525: std::cout << std::endl;
2526: }
2527: }
2528: if (entry != indexMap.end()) {
2529: this->setValue(indexLabel, *e_iter, entry->second);
2530: if (debug > 1) {std::cout << " Found existing indices with marker " << entry->second << std::endl;}
2531: } else {
2532: indexMap[indices] = ++marker;
2533: this->setValue(indexLabel, *e_iter, marker);
2534: if (debug > 1) {std::cout << " Created new indices with marker " << marker << std::endl;}
2535: }
2536: for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2537: indices[*g_iter].first = 0;
2538: for(unsigned int i = 0; i < indices[*g_iter].second.size(); ++i) indices[*g_iter].second[i] = 0;
2539: }
2540: }
2541: }
2542: }
2543: if (debug > 1) {indexLabel->view("cellExclusion");}
2544: for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
2545: if (debug > 1) {std::cout << "Setting indices for marker " << i_iter->second << std::endl;}
2546: for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
2547: const Obj<Discretization>& disc = this->getDiscretization(*g_iter);
2548: const indexSet indSet = ((indices_type) i_iter->first)[*g_iter].second;
2549: const int size = indSet.size();
2550: int *_indices = new int[size];
2552: if (debug > 1) {std::cout << " field " << *g_iter << std::endl;}
2553: for(int i = 0; i < size; ++i) {
2554: _indices[i] = indSet[i];
2555: if (debug > 1) {std::cout << " indices["<<i<<"] = " << _indices[i] << std::endl;}
2556: }
2557: disc->setIndices(_indices, i_iter->second);
2558: }
2559: }
2560: };
2561: void setupField(const Obj<real_section_type>& s, const int cellMarker = 2, const bool noUpdate = false) {
2562: typedef ISieveVisitor::PointRetriever<sieve_type> Visitor;
2563: const Obj<names_type>& discs = this->getDiscretizations();
2564: const int debug = s->debug();
2565: names_type bcLabels;
2567: s->setChart(this->getSieve()->getChart());
2568: this->_maxDof = this->setFiberDimensions(s, discs, bcLabels);
2569: this->calculateIndices();
2570: this->calculateIndicesExcluded(s, discs);
2571: this->allocate(s);
2572: s->defaultConstraintDof();
2573: const Obj<label_type>& cellExclusion = this->getLabel("cellExclusion");
2575: if (debug > 1) {std::cout << "Setting boundary values" << std::endl;}
2576: for(typename names_type::const_iterator n_iter = bcLabels.begin(); n_iter != bcLabels.end(); ++n_iter) {
2577: const Obj<label_sequence>& boundaryCells = this->getLabelStratum(*n_iter, cellMarker);
2578: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
2579: const Obj<names_type>& discs = this->getDiscretizations();
2580: const point_type firstCell = *boundaryCells->begin();
2581: const int numFields = discs->size();
2582: typename real_section_type::value_type *values = new typename real_section_type::value_type[this->sizeWithBC(s, firstCell)];
2583: int *dofs = new int[this->_maxDof];
2584: int *v = new int[numFields];
2585: typename real_section_type::value_type *v0 = new typename real_section_type::value_type[this->getDimension()];
2586: typename real_section_type::value_type *J = new typename real_section_type::value_type[this->getDimension()*this->getDimension()];
2587: typename real_section_type::value_type detJ;
2588: Visitor pV((int) pow((double) this->getSieve()->getMaxConeSize(), this->depth())+1, true);
2590: for(typename label_sequence::iterator c_iter = boundaryCells->begin(); c_iter != boundaryCells->end(); ++c_iter) {
2591: ISieveTraversal<sieve_type>::orientedClosure(*this->getSieve(), *c_iter, pV);
2592: const typename Visitor::point_type *oPoints = pV.getPoints();
2593: const int oSize = pV.getSize();
2595: if (debug > 1) {std::cout << " Boundary cell " << *c_iter << std::endl;}
2596: this->computeElementGeometry(coordinates, *c_iter, v0, J, PETSC_NULL, detJ);
2597: for(int f = 0; f < numFields; ++f) v[f] = 0;
2598: for(int cl = 0; cl < oSize; ++cl) {
2599: const int cDim = s->getConstraintDimension(oPoints[cl]);
2600: int off = 0;
2601: int f = 0;
2602: int i = -1;
2604: if (debug > 1) {std::cout << " point " << oPoints[cl] << std::endl;}
2605: if (cDim) {
2606: if (debug > 1) {std::cout << " constrained excMarker: " << this->getValue(cellExclusion, *c_iter) << std::endl;}
2607: for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2608: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
2609: const Obj<names_type> bcs = disc->getBoundaryConditions();
2610: const int fDim = s->getFiberDimension(oPoints[cl], f);//disc->getNumDof(this->depth(oPoints[cl]));
2611: const int *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
2612: int b = 0;
2614: for(typename names_type::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter, ++b) {
2615: const Obj<ALE::BoundaryCondition>& bc = disc->getBoundaryCondition(*bc_iter);
2616: const int value = this->getValue(this->getLabel(bc->getLabelName()), oPoints[cl]);
2618: if (b > 0) v[f] -= fDim;
2619: if (value == bc->getMarker()) {
2620: if (debug > 1) {std::cout << " field " << *f_iter << " marker " << value << std::endl;}
2621: for(int d = 0; d < fDim; ++d, ++v[f]) {
2622: dofs[++i] = off+d;
2623: if (!noUpdate) values[indices[v[f]]] = (*bc->getDualIntegrator())(v0, J, v[f], bc->getFunction());
2624: if (debug > 1) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2625: }
2626: // Allow only one condition per point
2627: ++b;
2628: break;
2629: } else {
2630: if (debug > 1) {std::cout << " field " << *f_iter << std::endl;}
2631: for(int d = 0; d < fDim; ++d, ++v[f]) {
2632: values[indices[v[f]]] = 0.0;
2633: if (debug > 1) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2634: }
2635: }
2636: }
2637: if (b == 0) {
2638: if (debug > 1) {std::cout << " field " << *f_iter << std::endl;}
2639: for(int d = 0; d < fDim; ++d, ++v[f]) {
2640: values[indices[v[f]]] = 0.0;
2641: if (debug > 1) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2642: }
2643: }
2644: off += fDim;
2645: }
2646: if (i != cDim-1) {throw ALE::Exception("Invalid constraint initialization");}
2647: s->setConstraintDof(oPoints[cl], dofs);
2648: } else {
2649: if (debug > 1) {std::cout << " unconstrained" << std::endl;}
2650: for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2651: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
2652: const int fDim = s->getFiberDimension(oPoints[cl], f);//disc->getNumDof(this->depth(oPoints[cl]));
2653: const int *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
2655: if (debug > 1) {std::cout << " field " << *f_iter << std::endl;}
2656: for(int d = 0; d < fDim; ++d, ++v[f]) {
2657: values[indices[v[f]]] = 0.0;
2658: if (debug > 1) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
2659: }
2660: }
2661: }
2662: }
2663: if (debug > 1) {
2664: for(int f = 0; f < numFields; ++f) v[f] = 0;
2665: for(int cl = 0; cl < oSize; ++cl) {
2666: int f = 0;
2667: for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
2668: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
2669: const int fDim = s->getFiberDimension(oPoints[cl], f);
2670: const int *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
2672: for(int d = 0; d < fDim; ++d, ++v[f]) {
2673: std::cout << " "<<*f_iter<<"-value["<<indices[v[f]]<<"] " << values[indices[v[f]]] << std::endl;
2674: }
2675: }
2676: }
2677: }
2678: if (!noUpdate) {
2679: this->updateAll(s, *c_iter, values);
2680: }
2681: pV.clear();
2682: }
2683: delete [] dofs;
2684: delete [] values;
2685: delete [] v0;
2686: delete [] J;
2687: }
2688: if (debug > 1) {s->view("");}
2689: };
2690: public:
2691: // Take in a map for the cells labels
2692: template<typename Section_>
2693: void relabel(Section_& labeling) {
2694: this->getSieve()->relabel(labeling);
2695: // Relabel sections
2696: Obj<std::set<std::string> > realNames = this->getRealSections();
2698: for(std::set<std::string>::const_iterator n_iter = realNames->begin(); n_iter != realNames->end(); ++n_iter) {
2699: Obj<real_section_type> section = new real_section_type(this->comm(), this->debug());
2701: section->setName(*n_iter);
2702: ALE::Ordering<>::relabelSection(*this->getRealSection(*n_iter), labeling, *section);
2703: this->setRealSection(*n_iter, section);
2704: }
2705: Obj<std::set<std::string> > intNames = this->getIntSections();
2707: for(std::set<std::string>::const_iterator n_iter = intNames->begin(); n_iter != intNames->end(); ++n_iter) {
2708: Obj<int_section_type> section = new int_section_type(this->comm(), this->debug());
2710: section->setName(*n_iter);
2711: ALE::Ordering<>::relabelSection(*this->getIntSection(*n_iter), labeling, *section);
2712: this->setIntSection(*n_iter, section);
2713: }
2714: // Relabel labels
2715: const labels_type& labels = this->getLabels();
2717: for(typename labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
2718: Obj<label_type> label = new label_type(this->comm(), this->debug());
2720: l_iter->second->relabel(labeling, *label);
2721: this->setLabel(l_iter->first, label);
2722: }
2723: // Relabel overlap
2724: Obj<send_overlap_type> sendOverlap = new send_overlap_type(this->comm(), this->debug());
2725: Obj<recv_overlap_type> recvOverlap = new recv_overlap_type(this->comm(), this->debug());
2727: this->getSendOverlap()->relabel(labeling, *sendOverlap);
2728: this->setSendOverlap(sendOverlap);
2729: this->getRecvOverlap()->relabel(labeling, *recvOverlap);
2730: this->setRecvOverlap(recvOverlap);
2731: // Relabel distribution overlap ???
2732: // Relabel renumbering
2733: }
2734: };
2735: }
2737: namespace ALE {
2738: template<typename IndexType, typename ScalarType>
2739: class Mesh : public Bundle<ALE::Sieve<IndexType,IndexType,IndexType>, GeneralSection<IndexType,ScalarType> > {
2740: public:
2741: typedef Bundle<ALE::Sieve<IndexType,IndexType,IndexType>, GeneralSection<IndexType,ScalarType> > base_type;
2742: typedef typename base_type::sieve_type sieve_type;
2743: typedef typename sieve_type::point_type point_type;
2744: typedef typename base_type::alloc_type alloc_type;
2745: typedef typename base_type::label_type label_type;
2746: typedef typename base_type::label_sequence label_sequence;
2747: typedef typename base_type::coneArray coneArray;
2748: typedef typename base_type::supportArray supportArray;
2749: typedef typename base_type::arrow_section_type arrow_section_type;
2750: typedef typename base_type::real_section_type real_section_type;
2751: typedef typename base_type::numbering_type numbering_type;
2752: typedef typename base_type::order_type order_type;
2753: typedef typename base_type::send_overlap_type send_overlap_type;
2754: typedef typename base_type::recv_overlap_type recv_overlap_type;
2755: typedef typename base_type::sieve_alg_type sieve_alg_type;
2756: typedef std::set<std::string> names_type;
2757: typedef std::map<std::string, Obj<Discretization> > discretizations_type;
2758: typedef std::vector<PETSc::Point<3> > holes_type;
2759: protected:
2760: int _dim;
2761: discretizations_type _discretizations;
2762: std::map<int,double> _periodicity;
2763: holes_type _holes;
2764: public:
2765: Mesh(MPI_Comm comm, int dim, int debug = 0) : base_type(comm, debug), _dim(dim) {
2766: ///this->_factory = MeshNumberingFactory::singleton(debug);
2767: //std::cout << "["<<this->commRank()<<"]: Creating an ALE::Mesh" << std::endl;
2768: };
2769: ~Mesh() {
2770: //std::cout << "["<<this->commRank()<<"]: Destroying an ALE::Mesh" << std::endl;
2771: };
2772: public: // Accessors
2773: int getDimension() const {return this->_dim;};
2774: void setDimension(const int dim) {this->_dim = dim;};
2775: const Obj<Discretization>& getDiscretization() {return this->getDiscretization("default");};
2776: const Obj<Discretization>& getDiscretization(const std::string& name) {return this->_discretizations[name];};
2777: void setDiscretization(const Obj<Discretization>& disc) {this->setDiscretization("default", disc);};
2778: void setDiscretization(const std::string& name, const Obj<Discretization>& disc) {this->_discretizations[name] = disc;};
2779: Obj<names_type> getDiscretizations() const {
2780: Obj<names_type> names = names_type();
2782: for(discretizations_type::const_iterator d_iter = this->_discretizations.begin(); d_iter != this->_discretizations.end(); ++d_iter) {
2783: names->insert(d_iter->first);
2784: }
2785: return names;
2786: };
2787: bool getPeriodicity(const int d) {return this->_periodicity[d];};
2788: void setPeriodicity(const int d, const double length) {this->_periodicity[d] = length;};
2789: const holes_type& getHoles() const {return this->_holes;};
2790: void addHole(const double hole[]) {
2791: this->_holes.push_back(hole);
2792: };
2793: void copyHoles(const Obj<Mesh>& m) {
2794: const holes_type& holes = m->getHoles();
2796: for(holes_type::const_iterator h_iter = holes.begin(); h_iter != holes.end(); ++h_iter) {
2797: this->_holes.push_back(*h_iter);
2798: }
2799: };
2800: void copy(const Obj<Mesh>& m) {
2801: this->setSieve(m->getSieve());
2802: this->setLabel("height", m->getLabel("height"));
2803: this->_maxHeight = m->height();
2804: this->setLabel("depth", m->getLabel("depth"));
2805: this->_maxDepth = m->depth();
2806: this->setLabel("marker", m->getLabel("marker"));
2807: this->setRealSection("coordinates", m->getRealSection("coordinates"));
2808: this->setArrowSection("orientation", m->getArrowSection("orientation"));
2809: };
2810: public: // Cell topology and geometry
2811: int getNumCellCorners(const point_type& p, const int depth = -1) const {
2812: return (this->getDimension() > 0) ? this->_sieve->nCone(p, depth < 0 ? this->depth() : depth)->size() : 1;
2813: };
2814: int getNumCellCorners() {
2815: return getNumCellCorners(*(this->heightStratum(0)->begin()));
2816: };
2817: void setupCoordinates(const Obj<real_section_type>& coordinates) {};
2818: void computeTriangleGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2819: const double *coords = this->restrictClosure(coordinates, e);
2820: const int dim = 2;
2821: double invDet;
2823: if (v0) {
2824: for(int d = 0; d < dim; d++) {
2825: v0[d] = coords[d];
2826: }
2827: }
2828: if (J) {
2829: for(int d = 0; d < dim; d++) {
2830: for(int f = 0; f < dim; f++) {
2831: J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2832: }
2833: }
2834: detJ = J[0]*J[3] - J[1]*J[2];
2835: if (detJ < 0.0) {
2836: const double xLength = this->_periodicity[0];
2838: if (xLength != 0.0) {
2839: double v0x = coords[0*dim+0];
2841: if (v0x == 0.0) {
2842: v0x = v0[0] = xLength;
2843: }
2844: for(int f = 0; f < dim; f++) {
2845: const double px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];
2847: J[0*dim+f] = 0.5*(px - v0x);
2848: }
2849: }
2850: detJ = J[0]*J[3] - J[1]*J[2];
2851: }
2852: PetscLogFlopsNoError(8.0 + 3.0);
2853: }
2854: if (invJ) {
2855: invDet = 1.0/detJ;
2856: invJ[0] = invDet*J[3];
2857: invJ[1] = -invDet*J[1];
2858: invJ[2] = -invDet*J[2];
2859: invJ[3] = invDet*J[0];
2860: PetscLogFlopsNoError(5.0);
2861: }
2862: };
2863: void computeQuadrilateralGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double point[], double v0[], double J[], double invJ[], double& detJ) {
2864: const double *coords = this->restrictClosure(coordinates, e);
2865: const int dim = 2;
2866: double invDet;
2868: if (v0) {
2869: for(int d = 0; d < dim; d++) {
2870: v0[d] = coords[d];
2871: }
2872: }
2873: if (J) {
2874: double x_1 = coords[2] - coords[0];
2875: double y_1 = coords[3] - coords[1];
2876: double x_2 = coords[6] - coords[0];
2877: double y_2 = coords[7] - coords[1];
2878: double x_3 = coords[4] - coords[0];
2879: double y_3 = coords[5] - coords[1];
2881: J[0] = x_1 + (x_3 - x_1 - x_2)*point[1];
2882: J[1] = x_2 + (x_3 - x_1 - x_2)*point[0];
2883: J[2] = y_1 + (y_3 - y_1 - y_2)*point[1];
2884: J[3] = y_1 + (y_3 - y_1 - y_2)*point[0];
2885: detJ = J[0]*J[3] - J[1]*J[2];
2886: PetscLogFlopsNoError(6.0 + 16.0 + 3.0);
2887: }
2888: if (invJ) {
2889: invDet = 1.0/detJ;
2890: invJ[0] = invDet*J[3];
2891: invJ[1] = -invDet*J[1];
2892: invJ[2] = -invDet*J[2];
2893: invJ[3] = invDet*J[0];
2894: PetscLogFlopsNoError(5.0);
2895: }
2896: };
2897: void computeTetrahedronGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2898: const double *coords = this->restrictClosure(coordinates, e);
2899: const int dim = 3;
2900: double invDet;
2902: if (v0) {
2903: for(int d = 0; d < dim; d++) {
2904: v0[d] = coords[d];
2905: }
2906: }
2907: if (J) {
2908: for(int d = 0; d < dim; d++) {
2909: for(int f = 0; f < dim; f++) {
2910: J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2911: }
2912: }
2913: // The minus sign is here since I orient the first face to get the outward normal
2914: detJ = -(J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2915: J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2916: J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
2917: PetscLogFlopsNoError(18.0 + 12.0);
2918: }
2919: if (invJ) {
2920: invDet = -1.0/detJ;
2921: invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2922: invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
2923: invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2924: invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2925: invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
2926: invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2927: invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2928: invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
2929: invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2930: PetscLogFlopsNoError(37.0);
2931: }
2932: };
2933: void computeHexahedralGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double point[], double v0[], double J[], double invJ[], double& detJ) {
2934: const double *coords = this->restrictClosure(coordinates, e);
2935: const int dim = 3;
2936: double invDet;
2938: if (v0) {
2939: for(int d = 0; d < dim; d++) {
2940: v0[d] = coords[d];
2941: }
2942: }
2943: if (J) {
2944: double x_1 = coords[3] - coords[0];
2945: double y_1 = coords[4] - coords[1];
2946: double z_1 = coords[5] - coords[2];
2947: double x_2 = coords[6] - coords[0];
2948: double y_2 = coords[7] - coords[1];
2949: double z_2 = coords[8] - coords[2];
2950: double x_3 = coords[9] - coords[0];
2951: double y_3 = coords[10] - coords[1];
2952: double z_3 = coords[11] - coords[2];
2953: double x_4 = coords[12] - coords[0];
2954: double y_4 = coords[13] - coords[1];
2955: double z_4 = coords[14] - coords[2];
2956: double x_5 = coords[15] - coords[0];
2957: double y_5 = coords[16] - coords[1];
2958: double z_5 = coords[17] - coords[2];
2959: double x_6 = coords[18] - coords[0];
2960: double y_6 = coords[19] - coords[1];
2961: double z_6 = coords[20] - coords[2];
2962: double x_7 = coords[21] - coords[0];
2963: double y_7 = coords[22] - coords[1];
2964: double z_7 = coords[23] - coords[2];
2965: double g_x = x_1 - x_2 + x_3 + x_4 - x_5 + x_6 - x_7;
2966: double g_y = y_1 - y_2 + y_3 + y_4 - y_5 + y_6 - y_7;
2967: double g_z = z_1 - z_2 + z_3 + z_4 - z_5 + z_6 - z_7;
2969: J[0] = x_1 + (x_2 - x_1 - x_3)*point[1] + (x_5 - x_1 - x_4)*point[2] + g_x*point[1]*point[2];
2970: J[1] = x_3 + (x_2 - x_1 - x_3)*point[0] + (x_7 - x_3 - x_4)*point[2] + g_x*point[2]*point[0];
2971: J[2] = x_4 + (x_7 - x_3 - x_4)*point[1] + (x_5 - x_1 - x_4)*point[0] + g_x*point[0]*point[1];
2972: J[3] = y_1 + (y_2 - y_1 - y_3)*point[1] + (y_5 - y_1 - y_4)*point[2] + g_y*point[1]*point[2];
2973: J[4] = y_3 + (y_2 - y_1 - y_3)*point[0] + (y_7 - y_3 - y_4)*point[2] + g_y*point[2]*point[0];
2974: J[5] = y_4 + (y_7 - y_3 - y_4)*point[1] + (y_5 - y_1 - y_4)*point[0] + g_y*point[0]*point[1];
2975: J[6] = z_1 + (z_2 - z_1 - z_3)*point[1] + (z_5 - z_1 - z_4)*point[2] + g_z*point[1]*point[2];
2976: J[7] = z_3 + (z_2 - z_1 - z_3)*point[0] + (z_7 - z_3 - z_4)*point[2] + g_z*point[2]*point[0];
2977: J[8] = z_4 + (z_7 - z_3 - z_4)*point[1] + (z_5 - z_1 - z_4)*point[0] + g_z*point[0]*point[1];
2978: detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2979: J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2980: J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
2981: PetscLogFlopsNoError(39.0 + 81.0 + 12.0);
2982: }
2983: if (invJ) {
2984: invDet = 1.0/detJ;
2985: invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2986: invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
2987: invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2988: invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2989: invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
2990: invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2991: invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2992: invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
2993: invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2994: PetscLogFlopsNoError(37.0);
2995: }
2996: };
2997: void computeElementGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2998: if (this->_dim == 2) {
2999: computeTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
3000: } else if (this->_dim == 3) {
3001: computeTetrahedronGeometry(coordinates, e, v0, J, invJ, detJ);
3002: } else {
3003: throw ALE::Exception("Unsupported dimension for element geometry computation");
3004: }
3005: };
3006: void computeLineFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
3007: const typename arrow_section_type::point_type arrow(cell, face);
3008: const bool reversed = (this->getArrowSection("orientation")->restrictPoint(arrow)[0] == -2);
3009: const int dim = this->getDimension();
3010: double norm = 0.0;
3011: double *vec = tangent;
3013: if (f == 0) {
3014: vec[0] = 0.0; vec[1] = -1.0;
3015: } else if (f == 1) {
3016: vec[0] = 0.70710678; vec[1] = 0.70710678;
3017: } else if (f == 2) {
3018: vec[0] = -1.0; vec[1] = 0.0;
3019: }
3020: for(int d = 0; d < dim; ++d) {
3021: normal[d] = 0.0;
3022: for(int e = 0; e < dim; ++e) normal[d] += cellInvJ[e*dim+d]*vec[e];
3023: if (reversed) normal[d] = -normal[d];
3024: norm += normal[d]*normal[d];
3025: }
3026: norm = std::sqrt(norm);
3027: for(int d = 0; d < dim; ++d) {
3028: normal[d] /= norm;
3029: }
3030: tangent[0] = normal[1];
3031: tangent[1] = -normal[0];
3032: if (this->debug()) {
3033: std::cout << "Cell: " << cell << " Face: " << face << "("<<f<<")" << std::endl;
3034: for(int d = 0; d < dim; ++d) {
3035: std::cout << "Normal["<<d<<"]: " << normal[d] << " Tangent["<<d<<"]: " << tangent[d] << std::endl;
3036: }
3037: }
3038: // Now get 1D Jacobian info
3039: // Should be a way to get this directly
3040: const double *coords = this->restrictClosure(this->getRealSection("coordinates"), face);
3041: detJ = std::sqrt(PetscSqr(coords[1*2+0] - coords[0*2+0]) + PetscSqr(coords[1*2+1] - coords[0*2+1]))/2.0;
3042: invJ[0] = 1.0/detJ;
3043: };
3044: void computeTriangleFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
3045: const typename arrow_section_type::point_type arrow(cell, face);
3046: const bool reversed = this->getArrowSection("orientation")->restrictPoint(arrow)[0] < 0;
3047: const int dim = this->getDimension();
3048: const int faceDim = dim-1;
3049: double norm = 0.0;
3050: double *vec = tangent;
3052: if (f == 0) {
3053: vec[0] = 0.0; vec[1] = 0.0; vec[2] = -1.0;
3054: } else if (f == 1) {
3055: vec[0] = 0.0; vec[1] = -1.0; vec[2] = 0.0;
3056: } else if (f == 2) {
3057: vec[0] = 0.57735027; vec[1] = 0.57735027; vec[2] = 0.57735027;
3058: } else if (f == 3) {
3059: vec[0] = -1.0; vec[1] = 0.0; vec[2] = 0.0;
3060: }
3061: for(int d = 0; d < dim; ++d) {
3062: normal[d] = 0.0;
3063: for(int e = 0; e < dim; ++e) normal[d] += cellInvJ[e*dim+d]*vec[e];
3064: if (reversed) normal[d] = -normal[d];
3065: norm += normal[d]*normal[d];
3066: }
3067: norm = std::sqrt(norm);
3068: for(int d = 0; d < dim; ++d) {
3069: normal[d] /= norm;
3070: }
3071: // Get tangents
3072: tangent[0] = normal[1] - normal[2];
3073: tangent[1] = normal[2] - normal[0];
3074: tangent[2] = normal[0] - normal[1];
3075: norm = 0.0;
3076: for(int d = 0; d < dim; ++d) {
3077: norm += tangent[d]*tangent[d];
3078: }
3079: norm = std::sqrt(norm);
3080: for(int d = 0; d < dim; ++d) {
3081: tangent[d] /= norm;
3082: }
3083: tangent[3] = normal[1]*tangent[2] - normal[2]*tangent[1];
3084: tangent[4] = normal[2]*tangent[0] - normal[0]*tangent[2];
3085: tangent[5] = normal[0]*tangent[1] - normal[1]*tangent[0];
3086: if (this->debug()) {
3087: std::cout << "Cell: " << cell << " Face: " << face << "("<<f<<")" << std::endl;
3088: for(int d = 0; d < dim; ++d) {
3089: std::cout << "Normal["<<d<<"]: " << normal[d] << " TangentA["<<d<<"]: " << tangent[d] << " TangentB["<<d<<"]: " << tangent[dim+d] << std::endl;
3090: }
3091: }
3092: // Now get 2D Jacobian info
3093: // Should be a way to get this directly
3094: const double *coords = this->restrictClosure(this->getRealSection("coordinates"), face);
3095: // Rotate so that normal in z
3096: double invR[9], R[9];
3097: double detR, invDetR;
3098: for(int d = 0; d < dim; d++) {
3099: invR[d*dim+0] = tangent[d];
3100: invR[d*dim+1] = tangent[dim+d];
3101: invR[d*dim+2] = normal[d];
3102: }
3103: invDetR = (invR[0*3+0]*(invR[1*3+1]*invR[2*3+2] - invR[1*3+2]*invR[2*3+1]) +
3104: invR[0*3+1]*(invR[1*3+2]*invR[2*3+0] - invR[1*3+0]*invR[2*3+2]) +
3105: invR[0*3+2]*(invR[1*3+0]*invR[2*3+1] - invR[1*3+1]*invR[2*3+0]));
3106: detR = 1.0/invDetR;
3107: R[0*3+0] = detR*(invR[1*3+1]*invR[2*3+2] - invR[1*3+2]*invR[2*3+1]);
3108: R[0*3+1] = detR*(invR[0*3+2]*invR[2*3+1] - invR[0*3+1]*invR[2*3+2]);
3109: R[0*3+2] = detR*(invR[0*3+1]*invR[1*3+2] - invR[0*3+2]*invR[1*3+1]);
3110: R[1*3+0] = detR*(invR[1*3+2]*invR[2*3+0] - invR[1*3+0]*invR[2*3+2]);
3111: R[1*3+1] = detR*(invR[0*3+0]*invR[2*3+2] - invR[0*3+2]*invR[2*3+0]);
3112: R[1*3+2] = detR*(invR[0*3+2]*invR[1*3+0] - invR[0*3+0]*invR[1*3+2]);
3113: R[2*3+0] = detR*(invR[1*3+0]*invR[2*3+1] - invR[1*3+1]*invR[2*3+0]);
3114: R[2*3+1] = detR*(invR[0*3+1]*invR[2*3+0] - invR[0*3+0]*invR[2*3+1]);
3115: R[2*3+2] = detR*(invR[0*3+0]*invR[1*3+1] - invR[0*3+1]*invR[1*3+0]);
3116: for(int d = 0; d < dim; d++) {
3117: for(int e = 0; e < dim; e++) {
3118: invR[d*dim+e] = 0.0;
3119: for(int g = 0; g < dim; g++) {
3120: invR[d*dim+e] += R[e*dim+g]*coords[d*dim+g];
3121: }
3122: }
3123: }
3124: for(int d = dim-1; d >= 0; --d) {
3125: invR[d*dim+2] -= invR[0*dim+2];
3126: if (this->debug() && (d == dim-1)) {
3127: double ref[9];
3128: for(int q = 0; q < dim; q++) {
3129: for(int e = 0; e < dim; e++) {
3130: ref[q*dim+e] = 0.0;
3131: for(int g = 0; g < dim; g++) {
3132: ref[q*dim+e] += cellInvJ[e*dim+g]*coords[q*dim+g];
3133: }
3134: }
3135: }
3136: std::cout << "f: " << f << std::endl;
3137: std::cout << this->printMatrix(std::string("coords"), dim, dim, coords) << std::endl;
3138: std::cout << this->printMatrix(std::string("ref coords"), dim, dim, ref) << std::endl;
3139: std::cout << this->printMatrix(std::string("R"), dim, dim, R) << std::endl;
3140: std::cout << this->printMatrix(std::string("invR"), dim, dim, invR) << std::endl;
3141: }
3142: if (fabs(invR[d*dim+2]) > 1.0e-8) {
3143: throw ALE::Exception("Invalid rotation");
3144: }
3145: }
3146: double J[4];
3147: for(int d = 0; d < faceDim; d++) {
3148: for(int e = 0; e < faceDim; e++) {
3149: J[d*faceDim+e] = 0.5*(invR[(e+1)*dim+d] - invR[0*dim+d]);
3150: }
3151: }
3152: detJ = fabs(J[0]*J[3] - J[1]*J[2]);
3153: // Probably need something here if detJ < 0
3154: const double invDet = 1.0/detJ;
3155: invJ[0] = invDet*J[3];
3156: invJ[1] = -invDet*J[1];
3157: invJ[2] = -invDet*J[2];
3158: invJ[3] = invDet*J[0];
3159: };
3160: void computeFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
3161: if (this->_dim == 2) {
3162: computeLineFaceGeometry(cell, face, f, cellInvJ, invJ, detJ, normal, tangent);
3163: } else if (this->_dim == 3) {
3164: computeTriangleFaceGeometry(cell, face, f, cellInvJ, invJ, detJ, normal, tangent);
3165: } else {
3166: throw ALE::Exception("Unsupported dimension for element geometry computation");
3167: }
3168: };
3169: double getMaxVolume() {
3170: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3171: const Obj<label_sequence>& cells = this->heightStratum(0);
3172: const int dim = this->getDimension();
3173: double v0[3], J[9], invJ[9], detJ, refVolume = 0.0, maxVolume = 0.0;
3175: if (dim == 1) refVolume = 2.0;
3176: if (dim == 2) refVolume = 2.0;
3177: if (dim == 3) refVolume = 4.0/3.0;
3178: for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
3179: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
3180: maxVolume = std::max(maxVolume, detJ*refVolume);
3181: }
3182: return maxVolume;
3183: };
3184: // Find the cell in which this point lies (stupid algorithm)
3185: point_type locatePoint_2D(const typename real_section_type::value_type point[]) {
3186: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3187: const Obj<label_sequence>& cells = this->heightStratum(0);
3188: const int embedDim = 2;
3189: double v0[2], J[4], invJ[4], detJ;
3191: for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
3192: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
3193: double xi = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]);
3194: double eta = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]);
3196: if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) {
3197: return *c_iter;
3198: }
3199: }
3200: throw ALE::Exception("Could not locate point");
3201: };
3202: // Assume a simplex and 3D
3203: point_type locatePoint_3D(const typename real_section_type::value_type point[]) {
3204: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3205: const Obj<label_sequence>& cells = this->heightStratum(0);
3206: const int embedDim = 3;
3207: double v0[3], J[9], invJ[9], detJ;
3209: for(typename label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
3210: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
3211: double xi = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]) + invJ[0*embedDim+2]*(point[2] - v0[2]);
3212: double eta = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]) + invJ[1*embedDim+2]*(point[2] - v0[2]);
3213: double zeta = invJ[2*embedDim+0]*(point[0] - v0[0]) + invJ[2*embedDim+1]*(point[1] - v0[1]) + invJ[2*embedDim+2]*(point[2] - v0[2]);
3215: if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) {
3216: return *c_iter;
3217: }
3218: }
3219: throw ALE::Exception("Could not locate point");
3220: };
3221: point_type locatePoint(const typename real_section_type::value_type point[], point_type guess = -1) {
3222: //guess overrides this by saying that we already know the relation of this point to this mesh. We will need to make it a more robust "guess" later for more than P1
3223: if (guess != -1) {
3224: return guess;
3225: }else if (this->_dim == 2) {
3226: return locatePoint_2D(point);
3227: } else if (this->_dim == 3) {
3228: return locatePoint_3D(point);
3229: } else {
3230: throw ALE::Exception("No point location for mesh dimension");
3231: }
3232: };
3233: public: // Discretization
3234: void markBoundaryCells(const std::string& name, const int marker = 1, const int newMarker = 2, const bool onlyVertices = false) {
3235: const Obj<label_type>& label = this->getLabel(name);
3236: const Obj<label_sequence>& boundary = this->getLabelStratum(name, marker);
3237: const Obj<sieve_type>& sieve = this->getSieve();
3239: if (!onlyVertices) {
3240: const typename label_sequence::iterator end = boundary->end();
3242: for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != end; ++e_iter) {
3243: if (this->height(*e_iter) == 1) {
3244: const point_type cell = *sieve->support(*e_iter)->begin();
3246: this->setValue(label, cell, newMarker);
3247: }
3248: }
3249: } else {
3250: const typename label_sequence::iterator end = boundary->end();
3251: const int depth = this->depth();
3253: for(typename label_sequence::iterator v_iter = boundary->begin(); v_iter != end; ++v_iter) {
3254: const Obj<supportArray> support = sieve->nSupport(*v_iter, depth);
3255: const typename supportArray::iterator sEnd = support->end();
3257: for(typename supportArray::iterator c_iter = support->begin(); c_iter != sEnd; ++c_iter) {
3258: const Obj<typename sieve_type::traits::coneSequence>& cone = sieve->cone(*c_iter);
3259: const typename sieve_type::traits::coneSequence::iterator cEnd = cone->end();
3261: for(typename sieve_type::traits::coneSequence::iterator e_iter = cone->begin(); e_iter != cEnd; ++e_iter) {
3262: if (sieve->support(*e_iter)->size() == 1) {
3263: this->setValue(label, *c_iter, newMarker);
3264: break;
3265: }
3266: }
3267: }
3268: }
3269: }
3270: };
3271: int setFiberDimensions(const Obj<real_section_type>& s, const Obj<names_type>& discs, names_type& bcLabels) {
3272: const int debug = this->debug();
3273: int maxDof = 0;
3275: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter) {
3276: s->addSpace();
3277: }
3278: for(int d = 0; d <= this->_dim; ++d) {
3279: int numDof = 0;
3280: int f = 0;
3282: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3283: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
3284: const int sDof = disc->getNumDof(d);
3286: numDof += sDof;
3287: if (sDof) s->setFiberDimension(this->depthStratum(d), sDof, f);
3288: }
3289: if (numDof) s->setFiberDimension(this->depthStratum(d), numDof);
3290: maxDof = std::max(maxDof, numDof);
3291: }
3292: // Process exclusions
3293: int f = 0;
3295: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3296: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
3297: std::string labelName = "exclude-"+*f_iter;
3298: std::set<point_type> seen;
3300: if (this->hasLabel(labelName)) {
3301: const Obj<label_type>& label = this->getLabel(labelName);
3302: const Obj<label_sequence>& exclusion = this->getLabelStratum(labelName, 1);
3303: const typename label_sequence::iterator end = exclusion->end();
3304: if (debug > 1) {label->view(labelName.c_str());}
3306: for(typename label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
3307: const Obj<coneArray> closure = ALE::SieveAlg<ALE::Mesh<IndexType,ScalarType> >::closure(this, this->getArrowSection("orientation"), *e_iter);
3308: const typename coneArray::iterator cEnd = closure->end();
3310: for(typename coneArray::iterator c_iter = closure->begin(); c_iter != cEnd; ++c_iter) {
3311: if (seen.find(*c_iter) != seen.end()) continue;
3312: if (this->getValue(label, *c_iter) == 1) {
3313: seen.insert(*c_iter);
3314: s->setFiberDimension(*c_iter, 0, f);
3315: s->addFiberDimension(*c_iter, -disc->getNumDof(this->depth(*c_iter)));
3316: if (debug > 1) {std::cout << " cell: " << *c_iter << " dim: " << disc->getNumDof(this->depth(*c_iter)) << std::endl;}
3317: }
3318: }
3319: }
3320: }
3321: }
3322: // Process constraints
3323: f = 0;
3324: for(typename std::set<std::string>::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3325: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
3326: const Obj<std::set<std::string> > bcs = disc->getBoundaryConditions();
3327: std::string excludeName = "exclude-"+*f_iter;
3329: for(typename std::set<std::string>::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter) {
3330: const Obj<ALE::BoundaryCondition>& bc = disc->getBoundaryCondition(*bc_iter);
3331: const Obj<label_sequence>& boundary = this->getLabelStratum(bc->getLabelName(), bc->getMarker());
3333: bcLabels.insert(bc->getLabelName());
3334: if (this->hasLabel(excludeName)) {
3335: const Obj<label_type>& label = this->getLabel(excludeName);
3337: for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
3338: if (!this->getValue(label, *e_iter)) {
3339: const int numDof = disc->getNumDof(this->depth(*e_iter));
3341: if (numDof) s->addConstraintDimension(*e_iter, numDof);
3342: if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
3343: }
3344: }
3345: } else {
3346: for(typename label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
3347: const int numDof = disc->getNumDof(this->depth(*e_iter));
3349: if (numDof) s->addConstraintDimension(*e_iter, numDof);
3350: if (numDof) s->setConstraintDimension(*e_iter, numDof, f);
3351: }
3352: }
3353: }
3354: }
3355: return maxDof;
3356: };
3357: void calculateIndices() {
3358: // Should have an iterator over the whole tree
3359: Obj<names_type> discs = this->getDiscretizations();
3360: Obj<Mesh> mesh = this;
3361: const int debug = this->debug();
3362: std::map<std::string, std::pair<int, int*> > indices;
3364: mesh.addRef();
3365: for(names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
3366: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
3368: indices[*d_iter] = std::pair<int, int*>(0, new int[disc->size(mesh)]);
3369: disc->setIndices(indices[*d_iter].second);
3370: }
3371: const Obj<label_sequence>& cells = this->heightStratum(0);
3372: const Obj<coneArray> closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *cells->begin());
3373: const typename coneArray::iterator end = closure->end();
3374: int offset = 0;
3376: if (debug > 1) {std::cout << "Closure for first element" << std::endl;}
3377: for(typename coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
3378: const int dim = this->depth(*cl_iter);
3380: if (debug > 1) {std::cout << " point " << *cl_iter << " depth " << dim << std::endl;}
3381: for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
3382: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
3383: const int num = disc->getNumDof(dim);
3385: if (debug > 1) {std::cout << " disc " << disc->getName() << " numDof " << num << std::endl;}
3386: for(int o = 0; o < num; ++o) {
3387: indices[*d_iter].second[indices[*d_iter].first++] = offset++;
3388: }
3389: }
3390: }
3391: if (debug > 1) {
3392: for(typename names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
3393: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
3395: std::cout << "Discretization " << disc->getName() << " indices:";
3396: for(int i = 0; i < indices[*d_iter].first; ++i) {
3397: std::cout << " " << indices[*d_iter].second[i];
3398: }
3399: std::cout << std::endl;
3400: }
3401: }
3402: };
3403: void calculateIndicesExcluded(const Obj<real_section_type>& s, const Obj<names_type>& discs) {
3404: typedef std::map<std::string, std::pair<int, indexSet> > indices_type;
3405: const Obj<label_type>& indexLabel = this->createLabel("cellExclusion");
3406: const int debug = this->debug();
3407: int marker = 0;
3408: Obj<Mesh> mesh = this;
3409: std::map<indices_type, int> indexMap;
3410: indices_type indices;
3412: mesh.addRef();
3413: for(names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
3414: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
3415: const int size = disc->size(mesh);
3417: indices[*d_iter].second.resize(size);
3418: }
3419: const names_type::const_iterator dBegin = discs->begin();
3420: const names_type::const_iterator dEnd = discs->end();
3421: std::set<point_type> seen;
3422: int f = 0;
3424: for(names_type::const_iterator f_iter = dBegin; f_iter != dEnd; ++f_iter, ++f) {
3425: std::string labelName = "exclude-"+*f_iter;
3427: if (this->hasLabel(labelName)) {
3428: const Obj<label_sequence>& exclusion = this->getLabelStratum(labelName, 1);
3429: const typename label_sequence::iterator end = exclusion->end();
3431: if (debug > 1) {std::cout << "Processing exclusion " << labelName << std::endl;}
3432: for(typename label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
3433: if (this->height(*e_iter)) continue;
3434: const Obj<coneArray> closure = ALE::SieveAlg<ALE::Mesh<IndexType,ScalarType> >::closure(this, this->getArrowSection("orientation"), *e_iter);
3435: const typename coneArray::iterator clEnd = closure->end();
3436: int offset = 0;
3438: if (debug > 1) {std::cout << " Closure for cell " << *e_iter << std::endl;}
3439: for(typename coneArray::iterator cl_iter = closure->begin(); cl_iter != clEnd; ++cl_iter) {
3440: int g = 0;
3442: if (debug > 1) {std::cout << " point " << *cl_iter << std::endl;}
3443: for(typename names_type::const_iterator g_iter = dBegin; g_iter != dEnd; ++g_iter, ++g) {
3444: const int fDim = s->getFiberDimension(*cl_iter, g);
3446: if (debug > 1) {std::cout << " disc " << *g_iter << " numDof " << fDim << std::endl;}
3447: for(int d = 0; d < fDim; ++d) {
3448: indices[*g_iter].second[indices[*g_iter].first++] = offset++;
3449: }
3450: }
3451: }
3452: const typename std::map<indices_type, int>::iterator entry = indexMap.find(indices);
3454: if (debug > 1) {
3455: for(typename std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
3456: for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3457: std::cout << "Discretization (" << i_iter->second << ") " << *g_iter << " indices:";
3458: for(int i = 0; i < ((indices_type) i_iter->first)[*g_iter].first; ++i) {
3459: std::cout << " " << ((indices_type) i_iter->first)[*g_iter].second[i];
3460: }
3461: std::cout << std::endl;
3462: }
3463: std::cout << "Comparison: " << (indices == i_iter->first) << std::endl;
3464: }
3465: for(typename names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3466: std::cout << "Discretization " << *g_iter << " indices:";
3467: for(int i = 0; i < indices[*g_iter].first; ++i) {
3468: std::cout << " " << indices[*g_iter].second[i];
3469: }
3470: std::cout << std::endl;
3471: }
3472: }
3473: if (entry != indexMap.end()) {
3474: this->setValue(indexLabel, *e_iter, entry->second);
3475: if (debug > 1) {std::cout << " Found existing indices with marker " << entry->second << std::endl;}
3476: } else {
3477: indexMap[indices] = ++marker;
3478: this->setValue(indexLabel, *e_iter, marker);
3479: if (debug > 1) {std::cout << " Created new indices with marker " << marker << std::endl;}
3480: }
3481: for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3482: indices[*g_iter].first = 0;
3483: for(unsigned int i = 0; i < indices[*g_iter].second.size(); ++i) indices[*g_iter].second[i] = 0;
3484: }
3485: }
3486: }
3487: }
3488: if (debug > 1) {indexLabel->view("cellExclusion");}
3489: for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
3490: if (debug > 1) {std::cout << "Setting indices for marker " << i_iter->second << std::endl;}
3491: for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
3492: const Obj<Discretization>& disc = this->getDiscretization(*g_iter);
3493: const indexSet indSet = ((indices_type) i_iter->first)[*g_iter].second;
3494: const int size = indSet.size();
3495: int *_indices = new int[size];
3497: if (debug > 1) {std::cout << " field " << *g_iter << std::endl;}
3498: for(int i = 0; i < size; ++i) {
3499: _indices[i] = indSet[i];
3500: if (debug > 1) {std::cout << " indices["<<i<<"] = " << _indices[i] << std::endl;}
3501: }
3502: disc->setIndices(_indices, i_iter->second);
3503: }
3504: }
3505: };
3506: void setupField(const Obj<real_section_type>& s, const int cellMarker = 2, const bool noUpdate = false) {
3507: const Obj<names_type>& discs = this->getDiscretizations();
3508: const int debug = s->debug();
3509: names_type bcLabels;
3510: int maxDof;
3512: maxDof = this->setFiberDimensions(s, discs, bcLabels);
3513: this->calculateIndices();
3514: this->calculateIndicesExcluded(s, discs);
3515: this->allocate(s);
3516: s->defaultConstraintDof();
3517: const Obj<label_type>& cellExclusion = this->getLabel("cellExclusion");
3519: if (debug > 1) {std::cout << "Setting boundary values" << std::endl;}
3520: for(names_type::const_iterator n_iter = bcLabels.begin(); n_iter != bcLabels.end(); ++n_iter) {
3521: const Obj<label_sequence>& boundaryCells = this->getLabelStratum(*n_iter, cellMarker);
3522: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3523: const Obj<names_type>& discs = this->getDiscretizations();
3524: const point_type firstCell = *boundaryCells->begin();
3525: const int numFields = discs->size();
3526: typename real_section_type::value_type *values = new typename real_section_type::value_type[this->sizeWithBC(s, firstCell)];
3527: int *dofs = new int[maxDof];
3528: int *v = new int[numFields];
3529: typename real_section_type::value_type *v0 = new typename real_section_type::value_type[this->getDimension()];
3530: typename real_section_type::value_type *J = new typename real_section_type::value_type[this->getDimension()*this->getDimension()];
3531: typename real_section_type::value_type detJ;
3533: for(typename label_sequence::iterator c_iter = boundaryCells->begin(); c_iter != boundaryCells->end(); ++c_iter) {
3534: const Obj<coneArray> closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *c_iter);
3535: const typename coneArray::iterator end = closure->end();
3537: if (debug > 1) {std::cout << " Boundary cell " << *c_iter << std::endl;}
3538: this->computeElementGeometry(coordinates, *c_iter, v0, J, PETSC_NULL, detJ);
3539: for(int f = 0; f < numFields; ++f) v[f] = 0;
3540: for(typename coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
3541: const int cDim = s->getConstraintDimension(*cl_iter);
3542: int off = 0;
3543: int f = 0;
3544: int i = -1;
3546: if (debug > 1) {std::cout << " point " << *cl_iter << std::endl;}
3547: if (cDim) {
3548: if (debug > 1) {std::cout << " constrained excMarker: " << this->getValue(cellExclusion, *c_iter) << std::endl;}
3549: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3550: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
3551: const Obj<names_type> bcs = disc->getBoundaryConditions();
3552: const int fDim = s->getFiberDimension(*cl_iter, f);//disc->getNumDof(this->depth(*cl_iter));
3553: const int *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
3554: int b = 0;
3556: for(names_type::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter, ++b) {
3557: const Obj<ALE::BoundaryCondition>& bc = disc->getBoundaryCondition(*bc_iter);
3558: const int value = this->getValue(this->getLabel(bc->getLabelName()), *cl_iter);
3560: if (b > 0) v[f] -= fDim;
3561: if (value == bc->getMarker()) {
3562: if (debug > 1) {std::cout << " field " << *f_iter << " marker " << value << std::endl;}
3563: for(int d = 0; d < fDim; ++d, ++v[f]) {
3564: dofs[++i] = off+d;
3565: if (!noUpdate) values[indices[v[f]]] = (*bc->getDualIntegrator())(v0, J, v[f], bc->getFunction());
3566: if (debug > 1) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3567: }
3568: // Allow only one condition per point
3569: ++b;
3570: break;
3571: } else {
3572: if (debug > 1) {std::cout << " field " << *f_iter << std::endl;}
3573: for(int d = 0; d < fDim; ++d, ++v[f]) {
3574: values[indices[v[f]]] = 0.0;
3575: if (debug > 1) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3576: }
3577: }
3578: }
3579: if (b == 0) {
3580: if (debug > 1) {std::cout << " field " << *f_iter << std::endl;}
3581: for(int d = 0; d < fDim; ++d, ++v[f]) {
3582: values[indices[v[f]]] = 0.0;
3583: if (debug > 1) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3584: }
3585: }
3586: off += fDim;
3587: }
3588: if (i != cDim-1) {throw ALE::Exception("Invalid constraint initialization");}
3589: s->setConstraintDof(*cl_iter, dofs);
3590: } else {
3591: if (debug > 1) {std::cout << " unconstrained" << std::endl;}
3592: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3593: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
3594: const int fDim = s->getFiberDimension(*cl_iter, f);//disc->getNumDof(this->depth(*cl_iter));
3595: const int *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
3597: if (debug > 1) {std::cout << " field " << *f_iter << std::endl;}
3598: for(int d = 0; d < fDim; ++d, ++v[f]) {
3599: values[indices[v[f]]] = 0.0;
3600: if (debug > 1) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
3601: }
3602: }
3603: }
3604: }
3605: if (debug > 1) {
3606: const Obj<coneArray> closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *c_iter);
3607: const typename coneArray::iterator end = closure->end();
3609: for(int f = 0; f < numFields; ++f) v[f] = 0;
3610: for(typename coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
3611: int f = 0;
3612: for(typename names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
3613: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
3614: const int fDim = s->getFiberDimension(*cl_iter, f);
3615: const int *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
3617: for(int d = 0; d < fDim; ++d, ++v[f]) {
3618: std::cout << " "<<*f_iter<<"-value["<<indices[v[f]]<<"] " << values[indices[v[f]]] << std::endl;
3619: }
3620: }
3621: }
3622: }
3623: if (!noUpdate) {
3624: this->updateAll(s, *c_iter, values);
3625: }
3626: }
3627: delete [] dofs;
3628: delete [] values;
3629: delete [] v0;
3630: delete [] J;
3631: }
3632: if (debug > 1) {s->view("");}
3633: };
3634: public:
3635: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
3636: if (comm == MPI_COMM_NULL) {
3637: comm = this->comm();
3638: }
3639: if (name == "") {
3640: PetscPrintf(comm, "viewing a Mesh\n");
3641: } else {
3642: PetscPrintf(comm, "viewing Mesh '%s'\n", name.c_str());
3643: }
3644: this->getSieve()->view("mesh sieve", comm);
3645: Obj<names_type> sections = this->getRealSections();
3647: for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
3648: this->getRealSection(*name)->view(*name);
3649: }
3650: sections = this->getIntSections();
3651: for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
3652: this->getIntSection(*name)->view(*name);
3653: }
3654: sections = this->getArrowSections();
3655: for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
3656: this->getArrowSection(*name)->view(*name);
3657: }
3658: };
3659: template<typename value_type>
3660: static std::string printMatrix(const std::string& name, const int rows, const int cols, const value_type matrix[], const int rank = -1)
3661: {
3662: ostringstream output;
3663: ostringstream rankStr;
3665: if (rank >= 0) {
3666: rankStr << "[" << rank << "]";
3667: }
3668: output << rankStr.str() << name << " = " << std::endl;
3669: for(int r = 0; r < rows; r++) {
3670: if (r == 0) {
3671: output << rankStr.str() << " /";
3672: } else if (r == rows-1) {
3673: output << rankStr.str() << " \\";
3674: } else {
3675: output << rankStr.str() << " |";
3676: }
3677: for(int c = 0; c < cols; c++) {
3678: output << " " << matrix[r*cols+c];
3679: }
3680: if (r == 0) {
3681: output << " \\" << std::endl;
3682: } else if (r == rows-1) {
3683: output << " /" << std::endl;
3684: } else {
3685: output << " |" << std::endl;
3686: }
3687: }
3688: return output.str();
3689: }
3690: };
3691: template<typename Mesh>
3692: class MeshBuilder {
3693: public:
3694: typedef typename Mesh::real_section_type::value_type real;
3695: public:
3698: /*
3699: Simple square boundary:
3701: 18--5-17--4--16
3702: | | |
3703: 6 10 3
3704: | | |
3705: 19-11-20--9--15
3706: | | |
3707: 7 8 2
3708: | | |
3709: 12--0-13--1--14
3710: */
3711: static Obj<Mesh> createSquareBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int edges[], const int debug = 0) {
3712: Obj<Mesh> mesh = new Mesh(comm, 1, debug);
3713: int numVertices = (edges[0]+1)*(edges[1]+1);
3714: int numEdges = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
3715: real *coords = new real[numVertices*2];
3716: const Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
3717: typename Mesh::point_type *vertices = new typename Mesh::point_type[numVertices];
3718: int order = 0;
3720: mesh->setSieve(sieve);
3721: const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
3722: if (mesh->commRank() == 0) {
3723: /* Create sieve and ordering */
3724: for(int v = numEdges; v < numEdges+numVertices; v++) {
3725: vertices[v-numEdges] = typename Mesh::point_type(v);
3726: }
3727: for(int vy = 0; vy <= edges[1]; vy++) {
3728: for(int ex = 0; ex < edges[0]; ex++) {
3729: typename Mesh::point_type edge(vy*edges[0] + ex);
3730: int vertex = vy*(edges[0]+1) + ex;
3732: sieve->addArrow(vertices[vertex+0], edge, order++);
3733: sieve->addArrow(vertices[vertex+1], edge, order++);
3734: if ((vy == 0) || (vy == edges[1])) {
3735: mesh->setValue(markers, edge, 1);
3736: mesh->setValue(markers, vertices[vertex], 1);
3737: if (ex == edges[0]-1) {
3738: mesh->setValue(markers, vertices[vertex+1], 1);
3739: }
3740: }
3741: }
3742: }
3743: for(int vx = 0; vx <= edges[0]; vx++) {
3744: for(int ey = 0; ey < edges[1]; ey++) {
3745: typename Mesh::point_type edge(vx*edges[1] + ey + edges[0]*(edges[1]+1));
3746: int vertex = ey*(edges[0]+1) + vx;
3748: sieve->addArrow(vertices[vertex], edge, order++);
3749: sieve->addArrow(vertices[vertex+edges[0]+1], edge, order++);
3750: if ((vx == 0) || (vx == edges[0])) {
3751: mesh->setValue(markers, edge, 1);
3752: mesh->setValue(markers, vertices[vertex], 1);
3753: if (ey == edges[1]-1) {
3754: mesh->setValue(markers, vertices[vertex+edges[0]+1], 1);
3755: }
3756: }
3757: }
3758: }
3759: }
3760: mesh->stratify();
3761: for(int vy = 0; vy <= edges[1]; ++vy) {
3762: for(int vx = 0; vx <= edges[0]; ++vx) {
3763: coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
3764: coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
3765: }
3766: }
3767: delete [] vertices;
3768: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
3769: return mesh;
3770: };
3773: /*
3774: Simple square boundary:
3776: 14--5-13--4--12
3777: | |
3778: 6 3
3779: | |
3780: 15 11
3781: | |
3782: 7 2
3783: | |
3784: 8--0--9--1--10
3785: */
3786: static Obj<Mesh> createSquareBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int edges, const int debug = 0) {
3787: Obj<Mesh> mesh = new Mesh(comm, 1, debug);
3788: int numVertices = edges*4;
3789: int numEdges = edges*4;
3790: real *coords = new real[numVertices*2];
3791: const Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
3792: typename Mesh::point_type *vertices = new typename Mesh::point_type[numVertices];
3794: mesh->setSieve(sieve);
3795: const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
3796: if (mesh->commRank() == 0) {
3797: /* Create sieve and ordering */
3798: for(int v = numEdges; v < numEdges+numVertices; v++) {
3799: vertices[v-numEdges] = typename Mesh::point_type(v);
3800: }
3801: for(int e = 0; e < numEdges; ++e) {
3802: typename Mesh::point_type edge(e);
3803: int order = 0;
3805: sieve->addArrow(vertices[e], edge, order++);
3806: sieve->addArrow(vertices[(e+1)%numVertices], edge, order++);
3807: mesh->setValue(markers, edge, 2);
3808: mesh->setValue(markers, vertices[e], 1);
3809: mesh->setValue(markers, vertices[(e+1)%numVertices], 1);
3810: }
3811: }
3812: mesh->stratify();
3813: for(int v = 0; v < edges; ++v) {
3814: coords[(v+edges*0)*2+0] = lower[0] + ((upper[0] - lower[0])/edges)*v;
3815: coords[(v+edges*0)*2+1] = lower[1];
3816: }
3817: for(int v = 0; v < edges; ++v) {
3818: coords[(v+edges*1)*2+0] = upper[0];
3819: coords[(v+edges*1)*2+1] = lower[1] + ((upper[1] - lower[1])/edges)*v;
3820: }
3821: for(int v = 0; v < edges; ++v) {
3822: coords[(v+edges*2)*2+0] = upper[0] - ((upper[0] - lower[0])/edges)*v;
3823: coords[(v+edges*2)*2+1] = upper[1];
3824: }
3825: for(int v = 0; v < edges; ++v) {
3826: coords[(v+edges*3)*2+0] = lower[0];
3827: coords[(v+edges*3)*2+1] = upper[1] - ((upper[1] - lower[1])/edges)*v;
3828: }
3829: delete [] vertices;
3830: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
3831: // Build normals for cells
3832: const Obj<typename Mesh::real_section_type>& normals = mesh->getRealSection("normals");
3833: const Obj<typename Mesh::label_sequence>& cells = mesh->heightStratum(0);
3835: //normals->setChart(typename Mesh::real_section_type::chart_type(*std::min_element(cells->begin(), cells->end()),
3836: // *std::max_element(cells->begin(), cells->end())+1));
3837: normals->setFiberDimension(cells, mesh->getDimension()+1);
3838: mesh->allocate(normals);
3839: for(int e = 0; e < edges; ++e) {
3840: real normal[2] = {0.0, -1.0};
3841: normals->updatePoint(e+edges*0, normal);
3842: }
3843: for(int e = 0; e < edges; ++e) {
3844: real normal[2] = {1.0, 0.0};
3845: normals->updatePoint(e+edges*1, normal);
3846: }
3847: for(int e = 0; e < edges; ++e) {
3848: real normal[2] = {0.0, 1.0};
3849: normals->updatePoint(e+edges*2, normal);
3850: }
3851: for(int e = 0; e < edges; ++e) {
3852: real normal[2] = {-1.0, 0.0};
3853: normals->updatePoint(e+edges*3, normal);
3854: }
3855: return mesh;
3856: };
3859: /*
3860: Simple square boundary:
3862: 18--5-17--4--16
3863: | | |
3864: 6 10 3
3865: | | |
3866: 19-11-20--9--15
3867: | | |
3868: 7 8 2
3869: | | |
3870: 12--0-13--1--14
3871: */
3872: static Obj<Mesh> createParticleInSquareBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int edges[], const real radius, const int partEdges, const int debug = 0) {
3873: Obj<Mesh> mesh = new Mesh(comm, 1, debug);
3874: const int numSquareVertices = (edges[0]+1)*(edges[1]+1);
3875: const int numVertices = numSquareVertices + partEdges;
3876: const int numSquareEdges = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
3877: const int numEdges = numSquareEdges + partEdges;
3878: real *coords = new real[numVertices*2];
3879: const Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
3880: typename Mesh::point_type *vertices = new typename Mesh::point_type[numVertices];
3881: int order = 0;
3883: mesh->setSieve(sieve);
3884: const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
3885: if (mesh->commRank() == 0) {
3886: /* Create sieve and ordering */
3887: for(int v = numEdges; v < numEdges+numVertices; v++) {
3888: vertices[v-numEdges] = typename Mesh::point_type(v);
3889: }
3890: // Make square
3891: for(int vy = 0; vy <= edges[1]; vy++) {
3892: for(int ex = 0; ex < edges[0]; ex++) {
3893: typename Mesh::point_type edge(vy*edges[0] + ex);
3894: int vertex = vy*(edges[0]+1) + ex;
3896: sieve->addArrow(vertices[vertex+0], edge, order++);
3897: sieve->addArrow(vertices[vertex+1], edge, order++);
3898: if ((vy == 0) || (vy == edges[1])) {
3899: mesh->setValue(markers, edge, 1);
3900: mesh->setValue(markers, vertices[vertex], 1);
3901: if (ex == edges[0]-1) {
3902: mesh->setValue(markers, vertices[vertex+1], 1);
3903: }
3904: }
3905: }
3906: }
3907: for(int vx = 0; vx <= edges[0]; vx++) {
3908: for(int ey = 0; ey < edges[1]; ey++) {
3909: typename Mesh::point_type edge(vx*edges[1] + ey + edges[0]*(edges[1]+1));
3910: int vertex = ey*(edges[0]+1) + vx;
3912: sieve->addArrow(vertices[vertex], edge, order++);
3913: sieve->addArrow(vertices[vertex+edges[0]+1], edge, order++);
3914: if ((vx == 0) || (vx == edges[0])) {
3915: mesh->setValue(markers, edge, 1);
3916: mesh->setValue(markers, vertices[vertex], 1);
3917: if (ey == edges[1]-1) {
3918: mesh->setValue(markers, vertices[vertex+edges[0]+1], 1);
3919: }
3920: }
3921: }
3922: }
3923: // Make particle
3924: for(int ep = 0; ep < partEdges; ++ep) {
3925: typename Mesh::point_type edge(numSquareEdges + ep);
3926: const int vertexA = numSquareVertices + ep;
3927: const int vertexB = numSquareVertices + (ep+1)%partEdges;
3929: sieve->addArrow(vertices[vertexA], edge, order++);
3930: sieve->addArrow(vertices[vertexB], edge, order++);
3931: mesh->setValue(markers, edge, 2);
3932: mesh->setValue(markers, vertices[vertexA], 2);
3933: mesh->setValue(markers, vertices[vertexB], 2);
3934: }
3935: }
3936: mesh->stratify();
3937: for(int vy = 0; vy <= edges[1]; ++vy) {
3938: for(int vx = 0; vx <= edges[0]; ++vx) {
3939: coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
3940: coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
3941: }
3942: }
3943: const real centroidX = 0.5*(upper[0] + lower[0]);
3944: const real centroidY = 0.5*(upper[1] + lower[1]);
3945: for(int vp = 0; vp < partEdges; ++vp) {
3946: const real rad = 2.0*PETSC_PI*vp/partEdges;
3947: coords[(numSquareVertices+vp)*2+0] = centroidX + radius*cos(rad);
3948: coords[(numSquareVertices+vp)*2+1] = centroidY + radius*sin(rad);
3949: }
3950: delete [] vertices;
3951: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
3952: return mesh;
3953: };
3956: /*
3957: Simple boundary with reentrant singularity:
3959: 12--5-11
3960: | |
3961: | 4
3962: | |
3963: 6 10--3--9
3964: | |
3965: | 2
3966: | |
3967: 7-----1-----8
3968: */
3969: static Obj<Mesh> createReentrantBoundary(const MPI_Comm comm, const real lower[], const real upper[], real notchpercent[], const int debug = 0) {
3970: Obj<Mesh> mesh = new Mesh(comm, 1, debug);
3971: int numVertices = 6;
3972: int numEdges = numVertices;
3973: real *coords = new real[numVertices*2];
3974: const Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
3975: typename Mesh::point_type *vertices = new typename Mesh::point_type[numVertices];
3977: mesh->setSieve(sieve);
3978: const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
3979: if (mesh->commRank() == 0) {
3980: /* Create sieve and ordering */
3981: for (int b = 0; b < numVertices; b++) {
3982: sieve->addArrow(numEdges+b, b);
3983: sieve->addArrow(numEdges+b, (b+1)%numVertices);
3984: mesh->setValue(markers, b, 1);
3985: mesh->setValue(markers, b+numVertices, 1);
3986: }
3987: coords[0] = upper[0];
3988: coords[1] = lower[1];
3990: coords[2] = lower[0];
3991: coords[3] = lower[1];
3992:
3993: coords[4] = lower[0];
3994: coords[5] = notchpercent[1]*lower[1] + (1 - notchpercent[1])*upper[1];
3995:
3996: coords[6] = notchpercent[0]*upper[0] + (1 - notchpercent[0])*lower[0];
3997: coords[7] = notchpercent[1]*lower[1] + (1 - notchpercent[1])*upper[1];
3998:
3999:
4000: coords[8] = notchpercent[0]*upper[0] + (1 - notchpercent[0])*lower[0];
4001: coords[9] = upper[1];
4003: coords[10] = upper[0];
4004: coords[11] = upper[1];
4005: mesh->stratify();
4006: }
4007: delete [] vertices;
4008: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4009: return mesh;
4010: }
4014: /*
4015: Circular boundary with reentrant singularity:
4017: ---1
4018: -- |
4019: - |
4020: | |
4021: | 0-----n
4022: | |
4023: - -
4024: -- --
4025: -------
4026: */
4027: static Obj<Mesh> createCircularReentrantBoundary(const MPI_Comm comm, const int segments, const real radius, const real arc_percent, const int debug = 0) {
4028: Obj<Mesh> mesh = new Mesh(comm, 1, debug);
4029: int numVertices = segments+2;
4030: int numEdges = numVertices;
4031: real *coords = new real[numVertices*2];
4032: const Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4033: typename Mesh::point_type *vertices = new typename Mesh::point_type[numVertices];
4035: mesh->setSieve(sieve);
4036: const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4037: if (mesh->commRank() == 0) {
4038: /* Create sieve and ordering */
4040: int startvertex = 1;
4041: if (arc_percent < 1.) {
4042: coords[0] = 0.;
4043: coords[1] = 0.;
4044: } else {
4045: numVertices = segments;
4046: numEdges = numVertices;
4047: startvertex = 0;
4048: }
4050: for (int b = 0; b < numVertices; b++) {
4051: sieve->addArrow(numEdges+b, b);
4052: sieve->addArrow(numEdges+b, (b+1)%numVertices);
4053: mesh->setValue(markers, b, 1);
4054: mesh->setValue(markers, b+numVertices, 1);
4055: }
4057: real anglestep = arc_percent*2.*3.14159265/((float)segments);
4059: for (int i = startvertex; i < numVertices; i++) {
4060: coords[2*i] = radius * sin(anglestep*(i-startvertex));
4061: coords[2*i+1] = radius*cos(anglestep*(i-startvertex));
4062: }
4063: mesh->stratify();
4064: }
4065: delete [] vertices;
4066: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4067: return mesh;
4068: };
4071: static Obj<Mesh> createAnnularBoundary(const MPI_Comm comm, const int segments, const real centers[4], const real radii[2], const int debug = 0) {
4072: Obj<Mesh> mesh = new Mesh(comm, 1, debug);
4073: int numVertices = segments*2;
4074: int numEdges = numVertices;
4075: real *coords = new real[numVertices*2];
4076: const Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4077: typename Mesh::point_type *vertices = new typename Mesh::point_type[numVertices];
4079: mesh->setSieve(sieve);
4080: const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4081: if (mesh->commRank() == 0) {
4082: for (int e = 0; e < segments; ++e) {
4083: sieve->addArrow(numEdges+e, e);
4084: sieve->addArrow(numEdges+(e+1)%segments, e);
4085: sieve->addArrow(numEdges+segments+e, e+segments);
4086: sieve->addArrow(numEdges+segments+(e+1)%segments, e+segments);
4087: mesh->setValue(markers, e, 1);
4088: mesh->setValue(markers, e+segments, 1);
4089: mesh->setValue(markers, e+numEdges, 1);
4090: mesh->setValue(markers, e+numEdges+segments, 1);
4091: }
4092: const real anglestep = 2.0*M_PI/segments;
4094: for (int v = 0; v < segments; ++v) {
4095: coords[v*2] = centers[0] + radii[0]*cos(anglestep*v);
4096: coords[v*2+1] = centers[1] + radii[0]*sin(anglestep*v);
4097: coords[(v+segments)*2] = centers[2] + radii[1]*cos(anglestep*v);
4098: coords[(v+segments)*2+1] = centers[3] + radii[1]*sin(anglestep*v);
4099: }
4100: mesh->addHole(¢ers[2]);
4101: }
4102: mesh->stratify();
4103: delete [] vertices;
4104: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4105: return mesh;
4106: };
4109: /*
4110: Simple cubic boundary:
4112: 30----31-----32
4113: | | |
4114: | 3 | 2 |
4115: | | |
4116: 27----28-----29
4117: | | |
4118: | 0 | 1 |
4119: | | |
4120: 24----25-----26
4121: */
4122: static Obj<Mesh> createCubeBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int faces[], const int debug = 0) {
4123: Obj<Mesh> mesh = new Mesh(comm, 2, debug);
4124: int numVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
4125: int numFaces = 6;
4126: real *coords = new real[numVertices*3];
4127: const Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4128: typename Mesh::point_type *vertices = new typename Mesh::point_type[numVertices];
4129: int order = 0;
4131: mesh->setSieve(sieve);
4132: const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4133: if (mesh->commRank() == 0) {
4134: /* Create sieve and ordering */
4135: for(int v = numFaces; v < numFaces+numVertices; v++) {
4136: vertices[v-numFaces] = typename Mesh::point_type(v);
4137: mesh->setValue(markers, vertices[v-numFaces], 1);
4138: }
4139: {
4140: // Side 0 (Front)
4141: typename Mesh::point_type face(0);
4142: sieve->addArrow(vertices[0], face, order++);
4143: sieve->addArrow(vertices[1], face, order++);
4144: sieve->addArrow(vertices[2], face, order++);
4145: sieve->addArrow(vertices[3], face, order++);
4146: mesh->setValue(markers, face, 1);
4147: }
4148: {
4149: // Side 1 (Back)
4150: typename Mesh::point_type face(1);
4151: sieve->addArrow(vertices[5], face, order++);
4152: sieve->addArrow(vertices[4], face, order++);
4153: sieve->addArrow(vertices[7], face, order++);
4154: sieve->addArrow(vertices[6], face, order++);
4155: mesh->setValue(markers, face, 1);
4156: }
4157: {
4158: // Side 2 (Bottom)
4159: typename Mesh::point_type face(2);
4160: sieve->addArrow(vertices[4], face, order++);
4161: sieve->addArrow(vertices[5], face, order++);
4162: sieve->addArrow(vertices[1], face, order++);
4163: sieve->addArrow(vertices[0], face, order++);
4164: mesh->setValue(markers, face, 1);
4165: }
4166: {
4167: // Side 3 (Top)
4168: typename Mesh::point_type face(3);
4169: sieve->addArrow(vertices[3], face, order++);
4170: sieve->addArrow(vertices[2], face, order++);
4171: sieve->addArrow(vertices[6], face, order++);
4172: sieve->addArrow(vertices[7], face, order++);
4173: mesh->setValue(markers, face, 1);
4174: }
4175: {
4176: // Side 4 (Left)
4177: typename Mesh::point_type face(4);
4178: sieve->addArrow(vertices[4], face, order++);
4179: sieve->addArrow(vertices[0], face, order++);
4180: sieve->addArrow(vertices[3], face, order++);
4181: sieve->addArrow(vertices[7], face, order++);
4182: mesh->setValue(markers, face, 1);
4183: }
4184: {
4185: // Side 5 (Right)
4186: typename Mesh::point_type face(5);
4187: sieve->addArrow(vertices[1], face, order++);
4188: sieve->addArrow(vertices[5], face, order++);
4189: sieve->addArrow(vertices[6], face, order++);
4190: sieve->addArrow(vertices[2], face, order++);
4191: mesh->setValue(markers, face, 1);
4192: }
4193: }
4194: mesh->stratify();
4195: #if 0
4196: for(int vz = 0; vz <= edges[2]; ++vz) {
4197: for(int vy = 0; vy <= edges[1]; ++vy) {
4198: for(int vx = 0; vx <= edges[0]; ++vx) {
4199: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
4200: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
4201: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
4202: }
4203: }
4204: }
4205: #else
4206: coords[0*3+0] = lower[0];
4207: coords[0*3+1] = lower[1];
4208: coords[0*3+2] = upper[2];
4209: coords[1*3+0] = upper[0];
4210: coords[1*3+1] = lower[1];
4211: coords[1*3+2] = upper[2];
4212: coords[2*3+0] = upper[0];
4213: coords[2*3+1] = upper[1];
4214: coords[2*3+2] = upper[2];
4215: coords[3*3+0] = lower[0];
4216: coords[3*3+1] = upper[1];
4217: coords[3*3+2] = upper[2];
4218: coords[4*3+0] = lower[0];
4219: coords[4*3+1] = lower[1];
4220: coords[4*3+2] = lower[2];
4221: coords[5*3+0] = upper[0];
4222: coords[5*3+1] = lower[1];
4223: coords[5*3+2] = lower[2];
4224: coords[6*3+0] = upper[0];
4225: coords[6*3+1] = upper[1];
4226: coords[6*3+2] = lower[2];
4227: coords[7*3+0] = lower[0];
4228: coords[7*3+1] = upper[1];
4229: coords[7*3+2] = lower[2];
4230: #endif
4231: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4232: return mesh;
4233: };
4235: // Creates a triangular prism boundary
4236: static Obj<Mesh> createPrismBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int debug = 0) {
4237: Obj<Mesh> mesh = new Mesh(comm, 2, debug);
4238: int numVertices = 6;
4239: int numFaces = 5;
4240: real *coords = new real[numVertices*3];
4241: const Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4242: typename Mesh::point_type *vertices = new typename Mesh::point_type[numVertices];
4243: int order = 0;
4245: mesh->setSieve(sieve);
4246: const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4247: if (mesh->commRank() == 0) {
4248: /* Create sieve and ordering */
4249: for(int v = numFaces; v < numFaces+numVertices; v++) {
4250: vertices[v-numFaces] = typename Mesh::point_type(v);
4251: mesh->setValue(markers, vertices[v-numFaces], 1);
4252: }
4253: {
4254: // Side 0 (Top)
4255: typename Mesh::point_type face(0);
4256: sieve->addArrow(vertices[0], face, order++);
4257: sieve->addArrow(vertices[1], face, order++);
4258: sieve->addArrow(vertices[2], face, order++);
4259: mesh->setValue(markers, face, 1);
4260: }
4261: {
4262: // Side 1 (Bottom)
4263: typename Mesh::point_type face(1);
4264: sieve->addArrow(vertices[3], face, order++);
4265: sieve->addArrow(vertices[5], face, order++);
4266: sieve->addArrow(vertices[4], face, order++);
4267: mesh->setValue(markers, face, 1);
4268: }
4269: {
4270: // Side 2 (Front)
4271: typename Mesh::point_type face(2);
4272: sieve->addArrow(vertices[0], face, order++);
4273: sieve->addArrow(vertices[3], face, order++);
4274: sieve->addArrow(vertices[4], face, order++);
4275: sieve->addArrow(vertices[1], face, order++);
4276: mesh->setValue(markers, face, 1);
4277: }
4278: {
4279: // Side 3 (Left)
4280: typename Mesh::point_type face(3);
4281: sieve->addArrow(vertices[1], face, order++);
4282: sieve->addArrow(vertices[4], face, order++);
4283: sieve->addArrow(vertices[5], face, order++);
4284: sieve->addArrow(vertices[2], face, order++);
4285: mesh->setValue(markers, face, 1);
4286: }
4287: {
4288: // Side 4 (Right)
4289: typename Mesh::point_type face(4);
4290: sieve->addArrow(vertices[2], face, order++);
4291: sieve->addArrow(vertices[5], face, order++);
4292: sieve->addArrow(vertices[3], face, order++);
4293: sieve->addArrow(vertices[0], face, order++);
4294: mesh->setValue(markers, face, 1);
4295: }
4296: }
4297: mesh->stratify();
4298: coords[0*3+0] = lower[0];
4299: coords[0*3+1] = lower[1];
4300: coords[0*3+2] = upper[2];
4301: coords[1*3+0] = upper[0];
4302: coords[1*3+1] = lower[1];
4303: coords[1*3+2] = upper[2];
4304: coords[2*3+0] = upper[0];
4305: coords[2*3+1] = upper[1];
4306: coords[2*3+2] = upper[2];
4307: coords[3*3+0] = lower[0];
4308: coords[3*3+1] = upper[1];
4309: coords[3*3+2] = upper[2];
4310: coords[4*3+0] = lower[0];
4311: coords[4*3+1] = lower[1];
4312: coords[4*3+2] = lower[2];
4313: coords[5*3+0] = upper[0];
4314: coords[5*3+1] = lower[1];
4315: coords[5*3+2] = lower[2];
4316: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4317: return mesh;
4318: };
4322: /* v0
4323: / \
4324: / \
4325: 2 / 4 \ 1
4326: / \
4327: / v12 \
4328: v6|\ /|\ /|v5
4329: | \v8 | v7/ | z
4330: | |7 |8 | | |
4331: | |v13\ | | <-v4 / \
4332: | v9/ 9 \v10| x y
4333: v1 | 5 \ / 6 |v2
4334: \ \ / /
4335: \ v11 /
4336: \ | /
4337: 3 \ | /
4338: \|/
4339: v3
4340: */
4341: static Obj<Mesh> createFicheraCornerBoundary(const MPI_Comm comm, const real lower[], const real upper[], const real offset[], const int debug = 0) {
4342: Obj<Mesh> mesh = new Mesh(comm, 2, debug);
4343: const int nVertices = 14;
4344: const int nFaces = 12;
4345: real ilower[3];
4346: ilower[0] = lower[0]*(1. - offset[0]) + upper[0]*offset[0];
4347: ilower[1] = lower[1]*(1. - offset[1]) + upper[1]*offset[1];
4348: ilower[2] = lower[2]*(1. - offset[2]) + upper[2]*offset[2];
4349: real coords[nVertices*3];
4350: //outer square-triplet
4351: coords[0*3+0] = lower[0];
4352: coords[0*3+1] = lower[1];
4353: coords[0*3+2] = upper[2];
4354: coords[1*3+0] = upper[0];
4355: coords[1*3+1] = lower[1];
4356: coords[1*3+2] = lower[2];
4357: coords[2*3+0] = lower[0];
4358: coords[2*3+1] = upper[1];
4359: coords[2*3+2] = lower[2];
4360: coords[3*3+0] = upper[0];
4361: coords[3*3+1] = upper[1];
4362: coords[3*3+2] = lower[2];
4363: coords[4*3+0] = lower[0];
4364: coords[4*3+1] = lower[1];
4365: coords[4*3+2] = lower[2];
4366: coords[5*3+0] = lower[0];
4367: coords[5*3+1] = upper[1];
4368: coords[5*3+2] = upper[2];
4369: coords[6*3+0] = upper[0];
4370: coords[6*3+1] = lower[1];
4371: coords[6*3+2] = upper[2];
4373: //inner square-triplet
4374: coords[7*3+0] = ilower[0];
4375: coords[7*3+1] = upper[1];
4376: coords[7*3+2] = upper[2];
4377: coords[8*3+0] = upper[0];
4378: coords[8*3+1] = ilower[1];
4379: coords[8*3+2] = upper[2];
4380: coords[9*3+0] = upper[0];
4381: coords[9*3+1] = ilower[1];
4382: coords[9*3+2] = ilower[2];
4383: coords[10*3+0] = ilower[0];
4384: coords[10*3+1] = upper[1];
4385: coords[10*3+2] = ilower[2];
4386: coords[11*3+0] = upper[0];
4387: coords[11*3+1] = upper[1];
4388: coords[11*3+2] = ilower[2];
4389: coords[12*3+0] = ilower[0];
4390: coords[12*3+1] = ilower[1];
4391: coords[12*3+2] = upper[2];
4392: coords[13*3+0] = ilower[0];
4393: coords[13*3+1] = ilower[1];
4394: coords[13*3+2] = ilower[2];
4396:
4397: const Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4398: mesh->setSieve(sieve);
4399: typename Mesh::point_type p[nVertices];
4400: typename Mesh::point_type f[nFaces];
4401: const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4402: for (int i = 0; i < nVertices; i++) {
4403: p[i] = typename Mesh::point_type(i+nFaces);
4404: mesh->setValue(markers, p[i], 1);
4405: }
4406: for (int i = 0; i < nFaces; i++) {
4407: f[i] = typename Mesh::point_type(i);
4408: }
4409: int order = 0;
4410: //assemble the larger square sides
4411: sieve->addArrow(p[0], f[0], order++);
4412: sieve->addArrow(p[5], f[0], order++);
4413: sieve->addArrow(p[2], f[0], order++);
4414: sieve->addArrow(p[4], f[0], order++);
4415: mesh->setValue(markers, f[0], 1);
4417: sieve->addArrow(p[0], f[1], order++);
4418: sieve->addArrow(p[4], f[1], order++);
4419: sieve->addArrow(p[1], f[1], order++);
4420: sieve->addArrow(p[6], f[1], order++);
4421: mesh->setValue(markers, f[1], 1);
4423: sieve->addArrow(p[4], f[2], order++);
4424: sieve->addArrow(p[1], f[2], order++);
4425: sieve->addArrow(p[3], f[2], order++);
4426: sieve->addArrow(p[2], f[2], order++);
4427: mesh->setValue(markers, f[2], 1);
4428:
4429: //assemble the L-shaped sides
4431: sieve->addArrow(p[0], f[3], order++);
4432: sieve->addArrow(p[12], f[3], order++);
4433: sieve->addArrow(p[7], f[3], order++);
4434: sieve->addArrow(p[5], f[3], order++);
4435: mesh->setValue(markers, f[3], 1);
4437: sieve->addArrow(p[0], f[4], order++);
4438: sieve->addArrow(p[12],f[4], order++);
4439: sieve->addArrow(p[8], f[4], order++);
4440: sieve->addArrow(p[6], f[4], order++);
4441: mesh->setValue(markers, f[4], 1);
4443: sieve->addArrow(p[9], f[5], order++);
4444: sieve->addArrow(p[1], f[5], order++);
4445: sieve->addArrow(p[3], f[5], order++);
4446: sieve->addArrow(p[11], f[5], order++);
4447: mesh->setValue(markers, f[5], 1);
4449: sieve->addArrow(p[9], f[6], order++);
4450: sieve->addArrow(p[1], f[6], order++);
4451: sieve->addArrow(p[6], f[6], order++);
4452: sieve->addArrow(p[8], f[6], order++);
4453: mesh->setValue(markers, f[6], 1);
4455: sieve->addArrow(p[10], f[7], order++);
4456: sieve->addArrow(p[2], f[7], order++);
4457: sieve->addArrow(p[5], f[7], order++);
4458: sieve->addArrow(p[7], f[7], order++);
4459: mesh->setValue(markers, f[7], 1);
4461: sieve->addArrow(p[10], f[8], order++);
4462: sieve->addArrow(p[2], f[8], order++);
4463: sieve->addArrow(p[3], f[8], order++);
4464: sieve->addArrow(p[11], f[8], order++);
4465: mesh->setValue(markers, f[8], 1);
4467: //assemble the smaller square sides
4469: sieve->addArrow(p[13], f[9], order++);
4470: sieve->addArrow(p[10], f[9], order++);
4471: sieve->addArrow(p[11], f[9], order++);
4472: sieve->addArrow(p[9], f[9], order++);
4473: mesh->setValue(markers, f[9], 1);
4475: sieve->addArrow(p[12], f[10], order++);
4476: sieve->addArrow(p[7], f[10], order++);
4477: sieve->addArrow(p[10], f[10], order++);
4478: sieve->addArrow(p[13], f[10], order++);
4479: mesh->setValue(markers, f[10], 1);
4481: sieve->addArrow(p[8], f[11], order++);
4482: sieve->addArrow(p[12], f[11], order++);
4483: sieve->addArrow(p[13], f[11], order++);
4484: sieve->addArrow(p[9], f[11], order++);
4485: mesh->setValue(markers, f[11], 1);
4487: mesh->stratify();
4488: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4489: Obj<typename Mesh::real_section_type> coordinates = mesh->getRealSection("coordinates");
4490: //coordinates->view("coordinates");
4491: return mesh;
4493: }
4497: /*
4498: //"sphere" out a cube
4500: */
4501: #if 0
4502: static Obj<Mesh> createSphereBoundary(const MPI_Comm comm, const real radius, const int refinement, const int debug = 0) {
4503: Obj<Mesh> m = new Mesh(comm, 2, debug);
4504: Obj<Mesh::sieve_type> s = new Mesh::sieve_type(comm, debug);
4505: m->setSieve(s);
4506: Mesh::point_type p = 0;
4507: int nVertices = 8+12*(refinement)+6*(refinement)*(refinement);
4508: Mesh::point_type vertices[nVertices];
4509: real coords[3*nVertices];
4510: int nCells = 6*2*(refinement+1)*(refinement+1);
4511: real delta = 2./((real)(refinement+1));
4512: Mesh::point_type cells[nCells];
4513: for (int i = 0; i < nCells; i++) {
4514: cells[i] = p;
4515: p++;
4516: }
4517: for (int i = 0; i < nVertices; i++) {
4518: vertices[i] = p;
4519: p++;
4520: }
4521: //set up the corners;
4522: //lll
4523: coords[0*3+0] = -1.;
4524: coords[0*3+1] = -1.;
4525: coords[0*3+2] = -1.;
4526: //llh
4527: coords[1*3+0] = -1.;
4528: coords[1*3+1] = -1.;
4529: coords[1*3+2] = 1.;
4530: //lhh
4531: coords[2*3+0] = -1.;
4532: coords[2*3+1] = 1.;
4533: coords[2*3+2] = 1.;
4534: //lhl
4535: coords[3*3+0] = -1.;
4536: coords[3*3+1] = 1.;
4537: coords[3*3+2] = -1.;
4538: //hhl
4539: coords[4*3+0] = 1.;
4540: coords[4*3+1] = 1.;
4541: coords[4*3+2] = -1.;
4542: //hhh
4543: coords[5*3+0] = 1.;
4544: coords[5*3+1] = 1.;
4545: coords[5*3+2] = 1.;
4546: //hlh
4547: coords[6*3+0] = 1.;
4548: coords[6*3+1] = -1.;
4549: coords[6*3+2] = 1.;
4550: //hll
4551: coords[7*3+0] = 1.;
4552: coords[7*3+1] = -1.;
4553: coords[7*3+2] = -1.;
4554: //set up the edges (always go low to high)
4555: //xll
4556: for (int i = 0; i < refinement; i++) {
4557: coords[3*(8+0*refinement+i)+0] = -1. + delta*i;
4558: coords[3*(8+0*refinement+i)+1] = -1.;
4559: coords[3*(8+0*refinement+i)+2] = -1.;
4560: }
4561: //xlh
4562: for (int i = 0; i < refinement; i++) {
4563: coords[3*(8+1*refinement+i)+0] = -1. + delta*i;
4564: coords[3*(8+1*refinement+i)+1] = -1.;
4565: coords[3*(8+1*refinement+i)+2] = 1.;
4566: }
4567: //xhh
4568: for (int i = 0; i < refinement; i++) {
4569: coords[3*(8+2*refinement+i)+0] = -1. + delta*i;
4570: coords[3*(8+2*refinement+i)+1] = 1.;
4571: coords[3*(8+2*refinement+i)+2] = 1.;
4572: }
4573: //xhl
4574: for (int i = 0; i < refinement; i++) {
4575: coords[3*(8+3*refinement+i)+0] = -1. + delta*i;
4576: coords[3*(8+3*refinement+i)+1] = 1.;
4577: coords[3*(8+3*refinement+i)+2] = -1.;
4578: }
4579: //lxl
4580: for (int i = 0; i < refinement; i++) {
4581: coords[3*(8+4*refinement+i)+0] = -1.;
4582: coords[3*(8+4*refinement+i)+1] = -1. + delta*i;
4583: coords[3*(8+4*refinement+i)+2] = -1.;
4584: }
4585: //lxh
4586: for (int i = 0; i < refinement; i++) {
4587: coords[3*(8+5*refinement+i)+0] = -1.;
4588: coords[3*(8+5*refinement+i)+1] = -1. + delta*i;
4589: coords[3*(8+5*refinement+i)+2] = 1.;
4590: }
4591: //hxh
4592: for (int i = 0; i < refinement; i++) {
4593: coords[3*(8+6*refinement+i)+0] = 1.;
4594: coords[3*(8+6*refinement+i)+1] = -1. + delta*i;
4595: coords[3*(8+6*refinement+i)+2] = 1.;
4596: }
4597: //hxl
4598: for (int i = 0; i < refinement; i++) {
4599: coords[3*(8+7*refinement+i)+0] = 1.;
4600: coords[3*(8+7*refinement+i)+1] = -1. + delta*i;
4601: coords[3*(8+7*refinement+i)+2] = -1.;
4602: }
4603: //llx
4604: for (int i = 0; i < refinement; i++) {
4605: coords[3*(8+8*refinement+i)+0] = -1.;
4606: coords[3*(8+8*refinement+i)+1] = -1.;
4607: coords[3*(8+8*refinement+i)+2] = -1. + delta*i;
4608: }
4609: //lhx
4610: for (int i = 0; i < refinement; i++) {
4611: coords[3*(8+9*refinement+i)+0] = -1.;
4612: coords[3*(8+9*refinement+i)+1] = 1.;
4613: coords[3*(8+9*refinement+i)+2] = -1. + delta*i;
4614: }
4615: //hhx
4616: for (int i = 0; i < refinement; i++) {
4617: coords[3*(8+10*refinement+i)+0] = 1.;
4618: coords[3*(8+10*refinement+i)+1] = 1.;
4619: coords[3*(8+10*refinement+i)+2] = -1. + delta*i;
4620: }
4621: //hlx
4622: for (int i = 0; i < refinement; i++) {
4623: coords[3*(8+11*refinement+i)+0] = 1.;
4624: coords[3*(8+11*refinement+i)+1] = -1.;
4625: coords[3*(8+11*refinement+i)+2] = -1. + delta*i;
4626: }
4627: //set up the faces
4628: //lxx
4629: for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4630: coords[3*(8+12*refinement+0*refinement*refinement+i*refinement+j)+0] = -1.;
4631: coords[3*(8+12*refinement+0*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4632: coords[3*(8+12*refinement+0*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4633: }
4634: //hxx
4635: for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4636: coords[3*(8+12*refinement+1*refinement*refinement+i*refinement+j)+0] = 1.;
4637: coords[3*(8+12*refinement+1*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4638: coords[3*(8+12*refinement+1*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4639: }
4640: //xlx
4641: for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4642: coords[3*(8+12*refinement+2*refinement*refinement+i*refinement+j)+0] = -1. + delta*j;
4643: coords[3*(8+12*refinement+2*refinement*refinement+i*refinement+j)+1] = -1.;
4644: coords[3*(8+12*refinement+2*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4645: }
4646: //xhx
4647: for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4648: coords[3*(8+12*refinement+3*refinement*refinement+i*refinement+j)+0] = -1. + delta*j;
4649: coords[3*(8+12*refinement+3*refinement*refinement+i*refinement+j)+1] = 1.;
4650: coords[3*(8+12*refinement+3*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4651: }
4652: //xxl
4653: for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4654: coords[3*(8+12*refinement+4*refinement*refinement+i*refinement+j)+0] = -1.;
4655: coords[3*(8+12*refinement+4*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4656: coords[3*(8+12*refinement+4*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4657: }
4658: //xxh
4659: for (int i = 0; i < refinement; i++) for (int j = 0; j < refinement; j++) {
4660: coords[3*(8+12*refinement+5*refinement*refinement+i*refinement+j)+0] = 1.;
4661: coords[3*(8+12*refinement+5*refinement*refinement+i*refinement+j)+1] = -1. + delta*j;
4662: coords[3*(8+12*refinement+5*refinement*refinement+i*refinement+j)+2] = -1. + delta*i;
4663: }
4664: //stitch the corners up with the edges and the faces
4665:
4666: //stitch the edges to the faces
4667: //fill in the faces
4668: int face_offset = 8 + 12*refinement;
4669: for (int i = 0; i < 6; i++) for (int j = 0; j < refinement; j++) for (int k = 0; k < refinement; k++) {
4670: //build each square doublet
4671: }
4672: }
4674: #endif
4678: /*
4679: Simple cubic boundary:
4681: 30----31-----32
4682: | | |
4683: | 3 | 2 |
4684: | | |
4685: 27----28-----29
4686: | | |
4687: | 0 | 1 |
4688: | | |
4689: 24----25-----26
4690: */
4691: static Obj<Mesh> createParticleInCubeBoundary(const MPI_Comm comm, const real lower[], const real upper[], const int faces[], const real radius, const int thetaEdges, const int phiSlices, const int debug = 0) {
4692: Obj<Mesh> mesh = new Mesh(comm, 2, debug);
4693: const int numCubeVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
4694: const int numPartVertices = (thetaEdges - 1)*phiSlices + 2;
4695: const int numVertices = numCubeVertices + numPartVertices;
4696: const int numCubeFaces = 6;
4697: const int numFaces = numCubeFaces + thetaEdges*phiSlices;
4698: real *coords = new real[numVertices*3];
4699: const Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
4700: typename Mesh::point_type *vertices = new typename Mesh::point_type[numVertices];
4701: int order = 0;
4703: mesh->setSieve(sieve);
4704: const Obj<typename Mesh::label_type>& markers = mesh->createLabel("marker");
4705: if (mesh->commRank() == 0) {
4706: // Make cube
4707: for(int v = numFaces; v < numFaces+numVertices; v++) {
4708: vertices[v-numFaces] = typename Mesh::point_type(v);
4709: mesh->setValue(markers, vertices[v-numFaces], 1);
4710: }
4711: {
4712: // Side 0 (Front)
4713: typename Mesh::point_type face(0);
4714: sieve->addArrow(vertices[0], face, order++);
4715: sieve->addArrow(vertices[1], face, order++);
4716: sieve->addArrow(vertices[2], face, order++);
4717: sieve->addArrow(vertices[3], face, order++);
4718: mesh->setValue(markers, face, 1);
4719: }
4720: {
4721: // Side 1 (Back)
4722: typename Mesh::point_type face(1);
4723: sieve->addArrow(vertices[5], face, order++);
4724: sieve->addArrow(vertices[4], face, order++);
4725: sieve->addArrow(vertices[7], face, order++);
4726: sieve->addArrow(vertices[6], face, order++);
4727: mesh->setValue(markers, face, 1);
4728: }
4729: {
4730: // Side 2 (Bottom)
4731: typename Mesh::point_type face(2);
4732: sieve->addArrow(vertices[4], face, order++);
4733: sieve->addArrow(vertices[5], face, order++);
4734: sieve->addArrow(vertices[1], face, order++);
4735: sieve->addArrow(vertices[0], face, order++);
4736: mesh->setValue(markers, face, 1);
4737: }
4738: {
4739: // Side 3 (Top)
4740: typename Mesh::point_type face(3);
4741: sieve->addArrow(vertices[3], face, order++);
4742: sieve->addArrow(vertices[2], face, order++);
4743: sieve->addArrow(vertices[6], face, order++);
4744: sieve->addArrow(vertices[7], face, order++);
4745: mesh->setValue(markers, face, 1);
4746: }
4747: {
4748: // Side 4 (Left)
4749: typename Mesh::point_type face(4);
4750: sieve->addArrow(vertices[4], face, order++);
4751: sieve->addArrow(vertices[0], face, order++);
4752: sieve->addArrow(vertices[3], face, order++);
4753: sieve->addArrow(vertices[7], face, order++);
4754: mesh->setValue(markers, face, 1);
4755: }
4756: {
4757: // Side 5 (Right)
4758: typename Mesh::point_type face(5);
4759: sieve->addArrow(vertices[1], face, order++);
4760: sieve->addArrow(vertices[5], face, order++);
4761: sieve->addArrow(vertices[6], face, order++);
4762: sieve->addArrow(vertices[2], face, order++);
4763: mesh->setValue(markers, face, 1);
4764: }
4765: // Make particle
4766: for(int s = 0; s < phiSlices; ++s) {
4767: for(int ep = 0; ep < thetaEdges; ++ep) {
4768: // Vertices on each slice are 0..thetaEdges
4769: typename Mesh::point_type face(numCubeFaces + s*thetaEdges + ep);
4770: int vertexA = numCubeVertices + ep + 0 + s*(thetaEdges+1);
4771: int vertexB = numCubeVertices + ep + 1 + s*(thetaEdges+1);
4772: int vertexC = numCubeVertices + (ep + 1 + (s+1)*(thetaEdges+1))%((thetaEdges+1)*phiSlices);
4773: int vertexD = numCubeVertices + (ep + 0 + (s+1)*(thetaEdges+1))%((thetaEdges+1)*phiSlices);
4774: const int correction1 = (s > 0)*((s-1)*2 + 1);
4775: const int correction2 = (s < phiSlices-1)*(s*2 + 1);
4777: if ((vertexA - numCubeVertices)%(thetaEdges+1) == 0) {
4778: vertexA = vertexD = numCubeVertices;
4779: vertexB -= correction1;
4780: vertexC -= correction2;
4781: } else if ((vertexB - numCubeVertices)%(thetaEdges+1) == thetaEdges) {
4782: vertexA -= correction1;
4783: vertexD -= correction2;
4784: vertexB = vertexC = numCubeVertices + thetaEdges;
4785: } else {
4786: vertexA -= correction1;
4787: vertexB -= correction1;
4788: vertexC -= correction2;
4789: vertexD -= correction2;
4790: }
4791: if ((vertexA >= numVertices) || (vertexB >= numVertices) || (vertexC >= numVertices) || (vertexD >= numVertices)) {
4792: throw ALE::Exception("Bad vertex");
4793: }
4794: sieve->addArrow(vertices[vertexA], face, order++);
4795: sieve->addArrow(vertices[vertexB], face, order++);
4796: if (vertexB != vertexC) sieve->addArrow(vertices[vertexC], face, order++);
4797: if (vertexA != vertexD) sieve->addArrow(vertices[vertexD], face, order++);
4798: mesh->setValue(markers, face, 2);
4799: mesh->setValue(markers, vertices[vertexA], 2);
4800: mesh->setValue(markers, vertices[vertexB], 2);
4801: if (vertexB != vertexC) mesh->setValue(markers, vertices[vertexC], 2);
4802: if (vertexA != vertexD) mesh->setValue(markers, vertices[vertexD], 2);
4803: }
4804: }
4805: }
4806: mesh->stratify();
4807: #if 0
4808: for(int vz = 0; vz <= edges[2]; ++vz) {
4809: for(int vy = 0; vy <= edges[1]; ++vy) {
4810: for(int vx = 0; vx <= edges[0]; ++vx) {
4811: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
4812: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
4813: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
4814: }
4815: }
4816: }
4817: #else
4818: coords[0*3+0] = lower[0];
4819: coords[0*3+1] = lower[1];
4820: coords[0*3+2] = upper[2];
4821: coords[1*3+0] = upper[0];
4822: coords[1*3+1] = lower[1];
4823: coords[1*3+2] = upper[2];
4824: coords[2*3+0] = upper[0];
4825: coords[2*3+1] = upper[1];
4826: coords[2*3+2] = upper[2];
4827: coords[3*3+0] = lower[0];
4828: coords[3*3+1] = upper[1];
4829: coords[3*3+2] = upper[2];
4830: coords[4*3+0] = lower[0];
4831: coords[4*3+1] = lower[1];
4832: coords[4*3+2] = lower[2];
4833: coords[5*3+0] = upper[0];
4834: coords[5*3+1] = lower[1];
4835: coords[5*3+2] = lower[2];
4836: coords[6*3+0] = upper[0];
4837: coords[6*3+1] = upper[1];
4838: coords[6*3+2] = lower[2];
4839: coords[7*3+0] = lower[0];
4840: coords[7*3+1] = upper[1];
4841: coords[7*3+2] = lower[2];
4842: #endif
4843: const real centroidX = 0.5*(upper[0] + lower[0]);
4844: const real centroidY = 0.5*(upper[1] + lower[1]);
4845: const real centroidZ = 0.5*(upper[2] + lower[2]);
4846: for(int s = 0; s < phiSlices; ++s) {
4847: for(int v = 0; v <= thetaEdges; ++v) {
4848: int vertex = numCubeVertices + v + s*(thetaEdges+1);
4849: const real theta = v*(PETSC_PI/thetaEdges);
4850: const real phi = s*(2.0*PETSC_PI/phiSlices);
4851: const int correction = (s > 0)*((s-1)*2 + 1);
4853: if ((vertex- numCubeVertices)%(thetaEdges+1) == 0) {
4854: vertex = numCubeVertices;
4855: } else if ((vertex - numCubeVertices)%(thetaEdges+1) == thetaEdges) {
4856: vertex = numCubeVertices + thetaEdges;
4857: } else {
4858: vertex -= correction;
4859: }
4860: coords[vertex*3+0] = centroidX + radius*sin(theta)*cos(phi);
4861: coords[vertex*3+1] = centroidY + radius*sin(theta)*sin(phi);
4862: coords[vertex*3+2] = centroidZ + radius*cos(theta);
4863: }
4864: }
4865: delete [] vertices;
4866: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
4867: return mesh;
4868: };
4870: #if 0 // WORKING ON REDESIGN WITHIN PYLITH SOURCE TREE
4871: template<typename MeshType, typename EdgeType>
4872: class CellRefiner {
4873: public:
4874: typedef typename MeshType::point_type point_type;
4875: typedef EdgeType edge_type;
4876: typedef typename std::map<edge_type, point_type> edge_map_type;
4877: typedef enum {LINE, LINE_LAGRANGE, TRIANGLE, QUADRILATERAL, TETRAHEDRON, HEXAHEDRON, TRIANGULAR_PRISM, TRIANGULAR_PRISM_LAGRANGE, HEXAHEDRON_LAGRANGE} CellType;
4878: protected:
4879: const MeshType& _mesh;
4880: int _dim;
4881: point_type _vertexOffset;
4882: edge_map_type _edge2vertex;
4883: public:
4884: CellRefiner(MeshType& mesh) : _mesh(mesh) {
4885: _dim = _mesh.getDimension();
4886: };
4887: ~CellRefiner() {};
4888: protected:
4889: CellType getCellType(const point_type cell) {
4890: const int corners = _mesh.getSieve()->getConeSize(cell);
4891: switch (_dim) {
4892: return LINE;
4893: case 2:
4894: switch (corners) {
4895: case 3:
4896: return TRIANGLE;
4897: case 4:
4898: throw ALE::Exception("Not implemented.");
4899: return QUADRILATERAL;
4900: case 6:
4901: return LINE_LAGRANGE;
4902: case 0: {
4903: std::ostringstream msg;
4904: std::cerr << "Internal error. Cone size for mesh point " << cell << " is zero. May be a vertex.";
4905: assert(0);
4906: throw ALE::Exception("Could not determine 2-D cell type.");
4907: } // case 0
4908: default : {
4909: std::ostringstream msg;
4910: std::cerr << "Internal error. Unknown cone size for mesh point " << cell << ". Unknown cell type.";
4911: assert(0);
4912: throw ALE::Exception("Could not determine 2-D cell type.");
4913: } // default
4914: } // switch
4915: case 3:
4916: switch (corners) {
4917: case 4:
4918: return TETRAHEDRON;
4919: case 6:
4920: return TRIANGULAR_PRISM;
4921: case 9:
4922: return TRIANGULAR_PRISM_LAGRANGE;
4923: case 12:
4924: throw ALE::Exception("Not implemented.");
4925: return HEXAHEDRON_LAGRANGE;
4926: case 0: {
4927: std::ostringstream msg;
4928: std::cerr << "Internal error. Cone size for mesh point " << cell << " is zero. May be a vertex.";
4929: assert(0);
4930: throw ALE::Exception("Could not determine 3-D cell type.");
4931: } // case 0
4932: default : {
4933: std::ostringstream msg;
4934: std::cerr << "Internal error. Unknown cone size for mesh point " << cell << ". Unknown cell type.";
4935: assert(0);
4936: throw ALE::Exception("Could not determine 3-D cell type.");
4937: } // default
4938: } // switch
4939: } // switch
4940: };
4941: void getEdges_TRIANGLE(const int coneSize, const point_type cone[], int *numEdges, const edge_type **edges) {
4942: static edge_type triEdges[3];
4944: assert(coneSize == 3);
4945: triEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4946: triEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
4947: triEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
4948: *numEdges = 3;
4949: *edges = triEdges;
4950: };
4951: void getEdges_LINE_LAGRANGE(const int coneSize, const point_type cone[], int *numEdges, const edge_type **edges) {
4952: static edge_type lineEdges[6];
4954: assert(coneSize == 6);
4955: lineEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4956: lineEdges[1] = edge_type(std::min(cone[2], cone[3]), std::max(cone[2], cone[3]));
4957: lineEdges[2] = edge_type(std::min(cone[4], cone[5]), std::max(cone[4], cone[5]));
4958: *numEdges = 3;
4959: *edges = lineEdges;
4960: };
4961: void getEdges_TETRAHEDRON(const int coneSize, const point_type cone[], int *numEdges, const edge_type **edges) {
4962: static edge_type tetEdges[6];
4964: assert(coneSize == 4);
4965: // As per Brad's diagram
4966: tetEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4967: tetEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
4968: tetEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
4969: tetEdges[3] = edge_type(std::min(cone[0], cone[3]), std::max(cone[0], cone[3]));
4970: tetEdges[4] = edge_type(std::min(cone[1], cone[3]), std::max(cone[1], cone[3]));
4971: tetEdges[5] = edge_type(std::min(cone[2], cone[3]), std::max(cone[2], cone[3]));
4972: *numEdges = 6;
4973: *edges = tetEdges;
4974: };
4975: void getEdges_TRIANGULAR_PRISM(const int coneSize, const point_type cone[], int *numEdges, const edge_type **edges) {
4976: static edge_type triPrismEdges[6];
4978: assert(coneSize == 6);
4979: triPrismEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4980: triPrismEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
4981: triPrismEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
4982: triPrismEdges[3] = edge_type(std::min(cone[3], cone[4]), std::max(cone[3], cone[4]));
4983: triPrismEdges[4] = edge_type(std::min(cone[4], cone[5]), std::max(cone[4], cone[5]));
4984: triPrismEdges[5] = edge_type(std::min(cone[5], cone[3]), std::max(cone[5], cone[3]));
4985: *numEdges = 6;
4986: *edges = triPrismEdges;
4987: };
4988: void getEdges_TRIANGULAR_PRISM_LAGRANGE(const int coneSize, const point_type cone[], int *numEdges, const edge_type **edges) {
4989: static edge_type triPrismLEdges[9];
4991: assert(coneSize == 9);
4992: triPrismLEdges[0] = edge_type(std::min(cone[0], cone[1]), std::max(cone[0], cone[1]));
4993: triPrismLEdges[1] = edge_type(std::min(cone[1], cone[2]), std::max(cone[1], cone[2]));
4994: triPrismLEdges[2] = edge_type(std::min(cone[2], cone[0]), std::max(cone[2], cone[0]));
4995: triPrismLEdges[3] = edge_type(std::min(cone[3], cone[4]), std::max(cone[3], cone[4]));
4996: triPrismLEdges[4] = edge_type(std::min(cone[4], cone[5]), std::max(cone[4], cone[5]));
4997: triPrismLEdges[5] = edge_type(std::min(cone[5], cone[3]), std::max(cone[5], cone[3]));
4998: triPrismLEdges[6] = edge_type(std::min(cone[6], cone[7]), std::max(cone[6], cone[7]));
4999: triPrismLEdges[7] = edge_type(std::min(cone[7], cone[8]), std::max(cone[7], cone[8]));
5000: triPrismLEdges[8] = edge_type(std::min(cone[8], cone[6]), std::max(cone[8], cone[6]));
5001: *numEdges = 9;
5002: *edges = triPrismLEdges;
5003: };
5004: void getNewCells_TRIANGLE(const int coneSize, const point_type cone[], int *numCells, const point_type **cells) {
5005: int numEdges;
5006: const edge_type *edges;
5007: static point_type triCells[4*3];
5008: point_type newVertices[3];
5010: getEdges_TRIANGLE(coneSize, cone, &numEdges, &edges);
5011: assert(numEdges == 3);
5012: for(int e = 0; e < numEdges; ++e) {
5013: if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5014: throw ALE::Exception("Missing edge in refined mesh");
5015: }
5016: newVertices[e] = _edge2vertex[edges[e]];
5017: }
5018: triCells[0*3+0] = cone[0]+_vertexOffset; triCells[0*3+1] = newVertices[0]; triCells[0*3+2] = newVertices[2];
5019: triCells[1*3+0] = newVertices[0]; triCells[1*3+1] = newVertices[1]; triCells[1*3+2] = newVertices[2];
5020: triCells[2*3+0] = cone[1]+_vertexOffset; triCells[2*3+1] = newVertices[1]; triCells[2*3+2] = newVertices[0];
5021: triCells[3*3+0] = cone[2]+_vertexOffset; triCells[3*3+1] = newVertices[2]; triCells[3*3+2] = newVertices[1];
5022: *numCells = 4;
5023: *cells = triCells;
5024: };
5025: void getNewCells_LINE_LAGRANGE(const int coneSize, const point_type cone[], int *numCells, const point_type **cells) {
5026: int numEdges;
5027: const edge_type *edges;
5028: static point_type lineCells[2*6];
5029: point_type newVertices[3];
5031: getEdges_LINE_LAGRANGE(coneSize, cone, &numEdges, &edges);
5032: assert(numEdges == 3);
5033: for(int e = 0; e < numEdges; ++e) {
5034: if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5035: throw ALE::Exception("Missing edge in refined mesh");
5036: }
5037: newVertices[e] = _edge2vertex[edges[e]];
5038: }
5039: lineCells[0*6+0] = cone[0]+_vertexOffset; // new cell 0
5040: lineCells[0*6+1] = newVertices[0];
5041: lineCells[0*6+2] = cone[2]+_vertexOffset;
5042: lineCells[0*6+3] = newVertices[1];
5043: lineCells[0*6+4] = cone[4]+_vertexOffset;
5044: lineCells[0*6+5] = newVertices[2];
5046: lineCells[1*6+0] = newVertices[0]; // new cell 1
5047: lineCells[1*6+1] = cone[1]+_vertexOffset;
5048: lineCells[1*6+2] = newVertices[1];
5049: lineCells[1*6+3] = cone[3]+_vertexOffset;
5050: lineCells[1*6+4] = newVertices[2];
5051: lineCells[1*6+5] = cone[5]+_vertexOffset;
5053: *numCells = 2;
5054: *cells = lineCells;
5055: };
5056: void getNewCells_TETRAHEDRON(const int coneSize, const point_type cone[], int *numCells, const point_type **cells) {
5057: int numEdges;
5058: const edge_type *edges;
5059: static point_type tetCells[8*4];
5060: point_type newVertices[6];
5062: getEdges_TETRAHEDRON(coneSize, cone, &numEdges, &edges);
5063: assert(numEdges == 6);
5064: for(int e = 0; e < numEdges; ++e) {
5065: if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5066: throw ALE::Exception("Missing edge in refined mesh");
5067: }
5068: newVertices[e] = _edge2vertex[edges[e]];
5069: }
5070: tetCells[0*4+0] = cone[0]+_vertexOffset; tetCells[0*4+1] = newVertices[3]; tetCells[0*4+2] = newVertices[0]; tetCells[0*4+3] = newVertices[2];
5071: tetCells[1*4+0] = newVertices[0]; tetCells[1*4+1] = newVertices[1]; tetCells[1*4+2] = newVertices[2]; tetCells[1*4+3] = newVertices[3];
5072: tetCells[2*4+0] = newVertices[0]; tetCells[2*4+1] = newVertices[3]; tetCells[2*4+2] = newVertices[4]; tetCells[2*4+3] = newVertices[1];
5073: tetCells[3*4+0] = cone[1]+_vertexOffset; tetCells[3*4+1] = newVertices[4]; tetCells[3*4+2] = newVertices[1]; tetCells[3*4+3] = newVertices[0];
5074: tetCells[4*4+0] = newVertices[2]; tetCells[4*4+1] = newVertices[5]; tetCells[4*4+2] = newVertices[3]; tetCells[4*4+3] = newVertices[1];
5075: tetCells[5*4+0] = cone[2]+_vertexOffset; tetCells[5*4+1] = newVertices[5]; tetCells[5*4+2] = newVertices[2]; tetCells[5*4+3] = newVertices[1];
5076: tetCells[6*4+0] = newVertices[1]; tetCells[6*4+1] = newVertices[4]; tetCells[6*4+2] = newVertices[5]; tetCells[6*4+3] = newVertices[3];
5077: tetCells[7*4+0] = cone[3]+_vertexOffset; tetCells[7*4+1] = newVertices[3]; tetCells[7*4+2] = newVertices[5]; tetCells[7*4+3] = newVertices[4];
5078: *numCells = 8;
5079: *cells = tetCells;
5080: };
5081: void getNewCells_TRIANGULAR_PRISM_LAGRANGE(const int coneSize, const point_type cone[], int *numCells, const point_type **cells) {
5082: int numEdges;
5083: const edge_type *edges;
5084: static point_type tcells[4*9];
5085: point_type newVertices[9];
5087: getEdges_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone, &numEdges, &edges);
5088: assert(numEdges == 9);
5089: for(int e = 0; e < numEdges; ++e) {
5090: if (_edge2vertex.find(edges[e]) == _edge2vertex.end()) {
5091: throw ALE::Exception("Missing edge in refined mesh");
5092: }
5093: newVertices[e] = _edge2vertex[edges[e]];
5094: }
5095: tcells[0*9+0] = cone[0]+_vertexOffset; // New cell 0
5096: tcells[0*9+1] = newVertices[0];
5097: tcells[0*9+2] = newVertices[2];
5098: tcells[0*9+3] = cone[3]+_vertexOffset;
5099: tcells[0*9+4] = newVertices[3];
5100: tcells[0*9+5] = newVertices[5];
5101: tcells[0*9+6] = cone[6]+_vertexOffset;
5102: tcells[0*9+7] = newVertices[6];
5103: tcells[0*9+8] = newVertices[8];
5105: tcells[1*9+0] = newVertices[0]; // New cell 1
5106: tcells[1*9+1] = newVertices[1];
5107: tcells[1*9+2] = newVertices[2];
5108: tcells[1*9+3] = newVertices[3];
5109: tcells[1*9+4] = newVertices[4];
5110: tcells[1*9+5] = newVertices[5];
5111: tcells[1*9+6] = newVertices[6];
5112: tcells[1*9+7] = newVertices[7];
5113: tcells[1*9+8] = newVertices[8];
5115: tcells[2*9+0] = cone[1]+_vertexOffset; // New cell 2
5116: tcells[2*9+1] = newVertices[1];
5117: tcells[2*9+2] = newVertices[0];
5118: tcells[2*9+3] = cone[4]+_vertexOffset;
5119: tcells[2*9+4] = newVertices[4];
5120: tcells[2*9+5] = newVertices[3];
5121: tcells[2*9+6] = cone[7]+_vertexOffset;
5122: tcells[2*9+7] = newVertices[7];
5123: tcells[2*9+8] = newVertices[6];
5125: tcells[3*9+0] = cone[2]+_vertexOffset; // New cell 3
5126: tcells[3*9+1] = newVertices[2];
5127: tcells[3*9+2] = newVertices[1];
5128: tcells[3*9+3] = cone[5]+_vertexOffset;
5129: tcells[3*9+4] = newVertices[5];
5130: tcells[3*9+5] = newVertices[4];
5131: tcells[3*9+6] = cone[8]+_vertexOffset;
5132: tcells[3*9+7] = newVertices[8];
5133: tcells[3*9+8] = newVertices[7];
5135: *numCells = 4;
5136: *cells = tcells;
5137: };
5138: public:
5139: point_type getVertexRelativeOffset() {return _vertexOffset;};
5140: void setVertexRelativeOffset(const point_type offset) {_vertexOffset = offset;};
5141: edge_map_type& getEdgeToVertex() {return _edge2vertex;};
5142: int numNewCells(const point_type cell) {
5143: switch(this->getCellType(cell)) {
5144: case TRIANGLE:
5145: return 4;
5146: case LINE_LAGRANGE:
5147: return 2;
5148: case TETRAHEDRON:
5149: return 8;
5150: case TRIANGULAR_PRISM:
5151: case TRIANGULAR_PRISM_LAGRANGE:
5152: return 4;
5153: }
5154: throw ALE::Exception("Could not determine number of new cells for this cell type");
5155: };
5156: void splitEdge(const point_type cell, const int coneSize, const point_type cone[], point_type& curNewVertex) {
5157: const CellType t = this->getCellType(cell);
5158: int numEdges;
5159: const edge_type *edges;
5161: switch(t) {
5162: case TRIANGLE:
5163: getEdges_TRIANGLE(coneSize, cone, &numEdges, &edges);
5164: break;
5165: case LINE_LAGRANGE:
5166: getEdges_LINE_LAGRANGE(coneSize, cone, &numEdges, &edges);
5167: break;
5168: case TETRAHEDRON:
5169: getEdges_TETRAHEDRON(coneSize, cone, &numEdges, &edges);
5170: break;
5171: case TRIANGULAR_PRISM:
5172: getEdges_TRIANGULAR_PRISM(coneSize, cone, &numEdges, &edges);
5173: break;
5174: case TRIANGULAR_PRISM_LAGRANGE:
5175: getEdges_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone, &numEdges, &edges);
5176: break;
5177: default:
5178: throw ALE::Exception("Could not determine number of new cells for this cell type");
5179: }
5180: // Check that vertex does not yet exist
5181: for(int v = 0; v < numEdges; ++v) {
5182: if (_edge2vertex.find(edges[v]) == _edge2vertex.end()) {
5183: std::cout << "Edge: " << edges[v] << ", new vertex: " << curNewVertex << std::endl;
5184: _edge2vertex[edges[v]] = curNewVertex++;
5185: }
5186: }
5187: };
5188: void getNewCell(const point_type cell, const int coneSize, const point_type cone[], int newCellNumber, int *newConeSize, const point_type **newCone) {
5189: const CellType t = this->getCellType(cell);
5190: int numCells;
5191: const point_type *cells;
5193: switch(t) {
5194: case TRIANGLE:
5195: getNewCells_TRIANGLE(coneSize, cone, &numCells, &cells);
5196: *newConeSize = 3;
5197: *newCone = &cells[newCellNumber*3];
5198: break;
5199: case LINE_LAGRANGE:
5200: getNewCells_LINE_LAGRANGE(coneSize, cone, &numCells, &cells);
5201: *newConeSize = 6;
5202: *newCone = &cells[newCellNumber*6];
5203: break;
5204: case TETRAHEDRON:
5205: getNewCells_TETRAHEDRON(coneSize, cone, &numCells, &cells);
5206: *newConeSize = 4;
5207: *newCone = &cells[newCellNumber*4];
5208: break;
5209: case TRIANGULAR_PRISM_LAGRANGE:
5210: getNewCells_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone, &numCells, &cells);
5211: *newConeSize = 9;
5212: *newCone = &cells[newCellNumber*9];
5213: break;
5214: default:
5215: throw ALE::Exception("Could not create new cell for this cell type");
5216: }
5217: };
5218: void getNeighboringVertices(const point_type cell, const int coneSize, const point_type cone[], const point_type firstNewVertex, point_type vertex2edge[]) {
5219: const CellType t = this->getCellType(cell);
5220: int numEdges;
5221: const edge_type *edges;
5223: switch(t) {
5224: case TRIANGLE:
5225: getEdges_TRIANGLE(coneSize, cone, &numEdges, &edges);
5226: break;
5227: case LINE_LAGRANGE:
5228: getEdges_LINE_LAGRANGE(coneSize, cone, &numEdges, &edges);
5229: break;
5230: case TETRAHEDRON:
5231: getEdges_TETRAHEDRON(coneSize, cone, &numEdges, &edges);
5232: break;
5233: case TRIANGULAR_PRISM:
5234: getEdges_TRIANGULAR_PRISM(coneSize, cone, &numEdges, &edges);
5235: break;
5236: case TRIANGULAR_PRISM_LAGRANGE:
5237: getEdges_TRIANGULAR_PRISM_LAGRANGE(coneSize, cone, &numEdges, &edges);
5238: break;
5239: default:
5240: throw ALE::Exception("Could not determine number of new cells for this cell type");
5241: }
5242: for(int v = 0; v < numEdges; ++v) {
5243: point_type newVertex = _edge2vertex[edges[v]];
5245: std::cout << "VERTEX2EDGE index: " << newVertex-firstNewVertex << ", first: " << edges[v].first << ", second: " << edges[v].second << std::endl;
5246: vertex2edge[(newVertex-firstNewVertex)*2+0] = edges[v].first;
5247: vertex2edge[(newVertex-firstNewVertex)*2+1] = edges[v].second;
5248: }
5249: };
5250: };
5251: // This method takes a mesh and performs a refinement of each cell
5252: //
5253: // triangle: 1 --> 4 refinement, adding a new vertex at the midpoint of each edge
5254: // tetrahedra: 1 --> 8 refinement, adding a new vertex at the midpoint of each edge
5255: //
5256: // :WARNING: This method currently only works for uninterpolated meshes with tri and tet cells.
5257: template<typename MeshType, typename Refiner>
5258: static void refineGeneral(const Obj<MeshType>& mesh, const Obj<MeshType>& newMesh, Refiner& refiner) {
5259: typedef typename MeshType::sieve_type sieve_type;
5260: typedef typename MeshType::point_type point_type;
5261: typedef typename Refiner::edge_type edge_type;
5263: // :WARNING: Assumed order of mesh points (cells and vertices):
5264: //
5265: // normal cells (in censored depth)
5266: // normal vertices (in censored depth)
5267: // other vertices
5268: // other cells
5269: //
5270: // This permits omitting in output the other vertices (e.g.,
5271: // Lagrange multipliers) and other cells (e.g., cohesive cells)
5272: // which have a custom reference cell that is not recognized.
5274: assert(!mesh.isNull());
5275: assert(!newMesh.isNull());
5277: // Get original mesh stuff.
5278: const Obj<typename MeshType::label_sequence>& cells = mesh->heightStratum(0);
5279: assert(!cells.isNull());
5280: const typename MeshType::label_sequence::iterator cellsEnd = cells->end();
5282: const Obj<typename MeshType::label_sequence>& vertices = mesh->depthStratum(0);
5283: assert(!vertices.isNull());
5285: const Obj<sieve_type>& sieve = mesh->getSieve();
5286: assert(!sieve.isNull());
5287: ALE::ISieveVisitor::PointRetriever<sieve_type> cV(std::max(1, sieve->getMaxConeSize()));
5289: if (mesh->hasLabel("censored depth")) {
5290: // :WARNING: Assume all cells in the censored depth come before
5291: // any other cells. This guarantees that we add vertices in the
5292: // censored depth before adding other vertices.
5294: int counterBegin = 0;
5296: int oldNumCellsNormal = 0;
5297: int oldNumCellsOther = 0;
5298: int oldNumVerticesNormal = 0;
5299: int oldNumVerticesOther = 0;
5301: int newNumCellsNormal = 0;
5302: int newNumCellsOther = 0;
5303: int newNumVerticesNormal = 0;
5304: int newNumVerticesOther = 0;
5306: // Count number of cells in censored depth (normal cells).
5307: const Obj<typename MeshType::label_sequence>& cellsNormal = mesh->getLabelStratum("censored depth", mesh->depth());
5308: assert(!cellsNormal.isNull());
5309: const typename MeshType::label_sequence::iterator cellsNormalEnd = cellsNormal->end();
5310: oldNumCellsNormal = cellsNormal->size();
5311: for(typename MeshType::label_sequence::iterator c_iter = cellsNormal->begin(); c_iter != cellsNormalEnd; ++c_iter)
5312: newNumCellsNormal += refiner.numNewCells(*c_iter);
5314: // Count number of remaining cells (other cells).
5315: const int numSkip = oldNumCellsNormal;
5316: oldNumCellsOther = cells->size() - oldNumCellsNormal;
5317: typename MeshType::label_sequence::iterator c_iter = cells->begin();
5318: for (int i=0; i < numSkip; ++i)
5319: ++c_iter;
5320: for (; c_iter != cellsEnd; ++c_iter)
5321: newNumCellsOther += refiner.numNewCells(*c_iter);
5323: // Get number of old normal vertices.
5324: assert(!mesh->getFactory.isNull());
5325: Obj<typename Mesh::numbering_type> vNumbering = mesh->getFactory()->getNumbering(mesh, "censored depth", 0);
5326: assert(!vNumbering.isNull());
5327: oldNumVerticesNormal = vNumbering->size();
5329: // Count number of new normal vertices.
5330: int counterBegin = newNumCellsNormal + vertices->size();
5331: const point_type curNewVertex = counterBegin;
5332: for(typename MeshType::label_sequence::iterator c_iter = cellsNormal->begin(); c_iter != cellsNormalEnd; ++c_iter) {
5333: cV.clear();
5334: sieve->cone(*c_iter, cV);
5335: refiner.splitEdge(*c_iter, cV.getSize(), cV.getPoints(), curNewVertex);
5336: } // for
5337: newNumVerticesNormal = curNewVertex - counterBegin;
5339: // Count number of remaining vertices (other vertices).
5340: oldNumVerticesOther = vertices->size() - oldNumVerticessNormal;
5341: counterBegin = curNewVertex + oldNumVerticesOther;
5342: curNewVertex = counterBegin;
5343: c_iter = cells->begin();
5344: for (int i=0; i < numSkip; ++i)
5345: ++c_iter;
5346: for (; c_iter != cellsEnd; ++c_iter) {
5347: cV.clear();
5348: sieve->cone(*c_iter, cV);
5349: refiner.splitEdge(*c_iter, cV.getSize(), cV.getPoints(), curNewVertex);
5350: } // for
5351: newNumVerticesOther = curNewVertex - counterBegin;
5353: Interval<point_type> oldCellsNormalRange(0, oldNumCellsNormal);
5354: Interval<point_type> newCellsNormalRange(0, newNumCellsNormal);
5356: Interval<point_type> oldVerticesNormalRange(oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal);
5357: Interval<point_type> newVerticesNormalRange(newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal);
5359: Interval<point_type> oldVerticesOtherRange(oldNumCellsNormal+oldNumVerticesNormal ,
5360: oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesOther);
5361: Interval<point_type> newVerticesOtherRange(newNumCellsNormal+newNumVerticesNormal ,
5362: newNumCellsNormal+newNumVerticesNormal+newNumVerticesOther);
5364: Interval<point_type> oldCellssOtherRange(oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesOther,
5365: oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesOther+oldNumCellsOther);
5366: Interval<point_type> newCellssOtherRange(newNumCellsNormal+newNumVerticesNormal+newNumVerticesOther,
5367: newNumCellsNormal+newNumVerticesNormal+newNumVerticesOther+newNumCellsOther);
5370: // Allocate chart for new sieve.
5371: const Obj<sieve_type>& newSieve = newMesh->getSieve();
5372: assert(!newSieve.isNull());
5373: newSieve->setChart(typename sieve_type::chart_type(0, newCellsOtherRange.end()));
5374: refiner.setVertexRelativeOffset(newNumCellsNormal-oldNumCellsNormal); // THIS DOES NOT WORK FOR COHESIVE CELLS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5376: // Create new sieve with correct sizes for refined cells
5378: // Start with normal cells.
5379: point_type curNewCell = newCellsNormalRange.begin();
5380: const typename Interval<point_type>::const_iterator oldCellsNormalRangeEnd = oldCellsNormalRange.end();
5381: for (typename Interval<point_type>::const_iterator c_iter=oldCellsNormalRange.begin();
5382: c_iter != oldCellsNormalRangeEnd;
5383: ++c_iter) {
5384: // Set new cone and support sizes
5385: cV.clear();
5386: sieve->cone(*c_iter, cV);
5387: const point_type *cone = cV.getPoints();
5388: const int coneSize = cV.getSize();
5389: const int newCells = refiner.numNewCells(*c_iter);
5391: for(int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5392: const point_type *newCone;
5393: int newConeSize;
5395: newSieve->setConeSize(curNewCell, sieve->getConeSize(*c_iter));
5396: // OPTIMIZE THIS
5397: refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5398: for(int v = 0; v < newConeSize; ++v)
5399: newSieve->addSupportSize(newCone[v], 1);
5400: } // for
5401: } // for
5403: // Continue with other cells.
5404: point_type curNewCell = newCellsOtherRange.begin();
5405: const typename Interval<point_type>::const_iterator oldCellsOtherRangeEnd = oldCellsOtherRange.end();
5406: for (typename Interval<point_type>::const_iterator c_iter=oldCellOtherRange.begin();
5407: c_iter != oldCellsOtherRangeEnd;
5408: ++c_iter) {
5409: // Set new cone and support sizes
5410: cV.clear();
5411: sieve->cone(*c_iter, cV);
5412: const point_type *cone = cV.getPoints();
5413: const int coneSize = cV.getSize();
5414: const int newCells = refiner.numNewCells(*c_iter);
5416: for(int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5417: const point_type *newCone;
5418: int newConeSize;
5420: newSieve->setConeSize(curNewCell, sieve->getConeSize(*c_iter));
5421: // OPTIMIZE THIS
5422: refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5423: for(int v = 0; v < newConeSize; ++v)
5424: newSieve->addSupportSize(newCone[v], 1);
5425: } // for
5426: } // for
5427: newSieve->allocate();
5428: point_type* vertex2edge = new point_type[(newNumVerticesNormal+newNumVerticesOther)*2];
5429: typename Refiner::edge_map_type& edge2vertex = refiner.getEdgeToVertex();
5432: // Create refined normal cells in new sieve.
5433: curNewCell = newCellsNormalRange.begin();
5434: for (typename Interval<point_type>::const_iterator c_iter=oldCellsNormalRange.begin();
5435: c_iter != oldCellsNormalRangeEnd;
5436: ++c_iter) {
5437: cV.clear();
5438: sieve->cone(*c_iter, cV);
5439: const point_type *cone = cV.getPoints();
5440: const int coneSize = cV.getSize();
5441: const int newCells = refiner.numNewCells(*c_iter);
5443: for (int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5444: const point_type *newCone;
5445: int newConeSize;
5447: refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5448: newSieve->setCone(newCone, curNewCell);
5449: } // for
5451: refiner.getNeighboringVertices(*c_iter, coneSize, cone, firstNewVertex, vertex2edge);
5452: } // for
5454: // Create refined other cells in new sieve.
5455: curNewCell = newCellsOtherRange.begin();
5456: for (typename Interval<point_type>::const_iterator c_iter=oldCellsOtherRange.begin();
5457: c_iter != oldCellsOtherRangeEnd;
5458: ++c_iter) {
5459: cV.clear();
5460: sieve->cone(*c_iter, cV);
5461: const point_type *cone = cV.getPoints();
5462: const int coneSize = cV.getSize();
5463: const int newCells = refiner.numNewCells(*c_iter);
5465: for (int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5466: const point_type *newCone;
5467: int newConeSize;
5469: refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5470: newSieve->setCone(newCone, curNewCell);
5471: } // for
5473: // FIX THIS!!! LAGRANGE VERTICES MUST BE AFTER ALL OTHER VERTICES (INCLUDING OLD LAGRANGE VERTICES)
5474: refiner.getNeighboringVertices(*c_iter, coneSize, cone, firstNewVertex, vertex2edge);
5475: } // for
5476: newSieve->symmetrize();
5478: // Set coordinates in refined mesh.
5479: const Obj<typename MeshType::real_section_type>& coordinates = mesh->getRealSection("coordinates");
5480: assert(!coordinates.isNull());
5481: const Obj<typename MeshType::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates");
5482: assert(!newCoordinates.isNull());
5484: const typename MeshType::label_sequence::const_iterator verticesEnd = vertices->end();
5485: assert(vertices->size() > 0);
5486: const int spaceDim = coordinates->getFiberDimension(*vertices->begin());
5487: assert(spaceDim > 0);
5488: newCoordinates->setChart(typename sieve_type::chart_type(newNumCellsNormal, newNumCellsNormal+newNumVertices));
5490: for (int iVertex=0, offset=newNumCellsNormal; iVertex < newNumVertices; ++iVertex) {
5491: const point_type vNew = iVertex + offset;
5492: newCoordinates->setFiberDimension(vNew, spaceDim);
5493: } // for
5494: newCoordinates->allocatePoint();
5496: for (int iVertex=0, oldOffset=oldNumCellsNormal, newOffset=newNumCellsNormal; iVertex < oldNumVertices; ++iVertex) {
5497: const point_type vOld = iVertex + oldOffset;
5498: const point_type vNew = iVertex + newOffset;
5499: newCoordinates->updatePoint(vNew, coordinates->restrictPoint(vOld));
5500: } // for
5501: for(int v=0, iVertex=oldNumVertices, newOffset=newNumCellsNormal; iVertex < newNumVertices; ++v, ++iVertex) {
5502: const point_type vNew = iVertex + newOffset;
5503: const point_type endpointA = vertex2edge[v*2+0];
5504: const point_type endpointB = vertex2edge[v*2+1];
5505: std::cout << "Setting coordinates of vertex " << vNew << " between vertices "
5506: << endpointA << " and " << endpointB << std::endl;
5507: const real *coordsA = coordinates->restrictPoint(endpointA);
5508: real coords[3];
5510: for(int d = 0; d < 3; ++d)
5511: coords[d] = coordsA[d];
5512: const real *coordsB = coordinates->restrictPoint(endpointB);
5513: for(int d = 0; d < 3; ++d) {
5514: coords[d] += coordsB[d];
5515: coords[d] *= 0.5;
5516: } // for
5517: newCoordinates->updatePoint(vNew, coords);
5518: } // for
5519: delete [] vertex2edge;
5520: // Fast stratification
5521: const Obj<typename MeshType::label_type>& height = newMesh->createLabel("height");
5522: const Obj<typename MeshType::label_type>& depth = newMesh->createLabel("depth");
5524: for (int iCell=0; iCell < newNumCellsNormal; ++iCell) {
5525: const point_type cNew = iCell;
5526: height->setCone(0, cNew);
5527: depth->setCone(1, cNew);
5528: } // for
5529: for (int iCell=newNumCellsNormal, offset=newNumVertices; iCell < newNumCells; ++iCell) {
5530: const point_type cNew = iCell + offset;
5531: height->setCone(0, cNew);
5532: depth->setCone(1, cNew);
5533: } // for
5534: for (int iVertex=0, newOffset=newNumCellsNormal; iVertex < newNumVertices; ++iVertex) {
5535: const point_type vNew = iVertex + newOffset;
5536: height->setCone(1, vNew);
5537: depth->setCone(0, vNew);
5538: } // for
5539: newMesh->setHeight(1);
5540: newMesh->setDepth(1);
5542: } else {
5543: int counterBegin = 0;
5545: int oldNumCells = 0;
5546: int oldNumVertices = 0;
5548: int newNumCells = 0;
5549: int newNumVertices = 0;
5551: // Count number of cells.
5552: oldNumCells = cells->size();
5553: for (typename MeshType::label_sequence::iterator c_iter = cells->begin(); c_iter != cellsEnd; ++c_iter)
5554: newNumCells += refiner.numNewCells(*c_iter);
5556: // Count number of vertices (normal vertices).
5557: oldNumVertices = vertices->size();
5558: int counterBegin = newNumCells + oldNumVertices;
5559: const point_type curNewVertex = counterBegin;
5560: for(typename MeshType::label_sequence::iterator c_iter = cells->begin(); c_iter != cellsEnd; ++c_iter) {
5561: cV.clear();
5562: sieve->cone(*c_iter, cV);
5563: refiner.splitEdge(*c_iter, cV.getSize(), cV.getPoints(), curNewVertex);
5564: } // for
5565: newNumVertices = curNewVertex - counterBegin;
5567: Interval<point_type> oldCellsRange(0, oldNumCells);
5568: Interval<point_type> newCellsRange(0, newNumCells);
5570: Interval<point_type> oldVerticesRange(oldNumCells, oldNumCells+oldNumVertices);
5571: Interval<point_type> newVerticesRange(newNumCells, newNumCells+newNumVertices);
5573: // Allocate chart for new sieve.
5574: const Obj<sieve_type>& newSieve = newMesh->getSieve();
5575: assert(!newSieve.isNull());
5576: newSieve->setChart(typename sieve_type::chart_type(0, newCellsOtherRange.end()));
5577: refiner.setVertexRelativeOffset(newNumCells-oldNumCells);
5579: // Create new sieve with correct sizes for refined cells
5581: // Start with normal cells.
5582: point_type curNewCell = newCellsRange.begin();
5583: const typename Interval<point_type>::const_iterator oldCellsRangeEnd = oldCellsRange.end();
5584: for (typename Interval<point_type>::const_iterator c_iter=oldCellsRange.begin();
5585: c_iter != oldCellsRangeEnd;
5586: ++c_iter) {
5587: // Set new cone and support sizes
5588: cV.clear();
5589: sieve->cone(*c_iter, cV);
5590: const point_type *cone = cV.getPoints();
5591: const int coneSize = cV.getSize();
5592: const int newCells = refiner.numNewCells(*c_iter);
5594: for(int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5595: const point_type *newCone;
5596: int newConeSize;
5598: newSieve->setConeSize(curNewCell, sieve->getConeSize(*c_iter));
5599: // OPTIMIZE THIS
5600: refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5601: for(int v = 0; v < newConeSize; ++v)
5602: newSieve->addSupportSize(newCone[v], 1);
5603: } // for
5604: } // for
5606: // Create refined normal cells in new sieve.
5607: curNewCell = newCellsRange.begin();
5608: for (typename Interval<point_type>::const_iterator c_iter=oldCellsRange.begin();
5609: c_iter != oldCellsRangeEnd;
5610: ++c_iter) {
5611: cV.clear();
5612: sieve->cone(*c_iter, cV);
5613: const point_type *cone = cV.getPoints();
5614: const int coneSize = cV.getSize();
5615: const int newCells = refiner.numNewCells(*c_iter);
5617: for (int iCell=0; iCell < newCells; ++iCell, ++curNewCell) {
5618: const point_type *newCone;
5619: int newConeSize;
5621: refiner.getNewCell(*c_iter, coneSize, cone, iCell, &newConeSize, &newCone);
5622: newSieve->setCone(newCone, curNewCell);
5623: } // for
5625: refiner.getNeighboringVertices(*c_iter, coneSize, cone, firstNewVertex, vertex2edge);
5626: } // for
5627: newSieve->symmetrize();
5629: // Set coordinates in refined mesh.
5630: const Obj<typename MeshType::real_section_type>& coordinates = mesh->getRealSection("coordinates");
5631: assert(!coordinates.isNull());
5632: const Obj<typename MeshType::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates");
5633: assert(!newCoordinates.isNull());
5635: const typename MeshType::label_sequence::const_iterator verticesEnd = vertices->end();
5636: assert(vertices->size() > 0);
5637: const int spaceDim = coordinates->getFiberDimension(*vertices->begin());
5638: assert(spaceDim > 0);
5639: newCoordinates->setChart(typename sieve_type::chart_type(newVerticesRange.begin(), newVerticesRange.end()));
5641: const typename Interval<point_type>::const_iterator newVerticesRangeEnd = newVerticesRange.end();
5642: for (typename Interval<point_type>::const_iterator v_iter=newVerticesRange.begin(); v_iter != newVerticesRangeEnd; ++v_iter)
5643: newCoordinates->setFiberDimension(v_iter, spaceDim);
5644: newCoordinates->allocatePoint();
5646: const typename Interval<point_type>::const_iterator oldVerticesRangeEnd = oldVerticesRange.end();
5647: for (typename Interval<point_type>::const_iterator vOld_iter=oldVerticesRange.begin(), vNew_iter=newVerticesRange.begin(); vOld_iter != oldVerticesRangeEnd; ++vOld_iter)
5648: newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter));
5649: for(int v=0, iVertex=oldNumVertices; iVertex < newNumVertices; ++v, ++iVertex) {
5650: const point_type vNew = newVerticesRange.begin() + iVertex;
5651: const point_type endpointA = vertex2edge[v*2+0];
5652: const point_type endpointB = vertex2edge[v*2+1];
5653: std::cout << "Setting coordinates of vertex " << vNew << " between vertices "
5654: << endpointA << " and " << endpointB << std::endl;
5655: const real *coordsA = coordinates->restrictPoint(endpointA);
5656: real coords[3];
5658: for(int d = 0; d < 3; ++d)
5659: coords[d] = coordsA[d];
5660: const real *coordsB = coordinates->restrictPoint(endpointB);
5661: for(int d = 0; d < 3; ++d) {
5662: coords[d] += coordsB[d];
5663: coords[d] *= 0.5;
5664: } // for
5665: newCoordinates->updatePoint(vNew, coords);
5666: } // for
5667: delete [] vertex2edge;
5669: // Fast stratification
5670: const Obj<typename MeshType::label_type>& height = newMesh->createLabel("height");
5671: const Obj<typename MeshType::label_type>& depth = newMesh->createLabel("depth");
5672: for (int iCell=0; iCell < newNumCells; ++iCell) {
5673: const point_type cNew = iCell;
5674: height->setCone(0, cNew);
5675: depth->setCone(1, cNew);
5676: } // for
5677: for (int iVertex=0, newOffset=newNumCellsNormal; iVertex < newNumVertices; ++iVertex) {
5678: const point_type vNew = iVertex + newOffset;
5679: height->setCone(1, vNew);
5680: depth->setCone(0, vNew);
5681: } // for
5682: newMesh->setHeight(1);
5683: newMesh->setDepth(1);
5684: } // if/else
5686: // Exchange new boundary vertices
5687: // We can convert endpoints, and then just match to new vertex on this side
5688: // 1) Create the overlap of edges which are vertex pairs (do not need for interpolated meshes)
5689: // 2) Create a section of overlap edge --> new vertex (this will generalize to other split points in interpolated meshes)
5690: // 3) Copy across new overlap
5691: // 4) Fuse matches new vertex pairs and inserts them into the old overlap
5694: // Create the parallel overlap
5695: int *oldNumCellsP = new int[mesh->commSize()];
5696: int *newNumCellsP = new int[newMesh->commSize()];
5697: int ierr;
5699: MPI_Allgather((void *) &oldNumCells, 1, MPI_INT, oldNumCellsP, 1, MPI_INT, mesh->comm());CHKERRXX(ierr);
5700: MPI_Allgather((void *) &newNumCells, 1, MPI_INT, newNumCellsP, 1, MPI_INT, newMesh->comm());CHKERRXX(ierr);
5701: Obj<typename MeshType::send_overlap_type> newSendOverlap = newMesh->getSendOverlap();
5702: Obj<typename MeshType::recv_overlap_type> newRecvOverlap = newMesh->getRecvOverlap();
5703: const Obj<typename MeshType::send_overlap_type>& sendOverlap = mesh->getSendOverlap();
5704: const Obj<typename MeshType::recv_overlap_type>& recvOverlap = mesh->getRecvOverlap();
5705: Obj<typename MeshType::send_overlap_type::traits::capSequence> sendPoints = sendOverlap->cap();
5706: const typename MeshType::send_overlap_type::source_type localOffset = newNumCellsP[newMesh->commRank()] - oldNumCellsP[mesh->commRank()];
5708: for(typename MeshType::send_overlap_type::traits::capSequence::iterator p_iter = sendPoints->begin(); p_iter != sendPoints->end(); ++p_iter) {
5709: const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& ranks = sendOverlap->support(*p_iter);
5710: const typename MeshType::send_overlap_type::source_type& localPoint = *p_iter;
5712: for(typename MeshType::send_overlap_type::traits::supportSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
5713: const int rank = *r_iter;
5714: const typename MeshType::send_overlap_type::source_type& remotePoint = r_iter.color();
5715: const typename MeshType::send_overlap_type::source_type remoteOffset = newNumCellsP[rank] - oldNumCellsP[rank];
5717: newSendOverlap->addArrow(localPoint+localOffset, rank, remotePoint+remoteOffset);
5718: }
5719: }
5720: Obj<typename MeshType::recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();
5722: for(typename MeshType::recv_overlap_type::traits::baseSequence::iterator p_iter = recvPoints->begin(); p_iter != recvPoints->end(); ++p_iter) {
5723: const Obj<typename MeshType::recv_overlap_type::traits::coneSequence>& ranks = recvOverlap->cone(*p_iter);
5724: const typename MeshType::recv_overlap_type::target_type& localPoint = *p_iter;
5726: for(typename MeshType::recv_overlap_type::traits::coneSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
5727: const int rank = *r_iter;
5728: const typename MeshType::recv_overlap_type::target_type& remotePoint = r_iter.color();
5729: const typename MeshType::recv_overlap_type::target_type remoteOffset = newNumCellsP[rank] - oldNumCellsP[rank];
5731: newRecvOverlap->addArrow(rank, localPoint+localOffset, remotePoint+remoteOffset);
5732: }
5733: }
5734: newMesh->setCalculatedOverlap(true);
5735: delete [] oldNumCellsP;
5736: delete [] newNumCellsP;
5737: // Check edges in edge2vertex for both endpoints sent to same process
5738: // Put it in section with point being the lowest numbered vertex and value (other endpoint, new vertex)
5739: Obj<ALE::Section<point_type, edge_type> > newVerticesSection = new ALE::Section<point_type, edge_type>(mesh->comm());
5740: std::map<edge_type, std::vector<int> > bdedge2rank;
5742: for(typename std::map<edge_type, point_type>::const_iterator e_iter = edge2vertex.begin(); e_iter != edge2vertex.end(); ++e_iter) {
5743: const point_type left = e_iter->first.first;
5744: const point_type right = e_iter->first.second;
5746: if (sendOverlap->capContains(left) && sendOverlap->capContains(right)) {
5747: const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& leftRanksSeq = sendOverlap->support(left);
5748: std::set<int> leftRanks(leftRanksSeq->begin(), leftRanksSeq->end());
5749: const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& rightRanksSeq = sendOverlap->support(right);
5750: std::set<int> rightRanks(rightRanksSeq->begin(), rightRanksSeq->end());
5751: std::set<int> ranks;
5752: std::set_intersection(leftRanks.begin(), leftRanks.end(), rightRanks->begin(), rightRanks->end(),
5753: std::insert_iterator<std::list<int> >(ranks, ranks.begin()));
5755: if(ranks.size()) {
5756: newVerticesSection->addFiberDimension(std::min(e_iter->first.first, e_iter->first.second)+localOffset, 1);
5757: for(typename std::list<int>::const_iterator r_iter = ranks.begin(); r_iter != ranks.end(); ++r_iter) {
5758: bdedge2rank[e_iter->first].push_back(*r_iter);
5759: }
5760: }
5761: }
5762: }
5763: newVerticesSection->allocatePoint();
5764: const typename ALE::Section<point_type, edge_type>::chart_type& chart = newVerticesSection->getChart();
5766: for(typename ALE::Section<point_type, edge_type>::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
5767: typedef typename ALE::Section<point_type, edge_type>::value_type value_type;
5768: const point_type p = *c_iter;
5769: const int dim = newVerticesSection->getFiberDimension(p);
5770: int v = 0;
5771: value_type *values = new value_type[dim];
5773: for(typename std::map<edge_type, std::vector<int> >::const_iterator e_iter = bdedge2rank.begin(); e_iter != bdedge2rank.end() && v < dim; ++e_iter) {
5774: if (std::min(e_iter->first.first, e_iter->first.second)+localOffset == p) {
5775: values[v++] = edge_type(std::max(e_iter->first.first, e_iter->first.second)+localOffset, edge2vertex[e_iter->first]);
5776: }
5777: }
5778: newVerticesSection->updatePoint(p, values);
5779: delete [] values;
5780: }
5781: // Copy across overlap
5782: typedef ALE::Pair<int, point_type> overlap_point_type;
5783: Obj<ALE::Section<overlap_point_type, edge_type> > overlapVertices = new ALE::Section<overlap_point_type, edge_type>(mesh->comm());
5785: ALE::Pullback::SimpleCopy::copy(newSendOverlap, newRecvOverlap, newVerticesSection, overlapVertices);
5786: // Merge by translating edge to local points, finding edge in edge2vertex, and adding (local new vetex, remote new vertex) to overlap
5787: for(typename std::map<edge_type, std::vector<int> >::const_iterator e_iter = bdedge2rank.begin(); e_iter != bdedge2rank.end(); ++e_iter) {
5788: const point_type localPoint = edge2vertex[e_iter->first];
5790: for(typename std::vector<int>::const_iterator r_iter = e_iter->second.begin(); r_iter != e_iter->second.end(); ++r_iter) {
5791: point_type remoteLeft = -1, remoteRight = -1;
5792: const int rank = *r_iter;
5794: const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& leftRanks = newSendOverlap->support(e_iter->first.first+localOffset);
5795: for(typename MeshType::send_overlap_type::traits::supportSequence::iterator lr_iter = leftRanks->begin(); lr_iter != leftRanks->end(); ++lr_iter) {
5796: if (rank == *lr_iter) {
5797: remoteLeft = lr_iter.color();
5798: break;
5799: }
5800: }
5801: const Obj<typename MeshType::send_overlap_type::traits::supportSequence>& rightRanks = newSendOverlap->support(e_iter->first.second+localOffset);
5802: for(typename MeshType::send_overlap_type::traits::supportSequence::iterator rr_iter = rightRanks->begin(); rr_iter != rightRanks->end(); ++rr_iter) {
5803: if (rank == *rr_iter) {
5804: remoteRight = rr_iter.color();
5805: break;
5806: }
5807: }
5808: const point_type remoteMin = std::min(remoteLeft, remoteRight);
5809: const point_type remoteMax = std::max(remoteLeft, remoteRight);
5810: const int remoteSize = overlapVertices->getFiberDimension(overlap_point_type(rank, remoteMin));
5811: const edge_type *remoteVals = overlapVertices->restrictPoint(overlap_point_type(rank, remoteMin));
5812: point_type remotePoint = -1;
5814: for(int d = 0; d < remoteSize; ++d) {
5815: if (remoteVals[d].first == remoteMax) {
5816: remotePoint = remoteVals[d].second;
5817: break;
5818: }
5819: }
5820: newSendOverlap->addArrow(localPoint, rank, remotePoint);
5821: newRecvOverlap->addArrow(rank, localPoint, remotePoint);
5822: }
5823: }
5824: };
5825: #endif
5826: };
5828: class MeshSerializer {
5829: public:
5830: template<typename Mesh>
5831: static void writeMesh(const std::string& filename, Mesh& mesh) {
5832: std::ofstream fs;
5834: if (mesh.commRank() == 0) {
5835: fs.open(filename.c_str());
5836: }
5837: writeMesh(fs, mesh);
5838: if (mesh.commRank() == 0) {
5839: fs.close();
5840: }
5841: }
5842: template<typename Mesh>
5843: static void writeMesh(std::ofstream& fs, Mesh& mesh) {
5844: ISieveSerializer::writeSieve(fs, *mesh.getSieve());
5845: // Write labels
5846: const typename Mesh::labels_type& labels = mesh.getLabels();
5848: if (!mesh.commRank()) {fs << labels.size() << std::endl;}
5849: for(typename Mesh::labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
5850: if (!mesh.commRank()) {fs << l_iter->first << std::endl;}
5851: LabelSifterSerializer::writeLabel(fs, *l_iter->second);
5852: }
5853: // Write sections
5854: Obj<std::set<std::string> > realNames = mesh.getRealSections();
5856: if (!mesh.commRank()) {fs << realNames->size() << std::endl;}
5857: for(std::set<std::string>::const_iterator n_iter = realNames->begin(); n_iter != realNames->end(); ++n_iter) {
5858: if (!mesh.commRank()) {fs << *n_iter << std::endl;}
5859: SectionSerializer::writeSection(fs, *mesh.getRealSection(*n_iter));
5860: }
5861: Obj<std::set<std::string> > intNames = mesh.getIntSections();
5863: if (!mesh.commRank()) {fs << intNames->size() << std::endl;}
5864: for(std::set<std::string>::const_iterator n_iter = intNames->begin(); n_iter != intNames->end(); ++n_iter) {
5865: if (!mesh.commRank()) {fs << *n_iter << std::endl;}
5866: SectionSerializer::writeSection(fs, *mesh.getIntSection(*n_iter));
5867: }
5868: // Write overlap
5869: #ifdef USE_NEW_OVERLAP
5870: PETSc::OverlapSerializer::writeOverlap(fs, *mesh.getSendOverlap());
5871: PETSc::OverlapSerializer::writeOverlap(fs, *mesh.getRecvOverlap());
5872: #else
5873: SifterSerializer::writeSifter(fs, *mesh.getSendOverlap());
5874: SifterSerializer::writeSifter(fs, *mesh.getRecvOverlap());
5875: #endif
5876: // Write distribution overlap
5877: // Write renumbering
5878: }
5879: template<typename Mesh>
5880: static void loadMesh(const std::string& filename, Mesh& mesh) {
5881: std::ifstream fs;
5883: if (mesh.commRank() == 0) {
5884: fs.open(filename.c_str());
5885: }
5886: loadMesh(fs, mesh);
5887: if (mesh.commRank() == 0) {
5888: fs.close();
5889: }
5890: }
5891: template<typename Mesh>
5892: static void loadMesh(std::ifstream& fs, Mesh& mesh) {
5893: ALE::Obj<typename Mesh::sieve_type> sieve = new typename Mesh::sieve_type(mesh.comm(), mesh.debug());
5894: PetscErrorCode ierr;
5896: ISieveSerializer::loadSieve(fs, *sieve);
5897: mesh.setSieve(sieve);
5898: // Load labels
5899: int numLabels;
5901: if (!mesh.commRank()) {fs >> numLabels;}
5902: MPI_Bcast(&numLabels, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5903: for(int l = 0; l < numLabels; ++l) {
5904: ALE::Obj<typename Mesh::label_type> label = new typename Mesh::label_type(mesh.comm(), mesh.debug());
5905: std::string name;
5906: int len;
5908: if (!mesh.commRank()) {
5909: fs >> name;
5910: len = name.size();
5911: MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5912: MPI_Bcast((void *) name.c_str(), len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5913: } else {
5914: MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5915: char *n = new char[len+1];
5916: MPI_Bcast(n, len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5917: name = n;
5918: delete [] n;
5919: }
5920: LabelSifterSerializer::loadLabel(fs, *label);
5921: mesh.setLabel(name, label);
5922: }
5923: // Load sections
5924: int numRealSections;
5926: if (!mesh.commRank()) {fs >> numRealSections;}
5927: MPI_Bcast(&numRealSections, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5928: for(int s = 0; s < numRealSections; ++s) {
5929: ALE::Obj<typename Mesh::real_section_type> section = new typename Mesh::real_section_type(mesh.comm(), mesh.debug());
5930: std::string name;
5931: int len;
5933: if (!mesh.commRank()) {
5934: fs >> name;
5935: len = name.size();
5936: MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5937: MPI_Bcast((void *) name.c_str(), len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5938: } else {
5939: MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5940: char *n = new char[len+1];
5941: MPI_Bcast(n, len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5942: name = n;
5943: delete [] n;
5944: }
5945: SectionSerializer::loadSection(fs, *section);
5946: mesh.setRealSection(name, section);
5947: }
5948: int numIntSections;
5950: if (!mesh.commRank()) {fs >> numIntSections;}
5951: MPI_Bcast(&numIntSections, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5952: for(int s = 0; s < numIntSections; ++s) {
5953: ALE::Obj<typename Mesh::int_section_type> section = new typename Mesh::int_section_type(mesh.comm(), mesh.debug());
5954: std::string name;
5955: int len;
5957: if (!mesh.commRank()) {
5958: fs >> name;
5959: len = name.size();
5960: MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5961: MPI_Bcast((void *) name.c_str(), len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5962: } else {
5963: MPI_Bcast(&len, 1, MPI_INT, 0, mesh.comm());CHKERRXX(ierr);
5964: char *n = new char[len+1];
5965: MPI_Bcast(n, len+1, MPI_CHAR, 0, mesh.comm());CHKERRXX(ierr);
5966: name = n;
5967: delete [] n;
5968: }
5969: SectionSerializer::loadSection(fs, *section);
5970: mesh.setIntSection(name, section);
5971: }
5972: // Load overlap
5973: #ifdef USE_NEW_OVERLAP
5974: PETSc::OverlapSerializer::loadOverlap(fs, *mesh.getSendOverlap());
5975: PETSc::OverlapSerializer::loadOverlap(fs, *mesh.getRecvOverlap());
5976: #else
5977: SifterSerializer::loadSifter(fs, *mesh.getSendOverlap());
5978: SifterSerializer::loadSifter(fs, *mesh.getRecvOverlap());
5979: #endif
5980: // Load distribution overlap
5981: // Load renumbering
5982: }
5983: };
5984: } // namespace ALE
5985: #endif