diff --git a/smr/build-assembly-long.py b/smr/build-assembly-long.py index cca7640..28447a0 100644 --- a/smr/build-assembly-long.py +++ b/smr/build-assembly-long.py @@ -20,16 +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('-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('--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 @@ -106,33 +108,52 @@ def clone(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 + +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='Differentiating materials'): - if cell.fill in materials: - # Fill cell with list of "differentiated" materials +for cell in tqdm(geometry.get_all_material_cells().values(), + 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[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 + # Determine volume of each fuel material + if is_fuel: + 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 + + if args.clone: for mat in cell.fill: mat.volume = pi * (ro*ro - ri*ri) * h else: + # 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: + 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...') @@ -173,34 +194,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..e0dabff 100644 --- a/smr/build-core-fresh.py +++ b/smr/build-core-fresh.py @@ -1,36 +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 +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 +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('-t', '--tallies', choices=('cell', 'mat'), default='cell', - help='Whether to use distribmats or distribcells for tallies') +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, @@ -38,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 @@ -57,18 +59,38 @@ 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 +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) - # 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 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 - 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)] + # Determine volume of each fuel material + 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: + 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() @@ -107,38 +129,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'))