In [1]:
# Import Necessary Packages
import openmc
import numpy as np
from math import pi, sin, cos
import os

# Creates the Necessary Folders
folders = ['inner', 'outer']
for folder in folders:
    if not os.path.exists(folder):
        os.makedirs(folder)
    else:
        print(f"The folder '{folder}' exists")
In [2]:
# ADD MATERIAL DEFINITIONS
# Fuel Material (MOX Fuels)
uranium = openmc.Material() # Depleted Uranium for ALFRED
uranium.add_nuclide('U234', 0.003)
uranium.add_nuclide('U235', 0.404)
uranium.add_nuclide('U236', 0.010)
uranium.add_nuclide('U238', 99.583)

plutonium = openmc.Material()
plutonium.add_nuclide('Pu238', 2.332)
plutonium.add_nuclide('Pu239', 56.873)
plutonium.add_nuclide('Pu240', 26.997)
plutonium.add_nuclide('Pu241', 6.105)
plutonium.add_nuclide('Pu242', 7.693)

oxygen = openmc.Material()
oxygen.add_element('O', 1.0)

uo2 = openmc.Material.mix_materials([uranium, oxygen],[0.3367, 0.6633])
puo2 = openmc.Material.mix_materials([plutonium, oxygen], [0.3367, 0.6633])

mox1 = openmc.Material.mix_materials([puo2, uo2], [0.217, 0.783], 'wo') # 21.7% PuO2 Enrichment
mox2 = openmc.Material.mix_materials([puo2, uo2], [0.278, 0.722], 'wo') # 27.8% PuO2 Enrichment

mox1.set_density('g/cm3', 11.07 * 0.95)    # Setting a density of 0.95 of theoretical density
mox2.set_density('g/cm3', 11.1 * 0.95)     # Setting a density of 0.95 of theoretical density

mox1.temperature = 1200
mox2.temperature = 1200

# Cladding Material (Ti-15-15 Steel)
clad = openmc.Material()
clad.add_element('Cr', 15, 'wo')
clad.add_element('Ni', 15, 'wo')
clad.add_element('Mo', 1.5, 'wo')
clad.add_element('Mn', 1.5, 'wo')
clad.add_element('Si', 0.9, 'wo')
clad.add_element('Ti', 0.4, 'wo')
clad.add_element('C', 0.09, 'wo')
clad.add_element('B', 0.006, 'wo')
clad.add_element('Fe', 65.604,'wo')
clad.set_density('g/cm3', 7.95)
clad.temperature = 900

# Coolant (Lead)
lead = openmc.Material()
lead.add_element('Pb', 1.0,)
lead.temperature = 700
lead.set_density('g/cm3', 10.6)
lead.depletable = True
lead.volume = 6134682.08   

# Gap (Helium)
he = openmc.Material()
he.add_element('He', 1)
he.set_density('g/cm3', 0.00016)
he.temperature= 700
 
# Absorber (Boron Carbide)
b4c = openmc.Material()
b4c.add_element('B', 4.0, enrichment=90, enrichment_target='B10', enrichment_type='wo')
b4c.add_element('C', 1.0)
b4c.set_density('g/cm3', 2.2)
b4c.temperature = 700

# Reflector (Yttria-Stabilized Zirconia)
zirconia = openmc.Material()
zirconia.add_elements_from_formula('ZrO2', 'ao', 1.0)

yttria = openmc.Material()
yttria.add_elements_from_formula('Y2O3', 'ao', 1.0)

ysz = openmc.Material.mix_materials([zirconia, yttria], [0.95, 0.05], 'wo')
ysz.temperature = 700
ysz.set_density('g/cm3', 6.08)

mat = openmc.Materials([mox1, mox2, clad, he, lead, b4c, ysz])
mat.export_to_xml("./inner/materials.xml")
mat.export_to_xml("./outer/materials.xml")
In [3]:
# ADD PRIMARY GEOMETRY DEFINITIONS
# Surfaces
fuel_ir = openmc.ZCylinder(r=0.1)
fuel_or = openmc.ZCylinder(r=0.45)
clad_ir = openmc.ZCylinder(r=0.465)
clad_or = openmc.ZCylinder(r=0.525)

top = openmc.ZPlane(z0=+30)
bottom = openmc.ZPlane(z0=-30)
cr_top = openmc.ZPlane(z0=-24)
cr_down = openmc.ZPlane(z0=-84.5)
up = openmc.ZPlane(z0=+42, boundary_type='vacuum')
down = openmc.ZPlane(z0=-85, boundary_type='vacuum')

# Regions
center_region = -fuel_ir & -up & +down
fuel_region = +fuel_ir & -fuel_or & -top & +bottom
gap_region = +fuel_or & -clad_ir & -top & +bottom
clad_region = +clad_ir & -clad_or & -top & +bottom
coolant_region = +clad_or & -up & +down

# Define Inner Assembly Fuel Pins
center_cell1 = openmc.Cell(region=center_region)
fuel_cell1 = openmc.Cell(fill=mox1, region=fuel_region)
gap_cell1 = openmc.Cell(fill=he, region=gap_region)
clad_cell1 = openmc.Cell(fill=clad, region=clad_region)
coolant_cell1 = openmc.Cell(fill=lead, region=coolant_region)

fuel_u1 = openmc.Universe(cells=[center_cell1, fuel_cell1, gap_cell1, clad_cell1, coolant_cell1])

