mpi_node.txx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /**
  2. * \file mpi_node.cpp
  3. * \author Dhairya Malhotra, dhairya.malhotra@gmail.com
  4. * \date 12-11-2010
  5. * \brief This file contains the implementation of the class MPI_Node.
  6. */
  7. #include <assert.h>
  8. #include <iostream>
  9. namespace pvfmm{
  10. template <class T>
  11. MPI_Node<T>::~MPI_Node(){
  12. }
  13. template <class T>
  14. void MPI_Node<T>::Initialize(TreeNode* parent_,int path2node_, TreeNode::NodeData* data_){
  15. TreeNode::Initialize(parent_,path2node_,data_);
  16. //Set node coordinates.
  17. Real_t coord_offset=((Real_t)1.0)/((Real_t)(((uint64_t)1)<<Depth()));
  18. if(!parent_){
  19. for(int j=0;j<dim;j++) coord[j]=0;
  20. }else if(parent_){
  21. int flag=1;
  22. for(int j=0;j<dim;j++){
  23. coord[j]=((MPI_Node<Real_t>*)parent_)->coord[j]+
  24. ((Path2Node() & flag)?coord_offset:0.0f);
  25. flag=flag<<1;
  26. }
  27. }
  28. //Initialize colleagues array.
  29. int n=(int)pow(3.0,Dim());
  30. for(int i=0;i<n;i++) colleague[i]=NULL;
  31. //Set MPI_Node specific data.
  32. typename MPI_Node<Real_t>::NodeData* mpi_data=dynamic_cast<typename MPI_Node<Real_t>::NodeData*>(data_);
  33. if(data_){
  34. max_pts =mpi_data->max_pts;
  35. pt_coord=mpi_data->pt_coord;
  36. pt_value=mpi_data->pt_value;
  37. }else if(parent){
  38. max_pts =((MPI_Node<T>*)parent)->max_pts;
  39. SetGhost(((MPI_Node<T>*)parent)->IsGhost());
  40. }
  41. }
  42. template <class T>
  43. void MPI_Node<T>::ClearData(){
  44. pt_coord.ReInit(0);
  45. pt_value.ReInit(0);
  46. }
  47. template <class T>
  48. MortonId MPI_Node<T>::GetMortonId(){
  49. assert(coord);
  50. Real_t s=0.25/(1UL<<MAX_DEPTH);
  51. return MortonId(coord[0]+s,coord[1]+s,coord[2]+s, Depth()); // TODO: Use interger coordinates instead of floating point.
  52. }
  53. template <class T>
  54. void MPI_Node<T>::SetCoord(MortonId& mid){
  55. assert(coord);
  56. mid.GetCoord(coord);
  57. depth=mid.GetDepth();
  58. }
  59. template <class T>
  60. TreeNode* MPI_Node<T>::NewNode(TreeNode* n_){
  61. MPI_Node<Real_t>* n=(n_?static_cast<MPI_Node<Real_t>*>(n_):new MPI_Node<Real_t>());
  62. n->max_pts=max_pts;
  63. return TreeNode::NewNode(n);
  64. }
  65. template <class T>
  66. bool MPI_Node<T>::SubdivCond(){
  67. int n=(1UL<<this->Dim());
  68. // Do not subdivide beyond max_depth
  69. if(this->Depth()>=this->max_depth-1) return false;
  70. if(!this->IsLeaf()){ // If has non-leaf children, then return true.
  71. for(int i=0;i<n;i++){
  72. MPI_Node<Real_t>* ch=static_cast<MPI_Node<Real_t>*>(this->Child(i));
  73. assert(ch); //ch==NULL should never happen
  74. if(!ch->IsLeaf() || ch->IsGhost()) return true;
  75. }
  76. }
  77. else{ // Do not refine ghost leaf nodes.
  78. if(this->IsGhost()) return false;
  79. }
  80. if(!this->IsLeaf()){
  81. size_t pt_vec_size=0;
  82. for(int i=0;i<n;i++){
  83. MPI_Node<Real_t>* ch=static_cast<MPI_Node<Real_t>*>(this->Child(i));
  84. pt_vec_size+=ch->pt_coord.Dim();
  85. }
  86. return pt_vec_size/Dim()>max_pts;
  87. }else{
  88. return pt_coord.Dim()/Dim()>max_pts;
  89. }
  90. }
  91. template <class T>
  92. void MPI_Node<T>::Subdivide(){
  93. if(!this->IsLeaf()) return;
  94. TreeNode::Subdivide();
  95. int nchld=(1UL<<this->Dim());
  96. if(!IsGhost()){ // Partition point coordinates and values.
  97. std::vector<Vector<Real_t>*> pt_coord;
  98. std::vector<Vector<Real_t>*> pt_value;
  99. std::vector<Vector<size_t>*> pt_scatter;
  100. this->NodeDataVec(pt_coord, pt_value, pt_scatter);
  101. std::vector<std::vector<Vector<Real_t>*> > chld_pt_coord(nchld);
  102. std::vector<std::vector<Vector<Real_t>*> > chld_pt_value(nchld);
  103. std::vector<std::vector<Vector<size_t>*> > chld_pt_scatter(nchld);
  104. for(size_t i=0;i<nchld;i++){
  105. static_cast<MPI_Node<Real_t>*>((MPI_Node<T>*)this->Child(i))
  106. ->NodeDataVec(chld_pt_coord[i], chld_pt_value[i], chld_pt_scatter[i]);
  107. }
  108. Real_t* c=this->Coord();
  109. Real_t s=pow(0.5,this->Depth()+1);
  110. for(size_t j=0;j<pt_coord.size();j++){
  111. if(!pt_coord[j] || !pt_coord[j]->Dim()) continue;
  112. Vector<Real_t>& coord=*pt_coord[j];
  113. size_t npts=coord.Dim()/this->dim;
  114. Vector<size_t> cdata(nchld+1);
  115. for(size_t i=0;i<nchld+1;i++){
  116. long long pt1=-1, pt2=npts;
  117. while(pt2-pt1>1){ // binary search
  118. long long pt3=(pt1+pt2)/2;
  119. assert(pt3<npts);
  120. if(pt3<0) pt3=0;
  121. int ch_id=(coord[pt3*3+0]>=c[0]+s)*1+
  122. (coord[pt3*3+1]>=c[1]+s)*2+
  123. (coord[pt3*3+2]>=c[2]+s)*4;
  124. if(ch_id< i) pt1=pt3;
  125. if(ch_id>=i) pt2=pt3;
  126. }
  127. cdata[i]=pt2;
  128. }
  129. if(pt_coord[j]){
  130. Vector<Real_t>& vec=*pt_coord[j];
  131. size_t dof=vec.Dim()/npts;
  132. if(dof>0) for(size_t i=0;i<nchld;i++){
  133. Vector<Real_t>& chld_vec=*chld_pt_coord[i][j];
  134. chld_vec.ReInit((cdata[i+1]-cdata[i])*dof, &vec[0]+cdata[i]*dof);
  135. }
  136. vec.ReInit(0);
  137. }
  138. if(pt_value[j]){
  139. Vector<Real_t>& vec=*pt_value[j];
  140. size_t dof=vec.Dim()/npts;
  141. if(dof>0) for(size_t i=0;i<nchld;i++){
  142. Vector<Real_t>& chld_vec=*chld_pt_value[i][j];
  143. chld_vec.ReInit((cdata[i+1]-cdata[i])*dof, &vec[0]+cdata[i]*dof);
  144. }
  145. vec.ReInit(0);
  146. }
  147. if(pt_scatter[j]){
  148. Vector<size_t>& vec=*pt_scatter[j];
  149. size_t dof=vec.Dim()/npts;
  150. if(dof>0) for(size_t i=0;i<nchld;i++){
  151. Vector<size_t>& chld_vec=*chld_pt_scatter[i][j];
  152. chld_vec.ReInit((cdata[i+1]-cdata[i])*dof, &vec[0]+cdata[i]*dof);
  153. }
  154. vec.ReInit(0);
  155. }
  156. }
  157. }
  158. };
  159. template <class T>
  160. void MPI_Node<T>::Truncate(){
  161. if(!this->IsLeaf()){
  162. int nchld=(1UL<<this->Dim());
  163. for(size_t i=0;i<nchld;i++){
  164. if(!this->Child(i)->IsLeaf()){
  165. this->Child(i)->Truncate();
  166. }
  167. }
  168. std::vector<Vector<Real_t>*> pt_coord;
  169. std::vector<Vector<Real_t>*> pt_value;
  170. std::vector<Vector<size_t>*> pt_scatter;
  171. this->NodeDataVec(pt_coord, pt_value, pt_scatter);
  172. std::vector<std::vector<Vector<Real_t>*> > chld_pt_coord(nchld);
  173. std::vector<std::vector<Vector<Real_t>*> > chld_pt_value(nchld);
  174. std::vector<std::vector<Vector<size_t>*> > chld_pt_scatter(nchld);
  175. for(size_t i=0;i<nchld;i++){
  176. static_cast<MPI_Node<Real_t>*>((MPI_Node<T>*)this->Child(i))
  177. ->NodeDataVec(chld_pt_coord[i], chld_pt_value[i], chld_pt_scatter[i]);
  178. }
  179. for(size_t j=0;j<pt_coord.size();j++){
  180. if(!pt_coord[j]) continue;
  181. if(pt_coord[j]){
  182. size_t vec_size=0;
  183. for(size_t i=0;i<nchld;i++){
  184. Vector<Real_t>& chld_vec=*chld_pt_coord[i][j];
  185. vec_size+=chld_vec.Dim();
  186. }
  187. Vector<Real_t> vec=*pt_coord[j];
  188. vec.ReInit(vec_size);
  189. vec_size=0;
  190. for(size_t i=0;i<nchld;i++){
  191. Vector<Real_t>& chld_vec=*chld_pt_coord[i][j];
  192. if(chld_vec.Dim()>0){
  193. mem::memcopy(&vec[vec_size],&chld_vec[0],chld_vec.Dim()*sizeof(Real_t));
  194. vec_size+=chld_vec.Dim();
  195. }
  196. }
  197. }
  198. if(pt_value[j]){
  199. size_t vec_size=0;
  200. for(size_t i=0;i<nchld;i++){
  201. Vector<Real_t>& chld_vec=*chld_pt_value[i][j];
  202. vec_size+=chld_vec.Dim();
  203. }
  204. Vector<Real_t> vec=*pt_value[j];
  205. vec.ReInit(vec_size);
  206. vec_size=0;
  207. for(size_t i=0;i<nchld;i++){
  208. Vector<Real_t>& chld_vec=*chld_pt_value[i][j];
  209. if(chld_vec.Dim()>0){
  210. mem::memcopy(&vec[vec_size],&chld_vec[0],chld_vec.Dim()*sizeof(Real_t));
  211. vec_size+=chld_vec.Dim();
  212. }
  213. }
  214. }
  215. if(pt_scatter[j]){
  216. size_t vec_size=0;
  217. for(size_t i=0;i<nchld;i++){
  218. Vector<size_t>& chld_vec=*chld_pt_scatter[i][j];
  219. vec_size+=chld_vec.Dim();
  220. }
  221. Vector<size_t> vec=*pt_scatter[j];
  222. vec.ReInit(vec_size);
  223. vec_size=0;
  224. for(size_t i=0;i<nchld;i++){
  225. Vector<size_t>& chld_vec=*chld_pt_scatter[i][j];
  226. if(chld_vec.Dim()>0){
  227. mem::memcopy(&vec[vec_size],&chld_vec[0],chld_vec.Dim()*sizeof(Real_t));
  228. vec_size+=chld_vec.Dim();
  229. }
  230. }
  231. }
  232. }
  233. }
  234. TreeNode::Truncate();
  235. }
  236. template <class T>
  237. PackedData MPI_Node<T>::Pack(bool ghost, void* buff_ptr, size_t offset){
  238. std::vector<Vector<Real_t>*> pt_coord;
  239. std::vector<Vector<Real_t>*> pt_value;
  240. std::vector<Vector<size_t>*> pt_scatter;
  241. this->NodeDataVec(pt_coord, pt_value, pt_scatter);
  242. PackedData p0;
  243. // Determine data length.
  244. p0.length =sizeof(size_t)+sizeof(int)+sizeof(long long)+sizeof(MortonId);
  245. for(size_t j=0;j<pt_coord.size();j++){
  246. p0.length+=3*sizeof(size_t);
  247. if(pt_coord [j]) p0.length+=(pt_coord [j]->Dim())*sizeof(Real_t);
  248. if(pt_value [j]) p0.length+=(pt_value [j]->Dim())*sizeof(Real_t);
  249. if(pt_scatter[j]) p0.length+=(pt_scatter[j]->Dim())*sizeof(size_t);
  250. }
  251. // Allocate memory.
  252. p0.data=(char*)buff_ptr;
  253. if(!p0.data){
  254. this->packed_data.Resize(p0.length+offset);
  255. p0.data=&this->packed_data[0];
  256. }
  257. char* data_ptr=(char*)p0.data;
  258. data_ptr+=offset;
  259. // Header
  260. ((size_t*)data_ptr)[0]=p0.length;
  261. data_ptr+=sizeof(size_t);
  262. ((int*)data_ptr)[0]=this->Depth();
  263. data_ptr+=sizeof(int);
  264. ((long long*)data_ptr)[0]=this->NodeCost();
  265. data_ptr+=sizeof(long long);
  266. ((MortonId*)data_ptr)[0]=this->GetMortonId();
  267. data_ptr+=sizeof(MortonId);
  268. // Copy Vector data.
  269. for(size_t j=0;j<pt_coord.size();j++){
  270. if(pt_coord[j]){
  271. Vector<Real_t>& vec=*pt_coord[j];
  272. ((size_t*)data_ptr)[0]=vec.Dim(); data_ptr+=sizeof(size_t);
  273. if(vec.Dim()>0 && data_ptr!=(char*)&vec[0])
  274. mem::memcopy(data_ptr, &vec[0], sizeof(Real_t)*vec.Dim());
  275. data_ptr+=vec.Dim()*sizeof(Real_t);
  276. }else{
  277. ((size_t*)data_ptr)[0]=0; data_ptr+=sizeof(size_t);
  278. }
  279. if(pt_value[j]){
  280. Vector<Real_t>& vec=*pt_value[j];
  281. ((size_t*)data_ptr)[0]=vec.Dim(); data_ptr+=sizeof(size_t);
  282. if(vec.Dim()>0 && data_ptr!=(char*)&vec[0])
  283. mem::memcopy(data_ptr, &vec[0], sizeof(Real_t)*vec.Dim());
  284. data_ptr+=vec.Dim()*sizeof(Real_t);
  285. }else{
  286. ((size_t*)data_ptr)[0]=0; data_ptr+=sizeof(size_t);
  287. }
  288. if(pt_scatter[j] && !ghost){
  289. Vector<size_t>& vec=*pt_scatter[j];
  290. ((size_t*)data_ptr)[0]=vec.Dim(); data_ptr+=sizeof(size_t);
  291. if(vec.Dim()>0 && data_ptr!=(char*)&vec[0])
  292. mem::memcopy(data_ptr, &vec[0], sizeof(size_t)*vec.Dim());
  293. data_ptr+=vec.Dim()*sizeof(size_t);
  294. }else{
  295. ((size_t*)data_ptr)[0]=0; data_ptr+=sizeof(size_t);
  296. }
  297. }
  298. return p0;
  299. }
  300. template <class T>
  301. void MPI_Node<T>::Unpack(PackedData p0, bool own_data){
  302. std::vector<Vector<Real_t>*> pt_coord;
  303. std::vector<Vector<Real_t>*> pt_value;
  304. std::vector<Vector<size_t>*> pt_scatter;
  305. this->NodeDataVec(pt_coord, pt_value, pt_scatter);
  306. char* data_ptr=(char*)p0.data;
  307. // Check header
  308. assert(((size_t*)data_ptr)[0]==p0.length);
  309. data_ptr+=sizeof(size_t);
  310. this->depth=(((int*)data_ptr)[0]);
  311. data_ptr+=sizeof(int);
  312. this->NodeCost()=(((long long*)data_ptr)[0]);
  313. data_ptr+=sizeof(long long);
  314. this->SetCoord(((MortonId*)data_ptr)[0]);
  315. data_ptr+=sizeof(MortonId);
  316. for(size_t j=0;j<pt_coord.size();j++){
  317. if(pt_coord[j]){
  318. Vector<Real_t>& vec=*pt_coord[j];
  319. size_t vec_sz=(((size_t*)data_ptr)[0]); data_ptr+=sizeof(size_t);
  320. if(own_data){
  321. vec=Vector<Real_t>(vec_sz,(Real_t*)data_ptr,false);
  322. }else{
  323. vec.ReInit(vec_sz,(Real_t*)data_ptr,false);
  324. }
  325. data_ptr+=vec_sz*sizeof(Real_t);
  326. }else{
  327. assert(!((size_t*)data_ptr)[0]);
  328. data_ptr+=sizeof(size_t);
  329. }
  330. if(pt_value[j]){
  331. Vector<Real_t>& vec=*pt_value[j];
  332. size_t vec_sz=(((size_t*)data_ptr)[0]); data_ptr+=sizeof(size_t);
  333. if(own_data){
  334. vec=Vector<Real_t>(vec_sz,(Real_t*)data_ptr,false);
  335. }else{
  336. vec.ReInit(vec_sz,(Real_t*)data_ptr,false);
  337. }
  338. data_ptr+=vec_sz*sizeof(Real_t);
  339. }else{
  340. assert(!((size_t*)data_ptr)[0]);
  341. data_ptr+=sizeof(size_t);
  342. }
  343. if(pt_scatter[j]){
  344. Vector<size_t>& vec=*pt_scatter[j];
  345. size_t vec_sz=(((size_t*)data_ptr)[0]); data_ptr+=sizeof(size_t);
  346. if(own_data){
  347. vec=Vector<size_t>(vec_sz,(size_t*)data_ptr,false);
  348. }else{
  349. vec.ReInit(vec_sz,(size_t*)data_ptr,false);
  350. }
  351. data_ptr+=vec_sz*sizeof(size_t);
  352. }else{
  353. assert(!((size_t*)data_ptr)[0]);
  354. data_ptr+=sizeof(size_t);
  355. }
  356. }
  357. }
  358. template <class T>
  359. void MPI_Node<T>::ReadVal(std::vector<Real_t> x,std::vector<Real_t> y, std::vector<Real_t> z, Real_t* val, bool show_ghost){
  360. if(!pt_coord.Dim()) return;
  361. size_t n_pts=pt_coord.Dim()/dim;
  362. size_t data_dof=pt_value.Dim()/n_pts;
  363. std::vector<Real_t> v(data_dof,0);
  364. for(size_t i=0;i<n_pts;i++)
  365. for(int j=0;j<data_dof;j++)
  366. v[j]+=pt_value[i*data_dof+j];
  367. for(int j=0;j<data_dof;j++)
  368. v[j]=v[j]/n_pts;
  369. for(size_t i=0;i<x.size()*y.size()*z.size()*data_dof;i++){
  370. val[i]=v[i%data_dof];
  371. }
  372. }
  373. template <class T>
  374. void MPI_Node<T>::VTU_Data(std::vector<Real_t>& coord, std::vector<Real_t>& value, std::vector<int32_t>& connect, std::vector<int32_t>& offset, std::vector<uint8_t>& types, int lod){
  375. if(!pt_coord.Dim()) return;
  376. size_t point_cnt=coord.size()/COORD_DIM;
  377. size_t connect_cnt=connect.size();
  378. for(size_t i=0;i<pt_coord.Dim();i+=3){
  379. coord.push_back(pt_coord[i+0]);
  380. coord.push_back(pt_coord[i+1]);
  381. coord.push_back(pt_coord[i+2]);
  382. connect_cnt++;
  383. connect.push_back(point_cnt);
  384. offset.push_back(connect_cnt);
  385. types.push_back(1);
  386. point_cnt++;
  387. }
  388. for(size_t i=0;i<pt_value.Dim();i++) value.push_back(pt_value[i]);
  389. Real_t* c=this->Coord();
  390. Real_t s=pow(0.5,this->Depth());
  391. size_t data_dof=pt_value.Dim()/(pt_coord.Dim()/dim);
  392. for(int i=0;i<8;i++){
  393. coord.push_back(c[0]+(i&1?1:0)*s);
  394. coord.push_back(c[1]+(i&2?1:0)*s);
  395. coord.push_back(c[2]+(i&4?1:0)*s);
  396. for(int j=0;j<data_dof;j++) value.push_back(0.0);
  397. connect.push_back(point_cnt+i);
  398. }
  399. offset.push_back(8+connect_cnt);
  400. types.push_back(11);
  401. {// Set point values.
  402. Real_t* val_ptr=&value[point_cnt*data_dof];
  403. std::vector<Real_t> x(2);
  404. std::vector<Real_t> y(2);
  405. std::vector<Real_t> z(2);
  406. x[0]=c[0]; x[1]=c[0]+s;
  407. y[0]=c[1]; y[1]=c[1]+s;
  408. z[0]=c[2]; z[1]=c[2]+s;
  409. this->ReadVal(x, y, z, val_ptr);
  410. //Rearrrange data
  411. //(x1,x2,x3,...,y1,y2,...z1,...) => (x1,y1,z1,x2,y2,z2,...)
  412. Matrix<Real_t> M(data_dof,8,val_ptr,false);
  413. M=M.Transpose();
  414. }
  415. }
  416. }//end namespace