fusion-energy / openmc-plasma-source Goto Github PK
View Code? Open in Web Editor NEWCreates a plasma source as an openmc.source object from input parameters that describe the plasma
License: MIT License
Creates a plasma source as an openmc.source object from input parameters that describe the plasma
License: MIT License
@shimwell what do you think of this?
I've implemented the method of this paper in this python code
What I didn't realise at first is that it's in fact what Andy did in parametric-plasma-source....
The sources should maybe have a method to compute the neutron rate in neutron/s .
usage could be
from openmc_plasma_source import FusionPointSource
my_source = FusionPointSource(.....)
neutron_rate = my_source.get_neutron_rate(fusion_power=1e9) # for 1 GW
I'm installing this package with a few others and hitting a requirements conflict.
Could we relax the version of matplotlib required
openmc-plasma-source 0.2.2 requires matplotlib>=3.4.3, but you'll have matplotlib 3.2.2 which is incompatible.
Currently just 'DD' or 'DT' sources are allowed using the fuel: str = "DT",
argument
We could add sources that have a fraction of DT and a different fraction of DD with a more flexible input for fuel.
How about fuel also accepts a list of tuples, where the first entry is 'DD' or 'DT' and the second entry is the relative strength
fuel = [('DD', 0.1, ('DT',0.90)]
or is a dictionary better
fuel = {'DD':0.1, 'DT':0.9}
While the pypi pip package has recently been updated the conda package update failed
https://github.com/fusion-energy/openmc-plasma-source/actions/runs/7061556757
package is missing code of conduct and contribution
perhaps this can be copied from paramak repo
Hello,
I am unsure if this is an issue or if, most likely, I am doing something wrong. When I try to plot the example plasma parameters (from EU-DEMO I believe), I get very strange values for the strength and neutron density in the core of the plasma. The only way I can affect it is by increasing the core ion density. The only thing that looks reasonable is the ion temperature.
I've tried changing the radius units to centimeter but same results. Unsure what I am doing wrong since I am just copying the parameters from the example.
Any help would be appreciated!
from openmc_plasma_source import TokamakSource, plotting
import matplotlib.pyplot as plt
source = TokamakSource(
elongation=1.557,
ion_density_centre=1.09e20,
ion_density_peaking_factor=1,
ion_density_pedestal=1.09e20,
ion_density_separatrix=3e19,
ion_temperature_centre=45.9,
ion_temperature_peaking_factor=8.06,
ion_temperature_pedestal=6.09,
ion_temperature_separatrix=0.1,
major_radius=9.06,
minor_radius=2.92258,
pedestal_radius=0.8 * 2.92258,
mode="H",
shafranov_factor=0.44789,
triangularity=0.270,
ion_temperature_beta=6)
fig = plotting.scatter_tokamak_source(source, quantity='ion_temperature')
plt.title('Ion temperature [keV]')
plt.savefig('ion_temp.png')
plt.close()
fig = plotting.scatter_tokamak_source(source, quantity='strength')
plt.title('Source strength []')
plt.savefig('strength.png')
plt.close()
fig = plotting.scatter_tokamak_source(source, quantity='neutron_source_density')
plt.title('Neutron source density [neutrons/m3/s]')
plt.savefig('neutron_density.png')
plt.close()
Hi John,
This is Mario Oliver (KF). I don't have much experience in GitHub so excuse me if this is not the right way to raise a comment on someone else's code.
I detected that in "src/openmc_plasma_source/tokamak_source.py", lines 42-44, shafranov_factor (float) should be defined in cm, not m.
Otherwise, formula in line 330 does not match.
Hope this is useful.
Best regards,
Mario
As @pshriwise suggested, it would be more convenient for users to have device specific plasma classes.
I can think of DEMO, ITER, MAST-U, SPARC (?)
Then again some parameters for these machines can change, but I guess the geometrical parameters can be fixed.
@shimwell do you know where we could find the info for these devices?
Currently, the strength of the sources in TokamakSource is directly the neutron source density (in neutron/m3/s).
However, to get relevant results, the sum of the strengths must be equal to 1.
We could still keep the neutron source density as an attribute though.
Test that point coordinates are generated within the ranges expected.
This is tricky for random samples as the results change
Allow for a wide tolerance to account for random distributions
Perhaps fixing the seed in openmc could help, openmc has a settings.seed
value that defaults to 1
openmc-plasma-source/openmc_plasma_source/tokamak_source.py
Lines 271 to 274 in fce6e92
This is broken and should be removed
The only dependency here is numpy really, it should be added either as a requirements.txt or in the setup.py
Currently, users can control the radius and the coverage of the FusionRingSource.
The z placement is assumed to be zero.
However, users should be able to control this z placement:
class FusionRingSource(openmc.Source):
"""An openmc.Source object with some presets to make it more convenient
for fusion simulations using a ring source. All attributes can be changed
after initialization if required. Default isotropic ring source with a Muir
energy distribution.
Args:
radius: the inner radius of the ring source
start_angle: the start angle of the ring in radians,
stop_angle: the end angle of the ring in radians,
temperature: the temperature to use in the Muir distribution in eV,
"""
def __init__(
self,
radius,
start_angle: float =0.,
stop_angle: float = 6.28318530718,
z_placement=0,
temperature: float = 20000.,
fuel='DT'
):
@shimwell what would you think of adding to ops some plotting features by importing openmc_source_plotter?
I wonder if the packages should be merged.
I guess the question is: "Would the openmc_source_plotter be used outside of fusion applications?"
If the name of this org is fusion-energy, i think the answer's no.
Maybe these two packages could be merged to reduce the number of dependencies.
What do you think?
This PR changes Muir
to muir
in the python API for openmc so we will need some changes on this package
Currently users need to create the TokamakSource instance, then call .sample_sources()
then call .make_openmc_sources()
Since this package is now heading towards an openmc-fusion subpackage, these steps should be performed all in one go in the __init__()
method.
def __init__(
self,
major_radius,
minor_radius,
elongation,
triangularity,
mode,
ion_density_centre,
ion_density_peaking_factor,
ion_density_pedestal,
ion_density_separatrix,
ion_temperature_centre,
ion_temperature_peaking_factor,
ion_temperature_beta,
ion_temperature_pedestal,
ion_temperature_separatrix,
pedestal_radius,
shafranov_factor,
sample_size=1000
) -> None:
self.major_radius = major_radius
self.minor_radius = minor_radius
self.elongation = elongation
self.triangularity = triangularity
self.ion_density_centre = ion_density_centre
self.mode = mode
self.ion_density_peaking_factor = ion_density_peaking_factor
self.pedestal_radius = pedestal_radius
self.ion_density_pedestal = ion_density_pedestal
self.ion_density_separatrix = ion_density_separatrix
self.ion_temperature_centre = ion_temperature_centre
self.ion_temperature_peaking_factor = ion_temperature_peaking_factor
self.ion_temperature_pedestal = ion_temperature_pedestal
self.ion_temperature_separatrix = ion_temperature_separatrix
self.ion_temperature_beta = ion_temperature_beta
self.shafranov_factor = shafranov_factor
self.sample_size = sample_size
# addition that need to be made
self.sample_sources()
self.sources = self.make_openmc_sources()
Is there any chance I can change this line to allow versions above 3.3.4
openmc-plasma-source/setup.cfg
Line 30 in e3931d1
I am installing this package in some CI and getting this error
error: matplotlib 3.3.4 is installed but matplotlib>=3.4.3 is required by {'openmc-plasma-source'}
Looking at the earlier releases (pre .toml file) it looks like "matplotlib >= 3.2.2" was accepted
Just running the tests on the main or develop branch and I am seeing this error and getting one failing test
@given(tokamak_source=tokamak_source_strategy())
@settings(max_examples=50)
def test_strengths_are_normalised(tokamak_source):
"""Tests that the sum of the strengths attribute is equal to"""
> assert pytest.approx(sum(tokamak_source.strengths)) == 1
E assert nan ± ??? == 1
E comparison failed
E Obtained: 1
E Expected: nan ± ???
E Falsifying example: test_strengths_are_normalised(
E tokamak_source=TokamakSource(angles=(0, 6.283185307179586), elongation=1.0, ion_density_centre=1.09e+20, ion_density_peaking_factor=1, ion_density_pedestal=1.09e+20, ion_density_separatrix=3e+19, ion_temperature_beta=6, ion_temperature_centre=45.9, ion_temperature_peaking_factor=8.06, ion_temperature_pedestal=6.09, ion_temperature_separatrix=0.1, major_radius=1.0, minor_radius=1.5258789062500003e-05, mode='H', name='TokamakSource', pedestal_radius=1.52587890625e-05, sample_size=1000, triangularity=0.0),
E )
Not sure if this will work as we run ci in a container.
However it would be great if multiple python versions can be tested
Here is an example
A github action can be added to check that proposed changes:
This action can perhaps be reused for this role.
Hi when creating and setting my source to a Tokamak source I followed the examples as shown. This states that the major and minor radii are in metres (also stated in the source code). Though when I actually fit this to a EU demo model the source appears near the origin. I changed the units to cm (i.e major _radius *100) and it fitted within my demo reactor. This was confirmed with a paraview image of the traces shown below (Images showing CM compared to M as an input). I don't know if it was a typo or something fundamentally different in the code.
my_source = TokamakSource(
elongation=1.557,
ion_density_centre=1.09e20,
ion_density_peaking_factor=1,
ion_density_pedestal=1.09e20,
ion_density_separatrix=3e19,
ion_temperature_centre=45.9,
ion_temperature_peaking_factor=8.06,
ion_temperature_pedestal=6.09,
ion_temperature_separatrix=0.1,
major_radius=906,
minor_radius=292.2,
pedestal_radius=0.8 * 292.2,
mode="H",
shafranov_factor= 0.44789,
triangularity=0.270,
ion_temperature_beta=6,
angles = (0, math.pi/2),
sample_size= 10
)
Other consideration are how this affects other properties. I believe the Shafranov factor is a ratio of these radii multiplied by the ratio of direction field strength so the cm to m conversion shouldn't affect this. I don't believe any other value needs changing in the parameters.
this line appears to be giving a run time warning
RuntimeWarning: invalid value encountered in power
* (1 - (r / pedestal_radius) ** ion_temperature_beta)
I it gets run in 'H' mode
perhaps related to this stack over flow
I was looking at the functions in plotting and thought these should maybe be methods of TokamakSource so that users can do:
my_source = TokamakSouce(....)
my_source.plot_3d(...)
The Python package param was recently brought to my attention, which solves the same problem as my own new library proper_tea, although it does so using 'descriptors' and a lot of metaclassing rather than property factories. As it's a much more mature library, it's likely to be more stable over time and is more feature-rich. On the other hand, I quite like the interface I've created. For a positive float in proper_tea, the user requires:
class MyClass:
val = proper_tea.positive_float()
Whereas in param, the user must specify bounds explicitly and inherit from a base class:
class MyClass(param.Parameterized):
val = param.Number( bounds=(0,None))
A significant advantage of param is that it offers better error messages when things go wrong. If you tried setting val
to -5 in each case, param would tell you that there was an error with 'Parameter val', while proper_tea only knows that a property setter in 'MyClass' has gone wrong. I think I'll need to get into metaclassing before I can solve that problem myself.
Do you think it would be worth refactoring to use param instead? I believe it should be possible to do so without changing any of the tests.
Now that PR openmc-dev/openmc#2524 has been merged in the class Source has been renamed
This package might need updating in a few places
grep -r 'Source(' .
Hello,
I'm trying to create an openmc model where I only model one half of the tokamak since my model is completely up/down symmetrical. Any ideas how I should accomplish this in TokamakSource()? I'm happy to create the entire source and then remove the source-points above or below the Z=0-plane but unsure how to remove points when I create the source like below. I can iterate over the my_source.sources and get the space-variable. Could I just delete the data points I don't want from the list?
Maybe it would be useful to have a Z-delimiter option in the input arguments, similar to the angles-argument.
my_source = TokamakSource(
elongation=1.557,
ion_density_centre=1.09e20,
ion_density_peaking_factor=1,
ion_density_pedestal=1.09e20,
ion_density_separatrix=3e19,
ion_temperature_centre=45.9,
ion_temperature_peaking_factor=8.06,
ion_temperature_pedestal=6.09,
ion_temperature_separatrix=0.1,
major_radius=9.06,
minor_radius=2.92258,
pedestal_radius=0.8 * 2.92258,
mode="H",
shafranov_factor=0.44789,
triangularity=0.270,
ion_temperature_beta=6
)
Currently, the default angles (full 360) are used when creating a TokamakSource object
However, this should be user-defined.
my_source = ops.TokamakSource(
elongation=1.557,
ion_density_centre=1.09e20,
ion_density_peaking_factor=1,
ion_density_pedestal=1.09e20,
ion_density_separatrix=3e19,
ion_temperature_centre=45.9,
ion_temperature_peaking_factor=8.06,
ion_temperature_pedestal=6.09,
ion_temperature_separatrix=0.1,
major_radius=9.06,
minor_radius=2.92258,
pedestal_radius=0.8 * 2.92258,
mode="H",
shafranov_factor=0.44789,
triangularity=0.270,
ion_temperature_beta=6,
# new parameter!!!
angles=(0, 3.14/2)
)
instead of a 14MeV or a 2.5MeV Muir distribution we could have a distribution that accounts for DD, TT and DT reactions
import NeSST as nst
def create_neutron_source_term(
ion_temperature: float,
fuel: dict = {'D':0.5, 'T':0.5},
) -> openmc.stats.Discrete:
"""Finds the energy distribution
"""
ion_temperature = ion_temperature / 1e3 # convert eV to keV
sum_fuel_isotopes = sum(fuel.values())
if sum_fuel_isotopes > 1.:
raise ValueError(f'isotope fractions within the fuel must sum to be below 1. Not {sum_fuel_isotopes}')
if sum_fuel_isotopes < 0.:
raise ValueError(f'isotope must sum to be above 0. Not {sum_fuel_isotopes}')
for k, v in fuel.dict:
if k not in ['D', 'T']:
raise ValueError('Fuel dictionary keys must be either "D" or "T" not "{k}".)
if v < 0
raise ValueError('Fuel dictionary values must be above 0 not "{k}".)
if v > 1
raise ValueError('Fuel dictionary values must be below 1 not "{k}".)
#Set atomic fraction of D and T in scattering medium and source
if 'D' in fuel.keys():
nst.frac_D_default = fuel['D']
else:
nst.frac_D_default = 0
if 'T' in fuel.keys():
nst.frac_T_default = fuel['T']
else:
nst.frac_T_default = 0
# 1.0 neutron yield, all reactions scaled by this value
num_of_vals = 500
# single grid for DT, DD and TT grid
E_pspec = np.linspace(0, 20, num_of_vals) # accepts MeV units
dNdE_DT_DD_TT = np.zeros(num_of_vals)
if 'D' in fuel.keys() and 'T' in fuel.keys():
DTmean, DTvar = nst.DTprimspecmoments(ion_temperature)
Y_DT = 1.0
dNdE_DT = Y_DT * nst.Qb(E_pspec, DTmean, DTvar) # Brysk shape i.e. Gaussian
dNdE_DT_DD_TT= dNdE_DT_DD_TT + dNdE_DT
if 'D' in fuel.keys()
DDmean, DDvar = nst.DDprimspecmoments(ion_temperature)
Y_DD = nst.yield_from_dt_yield_ratio("dd", 1.0, ion_temperature)
dNdE_DD = Y_DD * nst.Qb(E_pspec, DDmean, DDvar) # Brysk shape i.e. Gaussian
dNdE_DT_DD_TT= dNdE_DT_DD_TT + dNdE_DD
if 'T' in fuel.keys()
Y_TT = nst.yield_from_dt_yield_ratio("tt", 1.0, ion_temperature)
dNdE_TT = Y_TT * nst.dNdE_TT(E_pspec, ion_temperature)
dNdE_DT_DD_TT= dNdE_DT_DD_TT + dNdE_TT
return openmc.stats.Discrete(E_pspec * 1e6, dNdE_DT_DD_TT)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.