Skip to content

Commit

Permalink
fixed RZ len bug and filtering 0 val TT reactions
Browse files Browse the repository at this point in the history
  • Loading branch information
shimwell committed Aug 1, 2024
1 parent 62d72eb commit 280068a
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 95 deletions.
4 changes: 2 additions & 2 deletions examples/point_source_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
my_source = fusion_point_source(
coordinate=(0, 0, 0),
temperature=20000.0,
fuel={"D": 0.01, "T": 0.99}, # note this is mainly tritium fuel so that TT reactions are more likely
fuel={"D": 0.09, "T": 0.91}, # note this is mainly tritium fuel so that TT reactions are more likely
)

# Tell OpenMC we're going to use our custom source
Expand All @@ -38,7 +38,7 @@

plot = plot_source_energy(
this=settings,
n_samples=1000000, # increase this value for a smoother plot
n_samples=2000000, # increase this value for a smoother plot
energy_bins=np.linspace(0, 16e6, 1000),
yaxis_type="log",
)
Expand Down
4 changes: 2 additions & 2 deletions examples/tokamak_source_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
# optionally if you would like to plot the direction of particles then another package can be used
# https://github.com/fusion-energy/openmc_source_plotter

from openmc_source_plotter import plot_source_direction
from openmc_source_plotter import plot_source_position

plot = plot_source_direction(this=settings, n_samples=200)
plot = plot_source_position(this=settings, n_samples=200)

