00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <math.h>
00005 #include <mpi.h>
00006
00007 #include "allvars.h"
00008 #include "proto.h"
00009
00019 static struct peano_hilbert_data
00020 {
00021 peanokey key;
00022 int index;
00023 }
00024 *mp;
00025
00026 static int *Id;
00027
00028
00034 void peano_hilbert_order(void)
00035 {
00036 int i;
00037
00038 if(ThisTask == 0)
00039 printf("begin Peano-Hilbert order...\n");
00040
00041 if(N_gas)
00042 {
00043 mp = malloc(sizeof(struct peano_hilbert_data) * N_gas);
00044 Id = malloc(sizeof(int) * N_gas);
00045
00046 for(i = 0; i < N_gas; i++)
00047 {
00048 mp[i].index = i;
00049 mp[i].key = Key[i];
00050 }
00051
00052 qsort(mp, N_gas, sizeof(struct peano_hilbert_data), compare_key);
00053
00054 for(i = 0; i < N_gas; i++)
00055 Id[mp[i].index] = i;
00056
00057 reorder_gas();
00058
00059 free(Id);
00060 free(mp);
00061 }
00062
00063
00064 if(NumPart - N_gas > 0)
00065 {
00066 mp = malloc(sizeof(struct peano_hilbert_data) * (NumPart - N_gas));
00067 mp -= (N_gas);
00068
00069 Id = malloc(sizeof(int) * (NumPart - N_gas));
00070 Id -= (N_gas);
00071
00072 for(i = N_gas; i < NumPart; i++)
00073 {
00074 mp[i].index = i;
00075 mp[i].key = Key[i];
00076 }
00077
00078 qsort(mp + N_gas, NumPart - N_gas, sizeof(struct peano_hilbert_data), compare_key);
00079
00080 for(i = N_gas; i < NumPart; i++)
00081 Id[mp[i].index] = i;
00082
00083 reorder_particles();
00084
00085 Id += N_gas;
00086 free(Id);
00087 mp += N_gas;
00088 free(mp);
00089 }
00090
00091 if(ThisTask == 0)
00092 printf("Peano-Hilbert done.\n");
00093 }
00094
00095
00098 int compare_key(const void *a, const void *b)
00099 {
00100 if(((struct peano_hilbert_data *) a)->key < (((struct peano_hilbert_data *) b)->key))
00101 return -1;
00102
00103 if(((struct peano_hilbert_data *) a)->key > (((struct peano_hilbert_data *) b)->key))
00104 return +1;
00105
00106 return 0;
00107 }
00108
00109
00117 void reorder_gas(void)
00118 {
00119 int i;
00120 struct particle_data Psave, Psource;
00121 struct sph_particle_data SphPsave, SphPsource;
00122 int idsource, idsave, dest;
00123
00124 for(i = 0; i < N_gas; i++)
00125 {
00126 if(Id[i] != i)
00127 {
00128 Psource = P[i];
00129 SphPsource = SphP[i];
00130
00131 idsource = Id[i];
00132 dest = Id[i];
00133
00134 do
00135 {
00136 Psave = P[dest];
00137 SphPsave = SphP[dest];
00138 idsave = Id[dest];
00139
00140 P[dest] = Psource;
00141 SphP[dest] = SphPsource;
00142 Id[dest] = idsource;
00143
00144 if(dest == i)
00145 break;
00146
00147 Psource = Psave;
00148 SphPsource = SphPsave;
00149 idsource = idsave;
00150
00151 dest = idsource;
00152 }
00153 while(1);
00154 }
00155 }
00156 }
00157
00158
00166 void reorder_particles(void)
00167 {
00168 int i;
00169 struct particle_data Psave, Psource;
00170 int idsource, idsave, dest;
00171
00172 for(i = N_gas; i < NumPart; i++)
00173 {
00174 if(Id[i] != i)
00175 {
00176 Psource = P[i];
00177 idsource = Id[i];
00178
00179 dest = Id[i];
00180
00181 do
00182 {
00183 Psave = P[dest];
00184 idsave = Id[dest];
00185
00186 P[dest] = Psource;
00187 Id[dest] = idsource;
00188
00189 if(dest == i)
00190 break;
00191
00192 Psource = Psave;
00193 idsource = idsave;
00194
00195 dest = idsource;
00196 }
00197 while(1);
00198 }
00199 }
00200 }
00201
00202
00203
00204
00205
00206
00207 static int quadrants[24][2][2][2] = {
00208
00209 {{{0, 7}, {1, 6}}, {{3, 4}, {2, 5}}},
00210 {{{7, 4}, {6, 5}}, {{0, 3}, {1, 2}}},
00211 {{{4, 3}, {5, 2}}, {{7, 0}, {6, 1}}},
00212 {{{3, 0}, {2, 1}}, {{4, 7}, {5, 6}}},
00213
00214 {{{1, 0}, {6, 7}}, {{2, 3}, {5, 4}}},
00215 {{{0, 3}, {7, 4}}, {{1, 2}, {6, 5}}},
00216 {{{3, 2}, {4, 5}}, {{0, 1}, {7, 6}}},
00217 {{{2, 1}, {5, 6}}, {{3, 0}, {4, 7}}},
00218
00219 {{{6, 1}, {7, 0}}, {{5, 2}, {4, 3}}},
00220 {{{1, 2}, {0, 3}}, {{6, 5}, {7, 4}}},
00221 {{{2, 5}, {3, 4}}, {{1, 6}, {0, 7}}},
00222 {{{5, 6}, {4, 7}}, {{2, 1}, {3, 0}}},
00223
00224 {{{7, 6}, {0, 1}}, {{4, 5}, {3, 2}}},
00225 {{{6, 5}, {1, 2}}, {{7, 4}, {0, 3}}},
00226 {{{5, 4}, {2, 3}}, {{6, 7}, {1, 0}}},
00227 {{{4, 7}, {3, 0}}, {{5, 6}, {2, 1}}},
00228
00229 {{{6, 7}, {5, 4}}, {{1, 0}, {2, 3}}},
00230 {{{7, 0}, {4, 3}}, {{6, 1}, {5, 2}}},
00231 {{{0, 1}, {3, 2}}, {{7, 6}, {4, 5}}},
00232 {{{1, 6}, {2, 5}}, {{0, 7}, {3, 4}}},
00233
00234 {{{2, 3}, {1, 0}}, {{5, 4}, {6, 7}}},
00235 {{{3, 4}, {0, 7}}, {{2, 5}, {1, 6}}},
00236 {{{4, 5}, {7, 6}}, {{3, 2}, {0, 1}}},
00237 {{{5, 2}, {6, 1}}, {{4, 3}, {7, 0}}}
00238 };
00239
00240
00241 static int rotxmap_table[24] = { 4, 5, 6, 7, 8, 9, 10, 11,
00242 12, 13, 14, 15, 0, 1, 2, 3, 17, 18, 19, 16, 23, 20, 21, 22
00243 };
00244
00245 static int rotymap_table[24] = { 1, 2, 3, 0, 16, 17, 18, 19,
00246 11, 8, 9, 10, 22, 23, 20, 21, 14, 15, 12, 13, 4, 5, 6, 7
00247 };
00248
00249 static int rotx_table[8] = { 3, 0, 0, 2, 2, 0, 0, 1 };
00250 static int roty_table[8] = { 0, 1, 1, 2, 2, 3, 3, 0 };
00251
00252 static int sense_table[8] = { -1, -1, -1, +1, +1, -1, -1, -1 };
00253
00254 static int flag_quadrants_inverse = 1;
00255 static char quadrants_inverse_x[24][8];
00256 static char quadrants_inverse_y[24][8];
00257 static char quadrants_inverse_z[24][8];
00258
00259
00263 peanokey peano_hilbert_key(int x, int y, int z, int bits)
00264 {
00265 int i, quad, bitx, bity, bitz;
00266 int mask, rotation, rotx, roty, sense;
00267 peanokey key;
00268
00269
00270 mask = 1 << (bits - 1);
00271 key = 0;
00272 rotation = 0;
00273 sense = 1;
00274
00275
00276 for(i = 0; i < bits; i++, mask >>= 1)
00277 {
00278 bitx = (x & mask) ? 1 : 0;
00279 bity = (y & mask) ? 1 : 0;
00280 bitz = (z & mask) ? 1 : 0;
00281
00282 quad = quadrants[rotation][bitx][bity][bitz];
00283
00284 key <<= 3;
00285 key += (sense == 1) ? (quad) : (7 - quad);
00286
00287 rotx = rotx_table[quad];
00288 roty = roty_table[quad];
00289 sense *= sense_table[quad];
00290
00291 while(rotx > 0)
00292 {
00293 rotation = rotxmap_table[rotation];
00294 rotx--;
00295 }
00296
00297 while(roty > 0)
00298 {
00299 rotation = rotymap_table[rotation];
00300 roty--;
00301 }
00302 }
00303
00304 return key;
00305 }
00306
00307
00313 void peano_hilbert_key_inverse(peanokey key, int bits, int *x, int *y, int *z)
00314 {
00315 int i, keypart, bitx, bity, bitz, mask, quad, rotation, shift;
00316 char sense, rotx, roty;
00317
00318 if(flag_quadrants_inverse)
00319 {
00320 flag_quadrants_inverse = 0;
00321 for(rotation = 0; rotation < 24; rotation++)
00322 for(bitx = 0; bitx < 2; bitx++)
00323 for(bity = 0; bity < 2; bity++)
00324 for(bitz = 0; bitz < 2; bitz++)
00325 {
00326 quad = quadrants[rotation][bitx][bity][bitz];
00327 quadrants_inverse_x[rotation][quad] = bitx;
00328 quadrants_inverse_y[rotation][quad] = bity;
00329 quadrants_inverse_z[rotation][quad] = bitz;
00330 }
00331 }
00332
00333 shift = 3 * (bits - 1);
00334 mask = 7 << shift;
00335
00336 rotation = 0;
00337 sense = 1;
00338
00339 *x = *y = *z = 0;
00340
00341 for(i = 0; i < bits; i++, mask >>= 3, shift -= 3)
00342 {
00343 keypart = (key & mask) >> shift;
00344
00345 quad = (sense == 1) ? (keypart) : (7 - keypart);
00346
00347 *x = (*x << 1) + quadrants_inverse_x[rotation][quad];
00348 *y = (*y << 1) + quadrants_inverse_y[rotation][quad];
00349 *z = (*z << 1) + quadrants_inverse_z[rotation][quad];
00350
00351 rotx = rotx_table[quad];
00352 roty = roty_table[quad];
00353 sense *= sense_table[quad];
00354
00355 while(rotx > 0)
00356 {
00357 rotation = rotxmap_table[rotation];
00358 rotx--;
00359 }
00360
00361 while(roty > 0)
00362 {
00363 rotation = rotymap_table[rotation];
00364 roty--;
00365 }
00366 }
00367 }