From 37224d307ab7baa32b6eea666a981a9758ab06f4 Mon Sep 17 00:00:00 2001 From: Andrew Myers Date: Wed, 10 Jun 2020 10:29:44 -0700 Subject: [PATCH] Non const iterator neighbor list (#994) * build non-const iterator for neighbor lists * build non-const iterator for neighbor lists * implement non-const iterators for neighbor list * remove second access operator for Neighbors::iterator * const Co-authored-by: Johannes Blaschke --- Src/Particle/AMReX_NeighborList.H | 145 ++++++++++++------ .../NeighborParticles/MDParticleContainer.cpp | 6 +- 2 files changed, 99 insertions(+), 52 deletions(-) diff --git a/Src/Particle/AMReX_NeighborList.H b/Src/Particle/AMReX_NeighborList.H index 3ae0aa98f93..be57abb3eb1 100644 --- a/Src/Particle/AMReX_NeighborList.H +++ b/Src/Particle/AMReX_NeighborList.H @@ -10,77 +10,124 @@ namespace amrex template struct Neighbors -{ +{ struct iterator { AMREX_GPU_HOST_DEVICE - iterator (int start, int stop, const unsigned int * nbor_list_ptr, const ParticleType* pstruct) - : m_index(start), m_stop(stop), m_nbor_list_ptr(nbor_list_ptr), m_pstruct(pstruct) + iterator (int start, int stop, const unsigned int * nbor_list_ptr, ParticleType* pstruct) + : m_index(start), m_stop(stop), m_nbor_list_ptr(nbor_list_ptr), m_pstruct(pstruct) {} - + AMREX_GPU_HOST_DEVICE void operator++ () { ++m_index;; } - + AMREX_GPU_HOST_DEVICE bool operator!= (iterator const& rhs) const { return m_index < m_stop; } - + + AMREX_GPU_HOST_DEVICE + ParticleType& operator* () const { return m_pstruct[m_nbor_list_ptr[m_index]]; } + + private: + int m_index; + int m_stop; + const unsigned int* m_nbor_list_ptr; + ParticleType* m_pstruct; + }; + + struct const_iterator + { + AMREX_GPU_HOST_DEVICE + const_iterator (int start, int stop, const unsigned int * nbor_list_ptr, const ParticleType* pstruct) + : m_index(start), m_stop(stop), m_nbor_list_ptr(nbor_list_ptr), m_pstruct(pstruct) + {} + + AMREX_GPU_HOST_DEVICE + void operator++ () { ++m_index;; } + + AMREX_GPU_HOST_DEVICE + bool operator!= (const_iterator const& rhs) const { return m_index < m_stop; } + AMREX_GPU_HOST_DEVICE - ParticleType operator* () const { return m_pstruct[m_nbor_list_ptr[m_index]]; } - + const ParticleType& operator* () const { return m_pstruct[m_nbor_list_ptr[m_index]]; } + private: int m_index; int m_stop; const unsigned int* m_nbor_list_ptr; const ParticleType* m_pstruct; }; - + AMREX_GPU_HOST_DEVICE - iterator begin () const { - return iterator(m_nbor_offsets_ptr[m_i], m_nbor_offsets_ptr[m_i+1], + iterator begin () noexcept { + return iterator(m_nbor_offsets_ptr[m_i], m_nbor_offsets_ptr[m_i+1], m_nbor_list_ptr, m_pstruct); } AMREX_GPU_HOST_DEVICE - iterator end () const { - return iterator(m_nbor_offsets_ptr[m_i+1], m_nbor_offsets_ptr[m_i+1], + iterator end () noexcept { + return iterator(m_nbor_offsets_ptr[m_i+1], m_nbor_offsets_ptr[m_i+1], m_nbor_list_ptr, m_pstruct); } - AMREX_GPU_HOST_DEVICE + AMREX_GPU_HOST_DEVICE + const_iterator begin () const noexcept { + return const_iterator(m_nbor_offsets_ptr[m_i], m_nbor_offsets_ptr[m_i+1], + m_nbor_list_ptr, m_pstruct); + } + + AMREX_GPU_HOST_DEVICE + const_iterator end () const noexcept { + return const_iterator(m_nbor_offsets_ptr[m_i+1], m_nbor_offsets_ptr[m_i+1], + m_nbor_list_ptr, m_pstruct); + } + + AMREX_GPU_HOST_DEVICE + const_iterator cbegin () const noexcept { + return const_iterator(m_nbor_offsets_ptr[m_i], m_nbor_offsets_ptr[m_i+1], + m_nbor_list_ptr, m_pstruct); + } + + AMREX_GPU_HOST_DEVICE + const_iterator cend () const noexcept { + return const_iterator(m_nbor_offsets_ptr[m_i+1], m_nbor_offsets_ptr[m_i+1], + m_nbor_list_ptr, m_pstruct); + } + + AMREX_GPU_HOST_DEVICE Neighbors (int i, const unsigned int *nbor_offsets_ptr, const unsigned int *nbor_list_ptr, - const ParticleType* pstruct) + ParticleType* pstruct) : m_i(i), m_nbor_offsets_ptr(nbor_offsets_ptr), m_nbor_list_ptr(nbor_list_ptr), m_pstruct(pstruct) {} - + private: const int m_i; const unsigned int * m_nbor_offsets_ptr; const unsigned int * m_nbor_list_ptr; - const ParticleType * m_pstruct; + ParticleType * m_pstruct; }; template struct NeighborData { - NeighborData (const Gpu::DeviceVector& offsets, + NeighborData (const Gpu::DeviceVector& offsets, const Gpu::DeviceVector& list, - const ParticleType* pstruct) + ParticleType* pstruct) : m_nbor_offsets_ptr(offsets.dataPtr()), m_nbor_list_ptr(list.dataPtr()), m_pstruct(pstruct) {} - + AMREX_GPU_HOST_DEVICE amrex::Neighbors getNeighbors (int i) const { return Neighbors(i, m_nbor_offsets_ptr, m_nbor_list_ptr, m_pstruct); } - + const unsigned int * m_nbor_offsets_ptr; const unsigned int * m_nbor_list_ptr; - const ParticleType * m_pstruct; + ParticleType * m_pstruct; }; template @@ -89,20 +136,20 @@ class NeighborList public: template - void build (const PTile& ptile, + void build (PTile& ptile, const amrex::Box& bx, const amrex::Geometry& geom, CheckPair check_pair, int num_cells=1) { - const auto& vec = ptile.GetArrayOfStructs()(); + auto& vec = ptile.GetArrayOfStructs()(); m_pstruct = vec.dataPtr(); - + const auto dxi = geom.InvCellSizeArray(); const auto plo = geom.ProbLoArray(); - + const size_t np_real = ptile.numRealParticles(); const size_t np_total = vec.size(); const ParticleType* pstruct_ptr = vec.dataPtr(); - + const auto lo = lbound(bx); const auto hi = ubound(bx); m_bins.build(np_total, pstruct_ptr, bx, @@ -111,7 +158,7 @@ public: AMREX_D_TERM(AMREX_ASSERT((p.pos(0)-plo[0])*dxi[0] - lo.x >= 0.0);, AMREX_ASSERT((p.pos(1)-plo[1])*dxi[1] - lo.y >= 0.0);, AMREX_ASSERT((p.pos(2)-plo[2])*dxi[2] - lo.z >= 0.0)); - + return IntVect(AMREX_D_DECL(static_cast((p.pos(0)-plo[0])*dxi[0] - lo.x), static_cast((p.pos(1)-plo[1])*dxi[1] - lo.y), static_cast((p.pos(2)-plo[2])*dxi[2] - lo.z))); @@ -131,13 +178,13 @@ public: int ix = (pstruct_ptr[i].pos(0)-plo[0])*dxi[0] - lo.x; int iy = (pstruct_ptr[i].pos(1)-plo[1])*dxi[1] - lo.y; int iz = (pstruct_ptr[i].pos(2)-plo[2])*dxi[2] - lo.z; - + int nx = hi.x-lo.x+1; int ny = hi.y-lo.y+1; - int nz = hi.z-lo.z+1; - + int nz = hi.z-lo.z+1; + int count = 0; - + for (int ii = amrex::max(ix-num_cells, 0); ii <= amrex::min(ix+num_cells, nx-1); ++ii) { for (int jj = amrex::max(iy-num_cells, 0); jj <= amrex::min(iy+num_cells, ny-1); ++jj) { for (int kk = amrex::max(iz-num_cells, 0); kk <= amrex::min(iz+num_cells, nz-1); ++kk) { @@ -173,12 +220,12 @@ public: int ix = (pstruct_ptr[i].pos(0)-plo[0])*dxi[0] - lo.x; int iy = (pstruct_ptr[i].pos(1)-plo[1])*dxi[1] - lo.y; int iz = (pstruct_ptr[i].pos(2)-plo[2])*dxi[2] - lo.z; - + int nx = hi.x-lo.x+1; int ny = hi.y-lo.y+1; - int nz = hi.z-lo.z+1; - - int n = 0; + int nz = hi.z-lo.z+1; + + int n = 0; for (int ii = amrex::max(ix-num_cells, 0); ii <= amrex::min(ix+num_cells, nx-1); ++ii) { for (int jj = amrex::max(iy-num_cells, 0); jj <= amrex::min(iy+num_cells, ny-1); ++jj) { for (int kk = amrex::max(iz-num_cells, 0); kk <= amrex::min(iz+num_cells, nz-1); ++kk) { @@ -186,7 +233,7 @@ public: for (auto p = poffset[index]; p < poffset[index+1]; ++p) { if (pperm[p] == i) continue; if (check_pair(pstruct_ptr[i], pstruct_ptr[pperm[p]])) { - pm_nbor_list[pnbor_offset[i] + n] = pperm[p]; + pm_nbor_list[pnbor_offset[i] + n] = pperm[p]; ++n; } } @@ -195,10 +242,10 @@ public: } }); } - - NeighborData data () - { - return NeighborData(m_nbor_offsets, m_nbor_list, m_pstruct); + + NeighborData data () + { + return NeighborData(m_nbor_offsets, m_nbor_list, m_pstruct); } int numParticles () { return m_nbor_offsets.size() - 1; } @@ -211,17 +258,17 @@ public: Gpu::DeviceVector& GetList () { return m_nbor_list; } const Gpu::DeviceVector& GetList () const { return m_nbor_list; } - + void print () { BL_PROFILE("NeighborList::print"); - + Gpu::HostVector host_nbor_offsets(m_nbor_offsets.size()); Gpu::HostVector host_nbor_list(m_nbor_list.size()); - - Gpu::copy(Gpu::deviceToHost, m_nbor_offsets.begin(), m_nbor_offsets.end(), host_nbor_offsets.begin()); + + Gpu::copy(Gpu::deviceToHost, m_nbor_offsets.begin(), m_nbor_offsets.end(), host_nbor_offsets.begin()); Gpu::copy(Gpu::deviceToHost, m_nbor_list.begin(), m_nbor_list.end(), host_nbor_list.begin()); - + for (int i = 0; i < numParticles(); ++i) { amrex::Print() << "Particle " << i << " could collide with: "; for (int j = host_nbor_offsets[i]; j < host_nbor_offsets[i+1]; ++j) { @@ -232,14 +279,14 @@ public: } protected: - - const ParticleType* m_pstruct; + + ParticleType* m_pstruct; // This is the neighbor list data structure Gpu::DeviceVector m_nbor_offsets; Gpu::DeviceVector m_nbor_list; Gpu::DeviceVector m_nbor_counts; - + DenseBins m_bins; }; diff --git a/Tests/Particles/NeighborParticles/MDParticleContainer.cpp b/Tests/Particles/NeighborParticles/MDParticleContainer.cpp index 1a06253c5fa..cdcbca3d611 100644 --- a/Tests/Particles/NeighborParticles/MDParticleContainer.cpp +++ b/Tests/Particles/NeighborParticles/MDParticleContainer.cpp @@ -141,15 +141,15 @@ std::pair MDParticleContainer::minAndMaxDistance() ParticleType& p1 = pstruct[i]; for (const auto& p2 : nbor_data.getNeighbors(i)) - { + { Real dx = p1.pos(0) - p2.pos(0); Real dy = p1.pos(1) - p2.pos(1); Real dz = p1.pos(2) - p2.pos(2); - + Real r2 = dx*dx + dy*dy + dz*dz; r2 = amrex::max(r2, Params::min_r*Params::min_r); Real r = sqrt(r2); - + Gpu::Atomic::Min(pmin_d, r); Gpu::Atomic::Max(pmax_d, r); }