mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 21:55:41 -04:00
Merge pull request #1538 from paulromano/pullrequestinc-part3
Address review from PullRequest Inc. (Part 3)
This commit is contained in:
commit
d2cfe1e6a1
60 changed files with 517 additions and 609 deletions
|
|
@ -1,13 +1,12 @@
|
|||
import sys
|
||||
import copy
|
||||
from collections.abc import Iterable
|
||||
import copy
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
import openmc
|
||||
from openmc.filter import _FILTER_TYPES
|
||||
import openmc.checkvalue as cv
|
||||
from .filter import _FILTER_TYPES
|
||||
|
||||
|
||||
# Acceptable tally arithmetic binary operations
|
||||
|
|
|
|||
|
|
@ -4,18 +4,16 @@ from copy import deepcopy
|
|||
from math import cos, sin, pi
|
||||
from numbers import Real
|
||||
from xml.etree import ElementTree as ET
|
||||
from uncertainties import UFloat
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
from uncertainties import UFloat
|
||||
|
||||
import openmc
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.surface import Halfspace
|
||||
from openmc.region import Region, Intersection, Complement
|
||||
from openmc._xml import get_text
|
||||
from ._xml import get_text
|
||||
from .mixin import IDManagerMixin
|
||||
from .region import Region, Complement
|
||||
from .surface import Halfspace
|
||||
|
||||
|
||||
class Cell(IDManagerMixin):
|
||||
|
|
|
|||
|
|
@ -10,22 +10,21 @@ References
|
|||
|
||||
"""
|
||||
|
||||
from contextlib import contextmanager
|
||||
from collections.abc import Iterable, Mapping
|
||||
from contextlib import contextmanager
|
||||
from numbers import Real, Integral
|
||||
import sys
|
||||
import time
|
||||
from ctypes import c_int
|
||||
import warnings
|
||||
|
||||
import h5py
|
||||
import numpy as np
|
||||
from scipy import sparse
|
||||
import h5py
|
||||
|
||||
import openmc.lib
|
||||
from openmc.checkvalue import (check_type, check_length, check_value,
|
||||
check_greater_than, check_less_than)
|
||||
from openmc.exceptions import OpenMCError
|
||||
from .checkvalue import (check_type, check_length, check_value,
|
||||
check_greater_than, check_less_than)
|
||||
from .exceptions import OpenMCError
|
||||
|
||||
# See if mpi4py module can be imported, define have_mpi global variable
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -17,15 +17,14 @@ generates ACE-format cross sections.
|
|||
|
||||
from collections import OrderedDict
|
||||
import enum
|
||||
from pathlib import PurePath, Path
|
||||
from pathlib import Path
|
||||
import struct
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
from openmc.mixin import EqualityMixin
|
||||
import openmc.checkvalue as cv
|
||||
from .data import ATOMIC_SYMBOL, gnd_name
|
||||
from openmc.mixin import EqualityMixin
|
||||
from .data import ATOMIC_SYMBOL, gnd_name, EV_PER_MEV, K_BOLTZMANN
|
||||
from .endf import ENDF_FLOAT_RE
|
||||
|
||||
|
||||
|
|
@ -106,66 +105,59 @@ def ascii_to_binary(ascii_file, binary_file):
|
|||
|
||||
"""
|
||||
|
||||
# Open ASCII file
|
||||
ascii = open(str(ascii_file), 'r')
|
||||
# Read data from ASCII file
|
||||
with open(str(ascii_file), 'r') as ascii_file:
|
||||
lines = ascii_file.readlines()
|
||||
|
||||
# Set default record length
|
||||
record_length = 4096
|
||||
|
||||
# Read data from ASCII file
|
||||
lines = ascii.readlines()
|
||||
ascii.close()
|
||||
|
||||
# Open binary file
|
||||
binary = open(str(binary_file), 'wb')
|
||||
with open(str(binary_file), 'wb') as binary_file:
|
||||
idx = 0
|
||||
while idx < len(lines):
|
||||
# check if it's a > 2.0.0 version header
|
||||
if lines[idx].split()[0][1] == '.':
|
||||
if lines[idx + 1].split()[3] == '3':
|
||||
idx = idx + 3
|
||||
else:
|
||||
raise NotImplementedError('Only backwards compatible ACE'
|
||||
'headers currently supported')
|
||||
# Read/write header block
|
||||
hz = lines[idx][:10].encode()
|
||||
aw0 = float(lines[idx][10:22])
|
||||
tz = float(lines[idx][22:34])
|
||||
hd = lines[idx][35:45].encode()
|
||||
hk = lines[idx + 1][:70].encode()
|
||||
hm = lines[idx + 1][70:80].encode()
|
||||
binary_file.write(struct.pack(str('=10sdd10s70s10s'),
|
||||
hz, aw0, tz, hd, hk, hm))
|
||||
|
||||
idx = 0
|
||||
# Read/write IZ/AW pairs
|
||||
data = ' '.join(lines[idx + 2:idx + 6]).split()
|
||||
iz = np.array(data[::2], dtype=int)
|
||||
aw = np.array(data[1::2], dtype=float)
|
||||
izaw = [item for sublist in zip(iz, aw) for item in sublist]
|
||||
binary_file.write(struct.pack(str('=' + 16*'id'), *izaw))
|
||||
|
||||
while idx < len(lines):
|
||||
# check if it's a > 2.0.0 version header
|
||||
if lines[idx].split()[0][1] == '.':
|
||||
if lines[idx + 1].split()[3] == '3':
|
||||
idx = idx + 3
|
||||
else:
|
||||
raise NotImplementedError('Only backwards compatible ACE'
|
||||
'headers currently supported')
|
||||
# Read/write header block
|
||||
hz = lines[idx][:10].encode('UTF-8')
|
||||
aw0 = float(lines[idx][10:22])
|
||||
tz = float(lines[idx][22:34])
|
||||
hd = lines[idx][35:45].encode('UTF-8')
|
||||
hk = lines[idx + 1][:70].encode('UTF-8')
|
||||
hm = lines[idx + 1][70:80].encode('UTF-8')
|
||||
binary.write(struct.pack(str('=10sdd10s70s10s'), hz, aw0, tz, hd, hk, hm))
|
||||
# Read/write NXS and JXS arrays. Null bytes are added at the end so
|
||||
# that XSS will start at the second record
|
||||
nxs = [int(x) for x in ' '.join(lines[idx + 6:idx + 8]).split()]
|
||||
jxs = [int(x) for x in ' '.join(lines[idx + 8:idx + 12]).split()]
|
||||
binary_file.write(struct.pack(str('=16i32i{}x'.format(record_length - 500)),
|
||||
*(nxs + jxs)))
|
||||
|
||||
# Read/write IZ/AW pairs
|
||||
data = ' '.join(lines[idx + 2:idx + 6]).split()
|
||||
iz = list(map(int, data[::2]))
|
||||
aw = list(map(float, data[1::2]))
|
||||
izaw = [item for sublist in zip(iz, aw) for item in sublist]
|
||||
binary.write(struct.pack(str('=' + 16*'id'), *izaw))
|
||||
# Read/write XSS array. Null bytes are added to form a complete record
|
||||
# at the end of the file
|
||||
n_lines = (nxs[0] + 3)//4
|
||||
start = idx + _ACE_HEADER_SIZE
|
||||
xss = np.fromstring(' '.join(lines[start:start + n_lines]), sep=' ')
|
||||
extra_bytes = record_length - ((len(xss)*8 - 1) % record_length + 1)
|
||||
binary_file.write(struct.pack(str('={}d{}x'.format(
|
||||
nxs[0], extra_bytes)), *xss))
|
||||
|
||||
# Read/write NXS and JXS arrays. Null bytes are added at the end so
|
||||
# that XSS will start at the second record
|
||||
nxs = list(map(int, ' '.join(lines[idx + 6:idx + 8]).split()))
|
||||
jxs = list(map(int, ' '.join(lines[idx + 8:idx + 12]).split()))
|
||||
binary.write(struct.pack(str('=16i32i{0}x'.format(record_length - 500)),
|
||||
*(nxs + jxs)))
|
||||
|
||||
# Read/write XSS array. Null bytes are added to form a complete record
|
||||
# at the end of the file
|
||||
n_lines = (nxs[0] + 3)//4
|
||||
xss = list(map(float, ' '.join(lines[
|
||||
idx + 12:idx + 12 + n_lines]).split()))
|
||||
extra_bytes = record_length - ((len(xss)*8 - 1) % record_length + 1)
|
||||
binary.write(struct.pack(str('={0}d{1}x'.format(nxs[0], extra_bytes)),
|
||||
*xss))
|
||||
|
||||
# Advance to next table in file
|
||||
idx += 12 + n_lines
|
||||
|
||||
# Close binary file
|
||||
binary.close()
|
||||
# Advance to next table in file
|
||||
idx += _ACE_HEADER_SIZE + n_lines
|
||||
|
||||
|
||||
def get_table(filename, name=None):
|
||||
|
|
@ -197,6 +189,11 @@ def get_table(filename, name=None):
|
|||
.format(name))
|
||||
|
||||
|
||||
# The beginning of an ASCII ACE file consists of 12 lines that include the name,
|
||||
# atomic weight ratio, iz/aw pairs, and the NXS and JXS arrays
|
||||
_ACE_HEADER_SIZE = 12
|
||||
|
||||
|
||||
class Library(EqualityMixin):
|
||||
"""A Library objects represents an ACE-formatted file which may contain
|
||||
multiple tables with data.
|
||||
|
|
@ -298,15 +295,15 @@ class Library(EqualityMixin):
|
|||
continue
|
||||
|
||||
if verbose:
|
||||
kelvin = round(temperature * 1e6 / 8.617342e-5)
|
||||
print("Loading nuclide {0} at {1} K".format(name, kelvin))
|
||||
kelvin = round(temperature * EV_PER_MEV / K_BOLTZMANN)
|
||||
print("Loading nuclide {} at {} K".format(name, kelvin))
|
||||
|
||||
# Read JXS
|
||||
jxs = list(struct.unpack(str('=32i'), ace_file.read(128)))
|
||||
|
||||
# Read XSS
|
||||
ace_file.seek(start_position + recl_length)
|
||||
xss = list(struct.unpack(str('={0}d'.format(length)),
|
||||
xss = list(struct.unpack(str('={}d'.format(length)),
|
||||
ace_file.read(length*8)))
|
||||
|
||||
# Insert zeros at beginning of NXS, JXS, and XSS arrays so that the
|
||||
|
|
@ -346,7 +343,7 @@ class Library(EqualityMixin):
|
|||
|
||||
tables_seen = set()
|
||||
|
||||
lines = [ace_file.readline() for i in range(13)]
|
||||
lines = [ace_file.readline() for i in range(_ACE_HEADER_SIZE + 1)]
|
||||
|
||||
while len(lines) != 0 and lines[0].strip() != '':
|
||||
# Read name of table, atomic mass ratio, and temperature. If first
|
||||
|
|
@ -376,6 +373,8 @@ class Library(EqualityMixin):
|
|||
datastr = '0 ' + ' '.join(lines[6:8])
|
||||
nxs = np.fromstring(datastr, sep=' ', dtype=int)
|
||||
|
||||
# Detemrine number of lines in the XSS array; each line consists of
|
||||
# four values
|
||||
n_lines = (nxs[1] + 3)//4
|
||||
|
||||
# Ensure that we have more tables to read in
|
||||
|
|
@ -387,23 +386,23 @@ class Library(EqualityMixin):
|
|||
if (table_names is not None) and (name not in table_names):
|
||||
for _ in range(n_lines - 1):
|
||||
ace_file.readline()
|
||||
lines = [ace_file.readline() for i in range(13)]
|
||||
lines = [ace_file.readline() for i in range(_ACE_HEADER_SIZE + 1)]
|
||||
continue
|
||||
|
||||
# Read lines corresponding to this table
|
||||
lines += [ace_file.readline() for i in range(n_lines - 1)]
|
||||
|
||||
if verbose:
|
||||
kelvin = round(temperature * 1e6 / 8.617342e-5)
|
||||
print("Loading nuclide {0} at {1} K".format(name, kelvin))
|
||||
kelvin = round(temperature * EV_PER_MEV / K_BOLTZMANN)
|
||||
print("Loading nuclide {} at {} K".format(name, kelvin))
|
||||
|
||||
# Insert zeros at beginning of NXS, JXS, and XSS arrays so that the
|
||||
# indexing will be the same as Fortran. This makes it easier to
|
||||
# follow the ACE format specification.
|
||||
datastr = '0 ' + ' '.join(lines[8:12])
|
||||
datastr = '0 ' + ' '.join(lines[8:_ACE_HEADER_SIZE])
|
||||
jxs = np.fromstring(datastr, dtype=int, sep=' ')
|
||||
|
||||
datastr = '0.0 ' + ''.join(lines[12:12+n_lines])
|
||||
datastr = '0.0 ' + ''.join(lines[_ACE_HEADER_SIZE:_ACE_HEADER_SIZE + n_lines])
|
||||
xss = np.fromstring(datastr, sep=' ')
|
||||
|
||||
# When NJOY writes an ACE file, any values less than 1e-100 actually
|
||||
|
|
@ -422,7 +421,7 @@ class Library(EqualityMixin):
|
|||
self.tables.append(table)
|
||||
|
||||
# Read all data blocks
|
||||
lines = [ace_file.readline() for i in range(13)]
|
||||
lines = [ace_file.readline() for i in range(_ACE_HEADER_SIZE + 1)]
|
||||
|
||||
|
||||
class TableType(enum.Enum):
|
||||
|
|
|
|||
|
|
@ -179,11 +179,12 @@ class AngleDistribution(EqualityMixin):
|
|||
for i in range(n_energies):
|
||||
if lc[i] > 0:
|
||||
# Equiprobable 32 bin distribution
|
||||
n_bins = 32
|
||||
idx = location_dist + abs(lc[i]) - 1
|
||||
cos = ace.xss[idx:idx + 33]
|
||||
pdf = np.zeros(33)
|
||||
pdf[:32] = 1.0/(32.0*np.diff(cos))
|
||||
cdf = np.linspace(0.0, 1.0, 33)
|
||||
cos = ace.xss[idx:idx + n_bins + 1]
|
||||
pdf = np.zeros(n_bins + 1)
|
||||
pdf[:n_bins] = 1.0/(n_bins*np.diff(cos))
|
||||
cdf = np.linspace(0.0, 1.0, n_bins + 1)
|
||||
|
||||
mu_i = Tabular(cos, pdf, 'histogram', ignore_negative=True)
|
||||
mu_i.c = cdf
|
||||
|
|
@ -192,6 +193,7 @@ class AngleDistribution(EqualityMixin):
|
|||
idx = location_dist + abs(lc[i]) - 1
|
||||
intt = int(ace.xss[idx])
|
||||
n_points = int(ace.xss[idx + 1])
|
||||
# Data is given as rows of (values, PDF, CDF)
|
||||
data = ace.xss[idx + 2:idx + 2 + 3*n_points]
|
||||
data.shape = (3, n_points)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from abc import ABCMeta, abstractmethod
|
||||
from io import StringIO
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
import openmc.data
|
||||
from openmc.mixin import EqualityMixin
|
||||
|
||||
|
||||
class AngleEnergy(EqualityMixin, metaclass=ABCMeta):
|
||||
class AngleEnergy(EqualityMixin, ABC):
|
||||
"""Distribution in angle and energy of a secondary particle."""
|
||||
@abstractmethod
|
||||
def to_hdf5(self, group):
|
||||
|
|
|
|||
|
|
@ -163,6 +163,10 @@ class CorrelatedAngleEnergy(AngleEnergy):
|
|||
elif isinstance(d, Discrete):
|
||||
n_discrete_lines[i] = n
|
||||
interpolation[i] = 1
|
||||
else:
|
||||
raise ValueError(
|
||||
'Invalid univariate energy distribution as part of '
|
||||
'correlated angle-energy: {}'.format(d))
|
||||
eout[0, offset_e:offset_e+n] = d.x
|
||||
eout[1, offset_e:offset_e+n] = d.p
|
||||
eout[2, offset_e:offset_e+n] = d.c
|
||||
|
|
@ -345,10 +349,9 @@ class CorrelatedAngleEnergy(AngleEnergy):
|
|||
for i in range(n_energy_in):
|
||||
idx = ldis + loc_dist[i] - 1
|
||||
|
||||
# intt = interpolation scheme (1=hist, 2=lin-lin)
|
||||
INTTp = int(ace.xss[idx])
|
||||
intt = INTTp % 10
|
||||
n_discrete_lines = (INTTp - intt)//10
|
||||
# intt = interpolation scheme (1=hist, 2=lin-lin). When discrete
|
||||
# lines are present, the value given is 10*n_discrete_lines + intt
|
||||
n_discrete_lines, intt = divmod(int(ace.xss[idx]), 10)
|
||||
if intt not in (1, 2):
|
||||
warn("Interpolation scheme for continuous tabular distribution "
|
||||
"is not histogram or linear-linear.")
|
||||
|
|
|
|||
|
|
@ -177,8 +177,26 @@ ATOMIC_SYMBOL = {0: 'n', 1: 'H', 2: 'He', 3: 'Li', 4: 'Be', 5: 'B', 6: 'C',
|
|||
118: 'Og'}
|
||||
ATOMIC_NUMBER = {value: key for key, value in ATOMIC_SYMBOL.items()}
|
||||
|
||||
# Values here are from the Committee on Data for Science and Technology
|
||||
# (CODATA) 2014 recommendation (doi:10.1103/RevModPhys.88.035009).
|
||||
|
||||
# The value of the Boltzman constant in units of eV / K
|
||||
K_BOLTZMANN = 8.6173303e-5
|
||||
|
||||
# Unit conversions
|
||||
EV_PER_MEV = 1.0e6
|
||||
JOULE_PER_EV = 1.6021766208e-19
|
||||
|
||||
# Avogadro's constant
|
||||
AVOGADRO = 6.022140857e23
|
||||
|
||||
# Neutron mass in units of amu
|
||||
NEUTRON_MASS = 1.00866491588
|
||||
|
||||
# Used in atomic_mass function as a cache
|
||||
_ATOMIC_MASS = {}
|
||||
|
||||
# Regex for GND nuclide names (used in zam function)
|
||||
_GND_NAME_RE = re.compile(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)')
|
||||
|
||||
|
||||
|
|
@ -290,12 +308,14 @@ def water_density(temperature, pressure=0.1013):
|
|||
# but they only use 3 digits for their conversion to K.)
|
||||
if pressure > 100.0:
|
||||
warn("Results are not valid for pressures above 100 MPa.")
|
||||
if pressure < 0.0:
|
||||
warn("Results are not valid for pressures below zero.")
|
||||
elif pressure < 0.0:
|
||||
raise ValueError("Pressure must be positive.")
|
||||
if temperature < 273:
|
||||
warn("Results are not valid for temperatures below 273.15 K.")
|
||||
if temperature > 623.15:
|
||||
elif temperature > 623.15:
|
||||
warn("Results are not valid for temperatures above 623.15 K.")
|
||||
elif temperature <= 0.0:
|
||||
raise ValueError('Temperature must be positive.')
|
||||
|
||||
# IAPWS region 4 parameters
|
||||
n4 = [0.11670521452767e4, -0.72421316703206e6, -0.17073846940092e2,
|
||||
|
|
@ -410,20 +430,3 @@ def zam(name):
|
|||
|
||||
metastable = int(state[2:]) if state else 0
|
||||
return (ATOMIC_NUMBER[symbol], int(A), metastable)
|
||||
|
||||
|
||||
# Values here are from the Committee on Data for Science and Technology
|
||||
# (CODATA) 2014 recommendation (doi:10.1103/RevModPhys.88.035009).
|
||||
|
||||
# The value of the Boltzman constant in units of eV / K
|
||||
K_BOLTZMANN = 8.6173303e-5
|
||||
|
||||
# Unit conversions
|
||||
EV_PER_MEV = 1.0e6
|
||||
JOULE_PER_EV = 1.6021766208e-19
|
||||
|
||||
# Avogadro's constant
|
||||
AVOGADRO = 6.022140857e23
|
||||
|
||||
# Neutron mass in units of amu
|
||||
NEUTRON_MASS = 1.00866491588
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
from collections import namedtuple
|
||||
from collections.abc import Iterable
|
||||
from io import StringIO
|
||||
from math import log
|
||||
from numbers import Real
|
||||
import re
|
||||
from warnings import warn
|
||||
|
||||
import numpy as np
|
||||
from uncertainties import ufloat, unumpy, UFloat
|
||||
from uncertainties import ufloat, UFloat
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.mixin import EqualityMixin
|
||||
|
|
@ -142,12 +140,12 @@ class FissionProductYields(EqualityMixin):
|
|||
'isomeric_state': ev.target['isomeric_state']
|
||||
}
|
||||
|
||||
# Read independent yields
|
||||
# Read independent yields (MF=8, MT=454)
|
||||
if (8, 454) in ev.section:
|
||||
file_obj = StringIO(ev.section[8, 454])
|
||||
self.energies, self.independent = get_yields(file_obj)
|
||||
|
||||
# Read cumulative yields
|
||||
# Read cumulative yields (MF=8, MT=459)
|
||||
if (8, 459) in ev.section:
|
||||
file_obj = StringIO(ev.section[8, 459])
|
||||
energies, self.cumulative = get_yields(file_obj)
|
||||
|
|
@ -372,6 +370,7 @@ class Decay(EqualityMixin):
|
|||
|
||||
items, values = get_list_record(file_obj)
|
||||
spin = items[0]
|
||||
# ENDF-102 specifies that unknown spin should be reported as -77.777
|
||||
if spin == -77.777:
|
||||
self.nuclide['spin'] = None
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -7,19 +7,13 @@ http://www-nds.iaea.org/ndspub/documents/endf/endf102/endf102.pdf
|
|||
|
||||
"""
|
||||
import io
|
||||
import re
|
||||
import os
|
||||
from math import pi
|
||||
from pathlib import PurePath
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
import re
|
||||
|
||||
import numpy as np
|
||||
from numpy.polynomial.polynomial import Polynomial
|
||||
|
||||
from .data import ATOMIC_SYMBOL, gnd_name
|
||||
from .function import Tabulated1D, INTERPOLATION_SCHEME
|
||||
from openmc.stats.univariate import Uniform, Tabular, Legendre
|
||||
from .data import gnd_name
|
||||
from .function import Tabulated1D
|
||||
try:
|
||||
from ._endf import float_endf
|
||||
_CYTHON = True
|
||||
|
|
@ -397,8 +391,10 @@ class Evaluation:
|
|||
def __init__(self, filename_or_obj):
|
||||
if isinstance(filename_or_obj, (str, PurePath)):
|
||||
fh = open(str(filename_or_obj), 'r')
|
||||
need_to_close = True
|
||||
else:
|
||||
fh = filename_or_obj
|
||||
need_to_close = False
|
||||
self.section = {}
|
||||
self.info = {}
|
||||
self.target = {}
|
||||
|
|
@ -446,6 +442,9 @@ class Evaluation:
|
|||
section_data += line
|
||||
self.section[MF, MT] = section_data
|
||||
|
||||
if need_to_close:
|
||||
fh.close()
|
||||
|
||||
self._read_header()
|
||||
|
||||
def __repr__(self):
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
from abc import ABCMeta, abstractmethod
|
||||
from abc import ABC, abstractmethod
|
||||
from collections.abc import Iterable
|
||||
from numbers import Integral, Real
|
||||
from warnings import warn
|
||||
|
||||
import numpy as np
|
||||
|
||||
from .function import Tabulated1D, INTERPOLATION_SCHEME
|
||||
from openmc.stats.univariate import Univariate, Tabular, Discrete, Mixture
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.mixin import EqualityMixin
|
||||
from openmc.stats.univariate import Univariate, Tabular, Discrete, Mixture
|
||||
from .data import EV_PER_MEV
|
||||
from .endf import get_tab1_record, get_tab2_record
|
||||
from .function import Tabulated1D, INTERPOLATION_SCHEME
|
||||
|
||||
|
||||
class EnergyDistribution(EqualityMixin, metaclass=ABCMeta):
|
||||
class EnergyDistribution(EqualityMixin, ABC):
|
||||
"""Abstract superclass for all energy distributions."""
|
||||
def __init__(self):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -1,16 +1,12 @@
|
|||
from collections.abc import Callable
|
||||
from copy import deepcopy
|
||||
from io import StringIO
|
||||
import sys
|
||||
|
||||
import h5py
|
||||
import numpy as np
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.mixin import EqualityMixin
|
||||
from .data import EV_PER_MEV
|
||||
from .endf import get_cont_record, get_list_record, get_tab1_record, Evaluation
|
||||
from .function import Function1D, Tabulated1D, Polynomial, sum_functions
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.mixin import EqualityMixin
|
||||
|
||||
|
||||
_NAMES = (
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
from abc import ABCMeta, abstractmethod
|
||||
from abc import ABC, abstractmethod
|
||||
from collections.abc import Iterable, Callable
|
||||
from functools import reduce
|
||||
from itertools import zip_longest
|
||||
from numbers import Real, Integral
|
||||
from math import exp, log
|
||||
from numbers import Real, Integral
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc.data
|
||||
import openmc.checkvalue as cv
|
||||
import openmc.data
|
||||
from openmc.mixin import EqualityMixin
|
||||
from .data import EV_PER_MEV
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ def sum_functions(funcs):
|
|||
return Polynomial(coeffs)
|
||||
|
||||
|
||||
class Function1D(EqualityMixin, metaclass=ABCMeta):
|
||||
class Function1D(EqualityMixin, ABC):
|
||||
"""A function of one independent variable with HDF5 support."""
|
||||
@abstractmethod
|
||||
def __call__(self): pass
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from numbers import Real, Integral
|
|||
import numpy as np
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.stats import Tabular, Univariate, Discrete
|
||||
from openmc.stats import Tabular, Univariate
|
||||
from .angle_energy import AngleEnergy
|
||||
from .endf import get_tab2_record, get_tab1_record
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
from numbers import Integral, Real
|
||||
from numbers import Real
|
||||
from math import exp, erf, pi, sqrt
|
||||
|
||||
import h5py
|
||||
import numpy as np
|
||||
|
||||
from . import WMP_VERSION, WMP_VERSION_MAJOR
|
||||
from .data import K_BOLTZMANN
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.mixin import EqualityMixin
|
||||
from . import WMP_VERSION, WMP_VERSION_MAJOR
|
||||
from .data import K_BOLTZMANN
|
||||
|
||||
|
||||
# Constants that determine which value to access
|
||||
|
|
|
|||
|
|
@ -2,18 +2,17 @@ from collections import OrderedDict
|
|||
from collections.abc import Mapping, Callable
|
||||
from copy import deepcopy
|
||||
from io import StringIO
|
||||
from math import pi
|
||||
from numbers import Integral, Real
|
||||
from math import pi, sqrt
|
||||
import os
|
||||
|
||||
import h5py
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from scipy.interpolate import CubicSpline
|
||||
from scipy.integrate import quad
|
||||
|
||||
from openmc.mixin import EqualityMixin
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.mixin import EqualityMixin
|
||||
from . import HDF5_VERSION
|
||||
from .ace import Table, get_metadata, get_table
|
||||
from .data import ATOMIC_SYMBOL, EV_PER_MEV
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
from collections.abc import Iterable
|
||||
from io import StringIO
|
||||
from numbers import Real
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
from collections.abc import Iterable, Callable, MutableMapping
|
||||
from copy import deepcopy
|
||||
from numbers import Real, Integral
|
||||
from warnings import warn
|
||||
from io import StringIO
|
||||
from numbers import Real
|
||||
from warnings import warn
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
from collections import defaultdict
|
||||
from collections.abc import MutableSequence, Iterable
|
||||
import io
|
||||
|
||||
|
|
@ -6,6 +5,7 @@ import numpy as np
|
|||
from numpy.polynomial import Polynomial
|
||||
import pandas as pd
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
from .data import NEUTRON_MASS
|
||||
from .endf import get_head_record, get_cont_record, get_tab1_record, get_list_record
|
||||
try:
|
||||
|
|
@ -14,7 +14,6 @@ try:
|
|||
_reconstruct = True
|
||||
except ImportError:
|
||||
_reconstruct = False
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
|
||||
class Resonances:
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
An ndarray to store reaction rates with string, integer, or slice indexing.
|
||||
"""
|
||||
from collections import OrderedDict
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,9 @@ Contains results generation and saving capabilities.
|
|||
|
||||
from collections import OrderedDict
|
||||
import copy
|
||||
from warnings import warn
|
||||
|
||||
import numpy as np
|
||||
import h5py
|
||||
import numpy as np
|
||||
|
||||
from . import comm, have_mpi, MPI
|
||||
from .reaction_rates import ReactionRates
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
from collections import OrderedDict
|
||||
import re
|
||||
import os
|
||||
import re
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
from numbers import Real
|
||||
from openmc.data import NATURAL_ABUNDANCE, atomic_mass
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from abc import ABCMeta
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
import copy
|
||||
import hashlib
|
||||
from itertools import product
|
||||
from numbers import Real, Integral
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
from numbers import Integral, Real
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
from . import Filter
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,9 @@ from copy import deepcopy
|
|||
from pathlib import Path
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc
|
||||
import openmc._xml as xml
|
||||
from openmc.checkvalue import check_type
|
||||
from .checkvalue import check_type
|
||||
|
||||
|
||||
class Geometry:
|
||||
|
|
|
|||
|
|
@ -1,22 +1,21 @@
|
|||
from abc import ABCMeta
|
||||
from abc import ABC
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
from copy import deepcopy
|
||||
from math import sqrt, floor
|
||||
from numbers import Real
|
||||
import types
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import numpy as np
|
||||
import warnings
|
||||
import types
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
import openmc
|
||||
from openmc._xml import get_text
|
||||
from openmc.mixin import IDManagerMixin
|
||||
import openmc.checkvalue as cv
|
||||
from ._xml import get_text
|
||||
from .mixin import IDManagerMixin
|
||||
|
||||
|
||||
class Lattice(IDManagerMixin, metaclass=ABCMeta):
|
||||
class Lattice(IDManagerMixin, ABC):
|
||||
"""A repeating structure wherein each element is a universe.
|
||||
|
||||
Parameters
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ from ctypes import c_int, c_int32, c_double, c_char_p, POINTER
|
|||
from weakref import WeakValueDictionary
|
||||
|
||||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from openmc.exceptions import AllocationError, InvalidIDError
|
||||
from ..exceptions import AllocationError, InvalidIDError
|
||||
from . import _dll
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
import sys
|
||||
|
||||
from contextlib import contextmanager
|
||||
from ctypes import (CDLL, c_bool, c_int, c_int32, c_int64, c_double, c_char_p,
|
||||
from ctypes import (c_bool, c_int, c_int32, c_int64, c_double, c_char_p,
|
||||
c_char, POINTER, Structure, c_void_p, create_string_buffer)
|
||||
from warnings import warn
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from openmc.exceptions import AllocationError
|
||||
from . import _dll
|
||||
from .error import _error_handler
|
||||
import openmc.lib
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
from collections.abc import Mapping, Iterable
|
||||
from collections.abc import Mapping
|
||||
from ctypes import c_int, c_int32, c_double, POINTER
|
||||
from weakref import WeakValueDictionary
|
||||
|
||||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from openmc.exceptions import AllocationError, InvalidIDError
|
||||
from ..exceptions import AllocationError, InvalidIDError
|
||||
from . import _dll
|
||||
from .core import _FortranObjectWithID
|
||||
from .error import _error_handler
|
||||
from .material import Material
|
||||
|
||||
__all__ = ['RegularMesh', 'meshes']
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@ from collections.abc import Mapping
|
|||
from ctypes import c_int, c_char_p, POINTER, c_size_t
|
||||
from weakref import WeakValueDictionary
|
||||
|
||||
import numpy as np
|
||||
from numpy.ctypeslib import as_array
|
||||
|
||||
from openmc.exceptions import DataError, AllocationError
|
||||
from ..exceptions import DataError, AllocationError
|
||||
from . import _dll
|
||||
from .core import _FortranObject
|
||||
from .error import _error_handler
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
from ctypes import (c_int, c_int32, c_int64, c_double, c_char_p, c_bool,
|
||||
POINTER)
|
||||
from ctypes import c_int, c_int32, c_int64, c_double, c_char_p, c_bool
|
||||
|
||||
from . import _dll
|
||||
from .core import _DLLGlobal
|
||||
from .error import _error_handler
|
||||
|
||||
_RUN_MODES = {1: 'fixed source',
|
||||
2: 'eigenvalue',
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
from collections import OrderedDict, defaultdict, namedtuple, Counter
|
||||
from collections.abc import Iterable
|
||||
from copy import deepcopy
|
||||
from numbers import Real, Integral
|
||||
from numbers import Real
|
||||
from pathlib import Path
|
||||
import warnings
|
||||
import re
|
||||
import warnings
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import numpy as np
|
||||
|
|
@ -12,13 +12,13 @@ import numpy as np
|
|||
import openmc
|
||||
import openmc.data
|
||||
import openmc.checkvalue as cv
|
||||
from openmc._xml import clean_indentation
|
||||
from ._xml import clean_indentation
|
||||
from .mixin import IDManagerMixin
|
||||
|
||||
|
||||
# Units for density supported by OpenMC
|
||||
DENSITY_UNITS = ['g/cm3', 'g/cc', 'kg/m3', 'atom/b-cm', 'atom/cm3', 'sum',
|
||||
'macro']
|
||||
DENSITY_UNITS = ('g/cm3', 'g/cc', 'kg/m3', 'atom/b-cm', 'atom/cm3', 'sum',
|
||||
'macro')
|
||||
|
||||
|
||||
NuclideTuple = namedtuple('NuclideTuple', ['name', 'percent', 'percent_type'])
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
from abc import ABCMeta
|
||||
from abc import ABC
|
||||
from collections.abc import Iterable
|
||||
from numbers import Real, Integral
|
||||
from xml.etree import ElementTree as ET
|
||||
import sys
|
||||
import warnings
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
import openmc
|
||||
from openmc._xml import get_text
|
||||
from openmc.mixin import EqualityMixin, IDManagerMixin
|
||||
from ._xml import get_text
|
||||
from .mixin import IDManagerMixin
|
||||
from .surface import _BOUNDARY_TYPES
|
||||
|
||||
|
||||
class MeshBase(IDManagerMixin, metaclass=ABCMeta):
|
||||
class MeshBase(IDManagerMixin, ABC):
|
||||
"""A mesh that partitions geometry for tallying purposes.
|
||||
|
||||
Parameters
|
||||
|
|
@ -323,7 +323,7 @@ class RegularMesh(MeshBase):
|
|||
|
||||
return mesh
|
||||
|
||||
def build_cells(self, bc=['reflective'] * 6):
|
||||
def build_cells(self, bc=None):
|
||||
"""Generates a lattice of universes with the same dimensionality
|
||||
as the mesh object. The individual cells/universes produced
|
||||
will not have material definitions applied and so downstream code
|
||||
|
|
@ -331,12 +331,13 @@ class RegularMesh(MeshBase):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
bc : iterable of {'reflective', 'periodic', 'transmission', or 'vacuum'}
|
||||
bc : iterable of {'reflective', 'periodic', 'transmission', 'vacuum', or 'white'}
|
||||
Boundary conditions for each of the four faces of a rectangle
|
||||
(if aplying to a 2D mesh) or six faces of a parallelepiped
|
||||
(if applying to a 2D mesh) or six faces of a parallelepiped
|
||||
(if applying to a 3D mesh) provided in the following order:
|
||||
[x min, x max, y min, y max, z min, z max]. 2-D cells do not
|
||||
contain the z min and z max entries.
|
||||
contain the z min and z max entries. Defaults to 'reflective' for
|
||||
all faces.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -350,11 +351,12 @@ class RegularMesh(MeshBase):
|
|||
geometry.
|
||||
|
||||
"""
|
||||
|
||||
cv.check_length('bc', bc, length_min=4, length_max=6)
|
||||
if bc is None:
|
||||
bc = ['reflective'] * 6
|
||||
if len(bc) not in (4, 6):
|
||||
raise ValueError('Boundary condition must be of length 4 or 6')
|
||||
for entry in bc:
|
||||
cv.check_value('bc', entry, ['transmission', 'vacuum',
|
||||
'reflective', 'periodic'])
|
||||
cv.check_value('bc', entry, _BOUNDARY_TYPES)
|
||||
|
||||
n_dim = len(self.dimension)
|
||||
|
||||
|
|
@ -391,7 +393,7 @@ class RegularMesh(MeshBase):
|
|||
# We will concurrently build cells to assign to these universes
|
||||
cells = []
|
||||
universes = []
|
||||
for index in self.indices:
|
||||
for _ in self.indices:
|
||||
cells.append(openmc.Cell())
|
||||
universes.append(openmc.Universe())
|
||||
universes[-1].add_cell(cells[-1])
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from collections.abc import Iterable
|
||||
from numbers import Real
|
||||
import copy
|
||||
import sys
|
||||
from numbers import Real
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import sys
|
||||
import os
|
||||
import copy
|
||||
import pickle
|
||||
from numbers import Integral
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
import copy
|
||||
from numbers import Integral
|
||||
import os
|
||||
import pickle
|
||||
from warnings import warn
|
||||
|
||||
import numpy as np
|
||||
|
|
@ -12,7 +11,7 @@ import numpy as np
|
|||
import openmc
|
||||
import openmc.mgxs
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.tallies import ESTIMATOR_TYPES
|
||||
from ..tallies import ESTIMATOR_TYPES
|
||||
|
||||
|
||||
class Library:
|
||||
|
|
@ -864,11 +863,12 @@ class Library:
|
|||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
full_filename = os.path.join(directory, filename + '.pkl')
|
||||
full_filename = os.path.join(directory, '{}.pkl'.format(filename))
|
||||
full_filename = full_filename.replace(' ', '-')
|
||||
|
||||
# Load and return pickled Library object
|
||||
pickle.dump(self, open(full_filename, 'wb'))
|
||||
with open(full_filename, 'wb') as f:
|
||||
pickle.dump(self, f)
|
||||
|
||||
@staticmethod
|
||||
def load_from_file(filename='mgxs', directory='mgxs'):
|
||||
|
|
@ -903,7 +903,8 @@ class Library:
|
|||
full_filename = full_filename.replace(' ', '-')
|
||||
|
||||
# Load and return pickled Library object
|
||||
return pickle.load(open(full_filename, 'rb'))
|
||||
with open(full_filename, 'rb') as f:
|
||||
return pickle.load(f)
|
||||
|
||||
def get_xsdata(self, domain, xsdata_name, nuclide='total', xs_type='macro',
|
||||
subdomain=None):
|
||||
|
|
|
|||
|
|
@ -1,27 +1,25 @@
|
|||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
import copy
|
||||
import itertools
|
||||
from numbers import Integral
|
||||
import warnings
|
||||
import os
|
||||
import sys
|
||||
import copy
|
||||
from abc import ABCMeta
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc
|
||||
from openmc.mgxs import MGXS
|
||||
from openmc.mgxs.mgxs import _DOMAIN_TO_FILTER
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.mgxs import MGXS
|
||||
from .mgxs import _DOMAIN_TO_FILTER
|
||||
|
||||
|
||||
# Supported cross section types
|
||||
MDGXS_TYPES = ['delayed-nu-fission',
|
||||
'chi-delayed',
|
||||
'beta',
|
||||
'decay-rate',
|
||||
'delayed-nu-fission matrix']
|
||||
MDGXS_TYPES = (
|
||||
'delayed-nu-fission',
|
||||
'chi-delayed',
|
||||
'beta',
|
||||
'decay-rate',
|
||||
'delayed-nu-fission matrix'
|
||||
)
|
||||
|
||||
# Maximum number of delayed groups, from src/constants.F90
|
||||
MAX_DELAYED_GROUPS = 8
|
||||
|
|
@ -51,7 +49,7 @@ class MDGXS(MGXS):
|
|||
name : str, optional
|
||||
Name of the multi-group cross section. Used as a label to identify
|
||||
tallies in OpenMC 'tallies.xml' file.
|
||||
delayed_groups : list of int
|
||||
delayed_groups : list of int, optional
|
||||
Delayed groups to filter out the xs
|
||||
num_polar : Integral, optional
|
||||
Number of equi-width polar angle bins for angle discretization;
|
||||
|
|
@ -74,7 +72,7 @@ class MDGXS(MGXS):
|
|||
Domain type for spatial homogenization
|
||||
energy_groups : openmc.mgxs.EnergyGroups
|
||||
Energy group structure for energy condensation
|
||||
delayed_groups : list of int
|
||||
delayed_groups : list of int, optional
|
||||
Delayed groups to filter out the xs
|
||||
num_polar : Integral
|
||||
Number of equi-width polar angle bins for angle discretization
|
||||
|
|
@ -250,7 +248,7 @@ class MDGXS(MGXS):
|
|||
name : str, optional
|
||||
Name of the multi-group cross section. Used as a label to identify
|
||||
tallies in OpenMC 'tallies.xml' file. Defaults to the empty string.
|
||||
delayed_groups : list of int
|
||||
delayed_groups : list of int, optional
|
||||
Delayed groups to filter out the xs
|
||||
num_polar : Integral, optional
|
||||
Number of equi-width polar angle bins for angle discretization;
|
||||
|
|
@ -1320,10 +1318,10 @@ class ChiDelayed(MDGXS):
|
|||
|
||||
# Sum out all nuclides
|
||||
nuclides = self.get_nuclides()
|
||||
delayed_nu_fission_in = delayed_nu_fission_in.summation\
|
||||
(nuclides=nuclides)
|
||||
delayed_nu_fission_out = delayed_nu_fission_out.summation\
|
||||
(nuclides=nuclides)
|
||||
delayed_nu_fission_in = delayed_nu_fission_in.summation(
|
||||
nuclides=nuclides)
|
||||
delayed_nu_fission_out = delayed_nu_fission_out.summation(
|
||||
nuclides=nuclides)
|
||||
|
||||
# Remove coarse energy filter to keep it out of tally arithmetic
|
||||
energy_filter = delayed_nu_fission_in.find_filter(
|
||||
|
|
@ -2173,6 +2171,8 @@ class MatrixMDGXS(MDGXS):
|
|||
|
||||
# Eliminate the trivial score dimension
|
||||
xs = np.squeeze(xs, axis=len(xs.shape) - 1)
|
||||
|
||||
# Eliminate NaNs which may have been produced by dividing by density
|
||||
xs = np.nan_to_num(xs)
|
||||
|
||||
if in_groups == 'all':
|
||||
|
|
|
|||
|
|
@ -1,65 +1,80 @@
|
|||
from collections import OrderedDict
|
||||
from numbers import Integral
|
||||
import warnings
|
||||
import os
|
||||
import copy
|
||||
from abc import ABCMeta
|
||||
from numbers import Integral
|
||||
import os
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
import h5py
|
||||
import numpy as np
|
||||
|
||||
import openmc
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.tallies import ESTIMATOR_TYPES
|
||||
from openmc.mgxs import EnergyGroups
|
||||
from ..tallies import ESTIMATOR_TYPES
|
||||
from . import EnergyGroups
|
||||
|
||||
|
||||
# Supported cross section types
|
||||
MGXS_TYPES = ['total',
|
||||
'transport',
|
||||
'nu-transport',
|
||||
'absorption',
|
||||
'capture',
|
||||
'fission',
|
||||
'nu-fission',
|
||||
'kappa-fission',
|
||||
'scatter',
|
||||
'nu-scatter',
|
||||
'scatter matrix',
|
||||
'nu-scatter matrix',
|
||||
'multiplicity matrix',
|
||||
'nu-fission matrix',
|
||||
'scatter probability matrix',
|
||||
'consistent scatter matrix',
|
||||
'consistent nu-scatter matrix',
|
||||
'chi',
|
||||
'chi-prompt',
|
||||
'inverse-velocity',
|
||||
'prompt-nu-fission',
|
||||
'prompt-nu-fission matrix']
|
||||
MGXS_TYPES = (
|
||||
'total',
|
||||
'transport',
|
||||
'nu-transport',
|
||||
'absorption',
|
||||
'capture',
|
||||
'fission',
|
||||
'nu-fission',
|
||||
'kappa-fission',
|
||||
'scatter',
|
||||
'nu-scatter',
|
||||
'scatter matrix',
|
||||
'nu-scatter matrix',
|
||||
'multiplicity matrix',
|
||||
'nu-fission matrix',
|
||||
'scatter probability matrix',
|
||||
'consistent scatter matrix',
|
||||
'consistent nu-scatter matrix',
|
||||
'chi',
|
||||
'chi-prompt',
|
||||
'inverse-velocity',
|
||||
'prompt-nu-fission',
|
||||
'prompt-nu-fission matrix'
|
||||
)
|
||||
|
||||
# Supported domain types
|
||||
DOMAIN_TYPES = ['cell',
|
||||
'distribcell',
|
||||
'universe',
|
||||
'material',
|
||||
'mesh']
|
||||
DOMAIN_TYPES = (
|
||||
'cell',
|
||||
'distribcell',
|
||||
'universe',
|
||||
'material',
|
||||
'mesh'
|
||||
)
|
||||
|
||||
# Filter types corresponding to each domain
|
||||
_DOMAIN_TO_FILTER = {'cell': openmc.CellFilter,
|
||||
'distribcell': openmc.DistribcellFilter,
|
||||
'universe': openmc.UniverseFilter,
|
||||
'material': openmc.MaterialFilter,
|
||||
'mesh': openmc.MeshFilter}
|
||||
_DOMAIN_TO_FILTER = {
|
||||
'cell': openmc.CellFilter,
|
||||
'distribcell': openmc.DistribcellFilter,
|
||||
'universe': openmc.UniverseFilter,
|
||||
'material': openmc.MaterialFilter,
|
||||
'mesh': openmc.MeshFilter
|
||||
}
|
||||
|
||||
# Supported domain classes
|
||||
_DOMAINS = (openmc.Cell,
|
||||
openmc.Universe,
|
||||
openmc.Material,
|
||||
openmc.RegularMesh)
|
||||
_DOMAINS = (
|
||||
openmc.Cell,
|
||||
openmc.Universe,
|
||||
openmc.Material,
|
||||
openmc.RegularMesh
|
||||
)
|
||||
|
||||
# Supported ScatterMatrixXS angular distribution types
|
||||
MU_TREATMENTS = ('legendre', 'histogram')
|
||||
# Supported ScatterMatrixXS angular distribution types. Note that 'histogram' is
|
||||
# defined here and used in mgxs_library.py, but it is not used for the current
|
||||
# module
|
||||
SCATTER_TABULAR = 'tabular'
|
||||
SCATTER_LEGENDRE = 'legendre'
|
||||
SCATTER_HISTOGRAM = 'histogram'
|
||||
MU_TREATMENTS = (
|
||||
SCATTER_LEGENDRE,
|
||||
SCATTER_HISTOGRAM
|
||||
)
|
||||
|
||||
# Maximum Legendre order supported by OpenMC
|
||||
_MAX_LEGENDRE = 10
|
||||
|
|
@ -112,7 +127,7 @@ def _df_column_convert_to_bin(df, current_name, new_name, values_to_bin,
|
|||
df.rename(columns={current_name: new_name}, inplace=True)
|
||||
|
||||
|
||||
class MGXS(metaclass=ABCMeta):
|
||||
class MGXS:
|
||||
"""An abstract multi-group cross section for some energy group structure
|
||||
within some spatial domain.
|
||||
|
||||
|
|
@ -245,38 +260,37 @@ class MGXS(metaclass=ABCMeta):
|
|||
def __deepcopy__(self, memo):
|
||||
existing = memo.get(id(self))
|
||||
|
||||
# If this is the first time we have tried to copy this object, copy it
|
||||
if existing is None:
|
||||
clone = type(self).__new__(type(self))
|
||||
clone._name = self.name
|
||||
clone._rxn_type = self.rxn_type
|
||||
clone._by_nuclide = self.by_nuclide
|
||||
clone._nuclides = copy.deepcopy(self._nuclides, memo)
|
||||
clone._domain = self.domain
|
||||
clone._domain_type = self.domain_type
|
||||
clone._energy_groups = copy.deepcopy(self.energy_groups, memo)
|
||||
clone._num_polar = self._num_polar
|
||||
clone._num_azimuthal = self._num_azimuthal
|
||||
clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo)
|
||||
clone._rxn_rate_tally = copy.deepcopy(self._rxn_rate_tally, memo)
|
||||
clone._xs_tally = copy.deepcopy(self._xs_tally, memo)
|
||||
clone._sparse = self.sparse
|
||||
clone._loaded_sp = self._loaded_sp
|
||||
clone._derived = self.derived
|
||||
clone._hdf5_key = self._hdf5_key
|
||||
|
||||
clone._tallies = OrderedDict()
|
||||
for tally_type, tally in self.tallies.items():
|
||||
clone.tallies[tally_type] = copy.deepcopy(tally, memo)
|
||||
|
||||
memo[id(self)] = clone
|
||||
|
||||
return clone
|
||||
|
||||
# If this object has been copied before, return the first copy made
|
||||
else:
|
||||
if existing is not None:
|
||||
return existing
|
||||
|
||||
# If this is the first time we have tried to copy this object, copy it
|
||||
clone = type(self).__new__(type(self))
|
||||
clone._name = self.name
|
||||
clone._rxn_type = self.rxn_type
|
||||
clone._by_nuclide = self.by_nuclide
|
||||
clone._nuclides = copy.deepcopy(self._nuclides, memo)
|
||||
clone._domain = self.domain
|
||||
clone._domain_type = self.domain_type
|
||||
clone._energy_groups = copy.deepcopy(self.energy_groups, memo)
|
||||
clone._num_polar = self._num_polar
|
||||
clone._num_azimuthal = self._num_azimuthal
|
||||
clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo)
|
||||
clone._rxn_rate_tally = copy.deepcopy(self._rxn_rate_tally, memo)
|
||||
clone._xs_tally = copy.deepcopy(self._xs_tally, memo)
|
||||
clone._sparse = self.sparse
|
||||
clone._loaded_sp = self._loaded_sp
|
||||
clone._derived = self.derived
|
||||
clone._hdf5_key = self._hdf5_key
|
||||
|
||||
clone._tallies = OrderedDict()
|
||||
for tally_type, tally in self.tallies.items():
|
||||
clone.tallies[tally_type] = copy.deepcopy(tally, memo)
|
||||
|
||||
memo[id(self)] = clone
|
||||
|
||||
return clone
|
||||
|
||||
def _add_angle_filters(self, filters):
|
||||
"""Add the azimuthal and polar bins to the MGXS filters if needed.
|
||||
Filters will be provided as a ragged 2D list of openmc.Filter objects.
|
||||
|
|
@ -2170,6 +2184,7 @@ class MatrixMGXS(MGXS):
|
|||
if not isinstance(in_groups, str):
|
||||
cv.check_iterable_type('groups', in_groups, Integral)
|
||||
filters.append(openmc.EnergyFilter)
|
||||
energy_bins = []
|
||||
for group in in_groups:
|
||||
energy_bins.append((self.energy_groups.get_group_bounds(group),))
|
||||
filter_bins.append(tuple(energy_bins))
|
||||
|
|
@ -3725,7 +3740,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
num_polar, num_azimuthal)
|
||||
self._formulation = 'simple'
|
||||
self._correction = 'P0'
|
||||
self._scatter_format = 'legendre'
|
||||
self._scatter_format = SCATTER_LEGENDRE
|
||||
self._legendre_order = 0
|
||||
self._histogram_bins = 16
|
||||
self._estimator = 'analog'
|
||||
|
|
@ -3748,12 +3763,12 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
process
|
||||
"""
|
||||
if self.num_polar > 1 or self.num_azimuthal > 1:
|
||||
if self.scatter_format == 'histogram':
|
||||
if self.scatter_format == SCATTER_HISTOGRAM:
|
||||
return (0, 1, 3, 4, 5)
|
||||
else:
|
||||
return (0, 1, 3, 4)
|
||||
else:
|
||||
if self.scatter_format == 'histogram':
|
||||
if self.scatter_format == SCATTER_HISTOGRAM:
|
||||
return (1, 2, 3)
|
||||
else:
|
||||
return (1, 2)
|
||||
|
|
@ -3857,13 +3872,13 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
energy = openmc.EnergyFilter(group_edges)
|
||||
energyout = openmc.EnergyoutFilter(group_edges)
|
||||
|
||||
if self.scatter_format == 'legendre':
|
||||
if self.scatter_format == SCATTER_LEGENDRE:
|
||||
if self.correction == 'P0' and self.legendre_order == 0:
|
||||
angle_filter = openmc.LegendreFilter(order=1)
|
||||
else:
|
||||
angle_filter = \
|
||||
openmc.LegendreFilter(order=self.legendre_order)
|
||||
elif self.scatter_format == 'histogram':
|
||||
elif self.scatter_format == SCATTER_HISTOGRAM:
|
||||
bins = np.linspace(-1., 1., num=self.histogram_bins + 1,
|
||||
endpoint=True)
|
||||
angle_filter = openmc.MuFilter(bins)
|
||||
|
|
@ -3878,9 +3893,9 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
filters = [[energy], [energy]]
|
||||
|
||||
# Group-to-group scattering probability matrix
|
||||
if self.scatter_format == 'legendre':
|
||||
if self.scatter_format == SCATTER_LEGENDRE:
|
||||
angle_filter = openmc.LegendreFilter(order=self.legendre_order)
|
||||
elif self.scatter_format == 'histogram':
|
||||
elif self.scatter_format == SCATTER_HISTOGRAM:
|
||||
bins = np.linspace(-1., 1., num=self.histogram_bins + 1,
|
||||
endpoint=True)
|
||||
angle_filter = openmc.MuFilter(bins)
|
||||
|
|
@ -3903,7 +3918,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
if self._rxn_rate_tally is None:
|
||||
|
||||
if self.formulation == 'simple':
|
||||
if self.scatter_format == 'legendre':
|
||||
if self.scatter_format == SCATTER_LEGENDRE:
|
||||
# If using P0 correction subtract P1 scatter from the diag.
|
||||
if self.correction == 'P0' and self.legendre_order == 0:
|
||||
scatter_p0 = self.tallies[self.rxn_type].get_slice(
|
||||
|
|
@ -3937,7 +3952,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
# Otherwise, extract scattering moment reaction rate Tally
|
||||
else:
|
||||
self._rxn_rate_tally = self.tallies[self.rxn_type]
|
||||
elif self.scatter_format == 'histogram':
|
||||
elif self.scatter_format == SCATTER_HISTOGRAM:
|
||||
# Extract scattering rate distribution tally
|
||||
self._rxn_rate_tally = self.tallies[self.rxn_type]
|
||||
|
||||
|
|
@ -3967,14 +3982,14 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
tally_key = 'scatter matrix'
|
||||
|
||||
# Compute normalization factor summed across outgoing energies
|
||||
if self.scatter_format == 'legendre':
|
||||
if self.scatter_format == SCATTER_LEGENDRE:
|
||||
norm = self.tallies[tally_key].get_slice(
|
||||
scores=['scatter'],
|
||||
filters=[openmc.LegendreFilter],
|
||||
filter_bins=[('P0',)], squeeze=True)
|
||||
|
||||
# Compute normalization factor summed across outgoing mu bins
|
||||
elif self.scatter_format == 'histogram':
|
||||
elif self.scatter_format == SCATTER_HISTOGRAM:
|
||||
norm = self.tallies[tally_key].get_slice(
|
||||
scores=['scatter'])
|
||||
norm = norm.summation(
|
||||
|
|
@ -3994,14 +4009,14 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
if self.nu:
|
||||
numer = self.tallies['nu-scatter']
|
||||
# Get the denominator
|
||||
if self.scatter_format == 'legendre':
|
||||
if self.scatter_format == SCATTER_LEGENDRE:
|
||||
denom = self.tallies[tally_key].get_slice(
|
||||
scores=['scatter'],
|
||||
filters=[openmc.LegendreFilter],
|
||||
filter_bins=[('P0',)], squeeze=True)
|
||||
|
||||
# Compute normalization factor summed across mu bins
|
||||
elif self.scatter_format == 'histogram':
|
||||
elif self.scatter_format == SCATTER_HISTOGRAM:
|
||||
denom = self.tallies[tally_key].get_slice(
|
||||
scores=['scatter'])
|
||||
|
||||
|
|
@ -4048,7 +4063,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
self._compute_xs()
|
||||
|
||||
# Force the angle filter to be the last filter
|
||||
if self.scatter_format == 'histogram':
|
||||
if self.scatter_format == SCATTER_HISTOGRAM:
|
||||
angle_filter = self._xs_tally.find_filter(openmc.MuFilter)
|
||||
else:
|
||||
angle_filter = \
|
||||
|
|
@ -4105,13 +4120,13 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
def correction(self, correction):
|
||||
cv.check_value('correction', correction, ('P0', None))
|
||||
|
||||
if self.scatter_format == 'legendre':
|
||||
if self.scatter_format == SCATTER_LEGENDRE:
|
||||
if correction == 'P0' and self.legendre_order > 0:
|
||||
msg = 'The P0 correction will be ignored since the ' \
|
||||
'scattering order {} is greater than '\
|
||||
'zero'.format(self.legendre_order)
|
||||
warnings.warn(msg)
|
||||
elif self.scatter_format == 'histogram':
|
||||
elif self.scatter_format == SCATTER_HISTOGRAM:
|
||||
msg = 'The P0 correction will be ignored since the ' \
|
||||
'scatter format is set to histogram'
|
||||
warnings.warn(msg)
|
||||
|
|
@ -4131,14 +4146,14 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
cv.check_less_than('legendre_order', legendre_order, _MAX_LEGENDRE,
|
||||
equality=True)
|
||||
|
||||
if self.scatter_format == 'legendre':
|
||||
if self.scatter_format == SCATTER_LEGENDRE:
|
||||
if self.correction == 'P0' and legendre_order > 0:
|
||||
msg = 'The P0 correction will be ignored since the ' \
|
||||
'scattering order {} is greater than '\
|
||||
'zero'.format(self.legendre_order)
|
||||
warnings.warn(msg, RuntimeWarning)
|
||||
self.correction = None
|
||||
elif self.scatter_format == 'histogram':
|
||||
elif self.scatter_format == SCATTER_HISTOGRAM:
|
||||
msg = 'The legendre order will be ignored since the ' \
|
||||
'scatter format is set to histogram'
|
||||
warnings.warn(msg)
|
||||
|
|
@ -4226,7 +4241,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
slice_xs._xs_tally = None
|
||||
|
||||
# Slice the Legendre order if needed
|
||||
if legendre_order != 'same' and self.scatter_format == 'legendre':
|
||||
if legendre_order != 'same' and self.scatter_format == SCATTER_LEGENDRE:
|
||||
cv.check_type('legendre_order', legendre_order, Integral)
|
||||
cv.check_less_than('legendre_order', legendre_order,
|
||||
self.legendre_order, equality=True)
|
||||
|
|
@ -4363,7 +4378,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
filter_bins.append((self.energy_groups.get_group_bounds(group),))
|
||||
|
||||
# Construct CrossScore for requested scattering moment
|
||||
if self.scatter_format == 'legendre':
|
||||
if self.scatter_format == SCATTER_LEGENDRE:
|
||||
if moment != 'all':
|
||||
cv.check_type('moment', moment, Integral)
|
||||
cv.check_greater_than('moment', moment, 0, equality=True)
|
||||
|
|
@ -4508,7 +4523,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
paths=paths)
|
||||
|
||||
# If the matrix is P0, remove the legendre column
|
||||
if self.scatter_format == 'legendre' and self.legendre_order == 0:
|
||||
if self.scatter_format == SCATTER_LEGENDRE and self.legendre_order == 0:
|
||||
df = df.drop(axis=1, labels=['legendre'])
|
||||
|
||||
return df
|
||||
|
|
@ -4560,7 +4575,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
|
||||
cv.check_value('xs_type', xs_type, ['macro', 'micro'])
|
||||
|
||||
if self.correction != 'P0' and self.scatter_format == 'legendre':
|
||||
if self.correction != 'P0' and self.scatter_format == SCATTER_LEGENDRE:
|
||||
rxn_type = '{0} (P{1})'.format(self.rxn_type, moment)
|
||||
else:
|
||||
rxn_type = self.rxn_type
|
||||
|
|
@ -4648,7 +4663,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
return to_print
|
||||
|
||||
# Set the number of histogram bins
|
||||
if self.scatter_format == 'histogram':
|
||||
if self.scatter_format == SCATTER_HISTOGRAM:
|
||||
num_mu_bins = self.histogram_bins
|
||||
else:
|
||||
num_mu_bins = 0
|
||||
|
|
|
|||
|
|
@ -2,15 +2,16 @@ import copy
|
|||
from numbers import Real, Integral
|
||||
import os
|
||||
|
||||
import numpy as np
|
||||
import h5py
|
||||
from scipy.interpolate import interp1d
|
||||
import numpy as np
|
||||
from scipy.integrate import simps
|
||||
from scipy.interpolate import interp1d
|
||||
from scipy.special import eval_legendre
|
||||
|
||||
import openmc
|
||||
import openmc.mgxs
|
||||
from openmc.checkvalue import check_type, check_value, check_greater_than, \
|
||||
from openmc.mgxs import SCATTER_TABULAR, SCATTER_LEGENDRE, SCATTER_HISTOGRAM
|
||||
from .checkvalue import check_type, check_value, check_greater_than, \
|
||||
check_iterable_type, check_less_than, check_filetype_version
|
||||
|
||||
ROOM_TEMPERATURE_KELVIN = 294.0
|
||||
|
|
@ -24,9 +25,6 @@ _REPRESENTATIONS = [
|
|||
]
|
||||
|
||||
# Supported scattering angular distribution representations
|
||||
SCATTER_TABULAR = 'tabular'
|
||||
SCATTER_LEGENDRE = 'legendre'
|
||||
SCATTER_HISTOGRAM = 'histogram'
|
||||
_SCATTER_TYPES = [
|
||||
SCATTER_TABULAR,
|
||||
SCATTER_LEGENDRE,
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import openmc.checkvalue as cv
|
|||
|
||||
|
||||
class EqualityMixin:
|
||||
"""A Class which provides generic __eq__ and __ne__ functionality which
|
||||
can easily be inherited by downstream classes.
|
||||
"""A Class which provides a generic __eq__ method that can be inherited
|
||||
by downstream classes.
|
||||
"""
|
||||
|
||||
def __eq__(self, other):
|
||||
|
|
|
|||
|
|
@ -1,19 +1,24 @@
|
|||
from collections.abc import Iterable
|
||||
from functools import partial
|
||||
from math import sqrt
|
||||
from numbers import Real
|
||||
from functools import partial
|
||||
from warnings import warn
|
||||
from operator import attrgetter
|
||||
from warnings import warn
|
||||
|
||||
from openmc import (
|
||||
XPlane, YPlane, Plane, ZCylinder, Quadric, Cylinder, XCylinder,
|
||||
YCylinder, Material, Universe, Cell)
|
||||
from openmc.checkvalue import (
|
||||
XPlane, YPlane, Plane, ZCylinder, Cylinder, XCylinder,
|
||||
YCylinder, Universe, Cell)
|
||||
from ..checkvalue import (
|
||||
check_type, check_value, check_length, check_less_than,
|
||||
check_iterable_type)
|
||||
import openmc.data
|
||||
|
||||
|
||||
ZERO_CELSIUS_TO_KELVIN = 273.15
|
||||
ZERO_FAHRENHEIT_TO_KELVIN = 459.67
|
||||
PSI_TO_MPA = 0.006895
|
||||
|
||||
|
||||
def borated_water(boron_ppm, temperature=293., pressure=0.1013, temp_unit='K',
|
||||
press_unit='MPa', density=None, **kwargs):
|
||||
"""Return a Material with the composition of boron dissolved in water.
|
||||
|
|
@ -53,14 +58,14 @@ def borated_water(boron_ppm, temperature=293., pressure=0.1013, temp_unit='K',
|
|||
if temp_unit == 'K':
|
||||
T = temperature
|
||||
elif temp_unit == 'C':
|
||||
T = temperature + 273.15
|
||||
T = temperature + ZERO_CELSIUS_TO_KELVIN
|
||||
elif temp_unit == 'F':
|
||||
T = (temperature + 459.67) * 5.0 / 9.0
|
||||
T = (temperature + ZERO_FAHRENHEIT_TO_KELVIN) * (5/9)
|
||||
check_value('pressure unit', press_unit, ('MPa', 'psi'))
|
||||
if press_unit == 'MPa':
|
||||
P = pressure
|
||||
elif press_unit == 'psi':
|
||||
P = pressure * 0.006895
|
||||
P = pressure * PSI_TO_MPA
|
||||
|
||||
# Set the density of water, either from an explicitly given density or from
|
||||
# temperature and pressure.
|
||||
|
|
@ -440,7 +445,7 @@ def pin(surfaces, items, subdivisions=None, divide_vols=True,
|
|||
items
|
||||
"""
|
||||
if "cells" in kwargs:
|
||||
raise SyntaxError(
|
||||
raise ValueError(
|
||||
"Cells will be set by this function, not from input arguments.")
|
||||
check_type("items", items, Iterable)
|
||||
check_length("surfaces", surfaces, len(items) - 1, len(items) - 1)
|
||||
|
|
|
|||
|
|
@ -1,24 +1,29 @@
|
|||
import copy
|
||||
import warnings
|
||||
import itertools
|
||||
import random
|
||||
from abc import ABCMeta, abstractproperty, abstractmethod
|
||||
from abc import ABC, abstractproperty, abstractmethod
|
||||
from collections import Counter, defaultdict
|
||||
from collections.abc import Iterable
|
||||
import copy
|
||||
from heapq import heappush, heappop
|
||||
import itertools
|
||||
from math import pi, sin, cos, floor, log10, sqrt
|
||||
from numbers import Real
|
||||
import random
|
||||
from random import uniform, gauss
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
import scipy.spatial
|
||||
|
||||
import openmc
|
||||
from openmc.checkvalue import check_type
|
||||
from ..checkvalue import check_type
|
||||
|
||||
|
||||
MAX_PF_RSP = 0.38
|
||||
MAX_PF_CRP = 0.64
|
||||
MAX_PF_RSP = 0.38 # maximum packing fraction for random sequential packing
|
||||
MAX_PF_CRP = 0.64 # maximum packing fraction for close random packing
|
||||
|
||||
|
||||
def _volume_sphere(r):
|
||||
"""Return volume of a sphere of radius r"""
|
||||
return 4/3 * pi * r**3
|
||||
|
||||
|
||||
class TRISO(openmc.Cell):
|
||||
|
|
@ -95,7 +100,7 @@ class TRISO(openmc.Cell):
|
|||
k_min:k_max+1, j_min:j_max+1, i_min:i_max+1]))
|
||||
|
||||
|
||||
class _Container(metaclass=ABCMeta):
|
||||
class _Container(ABC):
|
||||
"""Container in which to pack spheres.
|
||||
|
||||
Parameters
|
||||
|
|
@ -696,7 +701,7 @@ class _SphericalShell(_Container):
|
|||
|
||||
@property
|
||||
def volume(self):
|
||||
return 4/3*pi*(self.radius**3 - self.inner_radius**3)
|
||||
return _volume_sphere(self.radius) - _volume_sphere(self.inner_radius)
|
||||
|
||||
@radius.setter
|
||||
def radius(self, radius):
|
||||
|
|
@ -1073,8 +1078,8 @@ def _close_random_pack(domain, spheres, contraction_rate):
|
|||
|
||||
"""
|
||||
|
||||
inner_pf = 4/3*pi*(inner_diameter/2)**3*num_spheres/domain.volume
|
||||
outer_pf = 4/3*pi*(outer_diameter/2)**3*num_spheres/domain.volume
|
||||
inner_pf = _volume_sphere(inner_diameter/2)*num_spheres / domain.volume
|
||||
outer_pf = _volume_sphere(outer_diameter/2)*num_spheres / domain.volume
|
||||
|
||||
j = floor(-log10(outer_pf - inner_pf))
|
||||
return (outer_diameter - 0.5**j * contraction_rate *
|
||||
|
|
@ -1289,7 +1294,7 @@ def pack_spheres(radius, region, pf=None, num_spheres=None, initial_pf=0.3,
|
|||
'sphere, and spherical shell.'.format(region))
|
||||
|
||||
# Determine the packing fraction/number of spheres
|
||||
volume = 4/3*pi*radius**3
|
||||
volume = _volume_sphere(radius)
|
||||
if pf is None and num_spheres is None:
|
||||
raise ValueError('`pf` or `num_spheres` must be specified.')
|
||||
elif pf is None:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import warnings
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
|
||||
class Nuclide(str):
|
||||
"""A nuclide that can be used in a material.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import copy
|
||||
import operator
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmoc
|
||||
|
||||
import openmc
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
# TODO: Get rid of global state by using memoization on functions below
|
||||
|
||||
# A dictionary of all OpenMC Materials created
|
||||
# Keys - Material IDs
|
||||
|
|
@ -408,12 +406,12 @@ def get_openmc_region(openmoc_region):
|
|||
side = '-' if openmoc_region.getHalfspace() == -1 else '+'
|
||||
openmc_region = openmc.Halfspace(surface, side)
|
||||
elif openmoc_region.getRegionType() == openmoc.INTERSECTION:
|
||||
openmc_region = openmc.Intersection()
|
||||
openmc_region = openmc.Intersection([])
|
||||
for openmoc_node in openmoc_region.getNodes():
|
||||
openmc_node = get_openmc_region(openmoc_node)
|
||||
openmc_region.append(openmc_node)
|
||||
elif openmoc_region.getRegionType() == openmoc.UNION:
|
||||
openmc_region = openmc.Union()
|
||||
openmc_region = openmc.Union([])
|
||||
for openmoc_node in openmoc_region.getNodes():
|
||||
openmc_node = get_openmc_region(openmoc_node)
|
||||
openmc_region.append(openmc_node)
|
||||
|
|
@ -452,10 +450,10 @@ def get_openmc_cell(openmoc_cell):
|
|||
name = openmoc_cell.getName()
|
||||
openmc_cell = openmc.Cell(cell_id, name)
|
||||
|
||||
if (openmoc_cell.getType() == openmoc.MATERIAL):
|
||||
if openmoc_cell.getType() == openmoc.MATERIAL:
|
||||
fill = openmoc_cell.getFillMaterial()
|
||||
openmc_cell.fill = get_openmc_material(fill)
|
||||
elif (openmoc_cell.getType() == openmoc.FILL):
|
||||
elif openmoc_cell.getType() == openmoc.FILL:
|
||||
fill = openmoc_cell.getFillUniverse()
|
||||
if fill.getType() == openmoc.LATTICE:
|
||||
fill = openmoc.castUniverseToLattice(fill)
|
||||
|
|
@ -464,9 +462,11 @@ def get_openmc_cell(openmoc_cell):
|
|||
openmc_cell.fill = get_openmc_universe(fill)
|
||||
|
||||
if openmoc_cell.isRotated():
|
||||
# get rotation for each of 3 axes
|
||||
rotation = openmoc_cell.retrieveRotation(3)
|
||||
openmc_cell.rotation = rotation
|
||||
if openmoc_cell.isTranslated():
|
||||
# get translation for each of 3 axes
|
||||
translation = openmoc_cell.retrieveTranslation(3)
|
||||
openmc_cell.translation = translation
|
||||
|
||||
|
|
|
|||
|
|
@ -42,52 +42,19 @@ class Particle:
|
|||
"""
|
||||
|
||||
def __init__(self, filename):
|
||||
self._f = h5py.File(filename, 'r')
|
||||
with h5py.File(filename, 'r') as f:
|
||||
|
||||
# Ensure filetype and version are correct
|
||||
cv.check_filetype_version(self._f, 'particle restart',
|
||||
_VERSION_PARTICLE_RESTART)
|
||||
# Ensure filetype and version are correct
|
||||
cv.check_filetype_version(f, 'particle restart', _VERSION_PARTICLE_RESTART)
|
||||
|
||||
@property
|
||||
def current_batch(self):
|
||||
return self._f['current_batch'][()]
|
||||
|
||||
@property
|
||||
def current_generation(self):
|
||||
return self._f['current_generation'][()]
|
||||
|
||||
@property
|
||||
def energy(self):
|
||||
return self._f['energy'][()]
|
||||
|
||||
@property
|
||||
def generations_per_batch(self):
|
||||
return self._f['generations_per_batch'][()]
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._f['id'][()]
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._f['type'][()]
|
||||
|
||||
@property
|
||||
def n_particles(self):
|
||||
return self._f['n_particles'][()]
|
||||
|
||||
@property
|
||||
def run_mode(self):
|
||||
return self._f['run_mode'][()].decode()
|
||||
|
||||
@property
|
||||
def uvw(self):
|
||||
return self._f['uvw'][()]
|
||||
|
||||
@property
|
||||
def weight(self):
|
||||
return self._f['weight'][()]
|
||||
|
||||
@property
|
||||
def xyz(self):
|
||||
return self._f['xyz'][()]
|
||||
self.current_batch = f['current_batch'][()]
|
||||
self.current_generation = f['current_generation'][()]
|
||||
self.energy = f['energy'][()]
|
||||
self.generations_per_batch = f['generations_per_batch'][()]
|
||||
self.id = f['id'][()]
|
||||
self.type = f['type'][()]
|
||||
self.n_particles = f['n_particles'][()]
|
||||
self.run_mode = f['run_mode'][()].decode()
|
||||
self.uvw = f['uvw'][()]
|
||||
self.weight = f['weight'][()]
|
||||
self.xyz = f['xyz'][()]
|
||||
|
|
|
|||
|
|
@ -2,16 +2,14 @@ from collections.abc import Iterable, Mapping
|
|||
from numbers import Real, Integral
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import warnings
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc
|
||||
import openmc.checkvalue as cv
|
||||
from openmc._xml import clean_indentation
|
||||
from openmc.mixin import IDManagerMixin
|
||||
from ._xml import clean_indentation
|
||||
from .mixin import IDManagerMixin
|
||||
|
||||
|
||||
_BASES = ['xy', 'xz', 'yz']
|
||||
|
|
@ -400,13 +398,13 @@ class Plot(IDManagerMixin):
|
|||
def meshlines(self, meshlines):
|
||||
cv.check_type('plot meshlines', meshlines, dict)
|
||||
if 'type' not in meshlines:
|
||||
msg = 'Unable to set on plot the meshlines "{0}" which ' \
|
||||
msg = 'Unable to set the meshlines to "{}" which ' \
|
||||
'does not have a "type" key'.format(meshlines)
|
||||
raise ValueError(msg)
|
||||
|
||||
elif meshlines['type'] not in ['tally', 'entropy', 'ufs', 'cmfd']:
|
||||
msg = 'Unable to set the meshlines with ' \
|
||||
'type "{0}"'.format(meshlines['type'])
|
||||
'type "{}"'.format(meshlines['type'])
|
||||
raise ValueError(msg)
|
||||
|
||||
if 'id' in meshlines:
|
||||
|
|
@ -450,11 +448,11 @@ class Plot(IDManagerMixin):
|
|||
string += '{: <16}=\t{}\n'.format('\tColor by', self._color_by)
|
||||
string += '{: <16}=\t{}\n'.format('\tBackground', self._background)
|
||||
string += '{: <16}=\t{}\n'.format('\tMask components',
|
||||
self._mask_components)
|
||||
self._mask_components)
|
||||
string += '{: <16}=\t{}\n'.format('\tMask background',
|
||||
self._mask_background)
|
||||
string += '{: <16}=\t{}\n'.format('\Overlap Color',
|
||||
self._overlap_color)
|
||||
self._mask_background)
|
||||
string += '{: <16}=\t{}\n'.format('\tOverlap Color',
|
||||
self._overlap_color)
|
||||
string += '{: <16}=\t{}\n'.format('\tColors', self._colors)
|
||||
string += '{: <16}=\t{}\n'.format('\tLevel', self._level)
|
||||
string += '{: <16}=\t{}\n'.format('\tMeshlines', self._meshlines)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from numbers import Integral, Real
|
||||
from itertools import chain
|
||||
from numbers import Integral, Real
|
||||
import string
|
||||
|
||||
import numpy as np
|
||||
|
|
@ -29,30 +29,37 @@ XI_MT = -2
|
|||
|
||||
# MTs to combine to generate associated plot_types
|
||||
_INELASTIC = [mt for mt in openmc.data.SUM_RULES[3] if mt != 27]
|
||||
PLOT_TYPES_MT = {'total': openmc.data.SUM_RULES[1],
|
||||
'scatter': [2] + _INELASTIC,
|
||||
'elastic': [2],
|
||||
'inelastic': _INELASTIC,
|
||||
'fission': [18],
|
||||
'absorption': [27], 'capture': [101],
|
||||
'nu-fission': [18],
|
||||
'nu-scatter': [2] + _INELASTIC,
|
||||
'unity': [UNITY_MT],
|
||||
'slowing-down power': [2] + _INELASTIC + [XI_MT],
|
||||
'damage': [444]}
|
||||
PLOT_TYPES_MT = {
|
||||
'total': openmc.data.SUM_RULES[1],
|
||||
'scatter': [2] + _INELASTIC,
|
||||
'elastic': [2],
|
||||
'inelastic': _INELASTIC,
|
||||
'fission': [18],
|
||||
'absorption': [27],
|
||||
'capture': [101],
|
||||
'nu-fission': [18],
|
||||
'nu-scatter': [2] + _INELASTIC,
|
||||
'unity': [UNITY_MT],
|
||||
'slowing-down power': [2] + _INELASTIC + [XI_MT],
|
||||
'damage': [444]
|
||||
}
|
||||
# Operations to use when combining MTs the first np.add is used in reference
|
||||
# to zero
|
||||
PLOT_TYPES_OP = {'total': (np.add,),
|
||||
'scatter': (np.add,) * (len(PLOT_TYPES_MT['scatter']) - 1),
|
||||
'elastic': (),
|
||||
'inelastic': (np.add,) * (len(PLOT_TYPES_MT['inelastic']) - 1),
|
||||
'fission': (), 'absorption': (),
|
||||
'capture': (), 'nu-fission': (),
|
||||
'nu-scatter': (np.add,) * (len(PLOT_TYPES_MT['nu-scatter']) - 1),
|
||||
'unity': (),
|
||||
'slowing-down power':
|
||||
(np.add,) * (len(PLOT_TYPES_MT['slowing-down power']) - 2) + (np.multiply,),
|
||||
'damage': ()}
|
||||
PLOT_TYPES_OP = {
|
||||
'total': (np.add,),
|
||||
'scatter': (np.add,) * (len(PLOT_TYPES_MT['scatter']) - 1),
|
||||
'elastic': (),
|
||||
'inelastic': (np.add,) * (len(PLOT_TYPES_MT['inelastic']) - 1),
|
||||
'fission': (),
|
||||
'absorption': (),
|
||||
'capture': (),
|
||||
'nu-fission': (),
|
||||
'nu-scatter': (np.add,) * (len(PLOT_TYPES_MT['nu-scatter']) - 1),
|
||||
'unity': (),
|
||||
'slowing-down power': \
|
||||
(np.add,) * (len(PLOT_TYPES_MT['slowing-down power']) - 2) + (np.multiply,),
|
||||
'damage': ()
|
||||
}
|
||||
|
||||
# Types of plots to plot linearly in y
|
||||
PLOT_TYPES_LINEAR = {'nu-fission / fission', 'nu-scatter / scatter',
|
||||
|
|
@ -189,8 +196,7 @@ def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None,
|
|||
|
||||
# Generate the plot
|
||||
if axis is None:
|
||||
fig = plt.figure(**kwargs)
|
||||
ax = fig.add_subplot(111)
|
||||
fig, ax = plt.subplots()
|
||||
else:
|
||||
fig = None
|
||||
ax = axis
|
||||
|
|
@ -287,7 +293,7 @@ def calculate_cexs(this, data_type, types, temperature=294., sab_name=None,
|
|||
energy_grid, xs = _calculate_cexs_nuclide(nuc, types, temperature,
|
||||
sab_name, cross_sections)
|
||||
# Convert xs (Iterable of Callable) to a grid of cross section values
|
||||
# calculated on @ the points in energy_grid for consistency with the
|
||||
# calculated on the points in energy_grid for consistency with the
|
||||
# element and material functions.
|
||||
data = np.zeros((len(types), len(energy_grid)))
|
||||
for line in range(len(types)):
|
||||
|
|
@ -397,8 +403,8 @@ def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None,
|
|||
grid = nuc.energy[nucT]
|
||||
sab_Emax = 0.
|
||||
sab_funcs = []
|
||||
if sab.elastic_xs:
|
||||
elastic = sab.elastic_xs[sabT]
|
||||
if sab.elastic is not None:
|
||||
elastic = sab.elastic.xs[sabT]
|
||||
if isinstance(elastic, openmc.data.CoherentElastic):
|
||||
grid = np.union1d(grid, elastic.bragg_edges)
|
||||
if elastic.bragg_edges[-1] > sab_Emax:
|
||||
|
|
@ -408,8 +414,8 @@ def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None,
|
|||
if elastic.x[-1] > sab_Emax:
|
||||
sab_Emax = elastic.x[-1]
|
||||
sab_funcs.append(elastic)
|
||||
if sab.inelastic_xs:
|
||||
inelastic = sab.inelastic_xs[sabT]
|
||||
if sab.inelastic is not None:
|
||||
inelastic = sab.inelastic.xs[sabT]
|
||||
grid = np.union1d(grid, inelastic.x)
|
||||
if inelastic.x[-1] > sab_Emax:
|
||||
sab_Emax = inelastic.x[-1]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import math
|
||||
import numpy as np
|
||||
import openmc
|
||||
from collections.abc import Iterable
|
||||
import math
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
def legendre_from_expcoef(coef, domain=(-1, 1)):
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
from abc import ABCMeta, abstractmethod
|
||||
from abc import ABC, abstractmethod
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable, MutableSequence
|
||||
from collections.abc import MutableSequence
|
||||
from copy import deepcopy
|
||||
|
||||
import numpy as np
|
||||
|
||||
from openmc.checkvalue import check_type
|
||||
from .checkvalue import check_type
|
||||
|
||||
|
||||
class Region(metaclass=ABCMeta):
|
||||
class Region(ABC):
|
||||
"""Region of space that can be assigned to a cell.
|
||||
|
||||
Region is an abstract base class that is inherited by
|
||||
|
|
|
|||
|
|
@ -2,15 +2,11 @@ from collections.abc import Iterable, MutableSequence, Mapping
|
|||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from numbers import Real, Integral
|
||||
import warnings
|
||||
from xml.etree import ElementTree as ET
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
from openmc._xml import clean_indentation, get_text
|
||||
import openmc.checkvalue as cv
|
||||
from openmc import VolumeCalculation, Source, RegularMesh
|
||||
from . import VolumeCalculation, Source, RegularMesh
|
||||
from ._xml import clean_indentation, get_text
|
||||
|
||||
|
||||
class RunMode(Enum):
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from numbers import Real
|
||||
import sys
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
from openmc._xml import get_text
|
||||
from openmc.stats.univariate import Univariate
|
||||
from openmc.stats.multivariate import UnitSphere, Spatial
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.stats.multivariate import UnitSphere, Spatial
|
||||
from openmc.stats.univariate import Univariate
|
||||
from ._xml import get_text
|
||||
|
||||
|
||||
class Source:
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from datetime import datetime
|
||||
import glob
|
||||
import re
|
||||
import os
|
||||
import warnings
|
||||
import glob
|
||||
|
||||
import numpy as np
|
||||
import h5py
|
||||
import numpy as np
|
||||
from uncertainties import ufloat
|
||||
|
||||
import openmc
|
||||
|
|
@ -416,14 +416,10 @@ class StatePoint:
|
|||
nuclide = openmc.Nuclide(name.decode().strip())
|
||||
tally.nuclides.append(nuclide)
|
||||
|
||||
scores = group['score_bins'][()]
|
||||
n_score_bins = group['n_score_bins'][()]
|
||||
|
||||
# Add the scores to the Tally
|
||||
for j, score in enumerate(scores):
|
||||
score = score.decode()
|
||||
|
||||
tally.scores.append(score)
|
||||
scores = group['score_bins'][()]
|
||||
for score in scores:
|
||||
tally.scores.append(score.decode())
|
||||
|
||||
# Add Tally to the global dictionary of all Tallies
|
||||
tally.sparse = self.sparse
|
||||
|
|
@ -586,15 +582,7 @@ class StatePoint:
|
|||
|
||||
# Determine if Tally has the queried score(s)
|
||||
if scores:
|
||||
contains_scores = True
|
||||
|
||||
# Iterate over the scores requested by the user
|
||||
for score in scores:
|
||||
if score not in test_tally.scores:
|
||||
contains_scores = False
|
||||
break
|
||||
|
||||
if not contains_scores:
|
||||
if not all(score in test_tally.scores for score in scores):
|
||||
continue
|
||||
|
||||
# Determine if Tally has the queried Filter(s)
|
||||
|
|
@ -620,15 +608,7 @@ class StatePoint:
|
|||
|
||||
# Determine if Tally has the queried Nuclide(s)
|
||||
if nuclides:
|
||||
contains_nuclides = True
|
||||
|
||||
# Iterate over the Nuclides requested by the user
|
||||
for nuclide in nuclides:
|
||||
if nuclide not in test_tally.nuclides:
|
||||
contains_nuclides = False
|
||||
break
|
||||
|
||||
if not contains_nuclides:
|
||||
if not all(nuclide in test_tally.nuclides for nuclide in nuclides):
|
||||
continue
|
||||
|
||||
# If the current Tally met user's request, break loop and return it
|
||||
|
|
@ -676,7 +656,7 @@ class StatePoint:
|
|||
|
||||
cells = summary.geometry.get_all_cells()
|
||||
|
||||
for tally_id, tally in self.tallies.items():
|
||||
for tally in self.tallies.values():
|
||||
tally.with_summary = True
|
||||
|
||||
for tally_filter in tally.filters:
|
||||
|
|
|
|||
|
|
@ -1,18 +1,17 @@
|
|||
from abc import ABCMeta, abstractmethod
|
||||
from abc import ABC, abstractmethod
|
||||
from collections.abc import Iterable
|
||||
from math import pi
|
||||
from numbers import Real
|
||||
import sys
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
from openmc._xml import get_text
|
||||
from openmc.stats.univariate import Univariate, Uniform
|
||||
from .._xml import get_text
|
||||
from .univariate import Univariate, Uniform
|
||||
|
||||
|
||||
class UnitSphere(metaclass=ABCMeta):
|
||||
class UnitSphere(ABC):
|
||||
"""Distribution of points on the unit sphere.
|
||||
|
||||
This abstract class is used for angular distributions, since a direction is
|
||||
|
|
@ -86,7 +85,7 @@ class PolarAzimuthal(UnitSphere):
|
|||
|
||||
"""
|
||||
|
||||
def __init__(self, mu=None, phi=None, reference_uvw=[0., 0., 1.]):
|
||||
def __init__(self, mu=None, phi=None, reference_uvw=(0., 0., 1.)):
|
||||
super().__init__(reference_uvw)
|
||||
if mu is not None:
|
||||
self.mu = mu
|
||||
|
|
@ -158,9 +157,7 @@ class PolarAzimuthal(UnitSphere):
|
|||
|
||||
|
||||
class Isotropic(UnitSphere):
|
||||
"""Isotropic angular distribution.
|
||||
|
||||
"""
|
||||
"""Isotropic angular distribution."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
|
@ -252,16 +249,13 @@ class Monodirectional(UnitSphere):
|
|||
return monodirectional
|
||||
|
||||
|
||||
class Spatial(metaclass=ABCMeta):
|
||||
class Spatial(ABC):
|
||||
"""Distribution of locations in three-dimensional Euclidean space.
|
||||
|
||||
Classes derived from this abstract class can be used for spatial
|
||||
distributions of source sites.
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def to_xml_element(self):
|
||||
return ''
|
||||
|
|
@ -309,7 +303,6 @@ class CartesianIndependent(Spatial):
|
|||
"""
|
||||
|
||||
def __init__(self, x, y, z):
|
||||
super().__init__()
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.z = z
|
||||
|
|
@ -417,7 +410,6 @@ class SphericalIndependent(Spatial):
|
|||
"""
|
||||
|
||||
def __init__(self, r, theta, phi, origin=(0.0, 0.0, 0.0)):
|
||||
super().__init__()
|
||||
self.r = r
|
||||
self.theta = theta
|
||||
self.phi = phi
|
||||
|
|
@ -537,7 +529,6 @@ class CylindricalIndependent(Spatial):
|
|||
"""
|
||||
|
||||
def __init__(self, r, phi, z, origin=(0.0, 0.0, 0.0)):
|
||||
super().__init__()
|
||||
self.r = r
|
||||
self.phi = phi
|
||||
self.z = z
|
||||
|
|
@ -646,7 +637,6 @@ class Box(Spatial):
|
|||
|
||||
|
||||
def __init__(self, lower_left, upper_right, only_fissionable=False):
|
||||
super().__init__()
|
||||
self.lower_left = lower_left
|
||||
self.upper_right = upper_right
|
||||
self.only_fissionable = only_fissionable
|
||||
|
|
@ -740,7 +730,6 @@ class Point(Spatial):
|
|||
"""
|
||||
|
||||
def __init__(self, xyz=(0., 0., 0.)):
|
||||
super().__init__()
|
||||
self.xyz = xyz
|
||||
|
||||
@property
|
||||
|
|
|
|||
|
|
@ -1,30 +1,31 @@
|
|||
from abc import ABCMeta, abstractmethod
|
||||
from abc import ABC, abstractmethod
|
||||
from collections.abc import Iterable
|
||||
from numbers import Real
|
||||
import sys
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
from openmc._xml import get_text
|
||||
from openmc.mixin import EqualityMixin
|
||||
from .._xml import get_text
|
||||
from ..mixin import EqualityMixin
|
||||
|
||||
|
||||
_INTERPOLATION_SCHEMES = ['histogram', 'linear-linear', 'linear-log',
|
||||
'log-linear', 'log-log']
|
||||
_INTERPOLATION_SCHEMES = [
|
||||
'histogram',
|
||||
'linear-linear',
|
||||
'linear-log',
|
||||
'log-linear',
|
||||
'log-log'
|
||||
]
|
||||
|
||||
|
||||
class Univariate(EqualityMixin, metaclass=ABCMeta):
|
||||
class Univariate(EqualityMixin, ABC):
|
||||
"""Probability distribution of a single random variable.
|
||||
|
||||
The Univariate class is an abstract class that can be derived to implement a
|
||||
specific probability distribution.
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def to_xml_element(self, element_name):
|
||||
return ''
|
||||
|
|
@ -81,7 +82,6 @@ class Discrete(Univariate):
|
|||
"""
|
||||
|
||||
def __init__(self, x, p):
|
||||
super().__init__()
|
||||
self.x = x
|
||||
self.p = p
|
||||
|
||||
|
|
@ -175,7 +175,6 @@ class Uniform(Univariate):
|
|||
"""
|
||||
|
||||
def __init__(self, a=0.0, b=1.0):
|
||||
super().__init__()
|
||||
self.a = a
|
||||
self.b = b
|
||||
|
||||
|
|
@ -264,7 +263,6 @@ class Maxwell(Univariate):
|
|||
"""
|
||||
|
||||
def __init__(self, theta):
|
||||
super().__init__()
|
||||
self.theta = theta
|
||||
|
||||
def __len__(self):
|
||||
|
|
@ -342,7 +340,6 @@ class Watt(Univariate):
|
|||
"""
|
||||
|
||||
def __init__(self, a=0.988e6, b=2.249e-6):
|
||||
super().__init__()
|
||||
self.a = a
|
||||
self.b = b
|
||||
|
||||
|
|
@ -430,7 +427,6 @@ class Normal(Univariate):
|
|||
"""
|
||||
|
||||
def __init__(self, mean_value, std_dev):
|
||||
super().__init__()
|
||||
self.mean_value = mean_value
|
||||
self.std_dev = std_dev
|
||||
|
||||
|
|
@ -525,7 +521,6 @@ class Muir(Univariate):
|
|||
"""
|
||||
|
||||
def __init__(self, e0=14.08e6, m_rat = 5., kt = 20000.):
|
||||
super().__init__()
|
||||
self.e0 = e0
|
||||
self.m_rat = m_rat
|
||||
self.kt = kt
|
||||
|
|
@ -634,7 +629,6 @@ class Tabular(Univariate):
|
|||
|
||||
def __init__(self, x, p, interpolation='linear-linear',
|
||||
ignore_negative=False):
|
||||
super().__init__()
|
||||
self._ignore_negative = ignore_negative
|
||||
self.x = x
|
||||
self.p = p
|
||||
|
|
@ -788,7 +782,6 @@ class Mixture(Univariate):
|
|||
"""
|
||||
|
||||
def __init__(self, probability, distribution):
|
||||
super().__init__()
|
||||
self.probability = probability
|
||||
self.distribution = distribution
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
from collections.abc import Iterable
|
||||
import re
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
import h5py
|
||||
import numpy as np
|
||||
|
||||
import openmc
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.region import Region
|
||||
from .region import Region
|
||||
|
||||
_VERSION_SUMMARY = 6
|
||||
|
||||
|
|
@ -55,9 +54,7 @@ class Summary:
|
|||
|
||||
self._read_nuclides()
|
||||
self._read_macroscopics()
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", openmc.IDWarning)
|
||||
self._read_geometry()
|
||||
self._read_geometry()
|
||||
|
||||
@property
|
||||
def date_and_time(self):
|
||||
|
|
@ -93,21 +90,25 @@ class Summary:
|
|||
def _read_macroscopics(self):
|
||||
if 'macroscopics/names' in self._f:
|
||||
names = self._f['macroscopics/names'][()]
|
||||
for name in names:
|
||||
self._macroscopics = name.decode()
|
||||
self._macroscopics = [name.decode() for name in names]
|
||||
|
||||
def _read_geometry(self):
|
||||
with warnings.catch_warnings():
|
||||
# We expect that new objects will be created with the same IDs as
|
||||
# objects that might already exist in the Python process (if it was
|
||||
# also used to create the model), so silence ID warnings
|
||||
warnings.simplefilter("ignore", openmc.IDWarning)
|
||||
|
||||
# Read in and initialize the Materials
|
||||
self._read_materials()
|
||||
# Read in and initialize the Materials
|
||||
self._read_materials()
|
||||
|
||||
# Read native geometry only
|
||||
if "dagmc" not in self._f['geometry'].attrs.keys():
|
||||
self._read_surfaces()
|
||||
cell_fills = self._read_cells()
|
||||
self._read_universes()
|
||||
self._read_lattices()
|
||||
self._finalize_geometry(cell_fills)
|
||||
# Read native geometry only
|
||||
if "dagmc" not in self._f['geometry'].attrs.keys():
|
||||
self._read_surfaces()
|
||||
cell_fills = self._read_cells()
|
||||
self._read_universes()
|
||||
self._read_lattices()
|
||||
self._finalize_geometry(cell_fills)
|
||||
|
||||
def _read_materials(self):
|
||||
for group in self._f['materials'].values():
|
||||
|
|
@ -135,11 +136,11 @@ class Summary:
|
|||
fill_type = group['fill_type'][()].decode()
|
||||
|
||||
if fill_type == 'material':
|
||||
fill = group['material'][()]
|
||||
fill_id = group['material'][()]
|
||||
elif fill_type == 'universe':
|
||||
fill = group['fill'][()]
|
||||
fill_id = group['fill'][()]
|
||||
else:
|
||||
fill = group['lattice'][()]
|
||||
fill_id = group['lattice'][()]
|
||||
|
||||
region = group['region'][()].decode() if 'region' in group else ''
|
||||
|
||||
|
|
@ -162,7 +163,7 @@ class Summary:
|
|||
cell.temperature = group['temperature'][()]
|
||||
|
||||
# Store Cell fill information for after Universe/Lattice creation
|
||||
cell_fills[cell.id] = (fill_type, fill)
|
||||
cell_fills[cell.id] = (fill_type, fill_id)
|
||||
|
||||
# Generate Region object given infix expression
|
||||
if region:
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
from abc import ABCMeta, abstractmethod
|
||||
from abc import ABC, abstractmethod
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
from copy import deepcopy
|
||||
import math
|
||||
from numbers import Real
|
||||
from xml.etree import ElementTree as ET
|
||||
from warnings import warn, catch_warnings, simplefilter
|
||||
import math
|
||||
|
||||
import numpy as np
|
||||
|
||||
from openmc.checkvalue import check_type, check_value, check_length
|
||||
from openmc.region import Region, Intersection, Union
|
||||
from openmc.mixin import IDManagerMixin, IDWarning
|
||||
from .checkvalue import check_type, check_value, check_length
|
||||
from .mixin import IDManagerMixin, IDWarning
|
||||
from .region import Region, Intersection, Union
|
||||
|
||||
|
||||
_BOUNDARY_TYPES = ['transmission', 'vacuum', 'reflective', 'periodic', 'white']
|
||||
|
|
@ -103,7 +103,7 @@ def get_rotation_matrix(rotation, order='xyz'):
|
|||
return R3 @ R2 @ R1
|
||||
|
||||
|
||||
class Surface(IDManagerMixin, metaclass=ABCMeta):
|
||||
class Surface(IDManagerMixin, ABC):
|
||||
"""An implicit surface with an associated boundary condition.
|
||||
|
||||
An implicit surface is defined as the set of zeros of a function of the
|
||||
|
|
@ -459,7 +459,7 @@ class Surface(IDManagerMixin, metaclass=ABCMeta):
|
|||
return cls(*coeffs, **kwargs)
|
||||
|
||||
|
||||
class PlaneMixin(metaclass=ABCMeta):
|
||||
class PlaneMixin:
|
||||
"""A Plane mixin class for all operations on order 1 surfaces"""
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
|
@ -918,7 +918,7 @@ class ZPlane(PlaneMixin, Surface):
|
|||
return point[2] - self.z0
|
||||
|
||||
|
||||
class QuadricMixin(metaclass=ABCMeta):
|
||||
class QuadricMixin:
|
||||
"""A Mixin class implementing common functionality for quadric surfaces"""
|
||||
|
||||
@property
|
||||
|
|
|
|||
|
|
@ -1,22 +1,20 @@
|
|||
from collections.abc import Iterable, MutableSequence
|
||||
import copy
|
||||
import re
|
||||
from functools import partial, reduce
|
||||
from itertools import product
|
||||
from numbers import Integral, Real
|
||||
import operator
|
||||
from pathlib import Path
|
||||
import warnings
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import h5py
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import scipy.sparse as sps
|
||||
import h5py
|
||||
|
||||
import openmc
|
||||
import openmc.checkvalue as cv
|
||||
from openmc._xml import clean_indentation
|
||||
from ._xml import clean_indentation
|
||||
from .mixin import IDManagerMixin
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import sys
|
||||
from numbers import Integral
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.mixin import EqualityMixin, IDManagerMixin
|
||||
from .mixin import EqualityMixin, IDManagerMixin
|
||||
|
||||
|
||||
class TallyDerivative(EqualityMixin, IDManagerMixin):
|
||||
|
|
@ -51,14 +50,9 @@ class TallyDerivative(EqualityMixin, IDManagerMixin):
|
|||
string = 'Tally Derivative\n'
|
||||
string += '{: <16}=\t{}\n'.format('\tID', self.id)
|
||||
string += '{: <16}=\t{}\n'.format('\tVariable', self.variable)
|
||||
|
||||
if self.variable == 'density':
|
||||
string += '{: <16}=\t{}\n'.format('\tMaterial', self.material)
|
||||
elif self.variable == 'nuclide_density':
|
||||
string += '{: <16}=\t{}\n'.format('\tMaterial', self.material)
|
||||
string += '{: <16}=\t{}\n'.format('\tMaterial', self.material)
|
||||
if self.variable == 'nuclide_density':
|
||||
string += '{: <16}=\t{}\n'.format('\tNuclide', self.nuclide)
|
||||
elif self.variable == 'temperature':
|
||||
string += '{: <16}=\t{}\n'.format('\tMaterial', self.material)
|
||||
|
||||
return string
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
from collections.abc import Iterable
|
||||
from numbers import Real
|
||||
from xml.etree import ElementTree as ET
|
||||
import sys
|
||||
import warnings
|
||||
from collections.abc import Iterable
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
from .mixin import EqualityMixin
|
||||
|
||||
|
||||
class Trigger:
|
||||
class Trigger(EqualityMixin):
|
||||
"""A criterion for when to finish a simulation based on tally uncertainties.
|
||||
|
||||
Parameters
|
||||
|
|
@ -35,14 +34,11 @@ class Trigger:
|
|||
self.threshold = threshold
|
||||
self._scores = []
|
||||
|
||||
def __eq__(self, other):
|
||||
return str(self) == str(other)
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Trigger\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._trigger_type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tThreshold', '=\t', self._threshold)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self._scores)
|
||||
string += '{: <16}=\t{}\n'.format('\tType', self._trigger_type)
|
||||
string += '{: <16}=\t{}\n'.format('\tThreshold', self._threshold)
|
||||
string += '{: <16}=\t{}\n'.format('\tScores', self._scores)
|
||||
return string
|
||||
|
||||
@property
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
from copy import copy, deepcopy
|
||||
from numbers import Integral, Real
|
||||
from numbers import Real
|
||||
import random
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.plots import _SVG_COLORS
|
||||
from openmc.mixin import IDManagerMixin
|
||||
from .mixin import IDManagerMixin
|
||||
from .plots import _SVG_COLORS
|
||||
|
||||
|
||||
class Universe(IDManagerMixin):
|
||||
|
|
@ -55,7 +54,7 @@ class Universe(IDManagerMixin):
|
|||
self._volume = None
|
||||
self._atoms = {}
|
||||
|
||||
# Keys - Cell IDs
|
||||
# Keys - Cell IDs
|
||||
# Values - Cells
|
||||
self._cells = OrderedDict()
|
||||
|
||||
|
|
@ -64,10 +63,9 @@ class Universe(IDManagerMixin):
|
|||
|
||||
def __repr__(self):
|
||||
string = 'Universe\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tCells', '=\t',
|
||||
list(self._cells.keys()))
|
||||
string += '{: <16}=\t{}\n'.format('\tID', self._id)
|
||||
string += '{: <16}=\t{}\n'.format('\tName', self._name)
|
||||
string += '{: <16}=\t{}\n'.format('\tCells', list(self._cells.keys()))
|
||||
return string
|
||||
|
||||
@property
|
||||
|
|
@ -543,7 +541,7 @@ class Universe(IDManagerMixin):
|
|||
|
||||
"""
|
||||
# Iterate over all Cells
|
||||
for cell_id, cell in self._cells.items():
|
||||
for cell in self._cells.values():
|
||||
|
||||
# If the cell was already written, move on
|
||||
if memo and cell in memo:
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ def test_failure(pin_mats, good_radii):
|
|||
pin(surfs, pin_mats)
|
||||
|
||||
# Passing cells argument
|
||||
with pytest.raises(SyntaxError, match="Cells"):
|
||||
with pytest.raises(ValueError, match="Cells"):
|
||||
pin(surfs, pin_mats, cells=[])
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue