Skip to content

Commit c7b6175

Browse files
authored
Merge pull request #36 from LukeSeifert/endf-data
Adds ENDF/B-VII.1 (emission probability and half-life) data and JEFF-3.1.1 (cumulative fission yield) data
2 parents 23e8e12 + 9b500b8 commit c7b6175

File tree

23 files changed

+1635
-595
lines changed

23 files changed

+1635
-595
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ cython_debug/
182182
/examples/msre/postproc.json
183183
/examples/msre/images/*
184184

185+
/examples/pure_endfb71/*.csv
186+
/examples/pure_endfb71/postproc.json
187+
/examples/pure_endfb71/images/*
188+
189+
/examples/iaea_matching/*.csv
190+
/examples/iaea_matching/postproc.json
191+
/examples/iaea_matching/images/*
192+
193+
185194
/examples/prelim_results/*
186195
!/examples/prelim_results/input.json
187196
!/examples/prelim_results/results_generator.py

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# MoSDeN
2-
Molten Salt Delayed Neutron (MoSDeN) is a tool used for reconstruction of
2+
Molten Salt Delayed Neutron (MoSDeN) is a tool used for generation of
33
delayed neutron precursor groups in molten salt reactors.
4+
This tool can also be used for traditional light water reactors, as users
5+
can adjust ex-core residence times of fissile samples to be zero and chemical
6+
removal rates to be zero.
47

58
## History
69
This tool had a previous version in this repository accessible with
@@ -26,9 +29,12 @@ The exact organization of raw, unprocessed data is flexible, with some notable
2629
exceptions:
2730
- OpenMC chain files to be should all be in a subdirectory labeled with
2831
"omcchain" (see `preprocessing.py` for all keywords)
29-
- ENDF NFY data should all be in a subdirectory labeled `nfy`
32+
- ENDF fission yield data should all be in a subdirectory labeled `nfy`
33+
- JEFF fission yield data should all be in a subdirectory labeled `nfpy`
3034
- ENDF NFY files should be named "nfy-<ZZZ>_<ID>_<AAA>.csv", so 235U would be
3135
`nfy-092_U_235.csv`.
36+
- JEFF NFPY files should be named "nfpy_<NUMS>_<ZZ>-<ID>-<AAA>.dat", so 235U
37+
would be `nfpy_3542_92-U-235.dat` (the `NUMS` value meaning is unclear).
3238
- IAEA beta-delayed neutron emission data should be in a directory `iaea` and
3339
be called `eval.csv` (default when downloading data).
3440

download_data.sh

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ roman_to_int() {
1818
}
1919

2020
DATA_DIR="mosden/data/unprocessed"
21+
mkdir -p "$DATA_DIR"
2122

2223
# ENDF --------------------------------------------------------------------
2324
ENDF_VERSION="VII.1"
@@ -29,8 +30,6 @@ if [[ ! " ${ALLOWED_VERSIONS[*]} " =~ " ${ENDF_VERSION} " ]]; then
2930
exit 1
3031
fi
3132

32-
mkdir -p "$DATA_DIR"
33-
3433
LOWERCASE_VERSION=$(echo "${ENDF_VERSION//./}" | tr '[:upper:]' '[:lower:]')
3534

3635
ROMAN_PART="${LOWERCASE_VERSION//[0-9]/}"
@@ -40,27 +39,80 @@ LOWERCASE_VERSION="${INTEGER_VALUE}${DIGIT_PART}"
4039

4140
ENDF_DIR="${DATA_DIR}/endfb${LOWERCASE_VERSION}"
4241
NFY_DIR="${ENDF_DIR}"
42+
decay_DIR="${ENDF_DIR}"
4343
mkdir -p "$NFY_DIR"
4444

4545
if [[ "${ENDF_VERSION}" == "VII.1" ]]; then
4646
SEPARATOR="-"
47+
decay_SEPARATOR="-"
4748
elif [[ "${ENDF_VERSION}" == "VIII.0" ]]; then
4849
SEPARATOR="_"
50+
decay_SEPARATOR="_"
4951
fi
5052

5153
NFY_ZIP_NAME="ENDF-B-${ENDF_VERSION}${SEPARATOR}nfy.zip"
52-
NFY_URL="https://www.nndc.bnl.gov/endf-b7.1/zips/${NFY_ZIP_NAME}"
54+
NFY_URL="https://www.nndc.bnl.gov/endf-b${INTEGER_VALUE}.${DIGIT_PART}/zips/${NFY_ZIP_NAME}"
5355

5456
echo "Downloading NFY data for ENDF/B-${ENDF_VERSION}..."
5557
TEMP_ZIP="${NFY_DIR}/${NFY_ZIP_NAME}"
58+
echo "Accessing ${NFY_URL}"
5659
wget --show-progress -O "$TEMP_ZIP" "$NFY_URL"
5760
echo "Extracting NFY data..."
5861
unzip "$TEMP_ZIP" -d "$NFY_DIR"
5962
rm "$TEMP_ZIP"
6063
echo "NFY data handled"
6164

65+
decay_ZIP_NAME="ENDF-B-${ENDF_VERSION}${decay_SEPARATOR}decay.zip"
66+
decay_URL="https://www.nndc.bnl.gov/endf-b${INTEGER_VALUE}.${DIGIT_PART}/zips/${decay_ZIP_NAME}"
67+
68+
echo "Downloading decay data for ENDF/B-${ENDF_VERSION}..."
69+
TEMP_ZIP="${decay_DIR}/${decay_ZIP_NAME}"
70+
echo "Accessing ${decay_URL}"
71+
wget --show-progress -O "$TEMP_ZIP" "$decay_URL"
72+
echo "Extracting decay data..."
73+
unzip "$TEMP_ZIP" -d "$decay_DIR"
74+
rm "$TEMP_ZIP"
75+
echo "Decay data handled"
76+
6277
# /ENDF --------------------------------------------------------------------
6378

79+
80+
81+
# JEFF --------------------------------------------------------------------
82+
JEFF_VERSION="3.1.1"
83+
ALLOWED_VERSIONS=("3.1.1")
84+
85+
if [[ ! " ${ALLOWED_VERSIONS[*]} " =~ " ${JEFF_VERSION} " ]]; then
86+
echo "Error: Invalid JEFF version '${JEFF_VERSION}'"
87+
echo "Allowed versions: ${ALLOWED_VERSIONS[*]}"
88+
exit 1
89+
fi
90+
JEFF_VERSION_NOP="${JEFF_VERSION//./}"
91+
92+
JEFF_DIR="${DATA_DIR}/jeff${JEFF_VERSION_NOP}"
93+
NFY_DIR="${JEFF_DIR}/nfpy/"
94+
mkdir -p "$NFY_DIR"
95+
echo "Saving data to ${NFY_DIR}"
96+
97+
if [[ "${JEFF_VERSION}" == "3.1.1" ]]; then
98+
JEFF_URL="https://www-nds.iaea.org/public/download-endf/JEFF-${JEFF_VERSION}/nfpy/"
99+
fi
100+
101+
102+
echo "Downloading NFY data for JEFF-${JEFF_VERSION}..."
103+
echo "Accessing ${JEFF_URL}"
104+
wget --show-progress --recursive --no-parent --accept "*.zip" --no-host-directories --cut-dirs=3 -P "${JEFF_DIR}" "$JEFF_URL"
105+
echo "Extracting NFY data..."
106+
for f in "$NFY_DIR"/*.zip; do
107+
unzip "$f" -d "$NFY_DIR"
108+
done
109+
echo "Removing zip files..."
110+
rm "$NFY_DIR"/*.zip
111+
echo "NFY data handled"
112+
113+
114+
# /JEFF --------------------------------------------------------------------
115+
64116
# IAEA --------------------------------------------------------------------
65117
IAEA_DIR="${DATA_DIR}/iaea"
66118
IAEA_FILE="$IAEA_DIR/eval.csv"

examples/empty_run/input.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

examples/iaea_matching/input.json

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"name": "IAEA",
3+
"file_options": {
4+
"overwrite": {
5+
"preprocessing": true,
6+
"concentrations": true,
7+
"count_rate": true,
8+
"group_fitting": true,
9+
"postprocessing": true,
10+
"logger": true
11+
},
12+
"unprocessed_data_dir": "/home/luke/github/mosden/mosden/data/unprocessed/",
13+
"log_level": 20
14+
},
15+
"data_options": {
16+
"half_life": "iaea/eval.csv",
17+
"cross_section": "",
18+
"emission_probability": "iaea/eval.csv",
19+
"fission_yield": "jeff311/nfpy/",
20+
"decay_time_spacing": "log",
21+
"temperature_K": 920,
22+
"density_g_cm3": 2.3275,
23+
"energy_MeV": 0.0253e-6,
24+
"fissile_fractions": {
25+
"U235": 1.0
26+
}
27+
},
28+
"modeling_options": {
29+
"parent_feeding": false,
30+
"concentration_handling": "CFY",
31+
"count_rate_handling": "data",
32+
"reprocessing_locations": ["excore"],
33+
"reprocessing": {
34+
"Xe": 0.0
35+
},
36+
"irrad_type": "saturation",
37+
"incore_s": 10,
38+
"excore_s": 0,
39+
"net_irrad_s": 420,
40+
"decay_time": 1200,
41+
"num_decay_times": 800
42+
},
43+
"group_options": {
44+
"num_groups": 6,
45+
"method": "nlls",
46+
"samples": 5000,
47+
"sample_func": "normal"
48+
}
49+
}

examples/prelim_results/contribution_plots.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434

3535
all_data = [yields, counts, concs]
3636
all_nucs = [
37-
'Other',
3837
'Ge86',
3938
'I137',
4039
'As86',
@@ -45,7 +44,8 @@
4544
'Br88',
4645
'Br87',
4746
'Cs141',
48-
'Te136'
47+
'Te136',
48+
'Other'
4949
]
5050
all_nucs.reverse()
5151
postobj = PostProcess(None)
@@ -63,18 +63,13 @@
6363
colors.append(color_nucs[k])
6464
if k != 'Other':
6565
k = postobj._convert_nuc_to_latex(k)
66-
labels.append(k)
66+
labels.append(k + ', ' + str(round(v)) + '\%')
6767

68-
fig, ax = plt.subplots()
69-
_, _, autotexts = ax.pie(sizes, labels=labels, autopct='%1.1f%%',
70-
pctdistance=0.7, labeldistance=1.1,
68+
fig, ax = plt.subplots(subplot_kw=dict(aspect='equal'))
69+
_, _ = ax.pie(sizes, labels=labels, labeldistance=1.1,
7170
colors=colors)
7271
ax.axis('equal')
7372

74-
for i, autotext in enumerate(autotexts):
75-
autotext.set_color('black')
76-
autotext.set_path_effects([path_effects.Stroke(linewidth=2.0, foreground='white'),
77-
path_effects.Normal()])
7873
plt.tight_layout()
7974
fig.savefig(f'{counter}dnp_yield.png')
8075
plt.close()

examples/pure_endfb71/input.json

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"name": "ENDFB71 Data",
3+
"file_options": {
4+
"overwrite": {
5+
"preprocessing": true,
6+
"concentrations": true,
7+
"count_rate": true,
8+
"group_fitting": true,
9+
"postprocessing": true,
10+
"logger": true
11+
},
12+
"unprocessed_data_dir": "/home/luke/github/mosden/mosden/data/unprocessed/",
13+
"processed_data_dir": "/home/luke/github/mosden/examples/pure_endfb71/",
14+
"output_dir": "/home/luke/github/mosden/examples/pure_endfb71/",
15+
"log_level": 20,
16+
"log_file": "/home/luke/github/mosden/examples/pure_endfb71/log.log"
17+
},
18+
"data_options": {
19+
"half_life": "endfb71/decay/",
20+
"cross_section": "",
21+
"emission_probability": "endfb71/decay/",
22+
"fission_yield": "endfb71/nfy/",
23+
"decay_time_spacing": "log",
24+
"temperature_K": 920,
25+
"density_g_cm3": 2.3275,
26+
"energy_MeV": 0.0253e-6,
27+
"fissile_fractions": {
28+
"U235": 1.0
29+
}
30+
},
31+
"modeling_options": {
32+
"parent_feeding": false,
33+
"concentration_handling": "CFY",
34+
"count_rate_handling": "data",
35+
"reprocessing_locations": ["excore"],
36+
"reprocessing": {
37+
"Xe": 0.0
38+
},
39+
"irrad_type": "saturation",
40+
"incore_s": 10,
41+
"excore_s": 0,
42+
"net_irrad_s": 420,
43+
"decay_time": 1200,
44+
"num_decay_times": 800
45+
},
46+
"group_options": {
47+
"num_groups": 6,
48+
"method": "nlls",
49+
"samples": 5000,
50+
"sample_func": "normal"
51+
},
52+
"post_options": {
53+
"sensitivity_subplots": true
54+
}
55+
}

mosden/base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ def __init__(self, input_path: str) -> None:
2020
Path to the input file
2121
"""
2222
self.omc_data_words: list[str] = ['omcchain']
23-
self.endf_data_words: list[str] = ['nfy']
23+
self.endf_data_words: list[str] = ['nfy', 'decay']
2424
self.iaea_data_words: list[str] = ['iaea']
25+
self.jeff_data_words: list[str] = ['jeff']
2526

2627
self.input_path: str = input_path
2728
self.input_handler: InputHandler = InputHandler(input_path)

mosden/groupfit.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from time import time
1010
import warnings
1111
from tqdm import tqdm
12+
from scipy.linalg import svd
1213

1314

1415
class Grouper(BaseClass):
@@ -97,6 +98,7 @@ def _residual_function(
9798
parameters: np.ndarray[float],
9899
times: np.ndarray[float],
99100
counts: np.ndarray[float],
101+
count_err: np.ndarray[float],
100102
fit_func: Callable) -> float:
101103
"""
102104
Calculate the residual of the current set of parameters
@@ -108,7 +110,9 @@ def _residual_function(
108110
times : np.ndarray[float]
109111
List of times
110112
counts : np.ndarray[float]
111-
List of nominal times
113+
List of delayed neutron counts
114+
count_err : np.ndarray[float]
115+
List of count errors
112116
fit_func : Callable
113117
Function that takes times and parameters to return list of counts
114118
@@ -117,7 +121,7 @@ def _residual_function(
117121
residual : float
118122
Value of the residual
119123
"""
120-
residual = (counts - fit_func(times, parameters)) / (counts + 1e-12)
124+
residual = (counts - fit_func(times, parameters)) / (counts)
121125
return residual
122126

123127
def _pulse_fit_function(self,
@@ -267,20 +271,24 @@ def _nonlinear_least_squares(self,
267271
xtol=1e-12,
268272
verbose=0,
269273
max_nfev=1e5,
270-
args=(times, counts, fit_function))
271-
274+
args=(times, counts, count_err, fit_function))
275+
J = result.jac
276+
s = svd(J, compute_uv=False)
277+
condition_number = s[0] / s[-1]
278+
self.logger.info(f'{condition_number = }')
272279
sampled_params: list[float] = list()
273280
tracked_counts: list[float] = list()
274281
sorted_params = self._sort_params_by_half_life(result.x)
275282
sampled_params.append(sorted_params)
276283
countrate = CountRate(self.input_path)
277284
self.logger.info(f'Currently using {self.sample_func} sampling')
278285
for _ in tqdm(range(1, self.MC_samples), desc='Solving least-squares'):
279-
data = countrate.calculate_count_rate(
280-
MC_run=True, sampler_func=self.sample_func)
281-
count_sample = data['counts']
282286
with warnings.catch_warnings():
283287
warnings.simplefilter('ignore')
288+
data = countrate.calculate_count_rate(
289+
MC_run=True, sampler_func=self.sample_func)
290+
count_sample = data['counts']
291+
count_sample_err = data['sigma counts']
284292
result = least_squares(
285293
self._residual_function,
286294
result.x,
@@ -294,6 +302,7 @@ def _nonlinear_least_squares(self,
294302
args=(
295303
times,
296304
count_sample,
305+
count_sample_err,
297306
fit_function))
298307
tracked_counts.append([i for i in count_sample])
299308
sorted_params = self._sort_params_by_half_life(result.x)

0 commit comments

Comments
 (0)