# Define Inner Fuel Assembly
all_lead_out = openmc.Cell(fill=lead)
all_lead_out_u = openmc.Universe(cells=[all_lead_out])
in_lat = openmc.HexLattice(name='inner_fuel_assembly')
in_lat.center = (0., 0.)
in_lat.pitch = (1.386,)
in_lat.outer = all_lead_out_u

in_ring6 = [fuel_u1]*36
in_ring5 = [fuel_u1]*30
in_ring4 = [fuel_u1]*24
in_ring3 = [fuel_u1]*18
in_ring2 = [fuel_u1]*12
in_ring1 = [fuel_u1]*6
in_ring0 = [fuel_u1]

in_lat.universes = [in_ring6, in_ring5, in_ring4, in_ring3, in_ring2, in_ring1, in_ring0]
in_lat.orientation = 'y'

outer_in_surface = openmc.model.HexagonalPrism(edge_length=9.0, orientation='y')

main_in_assembly = openmc.Cell(fill=in_lat, region=-outer_in_surface & -top & +bottom)

in_plenum_top = openmc.Cell(fill=lead, region= -outer_in_surface & -up & +top)
in_plenum_bottom = openmc.Cell(fill=lead, region= -outer_in_surface & +down & -bottom)

out_in_assembly = openmc.Cell(fill=lead, region=+outer_in_surface & -up & +down)

main_in_u = openmc.Universe(cells=[main_in_assembly, out_in_assembly, in_plenum_bottom, in_plenum_top])

# Define Outer Assembly Fuel Pins
center_cell2 = openmc.Cell(region=center_region)
fuel_cell2 = openmc.Cell(fill=mox2, region=fuel_region)
gap_cell2 = openmc.Cell(fill=he, region=gap_region)
clad_cell2 = openmc.Cell(fill=clad, region=clad_region)
coolant_cell2 = openmc.Cell(fill=lead, region=coolant_region)

fuel_u2 = openmc.Universe(cells=[center_cell2, fuel_cell2, gap_cell2, clad_cell2, coolant_cell2])

# Define Outer Fuel Assembly
out_lat = openmc.HexLattice(name='assembly')
out_lat.center = (0., 0.)
out_lat.pitch = (1.386,)
out_lat.outer=all_lead_out_u
out_lat.orientation = 'y'

out_ring6 = [fuel_u2]*36
out_ring5 = [fuel_u2]*30
out_ring4 = [fuel_u2]*24
out_ring3 = [fuel_u2]*18
out_ring2 = [fuel_u2]*12
out_ring1 = [fuel_u2]*6
out_ring0 = [fuel_u2]

out_lat.universes = [out_ring6, out_ring5, out_ring4, out_ring3, out_ring2, out_ring1, out_ring0]

outer_out_surface = openmc.model.HexagonalPrism(edge_length=9, orientation='y')

main_out_assembly = openmc.Cell(fill=out_lat, region=-outer_out_surface & -top & +bottom)

out_plenum_top = openmc.Cell(fill=lead, region=-outer_out_surface & -up & +top)
out_plenum_bottom = openmc.Cell(fill=lead, region=-outer_out_surface & +down & -bottom)

out_out_assembly = openmc.Cell(fill=lead, region=+outer_out_surface & -up & +down)

main_out_u = openmc.Universe(cells=[main_out_assembly, out_out_assembly, out_plenum_bottom, out_plenum_top])

# Define Shutdown Rod
outer_sr_surface = openmc.model.HexagonalPrism(edge_length=9, orientation='y')
sr_cell = openmc.Cell(fill=lead, region=-outer_sr_surface & -up & +down)
out_sr_cell = openmc.Cell(fill=lead, region=+outer_sr_surface & -up & +down)
sr_u = openmc.Universe(cells=[sr_cell, out_sr_cell])

# Define Control Rod

calendria_ir = 6.44780
calendria_or = 6.58750
r_rod = 1.48
r_clad = 1.53

ring_radii = np.array([0.0, 3.2, 6.2])

# These are the surfaces that will divide each of the rings
radial_surf = [openmc.ZCylinder(r=r) for r in
               (ring_radii[:-1] + ring_radii[1:])/2]

lead_cells = []
for i in range(ring_radii.size):
    # Create annular region
    if i == 0:
        lead_region = -radial_surf[i]  & -up & +down
    elif i == ring_radii.size - 1:
        lead_region = +radial_surf[i-1]  & -up & +down
    else:
        lead_region = +radial_surf[i-1] & -radial_surf[i]  & -up & +down
        
    lead_cells.append(openmc.Cell(fill=lead, region=lead_region  & -up & +down))

cr_u = openmc.Universe(cells=lead_cells)

# Pin Universe
surf_rod = openmc.ZCylinder(r=r_rod)

rod_cell = openmc.Cell(fill=b4c, region=-surf_rod & -cr_top & +cr_down)
clad_cell = openmc.Cell(fill=clad, region=+surf_rod  & -cr_top & +cr_down)

pin_universe = openmc.Universe(cells=(rod_cell, clad_cell))

num_pins = [1, 6, 12]
angles = [0, 30, 15]

cr_top_cell=openmc.Cell(fill=lead, region=-up & +cr_top)
cr_down_cell=openmc.Cell(fill=lead, region=+down & -cr_down)
cr_cyl_ir = openmc.ZCylinder(r=8)
cr_cyl_or = openmc.ZCylinder(r=8.5)

