AFEPack
|
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