#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of the Cortix toolkit environment
# https://cortix.org
import scipy.constants as const
from cortix.support.periodictable import ELEMENTS
[docs]class Species:
'''
All SI units (kg,s,K,Pa,J,W).
The Specie() class encapsulates either the molecular or empirical chemical
formula of a compound.
This is done as follows. Say MAO2 is either a molecular or empirical chemical
formula of a ficticious compound denoting minor actinides dioxide. The list
of atoms is given as follows:
['0.49*Np-237', '0.42*Am-241', '0.08*Am-243', '0.01*Cm-244', '2.0*O-16']
note the MA forming nuclides add to 1 = 0.49 + 0.42 + 0.08 + 0.01. Therefore
the number of atoms in this compound is 3. 1 MA "ficticious" atom and 2 O.
Note that the total number of "atoms" is obtained by summing all multipliers:
0.49 + 0.42 + 0.08 + 0.01 + 2.0.
The nuclide is indicated by the element symbol followed by a dash and the
atomic mass number. Here the number of nuclide types is 5 (self.num_nuclide_types).
The numbers preceeding the nuclide symbol before the * will be referred to as
multipliers. The sum of the multipliers will add to the number of "atoms" in
the formula. WARNING: a multiplier could be in the format 0.00e-00. In this
case a hiphen may appear twice, e.g.: 1.549e-09*U-233
Other forms can be used for common true species
['Np-237', '2.0*O-16'] or ['Np-237', 'O-16', 'O-16'] or [ '2*H', 'O' ] or
[ 'H', 'O', 'H' ] etc...
This code will calculate the molar mass of any species with a given valid
atom list using a provided periodic table of chemical elements. The user
can also reset the value of the molar mass with a setter method.
'''
def __init__( self,
name='null-species-name',
formula_name='null-species-formula-name',
atoms=list(),
flag='null-species-flag',
info=None):
assert isinstance(name, str)
self.name = name
assert isinstance(formula_name, str)
self.formula_name = formula_name
assert isinstance(atoms, list)
self.atoms = atoms
self.flag = flag # flag can be any type
self.info = info # info text such as technical name or other properties info
self.molar_mass = 0.0 # kg/mol
self.molar_heat_pwr = 0.0
self.molar_gamma_pwr = 0.0
self.molar_radioactivity = 0.0
self.molar_mass_unit = 'kg/mol'
self.molar_heat_pwr_unit = 'W/mol'
self.molar_gamma_pwr_unit = 'W/mol'
self.molar_radioactivity_unit = 'Ci/mol'
self.molar_radioactivity_fractions = list()
self.update_molar_mass()
return
[docs] def update_molar_mass(self):
'''
Updates the molar mass of the species after the molecular formula has
been changed.
'''
molar_mass_const = const.physical_constants['molar mass constant'][0]
molar_mass_const_unit = const.physical_constants['molar mass constant'][1]
for entry in self.atoms:
assert isinstance(entry, str)
tmp = entry.split('*')
nuclide = tmp[-1]
element = nuclide.split('-')[0]
assert element in ELEMENTS, 'element = %r'%(element)
self.num_atoms = 0
self.num_nuclide_types = 0
nuclides = dict()
num_atoms = 0
summ = 0.0
for entry in self.atoms:
assert isinstance(entry, str)
# format example: 3.2*O-18, or 3*O or O or O-16
tmp = entry.split('*')
multiple = 1.0
# single nuclide
if len(tmp) == 1:
nuclide = tmp[0]
# multiple nuclide
elif len(tmp) == 2:
multiple = float(tmp[0])
nuclide = tmp[1]
else:
assert False
nuclides[nuclide] = multiple
num_atoms += multiple
try:
tmp = nuclide.split('-')
if len(tmp) == 1:
element = ELEMENTS[tmp[0]]
rel_atomic_mass = element.exactmass # from isotopic composition
if rel_atomic_mass == 0.0:
rel_atomic_mass = element.mass
molar_mass = rel_atomic_mass * molar_mass_const
elif len(tmp) == 2:
element = ELEMENTS[tmp[0]].isotopes[int(tmp[1].strip('m'))]
molar_mass = element.mass * molar_mass_const
else:
assert False
except KeyError:
summ += multiple * 0.0
else:
summ += multiple * molar_mass
self.molar_mass = summ
self.num_atoms = num_atoms
self.num_nuclide_types = len(nuclides)
return
def __str__(self):
s = '\n\t ' + \
'\n\t Species(): name=%s;' + \
' formula_name=%s;' + \
'\n\t formula=%s;' + \
'\n\t # atoms=%s;' + ' # nuclide types=%s;' + ' molar mass=%9.3e[%s];' + \
'\n\t flag=%s;' + \
'\n\t info=%s;' + \
'\n\t molar radioactivity=%9.3e[%s];' + \
'\n\t molar heat pwr=%9.3e[%s];' + \
'\n\t molar gamma pwr=%9.3e[%s];' + \
'\n\t atoms=%s;' + \
'\n\t molar radioactivity fractions=%s'
return s % (self.name,
self.formula_name,
self.reorder_formula(),
self.num_atoms, self.num_nuclide_types, self.molar_mass, \
self.molar_mass_unit,
self.flag,
self.info,
self.molar_radioactivity, self.molar_radioactivity_unit,
self.molar_heat_pwr, self.molar_heat_pwr_unit,
self.molar_gamma_pwr, self.molar_gamma_pwr_unit,
[i.split('*')[-1] for i in self.atoms],
['%9.3e' % i for i in self.molar_radioactivity_fractions])
def __repr__(self):
s = '\n\t Species(): name=%s;' + \
' formula_name=%s;' + \
'\n\t formula=%s;' + \
'\n\t # atoms=%s;' + ' # nuclide types=%s;' + ' molar mass=%9.3e[%s];' + \
'\n\t flag=%s;' + \
'\n\t molar radioactivity=%9.3e[%s];' + \
'\n\t molar heat pwr=%9.3e[%s];' + \
'\n\t molar gamma pwr=%9.3e[%s];' + \
'\n\t atoms=%s;' + \
'\n\t molar radioactivity fractions=%s'
return s % (self.name,
self.formula_name,
self.reorder_formula(),
self.num_atoms, self.num_nuclide_types, self.molar_mass, \
self.molar_mass_unit,
self.flag,
self.molar_radioactivity, self.molar_radioactivity_unit,
self.molar_heat_pwr, self.molar_heat_pwr_unit,
self.molar_gamma_pwr, self.molar_gamma_pwr_unit,
[i.split('*')[-1] for i in self.atoms],
['%9.3e' % i for i in self.molar_radioactivity_fractions])
if __name__ == '__main__':
tbp_org = Species( name='TBP', formula_name='(C4H9O)_3PO(o)',
atoms=['12*C','27*H','4*O','P'] )
print(tbp_org)
no3Minus_aqu = Species( name='NO3-', formula_name='NO3-(a)',
atoms=['N','3*O'] )
print(no3Minus_aqu)