BioCMAMC-ST
contribution_kernel.hpp
1#ifndef __CONTRIBUTION_KERNEL_HPP__
2#define __CONTRIBUTION_KERNEL_HPP__
3#include "Kokkos_Assert.hpp"
4#include "Kokkos_Macros.hpp"
5#include "mc/events.hpp"
6#include <Kokkos_Core.hpp>
7#include <mc/particles_container.hpp>
8#include <mc/traits.hpp>
9
10template <ModelType M> struct ContributionFunctor
11{
12
13 struct Tag0D
14 {
15 };
16 struct Tag3D
17 {
18 };
19
20 using TeamPolicy = Kokkos::TeamPolicy<ComputeSpace>;
21 using TeamMember = TeamPolicy::member_type;
22 using float_type = float;
24 = Kokkos::View<float_type*,
25 TeamPolicy::execution_space::scratch_memory_space>;
27 ContributionFunctor(std::size_t particle_per_team,
28 MC::ContributionView contribution_scatter,
31 MC::KernelConcentrationType _concentrations,
32 MC::EventContainer _event)
33 : m_particle_per_team(particle_per_team),
34 m_contribution_scatter(std::move(contribution_scatter)),
35 m_particles(std::move(particles)), random_pool(rp),
36 concentrations(std::move(_concentrations)), events(std::move(_event))
37 {
38 }
40 size_t np{};
41
42 void
43 update(MC::ParticlesContainer<M> _particles, double _d_t)
44
45 {
46 this->d_t = _d_t;
47 this->m_particles = std::move(_particles);
48 np = m_particles.n_particles();
49 }
51 std::size_t m_particle_per_team;
58 M::FloatType d_t;
60
61 KOKKOS_INLINE_FUNCTION void
62 division(const std::size_t idx) const
63 {
64
65 using mem_space = ComputeSpace::memory_space;
66 if constexpr (AutoGenerated::FlagCompileTime::use_probe)
67 {
68 // Register probe here to sample BEFORE division and even if
69 // division procedure fails to spawn new particle, the age is
70 // still the same
71 const auto _ = this->probes.template set<mem_space>(
72 m_particles.ages(idx, 1)); // Skip error
73 }
74
75 if (!m_particles.handle_division(random_pool, idx)) [[unlikely]]
76 {
77 // reduce_val.waiting_allocation_particle += 1;
78 // events.wrap_incr<MC::EventType::Overflow>();
79 Kokkos::printf("[KERNEL] Division Overflow\r\n");
80 }
81
83 }
84
85 KOKKOS_INLINE_FUNCTION
86 void
87 operator()(Tag0D _tag, const TeamMember& team) const
88 {
89 (void)_tag;
90 const std::size_t p0 = team.league_rank() * m_particle_per_team;
91 const std::size_t n_particle = m_particles.n_particles();
92 const auto& status = m_particles.status;
93 const auto& contribs = m_particles.contribs;
94 static const auto n_c = M::n_c;
95
96 ScratchView scratch(team.team_scratch(0), n_c);
97
98 Kokkos::parallel_for(Kokkos::TeamVectorRange(team, n_c),
99 [&](const std::size_t j)
100 { scratch(j) = float_type{ 0 }; });
101
102 const auto upper_bound = ((p0 + m_particle_per_team) >= n_particle)
103 ? n_particle - p0
105
106 KOKKOS_ASSERT(upper_bound > 0 && upper_bound <= m_particle_per_team
107 && (p0 + upper_bound) <= n_particle);
108
109 Kokkos::parallel_for(
110 Kokkos::TeamThreadRange(team, 0, upper_bound),
111 [&](std::size_t relative_index)
112 {
113 const std::size_t flatten_index = p0 + relative_index;
114 KOKKOS_ASSERT(flatten_index < upper_bound);
115 const bool active = status(flatten_index) == MC::Status::Idle;
116
117 if (active)
118 {
119 const auto pos = m_particles.position(flatten_index);
120 const auto weight = m_particles.get_weight(flatten_index);
121 const auto new_status = M::update(random_pool,
122 d_t,
123 flatten_index,
124 m_particles.model,
125 contribs,
126 pos,
128
129 for (std::size_t j = 0; j < n_c; ++j)
130 {
131 Kokkos::atomic_add(&scratch(j),
132 weight * contribs(flatten_index, j));
133 }
134
135 if (new_status == MC::Status::Division)
136 {
137 division(flatten_index);
138 }
139 else
140 {
141 m_particles.ages(flatten_index, 1) += d_t;
142 }
143 }
144 });
145
146 team.team_barrier();
147 const auto& cs = m_contribution_scatter;
148 Kokkos::single(Kokkos::PerTeam(team),
149 [=]()
150 {
151 auto access = cs.access();
152 for (std::size_t j = 0; j < M::n_c; ++j)
153 {
154 access(j, 0) += scratch(j);
155 }
156 });
157 }
158
159 KOKKOS_INLINE_FUNCTION
160 void
161 operator()(const Tag3D _tag, const TeamMember& team) const
162 {
163 (void)_tag;
164
165 const std::size_t N = m_particle_per_team;
166 const std::size_t p0 = team.league_rank() * N;
167
168 const auto _ntot = m_particles.n_particles();
169 KOKKOS_ASSERT(p0 < _ntot)
170 const auto upper_bound = ((p0 + N) >= _ntot) ? _ntot - p0 : N;
171
172 KOKKOS_ASSERT(upper_bound > 0 && upper_bound <= _ntot);
173
174 const std::size_t p = team.team_size();
175
176 const std::size_t m = (upper_bound + p - 1) / p;
177
178 const auto& positions = m_particles.position;
179 const auto& contribs = m_particles.contribs;
180 const auto& status = m_particles.status;
181
182 Kokkos::parallel_for(
183 Kokkos::TeamThreadRange(team, 0, upper_bound),
184 [&](const std::size_t i)
185 {
186 const std::size_t flatten_index = p0 + i;
187 KOKKOS_ASSERT(flatten_index < upper_bound);
188 const bool active = status(flatten_index) == MC::Status::Idle;
189 if (active)
190 {
191 const auto pos = m_particles.position(flatten_index);
192 const auto weight = m_particles.get_weight(flatten_index);
193 const auto new_status = M::update(random_pool,
194 d_t,
195 flatten_index,
196 m_particles.model,
197 contribs,
198 pos,
200
201 if (new_status == MC::Status::Division)
202 {
203 division(flatten_index);
204 }
205 else
206 {
207 m_particles.ages(flatten_index, 1) += d_t;
208 }
209 }
210 });
211
212 team.team_barrier();
213
214 Kokkos::parallel_for(
215 Kokkos::TeamThreadRange(team, 0, p),
216 [&](const std::size_t tid)
217 {
218 auto access = m_contribution_scatter.access();
219 for (std::size_t k = 0; k < m; ++k)
220 {
221 const std::size_t idx = tid + k * p; // stride p
222 const std::size_t flat_index = p0 + idx;
223 if (idx >= upper_bound)
224 {
225 break;
226 }
227
228 KOKKOS_ASSERT(flat_index < _ntot);
229
230 const double weight = m_particles.get_weight(p);
231 const auto pos = positions(p);
232 Kokkos::parallel_for(
233 Kokkos::ThreadVectorRange(team, 0, M::n_c),
234 [&](const int j)
235 { access(j, pos) += weight * contribs(p, j); });
236 }
237 });
238 }
239};
240
241#endif
Main owning object for Monte-Carlo particles.
Definition particles_container.hpp:57
@ NewParticle
Spawn new particle.
Definition events.hpp:20
decltype(Kokkos::Experimental::create_scatter_view( kernelContribution())) ContributionView
Definition alias.hpp:162
@ Division
Definition alias.hpp:127
@ Idle
Definition alias.hpp:126
gen_pool_type< Kokkos::DefaultExecutionSpace > pool_type
Definition alias.hpp:100
Kokkos::View< const double **, Kokkos::LayoutLeft, ComputeSpace, Kokkos::MemoryTraits< Kokkos::RandomAccess > > KernelConcentrationType
Definition alias.hpp:165
Definition contribution_kernel.hpp:14
Definition contribution_kernel.hpp:17
Kokkos::View< float_type *, TeamPolicy::execution_space::scratch_memory_space > ScratchView
Definition contribution_kernel.hpp:23
TeamPolicy::member_type TeamMember
Definition contribution_kernel.hpp:21
KOKKOS_INLINE_FUNCTION void operator()(Tag0D _tag, const TeamMember &team) const
Definition contribution_kernel.hpp:86
M::FloatType d_t
Definition contribution_kernel.hpp:57
ContributionFunctor(std::size_t particle_per_team, MC::ContributionView contribution_scatter, MC::ParticlesContainer< M > particles, MC::pool_type rp, MC::KernelConcentrationType _concentrations, MC::EventContainer _event)
Definition contribution_kernel.hpp:26
Kokkos::TeamPolicy< ComputeSpace > TeamPolicy
Definition contribution_kernel.hpp:20
MC::EventContainer events
Definition contribution_kernel.hpp:58
MC::pool_type random_pool
Definition contribution_kernel.hpp:55
size_t np
Definition contribution_kernel.hpp:39
MC::ParticlesContainer< M > m_particles
Definition contribution_kernel.hpp:53
float float_type
Definition contribution_kernel.hpp:22
MC::KernelConcentrationType concentrations
Definition contribution_kernel.hpp:56
MC::ContributionView m_contribution_scatter
Definition contribution_kernel.hpp:52
void update(MC::ParticlesContainer< M > _particles, double _d_t)
Definition contribution_kernel.hpp:42
std::size_t m_particle_per_team
Definition contribution_kernel.hpp:50
KOKKOS_INLINE_FUNCTION void division(const std::size_t idx) const
Definition contribution_kernel.hpp:61
Use to count events that occurs during Monte-Carlo processing cycles.
Definition events.hpp:151