void peano_hilbert_order(void) { int i; if(ThisTask == 0) printf("begin Peano-Hilbert order...\n"); if(N_gas) { mp = malloc(sizeof(struct peano_hilbert_data) * N_gas); Id = malloc(sizeof(int) * N_gas); for(i = 0; i < N_gas; i++) { mp[i].index = i; mp[i].key = Key[i]; } qsort(mp, N_gas, sizeof(struct peano_hilbert_data), compare_key); for(i = 0; i < N_gas; i++) Id[mp[i].index] = i; reorder_gas(); free(Id); free(mp); } if(NumPart - N_gas > 0) { mp = malloc(sizeof(struct peano_hilbert_data) * (NumPart - N_gas)); mp -= (N_gas); Id = malloc(sizeof(int) * (NumPart - N_gas)); Id -= (N_gas); for(i = N_gas; i < NumPart; i++) { mp[i].index = i; mp[i].key = Key[i]; } qsort(mp + N_gas, NumPart - N_gas, sizeof(struct peano_hilbert_data), compare_key); for(i = N_gas; i < NumPart; i++) Id[mp[i].index] = i; reorder_particles(); Id += N_gas; free(Id); mp += N_gas; free(mp); } if(ThisTask == 0) printf("Peano-Hilbert done.\n"); }
/*! This function puts the particles into Peano-Hilbert order by sorting them * according to their keys. The latter half already been computed in the * domain decomposition. Since gas particles need to stay at the beginning of * the particle list, they are sorted as a separate block. */ void peano_hilbert_order(void) { int i; #if N_GRAVS > 1 int offset, k; #endif if(ThisTask == 0) printf("begin Peano-Hilbert order...\n"); if(N_gas) { mp = malloc(sizeof(struct peano_hilbert_data) * N_gas); Id = malloc(sizeof(int) * N_gas); for(i = 0; i < N_gas; i++) { mp[i].index = i; mp[i].key = Key[i]; } qsort(mp, N_gas, sizeof(struct peano_hilbert_data), compare_key); for(i = 0; i < N_gas; i++) Id[mp[i].index] = i; reorder_gas(); free(Id); free(mp); } #if N_GRAVS > 1 // && defined PMGRID // KC 10/8/14 // To keep from traversing the entire particle list N_GRAVS^2 times // while in PMGRID mode // we Peano-Hilbert sort each type of particle, but keep the types strictly // ordered on the local processors. Thus, we do what is done for gas particles (they sit // at the head of the P list) for all the types. // // Hopefully this will still reap some of the spatial localization/memory localization // benefits of Peano-Hilbert ordering! // First, type order if(NumPart - N_gas > 0) { mp = malloc(sizeof(struct peano_hilbert_data) * (NumPart - N_gas)); mp -= N_gas; Id = malloc(sizeof(int) * (NumPart - N_gas)); memset(Id, -1, NumPart-N_gas); Id -= N_gas; for(i = N_gas; i < NumPart; ++i) { mp[i].index = i; mp[i].key = TypeToGrav[P[i].Type]; } // KC 10/20/14 // Sort based on gravitational interaction, not on particle type // KC 10/12/14 // mp[position in P list] = {position in P list, type of particle in this position} qsort(mp + N_gas, NumPart - N_gas, sizeof(struct peano_hilbert_data), compare_key); // KC 10/12/14 // mp[destination position] = {(source) position in P list, type of particle in this position} // Now sort within type by peano-hilbert key // The indexes of Key correspond to the original indexes of P before any kind of sort. // So we care about mp[i].index // Temporarily ignore the gas particles NgravLocal[0] -= N_gas; offset = N_gas; for(k = 0; k < N_GRAVS; ++k) { mp2 = malloc(sizeof(struct peano_hilbert_data) * NgravLocal[k]); mp2 -= offset; for(i = offset; i < offset + NgravLocal[k]; ++i) { mp2[i].index = mp[i].index; mp2[i].key = Key[mp[i].index]; } qsort(mp2 + offset, NgravLocal[k], sizeof(struct peano_hilbert_data), compare_key); for(i = offset; i < offset + NgravLocal[k]; ++i) Id[mp2[i].index] = i; mp2 += offset; free(mp2); offset += NgravLocal[k]; } // Put the gas particles back on NgravLocal[0] += N_gas; mp += N_gas; free(mp); reorder_particles(); // Dump particles // for(i = 0; i < NumPart; ++i) // printf("PEANO: %d has {type,gravtype}={%d, %d}\n", i, P[i].Type, TypeToGrav[P[i].Type]); Id += N_gas; free(Id); if(ThisTask == 0) printf("ngravs: Type ordering complete, Peano-Hilbert subordered.\n"); } #else if(NumPart - N_gas > 0) { mp = malloc(sizeof(struct peano_hilbert_data) * (NumPart - N_gas)); mp -= (N_gas); Id = malloc(sizeof(int) * (NumPart - N_gas)); Id -= (N_gas); for(i = N_gas; i < NumPart; i++) { mp[i].index = i; mp[i].key = Key[i]; } qsort(mp + N_gas, NumPart - N_gas, sizeof(struct peano_hilbert_data), compare_key); for(i = N_gas; i < NumPart; i++) Id[mp[i].index] = i; reorder_particles(); Id += N_gas; free(Id); mp += N_gas; free(mp); } #endif if(ThisTask == 0) printf("Peano-Hilbert done.\n"); }