for i, (r, n, a) in enumerate(zip(ring_radii, num_pins, angles)):
    for j in range(n):
        # Determine the location of center of pin
        theta = (a + j/n*360.) * pi/180.
        x = r*cos(theta)
        y = r*sin(theta)
        
        pin_boundary = openmc.ZCylinder(x0=x, y0=y, r=r_clad)
        lead_cells[i].region &= +pin_boundary  
        
        # Create each fuel pin -- note that we explicitly assign an ID so 
        # that we can identify the pin later when looking at tallies
        pin = openmc.Cell(fill=pin_universe, region=-pin_boundary & -cr_top & +cr_down)
        pin.translation = (x, y, 0)
        pin.id = (i + 1)*100 + j
        cr_u.add_cell(pin)
        cr_u.add_cell(cr_top_cell)
        cr_u.add_cell(cr_down_cell) 

# Define Dummy/Reflector
outer_dummy_surface = openmc.model.HexagonalPrism(edge_length=9, orientation='y')
dummy_cell = openmc.Cell(fill=ysz, region=-outer_dummy_surface & -up & +down)
out_dummy_cell = openmc.Cell(fill=lead, region=+outer_dummy_surface & -up & +down)
dummy_u = openmc.Universe(cells=[dummy_cell, out_dummy_cell])

# Empty
outer_empty_surface = openmc.model.HexagonalPrism(edge_length=9, orientation='y')
empty_cell = openmc.Cell(fill=lead, region= None)
out_empty_cell = openmc.Cell(region= None)
empty_u = openmc.Universe(cells=[empty_cell,out_empty_cell])

# Define Core Geometry
core_lat = openmc.HexLattice(name='core')
core_lat.center = (0., 0.)
core_lat.pitch = (16.6,)
core_lat.outer = all_lead_out_u
core_lat.orientation = 'x'

core_ring10 =  ([empty_u]*3 + [dummy_u]*5 + [empty_u]*2)*6
core_ring9 = ([empty_u] + [dummy_u]*8)*6
core_ring8 = ([dummy_u]*3 + [main_out_u]*3 + [dummy_u]*2 )*6 
core_ring7 = [main_out_u]*42
core_ring6 = [main_out_u, main_out_u, cr_u, main_out_u, cr_u, main_out_u]*6
core_ring5 = [main_out_u]*30
core_ring4 = [main_in_u]*24
core_ring3 = [main_in_u]*18
core_ring2 = [sr_u, main_in_u, main_in_u]*4
core_ring1 = [main_in_u]*6
core_ring0 = [main_in_u]*1
core_lat.universes = [core_ring10, core_ring9, core_ring8, core_ring7, core_ring6, core_ring5, core_ring4, core_ring3, core_ring2, core_ring1, core_ring0]

outer_core_surface = openmc.ZCylinder(r=160, boundary_type='vacuum')

core = openmc.Cell(fill=core_lat, region=-outer_core_surface & -up & +down)

main_u = openmc.Universe(cells=[core])

geom = openmc.Geometry(main_u)
geom.export_to_xml("./inner/geometry.xml")
geom.export_to_xml("./outer/geometry.xml")
In [4]:
# Settings
# Used variables for better usability in getting tallies from values
number_of_batches = 30
number_of_particles = 10000

settings = openmc.Settings()
settings.temperature = {'method':'interpolation'}
settings.batches = number_of_batches
settings.inactive = 8
settings.particles = number_of_particles
settings.export_to_xml("./inner/settings.xml")
settings.export_to_xml("./outer/settings.xml")
In [5]:
# Tallies
H = openmc.Tally(tally_id=1)
H.scores = ['heating-local']

# Iterating over folders and assemblies to get tallies.xml files
assemblies = [main_in_assembly, main_out_assembly]
tally_ids = [6, 28]   # 6 for inner, 28 for outer

for folder, assembly, tally_id in zip(folders, assemblies, tally_ids):
    tally = openmc.Tally(tally_id=tally_id)
    tally.filters = [openmc.DistribcellFilter(assembly)]
    tally.scores = ['fission']
    
    tallies = openmc.Tallies([tally,H])
    tallies.export_to_xml(f"./{folder}/tallies.xml")
