Replace float_endf with a fast C/Cython version

This commit is contained in:
Paul Romano 2019-04-03 08:06:01 -05:00
parent 49c49110b7
commit d79524b9ce
5 changed files with 59 additions and 3 deletions

8
openmc/data/_endf.pyx Normal file
View file

@ -0,0 +1,8 @@
# cython: c_string_type=str, c_string_encoding=ascii
cdef extern from "endf.c":
double cfloat_endf(const char* buffer, int n)
def float_endf(s):
cdef const char* c_string = s
return cfloat_endf(c_string, len(s))

37
openmc/data/endf.c Normal file
View file

@ -0,0 +1,37 @@
#include <stdlib.h>
double cfloat_endf(const char* buffer, int n)
{
char arr[12]; // 11 characters plus a null terminator
int j = 0; // current position in arr
int found_decimal = 0;
int found_exponent = 0;
for (int i = 0; i < n; ++i) {
// Skip whitespace characters
char c = buffer[i];
if (c == ' ') continue;
if (found_decimal) {
if (!found_exponent) {
if (c == '+' || c == '-') {
// In the case that we encounter +/- and we haven't yet encountered
// e/E, we manually add it
arr[j++] = 'e';
found_exponent = 1;
} else if (c == 'e' || c == 'E') {
found_exponent = 1;
}
}
} else if (c == '.') {
found_decimal = 1;
}
// Copy character
arr[j++] = c;
}
// Done copying. Add null terminator and convert to double
arr[j] = '\0';
return atof(arr);
}

View file

@ -20,6 +20,11 @@ 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
try:
from ._endf import float_endf
_CYTHON = True
except ImportError:
_CYTHON = False
_LIBRARY = {0: 'ENDF/B', 1: 'ENDF/A', 2: 'JEFF', 3: 'EFF',
@ -69,7 +74,7 @@ SUM_RULES = {1: [2, 3],
ENDF_FLOAT_RE = re.compile(r'([\s\-\+]?\d*\.\d+)([\+\-]) ?(\d+)')
def float_endf(s):
def py_float_endf(s):
"""Convert string of floating point number in ENDF to float.
The ENDF-6 format uses an 'e-less' floating point number format,
@ -92,6 +97,10 @@ def float_endf(s):
return float(ENDF_FLOAT_RE.sub(r'\1e\2\3', s))
if not _CYTHON:
float_endf = py_float_endf
def int_endf(s):
"""Convert string of integer number in ENDF to int.

View file

@ -68,10 +68,10 @@ kwargs = {
},
}
# If Cython is present, add resonance reconstruction capability
# If Cython is present, add resonance reconstruction and fast float_endf
if have_cython:
kwargs.update({
'ext_modules': cythonize('openmc/data/reconstruct.pyx'),
'ext_modules': cythonize('openmc/data/*.pyx'),
'include_dirs': [np.get_include()]
})

View file

@ -9,6 +9,8 @@ def test_float_endf():
assert endf.float_endf('6.022-23') == approx(6.022e-23)
assert endf.float_endf(' +1.01+ 2') == approx(101.0)
assert endf.float_endf(' -1.01- 2') == approx(-0.0101)
assert endf.float_endf('+ 2 . 3+ 1') == approx(23.0)
assert endf.float_endf('-7 .8 -1') == approx(-0.78)
def test_int_endf():