BioCMAMC-ST
two_meta_nb.hpp
1// #ifndef __TWOMETA_MODEL_NB_HPP__
2// #define __TWOMETA_MODEL_NB_HPP__
3
4// #include <common/traits.hpp>
5// #include <mc/macros.hpp>
6// #include <mc/prng/prng_extension.hpp>
7// #include <mc/traits.hpp>
8// #include <models/uptake_dyn.hpp>
9// #include <models/utils.hpp>
10// #include <string_view>
11
12// namespace Models
13// {
14
15// struct TwoMetaNb
16// {
17// using uniform_weight = std::true_type; // Using type alias
18// using Self = TwoMetaNb;
19// using FloatType = float;
20// using Config = std::nullopt_t;
21
22// enum class particle_var : int
23// {
24// age = INDEX_FROM_ENUM(Uptakeparticle_var::COUNT),
25// length,
26// nu1,
27// nu2,
28// l_cp,
29// nu_eff_1, // This is not itself a model property but stored to be
30// exported nu_eff_2, // This is not itself a model property but stored to
31// be exported
32// // TODO FIND BETTER WAY TO STORE/GET CONTRIBUTIONS
33// phi_pts,
34// contrib_phi_s,
35// contrib_phi_o2,
36// contrib_phi_ac,
37// COUNT
38// };
39
40// static constexpr std::size_t n_var =
41// INDEX_FROM_ENUM(particle_var::COUNT); static constexpr std::string_view
42// name = "two_mode_nb"; using SelfParticle =
43// MC::ParticlesModel<Self::n_var, Self::FloatType>;
44
45// // Constants BEGIN
46// MODEL_CONSTANT FloatType MolarMassG
47// = Models::MolarMass::GramPerMole::glucose<FloatType>;
48// MODEL_CONSTANT FloatType MolarMassO2
49// = Models::MolarMass::GramPerMole::dioxygen<FloatType>; // g/mol
50
51// MODEL_CONSTANT FloatType l_max_m = 5e-6; // m
52// MODEL_CONSTANT FloatType l_c_m = 3e-6; // m
53// MODEL_CONSTANT FloatType d_m = 0.3e-6; // m
54// MODEL_CONSTANT FloatType l_min_m = 0.9e-6; // m
55
56// MODEL_CONSTANT FloatType dl_max_ms
57// = 10 * 2e-10; // m/s https://doi.org/10.7554/eLife.67495;
58
59// MODEL_CONSTANT FloatType lin_density
60// = c_linear_density(static_cast<FloatType>(1000), d_m);
61
62// MODEL_CONSTANT FloatType y_sx_1
63// = 1. / 2.217737e+00; // Mode 1 S to X yield
64// (mass)
65// MODEL_CONSTANT FloatType y_sx_2 = y_sx_1 / 3.; // Mode 2 S to X yield
66// (mass) MODEL_CONSTANT FloatType y_sa = 0.8; // S to A yield
67// (mass) MODEL_CONSTANT FloatType y_os_molar = 3; // 3 mol o2 per mol for
68// glucose
69
70// MODEL_CONSTANT FloatType tau_1 = 1000.; // s
71// MODEL_CONSTANT FloatType tau_2 = 1000.; // s
72
73// MODEL_CONSTANT FloatType phi_max = (dl_max_ms * lin_density) * y_sx_1;
74// MODEL_CONSTANT FloatType phi_o2_max
75// = 10 * phi_max / MolarMassG * y_os_molar * MolarMassO2; // kgS/s
76// MODEL_CONSTANT FloatType nu_max_kg_s = dl_max_ms * lin_density;
77
78// MODEL_CONSTANT FloatType k_o
79// = 0.0001; // g/L: Anane et. al 2017 (Biochem. Eng. J) (g/g)
80// MODEL_CONSTANT FloatType k = 1e-2;
81// MODEL_CONSTANT FloatType k_perm = 1e-3;
82// MODEL_CONSTANT FloatType beta = 7;
83// MODEL_CONSTANT FloatType tau_ap_1 = 300;
84// MODEL_CONSTANT FloatType tau_ap_2 = 200;
85// MODEL_CONSTANT FloatType tau_ap_3 = 1000;
86
87// MODEL_CONSTANT auto length_c_dist
88// = MC::Distributions::TruncatedNormal<FloatType>(
89// l_c_m, l_c_m / 2., l_min_m, l_max_m); // use in out_str_l3
90
91// MODEL_CONSTANT FloatType adder_mean = 1.5e-6; // m
92// MODEL_CONSTANT auto adder_dist
93// = MC::Distributions::TruncatedNormal<FloatType>(
94// adder_mean,
95// adder_mean / 2.,
96// adder_mean / 20.,
97// adder_mean * 10); // use in out_str_l3
98// // Constants END
99
100// static MC::ContribIndexBounds get_bounds();
101
102// KOKKOS_INLINE_FUNCTION static double
103// mass(std::size_t idx, const SelfParticle& arr)
104// {
105// return GET_PROPERTY(Self::particle_var::length) * lin_density;
106// }
107
108// static std::vector<std::string_view>
109// names()
110// {
111// return { "age", "length", "nu1", "nu2", "nu_eff_1", "nu_eff_2",
112// "a_p1", "a_p2", "a_p3", "phi_o2", "phi_g", "phi_pts" };
113// }
114
115// static std::vector<std::size_t>
116// get_number()
117// {
118// return { INDEX_FROM_ENUM(particle_var::age),
119// INDEX_FROM_ENUM(particle_var::length),
120// INDEX_FROM_ENUM(particle_var::nu1),
121// INDEX_FROM_ENUM(particle_var::nu2),
122// INDEX_FROM_ENUM(particle_var::nu_eff_1),
123// INDEX_FROM_ENUM(particle_var::nu_eff_2),
124// INDEX_FROM_ENUM(Uptakeparticle_var::ap_1),
125// INDEX_FROM_ENUM(Uptakeparticle_var::ap_2),
126// INDEX_FROM_ENUM(Uptakeparticle_var::ap_3),
127// INDEX_FROM_ENUM(particle_var::contrib_phi_o2),
128// INDEX_FROM_ENUM(particle_var::contrib_phi_s),
129// INDEX_FROM_ENUM(particle_var::phi_pts) };
130// }
131
132// static KOKKOS_INLINE_FUNCTION void
133// preinit()
134// {
135// Kokkos::printf("[Model]: PRENINIT:BEGIN\r\n");
136// // Kokkos::printf("[Model]: phi_max:%.12f\r\n", phi_pts_max *
137// 1e12);
138// // Kokkos::printf("[Model]: PRENINIT:END\r\n");
139// }
140
141// KOKKOS_INLINE_FUNCTION static void init(const MC::pool_type& random_pool,
142// std::size_t idx,
143// const SelfParticle& arr);
144
145// KOKKOS_INLINE_FUNCTION static MC::Status
146// update(const MC::pool_type& random_pool,
147// FloatType d_t,
148// std::size_t idx,
149// const SelfParticle& arr,
150// const MC::LocalConcentration& c);
151
152// KOKKOS_INLINE_FUNCTION static void
153// division(const MC::pool_type& random_pool,
154// std::size_t idx,
155// std::size_t idx2,
156// const SelfParticle& arr,
157// const SelfParticle& buffer_arr);
158
159// KOKKOS_INLINE_FUNCTION static void
160// contribution(std::size_t idx,
161// std::size_t position,
162// double weight,
163// const SelfParticle& arr,
164// const MC::ContributionView& contributions);
165// };
166
167// CHECK_MODEL(TwoMetaNb)
168
169// KOKKOS_INLINE_FUNCTION void
170// TwoMetaNb::init([[maybe_unused]] const MC::pool_type& random_pool,
171// std::size_t idx,
172// const SelfParticle& arr)
173// {
174
175// // auto& v = init_uptake_cst;
176// constexpr auto local_ac = adder_dist;
177
178// constexpr auto length_dist =
179// MC::Distributions::TruncatedNormal<FloatType>(
180// l_c_m / 2, l_c_m / 5., l_min_m, l_max_m);
181
182// constexpr auto mu_nu_dist = nu_max_kg_s * 0.1;
183// constexpr auto nu_1_initial_dist
184// = MC::Distributions::TruncatedNormal<FloatType>(
185// mu_nu_dist, mu_nu_dist / 7., 0.,
186// static_cast<double>(nu_max_kg_s));
187
188// auto gen = random_pool.get_state();
189// auto l = length_dist.draw(gen);
190
191// GET_PROPERTY(Self::particle_var::length) = l;
192// GET_PROPERTY(Self::particle_var::l_cp) = l + local_ac.draw(gen);
193// GET_PROPERTY(particle_var::nu1) = nu_1_initial_dist.draw(gen);
194// random_pool.free_state(gen);
195// GET_PROPERTY(particle_var::contrib_phi_s) = 0;
196
197// Uptake<Self>::init(random_pool, idx, arr);
198// }
199
200// KOKKOS_INLINE_FUNCTION MC::Status
201// TwoMetaNb::update([[maybe_unused]] const MC::pool_type& random_pool,
202// FloatType d_t,
203// std::size_t idx,
204// const SelfParticle& arr,
205// const MC::LocalConcentration& concentrations)
206// {
207// const auto phi_s
208// = Uptake<Self>::uptake_step(phi_max,
209// d_t,
210// idx,
211// arr,
212// concentrations,
213// &GET_PROPERTY(Self::particle_var::phi_pts));
214
215// const auto o = Kokkos::max(static_cast<FloatType>(concentrations(1)),
216// 0.F);
217
218// const auto phi_o2 = (phi_o2_max)*o / (o + k_o); // gO2/s
219
220// const auto nu_1_star
221// = y_sx_1 * MolarMassG
222// * Kokkos::min(phi_s / MolarMassG,
223// phi_o2 / MolarMassO2 / y_os_molar); // gX/s
224
225// const auto s_1_star = (1.F / y_sx_1 * nu_1_star);
226
227// const auto phi_s_residual_1_star = Kokkos::max(phi_s - s_1_star, 0.F);
228// KOKKOS_ASSERT(phi_s_residual_1_star >= 0.F);
229
230// const auto nu_2_star = y_sx_2 * phi_s_residual_1_star; // gX/s
231
232// auto& nu_eff_1 = GET_PROPERTY(Self::particle_var::nu_eff_1);
233// auto& nu_eff_2 = GET_PROPERTY(Self::particle_var::nu_eff_2);
234// auto& nu_1 = GET_PROPERTY(Self::particle_var::nu1);
235// auto& nu_2 = GET_PROPERTY(Self::particle_var::nu2);
236
237// nu_eff_1 = Kokkos::min(nu_1_star, nu_1); // gX/s
238
239// const auto s_1 = (1.F / y_sx_1 * nu_eff_1);
240// const auto phi_s_residual_1 = Kokkos::max(phi_s - s_1, 0.F);
241
242// nu_eff_2 = Kokkos::min(y_sx_2 * phi_s_residual_1,
243// nu_2); // gX/s
244
245// const auto sum_nu = (nu_eff_1 + nu_eff_2);
246
247// const auto s_growth = s_1 + (1 / y_sx_2 * nu_eff_2);
248
249// const auto s_overflow = phi_s - s_growth;
250
251// KOKKOS_ASSERT(nu_eff_1 >= 0.F);
252// KOKKOS_ASSERT(nu_eff_2 >= 0.F);
253
254// // CONTRIBS
255// GET_PROPERTY(Self::particle_var::contrib_phi_s) = -phi_s;
256// GET_PROPERTY(Self::particle_var::contrib_phi_o2)
257// = -1.F
258// * ((1.F / y_sx_1 / MolarMassG * y_os_molar * MolarMassO2 *
259// nu_eff_1)
260// + 0.F * nu_eff_2);
261
262// GET_PROPERTY(Self::particle_var::contrib_phi_ac)
263// = nu_eff_2 / y_sx_2 * y_sa
264// + (s_overflow > 0. ? y_sa * (s_overflow) : 0);
265
266// // ODE
267// nu_1 += d_t * ((nu_1_star - nu_1) / tau_1);
268
269// nu_2 += d_t * ((nu_2_star - nu_2) / tau_2);
270
271// GET_PROPERTY(Self::particle_var::length) += d_t * (sum_nu / lin_density);
272
273// GET_PROPERTY(Self::particle_var::age) += d_t;
274
275// return (GET_PROPERTY(Self::particle_var::length)
276// > GET_PROPERTY(Self::particle_var::l_cp))
277// ? MC::Status::Division
278// : MC::Status::Idle;
279// }
280
281// KOKKOS_INLINE_FUNCTION void
282// TwoMetaNb::division(const MC::pool_type& random_pool,
283// std::size_t idx,
284// std::size_t idx2,
285// const SelfParticle& arr,
286// const SelfParticle& child_buffer_arr)
287// {
288// constexpr FloatType half = 0.5;
289// constexpr auto local_ac = adder_dist;
290// const FloatType new_current_length
291// = GET_PROPERTY(particle_var::length) / static_cast<FloatType>(2.);
292
293// GET_PROPERTY(Self::particle_var::length) = new_current_length;
294// GET_PROPERTY(Self::particle_var::age) = 0;
295
296// GET_PROPERTY_FROM(idx2, child_buffer_arr, Self::particle_var::length)
297// = new_current_length;
298
299// GET_PROPERTY_FROM(idx2, child_buffer_arr, Self::particle_var::age) = 0;
300
301// const auto nu_1_o
302// = GET_PROPERTY_FROM(idx, arr, Self::particle_var::nu_eff_1);
303// const auto nu_2_o
304// = GET_PROPERTY_FROM(idx, arr, Self::particle_var::nu_eff_2);
305
306// auto gen = random_pool.get_state();
307
308// GET_PROPERTY(Self::particle_var::l_cp)
309// = new_current_length + local_ac.draw(gen);
310
311// if (nu_1_o != 0)
312// {
313// GET_PROPERTY_FROM(idx2, child_buffer_arr, Self::particle_var::nu1)
314// = MC::Distributions::TruncatedNormal<FloatType>::draw_from(
315// gen, nu_1_o, nu_1_o * half, 0.F, 1.F);
316// }
317
318// if (nu_2_o != 0)
319// {
320// GET_PROPERTY_FROM(idx2, child_buffer_arr, Self::particle_var::nu2)
321// = MC::Distributions::TruncatedNormal<FloatType>::draw_from(
322// gen, nu_2_o, nu_2_o * half, 0.F, 1.F);
323// }
324
325// GET_PROPERTY_FROM(idx2, child_buffer_arr, Self::particle_var::l_cp)
326// = new_current_length + local_ac.draw(gen);
327// random_pool.free_state(gen);
328
329// Uptake<Self>::division(random_pool, idx, idx2, arr, child_buffer_arr);
330// }
331
332// inline MC::ContribIndexBounds
333// TwoMetaNb::get_bounds()
334// {
335// const int begin = INDEX_FROM_ENUM(Self::particle_var::contrib_phi_s);
336// const int end = INDEX_FROM_ENUM(Self::particle_var::contrib_phi_ac);
337// assert(begin < end);
338// return { .begin = begin, .end = end };
339// }
340// // KOKKOS_INLINE_FUNCTION void
341// // TwoMetaNb::contribution([[maybe_unused]] std::size_t idx,
342// // std::size_t position,
343// // double weight,
344// // [[maybe_unused]] const SelfParticle& arr,
345// // const MC::ContributionView& contributions)
346// // {
347// // auto access = contributions.access();
348// // access(0, position) +=
349// // weight * GET_PROPERTY(Self::particle_var::contrib_phi_s); //
350// NOLINT
351// // access(1, position) +=
352// // weight * GET_PROPERTY(Self::particle_var::contrib_phi_o2); //
353// NOLINT
354// // access(2, position) +=
355// // weight * GET_PROPERTY(Self::particle_var::contrib_phi_ac); //
356// NOLINT
357// // }
358
359// static_assert(HasExportProperties<TwoMetaNb>, "ee");
360
361// } // namespace Models
362
363// #endif //__TWOMETA_MODEL_NB_HPP__