In [6]:
# We're ready to run the transport simulation and get tally results to plot.
for folder in folders:
    
    # We're ready to run the transport simulation and get tally results to plot.
    openmc.run(cwd=f'./{folder}/')
                                %%%%%%%%%%%%%%%
                           %%%%%%%%%%%%%%%%%%%%%%%%
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                                    %%%%%%%%%%%%%%%%%%%%%%%%
                                     %%%%%%%%%%%%%%%%%%%%%%%%
                 ###############      %%%%%%%%%%%%%%%%%%%%%%%%
                ##################     %%%%%%%%%%%%%%%%%%%%%%%
                ###################     %%%%%%%%%%%%%%%%%%%%%%%
                ####################     %%%%%%%%%%%%%%%%%%%%%%
                #####################     %%%%%%%%%%%%%%%%%%%%%
                ######################     %%%%%%%%%%%%%%%%%%%%
                #######################     %%%%%%%%%%%%%%%%%%
                 #######################     %%%%%%%%%%%%%%%%%
                 ######################     %%%%%%%%%%%%%%%%%
                  ####################     %%%%%%%%%%%%%%%%%
                    #################     %%%%%%%%%%%%%%%%%
                     ###############     %%%%%%%%%%%%%%%%
                       ############     %%%%%%%%%%%%%%%
                          ########     %%%%%%%%%%%%%%
                                      %%%%%%%%%%%

                 | The OpenMC Monte Carlo Code
       Copyright | 2011-2025 MIT, UChicago Argonne LLC, and contributors
         License | https://docs.openmc.org/en/latest/license.html
         Version | 0.15.2
     Commit Hash | e23760b0264c66fb7bb373aa0596801e5209d920
       Date/Time | 2025-06-30 03:23:33
   MPI Processes | 1
  OpenMP Threads | 8

 Reading settings XML file...
 Reading cross sections XML file...
 Reading materials XML file...
 Reading geometry XML file...
 Reading Pu238 from /home/triple-s/Documents/endfb80/neutron/Pu238.h5
 Reading Pu239 from /home/triple-s/Documents/endfb80/neutron/Pu239.h5
 Reading Pu240 from /home/triple-s/Documents/endfb80/neutron/Pu240.h5
 Reading Pu241 from /home/triple-s/Documents/endfb80/neutron/Pu241.h5
 Reading Pu242 from /home/triple-s/Documents/endfb80/neutron/Pu242.h5
 Reading O16 from /home/triple-s/Documents/endfb80/neutron/O16.h5
 Reading O17 from /home/triple-s/Documents/endfb80/neutron/O17.h5
 Reading O18 from /home/triple-s/Documents/endfb80/neutron/O18.h5
 Reading U234 from /home/triple-s/Documents/endfb80/neutron/U234.h5
 Reading U235 from /home/triple-s/Documents/endfb80/neutron/U235.h5
 Reading U236 from /home/triple-s/Documents/endfb80/neutron/U236.h5
 Reading U238 from /home/triple-s/Documents/endfb80/neutron/U238.h5
 Reading Cr50 from /home/triple-s/Documents/endfb80/neutron/Cr50.h5
 Reading Cr52 from /home/triple-s/Documents/endfb80/neutron/Cr52.h5
 Reading Cr53 from /home/triple-s/Documents/endfb80/neutron/Cr53.h5
 Reading Cr54 from /home/triple-s/Documents/endfb80/neutron/Cr54.h5
 Reading Ni58 from /home/triple-s/Documents/endfb80/neutron/Ni58.h5
 Reading Ni60 from /home/triple-s/Documents/endfb80/neutron/Ni60.h5
 Reading Ni61 from /home/triple-s/Documents/endfb80/neutron/Ni61.h5
 Reading Ni62 from /home/triple-s/Documents/endfb80/neutron/Ni62.h5
 Reading Ni64 from /home/triple-s/Documents/endfb80/neutron/Ni64.h5
 Reading Mo92 from /home/triple-s/Documents/endfb80/neutron/Mo92.h5
 Reading Mo94 from /home/triple-s/Documents/endfb80/neutron/Mo94.h5
 Reading Mo95 from /home/triple-s/Documents/endfb80/neutron/Mo95.h5
 Reading Mo96 from /home/triple-s/Documents/endfb80/neutron/Mo96.h5
 Reading Mo97 from /home/triple-s/Documents/endfb80/neutron/Mo97.h5
 Reading Mo98 from /home/triple-s/Documents/endfb80/neutron/Mo98.h5
 Reading Mo100 from /home/triple-s/Documents/endfb80/neutron/Mo100.h5
 Reading Mn55 from /home/triple-s/Documents/endfb80/neutron/Mn55.h5
 Reading Si28 from /home/triple-s/Documents/endfb80/neutron/Si28.h5
 Reading Si29 from /home/triple-s/Documents/endfb80/neutron/Si29.h5
 Reading Si30 from /home/triple-s/Documents/endfb80/neutron/Si30.h5
 Reading Ti46 from /home/triple-s/Documents/endfb80/neutron/Ti46.h5
 Reading Ti47 from /home/triple-s/Documents/endfb80/neutron/Ti47.h5
 Reading Ti48 from /home/triple-s/Documents/endfb80/neutron/Ti48.h5
 Reading Ti49 from /home/triple-s/Documents/endfb80/neutron/Ti49.h5
 Reading Ti50 from /home/triple-s/Documents/endfb80/neutron/Ti50.h5
 Reading C12 from /home/triple-s/Documents/endfb80/neutron/C12.h5
 Reading C13 from /home/triple-s/Documents/endfb80/neutron/C13.h5
 Reading B10 from /home/triple-s/Documents/endfb80/neutron/B10.h5
 Reading B11 from /home/triple-s/Documents/endfb80/neutron/B11.h5
 Reading Fe54 from /home/triple-s/Documents/endfb80/neutron/Fe54.h5
 Reading Fe56 from /home/triple-s/Documents/endfb80/neutron/Fe56.h5
 Reading Fe57 from /home/triple-s/Documents/endfb80/neutron/Fe57.h5
 Reading Fe58 from /home/triple-s/Documents/endfb80/neutron/Fe58.h5
 Reading Pb204 from /home/triple-s/Documents/endfb80/neutron/Pb204.h5
 Reading Pb206 from /home/triple-s/Documents/endfb80/neutron/Pb206.h5
 Reading Pb207 from /home/triple-s/Documents/endfb80/neutron/Pb207.h5
 Reading Pb208 from /home/triple-s/Documents/endfb80/neutron/Pb208.h5
 Reading He3 from /home/triple-s/Documents/endfb80/neutron/He3.h5
 Reading He4 from /home/triple-s/Documents/endfb80/neutron/He4.h5
 Reading Zr90 from /home/triple-s/Documents/endfb80/neutron/Zr90.h5
 Reading Zr91 from /home/triple-s/Documents/endfb80/neutron/Zr91.h5
 Reading Zr92 from /home/triple-s/Documents/endfb80/neutron/Zr92.h5
 Reading Zr94 from /home/triple-s/Documents/endfb80/neutron/Zr94.h5
 Reading Zr96 from /home/triple-s/Documents/endfb80/neutron/Zr96.h5
 WARNING: Negative value(s) found on probability table for nuclide Zr96 at 600K
 WARNING: Negative value(s) found on probability table for nuclide Zr96 at 900K
 Reading Y89 from /home/triple-s/Documents/endfb80/neutron/Y89.h5
 Minimum neutron data temperature: 600 K
 Maximum neutron data temperature: 2500 K
 Reading tallies XML file...
 Preparing distributed cell instances...
 Reading plot XML file...
 Writing summary.h5 file...
 Maximum neutron transport energy: 20000000 eV for Pu239
 Initializing source particles...

 ====================>     K EIGENVALUE SIMULATION     <====================

  Bat./Gen.      k            Average k
  =========   ========   ====================
        1/1    1.22124
        2/1    1.13446
        3/1    1.12988
        4/1    1.10178
        5/1    1.12222
        6/1    1.11108
        7/1    1.09043
        8/1    1.09397
        9/1    1.09470
       10/1    1.08747    1.09109 +/- 0.00362
       11/1    1.08017    1.08745 +/- 0.00419
       12/1    1.06958    1.08298 +/- 0.00536
       13/1    1.09024    1.08443 +/- 0.00440
       14/1    1.08659    1.08479 +/- 0.00361
       15/1    1.07927    1.08401 +/- 0.00315
       16/1    1.10810    1.08702 +/- 0.00406
       17/1    1.08311    1.08658 +/- 0.00361
       18/1    1.06768    1.08469 +/- 0.00374
       19/1    1.08548    1.08476 +/- 0.00339
       20/1    1.07131    1.08364 +/- 0.00329
       21/1    1.07317    1.08284 +/- 0.00313
       22/1    1.08305    1.08285 +/- 0.00290
       23/1    1.07975    1.08265 +/- 0.00271
       24/1    1.08431    1.08275 +/- 0.00253
       25/1    1.08455    1.08286 +/- 0.00238
       26/1    1.07698    1.08253 +/- 0.00227
       27/1    1.07595    1.08218 +/- 0.00217
       28/1    1.09287    1.08272 +/- 0.00213
       29/1    1.06428    1.08184 +/- 0.00221
       30/1    1.08196    1.08184 +/- 0.00211
 Creating state point statepoint.30.h5...

 =======================>     TIMING STATISTICS     <=======================

 Total time for initialization     = 8.7246e+00 seconds
   Reading cross sections          = 8.6390e+00 seconds
 Total time in simulation          = 6.2236e+01 seconds
   Time in transport only          = 6.2189e+01 seconds
   Time in inactive batches        = 1.1709e+01 seconds
   Time in active batches          = 5.0527e+01 seconds
   Time synchronizing fission bank = 2.3536e-02 seconds
     Sampling source sites         = 2.1578e-02 seconds
     SEND/RECV source sites        = 1.8894e-03 seconds
   Time accumulating tallies       = 3.8566e-03 seconds
   Time writing statepoints        = 5.7719e-03 seconds
 Total time for finalization       = 4.6848e-04 seconds
 Total time elapsed                = 7.1002e+01 seconds
 Calculation Rate (inactive)       = 6832.4 particles/second
 Calculation Rate (active)         = 4354.1 particles/second

 ============================>     RESULTS     <============================

 k-effective (Collision)     = 1.08192 +/- 0.00187
 k-effective (Track-length)  = 1.08184 +/- 0.00211
 k-effective (Absorption)    = 1.07963 +/- 0.00273
 Combined k-effective        = 1.08121 +/- 0.00160
 Leakage Fraction            = 0.20000 +/- 0.00077

                                %%%%%%%%%%%%%%%
                           %%%%%%%%%%%%%%%%%%%%%%%%
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                                    %%%%%%%%%%%%%%%%%%%%%%%%
                                     %%%%%%%%%%%%%%%%%%%%%%%%
                 ###############      %%%%%%%%%%%%%%%%%%%%%%%%
                ##################     %%%%%%%%%%%%%%%%%%%%%%%
                ###################     %%%%%%%%%%%%%%%%%%%%%%%
                ####################     %%%%%%%%%%%%%%%%%%%%%%
                #####################     %%%%%%%%%%%%%%%%%%%%%
                ######################     %%%%%%%%%%%%%%%%%%%%
                #######################     %%%%%%%%%%%%%%%%%%
                 #######################     %%%%%%%%%%%%%%%%%
                 ######################     %%%%%%%%%%%%%%%%%
                  ####################     %%%%%%%%%%%%%%%%%
                    #################     %%%%%%%%%%%%%%%%%
                     ###############     %%%%%%%%%%%%%%%%
                       ############     %%%%%%%%%%%%%%%
                          ########     %%%%%%%%%%%%%%
                                      %%%%%%%%%%%

                 | The OpenMC Monte Carlo Code
       Copyright | 2011-2025 MIT, UChicago Argonne LLC, and contributors
         License | https://docs.openmc.org/en/latest/license.html
         Version | 0.15.2
     Commit Hash | e23760b0264c66fb7bb373aa0596801e5209d920
       Date/Time | 2025-06-30 03:24:45
   MPI Processes | 1
  OpenMP Threads | 8

 Reading settings XML file...
 Reading cross sections XML file...
 Reading materials XML file...
 Reading geometry XML file...
 Reading Pu238 from /home/triple-s/Documents/endfb80/neutron/Pu238.h5
 Reading Pu239 from /home/triple-s/Documents/endfb80/neutron/Pu239.h5
 Reading Pu240 from /home/triple-s/Documents/endfb80/neutron/Pu240.h5
 Reading Pu241 from /home/triple-s/Documents/endfb80/neutron/Pu241.h5
 Reading Pu242 from /home/triple-s/Documents/endfb80/neutron/Pu242.h5
 Reading O16 from /home/triple-s/Documents/endfb80/neutron/O16.h5
 Reading O17 from /home/triple-s/Documents/endfb80/neutron/O17.h5
 Reading O18 from /home/triple-s/Documents/endfb80/neutron/O18.h5
 Reading U234 from /home/triple-s/Documents/endfb80/neutron/U234.h5
 Reading U235 from /home/triple-s/Documents/endfb80/neutron/U235.h5
 Reading U236 from /home/triple-s/Documents/endfb80/neutron/U236.h5
 Reading U238 from /home/triple-s/Documents/endfb80/neutron/U238.h5
 Reading Cr50 from /home/triple-s/Documents/endfb80/neutron/Cr50.h5
 Reading Cr52 from /home/triple-s/Documents/endfb80/neutron/Cr52.h5
 Reading Cr53 from /home/triple-s/Documents/endfb80/neutron/Cr53.h5
 Reading Cr54 from /home/triple-s/Documents/endfb80/neutron/Cr54.h5
 Reading Ni58 from /home/triple-s/Documents/endfb80/neutron/Ni58.h5
 Reading Ni60 from /home/triple-s/Documents/endfb80/neutron/Ni60.h5
 Reading Ni61 from /home/triple-s/Documents/endfb80/neutron/Ni61.h5
 Reading Ni62 from /home/triple-s/Documents/endfb80/neutron/Ni62.h5
 Reading Ni64 from /home/triple-s/Documents/endfb80/neutron/Ni64.h5
 Reading Mo92 from /home/triple-s/Documents/endfb80/neutron/Mo92.h5
 Reading Mo94 from /home/triple-s/Documents/endfb80/neutron/Mo94.h5
 Reading Mo95 from /home/triple-s/Documents/endfb80/neutron/Mo95.h5
 Reading Mo96 from /home/triple-s/Documents/endfb80/neutron/Mo96.h5
 Reading Mo97 from /home/triple-s/Documents/endfb80/neutron/Mo97.h5
 Reading Mo98 from /home/triple-s/Documents/endfb80/neutron/Mo98.h5
 Reading Mo100 from /home/triple-s/Documents/endfb80/neutron/Mo100.h5
 Reading Mn55 from /home/triple-s/Documents/endfb80/neutron/Mn55.h5
 Reading Si28 from /home/triple-s/Documents/endfb80/neutron/Si28.h5
 Reading Si29 from /home/triple-s/Documents/endfb80/neutron/Si29.h5
 Reading Si30 from /home/triple-s/Documents/endfb80/neutron/Si30.h5
 Reading Ti46 from /home/triple-s/Documents/endfb80/neutron/Ti46.h5
 Reading Ti47 from /home/triple-s/Documents/endfb80/neutron/Ti47.h5
 Reading Ti48 from /home/triple-s/Documents/endfb80/neutron/Ti48.h5
 Reading Ti49 from /home/triple-s/Documents/endfb80/neutron/Ti49.h5
 Reading Ti50 from /home/triple-s/Documents/endfb80/neutron/Ti50.h5
 Reading C12 from /home/triple-s/Documents/endfb80/neutron/C12.h5
 Reading C13 from /home/triple-s/Documents/endfb80/neutron/C13.h5
 Reading B10 from /home/triple-s/Documents/endfb80/neutron/B10.h5
 Reading B11 from /home/triple-s/Documents/endfb80/neutron/B11.h5
 Reading Fe54 from /home/triple-s/Documents/endfb80/neutron/Fe54.h5
 Reading Fe56 from /home/triple-s/Documents/endfb80/neutron/Fe56.h5
 Reading Fe57 from /home/triple-s/Documents/endfb80/neutron/Fe57.h5
 Reading Fe58 from /home/triple-s/Documents/endfb80/neutron/Fe58.h5
 Reading Pb204 from /home/triple-s/Documents/endfb80/neutron/Pb204.h5
 Reading Pb206 from /home/triple-s/Documents/endfb80/neutron/Pb206.h5
 Reading Pb207 from /home/triple-s/Documents/endfb80/neutron/Pb207.h5
 Reading Pb208 from /home/triple-s/Documents/endfb80/neutron/Pb208.h5
 Reading He3 from /home/triple-s/Documents/endfb80/neutron/He3.h5
 Reading He4 from /home/triple-s/Documents/endfb80/neutron/He4.h5
 Reading Zr90 from /home/triple-s/Documents/endfb80/neutron/Zr90.h5
 Reading Zr91 from /home/triple-s/Documents/endfb80/neutron/Zr91.h5
 Reading Zr92 from /home/triple-s/Documents/endfb80/neutron/Zr92.h5
 Reading Zr94 from /home/triple-s/Documents/endfb80/neutron/Zr94.h5
 Reading Zr96 from /home/triple-s/Documents/endfb80/neutron/Zr96.h5
 WARNING: Negative value(s) found on probability table for nuclide Zr96 at 600K
 WARNING: Negative value(s) found on probability table for nuclide Zr96 at 900K
 Reading Y89 from /home/triple-s/Documents/endfb80/neutron/Y89.h5
 Minimum neutron data temperature: 600 K
 Maximum neutron data temperature: 2500 K
 Reading tallies XML file...
 Preparing distributed cell instances...
 Reading plot XML file...
 Writing summary.h5 file...
 Maximum neutron transport energy: 20000000 eV for Pu239
 Initializing source particles...

 ====================>     K EIGENVALUE SIMULATION     <====================

  Bat./Gen.      k            Average k
  =========   ========   ====================
        1/1    1.22124
        2/1    1.13446
        3/1    1.12988
        4/1    1.10178
        5/1    1.12222
        6/1    1.11108
        7/1    1.09043
        8/1    1.09397
        9/1    1.09470
       10/1    1.08747    1.09109 +/- 0.00362
       11/1    1.08017    1.08745 +/- 0.00419
       12/1    1.06958    1.08298 +/- 0.00536
       13/1    1.09024    1.08443 +/- 0.00440
       14/1    1.08659    1.08479 +/- 0.00361
       15/1    1.07927    1.08401 +/- 0.00315
       16/1    1.10810    1.08702 +/- 0.00406
       17/1    1.08311    1.08658 +/- 0.00361
       18/1    1.06768    1.08469 +/- 0.00374
       19/1    1.08548    1.08476 +/- 0.00339
       20/1    1.07131    1.08364 +/- 0.00329
       21/1    1.07317    1.08284 +/- 0.00313
       22/1    1.08305    1.08285 +/- 0.00290
       23/1    1.07975    1.08265 +/- 0.00271
       24/1    1.08431    1.08275 +/- 0.00253
       25/1    1.08455    1.08286 +/- 0.00238
       26/1    1.07698    1.08253 +/- 0.00227
       27/1    1.07595    1.08218 +/- 0.00217
       28/1    1.09287    1.08272 +/- 0.00213
       29/1    1.06428    1.08184 +/- 0.00221
       30/1    1.08196    1.08184 +/- 0.00211
 Creating state point statepoint.30.h5...

 =======================>     TIMING STATISTICS     <=======================

 Total time for initialization     = 7.5085e+00 seconds
   Reading cross sections          = 7.4584e+00 seconds
 Total time in simulation          = 6.4965e+01 seconds
   Time in transport only          = 6.4914e+01 seconds
   Time in inactive batches        = 1.2950e+01 seconds
   Time in active batches          = 5.2014e+01 seconds
   Time synchronizing fission bank = 2.3215e-02 seconds
     Sampling source sites         = 2.1223e-02 seconds
     SEND/RECV source sites        = 1.9248e-03 seconds
   Time accumulating tallies       = 6.4549e-03 seconds
   Time writing statepoints        = 5.9975e-03 seconds
 Total time for finalization       = 9.0280e-04 seconds
 Total time elapsed                = 7.2510e+01 seconds
 Calculation Rate (inactive)       = 6177.48 particles/second
 Calculation Rate (active)         = 4229.61 particles/second

 ============================>     RESULTS     <============================

 k-effective (Collision)     = 1.08192 +/- 0.00187
 k-effective (Track-length)  = 1.08184 +/- 0.00211
 k-effective (Absorption)    = 1.07963 +/- 0.00273
 Combined k-effective        = 1.08121 +/- 0.00160
 Leakage Fraction            = 0.20000 +/- 0.00077

