interac_list.txx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /**
  2. * \file interac_list.txx
  3. * \author Dhairya Malhotra, dhairya.malhotra@gmail.com
  4. * \date 6-11-2012
  5. * \brief This file contains the implementation of the InteracList class.
  6. * Handles the logic for different interaction lists, and determines the
  7. * symmetry class for each interaction.
  8. */
  9. #include <math.h>
  10. #include <algorithm>
  11. #include <tree_node.hpp>
  12. #include <precomp_mat.hpp>
  13. #include <ompUtils.h>
  14. namespace pvfmm{
  15. /**
  16. * \brief Initialize.
  17. */
  18. template <class Node_t>
  19. void InteracList<Node_t>::Initialize(unsigned int dim_, PrecompMat<Real_t>* mat_){
  20. dim=dim_;
  21. assert(dim==3); //Only supporting 3D for now.
  22. mat=mat_;
  23. class_count.resize(Type_Count);
  24. interac_class.resize(Type_Count);
  25. perm_list.resize(Type_Count);
  26. rel_coord.resize(Type_Count);
  27. hash_lut.resize(Type_Count);
  28. InitList(0,0,1,UC2UE_Type);
  29. InitList(0,0,1,DC2DE_Type);
  30. InitList(0,0,1,S2U_Type);
  31. InitList(1,1,2,U2U_Type);
  32. InitList(1,1,2,D2D_Type);
  33. InitList(0,0,1,D2T_Type);
  34. InitList(3,3,2,U0_Type);
  35. InitList(1,0,1,U1_Type);
  36. InitList(3,3,2,U2_Type);
  37. InitList(3,2,1,V_Type);
  38. InitList(1,1,1,V1_Type);
  39. InitList(5,5,2,W_Type);
  40. InitList(5,5,2,X_Type);
  41. InitList(0,0,1,BC_Type);
  42. }
  43. /**
  44. * \brief Number of possible interactions in each list.
  45. */
  46. template <class Node_t>
  47. size_t InteracList<Node_t>::ListCount(Mat_Type t){
  48. return rel_coord[t].Dim(0);
  49. }
  50. /**
  51. * \brief Returns the relative octant coordinates for an interaction i of
  52. * type t.
  53. */
  54. template <class Node_t>
  55. int* InteracList<Node_t>::RelativeCoord(Mat_Type t, size_t i){
  56. return rel_coord[t][i];
  57. }
  58. /**
  59. * \brief For an interaction of type t and index i, returns the symmetry
  60. * class for the same.
  61. */
  62. template <class Node_t>
  63. size_t InteracList<Node_t>::InteracClass(Mat_Type t, size_t i){
  64. return interac_class[t][i];
  65. }
  66. /**
  67. * \brief Returns the list of permutations to be applied to the matrix to
  68. * convert it to its interac_class.
  69. */
  70. template <class Node_t>
  71. std::vector<Perm_Type>& InteracList<Node_t>::PermutList(Mat_Type t, size_t i){
  72. return perm_list[t][i];
  73. }
  74. /**
  75. * \brief Build interaction list for this node.
  76. */
  77. template <class Node_t>
  78. std::vector<Node_t*> InteracList<Node_t>::BuildList(Node_t* n, Mat_Type t){
  79. std::vector<Node_t*> interac_list(ListCount(t),NULL);
  80. int n_collg=(int)pow(3,dim);
  81. int n_child=(int)pow(2,dim);
  82. int rel_coord[3];
  83. switch (t){
  84. case S2U_Type:
  85. {
  86. if(!n->IsGhost() && n->IsLeaf()) interac_list[0]=n;
  87. break;
  88. }
  89. case U2U_Type:
  90. {
  91. if(n->IsGhost() || n->IsLeaf()) return interac_list;
  92. for(int j=0;j<n_child;j++){
  93. rel_coord[0]=-1+(j & 1?2:0);
  94. rel_coord[1]=-1+(j & 2?2:0);
  95. rel_coord[2]=-1+(j & 4?2:0);
  96. int c_hash = coord_hash(rel_coord);
  97. int idx=hash_lut[t][c_hash];
  98. Node_t* chld=(Node_t*)n->Child(j);
  99. if(idx>=0 && !chld->IsGhost()) interac_list[idx]=chld;
  100. }
  101. break;
  102. }
  103. case D2D_Type:
  104. {
  105. if(n->IsGhost() || n->Parent()==NULL) return interac_list;
  106. Node_t* p=(Node_t*)n->Parent();
  107. int p2n=n->Path2Node();
  108. {
  109. rel_coord[0]=-1+(p2n & 1?2:0);
  110. rel_coord[1]=-1+(p2n & 2?2:0);
  111. rel_coord[2]=-1+(p2n & 4?2:0);
  112. int c_hash = coord_hash(rel_coord);
  113. int idx=hash_lut[t][c_hash];
  114. if(idx>=0) interac_list[idx]=p;
  115. }
  116. break;
  117. }
  118. case D2T_Type:
  119. {
  120. if(!n->IsGhost() && n->IsLeaf()) interac_list[0]=n;
  121. break;
  122. }
  123. case U0_Type:
  124. {
  125. if(n->IsGhost() || n->Parent()==NULL || !n->IsLeaf()) return interac_list;
  126. Node_t* p=(Node_t*)n->Parent();
  127. int p2n=n->Path2Node();
  128. for(int i=0;i<n_collg;i++){
  129. Node_t* pc=(Node_t*)p->Colleague(i);
  130. if(pc!=NULL && pc->IsLeaf()){
  131. rel_coord[0]=( i %3)*4-4-(p2n & 1?2:0)+1;
  132. rel_coord[1]=((i/3)%3)*4-4-(p2n & 2?2:0)+1;
  133. rel_coord[2]=((i/9)%3)*4-4-(p2n & 4?2:0)+1;
  134. int c_hash = coord_hash(rel_coord);
  135. int idx=hash_lut[t][c_hash];
  136. if(idx>=0) interac_list[idx]=pc;
  137. }
  138. }
  139. break;
  140. }
  141. case U1_Type:
  142. {
  143. if(n->IsGhost() || !n->IsLeaf()) return interac_list;
  144. for(int i=0;i<n_collg;i++){
  145. Node_t* col=(Node_t*)n->Colleague(i);
  146. if(col!=NULL && col->IsLeaf()){
  147. rel_coord[0]=( i %3)-1;
  148. rel_coord[1]=((i/3)%3)-1;
  149. rel_coord[2]=((i/9)%3)-1;
  150. int c_hash = coord_hash(rel_coord);
  151. int idx=hash_lut[t][c_hash];
  152. if(idx>=0) interac_list[idx]=col;
  153. }
  154. }
  155. break;
  156. }
  157. case U2_Type:
  158. {
  159. if(n->IsGhost() || !n->IsLeaf()) return interac_list;
  160. for(int i=0;i<n_collg;i++){
  161. Node_t* col=(Node_t*)n->Colleague(i);
  162. if(col!=NULL && !col->IsLeaf()){
  163. for(int j=0;j<n_child;j++){
  164. rel_coord[0]=( i %3)*4-4+(j & 1?2:0)-1;
  165. rel_coord[1]=((i/3)%3)*4-4+(j & 2?2:0)-1;
  166. rel_coord[2]=((i/9)%3)*4-4+(j & 4?2:0)-1;
  167. int c_hash = coord_hash(rel_coord);
  168. int idx=hash_lut[t][c_hash];
  169. if(idx>=0){
  170. assert(col->Child(j)->IsLeaf()); //2:1 balanced
  171. interac_list[idx]=(Node_t*)col->Child(j);
  172. }
  173. }
  174. }
  175. }
  176. break;
  177. }
  178. case V_Type:
  179. {
  180. if(n->IsGhost() || n->Parent()==NULL) return interac_list;
  181. Node_t* p=(Node_t*)n->Parent();
  182. int p2n=n->Path2Node();
  183. for(int i=0;i<n_collg;i++){
  184. Node_t* pc=(Node_t*)p->Colleague(i);
  185. if(pc!=NULL?!pc->IsLeaf():0){
  186. for(int j=0;j<n_child;j++){
  187. rel_coord[0]=( i %3)*2-2+(j & 1?1:0)-(p2n & 1?1:0);
  188. rel_coord[1]=((i/3)%3)*2-2+(j & 2?1:0)-(p2n & 2?1:0);
  189. rel_coord[2]=((i/9)%3)*2-2+(j & 4?1:0)-(p2n & 4?1:0);
  190. int c_hash = coord_hash(rel_coord);
  191. int idx=hash_lut[t][c_hash];
  192. if(idx>=0) interac_list[idx]=(Node_t*)pc->Child(j);
  193. }
  194. }
  195. }
  196. break;
  197. }
  198. case V1_Type:
  199. {
  200. if(n->IsGhost() || n->IsLeaf()) return interac_list;
  201. for(int i=0;i<n_collg;i++){
  202. Node_t* col=(Node_t*)n->Colleague(i);
  203. if(col!=NULL && !col->IsLeaf()){
  204. rel_coord[0]=( i %3)-1;
  205. rel_coord[1]=((i/3)%3)-1;
  206. rel_coord[2]=((i/9)%3)-1;
  207. int c_hash = coord_hash(rel_coord);
  208. int idx=hash_lut[t][c_hash];
  209. if(idx>=0) interac_list[idx]=col;
  210. }
  211. }
  212. break;
  213. }
  214. case W_Type:
  215. {
  216. if(n->IsGhost() || !n->IsLeaf()) return interac_list;
  217. for(int i=0;i<n_collg;i++){
  218. Node_t* col=(Node_t*)n->Colleague(i);
  219. if(col!=NULL && !col->IsLeaf()){
  220. for(int j=0;j<n_child;j++){
  221. rel_coord[0]=( i %3)*4-4+(j & 1?2:0)-1;
  222. rel_coord[1]=((i/3)%3)*4-4+(j & 2?2:0)-1;
  223. rel_coord[2]=((i/9)%3)*4-4+(j & 4?2:0)-1;
  224. int c_hash = coord_hash(rel_coord);
  225. int idx=hash_lut[t][c_hash];
  226. if(idx>=0) interac_list[idx]=(Node_t*)col->Child(j);
  227. }
  228. }
  229. }
  230. break;
  231. }
  232. case X_Type:
  233. {
  234. if(n->IsGhost() || n->Parent()==NULL) return interac_list;
  235. Node_t* p=(Node_t*)n->Parent();
  236. int p2n=n->Path2Node();
  237. for(int i=0;i<n_collg;i++){
  238. Node_t* pc=(Node_t*)p->Colleague(i);
  239. if(pc!=NULL && pc->IsLeaf()){
  240. rel_coord[0]=( i %3)*4-4-(p2n & 1?2:0)+1;
  241. rel_coord[1]=((i/3)%3)*4-4-(p2n & 2?2:0)+1;
  242. rel_coord[2]=((i/9)%3)*4-4-(p2n & 4?2:0)+1;
  243. int c_hash = coord_hash(rel_coord);
  244. int idx=hash_lut[t][c_hash];
  245. if(idx>=0) interac_list[idx]=pc;
  246. }
  247. }
  248. break;
  249. }
  250. default:
  251. std::vector<Node_t*> empty_list;
  252. return empty_list;
  253. break;
  254. }
  255. return interac_list;
  256. }
  257. template <class Node_t>
  258. Matrix<typename Node_t::Real_t>& InteracList<Node_t>::ClassMat(int l, Mat_Type type, size_t indx){
  259. size_t indx0=InteracClass(type, indx);
  260. return mat->Mat(l, type, indx0);
  261. }
  262. template <class Node_t>
  263. Permutation<typename Node_t::Real_t>& InteracList<Node_t>::Perm_R(int l, Mat_Type type, size_t indx){
  264. size_t indx0=InteracClass(type, indx);
  265. Matrix<Real_t>& M0=mat->Mat(l, type, indx0);
  266. Permutation<Real_t>& row_perm=mat->Perm_R(type, indx);
  267. if(M0.Dim(0)==0 || M0.Dim(1)==0) return row_perm;
  268. //Get the necessary permutations.
  269. if(row_perm.Dim()==0){
  270. std::vector<Perm_Type>& p_list=PermutList(type, indx);
  271. row_perm=Permutation<Real_t>(M0.Dim(0));
  272. for(int i=p_list.size()-1; i>=0; i--){
  273. Permutation<Real_t>& pr=mat->Perm(type, R_Perm + p_list[i]);
  274. if(pr.Dim()!=M0.Dim(0)){
  275. row_perm=Permutation<Real_t>();
  276. break;
  277. }
  278. row_perm=pr.Transpose()*row_perm;
  279. }
  280. }
  281. return row_perm;
  282. }
  283. template <class Node_t>
  284. Permutation<typename Node_t::Real_t>& InteracList<Node_t>::Perm_C(int l, Mat_Type type, size_t indx){
  285. size_t indx0=InteracClass(type, indx);
  286. Matrix<Real_t>& M0=mat->Mat(l, type, indx0);
  287. Permutation<Real_t>& col_perm=mat->Perm_C(type, indx);
  288. if(M0.Dim(0)==0 || M0.Dim(1)==0) return col_perm;
  289. //Get the necessary permutations.
  290. if(col_perm.Dim()==0){
  291. std::vector<Perm_Type>& p_list=PermutList(type, indx);
  292. col_perm=Permutation<Real_t>(M0.Dim(1));
  293. for(int i=p_list.size()-1; i>=0; i--){
  294. Permutation<Real_t>& pc=mat->Perm(type, C_Perm + p_list[i]);
  295. if(pc.Dim()!=M0.Dim(1)){
  296. col_perm=Permutation<Real_t>();
  297. break;
  298. }
  299. col_perm=col_perm*pc;
  300. }
  301. }
  302. return col_perm;
  303. }
  304. /**
  305. * \brief A hash function defined on the relative coordinates of octants.
  306. */
  307. #define MAX_HASH 2000
  308. template <class Node_t>
  309. int InteracList<Node_t>::coord_hash(int* c){
  310. const int n=5;
  311. return ( (c[2]+n) * (2*n) + (c[1]+n) ) *(2*n) + (c[0]+n);
  312. }
  313. template <class Node_t>
  314. int InteracList<Node_t>::class_hash(int* c_){
  315. int c[3]={abs(c_[0]), abs(c_[1]), abs(c_[2])};
  316. if(c[1]>c[0] && c[1]>c[2])
  317. {int tmp=c[0]; c[0]=c[1]; c[1]=tmp;}
  318. if(c[0]>c[2])
  319. {int tmp=c[0]; c[0]=c[2]; c[2]=tmp;}
  320. if(c[0]>c[1])
  321. {int tmp=c[0]; c[0]=c[1]; c[1]=tmp;}
  322. assert(c[0]<=c[1] && c[1]<=c[2]);
  323. return coord_hash(&c[0]);
  324. }
  325. /**
  326. * \brief Set relative coordinates of the interacting node in
  327. * rel_coord[Type][idx][1:3].
  328. */
  329. template <class Node_t>
  330. void InteracList<Node_t>::InitList(int max_r, int min_r, int step, Mat_Type t){
  331. size_t count=(size_t)(pow((max_r*2)/step+1,dim)-(min_r>0?pow((min_r*2)/step-1,dim):0));
  332. Matrix<int>& M=rel_coord[t];
  333. M.Resize(count,dim);
  334. hash_lut[t].assign(MAX_HASH, -1);
  335. class_count[t]=0;
  336. std::vector<int> class_size_hash(MAX_HASH, 0);
  337. std::vector<int> class_disp_hash(MAX_HASH, 0);
  338. for(int k=-max_r;k<=max_r;k+=step)
  339. for(int j=-max_r;j<=max_r;j+=step)
  340. for(int i=-max_r;i<=max_r;i+=step)
  341. if(abs(i)>=min_r || abs(j)>=min_r || abs(k) >= min_r){
  342. int c[3]={i,j,k};
  343. int& idx=class_size_hash[class_hash(c)];
  344. if(idx==0) class_count[t]++;
  345. idx++;
  346. }
  347. omp_par::scan(&class_size_hash[0], &class_disp_hash[0], MAX_HASH);
  348. size_t count_=0;
  349. for(int k=-max_r;k<=max_r;k+=step)
  350. for(int j=-max_r;j<=max_r;j+=step)
  351. for(int i=-max_r;i<=max_r;i+=step)
  352. if(abs(i)>=min_r || abs(j)>=min_r || abs(k) >= min_r){
  353. int c[3]={i,j,k};
  354. int& idx=class_disp_hash[class_hash(c)];
  355. for(size_t l=0;l<dim;l++) M[idx][l]=c[l];
  356. hash_lut[t][coord_hash(c)]=idx;
  357. count_++;
  358. idx++;
  359. }
  360. assert(count_==count);
  361. interac_class[t].resize(count);
  362. perm_list[t].resize(count);
  363. std::vector<int> coord(3);
  364. for(size_t j=0;j<count;j++){
  365. if(M[j][0]<0) perm_list[t][j].push_back(ReflecX);
  366. if(M[j][1]<0) perm_list[t][j].push_back(ReflecY);
  367. if(M[j][2]<0) perm_list[t][j].push_back(ReflecZ);
  368. coord[0]=abs(M[j][0]);
  369. coord[1]=abs(M[j][1]);
  370. coord[2]=abs(M[j][2]);
  371. if(coord[1]>coord[0] && coord[1]>coord[2]){
  372. perm_list[t][j].push_back(SwapXY);
  373. int tmp=coord[0]; coord[0]=coord[1]; coord[1]=tmp;
  374. }
  375. if(coord[0]>coord[2]){
  376. perm_list[t][j].push_back(SwapXZ);
  377. int tmp=coord[0]; coord[0]=coord[2]; coord[2]=tmp;
  378. }
  379. if(coord[0]>coord[1]){
  380. perm_list[t][j].push_back(SwapXY);
  381. int tmp=coord[0]; coord[0]=coord[1]; coord[1]=tmp;
  382. }
  383. assert(coord[0]<=coord[1] && coord[1]<=coord[2]);
  384. int c_hash = coord_hash(&coord[0]);
  385. interac_class[t][j]=hash_lut[t][c_hash];
  386. }
  387. }
  388. #undef MAX_HASH
  389. }//end namespace