BioCMAMC-ST
old_model_ecoli.hpp
1// #ifndef __BIO_MODEL_UPTAKE_ACETATE_HPP__
2// #define __BIO_MODEL_UPTAKE_ACETATE_HPP__
3
4// #include "mc/prng/prng.hpp"
5// #include <Kokkos_Core.hpp>
6
7// #include <mc/particles/particle_model.hpp>
8
9// #include <models/utils.hpp>
10// #include <numbers>
11
12// namespace implEcoli
13// {
14
15// #define MONOD_RATIO(__c1__, __x1__, __k1__) ((__c1__) * (__x1__) / ((__x1__) + (__k1__)))
16
17// #define _INDICES(__name__) static_cast<std::size_t>(Indices::__name__)
18
19
20// struct Yields
21// {
22
23// static constexpr double Y_EG = 12.05; // mol_E/mol_G
24// static constexpr double Y_XG = 1.15; // mol_X/mol_G
25// static constexpr double m = 250; // µmol_G/g_X.h
26// static constexpr double Y_OG = 6.; // mol_O/mol_G
27// static constexpr double Yo_EG = 20.; // mol_E/mol_G
28// static constexpr double Yf_EG = 3.; // mol_E/mol_G
29// static constexpr double Y_AG = 1.5; // mol_A/mol_G (modified for CO2 production)
30// // static constexpr double Y_CO2G_over = 2.; // mol_CO2/mol_G (overflow metabolism) not used
31
32// static constexpr double Y_EA = 12.05 / 3.; // mol_E/mol_A
33// static constexpr double Y_XA = 0.4; // mol_X/mol_A
34// static constexpr double Y_OA = 2.; // mol_O/mol_A
35// static constexpr double Yo_EA = 4.67; // mol_E/mol_A
36// static constexpr double x_s = 1.15; // 2.;
37
38// static constexpr double nu_s_x = Models::MolarMass::glucose / Models::MolarMass::X *
39// (Yields::Y_EG + Yields::Yo_EG) /
40// (Yields::Y_XG * Yields::Yo_EG);
41// };
42
43
44
45// // All in seconds
46// struct Tau
47// {
48// static constexpr double new_permease = 40.;
49// static constexpr double tau_rm_perm = 200.;
50// static constexpr double pts = 20.;
51// static constexpr double Au = 40.;
52// static constexpr double Ad = 5.;
53// };
54
55// constexpr double l_1 = 4e-6;
56// constexpr double l_0 = 3e-6;
57// constexpr double d_m = l_0 / 5.;
58// constexpr double minimal_length = d_m * 1.4;
59// constexpr double factor = 1000. * 3.14 * d_m * d_m / 4.;
60// static_assert(l_0 < l_1, "Length");
61
62// consteval double f_num_max()
63// {
64// return l_0 * std::numbers::ln2 / 3600.; // NOLINT
65// }
66
67// consteval double f_phi_pts_max(double nu_m)
68// {
69// return nu_m * Yields::x_s * factor;
70// }
71
72// constexpr double nu_max = f_num_max(); // m/s
73
74// constexpr double phi_pts_max = f_phi_pts_max(nu_max);
75// constexpr double phi_o2_max = 15.6 / 3600; // mol0/gx/s
76// constexpr double phi_a_max = phi_pts_max / 3.; // mola/kgx/s
77// constexpr double k_pts = 1e-3;
78// constexpr double kppermease = 1e-2;
79// constexpr double phi_permease_specific = phi_pts_max / 40.;
80
81// constexpr double psi_o_meta = 20e-3 / 3600 * 32e-3; // 20mmmol O2 /h;
82// constexpr double tau_metabolism = 3600;
83
84// constexpr double NPermease_max = 200;
85// constexpr double NPermease_init = 1.;
86
87// KOKKOS_INLINE_FUNCTION double phi_pts(double a_pts, double S)
88// {
89// return a_pts * MONOD_RATIO(phi_pts_max, S, k_pts);
90// }
91
92// KOKKOS_INLINE_FUNCTION double phi_permease(double n_permease, double a_permease, double S)
93// {
94// return a_permease * MONOD_RATIO(n_permease * phi_permease_specific, S, kppermease);
95// }
96// // static_assert(NPermease_max * phi_permease_specific == 5. * phi_pts_max, "pts/perm");
97
98// } // namespace implEcoli
99
100// namespace Models
101// {
102
103// struct Ecoli
104// {
105
106// using PhiUptakes = struct Contribs
107// {
108// double glucose;
109// double acetate;
110// double oxygen;
111// };
112
113// struct Rates
114// {
115// double glucose;
116// double acetate;
117// double oxygen;
118// double carbon_dioxide;
119// double nu;
120// };
121
122// static constexpr std::size_t n_meta = 5;
123
124// enum class Indices : std::size_t
125// {
126// NU = 4,
127// GLUCOSE = 0,
128// O2 = 1,
129// Ac = 2,
130// CO2 = 3
131// };
132
133// double length;
134// double nu;
135// double a_pts;
136// double a_permease;
137// double n_permease;
138// Rates rates;
139// PhiUptakes phi_uptakes;
140
141// KOKKOS_FUNCTION void init(MC::ParticleDataHolder& p, MC::KPRNG _rng)
142// {
143
144
145// using namespace implEcoli;
146// constexpr double local_l = minimal_length;
147// auto generator = _rng.random_pool.get_state();
148
149// this->length =
150// Kokkos::max(local_l, Kokkos::max(generator.normal(l_0 / 1.5, l_0 / 1.5 / 5.), 0.));
151// this->a_permease = Kokkos::max(generator.normal(1e-3, 1e-4), 0.);
152// this->a_pts = Kokkos::min(1., Kokkos::max(generator.normal(0.8, 0.1), 0.));
153// this->n_permease =
154// Kokkos::max(generator.normal(NPermease_init / 2., NPermease_init / 5.), 0.);
155
156// this->nu =
157// nu_max; // Kokkos::max(generator.normal(nu_max / 2., nu_max / 2. / 5.), 0.) / length;
158// _rng.random_pool.free_state(generator);
159// }
160
161// KOKKOS_FUNCTION void metabolism()
162// {
163// using namespace ::implEcoli;
164// // yield n for mode i, yields in mol/mol
165// // E: ATP/G:glucose/O:Oxygen/A:Acetate
166// constexpr double y1_b = (Yields::Y_EG + Yields::Yo_EG) / Yields::Yo_EG; // None
167// constexpr double y2_b =
168// (Yields::Y_EG + Yields::Yo_EG) /
169// (Yields::Y_EG * Yields::Y_OG); // G/O //To modify divide by YO_EG not Y_Eg
170// constexpr double y1_c = (Yields::Y_EG + Yields::Yf_EG) / Yields::Yf_EG; // None
171// constexpr double y1_e = (Yields::Y_EA + Yields::Yo_EA) / Yields::Yo_EA; // None
172// constexpr double y2_e =
173// (Yields::Y_EA + Yields::Yo_EA) / (Yields::Yo_EA * Yields::Y_OA); // A/O
174// constexpr double yield_mol_S_O =
175// 1.; // Number of mol of S from mole of O for mode D conversion
176
177// // Yield for specie for specifc mode: id oxygen mode b => y_o2_b
178// constexpr double y_o2_b = (Yields::Y_EG * Yields::Y_OG) / (Yields::Y_EG + Yields::Yo_EG);
179// constexpr double y_o2_e = (Yields::Y_EA * Yields::Y_OA) / (Yields::Y_EA + Yields::Yo_EA);
180// constexpr double y_ac_c = (Yields::Y_AG * Yields::Y_EG) / (Yields::Y_EG + Yields::Yf_EG);
181// constexpr double y_x_b =
182// Yields::Y_XG * Yields::Yo_EG / (Yields::Y_EG + Yields::Yo_EG); // Y_xg /y1_b
183// constexpr double y_x_c = Yields::Y_XG * Yields::Yf_EG / (Yields::Y_EG + Yields::Yf_EG);
184// constexpr double y_x_e = Yields::Y_XA * Yields::Yo_EA / (Yields::Y_EA + Yields::Yo_EA);
185
186// constexpr double y_phi_o2_residual =
187// (Yields::Y_EG * Yields::Y_OG) / (Yields::Y_EG + Yields::Yo_EG); // y2_bthe same
188
189// // Incoming for uptake mecanism
190// const auto [phi_s_in, phi_a_in, phi_o2_in] = phi_uptakes; // kg/s
191// const double current_mass = mass();
192
193// // Incomin in molee y2_b = (Yields::Y_EG + Yields::Yo_EG) / (Yields::Y_EG * Yields::Y_OG); //
194// // G/O
195// const double phi_s_in_mol = phi_s_in / (current_mass * MolarMass::glucose); // mol/s
196// const double phi_a_in_mol = phi_a_in / (current_mass * MolarMass::acetate);
197// const double phi_o2_in_mol = phi_o2_in;
198
199// // Maximum growth on oxidative (best yield)
200// const double r1_max = nu / MolarMass::X / Yields::x_s / MolarMass::glucose; // molS/s
201// // Oxydative growth
202
203// const double phi_mode_b =
204// min_var(y1_b * r1_max, phi_s_in_mol, y2_b * phi_o2_in_mol); // molS/s
205
206// double phi_s_residual = phi_s_in_mol - phi_mode_b; // molS/s
207
208// const double phi_o2_residual = phi_o2_in_mol - (y_phi_o2_residual * phi_mode_b); // molO2/s
209
210// const double nu_residual =
211// ((Yields::Y_EG + Yields::Yo_EG) / Yields::Yo_EG * r1_max) - phi_mode_b; // molS/s
212
213// const double phi_mode_c = min_var(y1_c * nu_residual, phi_s_residual); // molS/s
214
215// phi_s_residual = phi_s_residual - phi_mode_c; // molS/s
216
217// const double phi_mode_d = min_var(phi_s_residual, yield_mol_S_O * phi_o2_residual); // molS/s
218
219// const double phi_mode_e = min_var(y1_e * nu_residual, phi_a_in_mol, y2_e * phi_o2_residual);
220
221// rates.glucose = -phi_s_in;
222// rates.oxygen = -current_mass * MolarMass::dioxygen *
223// (y_o2_b * phi_mode_b + y_o2_e * phi_mode_e + phi_mode_d);
224
225// rates.acetate = current_mass * MolarMass::acetate *
226// (y_ac_c * phi_mode_c + Yields::Y_AG * phi_mode_d - phi_mode_e);
227
228// rates.carbon_dioxide = -current_mass * MolarMass::co2 * (rates.oxygen / MolarMass::dioxygen);
229
230// rates.nu = MolarMass::X * (y_x_b * phi_mode_b + y_x_c * phi_mode_c + y_x_e * phi_mode_e);
231// }
232
233// KOKKOS_FUNCTION double uptake(const LocalConcentrationView& concentration)
234// {
235// using namespace implEcoli;
236// const double s = Kokkos::max(0., concentration(_INDICES(GLUCOSE)));
237// const double phi_s_pts = phi_pts(a_pts, s);
238// const double gamma_PTS_S = phi_s_pts / phi_pts_max;
239// // const double micro_mixing = 0.3;
240
241// phi_uptakes.glucose = phi_s_pts + phi_permease(n_permease, a_permease, s);
242// phi_uptakes.acetate = phi_a_max * concentration(_INDICES(Ac)) / 1;
243// // 1 / micro_mixing * concentration(_INDICES(Ac)) / 1000.;
244
245// phi_uptakes.oxygen = phi_o2_max; //* concentration(_INDICES(O2)) / 9e-3;
246// // 1 / micro_mixing * concentration(_INDICES(O2)) / 1000.;
247// return gamma_PTS_S;
248// }
249
250// KOKKOS_FUNCTION void update(double d_t,
251// MC::ParticleDataHolder& p,
252// const LocalConcentrationView& concentration,
253// MC::KPRNG _rng)
254// {
255// using namespace implEcoli;
256// const double s = Kokkos::max(0., concentration(0));
257// const double gamma_PTS_S = uptake(concentration);
258// const double nu_p = phi_uptakes.glucose / mass() / (Yields::nu_s_x);
259
260// metabolism();
261// this->length += d_t * length * rates.nu;
262// this->nu += d_t * (1.0 / tau_metabolism) * (nu_p - this->nu);
263// this->a_pts += d_t * 1.0 / Tau::pts * (MONOD_RATIO(1., s, k_pts) - this->a_pts);
264// this->a_permease +=
265// d_t * (((1.0 / Tau::Au) * gamma_PTS_S + (1.0 / Tau::Ad) * (1.0 - gamma_PTS_S)) *
266// (1.0 - gamma_PTS_S - a_permease));
267
268// this->n_permease += d_t *
269// (MONOD_RATIO(1. / Tau::new_permease, k_pts, s) +
270// MONOD_RATIO(1. / Tau::tau_rm_perm, s, k_pts)) *
271// (MONOD_RATIO(NPermease_max, k_pts, s) - n_permease);
272
273// Models::update_division_status(
274// p.status, d_t, GammaDivision::threshold_linear(length, l_0, l_1), _rng.random_pool);
275// }
276
277// KOKKOS_FUNCTION Ecoli division(MC::ParticleDataHolder& p, MC::KPRNG _rng)
278// {
279// using namespace implEcoli;
280// const double original_length = this->length;
281// const double original_n_permease = this->n_permease;
282// this->length = original_length / 2.;
283// this->n_permease = original_n_permease / 2;
284
285// auto child = *this;
286// // const bool mask = a_pts > a_permease;
287// // const double max_perm = mask ? a_pts : 1;
288// // const double max_pts = mask ? 1 : a_permease;
289
290// {
291// // auto generator = _rng.random_pool.get_state();
292// // child.a_pts =
293// // Kokkos::min(max_pts, Kokkos::max(generator.normal(this->a_pts, this->a_pts / 2.),
294// // 0.));
295
296// // child.a_permease = Kokkos::min(
297// // max_perm, Kokkos::max(generator.normal(this->a_permease, this->a_permease / 2.),
298// // 0.));
299
300// auto generator = _rng.random_pool.get_state();
301// child.a_pts =
302// Kokkos::min(1., Kokkos::max(generator.normal(this->a_pts, this->a_pts / 2.), 0.));
303
304// child.a_permease = Kokkos::min(
305// 1., Kokkos::max(generator.normal(this->a_permease, this->a_permease / 2.), 0.));
306
307// child.nu = Kokkos::max(generator.normal(this->nu, this->nu / 3.), 0.);
308// _rng.random_pool.free_state(generator);
309// }
310
311// return child;
312// }
313
314// KOKKOS_FUNCTION void contribution(MC::ParticleDataHolder& p,
315// const ContributionView& contribution)
316// {
317// using namespace implEcoli;
318// auto access_contribs = contribution.access();
319// access_contribs(_INDICES(GLUCOSE), p.current_container) += rates.glucose * p.weight;
320// // access_contribs(_INDICES(Ac), p.current_container) += rates.acetate * p.weight;
321// // access_contribs(_INDICES(O2), p.current_container) += rates.oxygen * p.weight;
322// // access_contribs(_INDICES(CO2), p.current_container) += rates.carbon_dioxide * p.weight;
323// }
324
325// [[nodiscard]] KOKKOS_FUNCTION double mass() const noexcept
326// {
327// using namespace implEcoli;
328// return implEcoli::factor * length;
329// }
330
331// template <class Archive> void serialize(Archive& ar)
332// {
333// ar(length, nu, a_pts, a_permease);
334// }
335
336// static std::vector<std::string> names()
337// {
338// return {"mass", "length", "nu_eff", "nu", "a_permease", "a_pts"};
339// }
340
341// KOKKOS_INLINE_FUNCTION static consteval std::size_t get_number()
342// {
343// return 6;
344// }
345
346// KOKKOS_INLINE_FUNCTION void fill_properties(SubViewtype full) const
347// {
348// full(0) = mass();
349// full(1) = this->length;
350// full(2) = this->rates.nu;
351// full(3) = this->nu;
352// full(4) = this->a_permease;
353// full(5) = this->a_pts;
354// }
355// };
356
357// } // namespace Models
358
359// #endif