Skip to content

Commit

Permalink
Merge pull request #2441 from RudolfWeeber/401_del
Browse files Browse the repository at this point in the history
Core: Backport particle deletion code from pr #2410
  • Loading branch information
RudolfWeeber authored Jan 16, 2019
2 parents 84491e5 + c96861b commit facc5af
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 30 deletions.
99 changes: 71 additions & 28 deletions src/core/particle_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Cell *, size_t> 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<Cell *, size_t> 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) {
Expand Down
16 changes: 14 additions & 2 deletions testsuite/python/particle.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ def test_parallel_property_setters(self):
"If this test hangs, there is an mpi deadlock in a particle property setter.")
for p in espressomd.particle_data.particle_attributes:
# Uncomment to identify guilty property
#print( p)
# print( p)

if not hasattr(s.part[0], p):
raise Exception(
Expand All @@ -260,7 +260,19 @@ def test_parallel_property_setters(self):
# Cause a differtn mpi callback to uncover deadlock immediately
x = getattr(s.part[:], p)

def test_zz_remove_all(self):
for id in self.system.part[:].id:
self.system.part[id].remove()
self.system.part.add(pos=np.random.random(
(100, 3)) * self.system.box_l, id=np.arange(100, dtype=int))
ids = self.system.part[:].id
np.random.shuffle(ids)
for id in ids:
self.system.part[id].remove()
with self.assertRaises(Exception):
self.system.part[17].remove()


if __name__ == "__main__":
#print("Features: ", espressomd.features())
# print("Features: ", espressomd.features())
ut.main()

0 comments on commit facc5af

Please sign in to comment.