make_set.c.svn-base 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. //---------------------------------------------------------------------
  2. //
  3. // Copyright 2010 Intel Corporation
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. //---------------------------------------------------------------------
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <math.h>
  21. #include "header.h"
  22. #include "mpinpb.h"
  23. #define mod(p,q) ((p)%(q))
  24. #define max(x,y) ((x)>(y)? (x) : (y))
  25. #define min(x,y) ((x)<(y)? (x) : (y))
  26. void make_set() {
  27. //---------------------------------------------------------------------
  28. //---------------------------------------------------------------------
  29. //---------------------------------------------------------------------
  30. // This function allocates space for a set of cells and fills the set
  31. // such that communication between cells on different nodes is only
  32. // nearest neighbor
  33. //---------------------------------------------------------------------
  34. int p, i, j, c, dir, size, excess, ierr,ierrcode;
  35. //---------------------------------------------------------------------
  36. // compute square root; add small number to allow for roundoff
  37. // (note: this is computed in setup_mpi.f also, but prefer to do
  38. // it twice because of some include file problems).
  39. //---------------------------------------------------------------------
  40. ncells = (int)(sqrt((double)(no_nodes) + 0.00001e0));
  41. //---------------------------------------------------------------------
  42. // this makes coding easier
  43. //---------------------------------------------------------------------
  44. p = ncells;
  45. //---------------------------------------------------------------------
  46. // determine the location of the cell at the bottom of the 3D
  47. // array of cells
  48. //---------------------------------------------------------------------
  49. cell_coord(1,1) = mod(node,p) ;
  50. cell_coord(2,1) = node/p ;
  51. cell_coord(3,1) = 0;
  52. //---------------------------------------------------------------------
  53. // set the cell_coords for cells in the rest of the z-layers;
  54. // this comes down to a simple linear numbering in the z-direct-
  55. // ion, and to the doubly-cyclic numbering in the other dirs
  56. //---------------------------------------------------------------------
  57. for (c = 2; c <= p; c++) {
  58. cell_coord(1,c) = mod(cell_coord(1,c-1)+1,p) ;
  59. cell_coord(2,c) = mod(cell_coord(2,c-1)-1+p,p) ;
  60. cell_coord(3,c) = c-1;
  61. }
  62. //---------------------------------------------------------------------
  63. // offset all the coordinates by 1 to adjust for Fortran arrays
  64. //---------------------------------------------------------------------
  65. for (dir = 1; dir <= 3; dir++) {
  66. for (c = 1; c <= p; c++) {
  67. cell_coord(dir,c) = cell_coord(dir,c) + 1;
  68. }
  69. }
  70. //---------------------------------------------------------------------
  71. // slice(dir,n) contains the sequence number of the cell that is in
  72. // coordinate plane n in the dir direction
  73. //---------------------------------------------------------------------
  74. for (dir = 1; dir <= 3; dir++) {
  75. for (c = 1; c <= p; c++) {
  76. slice(dir,cell_coord(dir,c)) = c;
  77. }
  78. }
  79. //---------------------------------------------------------------------
  80. // fill the predecessor and successor entries, using the indices
  81. // of the bottom cells (they are the same at each level of k
  82. // anyway) acting as if full periodicity pertains; note that p is
  83. // added to those arguments to the mod functions that might
  84. // otherwise return wrong values when using the modulo function
  85. //---------------------------------------------------------------------
  86. i = cell_coord(1,1)-1;
  87. j = cell_coord(2,1)-1;
  88. predecessor(1) = mod(i-1+p,p) + p*j;
  89. predecessor(2) = i + p*mod(j-1+p,p);
  90. predecessor(3) = mod(i+1,p) + p*mod(j-1+p,p);
  91. successor(1) = mod(i+1,p) + p*j;
  92. successor(2) = i + p*mod(j+1,p);
  93. successor(3) = mod(i-1+p,p) + p*mod(j+1,p);
  94. //---------------------------------------------------------------------
  95. // now compute the sizes of the cells
  96. //---------------------------------------------------------------------
  97. for (dir = 1; dir <= 3; dir++) {
  98. //---------------------------------------------------------------------
  99. // set cell_coord range for each direction
  100. //---------------------------------------------------------------------
  101. size = grid_points(dir)/p;
  102. excess = mod(grid_points(dir),p);
  103. for (c = 1; c <= ncells; c++) {
  104. if (cell_coord(dir,c) <= excess) {
  105. cell_size(dir,c) = size+1;
  106. cell_low(dir,c) = (cell_coord(dir,c)-1)*(size+1);
  107. cell_high(dir,c) = cell_low(dir,c)+size;
  108. } else {
  109. cell_size(dir,c) = size;
  110. cell_low(dir,c) = excess*(size+1)+
  111. (cell_coord(dir,c)-excess-1)*size;
  112. cell_high(dir,c) = cell_low(dir,c)+size-1;
  113. }
  114. if (cell_size(dir, c) <= 2) {
  115. printf(" Error: Cell size too small. Min size is 3\n");
  116. ierrcode = 1;
  117. exit(1);
  118. }
  119. }
  120. }
  121. return;
  122. }
  123. //---------------------------------------------------------------------
  124. //---------------------------------------------------------------------
  125. void make_color() {
  126. //---------------------------------------------------------------------
  127. //---------------------------------------------------------------------
  128. //---------------------------------------------------------------------
  129. // This function determines cycles in the communication graphs in
  130. // the six coordinate directions, and colors the ranks so they know
  131. // how to construct deadlock-free blocking communication schedules
  132. //---------------------------------------------------------------------
  133. int p, i, j, dir, node_loc, comm_color, node_min, length, start_found;
  134. //---------------------------------------------------------------------
  135. // compute square root; add small number to allow for roundoff
  136. // (note: this is computed in setup_mpi.f also, but prefer to do
  137. // it twice because of some include file problems).
  138. //---------------------------------------------------------------------
  139. ncells = (int)(sqrt((double)(no_nodes) + 0.00001e0));
  140. //---------------------------------------------------------------------
  141. // this makes coding easier
  142. //---------------------------------------------------------------------
  143. p = ncells;
  144. for (dir = 0; dir<6; dir++) {
  145. node_loc = node_min = node; length = 1; start_found = 0;
  146. while (!start_found) {
  147. i = mod(node_loc,p) ;
  148. j = node_loc/p ;
  149. switch (dir) {
  150. case (WESTDIR): node_loc = mod(i-1+p,p) + p*j; break;
  151. case (EASTDIR): node_loc = mod(i+1,p) + p*j; break;
  152. case (SOUTHDIR): node_loc = i + p*mod(j-1+p,p); break;
  153. case (NORTHDIR): node_loc = i + p*mod(j+1,p); break;
  154. case (BOTTOMDIR): node_loc = mod(i+1,p) + p*mod(j-1+p,p); break;
  155. case (TOPDIR): node_loc = mod(i-1+p,p) + p*mod(j+1,p); break;
  156. }
  157. // the next block ensures that the node with the lowest rank
  158. // in this cycle is colored WHITE (=0), and that nodes an even
  159. // number of jumps removed from that lowest-ranked member
  160. // are also white. The others are RED (1).
  161. if (node_loc <= node_min) {
  162. node_min = node_loc;
  163. comm_color = 0;
  164. } else comm_color = !comm_color;
  165. if (node_loc == node) start_found = 1;
  166. else length++;
  167. }
  168. send_color[dir] = comm_color;
  169. recv_color[dir] = !send_color[dir];
  170. // if the number of nodes in this cycle is odd, we need to treat the
  171. // last node before the "start" of the cycle differently
  172. if (length%2) {
  173. if (node == node_min) recv_color[dir] = 2;
  174. i = mod(node,p) ;
  175. j = node/p ;
  176. switch (dir) {
  177. case (WESTDIR): node_loc = mod(i-1+p,p) + p*j; break;
  178. case (EASTDIR): node_loc = mod(i+1,p) + p*j; break;
  179. case (SOUTHDIR): node_loc = i + p*mod(j-1+p,p); break;
  180. case (NORTHDIR): node_loc = i + p*mod(j+1,p); break;
  181. case (BOTTOMDIR): node_loc = mod(i+1,p) + p*mod(j-1+p,p); break;
  182. case (TOPDIR): node_loc = mod(i-1+p,p) + p*mod(j+1,p); break;
  183. }
  184. if (node_loc == node_min) send_color[dir] = 2;
  185. }
  186. }
  187. return;
  188. }
  189. //---------------------------------------------------------------------
  190. //---------------------------------------------------------------------