Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into dagmc_decoupling
Browse files Browse the repository at this point in the history
  • Loading branch information
bam241 committed Oct 11, 2024
2 parents dae5527 + fc3de1c commit 182d991
Show file tree
Hide file tree
Showing 57 changed files with 749 additions and 232 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ jobs:

- name: Environment Variables
run: |
echo "DAGMC_ROOT=$HOME/DAGMC"
echo "OPENMC_CROSS_SECTIONS=$HOME/nndc_hdf5/cross_sections.xml" >> $GITHUB_ENV
echo "OPENMC_ENDF_DATA=$HOME/endf-b-vii.1" >> $GITHUB_ENV
Expand Down Expand Up @@ -131,6 +130,11 @@ jobs:
echo "$HOME/NJOY2016/build" >> $GITHUB_PATH
$GITHUB_WORKSPACE/tools/ci/gha-install.sh
- name: display-config
shell: bash
run: |
openmc -v
- name: cache-xs
uses: actions/cache@v4
with:
Expand Down
13 changes: 8 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,14 @@ endif()
if(OPENMC_USE_DAGMC)
target_compile_definitions(libopenmc PRIVATE DAGMC)
target_link_libraries(libopenmc dagmc-shared)

if(OPENMC_USE_UWUW)
target_compile_definitions(libopenmc PRIVATE OPENMC_UWUW)
target_link_libraries(libopenmc uwuw-shared)
endif()
elseif(OPENMC_USE_UWUW)
set(OPENMC_USE_UWUW OFF)
message(FATAL_ERROR "DAGMC must be enabled when UWUW is enabled.")
endif()

if(OPENMC_USE_LIBMESH)
Expand Down Expand Up @@ -546,11 +554,6 @@ if(OPENMC_USE_NCRYSTAL)
target_link_libraries(libopenmc NCrystal::NCrystal)
endif()

if (OPENMC_USE_UWUW)
target_compile_definitions(libopenmc PRIVATE UWUW)
target_link_libraries(libopenmc uwuw-shared)
endif()

#===============================================================================
# Log build info that this executable can report later
#===============================================================================
Expand Down
4 changes: 2 additions & 2 deletions cmake/Modules/FindLIBMESH.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ if(DEFINED ENV{METHOD})
endif()

find_package(PkgConfig REQUIRED)
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${LIBMESH_PC}")
set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH True)

set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH TRUE)
pkg_check_modules(LIBMESH REQUIRED ${LIBMESH_PC_FILE}>=1.7.0 IMPORTED_TARGET)
pkg_get_variable(LIBMESH_PREFIX ${LIBMESH_PC_FILE} prefix)
6 changes: 3 additions & 3 deletions cmake/OpenMCConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ if(@OPENMC_USE_MCPL@)
find_package(MCPL REQUIRED)
endif()

if(@OPENMC_USE_UWUW@)
find_package(UWUW REQUIRED)
endif()
if(@OPENMC_USE_UWUW@ AND NOT ${DAGMC_BUILD_UWUW})
message(FATAL_ERROR "UWUW is enabled in OpenMC but the DAGMC installation discovered was not configured with UWUW.")
endif()
1 change: 1 addition & 0 deletions docs/source/pythonapi/model.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Composite Surfaces
:nosignatures:
:template: myclass.rst

openmc.model.ConicalFrustum
openmc.model.CruciformPrism
openmc.model.CylinderSector
openmc.model.HexagonalPrism
Expand Down
25 changes: 17 additions & 8 deletions docs/source/usersguide/geometry.rst
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ applied as universes in the OpenMC geometry file. A geometry represented
entirely by a DAGMC geometry will contain only the DAGMC universe. Using a
:class:`openmc.DAGMCUniverse` looks like the following::

dag_univ = openmc.DAGMCUniverse(filename='dagmc.h5m')
dag_univ = openmc.DAGMCUniverse('dagmc.h5m')
geometry = openmc.Geometry(dag_univ)
geometry.export_to_xml()

Expand All @@ -495,13 +495,22 @@ It is important in these cases to understand the DAGMC model's position
with respect to the CSG geometry. DAGMC geometries can be plotted with
OpenMC to verify that the model matches one's expectations.

**Note:** DAGMC geometries used in OpenMC are currently required to be clean,
meaning that all surfaces have been `imprinted and merged
<https://svalinn.github.io/DAGMC/usersguide/cubit_basics.html>`_ successfully
and that the model is `watertight
<https://svalinn.github.io/DAGMC/usersguide/tools.html#make-watertight>`_.
Future implementations of DAGMC geometry will support small volume overlaps and
un-merged surfaces.
By default, when you specify a .h5m file for a :class:`~openmc.DAGMCUniverse`
instance, it will store the absolute path to the .h5m file. If you prefer to
store the relative path, you can set the ``'resolve_paths'`` configuration
variable::

