2018-02-02 10:06:45 -06:00
|
|
|
from collections.abc import Iterable
|
2015-12-22 14:40:56 -08:00
|
|
|
import re
|
2017-06-02 13:25:34 -05:00
|
|
|
import warnings
|
2015-04-16 13:13:54 -05:00
|
|
|
|
2016-07-01 22:57:14 +07:00
|
|
|
import numpy as np
|
2016-11-14 11:26:08 -06:00
|
|
|
import h5py
|
2016-07-01 22:57:14 +07:00
|
|
|
|
2014-11-25 21:37:02 -05:00
|
|
|
import openmc
|
2017-02-17 14:29:34 -06:00
|
|
|
import openmc.checkvalue as cv
|
2015-09-26 19:52:07 +07:00
|
|
|
from openmc.region import Region
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2018-04-27 19:45:38 -04:00
|
|
|
_VERSION_SUMMARY = 6
|
2017-02-17 14:29:34 -06:00
|
|
|
|
2014-11-25 21:37:02 -05:00
|
|
|
|
|
|
|
|
class Summary(object):
|
2017-02-17 15:21:42 -06:00
|
|
|
"""Summary of geometry, materials, and tallies used in a simulation.
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2015-10-28 21:22:22 -04:00
|
|
|
Attributes
|
|
|
|
|
----------
|
2017-02-17 15:21:42 -06:00
|
|
|
date_and_time : str
|
|
|
|
|
Date and time when simulation began
|
|
|
|
|
geometry : openmc.Geometry
|
|
|
|
|
The geometry reconstructed from the summary file
|
|
|
|
|
materials : openmc.Materials
|
|
|
|
|
The materials reconstructed from the summary file
|
|
|
|
|
nuclides : dict
|
|
|
|
|
Dictionary whose keys are nuclide names and values are atomic weight
|
|
|
|
|
ratios.
|
2018-04-27 19:45:38 -04:00
|
|
|
macroscopics : list
|
|
|
|
|
Names of macroscopic data sets
|
2017-02-17 15:21:42 -06:00
|
|
|
version: tuple of int
|
|
|
|
|
Version of OpenMC
|
2015-10-28 21:22:22 -04:00
|
|
|
|
2015-06-02 19:22:33 +07:00
|
|
|
"""
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2015-06-02 19:22:33 +07:00
|
|
|
def __init__(self, filename):
|
2014-11-25 21:37:02 -05:00
|
|
|
if not filename.endswith(('.h5', '.hdf5')):
|
|
|
|
|
msg = 'Unable to open "{0}" which is not an HDF5 summary file'
|
|
|
|
|
raise ValueError(msg)
|
|
|
|
|
|
|
|
|
|
self._f = h5py.File(filename, 'r')
|
2017-02-17 14:29:34 -06:00
|
|
|
cv.check_filetype_version(self._f, 'summary', _VERSION_SUMMARY)
|
|
|
|
|
|
2017-02-17 15:21:42 -06:00
|
|
|
self._geometry = openmc.Geometry()
|
2017-03-29 17:30:18 -04:00
|
|
|
|
|
|
|
|
self._fast_materials = {}
|
|
|
|
|
self._fast_surfaces = {}
|
|
|
|
|
self._fast_cells = {}
|
2018-04-27 19:45:38 -04:00
|
|
|
self._fast_universes = {}
|
2017-03-29 17:30:18 -04:00
|
|
|
self._fast_lattices = {}
|
|
|
|
|
|
2017-02-17 15:21:42 -06:00
|
|
|
self._materials = openmc.Materials()
|
2017-02-20 09:03:50 -06:00
|
|
|
self._nuclides = {}
|
2018-04-27 19:45:38 -04:00
|
|
|
self._macroscopics = []
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2016-05-03 04:40:59 -04:00
|
|
|
self._read_nuclides()
|
2018-04-27 19:45:38 -04:00
|
|
|
self._read_macroscopics()
|
2017-06-02 13:25:34 -05:00
|
|
|
with warnings.catch_warnings():
|
2017-06-15 14:38:25 -05:00
|
|
|
warnings.simplefilter("ignore", openmc.IDWarning)
|
2017-06-02 13:25:34 -05:00
|
|
|
self._read_geometry()
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2015-10-28 21:22:22 -04:00
|
|
|
@property
|
2017-02-17 15:21:42 -06:00
|
|
|
def date_and_time(self):
|
2017-03-10 07:13:38 -06:00
|
|
|
return self._f.attrs['date_and_time'].decode()
|
2015-10-28 21:22:22 -04:00
|
|
|
|
|
|
|
|
@property
|
2017-02-17 15:21:42 -06:00
|
|
|
def geometry(self):
|
|
|
|
|
return self._geometry
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def materials(self):
|
|
|
|
|
return self._materials
|
|
|
|
|
|
2017-02-20 09:03:50 -06:00
|
|
|
@property
|
|
|
|
|
def nuclides(self):
|
|
|
|
|
return self._nuclides
|
2017-06-02 13:25:34 -05:00
|
|
|
|
2018-04-27 19:45:38 -04:00
|
|
|
@property
|
|
|
|
|
def macroscopics(self):
|
|
|
|
|
return self._macroscopics
|
|
|
|
|
|
2017-02-17 15:21:42 -06:00
|
|
|
@property
|
|
|
|
|
def version(self):
|
|
|
|
|
return tuple(self._f.attrs['openmc_version'])
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2016-05-03 04:40:59 -04:00
|
|
|
def _read_nuclides(self):
|
2018-04-27 19:45:38 -04:00
|
|
|
if 'nuclides/names' in self._f:
|
|
|
|
|
names = self._f['nuclides/names'].value
|
|
|
|
|
awrs = self._f['nuclides/awrs'].value
|
|
|
|
|
for name, awr in zip(names, awrs):
|
|
|
|
|
self._nuclides[name.decode()] = awr
|
|
|
|
|
|
|
|
|
|
def _read_macroscopics(self):
|
|
|
|
|
if 'macroscopics/names' in self._f:
|
|
|
|
|
names = self._f['macroscopics/names'].value
|
|
|
|
|
for name in names:
|
|
|
|
|
self._macroscopics = name.decode()
|
2016-05-03 04:40:59 -04:00
|
|
|
|
2014-11-25 21:37:02 -05:00
|
|
|
def _read_geometry(self):
|
|
|
|
|
# Read in and initialize the Materials and Geometry
|
|
|
|
|
self._read_materials()
|
2017-03-29 17:30:18 -04:00
|
|
|
self._read_surfaces()
|
|
|
|
|
cell_fills = self._read_cells()
|
|
|
|
|
self._read_universes()
|
|
|
|
|
self._read_lattices()
|
|
|
|
|
self._finalize_geometry(cell_fills)
|
2014-11-25 21:37:02 -05:00
|
|
|
|
|
|
|
|
def _read_materials(self):
|
2017-02-22 17:00:25 -06:00
|
|
|
for group in self._f['materials'].values():
|
|
|
|
|
material = openmc.Material.from_hdf5(group)
|
2017-02-17 14:53:34 -06:00
|
|
|
|
2017-02-22 17:00:25 -06:00
|
|
|
# Add the material to the Materials collection
|
2017-02-17 15:21:42 -06:00
|
|
|
self.materials.append(material)
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2017-03-29 17:30:18 -04:00
|
|
|
# Store in the dictionary of materials for fast queries
|
2017-05-04 14:58:30 -04:00
|
|
|
self._fast_materials[material.id] = material
|
2017-03-29 17:30:18 -04:00
|
|
|
|
2014-11-25 21:37:02 -05:00
|
|
|
def _read_surfaces(self):
|
2017-02-20 10:22:15 -06:00
|
|
|
for group in self._f['geometry/surfaces'].values():
|
|
|
|
|
surface = openmc.Surface.from_hdf5(group)
|
2017-05-04 14:58:30 -04:00
|
|
|
self._fast_surfaces[surface.id] = surface
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2017-03-29 17:30:18 -04:00
|
|
|
def _read_cells(self):
|
2014-11-25 21:37:02 -05:00
|
|
|
|
|
|
|
|
# Initialize dictionary for each Cell's fill
|
2017-02-17 15:21:42 -06:00
|
|
|
cell_fills = {}
|
|
|
|
|
|
|
|
|
|
for key, group in self._f['geometry/cells'].items():
|
2014-11-25 21:37:02 -05:00
|
|
|
cell_id = int(key.lstrip('cell '))
|
2017-03-01 12:11:37 -06:00
|
|
|
name = group['name'].value.decode() if 'name' in group else ''
|
2017-02-17 15:21:42 -06:00
|
|
|
fill_type = group['fill_type'].value.decode()
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2017-02-22 17:09:19 -06:00
|
|
|
if fill_type == 'material':
|
2017-02-17 15:21:42 -06:00
|
|
|
fill = group['material'].value
|
2014-12-02 08:31:16 -05:00
|
|
|
elif fill_type == 'universe':
|
2017-02-17 15:21:42 -06:00
|
|
|
fill = group['fill'].value
|
2014-11-25 21:37:02 -05:00
|
|
|
else:
|
2017-02-17 15:21:42 -06:00
|
|
|
fill = group['lattice'].value
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2017-03-01 12:11:37 -06:00
|
|
|
region = group['region'].value.decode() if 'region' in group else ''
|
2014-11-25 21:37:02 -05:00
|
|
|
|
|
|
|
|
# Create this Cell
|
2015-04-01 18:48:03 -04:00
|
|
|
cell = openmc.Cell(cell_id=cell_id, name=name)
|
2014-11-25 21:37:02 -05:00
|
|
|
|
|
|
|
|
if fill_type == 'universe':
|
2017-02-17 15:21:42 -06:00
|
|
|
if 'translation' in group:
|
|
|
|
|
translation = group['translation'][...]
|
2014-11-25 21:37:02 -05:00
|
|
|
translation = np.asarray(translation, dtype=np.float64)
|
2015-04-22 00:50:03 -05:00
|
|
|
cell.translation = translation
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2017-02-17 15:21:42 -06:00
|
|
|
if 'rotation' in group:
|
|
|
|
|
rotation = group['rotation'][...]
|
2014-11-25 21:37:02 -05:00
|
|
|
rotation = np.asarray(rotation, dtype=np.int)
|
2016-05-10 11:55:38 -05:00
|
|
|
cell._rotation = rotation
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2017-02-22 17:09:19 -06:00
|
|
|
elif fill_type == 'material':
|
2017-02-17 15:21:42 -06:00
|
|
|
cell.temperature = group['temperature'][...]
|
2014-11-25 21:37:02 -05:00
|
|
|
|
|
|
|
|
# Store Cell fill information for after Universe/Lattice creation
|
2017-02-17 15:21:42 -06:00
|
|
|
cell_fills[cell.id] = (fill_type, fill)
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2015-09-26 19:52:07 +07:00
|
|
|
# Generate Region object given infix expression
|
|
|
|
|
if region:
|
2017-05-04 14:58:30 -04:00
|
|
|
cell.region = Region.from_expression(region, self._fast_surfaces)
|
2014-11-25 21:37:02 -05:00
|
|
|
|
|
|
|
|
# Add the Cell to the global dictionary of all Cells
|
2017-05-04 14:58:30 -04:00
|
|
|
self._fast_cells[cell.id] = cell
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2017-03-29 17:30:18 -04:00
|
|
|
return cell_fills
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2017-03-29 17:30:18 -04:00
|
|
|
def _read_universes(self):
|
2017-02-22 17:00:25 -06:00
|
|
|
for group in self._f['geometry/universes'].values():
|
2017-05-04 14:58:30 -04:00
|
|
|
universe = openmc.Universe.from_hdf5(group, self._fast_cells)
|
|
|
|
|
self._fast_universes[universe.id] = universe
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2017-03-29 17:30:18 -04:00
|
|
|
def _read_lattices(self):
|
2017-02-22 17:00:25 -06:00
|
|
|
for group in self._f['geometry/lattices'].values():
|
2017-05-04 14:58:30 -04:00
|
|
|
lattice = openmc.Lattice.from_hdf5(group, self._fast_universes)
|
|
|
|
|
self._fast_lattices[lattice.id] = lattice
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2017-03-29 17:30:18 -04:00
|
|
|
def _finalize_geometry(self, cell_fills):
|
2017-02-22 17:00:25 -06:00
|
|
|
|
2017-03-06 19:53:09 -06:00
|
|
|
# Keep track of universes that are used as fills. That way, we can
|
|
|
|
|
# determine which universe is NOT used as a fill (and hence is the root
|
|
|
|
|
# universe)
|
|
|
|
|
fill_univ_ids = set()
|
|
|
|
|
|
2014-11-25 21:37:02 -05:00
|
|
|
# Iterate over all Cells and add fill Materials, Universes and Lattices
|
2017-02-17 15:21:42 -06:00
|
|
|
for cell_id, (fill_type, fill_id) in cell_fills.items():
|
2014-11-25 21:37:02 -05:00
|
|
|
# Retrieve the object corresponding to the fill type and ID
|
2017-02-22 17:09:19 -06:00
|
|
|
if fill_type == 'material':
|
2016-01-09 23:02:29 -05:00
|
|
|
if isinstance(fill_id, Iterable):
|
2017-05-04 14:58:30 -04:00
|
|
|
fill = [self._fast_materials[mat] if mat > 0 else None
|
2016-01-09 23:02:29 -05:00
|
|
|
for mat in fill_id]
|
2014-11-25 21:37:02 -05:00
|
|
|
else:
|
2017-05-04 14:58:30 -04:00
|
|
|
fill = self._fast_materials[fill_id] if fill_id > 0 else None
|
2014-11-25 21:37:02 -05:00
|
|
|
elif fill_type == 'universe':
|
2017-05-04 14:58:30 -04:00
|
|
|
fill = self._fast_universes[fill_id]
|
2017-03-06 19:53:09 -06:00
|
|
|
fill_univ_ids.add(fill_id)
|
2014-11-25 21:37:02 -05:00
|
|
|
else:
|
2017-05-04 14:58:30 -04:00
|
|
|
fill = self._fast_lattices[fill_id]
|
2017-03-06 19:53:09 -06:00
|
|
|
for idx in fill._natural_indices:
|
|
|
|
|
univ = fill.get_universe(idx)
|
|
|
|
|
fill_univ_ids.add(univ.id)
|
2017-03-10 07:13:38 -06:00
|
|
|
if fill.outer is not None:
|
|
|
|
|
fill_univ_ids.add(fill.outer.id)
|
2014-11-25 21:37:02 -05:00
|
|
|
|
|
|
|
|
# Set the fill for the Cell
|
2017-05-04 14:58:30 -04:00
|
|
|
self._fast_cells[cell_id].fill = fill
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2017-03-06 19:53:09 -06:00
|
|
|
# Determine root universe for geometry
|
2017-05-04 14:58:30 -04:00
|
|
|
non_fill = set(self._fast_universes.keys()) - fill_univ_ids
|
2017-03-06 19:53:09 -06:00
|
|
|
|
2017-05-04 14:58:30 -04:00
|
|
|
self.geometry.root_universe = self._fast_universes[non_fill.pop()]
|
2014-11-25 21:37:02 -05:00
|
|
|
|
2016-08-01 07:02:16 -05:00
|
|
|
def add_volume_information(self, volume_calc):
|
|
|
|
|
"""Add volume information to the geometry within the summary file
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
|
volume_calc : openmc.VolumeCalculation
|
|
|
|
|
Results from a stochastic volume calculation
|
|
|
|
|
|
|
|
|
|
"""
|
2017-02-17 15:21:42 -06:00
|
|
|
self.geometry.add_volume_information(volume_calc)
|