From 2b8e9e9f5d8f5b7f15e8934b15fd653353bab249 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Dec 2019 14:32:07 -0600 Subject: [PATCH 1/2] 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 2/2] 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())