diff --git a/src/fof.c b/src/fof.c index e094d81ccad20c0f92415429aab3bdae17c6f1d5..b4a83e36de3dbb3386e7fedcd2ada82bb6998083 100644 --- a/src/fof.c +++ b/src/fof.c @@ -39,7 +39,9 @@ #include "proxy.h" #include "common_io.h" +#ifdef WITH_MPI MPI_Datatype fof_mpi_type; +#endif FILE *fof_file; int node_offset; @@ -277,11 +279,12 @@ static void rec_fof_search_pair(struct cell *ci, struct cell *cj, struct space * } +#ifdef WITH_MPI /* Recurse on a pair of cells (one local, one foreign) and perform a FOF search between cells that are within * range. */ static void rec_fof_search_pair_foreign(struct cell *ci, struct cell *cj, struct space *s, const double *dim, - const double search_r2, int *link_count, struct fof_mpi *group_links) { + const double search_r2, int *link_count, struct fof_mpi **group_links, int *group_links_size) { /* Find the shortest distance between cells, remembering to account for * boundary conditions. */ @@ -297,50 +300,18 @@ static void rec_fof_search_pair_foreign(struct cell *ci, struct cell *cj, struct for (int l = 0; l < 8; l++) if (cj->progeny[l] != NULL) - rec_fof_search_pair_foreign(ci->progeny[k], cj->progeny[l], s, dim, search_r2, link_count, group_links); + rec_fof_search_pair_foreign(ci->progeny[k], cj->progeny[l], s, dim, search_r2, link_count, group_links, group_links_size); } } } /* Perform FOF search between pairs of cells that are within the linking * length and not the same cell. */ else if (ci != cj) - fof_search_pair_cells_foreign(s, ci, cj, link_count, group_links); - else if (ci == cj) error("Pair FOF called on same cell!!!"); - -} - -/* Recurse on a pair of cells (one local, one foreign) and count the total number of possible links between them. */ -static void rec_fof_search_pair_foreign_count(struct cell *ci, struct cell *cj, struct space *s, - const double *dim, - const double search_r2, size_t *nr_links) { - - /* Find the shortest distance between cells, remembering to account for - * boundary conditions. */ - const double r2 = cell_min_dist(ci, cj, dim); - - /* Return if cells are out of range of each other. */ - if (r2 > search_r2) return; - - /* Recurse on both cells if they are both split. */ - if (ci->split && cj->split) { - for (int k = 0; k < 8; k++) { - if (ci->progeny[k] != NULL) { - - for (int l = 0; l < 8; l++) - if (cj->progeny[l] != NULL) - rec_fof_search_pair_foreign_count(ci->progeny[k], cj->progeny[l], s, dim, search_r2, nr_links); - } - } - } - /* Perform FOF search between pairs of cells that are within the linking - * length and not the same cell. */ - else if (ci != cj) { - *nr_links += ci->gcount * cj->gcount; - return; - } + fof_search_pair_cells_foreign(s, ci, cj, link_count, group_links, group_links_size); else if (ci == cj) error("Pair FOF called on same cell!!!"); } +#endif /* Recurse on a cell and perform a FOF search between cells that are within * range. */ @@ -499,7 +470,7 @@ void fof_search_pair_cells(struct space *s, struct cell *ci, struct cell *cj) { /* Perform a FOF search between a local and foreign cell using the Union-Find algorithm. * Store any links found between particles.*/ -void fof_search_pair_cells_foreign(struct space *s, struct cell *ci, struct cell *cj, int *link_count, struct fof_mpi *group_links ) { +void fof_search_pair_cells_foreign(struct space *s, struct cell *ci, struct cell *cj, int *link_count, struct fof_mpi **group_links, int *group_links_size) { const size_t count_i = ci->gcount; const size_t count_j = cj->gcount; @@ -574,19 +545,32 @@ void fof_search_pair_cells_foreign(struct space *s, struct cell *ci, struct cell int found = 0; /* Check that the links have not already been added to the list. */ - for(size_t l=0; l<*link_count; l++) { - if(group_links[l].group_i == root_i && group_links[l].group_j == pj->root) found = 1; + for(int l=0; l<*link_count; l++) { + if((*group_links)[l].group_i == root_i && (*group_links)[l].group_j == pj->root) found = 1; } if(!found) { + + /* If the group_links array is not big enough re-allocate it. */ + if(*link_count + 1 > *group_links_size) { + + int new_size = *group_links_size + 0.1 * (double)(*group_links_size); + + *group_links_size = new_size; + + (*group_links) = (struct fof_mpi *)realloc(*group_links, new_size * sizeof(struct fof_mpi)); + + message("Re-allocating group links from %d to %d elements.", *link_count, new_size); + } + /* Store the particle group properties for communication. */ - group_links[*link_count].group_i = root_i; - group_links[*link_count].group_j = pj->root; - group_links[*link_count].group_i_size = group_size[root_i - node_offset]; - group_links[*link_count].group_i_mass = group_mass[root_i - node_offset]; - group_links[*link_count].group_i_CoM.x = group_CoM[root_i - node_offset].x; - group_links[*link_count].group_i_CoM.y = group_CoM[root_i - node_offset].y; - group_links[*link_count].group_i_CoM.z = group_CoM[root_i - node_offset].z; + (*group_links)[*link_count].group_i = root_i; + (*group_links)[*link_count].group_j = pj->root; + (*group_links)[*link_count].group_i_size = group_size[root_i - node_offset]; + (*group_links)[*link_count].group_i_mass = group_mass[root_i - node_offset]; + (*group_links)[*link_count].group_i_CoM.x = group_CoM[root_i - node_offset].x; + (*group_links)[*link_count].group_i_CoM.y = group_CoM[root_i - node_offset].y; + (*group_links)[*link_count].group_i_CoM.z = group_CoM[root_i - node_offset].z; (*link_count)++; } @@ -748,7 +732,7 @@ void fof_search_tree_mapper(void *map_data, int num_elements, /* Loop over cells and find which cells are in range of each other to perform * the FOF search. */ - for (size_t ind = 0; ind < num_elements; ind++) { + for (int ind = 0; ind < num_elements; ind++) { /* Get the cell. */ struct cell *restrict ci = &cells[ind]; @@ -795,75 +779,29 @@ void fof_search_foreign_cells(struct space *s) { int *group_size = s->fof_data.group_size; double *group_mass = s->fof_data.group_mass; struct fof_CoM *group_CoM = s->fof_data.group_CoM; - const int nr_gparts = s->nr_gparts; + const size_t nr_gparts = s->nr_gparts; const double dim[3] = {s->dim[0], s->dim[1], s->dim[2]}; const double search_r2 = s->l_x2; message("Searching foreign cells for links."); - size_t nr_links = 0; - int interface_cell_count = 0; - /* Make group IDs globally unique. */ for (size_t i = 0; i < nr_gparts; i++) group_index[i] += node_offset; - - /* Loop over the proxies and find local cells that touch foreign cells. Calculate the total number of possible links between these cells. */ - for(int i=0; i<e->nr_proxies; i++) { - - for(int j=0; j<e->proxies[i].nr_cells_out; j++) { - - /* Skip non-gravity cells. */ - if(e->proxies[i].cells_out_type[j] != proxy_cell_type_gravity) continue; - - struct cell *restrict local_cell = e->proxies[i].cells_out[j]; - int found = 0; - - /* Skip empty cells. */ - if(local_cell->gcount == 0) continue; - - for(int k=0; k<e->proxies[i].nr_cells_in; k++) { - - /* Skip non-gravity cells. */ - if(e->proxies[i].cells_in_type[k] != proxy_cell_type_gravity) continue; - - struct cell *restrict foreign_cell = e->proxies[i].cells_in[k]; - - /* Skip empty cells. */ - if(foreign_cell->gcount == 0) continue; - - /* Assume there are only links between cells that touch. */ - const double r2 = cell_min_dist(local_cell, foreign_cell, dim); - if(r2 < search_r2) { - rec_fof_search_pair_foreign_count(local_cell, foreign_cell, s, dim, search_r2, &nr_links); - - /* Only count the local cell once. */ - if(!found) { - interface_cell_count++; - found = 1; - } - } - } - } - } - - message("Rank: %d, Total no. of possible links: %zu, cells touching: %d", engine_rank, nr_links, interface_cell_count); - + + int group_links_size = 20000; + int interface_cell_size = 4000; struct fof_mpi *group_links; - int group_link_count = 0; struct cell **interface_cells; - - nr_links = 100000; + int group_link_count = 0; + int interface_cell_count = 0; if (posix_memalign((void**)&group_links, SWIFT_STRUCT_ALIGNMENT, - nr_links * sizeof(struct fof_mpi)) != 0) + group_links_size * sizeof(struct fof_mpi)) != 0) error("Error while allocating memory for FOF links over an MPI domain"); if (posix_memalign((void**)&interface_cells, SWIFT_STRUCT_ALIGNMENT, - interface_cell_count * sizeof(struct cell *)) != 0) + interface_cell_size * sizeof(struct cell *)) != 0) error("Error while allocating memory for FOF interface cells"); - - /* Use to index interface_cell array */ - interface_cell_count = 0; /* Loop over cells_in and cells_out for each proxy and find which cells are in range of each other to perform * the FOF search. Store local cells that are touching foreign cells in a list. */ @@ -893,7 +831,19 @@ void fof_search_foreign_cells(struct space *s) { /* Check if local cell has already been added to the local list of cells. */ const double r2 = cell_min_dist(local_cell, foreign_cell, dim); - if(r2 < search_r2) { + if(r2 < search_r2) { + + /* If the interface_cells array is not big enough re-allocate it. */ + if(interface_cell_count + 1 > interface_cell_size) { + + int new_size = interface_cell_size + 0.1 * (double)interface_cell_size; + + interface_cell_size = new_size; + interface_cells = (struct cell **)realloc(interface_cells, new_size * sizeof(struct cell *)); + + message("Re-allocating interface cells from %d to %d elements.", interface_cell_count, new_size); + } + interface_cells[interface_cell_count++] = local_cell; break; } @@ -964,7 +914,7 @@ void fof_search_foreign_cells(struct space *s) { /* Skip empty cells. */ if(foreign_cell->gcount == 0) continue; - rec_fof_search_pair_foreign(local_cell, foreign_cell, s, dim, search_r2, &group_link_count, group_links); + rec_fof_search_pair_foreign(local_cell, foreign_cell, s, dim, search_r2, &group_link_count, &group_links, &group_links_size); } } @@ -1445,7 +1395,8 @@ void fof_search_tree(struct space *s) { void fof_dump_group_data(char *out_file, struct space *s) { FILE *file = fopen(out_file, "w"); - const int min_group_size = s->fof_data.min_group_size, nr_gparts = s->nr_gparts; + const int min_group_size = s->fof_data.min_group_size; + const size_t nr_gparts = s->nr_gparts; int *group_index = s->fof_data.group_index; int *group_size = s->fof_data.group_size; @@ -1457,6 +1408,8 @@ void fof_dump_group_data(char *out_file, struct space *s) { fprintf(file, "# %7s %7s %7s %7s %7s %7s %7s %7s\n", "ID", "Root ID", "Group Size", "Group Mass", "x CoM", "y CoM", "z CoM", "Group ID"); fprintf(file, "#---------------------------------------\n"); + /* TODO: Order groups in descending order. */ + /* TODO: Set particle group ID in particle struct. */ for (size_t i = 0; i < nr_gparts; i++) { if(group_size[i] >= min_group_size) { const int root = fof_find_global(i - node_offset, group_index); diff --git a/src/fof.h b/src/fof.h index 430aedaba1da4f23ff8be0fd7b48f71ff8b0bf5a..76a2ec77ed4aee19d0ea666585e2108dff4dd38a 100644 --- a/src/fof.h +++ b/src/fof.h @@ -52,7 +52,7 @@ void fof_init(struct space *s, long long Ngas, long long Ngparts); void fof_search_serial(struct space *s); void fof_search_cell(struct space *s, struct cell *c); void fof_search_pair_cells(struct space *s, struct cell *ci, struct cell *cj); -void fof_search_pair_cells_foreign(struct space *s, struct cell *ci, struct cell *cj, int *link_count, struct fof_mpi *part_links); +void fof_search_pair_cells_foreign(struct space *s, struct cell *ci, struct cell *cj, int *link_count, struct fof_mpi **group_links, int *group_links_size); void fof_search_tree_serial(struct space *s); void fof_search_tree(struct space *s); void fof_dump_group_data(char *out_file, struct space *s);