Skip to content

Commit 143d3b3

Browse files
authored
Merge pull request #5 from open-radiation-sources/develop
Updating the main branch
2 parents e28622d + 9371dc7 commit 143d3b3

10 files changed

Lines changed: 254 additions & 16 deletions

File tree

.github/workflows/python.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Python package
1+
name: python_package
22

33
on:
44
push:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
*.exe
3131
*.out
3232
*.app
33+
source_generator
3334

3435
# Build path
3536
build/

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "pybind11"]
22
path = pybind11
33
url = https://github.com/pybind/pybind11
4+
[submodule "pugixml"]
5+
path = pugixml
6+
url = https://github.com/zeux/pugixml.git

CMakeLists.txt

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@ set(CMAKE_CXX_FLAGS "-Wall")
1313
set(CMAKE_CXX_FLAGS_DEBUG "-g")
1414
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
1515

16-
# Use output paths from OpenMC install - change if needed
17-
set(OPENMC_DIR /opt/openmc)
18-
set(OPENMC_INC_DIR ${OPENMC_DIR}/include)
19-
set(OPENMC_LIB_DIR ${OPENMC_DIR}/lib)
20-
2116
# Ensure submodules are available and up to date
2217
find_package(Git QUIET)
2318
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
@@ -44,16 +39,29 @@ list(APPEND source_sampling_SOURCES
4439
${SRC_DIR}/plasma_source.cpp
4540
)
4641

47-
add_library(source_sampling SHARED ${source_sampling_SOURCES})
42+
# Use output paths from OpenMC install
43+
# If OpenMC isn't available then we won't be able to build the plugin
44+
# However, the package can still be run by using the sampling methods directly
45+
# So don't terminate the build
46+
find_package(OpenMC QUIET)
47+
48+
if(OpenMC_FOUND)
49+
# Build the source_sampling OpenMC plugin if OpenMC is available
50+
set(OPENMC_INC_DIR ${OpenMC_DIR}/../../../include/openmc)
51+
set(OPENMC_LIB_DIR ${OpenMC_DIR}/../../../lib)
52+
53+
add_library(source_sampling SHARED ${source_sampling_SOURCES})
4854

49-
find_library(OPENMC_LIB openmc HINTS ${OPENMC_LIB_DIR} OPTIONAL)
55+
find_library(OPENMC_LIB openmc HINTS ${OPENMC_LIB_DIR} OPTIONAL)
5056

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+
if (OPENMC_LIB)
58+
set_target_properties(source_sampling PROPERTIES PREFIX "")
59+
set_target_properties(source_sampling PROPERTIES POSITION_INDEPENDENT_CODE ON)
60+
target_include_directories(source_sampling PUBLIC ${OPENMC_INC_DIR})
61+
target_link_libraries(source_sampling ${OPENMC_LIB} gfortran)
62+
endif()
63+
else()
64+
message(WARNING "Unable to find OpenMC installation - the source_sampling plugin will not be built.")
5765
endif()
5866

