From 61ac204338ad31cda9a047fcd797d16bcdbd658b Mon Sep 17 00:00:00 2001 From: Martin Kronbichler Date: Mon, 8 Nov 2021 13:24:02 +0100 Subject: [PATCH] Make access to list of particles more robust --- include/deal.II/particles/particle_handler.h | 104 +++++++++++++++---- source/particles/particle_handler.cc | 40 +++---- 2 files changed, 108 insertions(+), 36 deletions(-) diff --git a/include/deal.II/particles/particle_handler.h b/include/deal.II/particles/particle_handler.h index e84ea81a4b..66f9513341 100644 --- a/include/deal.II/particles/particle_handler.h +++ b/include/deal.II/particles/particle_handler.h @@ -930,9 +930,10 @@ namespace Particles /** * Iterator to the end of the list elements of particle_container which - * belong to locally owned elements. + * belong to locally owned elements. Made const to avoid accidental + * modification. */ - typename particle_container::iterator owned_particles_end; + const typename particle_container::iterator owned_particles_end; /** * List from the active cells on the present MPI process to positions in @@ -1152,6 +1153,34 @@ namespace Particles const typename Triangulation::CellStatus status, const boost::iterator_range::const_iterator> &data_range); + + /** + * Internal function returning an iterator to the begin of the container + * for owned particles. + */ + typename particle_container::iterator + particle_container_owned_begin() const; + + /** + * Internal function returning an iterator to the end of the container for + * owned particles. + */ + typename particle_container::iterator + particle_container_owned_end() const; + + /** + * Internal function returning an iterator to the begin of the container + * for ghost particles. + */ + typename particle_container::iterator + particle_container_ghost_begin() const; + + /** + * Internal function returning an iterator to the end of the container for + * ghost particles. + */ + typename particle_container::iterator + particle_container_ghost_end() const; }; @@ -1172,12 +1201,9 @@ namespace Particles inline typename ParticleHandler::particle_iterator ParticleHandler::begin() { - // We should always have at least the three anchor entries in the list of - // particles - Assert(!particles.empty(), ExcInternalError()); - - // jump over the first entry which is used for book-keeping - return particle_iterator(++particles.begin(), *property_pool, 0); + return particle_iterator(particle_container_owned_begin(), + *property_pool, + 0); } @@ -1195,7 +1221,7 @@ namespace Particles inline typename ParticleHandler::particle_iterator ParticleHandler::end() { - return particle_iterator(owned_particles_end, *property_pool, 0); + return particle_iterator(particle_container_owned_end(), *property_pool, 0); } @@ -1213,13 +1239,9 @@ namespace Particles inline typename ParticleHandler::particle_iterator ParticleHandler::begin_ghost() { - Assert(!particles.empty(), ExcInternalError()); - // find the start of ghost particles as one past the end of owned indices; - // the index in between is used for book-keeping - typename particle_container::iterator ghost_particles_begin = - owned_particles_end; - ++ghost_particles_begin; - return particle_iterator(ghost_particles_begin, *property_pool, 0); + return particle_iterator(particle_container_ghost_begin(), + *property_pool, + 0); } @@ -1237,8 +1259,54 @@ namespace Particles inline typename ParticleHandler::particle_iterator ParticleHandler::end_ghost() { - // skip the last entry which is used for book-keeping - return particle_iterator(--particles.end(), *property_pool, 0); + return particle_iterator(particle_container_ghost_end(), *property_pool, 0); + } + + + + template + inline typename ParticleHandler::particle_container::iterator + ParticleHandler::particle_container_owned_begin() const + { + // We should always have at least the three anchor entries in the list of + // particles + Assert(!particles.empty(), ExcInternalError()); + typename particle_container::iterator begin = + const_cast(particles).begin(); + return ++begin; + } + + + + template + inline typename ParticleHandler::particle_container::iterator + ParticleHandler::particle_container_owned_end() const + { + Assert(!particles.empty(), ExcInternalError()); + return owned_particles_end; + } + + + + template + inline typename ParticleHandler::particle_container::iterator + ParticleHandler::particle_container_ghost_begin() const + { + Assert(!particles.empty(), ExcInternalError()); + typename particle_container::iterator begin = owned_particles_end; + return ++begin; + } + + + + template + inline typename ParticleHandler::particle_container::iterator + ParticleHandler::particle_container_ghost_end() const + { + Assert(!particles.empty(), ExcInternalError()); + typename particle_container::iterator end = + const_cast(particles).end(); + return --end; } diff --git a/source/particles/particle_handler.cc b/source/particles/particle_handler.cc index d1ea72c6ec..57e17a8002 100644 --- a/source/particles/particle_handler.cc +++ b/source/particles/particle_handler.cc @@ -165,12 +165,15 @@ namespace Particles global_max_particles_per_cell = particle_handler.global_max_particles_per_cell; next_free_particle_index = particle_handler.next_free_particle_index; - particles = particle_handler.particles; - owned_particles_end = particles.begin(); - for (auto it = particle_handler.particles.begin(); - it != particle_handler.owned_particles_end; - ++it) - ++owned_particles_end; + + // Manually copy over the particles because we do not want to touch the + // anchor iterators set by initialize() + particles.insert(particle_container_owned_end(), + particle_handler.particle_container_owned_begin(), + particle_handler.particle_container_owned_end()); + particles.insert(particle_container_ghost_end(), + particle_handler.particle_container_ghost_begin(), + particle_handler.particle_container_ghost_end()); for (auto it = particles.begin(); it != particles.end(); ++it) if (!it->particles.empty()) @@ -228,19 +231,19 @@ namespace Particles const Triangulation *triangulation, particle_container & given_particles) { - TriaActiveIterator> past_the_end_iterator( - triangulation, -1, -1); given_particles.clear(); for (unsigned int i = 0; i < 3; ++i) given_particles.emplace_back( std::vector::Handle>(), - past_the_end_iterator); + triangulation->end()); // Set the end of owned particles to the middle of the three elements - owned_particles_end = ++given_particles.begin(); + const_cast(owned_particles_end) = + ++given_particles.begin(); } + template void ParticleHandler::update_cached_numbers() @@ -248,8 +251,8 @@ namespace Particles // first sort the owned particles by the active cell index bool sort_is_necessary = false; { - auto previous = ++particles.begin(); - for (auto next = previous; next != owned_particles_end; ++next) + auto previous = particle_container_owned_begin(); + for (auto next = previous; next != particle_container_owned_end(); ++next) { if (previous->cell.state() == IteratorState::valid && next->cell.state() == IteratorState::valid && @@ -280,11 +283,9 @@ namespace Particles if (cells_to_particle_cache[cell->active_cell_index()] != particles.end()) { - // observe that owned_particles_end was already set to point - // into the new sorted_particles array typename particle_container::iterator insert_position = - cell->is_locally_owned() ? owned_particles_end : - --sorted_particles.end(); + cell->is_locally_owned() ? particle_container_owned_end() : + particle_container_ghost_end(); typename particle_container::iterator new_entry = sorted_particles.insert( insert_position, typename particle_container::value_type()); @@ -324,7 +325,9 @@ namespace Particles // check that we only have locally owned particles in the first region of // cells; note that we skip the very first anchor element - for (auto it = ++particles.begin(); it != owned_particles_end; ++it) + for (auto it = particle_container_owned_begin(); + it != particle_container_owned_end(); + ++it) Assert(it->cell->is_locally_owned(), ExcInternalError()); // check that the cache is consistent with the iterators @@ -577,7 +580,8 @@ namespace Particles if (cache == particles.end()) { const typename particle_container::iterator insert_position = - cell->is_locally_owned() ? owned_particles_end : --particles.end(); + cell->is_locally_owned() ? particle_container_owned_end() : + particle_container_ghost_end(); cache = particles.emplace( insert_position, std::vector::Handle>{handle}, -- 2.39.5