def hexfunction(pitch, pack_frac): settings = openmc.Settings() # Set high tolerance to allow use of lower temperature xs settings.temperature['tolerance'] = 1000 settings.temperature['method'] = 'nearest' settings.temperature['multipole'] = True settings.cutoff = {'energy': 1e-8} #energy cutoff in eV ############################# ### MATERIALS ### ############################# mat_list = [] enrichment = 20.0 uo2 = openmc.Material(1, "uo2") uo2.add_element('U', 1.0, enrichment=enrichment) uo2.add_element('O', 2.0) uo2.set_density('g/cm3', 10.97) uo2.temperature = 900 #kelvin mat_list.append(uo2) graphite = openmc.Material(2, "graphite") graphite.set_density('g/cm3', 1.1995) graphite.add_element('C', 1.0) graphite.add_s_alpha_beta('c_Graphite') graphite.temperature = 900 #kelvin mat_list.append(graphite) # sodium = openmc.Material(3, "sodium") sodium = openmc.Material() sodium.set_density('g/cm3', 0.8017) # 900 K sodium.add_element('Na', 1.0) # sodium.add_s_alpha_beta('c_Graphite') sodium.temperature = 900 #kelvin mat_list.append(sodium) # naoh = openmc.Material(6, "naoh") naoh = openmc.Material() naoh.set_density('g/cm3', 1.5) # 900 K naoh.add_element('Na', 1.0) naoh.add_element('O', 1.0) naoh.add_element('H', 1.0) # sodium.add_s_alpha_beta('c_Graphite') naoh.temperature = 900 #kelvin mat_list.append(naoh) # TRISO Materials fuel = openmc.Material(name='Fuel') fuel.set_density('g/cm3', 10.5) # fuel.add_nuclide('U235', 4.6716e-02) fuel.add_nuclide('U235', 0.0667372) # fuel.add_nuclide('U238', 2.8697e-01) fuel.add_nuclide('U238', 0.2669488) fuel.add_nuclide('O16', 5.0000e-01) fuel.add_element('C', 1.6667e-01) mat_list.append(fuel) buff = openmc.Material(name='Buffer') buff.set_density('g/cm3', 1.0) buff.add_element('C', 1.0) buff.add_s_alpha_beta('c_Graphite') mat_list.append(buff) PyC1 = openmc.Material(name='PyC1') PyC1.set_density('g/cm3', 1.9) PyC1.add_element('C', 1.0) PyC1.add_s_alpha_beta('c_Graphite') mat_list.append(PyC1) PyC2 = openmc.Material(name='PyC2') PyC2.set_density('g/cm3', 1.87) PyC2.add_element('C', 1.0) PyC2.add_s_alpha_beta('c_Graphite') mat_list.append(PyC2) SiC = openmc.Material(name='SiC') SiC.set_density('g/cm3', 3.2) SiC.add_element('C', 0.5) SiC.add_element('Si', 0.5) mat_list.append(SiC) fuel_temp = 900 homogeneous_fuel = build_fuel_material(fuel_temp, pack_frac) mat_list.append(homogeneous_fuel) mats = openmc.Materials(mat_list) mats.export_to_xml() ############################# ### GEOMETRY ### ############################# pitch = 17.4 fuel_bottom = -pitch / 2 fuel_top = pitch / 2 coolant_r = 4 # fuel_r = (pitch/2 - coolant_r)/2 fuel_r = (pitch / (3**(1 / 2)) - coolant_r) / 2 hex_universe = openmc.Universe() top = openmc.ZPlane(z0=fuel_top, boundary_type='reflective') bottom = openmc.ZPlane(z0=fuel_bottom, boundary_type='reflective') surf_fuel = openmc.ZCylinder(r=fuel_r) # Make TRISOS to be filled in fuel cylinders by chopping up # fuel cylinder into segments n_cyls = 40 fuel_segment_heights = np.linspace(fuel_bottom, fuel_top, n_cyls) segment_height = fuel_segment_heights[1] - fuel_segment_heights[0] fuel_planes = [bottom] fuel_cells = [] for i, height in enumerate(fuel_segment_heights[1:-1]): this_plane = openmc.ZPlane(z0=height) fuel_planes.append(this_plane) this_cell = openmc.Cell() this_cell.region = +fuel_planes[i] & -fuel_planes[i + 1] & -surf_fuel fuel_cells.append(copy.deepcopy(this_cell)) # last cell fuel_planes.append(top) this_cell = openmc.Cell() this_cell.region = +fuel_planes[-2] & -fuel_planes[-1] & -surf_fuel fuel_cells.append(copy.deepcopy(this_cell)) # Make fuel cylinder fuel_cyl_top = openmc.ZPlane(z0=segment_height / 2) fuel_cyl_bottom = openmc.ZPlane(z0=-segment_height / 2) fuel_triso_region = -surf_fuel & +fuel_cyl_bottom & -fuel_cyl_top outer_radius = 425. * 1e-4 # openmc.model.triso._Cylinder.from_region(fuel_region, outer_radius) spheres = [openmc.Sphere(r=r * 1e-4) for r in [215., 315., 350., 385.]] cells = [ openmc.Cell(fill=fuel, region=-spheres[0]), openmc.Cell(fill=buff, region=+spheres[0] & -spheres[1]), openmc.Cell(fill=PyC1, region=+spheres[1] & -spheres[2]), openmc.Cell(fill=SiC, region=+spheres[2] & -spheres[3]), openmc.Cell(fill=PyC2, region=+spheres[3]) ] triso_univ = openmc.Universe(cells=cells) outer_radius = 425. * 1e-4 centers = openmc.model.pack_spheres(radius=outer_radius, region=fuel_triso_region, pf=pack_frac) trisos = [openmc.model.TRISO(outer_radius, triso_univ, c) for c in centers] outside_trisos = openmc.Intersection(~t.region for t in trisos) # background_region = outside_trisos & +fuel_cyl_bottom & \ # -fuel_cyl_top & -surf_fuel background_region = outside_trisos background_cell = openmc.Cell(fill=graphite, region=background_region) fuel_triso_univ = openmc.Universe() fuel_triso_univ.add_cell(background_cell) for idx, triso in enumerate(trisos): fuel_triso_univ.add_cell(triso) # Fill in fuel cells with triso cells and translate to location for i, cell in enumerate(fuel_cells): cell_height = segment_height * (i + 1 / 2) + fuel_bottom cell.translation = [0, 0, cell_height] cell.fill = fuel_triso_univ fuel_cell_univ = openmc.Universe(cells=fuel_cells) # For testing solid fuel # test_region = +bottom & -top & -surf_fuel # fuel_cell = openmc.Cell(region=test_region, fill=fuel) # fuel_cell_univ = openmc.Universe(cells=[fuel_cell]) coolant_cyl = openmc.ZCylinder(r=coolant_r) coolant_region = -coolant_cyl coolant_cell = openmc.Cell() coolant_cell.fill = naoh coolant_cell.region = coolant_region hex_universe.add_cell(coolant_cell) hex_prism = openmc.get_hexagonal_prism(edge_length=pitch / (3**1 / 2), boundary_type='reflective') graphite_region = hex_prism & +coolant_cyl & -top & +bottom graphite_cell = openmc.Cell() graphite_cell.fill = graphite graphite_cell.region = graphite_region hex_universe.add_cell(graphite_cell) fuel_cells = [] root3 = 3**(1 / 2) half_to_vertex = pitch / root3 / 2 half_to_edge = pitch / 4 # fuel_id = 100 offset_angle = 30 n_pins = 6 for i in range(n_pins): theta = (offset_angle + i / n_pins * 360) * pi / 180 r = coolant_r + fuel_r + 0.01 x = r * np.cos(theta) y = r * np.sin(theta) fuel_cyl_bound = openmc.ZCylinder(x0=x, y0=y, r=fuel_r) graphite_cell.region &= +fuel_cyl_bound fuel_cell = openmc.Cell() fuel_cell.fill = copy.deepcopy(fuel_cell_univ) fuel_cell.translation = [x, y, 0] fuel_cell.region = -fuel_cyl_bound & -top & +bottom # fuel_cell.id = fuel_id # fuel_id += 1 fuel_cells.append(fuel_cell) hex_universe.add_cell(fuel_cell) geom = openmc.Geometry(hex_universe) # geom = openmc.Geometry(fuel_cell_univ) geom.export_to_xml() ##################################### ### SOURCE/BATCHES ### ##################################### point = openmc.stats.Point((0, 0, 0)) src = openmc.Source(space=point) settings.source = src settings.batches = 50 settings.inactive = 10 settings.particles = 200 settings.export_to_xml() ############################# ### TALLIES ### ############################# # Instantiate an empty Tallies object tallies_file = openmc.Tallies() # K-Eigenvalue (infinity) tallies fiss_rate = openmc.Tally(name='fiss. rate') fiss_rate.scores = ['nu-fission'] tallies_file.append(fiss_rate) abs_rate = openmc.Tally(name='abs. rate') abs_rate.scores = ['absorption'] tallies_file.append(abs_rate) # Resonance Escape Probability tallies therm_abs_rate = openmc.Tally(name='therm. abs. rate') therm_abs_rate.scores = ['absorption'] therm_abs_rate.filters = [openmc.EnergyFilter([0., 0.625])] tallies_file.append(therm_abs_rate) # Thermal Flux Utilization tallies # fuel_therm_abs_rate = openmc.Tally(name='fuel therm. abs. rate') # fuel_therm_abs_rate.scores = ['absorption'] # fuel_therm_abs_rate.filters = [openmc.EnergyFilter([0., 0.625]), # openmc.CellFilter([fuel_cell])] # tallies_file.append(fuel_therm_abs_rate) # Fast Fission Factor tallies therm_fiss_rate = openmc.Tally(name='therm. fiss. rate') therm_fiss_rate.scores = ['nu-fission'] therm_fiss_rate.filters = [openmc.EnergyFilter([0., 0.625])] tallies_file.append(therm_fiss_rate) tallies_file.export_to_xml() ############################# ### PLOTTING ### ############################# zs = np.linspace(0, 1, 2) plots = [] for z in zs: p = openmc.Plot() p.filename = 'pinplot' + str(z) p.width = (1.4 * pitch, 1.4 * pitch) p.pixels = (2000, 2000) p.color_by = 'material' p.origin = [0, 0, z] # p.color_by = 'cell' # p.colors = {homogeneous_fuel: 'yellow', naoh: 'grey', graphite: 'black'} p.colors = {fuel: 'yellow', naoh: 'grey', graphite: 'black'} plots.append(copy.deepcopy(p)) plots = openmc.Plots(plots) plots.export_to_xml() # openmc.plot_geometry(output = False) openmc.plot_geometry() # pngstring = 'pinplot{}.png'.format(str(pitch)) # subprocess.call(['convert','pinplot.ppm',pngstring]) # subprocess.call(['mv',pngstring,'figures/'+pngstring]) ############################# ### EXECUTION ### ############################# # openmc.run(output=False) openmc.run() sp = openmc.StatePoint('statepoint.{}.h5'.format(settings.batches)) # Collect all the tallies fiss_rate = sp.get_tally(name='fiss. rate') fiss_rate_df = fiss_rate.get_pandas_dataframe() abs_rate = sp.get_tally(name='abs. rate') abs_rate_df = abs_rate.get_pandas_dataframe() therm_abs_rate = sp.get_tally(name='therm. abs. rate') therm_abs_rate_df = therm_abs_rate.get_pandas_dataframe() fuel_therm_abs_rate = sp.get_tally(name='fuel therm. abs. rate') fuel_therm_abs_rate_df = fuel_therm_abs_rate.get_pandas_dataframe() therm_fiss_rate = sp.get_tally(name='therm. fiss. rate') therm_fiss_rate_df = therm_fiss_rate.get_pandas_dataframe() # Compute k-infinity kinf = fiss_rate / abs_rate kinf_df = kinf.get_pandas_dataframe() # Compute resonance escape probability res_esc = (therm_abs_rate) / (abs_rate) res_esc_df = res_esc.get_pandas_dataframe() # Compute fast fission factor fast_fiss = fiss_rate / therm_fiss_rate fast_fiss_df = fast_fiss.get_pandas_dataframe() # Compute thermal flux utilization therm_util = fuel_therm_abs_rate / therm_abs_rate therm_util_df = therm_util.get_pandas_dataframe() # Compute neutrons produced per absorption eta = therm_fiss_rate / fuel_therm_abs_rate eta_df = eta.get_pandas_dataframe() columns = [ 'pitch', 'enrichment', 'kinf mean', 'kinf sd', 'res_esc mean', 'res_esc sd', 'fast_fiss mean', 'fast_fiss sd', 'therm_util mean', 'therm_util sd', 'eta mean', 'eta sd' ] data = [[ pitch, enrichment, kinf_df['mean'][0], kinf_df['std. dev.'][0], res_esc_df['mean'][0], res_esc_df['std. dev.'][0], fast_fiss_df['mean'][0], fast_fiss_df['std. dev.'][0], therm_util_df['mean'][0], therm_util_df['std. dev.'][0], eta_df['mean'][0], eta_df['std. dev.'][0] ]] all_tallies = pd.DataFrame(data, columns=columns) return all_tallies
def model(): model = openmc.Model() # materials (M4 steel alloy) m4 = openmc.Material() m4.set_density('g/cc', 2.3) m4.add_nuclide('H1', 0.168018676) m4.add_nuclide("H2", 1.93244e-05) m4.add_nuclide("O16", 0.561814465) m4.add_nuclide("O17", 0.00021401) m4.add_nuclide("Na23", 0.021365) m4.add_nuclide("Al27", 0.021343) m4.add_nuclide("Si28", 0.187439342) m4.add_nuclide("Si29", 0.009517714) m4.add_nuclide("Si30", 0.006273944) m4.add_nuclide("Ca40", 0.018026179) m4.add_nuclide("Ca42", 0.00012031) m4.add_nuclide("Ca43", 2.51033e-05) m4.add_nuclide("Ca44", 0.000387892) m4.add_nuclide("Ca46", 7.438e-07) m4.add_nuclide("Ca48", 3.47727e-05) m4.add_nuclide("Fe54", 0.000248179) m4.add_nuclide("Fe56", 0.003895875) m4.add_nuclide("Fe57", 8.99727e-05) m4.add_nuclide("Fe58", 1.19737e-05) s0 = openmc.Sphere(r=240) s1 = openmc.Sphere(r=250, boundary_type='vacuum') c0 = openmc.Cell(fill=m4, region=-s0) c1 = openmc.Cell(region=+s0 & -s1) model.geometry = openmc.Geometry([c0, c1]) # settings settings = model.settings settings.run_mode = 'fixed source' settings.particles = 200 settings.batches = 2 settings.max_splits = 200 settings.photon_transport = True space = Point((0.001, 0.001, 0.001)) energy = Discrete([14E6], [1.0]) settings.source = openmc.Source(space=space, energy=energy) # tally mesh = openmc.RegularMesh() mesh.lower_left = (-240, -240, -240) mesh.upper_right = (240, 240, 240) mesh.dimension = (5, 10, 15) mesh_filter = openmc.MeshFilter(mesh) e_bnds = [0.0, 0.5, 2E7] energy_filter = openmc.EnergyFilter(e_bnds) particle_filter = openmc.ParticleFilter(['neutron', 'photon']) tally = openmc.Tally() tally.filters = [mesh_filter, energy_filter, particle_filter] tally.scores = ['flux'] model.tallies.append(tally) # weight windows # load pre-generated weight windows # (created using the same tally as above) ww_n_lower_bnds = np.loadtxt('ww_n.txt') ww_p_lower_bnds = np.loadtxt('ww_p.txt') # create a mesh matching the one used # to generate the weight windows ww_mesh = openmc.RegularMesh() ww_mesh.lower_left = (-240, -240, -240) ww_mesh.upper_right = (240, 240, 240) ww_mesh.dimension = (5, 6, 7) ww_n = openmc.WeightWindows(ww_mesh, ww_n_lower_bnds, None, 10.0, e_bnds, max_lower_bound_ratio=1.5) ww_p = openmc.WeightWindows(ww_mesh, ww_p_lower_bnds, None, 10.0, e_bnds, max_lower_bound_ratio=1.5) model.settings.weight_windows = [ww_n, ww_p] return model
# Create a DT point source source = openmc.Source() source.space = openmc.stats.Point((150, 0, 0)) source.angle = openmc.stats.Isotropic() source.energy = openmc.stats.Discrete([14e6], [1]) sett.source = source sett.photon_transport = True # This line is required to switch on photons tracking # setup the tallies tallies = openmc.Tallies() photon_particle_filter = openmc.ParticleFilter(['photon']) # This line adds a particle filter for photons neutron_particle_filter = openmc.ParticleFilter(['neutron']) cell_filter = openmc.CellFilter(breeder_blanket_cell) energy_bins = openmc.mgxs.GROUP_STRUCTURES['VITAMIN-J-175'] energy_filter = openmc.EnergyFilter(energy_bins) spectra_tally = openmc.Tally(name='breeder_blanket_neutron_spectra') spectra_tally.filters = [cell_filter, neutron_particle_filter, energy_filter] spectra_tally.scores = ['flux'] tallies.append(spectra_tally) spectra_tally = openmc.Tally(name='breeder_blanket_photon_spectra') spectra_tally.filters = [cell_filter, photon_particle_filter, energy_filter] spectra_tally.scores = ['flux'] tallies.append(spectra_tally) # Run OpenMC! model = openmc.model.Model(geom, mats, sett, tallies) sp_filename = model.run()
def make_materials_geometry_tallies(v): enrichment_fraction, thickness = v inner_radius = 500 breeder_material_name = 'Li' temperature_in_C = 500 print('simulating enrichment,', enrichment_fraction, 'thickness ', thickness) # MATERIALS from library of materials in neutronics_material_maker package breeder_material = Material( material_name=breeder_material_name, enrichment_fraction=enrichment_fraction, temperature_in_C=temperature_in_C).neutronics_material eurofer = Material(material_name='eurofer').neutronics_material mats = openmc.Materials([breeder_material, eurofer]) # GEOMETRY breeder_blanket_inner_surface = openmc.Sphere(r=inner_radius) breeder_blanket_outer_surface = openmc.Sphere(r=inner_radius + thickness) vessel_inner_surface = openmc.Sphere(r=inner_radius + thickness + 10) vessel_outer_surface = openmc.Sphere(r=inner_radius + thickness + 20, boundary_type='vacuum') breeder_blanket_region = -breeder_blanket_outer_surface & +breeder_blanket_inner_surface breeder_blanket_cell = openmc.Cell(region=breeder_blanket_region) breeder_blanket_cell.fill = breeder_material breeder_blanket_cell.name = 'breeder_blanket' inner_void_region = -breeder_blanket_inner_surface inner_void_cell = openmc.Cell(region=inner_void_region) inner_void_cell.name = 'inner_void' vessel_region = +vessel_inner_surface & -vessel_outer_surface vessel_cell = openmc.Cell(region=vessel_region) vessel_cell.name = 'vessel' vessel_cell.fill = eurofer blanket_vessel_gap_region = -vessel_inner_surface & +breeder_blanket_outer_surface blanket_vessel_gap_cell = openmc.Cell(region=blanket_vessel_gap_region) blanket_vessel_gap_cell.name = 'blanket_vessel_gap' universe = openmc.Universe(cells=[ inner_void_cell, breeder_blanket_cell, blanket_vessel_gap_cell, vessel_cell ]) geom = openmc.Geometry(universe) # SIMULATION SETTINGS sett = openmc.Settings() # batches = 3 # this is parsed as an argument sett.batches = batches sett.inactive = 0 sett.particles = 500 sett.run_mode = 'fixed source' source = openmc.Source() source.space = openmc.stats.Point((0, 0, 0)) source.angle = openmc.stats.Isotropic() source.energy = openmc.stats.Muir( e0=14080000.0, m_rat=5.0, kt=20000.0 ) # neutron energy = 14.08MeV, AMU for D + T = 5, temperature is 20KeV sett.source = source # TALLIES tallies = openmc.Tallies() # define filters cell_filter_breeder = openmc.CellFilter(breeder_blanket_cell) cell_filter_vessel = openmc.CellFilter(vessel_cell) particle_filter = openmc.ParticleFilter([1]) # 1 is neutron, 2 is photon surface_filter_rear_blanket = openmc.SurfaceFilter( breeder_blanket_outer_surface) surface_filter_rear_vessel = openmc.SurfaceFilter(vessel_outer_surface) energy_bins = openmc.mgxs.GROUP_STRUCTURES['VITAMIN-J-175'] energy_filter = openmc.EnergyFilter(energy_bins) tally = openmc.Tally(name='TBR') tally.filters = [cell_filter_breeder, particle_filter] tally.scores = [ '(n,Xt)' ] # MT 205 is the (n,Xt) reaction where X is a wildcard, if MT 105 or (n,t) then some tritium production will be missed, for example (n,nt) which happens in Li7 would be missed tallies.append(tally) # RUN OPENMC model = openmc.model.Model(geom, mats, sett, tallies) model.run() sp = openmc.StatePoint('statepoint.' + str(batches) + '.h5') json_output = { 'enrichment_fraction': enrichment_fraction, 'inner_radius': inner_radius, 'thickness': thickness, 'breeder_material_name': breeder_material_name, 'temperature_in_C': temperature_in_C } tally = sp.get_tally(name='TBR') df = tally.get_pandas_dataframe() json_output['TBR'] = df['mean'].sum() json_output['TBR_std_dev'] = df['std. dev.'].sum() return json_output
# Define tallies # Create a mesh that will be used for tallying mesh = openmc.RegularMesh() mesh.dimension = (100, 100) mesh.lower_left = (-pitch / 2, -pitch / 2) mesh.upper_right = (pitch / 2, pitch / 2) # Create a mesh filter that can be used in a tally mesh_filter = openmc.MeshFilter(mesh) # Now use the mesh filter in a tally and indicate what scores are desired mesh_tally = openmc.Tally(name="Mesh tally") mesh_tally.filters = [mesh_filter] mesh_tally.scores = ['flux', 'fission', 'nu-fission'] # Let's also create a tally to get the flux energy spectrum. We start by # creating an energy filter e_min, e_max = 1e-5, 20.0e6 groups = 500 energies = np.logspace(log10(e_min), log10(e_max), groups + 1) energy_filter = openmc.EnergyFilter(energies) spectrum_tally = openmc.Tally(name="Flux spectrum") spectrum_tally.filters = [energy_filter] spectrum_tally.scores = ['flux'] # Instantiate a Tallies collection and export to XML tallies = openmc.Tallies([mesh_tally, spectrum_tally]) tallies.export_to_xml()
bounds = [-0.63, -0.63, -1, 0.63, 0.63, 1] uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:]) settings_file.source = openmc.source.Source(space=uniform_dist) settings_file.export_to_xml() ############################################################################### # Exporting to OpenMC tallies.xml file ############################################################################### # Instantiate a tally mesh mesh = openmc.Mesh(mesh_id=1) mesh.type = 'regular' mesh.dimension = [100, 100, 1] mesh.lower_left = [-0.63, -0.63, -1.e50] mesh.upper_right = [0.63, 0.63, 1.e50] # Instantiate some tally Filters energy_filter = openmc.EnergyFilter([1e-5, 0.0635, 10.0, 1.0e2, 1.0e3, 0.5e6, 1.0e6, 20.0e6]) mesh_filter = openmc.MeshFilter(mesh) # Instantiate the Tally tally = openmc.Tally(tally_id=1, name='tally 1') tally.filters = [energy_filter, mesh_filter] tally.scores = ['flux', 'fission', 'nu-fission'] # Instantiate a Tallies collection, register all Tallies, and export to XML tallies_file = openmc.Tallies([tally]) tallies_file.export_to_xml()
def make_geometry_tallies(batches, nps, inner_radius, thickness): first_wall_inner_surface = openmc.Sphere(r=inner_radius) first_wall_outer_surface = openmc.Sphere(r=inner_radius + thickness, boundary_type='vacuum') first_wall = +first_wall_inner_surface & -first_wall_outer_surface first_wall = openmc.Cell(region=first_wall) first_wall.fill = eurofer inner_vac_cell = -first_wall_inner_surface inner_vac_cell = openmc.Cell(region=inner_vac_cell) universe = openmc.Universe(cells=[first_wall, inner_vac_cell]) geom = openmc.Geometry(universe) geom.export_to_xml('geometry') vox_plot = openmc.Plot() vox_plot.type = 'voxel' vox_plot.width = (15, 15, 15) vox_plot.pixels = (200, 200, 200) vox_plot.filename = 'plot_3d' vox_plot.color_by = 'material' vox_plot.colors = {eurofer: 'blue'} plots = openmc.Plots([vox_plot]) plots.export_to_xml() openmc.plot_geometry() os.system('openmc-voxel-to-vtk plot_3d.h5 -o plot_3d.vti') os.system('paraview plot_3d.vti') sett = openmc.Settings() sett.batches = batches sett.inactive = 0 sett.particles = nps sett.run_mode = 'fixed source' source = openmc.Source() source.space = openmc.stats.Point((0, 0, 0)) source.angle = openmc.stats.Isotropic() source.energy = openmc.stats.Discrete([14.08e6], [1]) #source.energy = openmc.stats.Muir(e0=14080000.0, m_rat=5.0, kt=20000.0) sett.source = source sett.export_to_xml('settings.xml') #tallies particle_filter = openmc.ParticleFilter([1]) surface_filter_front = openmc.SurfaceFilter(first_wall_inner_surface) surface_filter_rear = openmc.SurfaceFilter(first_wall_outer_surface) bins = openmc.mgxs.GROUP_STRUCTURES['VITAMIN-J-175'] #think will need to change this energy_filter = openmc.EnergyFilter(bins) tallies = openmc.Tallies() tally = openmc.Tally(name='incident_neutron_current') tally.filters = [surface_filter_front, particle_filter] tally.scores = ['current'] tallies.append(tally) tally = openmc.Tally(name='leakage_neutron_current') tally.filters = [surface_filter_rear, particle_filter] tally.scores = ['current'] tallies.append(tally) tally = openmc.Tally(name='incident_neutron_spectrum') tally.filters = [surface_filter_rear, particle_filter, energy_filter] tally.scores = ['flux'] tallies.append(tally) tally = openmc.Tally(name='leakage_neutron_spectrum') tally.filters = [surface_filter_front, particle_filter, energy_filter] tally.scores = ['flux'] tallies.append(tally) model = openmc.model.Model(geom, mats, sett, tallies) model.run() sp = openmc.StatePoint('statepoint.' + str(batches) + '.h5') #we want to retrieve our tallies, but we now want to save them in a .json file #therefore, we setup the json file to recieve the tally data #for now, we will simply get the json file to get the neutron current #first, we specify the 'general' parameters about the setup that we want the .json file to recieve json_output = {'inner_radius': inner_radius, 'thickness': thickness} #i.e. these are the general parameters about the setup that we want the json file to recieve #however, we also want the json file to retrieve the data from the tallies #first, we want to retrieve the neutron current at the inner and outer surfaces tallies_to_retrieve = [ 'incident_neutron_current', 'leakage_neutron_current' ] for tally_name in tallies_to_retrieve: tally = sp.get_tally(name=tally_name) df = tally.get_pandas_dataframe() #defining something that stands for dataframe, need to investigate this #its basically something that we use to obtain the mean value and the std deviation value of the tally tally_result = df['mean'].sum() tally_std_dev = df['std. dev.'].sum() json_output[tally_name] = { 'value': tally_result, 'std_dev': tally_std_dev } #next we wnat to retrieve the neutron spectra data at the inner and outer surfaces of the shell spectra_tallies_to_retrieve = [ 'incident_neutron_spectrum', 'leakage_neutron_spectrum' ] for spectra_name in spectra_tallies_to_retrieve: spectra_tally = sp.get_tally(name=spectra_name) spectra_tally_result = [entry[0][0] for entry in spectra_tally.mean] spectra_tally_std_dev = [ entry[0][0] for entry in spectra_tally.std_dev ] #print(spectra_tally_result) return json_output
settings_file.source = openmc.source.Source(space=uniform_dist) entropy_mesh = openmc.RegularMesh() entropy_mesh.lower_left = [-entropy_mesh_value, -entropy_mesh_value, -1.e50] entropy_mesh.upper_right = [entropy_mesh_value, entropy_mesh_value, 1.e50] entropy_mesh.dimension = [10, 10, 1] settings_file.entropy_mesh = entropy_mesh settings_file.export_to_xml() ############################################################################### # Exporting to OpenMC tallies.xml file ############################################################################### tallies_file = openmc.Tallies() energy_filter = openmc.EnergyFilter([0., 0.625, 20.0e6]) # Instantiate flux Tally in moderator and fuel tally = openmc.Tally(name='flux') tally.filters = [openmc.CellFilter([fuel, water])] tally.filters.append(energy_filter) tally.scores = ['flux'] tallies_file.append(tally) # Instantiate reaction rate Tally in fuel tally = openmc.Tally(name='fuel rxn rates') tally.filters = [openmc.CellFilter(fuel)] tally.filters.append(energy_filter) tally.scores = ['nu-fission', 'scatter'] tally.nuclides = ['U238', 'U235'] tallies_file.append(tally)
def make_geometry_tallies(batches, nps, enrichment_fraction, inner_radius, thickness, breeder_material_name, temperature_in_C): #print('simulating ',batches,enrichment_fraction,inner_radius,thickness,breeder_material_name) #MATERIALS# breeder_material = make_breeder_materials(enrichment_fraction, breeder_material_name, temperature_in_C) eurofer = make_eurofer() copper = make_copper() mats = openmc.Materials([breeder_material, eurofer, copper]) mats.export_to_xml('materials.xml') #GEOMETRY# central_sol_surface = openmc.ZCylinder(R=100) central_shield_outer_surface = openmc.ZCylinder(R=110) first_wall_inner_surface = openmc.Sphere(R=inner_radius) first_wall_outer_surface = openmc.Sphere(R=inner_radius + 10) breeder_blanket_outer_surface = openmc.Sphere(R=inner_radius + 10.0 + thickness) vessel_outer_surface = openmc.Sphere(R=inner_radius + 10.0 + thickness + 10.0, boundary_type='vacuum') central_sol_region = -central_sol_surface & -breeder_blanket_outer_surface central_sol_cell = openmc.Cell(region=central_sol_region) central_sol_cell.fill = copper central_shield_region = +central_sol_surface & -central_shield_outer_surface & -breeder_blanket_outer_surface central_shield_cell = openmc.Cell(region=central_shield_region) central_shield_cell.fill = eurofer inner_void_region = -first_wall_inner_surface & +central_shield_outer_surface inner_void_cell = openmc.Cell(region=inner_void_region) inner_void_cell.name = 'inner_void' first_wall_region = -first_wall_outer_surface & +first_wall_inner_surface & +central_shield_outer_surface first_wall_cell = openmc.Cell(region=first_wall_region) first_wall_cell.fill = eurofer breeder_blanket_region = +first_wall_outer_surface & -breeder_blanket_outer_surface & +central_shield_outer_surface breeder_blanket_cell = openmc.Cell(region=breeder_blanket_region) breeder_blanket_cell.fill = breeder_material vessel_region = +breeder_blanket_outer_surface & -vessel_outer_surface vessel_cell = openmc.Cell(region=vessel_region) vessel_cell.name = 'vessel' vessel_cell.fill = eurofer universe = openmc.Universe(cells=[ central_sol_cell, central_shield_cell, inner_void_cell, first_wall_cell, breeder_blanket_cell, vessel_cell ]) #plt.show(universe.plot(width=(1500,1500),basis='xz')) geom = openmc.Geometry(universe) # geom.export_to_xml('geometry.xml') #SIMULATION SETTINGS# sett = openmc.Settings() sett.batches = batches sett.inactive = 1 sett.particles = nps sett.run_mode = 'fixed source' source = openmc.Source() source.space = openmc.stats.Point((150, 0, 0)) source.angle = openmc.stats.Isotropic() #source.energy = openmc.stats.Discrete([14.08e6], [1]) source.energy = openmc.stats.Muir( e0=14080000.0, m_rat=5.0, kt=20000.0 ) #neutron energy = 14.08MeV, AMU for D + T = 5, temperature is 20KeV sett.source = source sett.export_to_xml('settings.xml') #tally filters particle_filter = openmc.ParticleFilter([1]) #1 is neutron, 2 is photon cell_filter_breeder = openmc.CellFilter(breeder_blanket_cell) cell_filter_vessel = openmc.CellFilter(vessel_cell) surface_filter_front = openmc.SurfaceFilter(first_wall_inner_surface) surface_filter_rear = openmc.SurfaceFilter(breeder_blanket_outer_surface) energy_bins = openmc.mgxs.GROUP_STRUCTURES['VITAMIN-J-175'] energy_filter = openmc.EnergyFilter(energy_bins) #TALLIES# tallies = openmc.Tallies() tally = openmc.Tally(name='TBR') tally.filters = [cell_filter_breeder, particle_filter] tally.scores = ['205'] tallies.append(tally) tally = openmc.Tally(name='blanket_leakage') tally.filters = [surface_filter_rear, particle_filter] tally.scores = ['current'] tallies.append(tally) tally = openmc.Tally(name='vessel_leakage') tally.filters = [surface_filter_rear, particle_filter] tally.scores = ['current'] tallies.append(tally) tally = openmc.Tally(name='rear_neutron_spectra') tally.filters = [surface_filter_rear, particle_filter, energy_filter] tally.scores = ['flux'] tallies.append(tally) tally = openmc.Tally(name='front_neutron_spectra') tally.filters = [surface_filter_front, particle_filter, energy_filter] tally.scores = ['flux'] tallies.append(tally) tally = openmc.Tally(name='breeder_blanket_spectra') tally.filters = [cell_filter_breeder, particle_filter, energy_filter] tally.scores = ['flux'] tallies.append(tally) tally = openmc.Tally(name='vacuum_vessel_spectra') tally.filters = [cell_filter_vessel, particle_filter, energy_filter] tally.scores = ['flux'] tallies.append(tally) tally = openmc.Tally(name='DPA') tally.filters = [cell_filter_vessel, particle_filter] tally.scores = ['444'] tallies.append(tally) #RUN OPENMC # model = openmc.model.Model(geom, mats, sett, tallies) model.run() #RETRIEVING TALLY RESULTS sp = openmc.StatePoint('statepoint.' + str(batches) + '.h5') json_output = { 'enrichment_fraction': enrichment_fraction, 'inner_radius': inner_radius, 'thickness': thickness, 'breeder_material_name': breeder_material_name, 'temperature_in_C': temperature_in_C } tallies_to_retrieve = ['TBR', 'DPA', 'blanket_leakage', 'vessel_leakage'] for tally_name in tallies_to_retrieve: tally = sp.get_tally(name=tally_name) tally_result = tally.sum[0][0][ 0] / batches #for some reason the tally sum is a nested list tally_std_dev = tally.std_dev[0][0][ 0] / batches #for some reason the tally std_dev is a nested list json_output[tally_name] = { 'value': tally_result, 'std_dev': tally_std_dev } spectra_tallies_to_retrieve = [ 'front_neutron_spectra', 'breeder_blanket_spectra', 'vacuum_vessel_spectra', 'rear_neutron_spectra' ] for spectra_name in spectra_tallies_to_retrieve: spectra_tally = sp.get_tally(name=spectra_name) spectra_tally_result = [entry[0][0] for entry in spectra_tally.mean] spectra_tally_std_dev = [ entry[0][0] for entry in spectra_tally.std_dev ] json_output[spectra_name] = { 'value': spectra_tally_result, 'std_dev': spectra_tally_std_dev, 'energy_groups': list(energy_bins) } return json_output
def _make_openmc_input(self): """Generate the OpenMC input XML """ # Define material mat = openmc.Material() for nuclide, fraction in self.nuclides: mat.add_nuclide(nuclide, fraction) mat.set_density('g/cm3', self.density) materials = openmc.Materials([mat]) if self.xsdir is not None: xs_path = (self.openmc_dir / 'cross_sections.xml').resolve() materials.cross_sections = str(xs_path) materials.export_to_xml(self.openmc_dir / 'materials.xml') # Instantiate surfaces cyl = openmc.XCylinder(boundary_type='vacuum', r=1.e-6) px1 = openmc.XPlane(boundary_type='vacuum', x0=-1.) px2 = openmc.XPlane(boundary_type='transmission', x0=1.) px3 = openmc.XPlane(boundary_type='vacuum', x0=1.e9) # Instantiate cells inner_cyl_left = openmc.Cell() inner_cyl_right = openmc.Cell() outer_cyl = openmc.Cell() # Set cells regions and materials inner_cyl_left.region = -cyl & +px1 & -px2 inner_cyl_right.region = -cyl & +px2 & -px3 outer_cyl.region = ~(-cyl & +px1 & -px3) inner_cyl_right.fill = mat # Create root universe and export to XML geometry = openmc.Geometry( [inner_cyl_left, inner_cyl_right, outer_cyl]) geometry.export_to_xml(self.openmc_dir / 'geometry.xml') # Define source source = openmc.Source() source.space = openmc.stats.Point((0, 0, 0)) source.angle = openmc.stats.Monodirectional() source.energy = openmc.stats.Discrete([self.energy], [1.]) source.particle = 'neutron' # Settings settings = openmc.Settings() if self._temperature is not None: settings.temperature = {'default': self._temperature} settings.source = source settings.particles = self.particles // self._batches settings.run_mode = 'fixed source' settings.batches = self._batches settings.photon_transport = True settings.electron_treatment = self.electron_treatment settings.cutoff = {'energy_photon': self._cutoff_energy} settings.export_to_xml(self.openmc_dir / 'settings.xml') # Define filters surface_filter = openmc.SurfaceFilter(cyl) particle_filter = openmc.ParticleFilter('photon') energy_bins = np.logspace(np.log10(self._cutoff_energy), np.log10(self.max_energy), self._bins + 1) energy_filter = openmc.EnergyFilter(energy_bins) # Create tallies and export to XML tally = openmc.Tally(name='tally') tally.filters = [surface_filter, energy_filter, particle_filter] tally.scores = ['current'] tallies = openmc.Tallies([tally]) tallies.export_to_xml(self.openmc_dir / 'tallies.xml')
class Couple_openmc(object): # One-group energy bin energy_bin = openmc.EnergyFilter([0., 20.0e6]) # Multigroup energy bin minorder = -3 maxorder = 7 mg_energy = np.logspace(minorder, maxorder, (maxorder - minorder) * 30 + 1) mg_energy_mid_points = [(x+y)/2 for x,y in zip(mg_energy[1:],mg_energy[:-1])] #mg_energy = np.logspace(-3, 7, num=300, base=10.0) mg_energy_bin = openmc.EnergyFilter(mg_energy) zero_dens_1_atm = 1E-24 def __init__(self, MC_input_path = None, xs_mode = 'no constant lib', MPI = None): # If no MC_input_path is input, it is set to cwd if MC_input_path == None: MC_input_path = os.getcwd() self._MC_input_path = MC_input_path # If no mode is input by the user, mode is set by default to 'const_lib' if xs_mode == None: xs_mode == 'constant lib' self._xs_mode = xs_mode # # If MPI is not set to on by the user, MPI is set to off # if MPI == None: # MPI == 'off' # self._MPI = MPI self._MPI = None self._volume_set = 'no' # List of selected cells to deplete self.selected_bucells_name_list = None # Dict of selected cells to deplete with their user defined nucl list self.selected_bucells_nucl_list_dict = None self._fy_lib_set = 'no' self._decay_lib_set = 'no' self._xs_lib_set = 'no' self._sampled_isomeric_branching_data = None self._sampled_ng_cross_section_data = None # This is the path set in OpenMC for the hdf5 point-wise cross sections self._cross_sections_path = None self._openmc_bin_path = None # Old way of defaulting MC_input_path to cwd # if args: # self._MC_input_path = arg[0] # else: # self._MC_input_path = os.getcwd() # This method is used within the code to create a new material that is # uniquely associated to a particular cell @property def MC_input_path(self): return self._MC_input_path @property def xs_mode(self): return self._xs_mode @property def nucl_list_dict(self): return self._nucl_list_dict @property def root_cell(self): return self._root_cell @property def MPI(self): return self._MPI def set_MPI(self, execu, tasks): self._MPI = 'on' self._tasks = tasks self._exec = execu # for no_const_lib mode, defines the list of nucl that will be simulated # for mat id # # def set_nucl_list(self, mat_name, nucl_list): # self._nucl_list_dict[mat_name] = nucl_list def select_bucells(self, bucell_list): self.selected_bucells_name_list = [] self.selected_bucells_nucl_list_dict = {} for arg in bucell_list: # If this element is a tuple (bucell , nucl list) if isinstance(arg,tuple): bucell_name = arg[0].name self.selected_bucells_name_list.append(bucell_name) self.selected_bucells_nucl_list_dict[bucell_name] = arg[1] else: self.selected_bucells_name_list.append(arg.name) def get_nucl_to_be_tallied(self, bucell): # If the user has provided a list of nuclide to be tallied if bucell.name in self.selected_bucells_nucl_list_dict: nucl_list_input = self.selected_bucells_nucl_list_dict[bucell.name] if nucl_list_input == 'initial nuclides': nucl_list = bucell.init_nucl elif nucl_list_input == 'NAX': NAX_nucl_list_name = utils.zamid_list_to_name_list(data.NAX_nucl_list) NAX_nucl_list_name_new_format = utils.bu_namelist_to_mc_namelist(NAX_nucl_list_name) # I add init_nucl because I believe it is important for init nuclides to be tallied # Their density is usually high enough that their change can influence spectrum etc... nucl_list = [x for x in NAX_nucl_list_name_new_format if x in self.MC_XS_nucl_list] + bucell.init_nucl # Here we remove the potential duplicates nucl_list = list(dict.fromkeys(nucl_list)) else: nucl_list = nucl_list_input else: nucl_list = self.MC_XS_nucl_list return nucl_list # @property # def nucl_list(self): # return self._nucl_list # # for no_const_lib mode, defines a unique nuclide list for all materials # @nucl_list.setter # def nucl_list(self, nucl_list): # self._nucl_list = nucl_list # mat_dict = self.root_cell.get_all_materials() # for mat_id in mat_dict: # mat = mat_dict[mad_id] # mat_name = mat.name # self._nucl_list_dict[mat_id] = nucl_list @property def system(self): return self._system @system.setter def system(self, system): self._system = system def import_openmc(self, root_cell): #Instantiate a system system = System(1) self.system = system # read periodic surfaces (openmc summary forgets the periodic surfaces coupling) # This function stores the periodic coupling of surfaces and it will be used later self._periodic_surfaces_dict = read_periodic_surfaces() # prerun to access cells and materials objects, to set cell volumes and if chosen # add 0 density nuclides self._pre_run(root_cell) bucell_dict = self.get_bucell_from_cell() system.bucell_dict = bucell_dict system.bounding_box = self.bounding_box # reads, modifies and set settings self._read_user_settings() # Move input files to input file folder self.gen_user_input_folder() self.copy_user_input() # MOVED TO OPENMC RUN # # New material xml file needs to be written with zero dens nuclides # self.export_material_to_xml() # # New geometry xml file needs to be written with new materials id # self.export_geometry_to_xml() # # Tallies xml files needs to be writen # self.export_tallies_to_xml() # # New settings xml files needs to be written # self.export_settings_to_xml() # Proably for when OpenBU pass dens to OpenMC @property def bounding_box(self): return self._bounding_box def set_bounding_box(self, ll, ur): self._bounding_box = [ll, ur] # def _set_material_nuclides(self, cell): # cell_id = cell.id # passlist = cell.passlists # total_dens = cell.total_dens # material = openmc.Material(cell_id) # material.set_density('atom/b-cm', total_dens) # for nuc in passlist: # nuc_name = nuc.name.replace('-', '') # nuc_ao = nuc.dens/total_dens # material.add_nuclide(nuc_name, nuc_ao) def set_settings(self, settings, init_dist): # OpenMC simulation parameters batches = settings['batches'] inactive = settings['inactive'] particles = settings['particles'] # Instantiate a Settings object settings_file = openmc.Settings() settings_file.batches = batches settings_file.inactive = inactive settings_file.particles = particles settings_file.output = {'tallies': True} # Create an initial uniform spatial source distribution over fissionable zones init_dist = setting.init_dist shape = init_dist['shape'] low_left_bound = init_dist['low_left'] up_right_bound = init_dist['up_right'] if shape == 'Box': uniform_dist = openmc.stats.Box(low_left_bound, up_right_bound, only_fissionable=True) settings_file.source = openmc.source.Source(space=uniform_dist) # Export to "settings.xml" settings_file.export_to_xml() def gen_user_input_folder(self): utils.gen_folder('user_input') def copy_user_input(self): MC_input_path = self.MC_input_path user_input_folder_path = os.getcwd() + '/user_input' shutil.copyfile(MC_input_path + '/geometry.xml', user_input_folder_path + '/geometry.xml') shutil.copyfile(MC_input_path + '/materials.xml', user_input_folder_path + '/materials.xml') shutil.copyfile(MC_input_path + '/settings.xml', user_input_folder_path + '/settings.xml') # Probably obsolete # def get_summary(self): # MC_input_path = self.MC_input_path # get_summary_dir_path = MC_input_path +'/get_summary_dir' # os.mkdir(get_summary_dir_path) # # Instantiate a Settings object # settings_file = openmc.Settings() # settings_file.batches = 2 # settings_file.inactive = 1 # settings_file.particles = 8 # # Copy the geometry and material file to the new dummy dir # shutil.copyfile(MC_input_path + '/geometry.xml', get_summary_dir_path + '/geometry.xml') # shutil.copyfile(MC_input_path + '/materials.xml', get_summary_dir_path + '/materials.xml') # # Export to "settings.xml" # settings_file.export_to_xml(path = get_summary_dir_path + '/settings.xml') # openmc.run(cwd = get_summary_dir_path) # summary = openmc.Summary(get_summary_dir_path + '/summary.h5') # # geo = summary.geometry # # cells = geo.get_all_cells() # shutil.rmtree(get_summary_dir_path) # return summary #def pre_read_xml(self): # To be able to launch the prerun, OpenBU needs at least to extract the list of # openmc cells and the boundingbox of the system # For that, the user needs to provide the def _pre_run(self, root_cell): MC_input_path = self.MC_input_path pre_run_path = os.getcwd() +'/pre_run' try: shutil.rmtree(pre_run_path) except OSError: pass os.mkdir(pre_run_path) # Prepare the volume calculation #bounding_box = root_cell.bounding_box ll = self.bounding_box[0] ur = self.bounding_box[1] cell_dict = root_cell.get_all_cells() cell_list = utils.cell_dict_to_cell_list(cell_dict) cell_list.append(root_cell) # Add root_cell so that the total volume is calculated vol1 = openmc.VolumeCalculation(cell_list, 100000, lower_left = ll, upper_right = ur) settings = openmc.Settings() settings.volume_calculations = [vol1] settings.temperature = {'method':'interpolation'} settings.run_mode='volume' settings.export_to_xml(path = pre_run_path + '/settings.xml') # Copy the geometry and material file to the new dummy dir shutil.copyfile(MC_input_path + '/geometry.xml', pre_run_path + '/geometry.xml') shutil.copyfile(MC_input_path + '/materials.xml', pre_run_path + '/materials.xml') # By default, the openm_exec is set to 'openmc' # For some reasons, this does not work on the cluster (della) # On della, we need to explicitly define the absolute path to the bin we want to use # Right now a temporary path that depends on my installation is used #openmc.calculate_volumes(cwd = pre_run_path, openmc_exec='/tigress/jdtdl/openmc/py3-mpi-190324/bin/openmc') openmc.calculate_volumes(cwd = pre_run_path, openmc_exec=self.openmc_bin_path) #openmc.run() # Read and set initial nuclides dict self.set_init_nucl_dict(root_cell) # # Read each material object and add 1atm nuclides chosen by the user # if self.mode == 'no_const_lib': # self.add_zero_dens_nuclides(self.nucl_list_dict) self._set_initial_summary(pre_run_path) self._set_cross_sections_path(pre_run_path) # Read cross sections xml files, create MC_XS_nucl_list self.set_MC_XS_nucl_list() self.set_root_universe() root_cell_name = 'root cell' # need to be specified by the user at some point self._set_root_cell(root_cell_name) # Extract cells from summary, add 1 atm nuclides to their material self._change_cell_materials() # Read and distribute volumes to cells self.set_vol_to_cell(vol1, pre_run_path) # pdb.set_trace() shutil.rmtree(pre_run_path) def set_vol_to_cell(self, vol1, pre_run_path): root_cell = self.root_cell cell_dict = root_cell.get_all_cells() cell_list = utils.cell_dict_to_cell_list(cell_dict) vol2 = vol1.from_hdf5(pre_run_path + '/volume_1.h5') for cell in cell_list: cell.add_volume_information(vol2) # Add volume for the root cell too and set it to system root_cell.add_volume_information(vol2) # This is now done in pass_vol when user does not define vol manually # system = self.system # system.total_vol = root_cell.volume # About summary # There are two type of OpenMC summary stored in openbu: initial_summary and updated_summary # I have noticed that updating the initial summary was causing some problem in OpenBU, i.e., the material xml file # would not update the density. The material was updating densities normaly when relying on the initial summary # A temporary solution for that is to separate the initial summary (that will be used to set dens to cells) and the # updated summary that will be used to extract densities to get 1g xs for bucells @property def initial_summary(self): return self._initial_summary def _set_initial_summary(self, path = os.getcwd()): initial_summary = openmc.Summary(path + '/summary.h5') ######### OpenMC Summary src does not close the hdf5 file it opens ######### When OpenBU tries to shutil.rmtree the pre_run folder, it can't because ######### a stream to summary.h5 is still open ######### We therefore close it here ######### !!!! This should be modified in OpenMC at some points ########### initial_summary._f.close() ######### !!!! This should be modified in OpenMC at some points ########### self._initial_summary = initial_summary @property def updated_summary(self): return self._updated_summary def _set_updated_summary(self, path = os.getcwd()): updated_summary = openmc.Summary(path + '/summary.h5') ######### OpenMC Summary src does not close the hdf5 file it opens ######### When OpenBU tries to shutil.rmtree the pre_run folder, it can't because ######### a stream to summary.h5 is still open ######### We therefore close it here ######### !!!! This should be modified in OpenMC at some points ########### updated_summary._f.close() ######### !!!! This should be modified in OpenMC at some points ########### self._updated_summary = updated_summary @property def statepoint(self): return self._statepoint def _set_statepoint(self, path = os.getcwd()): file_list = os.listdir() for file in file_list: if 'statepoint' in file: st_name = file statepoint = openmc.StatePoint(path + '/{}'.format(st_name)) self._statepoint = statepoint def _set_kinf(self): statepoint = self.statepoint kinf = statepoint.k_combined system = self.system sequence = system.sequence sequence._set_macrostep_kinf(kinf) @property def root_cell(self): return self._root_cell def set_root_universe(self): summary = self.initial_summary geometry = summary.geometry root_universe = geometry.root_universe self._root_universe = root_universe def _set_root_cell(self, root_cell_name): summary = self.initial_summary # get_cells_by_name returns a list hence the index 0 self._root_cell = summary.geometry.get_cells_by_name(root_cell_name)[0] add_periodic_surfaces(self._root_cell, self._periodic_surfaces_dict) region = self._root_cell.region #print (region.get_surfaces()) for surface_id in region.get_surfaces(): surface = region.get_surfaces()[surface_id] # While the most convenient way would be to extract path from summary.materials. It looks like # summary does not store the cross sections path in materials def _set_cross_sections_path(self, pre_run_path): path_to_materials_xml = pre_run_path + '/materials.xml' tree = ET.parse(path_to_materials_xml) root = tree.getroot() for child in root: if child.tag == 'cross_sections': self._cross_sections_path = child.text.replace('/cross_sections.xml', '') @property def materials(self): return self._materials def _change_cell_materials(self): summary = self.initial_summary materials = summary.materials for bucell_name in self.selected_bucells_name_list: # If bucell should only tally initial nuclide, no need to add 1 atm nuclides if self.selected_bucells_nucl_list_dict != {}: if bucell_name in self.selected_bucells_nucl_list_dict: if self.selected_bucells_nucl_list_dict[bucell_name] == 'initial nuclides': continue cell = summary.geometry.get_cells_by_name(bucell_name)[0] self.add_zero_dens_nuclides(cell) # def _change_cells_materials(self): # root_cell = self.root_cell # print (root_cell) # cell_dict = root_cell.get_all_cells() # # materials with 1atm nuclides # materials = self.materials # for cell_id in cell_dict: # cell = cell_dict[cell_id] # cell.get_all_materials # material_dict = cell.get_all_materials() # material = material_dict[list(material_dict.keys())[0]] # mat_name = material.name # for new_mat in materials: # if new_mat.name == mat_name: # print(new_mat.get_nuclides(), material.get_nuclides()) # Add zero dens nuclide for each material def add_zero_dens_nuclides(self, cell): material_dict = cell.get_all_materials() material = material_dict[list(material_dict.keys())[0]] init_nucl = material.get_nuclides() cell_name = cell.name mat_name = material.name # Not sure if this is necessary if self.selected_bucells_nucl_list_dict != {}: if cell_name in self.selected_bucells_nucl_list_dict: nucl_list_input = self.selected_bucells_nucl_list_dict[cell_name] if nucl_list_input == 'initial nuclides': nucl_list = init_nucl elif nucl_list_input == 'NAX': NAX_nucl_list_name = utils.zamid_list_to_name_list(data.NAX_nucl_list) NAX_nucl_list_name_new_format = utils.bu_namelist_to_mc_namelist(NAX_nucl_list_name) # I add init_nucl because I believe it is important for init nuclides to be tallied # Their density is usually high enough that their change can influence spectrum etc... nucl_list = [x for x in NAX_nucl_list_name_new_format if x in self.MC_XS_nucl_list] + init_nucl # Here we remove the potential duplicates nucl_list = list(dict.fromkeys(nucl_list)) else: nucl_list = nucl_list_input else: nucl_list = self.MC_XS_nucl_list #nucl_list = utils.bu_namelist_to_mc_namelist(nucl_list) else: nucl_list = self.MC_XS_nucl_list if not utils.is_lista_in_listb(init_nucl, nucl_list): raise Initial_nuclides_not_in_nuclide_list('Some initial nuclides in cell {} material {} are not included in nucl_list'.format(cell_name, mat_name)) for nucl in nucl_list: if nucl not in init_nucl: material.add_nuclide(nucl, self.zero_dens_1_atm) # Material is rename 'cell name' + 'mat' # New material id is 'mat id' + 'cell id' material.name = '{} mat'.format(cell_name) material.id = int('{}{}'.format(material.id, cell.id)) @property def sequence(self): return self._sequence @sequence.setter def sequence(self, sequence): self._sequence = sequence def set_sequence(self, sequence): self.sequence = sequence system = self.system system.set_sequence(sequence, mode = 'couple') # Add zero dens nuclide for each cell # Sort of complicated # Will deal with that later # def add_zero_dens_nuclides(self, root_cell, nucl_list_dict): # cell_dict = root_cell.get_all_cells() # for cell_id in cell_dict: # cell = cell_dict[cell_id] # material_dict = cell.get_all_materials() # material = copy.deepcopy(material_dict[material_dict.key()[0]]) # init_nucl = material.get_nuclides() # nucl_list = nucl_list_dict[cell_id] # nucl_list = utils.bu_namelist_to_mc_namelist(nucl_list) # if not is_lista_in_listb(init_nucl, nucl_list): # raise Initial_nuclides_not_in_nuclide_list('Some initial nuclides of material {} are not included in nucl_list'.format(mat_id)) # for nucl in nucl_list: # if nucl not in init_nucl: # material.add_nuclide(nucl, 1E-22) @property def init_nucl_dict(self): return self._init_nucl_dict # Create a dict with initial nuclides of each cell before # cell material is added 1 atm nuclides def set_init_nucl_dict(self, root_cell): cell_dict = root_cell.get_all_cells() init_nucl_dict = {} for cell_id in cell_dict: cell = cell_dict[cell_id] material_dict = cell.get_all_materials() material = material_dict[list(material_dict.keys())[0]] init_nucl = material.get_nuclides() init_nucl_dict[cell_id] = init_nucl self._init_nucl_dict = init_nucl_dict # # If no nucl list has been defined, nucl_list_dict = init_nucl # if self.nucl_list_dict == None: # self.nucl_list_dict = self.init_nucl_dict # Use init_nucl_dict and distribute init_nucl to each bucell def set_init_nucl(self, cell_dict, bucell_dict): init_nucl_dict = self.init_nucl_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell.init_nucl = init_nucl_dict[bucell_id] @property def MC_XS_nucl_list(self): return self._MC_XS_nucl_list @MC_XS_nucl_list.setter def MC_XS_nucl_list(self, MC_XS_nucl_list): self._MC_XS_nucl_list = MC_XS_nucl_list def set_MC_XS_nucl_list(self): #path_to_xs_xml = os.environ['OPENMC_CROSS_SECTIONS'] path_to_xs_xml = self._cross_sections_path + '/cross_sections.xml' self.MC_XS_nucl_list = [] tree = ET.parse(path_to_xs_xml) root = tree.getroot() for child in root: if child.attrib['type'] == 'neutron': self._MC_XS_nucl_list.append(child.attrib['materials']) # Remove trouble makers that appears in JEFF32 cross section # For some reason, OpenMC can't find these nuclides in jeff lib at 800K # self._MC_XS_nucl_list.remove('Cu63') # self._MC_XS_nucl_list.remove('Cu65') # self._MC_XS_nucl_list.remove('Mn55') # # THose are not handled by OpenBU # self._MC_XS_nucl_list.remove('C0') # self._MC_XS_nucl_list.remove('V0') # self._MC_XS_nucl_list.remove('Zn0') # Remove trouble makers that appears in ENDFVIII cross section # For some reason, OpenMC can't find these nuclides in jeff lib at 800K # self._MC_XS_nucl_list.remove('Cu63') # self._MC_XS_nucl_list.remove('Cu65') # self._MC_XS_nucl_list.remove('Mn55') # # THose are not handled by OpenBU try: self._MC_XS_nucl_list.remove('C0') except ValueError: pass try: self._MC_XS_nucl_list.remove('V0') except ValueError: pass try: self._MC_XS_nucl_list.remove('Zn0') except ValueError: pass # When volume is passed from OpenMC to OpenBU def pass_vol(self, cell_dict, bucell_dict): # Need to loop over bucell_dict because there might be more cells than bucells for i in bucell_dict: cell = cell_dict[i] cell_volume = cell.volume bucell = bucell_dict[i] bucell.vol = cell_volume # root_cell is not in bucell_dict but it contains the info on the total volume # Here, the total volume is set to system system = self.system system.total_vol = self.root_cell.volume # When volume is set directly by user # Right now this should bet set after import openmc as it overwrites volume calculated by openmc def set_vol(self, vol_dict): system = self.system bucell_dict = system.bucell_dict # Need to loop over bucell_dict because there might be more cells than bucells for i in bucell_dict: bucell = bucell_dict[i] if bucell.name in vol_dict: bucell.vol = vol_dict[bucell.name] # We treat total volume separately system.total_vol = vol_dict['total volume'] self._volume_set = 'yes' def pass_nuclide_densities(self, cell_dict, bucell_dict): for i in bucell_dict: bucell = bucell_dict[i] cell = cell_dict[i] #init_nucl = self.init_nucl_dict[i] init_nucl = bucell.init_nucl materials = cell.get_all_materials() openmc_dens_dict = materials[list(materials.keys())[0]].get_nuclide_atom_densities() openbu_dens_dict = {} for nucl in openmc_dens_dict: #OpenMC xs has cross section for element carbon and Vanadinium (C0, V0) only. OpenBU can't handle that if nucl == 'C0' or nucl == 'V0': continue openbu_nucl = utils.openmc_name_to_openbu_name(nucl) # if nucl is one of the initial non-zero initial nuclide, pass the density if nucl in init_nucl: openbu_dens_dict[openbu_nucl] = openmc_dens_dict[nucl][1] # if nucl is not one of the non-zero initial nuclide, set densiy to zero else: openbu_dens_dict[openbu_nucl] = 0.0 bucell = bucell_dict[i] bucell.set_initial_dens(openbu_dens_dict) def get_bucell_from_cell(self): root_cell = self.root_cell bucell_dict = {} cell_dict = root_cell.get_all_cells() for i in cell_dict: cell = cell_dict[i] cell_name = cell.name if cell_name in self.selected_bucells_name_list: bucell_dict[i] = Cell(i, cell_name) self.set_init_nucl(cell_dict, bucell_dict) self.pass_vol(cell_dict, bucell_dict) self.pass_nuclide_densities(cell_dict, bucell_dict) return bucell_dict def get_flux_tally(self, bucell): flux = openmc.Tally(name='{} flux'.format(bucell.name)) flux.filters = [openmc.CellFilter(bucell.id)] flux.filters.append(self.energy_bin) flux.scores = ['flux'] return flux def get_flux_spectrum_tally(self, bucell): flux_spectrum = openmc.Tally(name='{} flux spectrum'.format(bucell.name)) flux_spectrum.filters = [openmc.CellFilter(bucell.id)] flux_spectrum.filters.append(self.mg_energy_bin) flux_spectrum.scores = ['flux'] return flux_spectrum # Every nuclide presents in cell material will have its tally taken def get_all_nucl_rxn_tally(self, bucell): nucl_list = self.get_nucl_to_be_tallied(bucell) print ('bucell name',bucell.name) print ('nucl list when set to tally',nucl_list) nucl_list = utils.bu_namelist_to_mc_namelist(nucl_list) rxn = openmc.Tally(name='{} rxn rate'.format(bucell.name)) rxn.filters = [openmc.CellFilter(bucell.id)] rxn.filters.append(self.energy_bin) rxn.scores = ['fission', '(n,gamma)', '(n,2n)', '(n,3n)', '(n,p)', '(n,a)'] #rxn.scores = ['fission', '(n,gamma)'] #rxn.scores = ['fission', '(n,gamma)', '(n,2n)'] rxn.nuclides = nucl_list return rxn def export_material_to_xml(self): # Collect materials from each cells and put them into a materials object materials = openmc.Materials() root_cell = self.root_cell cell_dict = root_cell.get_all_cells() # When different cells have the same material, the material should not be # counted twice id_list = [] for cell_id in cell_dict: cell = cell_dict[cell_id] material_dict = cell.get_all_materials() material = material_dict[list(material_dict.keys())[0]] if material.id not in id_list: materials.append(material) id_list.append(material.id) # If the input materials.xml file is in cwd, remove it try: os.remove(os.getcwd() + '/materials.xml') except OSError: pass # Set the cross section path again to materials materials.cross_sections = self._cross_sections_path +'/cross_sections.xml' materials.export_to_xml() def export_geometry_to_xml(self): # Collect each cells and put them into a geometry object # Need to re-instantiate a universe that will be filled with the modified root cell root_universe = self._root_universe geometry = openmc.Geometry(root_universe) region = self.root_cell.region #print (region.get_surfaces()) for surface_id in region.get_surfaces(): surface = region.get_surfaces()[surface_id] #quit() # If the input materials.xml file is in cwd, remove it try: os.remove(os.getcwd() + '/geometry.xml') except OSError: pass geometry.export_to_xml() def export_tallies_to_xml(self): system = self.system bucell_dict = system.bucell_dict tallies = openmc.Tallies() for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] flux = self.get_flux_tally(bucell) flux_spectrum = self.get_flux_spectrum_tally(bucell) rxn = self.get_all_nucl_rxn_tally(bucell) tallies.append(flux) tallies.append(flux_spectrum) tallies.append(rxn) # If the input tallies.xml file is in cwd, remove it try: os.remove(os.getcwd() + '/tallies.xml') except OSError: pass tallies.export_to_xml() # settings.xml as provided by the user is read # It is then modified and set to couple # Since it will not change during the simulation, it is not going # to be modified again @property def settings(self): return self._settings def _read_user_settings(self): system = self.system MC_input_path = self.MC_input_path file_path = MC_input_path + '/settings.xml' tree = ET.parse(file_path) root = tree.getroot() settings = openmc.Settings() for child in root: if child.tag == 'particles': settings.particles = int(child.text) self.partices = int(child.text) if child.tag == 'batches': settings.batches = int(child.text) self.batches = int(child.text) if child.tag == 'inactive': settings.inactive = int(child.text) self.inactive = int(child.text) settings.output = {'tallies': False} settings.temperature = {'method': 'interpolation'} ll = self.bounding_box[0] ur = self.bounding_box[1] #uniform_dist = openmc.stats.Box(ll, ur, only_fissionable=True) point = openmc.stats.Point(xyz=(0.0, 0.0, 0.0)) settings.source = openmc.source.Source(space=point) # To reduce the size of the statepoint file settings.sourcepoint['write'] = False self._settings = settings # the setting file created by the user should be stored somewhere def export_settings_to_xml(self): settings = self.settings # If the input settings.xml file is in cwd, remove it try: os.remove(os.getcwd() + '/settings.xml') except OSError: pass settings.export_to_xml() @property def particles(self): return self._particles @particles.setter def particles(self, particles): self._particles = particles @property def batches(self): return self._batches @batches.setter def batches(self, batches): self._batches = batches @property def inactive(self): return self._inactive @inactive.setter def inactive(self, inactive): self._inactive = inactive @property def openmc_bin_path(self): return self._openmc_bin_path @openmc_bin_path.setter def openmc_bin_path(self, openmc_bin_path): self._openmc_bin_path = openmc_bin_path def run_openmc(self): # New material xml file needs to be written with zero dens nuclides self.export_material_to_xml() # New geometry xml file needs to be written with new materials id self.export_geometry_to_xml() # Tallies xml files needs to be writen self.export_tallies_to_xml() # Settings xml files needs to be written self.export_settings_to_xml() #openmc_bin_path = '/tigress/jdtdl/openmc/py3-mpi-190324/bin/openmc' #openpc_bin_path = '/tigress/mkutt/openmc/py3-mpi/bin/openmc' if self.MPI == 'on': openmc.run(mpi_args=[self._exec, '-n', self._tasks], openmc_exec = self.openmc_bin_path) else: openmc.run(openmc_exec = self.openmc_bin_path) self._set_statepoint() self._set_updated_summary() # Append the new kinf to system sequence self._set_kinf() # This method set decay_lib_set to yes # It can be used when the user does not want the system to be set any decay data def no_decay(self): self._decay_lib_set = 'yes' def set_decay_lib(self, decay_lib_path): system = self.system self._decay_lib_set = 'yes' self._decay_lib_path = decay_lib_path system.set_decay_for_all(decay_lib_path) def set_default_decay_lib(self): system = self.system self._decay_lib_set = 'yes' #system.set_default_decay_for_all_no_add() self._decay_lib_path = 'default' system.set_default_decay_for_all() def set_decay_from_object(self, bucell, object): system = self.system # This should not set yes since it is only for one bucell # Need to be fixed later self._decay_lib_set = 'yes' bucell = system.get_bucell(bucell) bucell.set_decay(object) def set_xs_lib(self, xs_lib_path): system = self.system self._xs_lib_set = 'yes' system.set_xs_for_all(xs_lib_path) def set_default_xs_lib(self): system = self.system self._xs_lib_set = 'yes' #system.set_default_decay_for_all_no_add() system.set_default_xs_for_all() def set_fy_lib(self, fy_lib_path): system = self.system self._fy_lib_set = 'yes' self._fy_lib_path = fy_lib_path system.set_fy_for_all(fy_lib_path) def set_default_fy_lib(self): system = self.system self._fy_lib_set = 'yes' self._fy_lib_path = 'default' #system.set_default_fy_for_all_no_add() system.set_default_fy_for_all() def set_fy_from_object(self, bucell, object): system = self.system # This should not set yes since it is only for one bucell # Need to be fixed later self._fy_lib_set = 'yes' bucell = system.get_bucell(bucell) bucell.set_fy(object) # This method reads, samples the isomeric branching data and xs data # using the mg energy bin mid points data and fold them together # def fold_sampled_isomeric_xs_data(self): # sampled_iso_data = self.get_sampled_isomeric_branching_data() # sampled_xs_data = self.get_sampled_ng_cross_section_data() # iso_xs_data = {} # for nucl in sampled_iso_data: # iso_data = sampled_iso_data[nucl] # xs_data = sampled_xs_data[nucl] # iso_xs_data[nucl] = {} # iso_xs_data[nucl]['0'] = [x*y for x,y in zip(iso_data['0'], xs_data)] # iso_xs_data[nucl]['1'] = [x*y for x,y in zip(iso_data['1'], xs_data)] # self._iso_xs_data = iso_xs_data def set_sampled_isomeric_branching_data(self): print ('\n\n\n***********Sampling isomeric branching data***********\n\n\n') isomeric_branching_data = data.read_isomeric_data() sampled_isomeric_branching_data = {} for nucl in isomeric_branching_data: nucl_data = isomeric_branching_data[nucl] # print (nucl_data['0']) sampled_isomeric_branching_data[nucl] = {} sampled_isomeric_branching_data[nucl]['0'] = nucl_data['0'](self.mg_energy_mid_points) sampled_isomeric_branching_data[nucl]['1'] = nucl_data['1'](self.mg_energy_mid_points) self._sampled_isomeric_branching_data = sampled_isomeric_branching_data # This method reads and samples the point-wise cross section for ng of the nuclides that # have ng isomeric branching data only def set_sampled_ng_cross_section_data(self): print ('\n\n\n***********Sampling point-wise cross section data***********\n\n\n') sampled_isomeric_branching_data = self._sampled_isomeric_branching_data sampled_ng_cross_section_data = {} cross_section_path = self._cross_sections_path cross_sections_files_name = os.listdir(cross_section_path) total_count = 1 file_name_list = [] for file_name in cross_sections_files_name: nucl_name = file_name.replace('.h5', '') if nucl_name in sampled_isomeric_branching_data: total_count += 1 file_name_list.append(file_name) start = time.time() count = 1 for file_name in file_name_list: nucl_name = file_name.replace('.h5', '') if nucl_name in ['Pm147', 'Am241']: # make it a shorter nucl_path = cross_section_path+'/{}'.format(file_name) xs_data = openmc.data.IncidentNeutron.from_hdf5(nucl_path) ng_xs_data = xs_data[102].xs['294K'] print ('--- Sampling {} (n,gamma) point-wise cross section --- [{}/{}]'.format(nucl_name, count, total_count)) sampled_ng_xs_data = ng_xs_data(self.mg_energy_mid_points) sampled_ng_cross_section_data[nucl_name] = sampled_ng_xs_data count += 1 end = time.time() print('\n Time to sample cross sections: {}'.format(end - start)) self._sampled_ng_cross_section_data = sampled_ng_cross_section_data def set_tallies_to_bucells(self, s): system = self.system bucell_dict = system.bucell_dict sp = self.statepoint summary = self.updated_summary xs_mode = self.xs_mode sampled_isomeric_branching_data = self._sampled_isomeric_branching_data sampled_ng_cross_section_data = self._sampled_ng_cross_section_data for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] # densities from OpenMC are extracted # This is for nuclides which are zero in OpenBU but set to 1E-24 in OpenMC # 1E-24 fraction percent does not translate into 1E-24 atm/cm3 always # Therefore, the code needs to divide the reaction rate by the correct densities # taken from summary.geometry.cell.material cell = summary.geometry.get_cells_by_name(bucell.name)[0] material_dict = cell.get_all_materials() material = material_dict[list(material_dict.keys())[0]] mc_nuclides_densities = material.get_nuclide_atom_densities() flux_tally = sp.get_tally(name = '{} flux'.format(bucell.name)) flux_spectrum_tally = sp.get_tally(name = '{} flux spectrum'.format(bucell.name)) rxn_rate_tally = sp.get_tally(name = '{} rxn rate'.format(bucell.name)) bucell._set_MC_tallies(mc_nuclides_densities, flux_tally, flux_spectrum_tally, rxn_rate_tally, sampled_isomeric_branching_data, sampled_ng_cross_section_data, xs_mode, s) # YOU NEED TO CREATE LIST TO STORE EACH NEW XS # Normalize the flux in each cell with the FMF after each openmc calculation # Calculate the power of each cell from the normalized flux def step_normalization(self, s): system = self.system sequence = self.sequence FMF = sequence.get_FMF1(system, s) bucell_list = system.get_bucell_list() for bucell in bucell_list: bucell_sequence = bucell.sequence MC_flux = bucell_sequence.current_MC_flux # MC_flux is volume integrated (unit cm.sp # FMF is in sp.s # to have flux in cm.s you need to divide by volule of the cell flux = FMF*MC_flux/bucell.vol pow_dens = bucell._update_pow_dens(flux) print ('initial', pow_dens) bucell_sequence._set_macrostep_flux(flux) bucell_sequence._set_macrostep_pow_dens(pow_dens) # Normalize the flux in each cell with the FMF after each openmc calculation # Calculate the power of each cell from the normalized flux def initial_couple_step_normalization(self, norma_mode): system = self.system sequence = self.sequence FMF = sequence.get_FMF1(system, 0) bucell_list = system.get_bucell_list() for bucell in bucell_list: bucell_sequence = bucell.sequence MC_flux = bucell_sequence.current_MC_flux flux = FMF*MC_flux pow_dens = bucell._update_pow_dens(flux) bucell_sequence._set_initial_flux(flux) bucell_sequence._set_initial_pow_dens(pow_dens) def copy_MC_files(self, s): step_folder = '/step_{}'.format(s) openmc_file_path = os.getcwd()+step_folder+'/OpenMC' os.mkdir(openmc_file_path) all_MC_files = glob.glob('*.xml') + glob.glob('tallies.out') + glob.glob('*.h5') for file_name in all_MC_files: try: shutil.copyfile(os.getcwd()+'/{}'.format(file_name), openmc_file_path + '/{}'.format(file_name)) except IOError: continue for file_name in all_MC_files: os.remove(os.getcwd() + '/{}'.format(file_name)) def set_dens_to_cells(self): summary = self.initial_summary system = self.system bucell_dict = system.bucell_dict for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] tally_nucl_list = utils.mc_namelist_to_bu_namelist(self.get_nucl_to_be_tallied(bucell)) cell = summary.geometry.get_cells_by_name(bucell.name)[0] material_dict = cell.get_all_materials() material = material_dict[list(material_dict.keys())[0]] ### WARNING Openmc add_nuclide in atom percent is not in absolute atom percent ### but in relative ao, i.e., setting U235 and U238 to 0.34 and 0.34 will be the same ### as setting them to 50% and 50 % ### Therefore the ao value that needs to be updated needs to be normalize by the tot dens of ### only the nuclides to be tallied and not by the total dens of all nuclide in bucell tally_nucl_list_dens = bucell.get_subtotal_dens_counting_zero_dens(tally_nucl_list) material.set_density('atom/b-cm', tally_nucl_list_dens) for nucl in tally_nucl_list: openmc_nucl_name = utils.openbu_name_to_openmc_name(nucl) material.remove_nuclide(openmc_nucl_name) # No need to calculate ao, just directly give density #nucl_subao = bucell.get_nucl_subao(nucl, tally_nucl_list) nucl_dens = bucell.get_nucl_dens_for_openmc(nucl) material.add_nuclide(openmc_nucl_name, nucl_dens) def set_MC_XS_nuc_list_to_bucells(self): system = self.system bucell_dict = system.bucell_dict MC_XS_nucl_list = self.MC_XS_nucl_list MC_XS_nucl_list_obu_name = utils.mc_namelist_to_bu_namelist(MC_XS_nucl_list) MC_XS_nucl_list_zamid = utils.name_list_to_zamid_list(MC_XS_nucl_list_obu_name) for bucell_id in bucell_dict: bucell = bucell_dict[bucell_id] bucell.MC_XS_nucl_list = MC_XS_nucl_list_zamid def burn(self): start_time = time.time() # If no decay libs and fy libs have been set, set default libs if self._decay_lib_set == 'no': self.set_default_decay_lib() print ('\n\n\n---- Default decay constants library set for system ----\n---- {} ----'.format(data.default_decay_b_lib_path)) else: print ('\n\n\n---- User defined path for decay library ----\n\n') print ('---- {} ----\n\n\n'.format(self._decay_lib_path)) if self._fy_lib_set == 'no': self.set_default_fy_lib() print ('\n\n\n---- Default fission yields library set for system ----\n---- {} ----'.format(data.default_fy_lib_path)) else: print ('\n\n\n---- User defined path for fission yields library ----\n\n') print ('---- {} ----\n\n\n'.format(self._fy_lib_path)) #print (self.xs_mode, self._xs_lib_set) if self.xs_mode == 'constant lib' and self._xs_lib_set == 'no': self.set_default_xs_lib() print ('\n\n\n----Default cross section library set for system----\n\n\n') else: # This method simply pass the MC_XS_nucl_list to each cell so that each cell # can then build it own lib_nucl_list self.set_MC_XS_nuc_list_to_bucells() print ('\n\n\n---- Path for cross sections library ----\n\n') print ('---- {} ----\n\n\n'.format(self._cross_sections_path)) self.set_sampled_isomeric_branching_data() self.set_sampled_ng_cross_section_data() system = self.system sequence = system.sequence norma_mode = sequence.norma_unit # Check consistency of nuclides list & # Generate leaves for each cell # I attempted to update set_all_leaves in order to be able to # sort out nuclides and reduce nuclide set # But it is too complicated and risk to break the code bucell_list = system.get_bucell_list() for bucell in bucell_list: # Check if different nuclide list (initial list, lib list and nucl set (user defined set of nuclides to be considered)) # are consistent with each other bucell._check_nucl_list_consistency() # Create a list of all nuclides that should be produced, i.e., that belong to the network tree #bucell._reduce_nucl_set() # This should be somewhere else but for now it is done here system.zam_order_passlist() #steps_number = sequence.steps_number steps_number = sequence.macrosteps_number # Shift loop from 1 in order to align loop s and step indexes for s in range(1, steps_number+1): print ('\n\n\n\n====== STEP {}======\n\n\n\n'.format(s)) sequence.gen_step_folder(s) print (('\n\n\n=== OpenMC Transport {}===\n\n\n'.format(s))) self.run_openmc() self.set_tallies_to_bucells(s) self.step_normalization(s) self.copy_MC_files(s) print (('\n\n\n=== Salameche Burn {}===\n\n\n'.format(s))) salameche.burn_step(system, s, 'couple') self.set_dens_to_cells() # This last openmc_run is used to compute the last burnup/time point kinf print ('\n\n\n=== OpenMC Transport for Final Point===\n\n\n') self.run_openmc() system._gen_output_summary_folder() system._print_summary_allreacs_rank() system._print_summary_subdens() system._print_summary_dens() system._print_summary_xs() system._print_summary_flux_spectrum(self.mg_energy) system._print_summary_kinf() system._print_summary_param() system._print_summary_isomeric_branching_ratio() run_time = time.time() - start_time print ('\n\n\n >>>>>> OpenBU burn took {} seconds <<<<<<< \n\n\n'.format(run_time))
def _build_openmc(self): """Generate the OpenMC input XML """ # Directory from which openmc is run os.makedirs('openmc', exist_ok=True) # Define material mat = openmc.Material() for nuclide, fraction in self.nuclides: mat.add_nuclide(nuclide, fraction) mat.set_density('g/cm3', self.density) materials = openmc.Materials([mat]) materials.export_to_xml(os.path.join('openmc', 'materials.xml')) # Instantiate surfaces cyl = openmc.XCylinder(boundary_type='vacuum', R=1.e-6) px1 = openmc.XPlane(boundary_type='vacuum', x0=-1.) px2 = openmc.XPlane(boundary_type='transmission', x0=1.) px3 = openmc.XPlane(boundary_type='vacuum', x0=1.e9) # Instantiate cells inner_cyl_left = openmc.Cell() inner_cyl_right = openmc.Cell() outer_cyl = openmc.Cell() # Set cells regions and materials inner_cyl_left.region = -cyl & +px1 & -px2 inner_cyl_right.region = -cyl & +px2 & -px3 outer_cyl.region = ~(-cyl & +px1 & -px3) inner_cyl_right.fill = mat # Create root universe and export to XML geometry = openmc.Geometry( [inner_cyl_left, inner_cyl_right, outer_cyl]) geometry.export_to_xml(os.path.join('openmc', 'geometry.xml')) # Define source source = openmc.Source() source.space = openmc.stats.Point((0, 0, 0)) source.angle = openmc.stats.Monodirectional() source.energy = openmc.stats.Discrete([self.energy], [1.]) source.particle = 'neutron' # Settings settings = openmc.Settings() settings.source = source settings.particles = self.particles settings.run_mode = 'fixed source' settings.batches = 1 settings.photon_transport = True settings.electron_treatment = self.electron_treatment settings.cutoff = {'energy_photon': 1000.} settings.export_to_xml(os.path.join('openmc', 'settings.xml')) # Define filters surface_filter = openmc.SurfaceFilter(cyl) particle_filter = openmc.ParticleFilter('photon') energy_bins = np.logspace(3, np.log10(2 * self.energy), 500) energy_filter = openmc.EnergyFilter(energy_bins) # Create tallies and export to XML tally = openmc.Tally(name='photon current') tally.filters = [surface_filter, energy_filter, particle_filter] tally.scores = ['current'] tallies = openmc.Tallies([tally]) tallies.export_to_xml(os.path.join('openmc', 'tallies.xml'))
def model(): openmc.reset_auto_ids() model = openmc.Model() # materials (M4 steel alloy) m4 = openmc.Material() m4.set_density('g/cc', 2.3) m4.add_nuclide('H1', 0.168018676) m4.add_nuclide("H2", 1.93244e-05) m4.add_nuclide("O16", 0.561814465) m4.add_nuclide("O17", 0.00021401) m4.add_nuclide("Na23", 0.021365) m4.add_nuclide("Al27", 0.021343) m4.add_nuclide("Si28", 0.187439342) m4.add_nuclide("Si29", 0.009517714) m4.add_nuclide("Si30", 0.006273944) m4.add_nuclide("Ca40", 0.018026179) m4.add_nuclide("Ca42", 0.00012031) m4.add_nuclide("Ca43", 2.51033e-05) m4.add_nuclide("Ca44", 0.000387892) m4.add_nuclide("Ca46", 7.438e-07) m4.add_nuclide("Ca48", 3.47727e-05) m4.add_nuclide("Fe54", 0.000248179) m4.add_nuclide("Fe56", 0.003895875) m4.add_nuclide("Fe57", 8.99727e-05) m4.add_nuclide("Fe58", 1.19737e-05) s0 = openmc.Sphere(r=240) s1 = openmc.Sphere(r=250, boundary_type='vacuum') c0 = openmc.Cell(fill=m4, region=-s0) c1 = openmc.Cell(region=+s0 & -s1) model.geometry = openmc.Geometry([c0, c1]) # settings settings = model.settings settings.run_mode = 'fixed source' settings.particles = 500 settings.batches = 2 settings.max_splits = 100 settings.photon_transport = True space = Point((0.001, 0.001, 0.001)) energy = Discrete([14E6], [1.0]) settings.source = openmc.Source(space=space, energy=energy) # tally mesh = openmc.RegularMesh() mesh.lower_left = (-240, -240, -240) mesh.upper_right = (240, 240, 240) mesh.dimension = (3, 5, 7) mesh_filter = openmc.MeshFilter(mesh) e_bnds = [0.0, 0.5, 2E7] energy_filter = openmc.EnergyFilter(e_bnds) particle_filter = openmc.ParticleFilter(['neutron', 'photon']) tally = openmc.Tally() tally.filters = [mesh_filter, energy_filter, particle_filter] tally.scores = ['flux'] model.tallies.append(tally) return model
def _build_inputs(self): # Instantiate some Materials and register the appropriate Nuclides uo2 = openmc.Material(name='UO2 fuel at 2.4% wt enrichment') uo2.set_density('g/cc', 10.0) uo2.add_nuclide('U238', 1.0) uo2.add_nuclide('U235', 0.02) uo2.add_nuclide('O16', 2.0) borated_water = openmc.Material(name='Borated water') borated_water.set_density('g/cm3', 1) borated_water.add_nuclide('B10', 10e-5) borated_water.add_nuclide('H1', 2.0) borated_water.add_nuclide('O16', 1.0) # Instantiate a Materials collection and export to XML materials_file = openmc.Materials([uo2, borated_water]) materials_file.export_to_xml() # Instantiate ZCylinder surfaces fuel_or = openmc.ZCylinder(surface_id=1, x0=0, y0=0, r=1, name='Fuel OR') left = openmc.XPlane(surface_id=2, x0=-2, name='left') right = openmc.XPlane(surface_id=3, x0=2, name='right') bottom = openmc.YPlane(y0=-2, name='bottom') top = openmc.YPlane(y0=2, name='top') left.boundary_type = 'vacuum' right.boundary_type = 'reflective' top.boundary_type = 'reflective' bottom.boundary_type = 'reflective' # Instantiate Cells fuel = openmc.Cell(name='fuel') water = openmc.Cell(name='water') # Use surface half-spaces to define regions fuel.region = -fuel_or water.region = +fuel_or & -right & +bottom & -top # Register Materials with Cells fuel.fill = uo2 water.fill = borated_water # Instantiate pin cell Universe pin_cell = openmc.Universe(name='pin cell') pin_cell.add_cells([fuel, water]) # Instantiate root Cell and Universe root_cell = openmc.Cell(name='root cell') root_cell.region = +left & -right & +bottom & -top root_cell.fill = pin_cell root_univ = openmc.Universe(universe_id=0, name='root universe') root_univ.add_cell(root_cell) # Instantiate a Geometry, register the root Universe geometry = openmc.Geometry(root_univ) geometry.export_to_xml() # Instantiate a Settings object, set all runtime parameters settings_file = openmc.Settings() settings_file.batches = 10 settings_file.inactive = 0 settings_file.particles = 1000 #settings_file.output = {'tallies': True} # Create an initial uniform spatial source distribution bounds = [-0.62992, -0.62992, -1, 0.62992, 0.62992, 1] uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:],\ only_fissionable=True) settings_file.source = openmc.source.Source(space=uniform_dist) settings_file.export_to_xml() # Tallies file tallies_file = openmc.Tallies() # Create partial current tallies from fuel to water # Filters two_groups = [0., 4e6, 20e6] energy_filter = openmc.EnergyFilter(two_groups) polar_filter = openmc.PolarFilter([0, np.pi / 4, np.pi]) azimuthal_filter = openmc.AzimuthalFilter([0, np.pi / 4, np.pi]) surface_filter = openmc.SurfaceFilter([1]) cell_from_filter = openmc.CellFromFilter(fuel) cell_filter = openmc.CellFilter(water) # Use Cell to cell filters for partial current cell_to_cell_tally = openmc.Tally(name=str('fuel_to_water_1')) cell_to_cell_tally.filters = [cell_from_filter, cell_filter, \ energy_filter, polar_filter, azimuthal_filter] cell_to_cell_tally.scores = ['current'] tallies_file.append(cell_to_cell_tally) # Use a Cell from + surface filters for partial current cell_to_cell_tally = openmc.Tally(name=str('fuel_to_water_2')) cell_to_cell_tally.filters = [cell_from_filter, surface_filter, \ energy_filter, polar_filter, azimuthal_filter] cell_to_cell_tally.scores = ['current'] tallies_file.append(cell_to_cell_tally) # Create partial current tallies from water to fuel # Filters cell_from_filter = openmc.CellFromFilter(water) cell_filter = openmc.CellFilter(fuel) # Cell to cell filters for partial current cell_to_cell_tally = openmc.Tally(name=str('water_to_fuel_1')) cell_to_cell_tally.filters = [cell_from_filter, cell_filter, \ energy_filter, polar_filter, azimuthal_filter] cell_to_cell_tally.scores = ['current'] tallies_file.append(cell_to_cell_tally) # Cell from + surface filters for partial current cell_to_cell_tally = openmc.Tally(name=str('water_to_fuel_2')) cell_to_cell_tally.filters = [cell_from_filter, surface_filter, \ energy_filter, polar_filter, azimuthal_filter] cell_to_cell_tally.scores = ['current'] tallies_file.append(cell_to_cell_tally) # Create a net current tally on inner surface using a surface filter surface_filter = openmc.SurfaceFilter([1]) surf_tally1 = openmc.Tally(name='net_cylinder') surf_tally1.filters = [surface_filter, energy_filter, polar_filter, \ azimuthal_filter] surf_tally1.scores = ['current'] tallies_file.append(surf_tally1) # Create a net current tally on left surface using a surface filter # This surface has a vacuum boundary condition, so leakage is tallied surface_filter = openmc.SurfaceFilter([2]) surf_tally2 = openmc.Tally(name='leakage_left') surf_tally2.filters = [surface_filter, energy_filter, polar_filter, \ azimuthal_filter] surf_tally2.scores = ['current'] tallies_file.append(surf_tally2) # Create a net current tally on right surface using a surface filter # This surface has a reflective boundary condition, so the net current # should be zero. surface_filter = openmc.SurfaceFilter([3]) surf_tally3 = openmc.Tally(name='net_right') surf_tally3.filters = [surface_filter, energy_filter] surf_tally3.scores = ['current'] tallies_file.append(surf_tally3) surface_filter = openmc.SurfaceFilter([3]) surf_tally3 = openmc.Tally(name='net_right') surf_tally3.filters = [surface_filter, energy_filter] surf_tally3.scores = ['current'] tallies_file.append(surf_tally3) tallies_file.export_to_xml()
# Instantiate an empty Tallies object tallies_file = openmc.Tallies() # K-Eigenvalue (infinity) tallies fiss_rate = openmc.Tally(name='fiss. rate') fiss_rate.scores = ['nu-fission'] tallies_file.append(fiss_rate) abs_rate = openmc.Tally(name='abs. rate') abs_rate.scores = ['absorption'] tallies_file.append(abs_rate) # Resonance Escape Probability tallies therm_abs_rate = openmc.Tally(name='therm. abs. rate') therm_abs_rate.scores = ['absorption'] therm_abs_rate.filters = [openmc.EnergyFilter([0., 0.625])] tallies_file.append(therm_abs_rate) # Thermal Flux Utilization tallies fuel_therm_abs_rate = openmc.Tally(name='fuel therm. abs. rate') fuel_therm_abs_rate.scores = ['absorption'] fuel_therm_abs_rate.filters = [ openmc.EnergyFilter([0., 0.625]), openmc.CellFilter([fuel_cell]) ] tallies_file.append(fuel_therm_abs_rate) # Fast Fission Factor tallies therm_fiss_rate = openmc.Tally(name='therm. fiss. rate') therm_fiss_rate.scores = ['nu-fission'] therm_fiss_rate.filters = [openmc.EnergyFilter([0., 0.625])]
def hexfunction(pitch, pack_frac): settings = openmc.Settings() # Set high tolerance to allow use of lower temperature xs settings.temperature['tolerance'] = 1000 settings.temperature['method'] = 'nearest' settings.temperature['multipole'] = True settings.cutoff = {'energy': 1e-8} #energy cutoff in eV ############################# ### MATERIALS ### ############################# enrichment = 20.0 uo2 = openmc.Material(1, "uo2") uo2.add_element('U', 1.0, enrichment=enrichment) uo2.add_element('O', 2.0) uo2.set_density('g/cm3', 10.97) uo2.temperature = 900 #kelvin graphite = openmc.Material(2, "graphite") graphite.set_density('g/cm3', 1.1995) graphite.add_element('C', 1.0) graphite.add_s_alpha_beta('c_Graphite') graphite.temperature = 900 #kelvin sodium = openmc.Material(3, "sodium") sodium.set_density('g/cm3', 0.8017) # 900 K sodium.add_element('Na', 1.0) # sodium.add_s_alpha_beta('c_Graphite') sodium.temperature = 900 #kelvin naoh = openmc.Material(6, "naoh") naoh.set_density('g/cm3', 1.5) # 900 K naoh.add_element('Na', 1.0) naoh.add_element('O', 1.0) naoh.add_element('H', 1.0) # sodium.add_s_alpha_beta('c_Graphite') naoh.temperature = 900 #kelvin uo2 = openmc.Material(1, "uo2") uo2.add_element('U', 1.0, enrichment=enrichment) uo2.add_element('O', 2.0) uo2.set_density('g/cm3', 10.97) uo2.temperature = 900 #kelvin fuel_temp = 900 homogeneous_fuel = build_fuel_material(4, fuel_temp, pack_frac) mats = openmc.Materials([uo2, graphite, sodium, naoh, homogeneous_fuel]) mats.export_to_xml() ############################# ### GEOMETRY ### ############################# universe = openmc.Universe() coolant_cyl = openmc.ZCylinder(R=0.5) coolant_region = -coolant_cyl coolant_cell = openmc.Cell(1, 'coolant') coolant_cell.fill = naoh coolant_cell.region = coolant_region hex_prism = openmc.get_hexagonal_prism(edge_length=pitch / (3**1 / 2), boundary_type='reflective') top = openmc.YPlane(y0=pitch) bottom = openmc.YPlane(y0=-pitch) fuel_region = hex_prism & -top & +bottom fuel_cell = openmc.Cell(2, 'moderator') fuel_cell.fill = homogeneous_fuel fuel_cell.region = fuel_region root = openmc.Universe(cells=(fuel_cell, coolant_cell)) geom = openmc.Geometry(root) geom.export_to_xml() ##################################### ### SOURCE/BATCHES ### ##################################### point = openmc.stats.Point((0, 0, 0)) src = openmc.Source(space=point) settings.source = src settings.batches = 50 settings.inactive = 10 settings.particles = 200 settings.export_to_xml() ############################# ### TALLIES ### ############################# # Instantiate an empty Tallies object tallies_file = openmc.Tallies() # K-Eigenvalue (infinity) tallies fiss_rate = openmc.Tally(name='fiss. rate') fiss_rate.scores = ['nu-fission'] tallies_file.append(fiss_rate) abs_rate = openmc.Tally(name='abs. rate') abs_rate.scores = ['absorption'] tallies_file.append(abs_rate) # Resonance Escape Probability tallies therm_abs_rate = openmc.Tally(name='therm. abs. rate') therm_abs_rate.scores = ['absorption'] therm_abs_rate.filters = [openmc.EnergyFilter([0., 0.625])] tallies_file.append(therm_abs_rate) # Thermal Flux Utilization tallies fuel_therm_abs_rate = openmc.Tally(name='fuel therm. abs. rate') fuel_therm_abs_rate.scores = ['absorption'] fuel_therm_abs_rate.filters = [ openmc.EnergyFilter([0., 0.625]), openmc.CellFilter([fuel_cell]) ] tallies_file.append(fuel_therm_abs_rate) # Fast Fission Factor tallies therm_fiss_rate = openmc.Tally(name='therm. fiss. rate') therm_fiss_rate.scores = ['nu-fission'] therm_fiss_rate.filters = [openmc.EnergyFilter([0., 0.625])] tallies_file.append(therm_fiss_rate) tallies_file.export_to_xml() ############################# ### PLOTTING ### ############################# p = openmc.Plot() p.filename = 'pinplot' p.width = (2 * pitch, 2 * pitch) p.pixels = (200, 200) p.color_by = 'material' p.colors = {homogeneous_fuel: 'yellow', sodium: 'grey'} plots = openmc.Plots([p]) plots.export_to_xml() # openmc.plot_geometry(output = False) openmc.plot_geometry() pngstring = 'pinplot{}.png'.format(str(pitch)) subprocess.call(['convert', 'pinplot.ppm', pngstring]) subprocess.call(['mv', pngstring, 'figures/' + pngstring]) ############################# ### EXECUTION ### ############################# # openmc.run(output=False) openmc.run() sp = openmc.StatePoint('statepoint.{}.h5'.format(settings.batches)) # Collect all the tallies fiss_rate = sp.get_tally(name='fiss. rate') fiss_rate_df = fiss_rate.get_pandas_dataframe() abs_rate = sp.get_tally(name='abs. rate') abs_rate_df = abs_rate.get_pandas_dataframe() therm_abs_rate = sp.get_tally(name='therm. abs. rate') therm_abs_rate_df = therm_abs_rate.get_pandas_dataframe() fuel_therm_abs_rate = sp.get_tally(name='fuel therm. abs. rate') fuel_therm_abs_rate_df = fuel_therm_abs_rate.get_pandas_dataframe() therm_fiss_rate = sp.get_tally(name='therm. fiss. rate') therm_fiss_rate_df = therm_fiss_rate.get_pandas_dataframe() # Compute k-infinity kinf = fiss_rate / abs_rate kinf_df = kinf.get_pandas_dataframe() # Compute resonance escape probability res_esc = (therm_abs_rate) / (abs_rate) res_esc_df = res_esc.get_pandas_dataframe() # Compute fast fission factor fast_fiss = fiss_rate / therm_fiss_rate fast_fiss_df = fast_fiss.get_pandas_dataframe() # Compute thermal flux utilization therm_util = fuel_therm_abs_rate / therm_abs_rate therm_util_df = therm_util.get_pandas_dataframe() # Compute neutrons produced per absorption eta = therm_fiss_rate / fuel_therm_abs_rate eta_df = eta.get_pandas_dataframe() columns = [ 'pitch', 'enrichment', 'kinf mean', 'kinf sd', 'res_esc mean', 'res_esc sd', 'fast_fiss mean', 'fast_fiss sd', 'therm_util mean', 'therm_util sd', 'eta mean', 'eta sd' ] data = [[ pitch, enrichment, kinf_df['mean'][0], kinf_df['std. dev.'][0], res_esc_df['mean'][0], res_esc_df['std. dev.'][0], fast_fiss_df['mean'][0], fast_fiss_df['std. dev.'][0], therm_util_df['mean'][0], therm_util_df['std. dev.'][0], eta_df['mean'][0], eta_df['std. dev.'][0] ]] all_tallies = pd.DataFrame(data, columns=columns) return all_tallies
def create_neutronics_model(self, method: str = None): """Uses OpenMC python API to make a neutronics model, including tallies (cell_tallies and mesh_tally_2d), simulation settings (batches, particles per batch). Arguments: method: (str): The method to use when making the imprinted and merged geometry. Options are "ppp", "trelis", "pymoab". Defaults to None. """ self.create_materials() self.create_neutronics_geometry(method=method) # this is the underlying geometry container that is filled with the # faceteted DGAMC CAD model self.universe = openmc.Universe() geom = openmc.Geometry(self.universe) # settings for the number of neutrons to simulate settings = openmc.Settings() settings.batches = self.simulation_batches settings.inactive = 0 settings.particles = self.simulation_particles_per_batch settings.run_mode = "fixed source" settings.dagmc = True settings.photon_transport = True settings.source = self.source settings.max_lost_particles = self.max_lost_particles # details about what neutrons interactions to keep track of (tally) self.tallies = openmc.Tallies() if self.mesh_tally_3d is not None: mesh_xyz = openmc.RegularMesh(mesh_id=1, name='3d_mesh') mesh_xyz.dimension = self.mesh_3D_resolution mesh_xyz.lower_left = [ -self.geometry.largest_dimension, -self.geometry.largest_dimension, -self.geometry.largest_dimension ] mesh_xyz.upper_right = [ self.geometry.largest_dimension, self.geometry.largest_dimension, self.geometry.largest_dimension ] for standard_tally in self.mesh_tally_3d: if standard_tally == 'tritium_production': score = '(n,Xt)' # where X is a wild card prefix = 'tritium_production' else: score = standard_tally prefix = standard_tally mesh_filter = openmc.MeshFilter(mesh_xyz) tally = openmc.Tally(name=prefix + '_on_3D_mesh') tally.filters = [mesh_filter] tally.scores = [score] self.tallies.append(tally) if self.mesh_tally_2d is not None: # Create mesh which will be used for tally mesh_xz = openmc.RegularMesh(mesh_id=2, name='2d_mesh_xz') mesh_xz.dimension = [ self.mesh_2D_resolution[1], 1, self.mesh_2D_resolution[0] ] mesh_xz.lower_left = [ -self.geometry.largest_dimension, -1, -self.geometry.largest_dimension ] mesh_xz.upper_right = [ self.geometry.largest_dimension, 1, self.geometry.largest_dimension ] mesh_xy = openmc.RegularMesh(mesh_id=3, name='2d_mesh_xy') mesh_xy.dimension = [ self.mesh_2D_resolution[1], self.mesh_2D_resolution[0], 1 ] mesh_xy.lower_left = [ -self.geometry.largest_dimension, -self.geometry.largest_dimension, -1 ] mesh_xy.upper_right = [ self.geometry.largest_dimension, self.geometry.largest_dimension, 1 ] mesh_yz = openmc.RegularMesh(mesh_id=4, name='2d_mesh_yz') mesh_yz.dimension = [ 1, self.mesh_2D_resolution[1], self.mesh_2D_resolution[0] ] mesh_yz.lower_left = [ -1, -self.geometry.largest_dimension, -self.geometry.largest_dimension ] mesh_yz.upper_right = [ 1, self.geometry.largest_dimension, self.geometry.largest_dimension ] for standard_tally in self.mesh_tally_2d: if standard_tally == 'tritium_production': score = '(n,Xt)' # where X is a wild card prefix = 'tritium_production' else: score = standard_tally prefix = standard_tally for mesh_filter, plane in zip( [mesh_xz, mesh_xy, mesh_yz], ['xz', 'xy', 'yz']): mesh_filter = openmc.MeshFilter(mesh_filter) tally = openmc.Tally(name=prefix + '_on_2D_mesh_' + plane) tally.filters = [mesh_filter] tally.scores = [score] self.tallies.append(tally) if self.cell_tallies is not None: for standard_tally in self.cell_tallies: if standard_tally == 'TBR': score = '(n,Xt)' # where X is a wild card sufix = 'TBR' tally = openmc.Tally(name='TBR') tally.scores = [score] self.tallies.append(tally) self._add_tally_for_every_material(sufix, score) elif standard_tally == 'spectra': neutron_particle_filter = openmc.ParticleFilter([ 'neutron']) photon_particle_filter = openmc.ParticleFilter(['photon']) energy_bins = openmc.mgxs.GROUP_STRUCTURES['CCFE-709'] energy_filter = openmc.EnergyFilter(energy_bins) self._add_tally_for_every_material( 'neutron_spectra', 'flux', [neutron_particle_filter, energy_filter] ) self._add_tally_for_every_material( 'photon_spectra', 'flux', [photon_particle_filter, energy_filter] ) else: score = standard_tally sufix = standard_tally self._add_tally_for_every_material(sufix, score) # make the model from gemonetry, materials, settings and tallies self.model = openmc.model.Model( geom, self.mats, settings, self.tallies)
import openmc from openmc.examples import slab_mg if __name__ == '__main__': model = slab_mg(as_macro=False) # Instantiate a tally mesh mesh = openmc.Mesh(mesh_id=1) mesh.type = 'regular' mesh.dimension = [1, 1, 10] mesh.lower_left = [0.0, 0.0, 0.0] mesh.upper_right = [10, 10, 5] # Instantiate some tally filters energy_filter = openmc.EnergyFilter([0.0, 20.0e6]) energyout_filter = openmc.EnergyoutFilter([0.0, 20.0e6]) energies = [1e-5, 0.0635, 10.0, 1.0e2, 1.0e3, 0.5e6, 1.0e6, 20.0e6] matching_energy_filter = openmc.EnergyFilter(energies) matching_eout_filter = openmc.EnergyoutFilter(energies) mesh_filter = openmc.MeshFilter(mesh) mat_filter = openmc.MaterialFilter(model.materials) nuclides = model.xs_data scores = {False: ['total', 'absorption', 'flux', 'fission', 'nu-fission'], True: ['total', 'absorption', 'fission', 'nu-fission']} for do_nuclides in [False, True]: t = openmc.Tally()
def test_mg_tallies(): create_library() model = slab_mg() # Instantiate a tally mesh mesh = openmc.RegularMesh(mesh_id=1) mesh.dimension = [10, 1, 1] mesh.lower_left = [0.0, 0.0, 0.0] mesh.upper_right = [929.45, 1000, 1000] # Instantiate some tally filters energy_filter = openmc.EnergyFilter([0.0, 20.0e6]) energyout_filter = openmc.EnergyoutFilter([0.0, 20.0e6]) energies = [0.0, 0.625, 20.0e6] matching_energy_filter = openmc.EnergyFilter(energies) matching_eout_filter = openmc.EnergyoutFilter(energies) mesh_filter = openmc.MeshFilter(mesh) mat_filter = openmc.MaterialFilter(model.materials) nuclides = model.xs_data scores_with_nuclides = [ 'total', 'absorption', 'fission', 'nu-fission', 'inverse-velocity', 'prompt-nu-fission', 'delayed-nu-fission', 'kappa-fission', 'events', 'decay-rate' ] scores_without_nuclides = scores_with_nuclides + ['flux'] for do_nuclides, scores in ((False, scores_without_nuclides), (True, scores_with_nuclides)): t = openmc.Tally() t.filters = [mesh_filter] t.estimator = 'analog' t.scores = scores if do_nuclides: t.nuclides = nuclides model.tallies.append(t) t = openmc.Tally() t.filters = [mesh_filter] t.estimator = 'tracklength' t.scores = scores if do_nuclides: t.nuclides = nuclides model.tallies.append(t) # Impose energy bins that dont match the MG structure and those # that do for match_energy_bins in [False, True]: if match_energy_bins: e_filter = matching_energy_filter eout_filter = matching_eout_filter else: e_filter = energy_filter eout_filter = energyout_filter t = openmc.Tally() t.filters = [mat_filter, e_filter] t.estimator = 'analog' t.scores = scores + ['scatter', 'nu-scatter'] if do_nuclides: t.nuclides = nuclides model.tallies.append(t) t = openmc.Tally() t.filters = [mat_filter, e_filter] t.estimator = 'collision' t.scores = scores if do_nuclides: t.nuclides = nuclides model.tallies.append(t) t = openmc.Tally() t.filters = [mat_filter, e_filter] t.estimator = 'tracklength' t.scores = scores if do_nuclides: t.nuclides = nuclides model.tallies.append(t) t = openmc.Tally() t.filters = [mat_filter, e_filter, eout_filter] t.scores = ['scatter', 'nu-scatter', 'nu-fission'] if do_nuclides: t.nuclides = nuclides model.tallies.append(t) harness = MGXSTestHarness('statepoint.10.h5', model) harness.main()
def generate_model(sol_temp=303., sol_conc=0.299, U_enrch=0.1467, cr_wd=0.1): sol_atom_densities = BoilerAtomDensities(enrich=U_enrch, temp=sol_temp, conc=sol_conc) sol = openmc.Material(name='sol') sol.add_element('H', sol_atom_densities['H'], percent_type='ao') sol.add_element('O', sol_atom_densities['O'], percent_type='ao') sol.add_element('S', sol_atom_densities['S'], percent_type='ao') sol.add_nuclide('U234', sol_atom_densities['U234'], percent_type='ao') sol.add_nuclide('U235', sol_atom_densities['U235'], percent_type='ao') sol.add_nuclide('U238', sol_atom_densities['U238'], percent_type='ao') sol.add_s_alpha_beta('c_H_in_H2O') ad_tot = 0. for key in sol_atom_densities: ad_tot += sol_atom_densities[key] sol.set_density('atom/b-cm', ad_tot) brass = openmc.Material(name='brass') brass.add_element('Fe', 0.001002) brass.add_element('Cu', 0.674918) brass.add_element('Zn', 0.320956) brass.add_element('Sn', 0.001451) brass.add_element('Pb', 0.001673) brass.set_density('g/cc', 8.070) cadmium = openmc.Material(name='cadmium') cadmium.add_element('Cd', 1.0) cadmium.set_density('g/cc', 8.65) shell = openmc.Material(name='shell') shell.add_element('C', 0.003659) shell.add_element('Si', 0.019559) shell.add_element('P', 0.000798) shell.add_element('S', 0.000514) shell.add_element('Cr', 0.179602) shell.add_element('Mn', 0.019998) shell.add_element('Fe', 0.669338) shell.add_element('Ni', 0.102952) shell.add_element('Nb', 0.002365) shell.add_element('Ta', 0.001214) shell.set_density('g/cc', 8.0) beryl_ref = openmc.Material(name='beryl_ref') beryl_ref.add_element('O', 6.6210e-2) beryl_ref.add_element('Be', 6.6210e-2) beryl_ref.add_element('B', 3.0637e-7) beryl_ref.add_element('Co', 5.6202e-7) beryl_ref.add_element('Ag', 3.0706e-8) beryl_ref.add_element('Cd', 7.3662e-8) beryl_ref.add_element('In', 1.4423e-8) beryl_ref.add_s_alpha_beta('c_Be_in_BeO') beryl_ref.set_density('g/cc', 2.75) grph = openmc.Material(name='grph') grph.add_element('C', 0.999999) grph.add_element('B', 0.000001) grph.set_density('g/cc', 1.7) grph.add_s_alpha_beta('c_Graphite') air = openmc.Material(name='air') air.add_element('C', 0.000150) air.add_element('N', 0.784431) air.add_element('O', 0.210748) air.add_element('Ar', 0.004671) air.set_density('g/cc', 0.001205) materials = openmc.Materials( [sol, shell, beryl_ref, grph, air, brass, cadmium]) rx_origin = [0., 76.3214, 0.] ref_sphere = openmc.Sphere(y0=rx_origin[1], r=47.4210) tank_o = openmc.Sphere(y0=rx_origin[1], r=15.3614) tank_i = openmc.Sphere(y0=rx_origin[1], r=15.282) graph_base_cyl = openmc.YCylinder(r=47.4210) #fill_drain_cav = openmc.YCylinder(r=4.445/2.); fill_drain_o = openmc.YCylinder(r=2.06375) fill_drain_i = openmc.YCylinder(r=1.905) plate_plane = openmc.YPlane(y0=0.) base_plane = openmc.YPlane(y0=34.4114) sphere_center_plane = openmc.YPlane(y0=rx_origin[1]) upper_plane = openmc.YPlane(y0=118.2314) bbox = openmc.model.RightCircularCylinder([0., -10., 0.], 230., 60., axis='y', boundary_type='vacuum') # surfaces for the control rod rod_channel_bottom = 118.2314 - 76.20 cr_cyl = openmc.YCylinder(x0=-18.891, z0=0., r=1.42875) cr_cyl_bottom = openmc.YPlane(y0=rod_channel_bottom) # surfaces for the safety rod sr_right = openmc.XPlane(x0=17.3664) sr_left = openmc.XPlane(x0=15.4614) sr_front = openmc.ZPlane(z0=7.62 / 2.) sr_back = openmc.ZPlane(z0=-7.62 / 2.) # top plane for cr/sr rod_channel_top = openmc.YPlane(y0=200.) rod_length = 76.20 #sr_wd = 76.20;# cm, distance from fully inserted cr_bottom = openmc.YPlane(y0=(rod_channel_bottom + cr_wd)) cr_top = openmc.YPlane(y0=(rod_channel_bottom + cr_wd + rod_length)) #sr_bottom = openmc.YPlane(y0=(rod_channel_bottom+sr_wd)); #sr_top = openmc.YPlane(y0=(rod_channel_bottom+sr_wd+rod_length)); cr_brass_o = openmc.YCylinder(x0=-18.891, z0=0., r=0.9525) cr_brass_i = openmc.YCylinder(x0=-18.891, z0=0., r=0.7000) cr_cd_o = openmc.YCylinder(x0=-18.891, z0=0.0, r=1.03375) core = openmc.Cell() core.fill = sol core.region = (-tank_i) | (-fill_drain_i) & -bbox steel_tank_and_pipe = openmc.Cell() steel_tank_and_pipe.fill = shell #steel_tank_and_pipe.region = (+tank_i & -tank_o & ~(-fill_drain_i)) | \ # (+fill_drain_i & -fill_drain_o & +tank_i) & -bbox steel_tank_and_pipe.region = (+tank_i & -tank_o & ~(-fill_drain_i)) | \ (+fill_drain_i & -fill_drain_o & +tank_i) & -bbox # make a universe for the control rod cr_brass = openmc.Cell() cr_brass.fill = brass cr_brass.region = +cr_brass_i & -cr_brass_o & +cr_bottom & -cr_top cr_cd = openmc.Cell() cr_cd.fill = cadmium cr_cd.region = +cr_brass_o & -cr_cd_o & +cr_bottom & -cr_top cr_air = openmc.Cell() cr_air.fill = air cr_air.region = +cr_cyl_bottom & -rod_channel_top & -cr_cyl & ~cr_cd.region & ~cr_brass.region cr_univ = openmc.Universe() cr_univ.add_cells([cr_brass, cr_cd, cr_air]) cr = openmc.Cell() cr.fill = cr_univ cr.region = -cr_cyl & +cr_cyl_bottom & -rod_channel_top sr = openmc.Cell() sr.fill = air sr.region = +sr_left & -sr_right & +cr_cyl_bottom & -upper_plane & -sr_front & +sr_back ref = openmc.Cell() ref.fill = beryl_ref ref.region = ((+tank_o & +fill_drain_o) & -ref_sphere & +base_plane & -upper_plane) & ~cr.region & ~sr.region outside = openmc.Cell() outside.fill = air outside.region = -bbox & (+graph_base_cyl | (+ref_sphere & -upper_plane) | (+upper_plane & +fill_drain_o & ~cr.region)) graph_base = openmc.Cell() graph_base.fill = grph graph_base.region = ( (-graph_base_cyl & +plate_plane & -base_plane & +fill_drain_o) | (-graph_base_cyl & +ref_sphere & +base_plane & -sphere_center_plane)) root = openmc.Universe() root.add_cells( [graph_base, ref, core, steel_tank_and_pipe, outside, cr, sr]) geometry = openmc.Geometry() geometry.root_universe = root cell_filter = openmc.CellFilter(core) N = 1001 energy_bins = np.logspace(-3, 7, num=N) energy_filter = openmc.EnergyFilter(values=energy_bins) abs_core = openmc.Tally(name='abs_core') abs_core.scores = ['absorption'] abs_core.filters = [cell_filter, energy_filter] fission = openmc.Tally(name='fission') fission.scores = ['fission'] fission.filters = [cell_filter, energy_filter] fission_by_nuclide = openmc.Tally(name='fission_by_nuclide') fission_by_nuclide.scores = ['fission'] fission_by_nuclide.nuclides = ['U234', 'U235', 'U238'] fission_by_nuclide.filters = [cell_filter, energy_filter] capture = openmc.Tally(name='capture') capture.scores = ['(n,gamma)'] capture.filters = [cell_filter, energy_filter] capture_by_nuclide = openmc.Tally(name='capture_by_nuclide') capture_by_nuclide.scores = ['(n,gamma)'] capture_by_nuclide.nuclides = ['U234', 'U238', 'H1', 'O16', 'S32'] capture_by_nuclide.filters = [cell_filter, energy_filter] flux = openmc.Tally(name='flux') flux.scores = ['flux'] flux.filters = [cell_filter, energy_filter] tallies = openmc.Tallies([ abs_core, flux, fission, capture, fission_by_nuclide, capture_by_nuclide ]) settings = openmc.Settings() settings.batches = 100 settings.inactive = 20 settings.particles = 5000 R = 15. y_org = 76.3214 bounds = [-R, -R + y_org, -R, R, R + y_org, R] uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True) settings.source = openmc.source.Source(space=uniform_dist) #settings.temperature['method']='interpolation'; return materials, geometry, tallies, settings
plots.export_to_xml() openmc.plot_geometry() get_ipython().system('convert coreplot.ppm core1.png') tallies = openmc.Tallies() # Create mesh which will be used for tally mesh_core = openmc.Mesh() mesh_core.dimension = [21, 1, 1] mesh_core.lower_left = (-100, -100, 0) mesh_core.upper_right = (100, 100, 160) # Create filter for tally mesh_filtercore = openmc.MeshFilter(mesh_core) core_filter = openmc.UniverseFilter([a1, a2, a3, a4, ba]) energy_filter = openmc.EnergyFilter([0.0, 1.0, 1.0e5, 2.0e7]) # Create mesh tally to score flux and fission rate tally_core = openmc.Tally(name='flux') tally_core.filters = [mesh_filtercore] tally_core.scores = ['fission-q-prompt'] tallies.append(tally_core) tallies.export_to_xml() coretest = openmc.Settings() coretest.batches = 40 coretest.inactive = 10 coretest.particles = 10000 core_dist = openmc.stats.Box((-10, -10, 60), (10, 10, 70), only_fissionable=True)
nGroups = len(groups) - 1 mgxs_lib = openmc.mgxs.Library(geometry) mgxs_lib.energy_groups = openmc.mgxs.EnergyGroups(groups) mgxs_lib.correction = None mgxs_lib.mgxs_types = ('total','absorption','nu-fission',\ 'fission','consistent nu-scatter matrix','chi') mgxs_lib.domain_type = 'cell' mgxs_lib.domains = geometry.get_all_material_cells().values() mgxs_lib.build_library() tallies = openmc.Tallies() mgxs_lib.add_to_tallies_file(tallies) flux_tally = openmc.Tally(name='flux') energy_filter = openmc.EnergyFilter(groups) flux_tally.filters = [ openmc.CellFilter(mCells + fCells), openmc.EnergyFilter(groups) ] #flux_tally.scores = ['flux','nu-fission'] flux_tally.scores = ['flux'] tallies.append(flux_tally) ############################################################################### ############################################################################### # Extract all Cells filled by Materials openmc_cells = geometry.get_all_material_cells().values() # Create dictionary to store multi-group cross sections for all cells xs_library = {}
def get_neutron_spectrum_from_plasma(plasma_temperature=14080000.0): # MATERIALS (there are none in this model) mats = openmc.Materials([]) # GEOMETRY # surfaces inner_surface = openmc.Sphere(r=100) outer_surface = openmc.Sphere(r=101, boundary_type='vacuum') # cells inner_cell = openmc.Cell(region=-inner_surface) # this is filled with a void / vauum by default outer_cell = openmc.Cell(region=+inner_surface & -outer_surface) # this is filled with a void / vauum by default universe = openmc.Universe(cells=[inner_cell, outer_cell]) geom = openmc.Geometry(universe) # SIMULATION SETTINGS # Instantiate a Settings object sett = openmc.Settings() sett.batches = 20 sett.inactive = 0 # the default is 10, which would be wasted computing for us sett.particles = 500000 sett.run_mode = 'fixed source' # Create a DT point source source = openmc.Source() source.space = openmc.stats.Point((0, 0, 0)) source.angle = openmc.stats.Isotropic() source.energy = openmc.stats.Muir(kt=plasma_temperature) sett.source = source # setup the filters for the tallies neutron_particle_filter = openmc.ParticleFilter(['neutron']) surface_filter = openmc.SurfaceFilter( inner_surface) # detects particles across a surface energy_filter = openmc.EnergyFilter(energy_bins) spectra_tally = openmc.Tally(name='energy_spectra') spectra_tally.scores = ['current'] spectra_tally.filters = [ surface_filter, neutron_particle_filter, energy_filter ] tallies = openmc.Tallies() tallies.append(spectra_tally) # combine all the required parts to make a model model = openmc.model.Model(geom, mats, sett, tallies) # Run OpenMC! results_filename = model.run() # open the results file results = openmc.StatePoint(results_filename) #extracts the tally values from the simulation results surface_tally = results.get_tally(name='energy_spectra') surface_tally = surface_tally.get_pandas_dataframe() surface_tally_values = surface_tally['mean'] return surface_tally_values
def make_materials_geometry_tallies(v): enrichment_fraction_list, thickness = v batches = 2 inner_radius = 500 breeder_material_name = 'Li' temperature_in_C = 500 if isinstance(enrichment_fraction_list, list): enrichment_fraction = enrichment_fraction_list[0] else: enrichment_fraction = enrichment_fraction_list print('simulating ', batches, enrichment_fraction, inner_radius, thickness, breeder_material_name) #MATERIALS# breeder_material = make_breeder_material(enrichment_fraction, breeder_material_name, temperature_in_C) eurofer = make_eurofer() mats = openmc.Materials([breeder_material, eurofer]) #GEOMETRY# breeder_blanket_inner_surface = openmc.Sphere(r=inner_radius) breeder_blanket_outer_surface = openmc.Sphere(r=inner_radius + thickness) vessel_inner_surface = openmc.Sphere(r=inner_radius + thickness + 10) vessel_outer_surface = openmc.Sphere(r=inner_radius + thickness + 20, boundary_type='vacuum') breeder_blanket_region = -breeder_blanket_outer_surface & +breeder_blanket_inner_surface breeder_blanket_cell = openmc.Cell(region=breeder_blanket_region) breeder_blanket_cell.fill = breeder_material breeder_blanket_cell.name = 'breeder_blanket' inner_void_region = -breeder_blanket_inner_surface inner_void_cell = openmc.Cell(region=inner_void_region) inner_void_cell.name = 'inner_void' vessel_region = +vessel_inner_surface & -vessel_outer_surface vessel_cell = openmc.Cell(region=vessel_region) vessel_cell.name = 'vessel' vessel_cell.fill = eurofer blanket_vessel_gap_region = -vessel_inner_surface & +breeder_blanket_outer_surface blanket_vessel_gap_cell = openmc.Cell(region=blanket_vessel_gap_region) blanket_vessel_gap_cell.name = 'blanket_vessel_gap' universe = openmc.Universe(cells=[ inner_void_cell, breeder_blanket_cell, blanket_vessel_gap_cell, vessel_cell ]) geom = openmc.Geometry(universe) #SIMULATION SETTINGS# sett = openmc.Settings() # batches = 3 # this is parsed as an argument sett.batches = batches sett.inactive = 10 sett.particles = 500 sett.run_mode = 'fixed source' source = openmc.Source() source.space = openmc.stats.Point((0, 0, 0)) source.angle = openmc.stats.Isotropic() source.energy = openmc.stats.Muir( e0=14080000.0, m_rat=5.0, kt=20000.0 ) #neutron energy = 14.08MeV, AMU for D + T = 5, temperature is 20KeV sett.source = source #TALLIES# tallies = openmc.Tallies() # define filters cell_filter_breeder = openmc.CellFilter(breeder_blanket_cell) cell_filter_vessel = openmc.CellFilter(vessel_cell) particle_filter = openmc.ParticleFilter([1]) #1 is neutron, 2 is photon surface_filter_rear_blanket = openmc.SurfaceFilter( breeder_blanket_outer_surface) surface_filter_rear_vessel = openmc.SurfaceFilter(vessel_outer_surface) energy_bins = openmc.mgxs.GROUP_STRUCTURES['VITAMIN-J-175'] energy_filter = openmc.EnergyFilter(energy_bins) tally = openmc.Tally(name='TBR') tally.filters = [cell_filter_breeder, particle_filter] tally.scores = [ '205' ] # MT 205 is the (n,Xt) reaction where X is a wildcard, if MT 105 or (n,t) then some tritium production will be missed, for example (n,nt) which happens in Li7 would be missed tallies.append(tally) tally = openmc.Tally(name='blanket_leakage') tally.filters = [surface_filter_rear_blanket, particle_filter] tally.scores = ['current'] tallies.append(tally) tally = openmc.Tally(name='vessel_leakage') tally.filters = [surface_filter_rear_vessel, particle_filter] tally.scores = ['current'] tallies.append(tally) tally = openmc.Tally(name='breeder_blanket_spectra') tally.filters = [cell_filter_breeder, particle_filter, energy_filter] tally.scores = ['flux'] tallies.append(tally) tally = openmc.Tally(name='vacuum_vessel_spectra') tally.filters = [cell_filter_vessel, particle_filter, energy_filter] tally.scores = ['flux'] tallies.append(tally) tally = openmc.Tally(name='DPA') tally.filters = [cell_filter_vessel, particle_filter] tally.scores = ['444'] tallies.append(tally) #RUN OPENMC # model = openmc.model.Model(geom, mats, sett, tallies) model.run() sp = openmc.StatePoint('statepoint.' + str(batches) + '.h5') json_output = { 'enrichment_fraction': enrichment_fraction, 'inner_radius': inner_radius, 'thickness': thickness, 'breeder_material_name': breeder_material_name, 'temperature_in_C': temperature_in_C } tallies_to_retrieve = ['TBR', 'DPA', 'blanket_leakage', 'vessel_leakage'] for tally_name in tallies_to_retrieve: tally = sp.get_tally(name=tally_name) df = tally.get_pandas_dataframe() tally_result = df['mean'].sum() tally_std_dev = df['std. dev.'].sum() json_output[tally_name] = { 'value': tally_result, 'std_dev': tally_std_dev } spectra_tallies_to_retrieve = [ 'breeder_blanket_spectra', 'vacuum_vessel_spectra' ] for spectra_name in spectra_tallies_to_retrieve: spectra_tally = sp.get_tally(name=spectra_name) spectra_tally_result = [entry[0][0] for entry in spectra_tally.mean] spectra_tally_std_dev = [ entry[0][0] for entry in spectra_tally.std_dev ] json_output[spectra_name] = { 'value': spectra_tally_result, 'std_dev': spectra_tally_std_dev, 'energy_groups': list(energy_bins) } return json_output
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Define nuclides and scores to add to both tallies self.nuclides = ['U235', 'U238'] self.scores = ['fission', 'nu-fission'] # Define filters for energy and spatial domain low_energy = openmc.EnergyFilter([0., 0.625]) high_energy = openmc.EnergyFilter([0.625, 20.e6]) merged_energies = low_energy.merge(high_energy) cell_21 = openmc.CellFilter(21) cell_27 = openmc.CellFilter(27) distribcell_filter = openmc.DistribcellFilter(21) mesh = openmc.RegularMesh(name='mesh') mesh.dimension = [2, 2] mesh.lower_left = [-50., -50.] mesh.upper_right = [+50., +50.] mesh_filter = openmc.MeshFilter(mesh) self.cell_filters = [cell_21, cell_27] self.energy_filters = [low_energy, high_energy] # Initialize cell tallies with filters, nuclides and scores tallies = [] for energy_filter in self.energy_filters: for cell_filter in self.cell_filters: for nuclide in self.nuclides: for score in self.scores: tally = openmc.Tally() tally.estimator = 'tracklength' tally.scores.append(score) tally.nuclides.append(nuclide) tally.filters.append(cell_filter) tally.filters.append(energy_filter) tallies.append(tally) # Merge all cell tallies together while len(tallies) != 1: halfway = len(tallies) // 2 zip_split = zip(tallies[:halfway], tallies[halfway:]) tallies = list(map(lambda xy: xy[0].merge(xy[1]), zip_split)) # Specify a name for the tally tallies[0].name = 'cell tally' # Initialize a distribcell tally distribcell_tally = openmc.Tally(name='distribcell tally') distribcell_tally.estimator = 'tracklength' distribcell_tally.filters = [distribcell_filter, merged_energies] for score in self.scores: distribcell_tally.scores.append(score) for nuclide in self.nuclides: distribcell_tally.nuclides.append(nuclide) mesh_tally = openmc.Tally(name='mesh tally') mesh_tally.estimator = 'tracklength' mesh_tally.filters = [mesh_filter, merged_energies] mesh_tally.scores = self.scores mesh_tally.nuclides = self.nuclides # Add tallies to a Tallies object self._model.tallies = [tallies[0], distribcell_tally, mesh_tally]
def pincellfunction(pitch, enrichment): settings = openmc.Settings() # Set high tolerance to allow use of lower temperature xs settings.temperature['tolerance'] = 10000 settings.temperature['method'] = 'nearest' settings.temperature['multipole'] = True settings.cutoff = {'energy': 1e-8} #energy cutoff in eV ############################# ### MATERIALS ### ############################# uo2 = openmc.Material(1, "uo2") uo2.add_element('U', 1.0, enrichment=enrichment) uo2.add_element('O', 2.0) uo2.set_density('g/cm3', 10.97) uo2.temperature = 900 #kelvin graphite = openmc.Material(2, "graphite") graphite.set_density('g/cm3', 1.1995) graphite.add_element('C', 1.0) graphite.add_s_alpha_beta('c_Graphite') graphite.temperature = 600 #kelvin mats = openmc.Materials([uo2, graphite]) mats.export_to_xml() ############################# ### GEOMETRY ### ############################# universe = openmc.Universe() fuel_or = openmc.ZCylinder(R=0.5) fuel_region = -fuel_or fuel_cell = openmc.Cell(1, 'fuel') fuel_cell.fill = uo2 fuel_cell.region = fuel_region box = openmc.get_rectangular_prism(width=pitch, height=pitch, boundary_type='reflective') water_region = box & +fuel_or moderator = openmc.Cell(2, 'moderator') moderator.fill = graphite moderator.region = water_region root = openmc.Universe(cells=(fuel_cell, moderator)) geom = openmc.Geometry(root) geom.export_to_xml() ##################################### ### SOURCE/BATCHES ### ##################################### point = openmc.stats.Point((0, 0, 0)) src = openmc.Source(space=point) settings.source = src settings.batches = 100 settings.inactive = 10 settings.particles = 1000 settings.export_to_xml() ############################# ### TALLIES ### ############################# # Instantiate an empty Tallies object tallies_file = openmc.Tallies() # K-Eigenvalue (infinity) tallies fiss_rate = openmc.Tally(name='fiss. rate') fiss_rate.scores = ['nu-fission'] tallies_file.append(fiss_rate) abs_rate = openmc.Tally(name='abs. rate') abs_rate.scores = ['absorption'] tallies_file.append(abs_rate) # Resonance Escape Probability tallies therm_abs_rate = openmc.Tally(name='therm. abs. rate') therm_abs_rate.scores = ['absorption'] therm_abs_rate.filters = [openmc.EnergyFilter([0., 0.625])] tallies_file.append(therm_abs_rate) # Thermal Flux Utilization tallies fuel_therm_abs_rate = openmc.Tally(name='fuel therm. abs. rate') fuel_therm_abs_rate.scores = ['absorption'] fuel_therm_abs_rate.filters = [ openmc.EnergyFilter([0., 0.625]), openmc.CellFilter([fuel_cell]) ] tallies_file.append(fuel_therm_abs_rate) # Fast Fission Factor tallies therm_fiss_rate = openmc.Tally(name='therm. fiss. rate') therm_fiss_rate.scores = ['nu-fission'] therm_fiss_rate.filters = [openmc.EnergyFilter([0., 0.625])] tallies_file.append(therm_fiss_rate) tallies_file.export_to_xml() ############################# ### PLOTTING ### ############################# p = openmc.Plot() p.filename = 'pinplot' p.width = (pitch, pitch) p.pixels = (200, 200) p.color_by = 'material' p.colors = {uo2: 'yellow', graphite: 'grey'} plots = openmc.Plots([p]) plots.export_to_xml() openmc.plot_geometry(output=False) pngstring = 'pinplot{}.png'.format(str(pitch)) subprocess.call(['convert', 'pinplot.ppm', pngstring]) subprocess.call(['mv', pngstring, 'figures/' + pngstring]) ############################# ### EXECUTION ### ############################# openmc.run(output=False) sp = openmc.StatePoint('statepoint.{}.h5'.format(settings.batches)) # Collect all the tallies fiss_rate = sp.get_tally(name='fiss. rate') fiss_rate_df = fiss_rate.get_pandas_dataframe() abs_rate = sp.get_tally(name='abs. rate') abs_rate_df = abs_rate.get_pandas_dataframe() therm_abs_rate = sp.get_tally(name='therm. abs. rate') therm_abs_rate_df = therm_abs_rate.get_pandas_dataframe() fuel_therm_abs_rate = sp.get_tally(name='fuel therm. abs. rate') fuel_therm_abs_rate_df = fuel_therm_abs_rate.get_pandas_dataframe() therm_fiss_rate = sp.get_tally(name='therm. fiss. rate') therm_fiss_rate_df = therm_fiss_rate.get_pandas_dataframe() # Compute k-infinity kinf = fiss_rate / abs_rate kinf_df = kinf.get_pandas_dataframe() # Compute resonance escape probability res_esc = (therm_abs_rate) / (abs_rate) res_esc_df = res_esc.get_pandas_dataframe() # Compute fast fission factor fast_fiss = fiss_rate / therm_fiss_rate fast_fiss_df = fast_fiss.get_pandas_dataframe() # Compute thermal flux utilization therm_util = fuel_therm_abs_rate / therm_abs_rate therm_util_df = therm_util.get_pandas_dataframe() # Compute neutrons produced per absorption eta = therm_fiss_rate / fuel_therm_abs_rate eta_df = eta.get_pandas_dataframe() columns = [ 'pitch', 'enrichment', 'kinf mean', 'kinf sd', 'res_esc mean', 'res_esc sd', 'fast_fiss mean', 'fast_fiss sd', 'therm_util mean', 'therm_util sd', 'eta mean', 'eta sd' ] data = [[ pitch, enrichment, kinf_df['mean'][0], kinf_df['std. dev.'][0], res_esc_df['mean'][0], res_esc_df['std. dev.'][0], fast_fiss_df['mean'][0], fast_fiss_df['std. dev.'][0], therm_util_df['mean'][0], therm_util_df['std. dev.'][0], eta_df['mean'][0], eta_df['std. dev.'][0] ]] all_tallies = pd.DataFrame(data, columns=columns) return all_tallies
mesh.lower_left = assembly.lower_left mesh.width = assembly.pitch # Instantiate mesh Filter mesh_filter = openmc.MeshFilter(mesh) # Fission rate mesh Tally mesh_fiss = openmc.Tally(name='mesh fission') mesh_fiss.filters = [mesh_filter] mesh_fiss.scores = ['fission'] mesh_fiss.nuclides = ['U235', 'U238'] # Fine energy flux Tally flux = openmc.Tally(name='flux') energies = np.logspace(-2, np.log10(8e6), 1000) flux.filters = [openmc.EnergyFilter(energies)] flux.scores = ['flux'] # U-238 capture and fission distribcell Tally distribcell = openmc.Tally(name='distribcell') distribcell.filters = [openmc.DistribcellFilter(fuel.id)] distribcell.nuclides = ['U235', 'U238'] distribcell.scores = ['absorption', 'fission'] # Resonance escape probability Tallies therm_abs = openmc.Tally(name='thermal absorption') therm_abs.scores = ['absorption'] therm_abs.filters = [openmc.EnergyFilter([0., 0.625])] tot_abs = openmc.Tally(name='total absorption') tot_abs.scores = ['absorption']
entropy_mesh.lower_left = [-0.39218, -0.39218, -1.e50] entropy_mesh.upper_right = [0.39218, 0.39218, 1.e50] entropy_mesh.dimension = [10, 10, 1] settings_file.entropy_mesh = entropy_mesh settings_file.export_to_xml() ############################################################################### # Exporting to OpenMC tallies.xml file ############################################################################### # Instantiate a tally mesh mesh = openmc.Mesh(mesh_id=1) mesh.type = 'regular' mesh.dimension = [100, 100, 1] mesh.lower_left = [-0.62992, -0.62992, -1.e50] mesh.upper_right = [0.62992, 0.62992, 1.e50] # Instantiate some tally Filters energy_filter = openmc.EnergyFilter([0., 4., 20.e6]) mesh_filter = openmc.MeshFilter(mesh) # Instantiate the Tally tally = openmc.Tally(tally_id=1, name='tally 1') tally.filters = [energy_filter, mesh_filter] tally.scores = ['flux', 'fission', 'nu-fission'] # Instantiate a Tallies collection and export to XML tallies_file = openmc.Tallies([tally]) tallies_file.export_to_xml()
def tallies_generation(root): """ Creates tallies.xml file Parameters ---------- root: openmc.Universe with all the relevant cells for the geometry. Returns ------- This function generates the tallies.xml file. """ tallies_file = openmc.Tallies() # phase1a-b energy_filter_b = openmc.EnergyFilter([1e-6, 20.0e6]) mesh_b = openmc.RegularMesh(mesh_id=16) mesh_b.dimension = [1, 1] L = 27.02 mesh_b.lower_left = [-L, -L] mesh_b.upper_right = [L, L] mesh_filter_b = openmc.MeshFilter(mesh_b) tally_b = openmc.Tally(name='mesh tally b') tally_b.filters = [mesh_filter_b, energy_filter_b] tally_b.scores = ['delayed-nu-fission', 'nu-fission'] tallies_file.append(tally_b) # phase1a-c mesh_no = 0 for t in range(6): mesh_no += 1 for x in range(2): x_trans = t * T['A1']['P']['x'] y_trans = t * T['A1']['P']['y'] if x == 1: mesh_no += 1 x_trans += T['A1']['F']['x'] y_trans += T['A1']['F']['y'] mesh_c = openmc.RegularMesh(mesh_id=mesh_no) mesh_c.dimension = [1, 5] mesh_c.lower_left = [ V['A1']['F']['L']['x'] + x_trans, V['A1']['F']['B']['y'] + y_trans ] mesh_c.upper_right = [ V['A1']['F']['R']['x'] + x_trans, V['A1']['F']['T']['y'] + y_trans ] mesh_filter_c = openmc.MeshFilter(mesh_c) tally_c = openmc.Tally(name='mesh tally c' + str(mesh_no)) tally_c.filters = [mesh_filter_c] tally_c.scores = ['fission'] tallies_file.append(tally_c) # phase 1a-d energy_filter_d = openmc.EnergyFilter([1e-5, 3, 1.0e5, 20.0e6]) mesh_d = openmc.RegularMesh(mesh_id=13) mesh_d.dimension = [1, 1] L = 27.02 mesh_d.lower_left = [-L, -L] mesh_d.upper_right = [L, L] mesh_filter_d = openmc.MeshFilter(mesh_d) tally_d = openmc.Tally(name='mesh tally d') tally_d.filters = [mesh_filter_d, energy_filter_d] tally_d.scores = ['flux', 'nu-fission', 'fission'] tallies_file.append(tally_d) # phase 1a-e energy_filter_e = openmc.EnergyFilter([1e-5, 3, 0.1e6, 20.0e6]) mesh_e = openmc.RegularMesh(mesh_id=14) mesh_e.dimension = [100, 100] L = 27.02 mesh_e.lower_left = [-L, -L] mesh_e.upper_right = [L, L] mesh_filter_e = openmc.MeshFilter(mesh_e) tally_e = openmc.Tally(name='mesh tally e') tally_e.filters = [mesh_filter_e, energy_filter_e] tally_e.scores = ['flux', 'nu-fission', 'fission'] tallies_file.append(tally_e) # phase 1a-f energy_filter_f = openmc.EnergyFilter(engs) mesh_f = openmc.RegularMesh(mesh_id=15) mesh_f.dimension = [1, 1] L = 27.02 mesh_f.lower_left = [-L, -L] mesh_f.upper_right = [L, L] mesh_filter_f = openmc.MeshFilter(mesh_f) tally_f = openmc.Tally(name='mesh tally f') tally_f.filters = [mesh_filter_f, energy_filter_f] tally_f.scores = ['flux', 'nu-fission', 'fission'] tallies_file.append(tally_f) tallies_file.export_to_xml() return