From ed9a5d5a016e82d24630bea79fed0011a86bd70e Mon Sep 17 00:00:00 2001 From: Rudolf Weeber Date: Tue, 15 Jan 2019 14:03:41 +0100 Subject: [PATCH] Core: Backport particle deletion code from pr #2410 --- src/core/particle_data.cpp | 99 +++++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 28 deletions(-) diff --git a/src/core/particle_data.cpp b/src/core/particle_data.cpp index 1776fa63724..35957c6d436 100644 --- a/src/core/particle_data.cpp +++ b/src/core/particle_data.cpp @@ -821,42 +821,85 @@ int remove_particle(int p_id) { return ES_OK; } -void local_remove_particle(int part) { - int ind, c; - Particle *p = local_particles[part]; - ParticleList *pl = nullptr, *tmp; +/** + * @brief Extract an indexed particle from a list. + * + * Removes a particle from a particle list and + * from the particle index. + * + * @param i Index of particle to remove, + * needs to be valid. + * @param sl List to remove the particle from, + * needs to be non-empty. + * @return The extracted particle. + */ +Particle extract_indexed_particle(ParticleList *sl, int i) { + assert(sl->n > 0); + assert(i < sl->n); + Particle *src = &sl->part[i]; + Particle *end = &sl->part[sl->n - 1]; - /* the tricky - say ugly - part: determine - the cell the particle is located in by checking - whether the particle address is inside the array */ - for (c = 0; c < local_cells.n; c++) { - tmp = local_cells.cell[c]; - ind = p - tmp->part; - if (ind >= 0 && ind < tmp->n) { - pl = tmp; - break; - } + Particle p = std::move(*src); + + assert(p.p.identity <= max_seen_particle); + local_particles[p.p.identity] = nullptr; + + if (src != end) { + new (src) Particle(std::move(*end)); } - if (!pl) { - fprintf(stderr, - "%d: INTERNAL ERROR: could not find cell of particle %d, exiting\n", - this_node, part); - errexit(); + + if (realloc_particlelist(sl, --sl->n)) { + update_local_particles(sl); + } else if (src != end) { + local_particles[src->p.identity] = src; } + return p; +} - free_particle(p); +namespace { +std::pair find_particle(Particle *p, Cell *c) { + for (int i = 0; i < c->n; ++i) { + if ((c->part + i) == p) { + return {c, i}; + } + } + return {nullptr, 0}; +} + +std::pair find_particle(Particle *p, CellPList cells) { + for (auto &c : cells) { + auto res = find_particle(p, c); + if (res.first) { + return res; + } + } - /* remove local_particles entry */ - local_particles[p->p.identity] = nullptr; + return {nullptr, 0}; +} +} // namespace - if (&pl->part[pl->n - 1] != p) { - /* move last particle to free position */ - *p = pl->part[pl->n - 1]; +void local_remove_particle(int part) { + Particle *p = local_particles[part]; + assert(p); + assert(not p->l.ghost); + + /* If the particles are sorted we can use the + * cell system to find the cell containing the + * particle. Otherwise we do a brute force search + * of the cells. */ + Cell *cell = nullptr; + size_t n = 0; + if (Cells::RESORT_NONE == get_resort_particles()) { + std::tie(cell, n) = find_particle(p, find_current_cell(*p)); + } - /* update the local_particles array for the moved particle */ - local_particles[p->p.identity] = p; + if (not cell) { + std::tie(cell, n) = find_particle(p, local_cells); } - pl->n--; + + assert(cell && cell->part && (n < cell->n) && ((cell->part + n) == p)); + + Particle p_destroy = extract_indexed_particle(cell, n); } void local_place_particle(int part, const double p[3], int _new) {