Repository: fusion-energy/openmc-plasma-source (language: python)

Issue:
changed plasma to tokamaksource
This PR :

- changes the ```Plasma``` class name to ```TokamakPlasma``` 
- adds an example ```FusionPointSource``` to the readme
- adds an ```FusionRingSource``` to the readme


Discussion / hints:

Fix patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 850ccf2..9741b38 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -10,10 +10,13 @@ jobs:
           name: install
           command: |
             python setup.py install
+            apt-get update -y && apt-get install -y curl
       - run:
           name: run tests
-          command: 
-            python openmc_example.py -v --cov=openmc_dagmc_wrapper --cov-append --cov-report term --cov-report xml
+          command: |
+            pytest tests/test_point_source.py -v --cov=openmc_plasma_source --cov-append --cov-report term --cov-report xml
+            pytest tests/test_ring_source.py -v --cov=openmc_plasma_source --cov-append --cov-report term --cov-report xml
+            pytest tests/test_tokamak_source.py -v --cov=openmc_plasma_source --cov-append --cov-report term --cov-report xml
 
       - store_test_results:
           path: test-reports
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 625d3c7..776d907 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -18,7 +18,12 @@ jobs:
     steps:
       - name: Checkout repository
         uses: actions/checkout@v2
+      
+      - name: Install
+        run: python setup.py install
 
       - name: run example
-        run: python openmc_example.py
-        
+        run: |
+          python examples/point_source_example.py
+          python examples/ring_source_example.py
+          python examples/tokamak_source_example.py
diff --git a/.gitignore b/.gitignore
index b6e4761..a449343 100644
--- a/.gitignore
+++ b/.gitignore
@@ -127,3 +127,6 @@ dmypy.json
 
 # Pyre type checker
 .pyre/
+
+# openmc files
+*.xml
diff --git a/README.md b/README.md
index 35fc458..84b37ca 100644
--- a/README.md
+++ b/README.md
@@ -15,14 +15,16 @@ pip install openmc-plasma-source
 ```
 
 
-## Basic usage
+## Usage
 
-```python
-from openmc_plasma_source import Plasma
+### Tokamak Source
+
+Create a source with a spatial and temperature distribution of a tokamak plasma.
 
+```python
+from openmc_plasma_source import TokamakSource
 
-# create a plasma source
-my_plasma = Plasma(
+my_plasma = TokamakSource(
     elongation=1.557,
     ion_density_centre=1.09e20,
     ion_density_peaking_factor=1,
@@ -46,3 +48,29 @@ my_sources = my_plasma.make_openmc_sources()
 ```
 
 For a more complete example check out the example script.
