AFEPack
MPI_SyncProp.h
浏览该文件的文档。
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