mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 14:15:42 -04:00
1076 lines
35 KiB
Python
1076 lines
35 KiB
Python
import copy
|
|
|
|
import numpy as np
|
|
|
|
try:
|
|
import opencg
|
|
except ImportError:
|
|
msg = 'Unable to import opencg which is needed by openmc.opencg_compatible'
|
|
raise ImportError(msg)
|
|
|
|
import openmc
|
|
|
|
|
|
# A dictionary of all OpenMC Materials created
|
|
# Keys - Material IDs
|
|
# Values - Materials
|
|
OPENMC_MATERIALS = {}
|
|
|
|
# A dictionary of all OpenCG Materials created
|
|
# Keys - Material IDs
|
|
# Values - Materials
|
|
OPENCG_MATERIALS = {}
|
|
|
|
# A dictionary of all OpenMC Surfaces created
|
|
# Keys - Surface IDs
|
|
# Values - Surfaces
|
|
OPENMC_SURFACES = {}
|
|
|
|
# A dictionary of all OpenCG Surfaces created
|
|
# Keys - Surface IDs
|
|
# Values - Surfaces
|
|
OPENCG_SURFACES = {}
|
|
|
|
# A dictionary of all OpenMC Cells created
|
|
# Keys - Cell IDs
|
|
# Values - Cells
|
|
OPENMC_CELLS = {}
|
|
|
|
# A dictionary of all OpenCG Cells created
|
|
# Keys - Cell IDs
|
|
# Values - Cells
|
|
OPENCG_CELLS = {}
|
|
|
|
# A dictionary of all OpenMC Universes created
|
|
# Keys - Universes IDs
|
|
# Values - Universes
|
|
OPENMC_UNIVERSES = {}
|
|
|
|
# A dictionary of all OpenCG Universes created
|
|
# Keys - Universes IDs
|
|
# Values - Universes
|
|
OPENCG_UNIVERSES = {}
|
|
|
|
# A dictionary of all OpenMC Lattices created
|
|
# Keys - Lattice IDs
|
|
# Values - Lattices
|
|
OPENMC_LATTICES = {}
|
|
|
|
# A dictionary of all OpenCG Lattices created
|
|
# Keys - Lattice IDs
|
|
# Values - Lattices
|
|
OPENCG_LATTICES = {}
|
|
|
|
|
|
def get_opencg_material(openmc_material):
|
|
"""Return an OpenCG material corresponding to an OpenMC material.
|
|
|
|
Parameters
|
|
----------
|
|
openmc_material : openmc.material.Material
|
|
OpenMC material
|
|
|
|
Returns
|
|
-------
|
|
opencg_material : opencg.Material
|
|
Equivalent OpenCG material
|
|
|
|
"""
|
|
|
|
if not isinstance(openmc_material, openmc.Material):
|
|
msg = 'Unable to create an OpenCG Material from "{0}" ' \
|
|
'which is not an OpenMC Material'.format(openmc_material)
|
|
raise ValueError(msg)
|
|
|
|
global OPENCG_MATERIALS
|
|
material_id = openmc_material._id
|
|
|
|
# If this Material was already created, use it
|
|
if material_id in OPENCG_MATERIALS:
|
|
return OPENCG_MATERIALS[material_id]
|
|
|
|
# Create an OpenCG Material to represent this OpenMC Material
|
|
name = openmc_material._name
|
|
opencg_material = opencg.Material(material_id=material_id, name=name)
|
|
|
|
# Add the OpenMC Material to the global collection of all OpenMC Materials
|
|
OPENMC_MATERIALS[material_id] = openmc_material
|
|
|
|
# Add the OpenCG Material to the global collection of all OpenCG Materials
|
|
OPENCG_MATERIALS[material_id] = opencg_material
|
|
|
|
return opencg_material
|
|
|
|
|
|
def get_openmc_material(opencg_material):
|
|
"""Return an OpenMC material corresponding to an OpenCG material.
|
|
|
|
Parameters
|
|
----------
|
|
opencg_material : opencg.Material
|
|
OpenCG material
|
|
|
|
Returns
|
|
-------
|
|
openmc_material : openmc.material.Material
|
|
Equivalent OpenMC material
|
|
|
|
"""
|
|
|
|
if not isinstance(opencg_material, opencg.Material):
|
|
msg = 'Unable to create an OpenMC Material from "{0}" ' \
|
|
'which is not an OpenCG Material'.format(opencg_material)
|
|
raise ValueError(msg)
|
|
|
|
global OPENMC_MATERIALS
|
|
material_id = opencg_material._id
|
|
|
|
# If this Material was already created, use it
|
|
if material_id in OPENMC_MATERIALS:
|
|
return OPENMC_MATERIALS[material_id]
|
|
|
|
# Create an OpenMC Material to represent this OpenCG Material
|
|
name = opencg_material._name
|
|
openmc_material = openmc.Material(material_id=material_id, name=name)
|
|
|
|
# Add the OpenMC Material to the global collection of all OpenMC Materials
|
|
OPENMC_MATERIALS[material_id] = openmc_material
|
|
|
|
# Add the OpenCG Material to the global collection of all OpenCG Materials
|
|
OPENCG_MATERIALS[material_id] = opencg_material
|
|
|
|
return openmc_material
|
|
|
|
|
|
def is_opencg_surface_compatible(opencg_surface):
|
|
"""Determine whether OpenCG surface is compatible with OpenMC geometry.
|
|
|
|
A surface is considered compatible if there is a one-to-one correspondence
|
|
between OpenMC and OpenCG surface types. Note that some OpenCG surfaces,
|
|
e.g. SquarePrism, do not have a one-to-one correspondence with OpenMC
|
|
surfaces but can still be converted into an equivalent collection of OpenMC
|
|
surfaces.
|
|
|
|
Parameters
|
|
----------
|
|
opencg_surface : opencg.Surface
|
|
OpenCG surface
|
|
|
|
Returns
|
|
-------
|
|
bool
|
|
Whether OpenCG surface is compatible with OpenMC
|
|
|
|
"""
|
|
|
|
if not isinstance(opencg_surface, opencg.Surface):
|
|
msg = 'Unable to check if OpenCG Surface is compatible' \
|
|
'since "{0}" is not a Surface'.format(opencg_surface)
|
|
raise ValueError(msg)
|
|
|
|
if opencg_surface._type in ['x-squareprism',
|
|
'y-squareprism', 'z-squareprism']:
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
|
|
def get_opencg_surface(openmc_surface):
|
|
"""Return an OpenCG surface corresponding to an OpenMC surface.
|
|
|
|
Parameters
|
|
----------
|
|
openmc_surface : openmc.surface.Surface
|
|
OpenMC surface
|
|
|
|
Returns
|
|
-------
|
|
opencg_surface : opencg.Surface
|
|
Equivalent OpenCG surface
|
|
|
|
"""
|
|
|
|
if not isinstance(openmc_surface, openmc.Surface):
|
|
msg = 'Unable to create an OpenCG Surface from "{0}" ' \
|
|
'which is not an OpenMC Surface'.format(openmc_surface)
|
|
raise ValueError(msg)
|
|
|
|
global OPENCG_SURFACES
|
|
surface_id = openmc_surface._id
|
|
|
|
# If this Material was already created, use it
|
|
if surface_id in OPENCG_SURFACES:
|
|
return OPENCG_SURFACES[surface_id]
|
|
|
|
# Create an OpenCG Surface to represent this OpenMC Surface
|
|
name = openmc_surface._name
|
|
|
|
# Correct for OpenMC's syntax for Surfaces dividing Cells
|
|
boundary = openmc_surface._boundary_type
|
|
if boundary == 'transmission':
|
|
boundary = 'interface'
|
|
|
|
opencg_surface = None
|
|
|
|
if openmc_surface._type == 'plane':
|
|
A = openmc_surface._coeffs['A']
|
|
B = openmc_surface._coeffs['B']
|
|
C = openmc_surface._coeffs['C']
|
|
D = openmc_surface._coeffs['D']
|
|
opencg_surface = opencg.Plane(surface_id, name, boundary, A, B, C, D)
|
|
|
|
elif openmc_surface._type == 'x-plane':
|
|
x0 = openmc_surface._coeffs['x0']
|
|
opencg_surface = opencg.XPlane(surface_id, name, boundary, x0)
|
|
|
|
elif openmc_surface._type == 'y-plane':
|
|
y0 = openmc_surface._coeffs['y0']
|
|
opencg_surface = opencg.YPlane(surface_id, name, boundary, y0)
|
|
|
|
elif openmc_surface._type == 'z-plane':
|
|
z0 = openmc_surface._coeffs['z0']
|
|
opencg_surface = opencg.ZPlane(surface_id, name, boundary, z0)
|
|
|
|
elif openmc_surface._type == 'x-cylinder':
|
|
y0 = openmc_surface._coeffs['y0']
|
|
z0 = openmc_surface._coeffs['z0']
|
|
R = openmc_surface._coeffs['R']
|
|
opencg_surface = opencg.XCylinder(surface_id, name,
|
|
boundary, y0, z0, R)
|
|
|
|
elif openmc_surface._type == 'y-cylinder':
|
|
x0 = openmc_surface._coeffs['x0']
|
|
z0 = openmc_surface._coeffs['z0']
|
|
R = openmc_surface._coeffs['R']
|
|
opencg_surface = opencg.YCylinder(surface_id, name,
|
|
boundary, x0, z0, R)
|
|
|
|
elif openmc_surface._type == 'z-cylinder':
|
|
x0 = openmc_surface._coeffs['x0']
|
|
y0 = openmc_surface._coeffs['y0']
|
|
R = openmc_surface._coeffs['R']
|
|
opencg_surface = opencg.ZCylinder(surface_id, name,
|
|
boundary, x0, y0, R)
|
|
|
|
# Add the OpenMC Surface to the global collection of all OpenMC Surfaces
|
|
OPENMC_SURFACES[surface_id] = openmc_surface
|
|
|
|
# Add the OpenCG Surface to the global collection of all OpenCG Surfaces
|
|
OPENCG_SURFACES[surface_id] = opencg_surface
|
|
|
|
return opencg_surface
|
|
|
|
|
|
def get_openmc_surface(opencg_surface):
|
|
"""Return an OpenMC surface corresponding to an OpenCG surface.
|
|
|
|
Parameters
|
|
----------
|
|
opencg_surface : opencg.Surface
|
|
OpenCG surface
|
|
|
|
Returns
|
|
-------
|
|
openmc_surface : openmc.surface.Surface
|
|
Equivalent OpenMC surface
|
|
|
|
"""
|
|
|
|
if not isinstance(opencg_surface, opencg.Surface):
|
|
msg = 'Unable to create an OpenMC Surface from "{0}" which ' \
|
|
'is not an OpenCG Surface'.format(opencg_surface)
|
|
raise ValueError(msg)
|
|
|
|
global openmc_surface
|
|
surface_id = opencg_surface._id
|
|
|
|
# If this Surface was already created, use it
|
|
if surface_id in OPENMC_SURFACES:
|
|
return OPENMC_SURFACES[surface_id]
|
|
|
|
# Create an OpenMC Surface to represent this OpenCG Surface
|
|
name = opencg_surface._name
|
|
|
|
# Correct for OpenMC's syntax for Surfaces dividing Cells
|
|
boundary = opencg_surface._boundary_type
|
|
if boundary == 'interface':
|
|
boundary = 'transmission'
|
|
|
|
if opencg_surface._type == 'plane':
|
|
A = opencg_surface._coeffs['A']
|
|
B = opencg_surface._coeffs['B']
|
|
C = opencg_surface._coeffs['C']
|
|
D = opencg_surface._coeffs['D']
|
|
openmc_surface = openmc.Plane(surface_id, boundary, A, B, C, D, name)
|
|
|
|
elif opencg_surface._type == 'x-plane':
|
|
x0 = opencg_surface._coeffs['x0']
|
|
openmc_surface = openmc.XPlane(surface_id, boundary, x0, name)
|
|
|
|
elif opencg_surface._type == 'y-plane':
|
|
y0 = opencg_surface._coeffs['y0']
|
|
openmc_surface = openmc.YPlane(surface_id, boundary, y0, name)
|
|
|
|
elif opencg_surface._type == 'z-plane':
|
|
z0 = opencg_surface._coeffs['z0']
|
|
openmc_surface = openmc.ZPlane(surface_id, boundary, z0, name)
|
|
|
|
elif opencg_surface._type == 'x-cylinder':
|
|
y0 = opencg_surface._coeffs['y0']
|
|
z0 = opencg_surface._coeffs['z0']
|
|
R = opencg_surface._coeffs['R']
|
|
openmc_surface = openmc.XCylinder(surface_id, boundary, y0, z0, R, name)
|
|
|
|
elif opencg_surface._type == 'y-cylinder':
|
|
x0 = opencg_surface._coeffs['x0']
|
|
z0 = opencg_surface._coeffs['z0']
|
|
R = opencg_surface._coeffs['R']
|
|
openmc_surface = openmc.YCylinder(surface_id, boundary, x0, z0, R, name)
|
|
|
|
elif opencg_surface._type == 'z-cylinder':
|
|
x0 = opencg_surface._coeffs['x0']
|
|
y0 = opencg_surface._coeffs['y0']
|
|
R = opencg_surface._coeffs['R']
|
|
openmc_surface = openmc.ZCylinder(surface_id, boundary, x0, y0, R, name)
|
|
|
|
else:
|
|
msg = 'Unable to create an OpenMC Surface from an OpenCG ' \
|
|
'Surface of type "{0}" since it is not a compatible ' \
|
|
'Surface type in OpenMC'.format(opencg_surface._type)
|
|
raise ValueError(msg)
|
|
|
|
# Add the OpenMC Surface to the global collection of all OpenMC Surfaces
|
|
OPENMC_SURFACES[surface_id] = openmc_surface
|
|
|
|
# Add the OpenCG Surface to the global collection of all OpenCG Surfaces
|
|
OPENCG_SURFACES[surface_id] = opencg_surface
|
|
|
|
return openmc_surface
|
|
|
|
|
|
def get_compatible_opencg_surfaces(opencg_surface):
|
|
"""Generate OpenCG surfaces that are compatible with OpenMC equivalent to an
|
|
OpenCG surface that is not compatible. For example, this method may be used
|
|
to convert a ZSquarePrism OpenCG surface into a collection of equivalent
|
|
XPlane and YPlane OpenCG surfaces.
|
|
|
|
Parameters
|
|
----------
|
|
opencg_surface : opencg.Surface
|
|
OpenCG surface that is incompatible with OpenMC
|
|
|
|
Returns
|
|
-------
|
|
surfaces : list of opencg.Surface
|
|
Collection of surfaces equivalent to the original one but compatible
|
|
with OpenMC
|
|
|
|
"""
|
|
|
|
if not isinstance(opencg_surface, opencg.Surface):
|
|
msg = 'Unable to create an OpenMC Surface from "{0}" which ' \
|
|
'is not an OpenCG Surface'.format(opencg_surface)
|
|
raise ValueError(msg)
|
|
|
|
global OPENMC_SURFACES
|
|
surface_id = opencg_surface._id
|
|
|
|
# If this Surface was already created, use it
|
|
if surface_id in OPENMC_SURFACES:
|
|
return OPENMC_SURFACES[surface_id]
|
|
|
|
# Create an OpenMC Surface to represent this OpenCG Surface
|
|
name = opencg_surface._name
|
|
boundary = opencg_surface._boundary_type
|
|
|
|
if opencg_surface._type == 'x-squareprism':
|
|
y0 = opencg_surface._coeffs['y0']
|
|
z0 = opencg_surface._coeffs['z0']
|
|
R = opencg_surface._coeffs['R']
|
|
|
|
# Create a list of the four planes we need
|
|
left = opencg.YPlane(name=name, boundary=boundary, y0=y0-R)
|
|
right = opencg.YPlane(name=name, boundary=boundary, y0=y0+R)
|
|
bottom = opencg.ZPlane(name=name, boundary=boundary, z0=z0-R)
|
|
top = opencg.ZPlane(name=name, boundary=boundary, z0=z0+R)
|
|
surfaces = [left, right, bottom, top]
|
|
|
|
elif opencg_surface._type == 'y-squareprism':
|
|
x0 = opencg_surface._coeffs['x0']
|
|
z0 = opencg_surface._coeffs['z0']
|
|
R = opencg_surface._coeffs['R']
|
|
|
|
# Create a list of the four planes we need
|
|
left = opencg.XPlane(name=name, boundary=boundary, x0=x0-R)
|
|
right = opencg.XPlane(name=name, boundary=boundary, x0=x0+R)
|
|
bottom = opencg.ZPlane(name=name, boundary=boundary, z0=z0-R)
|
|
top = opencg.ZPlane(name=name, boundary=boundary, z0=z0+R)
|
|
surfaces = [left, right, bottom, top]
|
|
|
|
elif opencg_surface._type == 'z-squareprism':
|
|
x0 = opencg_surface._coeffs['x0']
|
|
y0 = opencg_surface._coeffs['y0']
|
|
R = opencg_surface._coeffs['R']
|
|
|
|
# Create a list of the four planes we need
|
|
left = opencg.XPlane(name=name, boundary=boundary, x0=x0-R)
|
|
right = opencg.XPlane(name=name, boundary=boundary, x0=x0+R)
|
|
bottom = opencg.YPlane(name=name, boundary=boundary, y0=y0-R)
|
|
top = opencg.YPlane(name=name, boundary=boundary, y0=y0+R)
|
|
surfaces = [left, right, bottom, top]
|
|
|
|
else:
|
|
msg = 'Unable to create a compatible OpenMC Surface an OpenCG ' \
|
|
'Surface of type "{0}" since it already a compatible ' \
|
|
'Surface type in OpenMC'.format(opencg_surface._type)
|
|
raise ValueError(msg)
|
|
|
|
# Add the OpenMC Surface(s) to the global collection of all OpenMC Surfaces
|
|
OPENMC_SURFACES[surface_id] = surfaces
|
|
|
|
# Add the OpenCG Surface to the global collection of all OpenCG Surfaces
|
|
OPENCG_SURFACES[surface_id] = opencg_surface
|
|
|
|
return surfaces
|
|
|
|
|
|
def get_opencg_cell(openmc_cell):
|
|
"""Return an OpenCG cell corresponding to an OpenMC cell.
|
|
|
|
Parameters
|
|
----------
|
|
openmc_cell : openmc.universe.Cell
|
|
OpenMC cell
|
|
|
|
Returns
|
|
-------
|
|
opencg_cell : opencg.Cell
|
|
Equivalent OpenCG cell
|
|
|
|
"""
|
|
|
|
if not isinstance(openmc_cell, openmc.Cell):
|
|
msg = 'Unable to create an OpenCG Cell from "{0}" which ' \
|
|
'is not an OpenMC Cell'.format(openmc_cell)
|
|
raise ValueError(msg)
|
|
|
|
global OPENCG_CELLS
|
|
cell_id = openmc_cell._id
|
|
|
|
# If this Cell was already created, use it
|
|
if cell_id in OPENCG_CELLS:
|
|
return OPENCG_CELLS[cell_id]
|
|
|
|
# Create an OpenCG Cell to represent this OpenMC Cell
|
|
name = openmc_cell._name
|
|
opencg_cell = opencg.Cell(cell_id, name)
|
|
|
|
fill = openmc_cell._fill
|
|
|
|
if (openmc_cell._type == 'normal'):
|
|
opencg_cell.setFill(get_opencg_material(fill))
|
|
elif (openmc_cell._type == 'fill'):
|
|
opencg_cell.setFill(get_opencg_universe(fill))
|
|
else:
|
|
opencg_cell.setFill(get_opencg_lattice(fill))
|
|
|
|
if openmc_cell._rotation is not None:
|
|
opencg_cell.setRotation(openmc_cell._rotation)
|
|
|
|
if openmc_cell._translation is not None:
|
|
opencg_cell.setTranslation(openmc_cell._translation)
|
|
|
|
surfaces = openmc_cell._surfaces
|
|
|
|
for surface_id in surfaces:
|
|
surface = surfaces[surface_id][0]
|
|
halfspace = surfaces[surface_id][1]
|
|
opencg_cell.addSurface(get_opencg_surface(surface), halfspace)
|
|
|
|
# Add the OpenMC Cell to the global collection of all OpenMC Cells
|
|
OPENMC_CELLS[cell_id] = openmc_cell
|
|
|
|
# Add the OpenCG Cell to the global collection of all OpenCG Cells
|
|
OPENCG_CELLS[cell_id] = opencg_cell
|
|
|
|
return opencg_cell
|
|
|
|
|
|
def get_compatible_opencg_cells(opencg_cell, opencg_surface, halfspace):
|
|
"""Generate OpenCG cells that are compatible with OpenMC equivalent to an OpenCG
|
|
cell that is not compatible.
|
|
|
|
Parameters
|
|
----------
|
|
opencg_cell : opencg.Cell
|
|
OpenCG cell
|
|
opencg_surface : opencg.Surface
|
|
OpenCG surface that causes the incompatibility, e.g. an instance of
|
|
XSquarePrism
|
|
halfspace : {-1, 1}
|
|
Which halfspace defined by the surface is contained in the cell
|
|
|
|
Returns
|
|
-------
|
|
compatible_cells : list of opencg.Cell
|
|
Collection of cells equivalent to the original one but compatible with
|
|
OpenMC
|
|
|
|
"""
|
|
if not isinstance(opencg_cell, opencg.Cell):
|
|
msg = 'Unable to create compatible OpenMC Cell from "{0}" which ' \
|
|
'is not an OpenCG Cell'.format(opencg_cell)
|
|
raise ValueError(msg)
|
|
|
|
elif not isinstance(opencg_surface, opencg.Surface):
|
|
msg = 'Unable to create compatible OpenMC Cell since "{0}" is ' \
|
|
'not an OpenCG Surface'.format(opencg_surface)
|
|
raise ValueError(msg)
|
|
|
|
elif halfspace not in [-1, +1]:
|
|
msg = 'Unable to create compatible Cell since "{0}"' \
|
|
'is not a +/-1 halfspace'.format(halfspace)
|
|
raise ValueError(msg)
|
|
|
|
# Initialize an empty list for the new compatible cells
|
|
compatible_cells = []
|
|
|
|
# SquarePrism Surfaces
|
|
if opencg_surface._type in ['x-squareprism', 'y-squareprism',
|
|
'z-squareprism']:
|
|
|
|
# Get the compatible Surfaces (XPlanes and YPlanes)
|
|
compatible_surfaces = get_compatible_opencg_surfaces(opencg_surface)
|
|
|
|
opencg_cell.removeSurface(opencg_surface)
|
|
|
|
# If Cell is inside SquarePrism, add "inside" of Surface halfspaces
|
|
if halfspace == -1:
|
|
opencg_cell.addSurface(compatible_surfaces[0], +1)
|
|
opencg_cell.addSurface(compatible_surfaces[1], -1)
|
|
opencg_cell.addSurface(compatible_surfaces[2], +1)
|
|
opencg_cell.addSurface(compatible_surfaces[3], -1)
|
|
compatible_cells.append(opencg_cell)
|
|
|
|
# If Cell is outside SquarePrism, add "outside" of Surface halfspaces
|
|
else:
|
|
# Create 8 Cell clones to represent each of the disjoint planar
|
|
# Surface halfspace intersections
|
|
num_clones = 8
|
|
|
|
for clone_id in range(num_clones):
|
|
# Create a cloned OpenCG Cell with Surfaces compatible with OpenMC
|
|
clone = opencg_cell.clone()
|
|
compatible_cells.append(clone)
|
|
|
|
# Top left subcell - add left XPlane, top YPlane
|
|
if clone_id == 0:
|
|
clone.add_surface(compatible_surfaces[0], -1)
|
|
clone.add_surface(compatible_surfaces[3], +1)
|
|
|
|
# Top center subcell - add top YPlane, left/right XPlanes
|
|
elif clone_id == 1:
|
|
clone.add_surface(compatible_surfaces[0], +1)
|
|
clone.add_surface(compatible_surfaces[1], -1)
|
|
clone.add_surface(compatible_surfaces[3], +1)
|
|
|
|
# Top right subcell - add top YPlane, right XPlane
|
|
elif clone_id == 2:
|
|
clone.add_surface(compatible_surfaces[1], +1)
|
|
clone.add_surface(compatible_surfaces[3], +1)
|
|
|
|
# Right center subcell - add right XPlane, top/bottom YPlanes
|
|
elif clone_id == 3:
|
|
clone.add_surface(compatible_surfaces[1], +1)
|
|
clone.add_surface(compatible_surfaces[3], -1)
|
|
clone.add_surface(compatible_surfaces[2], +1)
|
|
|
|
# Bottom right subcell - add right XPlane, bottom YPlane
|
|
elif clone_id == 4:
|
|
clone.add_surface(compatible_surfaces[1], +1)
|
|
clone.add_surface(compatible_surfaces[2], -1)
|
|
|
|
# Bottom center subcell - add bottom YPlane, left/right XPlanes
|
|
elif clone_id == 5:
|
|
clone.add_surface(compatible_surfaces[0], +1)
|
|
clone.add_surface(compatible_surfaces[1], -1)
|
|
clone.add_surface(compatible_surfaces[2], -1)
|
|
|
|
# Bottom left subcell - add bottom YPlane, left XPlane
|
|
elif clone_id == 6:
|
|
clone.add_surface(compatible_surfaces[0], -1)
|
|
clone.add_surface(compatible_surfaces[2], -1)
|
|
|
|
# Left center subcell - add left XPlane, top/bottom YPlanes
|
|
elif clone_id == 7:
|
|
clone.add_surface(compatible_surfaces[0], -1)
|
|
clone.add_surface(compatible_surfaces[3], -1)
|
|
clone.add_surface(compatible_surfaces[2], +1)
|
|
|
|
# Remove redundant Surfaces from the Cells
|
|
for cell in compatible_cells:
|
|
cell.removeRedundantSurfaces()
|
|
|
|
# Return the list of OpenMC compatible OpenCG Cells
|
|
return compatible_cells
|
|
|
|
|
|
def make_opencg_cells_compatible(opencg_universe):
|
|
"""Make all cells in an OpenCG universe compatible with OpenMC.
|
|
|
|
Parameters
|
|
----------
|
|
opencg_universe : opencg.Universe
|
|
Universe to check
|
|
|
|
"""
|
|
|
|
if not isinstance(opencg_universe, opencg.Universe):
|
|
msg = 'Unable to make compatible OpenCG Cells for "{0}" which ' \
|
|
'is not an OpenCG Universe'.format(opencg_universe)
|
|
raise ValueError(msg)
|
|
|
|
# Check all OpenCG Cells in this Universe for compatibility with OpenMC
|
|
opencg_cells = opencg_universe._cells
|
|
|
|
for cell_id, opencg_cell in opencg_cells.items():
|
|
|
|
# Check each of the OpenCG Surfaces for OpenMC compatibility
|
|
surfaces = opencg_cell._surfaces
|
|
|
|
for surface_id in surfaces:
|
|
surface = surfaces[surface_id][0]
|
|
halfspace = surfaces[surface_id][1]
|
|
|
|
# If this Surface is not compatible with OpenMC, create compatible
|
|
# OpenCG cells with a compatible version of this OpenCG Surface
|
|
if not is_opencg_surface_compatible(surface):
|
|
|
|
# Get one or more OpenCG Cells that are compatible with OpenMC
|
|
# NOTE: This does not necessarily make OpenCG fully compatible.
|
|
# It only removes the incompatible Surface and replaces it with
|
|
# compatible OpenCG Surface(s). The recursive call at the end
|
|
# of this block is necessary in the event that there are more
|
|
# incompatible Surfaces in this Cell that are not accounted for.
|
|
cells = get_compatible_opencg_cells(opencg_cell,
|
|
surface, halfspace)
|
|
|
|
# Remove the non-compatible OpenCG Cell from the Universe
|
|
opencg_universe.removeCell(opencg_cell)
|
|
|
|
# Add the compatible OpenCG Cells to the Universe
|
|
opencg_universe.addCells(cells)
|
|
|
|
# Make recursive call to look at the updated state of the
|
|
# OpenCG Universe and return
|
|
return make_opencg_cells_compatible(opencg_universe)
|
|
|
|
# If all OpenCG Cells in the OpenCG Universe are compatible, return
|
|
return
|
|
|
|
|
|
def get_openmc_cell(opencg_cell):
|
|
"""Return an OpenMC cell corresponding to an OpenCG cell.
|
|
|
|
Parameters
|
|
----------
|
|
opencg_cell : opencg.Cell
|
|
OpenCG cell
|
|
|
|
Returns
|
|
-------
|
|
openmc_cell : openmc.universe.Cell
|
|
Equivalent OpenMC cell
|
|
|
|
"""
|
|
|
|
if not isinstance(opencg_cell, opencg.Cell):
|
|
msg = 'Unable to create an OpenMC Cell from "{0}" which ' \
|
|
'is not an OpenCG Cell'.format(opencg_cell)
|
|
raise ValueError(msg)
|
|
|
|
global OPENMC_CELLS
|
|
cell_id = opencg_cell._id
|
|
|
|
# If this Cell was already created, use it
|
|
if cell_id in OPENMC_CELLS:
|
|
return OPENMC_CELLS[cell_id]
|
|
|
|
# Create an OpenCG Cell to represent this OpenMC Cell
|
|
name = opencg_cell._name
|
|
openmc_cell = openmc.Cell(cell_id, name)
|
|
|
|
fill = opencg_cell._fill
|
|
|
|
if (opencg_cell._type == 'universe'):
|
|
openmc_cell.fill = get_openmc_universe(fill)
|
|
elif (opencg_cell._type == 'lattice'):
|
|
openmc_cell.fill = get_openmc_lattice(fill)
|
|
else:
|
|
openmc_cell.fill = get_openmc_material(fill)
|
|
|
|
if opencg_cell._rotation:
|
|
rotation = np.asarray(opencg_cell._rotation, dtype=np.int)
|
|
openmc_cell.rotation = rotation
|
|
|
|
if opencg_cell._translation:
|
|
translation = np.asarray(opencg_cell._translation, dtype=np.float64)
|
|
openmc_cell.setTranslation(translation)
|
|
|
|
surfaces = opencg_cell._surfaces
|
|
|
|
for surface_id in surfaces:
|
|
surface = surfaces[surface_id][0]
|
|
halfspace = surfaces[surface_id][1]
|
|
openmc_cell.add_surface(get_openmc_surface(surface), halfspace)
|
|
|
|
# Add the OpenMC Cell to the global collection of all OpenMC Cells
|
|
OPENMC_CELLS[cell_id] = openmc_cell
|
|
|
|
# Add the OpenCG Cell to the global collection of all OpenCG Cells
|
|
OPENCG_CELLS[cell_id] = opencg_cell
|
|
|
|
return openmc_cell
|
|
|
|
|
|
def get_opencg_universe(openmc_universe):
|
|
"""Return an OpenCG universe corresponding to an OpenMC universe.
|
|
|
|
Parameters
|
|
----------
|
|
openmc_universe : openmc.universe.Universe
|
|
OpenMC universe
|
|
|
|
Returns
|
|
-------
|
|
opencg_universe : opencg.Universe
|
|
Equivalent OpenCG universe
|
|
|
|
"""
|
|
|
|
if not isinstance(openmc_universe, openmc.Universe):
|
|
msg = 'Unable to create an OpenCG Universe from "{0}" which ' \
|
|
'is not an OpenMC Universe'.format(openmc_universe)
|
|
raise ValueError(msg)
|
|
|
|
global OPENCG_UNIVERSES
|
|
universe_id = openmc_universe._id
|
|
|
|
# If this Universe was already created, use it
|
|
if universe_id in OPENCG_UNIVERSES:
|
|
return OPENCG_UNIVERSES[universe_id]
|
|
|
|
# Create an OpenCG Universe to represent this OpenMC Universe
|
|
name = openmc_universe._name
|
|
opencg_universe = opencg.Universe(universe_id, name)
|
|
|
|
# Convert all OpenMC Cells in this Universe to OpenCG Cells
|
|
openmc_cells = openmc_universe._cells
|
|
|
|
for cell_id, openmc_cell in openmc_cells.items():
|
|
opencg_cell = get_opencg_cell(openmc_cell)
|
|
opencg_universe.addCell(opencg_cell)
|
|
|
|
# Add the OpenMC Universe to the global collection of all OpenMC Universes
|
|
OPENMC_UNIVERSES[universe_id] = openmc_universe
|
|
|
|
# Add the OpenCG Universe to the global collection of all OpenCG Universes
|
|
OPENCG_UNIVERSES[universe_id] = opencg_universe
|
|
|
|
return opencg_universe
|
|
|
|
|
|
def get_openmc_universe(opencg_universe):
|
|
"""Return an OpenMC universe corresponding to an OpenCG universe.
|
|
|
|
Parameters
|
|
----------
|
|
opencg_universe : opencg.Universe
|
|
OpenCG universe
|
|
|
|
Returns
|
|
-------
|
|
openmc_universe : openmc.universe.Universe
|
|
Equivalent OpenMC universe
|
|
|
|
"""
|
|
|
|
if not isinstance(opencg_universe, opencg.Universe):
|
|
msg = 'Unable to create an OpenMC Universe from "{0}" which ' \
|
|
'is not an OpenCG Universe'.format(opencg_universe)
|
|
raise ValueError(msg)
|
|
|
|
global OPENMC_UNIVERSES
|
|
universe_id = opencg_universe._id
|
|
|
|
# If this Universe was already created, use it
|
|
if universe_id in OPENMC_UNIVERSES:
|
|
return OPENMC_UNIVERSES[universe_id]
|
|
|
|
# Make all OpenCG Cells and Surfaces in this Universe compatible with OpenMC
|
|
make_opencg_cells_compatible(opencg_universe)
|
|
|
|
# Create an OpenMC Universe to represent this OpenCSg Universe
|
|
name = opencg_universe._name
|
|
openmc_universe = openmc.Universe(universe_id, name)
|
|
|
|
# Convert all OpenCG Cells in this Universe to OpenMC Cells
|
|
opencg_cells = opencg_universe._cells
|
|
|
|
for cell_id, opencg_cell in opencg_cells.items():
|
|
openmc_cell = get_openmc_cell(opencg_cell)
|
|
openmc_universe.add_cell(openmc_cell)
|
|
|
|
# Add the OpenMC Universe to the global collection of all OpenMC Universes
|
|
OPENMC_UNIVERSES[universe_id] = openmc_universe
|
|
|
|
# Add the OpenCG Universe to the global collection of all OpenCG Universes
|
|
OPENCG_UNIVERSES[universe_id] = opencg_universe
|
|
|
|
return openmc_universe
|
|
|
|
|
|
def get_opencg_lattice(openmc_lattice):
|
|
"""Return an OpenCG lattice corresponding to an OpenMC lattice.
|
|
|
|
Parameters
|
|
----------
|
|
openmc_lattice : openmc.universe.Lattice
|
|
OpenMC lattice
|
|
|
|
Returns
|
|
-------
|
|
opencg_lattice : opencg.Lattice
|
|
Equivalent OpenCG lattice
|
|
|
|
"""
|
|
|
|
if not isinstance(openmc_lattice, openmc.Lattice):
|
|
msg = 'Unable to create an OpenCG Lattice from "{0}" which ' \
|
|
'is not an OpenMC Lattice'.format(openmc_lattice)
|
|
raise ValueError(msg)
|
|
|
|
global OPENCG_LATTICES
|
|
lattice_id = openmc_lattice._id
|
|
|
|
# If this Lattice was already created, use it
|
|
if lattice_id in OPENCG_LATTICES:
|
|
return OPENCG_LATTICES[lattice_id]
|
|
|
|
# Create an OpenCG Lattice to represent this OpenMC Lattice
|
|
name = openmc_lattice.name
|
|
dimension = openmc_lattice.dimension
|
|
pitch = openmc_lattice.pitch
|
|
lower_left = openmc_lattice.lower_left
|
|
universes = openmc_lattice.universes
|
|
|
|
if len(pitch) == 2:
|
|
new_pitch = np.ones(3, dtype=np.float64)
|
|
new_pitch[:2] = pitch
|
|
pitch = new_pitch
|
|
|
|
if len(lower_left) == 2:
|
|
new_lower_left = np.ones(3, dtype=np.float64)
|
|
new_lower_left[:2] = lower_left
|
|
lower_left = new_lower_left
|
|
|
|
# Initialize an empty array for the OpenCG nested Universes in this Lattice
|
|
universe_array = np.ndarray(tuple(np.array(dimension)[::-1]),
|
|
dtype=opencg.Universe)
|
|
|
|
# Create OpenCG Universes for each unique nested Universe in this Lattice
|
|
unique_universes = openmc_lattice.get_unique_universes()
|
|
|
|
for universe_id, universe in unique_universes.items():
|
|
unique_universes[universe_id] = get_opencg_universe(universe)
|
|
|
|
# Build the nested Universe array
|
|
for z in range(dimension[2]):
|
|
for y in range(dimension[1]):
|
|
for x in range(dimension[0]):
|
|
universe_id = universes[x][dimension[1]-y-1][z]._id
|
|
universe_array[z][y][x] = unique_universes[universe_id]
|
|
|
|
opencg_lattice = opencg.Lattice(lattice_id, name)
|
|
opencg_lattice.setDimension(dimension)
|
|
opencg_lattice.setWidth(pitch)
|
|
opencg_lattice.setUniverses(universe_array)
|
|
|
|
offset = np.array(lower_left, dtype=np.float64) - \
|
|
((np.array(pitch, dtype=np.float64) *
|
|
np.array(dimension, dtype=np.float64))) / -2.0
|
|
opencg_lattice.setOffset(offset)
|
|
|
|
# Add the OpenMC Lattice to the global collection of all OpenMC Lattices
|
|
OPENMC_LATTICES[lattice_id] = openmc_lattice
|
|
|
|
# Add the OpenCG Lattice to the global collection of all OpenCG Lattices
|
|
OPENCG_LATTICES[lattice_id] = opencg_lattice
|
|
|
|
return opencg_lattice
|
|
|
|
|
|
def get_openmc_lattice(opencg_lattice):
|
|
"""Return an OpenMC lattice corresponding to an OpenCG lattice.
|
|
|
|
Parameters
|
|
----------
|
|
opencg_lattice : opencg.Lattice
|
|
OpenCG lattice
|
|
|
|
Returns
|
|
-------
|
|
openmc_lattice : openmc.universe.Lattice
|
|
Equivalent OpenMC lattice
|
|
|
|
"""
|
|
|
|
if not isinstance(opencg_lattice, opencg.Lattice):
|
|
msg = 'Unable to create an OpenMC Lattice from "{0}" which ' \
|
|
'is not an OpenCG Lattice'.format(opencg_lattice)
|
|
raise ValueError(msg)
|
|
|
|
global OPENMC_LATTICES
|
|
lattice_id = opencg_lattice._id
|
|
|
|
# If this Lattice was already created, use it
|
|
if lattice_id in OPENMC_LATTICES:
|
|
return OPENMC_LATTICES[lattice_id]
|
|
|
|
dimension = opencg_lattice._dimension
|
|
width = opencg_lattice._width
|
|
offset = opencg_lattice._offset
|
|
universes = opencg_lattice._universes
|
|
|
|
# Initialize an empty array for the OpenMC nested Universes in this Lattice
|
|
universe_array = np.ndarray(tuple(np.array(dimension)),
|
|
dtype=openmc.Universe)
|
|
|
|
# Create OpenMC Universes for each unique nested Universe in this Lattice
|
|
unique_universes = opencg_lattice.getUniqueUniverses()
|
|
|
|
for universe_id, universe in unique_universes.items():
|
|
unique_universes[universe_id] = get_openmc_universe(universe)
|
|
|
|
# Build the nested Universe array
|
|
for z in range(dimension[2]):
|
|
for y in range(dimension[1]):
|
|
for x in range(dimension[0]):
|
|
universe_id = universes[z][y][x]._id
|
|
universe_array[x][y][z] = unique_universes[universe_id]
|
|
|
|
# Reverse y-dimension in array to match ordering in OpenCG
|
|
universe_array = universe_array[:, ::-1, :]
|
|
|
|
lower_left = np.array(offset, dtype=np.float64) + \
|
|
((np.array(width, dtype=np.float64) *
|
|
np.array(dimension, dtype=np.float64))) / -2.0
|
|
|
|
openmc_lattice = openmc.RectLattice(lattice_id=lattice_id)
|
|
openmc_lattice.dimension = dimension
|
|
openmc_lattice.pitch = width
|
|
openmc_lattice.universes = universe_array
|
|
openmc_lattice.lower_left = lower_left
|
|
|
|
# Add the OpenMC Lattice to the global collection of all OpenMC Lattices
|
|
OPENMC_LATTICES[lattice_id] = openmc_lattice
|
|
|
|
# Add the OpenCG Lattice to the global collection of all OpenCG Lattices
|
|
OPENCG_LATTICES[lattice_id] = opencg_lattice
|
|
|
|
return openmc_lattice
|
|
|
|
|
|
def get_opencg_geometry(openmc_geometry):
|
|
"""Return an OpenCG geometry corresponding to an OpenMC geometry.
|
|
|
|
Parameters
|
|
----------
|
|
openmc_geometry : openmc.universe.Geometry
|
|
OpenMC geometry
|
|
|
|
Returns
|
|
-------
|
|
opencg_geometry : opencg.Geometry
|
|
Equivalent OpenCG geometry
|
|
|
|
"""
|
|
|
|
if not isinstance(openmc_geometry, openmc.Geometry):
|
|
msg = 'Unable to get OpenCG geometry from "{0}" which is ' \
|
|
'not an OpenMC Geometry object'.format(openmc_geometry)
|
|
raise ValueError(msg)
|
|
|
|
# Clear dictionaries and auto-generated IDs
|
|
OPENMC_SURFACES.clear()
|
|
OPENCG_SURFACES.clear()
|
|
OPENMC_CELLS.clear()
|
|
OPENCG_CELLS.clear()
|
|
OPENMC_UNIVERSES.clear()
|
|
OPENCG_UNIVERSES.clear()
|
|
OPENMC_LATTICES.clear()
|
|
OPENCG_LATTICES.clear()
|
|
|
|
openmc_root_universe = openmc_geometry._root_universe
|
|
opencg_root_universe = get_opencg_universe(openmc_root_universe)
|
|
|
|
opencg_geometry = opencg.Geometry()
|
|
opencg_geometry.setRootUniverse(opencg_root_universe)
|
|
opencg_geometry.initializeCellOffsets()
|
|
|
|
return opencg_geometry
|
|
|
|
|
|
def get_openmc_geometry(opencg_geometry):
|
|
"""Return an OpenMC geometry corresponding to an OpenCG geometry.
|
|
|
|
Parameters
|
|
----------
|
|
opencg_geometry : opencg.Geometry
|
|
OpenCG geometry
|
|
|
|
Returns
|
|
-------
|
|
openmc_geometry : openmc.universe.Geometry
|
|
Equivalent OpenMC geometry
|
|
|
|
"""
|
|
|
|
if not isinstance(opencg_geometry, opencg.Geometry):
|
|
msg = 'Unable to get OpenMC geometry from "{0}" which is ' \
|
|
'not an OpenCG Geometry object'.format(opencg_geometry)
|
|
raise ValueError(msg)
|
|
|
|
# Deep copy the goemetry since it may be modified to make all Surfaces
|
|
# compatible with OpenMC's specifications
|
|
opencg_geometry.assignAutoIds()
|
|
opencg_geometry = copy.deepcopy(opencg_geometry)
|
|
|
|
# Update Cell bounding boxes in Geometry
|
|
opencg_geometry.updateBoundingBoxes()
|
|
|
|
# Clear dictionaries and auto-generated ID
|
|
OPENMC_SURFACES.clear()
|
|
OPENCG_SURFACES.clear()
|
|
OPENMC_CELLS.clear()
|
|
OPENCG_CELLS.clear()
|
|
OPENMC_UNIVERSES.clear()
|
|
OPENCG_UNIVERSES.clear()
|
|
OPENMC_LATTICES.clear()
|
|
OPENCG_LATTICES.clear()
|
|
|
|
# Make the entire geometry "compatible" before assigning auto IDs
|
|
universes = opencg_geometry.getAllUniverses()
|
|
for universe_id, universe in universes.items():
|
|
if not isinstance(universe, opencg.Lattice):
|
|
make_opencg_cells_compatible(universe)
|
|
|
|
opencg_geometry.assignAutoIds()
|
|
|
|
opencg_root_universe = opencg_geometry._root_universe
|
|
openmc_root_universe = get_openmc_universe(opencg_root_universe)
|
|
|
|
openmc_geometry = openmc.Geometry()
|
|
openmc_geometry.root_universe = openmc_root_universe
|
|
|
|
return openmc_geometry
|