openmc.config['resolve_paths'] = False
dag_univ = openmc.DAGMCUniverse('dagmc.h5m')

.. note::
DAGMC geometries used in OpenMC are currently required to be clean,
meaning that all surfaces have been `imprinted and merged
<https://svalinn.github.io/DAGMC/usersguide/cubit_basics.html>`_ successfully
and that the model is `watertight
<https://svalinn.github.io/DAGMC/usersguide/tools.html#make-watertight>`_.
Future implementations of DAGMC geometry will support small volume overlaps and
un-merged surfaces.

Cell, Surface, and Material IDs
-------------------------------
Expand Down
27 changes: 24 additions & 3 deletions openmc/config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from collections.abc import MutableMapping
from contextlib import contextmanager
import os
from pathlib import Path
import warnings
Expand All @@ -11,7 +12,7 @@

class _Config(MutableMapping):
def __init__(self, data=()):
self._mapping = {}
self._mapping = {'resolve_paths': True}
self.update(data)

def __getitem__(self, key):
Expand Down Expand Up @@ -42,10 +43,12 @@ def __setitem__(self, key, value):
# Reset photon source data since it relies on chain file
_DECAY_PHOTON_ENERGY.clear()
_DECAY_ENERGY.clear()
elif key == 'resolve_paths':
self._mapping[key] = value
else:
raise KeyError(f'Unrecognized config key: {key}. Acceptable keys '
'are "cross_sections", "mg_cross_sections" and '
'"chain_file"')
'are "cross_sections", "mg_cross_sections", '
'"chain_file", and "resolve_paths".')

def __iter__(self):
return iter(self._mapping)
Expand All @@ -61,6 +64,24 @@ def _set_path(self, key, value):
if not p.exists():
warnings.warn(f"'{value}' does not exist.")

@contextmanager
def patch(self, key, value):
"""Temporarily change a value in the configuration.
Parameters
----------
key : str
Key to change
value : object
New value
"""
previous_value = self.get(key)
self[key] = value
yield
if previous_value is None:
del self[key]
else:
self[key] = previous_value

def _default_config():
"""Return default configuration"""
Expand Down
15 changes: 7 additions & 8 deletions openmc/dagmc.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ class DAGMCUniverse(openmc.UniverseBase):
material name is found in the DAGMC file, the material will be replaced
with the openmc.Material object in the value.
"""

def __init__(self,
filename,
filename: cv.PathLike,
universe_id=None,
name='',
auto_geom_ids=False,
Expand Down Expand Up @@ -179,9 +179,9 @@ def add_material_override(self, mat_name=None, cell_id=None, overrides=None):
self.material_overrides[mat_name] = overrides

@filename.setter
def filename(self, val):
cv.check_type('DAGMC filename', val, (Path, str))
self._filename = val
def filename(self, val: cv.PathLike):
cv.check_type('DAGMC filename', val, cv.PathLike)
self._filename = input_path(val)

@property
def auto_geom_ids(self):
Expand Down Expand Up @@ -241,8 +241,7 @@ def _n_geom_elements(self, geom_type):
def decode_str_tag(tag_val):
return tag_val.tobytes().decode().replace('\x00', '')

dagmc_filepath = Path(self.filename).resolve()
with h5py.File(dagmc_filepath) as dagmc_file:
with h5py.File(self.filename) as dagmc_file:
category_data = dagmc_file['tstt/tags/CATEGORY/values']
category_strs = map(decode_str_tag, category_data)
n = sum([v == geom_type.capitalize() for v in category_strs])
Expand Down Expand Up @@ -580,7 +579,7 @@ def boundingbox(self):
warnings.warn("Bounding box is not available for cells in a DAGMC "
"universe", Warning)
return BoundingBox.infinite()

def get_all_cells(self, memo=None):
warnings.warn("get_all_cells is not available for cells in a DAGMC "
"universe", Warning)
Expand Down
110 changes: 69 additions & 41 deletions openmc/data/effective_dose/dose.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,61 @@

import numpy as np

_FILES = (
('electron', 'electrons.txt'),
('helium', 'helium_ions.txt'),
('mu-', 'negative_muons.txt'),
('pi-', 'negative_pions.txt'),
('neutron', 'neutrons.txt'),
('photon', 'photons.txt'),
('photon kerma', 'photons_kerma.txt'),
('mu+', 'positive_muons.txt'),
('pi+', 'positive_pions.txt'),
('positron', 'positrons.txt'),
('proton', 'protons.txt')
)

_DOSE_ICRP116 = {}


def _load_dose_icrp116():
"""Load effective dose tables from text files"""
for particle, filename in _FILES:
path = Path(__file__).parent / filename
data = np.loadtxt(path, skiprows=3, encoding='utf-8')
data[:, 0] *= 1e6 # Change energies to eV
_DOSE_ICRP116[particle] = data


def dose_coefficients(particle, geometry='AP'):
"""Return effective dose conversion coefficients from ICRP-116
This function provides fluence (and air kerma) to effective dose conversion
coefficients for various types of external exposures based on values in
`ICRP Publication 116 <https://doi.org/10.1016/j.icrp.2011.10.001>`_.
Corrected values found in a correigendum are used rather than the values in
theoriginal report.
import openmc.checkvalue as cv

