Source code for onix.system

import onix.utils as utils
from . import salameche
import os

[docs]class System(object): """The system oject contains and organizes the ensemble of BUCells. When running a standalone simulation, the system object is the the object with which the user can set certain attributes and parameters for the simulation (nuclear data libraries, burnup sequence, new BUCells). In a coupled simulation, the class onix.couple.Couple_openmc fullfills that role and passes-on directives to the system object. Parameters ---------- system_id: int Number id for the system object """ def __init__(self, system_id): self._id = system_id self._bucell_dict = None self._bounding_box = None self._sequence = None self._output_summary_path = None self._reac_rank = 'off' @property def id(self): """Returns the number id of the system object. """ return self._id @property def bucell_dict(self): """Returns a dictionnary where keys are BUCell number ids and entries are corresponding BUCells objects""" return self._bucell_dict @bucell_dict.setter def bucell_dict(self, bucell_dict): self._bucell_dict = bucell_dict # Probably obsolete def add_bucell_dict(self, new_bucell_dict): # You need to make sure that there are no cells with same ids if self.bucell_dict == None: self.bucell_dict = new_bucell_dict else: old_bucell_dict = self.bucell_dict.copy() updated_bucell_dict = {**old_bucell_dict, **new_bucell_dict} self.bucell_dict = updated_bucell_dict
[docs] def add_bucell(self, new_bucell): """Adds a new BUCell to System. Parameters ---------- new_BUCell: onix.Cell """ if self.bucell_dict == None: self.bucell_dict = {new_bucell.id : new_bucell} else: # You need to make sure this id is not already taken by other cell updated_bucell_dict = self.bucell_dict.copy() updated_bucell_dict[new_bucell.id] = new_bucell self.bucell_dict = updated_bucell_dict
[docs] def get_bucell(self, name): """Returns the BUCell object with corresponding name. Parameters ---------- name: str Name of the BUCell """ result = None bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] if bucell.name == name: result = bucell if result == None: raise Cell_name_not_found('BUCell named {} has not been found in system no. {}'.format(name, self.id)) return result
[docs] def get_bucell_list(self): """Returns a list of the BUCell objects""" bucell_dict = self.bucell_dict bucell_list = utils.cell_dict_to_cell_list(bucell_dict) return bucell_list
@property def bounding_box(self): """Returns the bounding box defined by the user for the system""" return self._bounding_box # This function is only used within the code by Coupe_openmc. No need in standalone. @bounding_box.setter def bounding_box(self, bounding_box): self._bounding_box = bounding_box @property def reac_rank(self): return self._reac_rank
[docs] def reac_rank_on(self): """Calling this method will tell ONIX to produce production and destrubtion reaction rates ranking for each nuclide and print the data for each BUCells. By default ONIX does not produce reaction rates ranking as it takes a lot of memory. """ self._reac_rank = 'on'
@property def total_vol(self): """Returns the total volume of the system. The total volume of the system is the volume of all BUCells plus the volume of regions that are not depleted (moderator for instance if no BUCell is created for the moderator). In standalone mode, the total volume will simply be the addition of all BUCells' volume as all regions should be depleted. """ return self._total_vol @total_vol.setter def total_vol(self, total_vol): """Sets the total volume of the system. The total volume of the system is the volume of all BUCells plus the volume of regions that are not depleted (moderator for instance if no BUCell is created for the moderator). In standalone mode, the total volume will simply be the addition of all BUCells' volume as all regions should be depleted. Parameters ---------- total_vol: float Total volume of the system """ self._total_vol = total_vol
[docs] def get_tot_hm(self): """Returns the current total heavy metal mass contained in System (g).""" tot_hm = 0 bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] tot_hm += bucell.get_hm() return tot_hm
[docs] def get_tot_ihm(self): """Returns the total initial heavy metal (IHM) mass contained in System (g).""" tot_ihm = 0 bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] tot_ihm += bucell.ihm return tot_ihm
[docs] def set_default_decay_for_all(self): """Sets the decay library to the default one (ENDF/B-VIII.0) for all BUCells. This function will add all nuclides for which there are decay data in the library but which are not yet in the onix.Passlist object of the BUCells. This means that the depletion system will be significantly enlarged. """ bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell.set_default_decay_lib()
[docs] def set_default_decay_for_all_no_add(self): """Sets the decay library to the default one (ENDF/B-VIII.0) for all BUCells. This function will only take nuclear decay data for nuclides that are already in the onix.Passlist object of the BUCells. This enables to run simulation where the depletion system is not enlarged when adding decay data. """ bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell.set_default_decay_lib_no_add()
[docs] def set_decay_for_all(self, decay_lib_path): """Sets the decay library for all BUCells. This function will add all nuclides for which there are decay data in the library but which are not yet in the onix.Passlist object of the BUCells. This means that the depletion system will be significantly enlarged. Parameters ---------- decay_lib_path: str Path to the decay library provided by the user """ bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell.set_decay_lib(decay_lib_path)
[docs] def set_default_xs_for_all(self): """Sets the cross section library to the default one for all BUCells. The default cross section library in ONIX has been obtained by computing middle-burnup one-group cross section for a coupled simumation of a LWR fuel pin-cell. Therefore, this library is only adapted for LWR reactors. """ bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell.set_default_xs_lib()
[docs] def set_xs_for_all(self, xs_lib_path): """Sets the cross section library for all BUCells. Parameters ---------- xs_lib_path: str Path to the cross section library provided by the user """ bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell.set_xs_lib(xs_lib_path)
[docs] def set_default_fy_for_all(self): """Sets the fission yield library to the default one (ENDF/B-VIII.0) for all BUCells. This function will add all fission products for which there are fission yield data in the library but which are not yet in the onix.Passlist object of the BUCells. This means that the depletion system will be significantly enlarged. """ bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell.set_default_fy_lib()
[docs] def set_default_fy_for_all_no_add(self): """Sets the fission yield library to the default one (ENDF/B-VIII.0) for all BUCells. This function will only take fission yield data for fission products that are already in the onix.Passlist object of the BUCells. This enables to run simulation where the depletion system is not enlarged when adding fission yield data. """ bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell.set_default_fy_lib_no_add()
[docs] def set_fy_for_all(self, fy_lib_path, complete): """Sets the fission yield library for all BUCells. Setting the *complete* parameter to True allows ONIX to complement the data of the provided library with additional data found in ENDF/B-VIII.0. This function will add all fission products for which there are fission yield data in the library but which are not yet in the onix.Passlist object of the BUCells. This means that the depletion system will be significantly enlarged. Parameters ---------- decay_lib_path: str Path to the decay library provided by the user complete: bool Indicates to ONIX whether or not to complement the provided library with additional fission yields from ENDF:B-VIII.0 library. """ bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell.set_fy_lib(fy_lib_path, complete)
@property def sequence(self): """Returns the sequence object associated with System""" return self._sequence @sequence.setter def sequence(self, sequence): self._sequence = sequence # In addition to set sequence for each cells # This method also converts the average power_dens sequence to tot_power sequence if constant_power mode # It seems the mode parameters is not used. Will have to investigate if its obsolete
[docs] def set_sequence(self, sequence, mode = 'stand alone'): """Sets a sequence object to the System and distributes unique copies of the sequence object to each BUCells. Parameters ---------- sequence: onix.Sequence ONIX sequence object defined by the user """ # Create tot_pow, av_pow_dens sequence # set time seq or bu seq depending on input sequence._initial_system_conversion(self) self.sequence = sequence bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] if mode == 'stand alone': bucell._set_sequence(sequence) elif mode == 'couple': bucell._set_sequence(sequence, mode = 'couple')
@property def bu_sec_conv_factor(self): return self._bu_sec_conv_factor def _set_bu_sec_conv_factor(self): total_vol = self.total_vol # Since this get_tot_hm is called before burn, hm is ihm total_ihm = self.get_tot_hm() if total_ihm == 0: self._bu_sec_conv_factor = 0 else: self._bu_sec_conv_factor = utils.get_bu_sec_conv_factor(total_vol, total_ihm) def zam_order_passlist(self): bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell.passlist.zam_order_passport_list_2() # Burn the system according to the sequence set to system # def burn_loop(self): # sequence = self.sequence # steps_number = sequence.steps_number # for s in range(steps_number): def _print_current_allreacs_rank(self): bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell._print_current_allreacs_rank() def _print_summary_allreacs_rank(self): summary_path = self._output_summary_path bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell._print_summary_allreacs_rank(summary_path) def _print_summary_dens(self): summary_path = self._output_summary_path bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell._print_summary_dens(summary_path) def _print_summary_activity(self): summary_path = self._output_summary_path bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell._print_summary_activity(summary_path) def _print_summary_subdens(self): summary_path = self._output_summary_path bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell._print_summary_subdens(summary_path) def _print_summary_xs(self): summary_path = self._output_summary_path bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell._print_summary_xs(summary_path) def _print_summary_isomeric_branching_ratio(self): summary_path = self._output_summary_path bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell._print_summary_isomeric_branching_ratio(summary_path) def _print_summary_flux_spectrum(self, mg_energy_bin): summary_path = self._output_summary_path bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell._print_summary_flux_spectrum(summary_path, mg_energy_bin) def _print_summary_kinf(self): summary_path = self._output_summary_path file_name = summary_path + '/kinf' write_file = open(file_name, 'w') sequence = self.sequence time_seq = sequence.time_seq system_bu_seq = sequence.system_bu_seq kinf_seq = sequence.kinf_seq steps_number = sequence.macrosteps_number txt = '' txt += '{:<12}'.format('TIME') txt += '{:<13.5E}'.format(time_seq[0]/(24*3600))# in days for s in range(steps_number): txt += '{:<13.5E}'.format(time_seq[s+1]/(24*3600))# in days txt += '\n' txt += '{:<12}'.format('SYSTEM-BU') txt += '{:<13.5E}'.format(system_bu_seq[0]) for s in range(steps_number): txt += '{:<13.5E}'.format(system_bu_seq[s+1]) txt += '\n\n' txt += '{:<12}'.format('K-INF') txt += '{:<13.5E}'.format(kinf_seq[0].n) for s in range(steps_number): txt += '{:<13.5E}'.format(kinf_seq[s+1].n) txt += '\n' txt += '{:<12}'.format('UNCERTAINTY') txt += '{:<13.5E}'.format(kinf_seq[0].s) for s in range(steps_number): txt += '{:<13.5E}'.format(kinf_seq[s+1].s) write_file.write(txt) write_file.close() def _print_summary_param(self): summary_path = self._output_summary_path file_name = summary_path + '/system_parameters' write_file = open(file_name, 'w') txt = 'System Volume [cm³] = {}\n'.format(self.total_vol) txt += 'System IHM [g] = {}\n\n'.format(self.get_tot_ihm()) for bucell_id in self.bucell_dict: bucell = self.bucell_dict[bucell_id] txt += 'BuCell {}\n'.format(bucell.name) txt += 'Volume [cm³] = {}\n'.format(bucell.vol) txt += 'IHM [g] = {}\n\n'.format(bucell.ihm) write_file.write(txt) write_file.close() def _copy_cell_folders_to_step_folder(self, s): bucell_dict = self.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell._copy_cell_folders_to_step_folder(s) def _gen_output_summary_folder(self): name = 'output_summary' self._output_summary_path = utils.get_folder_path(name) utils.gen_folder(name)
[docs] def burn(self): """Launches a standalone simulation.""" sequence = self.sequence steps_number = sequence.steps_number for s in range(steps_number): print ('\n\n\n\n STEP {}\n\n\n\n'.format(s)) sequence._gen_step_folder(s) salameche.burn_step(self, s) system._gen_output_summary_folder() system._print_summary_allreacs_rank() system._print_summary_dens()
def print_bucell_nuclides(self, bucell, step, nuclide_list): bucell = self.get_bucell(bucell) file_path = os.getcwd() + '/{}_step{}_nucl_print'.format(bucell.name, step) file = open(file_path, 'w') passport_list = bucell.passlist.passport_list nucl_name_density = [] txt = '' for nucl in passport_list: nucl_name = utils.onix_name_to_openmc_name(nucl.name) if nucl_name in nuclide_list: txt += '{:<10}'.format(nucl_name) txt += '{:<13.5E}'.format(nucl.dens_seq[step]) txt += '\n' file.write(txt) file.close()
class Cell_name_not_found(Exception): pass