BioCMAMC-ST
post_process.hpp
1#ifndef __CORE_POST_PROCESS_PUBLIC_HPP__
2#define __CORE_POST_PROCESS_PUBLIC_HPP__
3#include <Kokkos_Core.hpp>
4#include <Kokkos_Core_fwd.hpp>
5#include <Kokkos_Macros.hpp>
6#include <Kokkos_ScatterView.hpp>
7#include <common/common.hpp>
8#include <mc/alias.hpp>
9#include <mc/particles_container.hpp>
10#include <mc/traits.hpp>
11#include <stdexcept>
12
13template <typename MemorySpace>
14using ParticlePropertyViewType
15 = Kokkos::View<double**, Kokkos::LayoutRight, MemorySpace>;
16
17using SubViewtype = Kokkos::Subview<ParticlePropertyViewType<ComputeSpace>,
18 decltype(Kokkos::ALL),
19 std::size_t>;
20namespace PostProcessing
22 struct BonceBuffer
23 {
24 std::optional<ParticlePropertyViewType<HostSpace>> particle_values;
25 std::optional<ParticlePropertyViewType<HostSpace>> spatial_values;
26 std::optional<ParticlePropertyViewType<HostSpace>> ages;
27 std::optional<std::vector<std::string>> vnames;
28 std::optional<MC::ParticlePositionT<MC::HostSpace>> position;
29 };
30
31 namespace
32 {
33 template <typename Model, typename ExecutionSpace>
34 struct GetPropertiesFunctor
35 {
36 using ComputeSpace = typename ExecutionSpace::memory_space;
37
38 GetPropertiesFunctor(
39 std::size_t n_p,
40 MC::ParticlePositions position,
41 typename Model::SelfParticle model,
43 ParticlePropertyViewType<ComputeSpace> particle_values,
44 ParticlePropertyViewType<ComputeSpace> spatial_values,
45 ParticlePropertyViewType<ComputeSpace> ages_value,
46 MC::ParticleStatus status)
47 : n_p(n_p), position(std::move(position)), model(std::move(model)),
48 ages(std::move(ages)), particle_values(std::move(particle_values)),
49 spatial_values(std::move(spatial_values)),
50 ages_value(std::move(ages_value)), status(std::move(status))
51 {
52 }
53
54 KOKKOS_INLINE_FUNCTION
55 void
56 operator()(const int i_particle) const
58 {
59 if (status(i_particle) != MC::Status::Idle)
60 {
61 return;
62 }
63
64 auto access = scatter_spatial_values.access();
65 for (size_t k_var = 0; k_var < Model::n_var; ++k_var)
66 {
67 const auto current = model(i_particle, k_var);
68 access(k_var, position(i_particle)) += current;
69 particle_values(k_var, i_particle) = current;
70 }
71
72 const auto mass = Model::mass(i_particle, model);
73 access(Model::n_var, position(i_particle)) += mass;
74 particle_values(Model::n_var, i_particle) = mass;
75 ages_value(0, i_particle) = ages(i_particle, 0);
76 ages_value(1, i_particle) = ages(i_particle, 1);
77 }
78
79 KOKKOS_INLINE_FUNCTION
80 void
81 operator()(const int i_particle) const
83 {
84 if (status(i_particle) != MC::Status::Idle)
85 {
86 return;
87 }
88
89 auto access = scatter_spatial_values.access();
90 for (size_t k_var = 0; k_var < kindices.extent(0); ++k_var)
91 {
92 const auto current = model(i_particle, kindices(k_var));
93 access(k_var, position(i_particle)) += current;
94 particle_values(k_var, i_particle) = current;
95 }
96
97 const auto mass = Model::mass(i_particle, model);
98 access(kindices.extent(0), position(i_particle)) += mass;
99 particle_values(kindices.extent(0), i_particle) = mass;
100 ages_value(0, i_particle) = ages(i_particle, 0);
101 ages_value(1, i_particle) = ages(i_particle, 1);
102 }
103
104 void
105 run()
106 {
107
108 scatter_spatial_values
109 = Kokkos::Experimental::create_scatter_view(spatial_values);
110
111 // Use kindices for partial to map with correct vector position
112 // Warning UB if len(kindex)!=len(vnames)
114 {
115 static const auto indices = Model::get_number();
116
117 Kokkos::View<size_t*, HostSpace> host_index("host_index",
118 indices.size());
119 for (size_t i = 0; i < indices.size(); ++i)
120 {
121 host_index(i) = indices[i];
122 }
123 kindices
124 = Kokkos::create_mirror_view_and_copy(ComputeSpace(), host_index);
125 }
126
127 Kokkos::parallel_for("get_properties",
128 Kokkos::RangePolicy<ExecutionSpace>(0, n_p),
129 *this);
130
131 Kokkos::fence();
132 Kokkos::Experimental::contribute(spatial_values,
133 scatter_spatial_values);
134 }
135
136 std::size_t n_p;
137 MC::ParticlePositions position;
138 typename Model::SelfParticle model;
139 MC::ParticleAges ages;
140 ParticlePropertyViewType<ComputeSpace> particle_values;
141 ParticlePropertyViewType<ComputeSpace> spatial_values;
142 ParticlePropertyViewType<ComputeSpace> ages_value;
143 MC::ParticleStatus status;
144 Kokkos::View<const size_t*, ComputeSpace> kindices;
145 Kokkos::Experimental::
146 ScatterView<double**, Kokkos::LayoutRight, ComputeSpace>
147 scatter_spatial_values;
148 };
149 } // namespace
150
151 template <ModelType M>
152 ParticlePropertyViewType<ComputeSpace>
154 {
155 // USE list size not Kokkos View size.
156 // bcause container allocates more
157 // particles than needed
158 const std::size_t n_p = container.n_particles();
159 auto p_age = container.ages;
160 ParticlePropertyViewType<ComputeSpace> ages_values("ages_values", 2, n_p);
161
162 Kokkos::parallel_for(
163 "get_age",
164 Kokkos::RangePolicy<ComputeSpace>(0, n_p),
165 KOKKOS_LAMBDA(const std::size_t i_particle) {
166 ages_values(0, i_particle) = p_age(i_particle, 0);
167 ages_values(1, i_particle) = p_age(i_particle, 1);
168 });
169 return ages_values;
170 }
171
172 template <ModelType M>
173 std::optional<PostProcessing::BonceBuffer>
175 const std::size_t n_compartment,
176 const bool with_age)
177 {
178 if constexpr (HasExportProperties<M>)
179 {
180 container.force_remove_dead();
181 BonceBuffer properties;
182 properties.ages = std::nullopt;
183
184 // USE list size not Kokkos View size. bcause container allocates more
185 // particles than needed
186 const std::size_t n_p = container.n_particles();
187
188 auto ar = M::names();
189 properties.vnames = std::vector<std::string>(ar.begin(), ar.end());
190 properties.vnames->emplace_back("mass");
191
192 std::size_t n_var = M::n_var + 1;
193 if constexpr (HasExportPropertiesPartial<M>)
194 {
195 n_var = ar.size() + 1;
196 if (ar.size() != M::get_number().size())
197 {
198 throw std::invalid_argument("Partial export Model need to have same "
199 "number of name and indices");
200 }
201 }
202
203 ParticlePropertyViewType<ComputeSpace> spatial_values(
204 "property_spatial", n_var, n_compartment);
205 ParticlePropertyViewType<ComputeSpace> particle_values(
206 "property_values", n_var, n_p);
207
208 // TODO Currently view is allocated and filled even if with_age flag is
209 // turned of, with_age controlls export but not postprocessing
210 ParticlePropertyViewType<ComputeSpace> ages_values("ages_values", 2, n_p);
211
212 using space = ComputeSpace;
213
214 GetPropertiesFunctor<M, space>(n_p,
215 container.position,
216 container.model,
217 container.ages,
218 particle_values,
219 spatial_values,
220 ages_values,
221 container.status)
222 .run();
223
224 properties.particle_values = Kokkos::create_mirror_view_and_copy(
225 Kokkos::HostSpace(), particle_values);
226 properties.spatial_values = Kokkos::create_mirror_view_and_copy(
227 Kokkos::HostSpace(), spatial_values);
228
229 if constexpr (AutoGenerated::PostProcessing::FlagCompileTime::
230 export_position)
231 {
232 if (n_compartment > 1)
233 {
234 auto position = Kokkos::create_mirror_view_and_copy(
235 MC::HostSpace(), container.position);
236 properties.position.emplace(position);
237 }
238 }
239
240 if (with_age)
241 {
242 // ParticlePropertyViewType<ComputeSpace> ages_values(
243 // "ages_values", 2, n_p);
244
245 properties.ages = Kokkos::create_mirror_view_and_copy(
246 Kokkos::HostSpace(), ages_values);
247 }
248
249 return properties;
250 }
251 else
252 {
253
254 if (with_age)
255 {
256 BonceBuffer properties;
257 properties.ages = Kokkos::create_mirror_view_and_copy(
258 Kokkos::HostSpace(), get_particle_age_only(container));
259 return properties;
260 }
261 return std::nullopt;
262 }
263 }
264
265} // namespace PostProcessing
266#endif
Main owning object for Monte-Carlo particles.
Definition particles_container.hpp:59
void force_remove_dead()
Clean all the non-idle particle even if number smaller than threshold.
Definition particles_container.hpp:467
Model::SelfParticle model
Definition particles_container.hpp:84
KOKKOS_INLINE_FUNCTION std::size_t n_particles() const
Gets the number of particles in the container.
Definition particles_container.hpp:453
MC::ParticlePositions position
Definition particles_container.hpp:87
ParticleAges ages
Definition particles_container.hpp:90
MC::ParticleStatus status
Definition particles_container.hpp:88
SFNIAE way to check whether model allow all value saving.
Definition traits.hpp:172
SFNIAE way to check whether model allow partial value saving.
Definition traits.hpp:178
Model that can export properties.
Definition traits.hpp:186
Kokkos::DefaultHostExecutionSpace HostSpace
Definition alias.hpp:18
Kokkos::View< Status *, ComputeSpace > ParticleStatus
Definition alias.hpp:144
ParticlePositionT< ComputeSpace > ParticlePositions
Definition alias.hpp:143
@ Idle
Definition alias.hpp:126
ParticleAgesBase< ComputeSpace > ParticleAges
Definition alias.hpp:147
Definition impl_post_process.hpp:21
std::optional< PostProcessing::BonceBuffer > get_properties(MC::ParticlesContainer< M > &container, const std::size_t n_compartment, const bool with_age)
Definition post_process.hpp:173
ParticlePropertyViewType< ComputeSpace > get_particle_age_only(MC::ParticlesContainer< M > &container)
Definition post_process.hpp:152
Definition post_process.hpp:22
std::optional< ParticlePropertyViewType< HostSpace > > ages
Definition post_process.hpp:25
std::optional< ParticlePropertyViewType< HostSpace > > particle_values
Definition post_process.hpp:23
std::optional< std::vector< std::string > > vnames
Definition post_process.hpp:26
std::optional< MC::ParticlePositionT< MC::HostSpace > > position
Definition post_process.hpp:27
std::optional< ParticlePropertyViewType< HostSpace > > spatial_values
Definition post_process.hpp:24