<jupyter_start><jupyter_text>Part 1 - Constructing simple CSG geometryTo perform a neutronics simulation the geometry of the model must be defined. The simplest way to do this is to use Constructive Solid Geometry (CSG) which involves using primitive shapes and boolean operations to create cells and void spaces.This python notebook allows users to make a simple CSG using OpenMC and plot 2D slices of the geometry.<jupyter_code>from IPython.display import HTML
HTML('<iframe width="560" height="315" src="https://www.youtube.com/embed/Ovr7oYukYRw" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>')<jupyter_output><empty_output><jupyter_text>This first code block creates a simple spherical shell geometry by defining two spherical surfaces at different radii. The region between the two surfaces is then defined and a cell created which is added to the geometry 'universe'.Run the cell to produce three 2D slices of the geometry in different planes.<jupyter_code>import openmc
import matplotlib.pyplot as plt

# example surfaces
inner_sphere_surface = openmc.Sphere(r=500)
outer_sphere_surface = openmc.Sphere(r=600)

# above (+) inner_sphere_surface and below (-) outer_sphere_surface
blanket_region = +inner_sphere_surface & -outer_sphere_surface  

# example cell
blanket_cell = openmc.Cell(region=blanket_region)

# makes a universe to cotain all the cells
universe = openmc.Universe(cells=[blanket_cell])  

# shows the plots, as the geometry is symmetrical the plots look the same
color_assignment = {blanket_cell: 'blue'}
plt.show(universe.plot(width=(1200, 1200), basis='xz', colors=color_assignment))
plt.show(universe.plot(width=(1200, 1200), basis='xy', colors=color_assignment))
plt.show(universe.plot(width=(1200, 1200), basis='yz', colors=color_assignment))<jupyter_output><empty_output><jupyter_text>The next code block adds a firstwall cell to the inner surface of the spherical shell.<jupyter_code># example surfaces
inner_sphere_surface = openmc.Sphere(r=480)
middle_sphere_surface = openmc.Sphere(r=500) # note the extra surface
outer_sphere_surface = openmc.Sphere(r=600)

# above (+) middle_sphere_surface and below (-) outer_sphere_surface
blanket_region = +middle_sphere_surface & -outer_sphere_surface
# above (+) inner_sphere_surface and below (-) middle_sphere_surface
firstwall_region = +inner_sphere_surface & -middle_sphere_surface

# now we have two cells
blanket_cell = openmc.Cell(region=blanket_region)
firstwall_cell = openmc.Cell(region=firstwall_region)

# there are now two cells in the list
universe = openmc.Universe(cells=[blanket_cell, firstwall_cell])  

# shows the plots, which still look the same for all directions
color_assignment = {blanket_cell: 'blue', firstwall_cell: 'red'}
plt.show(universe.plot(width=(1200, 1200), basis='xz', colors=color_assignment))
plt.show(universe.plot(width=(1200, 1200), basis='xy', colors=color_assignment))
plt.show(universe.plot(width=(1200, 1200), basis='yz', colors=color_assignment))<jupyter_output><empty_output><jupyter_text>When creating CSG there is another key aspect of the geometry required when we want to use it to simulate particle movement and interactions - the entire geometry must be defined.As well as defining the cells which contain materials, we must also define areas of the geometry with no materials, which are also called 'voids'. By default, cells are all voids until a material is assigned to those cells.Also, the outermost surface must be identified with the boundary_type='vacuum' keyword which tells OpenMC to not compute the movement of particles beyond this surface. The next code block shows how void regions and a vacuum boundary can be defined.<jupyter_code># surfaces
inner_sphere_surface = openmc.Sphere(r=480)
middle_sphere_surface = openmc.Sphere(r=500)
outer_sphere_surface = openmc.Sphere(r=600, boundary_type='vacuum') # note the extra keyword

# regions
blanket_region = +middle_sphere_surface & -outer_sphere_surface
firstwall_region = +inner_sphere_surface & -middle_sphere_surface
inner_vessel_region = -inner_sphere_surface # this is the void region

# cells
blanket_cell = openmc.Cell(region=blanket_region)
firstwall_cell = openmc.Cell(region=firstwall_region)
inner_vessel_cell = openmc.Cell(region=inner_vessel_region) # here as the cell is th new void cell

universe = openmc.Universe(cells=[blanket_cell, firstwall_cell, inner_vessel_cell])  

# note the new color scheme is based on materials not cells
color_assignment = {blanket_cell: 'blue', firstwall_cell: 'red', inner_vessel_cell:'grey'}
# note the additional argument color_by, normally this defaults to 'cell'
plt.show(universe.plot(width=(1200, 1200), basis='xz', colors=color_assignment))
plt.show(universe.plot(width=(1200, 1200), basis='xy', colors=color_assignment))
plt.show(universe.plot(width=(1200, 1200), basis='yz', colors=color_assignment))<jupyter_output><empty_output><jupyter_text>Assigning materials to cells is also necessary when wanting to use the geometry for particle transport.Material creation was covered in Task 2 so these are just minimal materials to demonstrate material assignment to cells.Additionally, this plot uses the color_by='material' argument to colour the plots by materials instead of cells.<jupyter_code>inner_sphere_surface = openmc.Sphere(r=480)
middle_sphere_surface = openmc.Sphere(r=500)
outer_sphere_surface = openmc.Sphere(r=600)

blanket_region = +middle_sphere_surface & -outer_sphere_surface
firstwall_region = +inner_sphere_surface & -middle_sphere_surface
inner_vessel_region = -inner_sphere_surface # this is the void region, it will not have a material

# This makes a minimal material 
lithium_mat = openmc.Material(name='lithium')
lithium_mat.set_density('g/cm3', 2)
lithium_mat.add_element('Li', 1.0)

# This makes another minimal material 
tungsten_mat = openmc.Material(name='tungsten')
tungsten_mat.set_density('g/cm3', 19)
tungsten_mat.add_element('W', 1.0)

blanket_cell = openmc.Cell(region=blanket_region)
blanket_cell.fill = lithium_mat  # this assigns a material to a cell

firstwall_cell = openmc.Cell(region=firstwall_region)
firstwall_cell.fill = tungsten_mat  # this assigns a material to a cell

inner_vessel_cell = openmc.Cell(region=inner_vessel_region)
# note there is no material assignment here as the cell a void cell

universe = openmc.Universe(cells=[blanket_cell, firstwall_cell, inner_vessel_cell])  

# note the new color scheme is based on materials not cells
color_assignment = {lithium_mat: 'green', tungsten_mat: 'yellow'}

# note the additional argument color_by, normally this defaults to 'cell'
plt.show(universe.plot(width=(1200, 1200), basis='xz', color_by='material', colors=color_assignment))
plt.show(universe.plot(width=(1200, 1200), basis='xy', color_by='material', colors=color_assignment))
plt.show(universe.plot(width=(1200, 1200), basis='yz', color_by='material', colors=color_assignment))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09018264840182648, 'fraction_numerical': 0.021404109589041095, 'mean_word_length': 7.093533487297922, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '135036', 'license': 'MIT', 'n_tokens_mistral': 2293, 'n_tokens_neox': 2072, 'n_words': 646, 'path': 'tasks/task_03_making_CSG_geometry/1_simple_csg_geometry.ipynb', 'repo_name': 'khurrumsaleem/neutronics-workshop', 'size': '7008'}