|
2 | 2 | from abc import ABC, abstractmethod |
3 | 3 | from collections import defaultdict |
4 | 4 | from collections.abc import Iterable, Sequence |
5 | | -from copy import deepcopy |
6 | | -from math import sqrt, pi, exp |
| 5 | +from math import sqrt, pi, exp, log |
7 | 6 | from numbers import Real |
8 | 7 | from warnings import warn |
9 | 8 |
|
|
14 | 13 | import scipy |
15 | 14 |
|
16 | 15 | import openmc.checkvalue as cv |
| 16 | +from openmc.data import atomic_mass, NEUTRON_MASS |
17 | 17 | from .._xml import get_elem_list, get_text |
18 | 18 | from ..mixin import EqualityMixin |
19 | 19 |
|
@@ -1277,6 +1277,138 @@ def Muir(*args, **kwargs): |
1277 | 1277 | return muir(*args, **kwargs) |
1278 | 1278 |
|
1279 | 1279 |
|
| 1280 | +def fusion_neutron_spectrum( |
| 1281 | + ion_temp: float, |
| 1282 | + reactants: str = 'DD', |
| 1283 | + bias: Univariate | None = None |
| 1284 | +) -> Normal: |
| 1285 | + r"""Return a Gaussian energy distribution for fusion neutron emission. |
| 1286 | +
|
| 1287 | + Computes the mean energy and spectral width of the neutron energy spectrum |
| 1288 | + from thermonuclear fusion reactions in a plasma with Maxwellian ion velocity |
| 1289 | + distributions. The mean neutron energy is calculated as |
| 1290 | +
|
| 1291 | + .. math:: |
| 1292 | +
|
| 1293 | + \langle E_n \rangle = E_0 + \Delta E_\text{th} |
| 1294 | +
|
| 1295 | + where :math:`E_0` is the neutron energy at zero ion temperature and |
| 1296 | + :math:`\Delta E_\text{th}` is the thermal peak shift due to the motion of |
| 1297 | + the reacting ions. The spectral width is characterized by the FWHM: |
| 1298 | +
|
| 1299 | + .. math:: |
| 1300 | +
|
| 1301 | + W_{1/2} = \omega_0 (1 + \delta_\omega) \sqrt{T_i} |
| 1302 | +
|
| 1303 | + where :math:`\omega_0` is the width at the :math:`T_i \to 0` limit and |
| 1304 | + :math:`\delta_\omega` is a temperature-dependent correction term. Both |
| 1305 | + :math:`\Delta E_\text{th}` and :math:`\delta_\omega` are evaluated using |
| 1306 | + interpolation formulas from `Ballabio et al. |
| 1307 | + <https://doi.org/10.1088/0029-5515/38/11/310>`_: Table III for :math:`0 < |
| 1308 | + T_i \le 40` keV and Table IV for :math:`40 < T_i < 100` keV. The returned |
| 1309 | + distribution is a normal (Gaussian) approximation to the spectrum. |
| 1310 | +
|
| 1311 | + .. versionadded:: 0.15.4 |
| 1312 | +
|
| 1313 | + Parameters |
| 1314 | + ---------- |
| 1315 | + ion_temp : float |
| 1316 | + Ion temperature of the plasma in [eV]. |
| 1317 | + reactants : {'DD', 'DT'} |
| 1318 | + Fusion reactants. 'DD' corresponds to the D(d,n)\ :sup:`3`\ He reaction |
| 1319 | + and 'DT' to the T(d,n)\ :math:`\alpha` reaction. |
| 1320 | + bias : openmc.stats.Univariate, optional |
| 1321 | + Distribution for biased sampling. |
| 1322 | +
|
| 1323 | + Returns |
| 1324 | + ------- |
| 1325 | + openmc.stats.Normal |
| 1326 | + Normal distribution with mean and standard deviation corresponding to |
| 1327 | + the first and second moments of the fusion neutron energy spectrum. Both |
| 1328 | + the mean and standard deviation are in [eV]. |
| 1329 | +
|
| 1330 | + """ |
| 1331 | + if ion_temp < 0.0 or ion_temp > 100e3: |
| 1332 | + raise ValueError("Ion temperature must be between 0 and 100 keV.") |
| 1333 | + |
| 1334 | + # Formulas from doi:10.1088/0029-5515/38/11/310 |
| 1335 | + mn = NEUTRON_MASS |
| 1336 | + md = atomic_mass('H2') |
| 1337 | + ev_per_c2 = 931.49410372*1e6 |
| 1338 | + if reactants == 'DD': |
| 1339 | + mhe3 = atomic_mass('He3') |
| 1340 | + Q = (md + md - mhe3 - mn)*ev_per_c2 |
| 1341 | + E_n = mhe3/(mhe3 + mn)*Q |
| 1342 | + w0 = 82.542 |
| 1343 | + |
| 1344 | + # Low-T constants for peak shift (Table III) |
| 1345 | + a1 = 4.69515 |
| 1346 | + a2 = -0.040729 |
| 1347 | + a3 = 0.47 |
| 1348 | + a4 = 0.81844 |
| 1349 | + |
| 1350 | + # Low-T constants for width correction (Table III) |
| 1351 | + b1 = 1.7013e-3 |
| 1352 | + b2 = 0.16888 |
| 1353 | + b3 = 0.49 |
| 1354 | + b4 = 7.9460e-4 |
| 1355 | + |
| 1356 | + # High-T constants for peak shift (Table IV) |
| 1357 | + a5 = 18.225 |
| 1358 | + a6 = 2.1525 |
| 1359 | + |
| 1360 | + # High-T constants for width correction (Table IV) |
| 1361 | + b5 = 8.4619e-3 |
| 1362 | + b6 = 8.3241e-4 |
| 1363 | + |
| 1364 | + elif reactants == 'DT': |
| 1365 | + mt = atomic_mass('H3') |
| 1366 | + ma = atomic_mass('He4') |
| 1367 | + Q = (md + mt - ma - mn)*ev_per_c2 |
| 1368 | + E_n = ma/(ma + mn)*Q |
| 1369 | + w0 = 177.259 |
| 1370 | + |
| 1371 | + # Low-T constants for peak shift (Table III) |
| 1372 | + a1 = 5.30509 |
| 1373 | + a2 = 2.4736e-3 |
| 1374 | + a3 = 1.84 |
| 1375 | + a4 = 1.3818 |
| 1376 | + |
| 1377 | + # Low-T constants for width correction (Table III) |
| 1378 | + b1 = 5.1068e-4 |
| 1379 | + b2 = 7.6223e-3 |
| 1380 | + b3 = 1.78 |
| 1381 | + b4 = 8.7691e-5 |
| 1382 | + |
| 1383 | + # High-T constants for peak shift (Table IV) |
| 1384 | + a5 = 37.771 |
| 1385 | + a6 = 0.92181 |
| 1386 | + |
| 1387 | + # High-T constants for width correction (Table IV) |
| 1388 | + b5 = 2.0199e-3 |
| 1389 | + b6 = 5.9501e-5 |
| 1390 | + else: |
| 1391 | + raise ValueError("Invalid reactants specified. Must be 'DD' or 'DT'.") |
| 1392 | + |
| 1393 | + # Ion temperature in keV |
| 1394 | + T = ion_temp * 1e-3 |
| 1395 | + |
| 1396 | + if T <= 40.0: |
| 1397 | + # Low-temperature interpolation (Table III, 0 < T_i <= 40 keV) |
| 1398 | + Delta_E = a1/(1 + a2*T**a3)*T**(2/3) + a4*T |
| 1399 | + delta_w = b1/(1 + b2*T**b3)*T**(2/3) + b4*T |
| 1400 | + else: |
| 1401 | + # High-temperature interpolation (Table IV, 40 < T_i < 100 keV) |
| 1402 | + Delta_E = a5 + a6*T |
| 1403 | + delta_w = b5 + b6*T |
| 1404 | + |
| 1405 | + # Calculate FWHM |
| 1406 | + fwhm = (w0*(1 + delta_w) * sqrt(T))*1e3 |
| 1407 | + |
| 1408 | + sigma = fwhm / (2*sqrt(2*log(2))) |
| 1409 | + return Normal(E_n + Delta_E * 1e3, sigma, bias=bias) |
| 1410 | + |
| 1411 | + |
1280 | 1412 | class Tabular(Univariate): |
1281 | 1413 | """Piecewise continuous probability distribution. |
1282 | 1414 |
|
|
0 commit comments