@@ -919,7 +919,7 @@ ParticleContainer_impl<ParticleType, NArrayReal, NArrayInt, Allocator>
919919 int * iptr = istuff.dataPtr ();
920920 RTYPE* rptr = rstuff.dataPtr ();
921921
922- ParticleType p ;
922+ Particle<NStructReal, NStructInt> ptemp ;
923923 ParticleLocData pld;
924924
925925 Vector<std::map<std::pair<int , int >, Gpu::HostVector<ParticleType> > > host_particles;
@@ -937,77 +937,113 @@ ParticleContainer_impl<ParticleType, NArrayReal, NArrayInt, Allocator>
937937 host_int_attribs.resize (finest_level_in_file+1 );
938938
939939 for (int i = 0 ; i < cnt; i++) {
940- if (convert_ids) {
940+ // note: for pure SoA particle layouts, we do write the id, cpu and positions as a struct
941+ // for backwards compatibility with readers
942+ if (!ParticleType::is_soa_particle && convert_ids) {
941943 std::int32_t xi, yi;
942944 std::uint32_t xu, yu;
943945 xi = iptr[0 ];
944946 yi = iptr[1 ];
945947 std::memcpy (&xu, &xi, sizeof (xi));
946948 std::memcpy (&yu, &yi, sizeof (yi));
947- p .m_idcpu = ((std::uint64_t )xu) << 32 | yu;
949+ ptemp .m_idcpu = ((std::uint64_t )xu) << 32 | yu;
948950 } else {
949- p .id () = iptr[0 ];
950- p .cpu () = iptr[1 ];
951+ ptemp .id () = iptr[0 ];
952+ ptemp .cpu () = iptr[1 ];
951953 }
952954 iptr += 2 ;
953955
954956 for (int j = 0 ; j < NStructInt; j++)
955957 {
956- p .idata (j) = *iptr;
958+ ptemp .idata (j) = *iptr;
957959 ++iptr;
958960 }
959961
960- AMREX_ASSERT (p .id () > 0 );
962+ AMREX_ASSERT (ptemp .id () > 0 );
961963
962- AMREX_D_TERM (p .pos (0 ) = ParticleReal (rptr[0 ]);,
963- p .pos (1 ) = ParticleReal (rptr[1 ]);,
964- p .pos (2 ) = ParticleReal (rptr[2 ]););
964+ AMREX_D_TERM (ptemp .pos (0 ) = ParticleReal (rptr[0 ]);,
965+ ptemp .pos (1 ) = ParticleReal (rptr[1 ]);,
966+ ptemp .pos (2 ) = ParticleReal (rptr[2 ]););
965967
966968 rptr += AMREX_SPACEDIM;
967969
968970 for (int j = 0 ; j < NStructReal; j++)
969971 {
970- p .rdata (j) = ParticleReal (*rptr);
972+ ptemp .rdata (j) = ParticleReal (*rptr);
971973 ++rptr;
972974 }
973975
974- locateParticle (p , pld, 0 , finestLevel (), 0 );
976+ locateParticle (ptemp , pld, 0 , finestLevel (), 0 );
975977
976978 std::pair<int , int > ind (grd, pld.m_tile );
977979
978980 host_real_attribs[lev][ind].resize (NumRealComps ());
979981 host_int_attribs[lev][ind].resize (NumIntComps ());
980982
981983 // add the struct
982- host_particles[lev][ind].push_back (p);
984+ if constexpr (!ParticleType::is_soa_particle)
985+ {
986+ host_particles[lev][ind].push_back (ptemp);
983987
984- // add the real...
985- for (int icomp = 0 ; icomp < NumRealComps (); icomp++) {
986- host_real_attribs[lev][ind][icomp].push_back (*rptr);
987- ++rptr;
988- }
988+ // add the real...
989+ for (int icomp = 0 ; icomp < NumRealComps (); icomp++) {
990+ host_real_attribs[lev][ind][icomp].push_back (*rptr);
991+ ++rptr;
992+ }
989993
990- // ... and int array data
991- for (int icomp = 0 ; icomp < NumIntComps (); icomp++) {
992- host_int_attribs[lev][ind][icomp].push_back (*iptr);
993- ++iptr;
994+ // ... and int array data
995+ for (int icomp = 0 ; icomp < NumIntComps (); icomp++) {
996+ host_int_attribs[lev][ind][icomp].push_back (*iptr);
997+ ++iptr;
998+ }
999+ } else {
1000+ host_particles[lev][ind];
1001+
1002+ for (int j = 0 ; j < AMREX_SPACEDIM; j++) {
1003+ host_real_attribs[pld.m_lev ][ind][j].push_back (ptemp.pos (j));
1004+ }
1005+
1006+ host_int_attribs[pld.m_lev ][ind][0 ].push_back (ptemp.id ());
1007+ host_int_attribs[pld.m_lev ][ind][1 ].push_back (ptemp.cpu ());
1008+
1009+ // read all other SoA
1010+ // add the real...
1011+ for (int icomp = AMREX_SPACEDIM; icomp < NumRealComps (); icomp++) {
1012+ host_real_attribs[lev][ind][icomp].push_back (*rptr);
1013+ ++rptr;
1014+ }
1015+
1016+ // ... and int array data
1017+ for (int icomp = 2 ; icomp < NumIntComps (); icomp++) {
1018+ host_int_attribs[lev][ind][icomp].push_back (*iptr);
1019+ ++iptr;
1020+ }
9941021 }
9951022 }
9961023
9971024 for (int host_lev = 0 ; host_lev < static_cast <int >(host_particles.size ()); ++host_lev)
998- {
1025+ {
9991026 for (auto & kv : host_particles[host_lev]) {
10001027 auto grid = kv.first .first ;
10011028 auto tile = kv.first .second ;
10021029 const auto & src_tile = kv.second ;
10031030
10041031 auto & dst_tile = DefineAndReturnParticleTile (host_lev, grid, tile);
1005- auto old_size = dst_tile.GetArrayOfStructs ().size ();
1006- auto new_size = old_size + src_tile.size ();
1032+ auto old_size = dst_tile.size ();
1033+ auto new_size = old_size;
1034+ if constexpr (!ParticleType::is_soa_particle)
1035+ {
1036+ new_size += src_tile.size ();
1037+ } else {
1038+ new_size += host_real_attribs[host_lev][std::make_pair (grid,tile)][0 ].size ();
1039+ }
10071040 dst_tile.resize (new_size);
10081041
1009- Gpu::copyAsync (Gpu::hostToDevice, src_tile.begin (), src_tile.end (),
1010- dst_tile.GetArrayOfStructs ().begin () + old_size);
1042+ if constexpr (!ParticleType::is_soa_particle)
1043+ {
1044+ Gpu::copyAsync (Gpu::hostToDevice, src_tile.begin (), src_tile.end (),
1045+ dst_tile.GetArrayOfStructs ().begin () + old_size);
1046+ }
10111047
10121048 for (int i = 0 ; i < NumRealComps (); ++i) {
10131049 Gpu::copyAsync (Gpu::hostToDevice,
0 commit comments