@@ -103,33 +103,30 @@ namespace picongpu
103103
104104 auto numRanks = gc.getGlobalSize ();
105105
106- size_t patchIdx = getPatchIdx (params, particleSpecies);
106+ auto [fullMatches, partialMatches] = getPatchIdx (params, particleSpecies);
107107
108- std::shared_ptr<uint64_t > fullParticlesInfoShared
109- = particleSpecies.particlePatches [" numParticles" ][::openPMD::RecordComponent::SCALAR]
110- .load <uint64_t >();
111- particles.seriesFlush ();
112- uint64_t * fullParticlesInfo = fullParticlesInfoShared.get ();
113-
114- /* Run a prefix sum over the numParticles[0] element in
115- * particlesInfo to retreive the offset of particles
116- */
117- uint64_t particleOffset = 0u ;
118- /* count total number of particles on the device */
119- uint64_t totalNumParticles = 0u ;
120-
121- assert (patchIdx < numRanks);
122-
123- for (size_t i = 0u ; i <= patchIdx; ++i)
108+ if (!partialMatches.empty ())
124109 {
125- if (i < patchIdx )
126- particleOffset += fullParticlesInfo[i];
127- if (i == patchIdx)
128- totalNumParticles = fullParticlesInfo[i] ;
110+ std::cerr << " WARNING: Found " << partialMatches. size ( )
111+ << " particle patches that only partially intersect with the local domain. Will ignore "
112+ " this patch and lose those particles. "
113+ << std::endl ;
129114 }
130115
131- log<picLog::INPUT_OUTPUT>(" openPMD: Loading %1% particles from offset %2%" )
132- % (long long unsigned ) totalNumParticles % (long long unsigned ) particleOffset;
116+ std::shared_ptr<uint64_t > numParticlesShared
117+ = particleSpecies.particlePatches [" numParticles" ].load <uint64_t >();
118+ std::shared_ptr<uint64_t > numParticlesOffsetShared
119+ = particleSpecies.particlePatches [" numParticlesOffset" ].load <uint64_t >();
120+ particles.seriesFlush ();
121+ uint64_t * patchNumParticles = numParticlesShared.get ();
122+ uint64_t * patchNumParticlesOffset = numParticlesOffsetShared.get ();
123+
124+ uint64_t totalNumParticles = std::transform_reduce (
125+ fullMatches.begin (),
126+ fullMatches.end (),
127+ 0 ,
128+ /* reduce = */ [](uint64_t left, uint64_t right) { return left + right; },
129+ /* transform = */ [patchNumParticles](size_t patchIdx) { return patchNumParticles[patchIdx]; });
133130
134131 log<picLog::INPUT_OUTPUT>(" openPMD: malloc mapped memory: %1%" ) % speciesName;
135132
@@ -146,43 +143,53 @@ namespace picongpu
146143 mallocMem;
147144 mallocMem (buffers, mappedFrame, maxChunkSize);
148145
149- uint32_t const numLoadIterations
150- = maxChunkSize == 0u ? 0u : alpaka::core::divCeil (totalNumParticles, maxChunkSize);
151-
152- for (uint64_t loadRound = 0u ; loadRound < numLoadIterations; ++loadRound)
146+ for (size_t const patchIdx : fullMatches)
153147 {
154- auto particleLoadOffset = particleOffset + loadRound * maxChunkSize;
155- auto numLeftParticles = totalNumParticles - loadRound * maxChunkSize;
148+ uint64_t particleOffset = patchNumParticlesOffset[patchIdx];
149+ uint64_t numParticles = patchNumParticles[patchIdx];
150+
151+ log<picLog::INPUT_OUTPUT>(" openPMD: Loading %1% particles from offset %2%" )
152+ % (long long unsigned ) totalNumParticles % (long long unsigned ) particleOffset;
153+
156154
157- auto numParticlesCurrentBatch = std::min (numLeftParticles, maxChunkSize);
155+ uint32_t const numLoadIterations
156+ = maxChunkSize == 0u ? 0u : alpaka::core::divCeil (numParticles, maxChunkSize);
158157
159- log<picLog::INPUT_OUTPUT>(" openPMD: (begin) load species %1% round: %2%/%3%" ) % speciesName
160- % (loadRound + 1 ) % numLoadIterations;
161- if (numParticlesCurrentBatch != 0 )
158+ for (uint64_t loadRound = 0u ; loadRound < numLoadIterations; ++loadRound)
162159 {
163- meta::ForEach<
164- typename NewParticleDescription::ValueTypeSeq,
165- LoadParticleAttributesFromOpenPMD<boost::mpl::_1>>
166- loadAttributes;
167- loadAttributes (
168- params,
169- mappedFrame,
170- particleSpecies,
171- particleLoadOffset,
172- numParticlesCurrentBatch);
173-
174-
175- pmacc::particles::operations::splitIntoListOfFrames (
176- *speciesTmp,
177- mappedFrame,
178- numParticlesCurrentBatch,
179- cellOffsetToTotalDomain,
180- totalCellIdx_,
181- *(params->cellDescription ),
182- picLog::INPUT_OUTPUT ());
160+ auto particleLoadOffset = particleOffset + loadRound * maxChunkSize;
161+ auto numLeftParticles = numParticles - loadRound * maxChunkSize;
162+
163+ auto numParticlesCurrentBatch = std::min (numLeftParticles, maxChunkSize);
164+
165+ log<picLog::INPUT_OUTPUT>(" openPMD: (begin) load species %1% round: %2%/%3%" ) % speciesName
166+ % (loadRound + 1 ) % numLoadIterations;
167+ if (numParticlesCurrentBatch != 0 )
168+ {
169+ meta::ForEach<
170+ typename NewParticleDescription::ValueTypeSeq,
171+ LoadParticleAttributesFromOpenPMD<boost::mpl::_1>>
172+ loadAttributes;
173+ loadAttributes (
174+ params,
175+ mappedFrame,
176+ particleSpecies,
177+ particleLoadOffset,
178+ numParticlesCurrentBatch);
179+
180+
181+ pmacc::particles::operations::splitIntoListOfFrames (
182+ *speciesTmp,
183+ mappedFrame,
184+ numParticlesCurrentBatch,
185+ cellOffsetToTotalDomain,
186+ totalCellIdx_,
187+ *(params->cellDescription ),
188+ picLog::INPUT_OUTPUT ());
189+ }
190+ log<picLog::INPUT_OUTPUT>(" openPMD: ( end ) load species %1% round: %2%/%3%" ) % speciesName
191+ % (loadRound + 1 ) % numLoadIterations;
183192 }
184- log<picLog::INPUT_OUTPUT>(" openPMD: ( end ) load species %1% round: %2%/%3%" ) % speciesName
185- % (loadRound + 1 ) % numLoadIterations;
186193 }
187194 log<picLog::INPUT_OUTPUT>(" openPMD: ( end ) load species: %1%" ) % speciesName;
188195 }
@@ -220,7 +227,9 @@ namespace picongpu
220227 *
221228 * @return index of the particle patch within the openPMD data
222229 */
223- HINLINE size_t getPatchIdx (ThreadParams* params, ::openPMD::ParticleSpecies particleSpecies)
230+ HINLINE std::pair<std::deque<size_t >, std::deque<size_t >> getPatchIdx (
231+ ThreadParams* params,
232+ ::openPMD::ParticleSpecies particleSpecies)
224233 {
225234 std::string const name_lookup[] = {" x" , " y" , " z" };
226235
@@ -297,15 +306,7 @@ namespace picongpu
297306 << fullMatches.size () << " full matches, " << partialMatches.size () << " partial matches, "
298307 << noMatches << " unmatched." << std ::endl;
299308
300- // If no patch fits the conditions, something went wrong before
301- if (fullMatches.empty ())
302- {
303- throw std::runtime_error (
304- " Error while restarting: no particle patch matches the required offset and extent" );
305- }
306-
307- // For now, ignore all the others
308- return *fullMatches.begin ();
309+ return std::make_pair (std::move (fullMatches), std::move (partialMatches));
309310 }
310311 };
311312
0 commit comments