TkN 2.5
Toolkit for Nuclei
Loading...
Searching...
No Matches
tkmanager.cpp
1/********************************************************************************
2 * Copyright (c) : Université de Lyon 1, CNRS/IN2P3, UMR5822, *
3 * IP2I, F-69622 Villeurbanne Cedex, France *
4 * Normandie Université, ENSICAEN, UNICAEN, CNRS/IN2P3, *
5 * LPC Caen, F-14000 Caen, France *
6 * Contibutor(s) : *
7 * Jérémie Dudouet jeremie.dudouet@cnrs.fr [2020] *
8 * Diego Gruyer diego.gruyer@cnrs.fr [2020] *
9 * *
10 * Licensed under the MIT License <http://opensource.org/licenses/MIT>. *
11 * SPDX-License-Identifier: MIT *
12 ********************************************************************************/
13
14#include <algorithm>
15#include <fstream>
16#include <iterator>
17
18#include "tkmanager.h"
19#include "tklog.h"
20#include "tkdatabase.h"
21#include "json.hpp"
22
23namespace tkn {
31
32}
33
34using namespace tkn;
35using json = nlohmann::json;
36
37tkmanager *tkmanager::g_data_manager = nullptr;
38
40{
41 if (g_data_manager) return g_data_manager;
42
43 std::lock_guard<std::recursive_mutex> lock(get_mutex());
44
45 if (g_data_manager == nullptr) {
46 g_data_manager = new tkmanager();
47 }
48
49 return g_data_manager;
50}
51
53{
54 std::lock_guard<std::recursive_mutex> lock(get_mutex());
55
56 preload_nuclei();
57
58 g_data_manager = this;
59}
60
62{
63 g_data_manager = nullptr;
64}
65
66shared_ptr<tklevel_scheme> tkmanager::get_level_scheme(const tkn::tkstring &_nuc, int _zz, int _aa)
67{
68 if (fmap_of_level_scheme.count(_nuc)) return fmap_of_level_scheme[_nuc];
69
70 std::lock_guard<std::recursive_mutex> lock(get_mutex());
71
72 auto [it, inserted] = fmap_of_level_scheme.try_emplace(
73 _nuc, make_shared<tklevel_scheme>(_nuc, _zz, _aa));
74 return it->second;
75}
76
77void tkmanager::preload_nuclei()
78{
79 // try with isotope.*, element.*
80 gdatabase->begin("isotope.*, element.*", "isotope INNER JOIN element on isotope.element_id=element.element_id");
81
82 while (gdatabase->next()) {
83 tkdb_table &element = (*gdatabase)["ELEMENT"];
84 tkdb_table &iso_table = (*gdatabase)["ISOTOPE"];
85
86 shared_ptr<tknucleus> anucleus = make_shared<tknucleus>();
87
88 tkstring name = element["symbol"].get_value();
89 anucleus->felement_symbol = name;
90 anucleus->felement_name = element["element_name"].get_value();
91
92 int zz = element["charge"].get_value().atoi();
93 int aa = iso_table["mass"].get_value().atoi();
94
95 gdebug << aa << name << " loaded" << do_endl;
97 name.prepend(iso_table["mass"].get_value());
98
99 anucleus->set_name(name.data());
100 anucleus->fA = aa;
101 anucleus->fZ = zz;
102 anucleus->fN = aa - zz;
103 anucleus->fis_known = true;
104
105 // load element properties
106 for (auto &col : element.get_columns()) {
107 tkstring colname = col.first;
108 if (colname == "element_id") continue;
109 if (colname.ends_with("_unit")) continue;
110
111 tkstring colname_unit = colname + "_unit";
112 tkstring unit("");
113 tkstring value = col.second.get_value();
114 if (element.get_columns().count(colname_unit)) {
115 unit = element.get_columns().at(colname_unit).get_value();
116 }
117 if (colname == "atomic_mass" ||
118 colname == "atomic_radius_van_der_Waals" ||
119 colname == "boiling_point" ||
120 colname == "density" ||
121 colname == "ionization_energy" ||
122 colname == "melting_point") {
123 shared_ptr<tkmeasure> data = make_shared<tkmeasure>(value.atof(), unit);
124 data->set_info(tkproperty::kKnown);
125 data->set_type(colname);
126 anucleus->add_property(colname, data);
127 } else if (colname.begins_with("XRay")) {
128 unit = "keV";
129 shared_ptr<tkmeasure> data = make_shared<tkmeasure>(value.atof(), unit);
130 data->set_info(tkproperty::kKnown);
131 data->set_type(colname);
132 if (value.atof() > 0) anucleus->add_property(colname, data);
133 } else {
134 anucleus->add_property_str(colname, value, unit);
135 }
136 }
137
138 // load isotope properties
139 vector<tkstring> fNames = {
140 "lifetime", // From ENSDF
141 "abundance", "quadrupoleDeformation", "FY235U", "FY238U", "FY239Pu", "FY241Pu", "FY252Cf", "cFY235U", "cFY238U", "cFY239Pu", "cFY241Pu", "cFY252Cf", // From NUDAT
142 "mass_excess", "radius", "magnetic_dipole", "electric_quadrupole" // From IAEA-NDS API
143 };
144
145 for (auto &property_name : fNames) {
147 iso_table.read_measure(data_struct, property_name);
148 if (data_struct.filled) {
149 shared_ptr<tkmeasure> data = make_shared<tkmeasure>(data_struct.value, data_struct.unit, data_struct.err);
150 if (data_struct.info.contains("ERR=SY"))
151 data->set_info(tkproperty::kSystematic);
152 else
153 data->set_info(tkproperty::kKnown);
154 data->set_type(property_name);
155
156 if (property_name == "lifetime") {
157 if (!data_struct.info.is_empty()) data->set_info_tag(data_struct.info);
158 if (data->get_info_tag().contains("STABLE")) {
159 anucleus->fis_stable = true;
160 data->set_error(0);
161 anucleus->add_property(property_name, data, "STABLE", "");
162 } else
163 anucleus->add_property(property_name, data, tkstring::form("%g", data->get_value()));
164 } else {
165 anucleus->add_property(property_name, data);
166 }
167 }
168 }
169
170 anucleus->add_property_str("isotope_year_discovered", iso_table["isotope_year_discovered"].get_value(), "");
171
172 tkstring decay_modes = iso_table["decay_modes"].get_value();
173 anucleus->add_property_str("decay_modes", decay_modes, "");
174
175 tkstring spin_parity_str = iso_table["spin_parity"].get_value();
176 double spin = iso_table["spin"].get_value().atof();
177 int parity = iso_table["parity"].get_value().atoi();
178
179 anucleus->fspin_parity.set_spin(spin);
180 anucleus->fspin_parity.set_parity(parity);
181 anucleus->fspin_parity.set_from_str(spin_parity_str);
182
183 anucleus->add_property_str("spin_parity", spin_parity_str, "");
184
185 fmap_of_nuclei[name] = anucleus;
186 fmap_of_nuclei_per_z[anucleus->fZ].push_back(anucleus);
187 fmap_of_nuclei_per_a[anucleus->fA].push_back(anucleus);
188 fmap_of_nuclei_per_n[anucleus->fN].push_back(anucleus);
189 fmap_of_nuclei_per_z_and_a[anucleus->fZ][anucleus->fA] = anucleus;
190 fvector_of_nuclei.push_back(anucleus);
191
192 if (!fmap_of_symbols.count(anucleus->get_z()))
193 fmap_of_symbols[anucleus->get_z()] = anucleus->get_element_symbol();
194 }
195
196 // separation energy calculation
197 if (!get_nucleus(0, 1) || !get_nucleus(1, 1) || !get_nucleus(2, 4)) return;
198 auto neutron_ME = fmap_of_nuclei_per_z_and_a.at(0).at(1)->get("mass_excess");
199 auto proton_ME = fmap_of_nuclei_per_z_and_a.at(1).at(1)->get("mass_excess");
200 auto alpha_ME = fmap_of_nuclei_per_z_and_a.at(2).at(4)->get("mass_excess");
201 tkmeasure electron_mass(0.51099895000, "MeV", 0.00000000015);
202 for (auto &nuc : fmap_of_nuclei) {
203 auto ME = nuc.second->get("mass_excess");
204 if (!ME) continue;
205 // Sn calculation: Sn(A,Z) = − ME(A,Z) + ME(A−1,Z) + ME(n)
206 auto daughter = get_nucleus(nuc.second->get_z(), nuc.second->get_a() - 1);
207 if (daughter && daughter->get("mass_excess")) {
208 shared_ptr<tkmeasure> Sn = make_shared<tkmeasure>(-*ME + *daughter->get("mass_excess") + *neutron_ME);
209 Sn->set_type("neutronSeparationEnergy");
210 nuc.second->add_property("neutronSeparationEnergy", Sn);
211 }
212 // S2n calculation: S2n(A,Z) = − ME(A,Z) + ME(A−2,Z) + 2*ME(n)
213 daughter = get_nucleus(nuc.second->get_z(), nuc.second->get_a() - 2);
214 if (daughter && daughter->get("mass_excess")) {
215 shared_ptr<tkmeasure> S2n = make_shared<tkmeasure>(-*ME + *daughter->get("mass_excess") + 2. * (*neutron_ME));
216 S2n->set_type("twoNeutronSeparationEnergy");
217 nuc.second->add_property("twoNeutronSeparationEnergy", S2n);
218 }
219 // Sp calculation: Sp(A,Z) = − ME(A,Z) + ME(A−1,Z-1) + ME(p)
220 daughter = get_nucleus(nuc.second->get_z() - 1, nuc.second->get_a() - 1);
221 if (daughter && daughter->get("mass_excess")) {
222 shared_ptr<tkmeasure> Sp = make_shared<tkmeasure>(-*ME + *daughter->get("mass_excess") + *proton_ME);
223 Sp->set_type("protonSeparationEnergy");
224 nuc.second->add_property("protonSeparationEnergy", Sp);
225 }
226 // S2p calculation: S2p(A,Z) = − ME(A,Z) + ME(A−2,Z-2) + 2*ME(p)
227 daughter = get_nucleus(nuc.second->get_z() - 2, nuc.second->get_a() - 2);
228 if (daughter && daughter->get("mass_excess")) {
229 shared_ptr<tkmeasure> S2p = make_shared<tkmeasure>(-*ME + *daughter->get("mass_excess") + 2. * (*proton_ME));
230 S2p->set_type("twoProtonSeparationEnergy");
231 nuc.second->add_property("twoProtonSeparationEnergy", S2p);
232 }
233
234 // Qalpha
235 daughter = get_nucleus(nuc.second->get_z() - 2, nuc.second->get_a() - 4);
236 if (daughter && daughter->get("mass_excess")) {
237 shared_ptr<tkmeasure> Q = make_shared<tkmeasure>(*ME - *daughter->get("mass_excess") - *alpha_ME);
238 Q->set_type("Qalpha");
239 nuc.second->add_property("Qalpha", Q);
240 }
241 // QbetaMinus
242 daughter = get_nucleus(nuc.second->get_z() + 1, nuc.second->get_a());
243 if (daughter && daughter->get("mass_excess")) {
244 shared_ptr<tkmeasure> Q = make_shared<tkmeasure>(*ME - *daughter->get("mass_excess"));
245 Q->set_type("QbetaMinus");
246 nuc.second->add_property("QbetaMinus", Q);
247 }
248 // QbetaMinusOneNeutronEmission
249 daughter = get_nucleus(nuc.second->get_z() + 1, nuc.second->get_a() - 1);
250 if (daughter && daughter->get("mass_excess")) {
251 shared_ptr<tkmeasure> Q = make_shared<tkmeasure>(*ME - *daughter->get("mass_excess") - *neutron_ME);
252 Q->set_type("QbetaMinusOneNeutronEmission");
253 nuc.second->add_property("QbetaMinusOneNeutronEmission", Q);
254 }
255 // QbetaMinusTwoNeutronEmission
256 daughter = get_nucleus(nuc.second->get_z() + 1, nuc.second->get_a() - 2);
257 if (daughter && daughter->get("mass_excess")) {
258 shared_ptr<tkmeasure> Q = make_shared<tkmeasure>(*ME - *daughter->get("mass_excess") - 2. * (*neutron_ME));
259 Q->set_type("QbetaMinusTwoNeutronEmission");
260 nuc.second->add_property("QbetaMinusTwoNeutronEmission", Q);
261 }
262 // QdeltaAlpha: 0.5*(Qa(Z+2,N+2)-Qa(Z,N))
263 daughter = get_nucleus(nuc.second->get_z() + 2, nuc.second->get_a() + 4);
264 if (daughter && daughter->get("mass_excess") && nuc.second->get("Qalpha")) {
265 auto Qa = nuc.second->get("Qalpha");
266 auto Qa2 = *daughter->get("mass_excess") - *ME - *alpha_ME;
267 shared_ptr<tkmeasure> Q = make_shared<tkmeasure>(0.5 * (Qa2 - *Qa));
268 Q->set_type("QdeltaAlpha");
269 nuc.second->add_property("QdeltaAlpha", Q);
270 }
271 // QdoubleBetaMinus
272 daughter = get_nucleus(nuc.second->get_z() + 2, nuc.second->get_a());
273 if (daughter && daughter->get("mass_excess")) {
274 shared_ptr<tkmeasure> Q = make_shared<tkmeasure>(*ME - *daughter->get("mass_excess"));
275 Q->set_type("QdoubleBetaMinus");
276 nuc.second->add_property("QdoubleBetaMinus", Q);
277 }
278 // QelectronCapture
279 daughter = get_nucleus(nuc.second->get_z() - 1, nuc.second->get_a());
280 if (daughter && daughter->get("mass_excess")) {
281 shared_ptr<tkmeasure> Q = make_shared<tkmeasure>(*ME - *daughter->get("mass_excess"));
282 Q->set_type("QelectronCapture");
283 nuc.second->add_property("QelectronCapture", Q);
284 }
285 // QdoubleElectronCapture
286 daughter = get_nucleus(nuc.second->get_z() - 2, nuc.second->get_a());
287 if (daughter && daughter->get("mass_excess")) {
288 shared_ptr<tkmeasure> Q = make_shared<tkmeasure>(*ME - *daughter->get("mass_excess"));
289 Q->set_type("QdoubleElectronCapture");
290 nuc.second->add_property("QdoubleElectronCapture", Q);
291 }
292 // QelectronCaptureOneProtonEmission
293 daughter = get_nucleus(nuc.second->get_z() - 2, nuc.second->get_a() - 1);
294 if (daughter && daughter->get("mass_excess")) {
295 shared_ptr<tkmeasure> Q = make_shared<tkmeasure>(*ME - *daughter->get("mass_excess") - *proton_ME);
296 Q->set_type("QelectronCaptureOneProtonEmission");
297 nuc.second->add_property("QelectronCaptureOneProtonEmission", Q);
298 }
299 // QpositronEmission
300 daughter = get_nucleus(nuc.second->get_z() - 1, nuc.second->get_a());
301 if (daughter && daughter->get("mass_excess")) {
302 auto q_positron = make_shared<tkmeasure>(*ME - *daughter->get("mass_excess") - 2. * electron_mass);
303 q_positron->set_type("QpositronEmission");
304 nuc.second->add_property("QpositronEmission", q_positron);
305 }
306
307 // binding energy
308 auto q_binding = make_shared<tkmeasure>(1. / nuc.second->get_a() * (nuc.second->get_z() * (*proton_ME) + nuc.second->get_n() * (*neutron_ME) - *ME));
309 q_binding->set_type("binding_energy_overA");
310 nuc.second->add_property("binding_energy_overA", q_binding);
311
312 // pairingGap PG=0.5 x (-1)N x ( 2BE(Z,N) - BE(Z,N-1) -BE(Z,N+1) )
313 auto nuc_minus = get_nucleus(nuc.second->get_z(), nuc.second->get_a() - 1);
314 auto nuc_plus = get_nucleus(nuc.second->get_z(), nuc.second->get_a() + 1);
315 if (nuc_minus && nuc_plus && nuc_minus->get("mass_excess") && nuc_plus->get("mass_excess")) {
316 auto q_pairing = make_shared<tkmeasure>(0.5 * pow(-1, nuc.second->get_n()) * (-2 * (*ME) + *nuc_minus->get("mass_excess") + *nuc_plus->get("mass_excess")));
317 q_pairing->set_type("pairingGap");
318 nuc.second->add_property("pairingGap", q_pairing);
319 }
320 }
321}
322
323void tkmanager::preload_level_schemes(bool _verbose)
324{
325 size_t nnuc = fvector_of_nuclei.size(), inuc = 0;
326 for (const auto &nuc : fvector_of_nuclei) {
327 if (_verbose) glog.progress_bar(nnuc, inuc, "... pre-loading");
328 get_level_scheme(nuc->get_symbol(), nuc->get_z(), nuc->get_a());
329 inuc++;
330 }
331}
332
348vector<shared_ptr<tknucleus>> tkmanager::get_nuclei(const std::function<bool(shared_ptr<tknucleus>)> &_selection)
349{
350 vector<shared_ptr<tknucleus>> res;
351 std::copy_if(fvector_of_nuclei.begin(), fvector_of_nuclei.end(), std::back_inserter(res),
352 [&_selection](const auto &nuc) { return _selection(nuc); });
353 return res;
354}
355
356bool tkmanager::known_element(tkstring _nuc, int &_z)
357{
358 tkstring symbol = _nuc.extract_alpha();
359 for (auto &nuc_test : fmap_of_nuclei) {
360 if (nuc_test.first.copy().extract_alpha() == symbol) {
361 _z = nuc_test.second->get_z();
362 return true;
363 }
364 }
365 return false;
366}
369{
370 std::lock_guard<std::recursive_mutex> lock(get_mutex());
371 fmax_level_id++;
372 return fmax_level_id;
373}
374
376{
377 std::lock_guard<std::recursive_mutex> lock(get_mutex());
378 fmax_decay_id++;
379 return fmax_decay_id;
380}
381
392 * - `S2n`, `S2n_sigma`
393 * - `S1p`, `S1p_sigma`
394 * - `S2p`, `S2p_sigma`
395 *
396 * @param json_path Path to the JSON file (default: "%s/databases/driplines.json").
397 *
398 * @note After loading, all points are sorted by (Z,N) for deterministic order.
399 *
400 * @note Data extracted from the supplementary material of:
401 * L. Neufcourt, Y. Cao, S. A. Giuliani, W. Nazarewicz, E. Olsen, O. B. Tarasov,
402 * "Quantified limits of the nuclear landscape", Phys. Rev. C 101, 044307 (2020).
403 *
404 * @code
405 * // Example usage:
406 * gmanager->load_drip_lines("path/to/nuclei_quantities.json");
407 * auto s2n = gmanager->get_drip_line("S2n");
408 * @endcode
409 */
410void tkmanager::load_drip_lines(const tkstring &json_path)
411{
412 std::ifstream f(json_path);
413 if (!f.is_open()) {
414 glog << error << "tkmanager::load_drip_lines: cannot open " << json_path << do_endl;
415 return;
416 }
417
418 json j;
419 try {
420 f >> j;
421 } catch (const std::exception &e) {
422 glog << error << "tkmanager::load_drip_lines: JSON parse error in "
423 << json_path << " : " << e.what() << do_endl;
424 return;
425 }
426
427 if (!j.is_array()) {
428 glog << error << "tkmanager::load_drip_lines: root is not an array in "
429 << json_path << do_endl;
430 return;
431 }
432
433 fdrip_lines.clear();
434
435 auto push_if_present = [&](const json &o, const char *qname, const char *sname) {
436 if (!o.contains(qname)) return;
437 if (o[qname].is_null()) return;
438
439 tkn_drip_point p;
440 p.Z = o.value("Z", 0);
441 p.N = o.value("N", 0);
442 p.value_mev = o.value(qname, std::numeric_limits<double>::quiet_NaN());
443 // sigma may be absent → keep NaN
444 if (o.contains(sname) && !o[sname].is_null()) {
445 p.sigma_mev = o.value(sname, std::numeric_limits<double>::quiet_NaN());
446 }
447 p.type = qname;
448
449 fdrip_lines[p.type].push_back(std::move(p));
450 };
451
452 try {
453 for (const auto &o : j) {
454 if (!o.is_object()) continue;
455 // Z and N must exist; skip otherwise
456 if (!o.contains("Z") || !o.contains("N")) continue;
457
458 push_if_present(o, "S1n", "S1n_sigma");
459 push_if_present(o, "S2n", "S2n_sigma");
460 push_if_present(o, "S1p", "S1p_sigma");
461 push_if_present(o, "S2p", "S2p_sigma");
462 }
463 } catch (const std::exception &e) {
464 glog << error << "tkmanager::load_drip_lines: error while iterating JSON: "
465 << e.what() << do_endl;
466 fdrip_lines.clear();
467 return;
468 }
469
470 // Sort deterministically by Z, then N
471 for (auto &kv : fdrip_lines) {
472 auto &vec = kv.second;
473 std::sort(vec.begin(), vec.end(), [](const tkn_drip_point &a, const tkn_drip_point &b) {
474 if (a.Z != b.Z) return a.Z < b.Z;
475 return a.N < b.N;
476 });
477 }
478
479 glog << info << "load_drip_lines: loaded " << j.size()
480 << " nuclei objects from " << json_path << do_endl;
481}
482
507std::vector<tkn_drip_point> tkmanager::get_drip_line(const std::string &_type, bool reduce_per_Z)
508{
509 if (fdrip_lines.empty()) {
510 // charge par défaut si pas déjà fait
511 load_drip_lines(tkstring::Form("%s/databases/driplines.json", TKN_SYS));
512 }
513
514 auto it = fdrip_lines.find(_type);
515 if (it == fdrip_lines.end()) {
516 glog << warning << "get_drip_line: unknown type '" << _type << "'" << do_endl;
517 return {};
518 }
519
520 const auto &vec = it->second;
521
522 if (!reduce_per_Z) {
523 return vec;
524 }
525
526 // --- Réduction : garder seulement le point avec min |value| par Z
527 std::unordered_map<int, tkn_drip_point> best_by_Z;
528 for (const auto &p : vec) {
529 auto itZ = best_by_Z.find(p.Z);
530 if (itZ == best_by_Z.end()) {
531 best_by_Z[p.Z] = p;
532 } else {
533 const auto &cur = itZ->second;
534 if (std::isnan(cur.value_mev) ||
535 (!std::isnan(p.value_mev) && std::abs(p.value_mev) < std::abs(cur.value_mev))) {
536 best_by_Z[p.Z] = p;
537 }
538 }
539 }
540
541 std::vector<tkn_drip_point> reduced;
542 reduced.reserve(best_by_Z.size());
543 std::transform(best_by_Z.begin(), best_by_Z.end(), std::back_inserter(reduced),
544 [](const auto &kv) { return kv.second; });
545
546 std::sort(reduced.begin(), reduced.end(), [](const tkn_drip_point &a, const tkn_drip_point &b) {
547 if (a.Z != b.Z) return a.Z < b.Z;
548 return a.N < b.N;
549 });
550
551 return reduced;
552}
553
554#ifdef HAS_ROOT
556ClassImp(tkmanager)
557#endif
Representaiton of a sqlite data table.
Definition tkdb_table.h:29
void read_measure(measure_data_struct &_struct, const tkstring &_col_base_name)
row & get_columns()
Definition tkdb_table.h:116
void clear()
Definition tklog.h:156
Manages the database loading and provides access to the physics properties.
Definition tkmanager.h:51
static tkmanager * the_data_manager()
Definition tkmanager.cpp:83
int get_new_level_id()
define a new unique level id
std::vector< tkn_drip_point > get_drip_line(const std::string &_type, bool reduce_per_Z=true)
Get the drip line for a given type (optionally reduced per Z)
shared_ptr< tknucleus > get_nucleus(const tkstring &_nuc)
return a shared pointer to a nucleus from its name
Definition tkmanager.h:125
const vector< shared_ptr< tknucleus > > & get_nuclei()
return a vector containing all the known nuclei
Definition tkmanager.h:106
int get_new_decay_id()
define a new unique decay id
virtual ~tkmanager()
bool known_element(tkstring _nuc, int &_z)
is the element symbol is known (ex: "C")
void preload_level_schemes(bool _verbose=false)
preload all the level schemes from the database
std::string with usefull tricks from TString (ROOT) and KVString (KaliVeda) and more....
Definition tkstring.h:32
tkstring extract_alpha()
Returns a tkstring composed only of the alphabetic letters of the original tkstring.
Definition tkstring.cpp:408
static const char * form(const char *_format,...)
Definition tkstring.cpp:452
static tkstring Form(const char *_format,...)
Definition tkstring.cpp:366
bool is_empty() const
Definition tkstring.h:141
bool ends_with(const char *_s, ECaseCompare _cmp=kExact) const
Definition tkstring.cpp:262
bool contains(const char *_pat, ECaseCompare _cmp=kExact) const
Definition tkstring.h:175
tkstring & prepend(const tkstring &_st)
Definition tkstring.h:202
bool begins_with(const char *_s, ECaseCompare _cmp=kExact) const
Definition tkstring.h:163
double atof() const
Converts a string to double value.
Definition tkstring.cpp:212
Definition tklog.cpp:16
tklog & info(tklog &log)
Definition tklog.h:313
tklog & error(tklog &log)
Definition tklog.h:344
tklog & do_endl(tklog &log)
Definition tklog.h:212
tklog & warning(tklog &log)
Definition tklog.h:331
data structure used to fill a tkmeasure object from the sqlite database
Definition tkdb_table.h:49
int Z
Proton number.
Definition tkmanager.h:41
double value_mev
Quantity value (MeV)
Definition tkmanager.h:43
std::string type
Quantity type: "S1n", "S2n", "S1p", or "S2p".
Definition tkmanager.h:45
int N
Neutron number.
Definition tkmanager.h:42
double sigma_mev
Quantity uncertainty (MeV)
Definition tkmanager.h:44