void cells_re_init(int new_cs) { CellPList tmp_local; Cell *tmp_cells; int tmp_n_cells,i; CELL_TRACE(fprintf(stderr, "%d: cells_re_init: convert type (%d->%d)\n", this_node, cell_structure.type, new_cs)); invalidate_ghosts(); /* CELL_TRACE({ int p; for (p = 0; p < n_total_particles; p++) if (local_particles[p]) fprintf(stderr, "%d: cells_re_init: got particle %d\n", this_node, p); } ); */ topology_release(cell_structure.type); /* MOVE old local_cell list to temporary buffer */ memcpy(&tmp_local,&local_cells,sizeof(CellPList)); init_cellplist(&local_cells); /* MOVE old cells to temporary buffer */ tmp_cells = cells; tmp_n_cells = n_cells; cells = NULL; n_cells = 0; topology_init(new_cs, &tmp_local); particle_invalidate_part_node(); /* finally deallocate the old cells */ realloc_cellplist(&tmp_local,0); for(i=0;i<tmp_n_cells;i++) realloc_particlelist(&tmp_cells[i],0); free(tmp_cells); CELL_TRACE(fprintf(stderr, "%d: old cells deallocated\n",this_node)); /* CELL_TRACE({ int p; for (p = 0; p < n_total_particles; p++) if (local_particles[p]) fprintf(stderr, "%d: cells_re_init: now got particle %d\n", this_node, p); } ); */ /* to enforce initialization of the ghost cells */ resort_particles = 1; #ifdef ADDITIONAL_CHECKS check_cells_consistency(); #endif }
void nsq_topology_init(CellPList *old) { Particle *part; int n, c, p, np, ntodo, diff; CELL_TRACE(fprintf(stderr, "%d: nsq_topology_init, %d\n", this_node, old->n)); cell_structure.type = CELL_STRUCTURE_NSQUARE; cell_structure.position_to_node = map_position_node_array; cell_structure.position_to_cell = nsq_position_to_cell; realloc_cells(n_nodes); /* mark cells */ local = &cells[this_node]; realloc_cellplist(&local_cells, local_cells.n = 1); local_cells.cell[0] = local; realloc_cellplist(&ghost_cells, ghost_cells.n = n_nodes - 1); c = 0; for (n = 0; n < n_nodes; n++) if (n != this_node) ghost_cells.cell[c++] = &cells[n]; /* distribute force calculation work */ ntodo = (n_nodes + 3)/2; init_cellplist(&me_do_ghosts); realloc_cellplist(&me_do_ghosts, ntodo); for (n = 0; n < n_nodes; n++) { diff = n - this_node; /* simple load balancing formula. Basically diff % n, where n >= n_nodes, n odd. The node itself is also left out, as it is treated differently */ if (((diff > 0 && (diff % 2) == 0) || (diff < 0 && ((-diff) % 2) == 1))) { CELL_TRACE(fprintf(stderr, "%d: doing interactions with %d\n", this_node, n)); me_do_ghosts.cell[me_do_ghosts.n++] = &cells[n]; } } /* create communicators */ nsq_prepare_comm(&cell_structure.ghost_cells_comm, GHOSTTRANS_PARTNUM); nsq_prepare_comm(&cell_structure.exchange_ghosts_comm, GHOSTTRANS_PROPRTS | GHOSTTRANS_POSITION); nsq_prepare_comm(&cell_structure.update_ghost_pos_comm, GHOSTTRANS_POSITION); nsq_prepare_comm(&cell_structure.collect_ghost_force_comm, GHOSTTRANS_FORCE); /* here we just decide what to transfer where */ if (n_nodes > 1) { for (n = 0; n < n_nodes; n++) { /* use the prefetched send buffers. Node 0 transmits first and never prefetches. */ if (this_node == 0 || this_node != n) { cell_structure.ghost_cells_comm.comm[n].type = GHOST_BCST; cell_structure.exchange_ghosts_comm.comm[n].type = GHOST_BCST; cell_structure.update_ghost_pos_comm.comm[n].type = GHOST_BCST; } else { cell_structure.ghost_cells_comm.comm[n].type = GHOST_BCST | GHOST_PREFETCH; cell_structure.exchange_ghosts_comm.comm[n].type = GHOST_BCST | GHOST_PREFETCH; cell_structure.update_ghost_pos_comm.comm[n].type = GHOST_BCST | GHOST_PREFETCH; } cell_structure.collect_ghost_force_comm.comm[n].type = GHOST_RDCE; } /* first round: all nodes except the first one prefetch their send data */ if (this_node != 0) { cell_structure.ghost_cells_comm.comm[0].type |= GHOST_PREFETCH; cell_structure.exchange_ghosts_comm.comm[0].type |= GHOST_PREFETCH; cell_structure.update_ghost_pos_comm.comm[0].type |= GHOST_PREFETCH; } } /* copy particles */ for (c = 0; c < old->n; c++) { part = old->cell[c]->part; np = old->cell[c]->n; for (p = 0; p < np; p++) append_unindexed_particle(local, &part[p]); } update_local_particles(local); }