fmm_node.txx 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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. #include <cassert>
  8. #include <mem_mgr.hpp>
  9. #include <mpi_node.hpp>
  10. namespace pvfmm{
  11. template <class Node>
  12. FMM_Node<Node>::~FMM_Node(){
  13. if(fmm_data!=NULL) mem::aligned_delete(fmm_data);
  14. fmm_data=NULL;
  15. }
  16. template <class Node>
  17. void FMM_Node<Node>::Initialize(TreeNode* parent_,int path2node_, TreeNode::NodeData* data_){
  18. Node::Initialize(parent_,path2node_,data_);
  19. //Set FMM_Node specific data.
  20. typename FMM_Node<Node>::NodeData* data=dynamic_cast<typename FMM_Node<Node>::NodeData*>(data_);
  21. if(data_!=NULL){
  22. src_coord=data->src_coord;
  23. src_value=data->src_value;
  24. surf_coord=data->surf_coord;
  25. surf_value=data->surf_value;
  26. trg_coord=data->trg_coord;
  27. trg_value=data->trg_value;
  28. }
  29. }
  30. template <class Node>
  31. void FMM_Node<Node>::ClearData(){
  32. ClearFMMData();
  33. TreeNode::ClearData();
  34. }
  35. template <class Node>
  36. void FMM_Node<Node>::ClearFMMData(){
  37. if(fmm_data!=NULL)
  38. fmm_data->Clear();
  39. }
  40. template <class Node>
  41. TreeNode* FMM_Node<Node>::NewNode(TreeNode* n_){
  42. FMM_Node<Node>* n=(n_==NULL?mem::aligned_new<FMM_Node<Node> >():static_cast<FMM_Node<Node>*>(n_));
  43. if(fmm_data!=NULL) n->fmm_data=fmm_data->NewData();
  44. return Node_t::NewNode(n);
  45. }
  46. template <class Node>
  47. bool FMM_Node<Node>::SubdivCond(){
  48. int n=(1UL<<this->Dim());
  49. // Do not subdivide beyond max_depth
  50. if(this->Depth()>=this->max_depth-1) return false;
  51. if(!this->IsLeaf()){ // If has non-leaf children, then return true.
  52. for(int i=0;i<n;i++){
  53. MPI_Node<Real_t>* ch=static_cast<MPI_Node<Real_t>*>(this->Child(i));
  54. assert(ch!=NULL); //This should never happen
  55. if(!ch->IsLeaf() || ch->IsGhost()) return true;
  56. }
  57. }
  58. else{ // Do not refine ghost leaf nodes.
  59. if(this->IsGhost()) return false;
  60. }
  61. if(Node::SubdivCond()) return true;
  62. if(!this->IsLeaf()){
  63. size_t pt_vec_size=0;
  64. for(int i=0;i<n;i++){
  65. FMM_Node<Node>* ch=static_cast<FMM_Node<Node>*>(this->Child(i));
  66. pt_vec_size+=ch->src_coord.Dim();
  67. pt_vec_size+=ch->surf_coord.Dim();
  68. pt_vec_size+=ch->trg_coord.Dim();
  69. }
  70. return pt_vec_size/this->Dim()>this->max_pts;
  71. }else{
  72. size_t pt_vec_size=0;
  73. pt_vec_size+=src_coord.Dim();
  74. pt_vec_size+=surf_coord.Dim();
  75. pt_vec_size+=trg_coord.Dim();
  76. return pt_vec_size/this->Dim()>this->max_pts;
  77. }
  78. }
  79. template <class Node>
  80. void FMM_Node<Node>::Subdivide(){
  81. if(!this->IsLeaf()) return;
  82. Node::Subdivide();
  83. }
  84. template <class Node>
  85. void FMM_Node<Node>::Truncate(){
  86. Node::Truncate();
  87. }
  88. template <class Node>
  89. PackedData FMM_Node<Node>::Pack(bool ghost, void* buff_ptr, size_t offset){
  90. PackedData p0,p1,p2;
  91. if(buff_ptr==NULL){
  92. p2=PackMultipole();
  93. }else{
  94. char* data_ptr=(char*)buff_ptr+offset;
  95. p2=PackMultipole(data_ptr+2*sizeof(size_t));
  96. }
  97. p0.length =sizeof(size_t);
  98. p0.length+=sizeof(size_t)+p2.length;
  99. p1=Node_t::Pack(ghost,buff_ptr,p0.length+offset);
  100. p0.length+=p1.length;
  101. p0.data=p1.data;
  102. char* data_ptr=(char*)p0.data;
  103. data_ptr+=offset;
  104. // Header
  105. ((size_t*)data_ptr)[0]=p0.length;
  106. data_ptr+=sizeof(size_t);
  107. // Copy multipole data.
  108. ((size_t*)data_ptr)[0]=p2.length; data_ptr+=sizeof(size_t);
  109. mem::memcopy(data_ptr,p2.data,p2.length);
  110. return p0;
  111. }
  112. template <class Node>
  113. void FMM_Node<Node>::Unpack(PackedData p0, bool own_data){
  114. char* data_ptr=(char*)p0.data;
  115. // Check header
  116. assert(((size_t*)data_ptr)[0]==p0.length);
  117. data_ptr+=sizeof(size_t);
  118. PackedData p2;
  119. p2.length=(((size_t*)data_ptr)[0]); data_ptr+=sizeof(size_t);
  120. p2.data=(void*)data_ptr; data_ptr+=p2.length;
  121. InitMultipole(p2,own_data);
  122. PackedData p1;
  123. p1.data=data_ptr;
  124. p1.length=((size_t*)data_ptr)[0];
  125. Node::Unpack(p1, own_data);
  126. }
  127. template <class Node>
  128. PackedData FMM_Node<Node>::PackMultipole(void* buff_ptr){
  129. if(fmm_data!=NULL)
  130. return fmm_data->PackMultipole(buff_ptr);
  131. else{
  132. PackedData pkd;
  133. pkd.length=0;
  134. pkd.data=buff_ptr;
  135. return pkd;
  136. }
  137. };
  138. template <class Node>
  139. void FMM_Node<Node>::AddMultipole(PackedData data){
  140. if(data.length>0){
  141. assert(fmm_data!=NULL);
  142. fmm_data->AddMultipole(data);
  143. }
  144. };
  145. template <class Node>
  146. void FMM_Node<Node>::InitMultipole(PackedData data, bool own_data){
  147. if(data.length>0){
  148. assert(fmm_data!=NULL);
  149. fmm_data->InitMultipole(data, own_data);
  150. }
  151. };
  152. template <class Node>
  153. template <class VTUData_t, class VTUNode_t>
  154. void FMM_Node<Node>::VTU_Data(VTUData_t& vtu_data, std::vector<VTUNode_t*>& nodes, int lod){
  155. typedef typename VTUData_t::VTKReal_t VTKReal_t;
  156. Node::VTU_Data(vtu_data, nodes, lod);
  157. VTUData_t src_data;
  158. VTUData_t surf_data;
  159. VTUData_t trg_data;
  160. { // Set src_data
  161. VTUData_t& new_data=src_data;
  162. new_data.value.resize(1);
  163. new_data.name.push_back("src_value");
  164. std::vector<VTKReal_t>& coord=new_data.coord;
  165. std::vector<VTKReal_t>& value=new_data.value[0];
  166. std::vector<int32_t>& connect=new_data.connect;
  167. std::vector<int32_t>& offset =new_data.offset;
  168. std::vector<uint8_t>& types =new_data.types;
  169. size_t point_cnt=0;
  170. size_t connect_cnt=0;
  171. for(size_t nid=0;nid<nodes.size();nid++){
  172. VTUNode_t* n=nodes[nid];
  173. if(n->IsGhost() || !n->IsLeaf()) continue;
  174. for(size_t i=0;i<n->src_coord.Dim();i+=3){
  175. coord.push_back(n->src_coord[i+0]);
  176. coord.push_back(n->src_coord[i+1]);
  177. coord.push_back(n->src_coord[i+2]);
  178. connect_cnt++;
  179. connect.push_back(point_cnt);
  180. offset.push_back(connect_cnt);
  181. types.push_back(1);
  182. point_cnt++;
  183. }
  184. for(size_t i=0;i<n->src_value.Dim();i++){
  185. value.push_back(n->src_value[i]);
  186. }
  187. }
  188. }
  189. { // Set surf_data
  190. VTUData_t& new_data=surf_data;
  191. new_data.value.resize(1);
  192. new_data.name.push_back("surf_value");
  193. std::vector<VTKReal_t>& coord=new_data.coord;
  194. std::vector<VTKReal_t>& value=new_data.value[0];
  195. std::vector<int32_t>& connect=new_data.connect;
  196. std::vector<int32_t>& offset =new_data.offset;
  197. std::vector<uint8_t>& types =new_data.types;
  198. size_t point_cnt=0;
  199. size_t connect_cnt=0;
  200. for(size_t nid=0;nid<nodes.size();nid++){
  201. VTUNode_t* n=nodes[nid];
  202. if(n->IsGhost() || !n->IsLeaf()) continue;
  203. for(size_t i=0;i<n->surf_coord.Dim();i+=3){
  204. coord.push_back(n->surf_coord[i+0]);
  205. coord.push_back(n->surf_coord[i+1]);
  206. coord.push_back(n->surf_coord[i+2]);
  207. connect_cnt++;
  208. connect.push_back(point_cnt);
  209. offset.push_back(connect_cnt);
  210. types.push_back(1);
  211. point_cnt++;
  212. }
  213. for(size_t i=0;i<n->surf_value.Dim();i++){
  214. value.push_back(n->surf_value[i]);
  215. }
  216. }
  217. }
  218. { // Set trg_data
  219. VTUData_t& new_data=trg_data;
  220. new_data.value.resize(1);
  221. new_data.name.push_back("trg_value");
  222. std::vector<VTKReal_t>& coord=new_data.coord;
  223. std::vector<VTKReal_t>& value=new_data.value[0];
  224. std::vector<int32_t>& connect=new_data.connect;
  225. std::vector<int32_t>& offset =new_data.offset;
  226. std::vector<uint8_t>& types =new_data.types;
  227. size_t point_cnt=0;
  228. size_t connect_cnt=0;
  229. for(size_t nid=0;nid<nodes.size();nid++){
  230. VTUNode_t* n=nodes[nid];
  231. if(n->IsGhost() || !n->IsLeaf()) continue;
  232. for(size_t i=0;i<n->trg_coord.Dim();i+=3){
  233. coord.push_back(n->trg_coord[i+0]);
  234. coord.push_back(n->trg_coord[i+1]);
  235. coord.push_back(n->trg_coord[i+2]);
  236. connect_cnt++;
  237. connect.push_back(point_cnt);
  238. offset.push_back(connect_cnt);
  239. types.push_back(1);
  240. point_cnt++;
  241. }
  242. for(size_t i=0;i<n->trg_value.Dim();i++){
  243. value.push_back(n->trg_value[i]);
  244. }
  245. }
  246. }
  247. AppendVTUData(vtu_data, src_data);
  248. AppendVTUData(vtu_data, surf_data);
  249. AppendVTUData(vtu_data, trg_data);
  250. }
  251. }//end namespace