Actual source code: Mesh.hh
1: #ifndef included_ALE_Mesh_hh
2: #define included_ALE_Mesh_hh
4: #include <valarray>
6: #ifndef included_ALE_Numbering_hh
7: #include <Numbering.hh>
8: #endif
10: #ifndef included_ALE_Field_hh
11: #include <Field.hh>
12: #endif
14: #ifndef included_ALE_SieveBuilder_hh
15: #include <SieveBuilder.hh>
16: #endif
18: #ifndef included_ALE_LabelSifter_hh
19: #include <LabelSifter.hh>
20: #endif
22: namespace ALE {
23: class indexSet : public std::valarray<int> {
24: public:
25: inline bool
26: operator<(const indexSet& __x) {
27: if (__x.size() != this->size()) return __x.size() < this->size();
28: for(unsigned int i = 0; i < __x.size(); ++i) {
29: if (__x[i] == (*this)[i]) continue;
30: return __x[i] < (*this)[i];
31: }
32: return false;
33: }
34: };
35: inline bool
36: operator<(const indexSet& __x, const indexSet& __y) {
37: if (__x.size() != __y.size()) return __x.size() < __y.size();
38: for(unsigned int i = 0; i < __x.size(); ++i) {
39: if (__x[i] == __y[i]) continue;
40: return __x[i] < __y[i];
41: }
42: return false;
43: };
44: inline bool
45: operator<=(const indexSet& __x, const indexSet& __y) {
46: if (__x.size() != __y.size()) return __x.size() < __y.size();
47: for(unsigned int i = 0; i < __x.size(); ++i) {
48: if (__x[i] == __y[i]) continue;
49: return __x[i] < __y[i];
50: }
51: return true;
52: };
53: inline bool
54: operator==(const indexSet& __x, const indexSet& __y) {
55: if (__x.size() != __y.size()) return false;
56: for(unsigned int i = 0; i < __x.size(); ++i) {
57: if (__x[i] != __y[i]) return false;
58: }
59: return true;
60: };
61: inline bool
62: operator!=(const indexSet& __x, const indexSet& __y) {
63: if (__x.size() != __y.size()) return true;
64: for(unsigned int i = 0; i < __x.size(); ++i) {
65: if (__x[i] != __y[i]) return true;
66: }
67: return false;
68: };
70: template<typename Sieve_,
71: typename RealSection_ = Section<typename Sieve_::point_type, double>,
72: typename IntSection_ = Section<typename Sieve_::point_type, int>,
73: typename ArrowSection_ = UniformSection<MinimalArrow<typename Sieve_::point_type, typename Sieve_::point_type>, int> >
74: class Bundle : public ALE::ParallelObject {
75: public:
76: typedef Sieve_ sieve_type;
77: typedef RealSection_ real_section_type;
78: typedef IntSection_ int_section_type;
79: typedef ArrowSection_ arrow_section_type;
80: typedef Bundle<Sieve_,RealSection_,IntSection_,ArrowSection_> this_type;
81: typedef typename sieve_type::point_type point_type;
82: #define NEW_LABEL
83: #ifdef NEW_LABEL
84: typedef typename ALE::LabelSifter<int, point_type> label_type;
85: #else
86: typedef typename ALE::Sifter<int, point_type, int> label_type;
87: #endif
88: typedef typename std::map<const std::string, Obj<label_type> > labels_type;
89: typedef typename label_type::supportSequence label_sequence;
90: typedef std::map<std::string, Obj<arrow_section_type> > arrow_sections_type;
91: typedef std::map<std::string, Obj<real_section_type> > real_sections_type;
92: typedef std::map<std::string, Obj<int_section_type> > int_sections_type;
93: typedef ALE::Point index_type;
94: typedef std::pair<index_type, int> oIndex_type;
95: typedef std::vector<oIndex_type> oIndexArray;
96: typedef std::pair<int *, int> indices_type;
97: typedef NumberingFactory<this_type> NumberingFactory;
98: typedef typename NumberingFactory::numbering_type numbering_type;
99: typedef typename NumberingFactory::order_type order_type;
100: typedef typename ALE::Sifter<int,point_type,point_type> send_overlap_type;
101: typedef typename ALE::Sifter<point_type,int,point_type> recv_overlap_type;
102: typedef typename ALE::SieveAlg<this_type> sieve_alg_type;
103: typedef typename sieve_alg_type::coneArray coneArray;
104: typedef typename sieve_alg_type::orientedConeArray oConeArray;
105: typedef typename sieve_alg_type::supportArray supportArray;
106: protected:
107: Obj<sieve_type> _sieve;
108: labels_type _labels;
109: int _maxHeight;
110: int _maxDepth;
111: arrow_sections_type _arrowSections;
112: real_sections_type _realSections;
113: int_sections_type _intSections;
114: Obj<oIndexArray> _indexArray;
115: Obj<NumberingFactory> _factory;
116: bool _calculatedOverlap;
117: Obj<send_overlap_type> _sendOverlap;
118: Obj<recv_overlap_type> _recvOverlap;
119: Obj<send_overlap_type> _distSendOverlap;
120: Obj<recv_overlap_type> _distRecvOverlap;
121: // Work space
122: Obj<std::set<point_type> > _modifiedPoints;
123: public:
124: Bundle(MPI_Comm comm, int debug = 0) : ALE::ParallelObject(comm, debug), _maxHeight(-1), _maxDepth(-1) {
125: this->_indexArray = new oIndexArray();
126: this->_modifiedPoints = new std::set<point_type>();
127: this->_factory = NumberingFactory::singleton(this->comm(), this->debug());
128: this->_calculatedOverlap = false;
129: this->_sendOverlap = new send_overlap_type(comm, debug);
130: this->_recvOverlap = new recv_overlap_type(comm, debug);
131: };
132: Bundle(const Obj<sieve_type>& sieve) : ALE::ParallelObject(sieve->comm(), sieve->debug()), _sieve(sieve), _maxHeight(-1), _maxDepth(-1) {
133: this->_indexArray = new oIndexArray();
134: this->_modifiedPoints = new std::set<point_type>();
135: this->_factory = NumberingFactory::singleton(this->comm(), this->debug());
136: this->_calculatedOverlap = false;
137: this->_sendOverlap = new send_overlap_type(comm, debug);
138: this->_recvOverlap = new recv_overlap_type(comm, debug);
139: };
140: virtual ~Bundle() {};
141: public: // Verifiers
142: bool hasLabel(const std::string& name) {
143: if (this->_labels.find(name) != this->_labels.end()) {
144: return true;
145: }
146: return false;
147: };
148: void checkLabel(const std::string& name) {
149: if (!this->hasLabel(name)) {
150: ostringstream msg;
151: msg << "Invalid label name: " << name << std::endl;
152: throw ALE::Exception(msg.str().c_str());
153: }
154: };
155: public: // Accessors
156: const Obj<sieve_type>& getSieve() const {return this->_sieve;};
157: void setSieve(const Obj<sieve_type>& sieve) {this->_sieve = sieve;};
158: bool hasArrowSection(const std::string& name) const {
159: return this->_arrowSections.find(name) != this->_arrowSections.end();
160: };
161: const Obj<arrow_section_type>& getArrowSection(const std::string& name) {
162: if (!this->hasArrowSection(name)) {
163: Obj<arrow_section_type> section = new arrow_section_type(this->comm(), this->debug());
165: section->setName(name);
166: if (this->_debug) {std::cout << "Creating new arrow section: " << name << std::endl;}
167: this->_arrowSections[name] = section;
168: }
169: return this->_arrowSections[name];
170: };
171: void setArrowSection(const std::string& name, const Obj<arrow_section_type>& section) {
172: this->_arrowSections[name] = section;
173: };
174: Obj<std::set<std::string> > getArrowSections() const {
175: Obj<std::set<std::string> > names = std::set<std::string>();
177: for(typename arrow_sections_type::const_iterator s_iter = this->_arrowSections.begin(); s_iter != this->_arrowSections.end(); ++s_iter) {
178: names->insert(s_iter->first);
179: }
180: return names;
181: };
182: bool hasRealSection(const std::string& name) const {
183: return this->_realSections.find(name) != this->_realSections.end();
184: };
185: const Obj<real_section_type>& getRealSection(const std::string& name) {
186: if (!this->hasRealSection(name)) {
187: Obj<real_section_type> section = new real_section_type(this->comm(), this->debug());
189: section->setName(name);
190: if (this->_debug) {std::cout << "Creating new real section: " << name << std::endl;}
191: this->_realSections[name] = section;
192: }
193: return this->_realSections[name];
194: };
195: void setRealSection(const std::string& name, const Obj<real_section_type>& section) {
196: this->_realSections[name] = section;
197: };
198: Obj<std::set<std::string> > getRealSections() const {
199: Obj<std::set<std::string> > names = std::set<std::string>();
201: for(typename real_sections_type::const_iterator s_iter = this->_realSections.begin(); s_iter != this->_realSections.end(); ++s_iter) {
202: names->insert(s_iter->first);
203: }
204: return names;
205: };
206: bool hasIntSection(const std::string& name) const {
207: return this->_intSections.find(name) != this->_intSections.end();
208: };
209: const Obj<int_section_type>& getIntSection(const std::string& name) {
210: if (!this->hasIntSection(name)) {
211: Obj<int_section_type> section = new int_section_type(this->comm(), this->debug());
213: section->setName(name);
214: if (this->_debug) {std::cout << "Creating new int section: " << name << std::endl;}
215: this->_intSections[name] = section;
216: }
217: return this->_intSections[name];
218: };
219: void setIntSection(const std::string& name, const Obj<int_section_type>& section) {
220: this->_intSections[name] = section;
221: };
222: Obj<std::set<std::string> > getIntSections() const {
223: Obj<std::set<std::string> > names = std::set<std::string>();
225: for(typename int_sections_type::const_iterator s_iter = this->_intSections.begin(); s_iter != this->_intSections.end(); ++s_iter) {
226: names->insert(s_iter->first);
227: }
228: return names;
229: };
230: const Obj<NumberingFactory>& getFactory() const {return this->_factory;};
231: const Obj<send_overlap_type>& getSendOverlap() const {return this->_sendOverlap;};
232: void setSendOverlap(const Obj<send_overlap_type>& overlap) {this->_sendOverlap = overlap;};
233: const Obj<recv_overlap_type>& getRecvOverlap() const {return this->_recvOverlap;};
234: void setRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_recvOverlap = overlap;};
235: const Obj<send_overlap_type>& getDistSendOverlap() const {return this->_distSendOverlap;};
236: void setDistSendOverlap(const Obj<send_overlap_type>& overlap) {this->_distSendOverlap = overlap;};
237: const Obj<recv_overlap_type>& getDistRecvOverlap() const {return this->_distRecvOverlap;};
238: void setDistRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_distRecvOverlap = overlap;};
239: public: // Labels
240: int getValue (const Obj<label_type>& label, const point_type& point, const int defValue = 0) {
241: const Obj<typename label_type::coneSequence>& cone = label->cone(point);
243: if (cone->size() == 0) return defValue;
244: return *cone->begin();
245: };
246: void setValue(const Obj<label_type>& label, const point_type& point, const int value) {
247: label->setCone(value, point);
248: };
249: template<typename InputPoints>
250: int getMaxValue (const Obj<label_type>& label, const Obj<InputPoints>& points, const int defValue = 0) {
251: int maxValue = defValue;
253: for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
254: maxValue = std::max(maxValue, this->getValue(label, *p_iter, defValue));
255: }
256: return maxValue;
257: };
258: const Obj<label_type>& createLabel(const std::string& name) {
259: this->_labels[name] = new label_type(this->comm(), this->debug());
260: return this->_labels[name];
261: };
262: const Obj<label_type>& getLabel(const std::string& name) {
263: this->checkLabel(name);
264: return this->_labels[name];
265: };
266: void setLabel(const std::string& name, const Obj<label_type>& label) {
267: this->_labels[name] = label;
268: };
269: const labels_type& getLabels() {
270: return this->_labels;
271: };
272: virtual const Obj<label_sequence>& getLabelStratum(const std::string& name, int value) {
273: this->checkLabel(name);
274: return this->_labels[name]->support(value);
275: };
276: public: // Stratification
277: template<class InputPoints>
278: void computeHeight(const Obj<label_type>& height, const Obj<sieve_type>& sieve, const Obj<InputPoints>& points, int& maxHeight) {
279: this->_modifiedPoints->clear();
281: for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
282: // Compute the max height of the points in the support of p, and add 1
283: int h0 = this->getValue(height, *p_iter, -1);
284: int h1 = this->getMaxValue(height, sieve->support(*p_iter), -1) + 1;
286: if(h1 != h0) {
287: this->setValue(height, *p_iter, h1);
288: if (h1 > maxHeight) maxHeight = h1;
289: this->_modifiedPoints->insert(*p_iter);
290: }
291: }
292: // FIX: We would like to avoid the copy here with cone()
293: if(this->_modifiedPoints->size() > 0) {
294: this->computeHeight(height, sieve, sieve->cone(this->_modifiedPoints), maxHeight);
295: }
296: };
297: void computeHeights() {
298: const Obj<label_type>& label = this->createLabel(std::string("height"));
300: this->_maxHeight = -1;
301: this->computeHeight(label, this->_sieve, this->_sieve->leaves(), this->_maxHeight);
302: };
303: virtual int height() const {return this->_maxHeight;};
304: virtual int height(const point_type& point) {
305: return this->getValue(this->_labels["height"], point, -1);
306: };
307: virtual const Obj<label_sequence>& heightStratum(int height) {
308: return this->getLabelStratum("height", height);
309: };
310: template<class InputPoints>
311: void computeDepth(const Obj<label_type>& depth, const Obj<sieve_type>& sieve, const Obj<InputPoints>& points, int& maxDepth) {
312: this->_modifiedPoints->clear();
314: for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
315: // Compute the max depth of the points in the cone of p, and add 1
316: int d0 = this->getValue(depth, *p_iter, -1);
317: int d1 = this->getMaxValue(depth, sieve->cone(*p_iter), -1) + 1;
319: if(d1 != d0) {
320: this->setValue(depth, *p_iter, d1);
321: if (d1 > maxDepth) maxDepth = d1;
322: this->_modifiedPoints->insert(*p_iter);
323: }
324: }
325: // FIX: We would like to avoid the copy here with support()
326: if(this->_modifiedPoints->size() > 0) {
327: this->computeDepth(depth, sieve, sieve->support(this->_modifiedPoints), maxDepth);
328: }
329: };
330: void computeDepths() {
331: const Obj<label_type>& label = this->createLabel(std::string("depth"));
333: this->_maxDepth = -1;
334: this->computeDepth(label, this->_sieve, this->_sieve->roots(), this->_maxDepth);
335: };
336: virtual int depth() const {return this->_maxDepth;};
337: virtual int depth(const point_type& point) {
338: return this->getValue(this->_labels["depth"], point, -1);
339: };
340: virtual const Obj<label_sequence>& depthStratum(int depth) {
341: return this->getLabelStratum("depth", depth);
342: };
345: virtual void stratify() {
346: ALE_LOG_EVENT_BEGIN;
347: this->computeHeights();
348: this->computeDepths();
349: ALE_LOG_EVENT_END;
350: };
351: public: // Size traversal
352: template<typename Section_>
353: int size(const Obj<Section_>& section, const point_type& p) {
354: const typename Section_::chart_type& chart = section->getChart();
355: int size = 0;
357: if (this->height() < 2) {
358: const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
359: typename sieve_type::coneSequence::iterator end = cone->end();
361: if (chart.count(p)) {
362: size += section->getConstrainedFiberDimension(p);
363: }
364: for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
365: if (chart.count(*c_iter)) {
366: size += section->getConstrainedFiberDimension(*c_iter);
367: }
368: }
369: } else {
370: const Obj<coneArray> closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), p);
371: typename coneArray::iterator end = closure->end();
373: for(typename coneArray::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
374: if (chart.count(*c_iter)) {
375: size += section->getConstrainedFiberDimension(*c_iter);
376: }
377: }
378: }
379: return size;
380: };
381: template<typename Section_>
382: int sizeWithBC(const Obj<Section_>& section, const point_type& p) {
383: const typename Section_::chart_type& chart = section->getChart();
384: int size = 0;
386: if (this->height() < 2) {
387: const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
388: typename sieve_type::coneSequence::iterator end = cone->end();
390: if (chart.count(p)) {
391: size += section->getFiberDimension(p);
392: }
393: for(typename sieve_type::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
394: if (chart.count(*c_iter)) {
395: size += section->getFiberDimension(*c_iter);
396: }
397: }
398: } else {
399: const Obj<coneArray> closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), p);
400: typename coneArray::iterator end = closure->end();
402: for(typename coneArray::iterator c_iter = closure->begin(); c_iter != end; ++c_iter) {
403: if (chart.count(*c_iter)) {
404: size += section->getFiberDimension(*c_iter);
405: }
406: }
407: }
408: return size;
409: };
410: protected:
411: int *getIndexArray(const int size) {
412: static int *array = NULL;
413: static int maxSize = 0;
415: if (size > maxSize) {
416: maxSize = size;
417: if (array) delete [] array;
418: array = new int[maxSize];
419: };
420: return array;
421: };
422: public: // Index traversal
423: void expandInterval(const index_type& interval, PetscInt indices[], PetscInt *indx) {
424: const int end = interval.prefix + interval.index;
426: for(int i = interval.index; i < end; ++i) {
427: indices[(*indx)++] = i;
428: }
429: };
430: void expandInterval(const index_type& interval, const int orientation, PetscInt indices[], PetscInt *indx) {
431: if (orientation >= 0) {
432: for(int i = 0; i < interval.prefix; ++i) {
433: indices[(*indx)++] = interval.index + i;
434: }
435: } else {
436: for(int i = interval.prefix-1; i >= 0; --i) {
437: indices[(*indx)++] = interval.index + i;
438: }
439: }
440: for(int i = 0; i < -interval.prefix; ++i) {
441: indices[(*indx)++] = -1;
442: }
443: };
444: void expandIntervals(Obj<oIndexArray> intervals, PetscInt *indices) {
445: int k = 0;
447: for(typename oIndexArray::iterator i_iter = intervals->begin(); i_iter != intervals->end(); ++i_iter) {
448: this->expandInterval(i_iter->first, i_iter->second, indices, &k);
449: }
450: }
451: template<typename Section_>
452: const indices_type getIndicesRaw(const Obj<Section_>& section, const point_type& p) {
453: int *indexArray = NULL;
454: int size = 0;
456: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
457: typename oConeArray::iterator begin = closure->begin();
458: typename oConeArray::iterator end = closure->end();
460: for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
461: size += section->getFiberDimension(p_iter->first);
462: }
463: indexArray = this->getIndexArray(size);
464: int k = 0;
465: for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
466: section->getIndicesRaw(p_iter->first, section->getIndex(p_iter->first), indexArray, &k, p_iter->second);
467: }
468: return indices_type(indexArray, size);
469: };
470: template<typename Section_>
471: const indices_type getIndices(const Obj<Section_>& section, const point_type& p, const int level = -1) {
472: int *indexArray = NULL;
473: int size = 0;
475: if (level == 0) {
476: size += section->getFiberDimension(p);
477: indexArray = this->getIndexArray(size);
478: int k = 0;
480: section->getIndices(p, indexArray, &k);
481: } else if ((level == 1) || (this->height() == 1)) {
482: const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
483: typename sieve_type::coneSequence::iterator end = cone->end();
485: size += section->getFiberDimension(p);
486: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
487: size += section->getFiberDimension(*p_iter);
488: }
489: indexArray = this->getIndexArray(size);
490: int k = 0;
492: section->getIndices(p, indexArray, &k);
493: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
494: section->getIndices(*p_iter, indexArray, &k);
495: }
496: } else if (level == -1) {
497: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
498: typename oConeArray::iterator begin = closure->begin();
499: typename oConeArray::iterator end = closure->end();
501: for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
502: size += section->getFiberDimension(p_iter->first);
503: }
504: indexArray = this->getIndexArray(size);
505: int k = 0;
506: for(typename oConeArray::iterator p_iter = begin; p_iter != end; ++p_iter) {
507: section->getIndices(p_iter->first, indexArray, &k, p_iter->second);
508: }
509: } else {
510: throw ALE::Exception("Bundle has not yet implemented getIndices() for an arbitrary level");
511: }
512: if (this->debug()) {
513: for(int i = 0; i < size; ++i) {
514: printf("[%d]index %d: %d\n", this->commRank(), i, indexArray[i]);
515: }
516: }
517: return indices_type(indexArray, size);
518: };
519: template<typename Section_, typename Numbering>
520: const indices_type getIndices(const Obj<Section_>& section, const point_type& p, const Obj<Numbering>& numbering, const int level = -1) {
521: int *indexArray = NULL;
522: int size = 0;
524: if (level == 0) {
525: size += section->getFiberDimension(p);
526: indexArray = this->getIndexArray(size);
527: int k = 0;
529: section->getIndices(p, numbering, indexArray, &k);
530: } else if ((level == 1) || (this->height() == 1)) {
531: const Obj<typename sieve_type::coneSequence>& cone = this->_sieve->cone(p);
532: typename sieve_type::coneSequence::iterator end = cone->end();
534: size += section->getFiberDimension(p);
535: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
536: size += section->getFiberDimension(*p_iter);
537: }
538: indexArray = this->getIndexArray(size);
539: int k = 0;
541: section->getIndices(p, numbering, indexArray, &k);
542: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
543: section->getIndices(*p_iter, numbering, indexArray, &k);
544: }
545: } else if (level == -1) {
546: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
547: typename oConeArray::iterator end = closure->end();
549: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
550: size += section->getFiberDimension(p_iter->first);
551: }
552: indexArray = this->getIndexArray(size);
553: int k = 0;
554: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
555: section->getIndices(p_iter->first, numbering, indexArray, &k, p_iter->second);
556: }
557: } else {
558: throw ALE::Exception("Bundle has not yet implemented getIndices() for an arbitrary level");
559: }
560: return indices_type(indexArray, size);
561: };
562: public: // Retrieval traversal
563: // Return the values for the closure of this point
564: // use a smart pointer?
565: template<typename Section_>
566: const typename Section_::value_type *restrict(const Obj<Section_>& section, const point_type& p) {
567: const int size = this->sizeWithBC(section, p);
568: return this->restrict(section, p, section->getRawArray(size), size);
569: };
570: template<typename Section_>
571: const typename Section_::value_type *restrict(const Obj<Section_>& section, const point_type& p, typename Section_::value_type *values, const int valuesSize) {
572: const int size = this->sizeWithBC(section, p);
573: int j = -1;
574: if (valuesSize < size) throw ALE::Exception("Input array too small");
576: // We could actually ask for the height of the individual point
577: if (this->height() < 2) {
578: const int& dim = section->getFiberDimension(p);
579: const typename Section_::value_type *array = section->restrictPoint(p);
581: for(int i = 0; i < dim; ++i) {
582: values[++j] = array[i];
583: }
584: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
585: typename sieve_type::coneSequence::iterator end = cone->end();
587: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != end; ++p_iter) {
588: const int& dim = section->getFiberDimension(*p_iter);
590: array = section->restrictPoint(*p_iter);
591: for(int i = 0; i < dim; ++i) {
592: values[++j] = array[i];
593: }
594: }
595: } else {
596: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
597: typename oConeArray::iterator end = closure->end();
599: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
600: const typename Section_::value_type *array = section->restrictPoint(p_iter->first);
601: const int& dim = section->getFiberDimension(p_iter->first);
603: if (p_iter->second >= 0) {
604: for(int i = 0; i < dim; ++i) {
605: values[++j] = array[i];
606: }
607: } else {
608: for(int i = dim-1; i >= 0; --i) {
609: values[++j] = array[i];
610: }
611: }
612: }
613: }
614: if (j != size-1) {
615: ostringstream txt;
617: txt << "Invalid restrict to point " << p << std::endl;
618: txt << " j " << j << " should be " << (size-1) << std::endl;
619: std::cout << txt.str();
620: throw ALE::Exception(txt.str().c_str());
621: }
622: return values;
623: };
624: template<typename Section_>
625: const typename Section_::value_type *restrictNew(const Obj<Section_>& section, const point_type& p) {
626: const int size = this->sizeWithBC(section, p);
627: typename Section_::value_type *values = section->getRawArray(size);
628: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
629: typename oConeArray::iterator end = closure->end();
630: int j = -1;
632: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
633: const typename Section_::value_type *array = section->restrictPoint(p_iter->first);
635: if (p_iter->second >= 0) {
636: const int& dim = section->getFiberDimension(p_iter->first);
638: for(int i = 0; i < dim; ++i) {
639: values[++j] = array[i];
640: }
641: } else {
642: int offset = 0;
644: for(int space = 0; space < section->getNumSpaces(); ++space) {
645: const int& dim = section->getFiberDimension(p_iter->first, space);
647: for(int i = dim-1; i >= 0; --i) {
648: values[++j] = array[i+offset];
649: }
650: offset += dim;
651: }
652: }
653: }
654: if (j != size-1) {
655: ostringstream txt;
657: txt << "Invalid restrict to point " << p << std::endl;
658: txt << " j " << j << " should be " << (size-1) << std::endl;
659: std::cout << txt.str();
660: throw ALE::Exception(txt.str().c_str());
661: }
662: return values;
663: };
664: template<typename Section_>
665: void update(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
666: int j = 0;
668: if (this->height() < 2) {
669: section->updatePoint(p, &v[j]);
670: j += section->getFiberDimension(p);
671: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
673: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
674: section->updatePoint(*p_iter, &v[j]);
675: j += section->getFiberDimension(*p_iter);
676: }
677: } else {
678: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
679: typename oConeArray::iterator end = closure->end();
681: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
682: section->updatePoint(p_iter->first, &v[j], p_iter->second);
683: j += section->getFiberDimension(p_iter->first);
684: }
685: }
686: };
687: template<typename Section_>
688: void updateAdd(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
689: int j = 0;
691: if (this->height() < 2) {
692: section->updateAddPoint(p, &v[j]);
693: j += section->getFiberDimension(p);
694: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
696: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
697: section->updateAddPoint(*p_iter, &v[j]);
698: j += section->getFiberDimension(*p_iter);
699: }
700: } else {
701: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
702: typename oConeArray::iterator end = closure->end();
704: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
705: section->updateAddPoint(p_iter->first, &v[j], p_iter->second);
706: j += section->getFiberDimension(p_iter->first);
707: }
708: }
709: };
710: template<typename Section_>
711: void updateBC(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
712: int j = 0;
714: if (this->height() < 2) {
715: section->updatePointBC(p, &v[j]);
716: j += section->getFiberDimension(p);
717: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
719: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
720: section->updatePointBC(*p_iter, &v[j]);
721: j += section->getFiberDimension(*p_iter);
722: }
723: } else {
724: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
725: typename oConeArray::iterator end = closure->end();
727: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
728: section->updatePointBC(p_iter->first, &v[j], p_iter->second);
729: j += section->getFiberDimension(p_iter->first);
730: }
731: }
732: };
733: template<typename Section_>
734: void updateAll(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
735: int j = 0;
737: if (this->height() < 2) {
738: section->updatePointAll(p, &v[j]);
739: j += section->getFiberDimension(p);
740: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
742: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
743: section->updatePointAll(*p_iter, &v[j]);
744: j += section->getFiberDimension(*p_iter);
745: }
746: } else {
747: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
748: typename oConeArray::iterator end = closure->end();
750: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
751: section->updatePointAll(p_iter->first, &v[j], p_iter->second);
752: j += section->getFiberDimension(p_iter->first);
753: }
754: }
755: };
756: template<typename Section_>
757: void updateAllAdd(const Obj<Section_>& section, const point_type& p, const typename Section_::value_type v[]) {
758: int j = 0;
760: if (this->height() < 2) {
761: section->updatePointAllAdd(p, &v[j]);
762: j += section->getFiberDimension(p);
763: const Obj<typename sieve_type::coneSequence>& cone = this->getSieve()->cone(p);
765: for(typename sieve_type::coneSequence::iterator p_iter = cone->begin(); p_iter != cone->end(); ++p_iter) {
766: section->updatePointAllAdd(*p_iter, &v[j]);
767: j += section->getFiberDimension(*p_iter);
768: }
769: } else {
770: const Obj<oConeArray> closure = sieve_alg_type::orientedClosure(this, this->getArrowSection("orientation"), p);
771: typename oConeArray::iterator end = closure->end();
773: for(typename oConeArray::iterator p_iter = closure->begin(); p_iter != end; ++p_iter) {
774: section->updatePointAllAdd(p_iter->first, &v[j], p_iter->second);
775: j += section->getFiberDimension(p_iter->first);
776: }
777: }
778: };
779: public: // Optimization
780: // Calculate a custom atlas for the given traversal
781: // This returns the tag value assigned to the traversal
782: template<typename Section_, typename Sequence_>
783: int calculateCustomAtlas(const Obj<Section_>& section, const Obj<Sequence_>& points) {
784: const typename Sequence_::iterator begin = points->begin();
785: const typename Sequence_::iterator end = points->end();
786: const int num = points->size();
787: int *rOffsets = new int[num+1];
788: int *rIndices;
789: int *uOffsets = new int[num+1];
790: int *uIndices;
791: int p;
793: p = 0;
794: rOffsets[p] = 0;
795: uOffsets[p] = 0;
796: for(typename Sequence_::iterator p_iter = begin; p_iter != end; ++p_iter, ++p) {
797: rOffsets[p+1] = rOffsets[p] + this->sizeWithBC(section, *p_iter);
798: uOffsets[p+1] = rOffsets[p+1];
799: //uOffsets[p+1] = uOffsets[p] + this->size(section, *p_iter);
800: }
801: rIndices = new int[rOffsets[p]];
802: uIndices = new int[uOffsets[p]];
803: p = 0;
804: for(typename Sequence_::iterator p_iter = begin; p_iter != end; ++p_iter, ++p) {
805: const indices_type rIdx = this->getIndicesRaw(section, *p_iter);
806: for(int i = 0, k = rOffsets[p]; k < rOffsets[p+1]; ++i, ++k) rIndices[k] = rIdx.first[i];
808: const indices_type uIdx = this->getIndices(section, *p_iter);
809: for(int i = 0, k = uOffsets[p]; k < uOffsets[p+1]; ++i, ++k) uIndices[k] = uIdx.first[i];
810: }
811: return section->setCustomAtlas(rOffsets, rIndices, uOffsets, uIndices);
812: };
813: template<typename Section_>
814: const typename Section_::value_type *restrict(const Obj<Section_>& section, const int tag, const int p) {
815: const int *offsets, *indices;
817: section->getCustomRestrictAtlas(tag, &offsets, &indices);
818: const int size = offsets[p+1] - offsets[p];
819: return this->restrict(section, tag, p, section->getRawArray(size), offsets, indices);
820: };
821: template<typename Section_>
822: const typename Section_::value_type *restrict(const Obj<Section_>& section, const int tag, const int p, typename Section_::value_type *values, const int valuesSize) {
823: const int *offsets, *indices;
825: section->getCustomRestrictAtlas(tag, &offsets, &indices);
826: const int size = offsets[p+1] - offsets[p];
827: if (valuesSize < size) {throw ALE::Exception("Input array too small");}
828: return this->restrict(section, tag, p, values, offsets, indices);
829: };
830: template<typename Section_>
831: const typename Section_::value_type *restrict(const Obj<Section_>& section, const int tag, const int p, typename Section_::value_type *values, const int offsets[], const int indices[]) {
832: const typename Section_::value_type *array = section->restrict();
834: const int size = offsets[p+1] - offsets[p];
835: for(int j = 0, k = offsets[p]; j < size; ++j, ++k) {
836: values[j] = array[indices[k]];
837: }
838: return values;
839: };
840: template<typename Section_>
841: void updateAdd(const Obj<Section_>& section, const int tag, const int p, const typename Section_::value_type values[]) {
842: typename Section_::value_type *array = (typename Section_::value_type *) section->restrict();
843: const int *offsets, *indices;
845: section->getCustomUpdateAtlas(tag, &offsets, &indices);
846: const int size = offsets[p+1] - offsets[p];
847: for(int j = 0, k = offsets[p]; j < size; ++j, ++k) {
848: if (indices[k] < 0) continue;
849: array[indices[k]] += values[j];
850: }
851: };
852: public: // Allocation
853: template<typename Section_>
854: void allocate(const Obj<Section_>& section, const Obj<send_overlap_type>& sendOverlap = NULL) {
855: bool doGhosts = !sendOverlap.isNull();
857: this->_factory->orderPatch(section, this->getSieve(), sendOverlap);
858: if (doGhosts) {
859: if (this->_debug > 1) {std::cout << "Ordering patch for ghosts" << std::endl;}
860: const typename Section_::chart_type& points = section->getChart();
861: typename Section_::index_type::index_type offset = 0;
863: for(typename Section_::chart_type::iterator point = points.begin(); point != points.end(); ++point) {
864: const typename Section_::index_type& idx = section->getIndex(*point);
866: offset = std::max(offset, idx.index + std::abs(idx.prefix));
867: }
868: this->_factory->orderPatch(section, this->getSieve(), NULL, offset);
869: if (offset != section->sizeWithBC()) throw ALE::Exception("Inconsistent array sizes in section");
870: }
871: section->allocateStorage();
872: };
873: template<typename Section_>
874: void reallocate(const Obj<Section_>& section) {
875: if (section->getNewAtlas().isNull()) return;
876: // Since copy() preserves offsets, we must reinitialize them before ordering
877: const Obj<typename Section_::atlas_type> atlas = section->getAtlas();
878: const Obj<typename Section_::atlas_type>& newAtlas = section->getNewAtlas();
879: const typename Section_::atlas_type::chart_type& chart = newAtlas->getChart();
880: const typename Section_::atlas_type::chart_type& oldChart = atlas->getChart();
881: int newSize = 0;
882: typename Section_::index_type defaultIdx(0, -1);
884: for(typename Section_::atlas_type::chart_type::const_iterator c_iter = chart.begin(); c_iter != chart.end(); ++c_iter) {
885: defaultIdx.prefix = newAtlas->restrictPoint(*c_iter)[0].prefix;
886: newAtlas->updatePoint(*c_iter, &defaultIdx);
887: newSize += defaultIdx.prefix;
888: }
889: section->setAtlas(newAtlas);
890: this->_factory->orderPatch(section, this->getSieve());
891: // Copy over existing values
892: typename Section_::value_type *newArray = new typename Section_::value_type[newSize];
893: const typename Section_::value_type *array = section->restrict();
895: for(typename Section_::atlas_type::chart_type::const_iterator c_iter = oldChart.begin(); c_iter != oldChart.end(); ++c_iter) {
896: const int& dim = section->getFiberDimension(*c_iter);
897: const int& offset = atlas->restrictPoint(*c_iter)->index;
898: const int& newOffset = newAtlas->restrictPoint(*c_iter)->index;
900: for(int i = 0; i < dim; ++i) {
901: newArray[newOffset+i] = array[offset+i];
902: }
903: }
904: section->replaceStorage(newArray);
905: };
906: public: // Overlap
907: template<typename Sequence>
908: void constructOverlap(const Obj<Sequence>& points, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap) {
909: point_type *sendBuf = new point_type[points->size()];
910: int size = 0;
911: for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
912: sendBuf[size++] = *l_iter;
913: }
914: int *sizes = new int[this->commSize()]; // The number of points coming from each process
915: int *offsets = new int[this->commSize()+1]; // Prefix sums for sizes
916: int *oldOffs = new int[this->commSize()+1]; // Temporary storage
917: point_type *remotePoints = NULL; // The points from each process
918: int *remoteRanks = NULL; // The rank and number of overlap points of each process that overlaps another
920: // Change to Allgather() for the correct binning algorithm
921: MPI_Gather(&size, 1, MPI_INT, sizes, 1, MPI_INT, 0, this->comm());
922: if (this->commRank() == 0) {
923: offsets[0] = 0;
924: for(int p = 1; p <= this->commSize(); p++) {
925: offsets[p] = offsets[p-1] + sizes[p-1];
926: }
927: remotePoints = new point_type[offsets[this->commSize()]];
928: }
929: MPI_Gatherv(sendBuf, size, MPI_INT, remotePoints, sizes, offsets, MPI_INT, 0, this->comm());
930: delete [] sendBuf;
931: std::map<int, std::map<int, std::set<point_type> > > overlapInfo; // Maps (p,q) to their set of overlap points
933: if (this->commRank() == 0) {
934: for(int p = 0; p < this->commSize(); p++) {
935: std::sort(&remotePoints[offsets[p]], &remotePoints[offsets[p+1]]);
936: }
937: for(int p = 0; p <= this->commSize(); p++) {
938: oldOffs[p] = offsets[p];
939: }
940: for(int p = 0; p < this->commSize(); p++) {
941: for(int q = p+1; q < this->commSize(); q++) {
942: std::set_intersection(&remotePoints[oldOffs[p]], &remotePoints[oldOffs[p+1]],
943: &remotePoints[oldOffs[q]], &remotePoints[oldOffs[q+1]],
944: std::insert_iterator<std::set<point_type> >(overlapInfo[p][q], overlapInfo[p][q].begin()));
945: overlapInfo[q][p] = overlapInfo[p][q];
946: }
947: sizes[p] = overlapInfo[p].size()*2;
948: offsets[p+1] = offsets[p] + sizes[p];
949: }
950: remoteRanks = new int[offsets[this->commSize()]];
951: int k = 0;
952: for(int p = 0; p < this->commSize(); p++) {
953: for(typename std::map<int, std::set<point_type> >::iterator r_iter = overlapInfo[p].begin(); r_iter != overlapInfo[p].end(); ++r_iter) {
954: remoteRanks[k*2] = r_iter->first;
955: remoteRanks[k*2+1] = r_iter->second.size();
956: k++;
957: }
958: }
959: }
960: int numOverlaps; // The number of processes overlapping this process
961: MPI_Scatter(sizes, 1, MPI_INT, &numOverlaps, 1, MPI_INT, 0, this->comm());
962: int *overlapRanks = new int[numOverlaps]; // The rank and overlap size for each overlapping process
963: MPI_Scatterv(remoteRanks, sizes, offsets, MPI_INT, overlapRanks, numOverlaps, MPI_INT, 0, this->comm());
964: point_type *sendPoints = NULL; // The points to send to each process
965: if (this->commRank() == 0) {
966: for(int p = 0, k = 0; p < this->commSize(); p++) {
967: sizes[p] = 0;
968: for(int r = 0; r < (int) overlapInfo[p].size(); r++) {
969: sizes[p] += remoteRanks[k*2+1];
970: k++;
971: }
972: offsets[p+1] = offsets[p] + sizes[p];
973: }
974: sendPoints = new point_type[offsets[this->commSize()]];
975: for(int p = 0, k = 0; p < this->commSize(); p++) {
976: for(typename std::map<int, std::set<point_type> >::iterator r_iter = overlapInfo[p].begin(); r_iter != overlapInfo[p].end(); ++r_iter) {
977: int rank = r_iter->first;
978: for(typename std::set<point_type>::iterator p_iter = (overlapInfo[p][rank]).begin(); p_iter != (overlapInfo[p][rank]).end(); ++p_iter) {
979: sendPoints[k++] = *p_iter;
980: }
981: }
982: }
983: }
984: int numOverlapPoints = 0;
985: for(int r = 0; r < numOverlaps/2; r++) {
986: numOverlapPoints += overlapRanks[r*2+1];
987: }
988: point_type *overlapPoints = new point_type[numOverlapPoints];
989: MPI_Scatterv(sendPoints, sizes, offsets, MPI_INT, overlapPoints, numOverlapPoints, MPI_INT, 0, this->comm());
991: for(int r = 0, k = 0; r < numOverlaps/2; r++) {
992: int rank = overlapRanks[r*2];
994: for(int p = 0; p < overlapRanks[r*2+1]; p++) {
995: point_type point = overlapPoints[k++];
997: sendOverlap->addArrow(point, rank, point);
998: recvOverlap->addArrow(rank, point, point);
999: }
1000: }
1002: delete [] overlapPoints;
1003: delete [] overlapRanks;
1004: delete [] sizes;
1005: delete [] offsets;
1006: delete [] oldOffs;
1007: if (this->commRank() == 0) {
1008: delete [] remoteRanks;
1009: delete [] remotePoints;
1010: delete [] sendPoints;
1011: }
1012: };
1013: void constructOverlap() {
1014: if (this->_calculatedOverlap) return;
1015: this->constructOverlap(this->getSieve()->base(), this->getSendOverlap(), this->getRecvOverlap());
1016: this->constructOverlap(this->getSieve()->cap(), this->getSendOverlap(), this->getRecvOverlap());
1017: if (this->debug()) {
1018: this->_sendOverlap->view("Send overlap");
1019: this->_recvOverlap->view("Receive overlap");
1020: }
1021: this->_calculatedOverlap = true;
1022: };
1023: };
1024: class BoundaryCondition : public ALE::ParallelObject {
1025: public:
1026: typedef double (*function_type)(const double []);
1027: typedef double (*integrator_type)(const double [], const double [], const int, function_type);
1028: protected:
1029: std::string _labelName;
1030: int _marker;
1031: function_type _func;
1032: integrator_type _integrator;
1033: public:
1034: BoundaryCondition(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {};
1035: ~BoundaryCondition() {};
1036: public:
1037: const std::string& getLabelName() const {return this->_labelName;};
1038: void setLabelName(const std::string& name) {this->_labelName = name;};
1039: int getMarker() const {return this->_marker;};
1040: void setMarker(const int marker) {this->_marker = marker;};
1041: function_type getFunction() const {return this->_func;};
1042: void setFunction(function_type func) {this->_func = func;};
1043: integrator_type getDualIntegrator() const {return this->_integrator;};
1044: void setDualIntegrator(integrator_type integrator) {this->_integrator = integrator;};
1045: public:
1046: double evaluate(const double coords[]) const {return this->_func(coords);};
1047: double integrateDual(const double v0[], const double J[], const int dualIndex) const {return this->_integrator(v0, J, dualIndex, this->_func);};
1048: };
1049: class Discretization : public ALE::ParallelObject {
1050: typedef std::map<std::string, Obj<BoundaryCondition> > boundaryConditions_type;
1051: protected:
1052: boundaryConditions_type _boundaryConditions;
1053: Obj<BoundaryCondition> _exactSolution;
1054: std::map<int,int> _dim2dof;
1055: std::map<int,int> _dim2class;
1056: int _quadSize;
1057: const double *_points;
1058: const double *_weights;
1059: int _basisSize;
1060: const double *_basis;
1061: const double *_basisDer;
1062: const int *_indices;
1063: std::map<int, const int *> _exclusionIndices;
1064: public:
1065: 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) {};
1066: virtual ~Discretization() {
1067: if (this->_indices) {delete [] this->_indices;}
1068: for(std::map<int, const int *>::iterator i_iter = _exclusionIndices.begin(); i_iter != _exclusionIndices.end(); ++i_iter) {
1069: delete [] i_iter->second;
1070: }
1071: };
1072: public:
1073: const bool hasBoundaryCondition() {return (this->_boundaryConditions.find("default") != this->_boundaryConditions.end());};
1074: const Obj<BoundaryCondition>& getBoundaryCondition() {return this->getBoundaryCondition("default");};
1075: void setBoundaryCondition(const Obj<BoundaryCondition>& boundaryCondition) {this->setBoundaryCondition("default", boundaryCondition);};
1076: const Obj<BoundaryCondition>& getBoundaryCondition(const std::string& name) {return this->_boundaryConditions[name];};
1077: void setBoundaryCondition(const std::string& name, const Obj<BoundaryCondition>& boundaryCondition) {this->_boundaryConditions[name] = boundaryCondition;};
1078: Obj<std::set<std::string> > getBoundaryConditions() const {
1079: Obj<std::set<std::string> > names = std::set<std::string>();
1081: for(boundaryConditions_type::const_iterator d_iter = this->_boundaryConditions.begin(); d_iter != this->_boundaryConditions.end(); ++d_iter) {
1082: names->insert(d_iter->first);
1083: }
1084: return names;
1085: };
1086: const Obj<BoundaryCondition>& getExactSolution() {return this->_exactSolution;};
1087: void setExactSolution(const Obj<BoundaryCondition>& exactSolution) {this->_exactSolution = exactSolution;};
1088: const int getQuadratureSize() {return this->_quadSize;};
1089: void setQuadratureSize(const int size) {this->_quadSize = size;};
1090: const double *getQuadraturePoints() {return this->_points;};
1091: void setQuadraturePoints(const double *points) {this->_points = points;};
1092: const double *getQuadratureWeights() {return this->_weights;};
1093: void setQuadratureWeights(const double *weights) {this->_weights = weights;};
1094: const int getBasisSize() {return this->_basisSize;};
1095: void setBasisSize(const int size) {this->_basisSize = size;};
1096: const double *getBasis() {return this->_basis;};
1097: void setBasis(const double *basis) {this->_basis = basis;};
1098: const double *getBasisDerivatives() {return this->_basisDer;};
1099: void setBasisDerivatives(const double *basisDer) {this->_basisDer = basisDer;};
1100: int getNumDof(const int dim) {return this->_dim2dof[dim];};
1101: void setNumDof(const int dim, const int numDof) {this->_dim2dof[dim] = numDof;};
1102: int getDofClass(const int dim) {return this->_dim2class[dim];};
1103: void setDofClass(const int dim, const int dofClass) {this->_dim2class[dim] = dofClass;};
1104: public:
1105: const int *getIndices() {return this->_indices;};
1106: const int *getIndices(const int marker) {
1107: if (!marker) return this->getIndices();
1108: return this->_exclusionIndices[marker];
1109: };
1110: void setIndices(const int *indices) {this->_indices = indices;};
1111: void setIndices(const int *indices, const int marker) {
1112: if (!marker) this->_indices = indices;
1113: this->_exclusionIndices[marker] = indices;
1114: };
1115: template<typename Bundle>
1116: int size(const Obj<Bundle>& mesh) {
1117: const Obj<typename Bundle::label_sequence>& cells = mesh->heightStratum(0);
1118: const Obj<typename Bundle::coneArray> closure = ALE::SieveAlg<Bundle>::closure(mesh, *cells->begin());
1119: const typename Bundle::coneArray::iterator end = closure->end();
1120: int size = 0;
1122: for(typename Bundle::coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
1123: size += this->_dim2dof[mesh->depth(*cl_iter)];
1124: }
1125: return size;
1126: };
1127: };
1128: }
1130: namespace ALE {
1131: #ifdef NEW_SECTION
1132: class Mesh : public Bundle<ALE::Sieve<int,int,int>, GeneralSection<int, double> > {
1133: #else
1134: class Mesh : public Bundle<ALE::Sieve<int,int,int> > {
1135: #endif
1136: public:
1137: #ifdef NEW_SECTION
1138: typedef Bundle<ALE::Sieve<int,int,int>, GeneralSection<int, double> > base_type;
1139: #else
1140: typedef Bundle<ALE::Sieve<int,int,int> > base_type;
1141: #endif
1142: typedef base_type::sieve_type sieve_type;
1143: typedef sieve_type::point_type point_type;
1144: typedef base_type::label_sequence label_sequence;
1145: typedef base_type::real_section_type real_section_type;
1146: typedef base_type::numbering_type numbering_type;
1147: typedef base_type::order_type order_type;
1148: typedef base_type::send_overlap_type send_overlap_type;
1149: typedef base_type::recv_overlap_type recv_overlap_type;
1150: typedef base_type::sieve_alg_type sieve_alg_type;
1151: typedef std::set<std::string> names_type;
1152: typedef std::map<std::string, Obj<Discretization> > discretizations_type;
1153: protected:
1154: int _dim;
1155: discretizations_type _discretizations;
1156: std::map<int,double> _periodicity;
1157: public:
1158: Mesh(MPI_Comm comm, int dim, int debug = 0) : base_type(comm, debug), _dim(dim) {
1159: ///this->_factory = NumberingFactory::singleton(debug);
1160: };
1161: public: // Accessors
1162: int getDimension() const {return this->_dim;};
1163: void setDimension(const int dim) {this->_dim = dim;};
1164: const Obj<Discretization>& getDiscretization() {return this->getDiscretization("default");};
1165: const Obj<Discretization>& getDiscretization(const std::string& name) {return this->_discretizations[name];};
1166: void setDiscretization(const Obj<Discretization>& disc) {this->setDiscretization("default", disc);};
1167: void setDiscretization(const std::string& name, const Obj<Discretization>& disc) {this->_discretizations[name] = disc;};
1168: Obj<names_type> getDiscretizations() const {
1169: Obj<names_type> names = names_type();
1171: for(discretizations_type::const_iterator d_iter = this->_discretizations.begin(); d_iter != this->_discretizations.end(); ++d_iter) {
1172: names->insert(d_iter->first);
1173: }
1174: return names;
1175: };
1176: bool getPeriodicity(const int d) {return this->_periodicity[d];};
1177: void setPeriodicity(const int d, const double length) {this->_periodicity[d] = length;};
1178: public: // Mesh geometry
1179: void computeTriangleGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
1180: const double *coords = this->restrict(coordinates, e);
1181: const int dim = 2;
1182: double invDet;
1184: if (v0) {
1185: for(int d = 0; d < dim; d++) {
1186: v0[d] = coords[d];
1187: }
1188: }
1189: if (J) {
1190: for(int d = 0; d < dim; d++) {
1191: for(int f = 0; f < dim; f++) {
1192: J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
1193: }
1194: }
1195: detJ = J[0]*J[3] - J[1]*J[2];
1196: if (detJ < 0.0) {
1197: const double xLength = this->_periodicity[0];
1199: if (xLength != 0.0) {
1200: double v0x = coords[0*dim+0];
1202: if (v0x == 0.0) {
1203: v0x = v0[0] = xLength;
1204: }
1205: for(int f = 0; f < dim; f++) {
1206: const double px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];
1208: J[0*dim+f] = 0.5*(px - v0x);
1209: }
1210: }
1211: detJ = J[0]*J[3] - J[1]*J[2];
1212: }
1213: PetscLogFlopsNoCheck(8 + 3);
1214: }
1215: if (invJ) {
1216: invDet = 1.0/detJ;
1217: invJ[0] = invDet*J[3];
1218: invJ[1] = -invDet*J[1];
1219: invJ[2] = -invDet*J[2];
1220: invJ[3] = invDet*J[0];
1221: PetscLogFlopsNoCheck(5);
1222: }
1223: };
1224: void computeQuadrilateralGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double point[], double v0[], double J[], double invJ[], double& detJ) {
1225: const double *coords = this->restrict(coordinates, e);
1226: const int dim = 2;
1227: double invDet;
1229: if (v0) {
1230: for(int d = 0; d < dim; d++) {
1231: v0[d] = coords[d];
1232: }
1233: }
1234: if (J) {
1235: double x_1 = coords[2] - coords[0];
1236: double y_1 = coords[3] - coords[1];
1237: double x_2 = coords[6] - coords[0];
1238: double y_2 = coords[7] - coords[1];
1239: double x_3 = coords[4] - coords[0];
1240: double y_3 = coords[5] - coords[1];
1242: J[0] = x_1 + (x_3 - x_1 - x_2)*point[1];
1243: J[1] = x_2 + (x_3 - x_1 - x_2)*point[0];
1244: J[2] = y_1 + (y_3 - y_1 - y_2)*point[1];
1245: J[3] = y_1 + (y_3 - y_1 - y_2)*point[0];
1246: detJ = J[0]*J[3] - J[1]*J[2];
1247: PetscLogFlopsNoCheck(6 + 16 + 3);
1248: }
1249: if (invJ) {
1250: invDet = 1.0/detJ;
1251: invJ[0] = invDet*J[3];
1252: invJ[1] = -invDet*J[1];
1253: invJ[2] = -invDet*J[2];
1254: invJ[3] = invDet*J[0];
1255: PetscLogFlopsNoCheck(5);
1256: }
1257: };
1258: void computeTetrahedronGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
1259: const double *coords = this->restrict(coordinates, e);
1260: const int dim = 3;
1261: double invDet;
1263: if (v0) {
1264: for(int d = 0; d < dim; d++) {
1265: v0[d] = coords[d];
1266: }
1267: }
1268: if (J) {
1269: for(int d = 0; d < dim; d++) {
1270: for(int f = 0; f < dim; f++) {
1271: J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
1272: }
1273: }
1274: // The minus sign is here since I orient the first face to get the outward normal
1275: detJ = -(J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
1276: J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
1277: J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
1278: PetscLogFlopsNoCheck(18 + 12);
1279: }
1280: if (invJ) {
1281: invDet = -1.0/detJ;
1282: invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
1283: invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
1284: invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
1285: invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
1286: invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
1287: invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
1288: invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
1289: invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
1290: invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
1291: PetscLogFlopsNoCheck(37);
1292: }
1293: };
1294: void computeHexahedralGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double point[], double v0[], double J[], double invJ[], double& detJ) {
1295: const double *coords = this->restrict(coordinates, e);
1296: const int dim = 3;
1297: double invDet;
1299: if (v0) {
1300: for(int d = 0; d < dim; d++) {
1301: v0[d] = coords[d];
1302: }
1303: }
1304: if (J) {
1305: double x_1 = coords[3] - coords[0];
1306: double y_1 = coords[4] - coords[1];
1307: double z_1 = coords[5] - coords[2];
1308: double x_2 = coords[6] - coords[0];
1309: double y_2 = coords[7] - coords[1];
1310: double z_2 = coords[8] - coords[2];
1311: double x_3 = coords[9] - coords[0];
1312: double y_3 = coords[10] - coords[1];
1313: double z_3 = coords[11] - coords[2];
1314: double x_4 = coords[12] - coords[0];
1315: double y_4 = coords[13] - coords[1];
1316: double z_4 = coords[14] - coords[2];
1317: double x_5 = coords[15] - coords[0];
1318: double y_5 = coords[16] - coords[1];
1319: double z_5 = coords[17] - coords[2];
1320: double x_6 = coords[18] - coords[0];
1321: double y_6 = coords[19] - coords[1];
1322: double z_6 = coords[20] - coords[2];
1323: double x_7 = coords[21] - coords[0];
1324: double y_7 = coords[22] - coords[1];
1325: double z_7 = coords[23] - coords[2];
1326: double g_x = x_1 - x_2 + x_3 + x_4 - x_5 + x_6 - x_7;
1327: double g_y = y_1 - y_2 + y_3 + y_4 - y_5 + y_6 - y_7;
1328: double g_z = z_1 - z_2 + z_3 + z_4 - z_5 + z_6 - z_7;
1330: 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];
1331: 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];
1332: 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];
1333: 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];
1334: 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];
1335: 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];
1336: 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];
1337: 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];
1338: 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];
1339: detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
1340: J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
1341: J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
1342: PetscLogFlopsNoCheck(39 + 81 + 12);
1343: }
1344: if (invJ) {
1345: invDet = 1.0/detJ;
1346: invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
1347: invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
1348: invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
1349: invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
1350: invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
1351: invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
1352: invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
1353: invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
1354: invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
1355: PetscLogFlopsNoCheck(37);
1356: }
1357: };
1358: void computeElementGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
1359: if (this->_dim == 2) {
1360: computeTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
1361: } else if (this->_dim == 3) {
1362: computeTetrahedronGeometry(coordinates, e, v0, J, invJ, detJ);
1363: } else {
1364: throw ALE::Exception("Unsupport dimension for element geometry computation");
1365: }
1366: };
1367: void computeLineFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
1368: const arrow_section_type::point_type arrow(cell, face);
1369: const bool reversed = (this->getArrowSection("orientation")->restrictPoint(arrow)[0] == -2);
1370: const int dim = this->getDimension();
1371: double norm = 0.0;
1372: double *vec = tangent;
1374: if (f == 0) {
1375: vec[0] = 0.0; vec[1] = -1.0;
1376: } else if (f == 1) {
1377: vec[0] = 0.70710678; vec[1] = 0.70710678;
1378: } else if (f == 2) {
1379: vec[0] = -1.0; vec[1] = 0.0;
1380: }
1381: for(int d = 0; d < dim; ++d) {
1382: normal[d] = 0.0;
1383: for(int e = 0; e < dim; ++e) normal[d] += cellInvJ[e*dim+d]*vec[e];
1384: if (reversed) normal[d] = -normal[d];
1385: norm += normal[d]*normal[d];
1386: }
1387: norm = std::sqrt(norm);
1388: for(int d = 0; d < dim; ++d) {
1389: normal[d] /= norm;
1390: }
1391: tangent[0] = normal[1];
1392: tangent[1] = -normal[0];
1393: if (this->debug()) {
1394: std::cout << "Cell: " << cell << " Face: " << face << "("<<f<<")" << std::endl;
1395: for(int d = 0; d < dim; ++d) {
1396: std::cout << "Normal["<<d<<"]: " << normal[d] << " Tangent["<<d<<"]: " << tangent[d] << std::endl;
1397: }
1398: }
1399: // Now get 1D Jacobian info
1400: // Should be a way to get this directly
1401: const double *coords = this->restrict(this->getRealSection("coordinates"), face);
1402: detJ = std::sqrt(PetscSqr(coords[1*2+0] - coords[0*2+0]) + PetscSqr(coords[1*2+1] - coords[0*2+1]))/2.0;
1403: invJ[0] = 1.0/detJ;
1404: };
1405: void computeTriangleFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
1406: const arrow_section_type::point_type arrow(cell, face);
1407: const bool reversed = this->getArrowSection("orientation")->restrictPoint(arrow)[0] < 0;
1408: const int dim = this->getDimension();
1409: const int faceDim = dim-1;
1410: double norm = 0.0;
1411: double *vec = tangent;
1413: if (f == 0) {
1414: vec[0] = 0.0; vec[1] = 0.0; vec[2] = -1.0;
1415: } else if (f == 1) {
1416: vec[0] = 0.0; vec[1] = -1.0; vec[2] = 0.0;
1417: } else if (f == 2) {
1418: vec[0] = 0.57735027; vec[1] = 0.57735027; vec[2] = 0.57735027;
1419: } else if (f == 3) {
1420: vec[0] = -1.0; vec[1] = 0.0; vec[2] = 0.0;
1421: }
1422: for(int d = 0; d < dim; ++d) {
1423: normal[d] = 0.0;
1424: for(int e = 0; e < dim; ++e) normal[d] += cellInvJ[e*dim+d]*vec[e];
1425: if (reversed) normal[d] = -normal[d];
1426: norm += normal[d]*normal[d];
1427: }
1428: norm = std::sqrt(norm);
1429: for(int d = 0; d < dim; ++d) {
1430: normal[d] /= norm;
1431: }
1432: // Get tangents
1433: tangent[0] = normal[1] - normal[2];
1434: tangent[1] = normal[2] - normal[0];
1435: tangent[2] = normal[0] - normal[1];
1436: norm = 0.0;
1437: for(int d = 0; d < dim; ++d) {
1438: norm += tangent[d]*tangent[d];
1439: }
1440: norm = std::sqrt(norm);
1441: for(int d = 0; d < dim; ++d) {
1442: tangent[d] /= norm;
1443: }
1444: tangent[3] = normal[1]*tangent[2] - normal[2]*tangent[1];
1445: tangent[4] = normal[2]*tangent[0] - normal[0]*tangent[2];
1446: tangent[5] = normal[0]*tangent[1] - normal[1]*tangent[0];
1447: if (this->debug()) {
1448: std::cout << "Cell: " << cell << " Face: " << face << "("<<f<<")" << std::endl;
1449: for(int d = 0; d < dim; ++d) {
1450: std::cout << "Normal["<<d<<"]: " << normal[d] << " TangentA["<<d<<"]: " << tangent[d] << " TangentB["<<d<<"]: " << tangent[dim+d] << std::endl;
1451: }
1452: }
1453: // Now get 2D Jacobian info
1454: // Should be a way to get this directly
1455: const double *coords = this->restrict(this->getRealSection("coordinates"), face);
1456: // Rotate so that normal in z
1457: double invR[9], R[9];
1458: double detR, invDetR;
1459: for(int d = 0; d < dim; d++) {
1460: invR[d*dim+0] = tangent[d];
1461: invR[d*dim+1] = tangent[dim+d];
1462: invR[d*dim+2] = normal[d];
1463: }
1464: invDetR = (invR[0*3+0]*(invR[1*3+1]*invR[2*3+2] - invR[1*3+2]*invR[2*3+1]) +
1465: invR[0*3+1]*(invR[1*3+2]*invR[2*3+0] - invR[1*3+0]*invR[2*3+2]) +
1466: invR[0*3+2]*(invR[1*3+0]*invR[2*3+1] - invR[1*3+1]*invR[2*3+0]));
1467: detR = 1.0/invDetR;
1468: R[0*3+0] = detR*(invR[1*3+1]*invR[2*3+2] - invR[1*3+2]*invR[2*3+1]);
1469: R[0*3+1] = detR*(invR[0*3+2]*invR[2*3+1] - invR[0*3+1]*invR[2*3+2]);
1470: R[0*3+2] = detR*(invR[0*3+1]*invR[1*3+2] - invR[0*3+2]*invR[1*3+1]);
1471: R[1*3+0] = detR*(invR[1*3+2]*invR[2*3+0] - invR[1*3+0]*invR[2*3+2]);
1472: R[1*3+1] = detR*(invR[0*3+0]*invR[2*3+2] - invR[0*3+2]*invR[2*3+0]);
1473: R[1*3+2] = detR*(invR[0*3+2]*invR[1*3+0] - invR[0*3+0]*invR[1*3+2]);
1474: R[2*3+0] = detR*(invR[1*3+0]*invR[2*3+1] - invR[1*3+1]*invR[2*3+0]);
1475: R[2*3+1] = detR*(invR[0*3+1]*invR[2*3+0] - invR[0*3+0]*invR[2*3+1]);
1476: R[2*3+2] = detR*(invR[0*3+0]*invR[1*3+1] - invR[0*3+1]*invR[1*3+0]);
1477: for(int d = 0; d < dim; d++) {
1478: for(int e = 0; e < dim; e++) {
1479: invR[d*dim+e] = 0.0;
1480: for(int g = 0; g < dim; g++) {
1481: invR[d*dim+e] += R[e*dim+g]*coords[d*dim+g];
1482: }
1483: }
1484: }
1485: for(int d = dim-1; d >= 0; --d) {
1486: invR[d*dim+2] -= invR[0*dim+2];
1487: if (this->debug() && (d == dim-1)) {
1488: double ref[9];
1489: for(int q = 0; q < dim; q++) {
1490: for(int e = 0; e < dim; e++) {
1491: ref[q*dim+e] = 0.0;
1492: for(int g = 0; g < dim; g++) {
1493: ref[q*dim+e] += cellInvJ[e*dim+g]*coords[q*dim+g];
1494: }
1495: }
1496: }
1497: std::cout << "f: " << f << std::endl;
1498: std::cout << this->printMatrix(std::string("coords"), dim, dim, coords) << std::endl;
1499: std::cout << this->printMatrix(std::string("ref coords"), dim, dim, ref) << std::endl;
1500: std::cout << this->printMatrix(std::string("R"), dim, dim, R) << std::endl;
1501: std::cout << this->printMatrix(std::string("invR"), dim, dim, invR) << std::endl;
1502: }
1503: if (fabs(invR[d*dim+2]) > 1.0e-8) {
1504: throw ALE::Exception("Invalid rotation");
1505: }
1506: }
1507: double J[4];
1508: for(int d = 0; d < faceDim; d++) {
1509: for(int e = 0; e < faceDim; e++) {
1510: J[d*faceDim+e] = 0.5*(invR[(e+1)*dim+d] - invR[0*dim+d]);
1511: }
1512: }
1513: detJ = fabs(J[0]*J[3] - J[1]*J[2]);
1514: // Probably need something here if detJ < 0
1515: const double invDet = 1.0/detJ;
1516: invJ[0] = invDet*J[3];
1517: invJ[1] = -invDet*J[1];
1518: invJ[2] = -invDet*J[2];
1519: invJ[3] = invDet*J[0];
1520: };
1521: void computeFaceGeometry(const point_type& cell, const point_type& face, const int f, const double cellInvJ[], double invJ[], double& detJ, double normal[], double tangent[]) {
1522: if (this->_dim == 2) {
1523: computeLineFaceGeometry(cell, face, f, cellInvJ, invJ, detJ, normal, tangent);
1524: } else if (this->_dim == 3) {
1525: computeTriangleFaceGeometry(cell, face, f, cellInvJ, invJ, detJ, normal, tangent);
1526: } else {
1527: throw ALE::Exception("Unsupport dimension for element geometry computation");
1528: }
1529: };
1530: double getMaxVolume() {
1531: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1532: const Obj<label_sequence>& cells = this->heightStratum(0);
1533: const int dim = this->getDimension();
1534: double v0[3], J[9], invJ[9], detJ, refVolume = 0.0, maxVolume = 0.0;
1536: if (dim == 1) refVolume = 2.0;
1537: if (dim == 2) refVolume = 2.0;
1538: if (dim == 3) refVolume = 4.0/3.0;
1539: for(label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1540: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
1541: maxVolume = std::max(maxVolume, detJ*refVolume);
1542: }
1543: return maxVolume;
1544: };
1545: // Find the cell in which this point lies (stupid algorithm)
1546: point_type locatePoint_2D(const real_section_type::value_type point[]) {
1547: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1548: const Obj<label_sequence>& cells = this->heightStratum(0);
1549: const int embedDim = 2;
1550: double v0[2], J[4], invJ[4], detJ;
1552: for(label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1553: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
1554: double xi = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]);
1555: double eta = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]);
1557: if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) {
1558: return *c_iter;
1559: }
1560: }
1561: throw ALE::Exception("Could not locate point");
1562: };
1563: // Assume a simplex and 3D
1564: point_type locatePoint_3D(const real_section_type::value_type point[]) {
1565: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1566: const Obj<label_sequence>& cells = this->heightStratum(0);
1567: const int embedDim = 3;
1568: double v0[3], J[9], invJ[9], detJ;
1570: for(label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
1571: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
1572: 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]);
1573: 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]);
1574: 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]);
1576: if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) {
1577: return *c_iter;
1578: }
1579: }
1580: throw ALE::Exception("Could not locate point");
1581: };
1582: point_type locatePoint(const real_section_type::value_type point[], point_type guess = -1) {
1583: //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
1584: if (guess != -1) {
1585: return guess;
1586: }else if (this->_dim == 2) {
1587: return locatePoint_2D(point);
1588: } else if (this->_dim == 3) {
1589: return locatePoint_3D(point);
1590: } else {
1591: throw ALE::Exception("No point location for mesh dimension");
1592: }
1593: };
1594: public: // Discretization
1595: void markBoundaryCells(const std::string& name, const int marker = 1, const int newMarker = 2, const bool onlyVertices = false) {
1596: const Obj<label_type>& label = this->getLabel(name);
1597: const Obj<label_sequence>& boundary = this->getLabelStratum(name, marker);
1598: const Obj<sieve_type>& sieve = this->getSieve();
1600: if (!onlyVertices) {
1601: const label_sequence::iterator end = boundary->end();
1603: for(label_sequence::iterator e_iter = boundary->begin(); e_iter != end; ++e_iter) {
1604: if (this->height(*e_iter) == 1) {
1605: const point_type cell = *sieve->support(*e_iter)->begin();
1607: this->setValue(label, cell, newMarker);
1608: }
1609: }
1610: } else {
1611: const label_sequence::iterator end = boundary->end();
1612: const int depth = this->depth();
1614: for(label_sequence::iterator v_iter = boundary->begin(); v_iter != end; ++v_iter) {
1615: const Obj<supportArray> support = sieve->nSupport(*v_iter, depth);
1616: const supportArray::iterator sEnd = support->end();
1618: for(supportArray::iterator c_iter = support->begin(); c_iter != sEnd; ++c_iter) {
1619: const Obj<sieve_type::traits::coneSequence>& cone = sieve->cone(*c_iter);
1620: const sieve_type::traits::coneSequence::iterator cEnd = cone->end();
1622: for(sieve_type::traits::coneSequence::iterator e_iter = cone->begin(); e_iter != cEnd; ++e_iter) {
1623: if (sieve->support(*e_iter)->size() == 1) {
1624: this->setValue(label, *c_iter, newMarker);
1625: break;
1626: }
1627: }
1628: }
1629: }
1630: }
1631: };
1632: int setFiberDimensions(const Obj<real_section_type>& s, const Obj<names_type>& discs, names_type& bcLabels) {
1633: const int debug = this->debug();
1634: int maxDof = 0;
1636: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter) {
1637: s->addSpace();
1638: }
1639: for(int d = 0; d <= this->_dim; ++d) {
1640: int numDof = 0;
1641: int f = 0;
1643: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
1644: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
1646: numDof += disc->getNumDof(d);
1647: s->setFiberDimension(this->depthStratum(d), disc->getNumDof(d), f);
1648: }
1649: s->setFiberDimension(this->depthStratum(d), numDof);
1650: maxDof = std::max(maxDof, numDof);
1651: }
1652: // Process exclusions
1653: int f = 0;
1655: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
1656: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
1657: std::string labelName = "exclude-"+*f_iter;
1658: std::set<point_type> seen;
1660: if (this->hasLabel(labelName)) {
1661: const Obj<label_type>& label = this->getLabel(labelName);
1662: const Obj<label_sequence>& exclusion = this->getLabelStratum(labelName, 1);
1663: const label_sequence::iterator end = exclusion->end();
1664: if (debug) {label->view(labelName.c_str());}
1666: for(label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
1667: const Obj<coneArray> closure = ALE::SieveAlg<ALE::Mesh>::closure(this, this->getArrowSection("orientation"), *e_iter);
1668: const coneArray::iterator cEnd = closure->end();
1670: for(coneArray::iterator c_iter = closure->begin(); c_iter != cEnd; ++c_iter) {
1671: if (seen.find(*c_iter) != seen.end()) continue;
1672: if (this->getValue(label, *c_iter) == 1) {
1673: seen.insert(*c_iter);
1674: s->setFiberDimension(*c_iter, 0, f);
1675: s->addFiberDimension(*c_iter, -disc->getNumDof(this->depth(*c_iter)));
1676: if (debug) {std::cout << " cell: " << *c_iter << " dim: " << disc->getNumDof(this->depth(*c_iter)) << std::endl;}
1677: }
1678: }
1679: }
1680: }
1681: }
1682: // Process constraints
1683: f = 0;
1684: for(std::set<std::string>::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
1685: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
1686: const Obj<std::set<std::string> > bcs = disc->getBoundaryConditions();
1687: std::string excludeName = "exclude-"+*f_iter;
1689: for(std::set<std::string>::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter) {
1690: const Obj<ALE::BoundaryCondition>& bc = disc->getBoundaryCondition(*bc_iter);
1691: const Obj<label_sequence>& boundary = this->getLabelStratum(bc->getLabelName(), bc->getMarker());
1693: bcLabels.insert(bc->getLabelName());
1694: if (this->hasLabel(excludeName)) {
1695: const Obj<label_type>& label = this->getLabel(excludeName);
1697: for(label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
1698: if (!this->getValue(label, *e_iter)) {
1699: s->addConstraintDimension(*e_iter, disc->getNumDof(this->depth(*e_iter)));
1700: s->setConstraintDimension(*e_iter, disc->getNumDof(this->depth(*e_iter)), f);
1701: }
1702: }
1703: } else {
1704: for(label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
1705: s->addConstraintDimension(*e_iter, disc->getNumDof(this->depth(*e_iter)));
1706: s->setConstraintDimension(*e_iter, disc->getNumDof(this->depth(*e_iter)), f);
1707: }
1708: }
1709: }
1710: }
1711: return maxDof;
1712: };
1713: void calculateIndices() {
1714: // Should have an iterator over the whole tree
1715: Obj<names_type> discs = this->getDiscretizations();
1716: Obj<Mesh> mesh = this;
1717: const int debug = this->debug();
1718: std::map<std::string, std::pair<int, int*> > indices;
1720: mesh.addRef();
1721: for(names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
1722: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
1724: indices[*d_iter] = std::pair<int, int*>(0, new int[disc->size(mesh)]);
1725: disc->setIndices(indices[*d_iter].second);
1726: }
1727: const Obj<label_sequence>& cells = this->heightStratum(0);
1728: const Obj<coneArray> closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *cells->begin());
1729: const coneArray::iterator end = closure->end();
1730: int offset = 0;
1732: if (debug) {std::cout << "Closure for first element" << std::endl;}
1733: for(coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
1734: const int dim = this->depth(*cl_iter);
1736: if (debug) {std::cout << " point " << *cl_iter << " depth " << dim << std::endl;}
1737: for(names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
1738: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
1739: const int num = disc->getNumDof(dim);
1741: if (debug) {std::cout << " disc " << disc->getName() << " numDof " << num << std::endl;}
1742: for(int o = 0; o < num; ++o) {
1743: indices[*d_iter].second[indices[*d_iter].first++] = offset++;
1744: }
1745: }
1746: }
1747: if (debug) {
1748: for(names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
1749: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
1751: std::cout << "Discretization " << disc->getName() << " indices:";
1752: for(int i = 0; i < indices[*d_iter].first; ++i) {
1753: std::cout << " " << indices[*d_iter].second[i];
1754: }
1755: std::cout << std::endl;
1756: }
1757: }
1758: };
1759: void calculateIndicesExcluded(const Obj<real_section_type>& s, const Obj<names_type>& discs) {
1760: typedef std::map<std::string, std::pair<int, indexSet> > indices_type;
1761: const Obj<label_type>& indexLabel = this->createLabel("cellExclusion");
1762: Obj<Mesh> mesh = this;
1763: const int debug = this->debug();
1764: int marker = 0;
1765: std::map<indices_type, int> indexMap;
1766: indices_type indices;
1768: mesh.addRef();
1769: for(names_type::const_iterator d_iter = discs->begin(); d_iter != discs->end(); ++d_iter) {
1770: const Obj<Discretization>& disc = this->getDiscretization(*d_iter);
1771: const int size = disc->size(mesh);
1773: indices[*d_iter].second.resize(size);
1774: }
1775: const names_type::const_iterator dBegin = discs->begin();
1776: const names_type::const_iterator dEnd = discs->end();
1777: std::set<point_type> seen;
1778: int f = 0;
1780: for(names_type::const_iterator f_iter = dBegin; f_iter != dEnd; ++f_iter, ++f) {
1781: std::string labelName = "exclude-"+*f_iter;
1783: if (this->hasLabel(labelName)) {
1784: const Obj<label_sequence>& exclusion = this->getLabelStratum(labelName, 1);
1785: const label_sequence::iterator end = exclusion->end();
1787: if (debug) {std::cout << "Processing exclusion " << labelName << std::endl;}
1788: for(label_sequence::iterator e_iter = exclusion->begin(); e_iter != end; ++e_iter) {
1789: if (this->height(*e_iter)) continue;
1790: const Obj<coneArray> closure = ALE::SieveAlg<ALE::Mesh>::closure(this, this->getArrowSection("orientation"), *e_iter);
1791: const coneArray::iterator clEnd = closure->end();
1792: int offset = 0;
1794: if (debug) {std::cout << " Closure for cell " << *e_iter << std::endl;}
1795: for(coneArray::iterator cl_iter = closure->begin(); cl_iter != clEnd; ++cl_iter) {
1796: int g = 0;
1798: if (debug) {std::cout << " point " << *cl_iter << std::endl;}
1799: for(names_type::const_iterator g_iter = dBegin; g_iter != dEnd; ++g_iter, ++g) {
1800: const int fDim = s->getFiberDimension(*cl_iter, g);
1802: if (debug) {std::cout << " disc " << *g_iter << " numDof " << fDim << std::endl;}
1803: for(int d = 0; d < fDim; ++d) {
1804: indices[*g_iter].second[indices[*g_iter].first++] = offset++;
1805: }
1806: }
1807: }
1808: const std::map<indices_type, int>::iterator entry = indexMap.find(indices);
1810: if (debug) {
1811: for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
1812: for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
1813: std::cout << "Discretization (" << i_iter->second << ") " << *g_iter << " indices:";
1814: for(int i = 0; i < ((indices_type) i_iter->first)[*g_iter].first; ++i) {
1815: std::cout << " " << ((indices_type) i_iter->first)[*g_iter].second[i];
1816: }
1817: std::cout << std::endl;
1818: }
1819: std::cout << "Comparison: " << (indices == i_iter->first) << std::endl;
1820: }
1821: for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
1822: std::cout << "Discretization " << *g_iter << " indices:";
1823: for(int i = 0; i < indices[*g_iter].first; ++i) {
1824: std::cout << " " << indices[*g_iter].second[i];
1825: }
1826: std::cout << std::endl;
1827: }
1828: }
1829: if (entry != indexMap.end()) {
1830: this->setValue(indexLabel, *e_iter, entry->second);
1831: if (debug) {std::cout << " Found existing indices with marker " << entry->second << std::endl;}
1832: } else {
1833: indexMap[indices] = ++marker;
1834: this->setValue(indexLabel, *e_iter, marker);
1835: if (debug) {std::cout << " Created new indices with marker " << marker << std::endl;}
1836: }
1837: for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
1838: indices[*g_iter].first = 0;
1839: for(unsigned int i = 0; i < indices[*g_iter].second.size(); ++i) indices[*g_iter].second[i] = 0;
1840: }
1841: }
1842: }
1843: }
1844: if (debug) {indexLabel->view("cellExclusion");}
1845: for(std::map<indices_type, int>::iterator i_iter = indexMap.begin(); i_iter != indexMap.end(); ++i_iter) {
1846: if (debug) {std::cout << "Setting indices for marker " << i_iter->second << std::endl;}
1847: for(names_type::const_iterator g_iter = discs->begin(); g_iter != discs->end(); ++g_iter) {
1848: const Obj<Discretization>& disc = this->getDiscretization(*g_iter);
1849: const indexSet indSet = ((indices_type) i_iter->first)[*g_iter].second;
1850: const int size = indSet.size();
1851: int *_indices = new int[size];
1853: if (debug) {std::cout << " field " << *g_iter << std::endl;}
1854: for(int i = 0; i < size; ++i) {
1855: _indices[i] = indSet[i];
1856: if (debug) {std::cout << " indices["<<i<<"] = " << _indices[i] << std::endl;}
1857: }
1858: disc->setIndices(_indices, i_iter->second);
1859: }
1860: }
1861: };
1862: void setupField(const Obj<real_section_type>& s, const int cellMarker = 2, const bool noUpdate = false) {
1863: const Obj<names_type>& discs = this->getDiscretizations();
1864: const int debug = s->debug();
1865: names_type bcLabels;
1866: int maxDof;
1868: maxDof = this->setFiberDimensions(s, discs, bcLabels);
1869: this->calculateIndices();
1870: this->calculateIndicesExcluded(s, discs);
1871: this->allocate(s);
1872: s->defaultConstraintDof();
1873: const Obj<label_type>& cellExclusion = this->getLabel("cellExclusion");
1875: if (debug) {std::cout << "Setting boundary values" << std::endl;}
1876: for(names_type::const_iterator n_iter = bcLabels.begin(); n_iter != bcLabels.end(); ++n_iter) {
1877: const Obj<label_sequence>& boundaryCells = this->getLabelStratum(*n_iter, cellMarker);
1878: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
1879: const Obj<names_type>& discs = this->getDiscretizations();
1880: const point_type firstCell = *boundaryCells->begin();
1881: const int numFields = discs->size();
1882: real_section_type::value_type *values = new real_section_type::value_type[this->sizeWithBC(s, firstCell)];
1883: int *dofs = new int[maxDof];
1884: int *v = new int[numFields];
1885: double *v0 = new double[this->getDimension()];
1886: double *J = new double[this->getDimension()*this->getDimension()];
1887: double detJ;
1889: for(label_sequence::iterator c_iter = boundaryCells->begin(); c_iter != boundaryCells->end(); ++c_iter) {
1890: const Obj<coneArray> closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *c_iter);
1891: const coneArray::iterator end = closure->end();
1893: if (debug) {std::cout << " Boundary cell " << *c_iter << std::endl;}
1894: this->computeElementGeometry(coordinates, *c_iter, v0, J, PETSC_NULL, detJ);
1895: for(int f = 0; f < numFields; ++f) v[f] = 0;
1896: for(coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
1897: const int cDim = s->getConstraintDimension(*cl_iter);
1898: int off = 0;
1899: int f = 0;
1900: int i = -1;
1902: if (debug) {std::cout << " point " << *cl_iter << std::endl;}
1903: if (cDim) {
1904: if (debug) {std::cout << " constrained excMarker: " << this->getValue(cellExclusion, *c_iter) << std::endl;}
1905: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
1906: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
1907: const Obj<names_type> bcs = disc->getBoundaryConditions();
1908: const int fDim = s->getFiberDimension(*cl_iter, f);//disc->getNumDof(this->depth(*cl_iter));
1909: const int *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
1910: int b = 0;
1912: for(names_type::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter, ++b) {
1913: const Obj<ALE::BoundaryCondition>& bc = disc->getBoundaryCondition(*bc_iter);
1914: const int value = this->getValue(this->getLabel(bc->getLabelName()), *cl_iter);
1916: if (b > 0) v[f] -= fDim;
1917: if (value == bc->getMarker()) {
1918: if (debug) {std::cout << " field " << *f_iter << " marker " << value << std::endl;}
1919: for(int d = 0; d < fDim; ++d, ++v[f]) {
1920: dofs[++i] = off+d;
1921: if (!noUpdate) values[indices[v[f]]] = (*bc->getDualIntegrator())(v0, J, v[f], bc->getFunction());
1922: if (debug) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
1923: }
1924: // Allow only one condition per point
1925: ++b;
1926: break;
1927: } else {
1928: if (debug) {std::cout << " field " << *f_iter << std::endl;}
1929: for(int d = 0; d < fDim; ++d, ++v[f]) {
1930: values[indices[v[f]]] = 0.0;
1931: if (debug) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
1932: }
1933: }
1934: }
1935: if (b == 0) {
1936: if (debug) {std::cout << " field " << *f_iter << std::endl;}
1937: for(int d = 0; d < fDim; ++d, ++v[f]) {
1938: values[indices[v[f]]] = 0.0;
1939: if (debug) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
1940: }
1941: }
1942: off += fDim;
1943: }
1944: if (i != cDim-1) {throw ALE::Exception("Invalid constraint initialization");}
1945: s->setConstraintDof(*cl_iter, dofs);
1946: } else {
1947: if (debug) {std::cout << " unconstrained" << std::endl;}
1948: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
1949: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
1950: const int fDim = s->getFiberDimension(*cl_iter, f);//disc->getNumDof(this->depth(*cl_iter));
1951: const int *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
1953: if (debug) {std::cout << " field " << *f_iter << std::endl;}
1954: for(int d = 0; d < fDim; ++d, ++v[f]) {
1955: values[indices[v[f]]] = 0.0;
1956: if (debug) {std::cout << " setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
1957: }
1958: }
1959: }
1960: }
1961: if (debug) {
1962: const Obj<coneArray> closure = sieve_alg_type::closure(this, this->getArrowSection("orientation"), *c_iter);
1963: const coneArray::iterator end = closure->end();
1965: for(int f = 0; f < numFields; ++f) v[f] = 0;
1966: for(coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
1967: int f = 0;
1968: for(names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
1969: const Obj<ALE::Discretization>& disc = this->getDiscretization(*f_iter);
1970: const int fDim = s->getFiberDimension(*cl_iter, f);
1971: const int *indices = disc->getIndices(this->getValue(cellExclusion, *c_iter));
1973: for(int d = 0; d < fDim; ++d, ++v[f]) {
1974: std::cout << " "<<*f_iter<<"-value["<<indices[v[f]]<<"] " << values[indices[v[f]]] << std::endl;
1975: }
1976: }
1977: }
1978: }
1979: if (!noUpdate) {
1980: this->updateAll(s, *c_iter, values);
1981: }
1982: }
1983: delete [] dofs;
1984: delete [] values;
1985: delete [] v0;
1986: delete [] J;
1987: }
1988: if (debug) {s->view("");}
1989: };
1990: public:
1991: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
1992: if (comm == MPI_COMM_NULL) {
1993: comm = this->comm();
1994: }
1995: if (name == "") {
1996: PetscPrintf(comm, "viewing a Mesh\n");
1997: } else {
1998: PetscPrintf(comm, "viewing Mesh '%s'\n", name.c_str());
1999: }
2000: this->getSieve()->view("mesh sieve", comm);
2001: Obj<names_type> sections = this->getRealSections();
2003: for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2004: this->getRealSection(*name)->view(*name);
2005: }
2006: sections = this->getIntSections();
2007: for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2008: this->getIntSection(*name)->view(*name);
2009: }
2010: sections = this->getArrowSections();
2011: for(names_type::iterator name = sections->begin(); name != sections->end(); ++name) {
2012: this->getArrowSection(*name)->view(*name);
2013: }
2014: };
2015: template<typename value_type>
2016: static std::string printMatrix(const std::string& name, const int rows, const int cols, const value_type matrix[], const int rank = -1)
2017: {
2018: ostringstream output;
2019: ostringstream rankStr;
2021: if (rank >= 0) {
2022: rankStr << "[" << rank << "]";
2023: }
2024: output << rankStr.str() << name << " = " << std::endl;
2025: for(int r = 0; r < rows; r++) {
2026: if (r == 0) {
2027: output << rankStr.str() << " /";
2028: } else if (r == rows-1) {
2029: output << rankStr.str() << " \\";
2030: } else {
2031: output << rankStr.str() << " |";
2032: }
2033: for(int c = 0; c < cols; c++) {
2034: output << " " << matrix[r*cols+c];
2035: }
2036: if (r == 0) {
2037: output << " \\" << std::endl;
2038: } else if (r == rows-1) {
2039: output << " /" << std::endl;
2040: } else {
2041: output << " |" << std::endl;
2042: }
2043: }
2044: return output.str();
2045: };
2046: };
2047: class MeshBuilder {
2048: typedef ALE::Mesh Mesh;
2049: public:
2052: /*
2053: Simple square boundary:
2055: 18--5-17--4--16
2056: | | |
2057: 6 10 3
2058: | | |
2059: 19-11-20--9--15
2060: | | |
2061: 7 8 2
2062: | | |
2063: 12--0-13--1--14
2064: */
2065: static Obj<ALE::Mesh> createSquareBoundary(const MPI_Comm comm, const double lower[], const double upper[], const int edges[], const int debug = 0) {
2066: Obj<Mesh> mesh = new Mesh(comm, 1, debug);
2067: int numVertices = (edges[0]+1)*(edges[1]+1);
2068: int numEdges = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
2069: double *coords = new double[numVertices*2];
2070: const Obj<Mesh::sieve_type> sieve = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2071: Mesh::point_type *vertices = new Mesh::point_type[numVertices];
2072: int order = 0;
2074: mesh->setSieve(sieve);
2075: const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2076: if (mesh->commRank() == 0) {
2077: /* Create sieve and ordering */
2078: for(int v = numEdges; v < numEdges+numVertices; v++) {
2079: vertices[v-numEdges] = Mesh::point_type(v);
2080: }
2081: for(int vy = 0; vy <= edges[1]; vy++) {
2082: for(int ex = 0; ex < edges[0]; ex++) {
2083: Mesh::point_type edge(vy*edges[0] + ex);
2084: int vertex = vy*(edges[0]+1) + ex;
2086: sieve->addArrow(vertices[vertex+0], edge, order++);
2087: sieve->addArrow(vertices[vertex+1], edge, order++);
2088: if ((vy == 0) || (vy == edges[1])) {
2089: mesh->setValue(markers, edge, 1);
2090: mesh->setValue(markers, vertices[vertex], 1);
2091: if (ex == edges[0]-1) {
2092: mesh->setValue(markers, vertices[vertex+1], 1);
2093: }
2094: }
2095: }
2096: }
2097: for(int vx = 0; vx <= edges[0]; vx++) {
2098: for(int ey = 0; ey < edges[1]; ey++) {
2099: Mesh::point_type edge(vx*edges[1] + ey + edges[0]*(edges[1]+1));
2100: int vertex = ey*(edges[0]+1) + vx;
2102: sieve->addArrow(vertices[vertex], edge, order++);
2103: sieve->addArrow(vertices[vertex+edges[0]+1], edge, order++);
2104: if ((vx == 0) || (vx == edges[0])) {
2105: mesh->setValue(markers, edge, 1);
2106: mesh->setValue(markers, vertices[vertex], 1);
2107: if (ey == edges[1]-1) {
2108: mesh->setValue(markers, vertices[vertex+edges[0]+1], 1);
2109: }
2110: }
2111: }
2112: }
2113: }
2114: mesh->stratify();
2115: for(int vy = 0; vy <= edges[1]; ++vy) {
2116: for(int vx = 0; vx <= edges[0]; ++vx) {
2117: coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
2118: coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
2119: }
2120: }
2121: delete [] vertices;
2122: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2123: return mesh;
2124: };
2127: /*
2128: Simple square boundary:
2130: 18--5-17--4--16
2131: | | |
2132: 6 10 3
2133: | | |
2134: 19-11-20--9--15
2135: | | |
2136: 7 8 2
2137: | | |
2138: 12--0-13--1--14
2139: */
2140: static Obj<ALE::Mesh> createParticleInSquareBoundary(const MPI_Comm comm, const double lower[], const double upper[], const int edges[], const double radius, const int partEdges, const int debug = 0) {
2141: Obj<Mesh> mesh = new Mesh(comm, 1, debug);
2142: const int numSquareVertices = (edges[0]+1)*(edges[1]+1);
2143: const int numVertices = numSquareVertices + partEdges;
2144: const int numSquareEdges = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
2145: const int numEdges = numSquareEdges + partEdges;
2146: double *coords = new double[numVertices*2];
2147: const Obj<Mesh::sieve_type> sieve = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2148: Mesh::point_type *vertices = new Mesh::point_type[numVertices];
2149: int order = 0;
2151: mesh->setSieve(sieve);
2152: const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2153: if (mesh->commRank() == 0) {
2154: /* Create sieve and ordering */
2155: for(int v = numEdges; v < numEdges+numVertices; v++) {
2156: vertices[v-numEdges] = Mesh::point_type(v);
2157: }
2158: // Make square
2159: for(int vy = 0; vy <= edges[1]; vy++) {
2160: for(int ex = 0; ex < edges[0]; ex++) {
2161: Mesh::point_type edge(vy*edges[0] + ex);
2162: int vertex = vy*(edges[0]+1) + ex;
2164: sieve->addArrow(vertices[vertex+0], edge, order++);
2165: sieve->addArrow(vertices[vertex+1], edge, order++);
2166: if ((vy == 0) || (vy == edges[1])) {
2167: mesh->setValue(markers, edge, 1);
2168: mesh->setValue(markers, vertices[vertex], 1);
2169: if (ex == edges[0]-1) {
2170: mesh->setValue(markers, vertices[vertex+1], 1);
2171: }
2172: }
2173: }
2174: }
2175: for(int vx = 0; vx <= edges[0]; vx++) {
2176: for(int ey = 0; ey < edges[1]; ey++) {
2177: Mesh::point_type edge(vx*edges[1] + ey + edges[0]*(edges[1]+1));
2178: int vertex = ey*(edges[0]+1) + vx;
2180: sieve->addArrow(vertices[vertex], edge, order++);
2181: sieve->addArrow(vertices[vertex+edges[0]+1], edge, order++);
2182: if ((vx == 0) || (vx == edges[0])) {
2183: mesh->setValue(markers, edge, 1);
2184: mesh->setValue(markers, vertices[vertex], 1);
2185: if (ey == edges[1]-1) {
2186: mesh->setValue(markers, vertices[vertex+edges[0]+1], 1);
2187: }
2188: }
2189: }
2190: }
2191: // Make particle
2192: for(int ep = 0; ep < partEdges; ++ep) {
2193: Mesh::point_type edge(numSquareEdges + ep);
2194: const int vertexA = numSquareVertices + ep;
2195: const int vertexB = numSquareVertices + (ep+1)%partEdges;
2197: sieve->addArrow(vertices[vertexA], edge, order++);
2198: sieve->addArrow(vertices[vertexB], edge, order++);
2199: mesh->setValue(markers, edge, 2);
2200: mesh->setValue(markers, vertices[vertexA], 2);
2201: mesh->setValue(markers, vertices[vertexB], 2);
2202: }
2203: }
2204: mesh->stratify();
2205: for(int vy = 0; vy <= edges[1]; ++vy) {
2206: for(int vx = 0; vx <= edges[0]; ++vx) {
2207: coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
2208: coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
2209: }
2210: }
2211: const double centroidX = 0.5*(upper[0] + lower[0]);
2212: const double centroidY = 0.5*(upper[1] + lower[1]);
2213: for(int vp = 0; vp < partEdges; ++vp) {
2214: const double rad = 2.0*PETSC_PI*vp/partEdges;
2215: coords[(numSquareVertices+vp)*2+0] = centroidX + radius*cos(rad);
2216: coords[(numSquareVertices+vp)*2+1] = centroidY + radius*sin(rad);
2217: }
2218: delete [] vertices;
2219: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2220: return mesh;
2221: };
2224: /*
2225: Simple boundary with reentrant singularity:
2227: 12--5-11
2228: | |
2229: | 4
2230: | |
2231: 6 10--3--9
2232: | |
2233: | 2
2234: | |
2235: 7-----1-----8
2236: */
2237: static Obj<ALE::Mesh> createReentrantBoundary(const MPI_Comm comm, const double lower[], const double upper[], double notchpercent[], const int debug = 0) {
2238: Obj<Mesh> mesh = new Mesh(comm, 1, debug);
2239: int numVertices = 6;
2240: int numEdges = numVertices;
2241: double *coords = new double[numVertices*2];
2242: const Obj<Mesh::sieve_type> sieve = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2243: Mesh::point_type *vertices = new Mesh::point_type[numVertices];
2245: mesh->setSieve(sieve);
2246: const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2247: if (mesh->commRank() == 0) {
2248: /* Create sieve and ordering */
2249: for (int b = 0; b < numVertices; b++) {
2250: sieve->addArrow(numEdges+b, b);
2251: sieve->addArrow(numEdges+b, (b+1)%numVertices);
2252: mesh->setValue(markers, b, 1);
2253: mesh->setValue(markers, b+numVertices, 1);
2254: }
2255: coords[0] = upper[0];
2256: coords[1] = lower[1];
2258: coords[2] = lower[0];
2259: coords[3] = lower[1];
2260:
2261: coords[4] = lower[0];
2262: coords[5] = notchpercent[1]*lower[1] + (1 - notchpercent[1])*upper[1];
2263:
2264: coords[6] = notchpercent[0]*upper[0] + (1 - notchpercent[0])*lower[0];
2265: coords[7] = notchpercent[1]*lower[1] + (1 - notchpercent[1])*upper[1];
2266:
2267:
2268: coords[8] = notchpercent[0]*upper[0] + (1 - notchpercent[0])*lower[0];
2269: coords[9] = upper[1];
2271: coords[10] = upper[0];
2272: coords[11] = upper[1];
2273: mesh->stratify();
2274: }
2275: delete [] vertices;
2276: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2277: return mesh;
2278: }
2282: /*
2283: Circular boundary with reentrant singularity:
2285: ___--1
2286: | |
2287: | |
2288: | |
2289: - 0-----n
2290: - |
2291: - |
2292: -___ _|
2293: --
2294: */
2295: static Obj<ALE::Mesh> createCircularReentrantBoundary(const MPI_Comm comm, const int segments, const double radius, const double arc_percent, const int debug = 0) {
2296: Obj<Mesh> mesh = new Mesh(comm, 1, debug);
2297: int numVertices = segments+2;
2298: int numEdges = numVertices;
2299: double *coords = new double[numVertices*2];
2300: const Obj<Mesh::sieve_type> sieve = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2301: Mesh::point_type *vertices = new Mesh::point_type[numVertices];
2303: mesh->setSieve(sieve);
2304: const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2305: if (mesh->commRank() == 0) {
2306: /* Create sieve and ordering */
2308: int startvertex = 1;
2309: if (arc_percent < 1.) {
2310: coords[0] = 0.;
2311: coords[1] = 0.;
2312: } else {
2313: numVertices = segments;
2314: numEdges = numVertices;
2315: startvertex = 0;
2316: }
2318: for (int b = 0; b < numVertices; b++) {
2319: sieve->addArrow(numEdges+b, b);
2320: sieve->addArrow(numEdges+b, (b+1)%numVertices);
2321: mesh->setValue(markers, b, 1);
2322: mesh->setValue(markers, b+numVertices, 1);
2323: }
2325: double anglestep = arc_percent*2.*3.14159265/((float)segments);
2327: for (int i = startvertex; i < numVertices; i++) {
2328: coords[2*i] = radius * sin(anglestep*(i-startvertex));
2329: coords[2*i+1] = radius*cos(anglestep*(i-startvertex));
2330: }
2331: mesh->stratify();
2332: }
2333: delete [] vertices;
2334: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2335: return mesh;
2336: };
2339: /*
2340: Simple cubic boundary:
2342: 30----31-----32
2343: | | |
2344: | 3 | 2 |
2345: | | |
2346: 27----28-----29
2347: | | |
2348: | 0 | 1 |
2349: | | |
2350: 24----25-----26
2351: */
2352: static Obj<Mesh> createCubeBoundary(const MPI_Comm comm, const double lower[], const double upper[], const int faces[], const int debug = 0) {
2353: Obj<Mesh> mesh = new Mesh(comm, 2, debug);
2354: int numVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
2355: int numFaces = 6;
2356: double *coords = new double[numVertices*3];
2357: const Obj<Mesh::sieve_type> sieve = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2358: Mesh::point_type *vertices = new Mesh::point_type[numVertices];
2359: int order = 0;
2361: mesh->setSieve(sieve);
2362: const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2363: if (mesh->commRank() == 0) {
2364: /* Create sieve and ordering */
2365: for(int v = numFaces; v < numFaces+numVertices; v++) {
2366: vertices[v-numFaces] = Mesh::point_type(v);
2367: mesh->setValue(markers, vertices[v-numFaces], 1);
2368: }
2369: {
2370: // Side 0 (Front)
2371: Mesh::point_type face(0);
2372: sieve->addArrow(vertices[0], face, order++);
2373: sieve->addArrow(vertices[1], face, order++);
2374: sieve->addArrow(vertices[2], face, order++);
2375: sieve->addArrow(vertices[3], face, order++);
2376: mesh->setValue(markers, face, 1);
2377: }
2378: {
2379: // Side 1 (Back)
2380: Mesh::point_type face(1);
2381: sieve->addArrow(vertices[5], face, order++);
2382: sieve->addArrow(vertices[4], face, order++);
2383: sieve->addArrow(vertices[7], face, order++);
2384: sieve->addArrow(vertices[6], face, order++);
2385: mesh->setValue(markers, face, 1);
2386: }
2387: {
2388: // Side 2 (Bottom)
2389: Mesh::point_type face(2);
2390: sieve->addArrow(vertices[4], face, order++);
2391: sieve->addArrow(vertices[5], face, order++);
2392: sieve->addArrow(vertices[1], face, order++);
2393: sieve->addArrow(vertices[0], face, order++);
2394: mesh->setValue(markers, face, 1);
2395: }
2396: {
2397: // Side 3 (Top)
2398: Mesh::point_type face(3);
2399: sieve->addArrow(vertices[3], face, order++);
2400: sieve->addArrow(vertices[2], face, order++);
2401: sieve->addArrow(vertices[6], face, order++);
2402: sieve->addArrow(vertices[7], face, order++);
2403: mesh->setValue(markers, face, 1);
2404: }
2405: {
2406: // Side 4 (Left)
2407: Mesh::point_type face(4);
2408: sieve->addArrow(vertices[4], face, order++);
2409: sieve->addArrow(vertices[0], face, order++);
2410: sieve->addArrow(vertices[3], face, order++);
2411: sieve->addArrow(vertices[7], face, order++);
2412: mesh->setValue(markers, face, 1);
2413: }
2414: {
2415: // Side 5 (Right)
2416: Mesh::point_type face(5);
2417: sieve->addArrow(vertices[1], face, order++);
2418: sieve->addArrow(vertices[5], face, order++);
2419: sieve->addArrow(vertices[6], face, order++);
2420: sieve->addArrow(vertices[2], face, order++);
2421: mesh->setValue(markers, face, 1);
2422: }
2423: }
2424: mesh->stratify();
2425: #if 0
2426: for(int vz = 0; vz <= edges[2]; ++vz) {
2427: for(int vy = 0; vy <= edges[1]; ++vy) {
2428: for(int vx = 0; vx <= edges[0]; ++vx) {
2429: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
2430: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
2431: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
2432: }
2433: }
2434: }
2435: #else
2436: coords[0*3+0] = lower[0];
2437: coords[0*3+1] = lower[1];
2438: coords[0*3+2] = upper[2];
2439: coords[1*3+0] = upper[0];
2440: coords[1*3+1] = lower[1];
2441: coords[1*3+2] = upper[2];
2442: coords[2*3+0] = upper[0];
2443: coords[2*3+1] = upper[1];
2444: coords[2*3+2] = upper[2];
2445: coords[3*3+0] = lower[0];
2446: coords[3*3+1] = upper[1];
2447: coords[3*3+2] = upper[2];
2448: coords[4*3+0] = lower[0];
2449: coords[4*3+1] = lower[1];
2450: coords[4*3+2] = lower[2];
2451: coords[5*3+0] = upper[0];
2452: coords[5*3+1] = lower[1];
2453: coords[5*3+2] = lower[2];
2454: coords[6*3+0] = upper[0];
2455: coords[6*3+1] = upper[1];
2456: coords[6*3+2] = lower[2];
2457: coords[7*3+0] = lower[0];
2458: coords[7*3+1] = upper[1];
2459: coords[7*3+2] = lower[2];
2460: #endif
2461: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2462: return mesh;
2463: };
2466: /*
2467: Simple cubic boundary:
2469: 30----31-----32
2470: | | |
2471: | 3 | 2 |
2472: | | |
2473: 27----28-----29
2474: | | |
2475: | 0 | 1 |
2476: | | |
2477: 24----25-----26
2478: */
2479: static Obj<Mesh> createParticleInCubeBoundary(const MPI_Comm comm, const double lower[], const double upper[], const int faces[], const double radius, const int thetaEdges, const int phiSlices, const int debug = 0) {
2480: Obj<Mesh> mesh = new Mesh(comm, 2, debug);
2481: const int numCubeVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
2482: const int numPartVertices = (thetaEdges - 1)*phiSlices + 2;
2483: const int numVertices = numCubeVertices + numPartVertices;
2484: const int numCubeFaces = 6;
2485: const int numFaces = numCubeFaces + thetaEdges*phiSlices;
2486: double *coords = new double[numVertices*3];
2487: const Obj<Mesh::sieve_type> sieve = new Mesh::sieve_type(mesh->comm(), mesh->debug());
2488: Mesh::point_type *vertices = new Mesh::point_type[numVertices];
2489: int order = 0;
2491: mesh->setSieve(sieve);
2492: const Obj<Mesh::label_type>& markers = mesh->createLabel("marker");
2493: if (mesh->commRank() == 0) {
2494: // Make cube
2495: for(int v = numFaces; v < numFaces+numVertices; v++) {
2496: vertices[v-numFaces] = Mesh::point_type(v);
2497: mesh->setValue(markers, vertices[v-numFaces], 1);
2498: }
2499: {
2500: // Side 0 (Front)
2501: Mesh::point_type face(0);
2502: sieve->addArrow(vertices[0], face, order++);
2503: sieve->addArrow(vertices[1], face, order++);
2504: sieve->addArrow(vertices[2], face, order++);
2505: sieve->addArrow(vertices[3], face, order++);
2506: mesh->setValue(markers, face, 1);
2507: }
2508: {
2509: // Side 1 (Back)
2510: Mesh::point_type face(1);
2511: sieve->addArrow(vertices[5], face, order++);
2512: sieve->addArrow(vertices[4], face, order++);
2513: sieve->addArrow(vertices[7], face, order++);
2514: sieve->addArrow(vertices[6], face, order++);
2515: mesh->setValue(markers, face, 1);
2516: }
2517: {
2518: // Side 2 (Bottom)
2519: Mesh::point_type face(2);
2520: sieve->addArrow(vertices[4], face, order++);
2521: sieve->addArrow(vertices[5], face, order++);
2522: sieve->addArrow(vertices[1], face, order++);
2523: sieve->addArrow(vertices[0], face, order++);
2524: mesh->setValue(markers, face, 1);
2525: }
2526: {
2527: // Side 3 (Top)
2528: Mesh::point_type face(3);
2529: sieve->addArrow(vertices[3], face, order++);
2530: sieve->addArrow(vertices[2], face, order++);
2531: sieve->addArrow(vertices[6], face, order++);
2532: sieve->addArrow(vertices[7], face, order++);
2533: mesh->setValue(markers, face, 1);
2534: }
2535: {
2536: // Side 4 (Left)
2537: Mesh::point_type face(4);
2538: sieve->addArrow(vertices[4], face, order++);
2539: sieve->addArrow(vertices[0], face, order++);
2540: sieve->addArrow(vertices[3], face, order++);
2541: sieve->addArrow(vertices[7], face, order++);
2542: mesh->setValue(markers, face, 1);
2543: }
2544: {
2545: // Side 5 (Right)
2546: Mesh::point_type face(5);
2547: sieve->addArrow(vertices[1], face, order++);
2548: sieve->addArrow(vertices[5], face, order++);
2549: sieve->addArrow(vertices[6], face, order++);
2550: sieve->addArrow(vertices[2], face, order++);
2551: mesh->setValue(markers, face, 1);
2552: }
2553: // Make particle
2554: for(int s = 0; s < phiSlices; ++s) {
2555: for(int ep = 0; ep < thetaEdges; ++ep) {
2556: // Vertices on each slice are 0..thetaEdges
2557: Mesh::point_type face(numCubeFaces + s*thetaEdges + ep);
2558: int vertexA = numCubeVertices + ep + 0 + s*(thetaEdges+1);
2559: int vertexB = numCubeVertices + ep + 1 + s*(thetaEdges+1);
2560: int vertexC = numCubeVertices + (ep + 1 + (s+1)*(thetaEdges+1))%((thetaEdges+1)*phiSlices);
2561: int vertexD = numCubeVertices + (ep + 0 + (s+1)*(thetaEdges+1))%((thetaEdges+1)*phiSlices);
2562: const int correction1 = (s > 0)*((s-1)*2 + 1);
2563: const int correction2 = (s < phiSlices-1)*(s*2 + 1);
2565: if ((vertexA - numCubeVertices)%(thetaEdges+1) == 0) {
2566: vertexA = vertexD = numCubeVertices;
2567: vertexB -= correction1;
2568: vertexC -= correction2;
2569: } else if ((vertexB - numCubeVertices)%(thetaEdges+1) == thetaEdges) {
2570: vertexA -= correction1;
2571: vertexD -= correction2;
2572: vertexB = vertexC = numCubeVertices + thetaEdges;
2573: } else {
2574: vertexA -= correction1;
2575: vertexB -= correction1;
2576: vertexC -= correction2;
2577: vertexD -= correction2;
2578: }
2579: if ((vertexA >= numVertices) || (vertexB >= numVertices) || (vertexC >= numVertices) || (vertexD >= numVertices)) {
2580: throw ALE::Exception("Bad vertex");
2581: }
2582: sieve->addArrow(vertices[vertexA], face, order++);
2583: sieve->addArrow(vertices[vertexB], face, order++);
2584: if (vertexB != vertexC) sieve->addArrow(vertices[vertexC], face, order++);
2585: if (vertexA != vertexD) sieve->addArrow(vertices[vertexD], face, order++);
2586: mesh->setValue(markers, face, 2);
2587: mesh->setValue(markers, vertices[vertexA], 2);
2588: mesh->setValue(markers, vertices[vertexB], 2);
2589: if (vertexB != vertexC) mesh->setValue(markers, vertices[vertexC], 2);
2590: if (vertexA != vertexD) mesh->setValue(markers, vertices[vertexD], 2);
2591: }
2592: }
2593: }
2594: mesh->stratify();
2595: #if 0
2596: for(int vz = 0; vz <= edges[2]; ++vz) {
2597: for(int vy = 0; vy <= edges[1]; ++vy) {
2598: for(int vx = 0; vx <= edges[0]; ++vx) {
2599: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
2600: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
2601: coords[((vz*(edges[1]+1)+vy)*(edges[0]+1)+vx)*2+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
2602: }
2603: }
2604: }
2605: #else
2606: coords[0*3+0] = lower[0];
2607: coords[0*3+1] = lower[1];
2608: coords[0*3+2] = upper[2];
2609: coords[1*3+0] = upper[0];
2610: coords[1*3+1] = lower[1];
2611: coords[1*3+2] = upper[2];
2612: coords[2*3+0] = upper[0];
2613: coords[2*3+1] = upper[1];
2614: coords[2*3+2] = upper[2];
2615: coords[3*3+0] = lower[0];
2616: coords[3*3+1] = upper[1];
2617: coords[3*3+2] = upper[2];
2618: coords[4*3+0] = lower[0];
2619: coords[4*3+1] = lower[1];
2620: coords[4*3+2] = lower[2];
2621: coords[5*3+0] = upper[0];
2622: coords[5*3+1] = lower[1];
2623: coords[5*3+2] = lower[2];
2624: coords[6*3+0] = upper[0];
2625: coords[6*3+1] = upper[1];
2626: coords[6*3+2] = lower[2];
2627: coords[7*3+0] = lower[0];
2628: coords[7*3+1] = upper[1];
2629: coords[7*3+2] = lower[2];
2630: #endif
2631: const double centroidX = 0.5*(upper[0] + lower[0]);
2632: const double centroidY = 0.5*(upper[1] + lower[1]);
2633: const double centroidZ = 0.5*(upper[2] + lower[2]);
2634: for(int s = 0; s < phiSlices; ++s) {
2635: for(int v = 0; v <= thetaEdges; ++v) {
2636: int vertex = numCubeVertices + v + s*(thetaEdges+1);
2637: const double theta = v*(PETSC_PI/thetaEdges);
2638: const double phi = s*(2.0*PETSC_PI/phiSlices);
2639: const int correction = (s > 0)*((s-1)*2 + 1);
2641: if ((vertex- numCubeVertices)%(thetaEdges+1) == 0) {
2642: vertex = numCubeVertices;
2643: } else if ((vertex - numCubeVertices)%(thetaEdges+1) == thetaEdges) {
2644: vertex = numCubeVertices + thetaEdges;
2645: } else {
2646: vertex -= correction;
2647: }
2648: coords[vertex*3+0] = centroidX + radius*sin(theta)*cos(phi);
2649: coords[vertex*3+1] = centroidY + radius*sin(theta)*sin(phi);
2650: coords[vertex*3+2] = centroidZ + radius*cos(theta);
2651: }
2652: }
2653: delete [] vertices;
2654: ALE::SieveBuilder<Mesh>::buildCoordinates(mesh, mesh->getDimension()+1, coords);
2655: return mesh;
2656: };
2657: };
2658: } // namespace ALE
2660: namespace ALECompat {
2661: using ALE::Obj;
2662: template<typename Topology_>
2663: class Bundle : public ALE::ParallelObject {
2664: public:
2665: typedef Topology_ topology_type;
2666: typedef typename topology_type::patch_type patch_type;
2667: typedef typename topology_type::point_type point_type;
2668: typedef typename topology_type::sieve_type sieve_type;
2669: typedef typename sieve_type::coneArray coneArray;
2670: typedef ALECompat::New::Section<topology_type, double> real_section_type;
2671: typedef ALECompat::New::Section<topology_type, int> int_section_type;
2672: typedef ALE::MinimalArrow<point_type, point_type> arrow_type;
2673: typedef ALE::UniformSection<arrow_type, int> arrow_section_type;
2674: typedef struct {double x, y, z;} split_value;
2675: typedef ALE::pair<point_type, split_value> pair_type;
2676: typedef ALECompat::New::Section<topology_type, pair_type> pair_section_type;
2677: typedef std::map<std::string, Obj<real_section_type> > real_sections_type;
2678: typedef std::map<std::string, Obj<int_section_type> > int_sections_type;
2679: typedef std::map<std::string, Obj<pair_section_type> > pair_sections_type;
2680: typedef std::map<std::string, Obj<arrow_section_type> > arrow_sections_type;
2681: typedef typename topology_type::send_overlap_type send_overlap_type;
2682: typedef typename topology_type::recv_overlap_type recv_overlap_type;
2683: typedef typename ALECompat::New::SectionCompletion<topology_type, point_type>::topology_type comp_topology_type;
2684: typedef typename ALECompat::New::OverlapValues<send_overlap_type, comp_topology_type, point_type> send_section_type;
2685: typedef typename ALECompat::New::OverlapValues<recv_overlap_type, comp_topology_type, point_type> recv_section_type;
2686: protected:
2687: Obj<topology_type> _topology;
2688: bool _distributed;
2689: real_sections_type _realSections;
2690: int_sections_type _intSections;
2691: pair_sections_type _pairSections;
2692: arrow_sections_type _arrowSections;
2693: public:
2694: Bundle(MPI_Comm comm, int debug = 0) : ALE::ParallelObject(comm, debug), _distributed(false) {
2695: this->_topology = new topology_type(comm, debug);
2696: };
2697: Bundle(const Obj<topology_type>& topology) : ALE::ParallelObject(topology->comm(), topology->debug()), _topology(topology), _distributed(false) {};
2698: public: // Accessors
2699: bool getDistributed() const {return this->_distributed;};
2700: void setDistributed(const bool distributed) {this->_distributed = distributed;};
2701: const Obj<topology_type>& getTopology() const {return this->_topology;};
2702: void setTopology(const Obj<topology_type>& topology) {this->_topology = topology;};
2703: public:
2704: bool hasRealSection(const std::string& name) {
2705: return this->_realSections.find(name) != this->_realSections.end();
2706: };
2707: const Obj<real_section_type>& getRealSection(const std::string& name) {
2708: if (this->_realSections.find(name) == this->_realSections.end()) {
2709: Obj<real_section_type> section = new real_section_type(this->_topology);
2711: if (this->_debug) {std::cout << "Creating new real section: " << name << std::endl;}
2712: this->_realSections[name] = section;
2713: }
2714: return this->_realSections[name];
2715: };
2716: void setRealSection(const std::string& name, const Obj<real_section_type>& section) {
2717: this->_realSections[name] = section;
2718: };
2719: Obj<std::set<std::string> > getRealSections() const {
2720: Obj<std::set<std::string> > names = std::set<std::string>();
2722: for(typename real_sections_type::const_iterator s_iter = this->_realSections.begin(); s_iter != this->_realSections.end(); ++s_iter) {
2723: names->insert(s_iter->first);
2724: }
2725: return names;
2726: };
2727: bool hasIntSection(const std::string& name) {
2728: return this->_intSections.find(name) != this->_intSections.end();
2729: };
2730: const Obj<int_section_type>& getIntSection(const std::string& name) {
2731: if (this->_intSections.find(name) == this->_intSections.end()) {
2732: Obj<int_section_type> section = new int_section_type(this->_topology);
2734: if (this->_debug) {std::cout << "Creating new int section: " << name << std::endl;}
2735: this->_intSections[name] = section;
2736: }
2737: return this->_intSections[name];
2738: };
2739: void setIntSection(const std::string& name, const Obj<int_section_type>& section) {
2740: this->_intSections[name] = section;
2741: };
2742: Obj<std::set<std::string> > getIntSections() const {
2743: Obj<std::set<std::string> > names = std::set<std::string>();
2745: for(typename int_sections_type::const_iterator s_iter = this->_intSections.begin(); s_iter != this->_intSections.end(); ++s_iter) {
2746: names->insert(s_iter->first);
2747: }
2748: return names;
2749: };
2750: bool hasPairSection(const std::string& name) {
2751: return this->_pairSections.find(name) != this->_pairSections.end();
2752: };
2753: const Obj<pair_section_type>& getPairSection(const std::string& name) {
2754: if (this->_pairSections.find(name) == this->_pairSections.end()) {
2755: Obj<pair_section_type> section = new pair_section_type(this->_topology);
2757: if (this->_debug) {std::cout << "Creating new pair section: " << name << std::endl;}
2758: this->_pairSections[name] = section;
2759: }
2760: return this->_pairSections[name];
2761: };
2762: void setPairSection(const std::string& name, const Obj<pair_section_type>& section) {
2763: this->_pairSections[name] = section;
2764: };
2765: Obj<std::set<std::string> > getPairSections() const {
2766: Obj<std::set<std::string> > names = std::set<std::string>();
2768: for(typename pair_sections_type::const_iterator s_iter = this->_pairSections.begin(); s_iter != this->_pairSections.end(); ++s_iter) {
2769: names->insert(s_iter->first);
2770: }
2771: return names;
2772: };
2773: bool hasArrowSection(const std::string& name) {
2774: return this->_arrowSections.find(name) != this->_arrowSections.end();
2775: };
2776: const Obj<arrow_section_type>& getArrowSection(const std::string& name) {
2777: if (this->_arrowSections.find(name) == this->_arrowSections.end()) {
2778: Obj<arrow_section_type> section = new arrow_section_type(this->comm(), this->debug());
2780: if (this->_debug) {std::cout << "Creating new arrow section: " << name << std::endl;}
2781: this->_arrowSections[name] = section;
2782: }
2783: return this->_arrowSections[name];
2784: };
2785: void setArrowSection(const std::string& name, const Obj<arrow_section_type>& section) {
2786: this->_arrowSections[name] = section;
2787: };
2788: Obj<std::set<std::string> > getArrowSections() const {
2789: Obj<std::set<std::string> > names = std::set<std::string>();
2791: for(typename arrow_sections_type::const_iterator s_iter = this->_arrowSections.begin(); s_iter != this->_arrowSections.end(); ++s_iter) {
2792: names->insert(s_iter->first);
2793: }
2794: return names;
2795: };
2796: public: // Printing
2797: friend std::ostream& operator<<(std::ostream& os, const split_value& s) {
2798: os << "(" << s.x << ", "<< s.y << ", "<< s.z << ")";
2799: return os;
2800: };
2801: public: // Adapter
2802: const Obj<sieve_type>& getSieve() {return this->_topology->getPatch(0);};
2803: int height() {return 2;};
2804: int depth() {return 2;};
2805: };
2807: class Discretization : public ALE::ParallelObject {
2808: protected:
2809: std::map<int,int> _dim2dof;
2810: std::map<int,int> _dim2class;
2811: public:
2812: Discretization(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {};
2813: ~Discretization() {};
2814: public:
2815: const double *getQuadraturePoints() {return NULL;};
2816: const double *getQuadratureWeights() {return NULL;};
2817: const double *getBasis() {return NULL;};
2818: const double *getBasisDerivatives() {return NULL;};
2819: int getNumDof(const int dim) {return this->_dim2dof[dim];};
2820: void setNumDof(const int dim, const int numDof) {this->_dim2dof[dim] = numDof;};
2821: int getDofClass(const int dim) {return this->_dim2class[dim];};
2822: void setDofClass(const int dim, const int dofClass) {this->_dim2class[dim] = dofClass;};
2823: };
2825: class BoundaryCondition : public ALE::ParallelObject {
2826: protected:
2827: std::string _labelName;
2828: double (*_func)(const double []);
2829: public:
2830: BoundaryCondition(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug) {};
2831: ~BoundaryCondition() {};
2832: public:
2833: const std::string& getLabelName() {return this->_labelName;};
2834: void setLabelName(const std::string& name) {this->_labelName = name;};
2835: void setFunction(double (*func)(const double [])) {this->_func = func;};
2836: public:
2837: double evaluate(const double coords[]) {return this->_func(coords);};
2838: };
2840: class Mesh : public Bundle<ALE::Topology<int, ALE::Sieve<int,int,int> > > {
2841: public:
2842: typedef int point_type;
2843: typedef ALE::Sieve<point_type,int,int> sieve_type;
2844: typedef ALE::Topology<int, sieve_type> topology_type;
2845: typedef topology_type::patch_type patch_type;
2846: typedef Bundle<topology_type> base_type;
2847: typedef ALECompat::New::NumberingFactory<topology_type> NumberingFactory;
2848: typedef NumberingFactory::numbering_type numbering_type;
2849: typedef NumberingFactory::order_type order_type;
2850: typedef base_type::send_overlap_type send_overlap_type;
2851: typedef base_type::recv_overlap_type recv_overlap_type;
2852: typedef base_type::send_section_type send_section_type;
2853: typedef base_type::recv_section_type recv_section_type;
2854: typedef base_type::real_sections_type real_sections_type;
2855: // PCICE BC
2856: typedef struct {double rho,u,v,p;} bc_value_type;
2857: typedef std::map<int, bc_value_type> bc_values_type;
2858: // PyLith BC
2859: typedef ALECompat::New::Section<topology_type, ALE::pair<int,double> > foliated_section_type;
2860: protected:
2861: int _dim;
2862: Obj<NumberingFactory> _factory;
2863: // PCICE BC
2864: bc_values_type _bcValues;
2865: // PyLith BC
2866: Obj<foliated_section_type> _boundaries;
2867: // Discretization
2868: Obj<Discretization> _discretization;
2869: Obj<BoundaryCondition> _boundaryCondition;
2870: public:
2871: Mesh(MPI_Comm comm, int dim, int debug = 0) : Bundle<ALE::Topology<int, ALE::Sieve<int,int,int> > >(comm, debug), _dim(dim) {
2872: this->_factory = NumberingFactory::singleton(debug);
2873: this->_boundaries = NULL;
2874: this->_discretization = new Discretization(comm, debug);
2875: this->_boundaryCondition = new BoundaryCondition(comm, debug);
2876: };
2877: Mesh(const Obj<topology_type>& topology, int dim) : Bundle<ALE::Topology<int, ALE::Sieve<int,int,int> > >(topology), _dim(dim) {
2878: this->_factory = NumberingFactory::singleton(topology->debug());
2879: this->_boundaries = NULL;
2880: };
2881: public: // Accessors
2882: int getDimension() const {return this->_dim;};
2883: void setDimension(const int dim) {this->_dim = dim;};
2884: const Obj<NumberingFactory>& getFactory() {return this->_factory;};
2885: const Obj<Discretization>& getDiscretization() {return this->_discretization;};
2886: void setDiscretization(const Obj<Discretization>& discretization) {this->_discretization = discretization;};
2887: const Obj<BoundaryCondition>& getBoundaryCondition() {return this->_boundaryCondition;};
2888: void setBoundaryCondition(const Obj<BoundaryCondition>& boundaryCondition) {this->_boundaryCondition = boundaryCondition;};
2889: public: // Mesh geometry
2890: #if 0
2891: void computeTriangleGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2892: const double *coords = this->restrict(coordinates, e);
2893: const int dim = 2;
2894: double invDet;
2896: if (v0) {
2897: for(int d = 0; d < dim; d++) {
2898: v0[d] = coords[d];
2899: }
2900: }
2901: if (J) {
2902: for(int d = 0; d < dim; d++) {
2903: for(int f = 0; f < dim; f++) {
2904: J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2905: }
2906: }
2907: detJ = J[0]*J[3] - J[1]*J[2];
2908: }
2909: if (invJ) {
2910: invDet = 1.0/detJ;
2911: invJ[0] = invDet*J[3];
2912: invJ[1] = -invDet*J[1];
2913: invJ[2] = -invDet*J[2];
2914: invJ[3] = invDet*J[0];
2915: }
2916: };
2917: static void computeTetrahedronGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2918: const patch_type patch = 0;
2919: const double *coords = coordinates->restrict(patch, e);
2920: const int dim = 3;
2921: double invDet;
2923: if (v0) {
2924: for(int d = 0; d < dim; d++) {
2925: v0[d] = coords[d];
2926: }
2927: }
2928: if (J) {
2929: for(int d = 0; d < dim; d++) {
2930: for(int f = 0; f < dim; f++) {
2931: J[d*dim+f] = 0.5*(coords[(f+1)*dim+d] - coords[0*dim+d]);
2932: }
2933: }
2934: detJ = J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
2935: J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
2936: J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2937: }
2938: if (invJ) {
2939: invDet = 1.0/detJ;
2940: invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
2941: invJ[0*3+1] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
2942: invJ[0*3+2] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
2943: invJ[1*3+0] = invDet*(J[0*3+1]*J[2*3+2] - J[0*3+2]*J[2*3+1]);
2944: invJ[1*3+1] = invDet*(J[0*3+2]*J[2*3+0] - J[0*3+0]*J[2*3+2]);
2945: invJ[1*3+2] = invDet*(J[0*3+0]*J[2*3+1] - J[0*3+1]*J[2*3+0]);
2946: invJ[2*3+0] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
2947: invJ[2*3+1] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
2948: invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
2949: }
2950: };
2951: void computeElementGeometry(const Obj<real_section_type>& coordinates, const point_type& e, double v0[], double J[], double invJ[], double& detJ) {
2952: if (this->_dim == 2) {
2953: computeTriangleGeometry(coordinates, e, v0, J, invJ, detJ);
2954: } else if (this->_dim == 3) {
2955: computeTetrahedronGeometry(coordinates, e, v0, J, invJ, detJ);
2956: } else {
2957: throw ALE::Exception("Unsupport dimension for element geometry computation");
2958: }
2959: };
2960: double getMaxVolume() {
2961: const topology_type::sheaf_type& patches = this->getTopology()->getPatches();
2962: double v0[3], J[9], invJ[9], detJ, maxVolume = 0.0;
2964: for(topology_type::sheaf_type::const_iterator p_iter = patches.begin(); p_iter != patches.end(); ++p_iter) {
2965: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
2966: const Obj<topology_type::label_sequence>& cells = this->getTopology()->heightStratum(p_iter->first, 0);
2968: for(topology_type::label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
2969: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
2970: maxVolume = std::max(maxVolume, detJ);
2971: }
2972: }
2973: return maxVolume;
2974: };
2975: // Find the cell in which this point lies (stupid algorithm)
2976: point_type locatePoint_2D(const patch_type& patch, const real_section_type::value_type point[]) {
2977: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
2978: const Obj<topology_type::label_sequence>& cells = this->getTopology()->heightStratum(patch, 0);
2979: const int embedDim = 2;
2980: double v0[2], J[4], invJ[4], detJ;
2982: for(topology_type::label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
2983: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
2984: double xi = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]);
2985: double eta = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]);
2987: if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 1.0)) {
2988: return *c_iter;
2989: }
2990: }
2991: throw ALE::Exception("Could not locate point");
2992: };
2993: // Assume a simplex and 3D
2994: point_type locatePoint_3D(const patch_type& patch, const real_section_type::value_type point[]) {
2995: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
2996: const Obj<topology_type::label_sequence>& cells = this->getTopology()->heightStratum(patch, 0);
2997: const int embedDim = 3;
2998: double v0[3], J[9], invJ[9], detJ;
3000: for(topology_type::label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
3001: this->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
3002: 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]);
3003: 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]);
3004: 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]);
3006: if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 1.0)) {
3007: return *c_iter;
3008: }
3009: }
3010: throw ALE::Exception("Could not locate point");
3011: };
3012: point_type locatePoint(const patch_type& patch, const real_section_type::value_type point[]) {
3013: if (this->_dim == 2) {
3014: return locatePoint_2D(patch, point);
3015: } else if (this->_dim == 3) {
3016: return locatePoint_3D(patch, point);
3017: } else {
3018: throw ALE::Exception("No point location for mesh dimension");
3019: }
3020: };
3021: #endif
3022: // Only works in 2D
3023: int orientation(const patch_type& patch, const point_type& cell) {
3024: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3025: const Obj<topology_type>& topology = this->getTopology();
3026: const Obj<sieve_type>& sieve = topology->getPatch(patch);
3027: const Obj<sieve_type::coneArray>& cone = sieve->nCone(cell, topology->depth());
3028: sieve_type::coneArray::iterator cBegin = cone->begin();
3029: real_section_type::value_type root[2];
3030: real_section_type::value_type vA[2];
3031: real_section_type::value_type vB[2];
3033: const real_section_type::value_type *coords = coordinates->restrictPoint(patch, *cBegin);
3034: root[0] = coords[0];
3035: root[1] = coords[1];
3036: ++cBegin;
3037: coords = coordinates->restrictPoint(patch, *cBegin);
3038: vA[0] = coords[0] - root[0];
3039: vA[1] = coords[1] - root[1];
3040: ++cBegin;
3041: coords = coordinates->restrictPoint(patch, *cBegin);
3042: vB[0] = coords[0] - root[0];
3043: vB[1] = coords[1] - root[1];
3044: double det = vA[0]*vB[1] - vA[1]*vB[0];
3045: if (det > 0.0) return 1;
3046: if (det < 0.0) return -1;
3047: return 0;
3048: };
3049: public: // BC values for PCICE
3050: const bc_value_type& getBCValue(const int bcFunc) {
3051: return this->_bcValues[bcFunc];
3052: };
3053: void setBCValue(const int bcFunc, const bc_value_type& value) {
3054: this->_bcValues[bcFunc] = value;
3055: };
3056: bc_values_type& getBCValues() {
3057: return this->_bcValues;
3058: };
3059: void distributeBCValues() {
3060: int size = this->_bcValues.size();
3062: MPI_Bcast(&size, 1, MPI_INT, 0, this->comm());
3063: if (this->commRank()) {
3064: for(int bc = 0; bc < size; ++bc) {
3065: int funcNum;
3066: bc_value_type funcVal;
3068: MPI_Bcast((void *) &funcNum, 1, MPI_INT, 0, this->comm());
3069: MPI_Bcast((void *) &funcVal, 4, MPI_DOUBLE, 0, this->comm());
3070: this->_bcValues[funcNum] = funcVal;
3071: }
3072: } else {
3073: for(bc_values_type::iterator bc_iter = this->_bcValues.begin(); bc_iter != this->_bcValues.end(); ++bc_iter) {
3074: const int& funcNum = bc_iter->first;
3075: const bc_value_type& funcVal = bc_iter->second;
3076: MPI_Bcast((void *) &funcNum, 1, MPI_INT, 0, this->comm());
3077: MPI_Bcast((void *) &funcVal, 4, MPI_DOUBLE, 0, this->comm());
3078: }
3079: }
3080: };
3081: public: // BC values for PyLith
3082: const Obj<foliated_section_type>& getBoundariesNew() {
3083: if (this->_boundaries.isNull()) {
3084: this->_boundaries = new foliated_section_type(this->getTopology());
3085: }
3086: return this->_boundaries;
3087: };
3088: public: // Discretization
3089: void setupField(const Obj<real_section_type>& s, const bool postponeGhosts = false) {
3090: const std::string& name = this->_boundaryCondition->getLabelName();
3091: const patch_type patch = 0;
3093: for(int d = 0; d <= this->_dim; ++d) {
3094: s->setFiberDimensionByDepth(patch, d, this->_discretization->getNumDof(d));
3095: }
3096: if (!name.empty()) {
3097: const Obj<topology_type::label_sequence>& boundary = this->_topology->getLabelStratum(patch, name, 1);
3099: for(topology_type::label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
3100: s->setFiberDimension(patch, *e_iter, -this->_discretization->getNumDof(this->_topology->depth(patch, *e_iter)));
3101: }
3102: }
3103: s->allocate(postponeGhosts);
3104: if (!name.empty()) {
3105: const Obj<real_section_type>& coordinates = this->getRealSection("coordinates");
3106: const Obj<topology_type::label_sequence>& boundary = this->_topology->getLabelStratum(patch, name, 1);
3108: for(topology_type::label_sequence::iterator e_iter = boundary->begin(); e_iter != boundary->end(); ++e_iter) {
3109: const real_section_type::value_type *coords = coordinates->restrictPoint(patch, *e_iter);
3110: const PetscScalar value = this->_boundaryCondition->evaluate(coords);
3112: s->updatePointBC(patch, *e_iter, &value);
3113: }
3114: }
3115: };
3116: public:
3117: void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
3118: if (comm == MPI_COMM_NULL) {
3119: comm = this->comm();
3120: }
3121: if (name == "") {
3122: PetscPrintf(comm, "viewing a Mesh\n");
3123: } else {
3124: PetscPrintf(comm, "viewing Mesh '%s'\n", name.c_str());
3125: }
3126: this->getTopology()->view("mesh topology", comm);
3127: Obj<std::set<std::string> > sections = this->getRealSections();
3129: for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
3130: this->getRealSection(*name)->view(*name);
3131: }
3132: sections = this->getIntSections();
3133: for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
3134: this->getIntSection(*name)->view(*name);
3135: }
3136: sections = this->getPairSections();
3137: for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
3138: this->getPairSection(*name)->view(*name);
3139: }
3140: };
3141: template<typename value_type>
3142: static std::string printMatrix(const std::string& name, const int rows, const int cols, const value_type matrix[], const int rank = -1)
3143: {
3144: ostringstream output;
3145: ostringstream rankStr;
3147: if (rank >= 0) {
3148: rankStr << "[" << rank << "]";
3149: }
3150: output << rankStr.str() << name << " = " << std::endl;
3151: for(int r = 0; r < rows; r++) {
3152: if (r == 0) {
3153: output << rankStr.str() << " /";
3154: } else if (r == rows-1) {
3155: output << rankStr.str() << " \\";
3156: } else {
3157: output << rankStr.str() << " |";
3158: }
3159: for(int c = 0; c < cols; c++) {
3160: output << " " << matrix[r*cols+c];
3161: }
3162: if (r == 0) {
3163: output << " \\" << std::endl;
3164: } else if (r == rows-1) {
3165: output << " /" << std::endl;
3166: } else {
3167: output << " |" << std::endl;
3168: }
3169: }
3170: return output.str();
3171: };
3172: };
3173: } // namespace ALECompat
3174: #endif