In [7]:
# Now that the simulation is finished, we need to pull the resulting data

# Saving Data for Inner Assembly
sp_inner = openmc.StatePoint(f'./inner/statepoint.{number_of_batches}.h5')
t_inner = sp_inner.tallies[tally_ids[0]]                                        # Get the Tally object
df_inner = t_inner.get_pandas_dataframe()                                       # Show a Pandas dataframe
H_value_inner = sp_inner.tallies[H.id].get_pandas_dataframe()['mean'][0]        # H Value for normalization

# Saving Data for Outer Assembly
sp_outer = openmc.StatePoint(f'./outer/statepoint.{number_of_batches}.h5')
t_outer = sp_outer.tallies[tally_ids[1]]                                        # Get the Tally object
df_outer = t_outer.get_pandas_dataframe()                                       # Show a Pandas dataframe
H_value_outer = sp_outer.tallies[H.id].get_pandas_dataframe()['mean'][0]        # H Value for normalization

# Free the Memory
sp_inner.close()
sp_outer.close()
In [8]:
# Calculating the Q Values
inner_pu_enrichment = 21.7
outer_pu_enrichment = 27.8

Q_PuO2 = 209    # Roughly
Q_UO2 = 200

energy_rpf_inner = (inner_pu_enrichment * Q_PuO2 + (100 - inner_pu_enrichment) * Q_UO2) / 100
energy_rpf_outer = (outer_pu_enrichment * Q_PuO2 + (100 - outer_pu_enrichment) * Q_UO2) / 100

