From c4268f4cffb8fea77ef082e475f0f0e290992c3a Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 19 Apr 2023 00:27:00 -0700 Subject: [PATCH] Update Particle Container to Pure SoA Transition particle containers to pure SoA layouts. --- cmake/dependencies/ABLASTR.cmake | 4 +- src/particles/ImpactXParticleContainer.H | 49 +++++++---- src/particles/ImpactXParticleContainer.cpp | 43 ++++------ .../diagnostics/DiagnosticOutput.cpp | 34 +++----- .../elements/diagnostics/openPMD.cpp | 86 ++++++++----------- src/particles/elements/mixin/beamoptic.H | 24 +++--- .../CoordinateTransformation.cpp | 12 +-- src/python/ImpactXParticleContainer.cpp | 18 ++-- 8 files changed, 127 insertions(+), 143 deletions(-) diff --git a/cmake/dependencies/ABLASTR.cmake b/cmake/dependencies/ABLASTR.cmake index 134829094..d50e7c7fd 100644 --- a/cmake/dependencies/ABLASTR.cmake +++ b/cmake/dependencies/ABLASTR.cmake @@ -166,10 +166,10 @@ set(ImpactX_openpmd_src "" "Local path to openPMD-api source directory (preferred if set)") # Git fetcher -set(ImpactX_ablastr_repo "https://github.com/ECP-WarpX/WarpX.git" +set(ImpactX_ablastr_repo "https://github.com/ax3l/WarpX.git" CACHE STRING "Repository URI to pull and build ABLASTR from if(ImpactX_ablastr_internal)") -set(ImpactX_ablastr_branch "f71597fca2cf9d3700e7e11533f4a85a1846a2b8" +set(ImpactX_ablastr_branch "topic-particle-soa" CACHE STRING "Repository branch for ImpactX_ablastr_repo if(ImpactX_ablastr_internal)") diff --git a/src/particles/ImpactXParticleContainer.H b/src/particles/ImpactXParticleContainer.H index 40eaa2938..f484d28bb 100644 --- a/src/particles/ImpactXParticleContainer.H +++ b/src/particles/ImpactXParticleContainer.H @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,7 @@ namespace impactx * because we change the meaning of these "positions" depending on the * coordinate system we are currently in. */ + /* struct RealAoS { enum @@ -52,6 +54,7 @@ namespace impactx static_assert(names_t.size() == nattribs); static_assert(names_s.size() == nattribs); }; + */ /** This struct indexes the additional Real attributes * stored in an SoA in ImpactXParticleContainer @@ -60,18 +63,21 @@ namespace impactx { enum { + x, ///< position in x [m] (at fixed t OR fixed s) + y, ///< position in y [m] (at fixed t OR fixed s) + z, ///< position in z [m] (at fixed t) OR time-of-flight ct [m] (at fixed s) ux, ///< momentum in x, scaled by the magnitude of the reference momentum [unitless] (at fixed t or s) uy, ///< momentum in y, scaled by the magnitude of the reference momentum [unitless] (at fixed t or s) pt, ///< momentum in z, scaled by the magnitude of the reference momentum [unitless] (at fixed t) OR energy deviation, scaled by speed of light * the magnitude of the reference momentum [unitless] (at fixed s) m_qm, ///< charge to mass ratio, in q_e/m_e (q_e/eV) TODO: rename to qm_m - w, ///< particle weight, unitless + w, ///< particle weight, unitless nattribs ///< the number of attributes above (always last) }; //! named labels for fixed t - static constexpr auto names_t = { "momentum_x", "momentum_y", "momentum_z", "qmm", "weighting" }; + static constexpr auto names_t = { "position_x", "position_y", "position_z", "momentum_x", "momentum_y", "momentum_z", "qmm", "weighting" }; //! named labels for fixed s - static constexpr auto names_s = { "momentum_x", "momentum_y", "momentum_t", "qmm", "weighting" }; + static constexpr auto names_s = { "position_x", "position_y", "position_ct", "momentum_x", "momentum_y", "momentum_t", "qmm", "weighting" }; static_assert(names_t.size() == nattribs); static_assert(names_s.size() == nattribs); }; @@ -83,8 +89,17 @@ namespace impactx { enum { - nattribs ///< the number of particles above (always last) + id, + cpu, + nattribs ///< the number of attributes above (always last) }; + + //! named labels for fixed t + static constexpr auto names_t = { "id", "cpu" }; + //! named labels for fixed s + static constexpr auto names_s = { "id", "cpu" }; + static_assert(names_t.size() == nattribs); + static_assert(names_s.size() == nattribs); }; /** AMReX iterator for particle boxes @@ -92,15 +107,15 @@ namespace impactx * We subclass here to change the default threading strategy, which is * `static` in AMReX, to `dynamic` in ImpactX. */ - class ParIter - : public amrex::ParIter<0, 0, RealSoA::nattribs, IntSoA::nattribs> + class ParIterSoA + : public amrex::ParIterSoA { public: - using amrex::ParIter<0, 0, RealSoA::nattribs, IntSoA::nattribs>::ParIter; + using amrex::ParIterSoA::ParIterSoA; - ParIter (ContainerType& pc, int level); + ParIterSoA (ContainerType& pc, int level); - ParIter (ContainerType& pc, int level, amrex::MFItInfo& info); + ParIterSoA (ContainerType& pc, int level, amrex::MFItInfo& info); }; /** Const AMReX iterator for particle boxes - data is read only. @@ -108,15 +123,15 @@ namespace impactx * We subclass here to change the default threading strategy, which is * `static` in AMReX, to `dynamic` in ImpactX. */ - class ParConstIter - : public amrex::ParConstIter<0, 0, RealSoA::nattribs, IntSoA::nattribs> + class ParConstIterSoA + : public amrex::ParConstIterSoA { public: - using amrex::ParConstIter<0, 0, RealSoA::nattribs, IntSoA::nattribs>::ParConstIter; + using amrex::ParConstIterSoA::ParConstIterSoA; - ParConstIter (ContainerType& pc, int level); + ParConstIterSoA (ContainerType& pc, int level); - ParConstIter (ContainerType& pc, int level, amrex::MFItInfo& info); + ParConstIterSoA (ContainerType& pc, int level, amrex::MFItInfo& info); }; /** Beam Particles in ImpactX @@ -124,14 +139,14 @@ namespace impactx * This class stores particles, distributed over MPI ranks. */ class ImpactXParticleContainer - : public amrex::ParticleContainer<0, 0, RealSoA::nattribs, IntSoA::nattribs> + : public amrex::ParticleContainerPureSoA { public: //! amrex iterator for particle boxes - using iterator = impactx::ParIter; + using iterator = impactx::ParIterSoA; //! amrex constant iterator for particle boxes (read-only) - using const_iterator = impactx::ParConstIter; + using const_iterator = impactx::ParConstIterSoA; //! Construct a new particle container ImpactXParticleContainer (amrex::AmrCore* amr_core); diff --git a/src/particles/ImpactXParticleContainer.cpp b/src/particles/ImpactXParticleContainer.cpp index 6056183d6..a00292f21 100644 --- a/src/particles/ImpactXParticleContainer.cpp +++ b/src/particles/ImpactXParticleContainer.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include @@ -31,24 +30,24 @@ namespace impactx return do_dynamic; } - ParIter::ParIter (ContainerType& pc, int level) - : amrex::ParIter<0, 0, RealSoA::nattribs, IntSoA::nattribs>(pc, level, + ParIterSoA::ParIterSoA (ContainerType& pc, int level) + : amrex::ParIterSoA(pc, level, amrex::MFItInfo().SetDynamic(do_omp_dynamic())) {} - ParIter::ParIter (ContainerType& pc, int level, amrex::MFItInfo& info) - : amrex::ParIter<0, 0, RealSoA::nattribs, IntSoA::nattribs>(pc, level, + ParIterSoA::ParIterSoA (ContainerType& pc, int level, amrex::MFItInfo& info) + : amrex::ParIterSoA(pc, level, info.SetDynamic(do_omp_dynamic())) {} - ParConstIter::ParConstIter (ContainerType& pc, int level) - : amrex::ParConstIter<0, 0, RealSoA::nattribs, IntSoA::nattribs>(pc, level, + ParConstIterSoA::ParConstIterSoA (ContainerType& pc, int level) + : amrex::ParConstIterSoA(pc, level, amrex::MFItInfo().SetDynamic(do_omp_dynamic())) {} - ParConstIter::ParConstIter (ContainerType& pc, int level, amrex::MFItInfo& info) - : amrex::ParConstIter<0, 0, RealSoA::nattribs, IntSoA::nattribs>(pc, level, + ParConstIterSoA::ParConstIterSoA (ContainerType& pc, int level, amrex::MFItInfo& info) + : amrex::ParConstIterSoA(pc, level, info.SetDynamic(do_omp_dynamic())) {} ImpactXParticleContainer::ImpactXParticleContainer (amrex::AmrCore* amr_core) - : amrex::ParticleContainer<0, 0, RealSoA::nattribs, IntSoA::nattribs>(amr_core->GetParGDB()) + : amrex::ParticleContainerPureSoA(amr_core->GetParGDB()) { SetParticleSize(); } @@ -105,35 +104,26 @@ namespace impactx reserveData(); resizeData(); + // write Real attributes (SoA) to particle initialized zero auto& particle_tile = DefineAndReturnParticleTile(0, 0, 0); /* Create a temporary tile to obtain data from simulation. This data * is then copied to the permanent tile which is stored on the particle * (particle_tile). */ - using PinnedTile = amrex::ParticleTile< - amrex::Particle, - NArrayReal, NArrayInt, - amrex::PinnedArenaAllocator - >; + using PinnedTile = typename ContainerLike::ParticleTileType; PinnedTile pinned_tile; pinned_tile.define(NumRuntimeRealComps(), NumRuntimeIntComps()); for (int i = 0; i < np; i++) { - ParticleType p; - p.id() = ParticleType::NextID(); - p.cpu() = amrex::ParallelDescriptor::MyProc(); - p.pos(0) = x[i]; - p.pos(1) = y[i]; - p.pos(2) = z[i]; - // write position, creating cpu id, and particle id - pinned_tile.push_back(p); + pinned_tile.push_back_int(IntSoA::id, ParticleType::NextID()); + pinned_tile.push_back_int(IntSoA::cpu, amrex::ParallelDescriptor::MyProc()); } - // write Real attributes (SoA) to particle initialized zero - DefineAndReturnParticleTile(0, 0, 0); - + pinned_tile.push_back_real(RealSoA::x, x); + pinned_tile.push_back_real(RealSoA::y, y); + pinned_tile.push_back_real(RealSoA::z, z); pinned_tile.push_back_real(RealSoA::ux, px); pinned_tile.push_back_real(RealSoA::uy, py); pinned_tile.push_back_real(RealSoA::pt, pz); @@ -145,6 +135,7 @@ namespace impactx */ auto old_np = particle_tile.numParticles(); auto new_np = old_np + pinned_tile.numParticles(); + amrex::AllPrint() << "old_np=" << old_np << " new_np=" << new_np << "\n"; particle_tile.resize(new_np); amrex::copyParticles( particle_tile, pinned_tile, 0, old_np, pinned_tile.numParticles()); diff --git a/src/particles/diagnostics/DiagnosticOutput.cpp b/src/particles/diagnostics/DiagnosticOutput.cpp index 0af5f3b7a..ee7366bf8 100644 --- a/src/particles/diagnostics/DiagnosticOutput.cpp +++ b/src/particles/diagnostics/DiagnosticOutput.cpp @@ -17,6 +17,7 @@ #include // for ParmParse #include // for ParticleReal #include // for PrintToFile +#include // for constructor of SoAParticle namespace impactx::diagnostics @@ -46,7 +47,8 @@ namespace impactx::diagnostics } // create a host-side particle buffer - auto tmp = pc.make_alike(); + using ParticleType = amrex::SoAParticle; + auto tmp = pc.template make_alike(); // copy device-to-host bool const local = true; @@ -56,34 +58,29 @@ namespace impactx::diagnostics int const nLevel = tmp.finestLevel(); for (int lev = 0; lev <= nLevel; ++lev) { // loop over all particle boxes - using ParIt = typename decltype(tmp)::ParConstIterType; - for (ParIt pti(tmp, lev); pti.isValid(); ++pti) { + using MyPinnedParIter = amrex::ParIterSoA; + for (MyPinnedParIter pti(tmp, lev); pti.isValid(); ++pti) { const int np = pti.numParticles(); - // preparing access to particle data: AoS - using PType = ImpactXParticleContainer::ParticleType; - auto const &aos = pti.GetArrayOfStructs(); - PType const *const AMREX_RESTRICT aos_ptr = aos().dataPtr(); - // preparing access to particle data: SoA of Reals - auto &soa_real = pti.GetStructOfArrays().GetRealData(); - amrex::ParticleReal const *const AMREX_RESTRICT part_px = soa_real[RealSoA::ux].dataPtr(); - amrex::ParticleReal const *const AMREX_RESTRICT part_py = soa_real[RealSoA::uy].dataPtr(); - amrex::ParticleReal const *const AMREX_RESTRICT part_pt = soa_real[RealSoA::pt].dataPtr(); + auto const& particle_attributes = pti.GetStructOfArrays(); + auto const& part_px = particle_attributes.GetRealData(RealSoA::ux); + auto const& part_py = particle_attributes.GetRealData(RealSoA::uy); + auto const& part_pt = particle_attributes.GetRealData(RealSoA::pt); + + // Preparing the constructor for the new SoA Particle Type + auto ptd = pti.GetParticleTile().getParticleTileData(); if (otype == OutputType::PrintParticles) { // print out particles (this hack works only on CPU and on GPUs with // unified memory access) for (int i = 0; i < np; ++i) { - - // access AoS data such as positions and cpu/id - PType const &p = aos_ptr[i]; + ParticleType p(ptd, i); amrex::ParticleReal const x = p.pos(0); amrex::ParticleReal const y = p.pos(1); amrex::ParticleReal const t = p.pos(2); uint64_t const global_id = ablastr::particles::localIDtoGlobal(p.id(), p.cpu()); - // access SoA Real data amrex::ParticleReal const px = part_px[i]; amrex::ParticleReal const py = part_py[i]; amrex::ParticleReal const pt = part_pt[i]; @@ -119,14 +116,11 @@ namespace impactx::diagnostics // print out particles (this hack works only on CPU and on GPUs with // unified memory access) for (int i = 0; i < np; ++i) { - - // access AoS data such as positions and cpu/id - PType const &p = aos_ptr[i]; + ParticleType p(ptd, i); amrex::ParticleReal const x = p.pos(0); amrex::ParticleReal const y = p.pos(1); uint64_t const global_id = ablastr::particles::localIDtoGlobal(p.id(), p.cpu()); - // access SoA Real data amrex::ParticleReal const px = part_px[i]; amrex::ParticleReal const py = part_py[i]; diff --git a/src/particles/elements/diagnostics/openPMD.cpp b/src/particles/elements/diagnostics/openPMD.cpp index 310fae05d..1e5a45c6a 100644 --- a/src/particles/elements/diagnostics/openPMD.cpp +++ b/src/particles/elements/diagnostics/openPMD.cpp @@ -241,20 +241,10 @@ namespace detail // define data set and metadata io::Datatype dtype_fl = io::determineDatatype(); io::Datatype dtype_ui = io::determineDatatype(); + io::Datatype dtype_in = io::determineDatatype(); auto d_fl = io::Dataset(dtype_fl, {np}); auto d_ui = io::Dataset(dtype_ui, {np}); - - // AoS: Real - { - std::vector real_aos_names(RealAoS::names_s.size()); - std::copy(RealAoS::names_s.begin(), RealAoS::names_s.end(), real_aos_names.begin()); - for (auto real_idx=0; real_idx < RealAoS::nattribs; real_idx++) { - auto const component_name = real_aos_names.at(real_idx); - getComponentRecord(component_name).resetDataset(d_fl); - } - } - // AoS: Int - beam["id"][scalar].resetDataset(d_ui); + auto d_in = io::Dataset(dtype_in, {np}); // SoA: Real { @@ -266,7 +256,19 @@ namespace detail } } // SoA: Int - static_assert(IntSoA::nattribs == 0); // not yet used + { + // special case: id & cpu to openPMD int64 id + beam["id"][scalar].resetDataset(d_ui); + + // all other int properties + int const skip = 2; // skip: id, cpu + std::vector int_soa_names(IntSoA::names_s.size()); + std::copy(IntSoA::names_s.begin(), IntSoA::names_s.end(), int_soa_names.begin()); + for (auto int_idx = skip; int_idx < IntSoA::nattribs; int_idx++) { + auto const component_name = int_soa_names.at(int_idx); + getComponentRecord(component_name).resetDataset(d_in); + } + } #else amrex::ignore_unused(pc, step); #endif @@ -334,9 +336,6 @@ namespace detail auto & offset = m_offset.at(currentLevel); // ... - // preparing access to particle data: AoS - auto& aos = pti.GetArrayOfStructs(); - // series & iteration auto series = std::any_cast(m_series); io::WriteIterations iterations = series.writeIterations(); @@ -357,35 +356,7 @@ namespace detail return detail::get_component_record(beam, comp_name); }; - // AoS: position and particle ID - { - using vs = std::vector; - vs const positionComponents{"x", "y", "ct"}; // TODO: generalize - for (auto currDim = 0; currDim < AMREX_SPACEDIM; currDim++) { - std::shared_ptr curr( - new amrex::ParticleReal[numParticleOnTile], - [](amrex::ParticleReal const *p) { delete[] p; } - ); - for (auto i = 0; i < numParticleOnTile; i++) { - curr.get()[i] = aos[i].pos(currDim); - } - std::string const positionComponent = positionComponents[currDim]; - beam["position"][positionComponent].storeChunk(curr, {offset}, - {numParticleOnTile64}); - } - - // save particle ID after converting it to a globally unique ID - std::shared_ptr ids( - new uint64_t[numParticleOnTile], - [](uint64_t const *p) { delete[] p; } - ); - for (auto i = 0; i < numParticleOnTile; i++) { - ids.get()[i] = ablastr::particles::localIDtoGlobal(aos[i].id(), aos[i].cpu()); - } - beam["id"][scalar].storeChunk(ids, {offset}, {numParticleOnTile64}); - } - - // SoA: everything else + // SoA auto const& soa = pti.GetStructOfArrays(); // SoA floating point (ParticleReal) properties { @@ -394,25 +365,36 @@ namespace detail for (auto real_idx=0; real_idx < RealSoA::nattribs; real_idx++) { auto const component_name = real_soa_names.at(real_idx); + amrex::Print() << real_idx << " " << component_name << "\n"; getComponentRecord(component_name).storeChunkRaw( soa.GetRealData(real_idx).data(), {offset}, {numParticleOnTile64}); } } - // SoA integer (int) properties (not yet used) + // SoA integer (int) properties { - static_assert(IntSoA::nattribs == 0); // not yet used - /* - // comment this in once IntSoA::nattribs is > 0 + // special case: id & cpu to openPMD int64 id + std::shared_ptr ids( + new uint64_t[numParticleOnTile], + [](uint64_t const *p) { delete[] p; } + ); + for (auto i = 0; i < numParticleOnTile; i++) { + ids.get()[i] = ablastr::particles::localIDtoGlobal( + soa.GetIntData(IntSoA::id).data()[i], + soa.GetIntData(IntSoA::cpu).data()[i] + ); + } + beam["id"][scalar].storeChunk(ids, {offset}, {numParticleOnTile64}); - std::vector int_soa_names(IntSoA::names_s.size); + // all other int properties + int const skip = 2; // skip: id, cpu + std::vector int_soa_names(IntSoA::names_s.size()); std::copy(IntSoA::names_s.begin(), IntSoA::names_s.end(), int_soa_names.begin()); - for (auto int_idx=0; int_idx < RealSoA::nattribs; int_idx++) { + for (auto int_idx= skip; int_idx < IntSoA::nattribs; int_idx++) { auto const component_name = int_soa_names.at(int_idx); getComponentRecord(component_name).storeChunkRaw( soa.GetIntData(int_idx).data(), {offset}, {numParticleOnTile64}); } - */ } // TODO diff --git a/src/particles/elements/mixin/beamoptic.H b/src/particles/elements/mixin/beamoptic.H index 4461558bd..a7ab34d41 100644 --- a/src/particles/elements/mixin/beamoptic.H +++ b/src/particles/elements/mixin/beamoptic.H @@ -40,23 +40,25 @@ namespace detail struct PushSingleParticle { using PType = ImpactXParticleContainer::ParticleType; + using ParticleTileType = amrex::ParticleTile,RealSoA::nattribs, IntSoA::nattribs>; + using ParticleTileDataType = amrex::ParticleTileData; /** Constructor taking in pointers to particle data * * @param element the beamline element to push through - * @param aos_ptr the array-of-struct with position and ids + * @param ptd particle data tile * @param part_px the array to the particle momentum (x) * @param part_py the array to the particle momentum (y) * @param part_pt the array to the particle momentum (t) * @param ref_part the struct containing the reference particle */ PushSingleParticle (T_Element element, - PType* AMREX_RESTRICT aos_ptr, + ParticleTileDataType& AMREX_RESTRICT ptd, amrex::ParticleReal* AMREX_RESTRICT part_px, amrex::ParticleReal* AMREX_RESTRICT part_py, amrex::ParticleReal* AMREX_RESTRICT part_pt, RefPart ref_part) - : m_element(std::move(element)), m_aos_ptr(aos_ptr), + : m_element(std::move(element)), m_ptd(ptd), m_part_px(part_px), m_part_py(part_py), m_part_pt(part_pt), m_ref_part(std::move(ref_part)) { @@ -75,8 +77,7 @@ namespace detail void operator() (long i) const { - // access AoS data such as positions and cpu/id - PType& AMREX_RESTRICT p = m_aos_ptr[i]; + PType p(m_ptd, i); // access SoA Real data amrex::ParticleReal & AMREX_RESTRICT px = m_part_px[i]; @@ -90,7 +91,7 @@ namespace detail private: T_Element const m_element; - PType* const AMREX_RESTRICT m_aos_ptr; + ParticleTileDataType const m_ptd; amrex::ParticleReal* const AMREX_RESTRICT m_part_px; amrex::ParticleReal* const AMREX_RESTRICT m_part_py; amrex::ParticleReal* const AMREX_RESTRICT m_part_pt; @@ -107,10 +108,11 @@ namespace detail ) { const int np = pti.numParticles(); - // preparing access to particle data: AoS - using PType = ImpactXParticleContainer::ParticleType; - auto& aos = pti.GetArrayOfStructs(); - PType* AMREX_RESTRICT aos_ptr = aos().dataPtr(); + // preparing access to particle data + using ParticleTile = amrex::ParticleTile,RealSoA::nattribs, IntSoA::nattribs>; + using ParticleTileDataType = amrex::ParticleTileData; + + ParticleTileDataType tile_data = pti.GetParticleTile().getParticleTileData(); // preparing access to particle data: SoA of Reals auto& soa_real = pti.GetStructOfArrays().GetRealData(); @@ -119,7 +121,7 @@ namespace detail amrex::ParticleReal* const AMREX_RESTRICT part_pt = soa_real[RealSoA::pt].dataPtr(); detail::PushSingleParticle const pushSingleParticle( - element, aos_ptr, part_px, part_py, part_pt, ref_part); + element, tile_data, part_px, part_py, part_pt, ref_part); // loop over beam particles in the box amrex::ParallelFor(np, pushSingleParticle); } diff --git a/src/particles/transformation/CoordinateTransformation.cpp b/src/particles/transformation/CoordinateTransformation.cpp index 35187be40..d5130ca82 100644 --- a/src/particles/transformation/CoordinateTransformation.cpp +++ b/src/particles/transformation/CoordinateTransformation.cpp @@ -43,10 +43,7 @@ namespace transformation { for (ParIt pti(pc, lev); pti.isValid(); ++pti) { const int np = pti.numParticles(); - // preparing access to particle data: AoS using PType = ImpactXParticleContainer::ParticleType; - auto &aos = pti.GetArrayOfStructs(); - PType *AMREX_RESTRICT aos_ptr = aos().dataPtr(); // preparing access to particle data: SoA of Reals auto &soa_real = pti.GetStructOfArrays().GetRealData(); @@ -60,9 +57,11 @@ namespace transformation { amrex::ParticleReal const pzd = sqrt(pow(pd, 2) - 1.0); ToFixedS const to_s(pzd); + auto tile_data = pti.GetParticleTile().getParticleTileData(); + amrex::ParallelFor(np, [=] AMREX_GPU_DEVICE(long i) { - // access AoS data such as positions and cpu/id - PType &p = aos_ptr[i]; + + PType p(tile_data,i); // access SoA Real data amrex::ParticleReal &px = part_px[i]; @@ -75,9 +74,10 @@ namespace transformation { BL_PROFILE("impactx::transformation::CoordinateTransformation::to_fixed_t"); amrex::ParticleReal const ptd = pd; // Design value of pt/mc2 = -gamma. ToFixedT const to_t(ptd); + auto tile_data = pti.GetParticleTile().getParticleTileData(); amrex::ParallelFor(np, [=] AMREX_GPU_DEVICE(long i) { // access AoS data such as positions and cpu/id - PType &p = aos_ptr[i]; + PType p(tile_data,i); // access SoA Real data amrex::ParticleReal &px = part_px[i]; diff --git a/src/python/ImpactXParticleContainer.cpp b/src/python/ImpactXParticleContainer.cpp index 983d3d206..34c9be0e1 100644 --- a/src/python/ImpactXParticleContainer.cpp +++ b/src/python/ImpactXParticleContainer.cpp @@ -17,28 +17,28 @@ using namespace impactx; void init_impactxparticlecontainer(py::module& m) { py::class_< - ParIter, - amrex::ParIter<0, 0, RealSoA::nattribs, IntSoA::nattribs> + ParIterSoA, + amrex::ParIterSoA >(m, "ImpactXParIter") - .def(py::init(), + .def(py::init(), py::arg("particle_container"), py::arg("level")) - .def(py::init(), + .def(py::init(), py::arg("particle_container"), py::arg("level"), py::arg("info")) ; py::class_< - ParConstIter, - amrex::ParConstIter<0, 0, RealSoA::nattribs, IntSoA::nattribs> + ParConstIterSoA, + amrex::ParConstIterSoA >(m, "ImpactXParConstIter") - .def(py::init(), + .def(py::init(), py::arg("particle_container"), py::arg("level")) - .def(py::init(), + .def(py::init(), py::arg("particle_container"), py::arg("level"), py::arg("info")) ; py::class_< ImpactXParticleContainer, - amrex::ParticleContainer<0, 0, RealSoA::nattribs, IntSoA::nattribs> + amrex::ParticleContainerPureSoA >(m, "ImpactXParticleContainer") //.def(py::init<>()) .def("add_n_particles",