fmm_node.txx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /**
  2. * \file fmm_node.txx
  3. * \author Dhairya Malhotra, dhairya.malhotra@gmail.com
  4. * \date 12-11-2010
  5. * \brief This file contains the implementation of the FMM_Node class.
  6. */
  7. namespace pvfmm{
  8. template <class Node>
  9. FMM_Node<Node>::~FMM_Node(){
  10. if(fmm_data!=NULL) delete fmm_data;
  11. fmm_data=NULL;
  12. }
  13. template <class Node>
  14. void FMM_Node<Node>::Initialize(TreeNode* parent_,int path2node_, TreeNode::NodeData* data_){
  15. Node::Initialize(parent_,path2node_,data_);
  16. //Set FMM_Node specific data.
  17. typename FMM_Node<Node>::NodeData* data=dynamic_cast<typename FMM_Node<Node>::NodeData*>(data_);
  18. if(data_!=NULL){
  19. src_coord=data->src_coord;
  20. src_value=data->src_value;
  21. surf_coord=data->surf_coord;
  22. surf_value=data->surf_value;
  23. trg_coord=data->trg_coord;
  24. trg_value=data->trg_value;
  25. }
  26. }
  27. template <class Node>
  28. void FMM_Node<Node>::ClearData(){
  29. ClearFMMData();
  30. TreeNode::ClearData();
  31. }
  32. template <class Node>
  33. void FMM_Node<Node>::ClearFMMData(){
  34. if(fmm_data!=NULL)
  35. fmm_data->Clear();
  36. }
  37. template <class Node>
  38. TreeNode* FMM_Node<Node>::NewNode(TreeNode* n_){
  39. FMM_Node<Node>* n=(n_==NULL?new FMM_Node<Node>():static_cast<FMM_Node<Node>*>(n_));
  40. if(fmm_data!=NULL) n->fmm_data=fmm_data->NewData();
  41. return Node_t::NewNode(n);
  42. }
  43. template <class Node>
  44. bool FMM_Node<Node>::SubdivCond(){
  45. int n=(1UL<<this->Dim());
  46. // Do not subdivide beyond max_depth
  47. if(this->Depth()>=this->max_depth-1) return false;
  48. if(!this->IsLeaf()){ // If has non-leaf children, then return true.
  49. for(int i=0;i<n;i++){
  50. MPI_Node<Real_t>* ch=static_cast<MPI_Node<Real_t>*>(this->Child(i));
  51. assert(ch!=NULL); //This should never happen
  52. if(!ch->IsLeaf() || ch->IsGhost()) return true;
  53. }
  54. }
  55. else{ // Do not refine ghost leaf nodes.
  56. if(this->IsGhost()) return false;
  57. }
  58. if(Node::SubdivCond()) return true;
  59. if(!this->IsLeaf()){
  60. size_t pt_vec_size=0;
  61. for(int i=0;i<n;i++){
  62. FMM_Node<Node>* ch=static_cast<FMM_Node<Node>*>(this->Child(i));
  63. pt_vec_size+=ch->src_coord.Dim();
  64. pt_vec_size+=ch->surf_coord.Dim();
  65. pt_vec_size+=ch->trg_coord.Dim();
  66. }
  67. return pt_vec_size/this->Dim()>this->max_pts;
  68. }else{
  69. size_t pt_vec_size=0;
  70. pt_vec_size+=src_coord.Dim();
  71. pt_vec_size+=surf_coord.Dim();
  72. pt_vec_size+=trg_coord.Dim();
  73. return pt_vec_size/this->Dim()>this->max_pts;
  74. }
  75. }
  76. template <class Node>
  77. void FMM_Node<Node>::Subdivide(){
  78. if(!this->IsLeaf()) return;
  79. Node::Subdivide();
  80. }
  81. template <class Node>
  82. void FMM_Node<Node>::Truncate(){
  83. Node::Truncate();
  84. }
  85. template <class Node>
  86. PackedData FMM_Node<Node>::Pack(bool ghost, void* buff_ptr, size_t offset){
  87. PackedData p0,p1,p2;
  88. if(buff_ptr==NULL){
  89. p2=PackMultipole();
  90. }else{
  91. char* data_ptr=(char*)buff_ptr+offset;
  92. p2=PackMultipole(data_ptr+2*sizeof(size_t));
  93. }
  94. p0.length =sizeof(size_t);
  95. p0.length+=sizeof(size_t)+p2.length;
  96. p1=Node_t::Pack(ghost,buff_ptr,p0.length+offset);
  97. p0.length+=p1.length;
  98. p0.data=p1.data;
  99. char* data_ptr=(char*)p0.data;
  100. data_ptr+=offset;
  101. // Header
  102. ((size_t*)data_ptr)[0]=p0.length;
  103. data_ptr+=sizeof(size_t);
  104. // Copy multipole data.
  105. ((size_t*)data_ptr)[0]=p2.length; data_ptr+=sizeof(size_t);
  106. mem::memcopy(data_ptr,p2.data,p2.length);
  107. return p0;
  108. }
  109. template <class Node>
  110. void FMM_Node<Node>::Unpack(PackedData p0, bool own_data){
  111. char* data_ptr=(char*)p0.data;
  112. // Check header
  113. assert(((size_t*)data_ptr)[0]==p0.length);
  114. data_ptr+=sizeof(size_t);
  115. PackedData p2;
  116. p2.length=(((size_t*)data_ptr)[0]); data_ptr+=sizeof(size_t);
  117. p2.data=(void*)data_ptr; data_ptr+=p2.length;
  118. InitMultipole(p2,own_data);
  119. PackedData p1;
  120. p1.data=data_ptr;
  121. p1.length=((size_t*)data_ptr)[0];
  122. Node::Unpack(p1, own_data);
  123. }
  124. template <class Node>
  125. PackedData FMM_Node<Node>::PackMultipole(void* buff_ptr){
  126. if(fmm_data!=NULL)
  127. return fmm_data->PackMultipole(buff_ptr);
  128. else{
  129. PackedData pkd;
  130. pkd.length=0;
  131. pkd.data=buff_ptr;
  132. return pkd;
  133. }
  134. };
  135. template <class Node>
  136. void FMM_Node<Node>::AddMultipole(PackedData data){
  137. if(data.length>0){
  138. assert(fmm_data!=NULL);
  139. fmm_data->AddMultipole(data);
  140. }
  141. };
  142. template <class Node>
  143. void FMM_Node<Node>::InitMultipole(PackedData data, bool own_data){
  144. if(data.length>0){
  145. assert(fmm_data!=NULL);
  146. fmm_data->InitMultipole(data, own_data);
  147. }
  148. };
  149. }//end namespace