15#include "tknuclear_chart.h"
36vector<nucleus> nucleus_list;
38map<int, map<int, pair<int, nucleus>>> nuc_chart_mapping;
42double felapsed_time = 0;
44bool read_emitted_particle_count(
const tkstring &mode,
const tkstring &particle,
int &count)
46 if (mode == particle) {
51 if (!mode.
ends_with(particle))
return false;
52 tkstring number = mode.
substr(0, mode.length() - particle.length());
53 if (!number.
is_digit())
return false;
55 count = number.
atoi();
59bool parse_cluster_emission(
const tkstring &mode,
int &z_offset,
int &n_offset)
61 if (mode.empty() || !std::isdigit(
static_cast<unsigned char>(mode.front())))
return false;
64 if (!mass_str.
is_digit())
return false;
70 if (!gmanager->known_element(symbol, cluster_z))
return false;
72 const int cluster_a = mass_str.
atoi();
73 if (cluster_a <= cluster_z)
return false;
75 z_offset -= cluster_z;
76 n_offset -= cluster_a - cluster_z;
82 if (mode.empty())
return true;
85 if (read_emitted_particle_count(mode,
"N", count)) {
89 if (read_emitted_particle_count(mode,
"P", count)) {
98 if (mode ==
"F" || mode ==
"SF") {
102 if (parse_cluster_emission(mode, step.
z_offset, step.
n_offset))
return true;
109 if (gmanager->known_element(symbol, cluster_z) && cluster_z > 2) {
123 if (mode.empty())
return step;
141 if (apply_particle_emission(mode.
substr(2), step))
return step;
143 if (mode.
begins_with(
"B") && mode.length() > 1 && mode !=
"B+") {
145 legacy_step.
known =
true;
148 if (apply_particle_emission(mode.
substr(1), legacy_step))
return legacy_step;
151 if (mode ==
"B+" || mode ==
"EC" || mode ==
"EC+B+") {
167 if (apply_particle_emission(mode.
substr(2), step))
return step;
171 legacy_step.
known =
true;
174 if (apply_particle_emission(mode.
substr(1), legacy_step))
return legacy_step;
177 if (apply_particle_emission(mode, step)) {
192 if (tknuc_chart)
return;
196 for (
auto &nuc : gmanager->get_nuclei()) {
198 a_nuc.
name = nuc->get_symbol();
199 a_nuc.
z = nuc->get_z();
200 a_nuc.
n = nuc->get_n();
201 if (nuc->is_stable()) {
204 if (!nuc->get_lifetime_measure())
209 tkstring decay = nuc->get_property(
"decay_modes");
211 if (token.size() == 0)
214 decay = token.front();
215 auto decay_tokens = decay.
tokenize(
";");
216 tkstring decay_mode = decay_tokens.size() ? decay_tokens.front() :
"";
217 a_nuc.
decay = decode_decay_mode(decay_mode);
218 if (!a_nuc.
decay.
known && decay.length()) cout <<
"unknown decay: " << decay <<
" " << a_nuc.
name << endl;
220 nucleus_list.push_back(a_nuc);
221 nuc_chart_mapping[a_nuc.
z][a_nuc.
n] = make_pair(0, a_nuc);
226void init(Int_t NEvents = 1e6)
228 if (nucleus_list.empty()) make_db();
231 for (
auto &z : nuc_chart_mapping) {
232 for (
auto &n : z.second) {
236 tknuc_chart->reset();
238 std::default_random_engine generator;
239 uniform_int_distribution<Int_t> dist(0, nucleus_list.size() - 1);
241 for (Int_t inuc = 0; inuc < NEvents; inuc++) {
242 nucleus a_nuc = nucleus_list.at(dist(generator));
243 nuc_chart_mapping[a_nuc.
z][a_nuc.
n].first += 1;
244 tknuc_chart->fill(a_nuc.
z, a_nuc.
n);
247 tknuc_chart->set_title(
"T = 0");
251 gSystem->Unlink(
"animation.gif");
252 tknuc_chart->save_as(
"animation.gif+");
256void update_chart(
int z,
int n,
int N)
258 if (!(nuc_chart_mapping.count(z) && nuc_chart_mapping[z].count(n))) {
261 nuc_chart_mapping[z][n].first += N;
262 tknuc_chart->set_value(z, n, nuc_chart_mapping[z][n].first);
266void process_decay(
double dt,
bool save =
false)
269 if (tknuc_chart ==
nullptr) {
270 cout <<
"process first the init step to generate the T0 distribution" << endl;
275 map<int, map<int, int>> decay_to_process;
276 for (
auto &z : nuc_chart_mapping) {
277 for (
auto &n : z.second) {
278 auto &pair = n.second;
279 if (pair.first == 0)
continue;
280 auto &a_nuc = pair.second;
282 double Ndecay_double = pair.first - pair.first * exp(-TMath::Log(2) * dt / a_nuc.
lifetime_in_sec);
283 int Ndecay = TMath::Nint(Ndecay_double);
285 if (Ndecay_double < 1) {
286 if (gRandom->Uniform() < Ndecay_double) Ndecay = 1;
288 decay_to_process[z.first][n.first] = Ndecay;
291 for (
auto &z : decay_to_process) {
292 for (
auto &n : z.second) {
293 auto &a_nuc = nuc_chart_mapping[z.first][n.first].second;
294 int Ndecay = n.second;
295 update_chart(a_nuc.
z, a_nuc.
n, -Ndecay);
297 cout <<
"oups, a stable nucleus should not pass in this loop..." << endl;
303 for (
int i = 0; i < Ndecay; i++) {
305 int newz1 = TMath::Nint(gRandom->Uniform(fission_z / 4, fission_z / 2));
306 int newn1 = TMath::Nint(gRandom->Uniform(fission_n / 4, fission_n / 2));
307 int emitted_neutrons = TMath::Nint(gRandom->Uniform(2, 7));
308 int newz2 = fission_z - newz1;
309 int newn2 = fission_n - newn1 - emitted_neutrons;
310 if (!(nuc_chart_mapping.count(newz1) && nuc_chart_mapping[newz1].count(newn1)) || !(nuc_chart_mapping.count(newz2) && nuc_chart_mapping[newz2].count(newn2)))
continue;
311 update_chart(newz1, newn1, 1);
312 update_chart(newz2, newn2, 1);
329 if (felapsed_time < 60)
331 else if (felapsed_time < 60 * 60)
333 else if (felapsed_time < 60 * 60 * 24)
335 else if (felapsed_time < 60 * 60 * 24 * 365)
336 title +=
tkstring::form(
"%.1f days", felapsed_time / 60 / 60 / 24);
338 title +=
tkstring::form(
"%.1g years", felapsed_time / 60 / 60 / 24 / 365);
340 tknuc_chart->set_title(title);
341 tknuc_chart->update();
342 tknuc_chart->save_as(
"animation.gif+");
344 gSystem->ProcessEvents();
349void elapse_time_in_seconds(
double _time,
double dt = 0.,
int nsave = 5)
352 if (tknuc_chart ==
nullptr) {
353 cout <<
"process first the init step to generate the T0 distribution" << endl;
357 if (dt == 0.) dt = _time / 1000.;
359 int save = (_time / dt) / nsave;
360 for (
int i = 1; i * dt < _time; i++) {
362 process_decay(dt,
true);
367 process_decay(dt,
true);
370void elapse_time_in_hours(
double time,
double dt = 0.)
374 if (dt != 0.) dt = dt * 3600.;
376 elapse_time_in_seconds(time, dt, nsave);
379void elapse_time_in_days(
double time,
double dt = 0.)
382 time = time * 3600. * 24;
383 if (dt != 0.) dt = dt * 3600. * 24;
385 elapse_time_in_seconds(time, dt, nsave);
388void elapse_time_in_years(
double time,
double dt = 0.)
391 time = time * 3600. * 24 * 365;
392 if (dt != 0.) dt = dt * 3600. * 24 * 365;
394 elapse_time_in_seconds(time, dt, nsave);
398void decay_generator_animation()
401 elapse_time_in_seconds(1);
402 elapse_time_in_seconds(9);
403 elapse_time_in_seconds(20);
404 elapse_time_in_seconds(30);
405 elapse_time_in_seconds(60);
406 elapse_time_in_seconds(60 * 8);
407 elapse_time_in_seconds(60 * 20);
408 elapse_time_in_seconds(60 * 30);
409 elapse_time_in_hours(1);
410 elapse_time_in_hours(8);
411 elapse_time_in_hours(14);
412 elapse_time_in_days(1);
413 elapse_time_in_days(8);
414 elapse_time_in_days(40);
415 elapse_time_in_days(50);
416 elapse_time_in_days(100);
417 elapse_time_in_days(165);
418 elapse_time_in_years(1);
419 elapse_time_in_years(4);
420 elapse_time_in_years(5);
421 elapse_time_in_years(40);
422 elapse_time_in_years(50);
423 elapse_time_in_years(400);
424 elapse_time_in_years(500);
425 elapse_time_in_years(9000);
426 elapse_time_in_years(40000);
427 elapse_time_in_years(50000);
428 elapse_time_in_years(400000);
429 elapse_time_in_years(500000);
430 elapse_time_in_years(4e6);
431 elapse_time_in_years(5e6);
432 elapse_time_in_years(4e7);
433 elapse_time_in_years(5e7);
434 elapse_time_in_years(4e8);
435 elapse_time_in_years(5e8);
436 elapse_time_in_years(4e9);
437 tknuc_chart->save_as(
"animation.gif++");
nuclear chart plot with ROOT
std::string with usefull tricks from TString (ROOT) and KVString (KaliVeda) and more....
tkstring extract_alpha()
Returns a tkstring composed only of the alphabetic letters of the original tkstring.
tkstring copy() const
Returns a copy of this string.
tkstring & to_lower()
Change all letters to lower case.
static const char * form(const char *_format,...)
std::vector< tkstring > tokenize(const tkstring &_delim=" ") const
Create a vector of string separated by at least one delimiter.
tkstring & remove_all(const tkstring &_s1)
tkstring substr(size_type __pos=0, size_type __n=npos) const
Inlines.
int atoi() const
Converts a string to integer value.
bool ends_with(const char *_s, ECaseCompare _cmp=kExact) const
tkstring remove_alpha()
Returns a tkstring composed only of the non alphabetic letters of the original tkstring.
bool begins_with(const char *_s, ECaseCompare _cmp=kExact) const
tkstring & capitalize()
Change first letter of string from lower to upper case.
tkstring & replace_all(const tkstring &_s1, const tkstring &_s2)
bool is_digit() const
Checks if all characters in string are digits (0-9) or whitespaces.
tkstring & to_upper()
Change all letters to upper case.