Source code for saltproc.serpent_depcode
-import subprocess
+from pathlib import Path
+import subprocess
import os
import shutil
import re
@@ -87,39 +88,44 @@ Source code for saltproc.serpent_depcode
from saltproc.abc import Depcode
[docs]class SerpentDepcode(Depcode):
- """Class contains information about input, output, geometry, and
- template files for running Serpent2 depletion simulations.
- Also contains neutrons population, active, and inactive cycles.
- Contains methods to read template and output files,
- write new input files for Serpent2.
+ """Interface for running depletion steps in Serpent, as well as obtaining
+ depletion step results.
Attributes
-----------
- param : dict of str to type
- Holds Serpent depletion step parameter information. Parameter names are
+ neutronics_parameters : dict of str to type
+ Holds Serpent2 depletion step neutronics parameters. Parameter names are
keys and parameter values are values.
- sim_info : dict of str to type
- Holds Serpent simulation settings information. Setting names are keys
- and setting values are values.
- iter_inputfile : str
- Path to Serpent2 input file for Serpent2 rerunning.
- iter_matfile : str
- Path to iterative, rewritable material file for Serpent2
- rerunning. This file is modified during the simulation.
+ step_metadata : dict of str to type
+ Holds Serpent2 depletion step metadata. Metadata labels are keys
+ and metadata values are values.
+ runtime_inputfile : str
+ Path to Serpent2 input file used to run depletion step. Contains neutron
+ settings and non-burnable materials.
+ runtime_matfile : str
+ Path to Serpent2 material file containing burnable materials used to
+ run depletion step, and modified after fuel reprocessing.
+ npop : int
+ Size of neutron population per cycle
+ active_cycles : int
+ Number of active cycles.
+ inactive_cycles : int
+ Number of inactive cycles.
+
"""
[docs] def __init__(self,
- exec_path="sss2",
- template_input_file_path="reactor.serpent",
- geo_files=None,
- npop=50,
- active_cycles=20,
- inactive_cycles=20):
- """Initializes the SerpentDepcode object.
+ output_path,
+ exec_path,
+ template_input_file_path,
+ geo_files):
+ """Initialize a SerpentDepcode object.
Parameters
----------
+ output_path : str
+ Path to results storage directory.
exec_path : str
Path to Serpent2 executable.
template_input_file_path : str
@@ -128,118 +134,94 @@ Source code for saltproc.serpent_depcode
Path to file that contains the reactor geometry.
List of `str` if reactivity control by
switching geometry is `On` or just `str` otherwise.
- npop : int, optional
- Size of neutron population per cycle for Monte Carlo.
- active_cycles : int, optional
- Number of active cycles.
- inactive_cycles : int, optional
- Number of inactive cycles.
"""
super().__init__("serpent",
+ output_path,
exec_path,
template_input_file_path,
- geo_files=geo_files,
- npop=npop,
- active_cycles=active_cycles,
- inactive_cycles=inactive_cycles)
- self.iter_inputfile = './serpent_iter_input.serpent'
- self.iter_matfile = './serpent_iter_mat.ini'
-
-[docs] def change_sim_par(self, template_data):
- """Finds simulation parameters (neutron population, cycles) in the
- Serpent2 template file and change them to the parameters from the
- SaltProc input file.
+ geo_files)
+ self.runtime_inputfile = \
+ str((output_path / 'runtime_input.serpent').resolve())
+ self.runtime_matfile = str((output_path / 'runtime_mat.ini').resolve())
+
+[docs] def get_neutron_settings(self, file_lines):
+ """Get neutron settings (no. of neutrons per cycle, no. of active and
+ inactive cycles) from the Serpent2 input file
Parameters
----------
- template_data : list
- List of strings parsed from user's Serpent2 template file.
-
- Returns
- -------
- input_data : list
- List of strings containing Serpent2 input file with new
- simulation parameters.
+ file_lines : list of str
+ Serpent2 runtime input file.
"""
- if self.npop and self.active_cycles and self.inactive_cycles:
- sim_param = [s for s in template_data if s.startswith("set pop")]
- if len(sim_param) > 1:
- print('ERROR: Template file %s contains multiple lines with '
- 'simulation parameters:\n'
- % (self.template_input_file_path), sim_param)
- return
- elif len(sim_param) < 1:
- print(
- 'ERROR: Template file %s does not contain line with '
- 'simulation parameters.' %
- (self.template_input_file_path))
- return
- args = 'set pop %i %i %i\n' % (self.npop, self.active_cycles,
- self.inactive_cycles)
- return [s.replace(sim_param[0], args) for s in template_data]
-
-[docs] def create_iter_matfile(self, template_data):
- """Finds ``include`` line with path to material file, copies content of
- this file to iteration material file, changes path in ``include`` line
- to newly created iteration material file.
+ neutron_settings = \
+ [line for line in file_lines if line.startswith("set pop")]
+ if len(neutron_settings) > 1:
+ raise IOError('Template file '
+ f'{self.template_input_file_path} contains '
+ 'multuple lines with neutron settings')
+ elif len(neutron_settings) < 1:
+ raise IOError('Template file '
+ f'{self.template_input_file_path} does not '
+ 'contain neutron settings.')
+ _, _, npop, active_cycles, inactive_cycles = neutron_settings[0].split()
+ self.npop = int(npop)
+ self.active_cycles = int(active_cycles)
+ self.inactive_cycles = int(inactive_cycles)
+
+[docs] def create_runtime_matfile(self, file_lines):
+ """Creates the runtime material file tracking burnable materials
+ ans inserts the path to this file in the Serpent2 runtime input file
Parameters
----------
- template_data : list
- List of strings parsed from user's template file.
+ file_lines : list of str
+ Serpent2 runtime input file.
Returns
-------
- input_data : list
- List of strings containing modified user template file.
+ file_lines : list of str
+ Serpent2 runtime input file with updated material file path.
"""
- data_dir = os.path.dirname(self.template_input_file_path)
- include_str = [s for s in template_data if s.startswith("include ")]
- if not include_str:
- print('ERROR: Template file %s has no <include "material_file">'
- ' statements ' % (self.template_input_file_path))
- return
- src_file = include_str[0].split()[1][1:-1]
- if not os.path.isabs(src_file):
- abs_src_matfile = os.path.normpath(data_dir) + '/' + src_file
+ runtime_dir = Path(self.template_input_file_path).parents[0]
+ include_card = [line for line in file_lines if line.startswith("include ")]
+ if not include_card:
+ raise IOError('Template file '
+ f'{self.template_input_file_path} has no <include '
+ '"material_file"> statements')
+ burnable_materials_path = include_card[0].split()[1][1:-1]
+ if not Path(burnable_materials_path).is_absolute():
+ absolute_path = (runtime_dir / burnable_materials_path)
else:
- abs_src_matfile = src_file
- if 'mat ' not in open(abs_src_matfile).read():
- print('ERROR: Template file %s has not include file with'
- ' materials description or <include "material_file">'
- ' statement is not appears'
- ' as first <include> statement\n'
- % (self.template_input_file_path))
- return
+ absolute_path = Path(burnable_materials_path)
+ with open(absolute_path) as f:
+ if 'mat ' not in f.read():
+ raise IOError('Template file '
+ f'{self.template_input_file_path} includes '
+ 'no file with materials description')
# Create data directory
- try:
- os.mkdir(os.path.dirname(self.iter_matfile))
- except FileExistsError:
- pass
+ Path.mkdir(Path(self.runtime_matfile).parents[0], exist_ok=True)
+
# Create file with path for SaltProc rewritable iterative material file
- shutil.copy2(abs_src_matfile, self.iter_matfile)
- return [s.replace(src_file, self.iter_matfile) for s in template_data]
+ shutil.copy2(absolute_path, self.runtime_matfile)
+ return [line.replace(burnable_materials_path, self.runtime_matfile) for line in file_lines]
-[docs] def get_nuc_name(self, nuc_code):
- """Returns nuclide name in human-readable notation: chemical symbol
- (one or two characters), dash, and the atomic weight. Lastly, if the
- nuclide is in metastable state, the letter `m` is concatenated with
- number of excited state. For example, `Am-242m1`.
+[docs] def convert_nuclide_code_to_name(self, nuc_code):
+ """Converts Serpent2 nuclide code to symbolic nuclide name.
+ If nuclide is in a metastable state, the nuclide name is concatenated
+ with the letter `m` and the state index.
Parameters
----------
nuc_code : str
- Name of nuclide in Serpent2 form. For instance, `Am-242m`.
+ Nuclide code in Serpent2 format (`47310.09c`)
Returns
-------
nuc_name : str
- Name of nuclide in human-readable notation (`Am-242m1`).
- nuc_zzaaam : str
- Name of nuclide in `zzaaam` form (`952421`).
+ Symbolic nuclide name (`Am242m1`).
"""
@@ -248,7 +230,6 @@ Source code for saltproc.serpent_depcode
zz = pyname.znum(nuc_code)
aa = pyname.anum(nuc_code)
aa_str = str(aa)
- # at_mass = pydata.atomic_mass(nuc_code_id)
if aa > 300:
if zz > 76:
aa_str = str(aa - 100) + 'm1'
@@ -266,88 +247,90 @@ Source code for saltproc.serpent_depcode
nuc_name = pyname.name(nuc_code)[:-1] + 'm' + str(meta_flag)
else:
nuc_name = pyname.name(nuc_code)
- nuc_zzaaam = \
- self.convert_nuclide_name_serpent_to_zam(pyname.zzaaam(nuc_code))
- return nuc_name, nuc_zzaaam
-[docs] def create_nuclide_name_map_zam_to_serpent(self):
- """ Create a map that accepts nuclide names in `zzaaam` format and
- returns the Serpent2 nuclide code format. Uses Serpent2 `*.out` file
- with list of all nuclides in simulation.
+ return nuc_name
+
+[docs] def map_nuclide_code_zam_to_serpent(self):
+ """Creates a dictionary mapping nuclide codes in `zzaaam` format
+ to Serpent2's nuclide code format.
Returns
-------
- nuclide_map : dict of str to str
- Contains mapping for nuclide names from `zzaaam` to Serpent2
- format imported from Serpent2 ouput file:
+ nuc_code_map : dict of str to str
+ Maps `zzaaam` nuclide codes to Serpent2
+ nuclide codes.
``key``
- The key is nuclide name in `zzaaam` format. For example,
+ Nuclide code in `zzaaam` format. For example,
`922350` or `982510`.
``value``
- Serpent2-oriented name. For instance, 92235.09c for transport
- isotope or 982510 for decay only isotope).
+ Nuclide code in Serpent2 format. For instance, 92235.09c for a
+ nuclide with cross section data or 982510 for a decay-only nuclide.
"""
- map_dict = {}
+ nuc_code_map = {}
# Construct path to the *.out File
- out_file = os.path.join('%s.out' % self.iter_inputfile)
- file = open(out_file, 'r')
- str_list = file.read().split('\n')
- # Stop-line
- end = ' --- Table 2: Reaction and decay data: '
- for line in str_list:
- if not line:
- continue
- if end in line:
- break
- if 'c TRA' in line or 'c DEC' in line:
- line = line.split()
- iname, zzaaam = self.get_nuc_name(line[2])
- map_dict.update({zzaaam: line[2]})
- self.iso_map = map_dict
-
-[docs] def insert_path_to_geometry(self, template_data):
+ out_file = os.path.join('%s.out' % self.runtime_inputfile)
+ with open(out_file, 'r') as f:
+ file_lines = f.read().split('\n')
+ # Stop-line
+ end = ' --- Table 2: Reaction and decay data: '
+ for line in file_lines:
+ if not line:
+ continue
+ if end in line:
+ break
+ if 'c TRA' in line or 'c DEC' in line:
+ line = line.split()
+ nuc_code = line[2]
+ if '.' in str(nuc_code):
+ nuc_code = pyname.zzzaaa_to_id(int(nuc_code.split('.')[0]))
+
+ zzaaam = \
+ self.convert_nuclide_code_to_zam(pyname.zzaaam(nuc_code))
+
+ nuc_code_map.update({zzaaam: line[2]})
+ return nuc_code_map
+
+[docs] def insert_path_to_geometry(self, lines):
"""Inserts ``include <first_geometry_file>`` line on the 6th line of
Serpent2 input file.
Parameters
----------
- template_data : list
- List of strings parsed from user's template file.
+ lines : list of str
+ Serpent2 runtime input file.
Returns
-------
- template_data : list
- List of strings containing modified path to geometry
- in user's template file.
+ lines : list of str
+ Serpent 2 runtime input file containing modified path to geometry
"""
- template_data.insert(5, # Inserts on 6th line
+ lines.insert(5, # Inserts on 6th line
'include \"' + str(self.geo_files[0]) + '\"\n')
- return template_data
+ return lines
-[docs] def read_dep_comp(self, read_at_end=False):
- """Reads the Serpent2 `*_dep.m` file and returns a dictionary with
- a `Materialflow` object for each burnable material.
+[docs] def read_depleted_materials(self, read_at_end=False):
+ """Reads depleted materials from Serpent2's `*_dep.m`
+ file and returns a dictionary containing them.
Parameters
----------
read_at_end : bool, optional
- Controls at which moment in the depletion step to read the data.
If `True`, the function reads data at the end of the
depletion step. Otherwise, the function reads data at the
beginning of the depletion step.
Returns
-------
- mats : dict of str to Materialflow
- Dictionary that contains `Materialflow` objects.
+ depleted_materials : dict of str to Materialflow
+ Dictionary containing depleted materials.
``key``
Name of burnable material.
``value``
- `Materialflow` object holding composition and properties.
+ :class:`Materialflow` object holding material composition and properties.
"""
# Determine moment in depletion step to read data from
@@ -356,68 +339,73 @@ Source code for saltproc.serpent_depcode
else:
moment = 0
- dep_file = os.path.join('%s_dep.m' % self.iter_inputfile)
- dep = serpent.parse_dep(dep_file, make_mats=False)
- self.days = dep['DAYS'][moment]
- # Read materials names from the file
- mat_name = []
- mats = {}
- for key in dep.keys():
- m = re.search('MAT_(.+?)_VOLUME', key)
- if m:
- mat_name.append(m.group(1))
- zai = list(map(int, dep['ZAI'][:-2])) # zzaaam codes of isotopes
-
- for m in mat_name:
- volume = dep['MAT_' + m + '_VOLUME'][moment]
- nucvec = dict(zip(zai, dep['MAT_' + m + '_MDENS'][:, moment]))
- mats[m] = Materialflow(nucvec)
- mats[m].density = dep['MAT_' + m + '_MDENS'][-1, moment]
- mats[m].mass = mats[m].density * volume
- mats[m].vol = volume
- mats[m].burnup = dep['MAT_' + m + '_BURNUP'][moment]
- self.create_nuclide_name_map_zam_to_serpent()
- return mats
-
-[docs] def read_depcode_info(self):
- """Parses initial simulation info data from Serpent2 output and stores
- it in the `SerpentDepcode` object's ``sim_info`` attributes.
+ results_file = os.path.join('%s_dep.m' % self.runtime_inputfile)
+ results = serpent.parse_dep(results_file, make_mats=False)
+ self.days = results['DAYS'][moment]
+
+ # Get material names
+ mat_names = []
+ depleted_materials = {}
+ for key in results.keys():
+ name_match = re.search('MAT_(.+?)_VOLUME', key)
+ if name_match:
+ mat_names.append(name_match.group(1))
+ zai = list(map(int, results['ZAI'][:-2])) # zzaaam codes of isotopes
+
+ for name in mat_names:
+ volume = results[f'MAT_{name}_VOLUME'][moment]
+ nucvec = dict(zip(zai, results[f'MAT_{name}_MDENS'][:, moment]))
+ depleted_materials[name] = Materialflow(nucvec)
+ depleted_materials[name].density = results[f'MAT_{name}_MDENS'][-1, moment]
+ depleted_materials[name].mass = depleted_materials[name].density * volume
+ depleted_materials[name].vol = volume
+ depleted_materials[name].burnup = results[f'MAT_{name}_BURNUP'][moment]
+ return depleted_materials
+
+[docs] def read_step_metadata(self):
+ """Reads Serpent2 depletion step metadata and stores it in the
+ :class:`SerpentDepcode` object's :attr:`step_metadata` attribute.
"""
- res = serpent.parse_res(self.iter_inputfile + "_res.m")
+ res = serpent.parse_res(self.runtime_inputfile + "_res.m")
depcode_name, depcode_ver = res['VERSION'][0].decode('utf-8').split()
- self.sim_info['depcode_name'] = depcode_name
- self.sim_info['depcode_version'] = depcode_ver
- self.sim_info['title'] = res['TITLE'][0].decode('utf-8')
- self.sim_info['depcode_input_filename'] = \
+ self.step_metadata['depcode_name'] = depcode_name
+ self.step_metadata['depcode_version'] = depcode_ver
+ self.step_metadata['title'] = res['TITLE'][0].decode('utf-8')
+ self.step_metadata['depcode_input_filename'] = \
res['INPUT_FILE_NAME'][0].decode('utf-8')
- self.sim_info['depcode_working_dir'] = \
+ self.step_metadata['depcode_working_dir'] = \
res['WORKING_DIRECTORY'][0].decode('utf-8')
- self.sim_info['xs_data_path'] = \
+ self.step_metadata['xs_data_path'] = \
res['XS_DATA_FILE_PATH'][0].decode('utf-8')
- self.sim_info['OMP_threads'] = res['OMP_THREADS'][0]
- self.sim_info['MPI_tasks'] = res['MPI_TASKS'][0]
- self.sim_info['memory_optimization_mode'] = res['OPTIMIZATION_MODE'][0]
- self.sim_info['depletion_timestep'] = res['BURN_DAYS'][1][0]
- self.sim_info['depletion_timestep'] = res['BURN_DAYS'][1][0]
-
-[docs] def read_depcode_step_param(self):
- """Parses data from Serpent2 output for each step and stores it in
- `SerpentDepcode` object's ``param`` attributes.
+ self.step_metadata['OMP_threads'] = res['OMP_THREADS'][0]
+ self.step_metadata['MPI_tasks'] = res['MPI_TASKS'][0]
+ self.step_metadata['memory_optimization_mode'] = res['OPTIMIZATION_MODE'][0]
+ self.step_metadata['depletion_timestep'] = res['BURN_DAYS'][1][0]
+ self.step_metadata['execution_time'] = res['RUNNING_TIME'][1]
+ self.step_metadata['memory_usage'] = res['MEMSIZE'][0]
+
+
+[docs] def read_neutronics_parameters(self):
+ """Reads Serpent2 depletion step neutronics parameters and stores them
+ in :class:`SerpentDepcode` object's :attr:`neutronics_parameters`
+ attribute.
"""
- res = serpent.parse_res(self.iter_inputfile + "_res.m")
- self.param['keff_bds'] = res['IMP_KEFF'][0]
- self.param['keff_eds'] = res['IMP_KEFF'][1]
- self.param['breeding_ratio'] = res['CONVERSION_RATIO'][1]
- self.param['execution_time'] = res['RUNNING_TIME'][1]
- self.param['burn_days'] = res['BURN_DAYS'][1][0]
- self.param['power_level'] = res['TOT_POWER'][1][0]
- self.param['memory_usage'] = res['MEMSIZE'][0]
+ res = serpent.parse_res(self.runtime_inputfile + "_res.m")
+ self.neutronics_parameters['keff_bds'] = res['IMP_KEFF'][0]
+ self.neutronics_parameters['keff_eds'] = res['IMP_KEFF'][1]
+ self.neutronics_parameters['breeding_ratio'] = \
+ res['CONVERSION_RATIO'][1]
+ self.neutronics_parameters['burn_days'] = res['BURN_DAYS'][1][0]
+ self.neutronics_parameters['power_level'] = res['TOT_POWER'][1][0]
b_l = int(.5 * len(res['FWD_ANA_BETA_ZERO'][1]))
- self.param['beta_eff'] = res['FWD_ANA_BETA_ZERO'][1].reshape((b_l, 2))
- self.param['delayed_neutrons_lambda'] = \
+ self.neutronics_parameters['beta_eff'] = \
+ res['FWD_ANA_BETA_ZERO'][1].reshape((b_l, 2))
+ self.neutronics_parameters['delayed_neutrons_lambda'] = \
res['FWD_ANA_LAMBDA'][1].reshape((b_l, 2))
- self.param['fission_mass_bds'] = res['INI_FMASS'][1]
- self.param['fission_mass_eds'] = res['TOT_FMASS'][1]
+ self.neutronics_parameters['fission_mass_bds'] = \
+ res['INI_FMASS'][1]
+ self.neutronics_parameters['fission_mass_eds'] = \
+ res['TOT_FMASS'][1]
[docs] def read_plaintext_file(self, file_path):
"""Reads the content of a plaintext file for use by other methods.
@@ -429,63 +417,61 @@ Source code for saltproc.serpent_depcode
Returns
-------
- file_data : list
- List of strings containing file lines.
+ file_lines : list of str
+ File lines.
"""
- template_data = []
+ file_lines = []
with open(file_path, 'r') as file:
- template_data = file.readlines()
- return template_data
-
-[docs] def replace_burnup_parameters(
- self,
- template_data,
- reactor,
- current_depstep_idx):
- """Adds or replaces the ``set power P dep daystep DEPSTEP`` line in
- the Serpent2 input file. This line defines depletion history and power
- levels with respect to the depletion step in the single run and
- activates depletion calculation mode.
+ file_lines = file.readlines()
+ return file_lines
+
+[docs] def set_power_load(self,
+ file_lines,
+ reactor,
+ step_idx):
+ """Add power load attributes in a :class:`Reactor` object to the
+ ``set power P dep daystep DEPSTEP`` line in the Serpent2 runtime input
+ file.
Parameters
----------
- template_data : list
- List of strings parsed from user template file.
+ file_lines : list of str
+ Serpent2 runtime input file.
reactor : Reactor
Contains information about power load curve and cumulative
depletion time for the integration test.
- current_depstep_idx : int
+ step_idx : int
Current depletion step.
Returns
-------
- template_data : list
- List of strings containing modified in this function template file.
+ file_lines : list of str
+ Serpent2 runtime input file with power load specification.
"""
line_idx = 8 # burnup setting line index by default
- current_depstep_power = reactor.power_levels[current_depstep_idx]
- if current_depstep_idx == 0:
- current_depstep = reactor.dep_step_length_cumulative[0]
+ current_power = reactor.power_levels[step_idx]
+ if step_idx == 0:
+ step_length = reactor.dep_step_length_cumulative[0]
else:
- current_depstep = \
- reactor.dep_step_length_cumulative[current_depstep_idx] - \
- reactor.dep_step_length_cumulative[current_depstep_idx - 1]
- for line in template_data:
+ step_length = \
+ reactor.dep_step_length_cumulative[step_idx] - \
+ reactor.dep_step_length_cumulative[step_idx - 1]
+ for line in file_lines:
if line.startswith('set power '):
- line_idx = template_data.index(line)
- del template_data[line_idx]
+ line_idx = file_lines.index(line)
+ del file_lines[line_idx]
- template_data.insert(line_idx, # Insert on 9th line
- 'set power %5.9E dep daystep %7.5E\n' %
- (current_depstep_power,
- current_depstep))
- return template_data
+ file_lines.insert(line_idx, # Insert on 9th line
+ 'set power %5.9E dep daystep %7.5E\n' %
+ (current_power, step_length))
+ return file_lines
-[docs] def run_depcode(self, cores, nodes):
- """Runs Serpent2 as a subprocess with the given parameters.
+[docs] def run_depletion_step(self, cores, nodes):
+ """Runs a depletion step in Serpent2 as a subprocess with the given
+ parameters.
Parameters
----------
@@ -496,25 +482,7 @@ Source code for saltproc.serpent_depcode
"""
- if self.exec_path.startswith('/projects/sciteam/bahg/'): # check if BW
- args = (
- 'aprun',
- '-n',
- str(nodes),
- '-d', str(cores),
- self.exec_path,
- '-omp',
- str(cores),
- self.iter_inputfile)
- elif self.exec_path.startswith('/apps/exp_ctl/'): # check if Falcon
- args = (
- 'mpiexec',
- self.exec_path,
- self.iter_inputfile,
- '-omp',
- str(18))
- else:
- args = (self.exec_path, '-omp', str(cores), self.iter_inputfile)
+ args = (self.exec_path, '-omp', str(cores), self.runtime_inputfile)
print('Running %s' % (self.codename))
try:
subprocess.check_output(
@@ -527,22 +495,24 @@ Source code for saltproc.serpent_depcode
% (self.codename))
print('Finished Serpent2 Run')
-[docs] def convert_nuclide_name_serpent_to_zam(self, nuc_code):
- """Checks Serpent2-specific meta stable-flag for zzaaam. For instance,
+[docs] def convert_nuclide_code_to_zam(self, nuc_code):
+ """Converts nuclide code from Serpent2 format to zam format.
+ Checks Serpent2-specific meta stable-flag for zzaaam. For instance,
47310 instead of 471101 for `Ag-110m1`. Metastable isotopes represented
with `aaa` started with ``3``.
Parameters
----------
- nuc_code : str
- Name of nuclide in Serpent2 form. For instance, `47310`.
+ nuc_code : int
+ Nuclide code in Serpent2 format (`47310`).
Returns
-------
nuc_zzaam : int
- Name of nuclide in `zzaaam` form (`471101`).
+ Nuclide code in in `zzaaam` form (`471101`).
"""
+
zz = pyname.znum(nuc_code)
aa = pyname.anum(nuc_code)
if aa > 300:
@@ -560,11 +530,10 @@ Source code for saltproc.serpent_depcode
beginning of the Serpent iteration input file.
"""
geo_line_n = 5
- f = open(self.iter_inputfile, 'r')
- data = f.readlines()
- f.close()
+ with open(self.runtime_inputfile, 'r') as f:
+ lines = f.readlines()
- current_geo_file = data[geo_line_n].split('\"')[1]
+ current_geo_file = lines[geo_line_n].split('\"')[1]
current_geo_idx = self.geo_files.index(current_geo_file)
try:
new_geo_file = self.geo_files[current_geo_idx + 1]
@@ -572,16 +541,16 @@ Source code for saltproc.serpent_depcode
print('No more geometry files available \
and the system went subcritical \n\n')
print('Aborting simulation')
- return
- new_data = [d.replace(current_geo_file, new_geo_file) for d in data]
+
+ new_lines = \
+ [line.replace(current_geo_file, new_geo_file) for line in lines]
print('Switching to next geometry file: ', new_geo_file)
- f = open(self.iter_inputfile, 'w')
- f.writelines(new_data)
- f.close()
+ with open(self.runtime_inputfile, 'w') as f:
+ f.writelines(new_lines)
-[docs] def write_depcode_input(self, reactor, dep_step, restart):
- """Writes prepared data into the Serpent2 input file.
+[docs] def write_runtime_input(self, reactor, dep_step, restart):
+ """Write Serpent2 runtime input file for running depletion step
Parameters
----------
@@ -596,55 +565,50 @@ Source code for saltproc.serpent_depcode
"""
if dep_step == 0 and not restart:
- data = self.read_plaintext_file(self.template_input_file_path)
- data = self.insert_path_to_geometry(data)
- data = self.change_sim_par(data)
- data = self.create_iter_matfile(data)
+ lines = self.read_plaintext_file(self.template_input_file_path)
+ lines = self.insert_path_to_geometry(lines)
+ lines = self.create_runtime_matfile(lines)
+ self.get_neutron_settings(lines)
else:
- data = self.read_plaintext_file(self.iter_inputfile)
- data = self.replace_burnup_parameters(data, reactor, dep_step)
+ lines = self.read_plaintext_file(self.runtime_inputfile)
+ lines = self.set_power_load(lines, reactor, dep_step)
- if data:
- out_file = open(self.iter_inputfile, 'w')
- out_file.writelines(data)
- out_file.close()
+ with open(self.runtime_inputfile, 'w') as out_file:
+ out_file.writelines(lines)
-[docs] def write_mat_file(self, dep_dict, dep_end_time):
- """Writes the iteration input file containing the burnable materials
- composition used in Serpent2 runs and updated after each depletion
- step.
+[docs] def update_depletable_materials(self, mats, dep_end_time):
+ """Update material file with reprocessed material compositions.
Parameters
----------
- dep_dict : dict of str to Materialflow
- Dictionary that contains `Materialflow` objects.
+ mats : dict of str to Materialflow
+ Dictionary containing reprocessed material compositions
``key``
Name of burnable material.
``value``
- `Materialflow` object holding composition and properties.
+ :class:`Materialflow` object holding composition and properties.
dep_end_time : float
Current time at the end of the depletion step (d).
"""
- matf = open(self.iter_matfile, 'w')
- matf.write('%% Material compositions (after %f days)\n\n'
- % dep_end_time)
- for key, value in dep_dict.items():
- matf.write('mat %s %5.9E burn 1 fix %3s %4i vol %7.5E\n' %
- (key,
- -dep_dict[key].density,
- '09c',
- dep_dict[key].temp,
- dep_dict[key].vol))
- for nuc_code, wt_frac in dep_dict[key].comp.items():
- # Transforms iso name from zas to zzaaam and then to SERPENT
- iso_name_serpent = pyname.zzaaam(nuc_code)
- matf.write(' %9s %7.14E\n' %
- (self.iso_map[iso_name_serpent],
- -wt_frac))
- matf.close()
+ with open(self.runtime_matfile, 'w') as f:
+ f.write('%% Material compositions (after %f days)\n\n'
+ % dep_end_time)
+ nuc_code_map = self.map_nuclide_code_zam_to_serpent()
+ for name, mat in mats.items():
+ f.write('mat %s %5.9E burn 1 fix %3s %4i vol %7.5E\n' %
+ (name,
+ -mat.density,
+ '09c',
+ mat.temp,
+ mat.vol))
+ for nuc_code, mass_fraction in mat.comp.items():
+ zam_code = pyname.zzaaam(nuc_code)
+ f.write(' %9s %7.14E\n' %
+ (nuc_code_map[zam_code],
+ -mass_fraction))
diff --git a/master/_modules/saltproc/simulation.html b/master/_modules/saltproc/simulation.html
index d4149aaaa..aa9cb2016 100644
--- a/master/_modules/saltproc/simulation.html
+++ b/master/_modules/saltproc/simulation.html
@@ -160,8 +160,8 @@ Source code for saltproc.simulation
if not self.restart_flag:
try:
os.remove(self.db_path)
- os.remove(self.sim_depcode.iter_matfile)
- os.remove(self.sim_depcode.iter_inputfile)
+ os.remove(self.sim_depcode.runtime_matfile)
+ os.remove(self.sim_depcode.runtime_inputfile)
print("Previous run output files were deleted.")
except OSError as e:
pass
@@ -210,7 +210,7 @@ Source code for saltproc.simulation
# Read isotopes from Materialflow
for nuc, wt_frac in waste_dict[mn][proc].comp.items():
# Dictonary in format {isotope_name : index(int)}
- iso_idx[self.sim_depcode.get_nuc_name(nuc)[0]] = coun
+ iso_idx[self.sim_depcode.convert_nuclide_code_to_name(nuc)] = coun
# Convert wt% to absolute [user units]
iso_wt_frac.append(wt_frac * waste_dict[mn][proc].mass)
coun += 1
@@ -307,7 +307,7 @@ Source code for saltproc.simulation
# Read isotopes from Materialflow for material
for nuc_code, wt_frac in mats[key].comp.items():
# Dictonary in format {isotope_name : index(int)}
- iso_idx[key][self.sim_depcode.get_nuc_name(nuc_code)[0]] = coun
+ iso_idx[key][self.sim_depcode.convert_nuclide_code_to_name(nuc_code)] = coun
# Convert wt% to absolute [user units]
iso_wt_frac.append(wt_frac * mats[key].mass)
coun += 1
@@ -367,19 +367,17 @@ Source code for saltproc.simulation
"""
# Read info from depcode _res.m File
- self.sim_depcode.read_depcode_step_param()
+ self.sim_depcode.read_neutronics_parameters()
# Initialize beta groups number
- b_g = len(self.sim_depcode.param['beta_eff'])
+ b_g = len(self.sim_depcode.neutronics_parameters['beta_eff'])
# numpy array row storage for run info
class Step_info(tb.IsDescription):
keff_bds = tb.Float32Col((2,))
keff_eds = tb.Float32Col((2,))
breeding_ratio = tb.Float32Col((2,))
- step_execution_time = tb.Float32Col()
cumulative_time_at_eds = tb.Float32Col()
power_level = tb.Float32Col()
- memory_usage = tb.Float32Col()
beta_eff_eds = tb.Float32Col((b_g, 2))
delayed_neutrons_lambda_eds = tb.Float32Col((b_g, 2))
fission_mass_bds = tb.Float32Col()
@@ -403,28 +401,24 @@ Source code for saltproc.simulation
"Simulation parameters after each timestep")
# Intializing burn_time array at the first depletion step
self.burn_time = 0.0
- self.burn_time += self.sim_depcode.param['burn_days']
+ self.burn_time += self.sim_depcode.neutronics_parameters['burn_days']
# Define row of table as step_info
step_info = step_info_table.row
# Define all values in the row
- step_info['keff_bds'] = self.sim_depcode.param['keff_bds']
- step_info['keff_eds'] = self.sim_depcode.param['keff_eds']
- step_info['breeding_ratio'] = self.sim_depcode.param[
+ step_info['keff_bds'] = self.sim_depcode.neutronics_parameters['keff_bds']
+ step_info['keff_eds'] = self.sim_depcode.neutronics_parameters['keff_eds']
+ step_info['breeding_ratio'] = self.sim_depcode.neutronics_parameters[
'breeding_ratio']
- step_info['step_execution_time'] = self.sim_depcode.param[
- 'execution_time']
step_info['cumulative_time_at_eds'] = self.burn_time
- step_info['power_level'] = self.sim_depcode.param['power_level']
- step_info['memory_usage'] = self.sim_depcode.param[
- 'memory_usage']
- step_info['beta_eff_eds'] = self.sim_depcode.param[
+ step_info['power_level'] = self.sim_depcode.neutronics_parameters['power_level']
+ step_info['beta_eff_eds'] = self.sim_depcode.neutronics_parameters[
'beta_eff']
- step_info['delayed_neutrons_lambda_eds'] = self.sim_depcode.param[
+ step_info['delayed_neutrons_lambda_eds'] = self.sim_depcode.neutronics_parameters[
'delayed_neutrons_lambda']
- step_info['fission_mass_bds'] = self.sim_depcode.param[
+ step_info['fission_mass_bds'] = self.sim_depcode.neutronics_parameters[
'fission_mass_bds']
- step_info['fission_mass_eds'] = self.sim_depcode.param[
+ step_info['fission_mass_eds'] = self.sim_depcode.neutronics_parameters[
'fission_mass_eds']
# Inject the Record value into the table
@@ -444,7 +438,7 @@ Source code for saltproc.simulation
# numpy arraw row storage for run info
# delete and make this datatype specific
# to Depcode subclasses
- sim_info_dtype = np.dtype([
+ step_metadata_dtype = np.dtype([
('neutron_population', int),
('active_cycles', int),
('inactive_cycles', int),
@@ -457,27 +451,32 @@ Source code for saltproc.simulation
('OMP_threads', int),
('MPI_tasks', int),
('memory_optimization_mode', int),
- ('depletion_timestep', float)
+ ('depletion_timestep', float),
+ ('execution_time', float),
+ ('memory_usage', float)
])
# Read info from depcode _res.m File
- self.sim_depcode.read_depcode_info()
+ self.sim_depcode.read_step_metadata()
# Store information about material properties in new array row
- sim_info_row = (
+ step_metadata_row = (
self.sim_depcode.npop,
self.sim_depcode.active_cycles,
self.sim_depcode.inactive_cycles, # delete the below
- self.sim_depcode.sim_info['depcode_name'],
- self.sim_depcode.sim_info['depcode_version'],
- self.sim_depcode.sim_info['title'],
- self.sim_depcode.sim_info['depcode_input_filename'],
- self.sim_depcode.sim_info['depcode_working_dir'],
- self.sim_depcode.sim_info['xs_data_path'],
- self.sim_depcode.sim_info['OMP_threads'],
- self.sim_depcode.sim_info['MPI_tasks'],
- self.sim_depcode.sim_info['memory_optimization_mode'],
- self.sim_depcode.sim_info['depletion_timestep']
+ self.sim_depcode.step_metadata['depcode_name'],
+ self.sim_depcode.step_metadata['depcode_version'],
+ self.sim_depcode.step_metadata['title'],
+ self.sim_depcode.step_metadata['depcode_input_filename'],
+ self.sim_depcode.step_metadata['depcode_working_dir'],
+ self.sim_depcode.step_metadata['xs_data_path'],
+ self.sim_depcode.step_metadata['OMP_threads'],
+ self.sim_depcode.step_metadata['MPI_tasks'],
+ self.sim_depcode.step_metadata['memory_optimization_mode'],
+ self.sim_depcode.step_metadata['depletion_timestep'],
+ self.sim_depcode.step_metadata['execution_time'],
+ self.sim_depcode.step_metadata['memory_usage']
+
)
- sim_info_array = np.array([sim_info_row], dtype=sim_info_dtype)
+ step_metadata_array = np.array([step_metadata_row], dtype=step_metadata_dtype)
# Open or restore db and append datat to it
db = tb.open_file(
@@ -485,14 +484,14 @@ Source code for saltproc.simulation
mode='a',
filters=self.compression_params)
try:
- sim_info_table = db.get_node(db.root, 'initial_depcode_siminfo')
+ step_metadata_table = db.get_node(db.root, 'initial_depcode_siminfo')
except Exception:
- sim_info_table = db.create_table(
+ step_metadata_table = db.create_table(
db.root,
'initial_depcode_siminfo',
- sim_info_array,
+ step_metadata_array,
"Initial depletion code simulation parameters")
- sim_info_table.flush()
+ step_metadata_table.flush()
db.close()
[docs] def read_k_eds_delta(self, current_timestep):
diff --git a/master/_sources/releasenotes/v0.5.0.rst.txt b/master/_sources/releasenotes/v0.5.0.rst.txt
index 3cee61738..b4e995d75 100644
--- a/master/_sources/releasenotes/v0.5.0.rst.txt
+++ b/master/_sources/releasenotes/v0.5.0.rst.txt
@@ -54,6 +54,7 @@ New Features
Describe any new features to the code.
- ``openmc`` support via `DepcodeOpenMC`
+- OpenMC compatible MSBR model.
@@ -81,7 +82,9 @@ Script Changes
- Add ``SERPENT_DATA`` and ``SERPENT_ACELIB`` variables to ``.bashrc``
- A new script, ``scripts/ci/openmc-xs.bash``, that downloads the OpenMC HDF5 cross section library.
-
+- A new script, ``download_endfb71.bash``, that downloads the ENDF/B 7.1 cross section library -- including thermal scattering, decay, and fission yield data -- in ACE format.
+- A new script, ``process_endfb71_to_openmc.bash``, that converts the library created by ``download_endfb71.bash`` into an OpenMC-usable HDF5 format. Requires OpenMC to be installed from source to use.
+- A new script ``openmc_msbr_model.py``, that creates an OpenMC-usable MSBR model based on the Serpent MSBR model.
Python API Changes
@@ -108,27 +111,60 @@ Python API Changes
longer be initialized by the user during object creation.
-- New/changed classes and methods:
+- New/changed classes, methods, and attributes:
- ``Depcode``
+ - Add `output_path` parameter.
- ``template_inputfile_path`` → ``template_input_file_path``
- - Changed `iter_inputfile` and `iter_matfile` to be attributes instead of parameters
+ - Removed default values for `geo_files`
+ - Changed `iter_inputfile`, `iter_matfile` to be attributes instead of parameters
+ - Changed `npop`, `active_cycles`, `inactive_cycles` to be attributes instead of parameters
+ - ``read_depcode_info()`` → ``read_step_metadata()``
+ - ``sim_info`` → ``step_metadata``
+ - ``read_depcode_step_param()`` → ``read_neutronics_parameters()``
+ - ``param`` → ``neutronics_parameters``
+ - ``read_dep_comp()`` → ``read_depleted_materials()``
+ - ``run_depcode()`` → ``run_depletion_step()``
+ - ``write_mat_file()`` → ``update_depletable_materials()``
+ - ``write_depcode_input()`` → ``write_runtime_input()``
+ - ``iter_inputfile`` → ``runtime_inputfile``
+ - ``iter_matfile`` → ``runtime_matfile``
- ``DepcodeSerpent`` → ``SerpentDepcode``
+ - Add `output_path` parameter.
- ``template_inputfile_path`` → ``template_input_file_path``
- - Changed `iter_inputfile` and `iter_matfile` to be attributes instead of parameters
+ - Removed default values for `exec_path`, `template_input_file_path`, `geo_files`
+ - Changed `iter_inputfile`, `iter_matfile` to be attributes instead of parameters
+ - Changed `npop`, `active_cycles`, `inactive_cycles` to be attributes instead of parameters
+ - ``read_depcode_info()`` → ``read_depletion_step_metadata()``
+ - ``sim_info`` → ``step_metadata``
+ - ``read_depcode_step_param()`` → ``read_neutronics_parameters()``
+ - ``param`` → ``neutronics_parameters``
+ - ``read_dep_comp()`` → ``read_depleted_materials()``
+ - ``create_nuclide_name_map_zam_to_serpent()`` → ``map_nuclide_code_zam_to_serpent()``
+ - ``run_depcode()`` → ``run_depletion_step()``
+ - ``write_mat_file()`` → ``update_depletable_materials()``
+ - ``get_nuc_name()`` → ``convert_nuclide_code_to_name()``
+ - ``convert_nuclide_name_serpent_to_zam()`` → ``convert_nuclide_code_to_zam()``
+ - ``change_sim_par()`` → (deleted)
+ - (new function) → ``get_neutron_settings()``
+ - ``create_iter_matfile()`` → ``create_runtime_matfile()``
+ - ``replace_burnup_parameters()`` → ``set_power_load()``
+ - ``write_depcode_input()`` → ``write_runtime_input()``
+ - ``iter_inputfile`` → ``runtime_inputfile``
+ - ``iter_matfile`` → ``runtime_matfile``
- ``OpenMCDepcode`` is a ``Depcode`` subclass that interfaces with ``openmc``. This class implements the following functions
-
- - ``run_depcode()``
+ - ``run_depletion_step()``
- ``switch_to_next_geometry()``
- - ``write_depcode_input()``
+ - ``write_runtime_input()``
- ``write_depletion_settings()``
- ``write_saltproc_openmc_tallies()``
+
- ``app.py``
- ``reprocessing()`` → ``reprocess_materials()``
diff --git a/master/fileformatspec/inputfile.html b/master/fileformatspec/inputfile.html
index 44bf13731..eada35df4 100644
--- a/master/fileformatspec/inputfile.html
+++ b/master/fileformatspec/inputfile.html
@@ -145,7 +145,7 @@ SaltProc input file schemastring
pattern
-^\.\/(.*)$
+^(.\/)*(.*)$
-
+
depcode
@@ -194,75 +194,51 @@ SaltProc input file schemaPath(s) to user’s template depletion code input file(s) with reactor model
-
-npop
-
-
-Number of neutrons per generation
-
-type
-number
-
-minimum
-0
-
-
-active_cycles
-
-
-number of active generations
-
-type
-number
-
-minimum
-0
-
-
-inactive_cycles
-
-
-Number of inactive generations
-
-type
-number
-
-minimum
-0
-
-
+
geo_file_paths
Path(s) to geometry file(s) to switch to in depletion code runs
-type
+type
array
-items
+items
type
string
-minItems
+minItems
1
-uniqueItems
+uniqueItems
False
-allOf
+allOf
if
properties
-
+
codename
const
serpent
-then
+then
properties
+
+exec_path
+
+
+Path to Serpent executable
+
+type
+string
+
+default
+sss2
+
template_input_file_path
@@ -273,7 +249,7 @@ SaltProc input file schemastring
pattern
-^\.\/(.*)$
+^(.\/)*(.*)$
if
properties
@@ -285,33 +261,48 @@ SaltProc input file schemaopenmc
-then
+then
properties
-
+
+exec_path
+
+
+Path to OpenMC depletion script
+
+type
+string
+
+default
+openmc_deplete.py
+
+
template_input_file_path
Paths to OpenMC template input files
-type
+type
object
-properties
+properties
-
+
settings
OpenMC settings file
-type
+type
string
-pattern
-^\.\/(.*)\.xml$
+pattern
+^(.\/)*(.*)\.xml$
-
+default
+settings.xml
+
+
materials
@@ -321,19 +312,10 @@ SaltProc input file schemapattern
-^\.\/(.*)\.xml$
+^(.\/)*(.*)\.xml$
-
-plots
-
-
-OpenMC plots file (optional)
-
-type
-string
-
-pattern
-^\.\/(.*)\.xml$
+default
+materials.xml
+
+geo_file_paths
+
+
+Path(s) to geometry file(s) to switch to in OpenMC code runs
+
+type
+array
+
+default
+geometry.xml
+
+items
+type
+string
+
+pattern
+^(.\/)*(.*)\.xml$
+
+minItems
+1
simulation
diff --git a/master/genindex.html b/master/genindex.html
index 6cf51600a..a672de49d 100644
--- a/master/genindex.html
+++ b/master/genindex.html
@@ -88,12 +88,14 @@ Index
| K
| L
| M
+ | N
| O
| P
| Q
| R
| S
| T
+ | U
| W
@@ -145,6 +147,16 @@ _
A
G
- get_mass() (saltproc.materialflow.Materialflow method)
- - get_nuc_name() (saltproc.serpent_depcode.SerpentDepcode method)
+
- get_neutron_settings() (saltproc.serpent_depcode.SerpentDepcode method)
@@ -272,26 +282,18 @@ H
I
@@ -314,6 +316,8 @@ L
M
-O
+N
-
-
-P
-
+
+
+O
+
+
+
+
+P
+W
+U
+
+
+W
+