source: issm/trunk-jpl/externalpackages/petsc-dev/src/include/sieve/Topology.hh@ 11896

Last change on this file since 11896 was 11896, checked in by habbalf, 13 years ago

petsc-dev : Petsc development code in external packages. Mercurial updates

File size: 21.6 KB
Line 
1#ifndef included_ALE_CoSieve_hh
2#define included_ALE_CoSieve_hh
3
4#ifndef included_ALE_Sieve_hh
5#include <sieve/Sieve.hh>
6#endif
7
8namespace ALE {
9 // A Topology is a collection of Sieves
10 // Each Sieve has a label, which we call a \emph{patch}
11 // The collection itself we call a \emph{sheaf}
12 // The main operation we provide in Topology is the creation of a \emph{label}
13 // A label is a bidirectional mapping of Sieve points to integers, implemented with a Sifter
14 template<typename Patch_, typename Sieve_, typename Alloc_ = malloc_allocator<typename Sieve_::point_type> >
15 class Topology : public ALE::ParallelObject {
16 public:
17 typedef Patch_ patch_type;
18 typedef Sieve_ sieve_type;
19 typedef Alloc_ alloc_type;
20 typedef typename alloc_type::template rebind<int>::other int_alloc_type;
21 typedef typename sieve_type::point_type point_type;
22 typedef typename alloc_type::template rebind<std::pair<const patch_type, Obj<sieve_type> > >::other pair1_alloc_type;
23 typedef typename std::map<patch_type, Obj<sieve_type>, std::less<patch_type>, pair1_alloc_type> sheaf_type;
24 typedef typename ALE::Sifter<int, point_type, int> patch_label_type;
25 typedef typename alloc_type::template rebind<patch_label_type>::other patch_label_alloc_type;
26 typedef typename patch_label_alloc_type::pointer patch_label_ptr;
27 typedef typename alloc_type::template rebind<std::pair<const patch_type, Obj<patch_label_type> > >::other pair2_alloc_type;
28 typedef typename std::map<patch_type, Obj<patch_label_type>, std::less<patch_type>, pair2_alloc_type> label_type;
29 typedef typename alloc_type::template rebind<std::pair<const patch_type, int> >::other pair3_alloc_type;
30 typedef typename std::map<patch_type, int, std::less<patch_type>, pair3_alloc_type> max_label_type;
31 typedef typename alloc_type::template rebind<std::pair<const std::string, label_type> >::other pair4_alloc_type;
32 typedef typename std::map<const std::string, label_type, std::less<const std::string>, pair4_alloc_type> labels_type;
33 typedef typename patch_label_type::supportSequence label_sequence;
34 typedef typename std::set<point_type, std::less<point_type>, alloc_type> point_set_type;
35 typedef typename alloc_type::template rebind<point_set_type>::other point_set_alloc_type;
36 typedef typename point_set_alloc_type::pointer point_set_ptr;
37 typedef typename ALE::Sifter<int,point_type,point_type> send_overlap_type;
38 typedef typename alloc_type::template rebind<send_overlap_type>::other send_overlap_alloc_type;
39 typedef typename send_overlap_alloc_type::pointer send_overlap_ptr;
40 typedef typename ALE::Sifter<point_type,int,point_type> recv_overlap_type;
41 typedef typename alloc_type::template rebind<recv_overlap_type>::other recv_overlap_alloc_type;
42 typedef typename recv_overlap_alloc_type::pointer recv_overlap_ptr;
43 protected:
44 sheaf_type _sheaf;
45 labels_type _labels;
46 int _maxHeight;
47 max_label_type _maxHeights;
48 int _maxDepth;
49 max_label_type _maxDepths;
50 bool _calculatedOverlap;
51 Obj<send_overlap_type> _sendOverlap;
52 Obj<recv_overlap_type> _recvOverlap;
53 Obj<send_overlap_type> _distSendOverlap;
54 Obj<recv_overlap_type> _distRecvOverlap;
55 // Work space
56 Obj<point_set_type> _modifiedPoints;
57 alloc_type _allocator;
58 int_alloc_type _int_allocator;
59 public:
60 Topology(MPI_Comm comm, const int debug = 0) : ParallelObject(comm, debug), _maxHeight(-1), _maxDepth(-1), _calculatedOverlap(false) {
61 send_overlap_ptr pSendOverlap = send_overlap_alloc_type(this->_allocator).allocate(1);
62 send_overlap_alloc_type(this->_allocator).construct(pSendOverlap, send_overlap_type(this->comm(), this->debug()));
63 this->_sendOverlap = Obj<send_overlap_type>(pSendOverlap, sizeof(send_overlap_type));
64 ///this->_sendOverlap = new send_overlap_type(this->comm(), this->debug());
65 recv_overlap_ptr pRecvOverlap = recv_overlap_alloc_type(this->_allocator).allocate(1);
66 recv_overlap_alloc_type(this->_allocator).construct(pRecvOverlap, recv_overlap_type(this->comm(), this->debug()));
67 this->_recvOverlap = Obj<recv_overlap_type>(pRecvOverlap, sizeof(recv_overlap_type));
68 ///this->_recvOverlap = new recv_overlap_type(this->comm(), this->debug());
69 point_set_ptr pModPoints = point_set_alloc_type(this->_allocator).allocate(1);
70 point_set_alloc_type(this->_allocator).construct(pModPoints, point_set_type());
71 this->_modifiedPoints = Obj<point_set_type>(pModPoints, sizeof(point_set_type));
72 ///this->_modifiedPoints = new point_set_type();
73 };
74 virtual ~Topology() {};
75 public: // Verifiers
76 void checkPatch(const patch_type& patch) {
77 if (this->_sheaf.find(patch) == this->_sheaf.end()) {
78 ostringstream msg;
79 msg << "Invalid topology patch: " << patch << std::endl;
80 throw ALE::Exception(msg.str().c_str());
81 }
82 };
83 void checkLabel(const std::string& name, const patch_type& patch) {
84 this->checkPatch(patch);
85 if ((this->_labels.find(name) == this->_labels.end()) || (this->_labels[name].find(patch) == this->_labels[name].end())) {
86 ostringstream msg;
87 msg << "Invalid label name: " << name << " for patch " << patch << std::endl;
88 throw ALE::Exception(msg.str().c_str());
89 }
90 };
91 bool hasPatch(const patch_type& patch) {
92 if (this->_sheaf.find(patch) != this->_sheaf.end()) {
93 return true;
94 }
95 return false;
96 };
97 bool hasLabel(const std::string& name, const patch_type& patch) {
98 if ((this->_labels.find(name) != this->_labels.end()) && (this->_labels[name].find(patch) != this->_labels[name].end())) {
99 return true;
100 }
101 return false;
102 };
103 public: // Accessors
104 const Obj<sieve_type>& getPatch(const patch_type& patch) {
105 this->checkPatch(patch);
106 return this->_sheaf[patch];
107 };
108 void setPatch(const patch_type& patch, const Obj<sieve_type>& sieve) {
109 this->_sheaf[patch] = sieve;
110 };
111 int getValue (const Obj<patch_label_type>& label, const point_type& point, const int defValue = 0) {
112 const Obj<typename patch_label_type::coneSequence>& cone = label->cone(point);
113
114 if (cone->size() == 0) return defValue;
115 return *cone->begin();
116 };
117 template<typename InputPoints>
118 int getMaxValue (const Obj<patch_label_type>& label, const Obj<InputPoints>& points, const int defValue = 0) {
119 int maxValue = defValue;
120
121 for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
122 maxValue = std::max(maxValue, this->getValue(label, *p_iter, defValue));
123 }
124 return maxValue;
125 }
126 void setValue(const Obj<patch_label_type>& label, const point_type& point, const int value) {
127 label->setCone(value, point);
128 };
129 const Obj<patch_label_type>& createLabel(const patch_type& patch, const std::string& name) {
130 this->checkPatch(patch);
131 ///patch_label_ptr pLabel = patch_label_alloc_type(this->_allocator).allocate(1);
132 ///patch_label_alloc_type(this->_allocator).construct(pLabel, patch_label_type(this->comm(), this->debug()));
133 ///this->_labels[name][patch] = Obj<patch_label_type>(pLabel, sizeof(patch_label_type));
134 this->_labels[name][patch] = new patch_label_type(this->comm(), this->debug());
135 return this->_labels[name][patch];
136 };
137 const Obj<patch_label_type>& getLabel(const patch_type& patch, const std::string& name) {
138 this->checkLabel(name, patch);
139 return this->_labels[name][patch];
140 };
141 const Obj<label_sequence>& getLabelStratum(const patch_type& patch, const std::string& name, int value) {
142 this->checkLabel(name, patch);
143 return this->_labels[name][patch]->support(value);
144 };
145 const sheaf_type& getPatches() {
146 return this->_sheaf;
147 };
148 const labels_type& getLabels() {
149 return this->_labels;
150 };
151 void clear() {
152 this->_sheaf.clear();
153 this->_labels.clear();
154 this->_maxHeight = -1;
155 this->_maxHeights.clear();
156 this->_maxDepth = -1;
157 this->_maxDepths.clear();
158 };
159 const Obj<send_overlap_type>& getSendOverlap() const {return this->_sendOverlap;};
160 void setSendOverlap(const Obj<send_overlap_type>& overlap) {this->_sendOverlap = overlap;};
161 const Obj<recv_overlap_type>& getRecvOverlap() const {return this->_recvOverlap;};
162 void setRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_recvOverlap = overlap;};
163 const Obj<send_overlap_type>& getDistSendOverlap() const {return this->_distSendOverlap;};
164 void setDistSendOverlap(const Obj<send_overlap_type>& overlap) {this->_distSendOverlap = overlap;};
165 const Obj<recv_overlap_type>& getDistRecvOverlap() const {return this->_distRecvOverlap;};
166 void setDistRecvOverlap(const Obj<recv_overlap_type>& overlap) {this->_distRecvOverlap = overlap;};
167 public: // Stratification
168 template<class InputPoints>
169 void computeHeight(const Obj<patch_label_type>& height, const Obj<sieve_type>& sieve, const Obj<InputPoints>& points, int& maxHeight) {
170 this->_modifiedPoints->clear();
171
172 for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
173 // Compute the max height of the points in the support of p, and add 1
174 int h0 = this->getValue(height, *p_iter, -1);
175 int h1 = this->getMaxValue(height, sieve->support(*p_iter), -1) + 1;
176
177 if(h1 != h0) {
178 this->setValue(height, *p_iter, h1);
179 if (h1 > maxHeight) maxHeight = h1;
180 this->_modifiedPoints->insert(*p_iter);
181 }
182 }
183 // FIX: We would like to avoid the copy here with cone()
184 if(this->_modifiedPoints->size() > 0) {
185 this->computeHeight(height, sieve, sieve->cone(this->_modifiedPoints), maxHeight);
186 }
187 }
188 void computeHeights() {
189 const std::string name("height");
190
191 this->_maxHeight = -1;
192 for(typename sheaf_type::iterator s_iter = this->_sheaf.begin(); s_iter != this->_sheaf.end(); ++s_iter) {
193 const Obj<patch_label_type>& label = this->createLabel(s_iter->first, name);
194
195 this->_maxHeights[s_iter->first] = -1;
196 this->computeHeight(label, s_iter->second, s_iter->second->leaves(), this->_maxHeights[s_iter->first]);
197 if (this->_maxHeights[s_iter->first] > this->_maxHeight) this->_maxHeight = this->_maxHeights[s_iter->first];
198 }
199 }
200 int height() const {return this->_maxHeight;};
201 int height(const patch_type& patch) {
202 this->checkPatch(patch);
203 return this->_maxHeights[patch];
204 }
205 int height(const patch_type& patch, const point_type& point) {
206 return this->getValue(this->_labels["height"][patch], point, -1);
207 }
208 const Obj<label_sequence>& heightStratum(const patch_type& patch, int height) {
209 return this->getLabelStratum(patch, "height", height);
210 }
211 template<class InputPoints>
212 void computeDepth(const Obj<patch_label_type>& depth, const Obj<sieve_type>& sieve, const Obj<InputPoints>& points, int& maxDepth) {
213 this->_modifiedPoints->clear();
214
215 for(typename InputPoints::iterator p_iter = points->begin(); p_iter != points->end(); ++p_iter) {
216 // Compute the max depth of the points in the cone of p, and add 1
217 int d0 = this->getValue(depth, *p_iter, -1);
218 int d1 = this->getMaxValue(depth, sieve->cone(*p_iter), -1) + 1;
219
220 if(d1 != d0) {
221 this->setValue(depth, *p_iter, d1);
222 if (d1 > maxDepth) maxDepth = d1;
223 this->_modifiedPoints->insert(*p_iter);
224 }
225 }
226 // FIX: We would like to avoid the copy here with support()
227 if(this->_modifiedPoints->size() > 0) {
228 this->computeDepth(depth, sieve, sieve->support(this->_modifiedPoints), maxDepth);
229 }
230 }
231 void computeDepths() {
232 const std::string name("depth");
233
234 this->_maxDepth = -1;
235 for(typename sheaf_type::iterator s_iter = this->_sheaf.begin(); s_iter != this->_sheaf.end(); ++s_iter) {
236 const Obj<patch_label_type>& label = this->createLabel(s_iter->first, name);
237
238 this->_maxDepths[s_iter->first] = -1;
239 this->computeDepth(label, s_iter->second, s_iter->second->roots(), this->_maxDepths[s_iter->first]);
240 if (this->_maxDepths[s_iter->first] > this->_maxDepth) this->_maxDepth = this->_maxDepths[s_iter->first];
241 }
242 }
243 int depth() const {return this->_maxDepth;};
244 int depth(const patch_type& patch) {
245 this->checkPatch(patch);
246 return this->_maxDepths[patch];
247 }
248 int depth(const patch_type& patch, const point_type& point) {
249 return this->getValue(this->_labels["depth"][patch], point, -1);
250 }
251 const Obj<label_sequence>& depthStratum(const patch_type& patch, int depth) {
252 return this->getLabelStratum(patch, "depth", depth);
253 }
254#undef __FUNCT__
255#define __FUNCT__ "Topology::stratify"
256 void stratify() {
257 ALE_LOG_EVENT_BEGIN;
258 this->computeHeights();
259 this->computeDepths();
260 ALE_LOG_EVENT_END;
261 }
262 public: // Viewers
263 void view(const std::string& name, MPI_Comm comm = MPI_COMM_NULL) {
264 if (comm == MPI_COMM_NULL) {
265 comm = this->comm();
266 }
267 if (name == "") {
268 PetscPrintf(comm, "viewing a Topology\n");
269 } else {
270 PetscPrintf(comm, "viewing Topology '%s'\n", name.c_str());
271 }
272 PetscPrintf(comm, " maximum height %d maximum depth %d\n", this->height(), this->depth());
273 for(typename sheaf_type::const_iterator s_iter = this->_sheaf.begin(); s_iter != this->_sheaf.end(); ++s_iter) {
274 ostringstream txt;
275
276 txt << "Patch " << s_iter->first;
277 s_iter->second->view(txt.str().c_str(), comm);
278 PetscPrintf(comm, " maximum height %d maximum depth %d\n", this->height(s_iter->first), this->depth(s_iter->first));
279 }
280 for(typename labels_type::const_iterator l_iter = this->_labels.begin(); l_iter != this->_labels.end(); ++l_iter) {
281 PetscPrintf(comm, " label %s constructed\n", l_iter->first.c_str());
282 }
283 }
284 public:
285 void constructOverlap(const patch_type& patch) {
286 if (this->_calculatedOverlap) return;
287 if (this->hasPatch(patch)) {
288 this->constructOverlap(this->getPatch(patch)->base(), this->_sendOverlap, this->_recvOverlap);
289 this->constructOverlap(this->getPatch(patch)->cap(), this->_sendOverlap, this->_recvOverlap);
290 }
291 if (this->debug()) {
292 this->_sendOverlap->view("Send overlap");
293 this->_recvOverlap->view("Receive overlap");
294 }
295 this->_calculatedOverlap = true;
296 }
297 template<typename Sequence>
298 void constructOverlap(const Obj<Sequence>& points, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap) {
299 point_type *sendBuf = this->_allocator.allocate(points->size());
300 for(unsigned int i = 0; i < points->size(); ++i) {this->_allocator.construct(sendBuf+i, point_type());}
301 ///point_type *sendBuf = new point_type[points->size()];
302 int size = 0;
303 for(typename Sequence::iterator l_iter = points->begin(); l_iter != points->end(); ++l_iter) {
304 sendBuf[size++] = *l_iter;
305 }
306 int *sizes = this->_int_allocator.allocate(this->commSize()+1); // The number of points coming from each process
307 int *offsets = this->_int_allocator.allocate(this->commSize()+1); // Prefix sums for sizes
308 int *oldOffs = this->_int_allocator.allocate(this->commSize()+1); // Temporary storage
309 for(int i = 0; i < this->commSize()+1; ++i) {
310 this->_int_allocator.construct(sizes+i, 0);
311 this->_int_allocator.construct(offsets+i, 0);
312 this->_int_allocator.construct(oldOffs+i, 0);
313 }
314 ///int *sizes = new int[this->commSize()];
315 ///int *offsets = new int[this->commSize()+1];
316 ///int *oldOffs = new int[this->commSize()+1];
317 point_type *remotePoints = NULL; // The points from each process
318 int *remoteRanks = NULL; // The rank and number of overlap points of each process that overlaps another
319
320 // Change to Allgather() for the correct binning algorithm
321 MPI_Gather(&size, 1, MPI_INT, sizes, 1, MPI_INT, 0, this->comm());
322 if (this->commRank() == 0) {
323 offsets[0] = 0;
324 for(int p = 1; p <= this->commSize(); p++) {
325 offsets[p] = offsets[p-1] + sizes[p-1];
326 }
327 remotePoints = this->_allocator.allocate(offsets[this->commSize()]);
328 for(int i = 0; i < offsets[this->commSize()]; ++i) {this->_allocator.construct(remotePoints+i, point_type());}
329 ///remotePoints = new point_type[offsets[this->commSize()]];
330 }
331 MPI_Gatherv(sendBuf, size, MPI_INT, remotePoints, sizes, offsets, MPI_INT, 0, this->comm());
332 std::map<int, std::map<int, std::set<point_type> > > overlapInfo; // Maps (p,q) to their set of overlap points
333
334 if (this->commRank() == 0) {
335 for(int p = 0; p < this->commSize(); p++) {
336 std::sort(&remotePoints[offsets[p]], &remotePoints[offsets[p+1]]);
337 }
338 for(int p = 0; p <= this->commSize(); p++) {
339 oldOffs[p] = offsets[p];
340 }
341 for(int p = 0; p < this->commSize(); p++) {
342 for(int q = p+1; q < this->commSize(); q++) {
343 std::set_intersection(&remotePoints[oldOffs[p]], &remotePoints[oldOffs[p+1]],
344 &remotePoints[oldOffs[q]], &remotePoints[oldOffs[q+1]],
345 std::insert_iterator<std::set<point_type> >(overlapInfo[p][q], overlapInfo[p][q].begin()));
346 overlapInfo[q][p] = overlapInfo[p][q];
347 }
348 sizes[p] = overlapInfo[p].size()*2;
349 offsets[p+1] = offsets[p] + sizes[p];
350 }
351 remoteRanks = this->_int_allocator.allocate(offsets[this->commSize()]);
352 for(int i = 0; i < offsets[this->commSize()]; ++i) {this->_int_allocator.construct(remoteRanks+i, 0);}
353 ///remoteRanks = new int[offsets[this->commSize()]];
354 int k = 0;
355 for(int p = 0; p < this->commSize(); p++) {
356 for(typename std::map<int, std::set<point_type> >::iterator r_iter = overlapInfo[p].begin(); r_iter != overlapInfo[p].end(); ++r_iter) {
357 remoteRanks[k*2] = r_iter->first;
358 remoteRanks[k*2+1] = r_iter->second.size();
359 k++;
360 }
361 }
362 }
363 int numOverlaps; // The number of processes overlapping this process
364 MPI_Scatter(sizes, 1, MPI_INT, &numOverlaps, 1, MPI_INT, 0, this->comm());
365 int *overlapRanks = this->_int_allocator.allocate(numOverlaps);
366 for(int i = 0; i < numOverlaps; ++i) {this->_int_allocator.construct(overlapRanks+i, 0);}
367 ///int *overlapRanks = new int[numOverlaps]; // The rank and overlap size for each overlapping process
368 MPI_Scatterv(remoteRanks, sizes, offsets, MPI_INT, overlapRanks, numOverlaps, MPI_INT, 0, this->comm());
369 point_type *sendPoints = NULL; // The points to send to each process
370 if (this->commRank() == 0) {
371 for(int p = 0, k = 0; p < this->commSize(); p++) {
372 sizes[p] = 0;
373 for(int r = 0; r < (int) overlapInfo[p].size(); r++) {
374 sizes[p] += remoteRanks[k*2+1];
375 k++;
376 }
377 offsets[p+1] = offsets[p] + sizes[p];
378 }
379 sendPoints = this->_allocator.allocate(offsets[this->commSize()]);
380 for(int i = 0; i < offsets[this->commSize()]; ++i) {this->_allocator.construct(sendPoints+i, point_type());}
381 ///sendPoints = new point_type[offsets[this->commSize()]];
382 for(int p = 0, k = 0; p < this->commSize(); p++) {
383 for(typename std::map<int, std::set<point_type> >::iterator r_iter = overlapInfo[p].begin(); r_iter != overlapInfo[p].end(); ++r_iter) {
384 int rank = r_iter->first;
385 for(typename std::set<point_type>::iterator p_iter = (overlapInfo[p][rank]).begin(); p_iter != (overlapInfo[p][rank]).end(); ++p_iter) {
386 sendPoints[k++] = *p_iter;
387 }
388 }
389 }
390 }
391 int numOverlapPoints = 0;
392 for(int r = 0; r < numOverlaps/2; r++) {
393 numOverlapPoints += overlapRanks[r*2+1];
394 }
395 point_type *overlapPoints = this->_allocator.allocate(numOverlapPoints);
396 for(int i = 0; i < numOverlapPoints; ++i) {this->_allocator.construct(overlapPoints+i, point_type());}
397 ///point_type *overlapPoints = new point_type[numOverlapPoints];
398 MPI_Scatterv(sendPoints, sizes, offsets, MPI_INT, overlapPoints, numOverlapPoints, MPI_INT, 0, this->comm());
399
400 for(int r = 0, k = 0; r < numOverlaps/2; r++) {
401 int rank = overlapRanks[r*2];
402
403 for(int p = 0; p < overlapRanks[r*2+1]; p++) {
404 point_type point = overlapPoints[k++];
405
406 sendOverlap->addArrow(point, rank, point);
407 recvOverlap->addArrow(rank, point, point);
408 }
409 }
410
411 delete [] overlapPoints;
412 delete [] overlapRanks;
413 delete [] sizes;
414 delete [] offsets;
415 delete [] oldOffs;
416 if (this->commRank() == 0) {
417 delete [] remoteRanks;
418 delete [] remotePoints;
419 delete [] sendPoints;
420 }
421 }
422 };
423
424 // An Overlap is a Sifter describing the overlap of two Sieves
425 // Each arrow is local point ---(remote point)---> remote rank right now
426 // For XSifter, this should change to (local patch, local point) ---> (remote rank, remote patch, remote point)
427}
428
429#endif
Note: See TracBrowser for help on using the repository browser.