# Calculating the Factors to Normalize the Flux
core_power = 300e6                                                # J/s
H_Jsrc_inner = 1.602e-19 * H_value_inner                          # J/src
H_Jsrc_outer = 1.602e-19 * H_value_outer                          # J/src

fission_normalization_factor_inner = core_power / H_Jsrc_inner    # src/s
fission_normalization_factor_outer = core_power / H_Jsrc_outer    # src/s
In [9]:
# Normalizing Inner Assemblies' Power Output Values
normalized_df_inner = df_inner
normalized_df_inner['mean'] = df_inner['mean'] * fission_normalization_factor_inner * energy_rpf_inner * 1.602e-19 # in MW

inner_df = normalized_df_inner['level 2']['lat'][['x', 'y']]
inner_df['Power (MW)'] = normalized_df_inner['mean']
inner_df['Std. Dev.'] = normalized_df_inner['std. dev.']

print('Inner FAs:', inner_df.describe(), sep="\n")

# Normalizing Outer Assemblies' Power Output Values
normalized_df_outer = df_outer
normalized_df_outer['mean'] = df_outer['mean'] * fission_normalization_factor_outer * energy_rpf_outer * 1.602e-19 # in MW

outer_df = normalized_df_outer['level 2']['lat'][['x', 'y']]
outer_df['Power (MW)'] = normalized_df_outer['mean']
outer_df['Std. Dev.'] = normalized_df_outer['std. dev.']