+
+### Ring Source
+
+
+Create a ring source with temperature distribution of a 2000eV plasma.
+
+```python
+my_plasma = FusionRingSource(
+    start_angle = 0.,
+    stop_angle = 6.28318530718,  # input is in radians
+    temperature = 20000.,
+    fuel='DT'
+)
+```
+### Point Source
+
+Create a point source with temperature distribution of a 2000eV plasma.
+
+
+```python
+my_plasma = FusionPointSource(
+    coordinate = (0, 0, 0),
+    temperature = 20000.,
+    fuel = 'DT'
+)
+```
\ No newline at end of file
diff --git a/examples/point_source_example.py b/examples/point_source_example.py
new file mode 100644
index 0000000..8e3e313
--- /dev/null
+++ b/examples/point_source_example.py
@@ -0,0 +1,49 @@
+
+import openmc
+from openmc_plasma_source import FusionPointSource
+
+my_source = FusionPointSource(
+        coordinate = (0,0,0),
+        temperature = 20000.,
+        fuel='DT'
+)
+
+# Create a single material
+iron = openmc.Material()
+iron.set_density("g/cm3", 5.0)
+iron.add_element("Fe", 1.0)
+mats = openmc.Materials([iron])
+
+# Create a 5 cm x 5 cm box filled with iron
+cells = []
+inner_box1 = openmc.ZCylinder(r=600.0)
+inner_box2 = openmc.ZCylinder(r=1400.0)
+outer_box = openmc.model.rectangular_prism(4000.0, 4000.0, boundary_type="vacuum")
+cells += [openmc.Cell(fill=iron, region=-inner_box1)]
+cells += [openmc.Cell(fill=None, region=+inner_box1 & -inner_box2)]
+cells += [openmc.Cell(fill=iron, region=+inner_box2 & outer_box)]
+geometry = openmc.Geometry(cells)
+
+# Tell OpenMC we're going to use our custom source
+settings = openmc.Settings()
+settings.run_mode = "fixed source"
+settings.batches = 10
+settings.particles = 1000
+settings.source = my_source
+
+# Finally, define a mesh tally so that we can see the resulting flux
+mesh = openmc.RegularMesh()
+mesh.lower_left = (-2000.0, -2000.0)
+mesh.upper_right = (2000.0, 2000.0)
+mesh.dimension = (50, 50)
+
+tally = openmc.Tally()
+tally.filters = [openmc.MeshFilter(mesh)]
+tally.scores = ["flux"]
+tallies = openmc.Tallies([tally])
+
+model = openmc.model.Model(
+    materials=mats, geometry=geometry, settings=settings, tallies=tallies
+)
+
+model.run()
diff --git a/examples/ring_source_example.py b/examples/ring_source_example.py
new file mode 100644
index 0000000..76c82fb
--- /dev/null
+++ b/examples/ring_source_example.py
@@ -0,0 +1,50 @@
+
+import openmc
+from openmc_plasma_source import FusionRingSource
+
+my_source = FusionRingSource(
+    radius = 700,
+    start_angle =0.,
+    stop_angle = 6.28318530718,
+    temperature = 20000.,
+)
+
+# Create a single material
+iron = openmc.Material()
+iron.set_density("g/cm3", 5.0)
+iron.add_element("Fe", 1.0)
+mats = openmc.Materials([iron])
+
+# Create a 5 cm x 5 cm box filled with iron
+cells = []
+inner_box1 = openmc.ZCylinder(r=600.0)
+inner_box2 = openmc.ZCylinder(r=1400.0)
+outer_box = openmc.model.rectangular_prism(4000.0, 4000.0, boundary_type="vacuum")
+cells += [openmc.Cell(fill=iron, region=-inner_box1)]
+cells += [openmc.Cell(fill=None, region=+inner_box1 & -inner_box2)]
+cells += [openmc.Cell(fill=iron, region=+inner_box2 & outer_box)]
+geometry = openmc.Geometry(cells)
+
+# Tell OpenMC we're going to use our custom source
+settings = openmc.Settings()
+settings.run_mode = "fixed source"
+settings.batches = 10
+settings.particles = 1000
+settings.source = my_source
+
+# Finally, define a mesh tally so that we can see the resulting flux
+mesh = openmc.RegularMesh()
+mesh.lower_left = (-2000.0, -2000.0)
+mesh.upper_right = (2000.0, 2000.0)
+mesh.dimension = (50, 50)
+
+tally = openmc.Tally()
+tally.filters = [openmc.MeshFilter(mesh)]
+tally.scores = ["flux"]
+tallies = openmc.Tallies([tally])
+
+model = openmc.model.Model(
+    materials=mats, geometry=geometry, settings=settings, tallies=tallies
+)
+
+model.run()
diff --git a/openmc_example.py b/examples/tokamak_source_example.py
similarity index 96%
rename from openmc_example.py
rename to examples/tokamak_source_example.py
index 5c98a0d..34c2ece 100644
--- a/openmc_example.py
+++ b/examples/tokamak_source_example.py
@@ -1,9 +1,9 @@
 import openmc
-from openmc_plasma_source import Plasma
+from openmc_plasma_source import TokamakSource
 
 
 # create a plasma source
