doc: Add serial to list of ci file reserved words
[charm.git] / examples / pose / LBSim / topology.C
1 /**
2  * \addtogroup CkLdb
3 */
4 /*@{*/
5
6 #ifndef _TOPOLOGY_C_
7 #define _TOPOLOGY_C_
8
9 #include <math.h>
10
11 //#include "LBDatabase.h"
12 //#include "charm.h"
13 #include "cklists.h"
14 #include "topology.h"
15 #include "typedefs.h"
16
17 // ring
18
19 LBTOPO_MACRO(LBTopo_ring);
20
21 int LBTopo_ring::max_neighbors()
22 {
23   if (npes > 2) return 2;
24   else return (npes-1);
25 }
26
27 void LBTopo_ring::neighbors(int mype, int* _n, int &nb)
28 {
29   nb = 0;
30   if (npes>1) _n[nb++] = (mype + npes -1) % npes;
31   if (npes>2) _n[nb++] = (mype + 1) % npes;
32 }
33
34 //  TORUS 2D
35
36 LBTOPO_MACRO(LBTopo_torus2d);
37
38 LBTopo_torus2d::LBTopo_torus2d(int p): LBTopology(p) 
39 {
40   width = (int)sqrt(p*1.0);
41   if (width * width < npes) width++;
42 }
43
44 int LBTopo_torus2d::max_neighbors()
45 {
46   return 4;
47 }
48
49 int LBTopo_torus2d::goodcoor(int x, int y)
50 {
51   if (x<0 || x>=width) return -1;
52   if (y<0 || y>=width) return -1;
53   int next = x*width + y;
54   if (next<npes && next>=0) return next;
55   return -1;
56 }
57
58 static int checkuniq(int *arr, int nb, int val) {
59   for (int i=0;i<nb;i++) if (arr[i]==val) return 0;
60   return 1;
61 }
62
63 void LBTopo_torus2d::neighbors(int mype, int* _n, int &nb)
64 {
65   int next;
66   int x = mype/width;
67   int y = mype%width;
68   nb=0;
69   for (int i=-1; i<=1; i+=2) {
70     int x1 = x+i;
71     if (x1 == -1) {
72       x1 = width-1;
73       while (goodcoor(x1, y)==-1) x1--;
74     }
75     else if (goodcoor(x1, y) == -1) x1=0;
76     next = goodcoor(x1, y);
77     //CmiAssert(next != -1);
78     if (next != mype && checkuniq(_n, nb, next)) _n[nb++] = next;
79
80     int y1 = y+i;
81     if (y1 == -1) {
82       y1 = width-1;
83       while (goodcoor(x, y1)==-1) y1--;
84     }
85     else if (goodcoor(x, y1) == -1) y1=0;
86     next = goodcoor(x, y1);
87     //CmiAssert(next != -1);
88     if (next != mype && checkuniq(_n, nb, next)) _n[nb++] = next;
89   }
90 }
91
92
93 //  TORUS 3D
94
95 LBTOPO_MACRO(LBTopo_torus3d);
96
97 LBTopo_torus3d::LBTopo_torus3d(int p): LBTopology(p) 
98 {
99   width = 1;
100   while ( (width+1) * (width+1) * (width+1) <= npes) width++;
101   if (width * width * width < npes) width++;
102 }
103
104 int LBTopo_torus3d::max_neighbors()
105 {
106   return 6;
107 }
108
109 int LBTopo_torus3d::goodcoor(int x, int y, int z)
110 {
111   if (x<0 || x>=width) return -1;
112   if (y<0 || y>=width) return -1;
113   if (z<0 || z>=width) return -1;
114   int next = x*width*width + y*width + z;
115   if (next<npes && next>=0) return next;
116   return -1;
117 }
118
119 void LBTopo_torus3d::neighbors(int mype, int* _n, int &nb)
120 {
121   int x = mype/(width*width);
122   int k = mype%(width*width);
123   int y = k/width;
124   int z = k%width;
125   int next;
126   nb=0;
127   for (int i=-1; i<=1; i+=2) {
128     int x1 = x+i;
129     if (x1 == -1) {
130       x1 = width-1;
131       while (goodcoor(x1, y, z)==-1) x1--;
132     }
133     else if (goodcoor(x1, y, z) == -1) x1=0;
134     next = goodcoor(x1, y, z);
135     //CmiAssert(next != -1);
136     if (next != mype && checkuniq(_n, nb, next)) _n[nb++] = next;
137
138     int y1 = y+i;
139     if (y1 == -1) {
140       y1 = width-1;
141       while (goodcoor(x, y1, z)==-1) y1--;
142     }
143     else if (goodcoor(x, y1, z) == -1) y1=0;
144     next = goodcoor(x, y1, z);
145     //CmiAssert(next != -1);
146     if (next != mype && checkuniq(_n, nb, next)) _n[nb++] = next;
147
148     int z1 = z+i;
149     if (z1 == -1) {
150       z1 = width-1;
151       while (goodcoor(x, y, z1)==-1) z1--;
152     }
153     else if (goodcoor(x, y, z1) == -1) z1=0;
154     next = goodcoor(x, y, z1);
155     //CmiAssert(next != -1);
156     if (next != mype && checkuniq(_n, nb, next)) _n[nb++] = next;
157   }
158 }
159
160 // dense graph
161
162 LBTOPO_MACRO(LBTopo_graph);
163
164 int LBTopo_graph::max_neighbors()
165 {
166   return (int)(1.0 + (log10(1.0*CmiNumPes())/log10(2.0)));
167 }
168
169 extern "C" void gengraph(int, int, int, int *, int *, int, int);
170
171 void LBTopo_graph::neighbors(int mype, int* na, int &nb)
172 {
173   gengraph(CmiNumPes(), (int)(1.0 + (log10(1.0*CmiNumPes())/log10(2.0))), 234, na, &nb, 0,mype);
174 }
175
176
177
178 //  TORUS ND 
179 //  added by zshao1
180
181
182 template <int dimension>
183 class LBTopo_torus_nd: public LBTopology {
184 private:
185   // inherited int npes;
186   int* Cardinality;
187   int VirtualProcessorCount;
188   int* TempCo;
189 private:
190   int GetNeighborID(int ProcessorID, int number) {
191     CmiAssert(number>=0 && number<max_neighbors());
192     CmiAssert(ProcessorID>=0 && ProcessorID<npes);
193     get_processor_coordinates(ProcessorID, TempCo);
194
195     int index = number/2;
196     int displacement = (number%2)? -1: 1;
197     do{
198       TempCo[index] = (TempCo[index] + displacement + Cardinality[index]) % Cardinality[index];
199       get_processor_id(TempCo, &ProcessorID);
200     } while (ProcessorID >= npes);
201     return ProcessorID;
202   }
203 public:
204   LBTopo_torus_nd(int p): LBTopology(p) /*inherited :npes(p) */ 
205   {  int i;
206     CmiAssert(dimension>=1 && dimension<=16);
207     CmiAssert(p>=1);
208
209     Cardinality = new int[dimension];
210     TempCo = new int[dimension];
211     double pp = p;
212     for(i=0;i<dimension;i++) {
213       Cardinality[i] = (int)ceil(pow(pp,1.0/(dimension-i))-1e-5);
214       pp = pp / Cardinality[i];
215     }
216     VirtualProcessorCount = 1;
217     for(i=0;i<dimension;i++) {
218       VirtualProcessorCount *= Cardinality[i];
219     }
220   }
221   ~LBTopo_torus_nd() {
222     delete[] Cardinality;
223     delete[] TempCo;
224   }
225   virtual int max_neighbors() {
226     return dimension*2;
227   }
228   virtual void neighbors(int mype, int* _n, int &nb) {
229     nb = 0;
230     for(int i=0;i<dimension*2;i++) {
231       _n[nb] = GetNeighborID(mype, i);
232       if (_n[nb]!=mype && (nb==0 || _n[nb-1]!=_n[nb]) ) nb++;
233     }
234   }
235   virtual int get_dimension() {
236     return dimension;
237   }
238   virtual bool get_processor_coordinates(int processor_id, int* processor_coordinates) {
239     CmiAssert(processor_id>=0 && processor_id<VirtualProcessorCount);
240     CmiAssert( processor_coordinates != NULL );
241     for(int i=0;i<dimension;i++) {
242       processor_coordinates[i] = processor_id % Cardinality[i];
243       processor_id = processor_id / Cardinality[i];
244     }
245     return true;
246   }
247   virtual bool get_processor_id(const int* processor_coordinates, int* processor_id) {
248     int i;
249     CmiAssert( processor_coordinates != NULL );
250     CmiAssert( processor_id != NULL );
251     for(i=dimension-1;i>=0;i--) 
252       CmiAssert( 0<=processor_coordinates[i] && processor_coordinates[i]<Cardinality[i]);
253     (*processor_id) = 0;
254     for(i=dimension-1;i>=0;i--) {
255       (*processor_id) = (*processor_id)* Cardinality[i] + processor_coordinates[i];
256     }
257     return true;
258   }
259   //Note: if abs(difference)*2 = cardinality, the difference is set to zero
260   virtual bool coordinate_difference(const int* my_coordinates, const int* target_coordinates, int* difference) { 
261 //    CkPrintf("[%d] coordiate_difference begin\n", CkMyPe());
262     CmiAssert( my_coordinates != NULL);
263     CmiAssert( target_coordinates != NULL);
264     CmiAssert( difference != NULL);
265 //    CkPrintf("[%d] after assert\n", CkMyPe());
266     for(int i=0;i<dimension;i++) {
267 //      CkPrintf("[%d] coordiate_difference iteration %d\n", i);
268       difference[i] = target_coordinates[i] - my_coordinates[i];
269       if (abs(difference[i])*2 > Cardinality[i]) {
270         difference[i] += (difference[i]>0) ? -Cardinality[i] : Cardinality[i];
271       } else if (abs(difference[i])*2 == Cardinality[i]) {
272         difference[i] = 0;
273       }
274     }
275 //    CkPrintf("[%d] coordiate_difference just before return\n");
276     return true;
277   }
278   //Note: if abs(difference)*2 = cardinality, the difference is set to zero
279   virtual bool coordinate_difference(int my_processor_id, int target_processor_id, int* difference) { 
280     CmiAssert( difference != NULL);
281     int my_coordinates[dimension];
282     int target_coordinates[dimension];
283     get_processor_coordinates(my_processor_id, my_coordinates);
284     get_processor_coordinates(target_processor_id, target_coordinates);
285     coordinate_difference(my_coordinates, target_coordinates, difference);
286     return true;
287   }
288 };
289
290 typedef LBTopo_torus_nd<1> LBTopo_torus_nd_1;
291 typedef LBTopo_torus_nd<2> LBTopo_torus_nd_2;
292 typedef LBTopo_torus_nd<3> LBTopo_torus_nd_3;
293 typedef LBTopo_torus_nd<4> LBTopo_torus_nd_4;
294 typedef LBTopo_torus_nd<5> LBTopo_torus_nd_5;
295 typedef LBTopo_torus_nd<6> LBTopo_torus_nd_6;
296 typedef LBTopo_torus_nd<7> LBTopo_torus_nd_7;
297
298 LBTOPO_MACRO(LBTopo_torus_nd_1);
299 LBTOPO_MACRO(LBTopo_torus_nd_2);
300 LBTOPO_MACRO(LBTopo_torus_nd_3);
301 LBTOPO_MACRO(LBTopo_torus_nd_4);
302 LBTOPO_MACRO(LBTopo_torus_nd_5);
303 LBTOPO_MACRO(LBTopo_torus_nd_6);
304 LBTOPO_MACRO(LBTopo_torus_nd_7);
305
306
307 // complete graph
308
309 class LBTopo_complete: public LBTopology {
310 public:
311   LBTopo_complete(int p): LBTopology(p) {}
312   int max_neighbors() {
313     return npes - 1;
314   }
315   void neighbors(int mype, int* _n, int &nb) {
316     nb = 0;
317     for (int i=0; i<npes; i++)  if (mype != i) _n[nb++] = i;
318   }
319 };
320
321 LBTOPO_MACRO(LBTopo_complete);
322
323 class LBTopoMap {
324 public:
325   char *name;
326   LBtopoFn fn;
327   LBTopoMap(char *s, LBtopoFn f): name(s), fn(f) {}
328 };
329
330
331 class LBTopoVec {
332   CkVec<LBTopoMap *> lbTopos;
333 public:
334   LBTopoVec() {
335     // register all topos
336     lbTopos.push_back(new LBTopoMap("ring", createLBTopo_ring));
337     lbTopos.push_back(new LBTopoMap("torus2d", createLBTopo_torus2d));
338     lbTopos.push_back(new LBTopoMap("torus3d", createLBTopo_torus3d));
339     lbTopos.push_back(new LBTopoMap("torus_nd_1", createLBTopo_torus_nd_1));
340     lbTopos.push_back(new LBTopoMap("torus_nd_2", createLBTopo_torus_nd_2));
341     lbTopos.push_back(new LBTopoMap("torus_nd_3", createLBTopo_torus_nd_3));
342     lbTopos.push_back(new LBTopoMap("torus_nd_4", createLBTopo_torus_nd_4));
343     lbTopos.push_back(new LBTopoMap("torus_nd_5", createLBTopo_torus_nd_5));
344     lbTopos.push_back(new LBTopoMap("torus_nd_6", createLBTopo_torus_nd_6));
345     lbTopos.push_back(new LBTopoMap("torus_nd_7", createLBTopo_torus_nd_7));
346     lbTopos.push_back(new LBTopoMap("graph", createLBTopo_graph));
347     lbTopos.push_back(new LBTopoMap("complete", createLBTopo_complete));
348   }
349   ~LBTopoVec() {
350     for (int i=0; i<lbTopos.length(); i++)
351       delete lbTopos[i];
352   }
353   void push_back(LBTopoMap *map) { lbTopos.push_back(map); }
354   int length() { return lbTopos.length(); }
355   LBTopoMap * operator[](size_t n) { return lbTopos[n]; }
356   void print() {
357     for (int i=0; i<lbTopos.length(); i++) {
358       CmiPrintf("  %s\n", lbTopos[i]->name);
359     }
360   }
361 };
362
363 static LBTopoVec lbTopoMap;
364
365 extern "C"
366 LBtopoFn LBTopoLookup(char *name)
367 {
368   //printf("maplen: %d\n",lbTopoMap.length());
369   for (int i=0; i<lbTopoMap.length(); i++) {
370     if (strcmp(name, lbTopoMap[i]->name)==0) return lbTopoMap[i]->fn;
371   }
372   return NULL;
373 }
374
375 // C wrapper functions
376 /*extern "C" void getTopoNeighbors(void *topo, int myid, int* narray, int *n)
377 {
378   ((LBTopology*)topo)->neighbors(myid, narray, *n);
379 }
380
381 extern "C" int getTopoMaxNeighbors(void *topo)
382 {
383   return ((LBTopology*)topo)->max_neighbors();
384 }
385
386 extern "C" void printoutTopo()
387 {
388   for (int i=0; i<lbTopoMap.length(); i++) {
389     CmiPrintf("  %s\n", lbTopoMap[i]->name);
390   }
391 }
392 */
393
394 #endif