_FILES = {
('icrp74', 'neutron'): Path('icrp74') / 'neutrons.txt',
('icrp74', 'photon'): Path('icrp74') / 'photons.txt',
('icrp116', 'electron'): Path('icrp116') / 'electrons.txt',
('icrp116', 'helium'): Path('icrp116') / 'helium_ions.txt',
('icrp116', 'mu-'): Path('icrp116') / 'negative_muons.txt',
('icrp116', 'pi-'): Path('icrp116') / 'negative_pions.txt',
('icrp116', 'neutron'): Path('icrp116') / 'neutrons.txt',
('icrp116', 'photon'): Path('icrp116') / 'photons.txt',
('icrp116', 'photon kerma'): Path('icrp116') / 'photons_kerma.txt',
('icrp116', 'mu+'): Path('icrp116') / 'positive_muons.txt',
('icrp116', 'pi+'): Path('icrp116') / 'positive_pions.txt',
('icrp116', 'positron'): Path('icrp116') / 'positrons.txt',
('icrp116', 'proton'): Path('icrp116') / 'protons.txt',
}

_DOSE_TABLES = {}


def _load_dose_icrp(data_source: str, particle: str):
"""Load effective dose tables from text files.
Parameters
----------
data_source : {'icrp74', 'icrp116'}
The dose conversion data source to use
particle : {'neutron', 'photon', 'photon kerma', 'electron', 'positron'}
Incident particle
"""
path = Path(__file__).parent / _FILES[data_source, particle]
data = np.loadtxt(path, skiprows=3, encoding='utf-8')
data[:, 0] *= 1e6 # Change energies to eV
_DOSE_TABLES[data_source, particle] = data


def dose_coefficients(particle, geometry='AP', data_source='icrp116'):
"""Return effective dose conversion coefficients.
This function provides fluence (and air kerma) to effective or ambient dose
(H*(10)) conversion coefficients for various types of external exposures
based on values in ICRP publications. Corrected values found in a
corrigendum are used rather than the values in the original report.
Available libraries include `ICRP Publication 74
<https://doi.org/10.1016/S0146-6453(96)90010-X>` and `ICRP Publication 116
<https://doi.org/10.1016/j.icrp.2011.10.001>`.
For ICRP 74 data, the photon effective dose per fluence is determined by
multiplying the air kerma per fluence values (Table A.1) by the effective
dose per air kerma (Table A.17). The neutron effective dose per fluence is
found in Table A.41. For ICRP 116 data, the photon effective dose per
fluence is found in Table A.1 and the neutron effective dose per fluence is
found in Table A.5.
Parameters
----------
Expand All @@ -44,6 +65,8 @@ def dose_coefficients(particle, geometry='AP'):
geometry : {'AP', 'PA', 'LLAT', 'RLAT', 'ROT', 'ISO'}
Irradiation geometry assumed. Refer to ICRP-116 (Section 3.2) for the
meaning of the options here.
data_source : {'icrp74', 'icrp116'}
The data source for the effective dose conversion coefficients.
Returns
-------
Expand All @@ -54,19 +77,24 @@ def dose_coefficients(particle, geometry='AP'):
'photon kerma', the coefficients are given in [Sv/Gy].
"""
if not _DOSE_ICRP116:
_load_dose_icrp116()

cv.check_value('geometry', geometry, {'AP', 'PA', 'LLAT', 'RLAT', 'ROT', 'ISO'})
cv.check_value('data_source', data_source, {'icrp74', 'icrp116'})

if (data_source, particle) not in _FILES:
raise ValueError(f"{particle} has no dose data in data source {data_source}.")
elif (data_source, particle) not in _DOSE_TABLES:
_load_dose_icrp(data_source, particle)

# Get all data for selected particle
data = _DOSE_ICRP116.get(particle)
if data is None:
raise ValueError(f"{particle} has no effective dose data")
data = _DOSE_TABLES[data_source, particle]

# Determine index for selected geometry
if particle in ('neutron', 'photon', 'proton', 'photon kerma'):
index = ('AP', 'PA', 'LLAT', 'RLAT', 'ROT', 'ISO').index(geometry)
columns = ('AP', 'PA', 'LLAT', 'RLAT', 'ROT', 'ISO')
else:
index = ('AP', 'PA', 'ISO').index(geometry)
columns = ('AP', 'PA', 'ISO')
index = columns.index(geometry)

# Pull out energy and dose from table
energy = data[:, 0].copy()
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 182d991

Please sign in to comment.