From b5b6f4611acef8183d7b9ce904cffa0f6d69117d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Dec 2019 14:59:44 -0600 Subject: [PATCH 01/18] Make sure model build doesn't fail if rings == 1 --- smr/build-assembly.py | 5 ++++- smr/build-core-fresh.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/smr/build-assembly.py b/smr/build-assembly.py index 327f3bc..392b114 100644 --- a/smr/build-assembly.py +++ b/smr/build-assembly.py @@ -44,7 +44,10 @@ else: directory.mkdir(exist_ok=True) # Define geometry with a single assembly -ring_radii = np.sqrt(np.arange(1, args.rings)*pellet_OR**2 / args.rings) +if args.rings > 1: + ring_radii = np.sqrt(np.arange(1, args.rings)*pellet_OR**2 / args.rings) +else: + ring_radii = None assembly = assembly_universes(ring_radii, args.axial, args.depleted) lattice_sides = openmc.model.get_rectangular_prism(lattice_pitch, lattice_pitch, boundary_type='reflective') diff --git a/smr/build-core-fresh.py b/smr/build-core-fresh.py index 1272f3b..a76ecda 100644 --- a/smr/build-core-fresh.py +++ b/smr/build-core-fresh.py @@ -51,7 +51,10 @@ else: directory = args.output_dir directory.mkdir(exist_ok=True) -ring_radii = np.sqrt(np.arange(1, args.rings)*pellet_OR**2 / args.rings) +if args.rings > 1: + ring_radii = np.sqrt(np.arange(1, args.rings)*pellet_OR**2 / args.rings) +else: + ring_radii = None geometry = core_geometry(ring_radii, args.axial, args.depleted) #### "Differentiate" the geometry if using distribmats From 2b8e9e9f5d8f5b7f15e8934b15fd653353bab249 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Dec 2019 14:32:07 -0600 Subject: [PATCH 02/18] Remove tallies, don't clone materials unless needed --- smr/build-assembly-long.py | 85 ++++++++++---------------------------- smr/build-core-fresh.py | 74 +++++++++------------------------ 2 files changed, 40 insertions(+), 119 deletions(-) diff --git a/smr/build-assembly-long.py b/smr/build-assembly-long.py index cca7640..79734c3 100644 --- a/smr/build-assembly-long.py +++ b/smr/build-assembly-long.py @@ -22,9 +22,7 @@ parser.add_argument('--multipole', action='store_true', help='Use multipole cross sections') parser.add_argument('--no-multipole', action='store_false', help='Do not use multipole cross sections') -parser.add_argument('-t', '--tallies', choices=('cell', 'mat'), default='mat', - help='Whether to use distribmats or distribcells for tallies') -parser.add_argument('-a', '--axial', type=int, default=92, +parser.add_argument('-a', '--axial', type=int, default=100, help='Number of axial subdivisions in fuel') parser.add_argument('-d', '--depleted', action='store_true', help='Whether UO2 compositions should represent depleted fuel') @@ -99,40 +97,30 @@ for halfspace in surfs['lat grid box inner']: # Define geometry with a single assembly geometry = openmc.Geometry(root_universe) - -def clone(material): - """Perform copy of material but share nuclide densities""" - shared_mat = copy.copy(material) - shared_mat.id = None - return shared_mat - - -#### "Differentiate" the geometry if using distribmats h = active_fuel_length / args.axial -if args.tallies == 'mat': - # Count the number of instances for each cell and material - geometry.determine_paths(instances_only=True) - for cell in tqdm(geometry.get_all_material_cells().values(), - desc='Differentiating materials'): - if cell.fill in materials: - # Fill cell with list of "differentiated" materials - cell.fill = [clone(cell.fill) for i in range(cell.num_instances)] +fuel_mats = {} - # Determine volume of each fuel material - if 'UO2 Fuel' in cell.fill[0].name: - upper_right = cell.region.bounding_box[1] - if isclose(upper_right[0], rings[0]): - ri, ro = 0.0, rings[0] - elif isclose(upper_right[0], rings[1]): - ri, ro = rings[0], rings[1] - else: - ri, ro = rings[1], pellet_OR - for mat in cell.fill: - mat.volume = pi * (ro*ro - ri*ri) * h +for cell in tqdm(geometry.get_all_material_cells().values(), + desc='Assigning volume'): + if cell.fill in materials: + # Determine volume of each fuel material + if 'UO2 Fuel' in cell.fill.name: + upper_right = cell.region.bounding_box[1] + if isclose(upper_right[0], rings[0]): + ri, ro = 0.0, rings[0] + elif isclose(upper_right[0], rings[1]): + ri, ro = rings[0], rings[1] else: - for mat in cell.fill: - mat.volume = 1.0 + ri, ro = rings[1], pellet_OR + if ri not in fuel_mats: + cell.fill = cell.fill.clone() + cell.fill.volume = pi * (ro*ro - ri*ri) * h + fuel_mats[ri] = cell.fill + else: + cell.fill = fuel_mats[ri] + else: + cell.fill.volume = 1.0 #### Create OpenMC "materials.xml" file print('Getting materials...') @@ -173,34 +161,3 @@ if args.multipole: } settings.export_to_xml(str(directory / 'settings.xml')) - - -#### Create OpenMC "tallies.xml" file -tallies = openmc.Tallies() - -# Extract all fuel materials -materials = geometry.get_materials_by_name(name='Fuel', matching=False) - -# If using distribcells, create distribcell tally needed for depletion -if args.tallies == 'cell': - # Extract all cells filled by a fuel material - fuel_cells = [] - for cell in geometry.get_all_cells().values(): - if cell.fill in materials: - tally = openmc.Tally(name='depletion tally') - tally.scores = ['(n,p)', '(n,a)', '(n,gamma)', - 'fission', '(n,2n)', '(n,3n)', '(n,4n)'] - tally.nuclides = cell.fill.get_nuclides() - tally.filters.append(openmc.DistribcellFilter([cell])) - tallies.append(tally) - -# If using distribmats, create material tally needed for depletion -elif args.tallies == 'mat': - tally = openmc.Tally(name='depletion tally') - tally.scores = ['(n,p)', '(n,a)', '(n,gamma)', - 'fission', '(n,2n)', '(n,3n)', '(n,4n)'] - tally.nuclides = materials[0].get_nuclides() - tally.filters = [openmc.MaterialFilter(materials)] - tallies.append(tally) - -tallies.export_to_xml(str(directory / 'tallies.xml')) diff --git a/smr/build-core-fresh.py b/smr/build-core-fresh.py index a76ecda..4265056 100644 --- a/smr/build-core-fresh.py +++ b/smr/build-core-fresh.py @@ -4,6 +4,7 @@ import os import shutil import copy import argparse +from math import pi from pathlib import Path import numpy as np @@ -11,26 +12,18 @@ import numpy as np import openmc from smr.materials import materials from smr.plots import core_plots -from smr.surfaces import lattice_pitch, bottom_fuel_stack, top_active_core, pellet_OR +from smr.surfaces import lattice_pitch, bottom_fuel_stack, top_active_core, \ + pellet_OR, active_fuel_length from smr.core import core_geometry from smr import inlet_temperature -def clone(mat): - """Make a shallow copy of a material (sharing compositions).""" - mat_copy = copy.copy(mat) - mat_copy.id = None - return mat_copy - - # Define command-line options parser = argparse.ArgumentParser() parser.add_argument('--multipole', action='store_true', help='Use multipole cross sections') parser.add_argument('--no-multipole', action='store_false', help='Do not use multipole cross sections') -parser.add_argument('-t', '--tallies', choices=('cell', 'mat'), default='cell', - help='Whether to use distribmats or distribcells for tallies') parser.add_argument('-r', '--rings', type=int, default=10, help='Number of annular regions in fuel') parser.add_argument('-a', '--axial', type=int, default=196, @@ -57,18 +50,24 @@ else: ring_radii = None geometry = core_geometry(ring_radii, args.axial, args.depleted) -#### "Differentiate" the geometry if using distribmats -if args.tallies == 'mat': - # Count the number of instances for each cell and material - geometry.determine_paths(instances_only=True) +h = active_fuel_length / args.axial +fuel_mats = {} - # Extract all cells filled by a fuel material - fuel_mats = {m for m in materials if 'UO2 Fuel' in m.name} +fuel_volume = pi * pellet_OR**2 * h / args.rings +for cell in geometry.get_all_cells().values(): + if cell.fill in materials: + # Determine volume of each fuel material + if 'UO2 Fuel' in cell.fill.name: + r_o = cell.region.bounding_box[1][0] + if r_o not in fuel_mats: + cell.fill = cell.fill.clone() + cell.fill.volume = fuel_volume + fuel_mats[r_o] = cell.fill + else: + cell.fill = fuel_mats[r_o] + else: + cell.fill.volume = 1.0 - for cell in geometry.get_all_cells().values(): - if cell.fill in fuel_mats: - # Fill cell with list of "differentiated" materials - cell.fill = [clone(cell.fill) for i in range(cell.num_instances)] #### Create OpenMC "materials.xml" file all_materials = geometry.get_all_materials() @@ -107,38 +106,3 @@ if args.multipole: settings.export_to_xml(str(directory / 'settings.xml')) - -#### Create OpenMC "plots.xml" file -plots = core_plots() -plots.export_to_xml(str(directory / 'plots.xml')) - - -#### Create OpenMC "tallies.xml" file -tallies = openmc.Tallies() - -# Extract all fuel materials -materials = geometry.get_materials_by_name(name='Fuel', matching=False) - -# If using distribcells, create distribcell tally needed for depletion -if args.tallies == 'cell': - # Extract all cells filled by a fuel material - fuel_cells = [] - for cell in geometry.get_all_cells().values(): - if cell.fill in materials: - tally = openmc.Tally(name='depletion tally') - tally.scores = ['(n,p)', '(n,a)', '(n,gamma)', - 'fission', '(n,2n)', '(n,3n)', '(n,4n)'] - tally.nuclides = cell.fill.get_nuclides() - tally.filters.append(openmc.DistribcellFilter([cell])) - tallies.append(tally) - -# If using distribmats, create material tally needed for depletion -elif args.tallies == 'mat': - tally = openmc.Tally(name='depletion tally') - tally.scores = ['(n,p)', '(n,a)', '(n,gamma)', - 'fission', '(n,2n)', '(n,3n)', '(n,4n)'] - tally.nuclides = materials[0].get_nuclides() - tally.filters = [openmc.MaterialFilter(materials)] - tallies.append(tally) - -tallies.export_to_xml(str(directory / 'tallies.xml')) From 1718798735824c5a66358a4f9acea1b5a86a1c56 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 6 Jun 2022 16:49:18 -0500 Subject: [PATCH 03/18] Make differentiation of materials optional for assembly-long and core-fresh --- smr/build-assembly-long.py | 53 +++++++++++++++++++++++++++++++------- smr/build-core-fresh.py | 53 +++++++++++++++++++++++++++----------- 2 files changed, 81 insertions(+), 25 deletions(-) diff --git a/smr/build-assembly-long.py b/smr/build-assembly-long.py index 79734c3..28447a0 100644 --- a/smr/build-assembly-long.py +++ b/smr/build-assembly-long.py @@ -20,14 +20,18 @@ from smr.pins import pin_universes, make_stack parser = argparse.ArgumentParser() parser.add_argument('--multipole', action='store_true', help='Use multipole cross sections') -parser.add_argument('--no-multipole', action='store_false', +parser.add_argument('--no-multipole', dest='multipole', action='store_false', help='Do not use multipole cross sections') +parser.add_argument('--clone', action='store_true', + help='Clone materials for each cell instance') +parser.add_argument('--no-clone', dest='clone', action='store_false', + help='Do not clone materials for each cell instance') parser.add_argument('-a', '--axial', type=int, default=100, help='Number of axial subdivisions in fuel') parser.add_argument('-d', '--depleted', action='store_true', help='Whether UO2 compositions should represent depleted fuel') parser.add_argument('-o', '--output-dir', type=Path, default=None) -parser.set_defaults(multipole=True) +parser.set_defaults(clone=False, multipole=True) args = parser.parse_args() # Make directory for inputs @@ -97,15 +101,33 @@ for halfspace in surfs['lat grid box inner']: # Define geometry with a single assembly geometry = openmc.Geometry(root_universe) + +def clone(material): + """Perform copy of material but share nuclide densities""" + shared_mat = copy.copy(material) + shared_mat.id = None + return shared_mat + h = active_fuel_length / args.axial fuel_mats = {} +# Count the number of instances for each cell and material +if args.clone: + geometry.determine_paths(instances_only=True) + for cell in tqdm(geometry.get_all_material_cells().values(), - desc='Assigning volume'): + desc='Differentiating materials / assigning volume'): if cell.fill in materials: + # Determine if this material is fuel + is_fuel = 'UO2 Fuel' in cell.fill.name + + # Fill cell with list of "differentiated" materials if requested + if args.clone: + cell.fill = [clone(cell.fill) for i in range(cell.num_instances)] + # Determine volume of each fuel material - if 'UO2 Fuel' in cell.fill.name: + if is_fuel: upper_right = cell.region.bounding_box[1] if isclose(upper_right[0], rings[0]): ri, ro = 0.0, rings[0] @@ -113,14 +135,25 @@ for cell in tqdm(geometry.get_all_material_cells().values(), ri, ro = rings[0], rings[1] else: ri, ro = rings[1], pellet_OR - if ri not in fuel_mats: - cell.fill = cell.fill.clone() - cell.fill.volume = pi * (ro*ro - ri*ri) * h - fuel_mats[ri] = cell.fill + + if args.clone: + for mat in cell.fill: + mat.volume = pi * (ro*ro - ri*ri) * h else: - cell.fill = fuel_mats[ri] + # In non-clone mode, we still need to create a copy of the + # material for each ring since they get different volumes + if ri not in fuel_mats: + cell.fill = cell.fill.clone() + cell.fill.volume = pi * (ro*ro - ri*ri) * h + fuel_mats[ri] = cell.fill + else: + cell.fill = fuel_mats[ri] else: - cell.fill.volume = 1.0 + if args.clone: + for mat in cell.fill: + mat.volume = 1.0 + else: + cell.fill.volume = 1.0 #### Create OpenMC "materials.xml" file print('Getting materials...') diff --git a/smr/build-core-fresh.py b/smr/build-core-fresh.py index 4265056..e0dabff 100644 --- a/smr/build-core-fresh.py +++ b/smr/build-core-fresh.py @@ -1,29 +1,38 @@ #!/usr/bin/env python3 -import os -import shutil import copy import argparse from math import pi from pathlib import Path import numpy as np - import openmc +from tqdm import tqdm + from smr.materials import materials -from smr.plots import core_plots from smr.surfaces import lattice_pitch, bottom_fuel_stack, top_active_core, \ pellet_OR, active_fuel_length from smr.core import core_geometry from smr import inlet_temperature +def clone(material): + """Perform copy of material but share nuclide densities""" + shared_mat = copy.copy(material) + shared_mat.id = None + return shared_mat + + # Define command-line options parser = argparse.ArgumentParser() parser.add_argument('--multipole', action='store_true', help='Use multipole cross sections') -parser.add_argument('--no-multipole', action='store_false', +parser.add_argument('--no-multipole', dest='multipole', action='store_false', help='Do not use multipole cross sections') +parser.add_argument('--clone', action='store_true', + help='Clone materials for each cell instance') +parser.add_argument('--no-clone', dest='clone', action='store_false', + help='Do not clone materials for each cell instance') parser.add_argument('-r', '--rings', type=int, default=10, help='Number of annular regions in fuel') parser.add_argument('-a', '--axial', type=int, default=196, @@ -31,7 +40,7 @@ parser.add_argument('-a', '--axial', type=int, default=196, parser.add_argument('-d', '--depleted', action='store_true', help='Whether UO2 compositions should represent depleted fuel') parser.add_argument('-o', '--output-dir', type=Path, default=None) -parser.set_defaults(multipole=True) +parser.set_defaults(clone=False, multipole=True) args = parser.parse_args() # Make directory for inputs @@ -53,22 +62,36 @@ geometry = core_geometry(ring_radii, args.axial, args.depleted) h = active_fuel_length / args.axial fuel_mats = {} +# Count the number of instances for each cell and material +if args.clone: + geometry.determine_paths(instances_only=True) + fuel_volume = pi * pellet_OR**2 * h / args.rings -for cell in geometry.get_all_cells().values(): +for cell in tqdm(geometry.get_all_cells().values(), + desc='Differentiating materials / assigning volume'): if cell.fill in materials: + # Determine if this material is fuel + name = cell.fill.name + is_fuel = 'UO2 Fuel' in name + # Determine volume of each fuel material - if 'UO2 Fuel' in cell.fill.name: - r_o = cell.region.bounding_box[1][0] - if r_o not in fuel_mats: - cell.fill = cell.fill.clone() - cell.fill.volume = fuel_volume - fuel_mats[r_o] = cell.fill + if is_fuel: + if args.clone: + # Fill cell with list of "differentiated" materials if requested + cell.fill = [clone(cell.fill) for i in range(cell.num_instances)] + for mat in cell.fill: + mat.volume = fuel_volume else: - cell.fill = fuel_mats[r_o] + r_o = cell.region.bounding_box[1][0] + if (name, r_o) not in fuel_mats: + cell.fill = cell.fill.clone() + cell.fill.volume = fuel_volume + fuel_mats[name, r_o] = cell.fill + else: + cell.fill = fuel_mats[name, r_o] else: cell.fill.volume = 1.0 - #### Create OpenMC "materials.xml" file all_materials = geometry.get_all_materials() materials = openmc.Materials(all_materials.values()) From 4ad8676efcdd1ef1eefe8beabdb97c035515938f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 17 Jun 2021 09:15:10 +0700 Subject: [PATCH 04/18] Only whitespace changes --- smr/smr/surfaces.py | 135 +++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 90 deletions(-) diff --git a/smr/smr/surfaces.py b/smr/smr/surfaces.py index 0adf0d8..d0653ee 100644 --- a/smr/smr/surfaces.py +++ b/smr/smr/surfaces.py @@ -128,74 +128,47 @@ neutron_shield_NEtop_SWbot = tan(-pi/6) surfs = {} -surfs['pellet OR'] = openmc.ZCylinder( - r=pellet_OR, name='Pellet OR') -surfs['plenum spring OR'] = openmc.ZCylinder( - r=plenum_spring_OR, name='FR Plenum Spring OR') -surfs['clad IR'] = openmc.ZCylinder( - r=clad_IR, name='Clad IR') -surfs['clad OR'] = openmc.ZCylinder( - r=clad_OR, name='Clad OR') -surfs['GT IR'] = openmc.ZCylinder( - r=guide_tube_IR, name='GT IR (above dashpot)') -surfs['GT OR'] = openmc.ZCylinder( - r=guide_tube_OR, name='GT OR (above dashpot)') -surfs['GT dashpot IR'] = openmc.ZCylinder( - r=guide_tube_dash_IR, name='GT IR (at dashpot)') -surfs['GT dashpot OR'] = openmc.ZCylinder( - r=guide_tube_dash_OR, name='GT OR (at dashpot)') -surfs['CP OR'] = openmc.ZCylinder( - r=boron_carbide_OR, name='Control Poison OR') -surfs['CR IR'] = openmc.ZCylinder( - r=control_rod_IR, name='CR Clad IR') -surfs['CR OR'] = openmc.ZCylinder( - r=control_rod_OR, name='CR Clad OR') -surfs['BA IR 1'] = openmc.ZCylinder( - r=burn_abs_r1, name='BA IR 1') -surfs['BA IR 2'] = openmc.ZCylinder( - r=burn_abs_r2, name='BA IR 2') -surfs['BA IR 3'] = openmc.ZCylinder( - r=burn_abs_r3, name='BA IR 3') -surfs['BA IR 4'] = openmc.ZCylinder( - r=burn_abs_r4, name='BA IR 4') -surfs['BA IR 5'] = openmc.ZCylinder( - r=burn_abs_r5, name='BA IR 5') -surfs['BA IR 6'] = openmc.ZCylinder( - r=burn_abs_r6, name='BA IR 6') -surfs['BA IR 7'] = openmc.ZCylinder( - r=burn_abs_r7, name='BA IR 7') -surfs['BA IR 8'] = openmc.ZCylinder( - r=burn_abs_r8, name='BA IR 8') +surfs['pellet OR'] = openmc.ZCylinder(r=pellet_OR, name='Pellet OR') +surfs['plenum spring OR'] = openmc.ZCylinder(r=plenum_spring_OR, name='FR Plenum Spring OR') +surfs['clad IR'] = openmc.ZCylinder(r=clad_IR, name='Clad IR') +surfs['clad OR'] = openmc.ZCylinder(r=clad_OR, name='Clad OR') +surfs['GT IR'] = openmc.ZCylinder(r=guide_tube_IR, name='GT IR (above dashpot)') +surfs['GT OR'] = openmc.ZCylinder(r=guide_tube_OR, name='GT OR (above dashpot)') +surfs['GT dashpot IR'] = openmc.ZCylinder(r=guide_tube_dash_IR, name='GT IR (at dashpot)') +surfs['GT dashpot OR'] = openmc.ZCylinder(r=guide_tube_dash_OR, name='GT OR (at dashpot)') +surfs['CP OR'] = openmc.ZCylinder(r=boron_carbide_OR, name='Control Poison OR') +surfs['CR IR'] = openmc.ZCylinder(r=control_rod_IR, name='CR Clad IR') +surfs['CR OR'] = openmc.ZCylinder(r=control_rod_OR, name='CR Clad OR') +surfs['BA IR 1'] = openmc.ZCylinder(r=burn_abs_r1, name='BA IR 1') +surfs['BA IR 2'] = openmc.ZCylinder(r=burn_abs_r2, name='BA IR 2') +surfs['BA IR 3'] = openmc.ZCylinder(r=burn_abs_r3, name='BA IR 3') +surfs['BA IR 4'] = openmc.ZCylinder(r=burn_abs_r4, name='BA IR 4') +surfs['BA IR 5'] = openmc.ZCylinder(r=burn_abs_r5, name='BA IR 5') +surfs['BA IR 6'] = openmc.ZCylinder(r=burn_abs_r6, name='BA IR 6') +surfs['BA IR 7'] = openmc.ZCylinder(r=burn_abs_r7, name='BA IR 7') +surfs['BA IR 8'] = openmc.ZCylinder(r=burn_abs_r8, name='BA IR 8') surfs['IT IR'] = surfs['BA IR 5'] surfs['IT OR'] = surfs['BA IR 6'] # Rectangular prisms for grid spacers -surfs['rod grid box'] = \ - openmc.rectangular_prism(rod_grid_side, rod_grid_side) +surfs['rod grid box'] = openmc.rectangular_prism(rod_grid_side, rod_grid_side) # Rectangular prisms for lattice grid sleeves -surfs['lat grid box inner'] = \ - openmc.rectangular_prism(17.*pin_pitch, 17.*pin_pitch) -surfs['lat grid box outer'] = \ - openmc.rectangular_prism(grid_strap_side, grid_strap_side) +surfs['lat grid box inner'] = openmc.rectangular_prism(17.*pin_pitch, 17.*pin_pitch) +surfs['lat grid box outer'] = openmc.rectangular_prism(grid_strap_side, grid_strap_side) -surfs['bot support plate'] = openmc.ZPlane( - z0=bottom_support_plate, name='bot support plate') -surfs['top support plate'] = openmc.ZPlane( - z0=top_support_plate, name='top support plate') +surfs['bot support plate'] = openmc.ZPlane(z0=bottom_support_plate, name='bot support plate') +surfs['top support plate'] = openmc.ZPlane(z0=top_support_plate, name='top support plate') surfs['bottom FR'] = openmc.ZPlane(z0=bottom_fuel_rod, name='bottom FR') surfs['top lower nozzle'] = surfs['bottom FR'] surfs['bot lower nozzle'] = surfs['top support plate'] # axial surfaces -surfs['bot active core'] = openmc.ZPlane( - z0=bottom_fuel_stack, name='bot active core') -surfs['top active core'] = openmc.ZPlane( - z0=top_active_core, name='top active core') +surfs['bot active core'] = openmc.ZPlane(z0=bottom_fuel_stack, name='bot active core') +surfs['top active core'] = openmc.ZPlane(z0=top_active_core, name='top active core') surfs['top lower thimble'] = surfs['bot active core'] -surfs['BA bot'] = openmc.ZPlane( - z0=bot_burn_abs, name='bottom of BA') +surfs['BA bot'] = openmc.ZPlane(z0=bot_burn_abs, name='bottom of BA') for i, (bottom, top) in enumerate(zip(grid_bottom, grid_top)): # Create plane for bottom of spacer grid @@ -208,17 +181,12 @@ for i, (bottom, top) in enumerate(zip(grid_bottom, grid_top)): name = 'top of grid {}'.format(i + 1) surfs[key] = openmc.ZPlane(z0=top, name=name) -surfs['dashpot top'] = openmc.ZPlane( - z0=step0H, name='top dashpot') +surfs['dashpot top'] = openmc.ZPlane(z0=step0H, name='top dashpot') -surfs['top pin plenum'] = openmc.ZPlane( - z0=top_plenum, name='top pin plenum') -surfs['top FR'] = openmc.ZPlane( - z0=top_fuel_rod, name='top FR') -surfs['bot upper nozzle'] = openmc.ZPlane( - z0=bottom_upper_nozzle, name='bottom upper nozzle') -surfs['top upper nozzle'] = openmc.ZPlane( - z0=top_upper_nozzle, name='top upper nozzle') +surfs['top pin plenum'] = openmc.ZPlane(z0=top_plenum, name='top pin plenum') +surfs['top FR'] = openmc.ZPlane(z0=top_fuel_rod, name='top FR') +surfs['bot upper nozzle'] = openmc.ZPlane(z0=bottom_upper_nozzle, name='bottom upper nozzle') +surfs['top upper nozzle'] = openmc.ZPlane(z0=top_upper_nozzle, name='top upper nozzle') # Control rod bank surfaces for ARO configuration for bank in ['A','B','C','D','E',]: @@ -227,30 +195,19 @@ for bank in ['A','B','C','D','E',]: surfs['bankS{} bot'.format(bank)] = openmc.ZPlane( z0=step248H, name='CR bankS{} bottom'.format(bank)) -surfs['bankA top'] = openmc.ZPlane( - z0=bank_top, name='CR bank A top') -surfs['bankA bot'] = openmc.ZPlane( - z0=bank_bot, name='CR bank A bottom') -surfs['bankB top'] = openmc.ZPlane( - z0=bank_top, name='CR bank B top') -surfs['bankB bot'] = openmc.ZPlane( - z0=bank_bot, name='CR bank B bottom') -surfs['bankC top'] = openmc.ZPlane( - z0=bank_top, name='CR bank C top') -surfs['bankC bot'] = openmc.ZPlane( - z0=bank_bot, name='CR bank C bottom') -surfs['bankD top'] = openmc.ZPlane( - z0=bank_top, name='CR bank D top') -surfs['bankD bot'] = openmc.ZPlane( - z0=bank_bot, name='CR bank D bottom') +surfs['bankA top'] = openmc.ZPlane(z0=bank_top, name='CR bank A top') +surfs['bankA bot'] = openmc.ZPlane(z0=bank_bot, name='CR bank A bottom') +surfs['bankB top'] = openmc.ZPlane(z0=bank_top, name='CR bank B top') +surfs['bankB bot'] = openmc.ZPlane(z0=bank_bot, name='CR bank B bottom') +surfs['bankC top'] = openmc.ZPlane(z0=bank_top, name='CR bank C top') +surfs['bankC bot'] = openmc.ZPlane(z0=bank_bot, name='CR bank C bottom') +surfs['bankD top'] = openmc.ZPlane(z0=bank_top, name='CR bank D top') +surfs['bankD bot'] = openmc.ZPlane(z0=bank_bot, name='CR bank D bottom') # outer radial surfaces -surfs['core barrel IR'] = openmc.ZCylinder( - r=core_barrel_IR, name='core barrel IR') -surfs['core barrel OR'] = openmc.ZCylinder( - r=core_barrel_OR, name='core barrel OR') -surfs['neutron shield OR'] = openmc.ZCylinder( - r=neutron_shield_OR, name='neutron shield OR') +surfs['core barrel IR'] = openmc.ZCylinder(r=core_barrel_IR, name='core barrel IR') +surfs['core barrel OR'] = openmc.ZCylinder(r=core_barrel_OR, name='core barrel OR') +surfs['neutron shield OR'] = openmc.ZCylinder(r=neutron_shield_OR, name='neutron shield OR') # neutron shield planes surfs['neutron shield NWbot SEtop'] = openmc.Plane( @@ -267,10 +224,8 @@ surfs['neutron shield NEtop SWbot'] = openmc.Plane( name='neutron shield NEtop SWbot') # outer radial surfaces -surfs['RPV IR'] = openmc.ZCylinder( - r=rpv_IR, name='RPV IR') -surfs['RPV OR'] = openmc.ZCylinder( - r=rpv_OR, name='RPV OR', boundary_type='vacuum') +surfs['RPV IR'] = openmc.ZCylinder(r=rpv_IR, name='RPV IR') +surfs['RPV OR'] = openmc.ZCylinder(r=rpv_OR, name='RPV OR', boundary_type='vacuum') # outer axial surfaces surfs['upper bound'] = openmc.ZPlane( From f9624e3e2cb3f09fc8fa3139a7756795e4113d05 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Jun 2021 11:04:47 +0700 Subject: [PATCH 05/18] Remove unnecessary import in surfaces.py --- smr/smr/surfaces.py | 1 - 1 file changed, 1 deletion(-) diff --git a/smr/smr/surfaces.py b/smr/smr/surfaces.py index d0653ee..b454c61 100644 --- a/smr/smr/surfaces.py +++ b/smr/smr/surfaces.py @@ -13,7 +13,6 @@ NuScale DC application, chapter 4: https://www.nrc.gov/docs/ML1701/ML17013A274.p """ -import copy from math import tan, pi import numpy as np From 0b3546f23a8f04ab5c7531204415db22d4ffd0fa Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Dec 2019 15:00:03 -0600 Subject: [PATCH 06/18] Remove assemblies with burnable absorber pins --- smr/smr/assemblies.py | 157 ---------------------------------- smr/smr/core.py | 34 ++++---- smr/smr/pins.py | 193 ------------------------------------------ 3 files changed, 17 insertions(+), 367 deletions(-) diff --git a/smr/smr/assemblies.py b/smr/smr/assemblies.py index 2fffb51..b13d0f9 100644 --- a/smr/smr/assemblies.py +++ b/smr/smr/assemblies.py @@ -147,7 +147,6 @@ def assembly_universes(ring_radii, num_axial, depleted): # commonly needed universes gtu = pins['GT empty stack'] gti = pins['GT empty instr'] - bas = pins['BA stack'] ins = pins['IT stack'] crA = pins['GT CR bank A'] crB = pins['GT CR bank B'] @@ -232,33 +231,6 @@ def assembly_universes(ring_radii, num_axial, depleted): univs['Assembly (2.4%) CR D' + comment] = \ make_assembly('Assembly (2.4%) CR D' + comment, universes) - # WITH 12 BURNABLE ABSORBERS - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (2.4%) stack'] - universes[nonfuel_y, nonfuel_x] = [ bas, gtu, bas, - bas, bas, - bas, gtu, gtu, gtu, bas, - gtu, gtu, cent, gtu, gtu, - bas, gtu, gtu, gtu, bas, - bas, bas, - bas, gtu, bas ] - univs['Assembly (2.4%) 12BA' + comment] = \ - make_assembly('Assembly (2.4%) 12BA' + comment, universes) - - # WITH 16 BURNABLE ABSORBERS - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (2.4%) stack'] - universes[nonfuel_y, nonfuel_x] = [ bas, bas, bas, - bas, bas, - bas, gtu, gtu, gtu, bas, - bas, gtu, cent, gtu, bas, - bas, gtu, gtu, gtu, bas, - bas, bas, - bas, bas, bas ] - univs['Assembly (2.4%) 16BA' + comment] = \ - make_assembly('Assembly (2.4%) 16BA' + comment, universes) - - #### 3.1% ENRICHED ASSEMBLIES for cent, comment in [(gti, ''), (ins, ' instr')]: @@ -289,134 +261,5 @@ def assembly_universes(ring_radii, num_axial, depleted): univs['Assembly (3.1%) CR SA' + comment] = \ make_assembly('Assembly (3.1%) CR SA' + comment, universes) - # WITH 20 BURNABLE ABSORBERS - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (3.1%) stack'] - universes[nonfuel_y, nonfuel_x] = [ bas, bas, bas, - bas, bas, - bas, bas, gtu, bas, bas, - bas, gtu, cent, gtu, bas, - bas, bas, gtu, bas, bas, - bas, bas, - bas, bas, bas ] - univs['Assembly (3.1%) 20BA' + comment] = \ - make_assembly('Assembly (3.1%) 20BA' + comment, universes) - - # WITH 16 BURNABLE ABSORBERS - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (3.1%) stack'] - universes[nonfuel_y, nonfuel_x] = [ bas, bas, bas, - bas, bas, - bas, gtu, gtu, gtu, bas, - bas, gtu, cent, gtu, bas, - bas, gtu, gtu, gtu, bas, - bas, bas, - bas, bas, bas ] - univs['Assembly (3.1%) 16BA' + comment] = \ - make_assembly('Assembly (3.1%) 16BA' + comment, universes) - - # WITH 15 BURNABLE ABSORBERS NW - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (3.1%) stack'] - universes[nonfuel_y, nonfuel_x] = [ gtu, gtu, gtu, - gtu, gtu, - gtu, bas, bas, bas, bas, - gtu, bas, cent, bas, bas, - gtu, bas, bas, bas, bas, - gtu, bas, - bas, bas, bas ] - univs['Assembly (3.1%) 15BANW' + comment] = \ - make_assembly('Assembly (3.1%) 15BANW' + comment, universes) - - # WITH 15 BURNABLE ABSORBERS NE - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (3.1%) stack'] - universes[nonfuel_y, nonfuel_x] = [ gtu, gtu, gtu, - gtu, gtu, - bas, bas, bas, bas, gtu, - bas, bas, cent, bas, gtu, - bas, bas, bas, bas, gtu, - bas, gtu, - bas, bas, bas ] - univs['Assembly (3.1%) 15BANE' + comment] = \ - make_assembly('Assembly (3.1%) 15BANE' + comment, universes) - - # WITH 15 BURNABLE ABSORBERS SW - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (3.1%) stack'] - universes[nonfuel_y, nonfuel_x] = [ bas, bas, bas, - gtu, bas, - gtu, bas, bas, bas, bas, - gtu, bas, cent, bas, bas, - gtu, bas, bas, bas, bas, - gtu, gtu, - gtu, gtu, gtu ] - univs['Assembly (3.1%) 15BASW' + comment] = \ - make_assembly('Assembly (3.1%) 15BASW' + comment, universes) - - # WITH 15 BURNABLE ABSORBERS SE - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (3.1%) stack'] - universes[nonfuel_y, nonfuel_x] = [ bas, bas, bas, - bas, gtu, - bas, bas, bas, bas, gtu, - bas, bas, cent, bas, gtu, - bas, bas, bas, bas, gtu, - gtu, gtu, - gtu, gtu, gtu ] - univs['Assembly (3.1%) 15BASE' + comment] = \ - make_assembly('Assembly (3.1%) 15BASE' + comment, universes) - - # WITH 6 BURNABLE ABSORBERS N - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (3.1%) stack'] - universes[nonfuel_y, nonfuel_x] = [ gtu, gtu, gtu, - gtu, gtu, - gtu, gtu, gtu, gtu, gtu, - gtu, gtu, cent, gtu, gtu, - bas, gtu, gtu, gtu, bas, - bas, bas, - bas, gtu, bas ] - univs['Assembly (3.1%) 6BAN' + comment] = \ - make_assembly('Assembly (3.1%) 6BAN' + comment, universes) - - # WITH 6 BURNABLE ABSORBERS S - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (3.1%) stack'] - universes[nonfuel_y, nonfuel_x] = [ bas, gtu, bas, - bas, bas, - bas, gtu, gtu, gtu, bas, - gtu, gtu, cent, gtu, gtu, - gtu, gtu, gtu, gtu, gtu, - gtu, gtu, - gtu, gtu, gtu ] - univs['Assembly (3.1%) 6BAS' + comment] = \ - make_assembly('Assembly (3.1%) 6BAS' + comment, universes) - - # WITH 6 BURNABLE ABSORBERS W - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (3.1%) stack'] - universes[nonfuel_y, nonfuel_x] = [ gtu, gtu, bas, - gtu, bas, - gtu, gtu, gtu, gtu, bas, - gtu, gtu, cent, gtu, gtu, - gtu, gtu, gtu, gtu, bas, - gtu, bas, - gtu, gtu, bas ] - univs['Assembly (3.1%) 6BAW' + comment] = \ - make_assembly('Assembly (3.1%) 6BAW' + comment, universes) - - # WITH 6 BURNABLE ABSORBERS E - universes = np.empty((17,17), dtype=openmc.Universe) - universes[:,:] = pins['Fuel (3.1%) stack'] - universes[nonfuel_y, nonfuel_x] = [ bas, gtu, gtu, - bas, gtu, - bas, gtu, gtu, gtu, gtu, - gtu, gtu, cent, gtu, gtu, - bas, gtu, gtu, gtu, gtu, - bas, gtu, - bas, gtu, gtu ] - univs['Assembly (3.1%) 6BAE' + comment] = \ - make_assembly('Assembly (3.1%) 6BAE' + comment, universes) return univs diff --git a/smr/smr/core.py b/smr/smr/core.py index c150e06..2e75dfe 100644 --- a/smr/smr/core.py +++ b/smr/smr/core.py @@ -46,9 +46,9 @@ def core_geometry(ring_radii, num_axial, depleted): universes[1, 1] = reflector['1,1'] universes[1, 2] = reflector['NW'] - universes[1, 3] = assembly['Assembly (3.1%) instr'] + universes[1, 3] = assembly['Assembly (3.1%)'] universes[1, 4] = assembly['Assembly (2.4%) CR D'] - universes[1, 5] = assembly['Assembly (3.1%) instr'] + universes[1, 5] = assembly['Assembly (3.1%)'] universes[1, 6] = reflector['NE'] universes[1, 7] = reflector['1,7'] @@ -56,47 +56,47 @@ def core_geometry(ring_radii, num_axial, depleted): universes[2, 1] = reflector['NW'] universes[2, 2] = assembly['Assembly (3.1%) instr'] universes[2, 3] = assembly['Assembly (2.4%) CR D'] - universes[2, 4] = assembly['Assembly (3.1%) 16BA'] + universes[2, 4] = assembly['Assembly (3.1%) instr'] universes[2, 5] = assembly['Assembly (2.4%) CR D'] universes[2, 6] = assembly['Assembly (3.1%) instr'] universes[2, 7] = reflector['NE'] universes[2, 8] = reflector['2,8'] universes[3, 0] = reflector['3,0'] - universes[3, 1] = assembly['Assembly (3.1%) instr'] + universes[3, 1] = assembly['Assembly (3.1%)'] universes[3, 2] = assembly['Assembly (2.4%) CR D'] - universes[3, 3] = assembly['Assembly (3.1%) 16BA'] + universes[3, 3] = assembly['Assembly (3.1%) instr'] universes[3, 4] = assembly['Assembly (2.4%) CR D'] - universes[3, 5] = assembly['Assembly (3.1%) 16BA'] + universes[3, 5] = assembly['Assembly (3.1%) instr'] universes[3, 6] = assembly['Assembly (2.4%) CR D'] - universes[3, 7] = assembly['Assembly (3.1%) instr'] + universes[3, 7] = assembly['Assembly (3.1%)'] universes[3, 8] = reflector['3,8'] universes[4, 0] = reflector['4,0'] universes[4, 1] = assembly['Assembly (2.4%) CR D'] - universes[4, 2] = assembly['Assembly (3.1%) 16BA'] + universes[4, 2] = assembly['Assembly (3.1%) instr'] universes[4, 3] = assembly['Assembly (2.4%) CR D'] - universes[4, 4] = assembly['Assembly (1.6%) instr'] + universes[4, 4] = assembly['Assembly (1.6%)'] universes[4, 5] = assembly['Assembly (2.4%) CR D'] - universes[4, 6] = assembly['Assembly (3.1%) 16BA'] + universes[4, 6] = assembly['Assembly (3.1%) instr'] universes[4, 7] = assembly['Assembly (2.4%) CR D'] universes[4, 8] = reflector['4,8'] universes[5, 0] = reflector['5,0'] - universes[5, 1] = assembly['Assembly (3.1%) instr'] + universes[5, 1] = assembly['Assembly (3.1%)'] universes[5, 2] = assembly['Assembly (2.4%) CR D'] - universes[5, 3] = assembly['Assembly (3.1%) 16BA'] + universes[5, 3] = assembly['Assembly (3.1%) instr'] universes[5, 4] = assembly['Assembly (2.4%) CR D'] - universes[5, 5] = assembly['Assembly (3.1%) 16BA'] + universes[5, 5] = assembly['Assembly (3.1%) instr'] universes[5, 6] = assembly['Assembly (2.4%) CR D'] - universes[5, 7] = assembly['Assembly (3.1%) instr'] + universes[5, 7] = assembly['Assembly (3.1%)'] universes[5, 8] = reflector['5,8'] universes[6, 0] = reflector['6,0'] universes[6, 1] = reflector['SW'] universes[6, 2] = assembly['Assembly (3.1%) instr'] universes[6, 3] = assembly['Assembly (2.4%) CR D'] - universes[6, 4] = assembly['Assembly (3.1%) 16BA'] + universes[6, 4] = assembly['Assembly (3.1%) instr'] universes[6, 5] = assembly['Assembly (2.4%) CR D'] universes[6, 6] = assembly['Assembly (3.1%) instr'] universes[6, 7] = reflector['SE'] @@ -104,9 +104,9 @@ def core_geometry(ring_radii, num_axial, depleted): universes[7, 1] = reflector['7,1'] universes[7, 2] = reflector['SW'] - universes[7, 3] = assembly['Assembly (3.1%) instr'] + universes[7, 3] = assembly['Assembly (3.1%)'] universes[7, 4] = assembly['Assembly (2.4%) CR D'] - universes[7, 5] = assembly['Assembly (3.1%) instr'] + universes[7, 5] = assembly['Assembly (3.1%)'] universes[7, 6] = reflector['SE'] universes[7, 7] = reflector['7,7'] diff --git a/smr/smr/pins.py b/smr/smr/pins.py index d804951..3966997 100644 --- a/smr/smr/pins.py +++ b/smr/smr/pins.py @@ -473,199 +473,6 @@ def pin_universes(ring_radii=None, num_axial=196, depleted=False): univs['GT CR bank {} dummy bare'.format(b)]]) - #### BURNABLE ABSORBER PIN CELLS - - univs['BA'] = make_pin( - 'BA', - surfaces=[surfs['BA IR 1'], - surfs['BA IR 2'], - surfs['BA IR 3'], - surfs['BA IR 4'], - surfs['BA IR 5'], - surfs['BA IR 6'], - surfs['BA IR 7'], - surfs['BA IR 8']], - materials=[mats['Air'], - mats['SS'], - mats['Air'], - mats['BSG'], - mats['Air'], - mats['SS'], - mats['H2O'], - mats['Zr'], - mats['H2O']]) - - univs['BA grid (bottom)'] = make_pin( - 'BA grid (bottom)', - surfaces=[surfs['BA IR 1'], - surfs['BA IR 2'], - surfs['BA IR 3'], - surfs['BA IR 4'], - surfs['BA IR 5'], - surfs['BA IR 6'], - surfs['BA IR 7'], - surfs['BA IR 8']], - materials=[mats['Air'], - mats['SS'], - mats['Air'], - mats['BSG'], - mats['Air'], - mats['SS'], - mats['H2O'], - mats['Zr'], - mats['H2O']], - grid='bottom') - - univs['BA grid (intermediate)'] = make_pin( - 'BA grid (intermediate)', - surfaces=[surfs['BA IR 1'], - surfs['BA IR 2'], - surfs['BA IR 3'], - surfs['BA IR 4'], - surfs['BA IR 5'], - surfs['BA IR 6'], - surfs['BA IR 7'], - surfs['BA IR 8']], - materials=[mats['Air'], - mats['SS'], - mats['Air'], - mats['BSG'], - mats['Air'], - mats['SS'], - mats['H2O'], - mats['Zr'], - mats['H2O']], - grid='intermediate') - - univs['BA dashpot'] = make_pin( - 'BA dashpot', - surfaces=[surfs['BA IR 1'], - surfs['BA IR 2'], - surfs['BA IR 3'], - surfs['BA IR 4'], - surfs['BA IR 5'], - surfs['BA IR 6'], - surfs['GT dashpot IR'], - surfs['GT dashpot OR']], - materials=[mats['Air'], - mats['SS'], - mats['Air'], - mats['BSG'], - mats['Air'], - mats['SS'], - mats['H2O'], - mats['Zr'], - mats['H2O']]) - - univs['BA dashpot grid (bottom)'] = make_pin( - 'BA dashpot grid (bottom)', - surfaces=[surfs['BA IR 1'], - surfs['BA IR 2'], - surfs['BA IR 3'], - surfs['BA IR 4'], - surfs['BA IR 5'], - surfs['BA IR 6'], - surfs['GT dashpot IR'], - surfs['GT dashpot OR']], - materials=[mats['Air'], - mats['SS'], - mats['Air'], - mats['BSG'], - mats['Air'], - mats['SS'], - mats['H2O'], - mats['Zr'], - mats['H2O']], - grid='bottom') - - univs['BA dashpot grid (intermediate)'] = make_pin( - 'BA dashpot grid (intermediate)', - surfaces=[surfs['BA IR 1'], - surfs['BA IR 2'], - surfs['BA IR 3'], - surfs['BA IR 4'], - surfs['BA IR 5'], - surfs['BA IR 6'], - surfs['GT dashpot IR'], - surfs['GT dashpot OR']], - materials=[mats['Air'], - mats['SS'], - mats['Air'], - mats['BSG'], - mats['Air'], - mats['SS'], - mats['H2O'], - mats['Zr'], - mats['H2O']], - grid='intermediate') - - univs['BA blank SS'] = make_pin( - 'BA blank SS', - surfaces=[surfs['BA IR 6'], - surfs['BA IR 7'], - surfs['BA IR 8']], - materials=[mats['SS'], - mats['H2O'], - mats['Zr'], - mats['H2O']]) - - univs['BA blank SS bare'] = make_pin( - 'BA blank SS bare', - surfaces=[surfs['BA IR 6']], - materials=[mats['SS'], - mats['H2O']]) - - stack_surfs_BA = [ - surfs['bot support plate'], - surfs['top support plate'], - surfs['top lower nozzle'], - surfs['top lower thimble'], - surfs['grid1bot'], - surfs['BA bot'], - surfs['grid1top'], - surfs['dashpot top'], - surfs['grid2bot'], - surfs['grid2top'], - surfs['grid3bot'], - surfs['grid3top'], - surfs['grid4bot'], - surfs['grid4top'], - surfs['top active core'], - surfs['grid5bot'], - surfs['grid5top'], - surfs['top pin plenum'], - surfs['top FR'], - surfs['bot upper nozzle'], - surfs['top upper nozzle']] - - # Stack all axial pieces of control rod tubes together for each bank - - univs['BA stack'] = make_stack( - 'BA stack', stack_surfs_BA, - universes=[univs['water pin'], - univs['water pin'], - univs['water pin'], - univs['GTd empty'], - univs['GTd empty'], - univs['GTd empty grid (bottom)'], - univs['BA dashpot grid (bottom)'], - univs['BA dashpot'], - univs['BA'], - univs['BA grid (intermediate)'], - univs['BA'], - univs['BA grid (intermediate)'], - univs['BA'], - univs['BA grid (intermediate)'], - univs['BA'], - univs['BA blank SS'], - univs['BA blank SS'], - univs['BA blank SS'], - univs['BA blank SS'], - univs['BA blank SS'], - univs['BA blank SS bare'], - univs['water pin']]) - - # Fuel pin cells univs['SS pin'] = make_pin( 'SS pin', From 6abc157770303149bbd8d0c1be45df27fe0b8d39 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 21 Jun 2021 11:58:42 +0700 Subject: [PATCH 07/18] Add script for building short full core, manually change lattice_pitch --- smr/build-core-short.py | 118 ++++++++++++++++++++++++++++++++++++++++ smr/smr/surfaces.py | 3 +- 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 smr/build-core-short.py diff --git a/smr/build-core-short.py b/smr/build-core-short.py new file mode 100644 index 0000000..5ed19b9 --- /dev/null +++ b/smr/build-core-short.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 + +import os +import shutil +import copy +import argparse +from math import pi +from pathlib import Path + +import numpy as np + +import openmc +from smr.materials import materials +from smr.plots import core_plots +from smr.surfaces import lattice_pitch, bottom_fuel_stack, top_active_core, \ + pellet_OR, surfs, pin_pitch +import smr.surfaces +import smr.pins +from smr.core import core_geometry +from smr import inlet_temperature + + +# Define command-line options +parser = argparse.ArgumentParser() +parser.add_argument('--multipole', action='store_true', + help='Use multipole cross sections') +parser.add_argument('--no-multipole', action='store_false', + help='Do not use multipole cross sections') +parser.add_argument('-a', '--axial', type=int, default=3, + help='Number of axial subdivisions in fuel') +parser.add_argument('-d', '--depleted', action='store_true', + help='Whether UO2 compositions should represent depleted fuel') +parser.add_argument('-o', '--output-dir', type=Path, default=None) +parser.set_defaults(multipole=True) +args = parser.parse_args() + +# Make directory for inputs +if args.output_dir is None: + if args.depleted: + directory = Path('core-short-depleted') + else: + directory = Path('core-short-fresh') +else: + directory = args.output_dir +directory.mkdir(exist_ok=True) + +# Modify fuel length +length = 3. * pin_pitch +smr.surfaces.active_fuel_length = length +smr.pins.top_active_core = length +surfs['top active core'].z0 = length + +# Change top and bottom of model to contain only fuel +surfs['lower bound'].z0 = 0.0 +surfs['lower bound'].boundary_type = 'reflective' +surfs['upper bound'].z0 = length +surfs['upper bound'].boundary_type = 'reflective' + +ring_radii = [0.1*pin_pitch, 0.2*pin_pitch] + +geometry = core_geometry(ring_radii, args.axial, args.depleted) + +h = length / args.axial +fuel_mats = {} + +fuel_volume = pi * pellet_OR**2 * h / (len(ring_radii) + 1) +for cell in geometry.get_all_cells().values(): + if cell.fill in materials: + # Determine volume of each fuel material + if 'UO2 Fuel' in cell.fill.name: + r_o = cell.region.bounding_box[1][0] + if r_o not in fuel_mats: + cell.fill = cell.fill.clone() + cell.fill.volume = fuel_volume + fuel_mats[r_o] = cell.fill + else: + cell.fill = fuel_mats[r_o] + else: + cell.fill.volume = 1.0 + + +#### Create OpenMC "materials.xml" file +all_materials = geometry.get_all_materials() +materials = openmc.Materials(all_materials.values()) +materials.export_to_xml(str(directory / 'materials.xml')) + + +#### Create OpenMC "geometry.xml" file +geometry.export_to_xml(str(directory / 'geometry.xml')) + + +#### Create OpenMC "settings.xml" file + +# Construct uniform initial source distribution over fissionable zones +lower_left = [-7.*lattice_pitch/2., -7.*lattice_pitch/2., bottom_fuel_stack] +upper_right = [+7.*lattice_pitch/2., +7.*lattice_pitch/2., top_active_core] +source = openmc.source.Source(space=openmc.stats.Box(lower_left, upper_right)) +source.space.only_fissionable = True + +settings = openmc.Settings() +settings.batches = 200 +settings.inactive = 100 +settings.particles = 10000 +settings.output = {'tallies': False, 'summary': False} +settings.source = source +settings.sourcepoint_write = False + +settings.temperature = { + 'default': inlet_temperature, + 'method': 'interpolation', + 'range': (300.0, 1500.0), +} +if args.multipole: + settings.temperature['multipole'] = True + settings.temperature['tolerance'] = 1000 + +settings.export_to_xml(str(directory / 'settings.xml')) + diff --git a/smr/smr/surfaces.py b/smr/smr/surfaces.py index b454c61..d91ec92 100644 --- a/smr/smr/surfaces.py +++ b/smr/smr/surfaces.py @@ -69,7 +69,8 @@ spacer_height = 1.750*INCHES # ML17013A274, Figure 4.2-7 # assembly parameters assembly_length = 95.89*INCHES # ML17013A274, Table 4.1-2 pin_pitch = 0.496*INCHES # ML17013A274, Table 4.1-2 -lattice_pitch = 8.466*INCHES # ML17013A274, Table 4.1-2 +#lattice_pitch = 8.466*INCHES # ML17013A274, Table 4.1-2 +lattice_pitch = 17*pin_pitch grid_strap_side = 21.47270 top_nozzle_height = 3.551*INCHES # ML17013A274, Figure 4.2-2 top_nozzle_width = 8.406*INCHES # ML17013A274, Figure 4.2-2 From 1713a4df1b49e09c4530e034946afa597c124a4c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 26 Jul 2021 22:36:48 -0500 Subject: [PATCH 08/18] Fix volumes in fullcore short model --- smr/build-core-short.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/smr/build-core-short.py b/smr/build-core-short.py index 5ed19b9..2e3033f 100644 --- a/smr/build-core-short.py +++ b/smr/build-core-short.py @@ -4,7 +4,7 @@ import os import shutil import copy import argparse -from math import pi +from math import pi, isclose from pathlib import Path import numpy as np @@ -13,7 +13,7 @@ import openmc from smr.materials import materials from smr.plots import core_plots from smr.surfaces import lattice_pitch, bottom_fuel_stack, top_active_core, \ - pellet_OR, surfs, pin_pitch + pellet_OR, surfs, pin_pitch, clad_IR, clad_OR import smr.surfaces import smr.pins from smr.core import core_geometry @@ -63,18 +63,27 @@ geometry = core_geometry(ring_radii, args.axial, args.depleted) h = length / args.axial fuel_mats = {} -fuel_volume = pi * pellet_OR**2 * h / (len(ring_radii) + 1) for cell in geometry.get_all_cells().values(): if cell.fill in materials: # Determine volume of each fuel material if 'UO2 Fuel' in cell.fill.name: - r_o = cell.region.bounding_box[1][0] - if r_o not in fuel_mats: - cell.fill = cell.fill.clone() - cell.fill.volume = fuel_volume - fuel_mats[r_o] = cell.fill + upper_right = cell.region.bounding_box[1][0] + if isclose(upper_right, ring_radii[0]): + ri, ro = 0.0, ring_radii[0] + elif isclose(upper_right, ring_radii[1]): + ri, ro = ring_radii[0], ring_radii[1] else: - cell.fill = fuel_mats[r_o] + ri, ro = ring_radii[1], pellet_OR + if ri not in fuel_mats: + cell.fill = cell.fill.clone() + cell.fill.volume = pi * (ro*ro - ri*ri) * h + fuel_mats[ri] = cell.fill + else: + cell.fill = fuel_mats[ri] + elif cell.fill.name == 'Helium': + cell.fill.volume = pi * (clad_IR**2 - pellet_OR**2) * h + elif cell.fill.name == 'M5': + cell.fill.volume = pi * (clad_OR**2 - clad_IR**2) * h else: cell.fill.volume = 1.0 From c9554e003a218dcd9140f7e44f0041931bb70835 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 9 Aug 2021 12:40:55 -0500 Subject: [PATCH 09/18] Fix volume assignment to clad/gap, use proper assemblies --- smr/build-core-short.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/smr/build-core-short.py b/smr/build-core-short.py index 2e3033f..317a8a0 100644 --- a/smr/build-core-short.py +++ b/smr/build-core-short.py @@ -66,7 +66,8 @@ fuel_mats = {} for cell in geometry.get_all_cells().values(): if cell.fill in materials: # Determine volume of each fuel material - if 'UO2 Fuel' in cell.fill.name: + name = cell.fill.name + if 'UO2 Fuel' in name: upper_right = cell.region.bounding_box[1][0] if isclose(upper_right, ring_radii[0]): ri, ro = 0.0, ring_radii[0] @@ -74,16 +75,17 @@ for cell in geometry.get_all_cells().values(): ri, ro = ring_radii[0], ring_radii[1] else: ri, ro = ring_radii[1], pellet_OR - if ri not in fuel_mats: + if (name, ri) not in fuel_mats: cell.fill = cell.fill.clone() cell.fill.volume = pi * (ro*ro - ri*ri) * h - fuel_mats[ri] = cell.fill + fuel_mats[name, ri] = cell.fill else: - cell.fill = fuel_mats[ri] - elif cell.fill.name == 'Helium': + cell.fill = fuel_mats[name, ri] + elif name == 'Helium': cell.fill.volume = pi * (clad_IR**2 - pellet_OR**2) * h - elif cell.fill.name == 'M5': - cell.fill.volume = pi * (clad_OR**2 - clad_IR**2) * h + elif name == 'M5': + # Clad is not subdivided + cell.fill.volume = pi * (clad_OR**2 - clad_IR**2) * length else: cell.fill.volume = 1.0 @@ -93,7 +95,6 @@ all_materials = geometry.get_all_materials() materials = openmc.Materials(all_materials.values()) materials.export_to_xml(str(directory / 'materials.xml')) - #### Create OpenMC "geometry.xml" file geometry.export_to_xml(str(directory / 'geometry.xml')) @@ -125,3 +126,11 @@ if args.multipole: settings.export_to_xml(str(directory / 'settings.xml')) +# Check assembly power distribution +core_lattice = geometry.get_cells_by_fill_name('Main core')[0].fill +mesh = openmc.RegularMesh.from_rect_lattice(core_lattice) +assembly_power = openmc.Tally() +assembly_power.filters = [openmc.MeshFilter(mesh)] +assembly_power.scores = ['nu-fission'] +tallies = openmc.Tallies([assembly_power]) +tallies.export_to_xml(directory / 'tallies.xml') From 2a8764b04f5aaf06741f6af0e056693bf93be1bf Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 9 Aug 2021 12:43:58 -0500 Subject: [PATCH 10/18] Change enrichment pattern to flatten power distribution --- smr/smr/assemblies.py | 2 +- smr/smr/core.py | 58 +++++++++++++++++++++---------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/smr/smr/assemblies.py b/smr/smr/assemblies.py index b13d0f9..6f10aaa 100644 --- a/smr/smr/assemblies.py +++ b/smr/smr/assemblies.py @@ -215,7 +215,7 @@ def assembly_universes(ring_radii, num_axial, depleted): gtu, gtu, gtu, gtu, gtu, gtu, gtu, gtu, gtu, gtu ] - univs['Assembly (2.4%) no BAs' + comment] = \ + univs['Assembly (2.4%)' + comment] = \ make_assembly('Assembly (2.4%) no BAs' + comment, universes) # WITH CONTROL ROD D BANK diff --git a/smr/smr/core.py b/smr/smr/core.py index 2e75dfe..68f3275 100644 --- a/smr/smr/core.py +++ b/smr/smr/core.py @@ -47,65 +47,65 @@ def core_geometry(ring_radii, num_axial, depleted): universes[1, 1] = reflector['1,1'] universes[1, 2] = reflector['NW'] universes[1, 3] = assembly['Assembly (3.1%)'] - universes[1, 4] = assembly['Assembly (2.4%) CR D'] + universes[1, 4] = assembly['Assembly (3.1%)'] universes[1, 5] = assembly['Assembly (3.1%)'] universes[1, 6] = reflector['NE'] universes[1, 7] = reflector['1,7'] universes[2, 0] = reflector['2,0'] universes[2, 1] = reflector['NW'] - universes[2, 2] = assembly['Assembly (3.1%) instr'] - universes[2, 3] = assembly['Assembly (2.4%) CR D'] - universes[2, 4] = assembly['Assembly (3.1%) instr'] - universes[2, 5] = assembly['Assembly (2.4%) CR D'] - universes[2, 6] = assembly['Assembly (3.1%) instr'] + universes[2, 2] = assembly['Assembly (3.1%)'] + universes[2, 3] = assembly['Assembly (2.4%)'] + universes[2, 4] = assembly['Assembly (1.6%)'] + universes[2, 5] = assembly['Assembly (2.4%)'] + universes[2, 6] = assembly['Assembly (3.1%)'] universes[2, 7] = reflector['NE'] universes[2, 8] = reflector['2,8'] universes[3, 0] = reflector['3,0'] universes[3, 1] = assembly['Assembly (3.1%)'] - universes[3, 2] = assembly['Assembly (2.4%) CR D'] - universes[3, 3] = assembly['Assembly (3.1%) instr'] - universes[3, 4] = assembly['Assembly (2.4%) CR D'] - universes[3, 5] = assembly['Assembly (3.1%) instr'] - universes[3, 6] = assembly['Assembly (2.4%) CR D'] + universes[3, 2] = assembly['Assembly (2.4%)'] + universes[3, 3] = assembly['Assembly (1.6%)'] + universes[3, 4] = assembly['Assembly (1.6%)'] + universes[3, 5] = assembly['Assembly (1.6%)'] + universes[3, 6] = assembly['Assembly (2.4%)'] universes[3, 7] = assembly['Assembly (3.1%)'] universes[3, 8] = reflector['3,8'] universes[4, 0] = reflector['4,0'] - universes[4, 1] = assembly['Assembly (2.4%) CR D'] - universes[4, 2] = assembly['Assembly (3.1%) instr'] - universes[4, 3] = assembly['Assembly (2.4%) CR D'] - universes[4, 4] = assembly['Assembly (1.6%)'] - universes[4, 5] = assembly['Assembly (2.4%) CR D'] - universes[4, 6] = assembly['Assembly (3.1%) instr'] - universes[4, 7] = assembly['Assembly (2.4%) CR D'] + universes[4, 1] = assembly['Assembly (3.1%)'] + universes[4, 2] = assembly['Assembly (1.6%)'] + universes[4, 3] = assembly['Assembly (1.6%)'] + universes[4, 4] = assembly['Assembly (2.4%)'] + universes[4, 5] = assembly['Assembly (1.6%)'] + universes[4, 6] = assembly['Assembly (1.6%)'] + universes[4, 7] = assembly['Assembly (3.1%)'] universes[4, 8] = reflector['4,8'] universes[5, 0] = reflector['5,0'] universes[5, 1] = assembly['Assembly (3.1%)'] - universes[5, 2] = assembly['Assembly (2.4%) CR D'] - universes[5, 3] = assembly['Assembly (3.1%) instr'] - universes[5, 4] = assembly['Assembly (2.4%) CR D'] - universes[5, 5] = assembly['Assembly (3.1%) instr'] - universes[5, 6] = assembly['Assembly (2.4%) CR D'] + universes[5, 2] = assembly['Assembly (2.4%)'] + universes[5, 3] = assembly['Assembly (1.6%)'] + universes[5, 4] = assembly['Assembly (1.6%)'] + universes[5, 5] = assembly['Assembly (1.6%)'] + universes[5, 6] = assembly['Assembly (2.4%)'] universes[5, 7] = assembly['Assembly (3.1%)'] universes[5, 8] = reflector['5,8'] universes[6, 0] = reflector['6,0'] universes[6, 1] = reflector['SW'] - universes[6, 2] = assembly['Assembly (3.1%) instr'] - universes[6, 3] = assembly['Assembly (2.4%) CR D'] - universes[6, 4] = assembly['Assembly (3.1%) instr'] - universes[6, 5] = assembly['Assembly (2.4%) CR D'] - universes[6, 6] = assembly['Assembly (3.1%) instr'] + universes[6, 2] = assembly['Assembly (3.1%)'] + universes[6, 3] = assembly['Assembly (2.4%)'] + universes[6, 4] = assembly['Assembly (1.6%)'] + universes[6, 5] = assembly['Assembly (2.4%)'] + universes[6, 6] = assembly['Assembly (3.1%)'] universes[6, 7] = reflector['SE'] universes[6, 8] = reflector['6,8'] universes[7, 1] = reflector['7,1'] universes[7, 2] = reflector['SW'] universes[7, 3] = assembly['Assembly (3.1%)'] - universes[7, 4] = assembly['Assembly (2.4%) CR D'] + universes[7, 4] = assembly['Assembly (3.1%)'] universes[7, 5] = assembly['Assembly (3.1%)'] universes[7, 6] = reflector['SE'] universes[7, 7] = reflector['7,7'] From 30355e218c42c19e16744a9762eedd86a78bca4a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 Aug 2021 07:39:01 -0500 Subject: [PATCH 11/18] Add script for building full length core model --- smr/build-core-long.py | 116 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 smr/build-core-long.py diff --git a/smr/build-core-long.py b/smr/build-core-long.py new file mode 100644 index 0000000..9fba0e5 --- /dev/null +++ b/smr/build-core-long.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +import argparse +from math import pi, isclose +from pathlib import Path + +import openmc +from smr.materials import materials +from smr.surfaces import lattice_pitch, bottom_fuel_stack, top_active_core, \ + pellet_OR, pin_pitch, clad_IR, clad_OR, active_fuel_length +from smr.core import core_geometry +from smr import inlet_temperature + + +# Define command-line options +parser = argparse.ArgumentParser() +parser.add_argument('--multipole', action='store_true', + help='Use multipole cross sections') +parser.add_argument('--no-multipole', action='store_false', + help='Do not use multipole cross sections') +parser.add_argument('-a', '--axial', type=int, default=100, + help='Number of axial subdivisions in fuel') +parser.add_argument('-d', '--depleted', action='store_true', + help='Whether UO2 compositions should represent depleted fuel') +parser.add_argument('-o', '--output-dir', type=Path, default=None) +parser.set_defaults(multipole=True) +args = parser.parse_args() + +# Make directory for inputs +if args.output_dir is None: + if args.depleted: + directory = Path('core-long-depleted') + else: + directory = Path('core-long-fresh') +else: + directory = args.output_dir +directory.mkdir(exist_ok=True) + +ring_radii = [0.1*pin_pitch, 0.2*pin_pitch] + +geometry = core_geometry(ring_radii, args.axial, args.depleted) + +h = active_fuel_length / args.axial +fuel_mats = {} + +for cell in geometry.get_all_cells().values(): + if cell.fill in materials: + # Determine volume of each fuel material + name = cell.fill.name + if 'UO2 Fuel' in name: + upper_right = cell.region.bounding_box[1][0] + if isclose(upper_right, ring_radii[0]): + ri, ro = 0.0, ring_radii[0] + elif isclose(upper_right, ring_radii[1]): + ri, ro = ring_radii[0], ring_radii[1] + else: + ri, ro = ring_radii[1], pellet_OR + if (name, ri) not in fuel_mats: + cell.fill = cell.fill.clone() + cell.fill.volume = pi * (ro*ro - ri*ri) * h + fuel_mats[name, ri] = cell.fill + else: + cell.fill = fuel_mats[name, ri] + elif name == 'Helium': + cell.fill.volume = pi * (clad_IR**2 - pellet_OR**2) * h + elif name == 'M5': + # Clad is not subdivided + cell.fill.volume = pi * (clad_OR**2 - clad_IR**2) * active_fuel_length + else: + cell.fill.volume = 1.0 + + +#### Create OpenMC "materials.xml" file +all_materials = geometry.get_all_materials() +materials = openmc.Materials(all_materials.values()) +materials.export_to_xml(str(directory / 'materials.xml')) + +#### Create OpenMC "geometry.xml" file +geometry.export_to_xml(str(directory / 'geometry.xml')) + + +#### Create OpenMC "settings.xml" file + +# Construct uniform initial source distribution over fissionable zones +lower_left = [-7.*lattice_pitch/2., -7.*lattice_pitch/2., bottom_fuel_stack] +upper_right = [+7.*lattice_pitch/2., +7.*lattice_pitch/2., top_active_core] +source = openmc.source.Source(space=openmc.stats.Box(lower_left, upper_right)) +source.space.only_fissionable = True + +settings = openmc.Settings() +settings.batches = 200 +settings.inactive = 100 +settings.particles = 20_000_000 +settings.output = {'tallies': False, 'summary': False} +settings.source = source +settings.sourcepoint_write = False + +settings.temperature = { + 'default': inlet_temperature, + 'method': 'interpolation', + 'range': (300.0, 1500.0), +} +if args.multipole: + settings.temperature['multipole'] = True + settings.temperature['tolerance'] = 1000 + +settings.export_to_xml(str(directory / 'settings.xml')) + +# Check assembly power distribution +core_lattice = geometry.get_cells_by_fill_name('Main core')[0].fill +mesh = openmc.RegularMesh.from_rect_lattice(core_lattice) +assembly_power = openmc.Tally() +assembly_power.filters = [openmc.MeshFilter(mesh)] +assembly_power.scores = ['nu-fission'] +tallies = openmc.Tallies([assembly_power]) +tallies.export_to_xml(directory / 'tallies.xml') From 9c4c8c87fbda027907de5e5392321d570fdbe650 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 6 Jun 2022 21:32:09 -0500 Subject: [PATCH 12/18] Only modify lattice_pitch in build-core-short/long.py scripts --- smr/build-core-long.py | 9 ++++++--- smr/build-core-short.py | 12 ++++-------- smr/smr/core.py | 4 +++- smr/smr/reflector.py | 3 ++- smr/smr/surfaces.py | 3 +-- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/smr/build-core-long.py b/smr/build-core-long.py index 9fba0e5..c3531c6 100644 --- a/smr/build-core-long.py +++ b/smr/build-core-long.py @@ -6,17 +6,17 @@ from pathlib import Path import openmc from smr.materials import materials -from smr.surfaces import lattice_pitch, bottom_fuel_stack, top_active_core, \ +from smr.surfaces import bottom_fuel_stack, top_active_core, \ pellet_OR, pin_pitch, clad_IR, clad_OR, active_fuel_length from smr.core import core_geometry from smr import inlet_temperature - +import smr.surfaces # Define command-line options parser = argparse.ArgumentParser() parser.add_argument('--multipole', action='store_true', help='Use multipole cross sections') -parser.add_argument('--no-multipole', action='store_false', +parser.add_argument('--no-multipole', dest='multipole', action='store_false', help='Do not use multipole cross sections') parser.add_argument('-a', '--axial', type=int, default=100, help='Number of axial subdivisions in fuel') @@ -36,6 +36,9 @@ else: directory = args.output_dir directory.mkdir(exist_ok=True) +# Modify lattice pitch +smr.surfaces.lattice_pitch = lattice_pitch = 17*smr.surfaces.pin_pitch + ring_radii = [0.1*pin_pitch, 0.2*pin_pitch] geometry = core_geometry(ring_radii, args.axial, args.depleted) diff --git a/smr/build-core-short.py b/smr/build-core-short.py index 317a8a0..e9cabc8 100644 --- a/smr/build-core-short.py +++ b/smr/build-core-short.py @@ -1,25 +1,18 @@ #!/usr/bin/env python3 -import os -import shutil -import copy import argparse from math import pi, isclose from pathlib import Path -import numpy as np - import openmc from smr.materials import materials -from smr.plots import core_plots -from smr.surfaces import lattice_pitch, bottom_fuel_stack, top_active_core, \ +from smr.surfaces import bottom_fuel_stack, top_active_core, \ pellet_OR, surfs, pin_pitch, clad_IR, clad_OR import smr.surfaces import smr.pins from smr.core import core_geometry from smr import inlet_temperature - # Define command-line options parser = argparse.ArgumentParser() parser.add_argument('--multipole', action='store_true', @@ -44,6 +37,9 @@ else: directory = args.output_dir directory.mkdir(exist_ok=True) +# Modify lattice pitch +smr.surfaces.lattice_pitch = lattice_pitch = 17*smr.surfaces.pin_pitch + # Modify fuel length length = 3. * pin_pitch smr.surfaces.active_fuel_length = length diff --git a/smr/smr/core.py b/smr/smr/core.py index 68f3275..81763fe 100644 --- a/smr/smr/core.py +++ b/smr/smr/core.py @@ -5,9 +5,9 @@ import numpy as np import openmc from .materials import mats -from .surfaces import surfs, lattice_pitch from .reflector import reflector_universes from .assemblies import assembly_universes +from smr import surfaces def core_geometry(ring_radii, num_axial, depleted): @@ -34,6 +34,7 @@ def core_geometry(ring_radii, num_axial, depleted): # Construct main core lattice core = openmc.RectLattice(name='Main core') + lattice_pitch = surfaces.lattice_pitch core.lower_left = (-9*lattice_pitch/2, -9*lattice_pitch/2) core.pitch = (lattice_pitch, lattice_pitch) universes = np.tile(reflector['solid'], (9, 9)) @@ -119,6 +120,7 @@ def core_geometry(ring_radii, num_axial, depleted): core.universes = universes root_univ = openmc.Universe(universe_id=0, name='root universe') + surfs = surfaces.surfs # Cylinder filled with core lattice cell = openmc.Cell(name='Main core') diff --git a/smr/smr/reflector.py b/smr/smr/reflector.py index ed143cc..74aa4bd 100644 --- a/smr/smr/reflector.py +++ b/smr/smr/reflector.py @@ -12,7 +12,7 @@ converted to actual dimensions by scaling according to the width of an assembly. import openmc from .materials import mats -from .surfaces import lattice_pitch +from smr import surfaces def make_reflector(name, parameters): @@ -91,6 +91,7 @@ def reflector_universes(): # All pixel widths are scaled according to the actual width of an assembly # divided by the width of an assembly in pixels + lattice_pitch = surfaces.lattice_pitch scale = lattice_pitch/width # Physical positions diff --git a/smr/smr/surfaces.py b/smr/smr/surfaces.py index d91ec92..b454c61 100644 --- a/smr/smr/surfaces.py +++ b/smr/smr/surfaces.py @@ -69,8 +69,7 @@ spacer_height = 1.750*INCHES # ML17013A274, Figure 4.2-7 # assembly parameters assembly_length = 95.89*INCHES # ML17013A274, Table 4.1-2 pin_pitch = 0.496*INCHES # ML17013A274, Table 4.1-2 -#lattice_pitch = 8.466*INCHES # ML17013A274, Table 4.1-2 -lattice_pitch = 17*pin_pitch +lattice_pitch = 8.466*INCHES # ML17013A274, Table 4.1-2 grid_strap_side = 21.47270 top_nozzle_height = 3.551*INCHES # ML17013A274, Figure 4.2-2 top_nozzle_width = 8.406*INCHES # ML17013A274, Figure 4.2-2 From f62a9c610f44ec0bad426c33cdcdaf868119d90c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 6 Jun 2022 22:01:59 -0500 Subject: [PATCH 13/18] Add markdown description of milestone models --- smr/milestones.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 smr/milestones.md diff --git a/smr/milestones.md b/smr/milestones.md new file mode 100644 index 0000000..bb89864 --- /dev/null +++ b/smr/milestones.md @@ -0,0 +1,20 @@ +# Milestone Models + +- **AD-SE-08-61, Coupled Multiphysics Driver Implementation** --- This milestone + used the singlerod short/long problems. Generating the model was done with the + script `tests/singlerod/make_openmc_model.py` from the ENRICO repository + (there is a `--short` command line option to generate the short version) + +- **AD-SE-08-66, Coupled Assembly Analysis** --- This milestone used the + assembly short and long (v2) problems. Generating the model was done with + `smr/build-assembly-long.py -a 100 --clone` on the ecp-benchmarks repository + (git commit `631fefe`, after pull request #14). In these models, materials are + fully differentiated across each fuel ring/axial segment. + +- **AD-SE-08-73, Full core coupled-physics simulation** --- This milestone used + the core-short and core-long (90 layer) models. Generating the models was done + with `smr/build-core-short.py` and `smr/build-assembly-long.py -a 90` on the + ecp-benchmarks repository (git commit `c7b89db`, after pull request #16). In + these models, materials are not differentiated and no grid spacers are + present. The lattice pitch is modified to be exactly 17 times the pin pitch + (slightly different than NuScale specification). From 3bdd23096adc845bf5fb76a5109bc2cbebf99b71 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 6 Jun 2022 22:07:36 -0500 Subject: [PATCH 14/18] Put clone function in smr/materials.py --- smr/build-assembly-long.py | 13 ++----------- smr/build-assembly-short.py | 11 +---------- smr/build-assembly.py | 11 +---------- smr/build-core-fresh.py | 9 +-------- smr/smr/materials.py | 9 +++++++++ 5 files changed, 14 insertions(+), 39 deletions(-) diff --git a/smr/build-assembly-long.py b/smr/build-assembly-long.py index 28447a0..98ade14 100644 --- a/smr/build-assembly-long.py +++ b/smr/build-assembly-long.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import argparse -import copy from math import pi, isclose from pathlib import Path @@ -9,10 +8,9 @@ import numpy as np from tqdm import tqdm import openmc -from smr.materials import materials, mats +from smr.materials import materials, clone from smr.surfaces import surfs, lattice_pitch, pin_pitch, bottom_fuel_stack, \ - top_active_core, pellet_OR, clad_OR, clad_IR, guide_tube_IR, guide_tube_OR, \ - active_fuel_length + top_active_core, pellet_OR, active_fuel_length from smr.pins import pin_universes, make_stack @@ -101,13 +99,6 @@ for halfspace in surfs['lat grid box inner']: # Define geometry with a single assembly geometry = openmc.Geometry(root_universe) - -def clone(material): - """Perform copy of material but share nuclide densities""" - shared_mat = copy.copy(material) - shared_mat.id = None - return shared_mat - h = active_fuel_length / args.axial fuel_mats = {} diff --git a/smr/build-assembly-short.py b/smr/build-assembly-short.py index c06c67b..dc13456 100644 --- a/smr/build-assembly-short.py +++ b/smr/build-assembly-short.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import argparse -import copy from math import pi, isclose from pathlib import Path @@ -9,7 +8,7 @@ import numpy as np from tqdm import tqdm import openmc -from smr.materials import materials, mats +from smr.materials import materials, clone from smr.surfaces import surfs, lattice_pitch, pin_pitch, bottom_fuel_stack, \ top_active_core, pellet_OR, clad_OR, clad_IR, guide_tube_IR, guide_tube_OR from smr.pins import pin_universes @@ -85,14 +84,6 @@ for halfspace in surfs['lat grid box inner']: # Define geometry with a single assembly geometry = openmc.Geometry(root_universe) - -def clone(material): - """Perform copy of material but share nuclide densities""" - shared_mat = copy.copy(material) - shared_mat.id = None - return shared_mat - - #### "Differentiate" the geometry if using distribmats h = 10.0*pin_pitch / args.axial if args.tallies == 'mat': diff --git a/smr/build-assembly.py b/smr/build-assembly.py index 392b114..123fa91 100644 --- a/smr/build-assembly.py +++ b/smr/build-assembly.py @@ -1,14 +1,13 @@ #!/usr/bin/env python3 import argparse -import copy from pathlib import Path import numpy as np from tqdm import tqdm import openmc -from smr.materials import materials +from smr.materials import materials, clone from smr.surfaces import surfs, lattice_pitch, bottom_fuel_stack, top_active_core, pellet_OR from smr.assemblies import assembly_universes from smr.plots import assembly_plots @@ -58,14 +57,6 @@ main_cell = openmc.Cell( root_univ = openmc.Universe(cells=[main_cell]) geometry = openmc.Geometry(root_univ) - -def clone(material): - """Perform copy of material but share nuclide densities""" - shared_mat = copy.copy(material) - shared_mat.id = None - return shared_mat - - #### "Differentiate" the geometry if using distribmats if args.tallies == 'mat': # Count the number of instances for each cell and material diff --git a/smr/build-core-fresh.py b/smr/build-core-fresh.py index e0dabff..3e3a1bf 100644 --- a/smr/build-core-fresh.py +++ b/smr/build-core-fresh.py @@ -9,20 +9,13 @@ import numpy as np import openmc from tqdm import tqdm -from smr.materials import materials +from smr.materials import materials, clone from smr.surfaces import lattice_pitch, bottom_fuel_stack, top_active_core, \ pellet_OR, active_fuel_length from smr.core import core_geometry from smr import inlet_temperature -def clone(material): - """Perform copy of material but share nuclide densities""" - shared_mat = copy.copy(material) - shared_mat.id = None - return shared_mat - - # Define command-line options parser = argparse.ArgumentParser() parser.add_argument('--multipole', action='store_true', diff --git a/smr/smr/materials.py b/smr/smr/materials.py index 72a39d6..ee6c754 100644 --- a/smr/smr/materials.py +++ b/smr/smr/materials.py @@ -1,5 +1,7 @@ """Instantiate the OpenMC Materials needed by the core model.""" +import copy + import openmc from openmc.data import atomic_weight, atomic_mass, water_density @@ -252,3 +254,10 @@ mats['UO2 3.1 depleted'] = mat # Construct a collection of Materials to export to XML materials = openmc.Materials(mats.values()) + + +def clone(material): + """Perform copy of material but share nuclide densities""" + shared_mat = copy.copy(material) + shared_mat.id = None + return shared_mat From 7805e62674d51ebc0ee0b806268d100307c02138 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 8 Jun 2022 09:10:38 -0500 Subject: [PATCH 15/18] Fix assembly assignment in build-assembly.py --- smr/build-assembly-long.py | 15 +++++++-------- smr/build-assembly.py | 13 ++++--------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/smr/build-assembly-long.py b/smr/build-assembly-long.py index 98ade14..623907c 100644 --- a/smr/build-assembly-long.py +++ b/smr/build-assembly-long.py @@ -174,14 +174,13 @@ settings.particles = 10000 settings.output = {'tallies': False, 'summary': False} settings.source = source settings.sourcepoint = {'write': False} - -if args.multipole: - settings.temperature = { - 'multipole': True, - 'tolerance': 1000, - 'default': 531.5, - 'method': 'interpolation', +settings.temperature = { + 'default': 531.5, + 'method': 'interpolation', 'range': (500.0, 1300.0) - } +} +if args.multipole: + settings.temperature['multipole'] = True + settings.temperature['tolerance'] = 1000 settings.export_to_xml(str(directory / 'settings.xml')) diff --git a/smr/build-assembly.py b/smr/build-assembly.py index 123fa91..1b2682e 100644 --- a/smr/build-assembly.py +++ b/smr/build-assembly.py @@ -10,7 +10,6 @@ import openmc from smr.materials import materials, clone from smr.surfaces import surfs, lattice_pitch, bottom_fuel_stack, top_active_core, pellet_OR from smr.assemblies import assembly_universes -from smr.plots import assembly_plots from smr import inlet_temperature @@ -48,10 +47,10 @@ if args.rings > 1: else: ring_radii = None assembly = assembly_universes(ring_radii, args.axial, args.depleted) -lattice_sides = openmc.model.get_rectangular_prism(lattice_pitch, lattice_pitch, - boundary_type='reflective') +lattice_sides = openmc.model.rectangular_prism(lattice_pitch, lattice_pitch, + boundary_type='reflective') main_cell = openmc.Cell( - fill=assembly['Assembly (3.1%) 16BA'], + fill=assembly['Assembly (3.1%)'], region=lattice_sides & +surfs['lower bound'] & -surfs['upper bound'] ) root_univ = openmc.Universe(cells=[main_cell]) @@ -98,7 +97,7 @@ settings.inactive = 100 settings.particles = 10000 settings.output = {'tallies': False, 'summary': False} settings.source = source -settings.sourcepoint_write = False +settings.sourcepoint = {'write': False} settings.temperature = { 'default': inlet_temperature, 'method': 'interpolation', @@ -140,7 +139,3 @@ elif args.tallies == 'mat': tallies.append(tally) tallies.export_to_xml(str(directory / 'tallies.xml')) - -# Create plots -plots = assembly_plots(main_cell.fill) -plots.export_to_xml(str(directory / 'plots.xml')) From ca7d63327fcdfe26d861176322850b9383ebfc36 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 8 Jun 2022 11:14:13 -0500 Subject: [PATCH 16/18] Add a --clone argument for build-assembly.py --- smr/build-assembly.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/smr/build-assembly.py b/smr/build-assembly.py index 1b2682e..0a76108 100644 --- a/smr/build-assembly.py +++ b/smr/build-assembly.py @@ -19,6 +19,10 @@ parser.add_argument('--multipole', action='store_true', help='Use multipole cross sections') parser.add_argument('--no-multipole', action='store_false', help='Do not use multipole cross sections') +parser.add_argument('--clone', action='store_true', + help='Clone materials for each cell instance') +parser.add_argument('--no-clone', dest='clone', action='store_false', + help='Do not clone materials for each cell instance') parser.add_argument('-t', '--tallies', choices=('cell', 'mat'), default='mat', help='Whether to use distribmats or distribcells for tallies') parser.add_argument('-r', '--rings', type=int, default=10, @@ -28,7 +32,7 @@ parser.add_argument('-a', '--axial', type=int, default=196, parser.add_argument('-d', '--depleted', action='store_true', help='Whether UO2 compositions should represent depleted fuel') parser.add_argument('-o', '--output-dir', type=Path, default=None) -parser.set_defaults(multipole=True) +parser.set_defaults(clone=False, multipole=True) args = parser.parse_args() # Make directory for inputs @@ -57,7 +61,7 @@ root_univ = openmc.Universe(cells=[main_cell]) geometry = openmc.Geometry(root_univ) #### "Differentiate" the geometry if using distribmats -if args.tallies == 'mat': +if args.clone: # Count the number of instances for each cell and material geometry.determine_paths(instances_only=True) From b47c173471e9641475a3b7a02d21c27d460e286f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 8 Jun 2022 12:44:21 -0500 Subject: [PATCH 17/18] Fix --no-multipole argument for build-assembly.py --- smr/build-assembly.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smr/build-assembly.py b/smr/build-assembly.py index 0a76108..d4bc166 100644 --- a/smr/build-assembly.py +++ b/smr/build-assembly.py @@ -17,7 +17,7 @@ from smr import inlet_temperature parser = argparse.ArgumentParser() parser.add_argument('--multipole', action='store_true', help='Use multipole cross sections') -parser.add_argument('--no-multipole', action='store_false', +parser.add_argument('--no-multipole', dest='multipole', action='store_false', help='Do not use multipole cross sections') parser.add_argument('--clone', action='store_true', help='Clone materials for each cell instance') From db5c6bfaf8b8c94656b23939d669c556bc04589f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 8 Jun 2022 14:26:56 -0500 Subject: [PATCH 18/18] Fix sourcepoint write in core scripts --- smr/build-core-fresh.py | 5 +---- smr/build-core-long.py | 3 +-- smr/build-core-short.py | 3 +-- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/smr/build-core-fresh.py b/smr/build-core-fresh.py index 3e3a1bf..9747ae8 100644 --- a/smr/build-core-fresh.py +++ b/smr/build-core-fresh.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -import copy import argparse from math import pi from pathlib import Path @@ -109,8 +108,7 @@ settings.inactive = 100 settings.particles = 10000 settings.output = {'tallies': False, 'summary': False} settings.source = source -settings.sourcepoint_write = False - +settings.sourcepoint = {'write': False} settings.temperature = { 'default': inlet_temperature, 'method': 'interpolation', @@ -121,4 +119,3 @@ if args.multipole: settings.temperature['tolerance'] = 1000 settings.export_to_xml(str(directory / 'settings.xml')) - diff --git a/smr/build-core-long.py b/smr/build-core-long.py index c3531c6..4033d6e 100644 --- a/smr/build-core-long.py +++ b/smr/build-core-long.py @@ -96,8 +96,7 @@ settings.inactive = 100 settings.particles = 20_000_000 settings.output = {'tallies': False, 'summary': False} settings.source = source -settings.sourcepoint_write = False - +settings.sourcepoint = {'write': False} settings.temperature = { 'default': inlet_temperature, 'method': 'interpolation', diff --git a/smr/build-core-short.py b/smr/build-core-short.py index e9cabc8..2f5339d 100644 --- a/smr/build-core-short.py +++ b/smr/build-core-short.py @@ -109,8 +109,7 @@ settings.inactive = 100 settings.particles = 10000 settings.output = {'tallies': False, 'summary': False} settings.source = source -settings.sourcepoint_write = False - +settings.sourcepoint = {'write': False} settings.temperature = { 'default': inlet_temperature, 'method': 'interpolation',