print('Outer FAs:', outer_df.describe(), sep="\n")
Inner FAs:
               x          y  Power (MW)  Std. Dev.
count  57.000000  57.000000   57.000000  57.000000
mean    0.000000   0.000000    2.009391   0.000064
std     2.427521   2.434866    0.129910   0.000018
min    -4.000000  -4.000000    1.693763   0.000029
25%    -2.000000  -2.000000    1.924293   0.000049
50%     0.000000   0.000000    2.000965   0.000062
75%     2.000000   2.000000    2.105096   0.000075
max     4.000000   4.000000    2.280495   0.000105
Outer FAs:
                x           y  Power (MW)   Std. Dev.
count  114.000000  114.000000  114.000000  114.000000
mean     0.000000    0.000000    1.600321    0.000052
std      4.844484    4.844484    0.329248    0.000011
min     -8.000000   -8.000000    1.046413    0.000029
25%     -5.000000   -5.000000    1.339975    0.000044
50%      0.000000    0.000000    1.493181    0.000050
75%      5.000000    5.000000    1.863042    0.000061
max      8.000000    8.000000    2.259795    0.000085
In [10]:
# Saving the Values in csv Files
inner_df.to_csv('./inner_FAs.csv')
outer_df.to_csv('./outer_FAs.csv')
In [11]:
# Plotting the Power Values
import math
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection
import pandas as pd
from armi import configure
from armi.reactor import grids

