-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Photon Transport Simulation with Two Layers of Material & Unstructured Mesh #27
base: main
Are you sure you want to change the base?
Changes from 14 commits
23c1469
8d1f88b
d7e58a3
39e2d4b
3dfb567
5bb02ff
1fdb1b1
569eb28
1008270
19e86ef
6fa1367
c3cf5db
e217e00
94519f9
3854660
a3db102
4199c1b
fdcb11f
2e209a6
e8a305a
3aa85b3
1cff395
64d14d5
88a9e83
2259f79
84bac07
0713d73
5c03a21
d761b1c
fd3cb83
ed0e05d
c7a0c03
4568353
f91820f
2347332
d3b612e
99af15a
bc4e8d3
e06fba5
7afd568
2b5e67b
4fb3156
c81e21f
1ae47ce
c3509d6
6676191
e6c9518
3a09bf8
0d0418b
93d5b56
80382a4
ab1b09b
43270df
8aff672
0679a68
fc583b1
785511e
ee8df5b
790db58
3b808c1
052b312
771b147
7f76500
2a7d52c
6b18246
a3a9921
608adba
15f64ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Wed Aug 7 10:07:33 2024 | ||
|
||
@author: Anupama Rajendra | ||
""" | ||
|
||
import openmc | ||
import argparse | ||
import numpy as np | ||
from Source_Mesh_Reader import summed_strengths, strengths_list | ||
from TwoLayers_Materials import * | ||
from TwoLayers_Geometry import * | ||
|
||
Mesh_File = 'OpenMC_Mesh.h5m' | ||
|
||
parser = argparse.ArgumentParser(description="Specify required inputs: file path to ALARA Element Library, element name, inner radius [cm], outer_radius [cm]") | ||
|
||
#Required user inputs: | ||
parser.add_argument('--filepath', type=str, required=True) | ||
parser.add_argument('--element_1', type=str, required=True) | ||
parser.add_argument('--element_2', type=str, required=True) | ||
#Shell radii are left as user inputs, but the mesh is specific to W_inner_radius = 1000, W_outer_radius = 1005, C_inner_radius = 995 | ||
parser.add_argument('--W_inner_radius', type=float, required=True) | ||
parser.add_argument('--W_outer_radius', type=float, required=True) | ||
parser.add_argument('--C_inner_radius', type=float, required=True) | ||
|
||
args = parser.parse_args() | ||
|
||
fp = args.filepath | ||
E_1 = args.element_1 | ||
E_2 = args.element_2 | ||
R_W_1 = args.W_inner_radius | ||
R_W_2 = args.W_outer_radius | ||
R_C_1 = args.C_inner_radius | ||
|
||
# fp = '../../ALARA/data/elelib.std' | ||
# E_1 = 'W' | ||
# E_2 = 'C' | ||
# R_W_1 = 1000 | ||
# R_W_2 = 1005 | ||
# R_C_1 = 995 | ||
bounds = [0, | ||
1.00e+4, | ||
2.00e+4, | ||
5.00e+4, | ||
1.00e+5, | ||
2.00e+5, | ||
3.00e+5, | ||
4.00e+5, | ||
6.00e+5, | ||
8.00e+5, | ||
1.00e+6, | ||
1.22e+6, | ||
1.44e+6, | ||
1.66e+6, | ||
2.00e+6, | ||
2.50e+6, | ||
3.00e+6, | ||
4.00e+6, | ||
5.00e+6, | ||
6.50e+6, | ||
8.00e+6, | ||
1.00e+7, | ||
1.20e+7, | ||
1.40e+7, | ||
2.00e+7] | ||
|
||
#Define source: | ||
def make_source(W_Shell, C_Shell, Cells): | ||
Source_List = [] | ||
Particle_Filter = openmc.ParticleFilter('photon') | ||
Total_Mesh = openmc.UnstructuredMesh(Mesh_File, library='moab') | ||
for index, bound in enumerate(bounds[:-1]): | ||
Mesh_Dist = openmc.stats.MeshSpatial(Total_Mesh, strengths=strengths_list[index], volume_normalized=False) | ||
Energy_Dist = openmc.stats.Uniform(a=bounds[index], b=bounds[index + 1]) | ||
#Source strengths given by strengths_list created by Source_Mesh_Reader | ||
Source = Source_List.append(openmc.IndependentSource(space=Mesh_Dist, energy=Energy_Dist, strength=summed_strengths[index], particle='photon', domains=Cells)) | ||
return Source_List, Particle_Filter, Total_Mesh, Mesh_Dist | ||
|
||
# Define tallies | ||
def tallies(W_Shell, C_Shell, Particle_Filter, Total_Mesh): | ||
Total_Filter = openmc.MeshFilter(Total_Mesh) | ||
|
||
neutron_tally = openmc.Tally(tally_id=1, name="Neutron tally") | ||
neutron_tally.scores = ['flux', 'elastic', 'absorption'] | ||
|
||
# Implementing filter for neutron tally through W shell | ||
cell_filter = openmc.CellFilter([W_Shell, C_Shell]) | ||
neutron_tally.filters = [cell_filter, Total_Filter] | ||
|
||
# Creating a tally to get the flux energy spectrum. | ||
# An energy filter is created to assign to the flux tally. | ||
energy_filter_flux = openmc.EnergyFilter.from_group_structure("VITAMIN-J-42") | ||
|
||
spectrum_tally = openmc.Tally(tally_id=2, name="Flux spectrum") | ||
# Implementing energy and cell filters for flux spectrum tally | ||
spectrum_tally.filters = [cell_filter, Total_Filter, energy_filter_flux, Particle_Filter] | ||
spectrum_tally.scores = ['flux'] | ||
|
||
tall = openmc.Tallies([neutron_tally, spectrum_tally]) | ||
tall.export_to_xml() | ||
return tall, neutron_tally, spectrum_tally, Total_Filter, cell_filter | ||
|
||
# Assign simulation settings | ||
def settings(Source_List): | ||
sets = openmc.Settings() | ||
sets.batches = 10 | ||
sets.inactive = 1 | ||
sets.particles = 100000 | ||
sets.source = Source_List | ||
sets.run_mode = 'fixed source' | ||
sets.export_to_xml() | ||
return sets | ||
|
||
def plot_universe(Void, W_Shell, C_Shell, Cells): | ||
universe_ss = openmc.Universe(cells=Cells) | ||
Plot = universe_ss.plot(width=(2500.0, 2500.0), basis='xz', | ||
colors={Void: 'blue', W_Shell: 'red', C_Shell: 'green'}, legend=True) | ||
Plot.figure.savefig('Universe') | ||
return universe_ss | ||
|
||
# Exporting materials, geometry, and tallies to .xml | ||
def export_to_xml(filepath, element_1, element_2, inner_radius_W, outer_radius_W, inner_radius_C): | ||
OpenMC_SF = mat_lib(filepath) | ||
materials = [] | ||
for material_id, element in enumerate(elements): | ||
materials.append(make_element(element, material_id+1, OpenMC_SF)) | ||
OpenMC_Mat = all_mat(OpenMC_W, OpenMC_C) | ||
OpenMC_Geometry = make_spherical_shell(inner_radius_W, outer_radius_W, inner_radius_C, OpenMC_W, OpenMC_C) | ||
OpenMC_Source = make_source(OpenMC_Geometry[2], OpenMC_Geometry[3], OpenMC_Geometry[4]) | ||
OpenMC_Settings = settings(OpenMC_Source[0]) | ||
OpenMC_Tallies = tallies(OpenMC_Geometry[2], OpenMC_Geometry[3], OpenMC_Source[1], OpenMC_Source[2]) | ||
OpenMC_Universe = plot_universe(OpenMC_Geometry[1], OpenMC_Geometry[2], OpenMC_Geometry[3], OpenMC_Geometry[4]) | ||
#return OpenMC_Materials, OpenMC_Geometry, OpenMC_Source, OpenMC_Settings, OpenMC_Tallies, OpenMC_Universe | ||
return OpenMC_SF, OpenMC_W, OpenMC_C, *OpenMC_Geometry, *OpenMC_Source, OpenMC_Settings, *OpenMC_Tallies | ||
|
||
Lib_Lines, M_1, M_2, geometry, Void, W_Shell, C_Shell, Cells, Source_List, Particle_Filter, Total_Mesh, Mesh_Dist, tall, neutron_tally, spectrum_tally, Total_Filter, cell_filter, sets = export_to_xml(fp, E_1, E_2, R_W_1, R_W_2, R_C_1) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Thu Oct 3 23:18:20 2024 | ||
|
||
@author: Anupama Rajendra | ||
""" | ||
import openmc | ||
import matplotlib.pyplot as plt | ||
|
||
with openmc.StatePoint("statepoint.10.h5") as sp: | ||
flux_spectrum = sp.get_tally(id=2) | ||
mesh=sp.meshes[1] | ||
# Get the reshaped tally data | ||
tally_data_reshaped = flux_spectrum.get_reshaped_data(value='mean') | ||
|
||
flux_sum_en = tally_data_reshaped.sum(axis=(0,1,3,4,5)) | ||
#Vitamin-J energy filter: | ||
e_filter = flux_spectrum.filters[2] | ||
#Lower bounds of the energy bins | ||
e_filter_lower = e_filter.bins[:, 0] | ||
|
||
# Plot flux spectrum | ||
fix, ax = plt.subplots() | ||
ax.loglog(e_filter_lower, flux_sum_en, drawstyle='steps-post') | ||
ax.set_xlabel('Energy [eV]') | ||
ax.set_ylabel('Flux [photon-cm/source]') | ||
ax.grid(True, which='both') | ||
plt.savefig('Photon_flux_vs_energy.png') | ||
plt.show() | ||
|
||
mesh_data = tally_data_reshaped.sum(axis=(0,2,3,4,5)) | ||
vtk = mesh.write_data_to_vtk(filename="Photon_Flux.vtk", datasets={"mean":mesh_data.flatten()}) | ||
anu1217 marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Mon Sep 30 15:16:44 2024 | ||
|
||
@author: Anupama Rajendra | ||
""" | ||
|
||
import h5py | ||
import numpy as np | ||
|
||
# Open the HDF5 files | ||
File_1 = h5py.File("source_mesh_1.h5m", 'r') | ||
File_2 = h5py.File("source_mesh_2.h5m", 'r') | ||
Files = [File_1, File_2] | ||
|
||
# Number of photon groups | ||
photon_groups = 24 | ||
|
||
# Process each file | ||
for file_index, file in enumerate(Files): | ||
# Extract data from the current file | ||
tstt = file['tstt'] | ||
elements = tstt['elements'] | ||
tet_four = elements['Tet4'] | ||
tags = tet_four['tags'] | ||
sd = tags['source_density'][:] | ||
|
||
# Write source density to a separate file for each mesh | ||
with open(f'source_density_{file_index + 1}.txt', 'w') as source: | ||
for tet_element in sd: | ||
source.write(' '.join(map(str, tet_element)) + '\n') | ||
|
||
# Calculate summed (and individual mesh) strengths for each photon group | ||
summed_strengths = [] | ||
strengths_list = [] | ||
anu1217 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for group in range(photon_groups): | ||
total_strengths = np.sum(sd[:, group]) # Sum over all mesh elements | ||
summed_strengths.append(total_strengths) | ||
strengths = sd[:,group] | ||
strengths_list.append(strengths) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I recommend putting this in a method that does everything you need for a single file. That kind of modularity enhances readability. You might also want to separate the functions of reading from a file, processing the data, and writing to files, so methods like
anu1217 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,33 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# -*- coding: utf-8 -*- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Created on Fri Oct 11 15:56:57 2024 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@author: Anupama Rajendra | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import openmc | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not clear that we need to import There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be missing something here, but OpenMC_PhotonTransport attempts to access openmc inside TwoLayers_Geometry even when only make_spherical_shells is imported |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Create geometry | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#Spherical shell: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def make_spherical_shell(inner_radius_W, outer_radius_W, inner_radius_C, M_1, M_2): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. docstrings here would help be clear about what everything is doing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes multiple shells, so maybe change the name. Could also generalize this to take an inner radius plus layers:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think materials will need to be an input as this function is also assigning materials to the geometry. I'm wondering if this can be done with one set of radii/thickness inputs and the materials from TwoLayers_Materials.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that the materials are necessary. My version had them bound in the
The function may be:
(There may be minor syntax errors, but this is the basic idea) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
S_W_1= openmc.Sphere(r=inner_radius_W) #sphere of radius 1000cm | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
inside_W_sphere_1 = -S_W_1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
outside_W_sphere_1 = +S_W_1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
S_W_2 = openmc.Sphere(r=outer_radius_W, boundary_type='vacuum') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
inside_W_sphere_2 = -S_W_2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
outside_W_sphere_2 = +S_W_2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
S_W_3 = outside_W_sphere_1 & inside_W_sphere_2 #filled with specified material | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
anu1217 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
S_C_1= openmc.Sphere(r=inner_radius_C) #sphere of radius 995cm | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
inside_C_sphere_1 = -S_C_1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
outside_C_sphere_1 = +S_C_1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
S_C_3 = outside_C_sphere_1 & inside_W_sphere_1 #filled with specified material | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Mapping materials to geometry: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Void = openmc.Cell(fill=None, region = inside_C_sphere_1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
W_Shell = openmc.Cell(fill=M_1, region=S_W_3) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
C_Shell = openmc.Cell(fill=M_2, region=S_C_3) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Cells = [Void, W_Shell, C_Shell] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
geometry = openmc.Geometry(Cells) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
geometry.export_to_xml() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
anu1217 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return geometry, Void, W_Shell, C_Shell, Cells | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
anu1217 marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Fri Oct 11 13:49:23 2024 | ||
|
||
@author: Anupama Rajendra | ||
""" | ||
import openmc | ||
|
||
#ALARA Element Library to read density for specified element: | ||
def mat_lib(filepath): | ||
with open(""+filepath+"") as ALARA_Lib: | ||
Lib_Lines = ALARA_Lib.readlines() | ||
anu1217 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return Lib_Lines | ||
|
||
def create_densities(elements, Lib_Lines): | ||
density_dict = {} | ||
for element in elements: | ||
for line in Lib_Lines: | ||
if line.split()[0].lower() == element.lower(): | ||
density_dict[element] = float(line.strip().split()[3]) | ||
return density_dict | ||
|
||
# Create materials & export to XML: | ||
#Simulating tungsten shell: | ||
def make_element(elements, density_dict): | ||
mats = openmc.Materials([]) | ||
for element_id, element in enumerate(elements): | ||
mat = openmc.Material(material_id=element_id+1, name=element) | ||
mat.add_element(element, 1.00) | ||
mat.set_density('g/cm3', density_dict.get(f'{element}')) | ||
mats.append(mat) | ||
return mats | ||
anu1217 marked this conversation as resolved.
Show resolved
Hide resolved
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of magic numbers here including tally ID, mesh number, axes for sum, etc... more readable if these are named as variables, and might make sense if they lived in a function that took some of these as arguments.