5967
# Build plasma_source Python bindings
@@ -65,3 +73,20 @@ list(APPEND plasma_source_pybind_SOURCES
6573
add_subdirectory(pybind11)
6674

6775
pybind11_add_module(plasma_source ${plasma_source_pybind_SOURCES})
76+
77+
add_subdirectory(pugixml)
78+
79+
# Build source_generator
80+
list(APPEND source_generator_SOURCES
81+
${SRC_DIR}/source_generator.cpp
82+
)
83+
84+
add_executable(source_generator ${source_generator_SOURCES})
85+
86+
find_package(HDF5 REQUIRED)
87+
88+
set_target_properties(source_generator PROPERTIES POSITION_INDEPENDENT_CODE ON)
89+
target_include_directories(source_generator PUBLIC ${OPENMC_INC_DIR})
90+
target_include_directories(source_generator PUBLIC ${HDF5_INCLUDE_DIRS})
91+
target_include_directories(source_generator PUBLIC ${OPENMC_DIR}/vendor/pugixml)
92+
target_link_libraries(source_generator ${OPENMC_LIB} ${HDF5_LIBRARIES} stdc++fs)

README.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# parametric-plasma-source
22

3-
![Python package](https://github.com/DanShort12/parametric-plasma-source/workflows/Python%20package/badge.svg)
3+
[![Python package](https://github.com/open-radiation-sources/parametric-plasma-source/workflows/python_package/badge.svg)](https://pypi.org/project/parametric-plasma-source/)
4+
5+
[![ActionsCI](https://github.com/open-radiation-sources/parametric-plasma-source/workflows/python_package/badge.svg)](https://github.com/open-radiation-sources/parametric-plasma-source/actions?query=workflow%3Apython_package)
46

57
Python package, C++ source and build files for parametric plasma source for use in fusion neutron transport calculations with OpenMC.
68

@@ -29,7 +31,7 @@ The package can be built and installed in editable mode by:
2931

3032
## Usage
3133

32-
The parametric plasma source can be sampled either directly in Python 3 or sampled in an OpenMC simulation.
34+
The parametric plasma source can be sampled either directly in Python 3, sampled in an OpenMC simulation, or sampled using OpenMC via a standalone executable without simulation.
3335

3436
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.
3537

@@ -108,6 +110,23 @@ settings.source = source
108110
settings.export_to_xml()
109111
```
110112

113+
### Sampling using Executable
114+
115+
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:
116+
117+
```bash
118+
Usage:
119+
source_generator [OPTIONS]
120+
121+
Options:
122+
-l,--library Source library, mandatory
123+
-n,--particles Number of particles, default 1000
124+
-o,--output Output directory, default {current directory}
125+
-v,--verbosity Verbosity, default 5
126+
```
127+
128+
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.
129+
111130
## Running Tests
112131

113132
The tests are run by executing `pytest tests` from within your virtual environment.
File renamed without changes.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""
2+
An example of how to read an initial_source.h5 file, as generated from source_generator
3+
4+
In order to create the initial source, first build the source_generator and then run
5+
the below, which will create an example source and sample it 1000 times.
6+
7+
../../build/source_generator -l ../../build/source_sampling.so -i "major_radius=9.06, \
8+
minor_radius=2.92258, elongation=1.557, triangularity=0.27, shafranov_shift=0.44789, \
9+
pedestal_radius=2.33806, ion_density_pedestal=1.09e+20, ion_density_separatrix=3e+19, \
10+
ion_density_origin=1.09e+20, ion_density_alpha=1, ion_temperature_pedestal=6.09, \
11+
ion_temperature_separatrix=0.1, ion_temperature_origin=45.9, \
12+
ion_temperature_alpha=8.06, ion_temperature_beta=6, plasma_type=plasma, plasma_id=1, \
13+
number_of_bins=100, minimum_toroidal_angle=0, maximum_toroidal_angle=360" \
14+
-v 10 -n 1000
15+
"""
16+
17+
import h5py
18+
import matplotlib.pyplot as plt
19+
import numpy as np
20+
21+
path_to_initial_source = "initial_source.h5"
22+
23+
with h5py.File(path_to_initial_source, "r") as f:
24+
r = np.sqrt(
25+
np.square(f["source_bank"][...]["r"]["x"])
26+
+ np.square(f["source_bank"][...]["r"]["y"])
27+
)
28+
z = f["source_bank"][...]["r"]["z"]
29+
30+
plt.scatter(r, z)
31+
32+
plt.ion()
33+
plt.show()
34+
plt.gca().set_aspect("equal")
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#include <iostream>
2+
#include <experimental/filesystem>
3+
4+
#include "pugixml.hpp"
5+
6+
#include "openmc/bank.h"
7+
#include "openmc/constants.h"
8+
#include "openmc/message_passing.h"
9+
#include "openmc/settings.h"
10+
#include "openmc/simulation.h"
11+
#include "openmc/source.h"
12+
13+
namespace source_generator
14+
{
15+
void print_settings(pugi::xml_node &root)
16+
{
17+
using namespace openmc;
18+
19+
std::cout << "Settings:" << std::endl;
20+
std::cout << " Number of particles: " << settings::n_particles << std::endl;
21+
std::cout << " Source library: " << root.child("source").attribute("library").value() << std::endl;
22+
std::cout << " Source parameters: " << root.child("source").attribute("parameters").value() << std::endl;
23+
std::cout << " Output path: " << settings::path_output << std::endl;
24+
std::cout << " Verbosity: " << settings::verbosity << std::endl;
25+
std::cout << std::endl;
26+
}
27+
28+
void print_help()
29+
{
30+
std::cout << "Usage:" << std::endl;
31+
std::cout << "source_generator [OPTIONS]" << std::endl;
32+
std::cout << std::endl;
33+
std::cout << "Options:" << std::endl;
34+
std::cout << " -l,--library Source library, mandatory" << std::endl;
35+
std::cout << " -i,--input Source definition, mandatory" << std::endl;
36+
std::cout << " -n,--particles Number of particles, default 1000" << std::endl;
37+
std::cout << " -o,--output Output directory, default {current directory}" << std::endl;
38+
std::cout << " -v,--verbosity Verbosity, default 5" << std::endl;
39+
}
40+
41+
void set_defaults()
42+
{
43+
using namespace openmc;
44+
using namespace std::experimental;
45+
46+
std::string current_path = filesystem::current_path().string();
47+
48+
// These are static to make sure we get some output...
49+
settings::run_mode = RunMode::EIGENVALUE;
50+
settings::write_initial_source = true;
51+
52+
// Variables with sensible default values
53+
settings::n_particles = 1000;
54+
settings::path_output = current_path + "/";
55+
settings::verbosity = 5;
56+
}
57+
58+
int parse_command_line(int argc, char* argv[], pugi::xml_node &root)
59+
{
60+
using namespace openmc;
61+
62+
root.append_child("source");
63+
64+
for (int i=1; i < argc; ++i)
65+
{
66+
std::string arg {argv[i]};
67+
if (arg[0] == '-')
68+
{
69+
if (arg == "-n" || arg == "--particles")
70+
{
71+
i += 1;
72+
settings::n_particles = std::stoll(argv[i]);
73+
}
74+
else if (arg == "-l" || arg == "--library")
75+
{
76+
i += 1;
77+
root.child("source").append_attribute("library").set_value(argv[i]);
78+
settings::path_source_library = argv[i];
79+
}
80+
else if (arg == "-i" || arg == "--input")
81+
{
82+
i += 1;
83+
root.child("source").append_attribute("parameters").set_value(argv[i]);
84+
}
85+
else if (arg == "-o" || arg == "--output")
86+
{
87+
i += 1;
88+
settings::path_output = argv[i];
89+
}
90+
else if (arg == "-v" || arg == "--verbosity")
91+
{
92+
i += 1;
93+
settings::verbosity = std::stoi(argv[i]);
94+
}
95+
else
96+
{
97+
source_generator::print_help();
98+
return -1;
99+
}
100+
}
101+
}
102+
103+
bool missing_arg = false;
104+
105+
if (!root.child("source").attribute("library"))
106+
{
107+
std::cout << "The --library or -l argument is mandatory and must be set." << std::endl;
108+
missing_arg = true;
109+
}
110+
111+
if (!root.child("source").attribute("parameters"))
112+
{
113+
std::cout << "The --input or -i argument is mandatory and must be set." << std::endl;
114+
missing_arg = true;
115+
}
116+
117+
if (missing_arg)
118+
{
119+
source_generator::print_help();
120+
return -1;
121+
}
122+
else
123+
{
124+
return 0;
125+
}
126+
}
127+
}
128+
129+
int main(int argc, char* argv[])
130+
{
131+
pugi::xml_document doc;
132+
pugi::xml_node root = doc.append_child("settings");
133+
134+
source_generator::set_defaults();
135+
136+
int run = source_generator::parse_command_line(argc, argv, root);
137+
138+
if (run < 0)
139+
{
140+
return run;
141+
}
142+
143+
if (openmc::settings::verbosity >= 5)
144+
{
145+
source_generator::print_settings(root);
146+
}
147+
148+
std::cout << "Sampling source:" << std::endl;
149+
openmc::SourceDistribution source = openmc::SourceDistribution(root.child("source"));
150+
openmc::calculate_work();
151+
openmc::allocate_banks();
152+
openmc::initialize_source();
153+
154+
return 0;
155+
}

pugixml

Submodule pugixml added at 22401ba

0 commit comments

Comments
 (0)