AFEPack
MPI_SyncDOF.h
浏览该文件的文档。
00001 
00011 #ifndef __MPI_SyncDOF_h__
00012 #define __MPI_SyncDOF_h__
00013 
00014 namespace MPI {
00015 
00016   template <class FOREST, class FESPACE>
00017     class DOFSyncer {
00018   private:
00019     typedef FOREST forest_t;
00020     typedef FESPACE fe_space_t;
00021 
00022     const forest_t * _p_forest;
00023     const fe_space_t * _p_fe_sp;
00024 
00025   public:
00026     DOFSyncer(const forest_t& forest,
00027               const fe_space_t& fe_sp) :
00028     _p_forest(&forest), _p_fe_sp(&fe_sp) {}
00029 
00030   private:
00031     template <class FEFUN>
00032     bool encode_geometry_data(const FEFUN& fun,
00033                               int i,
00034                               const property_id_t<BinaryBuffer<> >& pid) const {
00035       const DOFIndex& di = _p_fe_sp->dofIndex(i);
00036       const int& geo_dim = di.dimension;
00037       bool result = false;
00038       switch (geo_dim) {
00039       case 0: result = encode_geometry_data<0,FEFUN>(fun, i, di, pid); break;
00040       case 1: result = encode_geometry_data<1,FEFUN>(fun, i, di, pid); break;
00041       case 2: result = encode_geometry_data<2,FEFUN>(fun, i, di, pid); break;
00042       case 3: result = encode_geometry_data<3,FEFUN>(fun, i, di, pid); break;
00043       }
00044       return result;
00045     }
00046 
00047     template <int D, class FEFUN>
00048       bool encode_geometry_data(const FEFUN& fun,
00049                                 int i,
00050                                 const DOFIndex& di,
00051                                 const property_id_t<BinaryBuffer<> >& pid) const {
00052       typedef RegularMesh<forest_t::dim,forest_t::dow> mesh_t;
00053       typedef typename fe_space_t::dof_info_t dof_info_t;
00054       const int& geo_idx = di.geometry_index;
00055       const mesh_t& mesh = dynamic_cast<const mesh_t&>(_p_fe_sp->mesh());
00056       const HGeometry<D,forest_t::dow> * p_geo = mesh.template h_geometry<D>(geo_idx);
00057       if (_p_forest->get_shared_info(*p_geo) == NULL) return false;
00058 
00059       BinaryBuffer<> * p_buf = p_geo->get_property(pid);
00060       if (p_buf == NULL) {
00061         p_buf = p_geo->new_property(pid);
00062       }
00063 
00064       AFEPack::ostream<> os(*p_buf);
00065       const dof_info_t& dof_info = _p_fe_sp->dofInfo(i);
00066       os << dof_info.identity << dof_info.interp_point << fun(i);
00067       return true;
00068     }
00069 
00070     template <class FEFUN>
00071     void decode_geometry_data(FEFUN& fun,
00072                               int i,
00073                               const property_id_t<BinaryBuffer<> >& pid) const {
00074       const DOFIndex& di = _p_fe_sp->dofIndex(i);
00075       const int& geo_dim = di.dimension;
00076       switch (geo_dim) {
00077       case 0: decode_geometry_data<0,FEFUN>(fun, i, di, pid); break;
00078       case 1: decode_geometry_data<1,FEFUN>(fun, i, di, pid); break;
00079       case 2: decode_geometry_data<2,FEFUN>(fun, i, di, pid); break;
00080       case 3: decode_geometry_data<3,FEFUN>(fun, i, di, pid); break;
00081       }
00082     }
00083 
00084     template <int D, class FEFUN>
00085       void decode_geometry_data(FEFUN& fun,
00086                                 int i,
00087                                 const DOFIndex& di,
00088                                 const property_id_t<BinaryBuffer<> >& pid) const {
00089       typedef RegularMesh<forest_t::dim,forest_t::dow> mesh_t;
00090       typedef typename fe_space_t::dof_info_t dof_info_t;
00091       const int& geo_idx = di.geometry_index;
00092       const mesh_t& mesh = dynamic_cast<const mesh_t&>(_p_fe_sp->mesh());
00093       const HGeometry<D,forest_t::dow> * p_geo = mesh.template h_geometry<D>(geo_idx);
00094       if (_p_forest->get_shared_info(*p_geo) == NULL) return;
00095 
00096       BinaryBuffer<> * p_buf = p_geo->get_property(pid);
00097       if (p_buf == NULL) return;
00098 
00099       const dof_info_t& dof_info = _p_fe_sp->dofInfo(i);
00100       double D = dof_info.interp_point.length();
00101       AFEPack::istream<> is(*p_buf);
00102       do {
00103         dof_info_t dof_info_1;
00104         is >> dof_info_1.identity >> dof_info_1.interp_point >> fun(i);
00105         if (!(dof_info.identity == dof_info_1.identity)) continue;
00106         double D1 = dof_info_1.interp_point.length() + D;
00107         if (distance(dof_info.interp_point,
00108                      dof_info_1.interp_point) <= 1.0e-08*D1) break;
00109       } while (true);
00110     }
00111 
00112   public:
00119     template <class FEFUN, class MASK>
00120       void sync(FEFUN& fun, const MASK& mask) const {
00121       property_id_t<BinaryBuffer<> > pid;
00122       new_property_id(pid);
00123 
00124       std::vector<int> dim_mask(forest_t::dim + 1, 0);
00125       u_int n_dof = _p_fe_sp->n_dof();
00126       for (u_int i = 0;i < n_dof;++ i) {
00127         if (mask[i]) {
00128           if (encode_geometry_data(fun, i, pid)) {
00129             const DOFIndex& di = _p_fe_sp->dofIndex(i);
00130             const int& geo_dim = di.dimension;
00131             dim_mask[geo_dim] = 1;
00132           }
00133         }
00134       }
00135 
00136       PropSyncer<forest_t,BinaryBuffer<> > syncer(*_p_forest, pid);
00137       for (u_int i = 0;i <= forest_t::dim;++ i) {
00138         int is_sync;
00139         MPI_Allreduce(&dim_mask[i], &is_sync, 1, MPI_INT, 
00140                       MPI_SUM, _p_forest->communicator());
00141         if (is_sync > 0) syncer.sync(i);
00142       }
00143 
00144       for (u_int i = 0;i < n_dof;++ i) {
00145         if (! mask[i]) {
00146           decode_geometry_data(fun, i, pid);
00147         }
00148       }
00149       free_property_id(pid);
00150     }
00151   };
00152 }
00153 
00154 #endif // __MPI_SyncDOF_h__
00155