BioCMAMC-ST
model_kernel.hpp
1#ifndef __SIMULATION_MC_KERNEL_HPP
2#define __SIMULATION_MC_KERNEL_HPP
3
4#include <Kokkos_Assert.hpp>
5#include <Kokkos_Core.hpp>
6#include <Kokkos_Macros.hpp>
7#include <Kokkos_Printf.hpp>
8#include <Kokkos_Random.hpp>
9#include <biocma_cst_config.hpp>
10#include <cassert>
11#include <common/common.hpp>
12#include <mc/alias.hpp>
13#include <mc/domain.hpp>
14#include <mc/events.hpp>
15#include <mc/particles_container.hpp>
16#include <mc/prng/prng.hpp>
17#include <mc/traits.hpp>
18#include <simulation/probability_leaving.hpp>
19#include <simulation/probe.hpp>
20#include <utility>
21
22#define CHECK_STATUS_OR_RETURN(__idx__) \
23 if (particles.status(__idx__) != MC::Status::Idle) [[unlikely]] \
24 { \
25 return; \
26 }
27
29{
31 {
32 };
33 struct TagCycle
34 {
35 };
36
38 {
40 std::size_t dead_total;
41 };
42
43 template <class Space> class CycleReducer
44 {
45 public:
46 // Required for Concept
49 using result_view_type = Kokkos::View<value_type, Space>;
50
51 KOKKOS_INLINE_FUNCTION
52 void
53 join(value_type& dest, const value_type& src) const
54 {
55 dest.dead_total += src.dead_total;
57 }
58
59 KOKKOS_INLINE_FUNCTION
61 reference() const
62 {
63 return *value.data();
64 }
65
66 KOKKOS_INLINE_FUNCTION
68 view() const
69 {
70 return value;
71 }
72
73 KOKKOS_INLINE_FUNCTION
74 bool
76 {
78 }
79
80 // Optional
81 KOKKOS_INLINE_FUNCTION
82 void
83 init(value_type& val) const
84 {
85 val.dead_total = 0;
87 }
88
89 // KOKKOS_INLINE_FUNCTION
90 // void final(value_type& val) const
91 // {
92 // // NOP
93 // }
94
95 // Part of Build-In reducers for Kokkos
96 KOKKOS_INLINE_FUNCTION
98 {
99 }
100
101 KOKKOS_INLINE_FUNCTION
103 : value(value_), references_scalar_v(false)
104 {
105 }
106
107 private:
110 };
111
112 template <ModelType M> struct CycleFunctor
113 {
114 using TeamPolicy = Kokkos::TeamPolicy<ComputeSpace>;
115 using TeamMember = TeamPolicy::member_type;
117
118 CycleFunctor() = default;
119
120 KOKKOS_INLINE_FUNCTION
122 MC::pool_type _random_pool,
123 MC::KernelConcentrationType&& _concentrations,
124 MC::ContributionView _contribs_scatter,
125 MC::EventContainer _event,
127 : d_t(0.), particles(std::move(_particles)),
128 random_pool(std::move(_random_pool)),
129 concentrations(std::move(_concentrations)),
130 contribs_scatter(std::move(_contribs_scatter)),
131 events(std::move(_event)), probes(std::move(_probes))
132 {
133 }
134
135 bool
137 {
138 return particles.begin < particles.end;
139 }
140
141 void
142 update(double _d_t, MC::ParticlesContainer<M> _particles)
143 {
144 this->d_t = _d_t;
145 this->particles = std::move(_particles);
146 }
147
148 KOKKOS_INLINE_FUNCTION
149 void
150 operator()(const TagContribution _tag, const TeamMember& team) const
151 {
152 (void)_tag;
153 // std ::size_t idx = (team_handle.league_rank() *
154 // team_handle.team_size()) +
155 // team_handle.team_rank();
156 // if (idx >= (particles.n_particles()))
157 // {
158 // return;
159 // }
160 // if (particles.status(idx) != MC::Status::Idle) [[unlikely]]
161 // {
162 // return;
163 // }
164 constexpr int PARTICLES_PER_TEAM = 256;
165 // particles.get_contributions(idx, contribs_scatter);
166
167 const std::size_t p0 = team.league_rank() * PARTICLES_PER_TEAM;
168
169 Kokkos::parallel_for(
170 Kokkos::TeamThreadRange(team, PARTICLES_PER_TEAM),
171 [&](const int i)
172 {
173 const std::size_t p = p0 + i;
174 if (p >= particles.n_particles())
175 {
176 return;
177 }
178
179 if (particles.status(p) != MC::Status::Idle)
180 {
181 return;
182 }
183 // particles.get_contributions(p,
184 // contribs_scatter);
185
186 const double weight = particles.get_weight(p);
187 const auto pos = particles.position(p);
188 auto access = contribs_scatter.access();
189
190 Kokkos::parallel_for(
191 Kokkos::ThreadVectorRange(team, particles.begin, particles.end),
192 [&](const int j)
193 {
194 const int rel = j - particles.begin;
195 access(rel, pos) += weight * particles.model(p, j);
196 });
197 });
198 }
199
200 // KOKKOS_INLINE_FUNCTION
201 // void operator()(const TagContribution _tag, const std::size_t idx) const
202 // {
203 // (void)_tag;
204 // CHECK_STATUS_OR_RETURN(idx);
205
206 // particles.get_contributions(idx, contribs_scatter);
207 // }
208
209 // KOKKOS_INLINE_FUNCTION void operator()(const TagCycle _tag,
210 // const TeamMember& team_handle,
211 // value_type& reduce_val) const
212 // {
213
214 // (void)_tag;
215 // (void)reduce_val.dead_total; // Counter not used currently because
216 // // there is no cell mortality
217 // // GET_INDEX(particles.n_particles());
218
219 // std ::size_t start_idx =
220 // (team_handle.league_rank() * team_handle.team_size());
221 // std ::size_t idx = start_idx + team_handle.team_rank();
222 // // if (particles.status(idx) != MC::Status::Idle) [[unlikely]]
223 // // {
224 // // return;
225 // // }
226 // const std::size_t n_species = concentrations.extent(0);
227 // Kokkos::View<double**, Kokkos::MemoryTraits<Kokkos::Unmanaged>>
228 // shmem_view(
229 // team_handle.team_shmem(), team_handle.team_size(), n_species);
230
231 // Kokkos::parallel_for(
232 // Kokkos::TeamThreadRange(team_handle, 0, team_handle.team_size()),
233 // [&](int i)
234 // {
235 // std::size_t particle_idx = start_idx + i;
236 // const auto position = particles.position(particle_idx);
237 // for (int s = 0; s < n_species; ++s)
238 // {
239 // shmem_view(i, s) = concentrations(s, position);
240 // }
241 // });
242 // // team_handle.team_barrier();
243 // CHECK_STATUS_OR_RETURN(idx);
244 // if (idx > particles.n_particles())
245 // {
246 // return;
247 // }
248 // particles.ages(idx, 1) += d_t;
249
250 // auto local_c =
251 // Kokkos::subview(shmem_view, team_handle.team_rank(), Kokkos::ALL);
252
253 // if (M::update(random_pool, d_t, idx, particles.model, local_c) ==
254 // MC::Status::Division)
255 // {
256 // if (!particles.handle_division(random_pool, idx))
257 // {
258 // reduce_val.waiting_allocation_particle += 1;
259 // events.wrap_incr<MC::EventType::Overflow>();
260 // Kokkos::printf("[KERNEL] Division Overflow\r\n");
261 // }
262 // events.wrap_incr<MC::EventType::NewParticle>();
263 // };
264 // }
265
266 KOKKOS_INLINE_FUNCTION void
268 const Kokkos::TeamPolicy<ComputeSpace>::member_type& team,
269 value_type& reduce_val) const
270 {
271 (void)_tag;
272 const auto team_size = team.team_size();
273
274 const auto work_stride = team_size * team.league_size();
275 const auto work_start = team.league_rank() * team_size + team.team_rank();
276
277 for (auto idx = work_start; idx < particles.n_particles();
278 idx += work_stride)
279 {
280 CHECK_STATUS_OR_RETURN(idx);
281 exec_per_particle(idx, reduce_val);
282 }
283 }
284
285 KOKKOS_FORCEINLINE_FUNCTION void
287 const std::size_t idx,
288 value_type& reduce_val) const
289 {
290
291 (void)_tag;
292 (void)reduce_val.dead_total;
293 exec_per_particle(idx, reduce_val);
294 }
295
296 KOKKOS_INLINE_FUNCTION void
297 exec_per_particle(const std::size_t idx, value_type& reduce_val) const
298 {
299 using mem_space = ComputeSpace::memory_space;
300 particles.ages(idx, 1) += d_t;
301 const auto local_c = Kokkos::subview(
302 concentrations, Kokkos::ALL, particles.position(idx));
303 const auto new_status
304 = M::update(random_pool, d_t, idx, particles.model, local_c);
305 if (new_status == MC::Status::Division)
306 {
307 if constexpr (AutoGenerated::FlagCompileTime::use_probe)
308 {
309 // Register probe here to sample BEFORE division and even if division
310 // procedure fails to spawn new particle, the age is still the same
311 const auto _ = this->probes.template set<mem_space>(
312 particles.ages(idx, 1)); // Skip error
313 }
314
315 if (!particles.handle_division(random_pool, idx))
316 {
317 reduce_val.waiting_allocation_particle += 1;
318 events.wrap_incr<MC::EventType::Overflow>();
319 Kokkos::printf("[KERNEL] Division Overflow\r\n");
320 }
322
323 /*
324 TODO, it seems that after some calculation (example cstr 0d)
325 size(division probes) = number of tally+1 where the last probe is 0
326 where size(leaving time) == tally
327 Is it a bug ?
328 */
329 };
330 }
331
332 M::FloatType d_t;
337 // kernelContribution contribs;
341 };
342
343} // namespace Simulation::KernelInline
344#endif
Main owning object for Monte-Carlo particles.
Definition particles_container.hpp:57
Kokkos::View< value_type, Space > result_view_type
Definition model_kernel.hpp:49
KOKKOS_INLINE_FUNCTION CycleReducer(const result_view_type &value_)
Definition model_kernel.hpp:102
KOKKOS_INLINE_FUNCTION bool references_scalar() const
Definition model_kernel.hpp:75
KOKKOS_INLINE_FUNCTION void init(value_type &val) const
Definition model_kernel.hpp:83
KOKKOS_INLINE_FUNCTION result_view_type view() const
Definition model_kernel.hpp:68
KOKKOS_INLINE_FUNCTION void join(value_type &dest, const value_type &src) const
Definition model_kernel.hpp:53
CycleReduceType value_type
Definition model_kernel.hpp:48
KOKKOS_INLINE_FUNCTION CycleReducer(value_type &value_)
Definition model_kernel.hpp:97
KOKKOS_INLINE_FUNCTION value_type & reference() const
Definition model_kernel.hpp:61
bool references_scalar_v
Definition model_kernel.hpp:109
CycleReducer reducer
Definition model_kernel.hpp:47
result_view_type value
Definition model_kernel.hpp:108
@ Overflow
Definition events.hpp:22
@ NewParticle
Spawn new particle.
Definition events.hpp:18
decltype(Kokkos::Experimental::create_scatter_view( kernelContribution())) ContributionView
Definition alias.hpp:90
@ Division
Definition alias.hpp:60
@ Idle
Definition alias.hpp:59
gen_pool_type< Kokkos::DefaultExecutionSpace > pool_type
Definition alias.hpp:39
Kokkos::View< const double **, Kokkos::LayoutLeft, ComputeSpace, Kokkos::MemoryTraits< Kokkos::RandomAccess > > KernelConcentrationType
Definition alias.hpp:93
Definition kernels.hpp:12
Probes< AutoGenerated::probe_buffer_size > ProbeAutogeneratedBuffer
Definition probe.hpp:144
Use to count events that occurs during Monte-Carlo processing cycles.
Definition events.hpp:45
KOKKOS_INLINE_FUNCTION CycleFunctor(MC::ParticlesContainer< M > _particles, MC::pool_type _random_pool, MC::KernelConcentrationType &&_concentrations, MC::ContributionView _contribs_scatter, MC::EventContainer _event, ProbeAutogeneratedBuffer _probes)
Definition model_kernel.hpp:121
bool do_contribs() const
Definition model_kernel.hpp:136
KOKKOS_FORCEINLINE_FUNCTION void operator()(const TagCycle _tag, const std::size_t idx, value_type &reduce_val) const
Definition model_kernel.hpp:286
MC::EventContainer events
Definition model_kernel.hpp:339
M::FloatType d_t
Definition model_kernel.hpp:332
MC::ContributionView contribs_scatter
Definition model_kernel.hpp:336
MC::KernelConcentrationType concentrations
Definition model_kernel.hpp:335
MC::ParticlesContainer< M > particles
Definition model_kernel.hpp:333
TeamPolicy::member_type TeamMember
Definition model_kernel.hpp:115
CycleReduceType value_type
Definition model_kernel.hpp:116
KOKKOS_INLINE_FUNCTION void operator()(TagCycle _tag, const Kokkos::TeamPolicy< ComputeSpace >::member_type &team, value_type &reduce_val) const
Definition model_kernel.hpp:267
ProbeAutogeneratedBuffer probes
Definition model_kernel.hpp:340
Kokkos::TeamPolicy< ComputeSpace > TeamPolicy
Definition model_kernel.hpp:114
KOKKOS_INLINE_FUNCTION void exec_per_particle(const std::size_t idx, value_type &reduce_val) const
Definition model_kernel.hpp:297
void update(double _d_t, MC::ParticlesContainer< M > _particles)
Definition model_kernel.hpp:142
MC::KernelConcentrationType limitation_factor
Definition model_kernel.hpp:338
MC::pool_type random_pool
Definition model_kernel.hpp:334
KOKKOS_INLINE_FUNCTION void operator()(const TagContribution _tag, const TeamMember &team) const
Definition model_kernel.hpp:150
Definition model_kernel.hpp:38
std::size_t waiting_allocation_particle
Definition model_kernel.hpp:39
std::size_t dead_total
Definition model_kernel.hpp:40
Definition model_kernel.hpp:31
Definition model_kernel.hpp:34