Skip to content

Commit 43da2a6

Browse files
committed
Merge branch 'master' into source_sampling_executable
2 parents 64ee8ba + fb3ae38 commit 43da2a6

24 files changed

Lines changed: 918 additions & 1409 deletions

.flake8

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[flake8]
2+
max-line-length = 88
3+
exclude = __init__.py

.github/workflows/python.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Python package
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
jobs:
10+
build_and_test:
11+
12+
runs-on: ubuntu-latest
13+
strategy:
14+
matrix:
15+
python-version: [3.6, 3.7, 3.8]
16+
17+
steps:
18+
- uses: actions/checkout@v2
19+
- name: Set up Python ${{ matrix.python-version }}
20+
uses: actions/setup-python@v2
21+
with:
22+
python-version: ${{ matrix.python-version }}
23+
- name: Install OpenMC
24+
run: |
25+
sudo apt-get install -y g++ cmake libhdf5-dev
26+
git clone --recurse-submodules https://github.com/openmc-dev/openmc.git
27+
cd openmc
28+
git checkout
29+
mkdir build && cd build
30+
cmake ..
31+
make
32+
sudo make install
33+
- name: Install plasma source
34+
run: |
35+
pip install -r requirements-develop.txt
36+
python setup.py bdist_wheel
37+
python -m pip install --verbose dist/*.whl
38+
- name: Run tests
39+
run: |
40+
pytest tests
41+
- name: Upload wheel artifact
42+
uses: actions/upload-artifact@v2
43+
with:
44+
name: dist
45+
path: dist

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,13 @@ dist/
3939
# Python
4040
__pycache__/
4141
*.py[cod]
42+
.venv
4243

4344
source_generator
4445

45-
# Output files
46+
# Outputs
47+
*.xml
4648
*.h5
49+
50+
# VS Code
51+
.vscode

CMakeLists.txt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,15 @@ list(APPEND source_sampling_SOURCES
4646

4747
add_library(source_sampling SHARED ${source_sampling_SOURCES})
4848

49-
find_library(OPENMC_LIB openmc HINTS ${OPENMC_LIB_DIR})
50-
51-
set_target_properties(source_sampling PROPERTIES PREFIX "")
52-
set_target_properties(source_sampling PROPERTIES POSITION_INDEPENDENT_CODE ON)
53-
target_include_directories(source_sampling PUBLIC ${OPENMC_INC_DIR})
54-
target_include_directories(source_sampling PUBLIC ${OPENMC_DIR}/vendor/pugixml)
55-
target_link_libraries(source_sampling ${OPENMC_LIB} gfortran)
49+
find_library(OPENMC_LIB openmc HINTS ${OPENMC_LIB_DIR} OPTIONAL)
50+
51+
if (OPENMC_LIB)
52+
set_target_properties(source_sampling PROPERTIES PREFIX "")
53+
set_target_properties(source_sampling PROPERTIES POSITION_INDEPENDENT_CODE ON)
54+
target_include_directories(source_sampling PUBLIC ${OPENMC_INC_DIR})
55+
target_include_directories(source_sampling PUBLIC ${OPENMC_DIR}/vendor/pugixml)
56+
target_link_libraries(source_sampling ${OPENMC_LIB} gfortran)
57+
endif()
5658

5759
# Build plasma_source Python bindings
5860
list(APPEND plasma_source_pybind_SOURCES

README.md

Lines changed: 97 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,116 @@
11
# parametric-plasma-source
22

3+
![Python package](https://github.com/DanShort12/parametric-plasma-source/workflows/Python%20package/badge.svg)
4+
35
Python package, C++ source and build files for parametric plasma source for use in fusion neutron transport calculations with OpenMC.
46

57
The plasma source is based on a paper by [C. Fausser et al](https://www.sciencedirect.com/science/article/pii/S0920379612000853)
68

7-
# Installation
9+
## Installation
10+
11+
### Installing from PyPI
812

913
```pip install parametric_plasma_source```
1014

11-
# Usage
15+
### Installing from source
1216

13-
The parametric plasma source can be imported an used in Python 3 in the following manner.
17+
Installation of the parametric plasma source from source requires cmake to build the underlying C++ code. This can be obtained from
18+
your OS's package manager by e.g. `sudo apt-get install cmake` or from cmake source.
1419

15-
```
16-
from parametric_plasma_source import Plasma
17-
my_plasma = Plasma(major_radius=6,
18-
minor_radius=1.5,
19-
elongation = 2.0,
20-
triangularity = 0.55)
21-
my_plasma.export_plasma_source('custom_openmc_plasma_source.so')
22-
```
20+
If you intend to develop the code then it is recommended to work in a virtual environment.
2321

24-
In the above example the major_radius, minor_radius, elongation and triangularity while the other varibles are kept as the default values.
22+
The requirements for developing the code can be installed by running:
2523

26-
There are a number of additional arguments that can be passed to the Plasma class on construction. Units are in SI (e.g. meters not cm)
24+
```pip install -r requirements-develop.txt```
2725

28-
```
29-
ion_density_pedistal = 1.09e+20
30-
ion_density_seperatrix = 3e+19
31-
ion_density_origin = 1.09e+20
32-
ion_temperature_pedistal = 6.09
33-
ion_temperature_seperatrix = 0.1
34-
ion_temperature_origin = 45.9
35-
pedistal_radius = 0.8
36-
ion_density_peaking_factor = 1
37-
ion_temperature_peaking_factor = 8.06
38-
minor_radius = 1.56
39-
major_radius = 2.5
40-
elongation = 2.0
41-
triangularity = 0.55
42-
shafranov_shift = 0.0
43-
number_of_bins = 100
44-
plasma_type = 1
45-
```
26+
The package can be built and installed in editable mode by:
27+
28+
```pip install -e .```
29+
30+
## Usage
31+
32+
The parametric plasma source can be sampled either directly in Python 3 or sampled in an OpenMC simulation.
4633

4734
For a better understanding of the varibles take a look at the [C. Fausser et al](https://www.sciencedirect.com/science/article/pii/S0920379612000853) paper.
4835

49-
## Building and Running
36+
### Sampling in Python
37+
38+
The parametric plasma source can be imported an used in Python 3 in the following manner:
39+
40+
```[python]
41+
from parametric_plasma_source import PlasmaSource
42+
from random import random
43+
44+
plasma_params = {
45+
"elongation": 1.557,
46+
"ion_density_origin": 1.09e20,
47+
"ion_density_peaking_factor": 1,
48+
"ion_density_pedestal": 1.09e20,
49+
"ion_density_separatrix": 3e19,
50+
"ion_temperature_origin": 45.9,
51+
"ion_temperature_peaking_factor": 8.06,
52+
"ion_temperature_pedestal": 6.09,
53+
"ion_temperature_separatrix": 0.1,
54+
"major_radius": 9.06,
55+
"minor_radius": 2.92258,
56+
"pedestal_radius": 0.8 * 2.92258,
57+
"plasma_id": 1,
58+
"shafranov_shift": 0.44789,
59+
"triangularity": 0.270,
60+
"ion_temperature_beta": 6,
61+
}
62+
63+
my_plasma = PlasmaSource(**plasma_params)
64+
sample = my_plasma.sample([random(), random(), random(), random(), random(), random(), random(), random()])
65+
particle_x, particle_y, particle_z = sample[0], sample[1], sample[2]
66+
particle_x_dir, particle_y_dir, particle_z_dir = sample[3], sample[4], sample[5]
67+
particle_energy_mev = sample[6]
68+
```
5069

51-
Note: When building using the `Makefile` you may need to update the `OPENMC_DIR` parameter to select a relevant directory to obtain the OpenMC libraries and includes from.
70+
### Sampling in OpenMC
71+
72+
The parametric plasma source also contains a plugin library for OpenMC to allow the source to be sampled in an OpenMC simulation.
73+
74+
When using the OpenMC sampling the inputs must be provided in meters where applicable (the sampling will convert to cm).
75+
76+
```[python]
77+
from parametric_plasma_source import PlasmaSource, SOURCE_SAMPLING_PATH
78+
import openmc
79+
80+
plasma_params = {
81+
"elongation": 1.557,
82+
"ion_density_origin": 1.09e20,
83+
"ion_density_peaking_factor": 1,
84+
"ion_density_pedestal": 1.09e20,
85+
"ion_density_separatrix": 3e19,
86+
"ion_temperature_origin": 45.9,
87+
"ion_temperature_peaking_factor": 8.06,
88+
"ion_temperature_pedestal": 6.09,
89+
"ion_temperature_separatrix": 0.1,
90+
"major_radius": 9.06,
91+
"minor_radius": 2.92258,
92+
"pedestal_radius": 0.8 * 2.92258,
93+
"plasma_id": 1,
94+
"shafranov_shift": 0.44789,
95+
"triangularity": 0.270,
96+
"ion_temperature_beta": 6,
97+
}
98+
99+
my_plasma = PlasmaSource(**plasma_params)
100+
settings = openmc.Settings()
101+
settings.run_mode = "fixed source"
102+
settings.batches = 10
103+
settings.particles = 1000
104+
source = openmc.Source()
105+
source.library = SOURCE_SAMPLING_PATH
106+
source.parameters = str(my_plasma)
107+
settings.source = source
108+
settings.export_to_xml()
109+
```
52110

53-
The OpenMC plugin that samples the plasma source is built by running `make` or `make source_sampling` from within the parametric-plasma-source directory. This will generate the `source_sampling.so` shared object library, which can be referenced by the `library` attribute in the `source` element within the settings.xml being used for the run.
111+
### Sampling using Executable
54112

55-
It is also possible to generate a source outside of OpenMC by creating the `source_generator` executable by running `make` or `make source_generator` from within the parameteric-plasma-source directory. The `source_generator` can then be run as below:
113+
It is also possible to generate a source outside of OpenMC by creating the `source_generator` executable by running `cmake -H. -Bbuild` and then `cmake --build build` or `cmake --build build --target source_generator`. The `source_generator` can then be run as below:
56114

57115
```bash
58116
Usage:
@@ -66,3 +124,7 @@ Options:
66124
```
67125

68126
This will use OpenMC commands to sample the source generated using the specified library with the specified number of particles and output the resulting `initial_source.h5` file in the requested output directory. The `initial_source.h5` can then be analysed to check the properties of the source being generated.
127+
128+
## Running Tests
129+
130+
The tests are run by executing `pytest tests` from within your virtual environment.

data/example_source.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
major_radius=4.5, minor_radius=1.5, elongation=2, triangularity=0.55, shafranov_shift=0, pedestal_radius=1.2, ion_density_pedestal=1.09e+20, ion_density_separatrix=3e+19, ion_density_origin=1.09e+20, ion_density_alpha=1, ion_temperature_pedestal=6.09, ion_temperature_separatrix=0.1, ion_temperature_origin=45.9, ion_temperature_alpha=8.06, ion_temperature_beta=6, plasma_type=plasma, plasma_id=1, number_of_bins=100, minimum_toroidal_angle=0, maximum_toroidal_angle=360

examples/build_and_run_model.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""
2+
OpenMC Plasma Source example.
3+
4+
An example of how to generate a settings file containing the parameterised
5+
plasma source sampling library and how to generate the parameterisation in the
6+
OpenMC settings.xml file.
7+
"""
8+
9+
from parametric_plasma_source import PlasmaSource, SOURCE_SAMPLING_PATH
10+
import openmc
11+
12+
plasma_params = {
13+
"elongation": 1.557,
14+
"ion_density_origin": 1.09e20,
15+
"ion_density_peaking_factor": 1,
16+
"ion_density_pedestal": 1.09e20,
17+
"ion_density_separatrix": 3e19,
18+
"ion_temperature_origin": 45.9,
19+
"ion_temperature_peaking_factor": 8.06,
20+
"ion_temperature_pedestal": 6.09,
21+
"ion_temperature_separatrix": 0.1,
22+
"major_radius": 9.06,
23+
"minor_radius": 2.92258,
24+
"pedestal_radius": 0.8 * 2.92258,
25+
"plasma_id": 1,
26+
"shafranov_shift": 0.44789,
27+
"triangularity": 0.270,
28+
"ion_temperature_beta": 6,
29+
}
30+
31+
plasma = PlasmaSource(**plasma_params)
32+
33+
# Create a single material
34+
iron = openmc.Material()
35+
iron.set_density("g/cm3", 5.0)
36+
iron.add_element("Fe", 1.0)
37+
mats = openmc.Materials([iron])
38+
39+
# Create a 5 cm x 5 cm box filled with iron
40+
cells = []
41+
inner_box1 = openmc.ZCylinder(r=600.0)
42+
inner_box2 = openmc.ZCylinder(r=1400.0)
43+
outer_box = openmc.model.rectangular_prism(4000.0, 4000.0, boundary_type="vacuum")
44+
cells += [openmc.Cell(fill=iron, region=-inner_box1)]
45+
cells += [openmc.Cell(fill=None, region=+inner_box1 & -inner_box2)]
46+
cells += [openmc.Cell(fill=iron, region=+inner_box2 & outer_box)]
47+
geometry = openmc.Geometry(cells)
48+
49+
# Tell OpenMC we're going to use our custom source
50+
settings = openmc.Settings()
51+
settings.run_mode = "fixed source"
52+
settings.batches = 10
53+
settings.particles = 1000
54+
source = openmc.Source()
55+
source.library = SOURCE_SAMPLING_PATH
56+
source.parameters = str(plasma)
57+
settings.source = source
58+
59+
# Finally, define a mesh tally so that we can see the resulting flux
60+
mesh = openmc.RegularMesh()
61+
mesh.lower_left = (-2000.0, -2000.0)
62+
mesh.upper_right = (2000.0, 2000.0)
63+
mesh.dimension = (50, 50)
64+
65+
tally = openmc.Tally()
66+
tally.filters = [openmc.MeshFilter(mesh)]
67+
tally.scores = ["flux"]
68+
tallies = openmc.Tallies([tally])
69+
70+
model = openmc.model.Model(
71+
materials=mats, geometry=geometry, settings=settings, tallies=tallies
72+
)
73+
74+
model.run()

examples/plot_flux.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import matplotlib as mpl
2+
import matplotlib.pyplot as plt
3+
import numpy as np
4+
import openmc
5+
6+
mpl.use("TkAgg")
7+
8+
# Get the flux from the statepoint
9+
with openmc.StatePoint("statepoint.10.h5") as sp:
10+
flux = np.log(sp.get_tally(scores=["flux"]).mean)
11+
flux.shape = (50, 50)
12+
13+
# Plot the flux
14+
fig, ax = plt.subplots()
15+
ax.imshow(flux, origin="lower", extent=(-2000.0, 2000.0, -2000.0, 2000.0))
16+
ax.set_xlabel("x [cm]")
17+
ax.set_ylabel("y [cm]")
18+
plt.show()

0 commit comments

Comments
 (0)