diff --git a/doc/releasenotes/v0.5.0.rst b/doc/releasenotes/v0.5.0.rst index 3cee61738..d823581e9 100644 --- a/doc/releasenotes/v0.5.0.rst +++ b/doc/releasenotes/v0.5.0.rst @@ -108,27 +108,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/examples/msbr/msbr_main.json b/examples/msbr/msbr_main.json index f03b7ad1a..dccab2b94 100644 --- a/examples/msbr/msbr_main.json +++ b/examples/msbr/msbr_main.json @@ -1,16 +1,13 @@ { "proc_input_file": "msbr_objects.json", "dot_input_file": "msbr.dot", - "output_path": "./data", + "output_path": "data", "num_depsteps": 12, "depcode": { "codename": "serpent", "exec_path": "sss2", - "template_input_file_path": "./msbr.serpent", - "npop": 50, - "active_cycles": 20, - "inactive_cycles": 20, - "geo_file_paths": ["./geometry/msbr_full.ini"] + "template_input_file_path": "msbr.serpent", + "geo_file_paths": ["geometry/msbr_full.ini"] }, "simulation": { "sim_name": "msbr_example_simulation", diff --git a/examples/tap/tap_main.json b/examples/tap/tap_main.json index 3934f663f..7c2c5b0f4 100644 --- a/examples/tap/tap_main.json +++ b/examples/tap/tap_main.json @@ -1,31 +1,28 @@ { "proc_input_file": "tap_objects.json", "dot_input_file": "tap.dot", - "output_path": "./data", + "output_path": "data", "num_depsteps": 3, "depcode": { "codename": "serpent", "exec_path": "sss2", - "template_input_file_path": "./tap.serpent", - "npop": 50, - "active_cycles": 20, - "inactive_cycles": 20, + "template_input_file_path": "tap.serpent", "geo_file_paths": [ - "./geometry/347_base.ini", - "./geometry/406.ini", - "./geometry/427.ini", - "./geometry/505.ini", - "./geometry/576.ini", - "./geometry/633.ini", - "./geometry/681.ini", - "./geometry/840.ini", - "./geometry/880.ini", - "./geometry/900.ini", - "./geometry/988.ini", - "./geometry/1126.ini", - "./geometry/1338.ini", - "./geometry/1498.ini", - "./geometry/1668_all.ini" + "geometry/347_base.ini", + "geometry/406.ini", + "geometry/427.ini", + "geometry/505.ini", + "geometry/576.ini", + "geometry/633.ini", + "geometry/681.ini", + "geometry/840.ini", + "geometry/880.ini", + "geometry/900.ini", + "geometry/988.ini", + "geometry/1126.ini", + "geometry/1338.ini", + "geometry/1498.ini", + "geometry/1668_all.ini" ] }, "simulation": { diff --git a/saltproc/abc.py b/saltproc/abc.py index 2438ee1e2..4d04df979 100644 --- a/saltproc/abc.py +++ b/saltproc/abc.py @@ -1,40 +1,43 @@ from abc import ABC, abstractmethod class Depcode(ABC): - """Abstract class for interfacing with monte-carlo particle transport - codes. Contains information about input, output, geometry, and template - files for running depletion simulations. Also contains neutron - population, active, and inactive cycles. Contains methods to read template - and output files, and write new input files for the depletion code. + """Abstract interface for running depletion steps. Attributes ----------- - param : dict of str to type - Holds depletion step parameter information. Parameter names are keys + neutronics_parameters : dict of str to type + Holds depletion step neutronics parameters. Parameter names are keys and parameter values are values. - sim_info : dict of str to type - Holds simulation settings information. Setting names are keys - and setting values are values. - iter_inputfile : str - Path to depletion code input file for depletion code rerunning. - iter_matfile : str - Path to iterative, rewritable material file for depletion code - rerunning. This file is modified during the simulation. + step_metadata : dict of str to type + Holds depletion code depletion step metadata. Metadata labels are keys + and metadata values are values. + runtime_inputfile : str + Path to input file used to run depletion step. + runtime_matfile : str + Path to material file containing burnable materials used to + run depletion step. + npop : int + Size of neutron population per cycle + active_cycles : int + Number of active cycles. + inactive_cycles : int + Number of inactive cycles. + """ def __init__(self, codename, + output_path, exec_path, template_input_file_path, - geo_files=None, - npop=50, - active_cycles=20, - inactive_cycles=20): - """Initializes the Depcode object. + geo_files): + """Initialize a Depcode object. Parameters ---------- + output_path : str + Path to results storage directory. codename : str Name of depletion code. exec_path : str @@ -48,67 +51,58 @@ def __init__(self, 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. """ self.codename = codename + self.output_path = output_path self.exec_path = exec_path self.template_input_file_path = template_input_file_path self.geo_files = geo_files - self.npop = npop - self.active_cycles = active_cycles - self.inactive_cycles = inactive_cycles - self.param = {} - self.sim_info = {} - self.iter_inputfile = './iter_input' - self.iter_matfile = './iter_mat' + self.neutronics_parameters = {} + self.step_metadata = {} + self.runtime_inputfile = None + self.runtime_matfile = None @abstractmethod - def read_depcode_info(self): - """Parses initial depletion code info data from depletion code - output and stores it in the `Depcode` object's ``sim_info`` attribute. + def read_step_metadata(self): + """Reads depletion code's depletion step metadata and stores it in the + :class:`Depcode` object's :attr:`step_metadata` attribute. """ @abstractmethod - def read_depcode_step_param(self): - """Parses data from depletion code output for each step and stores - it in `Depcode` object's ``param`` attributes. + def read_neutronics_parameters(self): + """Reads depletion code's depletion step neutronics parameters and + stores them in :class:`Depcode` object's + :attr:`neutronics_parameters` attribute. """ @abstractmethod - def read_dep_comp(self, read_at_end=False): - """Reads the depleted material data from the depcode simulation - and returns a dictionary with a `Materialflow` object for each - burnable material. + def read_depleted_materials(self, read_at_end=False): + """Reads depleted materials from the depletion step results + 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. """ @abstractmethod - def run_depcode(self, cores, nodes): - """Runs depletion code as a subprocess with the given parameters. + def run_depletion_step(self, cores, nodes): + """Runs a depletion step as a subprocess with the given parameters. Parameters ---------- @@ -125,8 +119,8 @@ def switch_to_next_geometry(self): """ @abstractmethod - def write_depcode_input(self, reactor, dep_step, restart): - """ Writes prepared data into depletion code input file(s). + def write_runtime_input(self, reactor, dep_step, restart): + """Write input file(s) for running depletion step Parameters ---------- @@ -140,20 +134,18 @@ def write_depcode_input(self, reactor, dep_step, restart): """ @abstractmethod - def write_mat_file(self, dep_dict, dep_end_time): - """Writes the iteration input file containing the burnable materials - composition used in depletion runs and updated after each depletion - step. + 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). diff --git a/saltproc/app.py b/saltproc/app.py index 0cd1b5404..1ebcdf75a 100644 --- a/saltproc/app.py +++ b/saltproc/app.py @@ -26,33 +26,25 @@ def run(): object_input[1], depcode, cores, nodes) msr = _create_reactor_object(object_input[2]) - if isinstance(depcode.iter_inputfile, str): - depcode.iter_inputfile = (input_path / - depcode.iter_inputfile).resolve().as_posix() - else: - raise ValueError("not implemented") - depcode.iter_matfile = ( - input_path / - depcode.iter_matfile).resolve().as_posix() # Check: Restarting previous simulation or starting new? simulation.check_restart() # Run sequence # Start sequence for dep_step in range(len(msr.dep_step_length_cumulative)): print("\n\n\nStep #%i has been started" % (dep_step + 1)) - simulation.sim_depcode.write_depcode_input(msr, + simulation.sim_depcode.write_runtime_input(msr, dep_step, simulation.restart_flag) - depcode.run_depcode(cores, nodes) + depcode.run_depletion_step(cores, nodes) if dep_step == 0 and simulation.restart_flag is False: # First step # Read general simulation data which never changes simulation.store_run_init_info() # Parse and store data for initial state (beginning of dep_step) - mats = depcode.read_dep_comp(False) + mats = depcode.read_depleted_materials(False) simulation.store_mat_data(mats, dep_step - 1, False) # Finish of First step # Main sequence - mats = depcode.read_dep_comp(True) + mats = depcode.read_depleted_materials(True) simulation.store_mat_data(mats, dep_step, False) simulation.store_run_step_info() # Reprocessing here @@ -84,7 +76,7 @@ def run(): print("Removed mass [g]:", extracted_mass) # Store in DB after reprocessing and refill (right before next depl) simulation.store_after_repr(mats, waste_and_feed_streams, dep_step) - depcode.write_mat_file(mats, simulation.burn_time) + depcode.update_depletable_materials(mats, simulation.burn_time) del mats, waste_streams, waste_and_feed_streams, extracted_mass gc.collect() # Switch to another geometry? @@ -144,7 +136,7 @@ def read_main_input(main_inp_file): Returns ------- - input_path : PosixPath + input_path : Path Path to main input file process_file : str Path to the `.json` file describing the fuel reprocessing components. @@ -172,11 +164,11 @@ def read_main_input(main_inp_file): input_path = (Path.cwd() / Path(f.name).parents[0]) # Saltproc settings - process_file = (input_path / - j['proc_input_file']).resolve().as_posix() - dot_file = ( + process_file = str((input_path / + j['proc_input_file']).resolve()) + dot_file = str(( input_path / - j['dot_input_file']).resolve().as_posix() + j['dot_input_file']).resolve()) output_path = j['output_path'] num_depsteps = j['num_depsteps'] @@ -190,30 +182,31 @@ def read_main_input(main_inp_file): reactor_input = j['reactor'] if depcode_input['codename'] == 'serpent': - depcode_input['template_input_file_path'] = ( + depcode_input['template_input_file_path'] = str(( input_path / - depcode_input['template_input_file_path']).resolve().as_posix() + depcode_input['template_input_file_path']).resolve()) elif depcode_input['codename'] == 'openmc': for key in depcode_input['template_input_file_path']: value = depcode_input['template_input_file_path'][key] - depcode_input['template_input_file_path'][key] = ( - input_path / value).resolve().as_posix() + depcode_input['template_input_file_path'][key] = str(( + input_path / value).resolve()) else: raise ValueError( f'{depcode_input["codename"]} ' 'is not a supported depletion code') + depcode_input['output_path'] = output_path geo_list = depcode_input['geo_file_paths'] # Global geometry file paths geo_file_paths = [] for g in geo_list: - geo_file_paths += [(input_path / g).resolve().as_posix()] + geo_file_paths += [str((input_path / g).resolve())] depcode_input['geo_file_paths'] = geo_file_paths # Global output file paths db_name = (output_path / simulation_input['db_name']) - simulation_input['db_name'] = db_name.resolve().as_posix() + simulation_input['db_name'] = str(db_name.resolve()) reactor_input = _process_main_input_reactor_params( reactor_input, num_depsteps) @@ -238,21 +231,20 @@ def _print_simulation_input_info(simulation_input, depcode_input): def _create_depcode_object(depcode_input): """Helper function for `run()` """ - codename = depcode_input['codename'] + codename = depcode_input['codename'].lower() if codename == 'serpent': depcode = SerpentDepcode elif codename == 'openmc': depcode = OpenMCDepcode else: raise ValueError( - f'{depcode_input["codename"]} is not a supported depletion code') + f'{codename} is not a supported depletion code.' + 'Accepts: "serpent" or "openmc".') - depcode = depcode(depcode_input['exec_path'], + depcode = depcode(depcode_input['output_path'], + depcode_input['exec_path'], depcode_input['template_input_file_path'], - geo_files=depcode_input['geo_file_paths'], - npop=depcode_input['npop'], - active_cycles=depcode_input['active_cycles'], - inactive_cycles=depcode_input['inactive_cycles']) + geo_files=depcode_input['geo_file_paths']) return depcode @@ -520,7 +512,7 @@ def refill_materials(mats, extracted_mass, waste_streams, process_file): process_file : str Path to the `.json` file describing the fuel reprocessing components. - Returns + Returns ------- waste_streams : dict of str to dict Superset of the input parameter `waste_streams`. Dictionary has diff --git a/saltproc/input_schema.json b/saltproc/input_schema.json index 78cefd81f..995557c15 100644 --- a/saltproc/input_schema.json +++ b/saltproc/input_schema.json @@ -17,7 +17,7 @@ "output_path": { "description": "Path output data storing folder", "type": "string", - "pattern": "^\\.\\/(.*)$" + "pattern": "^(.\\/)*(.*)$" }, "num_depsteps": { "description": "Number of steps for constant power and depletion interval case", @@ -36,18 +36,6 @@ "type": "string" }, "template_input_file_path": { "description": "Path(s) to user's template depletion code input file(s) with reactor model"}, - "npop": { - "description": "Number of neutrons per generation", - "type": "number", - "minimum": 0}, - "active_cycles": { - "description": "number of active generations", - "type": "number", - "minimum": 0}, - "inactive_cycles": { - "description": "Number of inactive generations", - "type": "number", - "minimum": 0}, "geo_file_paths": { "description": "Path(s) to geometry file(s) to switch to in depletion code runs", "type": "array", @@ -63,10 +51,14 @@ }, "then": { "properties": { + "exec_path": { + "description": "Path to Serpent executable", + "type": "string", + "default": "sss2"}, "template_input_file_path": { "description": "Path to Serpent template inputfile", "type": "string", - "pattern": "^\\.\\/(.*)$"} + "pattern": "^(.\\/)*(.*)$"} } } }, @@ -76,6 +68,10 @@ }, "then": { "properties": { + "exec_path": { + "description": "Path to OpenMC depletion script", + "type": "string", + "default": "openmc_deplete.py"}, "template_input_file_path": { "description": "Paths to OpenMC template input files", "type": "object", @@ -83,22 +79,28 @@ "settings": { "description": "OpenMC settings file", "type": "string", - "pattern": "^\\.\\/(.*)\\.xml$"}, + "pattern": "^(.\\/)*(.*)\\.xml$", + "default": "settings.xml"}, "materials": { "description": "OpenMC materials file", "type": "string", - "pattern": "^\\.\\/(.*)\\.xml$"}, - "plots": { - "description": "OpenMC plots file (optional)", - "type": "string", - "pattern": "^\\.\\/(.*)\\.xml$"}, + "pattern": "^(.\\/)*(.*)\\.xml$", + "default": "materials.xml"}, "chain_file": { "description": "OpenMC depletion chain file", "type": "string", - "pattern": "^\\.\\/(.*)\\.xml$"} + "pattern": "^(.\\/)*(.*)\\.xml$"} }, "required": ["settings", "materials", "chain_file"] + }, + "geo_file_paths": { + "description": "Path(s) to geometry file(s) to switch to in OpenMC code runs", + "type": "array", + "items": { "type": "string", + "pattern": "^(.\\/)*(.*)\\.xml$"}, + "minItems": 1, + "default": ["geometry.xml"] } } } diff --git a/saltproc/openmc_depcode.py b/saltproc/openmc_depcode.py index 67ec1c250..e48004ba7 100644 --- a/saltproc/openmc_depcode.py +++ b/saltproc/openmc_depcode.py @@ -12,43 +12,43 @@ from saltproc.abc import Depcode class OpenMCDepcode(Depcode): - """Class contains information about input, output, geometry, and - template files for running OpenMC depletion simulations. - Also contains neutrons population, active, and inactive cycles. - Contains methods to read template and output files, - write new input files for OpenMC. + """Interface for running depletion steps in OpenMC, as well as obtaining + depletion step results. Attributes ---------- - param : dict of str to type - Holds depletion step parameter information. Parameter names are keys - and parameter values are values. - sim_info : dict of str to type - Holds simulation settings information. Setting names are keys - and setting values are values. - iter_inputfile : dict of str to str - Paths to OpenMC input files for OpenMC rerunning. - iter_matfile : str - Path to iterative, rewritable material file for OpenMC - rerunning. This file is modified during the simulation. - - + neutronics_parameters : dict of str to type + Holds OpenMC depletion step neutronics parameters. Parameter names are + keys and parameter values are values. + step_metadata : dict of str to type + Holds OpenMC depletion step metadata. Metadata labels are keys + and metadata values are values. + runtime_inputfile : dict of str to str + Paths to OpenMC input files used to run depletion step. Contains neutron + settings and geometry. + runtime_matfile : str + Path to OpenMC material file containing 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. """ def __init__(self, - exec_path="openmc_deplete.py", - template_input_file_path={"geometry": "./geometry.xml", - "settings": "./settings.xml", - "chain_file": "./chain_simple.xml"}, - geo_files=None, - npop=50, - active_cycles=20, - inactive_cycles=20): - """Initializes the OpenMCDepcode object. + output_path, + exec_path, + template_input_file_path, + geo_files): + """Initialize a OpenMCDepcode object. Parameters ---------- + output_path : str + Path to results storage directory. exec_path : str Path to OpenMC depletion script. template_input_file_path : dict of str to str @@ -60,62 +60,60 @@ def __init__(self, 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. """ + + # if using the default depletion file, make sure we have the right path + if exec_path == "openmc_deplete.py": + exec_path = (Path(__file__).parents[0] / exec_path) + super().__init__("openmc", + output_path, exec_path, template_input_file_path, - geo_files, - npop, - active_cycles, - inactive_cycles) - self.iter_inputfile = {'geometry': './geometry.xml', - 'settings': './settings.xml'}, - self.iter_matfile = './materials.xml' - - def read_depcode_info(self): - """Parses initial OpenMC simulation info from the OpenMC output files - and stores it in the `Depcode` object's ``sim_info`` attribute. + geo_files) + self.runtime_inputfile = \ + {'geometry': str((output_path / 'geometry.xml').resolve()), + 'settings': str((output_path / 'settings.xml').resolve())} + self.runtime_matfile = str((output_path / 'materials.xml').resolve()) + + def read_step_metadata(self): + """Reads OpenMC's depletion step metadata and stores it in the + :class:`OpenMCDepcode` object's :attr:`step_metadata` attribute. """ - def read_depcode_step_param(self): - """Parses data from OpenMC depletion output for each step and stores - it in `Depcode` object's ``param`` attributes. + def read_neutronics_parameters(self): + """Reads OpenMC depletion step neutronics parameters and stores them + in :class:`OpenMCDepcode` object's :attr:`neutronics_parameters` + attribute. """ - def read_dep_comp(self, read_at_end=False): - """Reads the depleted material data from the OpenMC depletion - simulation and returns a dictionary with a `Materialflow` object for - each burnable material. + def read_depleted_materials(self, read_at_end=False): + """Reads depleted materials from OpenMC's `depletion_results.h5` file + and returns a dictionary with a :class:`Materialflow` object for each + depleted material. 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 composition and properties. """ - def run_depcode(self, cores, nodes): - """Runs OpenMC depletion simulation as a subprocess with the given + def run_depletion_step(self, cores, nodes): + """Runs a depletion step in OpenMC as a subprocess with the given parameters. Parameters @@ -131,17 +129,17 @@ def run_depcode(self, cores, nodes): '-n', str(nodes), 'python', - './deplete_openmc.py' - '-mat', - self.iter_matfile, - '-geo', - self.iter_inputfile['geometry'], - '-set', - self.iter_inputfile['settings'], - '-tal', - self.iter_inputfile['tallies'], - '-dep', - self.iter_inputfile['depletion_settings']) + self.exec_path, + '--materials', + self.runtime_matfile, + '--geometry', + self.runtime_inputfile['geometry'], + '--settings', + self.runtime_inputfile['settings'], + '--tallies', + self.runtime_inputfile['tallies'], + '--depletion_settings', + self.runtime_inputfile['depletion_settings']) print('Running %s' % (self.codename)) # TODO: Need to figure out how to adapt this to openmc @@ -160,78 +158,78 @@ def switch_to_next_geometry(self): """Switches the geometry file for the OpenMC depletion simulation to the next geometry file in `geo_files`. """ - mats = openmc.Materials.from_xml(self.iter_matfile) + mats = openmc.Materials.from_xml(self.runtime_matfile) next_geometry = openmc.Geometry.from_xml( path=self.geo_files.pop(0), materials=mats) - next_geometry.export_to_xml(path=self.iter_inputfile['geometry']) + next_geometry.export_to_xml(path=self.runtime_inputfile['geometry']) del mats, next_geometry - def write_depcode_input(self, reactor, dep_step, restart): - """ Writes prepared data into OpenMC input file(s). + def write_runtime_input(self, reactor, depletion_step, restart): + """Write OpenMC runtime input files for running depletion step. Parameters ---------- reactor : Reactor Contains information about power load curve and cumulative depletion time for the integration test. - dep_step : int + depletion_step : int Current depletion time step. restart : bool Is the current simulation restarted? """ - if dep_step == 0 and not restart: + if depletion_step == 0 and not restart: materials = openmc.Materials.from_xml( self.template_input_file_path['materials']) geometry = openmc.Geometry.from_xml( self.geo_files[0], materials=materials) settings = openmc.Settings.from_xml( self.template_input_file_path['settings']) - settings.particles = self.npop - settings.inactive = self.inactive_cycles - settings.batches = self.active_cycles + self.inactive_cycles + self.npop = settings.particles + self.inactive_cycles = settings.inactive + self.active_cycles = settings.batches - self.inactive_cycles + else: - materials = openmc.Materials.from_xml(self.iter_matfile) + materials = openmc.Materials.from_xml(self.runtime_matfile) geometry = openmc.Geometry.from_xml( - self.iter_inputfile['geometry'], materials=materials) + self.runtime_inputfile['geometry'], materials=materials) settings = openmc.Settings.from_xml( - self.iter_inputfile['settings']) + self.runtime_inputfile['settings']) - materials.export_to_xml(self.iter_matfile) - geometry.export_to_xml(self.iter_inputfile['geometry']) - settings.export_to_xml(self.iter_inputfile['settings']) - self.write_depletion_settings(reactor, dep_step) + materials.export_to_xml(self.runtime_matfile) + geometry.export_to_xml(self.runtime_inputfile['geometry']) + settings.export_to_xml(self.runtime_inputfile['settings']) + self.write_depletion_settings(reactor, depletion_step) self.write_saltproc_openmc_tallies(materials, geometry) del materials, geometry, settings - def write_depletion_settings(self, reactor, current_depstep_idx): - """Write the depeletion settings for the ``openmc.deplete`` - module. + def write_depletion_settings(self, reactor, step_idx): + """Write the depeletion settings for the OpenMC depletion step. Parameters ---------- 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. """ depletion_settings = {} - current_depstep_power = reactor.power_levels[current_depstep_idx] + current_power = reactor.power_levels[step_idx] # Get current depletion step length - if current_depstep_idx == 0: - current_depstep = reactor.dep_step_length_cumulative[0] + 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] + step_length = \ + reactor.dep_step_length_cumulative[step_idx] - \ + reactor.dep_step_length_cumulative[step_idx - 1] - out_path = os.path.dirname(self.iter_inputfile['settings']) + out_path = os.path.dirname(self.runtime_inputfile['settings']) depletion_settings['directory'] = out_path - depletion_settings['timesteps'] = [current_depstep] + depletion_settings['timesteps'] = [step_length] operator_kwargs = {} @@ -243,32 +241,30 @@ def write_depletion_settings(self, reactor, current_depstep_idx): a chain file in your saltproc input file") integrator_kwargs = {} - integrator_kwargs['power'] = current_depstep_power + integrator_kwargs['power'] = current_power integrator_kwargs['timestep_units'] = 'd' # days depletion_settings['operator_kwargs'] = operator_kwargs depletion_settings['integrator_kwargs'] = integrator_kwargs - self.iter_inputfile['depletion_settings'] = \ + self.runtime_inputfile['depletion_settings'] = \ os.path.join(out_path, 'depletion_settings.json') json_dep_settings = json.JSONEncoder().encode(depletion_settings) - with open(self.iter_inputfile['depletion_settings'], 'w') as f: + with open(self.runtime_inputfile['depletion_settings'], 'w') as f: f.writelines(json_dep_settings) - def write_mat_file(self, dep_dict, dep_end_time): - """Writes the iteration input file containing the burnable materials - composition used in OpenMC depletion runs and updated after each - depletion step. + def update_depletable_materials(self, mats, dep_end_time): + """Updates 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). @@ -317,10 +313,10 @@ def write_saltproc_openmc_tallies(self, materials, geometry): tally.scores = ['heating'] tallies.append(tally) - out_path = os.path.dirname(self.iter_inputfile['settings']) - self.iter_inputfile['tallies'] = \ + out_path = os.path.dirname(self.runtime_inputfile['settings']) + self.runtime_inputfile['tallies'] = \ os.path.join(out_path, 'tallies.xml') - tallies.export_to_xml(self.iter_inputfile['tallies']) + tallies.export_to_xml(self.runtime_inputfile['tallies']) del tallies diff --git a/saltproc/openmc_deplete.py b/saltproc/openmc_deplete.py index ed3aaa679..1d377bfa8 100644 --- a/saltproc/openmc_deplete.py +++ b/saltproc/openmc_deplete.py @@ -21,50 +21,49 @@ def parse_arguments(): """ parser = argparse.ArgumentParser() - parser.add_argument('-mat', + parser.add_argument('--materials', type=str, default=1, help='path to openmc material \ material xml file') - parser.add_argument('-geo', + parser.add_argument('--geometry', type=str, default=1, help='path to openmc geometry \ xml file') - parser.add_argument('-set', + parser.add_argument('--settings', type=str, default=None, help='path to openmc settings \ xml file') - parser.add_argument('-tal', + parser.add_argument('--tallies', type=str, default=None, help='path to openmc tallies \ xml file') - parser.add_argument('-dep', + parser.add_argument('--depletion_settings', type=str, default=None, help='path to saltproc depletion \ settings json file') args = parser.parse_args() - return str(args.mat), str(args.geo), str(args.set), \ - str(args.dep), str(args.tal) + return str(args.materials), str(args.geometry), str(args.settings), \ + str(args.tallies), str(args.depletion_settings) args = parse_arguments() # Initalize OpenMC objects -materials = openmc.Materials.from_xml(path=args.mat) -geometry = openmc.Geometry.from_xml(path=args.geo, materials=materials) -settings = openmc.Settings.from_xml(args.set) -tallies = openmc.Tallies.from_xml(args.tal) +materials = openmc.Materials.from_xml(path=args.materials) +geometry = openmc.Geometry.from_xml(path=args.geometry, materials=materials) +settings = openmc.Settings.from_xml(args.settings) +tallies = openmc.Tallies.from_xml(args.tallies) model = openmc.model.Model(materials=materials, geometry=geometry, settings=settings, tallies=tallies) -depletion_settings = {} -with open(args.dep) as f: +with open(args.depletion_settings) as f: depletion_settings = json.load(f) model.deplete(depletion_settings['timesteps'], diff --git a/saltproc/serpent_depcode.py b/saltproc/serpent_depcode.py index aecdddbe5..679bff333 100644 --- a/saltproc/serpent_depcode.py +++ b/saltproc/serpent_depcode.py @@ -1,3 +1,4 @@ +from pathlib import Path import subprocess import os import shutil @@ -10,39 +11,44 @@ from saltproc.abc import Depcode 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. + """ 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 @@ -51,118 +57,94 @@ def __init__(self, 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' - - 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()) + + 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] - - 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) + + 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 ' - ' 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 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 ' - ' statement is not appears' - ' as first 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] - 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`. + 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`). """ @@ -171,7 +153,6 @@ def get_nuc_name(self, nuc_code): 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' @@ -189,88 +170,90 @@ def get_nuc_name(self, nuc_code): 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 - 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 + + 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 - - 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 + + def insert_path_to_geometry(self, lines): """Inserts ``include `` 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 - 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. + 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 @@ -279,68 +262,73 @@ def read_dep_comp(self, read_at_end=False): 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 - - 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 + + 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] - - 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] + + + 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] def read_plaintext_file(self, file_path): """Reads the content of a plaintext file for use by other methods. @@ -352,63 +340,61 @@ def read_plaintext_file(self, file_path): 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 - - 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 + + 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 - def run_depcode(self, cores, nodes): - """Runs Serpent2 as a subprocess with the given parameters. + def run_depletion_step(self, cores, nodes): + """Runs a depletion step in Serpent2 as a subprocess with the given + parameters. Parameters ---------- @@ -419,25 +405,7 @@ def run_depcode(self, cores, nodes): """ - 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( @@ -450,22 +418,24 @@ def run_depcode(self, cores, nodes): % (self.codename)) print('Finished Serpent2 Run') - def convert_nuclide_name_serpent_to_zam(self, nuc_code): - """Checks Serpent2-specific meta stable-flag for zzaaam. For instance, + 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: @@ -483,11 +453,10 @@ def switch_to_next_geometry(self): 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] @@ -495,16 +464,16 @@ def switch_to_next_geometry(self): 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) - def write_depcode_input(self, reactor, dep_step, restart): - """Writes prepared data into the Serpent2 input file. + def write_runtime_input(self, reactor, dep_step, restart): + """Write Serpent2 runtime input file for running depletion step Parameters ---------- @@ -519,52 +488,47 @@ def write_depcode_input(self, reactor, dep_step, restart): """ 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) - 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. + 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/saltproc/simulation.py b/saltproc/simulation.py index bfee76c72..fae69679f 100644 --- a/saltproc/simulation.py +++ b/saltproc/simulation.py @@ -83,8 +83,8 @@ def check_restart(self): 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 @@ -133,7 +133,7 @@ def store_after_repr(self, after_mats, waste_dict, dep_step): # 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 @@ -230,7 +230,7 @@ def store_mat_data(self, mats, dep_step, store_at_end=False): # 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 @@ -290,19 +290,17 @@ def store_run_step_info(self): """ # 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() @@ -326,28 +324,24 @@ class Step_info(tb.IsDescription): "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 @@ -367,7 +361,7 @@ def store_run_init_info(self): # 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), @@ -380,27 +374,32 @@ def store_run_init_info(self): ('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( @@ -408,14 +407,14 @@ def store_run_init_info(self): 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() def read_k_eds_delta(self, current_timestep): diff --git a/tests/conftest.py b/tests/conftest.py index 0e79f3c35..9deb3a466 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,10 +25,10 @@ def path_test_file(cwd): @pytest.fixture(scope='session') def serpent_depcode(cwd): """SerpentDepcode object for unit tests""" - saltproc_input = (cwd / 'serpent_data' / 'tap_input.json').as_posix() + saltproc_input = str(cwd / 'serpent_data' / 'tap_input.json') _, _, _, object_input = read_main_input(saltproc_input) depcode = _create_depcode_object(object_input[0]) - depcode.iter_inputfile = (cwd / 'serpent_data' / 'tap_reference').as_posix() + depcode.runtime_inputfile = str(cwd / 'serpent_data' / 'tap_reference') return depcode @@ -36,24 +36,24 @@ def serpent_depcode(cwd): @pytest.fixture(scope='session') def openmc_depcode(cwd): """OpenMCDepcode object for unit tests""" - saltproc_input = (cwd / 'openmc_data' / 'tap_input.json').as_posix() + saltproc_input = str(cwd / 'openmc_data' / 'tap_input.json') _, _, _, object_input = read_main_input(saltproc_input) depcode = _create_depcode_object(object_input[0]) # Openmc initlialization openmc_input_path = (cwd / 'openmc_data') - openmc_iter_inputfiles = { + openmc_runtime_inputfiles = { "geometry": "geometry.xml", "settings": "settings.xml", } - for key in openmc_iter_inputfiles: - openmc_iter_inputfiles[key] = \ - (openmc_input_path / openmc_iter_inputfiles[key]).as_posix() + for key in openmc_runtime_inputfiles: + openmc_runtime_inputfiles[key] = \ + str(openmc_input_path / openmc_runtime_inputfiles[key]) - depcode.iter_inputfile = openmc_iter_inputfiles - depcode.iter_matfile = (openmc_input_path / 'materials.xml').as_posix() + depcode.runtime_inputfile = openmc_runtime_inputfiles + depcode.runtime_matfile = str(openmc_input_path / 'materials.xml') return depcode @@ -66,8 +66,8 @@ def simulation(cwd, serpent_depcode): sim_depcode=serpent_depcode, core_number=1, node_number=1, - db_path=( + db_path=str( cwd / 'serpent_data' / - 'tap_reference_db.h5').as_posix()) + 'tap_reference_db.h5')) return simulation diff --git a/tests/integration_tests/basic_reprocessing/test.py b/tests/integration_tests/basic_reprocessing/test.py index 1fe2eb367..b4a115bcd 100644 --- a/tests/integration_tests/basic_reprocessing/test.py +++ b/tests/integration_tests/basic_reprocessing/test.py @@ -8,7 +8,7 @@ def test_reprocessing_and_refill( serpent_depcode, proc_test_file, path_test_file): - mats = serpent_depcode.read_dep_comp(True) + mats = serpent_depcode.read_depleted_materials(True) waste_streams, extracted_mass = reprocess_materials(mats, proc_test_file, path_test_file) diff --git a/tests/integration_tests/database_storage/test.py b/tests/integration_tests/database_storage/test.py index 7bfc3f99e..da291bebc 100644 --- a/tests/integration_tests/database_storage/test.py +++ b/tests/integration_tests/database_storage/test.py @@ -12,7 +12,7 @@ def db_file(simulation): cwd = Path.cwd() db_file = (cwd / (simulation.sim_depcode.codename + '_test.h5')) - return db_file.resolve().as_posix() + return str(db_file.resolve()) def test_store_after_reprocessing( @@ -34,7 +34,7 @@ def test_store_after_reprocessing( """ # read data - mats = simulation.sim_depcode.read_dep_comp( + mats = simulation.sim_depcode.read_depleted_materials( True) waste_streams, extracted_mass = reprocess_materials( mats, proc_test_file, path_test_file) @@ -139,9 +139,9 @@ def test_store_mat_data(simulation): explicity in value and implicitly in type. """ # read data - mats_before = simulation.sim_depcode.read_dep_comp( + mats_before = simulation.sim_depcode.read_depleted_materials( False) - mats_after = simulation.sim_depcode.read_dep_comp( + mats_after = simulation.sim_depcode.read_depleted_materials( True) fuel_before = mats_before['fuel'] @@ -268,8 +268,12 @@ def test_store_run_init_info(simulation): """ # read data - simulation.sim_depcode.read_depcode_info() - init_info = simulation.sim_depcode.sim_info + simulation.sim_depcode.read_step_metadata() + + file = simulation.sim_depcode.template_input_file_path + file_lines = simulation.sim_depcode.read_plaintext_file(file) + simulation.sim_depcode.get_neutron_settings(file_lines) + init_info = simulation.sim_depcode.step_metadata # we want to keep the old path for other sims, but for this # test we'll want a fresh db @@ -305,6 +309,8 @@ def test_store_run_init_info(simulation): assert tinit_info[10] == init_info['MPI_tasks'] assert tinit_info[11] == init_info['memory_optimization_mode'] assert tinit_info[12] == init_info['depletion_timestep'] + assert tinit_info[13] == init_info['execution_time'] + assert tinit_info[14] == init_info['memory_usage'] except AssertionError: db.close() os.remove(db_file) @@ -340,8 +346,8 @@ def test_store_run_step_info(simulation): explicity in value and implicitly in type. """ # read data - simulation.sim_depcode.read_depcode_step_param() - step_info = simulation.sim_depcode.param + simulation.sim_depcode.read_neutronics_parameters() + step_info = simulation.sim_depcode.neutronics_parameters # we want to keep the old path for other sims, but for this # test we'll want a fresh db @@ -376,9 +382,7 @@ def test_store_run_step_info(simulation): step_info['keff_bds'].astype('float32')) assert np.array_equal(tstep_info[7], step_info['keff_eds'].astype('float32')) - assert tstep_info[8] == step_info['memory_usage'].astype('float32') - assert tstep_info[9] == step_info['power_level'].astype('float32') - assert tstep_info[10] == step_info['execution_time'].astype('float32') + assert tstep_info[8] == step_info['power_level'].astype('float32') except AssertionError: db.close() os.remove(db_file) diff --git a/tests/integration_tests/file_interface_openmc/test.py b/tests/integration_tests/file_interface_openmc/test.py index c32f8931f..c5e056967 100644 --- a/tests/integration_tests/file_interface_openmc/test.py +++ b/tests/integration_tests/file_interface_openmc/test.py @@ -22,7 +22,7 @@ def msr(scope='module'): return reactor -def test_write_depcode_input(openmc_depcode, msr): +def test_write_runtime_input(openmc_depcode, msr): # OpenMC input_materials = openmc.Materials.from_xml( openmc_depcode.template_input_file_path['materials']) @@ -35,37 +35,37 @@ def test_write_depcode_input(openmc_depcode, msr): input_surfaces = input_geometry.get_all_surfaces() input_universes = input_geometry.get_all_universes() - openmc_depcode.write_depcode_input(msr, + openmc_depcode.write_runtime_input(msr, 0, False) - # Load in the iter_ objects - iter_materials = openmc.Materials.from_xml(openmc_depcode.iter_matfile) - iter_geometry = openmc.Geometry.from_xml( - openmc_depcode.iter_inputfile['geometry'], - materials=iter_materials) - iter_settings = openmc.Settings.from_xml( - openmc_depcode.iter_inputfile['settings']) - - iter_cells = iter_geometry.get_all_cells() - iter_lattices = iter_geometry.get_all_lattices() - iter_surfaces = iter_geometry.get_all_surfaces() - iter_universes = iter_geometry.get_all_universes() + # Load in the runtime_ objects + runtime_materials = openmc.Materials.from_xml(openmc_depcode.runtime_matfile) + runtime_geometry = openmc.Geometry.from_xml( + openmc_depcode.runtime_inputfile['geometry'], + materials=runtime_materials) + runtime_settings = openmc.Settings.from_xml( + openmc_depcode.runtime_inputfile['settings']) + + runtime_cells = runtime_geometry.get_all_cells() + runtime_lattices = runtime_geometry.get_all_lattices() + runtime_surfaces = runtime_geometry.get_all_surfaces() + runtime_universes = runtime_geometry.get_all_universes() # an easier approach may just be to compare the # file contents themselves - assertion_dict = {'mat': (input_materials, iter_materials), - 'cells': (input_cells, iter_cells), - 'lattices': (input_lattices, iter_lattices), - 'surfs': (input_surfaces, iter_surfaces), - 'univs': (input_universes, iter_universes)} + assertion_dict = {'mat': (input_materials, runtime_materials), + 'cells': (input_cells, runtime_cells), + 'lattices': (input_lattices, runtime_lattices), + 'surfs': (input_surfaces, runtime_surfaces), + 'univs': (input_universes, runtime_universes)} _check_openmc_iterables_equal(assertion_dict) - assert iter_settings.inactive == openmc_depcode.inactive_cycles - assert iter_settings.batches == openmc_depcode.active_cycles + \ + assert runtime_settings.inactive == openmc_depcode.inactive_cycles + assert runtime_settings.batches == openmc_depcode.active_cycles + \ openmc_depcode.inactive_cycles - assert iter_settings.particles == openmc_depcode.npop + assert runtime_settings.particles == openmc_depcode.npop - del iter_materials, iter_geometry + del runtime_materials, runtime_geometry del input_materials, input_geometry @@ -74,10 +74,10 @@ def test_write_depletion_settings(openmc_depcode, msr): Unit test for `Depcodeopenmc_depcode.write_depletion_settings` """ openmc_depcode.write_depletion_settings(msr, 0) - with open(openmc_depcode.iter_inputfile['depletion_settings']) as f: + with open(openmc_depcode.runtime_inputfile['depletion_settings']) as f: j = json.load(f) - assert j['directory'] == Path( - openmc_depcode.iter_inputfile['settings']).parents[0].as_posix() + assert j['directory'] == str(Path( + openmc_depcode.runtime_inputfile['settings']).parents[0]) assert j['timesteps'][0] == msr.dep_step_length_cumulative[0] assert j['operator_kwargs']['chain_file'] == \ openmc_depcode.template_input_file_path['chain_file'] @@ -96,7 +96,7 @@ def test_write_saltproc_openmc_tallies(openmc_depcode): openmc_depcode.geo_files[0], mat) openmc_depcode.write_saltproc_openmc_tallies(mat, geo) del mat, geo - tallies = openmc.Tallies.from_xml(openmc_depcode.iter_inputfile['tallies']) + tallies = openmc.Tallies.from_xml(openmc_depcode.runtime_inputfile['tallies']) # now write asserts statements based on the openmc_depcode.Tallies API and # what we expect our tallies to be @@ -140,7 +140,7 @@ def test_switch_to_next_geometry(openmc_depcode): openmc_depcode.switch_to_next_geometry() switched_geometry = openmc.Geometry.from_xml( - openmc_depcode.iter_inputfile['geometry'], mat) + openmc_depcode.runtime_inputfile['geometry'], mat) switched_cells = switched_geometry.get_all_cells() switched_lattices = switched_geometry.get_all_lattices() diff --git a/tests/integration_tests/file_interface_serpent/test.py b/tests/integration_tests/file_interface_serpent/test.py index 573aedfd8..e1e0bffd0 100644 --- a/tests/integration_tests/file_interface_serpent/test.py +++ b/tests/integration_tests/file_interface_serpent/test.py @@ -22,47 +22,40 @@ def msr(scope='module'): return reactor -def test_iter_input_from_template(serpent_depcode, msr): +def test_runtime_input_from_template(serpent_depcode, msr): file = serpent_depcode.template_input_file_path file_data = serpent_depcode.read_plaintext_file(file) - # change_sim_par - file_data = serpent_depcode.change_sim_par(file_data) - assert file_data[18] == 'set pop %i %i %i\n' % ( - serpent_depcode.npop, - serpent_depcode.active_cycles, - serpent_depcode.inactive_cycles) + serpent_depcode.get_neutron_settings(file_data) # insert_path_to_geometry file_data = serpent_depcode.insert_path_to_geometry(file_data) assert file_data[5].split('/')[-1] == 'tap_geometry_base.ini"\n' - # create_iter_matfile - file_data = serpent_depcode.create_iter_matfile(file_data) + # create_runtime_matfile + file_data = serpent_depcode.create_runtime_matfile(file_data) assert file_data[0].split()[-1] == '\"' + \ - serpent_depcode.iter_matfile + '\"' - remove(serpent_depcode.iter_matfile) + serpent_depcode.runtime_matfile + '\"' + remove(serpent_depcode.runtime_matfile) - # replace_burnup_parameters + # set_power_load time = msr.dep_step_length_cumulative.copy() time.insert(0, 0.0) depsteps = np.diff(time) for idx in range(len(msr.power_levels)): - file_data = serpent_depcode.replace_burnup_parameters(file_data, - msr, - idx) + file_data = serpent_depcode.set_power_load(file_data, msr, idx) assert file_data[8].split()[4] == 'daystep' assert file_data[8].split()[2] == str("%5.9E" % msr.power_levels[idx]) assert file_data[8].split()[5] == str("%7.5E" % depsteps[idx]) -def test_write_iter_files(serpent_depcode, msr): - mats = serpent_depcode.read_dep_comp(True) +def test_write_runtime_files(serpent_depcode, msr): + mats = serpent_depcode.read_depleted_materials(True) - # write_mat_file - serpent_depcode.write_mat_file(mats, 12.0) - file = serpent_depcode.iter_matfile + # update_depletable_materials + serpent_depcode.update_depletable_materials(mats, 12.0) + file = serpent_depcode.runtime_matfile file_data = serpent_depcode.read_plaintext_file(file) assert file_data[0] == '% Material compositions (after 12.000000 days)\n' if 'fuel' in file_data[3]: @@ -74,16 +67,16 @@ def test_write_iter_files(serpent_depcode, msr): elif 'ctrlPois' in file_data[3]: assert file_data[3].split()[-1] == '1.11635E+04' assert file_data[4] == ' 1001.09c -1.21000137902945E-35\n' - remove(serpent_depcode.iter_matfile) + remove(serpent_depcode.runtime_matfile) - # write_depcode_input - serpent_depcode.write_depcode_input(msr, + # write_runtime_input + serpent_depcode.write_runtime_input(msr, 0, False) - file = serpent_depcode.iter_inputfile + file = serpent_depcode.runtime_inputfile file_data = serpent_depcode.read_plaintext_file(file) - assert file_data[0] == 'include "./serpent_iter_mat.ini"\n' + assert file_data[0] == f'include "{serpent_depcode.runtime_matfile}"\n' assert file_data[8].split()[2] == '1.250000000E+09' assert file_data[8].split()[4] == 'daystep' assert file_data[8].split()[-1] == '1.11111E+02' @@ -96,4 +89,4 @@ def test_write_iter_files(serpent_depcode, msr): file_data = serpent_depcode.read_plaintext_file(file) assert file_data[5].split('/')[-1] == '406.inp"\n' - remove(serpent_depcode.iter_inputfile) + remove(serpent_depcode.runtime_inputfile) diff --git a/tests/integration_tests/run_constant_reprocessing/tap_input.json b/tests/integration_tests/run_constant_reprocessing/tap_input.json index d28858052..5c0a45838 100644 --- a/tests/integration_tests/run_constant_reprocessing/tap_input.json +++ b/tests/integration_tests/run_constant_reprocessing/tap_input.json @@ -7,9 +7,6 @@ "codename": "serpent", "exec_path": "sss2", "template_input_file_path": "tap_template.ini", - "npop": 50, - "active_cycles": 20, - "inactive_cycles": 20, "geo_file_paths": ["tap_geometry_base.ini"] }, "simulation": { diff --git a/tests/integration_tests/run_constant_reprocessing/tap_template.ini b/tests/integration_tests/run_constant_reprocessing/tap_template.ini index 18ff4832a..52e6e5c0a 100644 --- a/tests/integration_tests/run_constant_reprocessing/tap_template.ini +++ b/tests/integration_tests/run_constant_reprocessing/tap_template.ini @@ -28,7 +28,7 @@ set nfylib "sss_jeff33.nfy" set sfylib "sss_jeff33.sfy" % --- Neutron population and criticality cycles: -set pop 15000 500 200 +set pop 50 20 20 %set gcu -1 % --- Reproducibility off (set value to 1 and define seed to set on): diff --git a/tests/integration_tests/run_constant_reprocessing/test.py b/tests/integration_tests/run_constant_reprocessing/test.py index fea774adb..1c12b7a34 100644 --- a/tests/integration_tests/run_constant_reprocessing/test.py +++ b/tests/integration_tests/run_constant_reprocessing/test.py @@ -10,7 +10,7 @@ @pytest.fixture def setup(scope='module'): - cwd = Path(__file__).parents[0].resolve().as_posix() + cwd = str(Path(__file__).parents[0].resolve()) test_db = cwd + '/test_db.h5' ref_db = cwd + '/tap_reference_db.h5' tol = 1e-9 diff --git a/tests/integration_tests/run_no_reprocessing/test.py b/tests/integration_tests/run_no_reprocessing/test.py index 20e49f49f..fb78e7c5c 100644 --- a/tests/integration_tests/run_no_reprocessing/test.py +++ b/tests/integration_tests/run_no_reprocessing/test.py @@ -13,7 +13,7 @@ @pytest.fixture def setup(): - cwd = Path(__file__).parents[0].resolve().as_posix() + cwd = str(Path(__file__).parents[0].resolve()) main_input = cwd + '/test_input.json' input_path, process_input_file, path_input_file, object_input = \ @@ -21,8 +21,8 @@ def setup(): depcode = app._create_depcode_object(object_input[0]) sss_file = cwd + '/_test' - depcode.iter_inputfile = sss_file - depcode.iter_matfile = cwd + '/_test_mat' + depcode.runtime_inputfile = sss_file + depcode.runtime_matfile = cwd + '/_test_mat' simulation = app._create_simulation_object(object_input[1], depcode, 1, 1) @@ -78,29 +78,29 @@ def runsim_no_reproc(simulation, reactor, nsteps): for dep_step in range(nsteps): print("\nStep #%i has been started" % (dep_step + 1)) if dep_step == 0: # First step - simulation.sim_depcode.write_depcode_input( + simulation.sim_depcode.write_runtime_input( reactor, dep_step, False) - simulation.sim_depcode.run_depcode( + simulation.sim_depcode.run_depletion_step( simulation.core_number, simulation.node_number) # Read general simulation data which never changes simulation.store_run_init_info() # Parse and store data for initial state (beginning of dep_step) - mats = simulation.sim_depcode.read_dep_comp( + mats = simulation.sim_depcode.read_depleted_materials( False) simulation.store_mat_data(mats, dep_step, False) # Finish of First step # Main sequence else: - simulation.sim_depcode.run_depcode( + simulation.sim_depcode.run_depletion_step( simulation.core_number, simulation.node_number) - mats = simulation.sim_depcode.read_dep_comp( + mats = simulation.sim_depcode.read_depleted_materials( True) simulation.store_mat_data(mats, dep_step, False) simulation.store_run_step_info() - simulation.sim_depcode.write_mat_file( + simulation.sim_depcode.update_depletable_materials( mats, simulation.burn_time) diff --git a/tests/integration_tests/run_no_reprocessing/test_input.ini b/tests/integration_tests/run_no_reprocessing/test_input.ini index 02527308e..a5da15836 100644 --- a/tests/integration_tests/run_no_reprocessing/test_input.ini +++ b/tests/integration_tests/run_no_reprocessing/test_input.ini @@ -13,7 +13,7 @@ set nfylib "/home/andrei2/serpent/xsdata/jeff312/sss_jeff33.nfy" set sfylib "/home/andrei2/serpent/xsdata/jeff312/sss_jeff33.sfy" % --- Neutron population and criticality cycles: -set pop 300 40 10 +set pop 100 20 5 %set gcu -1 % --- Depletion parameters % --- Options for burnup calculation: diff --git a/tests/integration_tests/run_no_reprocessing/test_input.json b/tests/integration_tests/run_no_reprocessing/test_input.json index 140304a85..ff6eb6094 100644 --- a/tests/integration_tests/run_no_reprocessing/test_input.json +++ b/tests/integration_tests/run_no_reprocessing/test_input.json @@ -7,9 +7,6 @@ "codename": "serpent", "exec_path": "sss2", "template_input_file_path": "test_input.ini", - "npop": 100, - "active_cycles": 20, - "inactive_cycles": 5, "geo_file_paths": ["../../serpent_data/tap_geometry_base.ini"] }, "simulation": { diff --git a/tests/openmc_data/tap_input.json b/tests/openmc_data/tap_input.json index 9a44db43e..689ec4347 100644 --- a/tests/openmc_data/tap_input.json +++ b/tests/openmc_data/tap_input.json @@ -11,9 +11,6 @@ "settings": "tap_settings.xml", "chain_file": "tap_chain.xml" }, - "npop": 50, - "active_cycles": 20, - "inactive_cycles": 20, "geo_file_paths": ["tap_geometry_base.xml"] }, "simulation": { diff --git a/tests/openmc_data/tap_settings.xml b/tests/openmc_data/tap_settings.xml index 92e1f520b..eb9f8920c 100644 --- a/tests/openmc_data/tap_settings.xml +++ b/tests/openmc_data/tap_settings.xml @@ -1,7 +1,7 @@ eigenvalue - 100 - 50 - 10 + 50 + 40 + 20 diff --git a/tests/serpent_data/tap_input.json b/tests/serpent_data/tap_input.json index 260d9dc9d..98ca10fd6 100644 --- a/tests/serpent_data/tap_input.json +++ b/tests/serpent_data/tap_input.json @@ -7,9 +7,6 @@ "codename": "serpent", "exec_path": "sss2", "template_input_file_path": "tap_template.ini", - "npop": 50, - "active_cycles": 20, - "inactive_cycles": 20, "geo_file_paths": ["tap_geometry_base.ini"] }, "simulation": { diff --git a/tests/serpent_data/tap_template.ini b/tests/serpent_data/tap_template.ini index b1257b90e..7d5bc15bc 100644 --- a/tests/serpent_data/tap_template.ini +++ b/tests/serpent_data/tap_template.ini @@ -16,7 +16,7 @@ set nfylib "sss_jeff33.nfy" set sfylib "sss_jeff33.sfy" % --- Neutron population and criticality cycles: -set pop 30 20 10 +set pop 50 20 20 % --- Depletion parameters % --- Options for burnup calculation: diff --git a/tests/unit_tests/test_app.py b/tests/unit_tests/test_app.py index 10771eaad..e7cac6104 100644 --- a/tests/unit_tests/test_app.py +++ b/tests/unit_tests/test_app.py @@ -13,7 +13,7 @@ def test_read_main_input(cwd, codename, ext): data_path = codename + '_data' data_path = cwd / data_path - main_input = (data_path / 'tap_input.json').as_posix() + main_input = str(data_path / 'tap_input.json') out = read_main_input(main_input) input_path, process_input_file, path_input_file, object_input = out depcode_input, simulation_input, reactor_input = object_input @@ -21,14 +21,11 @@ def test_read_main_input(cwd, codename, ext): assert input_path == data_path assert depcode_input['codename'] == codename - assert depcode_input['npop'] == 50 - assert depcode_input['active_cycles'] == 20 - assert depcode_input['inactive_cycles'] == 20 assert depcode_input['geo_file_paths'][0] == \ - (data_path / ('tap_geometry_base' + ext)).as_posix() + str(data_path / ('tap_geometry_base' + ext)) assert simulation_input['db_name'] == \ - (data_path / '../temp_data/db_saltproc.h5').resolve().as_posix() + str((data_path / '../temp_data/db_saltproc.h5').resolve()) assert simulation_input['restart_flag'] is False np.testing.assert_equal( diff --git a/tests/unit_tests/test_materialflow.py b/tests/unit_tests/test_materialflow.py index 5180857c2..dca96ff42 100644 --- a/tests/unit_tests/test_materialflow.py +++ b/tests/unit_tests/test_materialflow.py @@ -2,13 +2,13 @@ def test_get_mass(serpent_depcode): - mats = serpent_depcode.read_dep_comp(True) + mats = serpent_depcode.read_depleted_materials(True) assert mats['fuel'].get_mass() == 112683343.50000001 assert mats['ctrlPois'].get_mass() == 65563.2355 def test_scale_matflow(serpent_depcode): - mats = serpent_depcode.read_dep_comp(True) + mats = serpent_depcode.read_depleted_materials(True) scale_factor = 0.7 scaled_matflow = mats['fuel'].scale_matflow(scale_factor) assert scaled_matflow[922350000] == scale_factor * 3499538.3359278883 @@ -18,7 +18,7 @@ def test_scale_matflow(serpent_depcode): def test_copy_pymat_attrs(serpent_depcode): - mats = serpent_depcode.read_dep_comp(True) + mats = serpent_depcode.read_depleted_materials(True) target_mat = mats['fuel'] target_mat.copy_pymat_attrs(mats['ctrlPois']) assert target_mat.density == 5.873 diff --git a/tests/unit_tests/test_process.py b/tests/unit_tests/test_process.py index f9b372a5f..4cd76bebc 100644 --- a/tests/unit_tests/test_process.py +++ b/tests/unit_tests/test_process.py @@ -15,7 +15,7 @@ def process(): def test_process_material(serpent_depcode, process): - mats = serpent_depcode.read_dep_comp(True) + mats = serpent_depcode.read_depleted_materials(True) thru, waste = process.process_material(mats['fuel']) np.testing.assert_almost_equal(waste[541350000], 19.79776930513891) np.testing.assert_almost_equal(waste[541360000], 176.44741987005173) diff --git a/tests/unit_tests/test_separator.py b/tests/unit_tests/test_separator.py index 64725ecce..79bc8b4ed 100644 --- a/tests/unit_tests/test_separator.py +++ b/tests/unit_tests/test_separator.py @@ -15,7 +15,7 @@ def separator(): def test_rem_elements(serpent_depcode, separator): - mats = serpent_depcode.read_dep_comp(True) + mats = serpent_depcode.read_depleted_materials(True) thru, waste = separator.process_material(mats['fuel']) np.testing.assert_almost_equal(waste[541350000], 19.5320018359295) np.testing.assert_almost_equal(waste[541360000], 174.0787699729534) diff --git a/tests/unit_tests/test_serpent_depcode.py b/tests/unit_tests/test_serpent_depcode.py index 06ad3f919..4a5f2d244 100644 --- a/tests/unit_tests/test_serpent_depcode.py +++ b/tests/unit_tests/test_serpent_depcode.py @@ -6,84 +6,93 @@ def test_create_nuclide_name_map_zam_to_serpent(serpent_depcode): - serpent_depcode.create_nuclide_name_map_zam_to_serpent() - assert serpent_depcode.iso_map[380880] == '38088.09c' - assert serpent_depcode.iso_map[962400] == '96240.09c' - assert serpent_depcode.iso_map[952421] == '95342.09c' - assert serpent_depcode.iso_map[340831] == '340831' - assert serpent_depcode.iso_map[300732] == '300732' - assert serpent_depcode.iso_map[511262] == '511262' - assert serpent_depcode.iso_map[420931] == '420931' - assert serpent_depcode.iso_map[410911] == '410911' - - -def test_convert_nuclide_name_serpent_to_zam(serpent_depcode): - assert serpent_depcode.convert_nuclide_name_serpent_to_zam(47310) == 471101 - assert serpent_depcode.convert_nuclide_name_serpent_to_zam(95342) == 952421 - assert serpent_depcode.convert_nuclide_name_serpent_to_zam(61348) == 611481 - assert serpent_depcode.convert_nuclide_name_serpent_to_zam(52327) == 521271 - assert serpent_depcode.convert_nuclide_name_serpent_to_zam(1001) == 1001 - assert serpent_depcode.convert_nuclide_name_serpent_to_zam(1002) == 1002 - assert serpent_depcode.convert_nuclide_name_serpent_to_zam(48315) == 481151 + nuc_code_map = serpent_depcode.map_nuclide_code_zam_to_serpent() + assert nuc_code_map[380880] == '38088.09c' + assert nuc_code_map[962400] == '96240.09c' + assert nuc_code_map[952421] == '95342.09c' + assert nuc_code_map[340831] == '340831' + assert nuc_code_map[300732] == '300732' + assert nuc_code_map[511262] == '511262' + assert nuc_code_map[420931] == '420931' + assert nuc_code_map[410911] == '410911' + + +def test_convert_nuclide_code_to_zam(serpent_depcode): + assert serpent_depcode.convert_nuclide_code_to_zam(47310) == 471101 + assert serpent_depcode.convert_nuclide_code_to_zam(95342) == 952421 + assert serpent_depcode.convert_nuclide_code_to_zam(61348) == 611481 + assert serpent_depcode.convert_nuclide_code_to_zam(52327) == 521271 + assert serpent_depcode.convert_nuclide_code_to_zam(1001) == 1001 + assert serpent_depcode.convert_nuclide_code_to_zam(1002) == 1002 + assert serpent_depcode.convert_nuclide_code_to_zam(48315) == 481151 + + +def test_get_neutron_settings(serpent_depcode): + template_str = serpent_depcode.read_plaintext_file( + serpent_depcode.template_input_file_path) + serpent_depcode.get_neutron_settings(template_str) + assert serpent_depcode.npop == 50 + assert serpent_depcode.active_cycles == 20 + assert serpent_depcode.inactive_cycles == 20 def test_read_plaintext_file(serpent_depcode): template_str = serpent_depcode.read_plaintext_file( serpent_depcode.template_input_file_path) assert template_str[6] == '%therm zrh_h 900 hzr05.32t hzr06.32t\n' - assert template_str[18] == 'set pop 30 20 10\n' + assert template_str[18] == 'set pop 50 20 20\n' assert template_str[22] == 'set bumode 2\n' assert template_str[23] == 'set pcc 1\n' -def test_get_nuc_name(serpent_depcode): - assert serpent_depcode.get_nuc_name('92235.09c')[0] == 'U235' - assert serpent_depcode.get_nuc_name('38088.09c')[0] == 'Sr88' - assert serpent_depcode.get_nuc_name('95342.09c')[0] == 'Am242m1' - assert serpent_depcode.get_nuc_name('61348.03c')[0] == 'Pm148m1' - assert serpent_depcode.get_nuc_name('20060')[0] == 'He6' - assert serpent_depcode.get_nuc_name('110241')[0] == 'Na24m1' - assert serpent_depcode.get_nuc_name('170381')[0] == 'Cl38m1' - assert serpent_depcode.get_nuc_name('310741')[0] == 'Ga74m1' - assert serpent_depcode.get_nuc_name('290702')[0] == 'Cu70m2' - assert serpent_depcode.get_nuc_name('250621')[0] == 'Mn62m1' - assert serpent_depcode.get_nuc_name('300732')[0] == 'Zn73m2' - assert serpent_depcode.get_nuc_name('370981')[0] == 'Rb98m1' - assert serpent_depcode.get_nuc_name('390972')[0] == 'Y97m2' - assert serpent_depcode.get_nuc_name('491142')[0] == 'In114m2' - - -def test_read_depcode_info(serpent_depcode): - serpent_depcode.read_depcode_info() - assert serpent_depcode.sim_info['depcode_name'] == 'Serpent' - assert serpent_depcode.sim_info['depcode_version'] == '2.1.31' - assert serpent_depcode.sim_info['title'] == 'Untitled' - assert serpent_depcode.sim_info['depcode_input_filename'] == \ +def test_convert_nuclide_code_to_name(serpent_depcode): + assert serpent_depcode.convert_nuclide_code_to_name('92235.09c') == 'U235' + assert serpent_depcode.convert_nuclide_code_to_name('38088.09c') == 'Sr88' + assert serpent_depcode.convert_nuclide_code_to_name('95342.09c') == 'Am242m1' + assert serpent_depcode.convert_nuclide_code_to_name('61348.03c') == 'Pm148m1' + assert serpent_depcode.convert_nuclide_code_to_name('20060') == 'He6' + assert serpent_depcode.convert_nuclide_code_to_name('110241') == 'Na24m1' + assert serpent_depcode.convert_nuclide_code_to_name('170381') == 'Cl38m1' + assert serpent_depcode.convert_nuclide_code_to_name('310741') == 'Ga74m1' + assert serpent_depcode.convert_nuclide_code_to_name('290702') == 'Cu70m2' + assert serpent_depcode.convert_nuclide_code_to_name('250621') == 'Mn62m1' + assert serpent_depcode.convert_nuclide_code_to_name('300732') == 'Zn73m2' + assert serpent_depcode.convert_nuclide_code_to_name('370981') == 'Rb98m1' + assert serpent_depcode.convert_nuclide_code_to_name('390972') == 'Y97m2' + assert serpent_depcode.convert_nuclide_code_to_name('491142') == 'In114m2' + + +def test_read_step_metadata(serpent_depcode): + serpent_depcode.read_step_metadata() + assert serpent_depcode.step_metadata['depcode_name'] == 'Serpent' + assert serpent_depcode.step_metadata['depcode_version'] == '2.1.31' + assert serpent_depcode.step_metadata['title'] == 'Untitled' + assert serpent_depcode.step_metadata['depcode_input_filename'] == \ '/home/andrei2/Desktop/git/saltproc/develop/saltproc/data/saltproc_tap' - assert serpent_depcode.sim_info['depcode_working_dir'] == \ + assert serpent_depcode.step_metadata['depcode_working_dir'] == \ '/home/andrei2/Desktop/git/saltproc/develop/saltproc' - assert serpent_depcode.sim_info['xs_data_path'] == \ + assert serpent_depcode.step_metadata['xs_data_path'] == \ '/home/andrei2/serpent/xsdata/jeff312/sss_jeff312.xsdata' - assert serpent_depcode.sim_info['MPI_tasks'] == 1 - assert serpent_depcode.sim_info['OMP_threads'] == 4 - assert serpent_depcode.sim_info['memory_optimization_mode'] == 4 - assert serpent_depcode.sim_info['depletion_timestep'] == 3.0 + assert serpent_depcode.step_metadata['MPI_tasks'] == 1 + assert serpent_depcode.step_metadata['OMP_threads'] == 4 + assert serpent_depcode.step_metadata['memory_optimization_mode'] == 4 + assert serpent_depcode.step_metadata['depletion_timestep'] == 3.0 + assert serpent_depcode.step_metadata['memory_usage'] == [10552.84] + assert serpent_depcode.step_metadata['execution_time'] == [81.933] -def test_read_depcode_step_param(serpent_depcode): - serpent_depcode.read_depcode_step_param() - assert serpent_depcode.param['memory_usage'] == [10552.84] - assert serpent_depcode.param['execution_time'] == [81.933] - assert serpent_depcode.param['keff_bds'][0] == 1.00651e+00 - assert serpent_depcode.param['keff_eds'][0] == 1.00569e+00 - assert serpent_depcode.param['fission_mass_bds'] == [70081] - assert serpent_depcode.param['fission_mass_eds'] == [70077.1] - assert serpent_depcode.param['breeding_ratio'][1] == 5.20000e-04 +def test_read_neutronics_parameters(serpent_depcode): + serpent_depcode.read_neutronics_parameters() + assert serpent_depcode.neutronics_parameters['keff_bds'][0] == 1.00651e+00 + assert serpent_depcode.neutronics_parameters['keff_eds'][0] == 1.00569e+00 + assert serpent_depcode.neutronics_parameters['fission_mass_bds'] == [70081] + assert serpent_depcode.neutronics_parameters['fission_mass_eds'] == [70077.1] + assert serpent_depcode.neutronics_parameters['breeding_ratio'][1] == 5.20000e-04 -def test_read_dep_comp(serpent_depcode): - mats = serpent_depcode.read_dep_comp(True) +def test_read_depleted_materials(serpent_depcode): + mats = serpent_depcode.read_depleted_materials(True) assert mats['fuel']['U235'] == 3499538.3359278883 assert mats['fuel']['U238'] == 66580417.24509208 assert mats['fuel']['F19'] == 37145139.35897285 diff --git a/tests/unit_tests/test_sparger.py b/tests/unit_tests/test_sparger.py index cf0ce047f..a9269426a 100644 --- a/tests/unit_tests/test_sparger.py +++ b/tests/unit_tests/test_sparger.py @@ -15,7 +15,7 @@ def sparger(): def test_rem_elements(serpent_depcode, sparger): - mats = serpent_depcode.read_dep_comp(True) + mats = serpent_depcode.read_depleted_materials(True) thru, waste = sparger.process_material(mats['fuel']) np.testing.assert_almost_equal(waste[541350000], 8.061014535231715) np.testing.assert_almost_equal(waste[541360000], 71.8437109936129)