1#ifndef __PARTICLES_CONTAINER_HPP__
2#define __PARTICLES_CONTAINER_HPP__
4#include "Kokkos_Core_fwd.hpp"
5#include "common/common.hpp"
6#include <Kokkos_Core.hpp>
7#include <common/has_serialize.hpp>
9#include <mc/prng/prng.hpp>
10#include <mc/traits.hpp>
16 template <ModelType M>
struct FillGapFunctor
20 M::SelfParticle _model,
22 std::size_t _to_remove,
23 std::size_t _last_used_index)
24 : status(std::move(_status)), model(std::move(_model)), position(std::move(_position)),
25 offset(
"offset"), to_remove(_to_remove), last_used_index(_last_used_index)
28 Kokkos::deep_copy(offset, 0);
31 KOKKOS_INLINE_FUNCTION
void operator()(
const int i, std::size_t& update,
const bool final)
const
35 std::size_t scan_index = update;
36 update += is_dead ? 1 : 0;
38 if (
final && is_dead && scan_index < to_remove)
41 const auto i_to_remove = i;
44 auto idx_to_move = last_used_index - Kokkos::atomic_fetch_add(&offset(), 1);
46 idx_to_move ==
static_cast<std::size_t
>(i_to_remove))
48 idx_to_move = last_used_index - Kokkos::atomic_fetch_add(&offset(), 1);
52 Kokkos::atomic_exchange(&position(i_to_remove), position(idx_to_move));
54 for (std::size_t i_properties = 0; i_properties < M::n_var; ++i_properties)
56 model(i_to_remove, i_properties) = model(idx_to_move, i_properties);
62 M::SelfParticle model;
64 Kokkos::View<std::size_t, ComputeSpace> offset;
65 std::size_t to_remove;
66 std::size_t last_used_index;
68 using TeamPolicy = Kokkos::TeamPolicy<ComputeSpace>;
69 using TeamMember = TeamPolicy::member_type;
70 template <ModelType M>
struct InsertFunctor
72 InsertFunctor(std::size_t _original_size,
73 M::SelfParticle _model,
75 M::SelfParticle _buffer_model,
77 : original_size(_original_size), model(std::move(_model)), position(std::move(_position)),
78 buffer_model(std::move(_buffer_model)), buffer_position(std::move(_buffer_position))
95 KOKKOS_INLINE_FUNCTION
96 void operator()(
const TeamMember& team)
const
98 auto range = M::n_var;
99 const int i = team.league_rank();
101 position(original_size + i) = buffer_position(i);
102 Kokkos::parallel_for(Kokkos::TeamVectorRange(team, range),
103 [&](
const int& j) { model(original_size + i, j) = buffer_model(i, j); });
106 std::size_t original_size;
107 M::SelfParticle model;
109 M::SelfParticle buffer_model;
161 [[nodiscard]] KOKKOS_INLINE_FUNCTION std::size_t
n_particles()
const
169 [[nodiscard]] KOKKOS_INLINE_FUNCTION
bool
181 template <
class Archive>
void save(Archive& ar)
const
186 serialize_view(ar,
status);
187 serialize_view(ar,
model);
190 template <
class Archive>
void load(Archive& ar)
195 deserialize_view(ar,
status);
196 deserialize_view(ar,
model);
200 [[nodiscard]] KOKKOS_INLINE_FUNCTION
double get_weight(std::size_t idx)
const;
226 template <ModelType Model>
227 KOKKOS_INLINE_FUNCTION
bool
229 std::size_t idx1)
const
231 if (Kokkos::atomic_load(&buffer_index()) < buffer_model.extent(0))
233 const auto idx2 = Kokkos::atomic_fetch_add(&buffer_index(), 1);
234 Model::division(random_pool, idx1, idx2, model, buffer_model);
235 buffer_position(idx2) = position(idx1);
239 Kokkos::printf(
"%ld %ld\r\n", Kokkos::atomic_load(&buffer_index()), buffer_model.extent(0));
245 PROFILE_SECTION(
"ParticlesContainer::merge_buffer")
246 const auto original_size = n_used_elements;
247 const auto n_add_item = buffer_index();
252 __allocate__(original_size + n_add_item);
260 auto get_policy_insert = [=]()
262 if constexpr (std::is_same_v<Kokkos::DefaultHostExecutionSpace, Kokkos::DefaultExecutionSpace>)
264 return TeamPolicy(n_add_item/Kokkos::num_threads(), Kokkos::AUTO, Model::n_var);
268 return TeamPolicy(n_add_item, Kokkos::AUTO, Model::n_var);
273 Kokkos::parallel_for(
275 TeamPolicy(n_add_item, Kokkos::AUTO, Model::n_var),
276 InsertFunctor<Model>(original_size, model, position, buffer_model, buffer_position));
279 n_used_elements += n_add_item;
280 __allocate_buffer__();
283 template <ModelType Model>
286 PROFILE_SECTION(
"ParticlesContainer::__allocate__")
289 if (new_size >= n_allocated_elements)
291 const auto new_allocated_size =
292 static_cast<std::size_t
>(std::ceil(
static_cast<double>(new_size) * allocation_factor));
293 n_allocated_elements = new_allocated_size;
294 Kokkos::resize(position, n_allocated_elements);
295 Kokkos::resize(model, n_allocated_elements,Model::n_var);
296 Kokkos::resize(status, n_allocated_elements);
299 Kokkos::resize(weights, 1);
303 Kokkos::resize(weights, n_allocated_elements);
309 template <ModelType Model>
312 PROFILE_SECTION(
"ParticlesContainer::__shrink__")
313 if (new_size > 0 && (new_size > n_used_elements || force))
315 const auto new_allocated_size =
316 static_cast<std::size_t
>(std::ceil(
static_cast<double>(new_size) * allocation_factor));
317 n_allocated_elements = new_allocated_size;
318 Kokkos::resize(position, n_allocated_elements);
319 Kokkos::resize(model, n_allocated_elements,Model::n_var);
320 Kokkos::resize(status, n_allocated_elements);
323 Kokkos::resize(weights, 1);
327 Kokkos::resize(weights, n_allocated_elements);
334 PROFILE_SECTION(
"ParticlesContainer::__allocate_buffer__")
335 auto buffer_size = buffer_position.extent(0);
336 if (
static_cast<double>(buffer_size) /
static_cast<double>(n_allocated_elements) < buffer_ratio)
338 buffer_size =
static_cast<std::size_t
>(
339 std::ceil(
static_cast<double>(n_allocated_elements) * buffer_ratio));
342 Kokkos::realloc(buffer_position, buffer_size);
343 Kokkos::realloc(buffer_model, buffer_size,Model::n_var);
348 template <ModelType M>
350 : model(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"particle_model"), 0),
351 position(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"particle_position"), 0),
352 status(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"particle_status"), 0),
353 weights(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"particle_weigth"), 0),
354 buffer_model(
"buffer_particle_model", 0),
355 buffer_position(
"buffer_particle_position", 0),
356 buffer_index(
"buffer_index"), allocation_factor(default_allocation_factor),
357 n_allocated_elements(0), n_used_elements(n_particle)
364 template <ModelType M>
366 : model(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"particle_model"), 0),
367 position(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"particle_position"), 0),
368 status(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"particle_status"), 0),
369 weights(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"particle_weigth"), 0),
371 buffer_model(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"buffer_particle_model"), 0),
372 buffer_position(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"buffer_particle_model")),
373 buffer_index(
"buffer_index"), allocation_factor(default_allocation_factor),
374 n_allocated_elements(0), n_used_elements(0)
381 PROFILE_SECTION(
"ParticlesContainer::remove_dead")
387 if (to_remove == n_used_elements)
392 else if (to_remove > n_used_elements)
394 throw std::runtime_error(
395 "clean_dead: Error in kernel cannot remove more element than existing");
400 const auto new_used_item = n_used_elements - to_remove;
405 const auto last_used_index = n_used_elements - 1;
406 Kokkos::parallel_scan(
"find_and_fill_gap",
407 Kokkos::RangePolicy<ComputeSpace>(0, n_used_elements),
408 FillGapFunctor<M>(status, model, position, to_remove, last_used_index));
443 KOKKOS_ASSERT(this->position.extent(0) == n_allocated_elements);
444 KOKKOS_ASSERT(this->model.extent(0) == n_allocated_elements);
445 KOKKOS_ASSERT(this->status.extent(0) == n_allocated_elements);
446 n_used_elements = new_used_item;
447 if (
static_cast<double>(n_used_elements) /
static_cast<double>(n_allocated_elements) <= 0.1)
450 __shrink__(n_used_elements * 2,
false);
455 template <ModelType M>
456 KOKKOS_INLINE_FUNCTION
void
461 const double weight = get_weight(idx);
462 M::contribution(idx, position(idx), weight, model, contributions);
465 template <ModelType M>
466 [[nodiscard]] KOKKOS_INLINE_FUNCTION
double
Kokkos::Random_XorShift1024_Pool< Kokkos::DefaultExecutionSpace > pool_type
Definition prng.hpp:17
Main owning object for Monte-Carlo particles.
Definition particles_container.hpp:128
~ParticlesContainer()=default
Default destructor.
void __allocate__(std::size_t new_size)
Definition particles_container.hpp:284
Model::SelfParticle model
Definition particles_container.hpp:139
KOKKOS_INLINE_FUNCTION void get_contributions(std::size_t idx, const ContributionView &contributions) const
Definition particles_container.hpp:457
KOKKOS_INLINE_FUNCTION std::size_t n_particles() const
Gets the number of particles in the container.
Definition particles_container.hpp:161
ParticlesContainer(std::size_t n_particle)
Definition particles_container.hpp:349
double allocation_factor
Definition particles_container.hpp:216
ParticleWeigths weights
Definition particles_container.hpp:142
double get_allocation_factor() const
Definition particles_container.hpp:202
Kokkos::View< uint64_t, Kokkos::SharedSpace > buffer_index
Definition particles_container.hpp:215
void __allocate_buffer__()
Definition particles_container.hpp:332
ParticlesContainer()
Definition particles_container.hpp:365
KOKKOS_INLINE_FUNCTION bool handle_division(const MC::KPRNG::pool_type &random_pool, std::size_t idx1) const
Definition particles_container.hpp:228
ParticlesContainer & operator=(ParticlesContainer &&)=default
void __shrink__(std::size_t new_size, bool force)
Definition particles_container.hpp:310
uint64_t n_used_elements
Definition particles_container.hpp:218
auto get_buffer_index() const
Definition particles_container.hpp:176
void merge_buffer()
Definition particles_container.hpp:243
Model::SelfParticle buffer_model
Definition particles_container.hpp:213
KOKKOS_INLINE_FUNCTION double get_weight(std::size_t idx) const
Definition particles_container.hpp:467
std::size_t capacity() const
Definition particles_container.hpp:207
ParticlePositions buffer_position
Definition particles_container.hpp:214
MC::ParticlePositions position
Definition particles_container.hpp:140
void save(Archive &ar) const
Definition particles_container.hpp:181
static constexpr double default_allocation_factor
Definition particles_container.hpp:220
static constexpr double buffer_ratio
Definition particles_container.hpp:130
Model UsedModel
Alias for the model used by the container.
Definition particles_container.hpp:134
void clean_dead(std::size_t to_remove)
Definition particles_container.hpp:379
ParticlesContainer & operator=(const ParticlesContainer &)=default
ParticlesContainer(const ParticlesContainer &)=default
Default copy and move constructors and assignment operators.
void load(Archive &ar)
Definition particles_container.hpp:190
ParticlesContainer(ParticlesContainer &&)=default
std::size_t n_allocated_elements
Definition particles_container.hpp:217
MC::ParticleStatus status
Definition particles_container.hpp:141
Definition traits.hpp:115
Namespace that contains classes and structures related to Monte Carlo (MC) simulations.
Definition alias.hpp:9
Kokkos::View< double *, ComputeSpace > ParticleWeigths
Definition alias.hpp:21
Kokkos::View< Status *, ComputeSpace > ParticleStatus
Definition alias.hpp:20
Kokkos::View< uint64_t *, ComputeSpace > ParticlePositions
Definition alias.hpp:19
Kokkos::Experimental::ScatterView< double **, Kokkos::LayoutRight > ContributionView
Definition alias.hpp:30