def translate_cm(inp_dict, names, out_dict, mode_nuclide): _nuclide_elemements = {} sections = make_csnucls() if (not mode_nuclide): for n in names: if (not n[-2:].isdigit()): _nuclide_elemements[n] = openmc.Element(n).expand(1.0, 'ao') for k, v in inp_dict.items(): print("proceed material in element {}".format(k)) mat = out_dict[k] for name, value in zip(names, v): if (value > 0): if (mode_nuclide): if (name in sections): mat.add_nuclide(name, value) else: if (name[-2:].isdigit()): mat._nuclides.append((name, value, 'ao')) else: for vv in _nuclide_elemements[name]: mat._nuclides.append((vv[0], vv[1] * value, 'ao')) #if (name[-2:].isdigit()): # mat.add_nuclide(name, value) #else: # mat.add_element(name, value) return out_dict
def translate_actinide(inp_dict, names, mode_nuclide): out_dict = {} _nuclide_elemements = {} sections = make_csnucls() if (not mode_nuclide): for n in names: if (not n[-2:].isdigit()): _nuclide_elemements[n] = openmc.Element(n).expand(1.0, 'ao') for k, v in inp_dict.items(): print("proceed material {}".format(k)) mat = openmc.Material(material_id = 100*k[0] + k[1] + 1,name=str(k)) mat.set_density('sum') for name, value in zip(names, v): if (value > 0.0): if (mode_nuclide): #mat.add_nuclide(name, value) if (name in sections): mat._nuclides.append((name, value, 'ao')) else: if (name[-2:].isdigit()): mat._nuclides.append((name, value, 'ao')) else: for vv in _nuclide_elemements[name]: mat._nuclides.append((vv[0], vv[1] * value, 'ao')) #if (name[-2:].isdigit()): # mat.add_nuclide(name, value) #else: # mat.add_element(name, value) out_dict[k] = mat return out_dict
def run(self): """Generate inputs, run problem, and plot results. """ # Create the HDF5 library if self.xsdir is not None: path = self.other_dir if self.code == 'serpent' else None create_library(self.xsdir, self.table_names, self.openmc_dir, path) # TODO: Currently the neutron libraries are still read in to OpenMC # even when doing pure photon transport, so we need to locate them and # register them with the library. path = os.getenv('OPENMC_CROSS_SECTIONS') lib = openmc.data.DataLibrary.from_xml(path) path = self.openmc_dir / 'cross_sections.xml' data_lib = openmc.data.DataLibrary.from_xml(path) for element, fraction in self.elements: element = openmc.Element(element) for nuclide, _, _ in element.expand(fraction, 'ao'): h5_file = lib.get_by_material(nuclide)['path'] data_lib.register_file(h5_file) data_lib.export_to_xml(path) # Generate input files self._make_openmc_input() if self.code == 'serpent': self._make_serpent_input() args = ['sss2', 'input'] else: self._make_mcnp_input() args = ['mcnp6'] if self.xsdir is not None: args.append(f'XSDIR={self.xsdir}') # Remove old MCNP output files for f in ('outp', 'runtpe'): try: os.remove(self.other_dir / f) except OSError: pass # Run code and capture and print output p = subprocess.Popen( args, cwd=self.other_dir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True ) while True: line = p.stdout.readline() if not line and p.poll() is not None: break print(line, end='') openmc.run(cwd=self.openmc_dir) self._plot()
def test_expand_enrichment(): """ Expand and verify enrichment of Li """ lithium = openmc.Element('Li') # Verify the enrichment by atoms ref = {'Li6': 75.0, 'Li7': 25.0} for isotope in lithium.expand(100.0, 'ao', 25.0, 'Li7', 'ao'): assert isotope[1] == approx(ref[isotope[0]]) # Verify the enrichment by weight for isotope in lithium.expand(100.0, 'wo', 25.0, 'Li7', 'wo'): assert isotope[1] == approx(ref[isotope[0]])
def add_element(self, element, percent, percent_type='ao', expand=False): """Add a natural element to the material Parameters ---------- element : openmc.Element or str Element to add percent : float Atom or weight percent percent_type : {'ao', 'wo'}, optional 'ao' for atom percent and 'wo' for weight percent. Defaults to atom percent. expand : bool, optional Whether to expand the natural element into its naturally-occurring isotopes. Defaults to False. """ if self._macroscopic is not None: msg = 'Unable to add an Element to Material ID="{0}" as a ' \ 'macroscopic data-set has already been added'.format(self._id) raise ValueError(msg) if not isinstance(element, (openmc.Element, basestring)): msg = 'Unable to add an Element to Material ID="{0}" with a ' \ 'non-Element value "{1}"'.format(self._id, element) raise ValueError(msg) if not isinstance(percent, Real): msg = 'Unable to add an Element to Material ID="{0}" with a ' \ 'non-floating point value "{1}"'.format(self._id, percent) raise ValueError(msg) if percent_type not in ['ao', 'wo']: msg = 'Unable to add an Element to Material ID="{0}" with a ' \ 'percent type "{1}"'.format(self._id, percent_type) raise ValueError(msg) # Copy this Element to separate it from same Element in other Materials if isinstance(element, openmc.Element): element = deepcopy(element) else: element = openmc.Element(element) if expand: if percent_type == 'wo': raise NotImplementedError('Expanding natural element based on ' 'weight percent is not yet supported.') for isotope, abundance in element.expand(): self._nuclides.append((isotope, percent*abundance, percent_type)) else: self._elements.append((element, percent, percent_type))
def _read_materials(self): self.n_materials = self._f['n_materials'].value # Initialize dictionary for each Material # Keys - Material keys # Values - Material objects self.materials = {} for key in self._f['materials'].keys(): if key == 'n_materials': continue material_id = int(key.lstrip('material ')) index = self._f['materials'][key]['index'].value name = self._f['materials'][key]['name'].value.decode() density = self._f['materials'][key]['atom_density'].value nuc_densities = self._f['materials'][key]['nuclide_densities'][...] nuclides = self._f['materials'][key]['nuclides'].value # Create the Material material = openmc.Material(material_id=material_id, name=name) # Read the names of the S(a,b) tables for this Material and add them if 'sab_names' in self._f['materials'][key]: sab_tables = self._f['materials'][key]['sab_names'].value for sab_table in sab_tables: name, xs = sab_table.decode().split('.') material.add_s_alpha_beta(name, xs) # Set the Material's density to atom/b-cm as used by OpenMC material.set_density(density=density, units='atom/b-cm') # Add all nuclides to the Material for fullname, density in zip(nuclides, nuc_densities): fullname = fullname.decode().strip() name, xs = fullname.split('.') if 'nat' in name: material.add_element(openmc.Element(name=name, xs=xs), percent=density, percent_type='ao') else: material.add_nuclide(openmc.Nuclide(name=name, xs=xs), percent=density, percent_type='ao') # Add the Material to the global dictionary of all Materials self.materials[index] = material
def test_expand_exceptions(): """ Test that correct exceptions are raised for invalid input """ # 1 Isotope Element with raises(ValueError): element = openmc.Element('Be') element.expand(70.0, 'ao', 4.0, 'Be9') # 3 Isotope Element with raises(ValueError): element = openmc.Element('Cr') element.expand(70.0, 'ao', 4.0, 'Cr52') # Non-present Enrichment Target with raises(ValueError): element = openmc.Element('H') element.expand(70.0, 'ao', 4.0, 'H4') # Enrichment Procedure for Uranium if not Uranium with raises(ValueError): element = openmc.Element('Li') element.expand(70.0, 'ao', 4.0) # Missing Enrichment Target with raises(ValueError): element = openmc.Element('Li') element.expand(70.0, 'ao', 4.0, enrichment_type='ao') # Invalid Enrichment Type Entry with raises(ValueError): element = openmc.Element('Li') element.expand(70.0, 'ao', 4.0, 'Li7', 'Grand Moff Tarkin') # Trying to enrich Uranium with raises(ValueError): element = openmc.Element('U') element.expand(70.0, 'ao', 4.0, 'U235', 'wo') # Trying to enrich Uranium with wrong enrichment_target with raises(ValueError): element = openmc.Element('U') element.expand(70.0, 'ao', 4.0, enrichment_type='ao')
def remove_element(self, element): """Remove a natural element from the material Parameters ---------- element : openmc.Element Element to remove """ cv.check_type('element', element, string_types + (openmc.Element, )) if isinstance(element, string_types): element = openmc.Element(element) # If the Material contains the Element, delete it for elm in self._elements: if element == elm[0]: self._elements.remove(elm)
def test_expand_no_enrichment(): """ Expand Li in natural compositions""" lithium = openmc.Element('Li') # Verify the expansion into ATOMIC fraction against natural composition for isotope in lithium.expand(100.0, 'ao'): assert isotope[1] == approx(NATURAL_ABUNDANCE[isotope[0]] * 100.0) # Verify the expansion into WEIGHT fraction against natural composition natural = { 'Li6': NATURAL_ABUNDANCE['Li6'] * atomic_mass('Li6'), 'Li7': NATURAL_ABUNDANCE['Li7'] * atomic_mass('Li7') } li_am = sum(natural.values()) for key in natural: natural[key] /= li_am for isotope in lithium.expand(100.0, 'wo'): assert isotope[1] == approx(natural[isotope[0]] * 100.0)
def add_element(self, element, percent, percent_type='ao', enrichment=None, enrichment_target=None, enrichment_type=None): """Add a natural element to the material Parameters ---------- element : str Element to add, e.g., 'Zr' or 'Zirconium' percent : float Atom or weight percent percent_type : {'ao', 'wo'}, optional 'ao' for atom percent and 'wo' for weight percent. Defaults to atom percent. enrichment : float, optional Enrichment of an enrichment_taget nuclide in percent (ao or wo). If enrichment_taget is not supplied then it is enrichment for U235 in weight percent. For example, input 4.95 for 4.95 weight percent enriched U. Default is None (natural composition). enrichment_target: str, optional Single nuclide name to enrich from a natural composition (e.g., 'O16') .. versionadded:: 0.12 enrichment_type: {'ao', 'wo'}, optional 'ao' for enrichment as atom percent and 'wo' for weight percent. Default is: 'ao' for two-isotope enrichment; 'wo' for U enrichment .. versionadded:: 0.12 Notes ----- General enrichment procedure is allowed only for elements composed of two isotopes. If `enrichment_target` is given without `enrichment` natural composition is added to the material. """ cv.check_type('nuclide', element, str) cv.check_type('percent', percent, Real) cv.check_value('percent type', percent_type, {'ao', 'wo'}) # Make sure element name is just that if not element.isalpha(): raise ValueError( "Element name should be given by the " "element's symbol or name, e.g., 'Zr', 'zirconium'") # Allow for element identifier to be given as a symbol or name if len(element) > 2: el = element.lower() element = openmc.data.ELEMENT_SYMBOL.get(el) if element is None: msg = 'Element name "{}" not recognised'.format(el) raise ValueError(msg) else: if element[0].islower(): msg = 'Element name "{}" should start with an uppercase ' \ 'letter'.format(element) raise ValueError(msg) if len(element) == 2 and element[1].isupper(): msg = 'Element name "{}" should end with a lowercase ' \ 'letter'.format(element) raise ValueError(msg) # skips the first entry of ATOMIC_SYMBOL which is n for neutron if element not in list(openmc.data.ATOMIC_SYMBOL.values())[1:]: msg = 'Element name "{}" not recognised'.format(element) raise ValueError(msg) if self._macroscopic is not None: msg = 'Unable to add an Element to Material ID="{}" as a ' \ 'macroscopic data-set has already been added'.format(self._id) raise ValueError(msg) if enrichment is not None and enrichment_target is None: if not isinstance(enrichment, Real): msg = 'Unable to add an Element to Material ID="{}" with a ' \ 'non-floating point enrichment value "{}"'\ .format(self._id, enrichment) raise ValueError(msg) elif element != 'U': msg = 'Unable to use enrichment for element {} which is not ' \ 'uranium for Material ID="{}"'.format(element, self._id) raise ValueError(msg) # Check that the enrichment is in the valid range cv.check_less_than('enrichment', enrichment, 100. / 1.008) cv.check_greater_than('enrichment', enrichment, 0., equality=True) if enrichment > 5.0: msg = 'A uranium enrichment of {} was given for Material ID='\ '"{}". OpenMC assumes the U234/U235 mass ratio is '\ 'constant at 0.008, which is only valid at low ' \ 'enrichments. Consider setting the isotopic ' \ 'composition manually for enrichments over 5%.'.\ format(enrichment, self._id) warnings.warn(msg) # Add naturally-occuring isotopes element = openmc.Element(element) for nuclide in element.expand(percent, percent_type, enrichment, enrichment_target, enrichment_type): self.add_nuclide(*nuclide)
def add_element(self, element, percent, percent_type='ao', enrichment=None): """Add a natural element to the material Parameters ---------- element : str Element to add, e.g., 'Zr' percent : float Atom or weight percent percent_type : {'ao', 'wo'}, optional 'ao' for atom percent and 'wo' for weight percent. Defaults to atom percent. enrichment : float, optional Enrichment for U235 in weight percent. For example, input 4.95 for 4.95 weight percent enriched U. Default is None (natural composition). """ cv.check_type('nuclide', element, str) cv.check_type('percent', percent, Real) cv.check_value('percent type', percent_type, {'ao', 'wo'}) if self._macroscopic is not None: msg = 'Unable to add an Element to Material ID="{}" as a ' \ 'macroscopic data-set has already been added'.format(self._id) raise ValueError(msg) if enrichment is not None: if not isinstance(enrichment, Real): msg = 'Unable to add an Element to Material ID="{}" with a ' \ 'non-floating point enrichment value "{}"'\ .format(self._id, enrichment) raise ValueError(msg) elif element != 'U': msg = 'Unable to use enrichment for element {} which is not ' \ 'uranium for Material ID="{}"'.format(element, self._id) raise ValueError(msg) # Check that the enrichment is in the valid range cv.check_less_than('enrichment', enrichment, 100. / 1.008) cv.check_greater_than('enrichment', enrichment, 0., equality=True) if enrichment > 5.0: msg = 'A uranium enrichment of {} was given for Material ID='\ '"{}". OpenMC assumes the U234/U235 mass ratio is '\ 'constant at 0.008, which is only valid at low ' \ 'enrichments. Consider setting the isotopic ' \ 'composition manually for enrichments over 5%.'.\ format(enrichment, self._id) warnings.warn(msg) # Make sure element name is just that if not element.isalpha(): raise ValueError("Element name should be given by the " "element's symbol, e.g., 'Zr'") # Add naturally-occuring isotopes element = openmc.Element(element) for nuclide in element.expand(percent, percent_type, enrichment): self.add_nuclide(*nuclide)
def add_element(self, element, percent, percent_type='ao', enrichment=None): """Add a natural element to the material Parameters ---------- element : openmc.Element or str Element to add percent : float Atom or weight percent percent_type : {'ao', 'wo'}, optional 'ao' for atom percent and 'wo' for weight percent. Defaults to atom percent. enrichment : float, optional Enrichment for U235 in weight percent. For example, input 4.95 for 4.95 weight percent enriched U. Default is None (natural composition). """ if self._macroscopic is not None: msg = 'Unable to add an Element to Material ID="{}" as a ' \ 'macroscopic data-set has already been added'.format(self._id) raise ValueError(msg) if not isinstance(element, string_types + (openmc.Element, )): msg = 'Unable to add an Element to Material ID="{}" with a ' \ 'non-Element value "{}"'.format(self._id, element) raise ValueError(msg) if not isinstance(percent, Real): msg = 'Unable to add an Element to Material ID="{}" with a ' \ 'non-floating point value "{}"'.format(self._id, percent) raise ValueError(msg) if percent_type not in ['ao', 'wo']: msg = 'Unable to add an Element to Material ID="{}" with a ' \ 'percent type "{}"'.format(self._id, percent_type) raise ValueError(msg) # Copy this Element to separate it from same Element in other Materials if isinstance(element, openmc.Element): element = deepcopy(element) else: element = openmc.Element(element) if enrichment is not None: if not isinstance(enrichment, Real): msg = 'Unable to add an Element to Material ID="{}" with a ' \ 'non-floating point enrichment value "{}"'\ .format(self._id, enrichment) raise ValueError(msg) elif element.name != 'U': msg = 'Unable to use enrichment for element {} which is not ' \ 'uranium for Material ID="{}"'.format(element.name, self._id) raise ValueError(msg) # Check that the enrichment is in the valid range cv.check_less_than('enrichment', enrichment, 100. / 1.008) cv.check_greater_than('enrichment', enrichment, 0., equality=True) if enrichment > 5.0: msg = 'A uranium enrichment of {} was given for Material ID='\ '"{}". OpenMC assumes the U234/U235 mass ratio is '\ 'constant at 0.008, which is only valid at low ' \ 'enrichments. Consider setting the isotopic ' \ 'composition manually for enrichments over 5%.'.\ format(enrichment, self._id) warnings.warn(msg) self._elements.append((element, percent, percent_type, enrichment))