AFEPack
MPI_MemoryReclaimer.h
浏览该文件的文档。
00001 
00012 #ifndef __MPI_MemoryReclaimer_h__
00013 #define __MPI_MemoryReclaimer_h__
00014 
00015 #include "MPI_HGeometry.h"
00016 
00045 namespace MPI {
00046   template <class FOREST>
00047     class MemoryReclaimer {
00048   public:
00049     enum { dim = FOREST::dim, dow = FOREST::dow };
00050     typedef FOREST tree_t;
00051     typedef BirdView<tree_t> ir_mesh_t;
00052   private:
00053     tree_t * h_tree;
00054     std::list<ir_mesh_t *> ir_mesh;
00055 
00056   public:
00057   MemoryReclaimer() : h_tree(NULL) {}
00058   MemoryReclaimer(tree_t& _h_tree) : h_tree(&_h_tree) {}
00059     virtual ~MemoryReclaimer() {}
00060 
00061   public:
00066     void setGeometryTree(tree_t& _h_tree) {
00067       h_tree = &_h_tree;
00068     }
00073     void addIrregularMesh(ir_mesh_t& _ir_mesh) {
00074       if (&(_ir_mesh.getForest()) != h_tree) {
00075         std::cout << "warning: the irregular mesh added is not based on the geometry tree used."
00076                   << std::endl;
00077       }
00078       ir_mesh.push_back(&_ir_mesh);
00079     }
00080     void clear() {
00081       h_tree = NULL;
00082       ir_mesh.clear();
00083     }
00084     void reclaim() {
00086       typename std::list<ir_mesh_t *>::iterator 
00087         the_ir_mesh = ir_mesh.begin(),
00088         end_ir_mesh = ir_mesh.end();
00089       for (;the_ir_mesh != end_ir_mesh;++ the_ir_mesh) {
00090         reclaimIrregularMesh(**the_ir_mesh);
00091       }
00092   
00094       new_property_id(_pid_is_shared);
00095       markSharedObject();
00096 
00098       initialTreeLabel();
00099 
00101       the_ir_mesh = ir_mesh.begin();
00102       for (;the_ir_mesh != end_ir_mesh;++ the_ir_mesh) {
00103         labelIrregularMesh(**the_ir_mesh);
00104       }
00105 
00107       reclaimTreeMemory();
00108       free_property_id(_pid_is_shared);
00109     }
00110 
00111   private:
00112     void markSharedObject() {
00113       typename HGeometryTree<dim,dow>::RootIterator 
00114         the_ele = h_tree->beginRootElement(),
00115         end_ele = h_tree->endRootElement();
00116       for (;the_ele != end_ele;++ the_ele) {
00117         HGeometry<dim,dow> * p_geo = &(*the_ele);
00118         do {
00119           if (p_geo->parent != NULL) {
00120             p_geo = p_geo->parent;
00121           } else break;
00122         } while (true);
00123         markSharedElement(*p_geo);
00124       }
00125 
00126       the_ele = h_tree->beginRootElement();
00127       for (;the_ele != end_ele;++ the_ele) {
00128         HGeometry<dim,dow> * p_geo = &(*the_ele);
00129         do {
00130           if (p_geo->parent != NULL) {
00131             p_geo = p_geo->parent;
00132           } else break;
00133         } while (true);
00134         markSharedGeometry(*p_geo);
00135       }
00136     }      
00137 
00138     void reclaimIrregularMesh(ir_mesh_t& m) {
00139       ActiveElementIterator<dim,dow>
00140         the_ele = m.beginActiveElement(),
00141         end_ele = m.endActiveElement();
00142       for (;the_ele != end_ele;++ the_ele) {
00143         if (the_ele->isRefined()) {
00144           for (int i = 0;i < the_ele->n_child;++ i) {
00145             m.deleteTree(the_ele->child[i]);
00146             the_ele->child[i] = NULL;
00147           }
00148         }
00149       }
00150     }
00151 
00152     void initialTreeLabel() {
00153       typename HGeometryTree<dim,dow>::RootIterator 
00154         the_ele = h_tree->beginRootElement(),
00155         end_ele = h_tree->endRootElement();
00156       for (;the_ele != end_ele;++ the_ele) {
00157         labelHGeometryRecursively(*the_ele, -1);
00158       }
00159     }
00160 
00161     void labelIrregularMesh(ir_mesh_t& m) {
00162       RootFirstElementIterator<dim,dow>
00163         the_ele = m.beginRootFirstElement(),
00164         end_ele = m.endRootFirstElement();
00165       for (;the_ele != end_ele;++ the_ele) {
00166         labelHGeometry(*(the_ele->h_element), 1);
00167       }
00168 
00169       typename ir_mesh_t::mesh_t& mesh = m.regularMesh();
00170 #define LABEL_USED_HGEOMETRY(D)                                         \
00171       if (dim >= D) {                                                   \
00172         int n_geo = mesh.h_geometry()[D].size();                        \
00173         for (int i = 0;i < n_geo;++ i) {                                \
00174           HGeometry<D,dow> * p_geo = mesh.template h_geometry<D>(i);    \
00175           labelHGeometry(*p_geo, 1);                                    \
00176         }                                                               \
00177       }
00178 
00179       LABEL_USED_HGEOMETRY(0);
00180       LABEL_USED_HGEOMETRY(1);
00181       LABEL_USED_HGEOMETRY(2);
00182       LABEL_USED_HGEOMETRY(3);
00183 
00184 #undef LABEL_USED_HGEOMETRY
00185     }
00186 
00187     void reclaimTreeMemory() {
00188       typename HGeometryTree<dim,dow>::RootIterator
00189         the_ele = h_tree->beginRootElement(),
00190         end_ele = h_tree->endRootElement();
00191       for (;the_ele != end_ele;++ the_ele) {
00192         relabelHGeometryRecursively(*the_ele);
00193       }
00194 
00195       the_ele = h_tree->beginRootElement();
00196       for (;the_ele != end_ele;++ the_ele) {
00197         reclaimHGeometryRecursively(*the_ele);
00198       }
00199     }
00200 
00201   private:
00202     property_id_t<> _pid_is_shared;
00203 
00207     template <class GEO> bool
00208       is_shared_geometry(const GEO& g) const {
00209       bool result = false;
00210       result |= (h_tree->get_shared_info(g) != NULL);
00211       if (! result) {
00212         for (int i = 0;i < g.n_vertex;++ i) {
00213           result |= is_shared_geometry(*(g.vertex[i]));
00214         }
00215       }
00216       if (result) {
00217         return result;
00218       } else {
00219         for (int i = 0;i < g.n_boundary;++ i) {
00220           result |= is_shared_geometry(*(g.boundary[i]));
00221         }
00222       }
00223       return result;
00224     }
00225 
00230     void markSharedElement(HGeometry<dim,dow>& ele) const {
00231       if ((ele.get_property(_pid_is_shared) == NULL) &&
00232           (is_shared_geometry(ele))) {
00233         ele.new_property(_pid_is_shared);
00234 
00235         if (ele.parent != NULL) {
00236           for (int i = 0;i < ele.parent->n_child;++ i) {
00237             HGeometry<dim,dow> * p_sibling = ele.parent->child[i];
00238             if (p_sibling == &ele) continue;
00239             if (p_sibling->get_property(_pid_is_shared) == NULL) {
00240               p_sibling->new_property(_pid_is_shared);
00241             }
00242           }
00243         }
00244       }
00245       
00246       if (ele.isRefined()) {
00247         for (int i = 0;i < ele.n_child;++ i) {
00248           markSharedElement(*ele.child[i]);
00249         }
00250       }
00251     }
00252 
00257     template <class GEO> void
00258       markSharedGeometry(GEO& g) const {
00259       if (g.get_property(_pid_is_shared) != NULL) {
00260         for (int i = 0;i < g.n_vertex;++ i) {
00261           if (g.vertex[i]->get_property(_pid_is_shared) == NULL) {
00262             g.vertex[i]->new_property(_pid_is_shared);
00263           }
00264         }
00265         for (int i = 0;i < g.n_boundary;++ i) {
00266           if (g.boundary[i]->get_property(_pid_is_shared) == NULL) {
00267             g.boundary[i]->new_property(_pid_is_shared);
00268           }
00269           markSharedGeometry(*g.boundary[i]);
00270         }
00271       }
00272       if (g.isRefined()) {
00273         for (int i = 0;i < g.n_child;++ i) {
00274           markSharedGeometry(*g.child[i]);
00275         }
00276       }
00277     }      
00278 
00279     template <class GEO> void 
00280       labelHGeometry(GEO& g, int lab) const {
00281       for (int i = 0;i < g.n_vertex;++ i) {
00282         labelHGeometry(*(g.vertex[i]), lab);
00283       }
00284       for (int i = 0;i < g.n_boundary;++ i) {
00285         labelHGeometry(*(g.boundary[i]), lab);
00286       }
00287       g.index = lab;
00288     }
00289 
00290     template <class GEO> void 
00291       labelHGeometryRecursively(GEO& g, int lab) const {
00292       labelHGeometry(g, lab);
00293 
00294       if (g.isRefined()) {
00295         for (int i = 0;i < g.n_child;++ i) {
00296           labelHGeometryRecursively(*(g.child[i]), lab);
00297         }
00298       }
00299     }
00300 
00301     template <class GEO> int 
00302       relabelHGeometryRecursively(GEO& g) const {
00303       if (g.get_property(_pid_is_shared) != NULL) {
00304         g.index = 1;
00305       }
00306 
00307       for (int i = 0;i < g.n_vertex;++ i) {
00308         if (g.vertex[i] == NULL) continue;
00309         if (relabelHGeometryRecursively(*(g.vertex[i])) == -2) {
00310           g.vertex[i] = NULL;
00311         }
00312       }
00313       for (int i = 0;i < g.n_boundary;++ i) {
00314         if (g.boundary[i] == NULL) continue;
00315         if (relabelHGeometryRecursively(*(g.boundary[i])) == -2) {
00316           g.boundary[i] = NULL;
00317         }
00318       }
00319       if (g.isRefined()) {
00320         for (int i = 0;i < g.n_child;++ i) {
00321           if (g.child[i] == NULL) continue;
00322           if (relabelHGeometryRecursively(*(g.child[i])) == -2) {
00323             g.child[i] = NULL;
00324           }
00325         }
00326       }
00327       if (g.index == -1) {
00328         g.index = -2;
00329         return -1;
00330       } else {
00331         return g.index;
00332       }
00333     }
00334 
00335     template <class GEO> int 
00336       reclaimHGeometryRecursively(GEO& g) const {
00337       for (int i = 0;i < g.n_vertex;++ i) {
00338         if (g.vertex[i] != NULL) {
00339           if (reclaimHGeometryRecursively(*(g.vertex[i])) == -1) {
00340             g.vertex[i] = NULL;
00341           }
00342         }
00343       }
00344       for (int i = 0;i < g.n_boundary;++ i) {
00345         if (g.boundary[i] != NULL) {
00346           if (reclaimHGeometryRecursively(*(g.boundary[i])) == -1) {
00347             g.boundary[i] = NULL;
00348           }
00349         }
00350       }
00351       for (int i = 0;i < g.n_child;++ i) {
00352         if (g.child[i] == NULL) continue;
00353         if (reclaimHGeometryRecursively(*(g.child[i])) == -1) {
00354           g.child[i] = NULL;
00355         }
00356       }
00357 
00358       if ((g.index == -2) && 
00359           (g.get_property(_pid_is_shared) == NULL)) {
00360         this->reclaimHGeometry(&g);
00361         return -1;
00362       } else {
00363         return 1;
00364       }
00365     }
00366 
00367     template <class GEO> void 
00368       reclaimHGeometry(GEO * p_geo) const {
00369       assert ((p_geo->get_property(_pid_is_shared) == NULL));
00370       delete p_geo;
00371     }
00372   };
00373 
00374 }
00375 #endif // __MPI_MemoryReclaimer_h__
00376