configure(permissive=True)

# Create hex grid with 1.0 cm pitch
hexes = grids.HexGrid.fromPitch(1.0)

# Load data from CSV files
inner_data = pd.read_csv("./inner_FAs.csv")
outer_data = pd.read_csv("./outer_FAs.csv")

# Combine data into a single dictionary of (i, j) to power values
power_values = {(row['x'], row['y']): row['Power (MW)'] for _, row in pd.concat([inner_data, outer_data]).iterrows()}

# Generate power list for color mapping
power_list = [power for power in power_values.values()]

plt.rcParams.update({
    "font.weight": "bold"
})

polys = []
fig, ax = plt.subplots(dpi=200)
ax.set_aspect("equal")
ax.set_axis_off()
assembly_numbers = 187

for hex_i in hexes.generateSortedHexLocationList(assembly_numbers):
    x, y, z = hex_i.getGlobalCoordinates()
    i, j = hex_i.i, hex_i.j
    if (i, j) in power_values:
        power = power_values[(i, j)]
        ax.text(x, y, f"{power:.2f}", ha="center", va="center", fontsize=4.5)
        polys.append(mpatches.RegularPolygon((x, y), numVertices=6, radius=1 / math.sqrt(3), orientation=math.pi / 2))
    else:
        polys.append(mpatches.RegularPolygon((x, y), numVertices=6, radius=1 / math.sqrt(3), orientation=math.pi / 2, facecolor='white', edgecolor='k'))

# Use raw power values for color mapping with a custom normalization
min_power = min(power_list) if power_list else 0
max_power = max(power_list) if power_list else 1
norm = plt.Normalize(min_power, max_power)
power_colors = [power_values.get((i, j), 0) for i, j in [(hex_i.i, hex_i.j) for hex_i in hexes.generateSortedHexLocationList(assembly_numbers)]]

patches = PatchCollection(polys, facecolors=plt.cm.Oranges(norm(power_colors)) if power_list else ['white'], ec='k')

ax.add_collection(patches)

# Create a bounding box around patches with a small margin (2%)
bbox = patches.get_datalim(ax.transData)
bbox = bbox.expanded(1.02, 1.02)
ax.set_xlim(bbox.xmin, bbox.xmax)
ax.set_ylim(bbox.ymin, bbox.ymax)

patches.set_array(np.array(power_colors))
patches.set_cmap(plt.cm.Oranges)
patches.set_norm(norm)
cbar = plt.colorbar(patches, ax=ax)
cbar.set_label("Power Density (MW)", fontsize=8, fontweight="normal")

cbar.ax.tick_params(labelsize=6)
for ticklabel in cbar.ax.get_yticklabels():
    ticklabel.set_fontweight("normal")

plt.show()
       +===================================================+
       |            _      ____     __  __    ___          |
       |           / \    |  _ \   |  \/  |  |_ _|         |
       |          / _ \   | |_) |  | |\/| |   | |          |
       |         / ___ \  |  _ <   | |  | |   | |          |
       |        /_/   \_\ |_| \_\  |_|  |_|  |___|         |
       |        Advanced  Reactor  Modeling Interface      |
       |                                                   |
       |                    version 0.5.1                  |
       |                                                   |
       +===================================================+
No description has been provided for this image
In [ ]: