BioCMAMC-ST
move_kernel.hpp
1#ifndef __SIMULATION_MOVE_KERNEL_HPP__
2#define __SIMULATION_MOVE_KERNEL_HPP__
3
4#include "Kokkos_Assert.hpp"
5#include <Kokkos_Core.hpp>
6#include <Kokkos_Random.hpp>
7#include <biocma_cst_config.hpp>
8#include <cassert>
9#include <mc/domain.hpp>
10#include <mc/events.hpp>
11#include <mc/prng/prng.hpp>
12#include <mc/traits.hpp>
13#include <simulation/alias.hpp>
14#include <simulation/probability_leaving.hpp>
15#include <simulation/probe.hpp>
16#include <utility>
17
19{
20 constexpr bool enable_leave =true;
21 constexpr bool disable_leave =false;
22 constexpr bool disable_move =false;
23 constexpr bool enable_move =true;
24
25 template <typename ExecSpace> struct MoveInfo
26 {
27 ConstNeighborsView<ExecSpace> neighbors;
32 Kokkos::View<double*, ExecSpace> liquid_volume;
33
35 : diag_transition("diag_transition", 0),
36 leaving_flow("leaving_flow", 0),
37 index_leaving_flow("index_leaving_flow", 0), liquid_volume("liquid_volume")
38 {
39 }
40 };
41
42 KOKKOS_INLINE_FUNCTION std::size_t
43 __find_next_compartment(const ConstNeighborsView<ComputeSpace>& neighbors,
44 const CumulativeProbabilityView<ComputeSpace>& cumulative_probability,
45 const std::size_t i_compartment,
46 const double random_number)
47 {
48 const int max_neighbor = static_cast<int>(neighbors.extent(1));
49
50 std::size_t next = neighbors(i_compartment, 0); // Default to the first neighbor
51
52 // Iterate through the neighbors to find the appropriate next compartment
53 for (int k_neighbor = 0; k_neighbor < max_neighbor - 1; ++k_neighbor)
54 {
55
56 // Get the cumulative probability range for the current neighbor
57 const auto pi = cumulative_probability(i_compartment, k_neighbor);
58 const auto pn =
59 cumulative_probability(i_compartment, k_neighbor + 1);
60
61
62 // Use of a Condition mask to avoid branching.
63 next = (random_number <= pn && pi <= random_number) ? neighbors(i_compartment, k_neighbor + 1)
64 : next;
65 }
66
67 return next; // Return the index of the chosen next compartment
68 }
69
70 template <bool enable_leave, bool enable_move> struct MoveFunctor
71 {
72 MoveFunctor(double _d_t,
74 MC::ParticleStatus _status,
75 std::size_t n_p,
77 MC::KPRNG::pool_type _random_pool,
78 MC::EventContainer _events)
79 : d_t(_d_t), positions(std::move(p)), n_particles(n_p), move(std::move(m)),
80 random_pool(_random_pool), status(std::move(_status)), events(std::move(_events)) {};
81
82 KOKKOS_INLINE_FUNCTION void
83 operator()(const Kokkos::TeamPolicy<ComputeSpace>::member_type& team_handle,
84 std::size_t& dead_count) const
85 {
86 GET_INDEX(n_particles);
87 if (status(idx) != MC::Status::Idle) [[unlikely]]
88 {
89 // Kokkos::printf("Skip %ld", idx);
90 return;
91 }
92
93 if constexpr (enable_move)
94 {
95 handle_move(idx);
96 }
97
98 if constexpr (enable_leave)
99 {
100 handle_exit(idx, dead_count);
101 }
102 }
103
104 KOKKOS_FUNCTION void handle_move(const std::size_t idx) const
105 {
106 auto generator = random_pool.get_state();
107 const float rng1 = generator.frand(0., 1.);
108 const double rng2 = generator.drand(0., 1.);
109 random_pool.free_state(generator);
110
111 const std::size_t i_current_compartment = positions(idx);
112
113 const bool mask_next = probability_leaving(rng1,
114 move.liquid_volume(i_current_compartment),
115 move.diag_transition(i_current_compartment),
116 d_t);
117
118 positions(idx) =
119 (mask_next)
121 move.neighbors, move.cumulative_probability, i_current_compartment, rng2)
122 : i_current_compartment;
123
124 KOKKOS_ASSERT(positions(idx) < move.liquid_volume.extent(0));
125
126 if constexpr (AutoGenerated::FlagCompileTime::enable_event_counter)
127 {
128 if (mask_next)
129 {
131 }
132 }
133 }
134
135 KOKKOS_FUNCTION void handle_exit(std::size_t idx, std::size_t& dead_count) const
136 {
137
138 for (size_t i = 0LU; i < move.index_leaving_flow.size(); ++i)
139 {
140 const auto position = positions(idx);
141 auto generator = random_pool.get_state();
142 const float random_number = generator.frand(0., 1.);
143 random_pool.free_state(generator);
144
145 const auto& index = move.index_leaving_flow(i);
146 const auto& flow = move.leaving_flow(i);
147 if (position != index)
148 {
149 return;
150 }
151
152 if (probability_leaving(random_number, move.liquid_volume(position), flow, d_t))
153 {
154 dead_count += 1;
157 if constexpr (AutoGenerated::FlagCompileTime::use_probe)
158 {
159 // Ignore ret value, if probe is full were gonna miss events which is not really
160 // important
161 // auto _ = probe_at_t.set(properties.hydraulic_time);
162 }
163 }
164 }
165 }
166
167 double d_t;
169 std::size_t n_particles;
174 };
175} // namespace Simulation::KernelInline
176
177#endif
Kokkos::Random_XorShift1024_Pool< Kokkos::DefaultExecutionSpace > pool_type
Definition prng.hpp:17
Kokkos::View< Status *, ComputeSpace > ParticleStatus
Definition alias.hpp:20
Kokkos::View< uint64_t *, ComputeSpace > ParticlePositions
Definition alias.hpp:19
@ Move
Move in domain.
@ Exit
Remove particle from list due to move in domain.
Definition move_kernel.hpp:19
constexpr bool enable_leave
Definition move_kernel.hpp:20
constexpr bool enable_move
Definition move_kernel.hpp:23
constexpr bool disable_leave
Definition move_kernel.hpp:21
KOKKOS_INLINE_FUNCTION std::size_t __find_next_compartment(const ConstNeighborsView< ComputeSpace > &neighbors, const CumulativeProbabilityView< ComputeSpace > &cumulative_probability, const std::size_t i_compartment, const double random_number)
Definition move_kernel.hpp:43
KOKKOS_INLINE_FUNCTION bool probability_leaving(float random_number, double volume, double flow, double dt)
Definition probability_leaving.hpp:31
constexpr bool disable_move
Definition move_kernel.hpp:22
Kokkos::View< std::size_t *, Kokkos::SharedHostPinnedSpace > LeavingFlowIndexType
Definition alias.hpp:25
Kokkos:: View< double *, Kokkos::LayoutLeft, ExecSpace, Kokkos::MemoryTraits< Kokkos::RandomAccess > > DiagonalView
Definition alias.hpp:14
Kokkos::View< double *, Kokkos::SharedHostPinnedSpace > LeavingFlowType
Definition alias.hpp:26
Kokkos:: View< const double **, Kokkos::LayoutRight, Space, Kokkos::MemoryTraits< Kokkos::RandomAccess > > CumulativeProbabilityView
Definition alias.hpp:20
Use to count events that occurs during Monte-Carlo processing cycles.
Definition events.hpp:43
KOKKOS_FORCEINLINE_FUNCTION constexpr void wrap_incr() const
Definition events.hpp:109
Definition move_kernel.hpp:71
KOKKOS_INLINE_FUNCTION void operator()(const Kokkos::TeamPolicy< ComputeSpace >::member_type &team_handle, std::size_t &dead_count) const
Definition move_kernel.hpp:83
MC::ParticleStatus status
Definition move_kernel.hpp:172
MoveFunctor(double _d_t, MC::ParticlePositions p, MC::ParticleStatus _status, std::size_t n_p, MoveInfo< ComputeSpace > m, MC::KPRNG::pool_type _random_pool, MC::EventContainer _events)
Definition move_kernel.hpp:72
MC::ParticlePositions positions
Definition move_kernel.hpp:168
MC::EventContainer events
Definition move_kernel.hpp:173
std::size_t n_particles
Definition move_kernel.hpp:169
MoveInfo< ComputeSpace > move
Definition move_kernel.hpp:170
KOKKOS_FUNCTION void handle_move(const std::size_t idx) const
Definition move_kernel.hpp:104
double d_t
Definition move_kernel.hpp:167
MC::KPRNG::pool_type random_pool
Definition move_kernel.hpp:171
KOKKOS_FUNCTION void handle_exit(std::size_t idx, std::size_t &dead_count) const
Definition move_kernel.hpp:135
Definition move_kernel.hpp:26
MoveInfo()
Definition move_kernel.hpp:34
DiagonalView< ExecSpace > diag_transition
Definition move_kernel.hpp:28
LeavingFlowType leaving_flow
Definition move_kernel.hpp:30
LeavingFlowIndexType index_leaving_flow
Definition move_kernel.hpp:31
CumulativeProbabilityView< ExecSpace > cumulative_probability
Definition move_kernel.hpp:29
ConstNeighborsView< ExecSpace > neighbors
Definition move_kernel.hpp:27
Kokkos::View< double *, ExecSpace > liquid_volume
Definition move_kernel.hpp:32