mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-21 14:35:27 -04:00
1621 lines
No EOL
62 KiB
Python
1621 lines
No EOL
62 KiB
Python
from numbers import Integral
|
|
|
|
import numpy as np
|
|
|
|
import openmc
|
|
|
|
PINCELL_PITCH = 1.26 # cm
|
|
|
|
def pwr_pin_cell() -> openmc.Model:
|
|
"""Create a PWR pin-cell model.
|
|
|
|
This model is a single fuel pin with 2.4 w/o enriched UO2 corresponding to a
|
|
beginning-of-cycle condition and borated water. The specifications are from
|
|
the `BEAVRS <https://crpg.mit.edu/research/beavrs>`_ benchmark. Note that
|
|
the number of particles/batches is initially set very low for testing
|
|
purposes.
|
|
|
|
Returns
|
|
-------
|
|
model : openmc.Model
|
|
A PWR pin-cell model
|
|
|
|
"""
|
|
model = openmc.Model()
|
|
|
|
# Define materials.
|
|
fuel = openmc.Material(name='UO2 (2.4%)')
|
|
fuel.set_density('g/cm3', 10.29769)
|
|
fuel.add_nuclide('U234', 4.4843e-6)
|
|
fuel.add_nuclide('U235', 5.5815e-4)
|
|
fuel.add_nuclide('U238', 2.2408e-2)
|
|
fuel.add_nuclide('O16', 4.5829e-2)
|
|
|
|
clad = openmc.Material(name='Zircaloy')
|
|
clad.set_density('g/cm3', 6.55)
|
|
clad.add_nuclide('Zr90', 2.1827e-2)
|
|
clad.add_nuclide('Zr91', 4.7600e-3)
|
|
clad.add_nuclide('Zr92', 7.2758e-3)
|
|
clad.add_nuclide('Zr94', 7.3734e-3)
|
|
clad.add_nuclide('Zr96', 1.1879e-3)
|
|
|
|
hot_water = openmc.Material(name='Hot borated water')
|
|
hot_water.set_density('g/cm3', 0.740582)
|
|
hot_water.add_nuclide('H1', 4.9457e-2)
|
|
hot_water.add_nuclide('O16', 2.4672e-2)
|
|
hot_water.add_nuclide('B10', 8.0042e-6)
|
|
hot_water.add_nuclide('B11', 3.2218e-5)
|
|
hot_water.add_s_alpha_beta('c_H_in_H2O')
|
|
|
|
# Define the materials file.
|
|
model.materials = (fuel, clad, hot_water)
|
|
|
|
# Instantiate ZCylinder surfaces
|
|
pitch = PINCELL_PITCH
|
|
fuel_or = openmc.ZCylinder(x0=0, y0=0, r=0.39218, name='Fuel OR')
|
|
clad_or = openmc.ZCylinder(x0=0, y0=0, r=0.45720, name='Clad OR')
|
|
left = openmc.XPlane(x0=-pitch/2, name='left', boundary_type='reflective')
|
|
right = openmc.XPlane(x0=pitch/2, name='right', boundary_type='reflective')
|
|
bottom = openmc.YPlane(y0=-pitch/2, name='bottom',
|
|
boundary_type='reflective')
|
|
top = openmc.YPlane(y0=pitch/2, name='top', boundary_type='reflective')
|
|
|
|
# Instantiate Cells
|
|
fuel_pin = openmc.Cell(name='Fuel', fill=fuel)
|
|
cladding = openmc.Cell(name='Cladding', fill=clad)
|
|
water = openmc.Cell(name='Water', fill=hot_water)
|
|
|
|
# Use surface half-spaces to define regions
|
|
fuel_pin.region = -fuel_or
|
|
cladding.region = +fuel_or & -clad_or
|
|
water.region = +clad_or & +left & -right & +bottom & -top
|
|
|
|
# Create root universe
|
|
model.geometry.root_universe = openmc.Universe(0, name='root universe')
|
|
model.geometry.root_universe.add_cells([fuel_pin, cladding, water])
|
|
|
|
model.settings.batches = 10
|
|
model.settings.inactive = 5
|
|
model.settings.particles = 100
|
|
model.settings.source = openmc.IndependentSource(
|
|
space=openmc.stats.Box([-pitch/2, -pitch/2, -1],
|
|
[pitch/2, pitch/2, 1]),
|
|
constraints={'fissionable': True}
|
|
)
|
|
|
|
plot = openmc.SlicePlot.from_geometry(model.geometry)
|
|
plot.pixels = (300, 300)
|
|
plot.color_by = 'material'
|
|
model.plots.append(plot)
|
|
|
|
return model
|
|
|
|
|
|
def pwr_core() -> openmc.Model:
|
|
"""Create a PWR full-core model.
|
|
|
|
This model is the OECD/NEA Monte Carlo Performance benchmark which is a
|
|
grossly simplified pressurized water reactor (PWR) with 241 fuel
|
|
assemblies. Note that the number of particles/batches is initially set very
|
|
low for testing purposes.
|
|
|
|
Returns
|
|
-------
|
|
model : openmc.Model
|
|
Full-core PWR model
|
|
|
|
"""
|
|
model = openmc.Model()
|
|
|
|
# Define materials.
|
|
fuel = openmc.Material(1, name='UOX fuel')
|
|
fuel.set_density('g/cm3', 10.062)
|
|
fuel.add_nuclide('U234', 4.9476e-6)
|
|
fuel.add_nuclide('U235', 4.8218e-4)
|
|
fuel.add_nuclide('U238', 2.1504e-2)
|
|
fuel.add_nuclide('Xe135', 1.0801e-8)
|
|
fuel.add_nuclide('O16', 4.5737e-2)
|
|
|
|
clad = openmc.Material(2, name='Zircaloy')
|
|
clad.set_density('g/cm3', 5.77)
|
|
clad.add_nuclide('Zr90', 0.5145)
|
|
clad.add_nuclide('Zr91', 0.1122)
|
|
clad.add_nuclide('Zr92', 0.1715)
|
|
clad.add_nuclide('Zr94', 0.1738)
|
|
clad.add_nuclide('Zr96', 0.0280)
|
|
|
|
cold_water = openmc.Material(3, name='Cold borated water')
|
|
cold_water.set_density('atom/b-cm', 0.07416)
|
|
cold_water.add_nuclide('H1', 2.0)
|
|
cold_water.add_nuclide('O16', 1.0)
|
|
cold_water.add_nuclide('B10', 6.490e-4)
|
|
cold_water.add_nuclide('B11', 2.689e-3)
|
|
cold_water.add_s_alpha_beta('c_H_in_H2O')
|
|
|
|
hot_water = openmc.Material(4, name='Hot borated water')
|
|
hot_water.set_density('atom/b-cm', 0.06614)
|
|
hot_water.add_nuclide('H1', 2.0)
|
|
hot_water.add_nuclide('O16', 1.0)
|
|
hot_water.add_nuclide('B10', 6.490e-4)
|
|
hot_water.add_nuclide('B11', 2.689e-3)
|
|
hot_water.add_s_alpha_beta('c_H_in_H2O')
|
|
|
|
rpv_steel = openmc.Material(5, name='Reactor pressure vessel steel')
|
|
rpv_steel.set_density('g/cm3', 7.9)
|
|
rpv_steel.add_nuclide('Fe54', 0.05437098, 'wo')
|
|
rpv_steel.add_nuclide('Fe56', 0.88500663, 'wo')
|
|
rpv_steel.add_nuclide('Fe57', 0.0208008, 'wo')
|
|
rpv_steel.add_nuclide('Fe58', 0.00282159, 'wo')
|
|
rpv_steel.add_nuclide('Ni58', 0.0067198, 'wo')
|
|
rpv_steel.add_nuclide('Ni60', 0.0026776, 'wo')
|
|
rpv_steel.add_nuclide('Mn55', 0.01, 'wo')
|
|
rpv_steel.add_nuclide('Cr52', 0.002092475, 'wo')
|
|
rpv_steel.add_nuclide('C0', 0.0025, 'wo')
|
|
rpv_steel.add_nuclide('Cu63', 0.0013696, 'wo')
|
|
|
|
lower_rad_ref = openmc.Material(6, name='Lower radial reflector')
|
|
lower_rad_ref.set_density('g/cm3', 4.32)
|
|
lower_rad_ref.add_nuclide('H1', 0.0095661, 'wo')
|
|
lower_rad_ref.add_nuclide('O16', 0.0759107, 'wo')
|
|
lower_rad_ref.add_nuclide('B10', 3.08409e-5, 'wo')
|
|
lower_rad_ref.add_nuclide('B11', 1.40499e-4, 'wo')
|
|
lower_rad_ref.add_nuclide('Fe54', 0.035620772088, 'wo')
|
|
lower_rad_ref.add_nuclide('Fe56', 0.579805982228, 'wo')
|
|
lower_rad_ref.add_nuclide('Fe57', 0.01362750048, 'wo')
|
|
lower_rad_ref.add_nuclide('Fe58', 0.001848545204, 'wo')
|
|
lower_rad_ref.add_nuclide('Ni58', 0.055298376566, 'wo')
|
|
lower_rad_ref.add_nuclide('Mn55', 0.0182870, 'wo')
|
|
lower_rad_ref.add_nuclide('Cr52', 0.145407678031, 'wo')
|
|
lower_rad_ref.add_s_alpha_beta('c_H_in_H2O')
|
|
|
|
upper_rad_ref = openmc.Material(
|
|
7, name='Upper radial reflector / Top plate region')
|
|
upper_rad_ref.set_density('g/cm3', 4.28)
|
|
upper_rad_ref.add_nuclide('H1', 0.0086117, 'wo')
|
|
upper_rad_ref.add_nuclide('O16', 0.0683369, 'wo')
|
|
upper_rad_ref.add_nuclide('B10', 2.77638e-5, 'wo')
|
|
upper_rad_ref.add_nuclide('B11', 1.26481e-4, 'wo')
|
|
upper_rad_ref.add_nuclide('Fe54', 0.035953677186, 'wo')
|
|
upper_rad_ref.add_nuclide('Fe56', 0.585224740891, 'wo')
|
|
upper_rad_ref.add_nuclide('Fe57', 0.01375486056, 'wo')
|
|
upper_rad_ref.add_nuclide('Fe58', 0.001865821363, 'wo')
|
|
upper_rad_ref.add_nuclide('Ni58', 0.055815129186, 'wo')
|
|
upper_rad_ref.add_nuclide('Mn55', 0.0184579, 'wo')
|
|
upper_rad_ref.add_nuclide('Cr52', 0.146766614995, 'wo')
|
|
upper_rad_ref.add_s_alpha_beta('c_H_in_H2O')
|
|
|
|
bot_plate = openmc.Material(8, name='Bottom plate region')
|
|
bot_plate.set_density('g/cm3', 7.184)
|
|
bot_plate.add_nuclide('H1', 0.0011505, 'wo')
|
|
bot_plate.add_nuclide('O16', 0.0091296, 'wo')
|
|
bot_plate.add_nuclide('B10', 3.70915e-6, 'wo')
|
|
bot_plate.add_nuclide('B11', 1.68974e-5, 'wo')
|
|
bot_plate.add_nuclide('Fe54', 0.03855611055, 'wo')
|
|
bot_plate.add_nuclide('Fe56', 0.627585036425, 'wo')
|
|
bot_plate.add_nuclide('Fe57', 0.014750478, 'wo')
|
|
bot_plate.add_nuclide('Fe58', 0.002000875025, 'wo')
|
|
bot_plate.add_nuclide('Ni58', 0.059855207342, 'wo')
|
|
bot_plate.add_nuclide('Mn55', 0.0197940, 'wo')
|
|
bot_plate.add_nuclide('Cr52', 0.157390026871, 'wo')
|
|
bot_plate.add_s_alpha_beta('c_H_in_H2O')
|
|
|
|
bot_nozzle = openmc.Material(9, name='Bottom nozzle region')
|
|
bot_nozzle.set_density('g/cm3', 2.53)
|
|
bot_nozzle.add_nuclide('H1', 0.0245014, 'wo')
|
|
bot_nozzle.add_nuclide('O16', 0.1944274, 'wo')
|
|
bot_nozzle.add_nuclide('B10', 7.89917e-5, 'wo')
|
|
bot_nozzle.add_nuclide('B11', 3.59854e-4, 'wo')
|
|
bot_nozzle.add_nuclide('Fe54', 0.030411411144, 'wo')
|
|
bot_nozzle.add_nuclide('Fe56', 0.495012237964, 'wo')
|
|
bot_nozzle.add_nuclide('Fe57', 0.01163454624, 'wo')
|
|
bot_nozzle.add_nuclide('Fe58', 0.001578204652, 'wo')
|
|
bot_nozzle.add_nuclide('Ni58', 0.047211231662, 'wo')
|
|
bot_nozzle.add_nuclide('Mn55', 0.0156126, 'wo')
|
|
bot_nozzle.add_nuclide('Cr52', 0.124142524198, 'wo')
|
|
bot_nozzle.add_s_alpha_beta('c_H_in_H2O')
|
|
|
|
top_nozzle = openmc.Material(10, name='Top nozzle region')
|
|
top_nozzle.set_density('g/cm3', 1.746)
|
|
top_nozzle.add_nuclide('H1', 0.0358870, 'wo')
|
|
top_nozzle.add_nuclide('O16', 0.2847761, 'wo')
|
|
top_nozzle.add_nuclide('B10', 1.15699e-4, 'wo')
|
|
top_nozzle.add_nuclide('B11', 5.27075e-4, 'wo')
|
|
top_nozzle.add_nuclide('Fe54', 0.02644016154, 'wo')
|
|
top_nozzle.add_nuclide('Fe56', 0.43037146399, 'wo')
|
|
top_nozzle.add_nuclide('Fe57', 0.0101152584, 'wo')
|
|
top_nozzle.add_nuclide('Fe58', 0.00137211607, 'wo')
|
|
top_nozzle.add_nuclide('Ni58', 0.04104621835, 'wo')
|
|
top_nozzle.add_nuclide('Mn55', 0.0135739, 'wo')
|
|
top_nozzle.add_nuclide('Cr52', 0.107931450781, 'wo')
|
|
top_nozzle.add_s_alpha_beta('c_H_in_H2O')
|
|
|
|
top_fa = openmc.Material(11, name='Top of fuel assemblies')
|
|
top_fa.set_density('g/cm3', 3.044)
|
|
top_fa.add_nuclide('H1', 0.0162913, 'wo')
|
|
top_fa.add_nuclide('O16', 0.1292776, 'wo')
|
|
top_fa.add_nuclide('B10', 5.25228e-5, 'wo')
|
|
top_fa.add_nuclide('B11', 2.39272e-4, 'wo')
|
|
top_fa.add_nuclide('Zr90', 0.43313403903, 'wo')
|
|
top_fa.add_nuclide('Zr91', 0.09549277374, 'wo')
|
|
top_fa.add_nuclide('Zr92', 0.14759527104, 'wo')
|
|
top_fa.add_nuclide('Zr94', 0.15280552077, 'wo')
|
|
top_fa.add_nuclide('Zr96', 0.02511169542, 'wo')
|
|
top_fa.add_s_alpha_beta('c_H_in_H2O')
|
|
|
|
bot_fa = openmc.Material(12, name='Bottom of fuel assemblies')
|
|
bot_fa.set_density('g/cm3', 1.762)
|
|
bot_fa.add_nuclide('H1', 0.0292856, 'wo')
|
|
bot_fa.add_nuclide('O16', 0.2323919, 'wo')
|
|
bot_fa.add_nuclide('B10', 9.44159e-5, 'wo')
|
|
bot_fa.add_nuclide('B11', 4.30120e-4, 'wo')
|
|
bot_fa.add_nuclide('Zr90', 0.3741373658, 'wo')
|
|
bot_fa.add_nuclide('Zr91', 0.0824858164, 'wo')
|
|
bot_fa.add_nuclide('Zr92', 0.1274914944, 'wo')
|
|
bot_fa.add_nuclide('Zr94', 0.1319920622, 'wo')
|
|
bot_fa.add_nuclide('Zr96', 0.0216912612, 'wo')
|
|
bot_fa.add_s_alpha_beta('c_H_in_H2O')
|
|
|
|
# Define the materials file.
|
|
model.materials = (fuel, clad, cold_water, hot_water, rpv_steel,
|
|
lower_rad_ref, upper_rad_ref, bot_plate,
|
|
bot_nozzle, top_nozzle, top_fa, bot_fa)
|
|
|
|
# Define surfaces.
|
|
s1 = openmc.ZCylinder(r=0.41, surface_id=1)
|
|
s2 = openmc.ZCylinder(r=0.475, surface_id=2)
|
|
s3 = openmc.ZCylinder(r=0.56, surface_id=3)
|
|
s4 = openmc.ZCylinder(r=0.62, surface_id=4)
|
|
s5 = openmc.ZCylinder(r=187.6, surface_id=5)
|
|
s6 = openmc.ZCylinder(r=209.0, surface_id=6)
|
|
s7 = openmc.ZCylinder(r=229.0, surface_id=7)
|
|
s8 = openmc.ZCylinder(r=249.0, surface_id=8, boundary_type='vacuum')
|
|
|
|
s31 = openmc.ZPlane(z0=-229.0, surface_id=31, boundary_type='vacuum')
|
|
s32 = openmc.ZPlane(z0=-199.0, surface_id=32)
|
|
s33 = openmc.ZPlane(z0=-193.0, surface_id=33)
|
|
s34 = openmc.ZPlane(z0=-183.0, surface_id=34)
|
|
s35 = openmc.ZPlane(z0=0.0, surface_id=35)
|
|
s36 = openmc.ZPlane(z0=183.0, surface_id=36)
|
|
s37 = openmc.ZPlane(z0=203.0, surface_id=37)
|
|
s38 = openmc.ZPlane(z0=215.0, surface_id=38)
|
|
s39 = openmc.ZPlane(z0=223.0, surface_id=39, boundary_type='vacuum')
|
|
|
|
# Define pin cells.
|
|
fuel_cold = openmc.Universe(name='Fuel pin, cladding, cold water',
|
|
universe_id=1)
|
|
c21 = openmc.Cell(cell_id=21, fill=fuel, region=-s1)
|
|
c22 = openmc.Cell(cell_id=22, fill=clad, region=+s1 & -s2)
|
|
c23 = openmc.Cell(cell_id=23, fill=cold_water, region=+s2)
|
|
fuel_cold.add_cells((c21, c22, c23))
|
|
|
|
tube_cold = openmc.Universe(name='Instrumentation guide tube, '
|
|
'cold water', universe_id=2)
|
|
c24 = openmc.Cell(cell_id=24, fill=cold_water, region=-s3)
|
|
c25 = openmc.Cell(cell_id=25, fill=clad, region=+s3 & -s4)
|
|
c26 = openmc.Cell(cell_id=26, fill=cold_water, region=+s4)
|
|
tube_cold.add_cells((c24, c25, c26))
|
|
|
|
fuel_hot = openmc.Universe(name='Fuel pin, cladding, hot water',
|
|
universe_id=3)
|
|
c27 = openmc.Cell(cell_id=27, fill=fuel, region=-s1)
|
|
c28 = openmc.Cell(cell_id=28, fill=clad, region=+s1 & -s2)
|
|
c29 = openmc.Cell(cell_id=29, fill=hot_water, region=+s2)
|
|
fuel_hot.add_cells((c27, c28, c29))
|
|
|
|
tube_hot = openmc.Universe(name='Instrumentation guide tube, hot water',
|
|
universe_id=4)
|
|
c30 = openmc.Cell(cell_id=30, fill=hot_water, region=-s3)
|
|
c31 = openmc.Cell(cell_id=31, fill=clad, region=+s3 & -s4)
|
|
c32 = openmc.Cell(cell_id=32, fill=hot_water, region=+s4)
|
|
tube_hot.add_cells((c30, c31, c32))
|
|
|
|
# Set positions occupied by guide tubes
|
|
tube_x = np.array([5, 8, 11, 3, 13, 2, 5, 8, 11, 14, 2, 5, 8, 11, 14,
|
|
2, 5, 8, 11, 14, 3, 13, 5, 8, 11])
|
|
tube_y = np.array([2, 2, 2, 3, 3, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8,
|
|
11, 11, 11, 11, 11, 13, 13, 14, 14, 14])
|
|
|
|
# Define fuel lattices.
|
|
l100 = openmc.RectLattice(
|
|
name='Fuel assembly (lower half)', lattice_id=100)
|
|
l100.lower_left = (-10.71, -10.71)
|
|
l100.pitch = (PINCELL_PITCH, PINCELL_PITCH)
|
|
l100.universes = np.tile(fuel_cold, (17, 17))
|
|
l100.universes[tube_x, tube_y] = tube_cold
|
|
|
|
l101 = openmc.RectLattice(
|
|
name='Fuel assembly (upper half)', lattice_id=101)
|
|
l101.lower_left = (-10.71, -10.71)
|
|
l101.pitch = (PINCELL_PITCH, PINCELL_PITCH)
|
|
l101.universes = np.tile(fuel_hot, (17, 17))
|
|
l101.universes[tube_x, tube_y] = tube_hot
|
|
|
|
# Define assemblies.
|
|
fa_cw = openmc.Universe(name='Water assembly (cold)', universe_id=5)
|
|
c50 = openmc.Cell(cell_id=50, fill=cold_water, region=+s34 & -s35)
|
|
fa_cw.add_cell(c50)
|
|
|
|
fa_hw = openmc.Universe(name='Water assembly (hot)', universe_id=7)
|
|
c70 = openmc.Cell(cell_id=70, fill=hot_water, region=+s35 & -s36)
|
|
fa_hw.add_cell(c70)
|
|
|
|
fa_cold = openmc.Universe(name='Fuel assembly (cold)', universe_id=6)
|
|
c60 = openmc.Cell(cell_id=60, fill=l100, region=+s34 & -s35)
|
|
fa_cold.add_cell(c60)
|
|
|
|
fa_hot = openmc.Universe(name='Fuel assembly (hot)', universe_id=8)
|
|
c80 = openmc.Cell(cell_id=80, fill=l101, region=+s35 & -s36)
|
|
fa_hot.add_cell(c80)
|
|
|
|
# Define core lattices
|
|
l200 = openmc.RectLattice(name='Core lattice (lower half)', lattice_id=200)
|
|
l200.lower_left = (-224.91, -224.91)
|
|
l200.pitch = (17 * PINCELL_PITCH, 17 * PINCELL_PITCH)
|
|
l200.universes = [
|
|
[fa_cw]*21,
|
|
[fa_cw]*21,
|
|
[fa_cw]*7 + [fa_cold]*7 + [fa_cw]*7,
|
|
[fa_cw]*5 + [fa_cold]*11 + [fa_cw]*5,
|
|
[fa_cw]*4 + [fa_cold]*13 + [fa_cw]*4,
|
|
[fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3,
|
|
[fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3,
|
|
[fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2,
|
|
[fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2,
|
|
[fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2,
|
|
[fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2,
|
|
[fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2,
|
|
[fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2,
|
|
[fa_cw]*2 + [fa_cold]*17 + [fa_cw]*2,
|
|
[fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3,
|
|
[fa_cw]*3 + [fa_cold]*15 + [fa_cw]*3,
|
|
[fa_cw]*4 + [fa_cold]*13 + [fa_cw]*4,
|
|
[fa_cw]*5 + [fa_cold]*11 + [fa_cw]*5,
|
|
[fa_cw]*7 + [fa_cold]*7 + [fa_cw]*7,
|
|
[fa_cw]*21,
|
|
[fa_cw]*21]
|
|
|
|
l201 = openmc.RectLattice(name='Core lattice (lower half)', lattice_id=201)
|
|
l201.lower_left = (-224.91, -224.91)
|
|
l201.pitch = (17 * PINCELL_PITCH, 17 * PINCELL_PITCH)
|
|
l201.universes = [
|
|
[fa_hw]*21,
|
|
[fa_hw]*21,
|
|
[fa_hw]*7 + [fa_hot]*7 + [fa_hw]*7,
|
|
[fa_hw]*5 + [fa_hot]*11 + [fa_hw]*5,
|
|
[fa_hw]*4 + [fa_hot]*13 + [fa_hw]*4,
|
|
[fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3,
|
|
[fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3,
|
|
[fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2,
|
|
[fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2,
|
|
[fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2,
|
|
[fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2,
|
|
[fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2,
|
|
[fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2,
|
|
[fa_hw]*2 + [fa_hot]*17 + [fa_hw]*2,
|
|
[fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3,
|
|
[fa_hw]*3 + [fa_hot]*15 + [fa_hw]*3,
|
|
[fa_hw]*4 + [fa_hot]*13 + [fa_hw]*4,
|
|
[fa_hw]*5 + [fa_hot]*11 + [fa_hw]*5,
|
|
[fa_hw]*7 + [fa_hot]*7 + [fa_hw]*7,
|
|
[fa_hw]*21,
|
|
[fa_hw]*21]
|
|
|
|
# Define root universe.
|
|
root = openmc.Universe(universe_id=0, name='root universe')
|
|
c1 = openmc.Cell(cell_id=1, fill=l200, region=-s6 & +s34 & -s35)
|
|
c2 = openmc.Cell(cell_id=2, fill=l201, region=-s6 & +s35 & -s36)
|
|
c3 = openmc.Cell(cell_id=3, fill=bot_plate, region=-s7 & +s31 & -s32)
|
|
c4 = openmc.Cell(cell_id=4, fill=bot_nozzle, region=-s5 & +s32 & -s33)
|
|
c5 = openmc.Cell(cell_id=5, fill=bot_fa, region=-s5 & +s33 & -s34)
|
|
c6 = openmc.Cell(cell_id=6, fill=top_fa, region=-s5 & +s36 & -s37)
|
|
c7 = openmc.Cell(cell_id=7, fill=top_nozzle, region=-s5 & +s37 & -s38)
|
|
c8 = openmc.Cell(cell_id=8, fill=upper_rad_ref, region=-s7 & +s38 & -s39)
|
|
c9 = openmc.Cell(cell_id=9, fill=bot_nozzle,
|
|
region=+s6 & -s7 & +s32 & -s38)
|
|
c10 = openmc.Cell(cell_id=10, fill=rpv_steel,
|
|
region=+s7 & -s8 & +s31 & -s39)
|
|
c11 = openmc.Cell(cell_id=11, fill=lower_rad_ref,
|
|
region=+s5 & -s6 & +s32 & -s34)
|
|
c12 = openmc.Cell(cell_id=12, fill=upper_rad_ref,
|
|
region=+s5 & -s6 & +s36 & -s38)
|
|
root.add_cells((c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12))
|
|
|
|
# Assign root universe to geometry
|
|
model.geometry.root_universe = root
|
|
|
|
model.settings.batches = 10
|
|
model.settings.inactive = 5
|
|
model.settings.particles = 100
|
|
model.settings.source = openmc.IndependentSource(space=openmc.stats.Box(
|
|
[-160, -160, -183], [160, 160, 183]))
|
|
|
|
plot = openmc.SlicePlot()
|
|
plot.origin = (125, 125, 0)
|
|
plot.width = (250, 250)
|
|
plot.pixels = (3000, 3000)
|
|
plot.color_by = 'material'
|
|
model.plots.append(plot)
|
|
|
|
return model
|
|
|
|
|
|
def pwr_assembly() -> openmc.Model:
|
|
"""Create a PWR assembly model.
|
|
|
|
This model is a reflected 17x17 fuel assembly from the the `BEAVRS
|
|
<https://crpg.mit.edu/research/beavrs>`_ benchmark. The fuel is 2.4 w/o
|
|
enriched UO2 corresponding to a beginning-of-cycle condition. Note that the
|
|
number of particles/batches is initially set very low for testing purposes.
|
|
|
|
Returns
|
|
-------
|
|
model : openmc.Model
|
|
A PWR assembly model
|
|
|
|
"""
|
|
|
|
model = openmc.Model()
|
|
|
|
# Define materials.
|
|
fuel = openmc.Material(name='Fuel')
|
|
fuel.set_density('g/cm3', 10.29769)
|
|
fuel.add_nuclide('U234', 4.4843e-6)
|
|
fuel.add_nuclide('U235', 5.5815e-4)
|
|
fuel.add_nuclide('U238', 2.2408e-2)
|
|
fuel.add_nuclide('O16', 4.5829e-2)
|
|
|
|
clad = openmc.Material(name='Cladding')
|
|
clad.set_density('g/cm3', 6.55)
|
|
clad.add_nuclide('Zr90', 2.1827e-2)
|
|
clad.add_nuclide('Zr91', 4.7600e-3)
|
|
clad.add_nuclide('Zr92', 7.2758e-3)
|
|
clad.add_nuclide('Zr94', 7.3734e-3)
|
|
clad.add_nuclide('Zr96', 1.1879e-3)
|
|
|
|
hot_water = openmc.Material(name='Hot borated water')
|
|
hot_water.set_density('g/cm3', 0.740582)
|
|
hot_water.add_nuclide('H1', 4.9457e-2)
|
|
hot_water.add_nuclide('O16', 2.4672e-2)
|
|
hot_water.add_nuclide('B10', 8.0042e-6)
|
|
hot_water.add_nuclide('B11', 3.2218e-5)
|
|
hot_water.add_s_alpha_beta('c_H_in_H2O')
|
|
|
|
# Define the materials file.
|
|
model.materials = (fuel, clad, hot_water)
|
|
|
|
# Instantiate ZCylinder surfaces
|
|
fuel_or = openmc.ZCylinder(x0=0, y0=0, r=0.39218, name='Fuel OR')
|
|
clad_or = openmc.ZCylinder(x0=0, y0=0, r=0.45720, name='Clad OR')
|
|
|
|
# Create boundary planes to surround the geometry
|
|
pitch = 17 * PINCELL_PITCH
|
|
min_x = openmc.XPlane(x0=-pitch/2, boundary_type='reflective')
|
|
max_x = openmc.XPlane(x0=+pitch/2, boundary_type='reflective')
|
|
min_y = openmc.YPlane(y0=-pitch/2, boundary_type='reflective')
|
|
max_y = openmc.YPlane(y0=+pitch/2, boundary_type='reflective')
|
|
|
|
# Create a fuel pin universe
|
|
fuel_pin_universe = openmc.Universe(name='Fuel Pin')
|
|
fuel_cell = openmc.Cell(name='fuel', fill=fuel, region=-fuel_or)
|
|
clad_cell = openmc.Cell(name='clad', fill=clad, region=+fuel_or & -clad_or)
|
|
hot_water_cell = openmc.Cell(
|
|
name='hot water', fill=hot_water, region=+clad_or)
|
|
fuel_pin_universe.add_cells([fuel_cell, clad_cell, hot_water_cell])
|
|
|
|
# Create a control rod guide tube universe
|
|
guide_tube_universe = openmc.Universe(name='Guide Tube')
|
|
gt_inner_cell = openmc.Cell(name='guide tube inner water', fill=hot_water,
|
|
region=-fuel_or)
|
|
gt_clad_cell = openmc.Cell(name='guide tube clad', fill=clad,
|
|
region=+fuel_or & -clad_or)
|
|
gt_outer_cell = openmc.Cell(name='guide tube outer water', fill=hot_water,
|
|
region=+clad_or)
|
|
guide_tube_universe.add_cells([gt_inner_cell, gt_clad_cell, gt_outer_cell])
|
|
|
|
# Create fuel assembly Lattice
|
|
assembly = openmc.RectLattice(name='Fuel Assembly')
|
|
assembly.pitch = (PINCELL_PITCH, PINCELL_PITCH)
|
|
assembly.lower_left = (-pitch/2, -pitch/2)
|
|
|
|
# Create array indices for guide tube locations in lattice
|
|
template_x = np.array([5, 8, 11, 3, 13, 2, 5, 8, 11, 14, 2, 5, 8,
|
|
11, 14, 2, 5, 8, 11, 14, 3, 13, 5, 8, 11])
|
|
template_y = np.array([2, 2, 2, 3, 3, 5, 5, 5, 5, 5, 8, 8, 8, 8,
|
|
8, 11, 11, 11, 11, 11, 13, 13, 14, 14, 14])
|
|
|
|
# Create 17x17 array of universes
|
|
assembly.universes = np.tile(fuel_pin_universe, (17, 17))
|
|
assembly.universes[template_x, template_y] = guide_tube_universe
|
|
|
|
# Create root Cell
|
|
root_cell = openmc.Cell(name='root cell', fill=assembly)
|
|
root_cell.region = +min_x & -max_x & +min_y & -max_y
|
|
|
|
# Create root Universe
|
|
model.geometry.root_universe = openmc.Universe(name='root universe')
|
|
model.geometry.root_universe.add_cell(root_cell)
|
|
|
|
model.settings.batches = 10
|
|
model.settings.inactive = 5
|
|
model.settings.particles = 100
|
|
model.settings.source = openmc.IndependentSource(
|
|
space=openmc.stats.Box([-pitch/2, -pitch/2, -1],
|
|
[pitch/2, pitch/2, 1]),
|
|
constraints={'fissionable': True}
|
|
)
|
|
|
|
plot = openmc.SlicePlot()
|
|
plot.origin = (0.0, 0.0, 0)
|
|
plot.width = (21.42, 21.42)
|
|
plot.pixels = (300, 300)
|
|
plot.color_by = 'material'
|
|
model.plots.append(plot)
|
|
|
|
return model
|
|
|
|
|
|
def slab_mg(num_regions=1, mat_names=None, mgxslib_name='2g.h5') -> openmc.Model:
|
|
"""Create a 1D slab model.
|
|
|
|
Parameters
|
|
----------
|
|
num_regions : int, optional
|
|
Number of regions in the problem, each with a unique MGXS dataset.
|
|
Defaults to 1.
|
|
|
|
mat_names : Iterable of str, optional
|
|
List of the material names to use; defaults to ['mat_1', 'mat_2',...].
|
|
|
|
mgxslib_name : str, optional
|
|
MGXS Library file to use; defaults to '2g.h5'.
|
|
|
|
Returns
|
|
-------
|
|
model : openmc.Model
|
|
One-group, 1D slab model
|
|
|
|
"""
|
|
|
|
openmc.check_type('num_regions', num_regions, Integral)
|
|
openmc.check_greater_than('num_regions', num_regions, 0)
|
|
if mat_names is not None:
|
|
openmc.check_length('mat_names', mat_names, num_regions)
|
|
openmc.check_iterable_type('mat_names', mat_names, str)
|
|
else:
|
|
mat_names = []
|
|
for i in range(num_regions):
|
|
mat_names.append('mat_' + str(i + 1))
|
|
|
|
# # Make Materials
|
|
materials_file = openmc.Materials()
|
|
macros = []
|
|
mats = []
|
|
for i in range(len(mat_names)):
|
|
macros.append(openmc.Macroscopic('mat_' + str(i + 1)))
|
|
mats.append(openmc.Material(name=mat_names[i]))
|
|
mats[-1].set_density('macro', 1.0)
|
|
mats[-1].add_macroscopic(macros[-1])
|
|
|
|
materials_file += mats
|
|
|
|
materials_file.cross_sections = mgxslib_name
|
|
|
|
# # Make Geometry
|
|
rad_outer = 929.45
|
|
# Set a cell boundary to exist for every material above (exclude the 0)
|
|
rads = np.linspace(0., rad_outer, len(mats) + 1, endpoint=True)[1:]
|
|
|
|
# Instantiate Universe
|
|
root = openmc.Universe(universe_id=0, name='root universe')
|
|
cells = []
|
|
|
|
surfs = []
|
|
surfs.append(openmc.XPlane(x0=0., boundary_type='reflective'))
|
|
for r, rad in enumerate(rads):
|
|
if r == len(rads) - 1:
|
|
surfs.append(openmc.XPlane(x0=rad, boundary_type='vacuum'))
|
|
else:
|
|
surfs.append(openmc.XPlane(x0=rad))
|
|
|
|
# Instantiate Cells
|
|
cells = []
|
|
for c in range(len(surfs) - 1):
|
|
cells.append(openmc.Cell())
|
|
cells[-1].region = (+surfs[c] & -surfs[c + 1])
|
|
cells[-1].fill = mats[c]
|
|
|
|
# Register Cells with Universe
|
|
root.add_cells(cells)
|
|
|
|
# Instantiate a Geometry, register the root Universe, and export to XML
|
|
geometry_file = openmc.Geometry(root)
|
|
|
|
# # Make Settings
|
|
# Instantiate a Settings object, set all runtime parameters
|
|
settings_file = openmc.Settings()
|
|
settings_file.energy_mode = 'multi-group'
|
|
settings_file.tabular_legendre = {'enable': False}
|
|
settings_file.batches = 10
|
|
settings_file.inactive = 5
|
|
settings_file.particles = 1000
|
|
|
|
# Build source distribution
|
|
INF = 1000.
|
|
bounds = [0., -INF, -INF, rads[0], INF, INF]
|
|
uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:])
|
|
settings_file.source = openmc.IndependentSource(space=uniform_dist)
|
|
|
|
settings_file.output = {'summary': False}
|
|
|
|
model = openmc.Model()
|
|
model.geometry = geometry_file
|
|
model.materials = materials_file
|
|
model.settings = settings_file
|
|
model.xs_data = macros
|
|
|
|
return model
|
|
|
|
|
|
def _generate_c5g7_materials(second_temp = False) -> openmc.Materials:
|
|
"""Generate materials utilizing multi-group cross sections based on the
|
|
the C5G7 Benchmark.
|
|
|
|
Parameters
|
|
----------
|
|
second_temp : bool, optional
|
|
Whether or not the cross sections should contain two temperature datapoints.
|
|
The first data point is the C5G7 cross sections, which corresponds to a temperature
|
|
of 294 K. The second data point is the C5G7 cross sections multiplied by 1/2,
|
|
which corresponds to a temperature of 394 K. This temperature dependence is
|
|
fictitious; it is used for testing temperature feedback in the random ray solver.
|
|
|
|
Returns
|
|
-------
|
|
materials : openmc.Materials
|
|
Materials object containing UO2 and water materials.
|
|
|
|
Data Sources
|
|
------------
|
|
All cross section data are from:
|
|
Lewis et al., "Benchmark specification for determinisitc 2D/3D MOX fuel
|
|
assembly transport calculations without spatial homogenization"
|
|
"""
|
|
# Instantiate the energy group data
|
|
# MGXS for the UO2 pins.
|
|
group_edges = [1e-5, 0.0635, 10.0, 1.0e2, 1.0e3, 0.5e6, 1.0e6, 20.0e6]
|
|
groups = openmc.mgxs.EnergyGroups(group_edges)
|
|
|
|
uo2_total = np.array([0.1779492, 0.3298048, 0.4803882, 0.5543674, 0.3118013, 0.3951678,
|
|
0.5644058])
|
|
uo2_abs = np.array([8.0248e-03, 3.7174e-03, 2.6769e-02, 9.6236e-02, 3.0020e-02,
|
|
1.1126e-01, 2.8278e-01])
|
|
uo2_scatter_matrix = np.array(
|
|
[[[0.1275370, 0.0423780, 0.0000094, 0.0000000, 0.0000000, 0.0000000, 0.0000000],
|
|
[0.0000000, 0.3244560, 0.0016314, 0.0000000, 0.0000000, 0.0000000, 0.0000000],
|
|
[0.0000000, 0.0000000, 0.4509400, 0.0026792, 0.0000000, 0.0000000, 0.0000000],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.4525650, 0.0055664, 0.0000000, 0.0000000],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.0001253, 0.2714010, 0.0102550, 0.0000000],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0012968, 0.2658020, 0.0168090],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0085458, 0.2730800]]])
|
|
uo2_scatter_matrix = np.rollaxis(uo2_scatter_matrix, 0, 3)
|
|
uo2_fission = np.array([7.21206e-03, 8.19301e-04, 6.45320e-03, 1.85648e-02, 1.78084e-02,
|
|
8.30348e-02, 2.16004e-01])
|
|
uo2_nu_fission = np.array([2.005998e-02, 2.027303e-03, 1.570599e-02, 4.518301e-02,
|
|
4.334208e-02, 2.020901e-01, 5.257105e-01])
|
|
uo2_chi = np.array([5.8791e-01, 4.1176e-01, 3.3906e-04, 1.1761e-07, 0.0000e+00,
|
|
0.0000e+00, 0.0000e+00])
|
|
|
|
# MGXS for the H2O moderator.
|
|
h2o_total = np.array([0.15920605, 0.412969593, 0.59030986, 0.58435, 0.718, 1.2544497,
|
|
2.650379])
|
|
h2o_abs = np.array([6.0105e-04, 1.5793e-05, 3.3716e-04, 1.9406e-03, 5.7416e-03,
|
|
1.5001e-02, 3.7239e-02])
|
|
h2o_scatter_matrix = np.array(
|
|
[[[0.0444777, 0.1134000, 0.0007235, 0.0000037, 0.0000001, 0.0000000, 0.0000000],
|
|
[0.0000000, 0.2823340, 0.1299400, 0.0006234, 0.0000480, 0.0000074, 0.0000010],
|
|
[0.0000000, 0.0000000, 0.3452560, 0.2245700, 0.0169990, 0.0026443, 0.0005034],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.0910284, 0.4155100, 0.0637320, 0.0121390],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.0000714, 0.1391380, 0.5118200, 0.0612290],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0022157, 0.6999130, 0.5373200],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.1324400, 2.4807000]]])
|
|
h2o_scatter_matrix = np.rollaxis(h2o_scatter_matrix, 0, 3)
|
|
|
|
# Instantiate the 7-group (C5G7) cross section data
|
|
uo2_xsdata = openmc.XSdata('UO2', groups)
|
|
uo2_xsdata.order = 0
|
|
uo2_xsdata.set_total(
|
|
[0.1779492, 0.3298048, 0.4803882, 0.5543674, 0.3118013, 0.3951678,
|
|
0.5644058])
|
|
uo2_xsdata.set_absorption([8.0248e-03, 3.7174e-03, 2.6769e-02, 9.6236e-02,
|
|
3.0020e-02, 1.1126e-01, 2.8278e-01])
|
|
scatter_matrix = np.array(
|
|
[[[0.1275370, 0.0423780, 0.0000094, 0.0000000, 0.0000000, 0.0000000, 0.0000000],
|
|
[0.0000000, 0.3244560, 0.0016314, 0.0000000,
|
|
0.0000000, 0.0000000, 0.0000000],
|
|
[0.0000000, 0.0000000, 0.4509400, 0.0026792,
|
|
0.0000000, 0.0000000, 0.0000000],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.4525650,
|
|
0.0055664, 0.0000000, 0.0000000],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.0001253,
|
|
0.2714010, 0.0102550, 0.0000000],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.0000000,
|
|
0.0012968, 0.2658020, 0.0168090],
|
|
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0085458, 0.2730800]]])
|
|
scatter_matrix = np.rollaxis(scatter_matrix, 0, 3)
|
|
uo2_xsdata.set_scatter_matrix(scatter_matrix)
|
|
uo2_xsdata.set_fission([7.21206e-03, 8.19301e-04, 6.45320e-03,
|
|
1.85648e-02, 1.78084e-02, 8.30348e-02,
|
|
2.16004e-01])
|
|
nu_fission = np.array([2.005998e-02, 2.027303e-03, 1.570599e-02,
|
|
4.518301e-02, 4.334208e-02, 2.020901e-01,
|
|
5.257105e-01])
|
|
uo2_xsdata.set_nu_fission(nu_fission)
|
|
uo2_xsdata.set_chi([5.8791e-01, 4.1176e-01, 3.3906e-04, 1.1761e-07, 0.0000e+00,
|
|
0.0000e+00, 0.0000e+00])
|
|
uo2_xsdata.set_total(uo2_total, temperature=294.0)
|
|
uo2_xsdata.set_absorption(uo2_abs, temperature=294.0)
|
|
uo2_xsdata.set_scatter_matrix(uo2_scatter_matrix, temperature=294.0)
|
|
uo2_xsdata.set_fission(uo2_fission, temperature=294.0)
|
|
uo2_xsdata.set_nu_fission(uo2_nu_fission, temperature=294.0)
|
|
uo2_xsdata.set_chi(uo2_chi, temperature=294.0)
|
|
|
|
h2o_xsdata = openmc.XSdata('LWTR', groups)
|
|
h2o_xsdata.order = 0
|
|
h2o_xsdata.set_total(h2o_total, temperature=294.0)
|
|
h2o_xsdata.set_absorption(h2o_abs, temperature=294.0)
|
|
h2o_xsdata.set_scatter_matrix(h2o_scatter_matrix, temperature=294.0)
|
|
|
|
# Add the second temperature data point if requested.
|
|
if second_temp:
|
|
uo2_xsdata.add_temperature(394.0)
|
|
uo2_xsdata.set_total(0.5 * uo2_total, temperature=394.0)
|
|
uo2_xsdata.set_absorption(0.5 * uo2_abs, temperature=394.0)
|
|
uo2_xsdata.set_scatter_matrix(0.5 * uo2_scatter_matrix, temperature=394.0)
|
|
uo2_xsdata.set_fission(0.5 * uo2_fission, temperature=394.0)
|
|
uo2_xsdata.set_nu_fission(0.5 * uo2_nu_fission, temperature=394.0)
|
|
uo2_xsdata.set_chi(uo2_chi, temperature=394.0)
|
|
|
|
h2o_xsdata.add_temperature(394.0)
|
|
h2o_xsdata.set_total(0.5 * h2o_total, temperature=394.0)
|
|
h2o_xsdata.set_absorption(0.5 * h2o_abs, temperature=394.0)
|
|
h2o_xsdata.set_scatter_matrix(0.5 * h2o_scatter_matrix, temperature=394.0)
|
|
|
|
mg_cross_sections = openmc.MGXSLibrary(groups)
|
|
mg_cross_sections.add_xsdatas([uo2_xsdata, h2o_xsdata])
|
|
mg_cross_sections.export_to_hdf5('mgxs.h5')
|
|
|
|
###########################################################################
|
|
# Create materials for the problem
|
|
|
|
# Instantiate some Materials and register the appropriate macroscopic data
|
|
uo2 = openmc.Material(name='UO2 fuel')
|
|
uo2.set_density('macro', 1.0)
|
|
uo2.add_macroscopic('UO2')
|
|
|
|
water = openmc.Material(name='Water')
|
|
water.set_density('macro', 1.0)
|
|
water.add_macroscopic('LWTR')
|
|
|
|
# Instantiate a Materials collection and export to XML
|
|
materials = openmc.Materials([uo2, water])
|
|
materials.cross_sections = "mgxs.h5"
|
|
return materials
|
|
|
|
|
|
def _generate_subdivided_pin_cell(uo2, water) -> openmc.Universe:
|
|
"""Create a radially and azimuthally subdivided pin cell universe. Helper
|
|
function for random_ray_pin_cell() and random_ray_lattice()
|
|
|
|
Parameters
|
|
----------
|
|
uo2 : openmc.Material
|
|
UO2 material
|
|
water : openmc.Material
|
|
Water material
|
|
|
|
Returns
|
|
-------
|
|
pincell : openmc.Universe
|
|
Universe containing an unbounded pin cell
|
|
|
|
"""
|
|
########################################
|
|
# Define an unbounded pin cell universe
|
|
|
|
# Create a surface for the fuel outer radius
|
|
fuel_or = openmc.ZCylinder(r=0.54, name='Fuel OR')
|
|
inner_ring_a = openmc.ZCylinder(r=0.33, name='inner ring a')
|
|
inner_ring_b = openmc.ZCylinder(r=0.45, name='inner ring b')
|
|
outer_ring_a = openmc.ZCylinder(r=0.60, name='outer ring a')
|
|
outer_ring_b = openmc.ZCylinder(r=0.69, name='outer ring b')
|
|
|
|
# Instantiate Cells
|
|
fuel_a = openmc.Cell(fill=uo2, region=-inner_ring_a, name='fuel inner a')
|
|
fuel_b = openmc.Cell(fill=uo2, region=+inner_ring_a & -
|
|
inner_ring_b, name='fuel inner b')
|
|
fuel_c = openmc.Cell(fill=uo2, region=+inner_ring_b & -
|
|
fuel_or, name='fuel inner c')
|
|
moderator_a = openmc.Cell(
|
|
fill=water, region=+fuel_or & -outer_ring_a, name='moderator inner a')
|
|
moderator_b = openmc.Cell(
|
|
fill=water, region=+outer_ring_a & -outer_ring_b, name='moderator outer b')
|
|
moderator_c = openmc.Cell(
|
|
fill=water, region=+outer_ring_b, name='moderator outer c')
|
|
|
|
# Create pin cell universe
|
|
pincell_base = openmc.Universe()
|
|
|
|
# Register Cells with Universe
|
|
pincell_base.add_cells(
|
|
[fuel_a, fuel_b, fuel_c, moderator_a, moderator_b, moderator_c])
|
|
|
|
# Create planes for azimuthal sectors
|
|
azimuthal_planes = []
|
|
for i in range(8):
|
|
angle = 2 * i * openmc.pi / 8
|
|
normal_vector = (-openmc.sin(angle), openmc.cos(angle), 0)
|
|
azimuthal_planes.append(openmc.Plane(
|
|
a=normal_vector[0], b=normal_vector[1], c=normal_vector[2], d=0))
|
|
|
|
# Create a cell for each azimuthal sector
|
|
azimuthal_cells = []
|
|
for i in range(8):
|
|
azimuthal_cell = openmc.Cell(name=f'azimuthal_cell_{i}')
|
|
azimuthal_cell.fill = pincell_base
|
|
azimuthal_cell.region = + \
|
|
azimuthal_planes[i] & -azimuthal_planes[(i+1) % 8]
|
|
azimuthal_cells.append(azimuthal_cell)
|
|
|
|
# Create a geometry with the azimuthal universes
|
|
pincell = openmc.Universe(cells=azimuthal_cells, name='pincell')
|
|
|
|
return pincell
|
|
|
|
|
|
def random_ray_pin_cell(second_temp = False) -> openmc.Model:
|
|
"""Create a PWR pin cell example using C5G7 cross section data.
|
|
cross section data.
|
|
|
|
Parameters
|
|
----------
|
|
second_temp : bool, optional
|
|
Whether or not the cross sections should contain two temperature datapoints.
|
|
The first data point is the C5G7 cross sections, which corresponds to a temperature
|
|
of 294 K. The second data point is the C5G7 cross sections multiplied by 1/2,
|
|
which corresponds to a temperature of 3934 K. This temperature dependence is
|
|
fictitious; it is used for testing temperature feedback in the random ray solver.
|
|
|
|
Returns
|
|
-------
|
|
model : openmc.Model
|
|
A PWR pin cell model
|
|
|
|
"""
|
|
model = openmc.Model()
|
|
|
|
###########################################################################
|
|
# Create Materials for the problem
|
|
materials = _generate_c5g7_materials(second_temp)
|
|
uo2 = materials[0]
|
|
water = materials[1]
|
|
|
|
###########################################################################
|
|
# Define problem geometry
|
|
pincell = _generate_subdivided_pin_cell(uo2, water)
|
|
|
|
########################################
|
|
# Define cell containing lattice and other stuff
|
|
pitch = PINCELL_PITCH
|
|
box = openmc.model.RectangularPrism(pitch, pitch, boundary_type='reflective')
|
|
|
|
pincell = openmc.Cell(fill=pincell, region=-box, name='pincell')
|
|
|
|
# Create a geometry with the top-level cell
|
|
geometry = openmc.Geometry([pincell])
|
|
|
|
###########################################################################
|
|
# Define problem settings
|
|
|
|
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
|
settings = openmc.Settings()
|
|
settings.energy_mode = "multi-group"
|
|
settings.batches = 400
|
|
settings.inactive = 200
|
|
settings.particles = 100
|
|
|
|
# Create an initial uniform spatial source distribution over fissionable zones
|
|
lower_left = (-pitch / 2, -pitch / 2, -1)
|
|
upper_right = (pitch / 2, pitch / 2, 1)
|
|
uniform_dist = openmc.stats.Box(lower_left, upper_right)
|
|
rr_source = openmc.IndependentSource(space=uniform_dist)
|
|
|
|
settings.random_ray['distance_active'] = 100.0
|
|
settings.random_ray['distance_inactive'] = 20.0
|
|
settings.random_ray['ray_source'] = rr_source
|
|
settings.random_ray['volume_normalized_flux_tallies'] = True
|
|
|
|
###########################################################################
|
|
# Define tallies
|
|
# Now use the mesh filter in a tally and indicate what scores are desired
|
|
tally = openmc.Tally(name="Pin tally")
|
|
tally.scores = ['flux', 'fission', 'nu-fission']
|
|
tally.estimator = 'analog'
|
|
|
|
# Instantiate a Tallies collection and export to XML
|
|
tallies = openmc.Tallies([tally])
|
|
|
|
###########################################################################
|
|
# Exporting to OpenMC model
|
|
###########################################################################
|
|
|
|
model.geometry = geometry
|
|
model.materials = materials
|
|
model.settings = settings
|
|
model.tallies = tallies
|
|
return model
|
|
|
|
|
|
def random_ray_lattice(second_temp = False) -> openmc.Model:
|
|
"""Create a 2x2 PWR pin cell asymmetrical lattice example.
|
|
|
|
This model is a 2x2 reflective lattice of fuel pins with one of the lattice
|
|
locations having just moderator instead of a fuel pin. It uses C5G7
|
|
cross section data.
|
|
|
|
Parameters
|
|
----------
|
|
second_temp : bool, optional
|
|
Whether or not the cross sections should contain two temperature datapoints.
|
|
The first data point is the C5G7 cross sections, which corresponds to a temperature
|
|
of 294 K. The second data point is the C5G7 cross sections multiplied by 1/2,
|
|
which corresponds to a temperature of 3934 K. This temperature dependence is
|
|
fictitious; it is used for testing temperature feedback in the random ray solver.
|
|
|
|
Returns
|
|
-------
|
|
model : openmc.Model
|
|
A PWR 2x2 lattice model
|
|
|
|
"""
|
|
model = openmc.Model()
|
|
|
|
###########################################################################
|
|
# Create Materials for the problem
|
|
materials = _generate_c5g7_materials(second_temp)
|
|
uo2 = materials[0]
|
|
water = materials[1]
|
|
|
|
###########################################################################
|
|
# Define problem geometry
|
|
pincell = _generate_subdivided_pin_cell(uo2, water)
|
|
|
|
########################################
|
|
# Define a moderator lattice universe
|
|
|
|
moderator_infinite = openmc.Cell(name='moderator infinite')
|
|
moderator_infinite.fill = water
|
|
|
|
mu = openmc.Universe()
|
|
mu.add_cells([moderator_infinite])
|
|
|
|
pitch = PINCELL_PITCH
|
|
lattice = openmc.RectLattice()
|
|
lattice.lower_left = [-pitch/2.0, -pitch/2.0]
|
|
lattice.pitch = [pitch/10.0, pitch/10.0]
|
|
lattice.universes = np.full((10, 10), mu)
|
|
|
|
mod_lattice_cell = openmc.Cell(fill=lattice)
|
|
|
|
mod_lattice_uni = openmc.Universe()
|
|
|
|
mod_lattice_uni.add_cells([mod_lattice_cell])
|
|
|
|
########################################
|
|
# Define 2x2 outer lattice
|
|
lattice2x2 = openmc.RectLattice()
|
|
lattice2x2.lower_left = (-pitch, -pitch)
|
|
lattice2x2.pitch = (pitch, pitch)
|
|
lattice2x2.universes = [
|
|
[pincell, pincell],
|
|
[pincell, mod_lattice_uni]
|
|
]
|
|
|
|
########################################
|
|
# Define cell containing lattice and other stuff
|
|
box = openmc.model.RectangularPrism(pitch*2, pitch*2, boundary_type='reflective')
|
|
|
|
assembly = openmc.Cell(fill=lattice2x2, region=-box, name='assembly')
|
|
|
|
# Create a geometry with the top-level cell
|
|
geometry = openmc.Geometry([assembly])
|
|
|
|
###########################################################################
|
|
# Define problem settings
|
|
|
|
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
|
settings = openmc.Settings()
|
|
settings.energy_mode = "multi-group"
|
|
settings.batches = 10
|
|
settings.inactive = 5
|
|
settings.particles = 100
|
|
|
|
# Create an initial uniform spatial source distribution over fissionable zones
|
|
lower_left = (-pitch, -pitch, -1)
|
|
upper_right = (pitch, pitch, 1)
|
|
uniform_dist = openmc.stats.Box(lower_left, upper_right)
|
|
rr_source = openmc.IndependentSource(space=uniform_dist)
|
|
|
|
settings.random_ray['distance_active'] = 100.0
|
|
settings.random_ray['distance_inactive'] = 20.0
|
|
settings.random_ray['ray_source'] = rr_source
|
|
settings.random_ray['volume_normalized_flux_tallies'] = True
|
|
|
|
###########################################################################
|
|
# Define tallies
|
|
|
|
# Create a mesh that will be used for tallying
|
|
mesh = openmc.RegularMesh()
|
|
mesh.dimension = (2, 2)
|
|
mesh.lower_left = (-pitch, -pitch)
|
|
mesh.upper_right = (pitch, pitch)
|
|
|
|
# Create a mesh filter that can be used in a tally
|
|
mesh_filter = openmc.MeshFilter(mesh)
|
|
|
|
# Create an energy group filter as well
|
|
group_edges = [1e-5, 0.0635, 10.0, 1.0e2, 1.0e3, 0.5e6, 1.0e6, 20.0e6]
|
|
energy_filter = openmc.EnergyFilter(group_edges)
|
|
|
|
# Now use the mesh filter in a tally and indicate what scores are desired
|
|
tally = openmc.Tally(name="Mesh tally")
|
|
tally.filters = [mesh_filter, energy_filter]
|
|
tally.scores = ['flux', 'fission', 'nu-fission']
|
|
tally.estimator = 'analog'
|
|
|
|
# Instantiate a Tallies collection and export to XML
|
|
tallies = openmc.Tallies([tally])
|
|
|
|
###########################################################################
|
|
# Exporting to OpenMC model
|
|
###########################################################################
|
|
|
|
model.geometry = geometry
|
|
model.materials = materials
|
|
model.settings = settings
|
|
model.tallies = tallies
|
|
return model
|
|
|
|
|
|
def random_ray_three_region_cube() -> openmc.Model:
|
|
"""Create a three region cube model.
|
|
|
|
This is a simple monoenergetic problem of a cube with three concentric cubic
|
|
regions. The innermost region is near void (with Sigma_t around 10^-5) and
|
|
contains an external isotropic source term, the middle region is void (with
|
|
Sigma_t around 10^-4), and the outer region of the cube is an absorber
|
|
(with Sigma_t around 1).
|
|
|
|
Returns
|
|
-------
|
|
model : openmc.Model
|
|
A three region cube model
|
|
|
|
"""
|
|
|
|
model = openmc.Model()
|
|
|
|
###########################################################################
|
|
# Helper function creates a 3 region cube with different fills in each region
|
|
def fill_cube(N, n_1, n_2, fill_1, fill_2, fill_3):
|
|
cube = [[[0 for _ in range(N)] for _ in range(N)] for _ in range(N)]
|
|
for i in range(N):
|
|
for j in range(N):
|
|
for k in range(N):
|
|
if i < n_1 and j >= (N-n_1) and k < n_1:
|
|
cube[i][j][k] = fill_1
|
|
elif i < n_2 and j >= (N-n_2) and k < n_2:
|
|
cube[i][j][k] = fill_2
|
|
else:
|
|
cube[i][j][k] = fill_3
|
|
return cube
|
|
|
|
###########################################################################
|
|
# Create multigroup data
|
|
|
|
# Instantiate the energy group data
|
|
ebins = [1e-5, 20.0e6]
|
|
groups = openmc.mgxs.EnergyGroups(group_edges=ebins)
|
|
|
|
void_sigma_a = 4.0e-6
|
|
void_sigma_s = 3.0e-4
|
|
void_mat_data = openmc.XSdata('void', groups)
|
|
void_mat_data.order = 0
|
|
void_mat_data.set_total([void_sigma_a + void_sigma_s])
|
|
void_mat_data.set_absorption([void_sigma_a])
|
|
void_mat_data.set_scatter_matrix(
|
|
np.rollaxis(np.array([[[void_sigma_s]]]), 0, 3))
|
|
|
|
absorber_sigma_a = 0.75
|
|
absorber_sigma_s = 0.25
|
|
absorber_mat_data = openmc.XSdata('absorber', groups)
|
|
absorber_mat_data.order = 0
|
|
absorber_mat_data.set_total([absorber_sigma_a + absorber_sigma_s])
|
|
absorber_mat_data.set_absorption([absorber_sigma_a])
|
|
absorber_mat_data.set_scatter_matrix(
|
|
np.rollaxis(np.array([[[absorber_sigma_s]]]), 0, 3))
|
|
|
|
multiplier = 0.1
|
|
source_sigma_a = void_sigma_a * multiplier
|
|
source_sigma_s = void_sigma_s * multiplier
|
|
source_mat_data = openmc.XSdata('source', groups)
|
|
source_mat_data.order = 0
|
|
source_mat_data.set_total([source_sigma_a + source_sigma_s])
|
|
source_mat_data.set_absorption([source_sigma_a])
|
|
source_mat_data.set_scatter_matrix(
|
|
np.rollaxis(np.array([[[source_sigma_s]]]), 0, 3))
|
|
|
|
mg_cross_sections_file = openmc.MGXSLibrary(groups)
|
|
mg_cross_sections_file.add_xsdatas(
|
|
[source_mat_data, void_mat_data, absorber_mat_data])
|
|
mg_cross_sections_file.export_to_hdf5()
|
|
|
|
###########################################################################
|
|
# Create materials for the problem
|
|
|
|
# Instantiate some Macroscopic Data
|
|
source_data = openmc.Macroscopic('source')
|
|
void_data = openmc.Macroscopic('void')
|
|
absorber_data = openmc.Macroscopic('absorber')
|
|
|
|
# Instantiate some Materials and register the appropriate Macroscopic objects
|
|
source_mat = openmc.Material(name='source')
|
|
source_mat.set_density('macro', 1.0)
|
|
source_mat.add_macroscopic(source_data)
|
|
|
|
void_mat = openmc.Material(name='void')
|
|
void_mat.set_density('macro', 1.0)
|
|
void_mat.add_macroscopic(void_data)
|
|
|
|
absorber_mat = openmc.Material(name='absorber')
|
|
absorber_mat.set_density('macro', 1.0)
|
|
absorber_mat.add_macroscopic(absorber_data)
|
|
|
|
# Instantiate a Materials collection and export to XML
|
|
materials_file = openmc.Materials([source_mat, void_mat, absorber_mat])
|
|
materials_file.cross_sections = "mgxs.h5"
|
|
|
|
###########################################################################
|
|
# Define problem geometry
|
|
|
|
source_cell = openmc.Cell(fill=source_mat, name='infinite source region')
|
|
void_cell = openmc.Cell(fill=void_mat, name='infinite void region')
|
|
absorber_cell = openmc.Cell(
|
|
fill=absorber_mat, name='infinite absorber region')
|
|
|
|
source_universe = openmc.Universe(name='source universe')
|
|
source_universe.add_cells([source_cell])
|
|
|
|
void_universe = openmc.Universe()
|
|
void_universe.add_cells([void_cell])
|
|
|
|
absorber_universe = openmc.Universe()
|
|
absorber_universe.add_cells([absorber_cell])
|
|
|
|
absorber_width = 30.0
|
|
n_base = 6
|
|
|
|
# This variable can be increased above 1 to refine the FSR mesh resolution further
|
|
refinement_level = 2
|
|
|
|
n = n_base * refinement_level
|
|
pitch = absorber_width / n
|
|
|
|
pattern = fill_cube(n, 1*refinement_level, 5*refinement_level,
|
|
source_universe, void_universe, absorber_universe)
|
|
|
|
lattice = openmc.RectLattice()
|
|
lattice.lower_left = [0.0, 0.0, 0.0]
|
|
lattice.pitch = [pitch, pitch, pitch]
|
|
lattice.universes = pattern
|
|
|
|
lattice_cell = openmc.Cell(fill=lattice)
|
|
|
|
lattice_uni = openmc.Universe()
|
|
lattice_uni.add_cells([lattice_cell])
|
|
|
|
x_low = openmc.XPlane(x0=0.0, boundary_type='reflective')
|
|
x_high = openmc.XPlane(x0=absorber_width, boundary_type='vacuum')
|
|
|
|
y_low = openmc.YPlane(y0=0.0, boundary_type='reflective')
|
|
y_high = openmc.YPlane(y0=absorber_width, boundary_type='vacuum')
|
|
|
|
z_low = openmc.ZPlane(z0=0.0, boundary_type='reflective')
|
|
z_high = openmc.ZPlane(z0=absorber_width, boundary_type='vacuum')
|
|
|
|
full_domain = openmc.Cell(fill=lattice_uni, region=+x_low & -
|
|
x_high & +y_low & -y_high & +z_low & -z_high, name='full domain')
|
|
|
|
root = openmc.Universe(name='root universe')
|
|
root.add_cell(full_domain)
|
|
|
|
# Create a geometry with the two cells and export to XML
|
|
geometry = openmc.Geometry(root)
|
|
|
|
###########################################################################
|
|
# Define problem settings
|
|
|
|
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
|
settings = openmc.Settings()
|
|
settings.energy_mode = "multi-group"
|
|
settings.inactive = 5
|
|
settings.batches = 10
|
|
settings.particles = 90
|
|
settings.run_mode = 'fixed source'
|
|
|
|
# Create an initial uniform spatial source for ray integration
|
|
lower_left_ray = [0.0, 0.0, 0.0]
|
|
upper_right_ray = [absorber_width, absorber_width, absorber_width]
|
|
uniform_dist_ray = openmc.stats.Box(
|
|
lower_left_ray, upper_right_ray, only_fissionable=False)
|
|
rr_source = openmc.IndependentSource(space=uniform_dist_ray)
|
|
|
|
settings.random_ray['distance_active'] = 500.0
|
|
settings.random_ray['distance_inactive'] = 100.0
|
|
settings.random_ray['ray_source'] = rr_source
|
|
settings.random_ray['volume_normalized_flux_tallies'] = True
|
|
|
|
# Create the neutron source in the bottom right of the moderator
|
|
# Good - fast group appears largest (besides most thermal)
|
|
strengths = [1.0]
|
|
midpoints = [100.0]
|
|
energy_distribution = openmc.stats.Discrete(x=midpoints, p=strengths)
|
|
|
|
source = openmc.IndependentSource(energy=energy_distribution, constraints={
|
|
'domains': [source_universe]}, strength=3.14)
|
|
|
|
settings.source = [source]
|
|
|
|
###########################################################################
|
|
# Define tallies
|
|
|
|
estimator = 'tracklength'
|
|
|
|
absorber_filter = openmc.MaterialFilter(absorber_mat)
|
|
absorber_tally = openmc.Tally(name="Absorber Tally")
|
|
absorber_tally.filters = [absorber_filter]
|
|
absorber_tally.scores = ['flux']
|
|
absorber_tally.estimator = estimator
|
|
|
|
void_filter = openmc.MaterialFilter(void_mat)
|
|
void_tally = openmc.Tally(name="Void Tally")
|
|
void_tally.filters = [void_filter]
|
|
void_tally.scores = ['flux']
|
|
void_tally.estimator = estimator
|
|
|
|
source_filter = openmc.MaterialFilter(source_mat)
|
|
source_tally = openmc.Tally(name="Source Tally")
|
|
source_tally.filters = [source_filter]
|
|
source_tally.scores = ['flux']
|
|
source_tally.estimator = estimator
|
|
|
|
# Instantiate a Tallies collection and export to XML
|
|
tallies = openmc.Tallies([source_tally, void_tally, absorber_tally])
|
|
|
|
###########################################################################
|
|
# Assmble Model
|
|
|
|
model.geometry = geometry
|
|
model.materials = materials_file
|
|
model.settings = settings
|
|
model.tallies = tallies
|
|
|
|
return model
|
|
|
|
def random_ray_three_region_cube_with_detectors() -> openmc.Model:
|
|
"""Create a three region cube model with two external tally regions.
|
|
|
|
This is an adaptation of the simple monoenergetic problem of a cube with
|
|
three concentric cubic regions. The innermost region is near void (with
|
|
Sigma_t around 10^-5) and contains an external isotropic source term, the
|
|
middle region is a mild scatterer (with Sigma_t around 10^-3), and the
|
|
outer region of the cube is a scatterer and absorber (with Sigma_t around
|
|
1).
|
|
|
|
Two cubic "detector" regions are found outside this geometry, one along the
|
|
y-axis near z=0, and the other in the upper right corner of the system.
|
|
The size of each detector is scaled to be equal to that of the source
|
|
region. The model returned by this function contains cell tallies on each
|
|
detector.
|
|
|
|
Returns
|
|
-------
|
|
model : openmc.Model
|
|
A three region cube model
|
|
|
|
"""
|
|
|
|
model = openmc.Model()
|
|
|
|
###########################################################################
|
|
# Helper function creates a 3 region cube with different fills in each region
|
|
def fill_cube(N, n_1, n_2, fill_1, fill_2, fill_3):
|
|
cube = [[[0 for _ in range(N)] for _ in range(N)] for _ in range(N)]
|
|
for i in range(N):
|
|
for j in range(N):
|
|
for k in range(N):
|
|
if i < n_1 and j >= (N-n_1) and k < n_1:
|
|
cube[i][j][k] = fill_1
|
|
elif i < n_2 and j >= (N-n_2) and k < n_2:
|
|
cube[i][j][k] = fill_2
|
|
else:
|
|
cube[i][j][k] = fill_3
|
|
return cube
|
|
|
|
###########################################################################
|
|
# Create multigroup data
|
|
|
|
# Instantiate the energy group data
|
|
ebins = [1e-5, 20.0e6]
|
|
groups = openmc.mgxs.EnergyGroups(group_edges=ebins)
|
|
|
|
cavity_sigma_a = 4.0e-5
|
|
cavity_sigma_s = 3.0e-3
|
|
cavity_mat_data = openmc.XSdata('cavity', groups)
|
|
cavity_mat_data.order = 0
|
|
cavity_mat_data.set_total([cavity_sigma_a + cavity_sigma_s])
|
|
cavity_mat_data.set_absorption([cavity_sigma_a])
|
|
cavity_mat_data.set_scatter_matrix(
|
|
np.rollaxis(np.array([[[cavity_sigma_s]]]), 0, 3))
|
|
|
|
absorber_sigma_a = 0.50
|
|
absorber_sigma_s = 0.50
|
|
absorber_mat_data = openmc.XSdata('absorber', groups)
|
|
absorber_mat_data.order = 0
|
|
absorber_mat_data.set_total([absorber_sigma_a + absorber_sigma_s])
|
|
absorber_mat_data.set_absorption([absorber_sigma_a])
|
|
absorber_mat_data.set_scatter_matrix(
|
|
np.rollaxis(np.array([[[absorber_sigma_s]]]), 0, 3))
|
|
|
|
multiplier = 0.01
|
|
source_sigma_a = cavity_sigma_a * multiplier
|
|
source_sigma_s = cavity_sigma_s * multiplier
|
|
source_mat_data = openmc.XSdata('source', groups)
|
|
source_mat_data.order = 0
|
|
source_mat_data.set_total([source_sigma_a + source_sigma_s])
|
|
source_mat_data.set_absorption([source_sigma_a])
|
|
source_mat_data.set_scatter_matrix(
|
|
np.rollaxis(np.array([[[source_sigma_s]]]), 0, 3))
|
|
|
|
mg_cross_sections_file = openmc.MGXSLibrary(groups)
|
|
mg_cross_sections_file.add_xsdatas(
|
|
[source_mat_data, cavity_mat_data, absorber_mat_data])
|
|
mg_cross_sections_file.export_to_hdf5()
|
|
|
|
###########################################################################
|
|
# Create materials for the problem
|
|
|
|
# Instantiate some Macroscopic Data
|
|
source_data = openmc.Macroscopic('source')
|
|
cavity_data = openmc.Macroscopic('cavity')
|
|
absorber_data = openmc.Macroscopic('absorber')
|
|
|
|
# Instantiate some Materials and register the appropriate Macroscopic objects
|
|
source_mat = openmc.Material(name='source')
|
|
source_mat.set_density('macro', 1.0)
|
|
source_mat.add_macroscopic(source_data)
|
|
|
|
cavity_mat = openmc.Material(name='cavity')
|
|
cavity_mat.set_density('macro', 1.0)
|
|
cavity_mat.add_macroscopic(cavity_data)
|
|
|
|
absorber_mat = openmc.Material(name='absorber')
|
|
absorber_mat.set_density('macro', 1.0)
|
|
absorber_mat.add_macroscopic(absorber_data)
|
|
|
|
# Instantiate a Materials collection
|
|
materials_file = openmc.Materials([source_mat, cavity_mat, absorber_mat])
|
|
materials_file.cross_sections = "mgxs.h5"
|
|
|
|
###########################################################################
|
|
# Define problem geometry
|
|
|
|
source_cell = openmc.Cell(fill=source_mat, name='infinite source region')
|
|
cavity_cell = openmc.Cell(fill=cavity_mat, name='cube cavity region')
|
|
absorber_cell = openmc.Cell(
|
|
fill=absorber_mat, name='absorber region')
|
|
|
|
source_universe = openmc.Universe(name='source universe')
|
|
source_universe.add_cells([source_cell])
|
|
|
|
cavity_universe = openmc.Universe()
|
|
cavity_universe.add_cells([cavity_cell])
|
|
|
|
absorber_universe = openmc.Universe()
|
|
absorber_universe.add_cells([absorber_cell])
|
|
|
|
absorber_width = 30.0
|
|
n_base = 6
|
|
|
|
# This variable can be increased above 1 to refine the FSR mesh resolution further
|
|
refinement_level = 2
|
|
|
|
n = n_base * refinement_level
|
|
pitch = absorber_width / n
|
|
|
|
pattern = fill_cube(n, 1*refinement_level, 5*refinement_level,
|
|
source_universe, cavity_universe, absorber_universe)
|
|
|
|
lattice = openmc.RectLattice()
|
|
lattice.lower_left = [0.0, 0.0, 0.0]
|
|
lattice.pitch = [pitch, pitch, pitch]
|
|
lattice.universes = pattern
|
|
|
|
lattice_cell = openmc.Cell(fill=lattice)
|
|
|
|
lattice_uni = openmc.Universe()
|
|
lattice_uni.add_cells([lattice_cell])
|
|
|
|
x_low = openmc.XPlane(x0=0.0, boundary_type='reflective')
|
|
x_high = openmc.XPlane(x0=absorber_width)
|
|
|
|
y_low = openmc.YPlane(y0=0.0, boundary_type='reflective')
|
|
y_high = openmc.YPlane(y0=absorber_width)
|
|
|
|
z_low = openmc.ZPlane(z0=0.0, boundary_type='reflective')
|
|
z_high = openmc.ZPlane(z0=absorber_width)
|
|
|
|
cube_domain = openmc.Cell(fill=lattice_uni, region=+x_low & -
|
|
x_high & +y_low & -y_high & +z_low & -z_high, name='full domain')
|
|
|
|
detect_width = absorber_width / n_base
|
|
outer_width = absorber_width + detect_width
|
|
|
|
x_outer = openmc.XPlane(x0=outer_width, boundary_type='vacuum')
|
|
y_outer = openmc.YPlane(y0=outer_width, boundary_type='vacuum')
|
|
z_outer = openmc.ZPlane(z0=outer_width, boundary_type='vacuum')
|
|
|
|
detector1_right = openmc.XPlane(x0=detect_width)
|
|
detector1_top = openmc.ZPlane(z0=detect_width)
|
|
|
|
detector1_region = (
|
|
+x_low & -detector1_right &
|
|
+y_high & -y_outer &
|
|
+z_low & -detector1_top
|
|
)
|
|
detector1 = openmc.Cell(
|
|
name='detector 1',
|
|
fill=absorber_mat,
|
|
region=detector1_region
|
|
)
|
|
|
|
detector2_region = (
|
|
+x_high & -x_outer &
|
|
+y_high & -y_outer &
|
|
+z_high & -z_outer
|
|
)
|
|
detector2 = openmc.Cell(
|
|
name='detector 2',
|
|
fill=absorber_mat,
|
|
region=detector2_region
|
|
)
|
|
|
|
external_x = (
|
|
+x_high & +y_low & +z_low & -x_outer &
|
|
((-y_outer & -z_high) | (-y_high & +z_high & -z_outer))
|
|
)
|
|
external_y = (
|
|
+y_high & -y_outer &
|
|
(
|
|
(+detector1_right & -x_high & +z_low & -z_outer) |
|
|
(-detector1_right & +x_low & +detector1_top & -z_outer) |
|
|
(+x_high & -x_outer & +z_low & -z_high)
|
|
)
|
|
)
|
|
external_z = (
|
|
+x_low & +y_low & +z_high & -z_outer &
|
|
((-y_outer & -x_high) | (-y_high & +x_high & -x_outer))
|
|
)
|
|
external_cell = openmc.Cell(fill=cavity_mat,
|
|
region=(external_x | external_y | external_z),
|
|
name='outside cube')
|
|
|
|
root = openmc.Universe(
|
|
name='root universe',
|
|
cells=[cube_domain, detector1, detector2, external_cell]
|
|
)
|
|
|
|
# Create a geometry with the two cells and export to XML
|
|
geometry = openmc.Geometry(root)
|
|
|
|
###########################################################################
|
|
# Define problem settings
|
|
|
|
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
|
settings = openmc.Settings()
|
|
settings.energy_mode = "multi-group"
|
|
settings.inactive = 5
|
|
settings.batches = 10
|
|
settings.particles = 500
|
|
settings.run_mode = 'fixed source'
|
|
|
|
# Create an initial uniform spatial source for ray integration
|
|
lower_left_ray = [0.0, 0.0, 0.0]
|
|
upper_right_ray = [outer_width, outer_width, outer_width]
|
|
uniform_dist_ray = openmc.stats.Box(
|
|
lower_left_ray, upper_right_ray, only_fissionable=False)
|
|
rr_source = openmc.IndependentSource(space=uniform_dist_ray)
|
|
|
|
settings.random_ray['distance_active'] = 800.0
|
|
settings.random_ray['distance_inactive'] = 100.0
|
|
settings.random_ray['ray_source'] = rr_source
|
|
settings.random_ray['volume_normalized_flux_tallies'] = True
|
|
|
|
# Create a rectilinear source region mesh
|
|
sr_mesh = openmc.RegularMesh()
|
|
sr_mesh.dimension = (14, 14, 14)
|
|
sr_mesh.lower_left = (0.0, 0.0, 0.0)
|
|
sr_mesh.upper_right = (outer_width, outer_width, outer_width)
|
|
settings.random_ray['source_region_meshes'] = [(sr_mesh, [root])]
|
|
|
|
# Create the neutron source in the bottom right of the moderator
|
|
# Good - fast group appears largest (besides most thermal)
|
|
strengths = [1.0]
|
|
midpoints = [100.0]
|
|
energy_distribution = openmc.stats.Discrete(x=midpoints, p=strengths)
|
|
|
|
source = openmc.IndependentSource(energy=energy_distribution, constraints={
|
|
'domains': [source_universe]}, strength=3.14)
|
|
|
|
settings.source = [source]
|
|
|
|
###########################################################################
|
|
# Define tallies
|
|
|
|
estimator = 'tracklength'
|
|
|
|
detector1_filter = openmc.CellFilter(detector1)
|
|
detector1_tally = openmc.Tally(name="Detector 1 Tally")
|
|
detector1_tally.filters = [detector1_filter]
|
|
detector1_tally.scores = ['flux']
|
|
detector1_tally.estimator = estimator
|
|
|
|
detector2_filter = openmc.CellFilter(detector2)
|
|
detector2_tally = openmc.Tally(name="Detector 2 Tally")
|
|
detector2_tally.filters = [detector2_filter]
|
|
detector2_tally.scores = ['flux']
|
|
detector2_tally.estimator = estimator
|
|
|
|
absorber_filter = openmc.MaterialFilter(absorber_mat)
|
|
absorber_tally = openmc.Tally(name="Absorber Tally")
|
|
absorber_tally.filters = [absorber_filter]
|
|
absorber_tally.scores = ['flux']
|
|
absorber_tally.estimator = estimator
|
|
|
|
cavity_filter = openmc.MaterialFilter(cavity_mat)
|
|
cavity_tally = openmc.Tally(name="Cavity Tally")
|
|
cavity_tally.filters = [cavity_filter]
|
|
cavity_tally.scores = ['flux']
|
|
cavity_tally.estimator = estimator
|
|
|
|
source_filter = openmc.MaterialFilter(source_mat)
|
|
source_tally = openmc.Tally(name="Source Tally")
|
|
source_tally.filters = [source_filter]
|
|
source_tally.scores = ['flux']
|
|
source_tally.estimator = estimator
|
|
|
|
# Instantiate a Tallies collection and export to XML
|
|
tallies = openmc.Tallies([detector1_tally,
|
|
detector2_tally,
|
|
absorber_tally,
|
|
cavity_tally,
|
|
source_tally])
|
|
|
|
###########################################################################
|
|
# Assmble Model
|
|
|
|
model.geometry = geometry
|
|
model.materials = materials_file
|
|
model.settings = settings
|
|
model.tallies = tallies
|
|
|
|
return model |