AFEPack
|
00001 00010 /*< 00011 00012 对表达成为几何体上的性质的数据进行分区间的同步。此类接受三个模板参数: 00013 00014 - FOREST:几何遗传树的类型; 00015 - PROPOUT:发送出去的性质的数据类型; 00016 - PROPIN:接收进来的性质的数据类型; 00017 00018 此类使用的方式为以下步骤: 00019 00020 1. 用户程序定义 property_id_t<PROPOUT> 和 property_id_t<PROPIN> 两个 00021 性质ID,并为部分几何体设置PROPOUT性质; 00022 00023 2. 声明一个本类的对象,并使用几何遗传数和两个性质ID对其进行初始化; 00024 00025 3. 调用本类对象的函数 sync<dim>() 对dim维的共享几何体上的数据进行交换; 00026 00027 类型 PROPOUT 和 PROPIN 需要提供下面的流操作符: 00028 00029 AFEPack::ostream<>& operator<<(AFEPack::ostream<>& os, 00030 const PROPOUT& prop_out) 00031 00032 AFEPack::istream<>& operator>>(AFEPack::istream<>& is, 00033 PROPIN& prop_in) 00034 00035 */ 00036 00037 #ifndef __MPI_SyncProp_h__ 00038 #define __MPI_SyncProp_h__ 00039 00040 #include "MPI_HGeometry.h" 00041 00042 namespace MPI { 00043 00044 template <class FOREST, class PROPOUT, class PROPIN = PROPOUT> 00045 class PropSyncer { 00046 private: 00047 typedef PropSyncer<FOREST,PROPOUT,PROPIN> this_t; 00048 const FOREST * _p_forest; 00049 const property_id_t<PROPOUT> * _p_pid_out; 00050 const property_id_t<PROPIN> * _p_pid_in; 00051 00052 public: 00053 PropSyncer() : _p_forest(NULL), _p_pid_out(NULL), _p_pid_in(NULL) {} 00054 PropSyncer(const FOREST& forest, 00055 const property_id_t<PROPOUT>& pid_out) 00056 : _p_forest(&forest), _p_pid_out(&pid_out), _p_pid_in(&pid_out) {} 00057 PropSyncer(const FOREST& forest, 00058 const property_id_t<PROPOUT>& pid_out, 00059 const property_id_t<PROPIN>& pid_in) 00060 : _p_forest(&forest), _p_pid_out(&pid_out), _p_pid_in(&pid_in) {} 00061 00062 public: 00063 void set_forest(const FOREST& forest) { 00064 _p_forest = &forest; 00065 } 00066 00067 void set_pid(const property_id_t<PROPOUT>& pid) { 00068 _p_pid_out = &pid; 00069 _p_pid_in = &pid; 00070 } 00071 void set_pid(const property_id_t<PROPOUT>& pid_out, 00072 const property_id_t<PROPIN>& pid_in) { 00073 _p_pid_out = &pid_out; 00074 _p_pid_in = &pid_in; 00075 } 00076 00077 void set_pid_out(const property_id_t<PROPOUT>& pid) { 00078 _p_pid_out = &pid; 00079 } 00080 void set_pid_in(const property_id_t<PROPIN>& pid) { 00081 _p_pid_in = &pid; 00082 } 00083 00084 template <int D> 00085 void sync() { 00086 sync_data(_p_forest->communicator(), 00087 _p_forest->template get_shared_list<D>(), 00088 *this, 00089 &this_t::template pack<D>, 00090 &this_t::template unpack<D>, 00091 &this_t::template is_pack_info<D>); 00092 } 00093 void sync(int D) { 00094 switch (D) { 00095 case 0: sync<0>(); break; 00096 case 1: sync<1>(); break; 00097 case 2: sync<2>(); break; 00098 case 3: sync<3>(); break; 00099 } 00100 } 00101 00102 public: 00103 template <int D> bool 00104 is_pack_info(HGeometry<D,FOREST::dow> * p_geo) { 00105 return (p_geo->get_property(*_p_pid_out) != NULL); 00106 } 00107 template <int D> 00108 void pack(HGeometry<D,FOREST::dow> * p_geo, 00109 int remote_rank, 00110 AFEPack::ostream<>& os) { 00111 const PROPOUT * p_buf = p_geo->get_property(*_p_pid_out); 00112 assert (p_buf != NULL); 00113 os << *p_buf; 00114 } 00115 template <int D> 00116 void unpack(HGeometry<D,FOREST::dow> * p_geo, 00117 int remote_rank, 00118 AFEPack::istream<>& is) { 00119 PROPIN * p_buf = p_geo->get_property(*_p_pid_in); 00120 if (p_buf == NULL) { 00121 p_buf = p_geo->new_property(*_p_pid_in); 00122 } 00123 is >> *p_buf; 00124 } 00125 00126 private: 00127 const void * p_op; 00128 public: 00129 template <int D, class OP> 00130 void sync(const OP& op) { 00131 p_op = &op; 00132 sync_data(_p_forest->communicator(), 00133 _p_forest->template get_shared_list<D>(), 00134 *this, 00135 &this_t::template pack<D>, 00136 &this_t::template varunpack<D,OP>, 00137 &this_t::template is_pack_info<D>); 00138 } 00139 template <class OP> 00140 void sync(int D, const OP& op) { 00141 switch (D) { 00142 case 0: sync<0,OP>(op); break; 00143 case 1: sync<1,OP>(op); break; 00144 case 2: sync<2,OP>(op); break; 00145 case 3: sync<3,OP>(op); break; 00146 } 00147 } 00148 00149 public: 00150 template <int D, class OP> 00151 void varunpack(HGeometry<D,FOREST::dow> * p_geo, 00152 int remote_rank, 00153 AFEPack::istream<>& is) { 00154 PROPIN * p_buf = p_geo->get_property(*_p_pid_in); 00155 if (p_buf == NULL) { 00156 p_buf = p_geo->new_property(*_p_pid_in); 00157 is >> *p_buf; 00158 } else { 00159 const OP& op = *((const OP *)p_op); 00160 PROPIN buf_in; 00161 is >> buf_in; 00162 *p_buf = op(*p_buf, buf_in); 00163 } 00164 } 00165 00166 }; 00167 } 00168 00169 #endif // __MPI_SyncProp_h__ 00170