-my_plasma = Plasma(
+my_plasma = TokamakSource(
     elongation=1.557,
     ion_density_centre=1.09e20,
     ion_density_peaking_factor=1,
diff --git a/openmc_plasma_source/__init__.py b/openmc_plasma_source/__init__.py
index c7a393a..05fbcdb 100644
--- a/openmc_plasma_source/__init__.py
+++ b/openmc_plasma_source/__init__.py
@@ -1,1 +1,3 @@
-from .main import Plasma
+from .tokamak_source import TokamakSource
+from .ring_source import FusionRingSource
+from .point_source import FusionPointSource
diff --git a/openmc_plasma_source/point_source.py b/openmc_plasma_source/point_source.py
new file mode 100644
index 0000000..b47230b
--- /dev/null
+++ b/openmc_plasma_source/point_source.py
@@ -0,0 +1,33 @@
+
+from typing import Tuple
+
+import openmc
+
+
+class FusionPointSource(openmc.Source):
+    """An openmc.Source object with some presets to make it more convenient
+    for fusion simulations using a point source. All attributes can be changed
+    after initialization if required. Default isotropic point source at the
+    origin with a Muir energy distribution. 
+    """
+    def __init__(
+        self,
+        coordinate: Tuple[float, float, float] = (0, 0, 0),
+        temperature: float = 20000.,
+        fuel: str = 'DT'
+    ):
+ 
+        super().__init__()
+
+        # performed after the super init as these are Source attributes
+        self.space = openmc.stats.Point(coordinate)
+        self.angle = openmc.stats.Isotropic()
+        if fuel == 'DT':
+            mean_energy = 14080000.  # mean energy in eV
+            mass_of_reactants = 5  # mass of the reactants (D + T) AMU
+        elif fuel == 'DT':
+            mean_energy = 2450000.  # mean energy in eV
+            mass_of_reactants = 4  # mass of the reactants (D + D) AMU
+        else:
+            raise ValueError(f'fuel must be either "DT" or "DD", not {fuel}')
+        self.energy = openmc.stats.Muir(e0=mean_energy , m_rat=mass_of_reactants , kt=temperature)
diff --git a/openmc_plasma_source/ring_source.py b/openmc_plasma_source/ring_source.py
new file mode 100644
index 0000000..30b73fe
--- /dev/null
+++ b/openmc_plasma_source/ring_source.py
@@ -0,0 +1,47 @@
+
+import openmc
+
+
+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,
+        temperature: float = 20000.,
+        fuel='DT'
+    ):
+
+        super().__init__()
+
+        # performed after the super init as these are Source attributes
+        radius = openmc.stats.Discrete([radius], [1])
+        z_values = openmc.stats.Discrete([0], [1])
+        angle = openmc.stats.Uniform(a=start_angle, b=stop_angle)
+        self.space = openmc.stats.CylindricalIndependent(
+            r=radius,
+            phi=angle,
+            z=z_values,
+            origin=(0.0, 0.0, 0.0)
+        )
+        self.angle = openmc.stats.Isotropic()
+        if fuel == 'DT':
+            mean_energy = 14080000.  # mean energy in eV
+            mass_of_reactants = 5  # mass of the reactants (D + T) AMU
+        elif fuel == 'DT':
+            mean_energy = 2450000.  # mean energy in eV
+            mass_of_reactants = 4  # mass of the reactants (D + D) AMU
+        else:
+            raise ValueError(f'fuel must be either "DT" or "DD", not {fuel}')
+        self.energy = openmc.stats.Muir(e0=mean_energy , m_rat=mass_of_reactants , kt=temperature)
diff --git a/openmc_plasma_source/main.py b/openmc_plasma_source/tokamak_source.py
similarity index 96%
rename from openmc_plasma_source/main.py
rename to openmc_plasma_source/tokamak_source.py
index f1aa3e2..0f3e927 100644
--- a/openmc_plasma_source/main.py
+++ b/openmc_plasma_source/tokamak_source.py
@@ -4,7 +4,7 @@
 from numpy.lib.function_base import iterable
 
 
-class Plasma():
+class TokamakSource():
     """Plasma neutron source sampling.
     This class greatly relies on models described in [1]
 
@@ -27,20 +27,20 @@ class Plasma():
         mode (str): Confinement mode ("L", "H", "A")
         ion_density_centre (float): Ion density at the plasma centre (m-3)
         ion_density_peaking_factor (float): Ion density peaking factor
-            (refered in [1] as ion density exponent)
+            (referred in [1] as ion density exponent)
         ion_density_pedestal (float): Ion density at pedestal (m-3)
         ion_density_separatrix (float): Ion density at separatrix (m-3)
         ion_temperature_centre (float): Ion temperature at the plasma
             centre (keV)
         ion_temperature_peaking_factor (float): Ion temperature peaking
-            factor (refered in [1] as ion temperature exponent alpha_T)
+            factor (referred in [1] as ion temperature exponent alpha_T)
         ion_temperature_beta (float): Ion temperature beta exponent
-            (refered in [1] as ion temperature exponent beta_T)
+            (referred in [1] as ion temperature exponent beta_T)
         ion_temperature_pedestal (float): Ion temperature at pedestal (keV)
         ion_temperature_separatrix (float): Ion temperature at separatrix
             (keV)
         pedestal_radius (float): Minor radius at pedestal (m)
-        shafranov_factor (float): Shafranov factor (refered in [1] as esh)
+        shafranov_factor (float): Shafranov factor (referred in [1] as esh)
             also known as outward radial displacement of magnetic surfaces
             (m)
         sample_size (int, optional): number of neutron sources. Defaults
@@ -268,6 +268,12 @@ def DT_xs(ion_temperature):
     return val
 
 
+def PlasmaSource(**plasma_prms):
+    my_plasma = Plasma(**plasma_prms)
+    my_plasma.sample_sources()
+    return my_plasma.make_openmc_sources()
+
+
 if __name__ == "__main__":
     my_plasma = Plasma(
         elongation=1.557,


Test patch:
diff --git a/tests/test_point_source.py b/tests/test_point_source.py
new file mode 100644
index 0000000..ed55b21
--- /dev/null
+++ b/tests/test_point_source.py
@@ -0,0 +1,8 @@
+from openmc_plasma_source import FusionPointSource
+
+from openmc import Source
+
+
+def test_creation():
+    my_source = FusionPointSource()
+    assert isinstance(my_source, Source)
diff --git a/tests/test_ring_source.py b/tests/test_ring_source.py
new file mode 100644
index 0000000..b5c1681
--- /dev/null
+++ b/tests/test_ring_source.py
@@ -0,0 +1,8 @@
+from openmc_plasma_source import FusionRingSource
+
+from openmc import Source
+
+
+def test_creation():
+    my_source = FusionRingSource()
+    assert isinstance(my_source, Source)
diff --git a/tests/test_tokamak_source.py b/tests/test_tokamak_source.py
new file mode 100644
index 0000000..c2a406e
--- /dev/null
+++ b/tests/test_tokamak_source.py
@@ -0,0 +1,9 @@
+from openmc_plasma_source import TokamkaSource
+
+from openmc import Source
+
+
+def test_creation():
+    my_source = TokamkaSource()
+    for source in my_source:
+        assert isinstance(source, Source)