plot.show()
57 changes: 37 additions & 20 deletions src/openmc_plasma_source/fuel_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,12 @@ def get_neutron_energy_distribution(
strength_TT = 1.0
dNdE_TT = strength_TT * nst.dNdE_TT(E_pspec, ion_temperature)
tt_source = openmc.stats.Tabular(E_pspec * 1e6, dNdE_TT)
return {"TT": tt_source}, {"TT": strength_TT}
return tt_source

elif reactions == ["DD"]:
strength_DD = 1.0
dd_source = openmc.stats.Normal(mean_value=DDmean, std_dev=DD_std_dev)
return {"DD": dd_source}, {"DD": strength_DD}
return dd_source

# DT, DD and TT reaction
else:
Expand All @@ -180,17 +180,6 @@ def get_neutron_energy_distribution(
"tt", 1.0, ion_temperature, fuel["D"], fuel["T"]
)

total_strength = sum([strength_TT, strength_DD, 1.0])

dNdE_TT = strength_TT * nst.dNdE_TT(E_pspec, ion_temperature)

# removing any zeros from the end of the array
dNdE_TT = np.trim_zeros(dNdE_TT, "b")
# making array lengths match
E_pspec = E_pspec[: len(dNdE_TT)]

tt_source = openmc.stats.Tabular(E_pspec, dNdE_TT)

dd_source = openmc.stats.Normal(mean_value=DDmean, std_dev=DD_std_dev)
# normal could be done with Muir but in this case we have the mean and std dev from NeSST
# dd_source = openmc.stats.muir(e0=DDmean * 1e6, m_rat=4, kt=ion_temperature)
Expand All @@ -199,10 +188,38 @@ def get_neutron_energy_distribution(
# normal could be done with Muir but in this case we have the mean and std dev from NeSST
# dt_source = openmc.stats.muir(e0=DTmean * 1e6, m_rat=5, kt=ion_temperature)

openmc_univariate = [tt_source, dd_source, dt_source]
probabilities = [
strength_TT / total_strength,
strength_DD / total_strength,
1.0 / total_strength,
]
return openmc.data.combine_distributions(openmc_univariate, probabilities)
dNdE_TT = strength_TT * nst.dNdE_TT(E_pspec, ion_temperature)

# removing any zeros from the end of the array
dNdE_TT = np.trim_zeros(dNdE_TT, "b")
# making array lengths match
E_pspec = E_pspec[: len(dNdE_TT)]

openmc_univariate = [dd_source, dt_source]

# sometimes bins are empty
if len(E_pspec) ==0:
total_strength = sum([strength_DD, 1.0])
probabilities = [
strength_DD / total_strength,
1.0 / total_strength
]
else:
total_strength = sum([strength_TT, strength_DD, 1.0])
tt_source = openmc.stats.Tabular(E_pspec[1:], dNdE_TT[1:])
probabilities = [
strength_DD / total_strength,
1.0 / total_strength,
strength_TT / total_strength
]
openmc_univariate.append(tt_source)




return openmc.stats.Mixture(probabilities,openmc_univariate)
# bug reported for combine_distributions #3105 on openmc
# return openmc.data.combine_distributions(
# dists=openmc_univariate,
# probs=probabilities
# )
102 changes: 31 additions & 71 deletions src/openmc_plasma_source/tokamak_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,7 @@ def tokamak_source(
fuel_densities = {}
for key, value in fuel.items():
fuel_densities[key] = densities * value
print('fuel_densities',fuel_densities.keys())
reactions = get_reactions_from_fuel(fuel)
print('freactions',reactions)

neutron_source_density = {}
total_source_density = 0
Expand All @@ -189,10 +187,10 @@ def tokamak_source(

all_sources = []
for reaction in reactions:
neutron_source_density = neutron_source_density[reaction] / total_source_density
strengths = neutron_source_density[reaction] / total_source_density

sources = tokamak_make_openmc_sources(
strengths=neutron_source_density,
strengths=strengths,
angles=angles,
temperatures=temperatures,
fuel=fuel,
Expand Down Expand Up @@ -267,7 +265,7 @@ def tokamak_ion_temperature(
r (float, ndarray): minor radius (cm)
Returns:
float, ndarray: ion temperature (keV)
float, ndarray: ion temperature (eV)
"""

r = np.asarray(r)
Expand Down Expand Up @@ -295,7 +293,7 @@ def tokamak_ion_temperature(
/ (major_radius - pedestal_radius)
),
)
return temperature
return temperature*1e3


def tokamak_convert_a_alpha_to_R_Z(
Expand Down Expand Up @@ -362,40 +360,32 @@ def tokamak_make_openmc_sources(

sources = []
# create a ring source for each sample in the plasma source
for i, (RZ_val, temperature) in enumerate(zip(RZ, temperatures)):
# extract the RZ values accordingly
radius = openmc.stats.Discrete([RZ_val[0]], [1])
z_values = openmc.stats.Discrete([RZ_val[1]], [1])
angle = openmc.stats.Uniform(a=angles[0], b=angles[1])

energy_distributions_and_dist_strengths = get_neutron_energy_distribution(
ion_temperature=temperature,
fuel=fuel,
)

# now we have potentially 3 distributions (DT, DD, TT)
for reaction, (
energy_distribution,
dist_strength,
) in energy_distributions_and_dist_strengths.items():

if dist_strength * strengths[reaction][i] > 0.0:
my_source = openmc.IndependentSource()

# create a ring source
my_source.space = openmc.stats.CylindricalIndependent(
r=radius, phi=angle, z=z_values, origin=(0.0, 0.0, 0.0)
)
my_source.angle = openmc.stats.Isotropic()

my_source.energy = energy_distribution

# the strength of the source (its probability) is given by the
# strength of the energy distribution and the location distribution
my_source.strength = dist_strength * strengths[reaction][i]

# append to the list of sources
sources.append(my_source)
R_vals= RZ[0]
Z_vals=RZ[1]
assert len(Z_vals) == len(R_vals) == len(temperatures) == len(strengths)
for (R_val, Z_val, temperature, strength) in zip(R_vals, Z_vals, temperatures, strengths):

if strength > 0.0:
radius = openmc.stats.Discrete([R_val], [1])
z_values = openmc.stats.Discrete([Z_val], [1])
angle = openmc.stats.Uniform(a=angles[0], b=angles[1])

my_source = openmc.IndependentSource()
my_source.energy = get_neutron_energy_distribution(
ion_temperature=temperature,
fuel=fuel,
)

# create a ring source
my_source.space = openmc.stats.CylindricalIndependent(
r=radius, phi=angle, z=z_values, origin=(0.0, 0.0, 0.0)
)
my_source.angle = openmc.stats.Isotropic()

my_source.strength = strength

# append to the list of sources
sources.append(my_source)
return sources


Expand All @@ -405,7 +395,7 @@ def tokamak_neutron_source_density(ion_density, ion_temperature, reaction):
Args:
ion_density (float, ndarray): Ion density (m-3)
ion_temperature (float, ndarray): Ion temperature (keV)
ion_temperature (float, ndarray): Ion temperature (eV)
reaction (str): The fusion reactions to consider e.g. 'DD'
Returns:
float, ndarray: Neutron source density (neutron/s/m3)
Expand All @@ -422,33 +412,3 @@ def tokamak_neutron_source_density(ion_density, ion_temperature, reaction):
return ion_density * reac_DT(ion_temperature) # could use _DT_xs instead
else:
raise ValueError('Reaction {reaction} not in available options ["DD", "DT", "TT"]')


# TODO consider replace with NeSST or getting DD version as well
def _DT_xs(ion_temperature):
"""Sadler–Van Belle formula
Ref : https://doi.org/10.1016/j.fusengdes.2012.02.025
Args:
ion_temperature (float, ndarray): ion temperature in eV
Returns:
float, ndarray: the DT cross section at the given temperature
"""
ion_temperature_kev = np.asarray(ion_temperature / 1e3)
c = [
2.5663271e-18,
19.983026,
2.5077133e-2,
2.5773408e-3,
6.1880463e-5,
6.6024089e-2,
8.1215505e-3,
]
U = 1 - ion_temperature_kev * (
c[2] + ion_temperature_kev * (c[3] - c[4] * ion_temperature_kev)
) / (1.0 + ion_temperature_kev * (c[5] + c[6] * ion_temperature_kev))
val = (
c[0]
* np.exp(-c[1] * (U / ion_temperature_kev) ** (1 / 3))
/ (U ** (5 / 6) * ion_temperature_kev ** (2 / 3))
)
return val

0 comments on commit 280068a

Please sign in to comment.