Segmentation Faults and Code Optimizations

So I have been working on a BWR quarter core for a project I have been working on, and due to its complex geometries it works, however; it uses a lot of ram for compilation of the geom and it will run into
“Openmc aborted unexpectedly” when it is trying to generate a plot for the geometry…

def create_core_lattice_with_structure(qpath):
“”“Optimized core lattice generation with precomputed universes based on blade position.”“”
df = pd.read_excel(qpath, header=None)
raw_lattice = df.values.tolist()
print(“Loaded lattice from Excel:”, raw_lattice)
blade_map = {
‘11’: 48, ‘12’: 48, ‘13’: 48, ‘14’: 48, ‘15’:48, ‘16’: 48, ‘17’: 48, ‘18’:48,

‘21’: 48, ‘22’: 8, ‘23’: 20, ‘24’: 20, ‘25’: 20, ‘26’: 8, ‘27’: 48, ‘28’:48,

‘31’: 48, ‘32’: 20, ‘33’: 40, ‘34’: 40, ‘35’: 40, ‘36’: 20, ‘37’: 48, ‘38’: 48,

‘41’: 48, ‘42’: 20, ‘43’: 40, ‘44’: 0, ‘45’: 40, ‘46’: 20, ‘47’: 48,

‘51’: 48, ‘52’: 20, ‘53’: 40, ‘54’: 40, ‘55’: 40, ‘56’: 20, ‘57’: 48,

‘61’: 48, ‘62’: 8, ‘63’: 20, ‘64’: 20, ‘65’: 20, ‘66’: 8, ‘67’: 48,

‘71’: 48, ‘72’: 48, ‘73’: 48, ‘74’: 48, ‘75’: 48,

‘81’: 48, ‘82’: 48, ‘83’: 48}

unique_positions = sorted(set(blade_map.values()))
print("Unique blade positions identified:", unique_positions)

# Pre-generate universes for unique blade positions
position_universes = {}
for position in unique_positions:
    print(f"Generating universes for blade position {position}")
    position_universes[position] = {
        "TL": top_left(f"TL_{position}", control_blade_length_array[position])[0],
        "TR": top_right(f"TR_{position}", control_blade_length_array[position])[0],
        "BL": bottom_left(f"BL_{position}", control_blade_length_array[position])[0],
        "BR": bottom_right(f"BR_{position}", control_blade_length_array[position])[0]
    }

# Create the single universe for 'ONE' and 'W' (water)
print("Creating universal structures for 'ONE' and 'W'")
_, ONE, water_universe = create_geom_of_assem_with_blade(2)

# Build lattice using pre-generated universes
lattice = []
for row_idx, row in enumerate(raw_lattice):
    lattice_row = []
    for col_idx, cell in enumerate(row):
        if cell.startswith('TL') or cell.startswith('TR') or cell.startswith('BL') or cell.startswith('BR'):
            name = cell[2:]  # Extract blade ID
            position = blade_map.get(name, None)
            if position is None:
                raise ValueError(f"Blade ID {name} not found in blade_map")
            univ = position_universes[position][cell[:2]]  # Fetch precomputed universe
            print(f"Mapping {cell} at ({row_idx}, {col_idx}) to position {position}")
        elif cell == 'ONE':
            univ = ONE
            print(f"Mapping 'ONE' at ({row_idx}, {col_idx})")
        elif cell == 'W':
            univ = water_universe
            print(f"Mapping 'W' at ({row_idx}, {col_idx})")
        else:
            raise ValueError(f"Unexpected cell value: {cell}")
        lattice_row.append(univ)
    lattice.append(lattice_row)

print("Lattice generation complete.")
return np.array(lattice), blade_map, water_universe

def create_quarter_core():
lattice, blade_map, water_universe = create_core_lattice_with_structure(qpath=‘excel/QCORE.xlsx’)

