Introduction
The TkN library gives access to a large amount of nuclear properties as:
These properties are taken from different official sources (see the data sources section) and merged in a sqlite3 home-made database.
In the ENSDF database, used for levels and decay properties, more than one dataset can be accessible for a given nucleus (usually one dataset per reaction). This is taken into account in TkN using the dataset manager
To easily browse the database, a database manager is provided. It allows for example to create list of nuclei on given ranges of neutron or proton numbers, or any other selections.
To manage the different data units, a units manager is also provided to convert the data extracted from the database in the requested units.
Finnally, TkN has been developped in thread safe way to allow a multi-thread access to the TkN database.
Properties
All the following used classes are part of the 'tkn' namespace. If you are using the tkn-root
executable, the namespace is already loaded, but in a c++ macro or project, use the following for an easier access:
Elements and nuclei
To access any nuclear property, a tkn::tknucleus needs to be created. it can be created using its symbol, or its proton and mass number:
A nucleus made of Z protons and N neutrons.
A nucleus can also be create only using it's element name or charge number. In such case, the most stable isotope will be returned, and the most abundant in case of multiple stable nuclei:
tknucleus nuc("U");
tknucleus nuc2(92);
The main properties of a nucleus can be printed with:
tknucleus nuc1("12C");
nuc1.print()
[ INFO ] 12C (Z=6, N=6) properties:
[ INFO ] Ground state configuration: 0+
[ INFO ] Stable nucleus, abundance: 98.93 %
tknucleus nuc2("U");
nuc2.print()
[ INFO ] 238U (Z=92, N=146) properties:
[ INFO ] Ground state configuration: 0+
[ INFO ] Radioactive nucleus:
[ INFO ] lifetime = 4e+09 (6e+06) y
[ INFO ] Decay: [A;100][SF;5.4e-05]
For each element, the following properties
can be available:
- charge
- symbol
- elemen_name
- group block
- standard state
- atomic mass (u)
- electronic configuration
- atomic radius (van der Waals) (pm)
- ionization energy (eV)
- melting point (K)
- boiling point (K)
- density (g/cm³)
- year discovered
- list of X-rays (keV)
Then, for each isotope, the following properties
can be available from the databases (see
(see the data sources section)):
- abundance (%)
- decay mode (returned as a string)
- charge radius (fm)
- electric quadrupole (barn)
- magnetic dipole (μN)
- mass excess (keV)
- lifetime
- spin-parity
- quadrupole deformation ß²
- fission yields:
- thermal neutron-induced fission yields for 235-Uranium
- fast neutron-induced fission yields for 238-Uranium
- thermal neutron-induced fission yields for 239-Plutonium
- thermal neutron-induced fission yields for 241-Plutonium
- spontaneous fission yields for 252-Californium
- cumulative fission yields:
- availaible for each independant fission yield cited above
- year of discovery of the isotope
From the mass excess values, the following properties are calculated in TkN:
- binding energy per nucleon (keV)
- pairing gap (keV)
- Q-values (keV):
- α
- ∆α: 0.5 x ( Qα(Z+2,N+2) - Qα(Z,N) )
- ß⁻
- double ß⁻
- ß⁺
- electron capture
- double electron capture
- ß⁻ delayed neutron emission
- ß⁻ delayed double neutron emission
- electron capture followed by proton emission
- separation energies(keV):
- neutron separation energy
- two neutron separation energy
- proton separation energy
- two proton separation energy
to see the available properties for a given nucleus, use the
tknucleus::list_properties() method:
tknucleus nuc("12C")
nuc.list_properties()
[ INFO ] nucleus properties:
[ INFO ] Qalpha -7366.587870 keV [FLOAT]
[ INFO ] QbetaMinus -17338.068000 keV [FLOAT]
[ INFO ] QbetaMinusOneNeutronEmission -32436.962060 keV [FLOAT]
[ INFO ] QbetaMinusTwoNeutronEmission -54942.663120 keV [FLOAT]
[ INFO ] QdeltaAlpha 102.334915 keV [FLOAT]
[ INFO ] QdoubleBetaMinus -32013.335000 keV [FLOAT]
[ INFO ] QdoubleElectronCapture -25077.761000 keV [FLOAT]
[ INFO ] QelectronCapture -13369.398000 keV [FLOAT]
[ INFO ] QelectronCaptureOneProtonEmission -27466.140064 keV [FLOAT]
[ INFO ] QpositronEmission -14391.395900 keV [FLOAT]
[ INFO ] XRay_Kalpha1 0.277000 keV [FLOAT]
[ INFO ] abundance 98.930000 % [FLOAT]
[ INFO ] atomic_mass 12.011000 u [FLOAT]
[ INFO ] atomic_radius_van_der_Waals 170.000000 pm [FLOAT]
[ INFO ] binding_energy_ldm_fit_overA -210.980700 keV [FLOAT]
[ INFO ] binding_energy_overA 7680.144562 keV [FLOAT]
[ INFO ] boiling_point 4098.000000 K [FLOAT]
[ INFO ] charge 6 [TEXT]
[ INFO ] decay_modes [TEXT]
[ INFO ] density 2.267000 [FLOAT]
[ INFO ] electric_quadrupole 0.060000 barn [FLOAT]
[ INFO ] electronic_configuration [He]2s2 2p2 [TEXT]
[ INFO ] group_block Nonmetal [TEXT]
[ INFO ] ionization_energy 11.260000 eV [FLOAT]
[ INFO ] isotope_year_discovered 1919 [TEXT]
[ INFO ] lifetime STABLE [FLOAT]
[ INFO ] mass_excess 0.000000 keV [FLOAT]
[ INFO ] melting_point 3823.000000 K [FLOAT]
[ INFO ] name Carbon [TEXT]
[ INFO ] neutronSeparationEnergy 18720.715060 keV [FLOAT]
[ INFO ] pairingGap 6887.203165 keV [FLOAT]
[ INFO ] protonSeparationEnergy 15956.679064 keV [FLOAT]
[ INFO ] quadrupoleDeformation 0.576601 [FLOAT]
[ INFO ] radius 2.470200 fm [FLOAT]
[ INFO ] spin_parity 0+ [TEXT]
[ INFO ] state Solid [TEXT]
[ INFO ] symbol C [TEXT]
[ INFO ] twoNeutronSeparationEnergy 31841.309120 keV [FLOAT]
[ INFO ] twoProtonSeparationEnergy 27185.429128 keV [FLOAT]
[ INFO ] year_discovered Ancient [TEXT]
The results can be filtered using a regular expression:
tknucleus nuc("12C")
nuc.list_properties("Q*")
[ INFO ] nucleus properties:
[ INFO ] Qalpha -7366.587870 keV [FLOAT]
[ INFO ] QbetaMinus -17338.068000 keV [FLOAT]
[ INFO ] QbetaMinusOneNeutronEmission -32436.962060 keV [FLOAT]
[ INFO ] QbetaMinusTwoNeutronEmission -54942.663120 keV [FLOAT]
[ INFO ] QdeltaAlpha 102.334915 keV [FLOAT]
[ INFO ] QdoubleBetaMinus -32013.335000 keV [FLOAT]
[ INFO ] QdoubleElectronCapture -25077.761000 keV [FLOAT]
[ INFO ] QelectronCapture -13369.398000 keV [FLOAT]
[ INFO ] QelectronCaptureOneProtonEmission -27466.140064 keV [FLOAT]
[ INFO ] QpositronEmission -14391.395900 keV [FLOAT]
To test if a property is available, use the use the
tknucleus::has_property() method:
- If the requested property is available and is a measured property (with a value and an associated error) get it using: tkproperty_list::get()
if(nuc.has_property("abundance")) {
auto value = nuc.get("abundance");
cout << nuc.get_symbol() << " abundance: " << value->get_value() << " +- " << value->get_error() << " " << value->get_unit() << endl;
}
12C abundance: 98.93 +- 0.08 %
The returned value is a tkn::tkmeasure, see the dedicated section
- If the requested property is available and is refering to a string value (e.g. drounf state spin parity), get it using tknucleus::get_property()
value = nuc.get_property("spin_parity");
cout << nuc.get_symbol() << " GS spin parity: " << value << endl;
For a faster access to the most used properties, few specific methods have been added to tknucleus objects:
The above methods giving access to a measure (ex:
get_lifetime() ), are directly returning the value as a double. Dedicated methods allows to access the
tkn::tkmeasure to access to units, uncertainties... etc (see
Measures and units).For exemple, for the lifetime, the method
get_lifetime_measure() returns the tkmeasure object.
Nuclear levels scheme
For all the nuclei with known data on the ENSDF or XUNDL databases, it is possible to access to a tkn::tklevel_scheme object.
The level scheme is determined for a given dataset see the dataset section.
For one dataset, the level scheme gives access to the nuclear levels and decay information see the level section or the decay section
Nuclear levels
For any nucleus, it is possible to access to its level scheme composed of the known levels and decays. Print the known levels as follows:
nuc.get_level_scheme()->print("level")
[ INFO ] dataset '8B : ADOPTED LEVELS, GAMMAS' contains 5 levels:
[ INFO ] Level energy = 0 keV [no uncertainty] ; Jpi: 2+ ; lifetime = 770 (3 ) ms
[ INFO ] Level energy = 769.5 (2.5 ) keV ; Jpi: 1+ ; lifetime = 35.6 (0.6 ) keV
[ INFO ] Level energy = 2320 (20 ) keV ; Jpi: 3+ ; lifetime = 350 (30 ) keV
[ INFO ] Level energy = 3500 (500 ) keV ; Jpi: 2- ; lifetime = 8 (4 ) MeV
[ INFO ] Level energy = 10619 (9 ) keV ; Jpi: 0+ ; lifetime < 60 keV [limit value]
The level list can be retrieved using:
auto levels = nuc.get_level_scheme()->get_levels();
or using a lambda function to filter the levels (e.g. all the positive parity states in):
auto levels = nuc.get_level_scheme()->get_levels( [](auto lvl) {
return lvl->get_spin_parity()->get_parity().is_parity(tkparity::kParityPlus);
});
for(auto &lev: levels) lev->print()
[ INFO ] Level energy = 0 keV [no uncertainty] ; Jpi: 2+ ; lifetime = 770 (3 ) ms
[ INFO ] Level energy = 769.5 (2.5 ) keV ; Jpi: 1+ ; lifetime = 35.6 (0.6 ) keV
[ INFO ] Level energy = 2320 (20 ) keV ; Jpi: 3+ ; lifetime = 350 (30 ) keV
[ INFO ] Level energy = 10619 (9 ) keV ; Jpi: 0+ ; lifetime < 60 keV [limit value]
A level can also been accessed directly by its name (e.g. the first 3⁺ state):
nuc.get_level_scheme()->get_level("3+1")->print();
[ INFO ] Level energy = 2320 (20 ) keV ; Jpi: 3+ ; lifetime = 350 (30 ) keV
, or using its energy (the closest level in energy will be returned):
nuc.get_level_scheme()->get_level(3000.)->print();
[ INFO ] Level energy = 3500 (500 ) keV ; Jpi: 2- ; lifetime = 8 (4 ) MeV
The get_level(...) methods return a
tkn::tklevel object, and the get_levels(...) methods return a vector of
tkn::tklevel objects.
In some cases, a level or a full band is known only relatively to an offset X because the bandhead energy is not known. The level energy in this case is its energy related to the bandhead offset (ex: X+100). The default method
get_energy() in this case will return a "nan" value to avoid confusions. To test is a level is known only with an offset, use the method
is_energy_offset(). To obtain its relative energy, use the
get_energy() with the _with_offset option.
Here are the main method that can be applied on a
tklevel:
The above methods giving access to a measure (ex:
get_lifetime() ), are directly returning the value as a double. Dedicated methods allows to access the
tkn::tkmeasure to access to units, uncertainties... etc (see
Measures and units).For exemple, for the lifetime, the method
get_lifetime_measure() returns the tkmeasure object.
Nuclear decays
As for the levels, from the level scheme, it is possible to access to all the known decays of a nucleus. In the current version, only gamma decays are implemented. Particle decays are planned to be added in next TkN version.Print the known decays as follows:
nuc.get_level_scheme()->print("decay")
[ INFO ] dataset '8B : ADOPTED LEVELS, GAMMAS' contains 2 decays:
[ INFO ] gamma decay energy = 769.5 (2.4 ) keV, mult M1
[ INFO ] gamma decay energy = 2320 (30 ) keV, mult M1
It is also possible to print at the same time the levels and its associated decays:
nuc.get_level_scheme()->print("level,decay")
[ INFO ] dataset '8B : ADOPTED LEVELS, GAMMAS' contains 5 levels
[ INFO ] dataset '8B : ADOPTED LEVELS, GAMMAS' contains 2 decays
[ INFO ] Level energy = 0 keV [no uncertainty] ; Jpi: 2+ ; lifetime = 770 (3 ) ms
[ INFO ] Level energy = 769.5 (2.5 ) keV ; Jpi: 1+ ; lifetime = 35.6 (0.6 ) keV
-> gamma decay energy = 769.5 (2.4 ) keV, mult M1
[ INFO ] Level energy = 2320 (20 ) keV ; Jpi: 3+ ; lifetime = 350 (30 ) keV
-> gamma decay energy = 2320 (30 ) keV, mult M1
[ INFO ] Level energy = 3500 (500 ) keV ; Jpi: 2- ; lifetime = 8 (4 ) MeV
[ INFO ] Level energy = 10619 (9 ) keV ; Jpi: 0+ ; lifetime < 60 keV [limit value]
As for the levels, The decay list can be retrieved using:
auto levels = nuc.get_level_scheme()->get_decays();
Is is also possible to restrict the decay list to a type of decay:
auto levels = nuc.get_level_scheme()->get_decays<
tkgammadecay>();
Stores information on a gamma-ray decay.
As for the moment only tkn::tkgammadecay are included, it is advised to only use this second option to easily benefit from the tkgammadecay methods on the decay list.The same can be done using a lambda function to filter the decays (e.g. only decays coming from a level lower than 1 MeV):
auto decays = nuc.get_level_scheme()->get_decays<
tkgammadecay>( [](
auto dec) {
return dec->get_level_from()->get_energy_measure()->get_value(tkunit_manager::MeV) < 1.;
});
for(
auto &dec: decays) dec->
print()
void print(const tkstring &_option="") const
print the decay properties
[ INFO ] gamma decay energy = 769.5 (2.4 ) keV, mult M1
A decay can also been accessed directly by its name (e.g. the decay from the first 3⁺ to the first 2⁺ state):
nuc.get_level_scheme()->get_decay<
tkgammadecay>(
"3+1->2+1")->print();
[ INFO ] gamma decay energy = 2320 (30 ) keV, mult M1
, or using its energy (the closest level in energy will be returned):
nuc.get_level_scheme()->get_decay<
tkgammadecay>(700.)->print();
[ INFO ] gamma decay energy = 769.5 (2.4 ) keV, mult M1
The get_decay(...) methods return a
tkn::tkdecay object, and the get_levels(...) methods return a vector of
tkn::tkdecay objects. As explained, if we want to play only with gamma decays, the template access get_decay<tkgammadecay>(...) methods return a
tkn::tkgammadecay object, and the get_levels<tkgammadecay>(...) methods return a vector of
tkn::tkgammadecay the
tkn::tkgammadecay class inherits from the
tkn::tkdecay, so all methods applicable for a tkdecay are also valid for a tkgammadecay.Here are the main method that can be applied on a
tkdecay:
Here are the main method that can be applied on a
tkgammadecay:
The above methods giving access to a measure (ex:
get_conv_coeff() ), are directly returning the value as a double. Dedicated methods allows to access the
tkn::tkmeasure to access to units, uncertainties... etc (see
Measures and units).For exemple, for the lifetime, the method
get_conv_coeff_measure() returns the tkmeasure object.
Data manager
Datasets
The database used for the levels and decays is extracted from the ENSDF database.For a given nucleus, the database is composed of different validated datasets, corresponding to different ways to produce the nucleus. A global dataset named : "ADOPTED LEVELS, GAMMAS" is used to merge all the different datasets in one. This is the default dataset of any nucleus in TkN.TkN allows to load the different datasets. For a given nucleus, the datasets and their associated ID can be listed using:
nuc.get_level_scheme()->print("dataset")
[ INFO ] Available datasets are :
[ INFO ] 132Sn : ADOPTED LEVELS, GAMMAS (12581)
[ INFO ] 133IN B-N DECAY (165 MS) (12582)
[ INFO ] 248CM SF DECAY (12583)
[ INFO ] COULOMB EXCITATION (12584)
[ INFO ] 132IN B- DECAY (0.200 S) (12585)
[ INFO ] 132SN IT DECAY (2.080 US) (12586)
[ INFO ] U(N,F):IS,RADIUS:XUNDL-3 (12587)
[ INFO ] COULOMB EXCITATION:XUNDL-4 (12588)
[ INFO ] 133IN B-N DECAY:162 MS:XUNDL-5 (12589)
[ INFO ] 133IN B-N DECAY:167 MS:XUNDL-6 (12590)
[ COMMENT ] Current dataset is '132Sn : ADOPTED LEVELS, GAMMAS' (12581)
As shown in the above example, TkN also include the non evaluated datasets (
XUNDL). These datasets are coming from recently published data, but that have still not been evaluated by the National Nuclear Data Center.The dataset can be selected as follows (using the Coulomb Excitation dataset ids):
nuc.get_level_scheme()->select_dataset(12584);
nuc.get_level_scheme()->print("level");
nuc.get_level_scheme()->select_dataset(12588);
nuc.get_level_scheme()->print("level");
[ INFO ] dataset 'COULOMB EXCITATION' contains 2 levels:
[ INFO ] Level energy = 0 keV [no uncertainty] ; Jpi: 0+
[ INFO ] Level energy = 4040 keV [no uncertainty] ; Jpi: 2+
[ INFO ] dataset 'COULOMB EXCITATION:XUNDL-4' contains 4 levels:
[ INFO ] Level energy = 0 keV [no uncertainty] ; Jpi: 0+
[ INFO ] Level energy = 4041.2 keV [no uncertainty] ; Jpi: 2+ ; lifetime = 2.95 (-0.47 ; +0.70 ) fs
[ INFO ] Level energy = 4351.9 keV [no uncertainty] ; Jpi: 3- ; lifetime = 2.4 (-0.6 ; +1.3 ) ps
[ INFO ] Level energy = 4416 keV [no uncertainty] ; Jpi: 4+ ; lifetime = 3.95 (0.13 ) ns uncertain level tag: S
Database
The TkN data manager is key part of the TkN library. It reads the TkN sqlite3 database, build the C++ structures in memory and make the links between these structures and any object created by the user. This way, the level scheme of a nucleus is only built once, even if the user create the corresponding nucleus millions times.Is also allows the user to easily browse the full database via the use of the gmanager
singleton. For example, we can loop on all the existing nuclei using:
for(const auto &nuc : gmanager->get_nuclei()) {
...
}
As seen previously with the levels and decays, we can also use a lambda expression to filter the list of nuclei, e.g. the carbon isotopes:
for(const auto &nuc : gmanager->get_nuclei( [](auto nuc) {
return (nuc->get_z()==6 && !nuc->get_level_scheme()->get_levels().empty());
})) {
cout << nuc->get_symbol() << " ";
} cout << endl;
8C 9C 10C 11C 12C 13C 14C 15C 16C 17C 18C 19C 20C 22C
Some tools are also provided to easily loop on the Z or N known ranges:
for(const auto &znucs : gmanager->get_map_of_nuclei_per_z()) {
cout<<znucs.first<<" ";
}
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
auto CarbonIsotopes = gmanager->get_map_of_nuclei_per_z().at(6);
for(auto &nuc : CarbonIsotopes) {
cout<<nuc->get_symbol()<<" ";
}
8C 9C 10C 11C 12C 13C 14C 15C 16C 17C 18C 19C 20C 21C 22C 23C
Measures and units
To handle the fact that a measure is always associated to a specific unit and an uncertainty, that can be in some cases assymetric, a dedicated class called tkn::tkmeasure has been created.In addition, a tkmeasure gives some properties on the measure, like if the measure is uncertain, is coming from a systematic strudy or from calculations. It can also handle the fact that some measures are given as a limit value.The standard way to access a tkmeasure is using the tkproperty_list::get() method:
auto measure = nuc.get("lifetime");
cout << measure->get_value() << " " << measure->get_unit() << " +- " << measure->get_error() << endl;
To list the accessible tkmeasure properties, use:
nuc.list_data_properties()
[ INFO ] nucleus data properties:
[ INFO ] Qalpha Qalpha = -12012.500 (0.081) keV
[ INFO ] QbetaMinus QbetaMinus = 156.4760 (0.0037) keV
[ INFO ] QbetaMinusOneNeutronEmission QbetaMinusOneNeutronEmission = -10396.9000 (0.2696) keV
[ INFO ] QbetaMinusTwoNeutronEmission QbetaMinusTwoNeutronEmission = -30460.80000000 (0.00537582) keV
[ INFO ] QdeltaAlpha QdeltaAlpha = 2892.4400000 (0.0405445) keV
[ INFO ] QdoubleBetaMinus QdoubleBetaMinus = -4987.8900 (0.0254) keV
[ INFO ] QdoubleElectronCapture QdoubleElectronCapture = -36934.600 (132.245) keV
[ INFO ] QelectronCapture QelectronCapture = -20643.8000 (21.2133) keV
[ INFO ] QelectronCaptureOneProtonEmission QelectronCaptureOneProtonEmission = -37928.2000 (10.1805) keV
[ INFO ] QpositronEmission QpositronEmission = -21665.8000 (21.2133) keV
[ INFO ] XRay_Kalpha1 XRay_Kalpha1 = 0.277 keV
[ INFO ] atomic_mass atomic_mass = 12.011 u
[ INFO ] atomic_radius_van_der_Waals atomic_radius_van_der_Waals = 170 pm
[ INFO ] binding_energy_ldm_fit_overA binding_energy_ldm_fit_overA = -37.0681 (0.0004) keV
[ INFO ] binding_energy_overA binding_energy_overA = 7520.3200 (0.0004) keV
[ INFO ] boiling_point boiling_point = 4098 K
[ INFO ] density density = 2.267
[ INFO ] ionization_energy ionization_energy = 11.26 eV
[ INFO ] lifetime lifetime = 5700 (30 ) y
[ INFO ] mass_excess mass_excess = 3019.89000 (0.00375) keV
[ INFO ] melting_point melting_point = 3823 K
[ INFO ] neutronSeparationEnergy neutronSeparationEnergy = 8176.4300 (0.0038) keV
[ INFO ] pairingGap pairingGap = 3479.180000 (0.399772) keV
[ INFO ] protonSeparationEnergy protonSeparationEnergy = 20831.0000 (1.0001) keV
[ INFO ] quadrupoleDeformation quadrupoleDeformation = 0.3593840 (0.0279568)
[ INFO ] twoNeutronSeparationEnergy twoNeutronSeparationEnergy = 13122.7000 (0.0039) keV
[ INFO ] twoProtonSeparationEnergy twoProtonSeparationEnergy = 36635.8000 (1.9086) keV
The same applies for a tklevel or a tkdecay:
auto level = nuc.get_level_scheme()->get_level("2+1");
level->list_data_properties();
[ INFO ] data properties:
[ INFO ] energy Level energy = 4041.20 (0.15 ) keV
[ INFO ] lifetime lifetime = 2.4 (-0.5 ; +0.9 ) fs
In this case, the lifetime uncertainty is asymetric, we can access it as follows:
auto level = nuc.get_level_scheme()->get_level("2+1");
auto lifetime = level->get("lifetime");
cout << lifetime->get_value() << " " << lifetime->get_unit() << " - " << lifetime->get_error_low() << " + " << lifetime->get_error_high() << endl;
As seen in the tkn::tkmeasure class, tkn offers the possibility to convert some measure into different units
Currently, tkn handles three unit types: Energy, Time en Lenght. Few other units are included in tkn but that cannot be converted
The available energy units are the following: eV, keV, MeV, GeV, TeV
The available time units are the following: as, fs, ps, ns, us, ms, s, min, h, d, y
The available lenght units are the following: am, fm, pm, nm, um, mm, cm, m
In general, units can be converted only in the scale of a same type. One exception is given for the energy to time conversion. For very low lifetimes, it is common to express the width of a level in energy. This conversion is taken into account in tkn.
Multi-thread compatibility
The TkN library can be used in a multi-threaded code.
In the examples, you can find an example of a multi-thread use of the TkN library, see the example