AFEPack
MPI_FaceData.h
浏览该文件的文档。
00001 
00011 #ifndef __MPI_FaceData_h__
00012 #define __MPI_FaceData_h__
00013 
00014 #include "MPI_HGeometry.h"
00015 #include <AFEPack/DGFEMSpace.h>
00016 
00017 namespace MPI {
00018   namespace FaceData {
00019 
00064     template <class FOREST, class PACKER>
00065       class Syncer {
00066     public:
00067       enum { dim = FOREST::dim, dow = FOREST::dow };
00068       typedef FOREST forest_t;
00069       typedef PACKER packer_t;
00070       typedef typename packer_t::data_t data_t;
00071       typedef HGeometry<dim-1,dow> geometry_t;
00072 
00073     private:
00074       typedef Syncer<forest_t,packer_t> this_t;
00075 
00076       const forest_t * _forest;
00077       packer_t _packer;
00078 
00079       property_id_t<data_t> _pid_out;
00080       property_id_t<data_t> _pid_in;
00081 
00082       Transmit_map<geometry_t> _transmit_map;
00083 
00084     public:
00085       Syncer() { new_property(); }
00086       Syncer(const forest_t& forest) : _forest(&forest) {
00087         new_property();
00088       }
00089       Syncer(const forest_t& forest, const packer_t& packer) :
00090       _forest(&forest), _packer(packer) {
00091         new_property();
00092       }
00093       Syncer(const this_t& syncer) :
00094       _forest(syncer._forest), _packer(syncer._packer) {
00095         new_property();
00096       }
00097 
00098     private:
00099       void new_property() {
00100         new_property_id(_pid_in);
00101         new_property_id(_pid_out);
00102       }
00103       void free_property() {
00104         free_property_id(_pid_in);
00105         free_property_id(_pid_out);
00106       }
00107 
00108     public:
00109       void set_forest(const forest_t& forest) { _forest = &forest; }
00110       const forest_t& forest() const { return *_forest; }
00111 
00112       void set_packer(const packer_t& packer) { 
00113         _packer = packer; 
00114         free_data_buffer();
00115       }
00116       const typename packer_t::packer_t * packer() const {
00117         return _packer.packer();
00118       }
00119 
00124       template <class OBJ> data_t *
00125         get_send_buffer(const OBJ& obj) const {
00126         data_t * p_data = _packer.get_property(obj, _pid_out);
00127         if (p_data == NULL) p_data = _packer.new_property(obj, _pid_out);
00128         return p_data;
00129       }
00134       template <class OBJ> data_t *
00135         get_recv_buffer(const OBJ& obj) const {
00136         data_t * p_data = _packer.get_property(obj, _pid_in);
00137         return p_data;
00138       }
00139 
00143       void free_data_buffer() {
00144         free_property();
00145         new_property();
00146       }
00147 
00151       void update_transmit_map() {
00152         _transmit_map.build(_forest->template get_shared_list<dim-1>(),
00153                             *this, &this_t::is_pack_data);
00154       }
00155 
00162       void sync(bool is_update_transmit_map = true) {
00163         if (is_update_transmit_map) {
00164           update_transmit_map();
00165         }
00166 
00167         sync_data(_forest->communicator(), 
00168                   _transmit_map, 
00169                   *this, 
00170                   &this_t::pack_data, 
00171                   &this_t::unpack_data);
00172       }
00173 
00178       bool is_pack_data(geometry_t * geo) const {
00179         assert (_forest->get_shared_info(*geo) != NULL);
00180         return (geo->get_property(_pid_out) != NULL);
00181       }
00182 
00183       void pack_data(geometry_t * geo,
00184                      int remote_rank,
00185                      AFEPack::ostream<>& os) {
00186         assert (_forest->get_shared_info(*geo) != NULL);
00187         data_t * p_data = geo->get_property(_pid_out);
00188         assert (p_data != NULL);
00189         os << *p_data;
00190       }
00191       void unpack_data(geometry_t * geo,
00192                        int remote_rank,
00193                        AFEPack::istream<>& is) {
00194         assert (_forest->get_shared_info(*geo) != NULL);
00195         data_t * p_data = geo->get_property(_pid_in);
00196         if (p_data == NULL) p_data = geo->new_property(_pid_in);
00197         is >> *p_data;
00198       }
00199     };
00200 
00228     template <class FOREST, class PACKER>
00229       class SyncerPtr {
00230     public:
00231       enum { dim = FOREST::dim, dow = FOREST::dow };
00232       typedef FOREST forest_t;
00233       typedef PACKER packer_t;
00234       typedef typename packer_t::data_t data_t; 
00235       typedef HGeometry<dim-1,dow> geometry_t;
00236 
00237     private:
00238       typedef SyncerPtr<forest_t,packer_t> this_t;
00239 
00240       packer_t _packer;
00241       const forest_t * _forest;
00242 
00243       property_id_t<data_t> _pid_out;
00244       property_id_t<data_t> _pid_in;
00245 
00246       Transmit_map<geometry_t> _transmit_map;
00247 
00248     public:
00249       SyncerPtr() { new_property(); }
00250       SyncerPtr(const forest_t& forest) : _forest(&forest) {
00251         new_property();
00252       }
00253       SyncerPtr(const forest_t& forest, const packer_t& packer) :
00254       _forest(&forest), _packer(packer) {
00255         new_property();
00256       }
00257       SyncerPtr(const this_t& syncer) :
00258       _forest(syncer._forest), _packer(syncer._packer) {
00259         new_property();
00260       }
00261 
00262     private:
00263       void new_property() {
00264         new_property_id(_pid_in);
00265         new_property_id(_pid_out);
00266       }
00267       void free_property() {
00268         free_property_id(_pid_in);
00269         free_property_id(_pid_out);
00270       }
00271 
00272     public:
00273       void set_forest(const forest_t& forest) { _forest = &forest; }
00274       const forest_t& forest() const { return *_forest; }
00275 
00276       void set_packer(const packer_t& packer) { 
00277         free_data_buffer();
00278         _packer = packer; 
00279       }
00280       const typename packer_t::packer_t * packer() const {
00281         return _packer.packer();
00282       }
00283 
00288       template <class OBJ> void
00289         attach_send_buffer(const OBJ& obj, const data_t data) const {
00290         data_t * p_data = _packer.get_property(obj, _pid_out);
00291         if (p_data == NULL) p_data = _packer.new_property(obj, _pid_out);
00292         (*p_data) = data;
00293       }
00298       template <class OBJ> void
00299         attach_recv_buffer(const OBJ& obj, const data_t data) const {
00300         data_t * p_data = _packer.get_property(obj, _pid_in);
00301         if (p_data == NULL) p_data = _packer.new_property(obj, _pid_in);
00302         (*p_data) = data;
00303       }
00304 
00308       void free_data_buffer() {
00309         free_property();
00310         new_property();
00311       }
00312 
00313       void update_transmit_map() {
00314         _transmit_map.build(_forest->template get_shared_list<dim-1>(),
00315                             *this, &this_t::is_pack_data);
00316       }
00317 
00324       void sync(bool is_update_transmit_map = true) {
00325         if (is_update_transmit_map) {
00326           update_transmit_map();
00327         }
00328 
00329         sync_data(_forest->communicator(), 
00330                   _transmit_map, 
00331                   *this, 
00332                   &this_t::pack_data, 
00333                   &this_t::unpack_data);
00334       }
00335 
00340       bool is_pack_data(geometry_t * geo) const {
00341         return (geo->get_property(_pid_out) != NULL);
00342       }
00343 
00344       void pack_data(geometry_t * geo,
00345                      int remote_rank,
00346                      AFEPack::ostream<>& os) {
00347         const data_t * p_data = geo->get_property(_pid_out);
00348         assert (p_data != NULL);
00349         assert (geo->get_property(_pid_in) != NULL);
00350         os << **p_data;
00351       }
00352       void unpack_data(geometry_t * geo,
00353                        int remote_rank,
00354                        AFEPack::istream<>& is) {
00355         const data_t * p_data = geo->get_property(_pid_in);
00356         assert (p_data != NULL);
00357         assert (geo->get_property(_pid_out) != NULL);
00358         is >> **p_data;
00359       }
00360     };
00361 
00362     namespace details {
00363       template <class OBJ, class DATA>
00364         struct _dummy_packer {
00365           DATA * _dummy_func(const OBJ&, const property_id_t<DATA>&) { return NULL; }
00366         };
00367 
00371       template <class OBJ, class DATA, 
00372         class PACKER = _dummy_packer<OBJ,DATA> >
00373         class Packer {
00374       public:
00375       typedef OBJ object_t;
00376       typedef DATA data_t;
00377       typedef PACKER packer_t;
00378       typedef property_id_t<data_t> pid_t;
00379       typedef data_t * (packer_t::*fun_ptr_t)(const object_t&, const pid_t&) const;
00380 
00381       private:
00382       typedef Packer<object_t,data_t,packer_t> this_t;
00383       const packer_t * _packer;
00384       fun_ptr_t _new_property;
00385       fun_ptr_t _get_property;
00386 
00387       public:
00388       Packer() {}
00389       Packer(const packer_t& pac, fun_ptr_t _np, fun_ptr_t _gp) :
00390       _packer(&pac), _new_property(_np), _get_property(_gp) {}
00391       Packer(const this_t& fdp) : _packer(fdp._packer),
00392       _new_property(fdp._new_property), _get_property(fdp._get_property) {}
00393       this_t& operator=(const this_t& fdp) {
00394         _packer = fdp._packer;
00395         _new_property = fdp._new_property;
00396         _get_property = fdp._get_property;
00397         return *this;
00398       }
00399 
00400       public:
00401       const packer_t * packer() const { return _packer; }
00402       data_t * get_property(const object_t& obj, const pid_t& pid) const {
00403         return (_packer->*_get_property)(obj, pid);
00404       };
00405       data_t * new_property(const object_t& obj, const pid_t& pid) const {
00406         return (_packer->*_new_property)(obj, pid);
00407       };
00408       };
00409 
00413       template <class OBJ, class DATA>
00414         class Packer<OBJ,DATA,_dummy_packer<OBJ,DATA> > {
00415       public:
00416         typedef OBJ object_t;
00417         typedef DATA data_t;
00418         typedef _dummy_packer<object_t,DATA> packer_t;
00419         typedef property_id_t<data_t> pid_t;
00420         typedef data_t * (*fun_ptr_t)(const object_t&, const pid_t&);
00421       private:
00422         typedef Packer<object_t,data_t,packer_t> this_t;
00423         fun_ptr_t _new_property;
00424         fun_ptr_t _get_property;
00425       public:
00426         Packer() {}
00427       Packer(fun_ptr_t _np, fun_ptr_t _gp) :
00428         _new_property(_np), _get_property(_gp) {}
00429       Packer(const this_t& fdp) :
00430         _new_property(fdp._new_property), _get_property(fdp._get_property) {}
00431         this_t& operator=(const this_t& fdp) {
00432           _new_property = fdp._new_property;
00433           _get_property = fdp._get_property;
00434           return *this;
00435         }
00436       public:
00437         const packer_t * packer() const { return NULL; }
00438         data_t * get_property(const object_t& obj, const pid_t& pid) const {
00439           return (*_get_property)(obj, pid);
00440         };
00441         data_t * new_property(const object_t& obj, const pid_t& pid) const {
00442           return (*_new_property)(obj, pid);
00443         };
00444       };
00445 
00446     } // namespace details
00447 
00452     template <class DATA, class MESH>
00453       struct Mesh {
00454         typedef MESH mesh_t;
00455         typedef typename mesh_t::ir_mesh_t ir_mesh_t;
00456         typedef details::Packer<GeometryBM, DATA, mesh_t> packer_t;
00457         typedef HGeometry<mesh_t::dim-1,mesh_t::dow> h_geometry_t;
00458         static packer_t get_packer(const mesh_t& mesh) {
00459           return packer_t(mesh, 
00460                           &mesh_t::template new_property<DATA,mesh_t::dim-1>,
00461                           &mesh_t::template get_property<DATA,mesh_t::dim-1>);
00462         }
00463         static packer_t get_packer(const ir_mesh_t& mesh) {
00464           return packer_t(mesh.regularMesh(), 
00465                           &mesh_t::template new_property<DATA,mesh_t::dim-1>,
00466                           &mesh_t::template get_property<DATA,mesh_t::dim-1>);
00467         }
00468       };
00469 
00474     template <class DATA, class SPACE>
00475       struct FESpace {
00476         typedef SPACE fe_space_t;
00477         typedef typename fe_space_t::dg_element_t dg_element_t;
00478         typedef details::Packer<dg_element_t, DATA, fe_space_t> packer_t;
00479         typedef HGeometry<fe_space_t::tdim1, fe_space_t::dow> h_geometry_t;
00480         static packer_t get_packer(const fe_space_t& sp) {
00481           return packer_t(sp,
00482                           &fe_space_t::template new_property<DATA>,
00483                           &fe_space_t::template get_property<DATA>);
00484         }
00485       };
00486 
00487   } // namespace FaceData
00488 } // namespace MPI
00489 
00490 #endif // __MPI_FaceData_h__
00491