BioCMAMC-ST
move_kernel.hpp
1#ifndef __SIMULATION_MOVE_KERNEL_HPP__
2#define __SIMULATION_MOVE_KERNEL_HPP__
3
4#include "Kokkos_Macros.hpp"
5#include "common/common.hpp"
6#include <Kokkos_Assert.hpp>
7#include <Kokkos_Core.hpp>
8#include <Kokkos_Printf.hpp>
9#include <Kokkos_Random.hpp>
10#include <biocma_cst_config.hpp>
11#include <cassert>
12#include <decl/Kokkos_Declare_OPENMP.hpp>
13#include <mc/alias.hpp>
14#include <mc/domain.hpp>
15#include <mc/events.hpp>
16#include <mc/prng/prng.hpp>
17#include <mc/traits.hpp>
18// #include <simulation/move_info.hpp>
19#include <simulation/probability_leaving.hpp>
20#include <simulation/probe.hpp>
21#include <utility>
22
24{
25 constexpr bool enable_leave = true;
26 constexpr bool disable_leave = false;
27 constexpr bool disable_move = false;
28 constexpr bool enable_move = true;
29
30 // KOKKOS_INLINE_FUNCTION std::size_t __find_next_compartment(
31 // const ConstNeighborsView<ComputeSpace>& neighbors,
32 // const CumulativeProbabilityView<ComputeSpace>& cumulative_probability,
33 // const std::size_t i_compartment,
34 // const double random_number)
35 // {
36 // const int max_neighbor = static_cast<int>(neighbors.extent(1));
37
38 // std::size_t next =
39 // neighbors(i_compartment, 0); // Default to the first neighbor
40
41 // // Iterate through the neighbors to find the appropriate next compartment
42 // for (int k_neighbor = 0; k_neighbor < max_neighbor - 1; ++k_neighbor)
43 // {
44
45 // // Get the cumulative probability range for the current neighbor
46 // const auto pi = cumulative_probability(i_compartment, k_neighbor);
47 // const auto pn = cumulative_probability(i_compartment, k_neighbor + 1);
48
49 // // Use of a Condition mask to avoid branching.
50 // next = (random_number <= pn && pi <= random_number)
51 // ? neighbors(i_compartment, k_neighbor + 1)
52 // : next;
53 // }
54
55 // return next; // Return the index of the chosen next compartment
56 // }
57
63 KOKKOS_INLINE_FUNCTION std::size_t
65 const bool do_serch,
68 cumulative_probability,
69 const std::size_t i_compartment,
70 const double random_number)
71 {
72 const int mask_do_serch = static_cast<int>(do_serch);
73
74 const int max_neighbor = static_cast<int>(neighbors.extent(1));
75
76 int left = 0;
77 int right = mask_do_serch * (max_neighbor - 1);
78 while (left < right)
79 {
80 int mid = (left + right) >> 1; // NOLINT
81 const auto pm = cumulative_probability(i_compartment, mid);
82 const int mask = static_cast<int>(random_number > pm);
83 left = mask * (mid + 1) + (1 - mask) * left;
84 right = mask * right + (1 - mask) * mid;
85 }
86
87 const auto ret = i_compartment * (1 - mask_do_serch)
88 + neighbors(i_compartment, left) * mask_do_serch;
89 return ret;
90 }
91
92 // KOKKOS_INLINE_FUNCTION std::size_t __find_next_compartment(
93 // const bool do_serch,
94 // const ConstNeighborsView<ComputeSpace>& neighbors,
95 // const CumulativeProbabilityView<ComputeSpace>& cumulative_probability,
96 // const std::size_t i_compartment,
97 // const double random_number)
98 // {
99 // const int mask_do_serch = static_cast<int>(do_serch);
100
101 // const int max_neighbor =
102 // mask_do_serch * static_cast<int>(neighbors.extent(1));
103
104 // std::size_t next =
105 // i_compartment * (1 - mask_do_serch) +
106 // mask_do_serch *
107 // neighbors(i_compartment, 0); // Default to the first neighbor
108
109 // for (int k_neighbor = 0; k_neighbor < max_neighbor - 1; ++k_neighbor)
110 // {
111
112 // // Get the cumulative probability range for the current neighbor
113 // const auto pi = cumulative_probability(i_compartment, k_neighbor);
114 // const auto pn = cumulative_probability(i_compartment, k_neighbor + 1);
115
116 // const auto cond =
117 // static_cast<int>(random_number <= pn && pi <= random_number);
118
119 // // Use of a Condition mask to avoid branching.
120 // next = cond * neighbors(i_compartment, k_neighbor + 1) + cond * next;
121 // }
122
123 // return next;
124 // }
125
126 struct TagMove
127 {
128 };
129 struct TagLeave
130 {
131 };
132
134 {
135 MoveFunctor() = default;
137 MC::ParticleStatus _status,
139 MC::pool_type _random_pool,
140 MC::EventContainer _events,
142 MC::ParticleAges _ages,
143 MC::ParticleSamples _random)
144 : MoveFunctor(0,
145 std::move(p),
146 std::move(_status),
147 0,
148 std::move(m),
149 std::move(_random_pool),
150 std::move(_events),
151 std::move(_probes),
152 std::move(_ages),
153 std::move(_random),
154 false,
155 false) {};
156
157 MoveFunctor(double _d_t,
159 MC::ParticleStatus _status,
160 std::size_t n_p,
162 MC::pool_type _random_pool,
163 MC::EventContainer _events,
165 MC::ParticleAges _ages,
166 MC::ParticleSamples _random,
167 bool b_move,
168 bool b_leave)
169 : d_t(_d_t), positions(std::move(p)), n_particles(n_p),
170 move(std::move(m)), random_pool(_random_pool), // NOLINT
171 status(std::move(_status)), events(std::move(_events)),
172 probes(std::move(_probes)), ages(std::move(_ages)),
173 random(std::move(_random)), enable_move(b_move),
174 enable_leave(b_leave) {};
175
176 void
177 update(const ComputeSpace& ex,
178 double _d_t,
179 std::size_t n_p,
181 MC::ParticlePositions _positions,
182 MC::ParticleStatus _status,
183 MC::ParticleAges _ages,
184 MC::ParticleSamples _random,
185 bool b_move,
186 bool b_leave)
187 {
188
189 this->d_t = _d_t;
190 this->n_particles = n_p;
191 this->enable_leave = b_leave;
192 this->enable_move = b_move;
193 this->move = std::move(move_i);
194 this->random = std::move(_random);
195
196 this->positions = std::move(_positions);
197 this->status = std::move(_status);
198 this->ages = std::move(_ages);
199
200 Kokkos::fill_random(ex, random, random_pool, 0., 1.);
201 }
202
203 KOKKOS_INLINE_FUNCTION void
205 TagMove /*tag*/,
206 const Kokkos::TeamPolicy<ComputeSpace>::member_type& team_handle) const
207 {
208 GET_INDEX(n_particles);
209 if (status(idx) != MC::Status::Idle) [[unlikely]]
210 {
211 return;
212 }
213
214 handle_move(idx);
215 }
216
217 KOKKOS_INLINE_FUNCTION void
218 operator()(TagMove /*tag*/, const std::size_t& idx) const
219 {
220
221 if (status(idx) != MC::Status::Idle) [[unlikely]]
222 {
223 return;
224 }
225
226 handle_move(idx);
227 }
228
229 // KOKKOS_INLINE_FUNCTION void
230 // operator()(TagLeave _tag,
231 // const Kokkos::TeamPolicy<ComputeSpace>::member_type& team,
232 // std::size_t& local_dead_count) const
233 // {
234 // const auto work_stride = team.team_size() * team.league_size();
235 // const auto work_end = n_particles;
236
237 // std::size_t iwork =
238 // team.league_rank() * team.team_size() + team.team_rank();
239
240 // for (; iwork < work_end; iwork += work_stride)
241 // {
242 // ages(iwork, 0) += d_t;
243 // handle_exit(iwork, local_dead_count);
244 // }
245 // }
246 //
247 KOKKOS_INLINE_FUNCTION void
248 operator()([[maybe_unused]] TagLeave _tag,
249 const std::size_t& idx,
250 std::size_t& local_dead_count) const
251 {
252 if (status(idx) != MC::Status::Idle) [[unlikely]]
253 {
254 return;
255 }
256
257 ages(idx, 0) += d_t;
258 handle_exit(idx, move.liquid_volume, local_dead_count);
259 }
260
261 // KOKKOS_INLINE_FUNCTION void
262 // operator()(TagLeave _tag,
263 // const Kokkos::TeamPolicy<ComputeSpace>::member_type&
264 // team_handle, std::size_t& local_dead_count) const
265 // {
266 // (void)_tag;
267 // const std::size_t league_size = team_handle.league_size();
268 // const std::size_t league_rank = team_handle.league_rank();
269 // const std::size_t start_idx = league_rank * (n_particles /
270 // league_size); std::size_t end_idx = (league_rank + 1) * (n_particles /
271 // league_size);
272
273 // if (league_rank == (league_size - 1))
274 // {
275 // end_idx = n_particles;
276 // }
277 // Kokkos::parallel_for(
278 // Kokkos::TeamThreadRange(team_handle, start_idx, end_idx),
279 // [&](int idx)
280 // {
281 // ages(idx, 0) += d_t;
282 // handle_exit(idx, local_dead_count);
283 // });
284 // }
285
286 [[nodiscard]] bool
288 {
289 return enable_leave || enable_move;
290 }
291
292 KOKKOS_FUNCTION void
293 handle_move(const std::size_t idx) const
294 {
295 // auto generator = random_pool.get_state();
296 // const float rng1 = generator.frand(0., 1.);
297 // const double rng2 = generator.drand(0., 1.);
298 // random_pool.free_state(generator);
299
300 const auto rng1 = static_cast<float>(random(idx, 0));
301 const auto rng2 = static_cast<float>(random(idx, 1));
302
303 const std::size_t i_current_compartment = positions(idx);
304
305 KOKKOS_ASSERT(i_current_compartment < move.liquid_volume.extent(0));
306
307 const bool mask_next = probability_leaving<void>(
308 rng1,
309 move.liquid_volume(i_current_compartment),
310 move.diag_transition(i_current_compartment),
311 d_t);
312
313 positions(idx) = __find_next_compartment(mask_next,
314 move.neighbors,
315 move.cumulative_probability,
316 i_current_compartment,
317 rng2);
318
319 // positions(idx) =
320 // (mask_next) ? __find_next_compartment(move.neighbors,
321 // move.cumulative_probability,
322 // i_current_compartment,
323 // rng2)
324 // : i_current_compartment;
325
326 KOKKOS_ASSERT(positions(idx) < move.liquid_volume.extent(0));
327
328 if constexpr (AutoGenerated::FlagCompileTime::enable_event_counter)
329 {
330 if (mask_next)
331 {
332 events.wrap_incr<MC::EventType::Move>();
333 }
334 }
335 }
336
337 KOKKOS_INLINE_FUNCTION void
338 inner_handle_exit(const std::size_t i_flow,
339 const std::size_t idx,
340 const double liquid_volume,
341 const std::size_t position,
342 const MC::LeavingFlowView<true>& leaving_flow,
343 std ::size_t& dead_count) const
344 {
345 // const float random_number = random(idx, i);
346
347 // SAMPLE_RANDOM_VARIABLES(random_pool,
348 // const float random_number =
349 // _generator_state_.frand(0., 1.);)
350
351 // FIXME when move AND exit, take the same random number, is it really
352 // important ?
353 const auto random_number = static_cast<float>(random(idx, 0));
354 const auto& [index, flow] = leaving_flow(i_flow);
355
356 const bool is_leaving = (position == index)
358 random_number, liquid_volume, flow, d_t);
359
360 const int leave_mask = static_cast<int>(is_leaving);
361
362 // If using probes
363 if constexpr (AutoGenerated::FlagCompileTime::use_probe)
364 {
365 // Execute probe set, but only actually do something if leaving
366
367 if (is_leaving)
368 {
369 probes.set(ages(idx, 0));
370 }
371
372 // if (is_leaving && !probes.set(probe_value))
373 // {
374 // Kokkos::printf("[Kernel]: PROBES OVERFLOW\r\n");
375 // }
376 }
377 if constexpr (AutoGenerated::FlagCompileTime::enable_event_counter)
378 {
379 // if (is_leaving)
380 // {
381 // events.incr<MC::EventType::Exit>();
382 // }
383 events.add<MC::EventType::Exit>(leave_mask);
384 }
385
386 dead_count += leave_mask;
387 ages(idx, 0) = leave_mask * 0 + (1 - leave_mask) * ages(idx, 0);
388 // status(idx) = is_leaving ? MC::Status::Exit : status(idx);
389 status(idx) = static_cast<MC::Status>(
390 static_cast<int>(MC::Status::Exit) * leave_mask
391 + (1 - leave_mask) * static_cast<int>(status(idx)));
392 }
393
394 KOKKOS_FORCEINLINE_FUNCTION void
395 handle_exit(std::size_t idx,
396 const MC::VolumeView<ComputeSpace, true>& liquid_volumes,
397 std::size_t& dead_count) const
398 {
399 const auto position = positions(idx);
400 const auto liquid_volume = liquid_volumes(position);
401 const MC::LeavingFlowView<true>& leaving_flow = move.leaving_flow;
402 const std::size_t n_flow = leaving_flow.size();
403 for (std::size_t i_flow = 0LU; i_flow < n_flow; ++i_flow)
404 {
406 i_flow, idx, liquid_volume, position, leaving_flow, dead_count);
407 }
408 }
409
410 double d_t{};
412 std::size_t n_particles{};
419 // Kokkos::View<float**, Kokkos::LayoutLeft> random;
420
422
425 };
426} // namespace Simulation::KernelInline
427
428#endif
Kokkos::View< Status *, ComputeSpace > ParticleStatus
Definition alias.hpp:74
std::conditional_t< is_const, Kokkos::View< const std::size_t **, Kokkos::LayoutRight, ExecSpace, Kokkos::MemoryTraits< Kokkos::RandomAccess > >, Kokkos::View< std::size_t **, Kokkos::LayoutRight, ExecSpace > > NeighborsView
Definition alias.hpp:147
Kokkos::View< uint64_t *, ComputeSpace > ParticlePositions
Definition alias.hpp:73
std::conditional_t< is_const, Kokkos::View< const double **, Kokkos::LayoutRight, ExecSpace, Kokkos::MemoryTraits< Kokkos::RandomAccess > >, Kokkos::View< double **, Kokkos::LayoutRight, ExecSpace > > CumulativeProbabilityView
Definition alias.hpp:138
@ Move
Move in domain.
Definition events.hpp:20
@ Exit
Remove particle from list due to move in domain.
Definition events.hpp:19
std::conditional_t< is_const, Kokkos::View< const double *, ExecSpace, Kokkos::MemoryTraits< Kokkos::RandomAccess > >, Kokkos::View< double *, ExecSpace > > VolumeView
Definition alias.hpp:115
Status
Definition alias.hpp:58
@ Idle
Definition alias.hpp:59
@ Exit
Definition alias.hpp:61
ParticleAgesBase< ComputeSpace > ParticleAges
Definition alias.hpp:76
gen_pool_type< Kokkos::DefaultExecutionSpace > pool_type
Definition alias.hpp:39
Kokkos:: View< Kokkos::Experimental::half_t **, Kokkos::LayoutRight, ComputeSpace > ParticleSamples
Definition alias.hpp:78
std::conditional_t< is_const, Kokkos::View< const LeavingFlow *, Kokkos::SharedHostPinnedSpace >, Kokkos::View< LeavingFlow *, Kokkos::SharedHostPinnedSpace > > LeavingFlowView
Definition alias.hpp:132
Definition kernels.hpp:12
constexpr bool enable_leave
Definition move_kernel.hpp:25
constexpr bool enable_move
Definition move_kernel.hpp:28
KOKKOS_INLINE_FUNCTION std::size_t __find_next_compartment(const bool do_serch, const MC::NeighborsView< ComputeSpace, true > &neighbors, const MC::CumulativeProbabilityView< ComputeSpace, true > &cumulative_probability, const std::size_t i_compartment, const double random_number)
probably overkill binary search to find next compartment
Definition move_kernel.hpp:64
constexpr bool disable_leave
Definition move_kernel.hpp:26
KOKKOS_INLINE_FUNCTION bool probability_leaving(float random_number, double volume, double flow, double dt)
Definition probability_leaving.hpp:22
KOKKOS_INLINE_FUNCTION bool probability_leaving< void >(float random_number, double volume, double flow, double dt)
Definition probability_leaving.hpp:35
constexpr bool disable_move
Definition move_kernel.hpp:27
Probes< AutoGenerated::probe_buffer_size > ProbeAutogeneratedBuffer
Definition probe.hpp:61
Structure to store information about domain needed during MC cycle data is likely to change between e...
Definition domain.hpp:27
Use to count events that occurs during Monte-Carlo processing cycles.
Definition events.hpp:45
KOKKOS_INLINE_FUNCTION void operator()(TagMove, const std::size_t &idx) const
Definition move_kernel.hpp:218
bool enable_leave
Definition move_kernel.hpp:424
KOKKOS_INLINE_FUNCTION void operator()(TagLeave _tag, const std::size_t &idx, std::size_t &local_dead_count) const
Definition move_kernel.hpp:248
KOKKOS_FUNCTION void handle_move(const std::size_t idx) const
Definition move_kernel.hpp:293
KOKKOS_INLINE_FUNCTION void operator()(TagMove, const Kokkos::TeamPolicy< ComputeSpace >::member_type &team_handle) const
Definition move_kernel.hpp:204
KOKKOS_FORCEINLINE_FUNCTION void handle_exit(std::size_t idx, const MC::VolumeView< ComputeSpace, true > &liquid_volumes, std::size_t &dead_count) const
Definition move_kernel.hpp:395
MC::ParticleSamples random
Definition move_kernel.hpp:421
MoveFunctor(MC::ParticlePositions p, MC::ParticleStatus _status, MC::DomainState< ComputeSpace > m, MC::pool_type _random_pool, MC::EventContainer _events, ProbeAutogeneratedBuffer _probes, MC::ParticleAges _ages, MC::ParticleSamples _random)
Definition move_kernel.hpp:136
bool need_launch() const
Definition move_kernel.hpp:287
MC::ParticlePositions positions
Definition move_kernel.hpp:411
double d_t
Definition move_kernel.hpp:410
MC::DomainState< ComputeSpace, true > move
Definition move_kernel.hpp:413
void update(const ComputeSpace &ex, double _d_t, std::size_t n_p, MC::DomainState< ComputeSpace > move_i, MC::ParticlePositions _positions, MC::ParticleStatus _status, MC::ParticleAges _ages, MC::ParticleSamples _random, bool b_move, bool b_leave)
Definition move_kernel.hpp:177
std::size_t n_particles
Definition move_kernel.hpp:412
MC::EventContainer events
Definition move_kernel.hpp:416
ProbeAutogeneratedBuffer probes
Definition move_kernel.hpp:417
MC::ParticleStatus status
Definition move_kernel.hpp:415
KOKKOS_INLINE_FUNCTION void inner_handle_exit(const std::size_t i_flow, const std::size_t idx, const double liquid_volume, const std::size_t position, const MC::LeavingFlowView< true > &leaving_flow, std ::size_t &dead_count) const
Definition move_kernel.hpp:338
bool enable_move
Definition move_kernel.hpp:423
MC::ParticleAges ages
Definition move_kernel.hpp:418
MC::pool_type random_pool
Definition move_kernel.hpp:414
MoveFunctor(double _d_t, MC::ParticlePositions p, MC::ParticleStatus _status, std::size_t n_p, MC::DomainState< ComputeSpace > m, MC::pool_type _random_pool, MC::EventContainer _events, ProbeAutogeneratedBuffer _probes, MC::ParticleAges _ages, MC::ParticleSamples _random, bool b_move, bool b_leave)
Definition move_kernel.hpp:157
Definition move_kernel.hpp:130
Definition move_kernel.hpp:127