fuel_def = 18.25 * assembly_pitch  # Fuel extends to 17 assembly pitches
shroud_def = fuel_def + 5.72  # Coolant extends 1 more pitch
downcomer_def = shroud_def + 38.265  # Downcomer extends 2 more pitches
rpv_def = downcomer_def + 3  # RPV extends 1 more pitch

# Cylindrical radial regions
fuel_cyl = openmc.ZCylinder(r=fuel_def)  # Inside fuel region
shroud_cyl = openmc.ZCylinder(r=shroud_def)  # Coolant region
downcomer_cyl = openmc.ZCylinder(r=downcomer_def)  # Downcomer
rpv_cyl = openmc.ZCylinder(r=rpv_def,boundary_type='reflective')  # RPV
exit_cyl = +openmc.ZCylinder(r=rpv_def)  # Vacuum region outside RPV

# Define quarter-core boundaries using RectangularParallelepiped
core_region = openmc.model.RectangularParallelepiped(
    xmin=0, xmax=34 * assembly_pitch / 2,  # Quarter-core in x (right side)
    ymin=-34 * assembly_pitch / 2, ymax=0,  # Quarter-core in y (bottom side)
    zmin=-length / 2, zmax=length / 2  # Full height
)

# Reflective boundary planes at x=0 and y=0
xplane = openmc.XPlane(x0=0, boundary_type='reflective',albedo=.5)
yplane = openmc.YPlane(y0=0, boundary_type='reflective',albedo=.5)
quarter_core_bound = +xplane & -yplane  # Keeps only bottom-right quarter
# Define nested radial regions within the quarter-core
fuel_bound = quarter_core_bound & -fuel_cyl & -core_region
coolant_bound = quarter_core_bound & -fuel_cyl & +core_region
shroud_bound = quarter_core_bound & +fuel_cyl & -shroud_cyl
downcomer_bound = quarter_core_bound & +shroud_cyl & -downcomer_cyl
rpv_bound = quarter_core_bound & +downcomer_cyl & -rpv_cyl

exit_bound = quarter_core_bound & exit_cyl  # Vacuum beyond RPV

# **Define RectLattice for the quarter core**
lattice_region = openmc.RectLattice(name='quarter core')
lattice_region.lower_left = (0. ,-34 * assembly_pitch / 2, -length / 2)  # Matches core bounds
lattice_region.pitch = [assembly_pitch, assembly_pitch, length]  # Lattice pitch
lattice_region.universes = np.array([lattice]*total_layers)  # Fill lattice with pre-defined universe
lattice_region.outer = openmc.Universe(cells=[openmc.Cell(fill=water_universe, region=-core_region)])
print(lattice_region.lower_left)
# Define Cells
fuel_cell = openmc.Cell(fill=lattice_region, region=fuel_bound)  # Lattice placed inside fuel region
coolant_cell = openmc.Cell(fill=COOLANT, region=coolant_bound)  # Coolant region
shroud_cell = openmc.Cell(fill=inconelX750, region=shroud_bound)
downcomer_cell = openmc.Cell(fill=COOLANT, region=downcomer_bound)  # Downcomer water
rpv_cell = openmc.Cell(fill=SA508Gr3C2, region=rpv_bound)  # Reactor Pressure Vessel
exit_cell = openmc.Cell(fill=None, region=exit_bound)  # Vacuum outside RPV
print('CELLS DEFINED ')
# Construct Universe and Geometry
root_universe = openmc.Universe(cells=[fuel_cell, coolant_cell,shroud_cell, downcomer_cell, rpv_cell])
geometry = openmc.Geometry(root_universe)
geometry.export_to_xml()
geometry.plot(basis='xy', width=(25*assembly_pitch, 25 * assembly_pitch), pixels=(400, 400))
plt.show()
print('geom set complete.')
return lattice,core_region, geometry

This is the general code of the core compilation of the geometries, it works, but when there are too many different blade positions it will run into the fault. My question is:
Are there better ways to do this, perhaps using the c++ api I am unfamiliar with…

I am currently running openmc through conda in Pop!OS ( based on jammy)

Thank you for your time.