diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 19ec060b..a1350bf7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,11 +11,8 @@ jobs:
strategy:
fail-fast: false
matrix:
- numpy-version: ["1.15.0", "1.16.6", "1.19.2"]
- python-version: ["3.6", "3.7", "3.8"]
- exclude:
- - python-version: "3.8"
- numpy-version: "1.15.0"
+ numpy-version: ["oldest-supported-numpy", "numpy"]
+ python-version: ["3.7", "3.8", "3.9", "3.10"]
steps:
- name: Checkout code
uses: actions/checkout@v2
@@ -26,9 +23,9 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Install Python dependencies
- run: python -m pip install cython>=0.28 numpy==${{ matrix.numpy-version }} scipy matplotlib
+ run: python -m pip install --prefer-binary cython>=0.28 ${{ matrix.numpy-version }} scipy matplotlib "pyopencl[pocl]>=2022.2.4"
- name: Install Raysect from pypi
- run: pip install raysect
+ run: pip install raysect==0.7.1
- name: Build cherab
run: dev/build.sh
- name: Run tests
diff --git a/.gitignore b/.gitignore
index b4bad474..7045bc61 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,4 @@ build/
.nfs*
.coverage
htmlcov*
+cherab.egg-info/
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e211f506..1ae0a7d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,39 @@
Project Changelog
=================
-Release 1.3.0 (8 Dec 2021)
+Release 1.4.0 (3 Feb 2023)
-------------------
+API changes:
+* Spectroscopic observers and their groups are deprecated and replaced by groups based on Raysect's 0D observers. (#332)
+* Support for Python 3.6 is dropped. It may still work, but is no longer actively tested.
+
+Bug fixes:
+* Fixed generomak plasma edge data paths.
+* Fix and improve OpenCL utility functions. (#358)
+* Fixed Bremsstrahlung trapezium evaluation (#384).
+
+New:
+* Make f_profile (current flux) a read-only attribute of EFITEquilibrium. (#355)
+* Add group observer class for each of Raysect's 0D observers. (#332)
+* Add a demo for observer group handling and plotting.
+* Add verbose parameter to SartOpencl solver (default is False). (#358)
+* Add Thomson Scattering model. (#97)
+* Add Generomak core plasma profiles. (#360)
+* Add toroidal_mesh_from_polygon for making mesh for not fully-360 degrees axisymmetric elements. (#365)
+* Add common spectroscopic instruments: Polychromator, SurveySpectrometer, CzernyTurnerSpectrometer. (#299)
+* Add new classes for free-free Gaunt factors and improve accuracy of the Gaunt factor used in Bremsstrahlung emission model. (#352)
+* Add GaussianQuadrature integration method for Function1D. (#366)
+* Add integrator attribute to LineShapeModel to use with lineshapes that cannot be analytically integrated over a spectral bin. (#366)
+* Add a numerical integration of StarkBroadenedLine over the spectral bin. (#366)
+* Add Generomak full plasma profiles obtained by blending the core and edge profiles. (#372)
+* Clean up build/install dependencies. (#353)
+* Test against Python 3.10 and latest released Numpy. Drop Python 3.6 and older Numpy from tests. (#391)
+
+
+Release 1.3.0 (8 Dec 2021)
+--------------------------
+
API changes:
* Use of Cherab's interpolators is now deprecated in favour of those upstream in Raysect.
diff --git a/README.md b/README.md
index b3141d05..963b0834 100644
--- a/README.md
+++ b/README.md
@@ -12,56 +12,66 @@ for guidance on using the code.
Installation
------------
-Cherab is a large code framework consisting of a core package and feature
-packages. Users will generally install the core package and the specific
-feature packages they need for their work. For example, users working on the
-JET tokamak will require the ``cherab-core`` package, and the ``cherab-jet``
+Cherab is a large code framework consisting of a core package and feature
+packages. Users will generally install the core package and the specific
+feature packages they need for their work. For example, users working on the
+JET tokamak will require the `cherab-core` package, and the `cherab-jet`
package.
-Unless developing new code for a cherab package, most users should clone the
-master branch. When developing new features for cherab, the development branch
+Unless developing new code for a cherab package, most users should clone the
+master branch. When developing new features for cherab, the development branch
should be used as the base.
-All cherab packages are standard python packages and basic installation is
+All cherab packages are standard python packages and basic installation is
achieved with:
```
-python setup.py install
+pip install cherab
```
-This will compile the Cherab cython extensions and install the package. If you
-don't have administrator access to install the package, add the ``--user`` flag
+This will compile the Cherab cython extensions and install the package. If you
+don't have administrator access to install the package, add the `--user` flag
to the above line to install the package under your own user account.
+Alternatively, consider creating a [virtual environment](https://docs.python.org/3/tutorial/venv.html)
+and installing `cherab` in the environment.
-When developing cherab it is usually preferred that the packages be installed
-in "develop" mode:
+When developing cherab it is usually preferred that the packages be installed
+in "editable" mode. Clone this repository and change directory to the root of
+the repository, then run:
```
-python setup.py develop
+pip install -e .
```
-This will cause the original installation folder to be added to the
-site-package path. Modifications to the code will therefore be visible to
-python next time the code is imported. The ``--user`` flag should be used if
-you do not have administrative permission for your python installation.
+This will cause the original installation folder to be added to the site-package
+path. Modifications to the code will therefore be visible to python next time
+the code is imported. A virtual environment or the ``--user`` flag should be
+used if you do not have administrative permission for your python installation.
+If you make any changes to Cython files you will need to run `./dev/build.sh` to
+rebuild the relevant files.
-As all the Cherab packages are dependent on the ``cherab-core`` package, this
-package must be installed first. Note that other packages may have their own
-inter-dependencies, see the specific package documentation for more
-information.
+As all the Cherab packages are dependent on the ``cherab-core`` package, this
+package must be installed first. Note that other packages may have their own
+inter-dependencies, see the specific package documentation for more information.
+
+Cherab is organised as a namespace package, where each of the submodules is
+installed in the same location as the core package. Any submodules using Cython
+with a build-time dependency on Cherab need to use a Cython version newer than
+3.0a5, due to a [bug](https://github.com/cython/cython/issues/2918) in how
+earlier versions of Cython handle namespaces.
Governance
----------
-The management of the project is divided into Scientific and Technical Project
-Management. The Scientific management happens through the normal community
+The management of the project is divided into Scientific and Technical Project
+Management. The Scientific management happens through the normal community
routes such as JET and MST1 task force meetings, ITPA meetings, etc.
-The Technical Management Committee (TMC) is a smaller subset of the community,
-being responsible for ensuring the integrity and high code quality of Cherab is
-maintained. These TMC members would have in-depth knowledge of the code base
-through a demonstrated history of contributing to the project. The TMC would
-primarily be responsible for accepting / rejecting merge requests on the basis
+The Technical Management Committee (TMC) is a smaller subset of the community,
+being responsible for ensuring the integrity and high code quality of Cherab is
+maintained. These TMC members would have in-depth knowledge of the code base
+through a demonstrated history of contributing to the project. The TMC would
+primarily be responsible for accepting / rejecting merge requests on the basis
of code / physics algorithm quality standards.
@@ -78,6 +88,6 @@ TMC Members
Citing The Code
---------------
-* Dr Carine Giroud, Dr Alex Meakins, Dr Matthew Carr, Dr Alfonso Baciero, &
-Mr Corentin Bertrand. (2018, March 23). Cherab Spectroscopy Modelling Framework
+* Dr Carine Giroud, Dr Alex Meakins, Dr Matthew Carr, Dr Alfonso Baciero, &
+Mr Corentin Bertrand. (2018, March 23). Cherab Spectroscopy Modelling Framework
(Version v0.1.0). Zenodo. http://doi.org/10.5281/zenodo.1206142
diff --git a/cherab/core/VERSION b/cherab/core/VERSION
index f0bb29e7..88c5fb89 100644
--- a/cherab/core/VERSION
+++ b/cherab/core/VERSION
@@ -1 +1 @@
-1.3.0
+1.4.0
diff --git a/cherab/core/atomic/__init__.pxd b/cherab/core/atomic/__init__.pxd
index 0aa3cb90..3b2aa5c6 100644
--- a/cherab/core/atomic/__init__.pxd
+++ b/cherab/core/atomic/__init__.pxd
@@ -22,4 +22,5 @@ from cherab.core.atomic.line cimport Line
from cherab.core.atomic.interface cimport AtomicData
from cherab.core.atomic.rates cimport *
from cherab.core.atomic.zeeman cimport ZeemanStructure
+from cherab.core.atomic.gaunt cimport *
diff --git a/cherab/core/atomic/__init__.py b/cherab/core/atomic/__init__.py
index 3bb11780..35a7f80e 100644
--- a/cherab/core/atomic/__init__.py
+++ b/cherab/core/atomic/__init__.py
@@ -22,3 +22,4 @@
from .interface import AtomicData
from .rates import *
from .zeeman import ZeemanStructure
+from .gaunt import *
diff --git a/cherab/core/atomic/data/maxwellian_free_free_gaunt_factor.json b/cherab/core/atomic/data/maxwellian_free_free_gaunt_factor.json
new file mode 100644
index 00000000..124e0622
--- /dev/null
+++ b/cherab/core/atomic/data/maxwellian_free_free_gaunt_factor.json
@@ -0,0 +1,946 @@
+{
+ "u": [
+ 0.0001,
+ 0.001,
+ 0.01,
+ 0.1,
+ 1.0,
+ 10.0,
+ 100.0,
+ 1000.0,
+ 10000.0
+ ],
+ "gamma2": [
+ 1e-08,
+ 1.5848931924611143e-08,
+ 2.511886431509582e-08,
+ 3.981071705534969e-08,
+ 6.30957344480193e-08,
+ 1e-07,
+ 1.584893192461114e-07,
+ 2.5118864315095823e-07,
+ 3.981071705534969e-07,
+ 6.30957344480193e-07,
+ 1e-06,
+ 1.584893192461114e-06,
+ 2.5118864315095823e-06,
+ 3.981071705534969e-06,
+ 6.30957344480193e-06,
+ 1e-05,
+ 1.584893192461114e-05,
+ 2.5118864315095822e-05,
+ 3.9810717055349695e-05,
+ 6.309573444801929e-05,
+ 0.0001,
+ 0.00015848931924611142,
+ 0.00025118864315095795,
+ 0.00039810717055349735,
+ 0.000630957344480193,
+ 0.001,
+ 0.001584893192461114,
+ 0.0025118864315095794,
+ 0.003981071705534973,
+ 0.00630957344480193,
+ 0.01,
+ 0.015848931924611134,
+ 0.025118864315095794,
+ 0.039810717055349734,
+ 0.06309573444801933,
+ 0.1,
+ 0.15848931924611134,
+ 0.251188643150958,
+ 0.3981071705534972,
+ 0.6309573444801932,
+ 1.0,
+ 1.5848931924611136,
+ 2.51188643150958,
+ 3.9810717055349722,
+ 6.309573444801933,
+ 10.0,
+ 15.848931924611133,
+ 25.118864315095795,
+ 39.810717055349734,
+ 63.09573444801933,
+ 100.0,
+ 158.48931924611142,
+ 251.18864315095797,
+ 398.1071705534973,
+ 630.957344480193,
+ 1000.0,
+ 1584.893192461114,
+ 2511.88643150958,
+ 3981.0717055349733,
+ 6309.57344480193,
+ 10000.0,
+ 15848.93192461114,
+ 25118.864315095823,
+ 39810.71705534969,
+ 63095.7344480193,
+ 100000.0,
+ 158489.3192461114,
+ 251188.6431509582,
+ 398107.1705534969,
+ 630957.344480193,
+ 1000000.0,
+ 1584893.1924611141,
+ 2511886.4315095823,
+ 3981071.7055349695,
+ 6309573.44480193,
+ 10000000.0,
+ 15848931.924611142,
+ 25118864.315095823,
+ 39810717.05534969,
+ 63095734.448019296,
+ 100000000.0,
+ 158489319.2461111,
+ 251188643.1509582,
+ 398107170.5534969,
+ 630957344.4801943,
+ 1000000000.0,
+ 1584893192.4611108,
+ 2511886431.509582,
+ 3981071705.5349693,
+ 6309573444.801943,
+ 10000000000.0
+ ],
+ "gaunt_factor": [
+ [
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.528,
+ 5.527,
+ 5.527,
+ 5.527,
+ 5.527,
+ 5.526,
+ 5.525,
+ 5.523,
+ 5.52,
+ 5.516,
+ 5.51,
+ 5.501,
+ 5.489,
+ 5.472,
+ 5.449,
+ 5.419,
+ 5.379,
+ 5.329,
+ 5.267,
+ 5.193,
+ 5.107,
+ 5.01,
+ 4.904,
+ 4.792,
+ 4.676,
+ 4.557,
+ 4.436,
+ 4.315,
+ 4.194,
+ 4.073,
+ 3.953,
+ 3.833,
+ 3.714,
+ 3.596,
+ 3.479,
+ 3.363,
+ 3.249,
+ 3.136,
+ 3.025,
+ 2.916,
+ 2.808,
+ 2.703,
+ 2.6,
+ 2.5,
+ 2.402,
+ 2.307,
+ 2.215,
+ 2.127,
+ 2.042,
+ 1.96,
+ 1.882,
+ 1.807,
+ 1.737,
+ 1.67,
+ 1.608,
+ 1.549,
+ 1.494,
+ 1.444,
+ 1.397,
+ 1.354,
+ 1.314,
+ 1.278,
+ 1.246,
+ 1.217,
+ 1.19,
+ 1.167,
+ 1.146,
+ 1.127,
+ 1.11,
+ 1.096,
+ 1.083,
+ 1.072
+ ],
+ [
+ 4.259,
+ 4.259,
+ 4.259,
+ 4.259,
+ 4.259,
+ 4.259,
+ 4.259,
+ 4.259,
+ 4.259,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.26,
+ 4.259,
+ 4.258,
+ 4.257,
+ 4.254,
+ 4.249,
+ 4.241,
+ 4.231,
+ 4.216,
+ 4.195,
+ 4.167,
+ 4.131,
+ 4.083,
+ 4.025,
+ 3.955,
+ 3.873,
+ 3.782,
+ 3.682,
+ 3.577,
+ 3.468,
+ 3.357,
+ 3.245,
+ 3.134,
+ 3.024,
+ 2.915,
+ 2.808,
+ 2.703,
+ 2.601,
+ 2.5,
+ 2.403,
+ 2.308,
+ 2.216,
+ 2.127,
+ 2.042,
+ 1.96,
+ 1.882,
+ 1.808,
+ 1.737,
+ 1.671,
+ 1.608,
+ 1.549,
+ 1.495,
+ 1.444,
+ 1.397,
+ 1.354,
+ 1.314,
+ 1.279,
+ 1.246,
+ 1.217,
+ 1.19,
+ 1.167,
+ 1.146,
+ 1.127,
+ 1.11,
+ 1.096,
+ 1.083,
+ 1.072,
+ 1.062,
+ 1.054,
+ 1.046,
+ 1.04,
+ 1.034,
+ 1.03,
+ 1.026,
+ 1.022,
+ 1.019,
+ 1.016
+ ],
+ [
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.002,
+ 3.003,
+ 3.003,
+ 3.003,
+ 3.004,
+ 3.004,
+ 3.005,
+ 3.006,
+ 3.007,
+ 3.008,
+ 3.01,
+ 3.011,
+ 3.013,
+ 3.015,
+ 3.016,
+ 3.018,
+ 3.018,
+ 3.016,
+ 3.012,
+ 3.004,
+ 2.991,
+ 2.971,
+ 2.944,
+ 2.907,
+ 2.86,
+ 2.803,
+ 2.735,
+ 2.658,
+ 2.574,
+ 2.486,
+ 2.396,
+ 2.306,
+ 2.216,
+ 2.129,
+ 2.045,
+ 1.963,
+ 1.885,
+ 1.811,
+ 1.74,
+ 1.673,
+ 1.61,
+ 1.552,
+ 1.497,
+ 1.446,
+ 1.399,
+ 1.355,
+ 1.316,
+ 1.28,
+ 1.247,
+ 1.218,
+ 1.191,
+ 1.167,
+ 1.146,
+ 1.128,
+ 1.111,
+ 1.096,
+ 1.084,
+ 1.072,
+ 1.063,
+ 1.054,
+ 1.047,
+ 1.04,
+ 1.035,
+ 1.03,
+ 1.026,
+ 1.022,
+ 1.019,
+ 1.016,
+ 1.014,
+ 1.012,
+ 1.01,
+ 1.009,
+ 1.008,
+ 1.007,
+ 1.006,
+ 1.005,
+ 1.004,
+ 1.004
+ ],
+ [
+ 1.806,
+ 1.806,
+ 1.806,
+ 1.807,
+ 1.807,
+ 1.807,
+ 1.807,
+ 1.807,
+ 1.807,
+ 1.807,
+ 1.807,
+ 1.808,
+ 1.808,
+ 1.808,
+ 1.809,
+ 1.81,
+ 1.81,
+ 1.812,
+ 1.813,
+ 1.815,
+ 1.817,
+ 1.819,
+ 1.823,
+ 1.827,
+ 1.832,
+ 1.838,
+ 1.846,
+ 1.855,
+ 1.865,
+ 1.877,
+ 1.89,
+ 1.903,
+ 1.914,
+ 1.923,
+ 1.928,
+ 1.926,
+ 1.917,
+ 1.898,
+ 1.869,
+ 1.831,
+ 1.785,
+ 1.733,
+ 1.678,
+ 1.622,
+ 1.566,
+ 1.512,
+ 1.461,
+ 1.413,
+ 1.369,
+ 1.328,
+ 1.291,
+ 1.257,
+ 1.227,
+ 1.199,
+ 1.175,
+ 1.153,
+ 1.133,
+ 1.116,
+ 1.101,
+ 1.087,
+ 1.076,
+ 1.065,
+ 1.056,
+ 1.049,
+ 1.042,
+ 1.036,
+ 1.031,
+ 1.027,
+ 1.023,
+ 1.02,
+ 1.017,
+ 1.015,
+ 1.013,
+ 1.011,
+ 1.009,
+ 1.008,
+ 1.007,
+ 1.006,
+ 1.005,
+ 1.004,
+ 1.004,
+ 1.003,
+ 1.003,
+ 1.002,
+ 1.002,
+ 1.002,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001
+ ],
+ [
+ 0.8424,
+ 0.8425,
+ 0.8425,
+ 0.8426,
+ 0.8426,
+ 0.8427,
+ 0.8428,
+ 0.8429,
+ 0.8431,
+ 0.8433,
+ 0.8436,
+ 0.8439,
+ 0.8443,
+ 0.8449,
+ 0.8455,
+ 0.8464,
+ 0.8474,
+ 0.8487,
+ 0.8504,
+ 0.8525,
+ 0.8552,
+ 0.8586,
+ 0.8628,
+ 0.8682,
+ 0.875,
+ 0.8835,
+ 0.8944,
+ 0.9079,
+ 0.925,
+ 0.9461,
+ 0.9719,
+ 1.003,
+ 1.04,
+ 1.081,
+ 1.126,
+ 1.172,
+ 1.216,
+ 1.253,
+ 1.279,
+ 1.294,
+ 1.296,
+ 1.287,
+ 1.27,
+ 1.248,
+ 1.224,
+ 1.2,
+ 1.178,
+ 1.157,
+ 1.137,
+ 1.12,
+ 1.104,
+ 1.091,
+ 1.079,
+ 1.068,
+ 1.059,
+ 1.051,
+ 1.044,
+ 1.038,
+ 1.032,
+ 1.028,
+ 1.024,
+ 1.021,
+ 1.018,
+ 1.015,
+ 1.013,
+ 1.011,
+ 1.01,
+ 1.008,
+ 1.007,
+ 1.006,
+ 1.005,
+ 1.004,
+ 1.004,
+ 1.003,
+ 1.003,
+ 1.002,
+ 1.002,
+ 1.002,
+ 1.002,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ],
+ [
+ 0.3035,
+ 0.3035,
+ 0.3035,
+ 0.3035,
+ 0.3036,
+ 0.3036,
+ 0.3037,
+ 0.3038,
+ 0.3039,
+ 0.304,
+ 0.3042,
+ 0.3044,
+ 0.3046,
+ 0.305,
+ 0.3054,
+ 0.3059,
+ 0.3066,
+ 0.3074,
+ 0.3084,
+ 0.3098,
+ 0.3114,
+ 0.3136,
+ 0.3163,
+ 0.3197,
+ 0.324,
+ 0.3296,
+ 0.3367,
+ 0.3457,
+ 0.3573,
+ 0.3722,
+ 0.3913,
+ 0.4156,
+ 0.4464,
+ 0.485,
+ 0.5328,
+ 0.5905,
+ 0.6581,
+ 0.7343,
+ 0.8157,
+ 0.8975,
+ 0.9731,
+ 1.037,
+ 1.084,
+ 1.113,
+ 1.127,
+ 1.129,
+ 1.124,
+ 1.115,
+ 1.104,
+ 1.093,
+ 1.083,
+ 1.073,
+ 1.064,
+ 1.056,
+ 1.049,
+ 1.042,
+ 1.036,
+ 1.032,
+ 1.027,
+ 1.023,
+ 1.02,
+ 1.017,
+ 1.015,
+ 1.013,
+ 1.011,
+ 1.01,
+ 1.008,
+ 1.007,
+ 1.006,
+ 1.005,
+ 1.004,
+ 1.004,
+ 1.003,
+ 1.003,
+ 1.002,
+ 1.002,
+ 1.002,
+ 1.002,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ],
+ [
+ 0.09801,
+ 0.09802,
+ 0.09803,
+ 0.09804,
+ 0.09806,
+ 0.09808,
+ 0.0981,
+ 0.09814,
+ 0.09818,
+ 0.09823,
+ 0.09829,
+ 0.09838,
+ 0.09848,
+ 0.09861,
+ 0.09877,
+ 0.09898,
+ 0.09924,
+ 0.09957,
+ 0.09999,
+ 0.1005,
+ 0.1012,
+ 0.102,
+ 0.1031,
+ 0.1045,
+ 0.1062,
+ 0.1084,
+ 0.1113,
+ 0.115,
+ 0.1198,
+ 0.126,
+ 0.134,
+ 0.1445,
+ 0.1582,
+ 0.1759,
+ 0.199,
+ 0.2286,
+ 0.2662,
+ 0.3132,
+ 0.3706,
+ 0.4388,
+ 0.5173,
+ 0.6044,
+ 0.6967,
+ 0.7898,
+ 0.8782,
+ 0.9561,
+ 1.019,
+ 1.064,
+ 1.091,
+ 1.104,
+ 1.107,
+ 1.103,
+ 1.096,
+ 1.087,
+ 1.078,
+ 1.069,
+ 1.061,
+ 1.054,
+ 1.047,
+ 1.041,
+ 1.036,
+ 1.031,
+ 1.027,
+ 1.023,
+ 1.02,
+ 1.017,
+ 1.015,
+ 1.013,
+ 1.011,
+ 1.009,
+ 1.008,
+ 1.007,
+ 1.006,
+ 1.005,
+ 1.004,
+ 1.004,
+ 1.003,
+ 1.003,
+ 1.002,
+ 1.002,
+ 1.002,
+ 1.002,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.0,
+ 1.0
+ ],
+ [
+ 0.03107,
+ 0.03107,
+ 0.03107,
+ 0.03108,
+ 0.03108,
+ 0.03109,
+ 0.0311,
+ 0.03111,
+ 0.03112,
+ 0.03114,
+ 0.03116,
+ 0.03119,
+ 0.03122,
+ 0.03127,
+ 0.03132,
+ 0.03139,
+ 0.03148,
+ 0.03159,
+ 0.03173,
+ 0.03191,
+ 0.03214,
+ 0.03242,
+ 0.03279,
+ 0.03325,
+ 0.03384,
+ 0.0346,
+ 0.03558,
+ 0.03684,
+ 0.03847,
+ 0.0406,
+ 0.04337,
+ 0.04702,
+ 0.05181,
+ 0.05812,
+ 0.06644,
+ 0.07735,
+ 0.09158,
+ 0.11,
+ 0.1335,
+ 0.1631,
+ 0.1998,
+ 0.2445,
+ 0.2981,
+ 0.361,
+ 0.4334,
+ 0.5146,
+ 0.6031,
+ 0.696,
+ 0.7892,
+ 0.8773,
+ 0.9548,
+ 1.017,
+ 1.062,
+ 1.089,
+ 1.102,
+ 1.104,
+ 1.101,
+ 1.094,
+ 1.085,
+ 1.076,
+ 1.068,
+ 1.06,
+ 1.053,
+ 1.046,
+ 1.04,
+ 1.035,
+ 1.03,
+ 1.026,
+ 1.023,
+ 1.019,
+ 1.017,
+ 1.014,
+ 1.012,
+ 1.011,
+ 1.009,
+ 1.008,
+ 1.007,
+ 1.006,
+ 1.005,
+ 1.004,
+ 1.004,
+ 1.003,
+ 1.003,
+ 1.002,
+ 1.002,
+ 1.002,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001,
+ 1.001
+ ],
+ [
+ 0.009826,
+ 0.009827,
+ 0.009828,
+ 0.00983,
+ 0.009831,
+ 0.009834,
+ 0.009836,
+ 0.00984,
+ 0.009845,
+ 0.00985,
+ 0.009857,
+ 0.009866,
+ 0.009877,
+ 0.009892,
+ 0.009909,
+ 0.009932,
+ 0.00996,
+ 0.009996,
+ 0.01004,
+ 0.0101,
+ 0.01017,
+ 0.01026,
+ 0.01038,
+ 0.01053,
+ 0.01072,
+ 0.01097,
+ 0.01128,
+ 0.01169,
+ 0.01222,
+ 0.01291,
+ 0.01381,
+ 0.015,
+ 0.01656,
+ 0.01863,
+ 0.02137,
+ 0.02499,
+ 0.02975,
+ 0.03597,
+ 0.04404,
+ 0.05439,
+ 0.06753,
+ 0.08403,
+ 0.1046,
+ 0.1299,
+ 0.161,
+ 0.1987,
+ 0.244,
+ 0.2979,
+ 0.3609,
+ 0.4334,
+ 0.5146,
+ 0.6031,
+ 0.696,
+ 0.7891,
+ 0.8772,
+ 0.9547,
+ 1.017,
+ 1.061,
+ 1.089,
+ 1.101,
+ 1.104,
+ 1.1,
+ 1.093,
+ 1.085,
+ 1.076,
+ 1.068,
+ 1.06,
+ 1.053,
+ 1.046,
+ 1.04,
+ 1.035,
+ 1.03,
+ 1.026,
+ 1.023,
+ 1.019,
+ 1.017,
+ 1.014,
+ 1.012,
+ 1.011,
+ 1.009,
+ 1.008,
+ 1.007,
+ 1.006,
+ 1.005,
+ 1.004,
+ 1.004,
+ 1.003,
+ 1.003,
+ 1.002,
+ 1.002,
+ 1.002
+ ]
+ ],
+ "reference": "M.A. de Avillez and D. Breitschwerdt, Temperature-averaged and total free-free Gaunt factors for κ and Maxwellian distributions of electrons, 2015, Astron. & Astrophys. 580, A124"
+}
diff --git a/cherab/core/atomic/gaunt.pxd b/cherab/core/atomic/gaunt.pxd
new file mode 100644
index 00000000..827831b6
--- /dev/null
+++ b/cherab/core/atomic/gaunt.pxd
@@ -0,0 +1,39 @@
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+from cherab.core.math cimport Function2D
+
+
+cdef class FreeFreeGauntFactor():
+
+ cpdef double evaluate(self, double z, double temperature, double wavelength) except? -1e999
+
+
+cdef class InterpolatedFreeFreeGauntFactor(FreeFreeGauntFactor):
+
+ cdef:
+ readonly tuple u_range, gamma2_range
+ readonly dict raw_data
+ double _u_min, _u_max, _gamma2_min, _gamma2_max
+ Function2D _gaunt_factor
+
+
+cdef class MaxwellianFreeFreeGauntFactor(InterpolatedFreeFreeGauntFactor):
+
+ pass
+
diff --git a/cherab/core/atomic/gaunt.pyx b/cherab/core/atomic/gaunt.pyx
new file mode 100644
index 00000000..eb1dbe59
--- /dev/null
+++ b/cherab/core/atomic/gaunt.pyx
@@ -0,0 +1,158 @@
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+from os import path
+import numpy as np
+import json
+
+from libc.math cimport log10, log, M_PI, sqrt
+from raysect.core.math.function.float cimport Interpolator2DArray
+from cherab.core.utility.constants cimport RYDBERG_CONSTANT_EV, SPEED_OF_LIGHT, ELEMENTARY_CHARGE, PLANCK_CONSTANT
+
+cimport cython
+
+
+DEF EULER_GAMMA = 0.5772156649015329
+
+cdef double PH_TO_EV_FACTOR = PLANCK_CONSTANT * SPEED_OF_LIGHT * 1e9 / ELEMENTARY_CHARGE
+
+
+cdef class FreeFreeGauntFactor():
+ """
+ The base class for temperature-averaged free-free Gaunt factors.
+ """
+
+ cpdef double evaluate(self, double z, double temperature, double wavelength) except? -1e999:
+ """
+ Returns the temperature-averaged free-free Gaunt factor for the supplied parameters.
+
+ :param double z: Species charge or effective plasma charge.
+ :param double temperature: Electron temperature in eV.
+ :param double wavelength: Spectral wavelength.
+
+ :return: free-free Gaunt factor
+ """
+ raise NotImplementedError("The evaluate() virtual method must be implemented.")
+
+ def __call__(self, double z, double temperature, double wavelength):
+ """
+ Returns the temperature-averaged free-free Gaunt factor for the supplied parameters.
+
+ :param double z: Species charge or effective plasma charge.
+ :param double temperature: Electron temperature in eV.
+ :param double wavelength: Spectral wavelength.
+
+ :return: free-free Gaunt factor
+ """
+
+ return self.evaluate(z, temperature, wavelength)
+
+
+cdef class InterpolatedFreeFreeGauntFactor(FreeFreeGauntFactor):
+ r"""
+ The temperature-averaged free-free Gaunt factors interpolated in the space of parameters:
+ :math:`u = h{\nu}/kT` and :math:`{\gamma}^{2} = Z^{2}Ry/kT`.
+ See T.R. Carson, 1988, Astron. & Astrophys., 189,
+ `319 `_ for details.
+
+ The cubic interpolation in a semi-log space is used.
+
+ The Born approximation is used outside the interpolation range.
+
+ :param object u: A 1D array-like object of real values.
+ :param object gamma2: A 1D array-like object of real values.
+ :param object gaunt_factor: 2D array-like object of real values
+ storing the Gaunt factor values at u, gamma2.
+
+ :ivar tuple u_range: The interpolation range of `u` parameter.
+ :ivar tuple gamma2_range: The interpolation range of :math:`\\gamma^2` parameter.
+ :ivar dict raw_data: Dictionary containing the raw data.
+ """
+
+ def __init__(self, object u, object gamma2, object gaunt_factor):
+
+ u = np.array(u, dtype=np.float64)
+ u.flags.writeable = False
+ gamma2 = np.array(gamma2, dtype=np.float64)
+ gamma2.flags.writeable = False
+ gaunt_factor = np.array(gaunt_factor, dtype=np.float64)
+ gaunt_factor.flags.writeable = False
+
+ self.raw_data = {'u': u, 'gamma2': gamma2, 'gaunt_factor': gaunt_factor}
+
+ self._u_min = u.min()
+ self._u_max = u.max()
+ self._gamma2_min = gamma2.min()
+ self._gamma2_max = gamma2.max()
+
+ self.u_range = (self._u_min, self._u_max)
+ self.gamma2_range = (self._gamma2_min, self._gamma2_max)
+
+ self._gaunt_factor = Interpolator2DArray(np.log10(u), np.log10(gamma2), gaunt_factor, 'cubic', 'none', 0, 0)
+
+ @cython.cdivision(True)
+ cpdef double evaluate(self, double z, double temperature, double wavelength) except? -1e999:
+ """
+ Returns the temperature-averaged free-free Gaunt factor for the supplied parameters.
+
+ :param double z: Species charge or effective plasma charge.
+ :param double temperature: Electron temperature in eV.
+ :param double wavelength: Spectral wavelength.
+
+ :return: free-free Gaunt factor
+ """
+
+ cdef:
+ double u, gamma2
+
+ if z == 0:
+
+ return 0
+
+ gamma2 = z * z * RYDBERG_CONSTANT_EV / temperature
+ u = PH_TO_EV_FACTOR / (temperature * wavelength)
+
+ # classical limit
+ if u >= self._u_max or gamma2 >= self._gamma2_max:
+
+ return 1
+
+ # Born approximation limit
+ if u < self._u_min or gamma2 < self._gamma2_min:
+
+ return sqrt(3) / M_PI * (log(4 / u) - EULER_GAMMA)
+
+ return self._gaunt_factor.evaluate(log10(u), log10(gamma2))
+
+
+cdef class MaxwellianFreeFreeGauntFactor(InterpolatedFreeFreeGauntFactor):
+ r"""
+ The Maxwellian-averaged free-free Gaunt factor interpolated over the data from Table A.1 in
+ M.A. de Avillez and D. Breitschwerdt, "Temperature-averaged and total free-free Gaunt factors
+ for κ and Maxwellian distributions of electrons", 2015, Astron. & Astrophys. 580,
+ `A124 `_.
+
+ The Born approximation is used outside the interpolation range.
+ """
+
+ def __init__(self):
+
+ with open(path.join(path.dirname(__file__), "data/maxwellian_free_free_gaunt_factor.json")) as f:
+ data = json.load(f)
+
+ super().__init__(data['u'], data['gamma2'], data['gaunt_factor'])
diff --git a/cherab/core/atomic/interface.pxd b/cherab/core/atomic/interface.pxd
index 9ada928e..66d8faf8 100644
--- a/cherab/core/atomic/interface.pxd
+++ b/cherab/core/atomic/interface.pxd
@@ -1,6 +1,6 @@
-# Copyright 2016-2018 Euratom
-# Copyright 2016-2018 United Kingdom Atomic Energy Authority
-# Copyright 2016-2018 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
#
# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
# European Commission - subsequent versions of the EUPL (the "Licence");
@@ -19,6 +19,7 @@
from cherab.core.atomic.elements cimport Element
from cherab.core.atomic.line cimport Line
from cherab.core.atomic.zeeman cimport ZeemanStructure
+from cherab.core.atomic.gaunt cimport FreeFreeGauntFactor
from cherab.core.atomic.rates cimport *
@@ -56,3 +57,5 @@ cdef class AtomicData:
cpdef ZeemanStructure zeeman_structure(self, Line line, object b_field=*)
+ cpdef FreeFreeGauntFactor free_free_gaunt_factor(self)
+
diff --git a/cherab/core/atomic/interface.pyx b/cherab/core/atomic/interface.pyx
index e5219205..286ebfb4 100644
--- a/cherab/core/atomic/interface.pyx
+++ b/cherab/core/atomic/interface.pyx
@@ -1,6 +1,6 @@
-# Copyright 2016-2018 Euratom
-# Copyright 2016-2018 United Kingdom Atomic Energy Authority
-# Copyright 2016-2018 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
#
# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
# European Commission - subsequent versions of the EUPL (the "Licence");
@@ -16,6 +16,8 @@
# See the Licence for the specific language governing permissions and limitations
# under the Licence.
+from .gaunt import MaxwellianFreeFreeGauntFactor
+
cdef class AtomicData:
"""
@@ -92,3 +94,14 @@ cdef class AtomicData:
cpdef ZeemanStructure zeeman_structure(self, Line line, object b_field=None):
raise NotImplementedError("The zeeman_structure() virtual method is not implemented for this atomic data source.")
+
+ cpdef FreeFreeGauntFactor free_free_gaunt_factor(self):
+ """
+ Returns the Maxwellian-averaged free-free Gaunt factor interpolated over the data
+ from Table A.1 in M.A. de Avillez and D. Breitschwerdt, 2015, Astron. & Astrophys. 580,
+ `A124 `_.
+
+ The Born approximation is used outside the interpolation range.
+ """
+
+ return MaxwellianFreeFreeGauntFactor()
diff --git a/cherab/core/laser/__init__.pxd b/cherab/core/laser/__init__.pxd
new file mode 100644
index 00000000..2760a2ea
--- /dev/null
+++ b/cherab/core/laser/__init__.pxd
@@ -0,0 +1,4 @@
+from cherab.core.laser.node cimport Laser
+from cherab.core.laser.model cimport LaserModel
+from cherab.core.laser.laserspectrum cimport LaserSpectrum
+from cherab.core.laser.profile cimport LaserProfile
\ No newline at end of file
diff --git a/cherab/core/laser/__init__.py b/cherab/core/laser/__init__.py
new file mode 100644
index 00000000..911a64b1
--- /dev/null
+++ b/cherab/core/laser/__init__.py
@@ -0,0 +1,4 @@
+from .node import Laser
+from .model import LaserModel
+from .laserspectrum import LaserSpectrum
+from .profile import LaserProfile
\ No newline at end of file
diff --git a/cherab/core/laser/laserspectrum.pxd b/cherab/core/laser/laserspectrum.pxd
new file mode 100644
index 00000000..a00945eb
--- /dev/null
+++ b/cherab/core/laser/laserspectrum.pxd
@@ -0,0 +1,47 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.core.math.function.float cimport Function1D
+
+from cherab.core.utility.constants cimport SPEED_OF_LIGHT, PLANCK_CONSTANT
+
+from numpy cimport ndarray
+
+
+cdef class LaserSpectrum(Function1D):
+
+ cdef:
+ double _min_wavelength, _max_wavelength, _delta_wavelength
+ int _bins
+ ndarray _power, _power_spectral_density, _wavelengths # power_spectral_density [w/nm]
+ double[::1] power_mv, power_spectral_density_mv, wavelengths_mv
+
+ cpdef double evaluate_integral(self, double lower_limit, double upper_limit)
+
+ cpdef void _update_cache(self)
+
+ cpdef double get_min_wavelenth(self)
+
+ cpdef double get_max_wavelenth(self)
+
+ cpdef int get_spectral_bins(self)
+
+ cpdef double get_delta_wavelength(self)
+
+ cpdef double _get_bin_power_spectral_density(self, double wavelength_lower, double wavelength_upper)
\ No newline at end of file
diff --git a/cherab/core/laser/laserspectrum.pyx b/cherab/core/laser/laserspectrum.pyx
new file mode 100644
index 00000000..e196fba1
--- /dev/null
+++ b/cherab/core/laser/laserspectrum.pyx
@@ -0,0 +1,192 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.core.math.function.float cimport Function1D
+from raysect.optical cimport Point3D, Vector3D
+
+from cherab.core.utility import Notifier
+from cherab.core.utility.constants cimport SPEED_OF_LIGHT, PLANCK_CONSTANT
+
+import numpy as np
+cimport numpy as np
+
+
+cdef class LaserSpectrum(Function1D):
+ """
+ Laser spectrum base class.
+
+ This is an abstract class and cannot be used for observing.
+
+ A 1D function holding information about the spectral properties
+ of a laser. The scattered spectrum is calculated as an iteration
+ over the laser spectrum.
+
+
+ .. warning::
+ When adding a LaserSpectrum, a special care should be given
+ to the integral power of the laser spectrum. During the
+ scattering calculation, the spectral power can be multiplied
+ by the power spatial distribution [W * m ** -3] of the laser
+ power from the LaserProfile. If the integral power
+ of the LaserSpectrum is not 1, unexpected values
+ might be obtained.
+
+ .. note::
+ It is expected that majority of the fusion applications can
+ neglect the influence of the spectral shape of the
+ laser and can use laser spectrum with a single
+ bin, which approximates an infinitely narrow laser spectrum.
+
+ :param float min_wavelength: The minimum wavelength of the laser
+ spectrum in nm.
+ :param float max_wavelength: The maximum wavelength of the laser
+ spectrum in nm.
+ :param int bins: The number of spectral bins of the laser spectrum.
+ :ivar float min_wavelength: The minimum wavelength of the laser
+ spectrum in nm.
+ :ivar float max_wavelength: The maximum wavelength of the laser
+ spectrum in nm.
+ :ivar int bins: The number of specral bins of the laser spectrum
+ :ivar ndarray wavelengths: The wavelengt coordinate vector in nm.
+ :ivar ndarray power_spectral_density: The values of the power
+ spectral density in W / nm.
+ :ivar float delta_wavelength: Spectral width of the bins in nm.
+ """
+
+ def __init__(self, double min_wavelength, double max_wavelength, int bins):
+
+ super().__init__()
+
+ self._check_wavelength_validity(min_wavelength, max_wavelength)
+
+ self._min_wavelength = min_wavelength
+ self._max_wavelength = max_wavelength
+
+ self.bins = bins
+
+ @property
+ def min_wavelength(self):
+ return self._min_wavelength
+
+ @min_wavelength.setter
+ def min_wavelength(self, double value):
+
+ self._check_wavelength_validity(value, self.max_wavelength)
+ self._min_wavelength = value
+ self._update_cache()
+
+ @property
+ def max_wavelength(self):
+ return self._max_wavelength
+
+ @max_wavelength.setter
+ def max_wavelength(self, double value):
+
+ self._check_wavelength_validity(self.min_wavelength, value)
+ self._max_wavelength = value
+ self._update_cache()
+
+ @property
+ def bins(self):
+ return self._bins
+
+ @bins.setter
+ def bins(self, int value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0")
+
+ self._bins = value
+ self._update_cache()
+
+ @property
+ def wavelengths(self):
+ return self._wavelengths
+
+ @property
+ def power_spectral_density(self):
+ return self._power_spectral_density
+
+ @property
+ def delta_wavelength(self):
+ return self._delta_wavelength
+
+ def _check_wavelength_validity(self, min_wavelength, max_wavelength):
+
+ if min_wavelength <= 0:
+ raise ValueError("min_wavelength has to be larger than 0, but {} passed.".format(min_wavelength))
+ if max_wavelength <= 0:
+ raise ValueError("min_wavelength has to be larger than 0, but {} passed.".format(max_wavelength))
+
+ if min_wavelength >= max_wavelength:
+ raise ValueError("min_wavelength has to be smaller than max_wavelength: min_wavelength={} > max_wavelength={}".format(min_wavelength, max_wavelength))
+
+ cpdef double get_min_wavelenth(self):
+ return self._min_wavelength
+
+ cpdef double get_max_wavelenth(self):
+ return self._min_wavelength
+
+ cpdef int get_spectral_bins(self):
+ return self._bins
+
+ cpdef double get_delta_wavelength(self):
+ return self._delta_wavelength
+
+ cpdef void _update_cache(self):
+
+ cdef:
+ Py_ssize_t index
+ double delta_wvl_half, wvl_lower, wvl_upper, wvl
+
+ self._delta_wavelength = (self._max_wavelength - self._min_wavelength) / self._bins
+ self._wavelengths = np.zeros(self.bins, dtype=np.double)
+ self.wavelengths_mv = self._wavelengths
+
+ for index in range(self._bins):
+ self._wavelengths[index] = self._min_wavelength + (0.5 + index) * self._delta_wavelength
+
+ self._power_spectral_density = np.zeros(self._bins, dtype=np.double) # power spectral density (PSD)
+ self.power_spectral_density_mv = self._power_spectral_density
+
+ self._power = np.zeros(self._bins, dtype=np.double) # power in a spectral bin (PSD * delta wavelength)
+ self.power_mv = self._power
+
+ delta_wvl_half = self._delta_wavelength * 0.5
+ wvl_lower = self.wavelengths_mv[0] - delta_wvl_half
+
+ for index in range(self._bins):
+ wvl = wvl_lower + delta_wvl_half
+ wvl_upper = wvl_lower + self._delta_wavelength
+
+ self.power_spectral_density_mv[index] = self._get_bin_power_spectral_density(wvl_lower, wvl_upper)
+ self.power_mv[index] = self.power_spectral_density_mv[index] * self._delta_wavelength # power in the spectral bin for scattering calculations
+
+ wvl_lower = wvl_upper
+
+ cpdef double evaluate_integral(self, double lower_limit, double upper_limit):
+ raise NotImplementedError('Virtual method must be implemented in a sub-class.')
+
+ cpdef double _get_bin_power_spectral_density(self, double wavelength_lower, double wavelength_upper):
+ """
+ Returns the power spectral density in a bin.
+
+ This method can be overidden if a better precision is needed.
+ For example for distributions with known cumulative distribution function.
+ """
+ return 0.5 * (self.evaluate(wavelength_lower) + self.evaluate(wavelength_upper))
diff --git a/cherab/core/laser/material.pxd b/cherab/core/laser/material.pxd
new file mode 100644
index 00000000..c91fa416
--- /dev/null
+++ b/cherab/core/laser/material.pxd
@@ -0,0 +1,31 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.core.scenegraph._nodebase cimport _NodeBase
+from raysect.core.math cimport AffineMatrix3D
+from raysect.optical.material.emitter cimport InhomogeneousVolumeEmitter
+
+from cherab.core.laser.node cimport Laser
+
+
+cdef class LaserMaterial(InhomogeneousVolumeEmitter):
+
+ cdef:
+ AffineMatrix3D _laser_to_plasma, _laser_segment_to_laser_node
+ list _models
diff --git a/cherab/core/laser/material.pyx b/cherab/core/laser/material.pyx
new file mode 100644
index 00000000..4732e01a
--- /dev/null
+++ b/cherab/core/laser/material.pyx
@@ -0,0 +1,66 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.core.scenegraph._nodebase cimport _NodeBase
+from raysect.optical cimport World, Primitive, Ray, Spectrum, Point3D, Vector3D, AffineMatrix3D
+from raysect.optical.material.emitter cimport InhomogeneousVolumeEmitter
+from raysect.optical.material.emitter.inhomogeneous cimport VolumeIntegrator
+
+from cherab.core.laser.node cimport Laser
+from cherab.core.laser.model cimport LaserModel
+
+
+cdef class LaserMaterial(InhomogeneousVolumeEmitter):
+
+ def __init__(self, Laser laser not None, _NodeBase laser_segment not None, list models, VolumeIntegrator integrator not None):
+
+ super().__init__(integrator)
+
+ self._laser_segment_to_laser_node = laser_segment.to(laser)
+ self._laser_to_plasma = laser_segment.to(laser.plasma)
+ self.importance = laser.importance
+
+ #validate and set models
+ for model in models:
+ if not isinstance(model, LaserModel):
+ raise TypeError("Model supplied to laser are not LaserMaterial is not LaserModel")
+ model.plasma = laser.plasma
+ model.laser_profile = laser.laser_profile
+ model.laser_spectrum = laser.laser_spectrum
+
+ self._models = models
+
+ cpdef Spectrum emission_function(self, Point3D point, Vector3D direction, Spectrum spectrum,
+ World world, Ray ray, Primitive primitive,
+ AffineMatrix3D to_local, AffineMatrix3D to_world):
+
+ cdef:
+ Point3D point_plasma, point_laser
+ Vector3D direction_plasma, direction_laser
+ LaserModel model
+
+ point_laser = point.transform(self._laser_segment_to_laser_node)
+ direction_laser = direction.transform(self._laser_segment_to_laser_node) # observation vector in the laser frame
+ point_plasma = point.transform(self._laser_to_plasma)
+ direction_plasma = direction.transform(self._laser_to_plasma)
+
+ for model in self._models:
+ spectrum = model.emission(point_plasma, direction_plasma, point_laser, direction_laser, spectrum)
+
+ return spectrum
diff --git a/cherab/core/laser/model.pxd b/cherab/core/laser/model.pxd
new file mode 100644
index 00000000..71cdf9a8
--- /dev/null
+++ b/cherab/core/laser/model.pxd
@@ -0,0 +1,37 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.optical cimport Vector3D, Point3D
+from raysect.optical.spectrum cimport Spectrum
+
+from cherab.core cimport Plasma
+from cherab.core.laser.profile cimport LaserProfile
+from cherab.core.laser.laserspectrum cimport LaserSpectrum
+
+
+cdef class LaserModel:
+ cdef:
+ Plasma _plasma
+ LaserSpectrum _laser_spectrum
+ LaserProfile _laser_profile
+
+ cpdef Spectrum emission(self, Point3D point_plasma, Vector3D observation_plasma, Point3D point_laser,
+ Vector3D observation_laser, Spectrum spectrum)
+
+ cdef object __weakref__
diff --git a/cherab/core/laser/model.pyx b/cherab/core/laser/model.pyx
new file mode 100644
index 00000000..c7d76cae
--- /dev/null
+++ b/cherab/core/laser/model.pyx
@@ -0,0 +1,78 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.optical cimport Vector3D, Point3D
+from raysect.optical.spectrum cimport Spectrum
+
+from cherab.core cimport Plasma
+from cherab.core.laser.profile cimport LaserProfile
+from cherab.core.laser.laserspectrum cimport LaserSpectrum
+
+
+cdef class LaserModel:
+ """
+ Laser spectrum base class.
+
+ This is an abstract class and cannot be used for observing.
+
+ Calculates the contribution to a spectrum caused by a laser.
+
+ :param laser_profile: LaserProfile object
+ :param plasma: Plasma object
+ :param laser_spectrum: LaserSpectrum object
+
+ :ivar laser_profile: LaserProfile object
+ :ivar plasma: Plasma object
+ :ivar laser_spectrum: LaserSpectrum object
+ """
+ def __init__(self, LaserProfile laser_profile=None, LaserSpectrum laser_spectrum=None, Plasma plasma=None):
+
+ self._laser_profile = laser_profile
+ self._laser_spectrum = laser_spectrum
+ self._plasma = plasma
+
+ cpdef Spectrum emission(self, Point3D point_plasma, Vector3D observation_plasma, Point3D point_laser, Vector3D observation_laser,
+ Spectrum spectrum):
+
+ raise NotImplementedError('Virtual method must be implemented in a sub-class.')
+
+ @property
+ def laser_profile(self):
+ return self._laser_profile
+
+ @laser_profile.setter
+ def laser_profile(self, LaserProfile value):
+ self._laser_profile = value
+
+ @property
+ def plasma(self):
+ return self._plasma
+
+ @plasma.setter
+ def plasma(self, Plasma value):
+ self._plasma = value
+
+ @property
+ def laser_spectrum(self):
+ return self._laser_spectrum
+
+ @laser_spectrum.setter
+ def laser_spectrum(self, LaserSpectrum value):
+
+ self._laser_spectrum = value
diff --git a/cherab/core/laser/node.pxd b/cherab/core/laser/node.pxd
new file mode 100644
index 00000000..6045fb4a
--- /dev/null
+++ b/cherab/core/laser/node.pxd
@@ -0,0 +1,55 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.optical cimport Point3D, Vector3D, Node, Spectrum, Primitive
+from raysect.optical.material.emitter.inhomogeneous cimport VolumeIntegrator
+from raysect.primitive cimport Cylinder
+
+from cherab.core.plasma cimport Plasma
+from cherab.core.laser.profile cimport LaserProfile
+from cherab.core.laser.laserspectrum cimport LaserSpectrum
+from cherab.core.laser.model cimport LaserModel
+
+
+cdef class ModelManager:
+
+ cdef:
+ list _models
+ readonly object notifier
+
+ cpdef object set(self, object models)
+
+ cpdef object add(self, LaserModel model)
+
+ cpdef object clear(self)
+
+
+cdef class Laser(Node):
+
+ cdef:
+ readonly object notifier
+ double _importance
+ Plasma _plasma
+ ModelManager _models
+ LaserProfile _laser_profile
+ LaserSpectrum _laser_spectrum
+ list _geometry
+ VolumeIntegrator _integrator
+
+ cdef object __weakref__
\ No newline at end of file
diff --git a/cherab/core/laser/node.pyx b/cherab/core/laser/node.pyx
new file mode 100644
index 00000000..b0b821b5
--- /dev/null
+++ b/cherab/core/laser/node.pyx
@@ -0,0 +1,261 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.primitive cimport Cylinder
+from raysect.optical cimport World, AffineMatrix3D, Primitive, Ray
+from raysect.optical.material.emitter.inhomogeneous cimport NumericalIntegrator
+from raysect.core cimport translate, Material
+
+from cherab.core.laser.material cimport LaserMaterial
+from cherab.core.laser.model cimport LaserModel
+from cherab.core.laser.profile import LaserProfile
+from cherab.core.laser.laserspectrum import LaserSpectrum
+from cherab.core.utility import Notifier
+from libc.math cimport M_PI
+
+from math import ceil
+
+cdef double DEGREES_TO_RADIANS = (M_PI / 180)
+
+
+cdef class ModelManager:
+
+ def __init__(self):
+ self._models = []
+ self.notifier = Notifier()
+
+ def __iter__(self):
+ return iter(self._models)
+
+ cpdef object set(self, object models):
+
+ # copy models and test it is an iterable
+ models = list(models)
+
+ # check contents of list are laser models
+ for model in models:
+ if not isinstance(model, LaserModel):
+ raise TypeError('The model list must consist of only LaserModel objects.')
+
+ self._models = models
+ self.notifier.notify()
+
+ cpdef object add(self, LaserModel model):
+
+ if not model:
+ raise ValueError('Model must not be None type.')
+
+ self._models.append(model)
+ self.notifier.notify()
+
+ cpdef object clear(self):
+ self._models = []
+ self.notifier.notify()
+
+
+cdef class Laser(Node):
+ """
+ A scene-graph object representing a laser of laser light.
+
+ The Cherab laser object holds basic information about the laser and connects
+ the components which are needed for the laser description. With specified
+ emission models it can contribute to observed radiation.
+
+ The Laser object is a Raysect scene-graph node and lives in it's own
+ coordinate space. This coordinate space is defined relative to it's parent
+ scene-graph object by an AffineTransform. The beam parameters are defined
+ in the Laser object coordinate space. Models using the beam object must
+ convert any spatial coordinates into beam space before requesting values
+ from the Laser object.
+
+ The main physical properties of the laser are defined by the three
+ attributes laser_spectrum, laser_profile and models. The laser_spectrum
+ has to be an instance of LaserSpectrum and defines the spectral properties
+ of the laser light. The laser_profile has to be an instance of LaserProfile
+ and it holds all the space related definitions as volumetric distribution
+ of laser light energy polarisation direction. In the models a list of LaserModels
+ can be stored, which calculate the contribution of the laser ligth to the observed
+ radiation. The models can cover various applications as for example
+ Thomson scattering. Please see the documentation of individual classes
+ for more detail.
+
+ The shape of the laser (e.g. cylinder) and its parameters (e.g. radius)
+ is controled by the LaserProfile.
+
+ The plasma reference has to be specified to attach the any models.
+
+ :param Node parent: The parent node in the Raysect scene-graph.
+ See the Raysect documentation for more guidance.
+ :param AffineMatrix3D transform: The transform defining the spatial position
+ and orientation of this laser. See the Raysect documentation if you need
+ guidance on how to use AffineMatrix3D transforms.
+ :param str name: The name for this laser object.
+ :ivar Plasma plasma: The plasma instance with which this laser interacts.
+ :ivar float importance: The importance sampling factor.
+ :ivar LaserSpectrum laser_spectrum: The LaserSpectrum instance with which this laser interacts.
+ :ivar LaserProfile laser_profile: The LaserProfile instance with which this laser interacts.
+ :ivar ModelManager models: The manager class that sets and provides access to the
+ emission models for this laser.
+ :ivar VolumeIntegrator integrator: The configurable method for doing
+ volumetric integration through the laser along a Ray's path. Defaults to
+ a numerical integrator with 1mm step size, NumericalIntegrator(step=0.001).
+ """
+
+ def __init__(self, object parent=None, AffineMatrix3D transform=None, str name=None):
+
+ super().__init__(parent, transform, name)
+
+ self._set_init_values()
+
+ self.notifier = Notifier()
+
+ self._models = ModelManager()
+
+ self._integrator = NumericalIntegrator(step=1e-3)
+
+ self._importance = 1.
+
+ def _set_init_values(self):
+ """
+ Sets initial values of the laser shape to avoid errors.
+ """
+ self._importance = 0.
+ self._geometry = []
+
+ @property
+ def plasma(self):
+ return self._plasma
+
+ @plasma.setter
+ def plasma(self, Plasma value not None):
+
+ #unregister from old plasma notifier
+ if self._plasma is not None:
+ self._plasma.notifier.remove(self._plasma_changed)
+
+ self._plasma = value
+ self._plasma.notifier.add(self._plasma_changed)
+
+ self._configure_materials()
+
+ @property
+ def importance(self):
+ return self._importance
+
+ @importance.setter
+ def importance(self, double value):
+
+ self._importance = value
+ self._configure_materials()
+
+ @property
+ def laser_spectrum(self):
+ return self._laser_spectrum
+
+ @laser_spectrum.setter
+ def laser_spectrum(self, LaserSpectrum value):
+ self._laser_spectrum = value
+ self._configure_materials()
+
+ @property
+ def laser_profile(self):
+ return self._laser_profile
+
+ @laser_profile.setter
+ def laser_profile(self, LaserProfile value):
+
+ if self._laser_profile is not None:
+ self._laser_profile.notifier.remove(self.configure_geometry)
+
+ self._laser_profile = value
+ self._laser_profile.notifier.add(self.configure_geometry)
+
+ self.configure_geometry()
+
+ @property
+ def models(self):
+ return list(self._models)
+
+ @models.setter
+ def models(self, value):
+
+ # check necessary data is available
+ if not all([self._plasma, self._laser_profile, self._laser_spectrum]):
+ raise ValueError("The plasma, laser_profile and laser_spectrum must be set before before specifying any models.")
+
+ self._models.set(value)
+ self._configure_materials()
+
+ @property
+ def integrator(self):
+ return self._integrator
+
+ @integrator.setter
+ def integrator(self, VolumeIntegrator value):
+ self._integrator = value
+
+ for i in self._geometry:
+ i.material.integrator = value
+
+ def configure_geometry(self):
+ """
+ Reconfigure the laser primitives and materials.
+ """
+
+ self._build_geometry()
+ self._configure_materials()
+
+ def _build_geometry(self):
+ """
+ Delete and build new laser segments
+ """
+ # remove old laser segments in any case
+ for i in self._geometry:
+ i.parent = None
+ self._geometry = []
+
+ # no point in adding segments if there is no model and profile
+ if self._laser_profile is None:
+ return
+
+ # rebuild geometry
+ self._geometry = self._laser_profile.generate_geometry()
+
+ for i in self._geometry:
+ i.parent = self
+
+ def _configure_materials(self):
+ """
+ Configure laser segment materials
+ """
+ if not list(self._models) or self._plasma is None or self._laser_spectrum is None:
+ return
+
+ for i in self._geometry:
+ i.material = LaserMaterial(self, i, list(self._models), self._integrator)
+
+ def get_geometry(self):
+ return self._geometry
+
+ def _plasma_changed(self):
+ """React to change of plasma and propagate the information."""
+ self._configure_materials()
+
+ def _modified(self):
+ self._configure_materials()
diff --git a/cherab/core/laser/profile.pxd b/cherab/core/laser/profile.pxd
new file mode 100644
index 00000000..c634a2f8
--- /dev/null
+++ b/cherab/core/laser/profile.pxd
@@ -0,0 +1,41 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.core.math.function.float cimport Function3D
+from raysect.core.math.function.vector3d cimport Function3D as VectorFunction3D
+
+from raysect.optical cimport Spectrum, Point3D, Vector3D
+
+from cherab.core.laser.node cimport Laser
+
+
+cdef class LaserProfile:
+
+ cdef:
+ VectorFunction3D _polarization3d, _pointing3d
+ Function3D _energy_density3d
+ readonly object notifier
+
+ cpdef Vector3D get_pointing(self, double x, double y, double z)
+
+ cpdef Vector3D get_polarization(self, double x, double y, double z)
+
+ cpdef double get_energy_density(self, double x, double y, double z)
+
+ cpdef list generate_geometry(self)
\ No newline at end of file
diff --git a/cherab/core/laser/profile.pyx b/cherab/core/laser/profile.pyx
new file mode 100644
index 00000000..6356d1cb
--- /dev/null
+++ b/cherab/core/laser/profile.pyx
@@ -0,0 +1,163 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.core.math.function.float cimport Function3D
+from raysect.core.math.function.vector3d cimport Function3D as VectorFunction3D
+
+from raysect.optical cimport SpectralFunction, Spectrum, InterpolatedSF, Point3D, Vector3D
+
+from cherab.core.laser.node cimport Laser
+from cherab.core.utility import Notifier
+
+
+cdef class LaserProfile:
+ """
+ LaserProfile base class.
+
+ This is an abstract class and cannot be used for observing.
+
+ Provides information about spatial properties of the laser beam:
+ direction of the laser propagation (direction
+ of the Poynting vector), polarisation of the ligth as the direction
+ of the electric component vector and volumetric energy density of
+ the laser light.
+
+ All the laser properties are evaluated in the frame of reference of
+ the laser.
+
+ .. warning::
+ When combining a LaserProfile with a LaserSpectrum for a laser,
+ a special care has to be given to obtain the correct power
+ of the scattered spectrum. Scattering models can multiply
+ both the spectral power density given by the LaserProfile and
+ the volumetric energy density given by the LaserProfile.
+ Combination of incompatible cases may yield incorrect
+ values of scattered power.
+
+ :ivar Laser laser: The Laser scenegraph node the LaserProfile
+ is connected to.
+ """
+
+ def __init__(self):
+
+ self.notifier = Notifier()
+
+ def set_polarization_function(self, VectorFunction3D function):
+ """
+ Assigns the 3D vector function describing the polarisation vector.
+
+ The polarisation is given as the direction of the electric
+ component of the electromagnetic wave.
+
+ The function is specified in the laser space.
+
+ :param VectorFunction3D function: A 3D vector function describing
+ the polarisation vector.
+ """
+ self._polarization3d = function
+
+ def set_pointing_function(self, VectorFunction3D function):
+ """
+ Assings the 3D vector function describing the direction of the laser propagation.
+
+ The direction of the laser light propagation is the direction
+ of the Poynting vector.
+
+ :param VectorFunction3D function: A 3D vector function describing
+ the laser light propagation direction
+ """
+ self._pointing3d = function
+
+ def set_energy_density_function(self, Function3D function):
+ """
+ Assigns the 3D scalar function describing the laser energy distribution.
+
+ The laser power distribution is the value of the volumetric
+ energy density of the laser light.
+ """
+ self._energy_density3d = function
+
+ cpdef Vector3D get_pointing(self, double x, double y, double z):
+ """
+ Returns the laser light propagation direction.
+
+ At the point (x, y, z) in the laser space.
+
+ :param x: x coordinate in meters.
+ :param y: y coordinate in meters.
+ :param z: z coordinate in meters.
+ :return: Intensity in m^-3.
+ """
+
+ return self._pointing3d.evaluate(x, y, z)
+
+ cpdef Vector3D get_polarization(self, double x, double y, double z):
+ """
+ Returns a vector denoting the laser polarisation.
+
+ The polarisation direction is the direction of the electric
+ component of the electromagnetic wave for the point (x, y, z)
+ in the laser space.
+
+ :param x: x coordinate in meters.
+ :param y: y coordinate in meters.
+ :param z: z coordinate in meters.
+ :return: power density in Wm^-3.
+ """
+
+ return self._polarization3d(x, y, z)
+
+ cpdef double get_energy_density(self, double x, double y, double z):
+ """
+ Returns the volumetric energy density of the laser light in W*m^-3.
+
+ At the point (x, y, z) in the laser space.
+
+ :param x: x coordinate in meters in the laser frame.
+ :param y: y coordinate in meters in the laser frame.
+ :param z: z coordinate in meters in the laser frame.
+ :return: power density in W*m^-3.
+ """
+
+ return self._energy_density3d.evaluate(x, y, z)
+
+ cpdef list generate_geometry(self):
+ """
+ returns list of raysect primitives composing the laser geometry
+
+ This method is called from the Laser instance to which the instance
+ of Profile is attached to. The Laser instance will be assigned as
+ the parent to the returned primitives in the Laser._configure method.
+ The Laser._configure method does not change any transforms. This is
+ why the returned primitives have to have their transforms already
+ initialised in the frame of the laser, when returned.
+ """
+
+ raise NotImplementedError("Virtual function density not defined.")
+
+ def _change(self):
+ """
+ Called if the laser properties change.
+
+ If the model caches calculation data that would be invalidated if its
+ source data changes then this method may be overridden to clear the
+ cache.
+ """
+
+ pass
diff --git a/cherab/core/laser/tests/__init__.py b/cherab/core/laser/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/cherab/core/laser/tests/test_laser.py b/cherab/core/laser/tests/test_laser.py
new file mode 100644
index 00000000..f9f85732
--- /dev/null
+++ b/cherab/core/laser/tests/test_laser.py
@@ -0,0 +1,110 @@
+import unittest
+
+from raysect.optical import World
+from raysect.optical.material.emitter.inhomogeneous import NumericalIntegrator
+
+from cherab.core import Plasma
+from cherab.core.laser.node import Laser
+from cherab.core.model.laser.laserspectrum import ConstantSpectrum
+from cherab.core.model.laser.model import SeldenMatobaThomsonSpectrum
+from cherab.core.model.laser.profile import UniformEnergyDensity
+
+
+class TestLaser(unittest.TestCase):
+
+ def test_laser_init(self):
+ """
+ Test correct initialisation of a laser instance.
+ """
+
+ world = World()
+ laser = Laser(parent=world)
+
+ with self.assertRaises(ValueError, msg="Model was attached before Plasma, Profile and LaserSpectrum were specified."):
+ laser.models = [SeldenMatobaThomsonSpectrum()]
+
+ laser.laser_profile = UniformEnergyDensity()
+ with self.assertRaises(ValueError, msg="Model was attached before Plasma, Profile and LaserSpectrum were specified."):
+ laser.models = [SeldenMatobaThomsonSpectrum()]
+
+ laser.laser_spectrum = ConstantSpectrum(min_wavelength=1059, max_wavelength=1061, bins=10)
+ with self.assertRaises(ValueError, msg="Model was attached before Plasma, Profile and LaserSpectrum were specified."):
+ laser.models = [SeldenMatobaThomsonSpectrum()]
+
+ laser.plasma = Plasma(parent=world)
+ laser.models = [SeldenMatobaThomsonSpectrum()]
+
+ def test_reference_change(self):
+
+ world = World()
+
+ laser_profile = UniformEnergyDensity(laser_length=1, laser_radius=0.1)
+ laser_spectrum = ConstantSpectrum(min_wavelength=1059, max_wavelength=1061, bins=10)
+ plasma = Plasma(parent=world)
+ models = [SeldenMatobaThomsonSpectrum()]
+
+ laser_profile2 = UniformEnergyDensity()
+ laser_spectrum2 = ConstantSpectrum(min_wavelength=1059, max_wavelength=1061, bins=10)
+ plasma2 = Plasma(parent=world)
+ models2 = [SeldenMatobaThomsonSpectrum()]
+
+ laser = Laser(parent=world)
+
+ laser.laser_spectrum = laser_spectrum
+ laser.plasma = plasma
+ laser.laser_profile = laser_profile
+ laser.models = models
+
+ for mod in list(laser.models):
+ self.assertIs(mod.laser_profile, laser_profile, msg="laser_profile reference in emission model"
+ "is not set correctly.")
+ self.assertIs(mod.plasma, plasma, msg="plasma reference in emission model"
+ "is not set correctly.")
+ self.assertIs(mod.laser_spectrum, laser_spectrum, msg="laser_spectrum reference in emission model"
+ "is not set correctly.")
+
+ laser.laser_spectrum = laser_spectrum2
+ laser.plasma = plasma2
+ laser.laser_profile = laser_profile2
+
+ for mod in list(laser.models):
+ self.assertIs(mod.laser_profile, laser_profile2, msg="laser_profile reference in emission model"
+ "is not set correctly.")
+ self.assertIs(mod.plasma, plasma2, msg="plasma reference in emission model"
+ "is not set correctly.")
+ self.assertIs(mod.laser_spectrum, laser_spectrum2, msg="laser_spectrum reference in emission model"
+ "is not set correctly.")
+
+ laser.models = models + models2
+
+ for mod in list(laser.models):
+ self.assertIs(mod.laser_profile, laser_profile2, msg="laser_profile reference in emission model"
+ "is not set correctly.")
+ self.assertIs(mod.plasma, plasma2, msg="plasma reference in emission model"
+ "is not set correctly.")
+ self.assertIs(mod.laser_spectrum, laser_spectrum2, msg="laser_spectrum reference in emission model"
+ "is not set correctly.")
+
+ def test_integrator_change(self):
+
+ world = World()
+
+ laser_profile = UniformEnergyDensity(laser_length=1, laser_radius=0.1)
+ laser_spectrum = ConstantSpectrum(min_wavelength=1059, max_wavelength=1061, bins=10)
+ plasma = Plasma(parent=world)
+ models = [SeldenMatobaThomsonSpectrum()]
+
+ laser = Laser(parent=world)
+
+ laser.laser_spectrum = laser_spectrum
+ laser.plasma = plasma
+ laser.laser_profile = laser_profile
+ laser.models = models
+
+ integrator = NumericalIntegrator(1e-4)
+
+ laser.integrator = integrator
+
+ for i in laser.get_geometry():
+ self.assertIs(i.material.integrator, integrator, msg="Integrator not updated properly")
+
diff --git a/cherab/core/laser/tests/test_laserspectrum.py b/cherab/core/laser/tests/test_laserspectrum.py
new file mode 100644
index 00000000..9473e43d
--- /dev/null
+++ b/cherab/core/laser/tests/test_laserspectrum.py
@@ -0,0 +1,62 @@
+import unittest
+import numpy as np
+
+from cherab.core.laser.laserspectrum import LaserSpectrum
+from raysect.optical.spectrum import Spectrum
+
+class TestLaserSpectrum(unittest.TestCase):
+
+ def test_laserspectrum_init(self):
+ # test min_wavelength boundaries
+ with self.assertRaises(ValueError,
+ msg="LaserSpectrum did not raise a ValueError with min_wavelength being zero."):
+ LaserSpectrum(0., 100, 200)
+ LaserSpectrum(-1, 100, 200)
+
+ # test max_wavelength boundaries
+ with self.assertRaises(ValueError,
+ msg="LaserSpectrum did not raise a ValueError with max_wavelength being zero."):
+ LaserSpectrum(10, 0, 200)
+ LaserSpectrum(10, -1, 200)
+
+ # test min_wavelength >= max_wavelength
+ with self.assertRaises(ValueError,
+ msg="LaserSpectrum did not raise a ValueError with max_wavelength < min_wavelength."):
+ LaserSpectrum(40, 30, 200)
+ LaserSpectrum(30, 30, 200)
+
+ # test bins > 0
+ with self.assertRaises(ValueError,
+ msg="LaserSpectrum did not raise a ValueError with max_wavelength < min_wavelength."):
+ LaserSpectrum(30, 30, 0)
+ LaserSpectrum(30, 30, -1)
+
+ def test_laserspectrum_changes(self):
+ laser_spectrum = LaserSpectrum(100, 200, 100)
+
+ # change min_wavelength to be larger or equal to max_wavelength
+ with self.assertRaises(ValueError,
+ msg="LaserSpectrum did not raise ValueError for min_wavelength change "
+ "with min_wavelength >= max_wavelength."):
+ laser_spectrum.min_wavelength = 300
+ laser_spectrum.min_wavelength = 200
+
+ # change max_wavelength to be smaller than max_wavelength
+ with self.assertRaises(ValueError,
+ msg="LaserSpectrum did not raise ValueError for max_wavelength change "
+ "with min_wavelength > max_wavelength."):
+ laser_spectrum.max_wavelength = 50
+ laser_spectrum.max_wavelength = 100
+
+ with self.assertRaises(ValueError,
+ msg="LaserSpectrum did not raise a ValueError with max_wavelength < min_wavelength."):
+ laser_spectrum.bins = -1
+ laser_spectrum.bins = 0
+
+ # laser spectrum should have same behaviour as Spectrum from raysect.optical
+ spectrum = Spectrum(laser_spectrum.min_wavelength, laser_spectrum.max_wavelength, laser_spectrum.bins)
+
+ # test caching of spectrum data, behaviour should be consistent with raysect.optical.spectrum.Spectrum
+ self.assertTrue(np.array_equal(laser_spectrum.wavelengths, spectrum.wavelengths),
+ "LaserSpectrum.wavelengths values are not equal to Spectrum.wavelengths "
+ "with same boundaries and number of bins")
\ No newline at end of file
diff --git a/cherab/core/math/integrators/__init__.pxd b/cherab/core/math/integrators/__init__.pxd
new file mode 100644
index 00000000..db06ef43
--- /dev/null
+++ b/cherab/core/math/integrators/__init__.pxd
@@ -0,0 +1,20 @@
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+from cherab.core.math.integrators.integrators1d cimport Integrator1D, GaussianQuadrature
+
diff --git a/cherab/core/math/integrators/__init__.py b/cherab/core/math/integrators/__init__.py
new file mode 100644
index 00000000..86b7d58d
--- /dev/null
+++ b/cherab/core/math/integrators/__init__.py
@@ -0,0 +1,19 @@
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+from .integrators1d import Integrator1D, GaussianQuadrature
diff --git a/cherab/core/math/integrators/integrators1d.pxd b/cherab/core/math/integrators/integrators1d.pxd
new file mode 100644
index 00000000..c451285f
--- /dev/null
+++ b/cherab/core/math/integrators/integrators1d.pxd
@@ -0,0 +1,39 @@
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+from numpy cimport ndarray
+from raysect.core.math.function.float cimport Function1D, Function2D
+
+
+cdef class Integrator1D:
+
+ cdef:
+ Function1D function
+
+ cdef double evaluate(self, double a, double b) except? -1e999
+
+
+cdef class GaussianQuadrature(Integrator1D):
+
+ cdef:
+ int _min_order, _max_order
+ double _rtol
+ ndarray _roots, _weights
+ double[:] _roots_mv, _weights_mv
+
+ cdef _build_cache(self)
diff --git a/cherab/core/math/integrators/integrators1d.pyx b/cherab/core/math/integrators/integrators1d.pyx
new file mode 100644
index 00000000..54ec4059
--- /dev/null
+++ b/cherab/core/math/integrators/integrators1d.pyx
@@ -0,0 +1,223 @@
+# cython: language_level=3
+
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+import numpy as np
+from scipy.special import roots_legendre
+
+from raysect.core.math.function.float cimport autowrap_function1d, Constant1D
+
+from libc.math cimport INFINITY
+cimport cython
+
+
+cdef class Integrator1D:
+ """
+ Compute a definite integral of a one-dimensional function.
+
+ :ivar Function1D integrand: A 1D function to integrate.
+ """
+
+ @property
+ def integrand(self):
+ """
+ A 1D function to integrate.
+
+ :rtype: int
+ """
+ return self.function
+
+ @integrand.setter
+ def integrand(self, object func not None):
+
+ self.function = autowrap_function1d(func)
+
+ cdef double evaluate(self, double a, double b) except? -1e999:
+
+ raise NotImplementedError("The evaluate() method has not been implemented.")
+
+ def __call__(self, double a, double b):
+ """
+ Integrates a one-dimensional function over a finite interval.
+
+ :param double a: Lower limit of integration.
+ :param double b: Upper limit of integration.
+
+ :returns: Definite integral of a one-dimensional function.
+ """
+
+ return self.evaluate(a, b)
+
+
+cdef class GaussianQuadrature(Integrator1D):
+ """
+ Compute an integral of a one-dimensional function over a finite interval
+ using fixed-tolerance Gaussian quadrature.
+ (see Scipy `quadrature `).
+
+ :param object integrand: A 1D function to integrate. Default is Constant1D(0).
+ :param double relative_tolerance: Iteration stops when relative error between
+ last two iterates is less than this value. Default is 1.e-5.
+ :param int max_order: Maximum order on Gaussian quadrature. Default is 50.
+ :param int min_order: Minimum order on Gaussian quadrature. Default is 1.
+
+ :ivar Function1D integrand: A 1D function to integrate.
+ :ivar double relative_tolerance: Iteration stops when relative error between
+ last two iterates is less than this value.
+ :ivar int max_order: Maximum order on Gaussian quadrature.
+ :ivar int min_order: Minimum order on Gaussian quadrature.
+ """
+
+ def __init__(self, object integrand=Constant1D(0), double relative_tolerance=1.e-5, int max_order=50, int min_order=1):
+
+ if min_order < 1 or max_order < 1:
+ raise ValueError("Order of Gaussian quadrature must be >= 1.")
+
+ if min_order > max_order:
+ raise ValueError("Minimum order of Gaussian quadrature must be less than or equal to the maximum order.")
+
+ self._min_order = min_order
+ self._max_order = max_order
+ self._build_cache()
+
+ self.integrand = integrand
+
+ self.relative_tolerance = relative_tolerance
+
+ @property
+ def min_order(self):
+ """
+ Minimum order on Gaussian quadrature.
+
+ :rtype: int
+ """
+ return self._min_order
+
+ @min_order.setter
+ def min_order(self, int value):
+
+ if value < 1:
+ raise ValueError("Order of Gaussian quadrature must be >= 1.")
+
+ if value > self._max_order:
+ raise ValueError("Minimum order of Gaussian quadrature must be less than or equal to the maximum order.")
+
+ self._min_order = value
+
+ self._build_cache()
+
+ @property
+ def max_order(self):
+ """
+ Maximum order on Gaussian quadrature.
+
+ :rtype: float
+ """
+ return self._max_order
+
+ @max_order.setter
+ def max_order(self, int value):
+
+ if value < 1:
+ raise ValueError("Order of Gaussian quadrature must be >= 1.")
+
+ if value < self._min_order:
+ raise ValueError("Maximum order of Gaussian quadrature must be greater than or equal to the minimum order.")
+
+ self._max_order = value
+
+ self._build_cache()
+
+ @property
+ def relative_tolerance(self):
+ """
+ Iteration stops when relative error between last two iterates is less than this value.
+
+ :rtype: double
+ """
+ return self._rtol
+
+ @relative_tolerance.setter
+ def relative_tolerance(self, double value):
+
+ if value <= 0:
+ raise ValueError("Relative tolerance must be positive.")
+
+ self._rtol = value
+
+ cdef _build_cache(self):
+ """
+ Caches the roots and weights of the Gauss-Legendre quadrature.
+ """
+
+ cdef:
+ int order, n, i
+
+ n = (self._max_order + self._min_order) * (self._max_order - self._min_order + 1) // 2
+
+ self._roots = np.zeros(n, dtype=np.float64)
+ self._weights = np.zeros(n, dtype=np.float64)
+
+ i = 0
+ for order in range(self._min_order, self._max_order + 1):
+ self._roots[i:i + order], self._weights[i:i + order] = roots_legendre(order)
+ i += order
+
+ self._roots_mv = self._roots
+ self._weights_mv = self._weights
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ @cython.initializedcheck(False)
+ cdef double evaluate(self, double a, double b) except? -1e999:
+ """
+ Integrates a one-dimensional function over a finite interval.
+
+ :param double a: Lower limit of integration.
+ :param double b: Upper limit of integration.
+
+ :returns: Gaussian quadrature approximation to integral.
+ """
+
+ cdef:
+ int order, i, ibegin
+ double newval, oldval, error, x, c, d
+
+ oldval = INFINITY
+ ibegin = 0
+ c = 0.5 * (a + b)
+ d = 0.5 * (b - a)
+
+ for order in range(self._min_order, self._max_order + 1):
+ newval = 0
+ for i in range(ibegin, ibegin + order):
+ x = c + d * self._roots_mv[i]
+ newval += self._weights_mv[i] * self.function.evaluate(x)
+ newval *= d
+
+ error = abs(newval - oldval)
+ oldval = newval
+
+ ibegin += order
+
+ if error < self._rtol * abs(newval):
+ break
+
+ return newval
diff --git a/cherab/core/math/tests/test_integrators.py b/cherab/core/math/tests/test_integrators.py
new file mode 100644
index 00000000..fa967165
--- /dev/null
+++ b/cherab/core/math/tests/test_integrators.py
@@ -0,0 +1,80 @@
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+from raysect.core.math.function.float import Exp1D, Arg1D
+from cherab.core.math.integrators import GaussianQuadrature
+from math import sqrt, pi
+from scipy.special import erf
+import unittest
+
+
+class TestGaussianQuadrature(unittest.TestCase):
+ """Gaussian quadrature integrator tests."""
+
+ def test_properties(self):
+ """Test property assignment."""
+ min_order = 3
+ max_order = 30
+ reltol = 1.e-6
+ quadrature = GaussianQuadrature(integrand=Arg1D, relative_tolerance=reltol, max_order=max_order, min_order=min_order)
+
+ self.assertEqual(quadrature.relative_tolerance, reltol)
+ self.assertEqual(quadrature.max_order, max_order)
+ self.assertEqual(quadrature.min_order, min_order)
+ self.assertEqual(quadrature.integrand, Arg1D)
+
+ min_order = 0
+ max_order = 2 # < min_order
+ reltol = -1
+
+ with self.assertRaises(ValueError):
+ quadrature.max_order = max_order
+
+ with self.assertRaises(ValueError):
+ quadrature.min_order = min_order
+
+ with self.assertRaises(ValueError):
+ quadrature.relative_tolerance = reltol
+
+ min_order = 1
+ max_order = 20
+ reltol = 1.e-5
+
+ quadrature.relative_tolerance = reltol
+ quadrature.min_order = min_order
+ quadrature.max_order = max_order
+ quadrature.integrand = Exp1D
+
+ self.assertEqual(quadrature.relative_tolerance, reltol)
+ self.assertEqual(quadrature.min_order, min_order)
+ self.assertEqual(quadrature.max_order, max_order)
+ self.assertEqual(quadrature.integrand, Exp1D)
+
+ def test_integrate(self):
+ """Test integration."""
+ quadrature = GaussianQuadrature(relative_tolerance=1.e-8)
+ a = -0.5
+ b = 3.
+ quadrature.integrand = (2 / sqrt(pi)) * Exp1D(- Arg1D() * Arg1D())
+ exact_integral = erf(b) - erf(a)
+
+ self.assertAlmostEqual(quadrature(a, b), exact_integral, places=8)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/cherab/core/model/laser/__init__.pxd b/cherab/core/model/laser/__init__.pxd
new file mode 100644
index 00000000..3b0e3818
--- /dev/null
+++ b/cherab/core/model/laser/__init__.pxd
@@ -0,0 +1,4 @@
+from cherab.core.model.laser.laserspectrum import ConstantSpectrum, GaussianSpectrum
+from cherab.core.model.laser.profile import UniformEnergyDensity, ConstantAxisymmetricGaussian
+from cherab.core.model.laser.profile import ConstantBivariateGaussian, TrivariateGaussian, GaussianBeamAxisymmetric
+from cherab.core.model.laser.model import SeldenMatobaThomsonSpectrum
\ No newline at end of file
diff --git a/cherab/core/model/laser/__init__.py b/cherab/core/model/laser/__init__.py
new file mode 100644
index 00000000..930b55a7
--- /dev/null
+++ b/cherab/core/model/laser/__init__.py
@@ -0,0 +1,4 @@
+from .laserspectrum import ConstantSpectrum, GaussianSpectrum
+from .profile import UniformEnergyDensity, ConstantAxisymmetricGaussian
+from .profile import ConstantBivariateGaussian, TrivariateGaussian, GaussianBeamAxisymmetric
+from .model import SeldenMatobaThomsonSpectrum
diff --git a/cherab/core/model/laser/laserspectrum.pxd b/cherab/core/model/laser/laserspectrum.pxd
new file mode 100644
index 00000000..e21d36fb
--- /dev/null
+++ b/cherab/core/model/laser/laserspectrum.pxd
@@ -0,0 +1,34 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from cherab.core.laser cimport LaserSpectrum
+
+
+cdef class ConstantSpectrum(LaserSpectrum):
+
+ cdef double evaluate(self, double x) except? -1e999
+
+
+cdef class GaussianSpectrum(LaserSpectrum):
+
+ cdef:
+ double _stddev, _recip_stddev, _normalisation, _mean
+ double _norm_cdf
+
+ cdef double evaluate(self, double x) except? -1e999
diff --git a/cherab/core/model/laser/laserspectrum.pyx b/cherab/core/model/laser/laserspectrum.pyx
new file mode 100644
index 00000000..58c1cada
--- /dev/null
+++ b/cherab/core/model/laser/laserspectrum.pyx
@@ -0,0 +1,133 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from cherab.core.laser cimport LaserSpectrum
+from libc.math cimport sqrt, exp, M_PI, erf, M_SQRT2
+
+
+cdef class ConstantSpectrum(LaserSpectrum):
+ """
+ A laser spectrum with constant power.
+
+ Has a constant, non-zero distribution of power spectral density
+ between the min_wavelength and max_wavelength. The integral value
+ of the power is 1 W.
+
+ .. note::
+ The ConstantSpectrum class is suitable for approximation
+ of an infinitely thin laser spectrum, e.g.:
+ ConstantSpectrum(1063.9, 1064.1, 1)
+ """
+
+ def __init__(self, double min_wavelength, double max_wavelength, int bins):
+
+ super().__init__(min_wavelength, max_wavelength, bins)
+
+ cdef double evaluate(self, double x) except? -1e999:
+ """
+ Returns the spectral power density for the given wavelength.
+
+ :param float x: Wavelength in nm.
+
+ :return: Power spectral density in W/nm.
+ """
+
+ cdef:
+ double spectrum_width
+ int index
+
+ if self._min_wavelength <= x <= self._max_wavelength:
+ return 1.0 / (self._max_wavelength - self._min_wavelength)
+ else:
+ return 0
+
+
+cdef class GaussianSpectrum(LaserSpectrum):
+ """
+ A laser spectrum with a normally distributed power spectral density.
+
+ Has a Gaussian-like spectral shape. The inegral value of power is 1 W.
+
+ :param float mean: The mean value of the Gaussian distribution
+ of the laser spectrum in nm, can be thought of as the central
+ wavelength of the laser.
+ :param float stddev: Standard deviation of the Gaussian
+ distribution of the laser spectrum.
+
+ :ivar float stddev: Standard deviation of the Gaussian
+ distribution of the laser spectrum.
+ :ivar float mean: The mean value of the Gaussian distribution
+ of the laser spectrum in nm, can be thought of as the central
+ wavelength of the laser.
+ """
+
+ def __init__(self, double min_wavelength, double max_wavelength, int bins, double mean, double stddev):
+
+ self.stddev = stddev
+ self.mean = mean
+ super().__init__(min_wavelength, max_wavelength, bins)
+
+ @property
+ def stddev(self):
+ return self._stddev
+
+ @stddev.setter
+ def stddev(self, value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0")
+
+ self._stddev = value
+ self._recip_stddev = 1 / value
+ self._normalisation = 1 / (value * sqrt(2 * M_PI))
+ self._norm_cdf = 1 / (value * M_SQRT2)
+
+ @property
+ def mean(self):
+ return self._mean
+
+ @mean.setter
+ def mean(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0")
+
+ self._mean = value
+
+ cdef double evaluate(self, double x) except? -1e999:
+ """
+ Returns the spectral power density for the given wavelength.
+
+ :param float x: Wavelength in nm.
+
+ :return: Power spectral density in W/nm.
+ """
+ return self._normalisation * exp(-0.5 * ((x - self._mean) * self._recip_stddev) ** 2)
+
+ cpdef double _get_bin_power_spectral_density(self, double wavelength_lower, double wavelength_upper):
+ """
+ Returns the power spectral density in a bin.
+
+ Overrides the parent method to deliver better precision.
+ """
+
+ cdef:
+ double val_lower, val_upper
+
+ val_lower = erf((wavelength_lower - self._mean) * self._norm_cdf)
+ val_upper = erf((wavelength_upper - self._mean) * self._norm_cdf)
+ return 0.5 * (val_upper - val_lower) / self._delta_wavelength
\ No newline at end of file
diff --git a/cherab/core/model/laser/math_functions.pxd b/cherab/core/model/laser/math_functions.pxd
new file mode 100644
index 00000000..08827094
--- /dev/null
+++ b/cherab/core/model/laser/math_functions.pxd
@@ -0,0 +1,48 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.core.math.function.float cimport Function3D
+
+cdef class ConstantAxisymmetricGaussian3D(Function3D):
+
+ cdef:
+ double _stddev, _normalisation, _kr
+
+ cdef double evaluate(self, double x, double y, double z) except? -1e999
+
+
+cdef class ConstantBivariateGaussian3D(Function3D):
+
+ cdef:
+ double _stddev_x, _stddev_y, _kx, _ky, _normalisation
+
+
+cdef class TrivariateGaussian3D(Function3D):
+
+ cdef:
+ double _mean_z, _stddev_x, _stddev_y, _stddev_z, _kx, _ky
+ double _kz, _normalisation
+
+
+cdef class GaussianBeamModel(Function3D):
+
+ cdef:
+ double _waist_z, _stddev_waist, _stddev_waist2, _wavelength, _rayleigh_range
+
+ cdef double evaluate(self, double x, double y, double z) except? -1e999
diff --git a/cherab/core/model/laser/math_functions.pyx b/cherab/core/model/laser/math_functions.pyx
new file mode 100644
index 00000000..1ed73a61
--- /dev/null
+++ b/cherab/core/model/laser/math_functions.pyx
@@ -0,0 +1,304 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+cimport cython
+
+from raysect.core.math.function.float cimport Function3D
+from raysect.core.math.cython.utility cimport find_index
+
+from libc.math cimport sqrt, exp, pi
+
+
+cdef class ConstantAxisymmetricGaussian3D(Function3D):
+ """
+ A function with a 2D Gaussian in the x-y plane and equal standard deviations in x and y directions.
+
+ .. math::
+ F(x, y, z) = \\frac{1}{2 * \\pi \\sigma^2} exp\\left(-\\frac{x^2 + y^2}{2 * \\sigma^2}\\right)
+
+ The function value has a Gaussian shape in the x-y plane with the standard deviations in
+ x and y direction being equal. The integral over an x-y plane is equal to 1
+ and the mean values in x and y directions are equal to 0.
+
+ :param float stddev: The standard deviation in both the x and y directions.
+ """
+
+ def __init__(self, stddev):
+
+ super().__init__()
+
+ self.stddev = stddev
+
+ @property
+ def stddev(self):
+
+ return self._stddev
+
+ @stddev.setter
+ def stddev(self, value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._stddev = value
+ self._kr = -1 / (2 * value ** 2)
+ self._normalisation = 1 / (2 * pi * value ** 2)
+
+ cdef double evaluate(self, double x, double y, double z) except? -1e999:
+ cdef:
+ double r2
+ r2 = x ** 2 + y ** 2
+ return self._normalisation * exp(r2 * self._kr)
+
+
+cdef class ConstantBivariateGaussian3D(Function3D):
+ """
+ A function with a 2D Gaussian in the x-y plane.
+
+ .. math::
+ F(x, y, z) = \\frac{1}{2 * \\pi \\sigma_x \\sigma_y} exp\\left(-\\frac{x^2 + y^2}{2 * \\sigma_x \\sigma_y}\\right)
+
+ The function value has a Gaussian shape in the x-y plane. The integral over an x-y plane is equal to 1
+ and the mean values in x and y directions are equal to 0.
+ The correlation between the standard deviations in x and y directions is equal to 0.
+
+ :param float stddev_x: The standard deviation in the x directions.
+ :param float stddev_y: The standard deviation in the y directions.
+ """
+
+ def __init__(self, stddev_x, stddev_y):
+
+ super().__init__()
+ self._init_params()
+
+ self.stddev_x = stddev_x
+ self.stddev_y = stddev_y
+
+ def _init_params(self):
+ self._stddev_x = 1
+ self._stddev_y = 1
+
+ @property
+ def stddev_x(self):
+ return self._stddev_x
+
+ @stddev_x.setter
+ def stddev_x(self, value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._stddev_x = value
+
+ self._cache_constants()
+
+ @property
+ def stddev_y(self):
+ return self._stddev_y
+
+ @stddev_y.setter
+ def stddev_y(self, value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._stddev_y = value
+
+ self._cache_constants()
+
+ def _cache_constants(self):
+ self._kx = -1 / (2 * self._stddev_x ** 2)
+ self._ky = -1 / (2 * self._stddev_y ** 2)
+ self._normalisation = 1 / (2 * pi * self._stddev_x * self._stddev_y)
+
+ cdef double evaluate(self, double x, double y, double z) except? -1e999:
+ return self._normalisation * exp(x ** 2 * self._kx +
+ y ** 2 * self._ky)
+
+
+cdef class TrivariateGaussian3D(Function3D):
+ """
+ A function with a 3D Gaussian shape.
+
+ .. math::
+ F(x, y, z) = \\frac{1}{\\sqrt{2 \\pi^3} \\sigma_x \\sigma_y \\sigma_z} exp\\left(-\\frac{x^2}{2 \\sigma_x^2} -\\frac{y^2}{2 \\sigma_y^2} - \\frac{(z - \\mu_z)^2}{2 \\sigma_z^2}\\right)
+
+ The integral over the whole 3D space is equal to 1.The correlation between the standard deviations in x and y directions is equal to 0. The mean value in the
+ x and y directions are equal to 0.
+
+ :param float mean_z: Mean value in the z direction.
+ :param float stddev_x: The standard deviation in the x directions.
+ :param float stddev_y: The standard deviation in the y directions.
+ :param float stddev_z: The standard deviation in the z directions.
+ """
+
+ def __init__(self, mean_z, stddev_x, stddev_y, stddev_z):
+
+ super().__init__()
+ self._init_params()
+
+ self.stddev_x = stddev_x
+ self.stddev_y = stddev_y
+ self.stddev_z = stddev_z
+ self.mean_z = mean_z
+
+ def _init_params(self):
+ self._mean_z = 1
+ self._stddev_x = 1
+ self._stddev_y = 1
+ self._stddev_z = 1
+
+ @property
+ def stddev_x(self):
+ return self._stddev_x
+
+ @stddev_x.setter
+ def stddev_x(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._stddev_x = value
+
+ self._cache_constants()
+
+ @property
+ def stddev_y(self):
+ return self._stddev_y
+
+ @stddev_y.setter
+ def stddev_y(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._stddev_y = value
+
+ self._cache_constants()
+
+ @property
+ def stddev_z(self):
+ return self._stddev_z
+
+ @stddev_z.setter
+ def stddev_z(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._stddev_z = value
+
+ self._cache_constants()
+
+ @property
+ def mean_z(self):
+ return self._mean_z
+
+ @mean_z.setter
+ def mean_z(self, double value):
+ self._mean_z = value
+
+ def _cache_constants(self):
+ self._kx = -1 / (2 * self._stddev_x ** 2)
+ self._ky = -1 / (2 * self._stddev_y ** 2)
+ self._kz = -1 / (2 * self._stddev_z ** 2)
+ self._normalisation = 1 / (sqrt((2 * pi) ** 3) * self._stddev_x * self._stddev_y * self._stddev_z)
+
+ cdef double evaluate(self, double x, double y, double z) except? -1e999:
+ return self._normalisation * exp(x ** 2 * self._kx +
+ y ** 2 * self._ky +
+ (z - self._mean_z) ** 2 * self._kz)
+
+
+cdef class GaussianBeamModel(Function3D):
+ """
+ A Gaussian beam function (https://en.wikipedia.org/wiki/Gaussian_beam)
+
+ .. math::
+ F(x, y, z) = \\frac{1}{2 \\pi \\sigma^2_z} exp\\left( -\\frac{x^2 + y^2}{2 \\sigma_z(z)^2 }\\right)
+
+ where the standard deviation in the z direction
+
+ .. math::
+ \\sigma_z(z) = \\sigma_0 \\sqrt{1 + \\left(\\frac{z - z_0}{z_R}\\right)^2}
+
+ is a function of position and the
+
+ .. math::
+ z_R = \\frac{\\pi \\omega_0^2 n}{\\lambda_l}
+
+ is the Rayleigh range.
+ """
+
+ def __init__(self, double wavelength, double waist_z, double stddev_waist):
+
+ # preset default values
+ self._wavelength = 1e3
+ self._waist_z = 0
+ self._stddev_waist = 1e-3
+
+ self.wavelength = wavelength
+ self.waist_z = waist_z
+ self.stddev_waist = stddev_waist
+
+ @property
+ def wavelength(self):
+ return self._wavelength
+
+ @wavelength.setter
+ def wavelength(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0, but {0} passed.".format(value))
+
+ self._wavelength = value
+ self._cache_constants()
+
+ @property
+ def waist_z(self):
+ return self._waist_z
+
+ @waist_z.setter
+ def waist_z(self, double value):
+ self._waist_z = value
+
+ @property
+ def stddev_waist(self):
+ return self._stddev_waist
+
+ @stddev_waist.setter
+ def stddev_waist(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0, but {0} passed.".format(value))
+
+ self._stddev_waist = value
+ self._stddev_waist2 = self._stddev_waist ** 2
+ self._cache_constants()
+
+ def _cache_constants(self):
+
+ n = 1 # refractive index of vacuum
+ self._rayleigh_range = 2 * pi * n * self._stddev_waist2 / self._wavelength / 1e-9
+
+ @cython.cdivision(True)
+ cdef double evaluate(self, double x, double y, double z) except? -1e999:
+
+ cdef:
+ double r2, stddev_z2, z_prime
+
+ # shift to correct gaussiam beam model coords, it works with waist at z=0
+ z_prime = z - self._waist_z
+
+ r2 = x ** 2 + y ** 2
+ stddev_z2 = self._stddev_waist2 * (1 + ((z_prime) / self._rayleigh_range) ** 2)
+
+ return 1 / (2 * pi * stddev_z2) * exp(r2 / (-2 * stddev_z2))
diff --git a/cherab/core/model/laser/model.pxd b/cherab/core/model/laser/model.pxd
new file mode 100644
index 00000000..27e0230f
--- /dev/null
+++ b/cherab/core/model/laser/model.pxd
@@ -0,0 +1,40 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.optical cimport Vector3D, Point3D
+from raysect.optical.spectrum cimport Spectrum
+
+from cherab.core.laser cimport Laser, LaserModel, LaserSpectrum, LaserProfile
+
+
+cdef class SeldenMatobaThomsonSpectrum(LaserModel):
+
+ cdef:
+ double _CONST_ALPHA, _RATE_TS, _RECIP_M_PI
+
+ cpdef Spectrum emission(self, Point3D point_plasma, Vector3D observation_plasma, Point3D point_laser,
+ Vector3D observation_laser, Spectrum spectrum)
+
+ cdef double seldenmatoba_spectral_shape(self, double epsilon, double cos_theta, double alpha)
+
+ cdef Spectrum _add_spectral_contribution(self, double ne, double te, double laser_energy, double angle_pointing,
+ double angle_polarization, double laser_wavelength, Spectrum spectrum)
+
+ cpdef Spectrum calculate_spectrum(self, double ne, double te, double laser_energy_density, double laser_wavelength,
+ double observation_angle, double angle_polarization, Spectrum spectrum)
\ No newline at end of file
diff --git a/cherab/core/model/laser/model.pyx b/cherab/core/model/laser/model.pyx
new file mode 100644
index 00000000..dbab8803
--- /dev/null
+++ b/cherab/core/model/laser/model.pyx
@@ -0,0 +1,220 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from libc.math cimport exp, sqrt, cos, M_PI, sin
+cimport cython
+
+from raysect.optical cimport Vector3D, Point3D
+from raysect.optical.spectrum cimport Spectrum
+
+from cherab.core cimport Plasma
+from cherab.core.laser cimport LaserModel, LaserProfile, LaserSpectrum
+from cherab.core.utility.constants cimport DEGREES_TO_RADIANS
+from cherab.core.utility.constants cimport SPEED_OF_LIGHT, ELECTRON_CLASSICAL_RADIUS, ELECTRON_REST_MASS, ELEMENTARY_CHARGE
+
+
+cdef class SeldenMatobaThomsonSpectrum(LaserModel):
+ """
+ Thomson Scattering based on Selden-Matoba.
+
+ The class calculates Thomson scattering of the laser to the spectrum. The model of the scattered spectrum used is based on
+ the semi-empirical model by Selden and the Thomson scattering cross-section is taken from Matoba articles. The spectral contribution
+ of the scattered laser light c is calculated as a sum of contributions of all laser wavelengths
+
+ .. math::
+ c(\lambda) = c r_e^2 n_e cos^2\\theta \\sum_{\\lambda_L} \\frac{E_L(\\lambda_l) S(\\frac{\\lambda}{\\lambda_L} - 1, \\varphi, T_e)}{\\lambda_L},
+
+
+ where :math:`\\lambda` is the spectrum's wavelength, :math:`r_e` is the classical electron radius, :math:`n_e` is the electron delsity,
+ :math:`\\theta` is the angle between the laser polarisation and scattering vectors, :math:`c` is the vacuum speed of light
+ :math:`\\lambda_L` is the laser wavelength, :math:`E_L` is the laser energy density, :math:`\\varphi` is the scattering angle and :math:`T_e` is the electron
+ temperature. The scattering function S is taken from the Matoba article. The multiplication by the speed of light is added to transfer the Thomson scattering
+ cross section into a reaction rate.
+
+ .. seealso::
+ The Prunty article provides a thorough introduction into the phyiscs of Thomson scattering. The articles by Selden and Matoba were used to build
+ this model.
+
+ :Selden: `Selden, A.C., 1980. Simple analytic form of the relativistic Thomson scattering spectrum. Physics Letters A, 79(5-6), pp.405-406.`
+ :Matoba: `Matoba, T., et al., 1979. Analytical approximations in the theory of relativistic Thomson scattering for high temperature fusion plasma.
+ Japanese Journal of Applied Physics, 18(6), p.1127.`
+ :Prunty: `Prunty, S.L., 2014. A primer on the theory of Thomson scattering for high-temperature fusion plasmas. Physica Scripta, 89(12), p.128001.`
+
+ """
+
+ def __init__(self, LaserProfile laser_profile=None, LaserSpectrum laser_spectrum=None, Plasma plasma=None):
+
+ super().__init__(laser_profile, laser_spectrum, plasma)
+
+ # Selden, A.C., 1980. Simple analytic form of the relativistic Thomson scattering spectrum. Physics Letters A, 79(5-6), pp.405-406.
+ self._CONST_ALPHA = ELECTRON_REST_MASS * SPEED_OF_LIGHT ** 2 / (2 * ELEMENTARY_CHARGE) #constant alpha, rewritten for Te in eV
+
+ # from: Prunty, S. L. "A primer on the theory of Thomson scattering for high-temperature fusion plasmas."
+ # TS cross section equiation ~ 3.28 or
+ # Matoba, T., et al., 1979. Analytical approximations in the theory of relativistic Thomson scattering for high temperature fusion plasma.
+ # Japanese Journal of Applied Physics, 18(6), p.1127., TS cross section equiation 18
+ # speed of light for correct normalisation of the scattered intensity calculation (from x-section to rate constant)
+ self._RATE_TS = ELECTRON_CLASSICAL_RADIUS ** 2 * SPEED_OF_LIGHT
+
+ self._RECIP_M_PI = 1 / M_PI
+
+ @cython.cdivision(True)
+ cdef double seldenmatoba_spectral_shape(self, double epsilon, double const_theta, double alpha):
+
+ cdef:
+ double c, a, b
+
+ # const_theta is 2 * (1 - cos(theta))
+
+ c = sqrt(alpha * self._RECIP_M_PI) * (1 - 15. / (16. * alpha) + 345. / (512. * alpha ** 2))
+ a = (1 + epsilon) ** 3 * sqrt(const_theta * (1 + epsilon) + epsilon ** 2)
+ b = sqrt(1 + epsilon ** 2 / (const_theta * (1 + epsilon))) - 1
+
+ return c / a * exp(-2 * alpha * b)
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ cpdef Spectrum emission(self, Point3D point_plasma, Vector3D observation_plasma, Point3D point_laser,
+ Vector3D observation_laser, Spectrum spectrum):
+ cdef:
+ double angle_scattering, angle_pointing, angle_polarization
+ double te, ne, laser_energy_density, laser_energy
+ double plasma_x, plasma_y, plasma_z, laser_x, laser_y, laser_z
+ double[::1] laser_wavelength_mv, laser_spectrum_power_mv
+ int bins
+ Vector3D pointing_vector, polarisation_vector
+ Py_ssize_t index
+
+ plasma_x = point_plasma.x
+ plasma_y = point_plasma.y
+ plasma_z = point_plasma.z
+
+ # get electron parameters for the plasma point
+ te = self._plasma.get_electron_distribution().effective_temperature(plasma_x, plasma_y, plasma_z)
+
+ #terminate early if electron temperature is 0
+ if te <= 0:
+ return spectrum
+
+ ne = self._plasma.get_electron_distribution().density(plasma_x, plasma_y, plasma_z)
+
+ #terminate early if electron density is 0
+ if ne <= 0:
+ return spectrum
+
+ laser_x = point_laser.x
+ laser_y = point_laser.y
+ laser_z = point_laser.z
+
+ #get laser volumetric power
+ laser_energy_density = self._laser_profile.get_energy_density(laser_x, laser_y, laser_z)
+
+ #terminate early if laser power is 0
+ if laser_energy_density == 0:
+ return spectrum
+
+ pointing_vector = self._laser_profile.get_pointing(laser_x, laser_y, laser_z)
+
+ #angle between observation and pointing vector
+ angle_pointing = observation_laser.angle(pointing_vector) # angle between observation and pointing vector of laser
+
+ angle_scattering = (180. - angle_pointing) # scattering direction is the opposite to obervation direction
+
+ # angle between polarisation and observation
+ polarisation_vector = self._laser_profile.get_polarization(laser_x, laser_y, laser_z)
+ angle_polarization = observation_laser.angle(polarisation_vector) # scattering direction is the opposite to obervation direction
+
+ laser_wavelength_mv = self._laser_spectrum.wavelengths_mv
+ laser_spectrum_power_mv = self._laser_spectrum.power_mv # power in spectral bins (PSD * delta wavelength)
+ bins = self._laser_spectrum.get_spectral_bins()
+
+ for index in range(bins):
+ laser_energy = laser_spectrum_power_mv[index] * laser_energy_density
+ if laser_energy > 0:
+ spectrum = self._add_spectral_contribution(ne, te, laser_energy, angle_scattering,
+ angle_polarization, laser_wavelength_mv[index], spectrum)
+
+ return spectrum
+
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ @cython.cdivision(True)
+ cdef Spectrum _add_spectral_contribution(self, double ne, double te, double laser_energy, double angle_scattering,
+ double angle_polarization, double laser_wavelength, Spectrum spectrum):
+
+ cdef:
+ int index, nbins
+ double alpha, epsilon, cos_anglescat, wavelength, min_wavelength, delta_wavelength
+ double const_theta, recip_laser_wavelength, scattered_power, spectrum_norm
+ double sin2_angle_pol
+
+ alpha = self._CONST_ALPHA / te
+ # scattering angle of the photon = pi - observation_angle
+ cos_anglescat = cos(angle_scattering * DEGREES_TO_RADIANS)
+
+ # pre-calculate constants for Selden-Matoba shape
+ const_theta = 2 * (1 - cos_anglescat)
+
+ nbins = spectrum.bins
+ min_wavelength = spectrum.min_wavelength
+ delta_wavelength = spectrum.delta_wavelength
+ recip_laser_wavelength = 1 / laser_wavelength
+
+ # dipole radiation has a cos ** 2 characteristic, here angle shifted by 90 deg
+ sin2_angle_pol = sin(angle_polarization * DEGREES_TO_RADIANS) ** 2
+
+ #from d_lambda to d_epsilon:d_epsilon = d_lambda / laser_wavelength
+ scattered_power = ne * self._RATE_TS * laser_energy * recip_laser_wavelength * sin2_angle_pol
+ for index in range(nbins):
+ wavelength = min_wavelength + (0.5 + index) * delta_wavelength
+ epsilon = (wavelength * recip_laser_wavelength) - 1
+ spectrum_norm = self.seldenmatoba_spectral_shape(epsilon, const_theta, alpha)
+ spectrum.samples_mv[index] += spectrum_norm * scattered_power
+
+ return spectrum
+
+ cpdef Spectrum calculate_spectrum(self, double ne, double te, double laser_energy_density, double laser_wavelength,
+ double observation_angle, double angle_polarization, Spectrum spectrum):
+ """
+ Calculates scattered spectrum for the given parameters.
+
+ The method returns the Thomson scattered spectrum given the plasma parameters, without the need of specifying
+ plasma or laser.
+
+ :param float ne: Plasma electron density in m**-3
+ :param float te: Plasma electron temperature in eV
+ :param float laser_energy_density: Energy density of the laser light in J * m**-3
+ :param float laser_wavelength: The laser light wavelength in nm
+ :param float observation_angle: The angle of observation is the angle between the observation direction and the direction
+ of the Poynting vector.
+ :param float angle_polarization: The angle between the observation direction and the polarisation direction of the laser light.
+
+ :return: Spectrum
+ """
+ # check for nonzero laser power, ne, te, wavelength
+ if ne <= 0 or te <= 0 or not laser_energy_density > 0:
+ return spectrum
+ if laser_wavelength <= 0:
+ raise ValueError("laser wavelength has to be larger than 0")
+
+ angle_scattering = (180. - observation_angle) # scattering direction is the opposite to obervation direction
+
+ return self._add_spectral_contribution(ne, te, laser_energy_density, angle_scattering, angle_polarization, laser_wavelength, spectrum)
+
+
\ No newline at end of file
diff --git a/cherab/core/model/laser/profile.pxd b/cherab/core/model/laser/profile.pxd
new file mode 100644
index 00000000..12379335
--- /dev/null
+++ b/cherab/core/model/laser/profile.pxd
@@ -0,0 +1,57 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+from raysect.core.math.function.float cimport Function3D
+from raysect.optical cimport Spectrum, Point3D, Vector3D
+
+from cherab.core.laser cimport LaserProfile
+
+
+cdef class UniformEnergyDensity(LaserProfile):
+
+ cdef:
+ double _energy_density, _laser_length, _laser_radius
+
+
+cdef class ConstantAxisymmetricGaussian(LaserProfile):
+
+ cdef:
+ double _stddev, _pulse_energy, _pulse_length, _laser_length, _laser_radius
+ Function3D _distribution
+
+
+cdef class ConstantBivariateGaussian(LaserProfile):
+
+ cdef:
+ double _stddev_x, _stddev_y, _pulse_energy, _pulse_length, _laser_length, _laser_radius
+ Function3D _distribution
+
+
+cdef class TrivariateGaussian(LaserProfile):
+
+ cdef:
+ double _stddev_x, _stddev_y, _stddev_z, _mean_z, _pulse_energy, _pulse_length, _laser_length, _laser_radius
+ Function3D _distribution
+
+
+cdef class GaussianBeamAxisymmetric(LaserProfile):
+
+ cdef:
+ double _pulse_energy, _pulse_length, _stddev_waist, _waist_z, _laser_wavelength, _laser_length, _laser_radius
+ Function3D _distribution
diff --git a/cherab/core/model/laser/profile.pyx b/cherab/core/model/laser/profile.pyx
new file mode 100644
index 00000000..82376980
--- /dev/null
+++ b/cherab/core/model/laser/profile.pyx
@@ -0,0 +1,765 @@
+from raysect.core.math.function.float import Constant3D
+from raysect.core.math.function.vector3d cimport Constant3D as ConstantVector3D
+from raysect.primitive import Cylinder
+from raysect.optical cimport Spectrum, Vector3D, translate
+
+from cherab.core.laser cimport Laser, LaserProfile
+from cherab.core.model.laser.math_functions cimport ConstantAxisymmetricGaussian3D, ConstantBivariateGaussian3D, TrivariateGaussian3D, GaussianBeamModel
+
+from cherab.core.utility.constants cimport SPEED_OF_LIGHT
+
+from libc.math cimport M_PI, sqrt, exp
+
+
+cdef class UniformEnergyDensity(LaserProfile):
+ """
+ LaserProfile with a constant volumetric energy density.
+
+ Returns a laser with a cylindrical shape within which the laser volumentric energy density is constant.
+ The laser starts at z=0 and extends in the positive z direction.
+
+ .. note:
+ The methods get_pointing, get_polarization and get_energy_density are not limited to the inside
+ of the laser cylinder. If called alone for position (x, y, z) outisde the laser cylinder,
+ they will still return non-zero values.
+
+ In the following example, a laser of length of 2 m (extending from z=0 to z=2 m) with a radius of 3 cm
+ and volumetric energy density of 5 J*m^-3 and polarisation in the y direction is created:
+
+ .. code-block:: pycon
+
+ >>> from raysect.core import Vector3D
+ >>> from cherab.core.model.laser import UniformEnergyDensity
+
+ >>> energy = 5 # energy density in J
+ >>> radius = 3e-2 # laser radius in m
+ >>> length = 2 # laser length in m
+ >>> polarisation = Vector3D(0, 1, 0) # polarisation direction
+
+ # create the laser profile
+ >>> laser_profile = UniformEnergyDensity(energy, radius, length, polarisation)
+
+ :param float energy_density: The volumetric energy density of the laser light.
+ :param float laser_length: The length of the laser cylinder.
+ :param float laser_radius: The radius of the laser cylinder.
+ :param Vector3D polarization: The direction of the laser polarization:
+
+ :ivar float energy_density: The volumetric energy density of the laser light.
+ :ivar float laser_radius: The radius of the laser cylinder.
+ :ivar float laser_length: The length of the laser cylinder.
+ """
+
+ def __init__(self, double energy_density=1., double laser_length=1., double laser_radius=0.05, Vector3D polarization=Vector3D(0, 1, 0)):
+ super().__init__()
+
+ self.set_polarization(polarization)
+ self.set_pointing_function(ConstantVector3D(Vector3D(0, 0, 1)))
+ self.energy_density = energy_density
+
+ self._laser_radius = 0.05
+ self._laser_length = 1.
+
+ self.laser_radius = laser_radius
+ self.laser_length = laser_length
+
+ def set_polarization(self, Vector3D value):
+ value = value.normalise()
+ self.set_polarization_function(ConstantVector3D(value))
+
+ @property
+ def laser_length(self):
+ return self._laser_length
+
+ @laser_length.setter
+ def laser_length(self, value):
+
+ if value <= 0:
+ raise ValueError("Laser length has to be larger than 0.")
+
+ self._laser_length = value
+ self.notifier.notify()
+
+ @property
+ def laser_radius(self):
+ return self._laser_radius
+
+ @laser_radius.setter
+ def laser_radius(self, value):
+
+ if value <= 0:
+ raise ValueError("Laser radius has to be larger than 0.")
+
+ self._laser_radius = value
+ self.notifier.notify()
+
+ @property
+ def energy_density(self):
+ return self._energy_density
+
+ @energy_density.setter
+ def energy_density(self, value):
+ if value <= 0:
+ raise ValueError("Laser power density has to be larger than 0.")
+
+ self._energy_density = value
+ funct = Constant3D(value)
+ self.set_energy_density_function(funct)
+
+ cpdef list generate_geometry(self):
+
+ return generate_segmented_cylinder(self.laser_radius, self.laser_length)
+
+
+cdef class ConstantBivariateGaussian(LaserProfile):
+ """
+ LaserProfile with a Gaussian-shaped volumetric energy density distribution in the xy plane
+ and constant pulse intensity.
+
+ Returns a laser with a cylindrical shape and the propagation of the laser light in the positive z direction.
+
+ The model imitates a laser beam with a uniform power output within a single pulse. This results
+ in the distribution of the energy density along the propagation direction of the laser (z-axis) to be also
+ uniform. The integral value of laser energy Exy in an x-y plane is given by
+
+ .. math::
+ E_{xy} = \\frac{E_p}{(c * \\tau)},
+
+ where Ep is the energy of the laser pulse, tau is the temporal pulse length and c is the speed of light in vacuum.
+ In an x-y plane, the volumetric energy density follows a bivariate Gaussian with a zero correlation:
+
+ .. math::
+ E(x, y) = \\frac{E_{xy}}{2 \\pi \\sigma_x \\sigma_y} exp\\left(-\\frac{x^2 + y^2}{2 \\sigma_x \\sigma_y}\\right).
+
+ The sigma_x and sigma_y are standard deviations in x and y directions, respectively.
+
+ .. note::
+ The height of the cylinder, forming the laser beam, is given by the laser_length and is independent from the
+ temporal length of the laser pulse given by pulse_length. This gives the possibility to independently control
+ the size of the laser primitive and the value of the volumetric energy density.
+
+ The methods get_pointing, get_polarization and get_energy_density are not limited to the inside
+ of the laser cylinder. If called for position (x, y, z) outisde the laser cylinder, they can still
+ return non-zero values.
+
+
+ The following example shows how to create a laser with sigma_x= 1 cm and sigma_y=2 cm, which makes the laser
+ profile in x-y plane to be elliptical. The pulse energy is 5 J and the laser temporal pulse length is 10 ns:
+
+ .. code-block:: pycon
+
+ >>> from raysect.core import Vector3D
+ >>> from cherab.core.model.laser import ConstantBivariateGaussian
+
+ >>> radius = 3e-2 # laser radius in m
+ >>> length = 2 # laser length in m
+ >>> polarisation = Vector3D(0, 1, 0) # polarisation direction
+ >>> pulse_energy = 5 # energy in a laser pulse in J
+ >>> pulse_length = 1e-8 # pulse length in s
+ >>> width_x = 1e-2 # standard deviation in x direction in m
+ >>> width_y = 2e-2 # standard deviation in y direction in m
+
+ # create the laser profile
+ >>> laser_profile = ConstantBivariateGaussian(pulse_energy, pulse_length, radius, length, width_x, width_y, polarisation)
+
+ :param float pulse_energy: The energy of the laser in Joules delivered in a single laser pulse.
+ :param float pulse_length: The temporal length of the laser pulse in seconds.
+ :param float laser_length: The length of the laser cylinder.
+ :param float laser_radius: The radius of the laser cylinder.
+ :param float stddev_x: The standard deviation of the bivariate Gaussian distribution of the volumetric energy
+ density distribution of the laser light in the x axis in meters.
+ :param float stddev_y: The standard deviation of the bivariate Gaussian distribution of the volumetric energy
+ density distribution of the laser light in the y axis in meters.
+ :param Vector3D polarization: The direction of the laser polarization:
+
+ :ivar float pulse_energy: The energy of the laser in Joules delivered in a single laser pulse.
+ :ivar float pulse_length: The temporal length of the laser pulse in seconds.
+ :ivar float laser_radius: The radius of the laser cylinder.
+ :ivar float laser_length: The length of the laser cylinder.
+ :ivar float stddev_x: The standard deviation of the bivariate Gaussian distribution of the volumetric energy
+ density distribution of the laser light in the x axis in meters.
+ :ivar float stddev_y: The standard deviation of the bivariate Gaussian distribution of the volumetric energy
+ density distribution of the laser light in the y axis in meters.
+ """
+ def __init__(self, double pulse_energy=1, double pulse_length=1, double laser_radius=0.05, double laser_length=1.,
+ double stddev_x=0.01, double stddev_y=0.01, Vector3D polarization=Vector3D(0, 1, 0)):
+
+ super().__init__()
+ # set initial values
+ self._pulse_energy = 1
+ self._pulse_length = 1
+ self._stddev_x = 0.1
+ self._stddev_y = 0.1
+
+ self._laser_radius = 0.05
+ self._laser_length = 1
+
+ self.laser_radius = laser_radius
+ self.laser_length = laser_length
+
+ self.set_polarization(polarization)
+ self.set_pointing_function(ConstantVector3D(Vector3D(0, 0, 1)))
+
+ self.stddev_x = stddev_x
+ self.stddev_y = stddev_y
+
+ self.pulse_energy = pulse_energy
+ self.pulse_length = pulse_length
+
+ # set laser constants
+ self.set_polarization(polarization)
+
+ def set_polarization(self, Vector3D value):
+ value = value.normalise()
+ self.set_polarization_function(ConstantVector3D(value))
+
+ @property
+ def laser_length(self):
+ return self._laser_length
+
+ @laser_length.setter
+ def laser_length(self, value):
+
+ if value <= 0:
+ raise ValueError("Laser length has to be larger than 0.")
+
+ self._laser_length = value
+ self.notifier.notify()
+
+ @property
+ def laser_radius(self):
+ return self._laser_radius
+
+ @laser_radius.setter
+ def laser_radius(self, value):
+
+ if value <= 0:
+ raise ValueError("Laser radius has to be larger than 0.")
+
+ self._laser_radius = value
+ self.notifier.notify()
+
+ @property
+ def pulse_energy(self):
+ return self._pulse_energy
+
+ @pulse_energy.setter
+ def pulse_energy(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._pulse_energy = value
+ self.notifier.notify()
+
+ @property
+ def pulse_length(self):
+ return self._pulse_length
+
+ @pulse_length.setter
+ def pulse_length(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._pulse_length = value
+ self._function_changed()
+
+ @property
+ def stddev_x(self):
+ return self._stddev_x
+
+ @stddev_x.setter
+ def stddev_x(self, value):
+ if value <= 0:
+ raise ValueError("Standard deviation of the laser power has to be larger than 0.")
+
+ self._stddev_x = value
+ self._function_changed()
+
+ @property
+ def stddev_y(self):
+ return self._stddev_y
+
+ @stddev_y.setter
+ def stddev_y(self, value):
+ if value <= 0:
+ raise ValueError("Standard deviation of the laser power has to be larger than 0.")
+
+ self._stddev_y = value
+ self._function_changed()
+
+ def _function_changed(self):
+ """
+ Energy density should be returned in units [J/m ** 3]. Energy shape in xy
+ plane is defined by normal distribution (integral over xy plane for
+ constant z is 1). The units of such distribution are [m ** -2].
+ In the z axis direction (direction of laser propagation),
+ the laser_energy is spread along the z axis using the velocity
+ of light SPEED_OF_LIGHT and the temporal duration of the pulse:
+ length = SPEED_OF_LIGTH * pulse_length. Combining the normal distribution with the normalisation
+ pulse_energy / length gives the units [J / m ** 3].
+ """
+ self._distribution = ConstantBivariateGaussian3D(self._stddev_x, self._stddev_y)
+
+ length = SPEED_OF_LIGHT * self._pulse_length # convert from temporal to spatial length of pulse
+ normalisation = self._pulse_energy / length # normalisation to have correct spatial energy density [J / m**3]
+
+ function = normalisation * self._distribution
+ self.set_energy_density_function(function)
+
+ cpdef list generate_geometry(self):
+
+ return generate_segmented_cylinder(self.laser_radius, self.laser_length)
+
+
+cdef class TrivariateGaussian(LaserProfile):
+ """
+ LaserProfile with a trivariate Gaussian-shaped volumetric energy density.
+
+ Returns a laser with a cylindrical shape and the propagation of the laser light in the positive z direction.
+ This model imitates a laser beam with a Gaussian distribution of power output within a single pulse frozen in time:
+
+ .. math::
+ E(x, y, z) = \\frac{E_p}{\\sqrt{2 \\pi^3} \\sigma_x \\sigma_y \\sigma_z} exp\\left(-\\frac{x^2}{2 \\sigma_x^2} -\\frac{y^2}{2 \\sigma_y^2} -\\frac{(z - \\mu_z)^2}{2 \\sigma_z^2}\\right).
+
+
+ The sigma_x and sigma_y are standard deviations in x and y directions, respectively, and E_p is the energy deliverd by laser in a
+ single laser pulse. The mu_z is the mean of the distribution in the z direction and controls th position of the laser pulse along the z direction.
+ The standard deviation in z direction sigma_z is calculated from the pulse length tau_p, which is the
+ standard deviation of the Gaussian distributed ouput power of the laser within a single pulse:
+
+ .. math::
+ \\sigma_z = \\tau_p c.
+
+ The c stands for the speed of light in vacuum.
+
+ .. note::
+ The height of the cylinder, forming the laser beam, is given by the laser_length and is independent from the
+ temporal length of the laser pulse given by pulse_length. This gives the possibility to independently control
+ the size of the laser primitive and the value of the volumetric energy density.
+
+ The methods get_pointing, get_polarization and get_energy_density are not limited to the inside
+ of the laser cylinder. If called alone for position (x, y, z) outisde the laser cylinder, they can still
+ return non-zero values.
+
+
+ The following example shows how to create a laser with sigma_x = 1 cm and sigma_y = 2 cm, which makes the laser
+ profile in an x-y plane to be elliptical. The pulse energy is 5 J and the laser temporal pulse length is 10 ns.
+ The position of the laser pulse maximum mean_z is set to 0.5:
+
+ .. code-block:: pycon
+
+ >>> from raysect.core import Vector3D
+ >>> from cherab.core.model.laser import ConstantBivariateGaussian
+
+ >>> radius = 3e-2 # laser radius in m
+ >>> length = 2 # laser length in m
+ >>> polarisation = Vector3D(0, 1, 0) # polarisation direction
+ >>> pulse_energy = 5 # energy in a laser pulse in J
+ >>> pulse_length = 1e-8 # pulse length in s
+ >>> pulse_z = 0.5 # position of the pulse mean
+ >>> width_x = 1e-2 # standard deviation in x direction in m
+ >>> width_y = 2e-2 # standard deviation in y direction in m
+
+ # create the laser profile
+ >>> laser_profile = ConstantBivariateGaussian(pulse_energy, pulse_length, pulse_z, radius, length, width_x, width_y, polarisation)
+
+
+ :param float pulse_energy: The energy of the laser in Joules delivered in a single laser pulse.
+ :param float pulse_length: The standard deviation of the laser pulse length in the temporal domain.
+ :param float mean_z: Position of the mean value of the laser pulse in the z direction. Can be used to control the
+ position of the laser pulse along the laser propagation.
+ :param float laser_length: The length of the laser cylinder.
+ :param float laser_radius: The radius of the laser cylinder.
+ :param float stddev_x: The standard deviation of the bivariate Gaussian distribution of the volumetric energy
+ density distribution of the laser light in the x axis in meters.
+ :param float stddev_y: The standard deviation of the bivariate Gaussian distribution of the volumetric energy
+ density distribution of the laser light in the y axis in meters.
+ :param Vector3D polarization: The direction of the laser polarization.
+
+ :ivar float pulse_energy: The energy of the laser in Joules delivered in a single laser pulse.
+ :ivar float pulse_length: The standard deviation of the laser pulse length in the temporal domain.
+ :ivar float mean_z: Position of the mean value of the laser pulse in the z direction.
+ Can be used to control the position of the laser pulse along the laser propagation.
+ :ivar float laser_radius: The radius of the laser cylinder.
+ :ivar float laser_length: The length of the laser cylinder.
+ :ivar float stddev_x: The standard deviation of the bivariate Gaussian distribution of the volumetric energy
+ density distribution of the laser light in the x axis in meters.
+ :ivar float stddev_y: The standard deviation of the bivariate Gaussian distribution of the volumetric energy
+ density distribution of the laser light in the y axis in meters.
+ """
+ def __init__(self, double pulse_energy=1, double pulse_length=1, double mean_z=0,
+ double laser_length=1., double laser_radius=0.05,
+ double stddev_x=0.01, double stddev_y=0.01,
+ Vector3D polarization=Vector3D(0, 1, 0)):
+
+ super().__init__()
+ # set initial values
+ self._pulse_energy = 1
+ self._pulse_length = 1
+ self._stddev_x = 0.1
+ self._stddev_y = 0.1
+ self._stddev_z = 1
+ self._laser_radius = 0.05
+ self._laser_length = 1
+ self._mean_z = mean_z
+
+
+ self.laser_radius = laser_radius
+ self.laser_length = laser_length
+ self.stddev_x = stddev_x
+ self.stddev_y = stddev_y
+ self.mean_z = mean_z
+
+ self.pulse_energy = pulse_energy
+ self.pulse_length = pulse_length
+
+ self.set_polarization(polarization)
+ self.set_pointing_function(ConstantVector3D(Vector3D(0, 0, 1)))
+
+ def set_polarization(self, Vector3D value):
+ value = value.normalise()
+ self.set_polarization_function(ConstantVector3D(value))
+
+ @property
+ def laser_length(self):
+ return self._laser_length
+
+ @laser_length.setter
+ def laser_length(self, value):
+
+ if value <= 0:
+ raise ValueError("Laser length has to be larger than 0.")
+
+ self._laser_length = value
+ self.notifier.notify()
+
+ @property
+ def laser_radius(self):
+ return self._laser_radius
+
+ @laser_radius.setter
+ def laser_radius(self, value):
+
+ if value <= 0:
+ raise ValueError("Laser radius has to be larger than 0.")
+
+ self._laser_radius = value
+ self.notifier.notify()
+
+ @property
+ def pulse_energy(self):
+ return self._pulse_energy
+
+ @pulse_energy.setter
+ def pulse_energy(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._pulse_energy = value
+ self._function_changed()
+
+ @property
+ def pulse_length(self):
+ return self._pulse_length
+
+ @pulse_length.setter
+ def pulse_length(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._pulse_length = value
+ self._stddev_z = self._pulse_length * SPEED_OF_LIGHT
+ self._function_changed()
+
+ @property
+ def stddev_x(self):
+ return self._stddev_x
+
+ @stddev_x.setter
+ def stddev_x(self, value):
+ if value <= 0:
+ raise ValueError("Standard deviation of the laser power has to be larger than 0.")
+
+ self._stddev_x = value
+ self._function_changed()
+
+ @property
+ def stddev_y(self):
+ return self._stddev_y
+
+ @stddev_y.setter
+ def stddev_y(self, value):
+ if value <= 0:
+ raise ValueError("Standard deviation of the laser power has to be larger than 0.")
+
+ self._stddev_y = value
+ self._function_changed()
+
+ @property
+ def mean_z(self):
+ return self._mean_z
+
+ @mean_z.setter
+ def mean_z(self, double value):
+ self._mean_z = value
+ self._function_changed()
+
+ def _function_changed(self):
+ """
+ Energy density should be returned in units [J/m ** 3]. The integral value of the _distribution
+ is 1, thus multiplying _distribution by _pulse_energy gives correct values.
+ """
+
+ self._distribution = TrivariateGaussian3D(self._mean_z, self._stddev_x, self._stddev_y,
+ self._stddev_z)
+
+ normalisation = self._pulse_energy
+
+ function = normalisation * self._distribution
+ self.set_energy_density_function(function)
+
+ cpdef list generate_geometry(self):
+
+ return generate_segmented_cylinder(self.laser_radius, self.laser_length)
+
+cdef class GaussianBeamAxisymmetric(LaserProfile):
+ """
+ LaserProfile with volumetric energy density following the Gaussian beam model.
+
+ Returns a laser with a cylindrical shape and the propagation of the laser light in the positive z direction. This model implements
+ the axisymmetrical Gaussian beam model. It immitates a focused axis symmetrical laser beam with a uniform power ouput in a laser pulse.
+ The volumetric energy density is given by
+
+ .. math::
+ E(x, y, z) = \\frac{E_{xy}}{2 \\pi \\sigma^2(z)} exp\\left( -\\frac{x^2 + y^2}{2 \\sigma^2(z) }\\right) \\\\
+
+ where the sigma is the standard deviation of the Gaussian shape in the xy plane and is given by
+
+ .. math::
+ sigma(z) = \\sigma_0 \\sqrt{1 + \\left(\\frac{z - z_0}{z_R}\\right)^2}.
+
+ The z_0 is the position of the beam focus and z_R is the Rayleigh length
+
+ .. math::
+ z_R = \\frac{\\pi \\omega_0^2 n}{\\lambda_l}
+
+ where the omega_0 is the standard deviation in the xy plane in the focal point (beam waist) and lambda_l is the central wavelength of
+ the laser. The E_xy stand for the laser energy in an xy plane and is calculated as:
+
+ .. math::
+ E_{xy} = \\frac{E_p}{(c * \\tau)},
+
+ where the E_p is the energy in a single laser pulse and tau is the temporal pulse length.
+
+ .. note::
+ For more information about the Gaussian beam model see https://en.wikipedia.org/wiki/Gaussian_beam
+
+ The methods get_pointing, get_polarization and get_energy_density are not limited to the inside
+ of the laser cylinder. If called alone for position (x, y, z) outisde the laser cylinder, they can still
+ return non-zero values.
+
+ The following example shows how to create a laser with pulse energy 5J, pulse length 10 ns and with the laser cylinder primitive
+ being 2m long with 5 cm in diameter. The the standard deviation of the beam in the focal point (waist) is 5mm and the position of the
+ waist is z=50 cm. The laser wavelength is 1060 nm.
+
+ .. code-block:: pycon
+
+ >>> from raysect.core import Vector3D
+ >>> from cherab.core.model.laser import GaussianBeamAxisymmetric
+
+ >>> radius = 5e-2 # laser radius in m
+ >>> length = 2 # laser length in m
+ >>> polarisation = Vector3D(0, 1, 0) # polarisation direction
+ >>> pulse_energy = 5 # energy in a laser pulse in J
+ >>> pulse_length = 1e-8 # pulse length in s
+ >>> waist_width = 5e-3 # standard deviation in the waist
+ >>> waist_z = 0.5 # position of the pulse mean
+ >>> width_x = 1e-2 # standard deviation in x direction in m
+ >>> width_y = 2e-2 # standard deviation in y direction in m
+ >>> laser_wlen = 1060 # laser wavelength in nm
+
+ # create the laser profile
+ >>> laser_profile = GaussianBeamAxisymmetric(pulse_energy, pulse_length, length, radius, waist_z, waist_width, laser_wlen)
+
+ :param float pulse_energy: The energy of the laser in Joules delivered in a single laser pulse.
+ :param float pulse_length: The temporal length of the laser pulse in seconds.
+ :param float laser_length: The length of the laser cylinder in meters.
+ :param float laser_radius: The radius of the laser cylinder in meters.
+ :param float waist_z: Position of the laser waist along the z axis in m.
+ :param float stddev_waist: The standard deviation of the laser width in the focal point (waist) in m.
+ :param float laser_wavelength: The central wavelength of the laser light in nanometers.
+ :param Vector3D polarization: The direction of the laser polarization.
+
+ :ivar float pulse_energy: The energy of the laser in Joules delivered in a single laser pulse.
+ :ivar float pulse_length: The temporal length of the laser pulse in seconds.
+ :ivar float laser_length: The length of the laser cylinder in meters.
+ :ivar float laser_radius: The radius of the laser cylinder in meters.
+ :ivar float waist_z: Position of the laser waist along the z axis in m.
+ :ivar float stddev_waist: The standard deviation of the laser width in the focal point (waist) in m.
+ :ivar float laser_wavelength: The central wavelength of the laser light in nanometers.
+ :ivar Vector3D polarization: The direction of the laser polarization.
+ """
+
+ def __init__(self, double pulse_energy=1, double pulse_length=1,
+ double laser_length=1., double laser_radius=0.05,
+ double waist_z=0, double stddev_waist=0.01,
+ double laser_wavelength=1e3, Vector3D polarization=Vector3D(0, 1, 0)):
+
+ super().__init__()
+ # set initial values
+ self._pulse_energy = 1
+ self._pulse_length = 1
+ self._stddev_waist = 0.1
+ self._waist_z = waist_z
+ self._laser_wavelength = 1e3
+ self._laser_radius = 0.05
+ self._laser_length = 1
+
+ self.laser_length = laser_length
+ self.laser_radius = laser_radius
+
+ self.set_polarization(polarization)
+ self.set_pointing_function(ConstantVector3D(Vector3D(0, 0, 1)))
+
+ self.stddev_waist = stddev_waist
+ self.waist_z = waist_z
+
+ self.pulse_energy = pulse_energy
+ self.pulse_length = pulse_length
+ self.laser_wavelength = laser_wavelength
+
+ def set_polarization(self, Vector3D value):
+ value = value.normalise()
+ self.set_polarization_function(ConstantVector3D(value))
+
+ @property
+ def laser_length(self):
+ return self._laser_length
+
+ @laser_length.setter
+ def laser_length(self, value):
+
+ if value <= 0:
+ raise ValueError("Laser length has to be larger than 0.")
+
+ self._laser_length = value
+ self.notifier.notify()
+
+ @property
+ def laser_radius(self):
+ return self._laser_radius
+
+ @laser_radius.setter
+ def laser_radius(self, value):
+
+ if value <= 0:
+ raise ValueError("Laser radius has to be larger than 0.")
+
+ self._laser_radius = value
+ self.notifier.notify()
+
+ @property
+ def pulse_energy(self):
+ return self._pulse_energy
+
+ @pulse_energy.setter
+ def pulse_energy(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._pulse_energy = value
+ self._function_changed()
+
+ @property
+ def pulse_length(self):
+ return self._pulse_length
+
+ @pulse_length.setter
+ def pulse_length(self, double value):
+ if value <= 0:
+ raise ValueError("Value has to be larger than 0.")
+
+ self._pulse_length = value
+ self._function_changed()
+
+ @property
+ def waist_z(self):
+ return self._waist_z
+
+ @waist_z.setter
+ def waist_z(self, double value):
+ self._waist_z = value
+ self._function_changed()
+
+ @property
+ def stddev_waist(self):
+ return self._stddev_waist
+
+ @stddev_waist.setter
+ def stddev_waist(self, double value):
+ self._stddev_waist = value
+ self._function_changed()
+
+ @property
+ def laser_wavelength(self):
+ return self._laser_wavelength
+
+ @laser_wavelength.setter
+ def laser_wavelength(self, double value):
+ self._laser_wavelength = value
+ self._function_changed()
+
+ def _function_changed(self):
+ """
+ Energy density should be returned in units [J/m ** 3]. Energy shape in xy
+ plane is defined by normal distribution (integral over xy plane for
+ constant z is 1). The units of such distribution are [m ** -2].
+ In the z axis direction (direction of laser propagation),
+ the laser_energy is spread along the z axis using the velocity
+ of light SPEED_OF_LIGHT and the temporal duration of the pulse:
+ length = SPEED_OF_LIGTH * pulse_length. Combining the normal distribution with the normalisation
+ pulse_energy / length gives the units [J / m ** 3].
+ """
+
+ self._distribution = GaussianBeamModel(self._laser_wavelength, self._waist_z, self._stddev_waist)
+ # calculate volumetric power dentiy
+ length = SPEED_OF_LIGHT * self._pulse_length # convert from temporal to spatial length of pulse
+ normalisation = self._pulse_energy / length # normalisation to have correct spatial energy density [J / m**3]
+
+ function = normalisation * self._distribution
+ self.set_energy_density_function(function)
+
+ cpdef list generate_geometry(self):
+
+ return generate_segmented_cylinder(self.laser_radius, self.laser_length)
+
+
+def generate_segmented_cylinder(radius, length):
+ """
+ Generates a segmented cylindrical laser geometry
+
+ Approximates a long cylinder with a cylindrical segments to optimize
+ targetted and importance sampling. The height of a cylinder segments is roughly
+ 2 * cylinder radius.
+
+ :return: List of cylinders
+ """
+
+ n_segments = int(length // (2 * radius)) # number of segments
+ geometry = []
+
+ #length of segment is either length / n_segments if length > radius or length if length < radius
+ if n_segments > 1:
+ segment_length = length / n_segments
+ for i in range(n_segments):
+ segment = Cylinder(name="Laser segment {0:d}".format(i), radius=radius, height=segment_length,
+ transform=translate(0, 0, i * segment_length))
+
+ geometry.append(segment)
+ elif 0 <= n_segments < 2:
+ segment = Cylinder(name="Laser segment {0:d}".format(0), radius=radius, height=length)
+
+ geometry.append(segment)
+ else:
+ raise ValueError("Incorrect number of segments calculated.")
+
+ return geometry
\ No newline at end of file
diff --git a/cherab/core/model/laser/tests/__init__.py b/cherab/core/model/laser/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/cherab/core/model/laser/tests/test_laserspectrum.py b/cherab/core/model/laser/tests/test_laserspectrum.py
new file mode 100644
index 00000000..1f72e666
--- /dev/null
+++ b/cherab/core/model/laser/tests/test_laserspectrum.py
@@ -0,0 +1,46 @@
+import unittest
+from scipy.integrate import nquad
+
+from cherab.core.model.laser.laserspectrum import GaussianSpectrum, ConstantSpectrum
+
+class TestLaserSpectrum(unittest.TestCase):
+
+ def test_constantspectrum(self):
+ """
+ Laser spectrum should be normalized, i.e. integral from minuns inf. to inf. should be one.
+ :return:
+ """
+ min_wavelength = 1039.9
+ max_wavelength = 1040.1
+ bins = 10
+
+ spectrum = ConstantSpectrum(min_wavelength, max_wavelength, bins)
+
+ # check if the power_spectral density is normalized
+
+ integral = spectrum.power_spectral_density.sum() * spectrum.delta_wavelength
+ self.assertTrue(integral == 1, msg="Power spectral density is not normalised.")
+
+ def test_gaussian_spectrum(self):
+ """
+ Laser spectrum should be normalized, i.e. integral from minuns inf. to inf. should be one.
+ :return:
+ """
+ min_wavelength = 1035
+ max_wavelength = 1045
+ bins = 100
+ mean = 1040
+ stddev = 0.5
+
+ spectrum = GaussianSpectrum(min_wavelength, max_wavelength, bins, mean, stddev)
+ integral = nquad(spectrum, [(min_wavelength, max_wavelength)])[0]
+
+ # check if the power_spectral density is normalized
+ self.assertAlmostEqual(integral, 1., 8, msg="Power spectral density function is not normalised.")
+
+ psd = spectrum.power_spectral_density
+ integral = 0
+ for index in range(0, spectrum.bins - 1):
+ integral += (psd[index] + psd[index + 1]) / 2 * spectrum.delta_wavelength
+
+ self.assertAlmostEqual(integral, 1, 8, msg="Power spectral density is not normalised.")
diff --git a/cherab/core/model/laser/tests/test_model.py b/cherab/core/model/laser/tests/test_model.py
new file mode 100644
index 00000000..992d5d52
--- /dev/null
+++ b/cherab/core/model/laser/tests/test_model.py
@@ -0,0 +1,104 @@
+import unittest
+import numpy as np
+from math import cos, sin, sqrt, radians, exp
+from scipy.constants import pi, c, e, m_e, epsilon_0
+
+from raysect.optical import World, Point3D, Vector3D, translate, Ray
+
+from cherab.core.laser import Laser
+from cherab.core.model.laser import ConstantSpectrum, SeldenMatobaThomsonSpectrum, UniformEnergyDensity
+
+from cherab.tools.plasmas.slab import build_constant_slab_plasma
+
+class TestScatteringModel(unittest.TestCase):
+ laser_wavelength = 1040
+ wavelength = np.linspace(600, 1200, 800)
+ scatangle = 45
+
+ def test_selden_matoba_scattered_spectrum(self):
+
+ # calculate TS cross section and constants
+ r_e = e ** 2 / (4 * pi * epsilon_0 * m_e * c ** 2) # classical electron radius
+
+ # re ** 2 is the cross section, c transforms xsection into rate constant
+ scat_const = r_e ** 2 * c
+
+ ray_origin = Point3D(0, 0, 0)
+
+ # angle of scattering
+ observation_angle = [45, 90, 135]
+ for obsangle in observation_angle:
+
+ # pointing vector is in +z direction, angle of observation is 180 - obsangle
+ z = cos((obsangle) / 180 * pi)
+ x = sin((obsangle) / 180 * pi)
+ ray_direction = Vector3D(x, 0, z).normalise()
+
+ # ray spectrum properties
+ min_wavelength = 600
+ max_wavelength = 1200
+ bins = 800
+
+ # plasma properties
+ e_density = 8e19
+ t_e = [100, 1e3, 1e4]
+
+ for vte in t_e:
+ # setup scene
+ world = World()
+ plasma = build_constant_slab_plasma(length=1, width=1, height=1, electron_density=e_density,
+ electron_temperature=vte, plasma_species=[], parent=world)
+
+ # setup laser
+ laser_spectrum = ConstantSpectrum(1059, 1061, 1)
+ laser_profile = UniformEnergyDensity(laser_length=1, laser_radius=0.015)
+ scattering_model = SeldenMatobaThomsonSpectrum()
+ laser = Laser()
+ laser.parent = world
+ laser.transform = translate(0.05, 0, -0.5)
+ laser.laser_profile = laser_profile
+ laser.laser_spectrum = laser_spectrum
+ laser.plasma = plasma
+ laser.models = [scattering_model]
+
+ # trace a single ray through the laser
+ ray = Ray(origin=ray_origin, direction=ray_direction, min_wavelength=min_wavelength,
+ max_wavelength=max_wavelength, bins=bins)
+ traced_spectrum = ray.trace(world)
+
+
+ # calculate spectrum ray-tracing should deliver
+ dl = 2 * laser_profile.laser_radius / sin((obsangle) / 180 * pi) # ray-laser cross section length
+ intensity_test = np.zeros_like(traced_spectrum.wavelengths)
+
+ for vl in laser.laser_spectrum.wavelengths:
+ intensity_const = scat_const * e_density / vl * dl
+ for iwvl, vwvl in enumerate(traced_spectrum.wavelengths):
+ intensity_test[iwvl] += _selden_matoba_shape(vwvl, vte, obsangle, vl) * intensity_const
+
+ for index, (vtest, vray) in enumerate(zip(intensity_test, traced_spectrum.samples)):
+ # skip the test for too low values of power spectral density, max is approx. 3e-5
+ if vray > 1e-30:
+ rel_error = np.abs((vtest - vray) / vray)
+ self.assertLess(rel_error, 1e-7,
+ msg="Traced and test spectrum value do not match: "
+ "scattering angle = {0} deg, Te = {1} eV, wavelength = {2} nm."
+ .format(180 - obsangle, vte, traced_spectrum.wavelengths[index]))
+
+
+def _selden_matoba_shape(wavelength, te, obsangle, laser_wavelength):
+ """
+ Returns Selden-Matoba Spectral shape
+ """
+ epsilon = wavelength / laser_wavelength - 1
+
+ alpha = m_e * c ** 2 / (2 * e * te)
+
+ scat_angle = 180 - obsangle
+ cos_scat = cos(radians(scat_angle))
+
+ const_c = sqrt(alpha / pi) * (1 - 15 / 16 / alpha + 345 / 512 / alpha ** 2)
+ const_a = (1 + epsilon) ** 3 * sqrt(2 * (1 - cos_scat) * (1 + epsilon) + epsilon ** 2)
+ const_b = sqrt(1 + epsilon ** 2 / (2 * (1 - cos_scat) * (1 + epsilon))) - 1
+
+ return const_c / const_a * exp(-2 * alpha * const_b)
diff --git a/cherab/core/model/laser/tests/test_profiles.py b/cherab/core/model/laser/tests/test_profiles.py
new file mode 100644
index 00000000..6f2c9fc3
--- /dev/null
+++ b/cherab/core/model/laser/tests/test_profiles.py
@@ -0,0 +1,198 @@
+import unittest
+import numpy as np
+from math import exp, sqrt
+
+from raysect.core import Vector3D
+
+from cherab.core.model.laser.profile import UniformEnergyDensity, ConstantBivariateGaussian
+from cherab.core.model.laser.profile import TrivariateGaussian, GaussianBeamAxisymmetric, generate_segmented_cylinder
+
+from scipy.integrate import nquad
+from scipy.constants import c, pi
+
+class TestSegmentedCylinder(unittest.TestCase):
+
+ def test_number_of_primitives(self):
+
+ # for r > l there should be 1 cylinder segment only
+ primitives = generate_segmented_cylinder(radius=1, length=0.5)
+ self.assertEqual(len(primitives), 1, msg="Wrong nuber of laser segments, expected 1.")
+
+ # for r < l tehre should be length // (2 * radius) segments
+ primitives = generate_segmented_cylinder(radius=0.5, length=10)
+ self.assertEqual(len(primitives), 10, msg="Wrong nuber of laser segments, expected 20.")
+
+
+class TestLaserProfile(unittest.TestCase):
+
+ def test_uniform_energy_density(self):
+ polarisation = Vector3D(1, 3, 8).normalise()
+ energy_density = 2
+ model = UniformEnergyDensity(energy_density=energy_density, polarization=polarisation)
+
+ # test polarisation
+ pol_model = model.get_polarization(1, 1, 1)
+ self.assertEqual(pol_model.x, polarisation.x,
+ msg="Model polarization x vector component does not agreee with input value.")
+ self.assertEqual(pol_model.y, polarisation.y,
+ msg="Model polarization y vector component does not agreee with input value.")
+ self.assertEqual(pol_model.z, polarisation.z,
+ msg="Model polarization z vector component does not agreee with input value.")
+
+ # test power
+ self.assertEqual(model.get_energy_density(3, 4, 1), energy_density,
+ msg="Model power density distribution does not agree with input.")
+
+ def test_bivariate_gaussian(self):
+
+ pulse_energy = 2
+ pulse_length = 1e-8
+ stddev_x = 0.03
+ stddev_y = 0.06
+ polarisation = Vector3D(2, 3, 4).normalise()
+ model = ConstantBivariateGaussian(pulse_energy=pulse_energy, pulse_length=pulse_length, stddev_x=stddev_x,
+ stddev_y=stddev_y, polarization=polarisation)
+
+ # test polarisation
+ pol_model = model.get_polarization(1, 1, 1)
+ self.assertEqual(pol_model.x, polarisation.x,
+ msg="Model polarization x vector component does not agreee with input value.")
+ self.assertEqual(pol_model.y, polarisation.y,
+ msg="Model polarization y vector component does not agreee with input value.")
+ self.assertEqual(pol_model.z, polarisation.z,
+ msg="Model polarization z vector component does not agreee with input value.")
+
+ # Integrate over laser volume to check energy
+ xlim = [-5 * stddev_x, 5 * stddev_x]
+ ylim = [-5 * stddev_y, 5 * stddev_y]
+ zlim = [0, pulse_length * c]
+ energy_integrated = nquad(model.get_energy_density, [xlim, ylim, zlim])[0]
+ self.assertTrue(np.isclose(energy_integrated / pulse_energy, 1, 1e-3),
+ msg="Integrated laser energy of the model does not give results close to input energy")
+
+ # Check laser power density profile
+ x = np.linspace(-3 * stddev_x, 3 * stddev_x, 30)
+ y = np.linspace(-3 * stddev_y, 3 * stddev_y, 30)
+ for vx in x:
+ for vy in y:
+ tmp = _constant_bivariate_gaussian2d(vx, vy, pulse_energy, pulse_length, stddev_x, stddev_y)
+ tmp2 = model.get_energy_density(vx, vy, 0)
+ self.assertTrue(np.isclose(tmp, tmp2, 1e-9),
+ msg="Model power density distribution for ({},{},{}) does not agree with input.".format(
+ vx, vy, 0))
+
+ def test_trivariate_gaussian(self):
+
+ pulse_energy = 2
+ pulse_length = 1e-8
+ mean_z = 0
+ stddev_x = 0.03
+ stddev_y = 0.06
+ polarisation = Vector3D(2, 3, 4).normalise()
+ model = TrivariateGaussian(pulse_energy=pulse_energy, pulse_length=pulse_length, mean_z=mean_z,
+ stddev_x=stddev_x, stddev_y=stddev_y, polarization=polarisation)
+
+ # test polarisation
+ pol_model = model.get_polarization(1, 1, 1)
+ self.assertEqual(pol_model.x, polarisation.x,
+ msg="Model polarization x vector component does not agreee with input value.")
+ self.assertEqual(pol_model.y, polarisation.y,
+ msg="Model polarization y vector component does not agreee with input value.")
+ self.assertEqual(pol_model.z, polarisation.z,
+ msg="Model polarization z vector component does not agreee with input value.")
+
+ # Integrate over laser volume to check energy
+ xlim = [-5 * stddev_x, 5 * stddev_x]
+ ylim = [-5 * stddev_y, 5 * stddev_y]
+ zlim = [mean_z - 5 * pulse_length * c, mean_z + 5 * pulse_length * c]
+ energy_integrated = nquad(model.get_energy_density, [xlim, ylim, zlim])[0]
+
+ self.assertTrue(np.isclose(energy_integrated / pulse_energy, 1, 1e-3),
+ msg="Integrated laser energy of the model does not give results close to input energy")
+
+ # Check laser power density profile
+ x = np.linspace(-3 * stddev_x, 3 * stddev_x, 30)
+ y = np.linspace(-3 * stddev_y, 3 * stddev_y, 30)
+ z = np.linspace(-3 * pulse_length * c, 3 * pulse_length * c, 30)
+
+ for vx in x:
+ for vy in y:
+ for vz in z:
+ tmp = _constant_trivariate_gaussian3d(vx, vy, vz, pulse_energy, pulse_length, mean_z, stddev_x,
+ stddev_y)
+ tmp2 = model.get_energy_density(vx, vy, vz)
+ self.assertTrue(np.isclose(tmp, tmp2, 1e-9),
+ msg="Model power density distribution for ({},{},{})"
+ " does not agree with input.".format(vx, vy, vz))
+
+ def test_gaussianbeam(self):
+
+ pulse_energy = 2
+ pulse_length = 1e-9
+ waist_z = 0
+ stddev_waist = 0.003
+ laser_wavelength = 1040
+ polarisation = Vector3D(2, 3, 4).normalise()
+
+ model = GaussianBeamAxisymmetric(pulse_energy=pulse_energy, pulse_length=pulse_length, waist_z=waist_z,
+ stddev_waist=stddev_waist, laser_wavelength=laser_wavelength,
+ polarization=polarisation)
+
+ # test polarisation
+ pol_model = model.get_polarization(1, 1, 1)
+ self.assertEqual(pol_model.x, polarisation.x,
+ msg="Model polarization x vector component does not agreee with input value.")
+ self.assertEqual(pol_model.y, polarisation.y,
+ msg="Model polarization y vector component does not agreee with input value.")
+ self.assertEqual(pol_model.z, polarisation.z,
+ msg="Model polarization z vector component does not agreee with input value.")
+
+ # Integrate over laser volume to check energy
+ xlim = [-20 * stddev_waist, 20 * stddev_waist]
+ zlim = [-1 * pulse_length / 2 * c, pulse_length / 2 * c]
+ energy_integrated = nquad(model.get_energy_density, [xlim, xlim, zlim])[0]
+
+ self.assertTrue(np.isclose(energy_integrated / pulse_energy, 1, 1e-3),
+ msg="Integrated laser energy of the model does not give results close to input energy")
+
+ # Check laser power density profile
+ x = np.linspace(-3 * stddev_waist, 3 * stddev_waist, 30)
+ y = np.linspace(-3 * stddev_waist, 3 * stddev_waist, 30)
+ z = np.linspace(-3 * pulse_length * c, 3 * pulse_length * c, 30)
+
+ for vx in x:
+ for vy in y:
+ for vz in z:
+ tmp = _gaussian_beam_model(vx, vy, vz, pulse_energy, pulse_length, waist_z, stddev_waist,
+ laser_wavelength * 1e-9)
+ tmp2 = model.get_energy_density(vx, vy, vz)
+ self.assertTrue(np.isclose(tmp, tmp2, 1e-9),
+ msg="Model power density distribution for ({},{},{}) "
+ "does not agree with input.".format(vx, vy, vz))
+
+
+def _gaussian_beam_model(x, y, z, pulse_energy, pulse_length, waist_z, stddev_waist, wavelength):
+ laser_power_axis = pulse_energy / (pulse_length * c)
+
+ n = 1 # refractive index
+ rayleigh_distance = 2 * pi * stddev_waist ** 2 * n / wavelength
+
+ z_prime = z - waist_z
+
+ stddev_z2 = stddev_waist ** 2 * (1 + (z_prime / rayleigh_distance) ** 2)
+
+ r2 = x ** 2 + y ** 2
+
+ return laser_power_axis / (2 * pi * stddev_z2) * exp(r2 / (-2 * stddev_z2))
+
+
+def _constant_trivariate_gaussian3d(x, y, z, pulse_energy, pulse_length, mean_z, stddev_x, stddev_y):
+ stddev_z = pulse_length * c
+ return (pulse_energy / (sqrt((2 * pi) ** 3) * stddev_x * stddev_y * stddev_z) *
+ exp(-1 / 2 * ((x / stddev_x) ** 2 + (y / stddev_y) ** 2 + ((z - mean_z) / stddev_z) ** 2)))
+
+
+def _constant_bivariate_gaussian2d(x, y, pulse_energy, pulse_length, stddev_x, stddev_y):
+ length = pulse_length * c
+ normalisation = pulse_energy / length
+ return normalisation / (stddev_x * stddev_y * 2 * pi) * exp(-1 / 2 * ((x / stddev_x) ** 2 + (y / stddev_y) ** 2))
diff --git a/cherab/core/model/lineshape.pxd b/cherab/core/model/lineshape.pxd
index 711475b5..2591efe3 100644
--- a/cherab/core/model/lineshape.pxd
+++ b/cherab/core/model/lineshape.pxd
@@ -24,6 +24,7 @@ cimport numpy as np
from raysect.optical cimport Spectrum, Point3D, Vector3D
from cherab.core cimport Line, Species, Plasma, Beam
from cherab.core.math cimport Function1D, Function2D
+from cherab.core.math.integrators cimport Integrator1D
from cherab.core.atomic.zeeman cimport ZeemanStructure
@@ -41,6 +42,7 @@ cdef class LineShapeModel:
double wavelength
Species target_species
Plasma plasma
+ Integrator1D integrator
cpdef Spectrum add_line(self, double radiance, Point3D point, Vector3D direction, Spectrum spectrum)
diff --git a/cherab/core/model/lineshape.pyx b/cherab/core/model/lineshape.pyx
index 5e346175..69278560 100644
--- a/cherab/core/model/lineshape.pyx
+++ b/cherab/core/model/lineshape.pyx
@@ -19,13 +19,17 @@
# under the Licence.
import numpy as np
+from scipy.special import hyp2f1
+
cimport numpy as np
from libc.math cimport sqrt, erf, M_SQRT2, floor, ceil, fabs
from raysect.optical.spectrum cimport new_spectrum
+from raysect.core.math.function.float cimport Function1D
from cherab.core cimport Plasma
from cherab.core.atomic.elements import hydrogen, deuterium, tritium, helium, helium3, beryllium, boron, carbon, nitrogen, oxygen, neon
from cherab.core.math.function cimport autowrap_function1d, autowrap_function2d
+from cherab.core.math.integrators cimport GaussianQuadrature
from cherab.core.utility.constants cimport ATOMIC_MASS, ELEMENTARY_CHARGE, SPEED_OF_LIGHT
cimport cython
@@ -78,8 +82,6 @@ cpdef double thermal_broadening(double wavelength, double temperature, double at
# the number of standard deviations outside the rest wavelength the line is considered to add negligible value (including a margin for safety)
DEF GAUSSIAN_CUTOFF_SIGMA = 10.0
-DEF LORENZIAN_CUTOFF_GAMMA = 50.0
-
@cython.cdivision(True)
@cython.initializedcheck(False)
@@ -146,14 +148,17 @@ cdef class LineShapeModel:
:param float wavelength: The rest wavelength for this emission line.
:param Species target_species: The target plasma species that is emitting.
:param Plasma plasma: The emitting plasma object.
+ :param Integrator1D integrator: Integrator1D instance to integrate the line shape
+ over the spectral bin. Default is None.
"""
- def __init__(self, Line line, double wavelength, Species target_species, Plasma plasma):
+ def __init__(self, Line line, double wavelength, Species target_species, Plasma plasma, Integrator1D integrator=None):
self.line = line
self.wavelength = wavelength
self.target_species = target_species
self.plasma = plasma
+ self.integrator = integrator
cpdef Spectrum add_line(self, double radiance, Point3D point, Vector3D direction, Spectrum spectrum):
raise NotImplementedError('Child lineshape class must implement this method.')
@@ -289,6 +294,38 @@ cdef class MultipletLineShape(LineShapeModel):
return spectrum
+DEF LORENZIAN_CUTOFF_GAMMA = 50.0
+
+
+cdef class StarkFunction(Function1D):
+ """
+ Normalised Stark function for the StarkBroadenedLine line shape.
+ """
+
+ cdef double _a, _x0, _norm
+
+ STARK_NORM_COEFFICIENT = 4 * LORENZIAN_CUTOFF_GAMMA * hyp2f1(0.4, 1, 1.4, -(2 * LORENZIAN_CUTOFF_GAMMA)**2.5)
+
+ def __init__(self, double wavelength, double lambda_1_2):
+
+ if wavelength <= 0:
+ raise ValueError("Argument 'wavelength' must be positive.")
+
+ if lambda_1_2 <= 0:
+ raise ValueError("Argument 'lambda_1_2' must be positive.")
+
+ self._x0 = wavelength
+ self._a = (0.5 * lambda_1_2)**2.5
+ # normalise, so the integral over x is equal to 1 in the limits
+ # (_x0 - LORENZIAN_CUTOFF_GAMMA * lambda_1_2, _x0 + LORENZIAN_CUTOFF_GAMMA * lambda_1_2)
+ self._norm = (0.5 * lambda_1_2)**1.5 / self.STARK_NORM_COEFFICIENT
+
+ @cython.cdivision(True)
+ cdef double evaluate(self, double x) except? -1e999:
+
+ return self._norm / ((fabs(x - self._x0))**2.5 + self._a)
+
+
cdef class StarkBroadenedLine(LineShapeModel):
"""
Parametrised Stark broadened line shape based on the Model Microfield Method (MMM).
@@ -308,6 +345,9 @@ cdef class StarkBroadenedLine(LineShapeModel):
:param dict stark_model_coefficients: Alternative model coefficients in the form
{line_ij: (c_ij, a_ij, b_ij), ...}.
If None, the default model parameters will be used.
+ :param Integrator1D integrator: Integrator1D instance to integrate the line shape
+ over the spectral bin. Default is `GaussianQuadrature()`.
+
"""
STARK_MODEL_COEFFICIENTS_DEFAULT = {
@@ -352,7 +392,8 @@ cdef class StarkBroadenedLine(LineShapeModel):
Line(tritium, 0, (9, 3)): (5.588e-15, 0.7165, 0.033)
}
- def __init__(self, Line line, double wavelength, Species target_species, Plasma plasma, dict stark_model_coefficients=None):
+ def __init__(self, Line line, double wavelength, Species target_species, Plasma plasma,
+ dict stark_model_coefficients=None, integrator=GaussianQuadrature()):
stark_model_coefficients = stark_model_coefficients or self.STARK_MODEL_COEFFICIENTS_DEFAULT
@@ -371,7 +412,7 @@ cdef class StarkBroadenedLine(LineShapeModel):
except IndexError:
raise ValueError('Stark broadening coefficients for {} is not currently available.'.format(line))
- super().__init__(line, wavelength, target_species, plasma)
+ super().__init__(line, wavelength, target_species, plasma, integrator)
def show_supported_transitions(self):
""" Prints all supported transitions."""
@@ -384,11 +425,13 @@ cdef class StarkBroadenedLine(LineShapeModel):
@cython.cdivision(True)
cpdef Spectrum add_line(self, double radiance, Point3D point, Vector3D direction, Spectrum spectrum):
- cdef double ne, te, lambda_1_2, lambda_5_2, wvl
- cdef double cutoff_lower_wavelength, cutoff_upper_wavelength
- cdef double lower_value, lower_wavelength, upper_value, upper_wavelength
- cdef int start, end, i
- cdef Spectrum raw_lineshape
+ cdef:
+ double ne, te, lambda_1_2, lambda_5_2, wvl
+ double cutoff_lower_wavelength, cutoff_upper_wavelength
+ double lower_wavelength, upper_wavelength
+ double bin_integral
+ int start, end, i
+ Spectrum raw_lineshape
ne = self.plasma.get_electron_distribution().density(point.x, point.y, point.z)
if ne <= 0.0:
@@ -400,6 +443,8 @@ cdef class StarkBroadenedLine(LineShapeModel):
lambda_1_2 = self._cij * ne**self._aij / (te**self._bij)
+ self.integrator.function = StarkFunction(self.wavelength, lambda_1_2)
+
# calculate and check end of limits
cutoff_lower_wavelength = self.wavelength - LORENZIAN_CUTOFF_GAMMA * lambda_1_2
if spectrum.max_wavelength < cutoff_lower_wavelength:
@@ -413,28 +458,16 @@ cdef class StarkBroadenedLine(LineShapeModel):
start = max(0, floor((cutoff_lower_wavelength - spectrum.min_wavelength) / spectrum.delta_wavelength))
end = min(spectrum.bins, ceil((cutoff_upper_wavelength - spectrum.min_wavelength) / spectrum.delta_wavelength))
- # TODO - replace with cumulative integrals
# add line to spectrum
- raw_lineshape = spectrum.new_spectrum()
+ lower_wavelength = spectrum.min_wavelength + start * spectrum.delta_wavelength
- lower_wavelength = raw_lineshape.min_wavelength + start * raw_lineshape.delta_wavelength
- lower_value = 1 / ((fabs(lower_wavelength - self.wavelength))**2.5 + (0.5 * lambda_1_2)**2.5)
for i in range(start, end):
+ upper_wavelength = spectrum.min_wavelength + spectrum.delta_wavelength * (i + 1)
- upper_wavelength = raw_lineshape.min_wavelength + raw_lineshape.delta_wavelength * (i + 1)
- upper_value = 1 / ((fabs(upper_wavelength - self.wavelength))**2.5 + (0.5 * lambda_1_2)**2.5)
-
- raw_lineshape.samples_mv[i] += 0.5 * (upper_value + lower_value)
+ bin_integral = self.integrator.evaluate(lower_wavelength, upper_wavelength)
+ spectrum.samples_mv[i] += radiance * bin_integral / spectrum.delta_wavelength
lower_wavelength = upper_wavelength
- lower_value = upper_value
-
- # perform normalisation
- raw_lineshape.div_scalar(raw_lineshape.total())
-
- for i in range(start, end):
- # Radiance ???
- spectrum.samples_mv[i] += radiance * raw_lineshape.samples_mv[i]
return spectrum
diff --git a/cherab/core/model/plasma/bremsstrahlung.pxd b/cherab/core/model/plasma/bremsstrahlung.pxd
index 4da3422f..f8251b28 100644
--- a/cherab/core/model/plasma/bremsstrahlung.pxd
+++ b/cherab/core/model/plasma/bremsstrahlung.pxd
@@ -1,6 +1,6 @@
-# Copyright 2016-2018 Euratom
-# Copyright 2016-2018 United Kingdom Atomic Energy Authority
-# Copyright 2016-2018 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
#
# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
# European Commission - subsequent versions of the EUPL (the "Licence");
@@ -18,16 +18,21 @@
# cython: language_level=3
-from cherab.core.atomic cimport Line
+from numpy cimport ndarray
+from cherab.core.atomic cimport FreeFreeGauntFactor
from cherab.core.plasma cimport PlasmaModel
-from cherab.core.species cimport Species
cdef class Bremsstrahlung(PlasmaModel):
cdef:
- Line _line
- double _wavelength
- Species _target_species
+ FreeFreeGauntFactor _gaunt_factor
+ bint _user_provided_gaunt_factor
+ ndarray _species_charge, _species_density
+ double[::1] _species_density_mv, _species_charge_mv
+
+ cdef double _bremsstrahlung(self, double wvl, double te, double ne)
+
+ cdef int _populate_cache(self) except -1
+
- cdef double _bremsstrahlung(self, double wvl, double te, double ne, double zeff)
diff --git a/cherab/core/model/plasma/bremsstrahlung.pyx b/cherab/core/model/plasma/bremsstrahlung.pyx
index 473fb76b..2ba7245b 100644
--- a/cherab/core/model/plasma/bremsstrahlung.pyx
+++ b/cherab/core/model/plasma/bremsstrahlung.pyx
@@ -1,6 +1,6 @@
-# Copyright 2016-2018 Euratom
-# Copyright 2016-2018 United Kingdom Atomic Energy Authority
-# Copyright 2016-2018 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
#
# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
# European Commission - subsequent versions of the EUPL (the "Licence");
@@ -18,7 +18,11 @@
# cython: language_level=3
+import numpy as np
from raysect.optical cimport Spectrum, Point3D, Vector3D
+from cherab.core cimport Plasma, AtomicData
+from cherab.core.atomic cimport FreeFreeGauntFactor
+from cherab.core.species cimport Species
from cherab.core.utility.constants cimport RECIP_4_PI, ELEMENTARY_CHARGE, SPEED_OF_LIGHT, PLANCK_CONSTANT
from libc.math cimport sqrt, log, exp
cimport cython
@@ -38,11 +42,37 @@ cdef class Bremsstrahlung(PlasmaModel):
et. al., 'ITER LIDAR performance analysis', Rev. Sci. Instrum. 79, 10E727 (2008),
.. math::
- \\epsilon (\\lambda) = \\frac{0.95 \\times 10^{-19}}{\\lambda 4 \\pi} g_{ff} n_e^2 Z_{eff} T_e^{1/2} \\times \\exp{\\frac{-hc}{\\lambda T_e}},
+ \\epsilon (\\lambda) = \\frac{0.95 \\times 10^{-19}}{\\lambda 4 \\pi} \\sum_{i} \\left(g_{ff}(Z_i, T_e, \\lambda) n_i Z_i^2\\right) n_e T_e^{-1/2} \\times \\exp{\\frac{-hc}{\\lambda T_e}},
where the emission :math:`\\epsilon (\\lambda)` is in units of radiance (ph/s/sr/m^3/nm).
+
+ :ivar Plasma plasma: The plasma to which this emission model is attached. Default is None.
+ :ivar AtomicData atomic_data: The atomic data provider for this model. Default is None.
+ :ivar FreeFreeGauntFactor gaunt_factor: Free-free Gaunt factor as a function of Z, Te and
+ wavelength. If not provided,
+ the `atomic_data` is used.
"""
+ def __init__(self, Plasma plasma=None, AtomicData atomic_data=None, FreeFreeGauntFactor gaunt_factor=None):
+
+ super().__init__(plasma, atomic_data)
+
+ self.gaunt_factor = gaunt_factor
+
+ # ensure that cache is initialised
+ self._change()
+
+ @property
+ def gaunt_factor(self):
+
+ return self._gaunt_factor
+
+ @gaunt_factor.setter
+ def gaunt_factor(self, value):
+
+ self._gaunt_factor = value
+ self._user_provided_gaunt_factor = True if value else False
+
def __repr__(self):
return ''
@@ -53,29 +83,38 @@ cdef class Bremsstrahlung(PlasmaModel):
cpdef Spectrum emission(self, Point3D point, Vector3D direction, Spectrum spectrum):
cdef:
- double ne, te, z_effective
+ double ne, te
double lower_wavelength, upper_wavelength
double lower_sample, upper_sample
+ Species species
int i
+ # cache data on first run
+ if self._species_charge is None:
+ self._populate_cache()
+
ne = self._plasma.get_electron_distribution().density(point.x, point.y, point.z)
- if ne == 0:
+ if ne <= 0:
return spectrum
te = self._plasma.get_electron_distribution().effective_temperature(point.x, point.y, point.z)
- if te == 0:
- return spectrum
- z_effective = self._plasma.z_effective(point.x, point.y, point.z)
- if z_effective == 0:
+ if te <= 0:
return spectrum
+ # collect densities of charged species
+ i = 0
+ for species in self._plasma.get_composition():
+ if species.charge > 0:
+ self._species_density_mv[i] = species.distribution.density(point.x, point.y, point.z)
+ i += 1
+
# numerically integrate using trapezium rule
# todo: add sub-sampling to increase numerical accuracy
lower_wavelength = spectrum.min_wavelength
- lower_sample = self._bremsstrahlung(lower_wavelength, te, ne, z_effective)
+ lower_sample = self._bremsstrahlung(lower_wavelength, te, ne)
for i in range(spectrum.bins):
- upper_wavelength = spectrum.min_wavelength + spectrum.delta_wavelength * i
- upper_sample = self._bremsstrahlung(upper_wavelength, te, ne, z_effective)
+ upper_wavelength = spectrum.min_wavelength + spectrum.delta_wavelength * (i + 1)
+ upper_sample = self._bremsstrahlung(upper_wavelength, te, ne)
spectrum.samples_mv[i] += 0.5 * (lower_sample + upper_sample)
@@ -85,23 +124,66 @@ cdef class Bremsstrahlung(PlasmaModel):
return spectrum
@cython.cdivision(True)
- cdef double _bremsstrahlung(self, double wvl, double te, double ne, double zeff):
+ @cython.boundscheck(False)
+ @cython.wraparound(False)
+ cdef double _bremsstrahlung(self, double wvl, double te, double ne):
"""
- :param wvl: in nm
- :param te: in eV
- :param ne: in m^-3
- :param zeff: a.u.
- :return:
+ :param double wvl: Wavelength in nm.
+ :param double te: Electron temperature in eV
+ :param double ne: Electron dencity in m^-3
+ :return:
"""
- cdef double gaunt_factor, radiance, pre_factor
+ cdef double ni_gff_z2, radiance, pre_factor, ni, z
+ cdef int i
- # gaunt factor
- gaunt_factor = max(1., 0.6183 * log(te) - 0.0821)
+ ni_gff_z2 = 0
+ for i in range(self._species_charge_mv.shape[0]):
+ z = self._species_charge_mv[i]
+ ni = self._species_density_mv[i]
+ if ni > 0:
+ ni_gff_z2 += ni * self._gaunt_factor.evaluate(z, te, wvl) * z * z
# bremsstrahlung equation W/m^3/str/nm
- pre_factor = 0.95e-19 * RECIP_4_PI * gaunt_factor * ne * ne * zeff / (sqrt(te) * wvl)
- radiance = pre_factor * exp(- EXP_FACTOR / (te * wvl)) * PH_TO_J_FACTOR
+ pre_factor = 0.95e-19 * RECIP_4_PI * ni_gff_z2 * ne / (sqrt(te) * wvl)
+ radiance = pre_factor * exp(- EXP_FACTOR / (te * wvl)) * PH_TO_J_FACTOR
# convert to W/m^3/str/nm
return radiance / wvl
+
+ cdef int _populate_cache(self) except -1:
+
+ cdef list species_charge
+ cdef Species species
+
+ if self._plasma is None:
+ raise RuntimeError("The emission model is not connected to a plasma object.")
+
+ if self._gaunt_factor is None:
+ if self._atomic_data is None:
+ raise RuntimeError("The emission model is not connected to an atomic data source.")
+
+ # initialise Gaunt factor on first run using the atomic data
+ self._gaunt_factor = self._atomic_data.free_free_gaunt_factor()
+
+ species_charge = []
+ for species in self._plasma.get_composition():
+ if species.charge > 0:
+ species_charge.append(species.charge)
+
+ # Gaunt factor takes Z as double to support Zeff, so caching Z as float64
+ self._species_charge = np.array(species_charge, dtype=np.float64)
+ self._species_charge_mv = self._species_charge
+
+ self._species_density = np.zeros_like(self._species_charge)
+ self._species_density_mv = self._species_density
+
+ def _change(self):
+
+ # clear cache to force regeneration on first use
+ if not self._user_provided_gaunt_factor:
+ self._gaunt_factor = None
+ self._species_charge = None
+ self._species_charge_mv = None
+ self._species_density = None
+ self._species_density_mv = None
diff --git a/cherab/core/tests/test_lineshapes.py b/cherab/core/tests/test_lineshapes.py
index c29f1f2e..da4dc41d 100644
--- a/cherab/core/tests/test_lineshapes.py
+++ b/cherab/core/tests/test_lineshapes.py
@@ -18,17 +18,17 @@
import unittest
-import os
import numpy as np
-from scipy.special import erf
+from scipy.special import erf, hyp2f1
+from scipy.integrate import quadrature
from raysect.core import Point3D, Vector3D
from raysect.core.math.function.float import Arg1D, Constant1D
from raysect.optical import Spectrum
from cherab.core import Line
+from cherab.core.math.integrators import GaussianQuadrature
from cherab.core.atomic import deuterium, nitrogen, ZeemanStructure
-from cherab.openadas import OpenADAS
from cherab.tools.plasmas.slab import build_constant_slab_plasma
from cherab.core.model import GaussianLine, MultipletLineShape, StarkBroadenedLine, ZeemanTriplet, ParametrisedZeemanTriplet, ZeemanMultiplet
@@ -116,7 +116,7 @@ def test_multiplet_line_shape(self):
for i in range(bins):
self.assertAlmostEqual(multi_gaussian[i], spectrum.samples[i], delta=1e-10,
- msg='GaussianLine.add_line() method gives a wrong value at {} nm.'.format(wavelengths[i]))
+ msg='MultipletLineShape.add_line() method gives a wrong value at {} nm.'.format(wavelengths[i]))
def test_zeeman_triplet(self):
# setting up a line shape model
@@ -167,7 +167,7 @@ def test_zeeman_triplet(self):
for pol in ('no', 'pi', 'sigma'):
for i in range(bins):
self.assertAlmostEqual(tri_gaussian[pol][i], spectrum[pol].samples[i], delta=1e-10,
- msg='GaussianLine.add_line() method gives a wrong value at {} nm.'.format(wavelengths[i]))
+ msg='ZeemanTriplet.add_line() method gives a wrong value at {} nm.'.format(wavelengths[i]))
def test_parametrised_zeeman_triplet(self):
# setting up a line shape model
@@ -219,7 +219,7 @@ def test_parametrised_zeeman_triplet(self):
for pol in ('no', 'pi', 'sigma'):
for i in range(bins):
self.assertAlmostEqual(tri_gaussian[pol][i], spectrum[pol].samples[i], delta=1e-10,
- msg='GaussianLine.add_line() method gives a wrong value at {} nm.'.format(wavelengths[i]))
+ msg='ParametrisedZeemanTriplet.add_line() method gives a wrong value at {} nm.'.format(wavelengths[i]))
def test_zeeman_multiplet(self):
# setting up a line shape model
@@ -277,14 +277,15 @@ def test_zeeman_multiplet(self):
for pol in ('no', 'pi', 'sigma'):
for i in range(bins):
self.assertAlmostEqual(tri_gaussian[pol][i], spectrum[pol].samples[i], delta=1e-10,
- msg='GaussianLine.add_line() method gives a wrong value at {} nm.'.format(wavelengths[i]))
+ msg='ZeemanMultiplet.add_line() method gives a wrong value at {} nm.'.format(wavelengths[i]))
def test_stark_broadened_line(self):
# setting up a line shape model
line = Line(deuterium, 0, (6, 2)) # D-delta line
target_species = self.plasma.composition.get(line.element, line.charge)
wavelength = 656.104
- stark_line = StarkBroadenedLine(line, wavelength, target_species, self.plasma)
+ integrator = GaussianQuadrature(relative_tolerance=1.e-5)
+ stark_line = StarkBroadenedLine(line, wavelength, target_species, self.plasma, integrator=integrator)
# spectrum parameters
min_wavelength = wavelength - 0.2
@@ -304,14 +305,19 @@ def test_stark_broadened_line(self):
te = self.plasma.electron_distribution.effective_temperature(point.x, point.y, point.z)
lambda_1_2 = cij * ne**aij / (te**bij)
+ lorenzian_cutoff_gamma = 50
+ stark_norm_coeff = 4 * lorenzian_cutoff_gamma * hyp2f1(0.4, 1, 1.4, -(2 * lorenzian_cutoff_gamma)**2.5)
+ norm = (0.5 * lambda_1_2)**1.5 / stark_norm_coeff
+
wavelengths, delta = np.linspace(min_wavelength, max_wavelength, bins + 1, retstep=True)
- stark_lineshape = 1 / ((np.abs(wavelengths - wavelength))**2.5 + (0.5 * lambda_1_2)**2.5)
- stark_lineshape = 0.5 * (stark_lineshape[1:] + stark_lineshape[:-1])
- stark_lineshape /= stark_lineshape.sum() * delta
+
+ def stark_lineshape(x):
+ return norm / ((np.abs(x - wavelength))**2.5 + (0.5 * lambda_1_2)**2.5)
for i in range(bins):
- self.assertAlmostEqual(stark_lineshape[i], spectrum.samples[i], delta=1e-10,
- msg='GaussianLine.add_line() method gives a wrong value at {} nm.'.format(wavelengths[i]))
+ stark_bin = quadrature(stark_lineshape, wavelengths[i], wavelengths[i + 1], rtol=integrator.relative_tolerance)[0] / delta
+ self.assertAlmostEqual(stark_bin, spectrum.samples[i], delta=1e-9,
+ msg='StarkBroadenedLine.add_line() method gives a wrong value at {} nm.'.format(wavelengths[i]))
if __name__ == '__main__':
diff --git a/cherab/core/utility/constants.pxd b/cherab/core/utility/constants.pxd
index fd3fa568..9cce304d 100644
--- a/cherab/core/utility/constants.pxd
+++ b/cherab/core/utility/constants.pxd
@@ -1,6 +1,6 @@
-# Copyright 2016-2018 Euratom
-# Copyright 2016-2018 United Kingdom Atomic Energy Authority
-# Copyright 2016-2018 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
#
# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
# European Commission - subsequent versions of the EUPL (the "Licence");
@@ -29,3 +29,4 @@ cdef:
double PLANCK_CONSTANT
double ELECTRON_CLASSICAL_RADIUS
double ELECTRON_REST_MASS
+ double RYDBERG_CONSTANT_EV
diff --git a/cherab/core/utility/constants.pyx b/cherab/core/utility/constants.pyx
index 348e28c3..03e70617 100644
--- a/cherab/core/utility/constants.pyx
+++ b/cherab/core/utility/constants.pyx
@@ -1,6 +1,6 @@
-# Copyright 2016-2018 Euratom
-# Copyright 2016-2018 United Kingdom Atomic Energy Authority
-# Copyright 2016-2018 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
#
# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
# European Commission - subsequent versions of the EUPL (the "Licence");
@@ -31,4 +31,4 @@ cdef:
double PLANCK_CONSTANT = 6.62607015e-34
double ELECTRON_CLASSICAL_RADIUS = 2.8179403262e-15
double ELECTRON_REST_MASS = 9.1093837015e-31
-
+ double RYDBERG_CONSTANT_EV = 13.605693122994
diff --git a/cherab/generomak/plasma/__init__.py b/cherab/generomak/plasma/__init__.py
index e7287963..7cccf703 100644
--- a/cherab/generomak/plasma/__init__.py
+++ b/cherab/generomak/plasma/__init__.py
@@ -1 +1,3 @@
-from .plasma import get_edge_distributions, get_edge_interpolators, get_edge_plasma
\ No newline at end of file
+from .plasma import get_2d_distributions, get_edge_interpolators, get_edge_plasma
+from .plasma import get_core_distributions, get_core_plasma
+from .plasma import get_full_profiles, get_plasma
diff --git a/cherab/generomak/plasma/data/core/carbon0.json b/cherab/generomak/plasma/data/core/carbon0.json
new file mode 100644
index 00000000..d8763cf4
--- /dev/null
+++ b/cherab/generomak/plasma/data/core/carbon0.json
@@ -0,0 +1,1294 @@
+{
+ "temperature": [
+ 2800.0,
+ 2795.5297458338687,
+ 2782.7582301214393,
+ 2762.5950477966007,
+ 2735.8851983639343,
+ 2703.411010968356,
+ 2665.8945476185836,
+ 2624.0003243064125,
+ 2578.338228519893,
+ 2529.466541110544,
+ 2477.8949930363638,
+ 2424.08780488189,
+ 2368.4666705053005,
+ 2311.4136566031007,
+ 2253.2739981035534,
+ 2194.3587756195216,
+ 2134.9474661044947,
+ 2075.290361665309,
+ 2015.6108544256936,
+ 1956.107587588782,
+ 1896.9564745570865,
+ 1838.3125892477842,
+ 1780.3119316786645,
+ 1723.0730735666177,
+ 1666.6986891326694,
+ 1611.2769765905086,
+ 1556.8829759454748,
+ 1503.5797887772371,
+ 1451.4197056453777,
+ 1400.4452466615378,
+ 1350.6901206300427,
+ 1302.1801079829825,
+ 1254.9338725355856,
+ 1208.9637068710047,
+ 1164.2762159367799,
+ 1120.8729432030323,
+ 1078.7509434988951,
+ 1037.903306411775,
+ 998.3196339061595,
+ 959.986475596583,
+ 922.8877248943963,
+ 887.004979041061,
+ 852.3178658425425,
+ 818.8043397302939,
+ 786.4409495946626,
+ 755.2030806662577,
+ 725.0651725599275,
+ 696.0009154442936,
+ 667.9834261571025,
+ 640.9854059526704,
+ 614.9792814421413,
+ 589.9373301697594,
+ 565.8317921585761,
+ 542.6349686565285,
+ 520.3193092183391,
+ 498.8574881697798,
+ 478.22247141812255,
+ 458.3875744958107,
+ 439.3265126530432,
+ 421.0134437488174,
+ 403.4230046287076,
+ 386.5303416208766,
+ 370.3111357293156,
+ 354.74162305475744,
+ 339.79861092883743,
+ 325.4594902056625,
+ 311.70224411672444,
+ 298.5054540598485,
+ 285.84830266038824,
+ 273.71057441296176,
+ 262.0726541844933,
+ 250.91552383399323,
+ 240.22075718122792,
+ 229.97051353503508,
+ 220.14752997240066,
+ 210.73511254139078,
+ 201.7171265444924,
+ 193.07798604378416,
+ 184.80264271546582,
+ 176.8765741685898,
+ 169.28577183121658,
+ 162.01672849659778,
+ 155.05642561229888,
+ 148.39232038631826,
+ 142.01233277619647,
+ 135.90483241974619,
+ 130.05862555934604,
+ 124.46294200564746,
+ 119.10742218101434,
+ 113.98210427798426,
+ 109.07741156349235,
+ 104.38413985546642,
+ 99.89344519467129,
+ 95.59683173130277,
+ 91.48613984279793,
+ 87.55353449656745,
+ 83.79149386891429,
+ 80.19279822915814,
+ 76.7505190960298,
+ 73.4580086716009,
+ 70.30888955644176,
+ 67.29704474828924,
+ 64.41660792525342,
+ 61.66195401348148,
+ 59.027690038231896,
+ 56.508646256439604,
+ 54.09986756812256,
+ 51.79660520330721,
+ 49.59430868060964,
+ 47.488618033112196,
+ 45.4753562967661,
+ 43.55052225621492,
+ 41.710283442635344,
+ 39.95096937796647,
+ 38.26906505970934,
+ 36.66120468032837,
+ 35.12416557519362,
+ 33.65486239291572,
+ 32.25034148188933,
+ 30.907775486848166,
+ 29.624458149229337,
+ 28.39779930519129,
+ 27.225320075155384,
+ 26.104648238820975,
+ 25.033513789664312,
+ 24.009744663032187,
+ 23.03126263202616,
+ 22.09607936549286,
+ 21.20229264253159,
+ 20.348082718071975,
+ 19.531708834175102,
+ 18.751505871858317,
+ 18.005881138361524,
+ 17.29331128491523,
+ 16.612339350196027,
+ 15.961571924800158,
+ 15.339676432189938,
+ 14.745378521713246,
+ 14.17745956942282,
+ 13.634754282558198,
+ 13.116148403687774,
+ 12.62057651063149,
+ 12.147019908417766,
+ 11.694504609655857,
+ 11.262099399819382,
+ 10.848913984069997,
+ 10.454097212357015,
+ 10.076835379651857,
+ 9.716350598285864,
+ 9.37189923947122,
+ 9.042770441189758,
+ 8.728284679739293,
+ 8.427792402331782,
+ 8.140672718228085,
+ 7.866332145997564,
+ 7.604203414576368,
+ 7.353744315892651,
+ 7.114436606910324,
+ 6.88578495902669,
+ 6.66731595284398,
+ 6.458577116405904,
+ 6.259136005074808,
+ 6.068579321290205,
+ 5.886512072521773,
+ 5.712556765802551,
+ 5.546352637286773,
+ 5.387554915341459,
+ 5.235834115747535,
+ 5.09087536763343,
+ 4.952377768832103,
+ 4.820053769398764,
+ 4.693628582080498,
+ 4.572839618581702,
+ 4.457435950513924,
+ 4.347177793965752,
+ 4.241836016675181,
+ 4.1411916668281155,
+ 4.045035522543728,
+ 3.953167661156071,
+ 3.8653970474291826,
+ 3.7815411398866017,
+ 3.701425514464914,
+ 3.624883504742671,
+ 3.5517558580176334,
+ 3.4818904065449097,
+ 3.4151417532737645,
+ 3.3513709714494597,
+ 3.2904453174754256,
+ 3.23223795645469,
+ 3.176627699856822,
+ 3.1234987547774122,
+ 3.0727404842841777,
+ 3.0242471783623297,
+ 2.9779178349937,
+ 2.933655950925356,
+ 2.8913693217009238,
+ 2.850969850548094,
+ 2.8123733657334666,
+ 2.7754994460091185,
+ 2.7402712537980722,
+ 2.706615375774928,
+ 2.6744616705174318,
+ 2.6437431229153345,
+ 2.6143957050402027,
+ 2.586358243189803,
+ 2.5595722908346312,
+ 2.5339820072055117,
+ 2.509534041273594,
+ 2.4861774208836924,
+ 2.4638634468137517,
+ 2.442545591541203,
+ 2.4221794025087373,
+ 2.4027224096911914,
+ 2.384134037270308,
+ 2.366375519239019,
+ 2.3494098187571737,
+ 2.3332015510957254,
+ 2.3177169100087984,
+ 2.302923597380779,
+ 2.288790756005567,
+ 2.2752889053561534,
+ 2.2623898802136084,
+ 2.250066772028685,
+ 2.23829387289304,
+ 2.2270466220056035,
+ 2.21630155452372,
+ 2.2060362526908253,
+ 2.196229299141507,
+ 2.1868602322873785,
+ 2.1779095036891287,
+ 2.1693584373282744,
+ 2.1611891906943277,
+ 2.1533847176048013,
+ 2.145928732682899,
+ 2.1388056774176825,
+ 2.1320006877379507,
+ 2.125499563030551,
+ 2.1192887365398065,
+ 2.113355247087553,
+ 2.1076867120526006,
+ 2.1022713015558105,
+ 2.0970977137961215,
+ 2.092155151486069,
+ 2.0874332993384708,
+ 2.082922302556797,
+ 2.0786127462849016,
+ 2.0744956359735283,
+ 2.070562378622614,
+ 2.0668047648594987,
+ 2.0632149518174363,
+ 2.059785446777764,
+ 2.0565090915410997,
+ 2.05337904749653,
+ 2.050388781356637,
+ 2.0475320515291053,
+ 1.9864209304153415
+ ],
+ "density": [
+ 0.04048744608721366,
+ 0.040991967564575016,
+ 0.041600133540233744,
+ 0.04226815318206501,
+ 0.04300976853695856,
+ 0.04382292413886765,
+ 0.044710990818178135,
+ 0.04566084382265294,
+ 0.04668132671587653,
+ 0.04778384269676666,
+ 0.04894347040181093,
+ 0.050217658359466025,
+ 0.05155120707621356,
+ 0.05298459045905281,
+ 0.05451328150461624,
+ 0.05613579339020678,
+ 0.05786886344594796,
+ 0.05971555622426197,
+ 0.06168940973780461,
+ 0.06379299848100341,
+ 0.06604924274633829,
+ 0.06845688699486069,
+ 0.07104012824009528,
+ 0.07381877203820006,
+ 0.07680888578177371,
+ 0.07999015982750216,
+ 0.0834079665219863,
+ 0.08705720329088246,
+ 0.09096350307186839,
+ 0.09519183101684933,
+ 0.09977767252368747,
+ 0.10473300929035899,
+ 0.1101772697322425,
+ 0.11612224522135849,
+ 0.12263233516381865,
+ 0.12965535501683825,
+ 0.13730843623793318,
+ 0.1456718556947092,
+ 0.15482815214674314,
+ 0.1649193448672138,
+ 0.17609578865161815,
+ 0.18843317970688814,
+ 0.20225092445258935,
+ 0.21769147208669645,
+ 0.235057725643753,
+ 0.25450284419119984,
+ 0.27607481059071376,
+ 0.3001968017285936,
+ 0.32721833903790154,
+ 0.35788158051591024,
+ 0.3927201787927346,
+ 0.3419825951457436,
+ 4.4007276393775686e-05,
+ 2.118242147089871e-06,
+ 9.990808414127548e-06,
+ 2.1760842922898868e-05,
+ 1.0701015086025121e-05,
+ 2.0686100893291997e-05,
+ 1.4102252243972512e-05,
+ 1.6341843536751136e-05,
+ 5.920055478903454e-05,
+ 3.1202822019714874e-05,
+ 7.006577902969221e-06,
+ 3.0485999375746203e-110,
+ 1.351046152877299e-05,
+ 3.723317857953726e-05,
+ 1.4621524348837632e-05,
+ 8.234384469567877e-05,
+ 4.724949485563587e-07,
+ 1.3234130610459686e-05,
+ 1.1250023529740069e-06,
+ 3.40650350246754e-05,
+ 8.61113675417637e-05,
+ 3.4544273659392032e-06,
+ 1.115441842931324e-05,
+ 6.750427753043206e-05,
+ 0.000101851956735232,
+ 4.1417751607125216e-07,
+ 1.733113479346441e-05,
+ 0.00014160026465313052,
+ 0.00017297702950056632,
+ 0.00026253696716014923,
+ 0.0003314571871220419,
+ 0.0006750813370322345,
+ 0.0011644314857210615,
+ 0.0019017827396563996,
+ 0.0032704725357429448,
+ 0.006078302645905549,
+ 0.010855190117619993,
+ 0.01953392347223397,
+ 1.8680620540029122e-05,
+ 7.144970850284283e-05,
+ 5.542912364767046e-06,
+ 7.435691322796886e-05,
+ 0.00016143391343427039,
+ 0.00020306133691749687,
+ 0.00028544558695254034,
+ 0.0008743656306073129,
+ 0.0024050292905490136,
+ 0.005775071597051694,
+ 0.0005348662947240205,
+ 0.0006539565495507168,
+ 0.0010281871631532197,
+ 0.0013522734276574968,
+ 0.0018752787770719434,
+ 0.0022794719905617836,
+ 0.0032833530457091267,
+ 0.001990519405536644,
+ 0.005452626266015973,
+ 0.00677493232228747,
+ 0.008864117251803522,
+ 0.011092803666997013,
+ 0.013852370395545835,
+ 0.0172470165417693,
+ 0.020371187929570215,
+ 0.025505315179375047,
+ 0.031074048340423287,
+ 0.037995782307585234,
+ 0.0465310460856086,
+ 0.05631424807984447,
+ 0.06745275939537863,
+ 0.08017572144032707,
+ 0.09451365752132886,
+ 0.11074564103118154,
+ 0.12885395814665107,
+ 0.1495571109436204,
+ 0.17305975617364092,
+ 0.19900124477774955,
+ 0.22795492765149622,
+ 0.26016815091843437,
+ 0.29558301290421074,
+ 0.335098447301964,
+ 0.3787529583978551,
+ 0.42680395334454346,
+ 0.47905611444170587,
+ 0.5362824136346813,
+ 0.5985500572439016,
+ 0.6662418422094794,
+ 0.7392810015960789,
+ 0.8192667858555257,
+ 0.9041791387661262,
+ 0.9967330727340975,
+ 1.0961554182560838,
+ 1.202232925311796,
+ 1.3149305765995665,
+ 1.435581443569537,
+ 1.5641755524988206,
+ 1.6995539260866523,
+ 1.8438087576258209,
+ 1.9952089389535912,
+ 2.1548842155881163,
+ 2.3225752489437097,
+ 2.497782026083675,
+ 2.6799685020901842,
+ 2.8702102138142576,
+ 3.067718277784516,
+ 3.272652118255717,
+ 3.4841842881068805,
+ 3.70264957750554,
+ 3.9265053166806303,
+ 4.157418486084073,
+ 4.391689392465598,
+ 4.632972611931735,
+ 4.8774029454280745,
+ 5.12689907629093,
+ 5.380601479886791,
+ 5.635293049863927,
+ 5.894617217838846,
+ 6.15540931208811,
+ 6.41854607357553,
+ 6.681319307917702,
+ 6.9455701730729045,
+ 7.20987457968002,
+ 7.475425480246554,
+ 7.738667122716035,
+ 8.00131956130091,
+ 8.26244637126789,
+ 8.522348348950743,
+ 8.779348920756686,
+ 9.032914882475161,
+ 9.284651592551567,
+ 9.532433301321392,
+ 9.777230760031252,
+ 10.0174789157339,
+ 10.254100706292657,
+ 10.487234177305957,
+ 10.71545840617981,
+ 10.939496800352414,
+ 11.158697017879582,
+ 11.37314606319091,
+ 11.58237151830138,
+ 11.786714430857282,
+ 11.98677813625825,
+ 12.1808353928344,
+ 12.369922844931047,
+ 12.55375159835506,
+ 12.733137363800198,
+ 12.905822998243242,
+ 13.074456274693999,
+ 13.237236622767275,
+ 13.396079440071818,
+ 13.55086631379442,
+ 13.69892325592837,
+ 13.84289554141327,
+ 13.981971275333507,
+ 14.117407405854768,
+ 14.246818740400403,
+ 14.37203389084361,
+ 14.493587620099008,
+ 14.609735497673544,
+ 14.723242173478098,
+ 14.831297504428605,
+ 14.935912532356166,
+ 15.037379352591227,
+ 15.133755168376675,
+ 15.226465373590704,
+ 15.31670960797513,
+ 15.402724885287265,
+ 15.486363892362997,
+ 15.566439939250113,
+ 15.642186731562068,
+ 15.717136638192025,
+ 15.787527775619653,
+ 15.85536956371587,
+ 15.919950135878985,
+ 15.982642593928864,
+ 16.043113366621782,
+ 16.09989366562893,
+ 16.15516174675919,
+ 16.207812578733854,
+ 16.259269128589985,
+ 16.308251288450823,
+ 16.354604739329357,
+ 16.39882478129081,
+ 16.441254777863826,
+ 16.482492572267855,
+ 16.52136186970244,
+ 16.559074281078065,
+ 16.594586374436723,
+ 16.62951333749602,
+ 16.662596876693172,
+ 16.693809896725444,
+ 16.723989679209343,
+ 16.75356267510578,
+ 16.779924132332624,
+ 16.807121709533483,
+ 16.831205414235242,
+ 16.856245388846574,
+ 16.878685435533402,
+ 16.901672493576328,
+ 16.92253181927624,
+ 16.94316073854124,
+ 16.9612022642688,
+ 16.979916247897123,
+ 16.997137492131074,
+ 17.325004601219867
+ ],
+ "vtor": [
+ 100000.0,
+ 99544.32023364124,
+ 98251.15453696062,
+ 96235.68685722632,
+ 93614.68356191639,
+ 90502.18847954353,
+ 87006.32501749854,
+ 83227.06508922808,
+ 79254.813872946,
+ 75169.66123127713,
+ 71041.16042746486,
+ 66928.50919629741,
+ 62881.02482158773,
+ 58938.821939433255,
+ 55133.61820859918,
+ 51489.60808192722,
+ 48024.35830839606,
+ 44749.69035052268,
+ 41672.524623402256,
+ 38795.66945343124,
+ 36118.54407642795,
+ 33637.83003375026,
+ 31348.04917610031,
+ 29242.06933764292,
+ 27311.54077408969,
+ 25547.26782590489,
+ 23939.521110407513,
+ 22478.295982958116,
+ 21153.523137258686,
+ 19955.237120191036,
+ 18873.708284120235,
+ 17899.54334214529,
+ 17023.759270761642,
+ 16237.834851443324,
+ 15533.743681380842,
+ 14903.972031120154,
+ 14341.524495030524,
+ 13839.919977172622,
+ 13393.180184865832,
+ 12995.812467288095,
+ 12642.788537234375,
+ 12329.520349892675,
+ 12051.83418147994,
+ 11805.94375056095,
+ 11588.423053275488,
+ 11396.179437797053,
+ 11226.42732039882,
+ 11076.662842842592,
+ 10944.639685904545,
+ 10828.34618435543,
+ 10725.983832469563,
+ 10635.94722420132,
+ 10556.805436804136,
+ 10487.284839339893,
+ 10426.253286892172,
+ 10372.705646187464,
+ 10325.750587737686,
+ 10284.598572685094,
+ 10248.550958525679,
+ 10216.990146193662,
+ 10189.370691092356,
+ 10165.211302127113,
+ 10144.087655281786,
+ 10125.625951492917,
+ 10109.49715228246,
+ 10095.411830623676,
+ 10083.115578687914,
+ 10072.384918337477,
+ 10063.023664403154,
+ 10054.85969484832,
+ 10047.742085826912,
+ 10041.538573356505,
+ 10036.133306828673,
+ 10031.424862854412,
+ 10027.3244909875,
+ 10023.75456568367,
+ 10020.647221443161,
+ 10017.943150456194,
+ 10015.59054423511,
+ 10013.544162684711,
+ 10011.764515845945,
+ 10010.217145160046,
+ 10008.871992553453,
+ 10007.702846950711,
+ 10006.686858995241,
+ 10005.804115808194,
+ 10005.037268554323,
+ 10004.371206421612,
+ 10003.792771367725,
+ 10003.29050865027,
+ 10002.85444874773,
+ 10002.475916801126,
+ 10002.14736617021,
+ 10001.86223310832,
+ 10001.614809922945,
+ 10001.400134309408,
+ 10001.213892828007,
+ 10001.052336744104,
+ 10000.912208670363,
+ 10000.790678643563,
+ 10000.68528843837,
+ 10000.593903069897,
+ 10000.514668568,
+ 10000.445975221452,
+ 10000.386425591105,
+ 10000.334806679686,
+ 10000.290065723417,
+ 10000.25128913859,
+ 10000.217684215675,
+ 10000.188563205464,
+ 10000.16332948734,
+ 10000.141465549392,
+ 10000.122522544827,
+ 10000.106111219531,
+ 10000.091894031972,
+ 10000.079578309811,
+ 10000.068910307727,
+ 10000.05967004848,
+ 10000.051666844598,
+ 10000.044735411424,
+ 10000.038732493818,
+ 10000.033533939033,
+ 10000.029032157028,
+ 10000.02513391718,
+ 10000.021758437058,
+ 10000.018835724715,
+ 10000.016305140998,
+ 10000.01411415281,
+ 10000.012217252064,
+ 10000.010575018385,
+ 10000.009153306504,
+ 10000.007922541854,
+ 10000.00685710995,
+ 10000.005934827166,
+ 10000.005136482061,
+ 10000.004445437868,
+ 10000.003847288048,
+ 10000.003329557814,
+ 10000.002881445527,
+ 10000.00249359863,
+ 10000.002157919536,
+ 10000.001867397486,
+ 10000.001615962863,
+ 10000.001398361033,
+ 10000.001210043049,
+ 10000.001047070993,
+ 10000.000906036008,
+ 10000.000783987294,
+ 10000.000678370623,
+ 10000.000586975104,
+ 10000.000507887078,
+ 10000.000439450198,
+ 10000.000380230858,
+ 10000.000328988277,
+ 10000.000284648579,
+ 10000.000246282361,
+ 10000.000213085277,
+ 10000.00018436122,
+ 10000.000159507772,
+ 10000.000138003594,
+ 10000.000119397531,
+ 10000.000103299173,
+ 10000.000089370667,
+ 10000.000077319659,
+ 10000.000066893168,
+ 10000.000057872281,
+ 10000.000050067574,
+ 10000.00004331514,
+ 10000.00003747315,
+ 10000.000032418886,
+ 10000.000028046165,
+ 10000.00002426311,
+ 10000.000020990228,
+ 10000.000018158735,
+ 10000.00001570912,
+ 10000.000013589894,
+ 10000.000011756505,
+ 10000.00001017041,
+ 10000.00000879826,
+ 10000.000007611205,
+ 10000.00000658428,
+ 10000.000005695889,
+ 10000.000004927346,
+ 10000.000004262487,
+ 10000.000003687326,
+ 10000.000003189763,
+ 10000.000002759334,
+ 10000.000002386978,
+ 10000.000002064864,
+ 10000.000001786213,
+ 10000.00000154516,
+ 10000.000001336637,
+ 10000.00000115625,
+ 10000.000001000204,
+ 10000.000000865217,
+ 10000.000000748445,
+ 10000.000000647431,
+ 10000.00000056005,
+ 10000.000000484462,
+ 10000.000000419075,
+ 10000.000000362512,
+ 10000.000000313583,
+ 10000.000000271257,
+ 10000.000000234644,
+ 10000.000000202972,
+ 10000.000000175574,
+ 10000.000000151877,
+ 10000.000000131377,
+ 10000.000000113641,
+ 10000.000000098302,
+ 10000.000000085032,
+ 10000.000000073554,
+ 10000.000000063626,
+ 10000.000000055037,
+ 10000.000000047608,
+ 10000.000000041182,
+ 10000.000000035621,
+ 10000.000000030814,
+ 10000.000000026654,
+ 10000.000000023056,
+ 10000.000000019943,
+ 10000.000000017251,
+ 10000.000000014923,
+ 10000.000000012908,
+ 10000.000000011165,
+ 10000.000000009659,
+ 10000.000000008355,
+ 10000.000000007227,
+ 10000.00000000625,
+ 10000.000000005406,
+ 10000.000000004677,
+ 10000.000000004045,
+ 10000.0000000035,
+ 10000.000000003027,
+ 10000.000000002618,
+ 10000.000000002265,
+ 10000.000000001959,
+ 10000.000000001695,
+ 10000.000000001466,
+ 10000.000000001268,
+ 10000.000000001097,
+ 10000.00000000095,
+ 10000.00000000082,
+ 10000.00000000071,
+ 10000.000000000615,
+ 10000.000000000531,
+ 10000.00000000046,
+ 10000.000000000397,
+ 10000.000000000344,
+ 10000.000000000296,
+ 10000.000000000256,
+ 10000.000000000222,
+ 10000.000000000193,
+ 10000.000000000167,
+ 10000.000000000144,
+ 10000.0
+ ],
+ "vpol": [
+ 18462.326927732716,
+ 18514.99979366994,
+ 18565.939231880784,
+ 18615.197379613106,
+ 18662.8251518226,
+ 18708.87224398403,
+ 18753.38713728863,
+ 18796.417106004,
+ 18838.008226787257,
+ 18878.20538975573,
+ 18917.052311132516,
+ 18954.591547296637,
+ 18990.864510079347,
+ 19025.91148315922,
+ 19059.7716394193,
+ 19092.483059139577,
+ 19124.08274890752,
+ 19154.60666113828,
+ 19184.089714104663,
+ 19212.565812384706,
+ 19240.067867642374,
+ 19266.627819663598,
+ 19292.27665757659,
+ 19317.044441191432,
+ 19340.960322399642,
+ 19364.052566579816,
+ 19386.34857396039,
+ 19407.874900895215,
+ 19428.65728101207,
+ 19448.720646198086,
+ 19468.08914739,
+ 19486.78617514046,
+ 19504.834379934928,
+ 19522.2556922367,
+ 19539.07134224024,
+ 19555.301879315663,
+ 19570.96719112952,
+ 19586.08652242914,
+ 19600.678493479918,
+ 19614.761118146518,
+ 19628.351821610984,
+ 19641.467457721887,
+ 19654.124325970388,
+ 19666.33818809011,
+ 19678.124284279074,
+ 19689.497349042842,
+ 19700.47162665909,
+ 19711.060886264648,
+ 19721.278436566783,
+ 19731.137140181316,
+ 19740.649427600623,
+ 19749.827310795343,
+ 19758.68239645382,
+ 19767.225898864108,
+ 19775.4686524434,
+ 19783.421123920307,
+ 19791.093424175622,
+ 19798.49531974744,
+ 19805.63624400677,
+ 19812.52530800986,
+ 19819.171311033715,
+ 19825.582750801284,
+ 19831.76783340299,
+ 19837.73448292125,
+ 19843.49035076469,
+ 19849.042824718887,
+ 19854.399037720275,
+ 19859.565876360022,
+ 19864.549989124593,
+ 19869.357794379575,
+ 19873.99548810352,
+ 19878.469051378208,
+ 19882.78425764191,
+ 19886.946679712015,
+ 19890.961696583312,
+ 19894.83450000816,
+ 19898.570100864654,
+ 19902.173335318803,
+ 19905.64887078662,
+ 19909.00121170188,
+ 19912.234705095303,
+ 19915.353545990587,
+ 19918.361782622906,
+ 19921.263321485007,
+ 19924.061932206263,
+ 19926.76125226966,
+ 19929.36479157172,
+ 19931.875936830187,
+ 19934.297955844206,
+ 19936.634001611572,
+ 19938.887116307546,
+ 19941.060235129582,
+ 19943.156190012254,
+ 19945.17771321644,
+ 19947.12744079687,
+ 19949.00791595186,
+ 19950.821592259108,
+ 19952.570836801166,
+ 19954.25793318425,
+ 19955.885084453774,
+ 19957.454415910102,
+ 19958.967977827684,
+ 19960.427748080827,
+ 19961.835634679162,
+ 19963.193478215824,
+ 19964.503054231183,
+ 19965.76607549503,
+ 19966.984194209857,
+ 19968.159004137942,
+ 19969.292042654735,
+ 19970.384792731096,
+ 19971.438684846682,
+ 19972.455098836952,
+ 19973.435365675872,
+ 19974.380769196654,
+ 19975.29254775252,
+ 19976.1718958196,
+ 19977.019965543906,
+ 19977.83786823432,
+ 19978.6266758034,
+ 19979.38742215782,
+ 19980.121104540183,
+ 19980.828684823875,
+ 19981.511090762506,
+ 19982.169217195635,
+ 19982.80392721215,
+ 19983.41605327286,
+ 19984.006398293674,
+ 19984.575736690727,
+ 19985.124815388765,
+ 19985.654354794107,
+ 19986.165049733347,
+ 19986.657570359053,
+ 19987.132563023555,
+ 19987.590651121973,
+ 19988.03243590553,
+ 19988.458497266216,
+ 19988.869394493737,
+ 19989.265667005842,
+ 19989.647835052798,
+ 19990.01640039704,
+ 19990.371846968832,
+ 19990.714641498744,
+ 19991.045234127785,
+ 19991.36405899601,
+ 19991.67153481026,
+ 19991.968065391884,
+ 19992.254040205054,
+ 19992.52983486641,
+ 19992.795811636643,
+ 19993.05231989471,
+ 19993.299696595244,
+ 19993.538266709777,
+ 19993.768343652326,
+ 19993.9902296899,
+ 19994.2042163385,
+ 19994.410584745023,
+ 19994.60960605568,
+ 19994.801541771343,
+ 19994.986644090288,
+ 19995.165156238767,
+ 19995.33731278991,
+ 19995.503339971237,
+ 19995.66345596134,
+ 19995.817871175987,
+ 19995.96678854407,
+ 19996.110403773815,
+ 19996.248905609486,
+ 19996.38247607898,
+ 19996.511290732687,
+ 19996.6355188738,
+ 19996.75532378048,
+ 19996.870862920143,
+ 19996.98228815611,
+ 19997.089745946923,
+ 19997.1933775386,
+ 19997.29331915003,
+ 19997.389702151813,
+ 19997.482653238705,
+ 19997.572294595982,
+ 19997.65874405985,
+ 19997.74211527218,
+ 19997.822517829743,
+ 19997.90005742811,
+ 19997.974836000485,
+ 19998.046951851553,
+ 19998.11649978661,
+ 19998.183571236077,
+ 19998.248254375594,
+ 19998.31063424184,
+ 19998.370792844253,
+ 19998.42880927274,
+ 19998.4847598016,
+ 19998.538717989708,
+ 19998.590754777182,
+ 19998.64093857857,
+ 19998.68933537273,
+ 19998.736008789543,
+ 19998.78102019351,
+ 19998.824428764387,
+ 19998.866291574945,
+ 19998.906663665974,
+ 19998.945598118597,
+ 19998.983146124054,
+ 19999.019357050955,
+ 19999.054278510157,
+ 19999.087956417356,
+ 19999.120435053414,
+ 19999.151757122556,
+ 19999.181963808518,
+ 19999.21109482865,
+ 19999.239188486128,
+ 19999.26628172031,
+ 19999.292410155274,
+ 19999.317608146655,
+ 19999.34190882679,
+ 19999.36534414829,
+ 19999.387944926013,
+ 19999.409740877607,
+ 19999.430760662537,
+ 19999.451031919776,
+ 19999.470581304155,
+ 19999.489434521372,
+ 19999.5076163618,
+ 19999.525150733072,
+ 19999.54206069153,
+ 19999.558368472495,
+ 19999.57409551955,
+ 19999.58926251268,
+ 19999.603889395497,
+ 19999.61799540144,
+ 19999.63159907907,
+ 19999.644718316464,
+ 19999.657370364694,
+ 19999.669571860562,
+ 19999.681338848437,
+ 19999.69268680136,
+ 19999.703630641383,
+ 19999.7141847592,
+ 19999.72436303305,
+ 19999.73417884697,
+ 19999.743645108418,
+ 19999.752774265195,
+ 19999.76157832185,
+ 19999.770068855447,
+ 19999.778257030794,
+ 19999.78615361512,
+ 19999.793768992236,
+ 19999.801113176174,
+ 19999.808195824375,
+ 19999.815026250366,
+ 19999.82161343603,
+ 19999.827966043387,
+ 19999.834092426012,
+ 19999.84000064,
+ 20000.0
+ ],
+ "vnorm": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "element": "carbon",
+ "charge": 0
+}
\ No newline at end of file
diff --git a/cherab/generomak/plasma/data/core/carbon1.json b/cherab/generomak/plasma/data/core/carbon1.json
new file mode 100644
index 00000000..b2d5c389
--- /dev/null
+++ b/cherab/generomak/plasma/data/core/carbon1.json
@@ -0,0 +1,1294 @@
+{
+ "temperature": [
+ 2800.0,
+ 2795.6140361201715,
+ 2783.083337747409,
+ 2763.3003486616526,
+ 2737.094135213008,
+ 2705.2322750926364,
+ 2668.4232152414806,
+ 2627.3189416606197,
+ 2582.5178419123567,
+ 2534.5676700076638,
+ 2483.96854551181,
+ 2431.1759357517954,
+ 2376.6035832043513,
+ 2320.6263503869714,
+ 2263.5829625419237,
+ 2205.7786346035323,
+ 2147.4875737595085,
+ 2088.955352654985,
+ 2030.4011511730957,
+ 1972.019866937452,
+ 1913.9840963599631,
+ 1856.4459893126868,
+ 1799.5389814222144,
+ 1743.3794086390585,
+ 1688.0680091781107,
+ 1633.691318203845,
+ 1580.3229607811295,
+ 1528.0248486579108,
+ 1476.8482864126447,
+ 1426.8349924056063,
+ 1378.018039834137,
+ 1330.4227230192646,
+ 1284.0673538547676,
+ 1238.963993137122,
+ 1195.1191212721988,
+ 1152.5342526267314,
+ 1111.2064975634503,
+ 1071.1290759712253,
+ 1032.291785877979,
+ 994.6814305162284,
+ 958.2822070001829,
+ 923.0760595703174,
+ 889.0430001669228,
+ 856.1613989086177,
+ 824.4082468755387,
+ 793.759393429837,
+ 764.1897601482588,
+ 735.6735332927431,
+ 708.1843366049751,
+ 681.6953860793737,
+ 656.1796282458071,
+ 631.6098633780208,
+ 607.9588549360606,
+ 585.1994264504128,
+ 563.3045469619041,
+ 542.2474060441687,
+ 522.0014793543342,
+ 502.5405855822321,
+ 483.8389355984452,
+ 465.8711745366052,
+ 448.61241748523827,
+ 432.0382794087496,
+ 416.124899865624,
+ 400.8489630442867,
+ 386.1877135930409,
+ 372.11896867986945,
+ 358.6211266803817,
+ 345.67317285760663,
+ 333.2546823654665,
+ 321.34582087841227,
+ 309.927343122692,
+ 298.9805895598673,
+ 288.4874814503533,
+ 278.4305145037626,
+ 268.79275130356683,
+ 259.5578126759042,
+ 250.7098681561356,
+ 242.23362569190442,
+ 234.11432070782254,
+ 226.33770464446184,
+ 218.89003307292606,
+ 211.75805347586066,
+ 204.92899277624957,
+ 198.39054468665884,
+ 192.13085694367678,
+ 186.13851848507585,
+ 180.40254662065936,
+ 174.91237424177845,
+ 169.65783710907806,
+ 164.62916125309604,
+ 159.8169505178761,
+ 155.21217427370195,
+ 150.80615532139907,
+ 146.59055800733688,
+ 142.55737656528729,
+ 138.69892369858735,
+ 135.00781941365733,
+ 131.47698011372418,
+ 128.09960795968092,
+ 124.86918050324817,
+ 121.77944059606116,
+ 118.82438657692074,
+ 115.99826273821829,
+ 113.29555007145385,
+ 110.71095729082082,
+ 108.23941213297381,
+ 105.87605293038021,
+ 103.6162204549953,
+ 101.45545002847112,
+ 99.38946389462029,
+ 97.41416384945612,
+ 95.52562412379939,
+ 93.72008451315051,
+ 91.99394374930452,
+ 90.34375310799985,
+ 88.7662102467457,
+ 87.25815326688075,
+ 85.81655499383113,
+ 84.43851746950027,
+ 83.12126665071017,
+ 81.86214730760918,
+ 80.65861811600642,
+ 79.5082469376184,
+ 78.408706282292,
+ 77.35776894632689,
+ 76.35330382111951,
+ 75.39327186643368,
+ 74.47572224272074,
+ 73.59878859700572,
+ 72.76068549699494,
+ 71.95970500815942,
+ 71.19421340869229,
+ 70.46264803735373,
+ 69.7635142693571,
+ 69.0953826155724,
+ 68.45688594046604,
+ 67.84671679431725,
+ 67.26362485539421,
+ 66.70641447789761,
+ 66.17394234161189,
+ 65.6651151993376,
+ 65.1788877182984,
+ 64.7142604118468,
+ 64.27027765791827,
+ 63.84602580079542,
+ 63.440631332874815,
+ 63.05325915323381,
+ 62.68311089991544,
+ 62.32942335295714,
+ 61.9914669052981,
+ 61.66854409880293,
+ 61.359988222742814,
+ 61.065161972176995,
+ 60.78345616376737,
+ 60.51428850665944,
+ 60.2571024261477,
+ 60.01136593793548,
+ 59.776570570881596,
+ 59.55223033620793,
+ 59.33788074122536,
+ 59.13307784570519,
+ 58.937397359105915,
+ 58.75043377692946,
+ 58.571799554551646,
+ 58.40112431694312,
+ 58.23805410275451,
+ 58.08225064130303,
+ 57.93339066106313,
+ 57.7911652283102,
+ 57.65527911463285,
+ 57.525450192074885,
+ 57.40140885472106,
+ 57.28289746559213,
+ 57.16966982775895,
+ 57.06149067863122,
+ 56.95813520642253,
+ 56.85938858783372,
+ 56.765045546033065,
+ 56.674909928059456,
+ 56.588794300802036,
+ 56.50651956475268,
+ 56.427914584755875,
+ 56.35281583702141,
+ 56.281067071686564,
+ 56.21251899025332,
+ 56.14702893725086,
+ 56.08446060550164,
+ 56.02468375439783,
+ 55.96757394061782,
+ 55.91301226073971,
+ 55.8608851052287,
+ 55.81108392330204,
+ 55.76350499819346,
+ 55.718049232360165,
+ 55.67462194219673,
+ 55.63313266183696,
+ 55.593494955645,
+ 55.55562623901411,
+ 55.51944760710454,
+ 55.484883671174465,
+ 55.45186240216659,
+ 55.42031498123234,
+ 55.390175656886,
+ 55.361381608497936,
+ 55.333872815845915,
+ 55.307591934457406,
+ 55.282484176486456,
+ 55.258497196881336,
+ 55.23558098460842,
+ 55.21368775870917,
+ 55.19277186897538,
+ 55.17278970103895,
+ 55.153699585681665,
+ 55.13546171217539,
+ 55.11803804547773,
+ 55.101392247108336,
+ 55.08548959954608,
+ 55.070296933989404,
+ 55.05578256132999,
+ 55.04191620619953,
+ 55.028668943950365,
+ 55.01601314044173,
+ 55.003922394507015,
+ 54.99237148298145,
+ 54.98133630817787,
+ 54.970793847702375,
+ 54.96072210650347,
+ 54.951100071057624,
+ 54.941907665596375,
+ 54.93312571028218,
+ 54.9247358812481,
+ 54.91672067241873,
+ 54.90906335903125,
+ 54.90174796278291,
+ 54.8947592185312,
+ 54.888082542479076,
+ 54.881704001777535,
+ 54.87561028548313,
+ 54.869788676811275,
+ 54.86422702662521,
+ 54.858913728107794,
+ 54.85383769256265,
+ 54.84898832629396,
+ 54.8443555085177,
+ 54.83992957025756,
+ 54.83570127418218,
+ 54.83166179534185,
+ 54.82780270276455,
+ 54.824115941872016,
+ 54.82059381768116,
+ 54.81722897875463,
+ 54.81401440186672,
+ 54.81094337735412,
+ 54.80800949511986,
+ 54.80520663126194,
+ 54.7452478101525
+ ],
+ "density": [
+ 0.48421585057396443,
+ 0.4902687240676583,
+ 0.49744711278943604,
+ 0.5051954006896824,
+ 0.5136620119549894,
+ 0.5228114951520789,
+ 0.5326752171258001,
+ 0.5430889205581807,
+ 0.5541504144444251,
+ 0.5659869467934964,
+ 0.5782948447729008,
+ 0.5917437089789345,
+ 0.6056712485911827,
+ 0.620542945043669,
+ 0.6362922713807064,
+ 0.6528879784388633,
+ 0.670509736386118,
+ 0.6891758543862906,
+ 0.7090235821831914,
+ 0.7300618223316414,
+ 0.7525298929070332,
+ 0.7763877953370656,
+ 0.8018826318051548,
+ 0.8292062565837163,
+ 0.8585038018336258,
+ 0.889508177208562,
+ 0.9226832625401263,
+ 0.9579291559694979,
+ 0.9954837795225133,
+ 1.0360065994185788,
+ 1.0798223982450068,
+ 1.1269947674435963,
+ 1.1787338800321392,
+ 1.2350760742733788,
+ 1.2966027474529238,
+ 1.3626536962098275,
+ 1.4343556208152823,
+ 1.5124235977441491,
+ 1.597576238405414,
+ 1.691121912675909,
+ 1.7944189321292177,
+ 1.9080331127816117,
+ 2.0349641993946186,
+ 2.176361663537031,
+ 2.3349380858639535,
+ 2.5118452848013555,
+ 2.707159678115966,
+ 2.9246174853883784,
+ 3.1671420854781687,
+ 3.4413506012389776,
+ 3.751694445122891,
+ 3.2477798067270536,
+ 0.006362863907386773,
+ 0.007372973669191416,
+ 0.009216593289128903,
+ 0.011548156028595503,
+ 0.014242714795831715,
+ 0.01786146488055299,
+ 0.022262162510133958,
+ 0.027939765134883766,
+ 0.03551634957985896,
+ 0.04443958387088995,
+ 0.055958579944039195,
+ 0.07088116012661974,
+ 0.09018659935564127,
+ 0.11496387559603737,
+ 0.14633834787935424,
+ 0.1875802388118898,
+ 0.23936517945868985,
+ 0.30754162306911564,
+ 0.3958068353549918,
+ 0.5112101892350656,
+ 0.6620966618289457,
+ 0.858660078735121,
+ 1.1181241421419907,
+ 1.46073435693994,
+ 1.911282430745415,
+ 2.5029504245674246,
+ 3.2846111449205577,
+ 4.318608003844665,
+ 5.687666141161567,
+ 7.506630045311503,
+ 9.92851137619441,
+ 13.163696880564427,
+ 17.493477080108423,
+ 23.303174917833566,
+ 31.091974173382223,
+ 41.45633739453835,
+ 55.267703371244075,
+ 73.72690488904475,
+ 98.20863422520927,
+ 131.2870853869013,
+ 175.83683138019174,
+ 235.99204766064628,
+ 316.38571854740593,
+ 421.7539328588253,
+ 559.4357994437013,
+ 738.9164751802173,
+ 972.3391869076578,
+ 1275.153777920394,
+ 1666.7711728749346,
+ 2171.6699589645095,
+ 2819.988751814856,
+ 3648.7031646271603,
+ 4702.668366138428,
+ 6035.779233963542,
+ 7686.47757537614,
+ 9663.067856260159,
+ 12007.31337433541,
+ 14768.024487039194,
+ 18001.483822967057,
+ 21772.849505706734,
+ 26157.550424254878,
+ 31242.376433647383,
+ 37126.23247711799,
+ 43920.55849586252,
+ 51749.31820504792,
+ 60748.85541615466,
+ 71036.10519259654,
+ 82505.25321944867,
+ 95172.6035262625,
+ 109100.32854050657,
+ 124351.58313892053,
+ 140991.89397504224,
+ 159090.80831541793,
+ 178723.66872728983,
+ 199973.32015148445,
+ 222931.63069035482,
+ 247704.87774357302,
+ 274402.6314683522,
+ 303149.57485778275,
+ 334081.81511881127,
+ 367346.4298088521,
+ 403095.30458799424,
+ 441271.5467435238,
+ 481872.1263701006,
+ 525005.3743482265,
+ 570775.3503247264,
+ 619280.1323497095,
+ 670610.2296256337,
+ 724847.0330594878,
+ 782061.4947899283,
+ 842312.7805629332,
+ 905647.1583655913,
+ 972096.9884098681,
+ 1041679.8789890977,
+ 1114397.9704522684,
+ 1190237.4178496636,
+ 1269168.0928057458,
+ 1351143.3680309465,
+ 1436100.2152481882,
+ 1523959.3923222842,
+ 1614625.8637893011,
+ 1707989.3899476596,
+ 1803925.2961875116,
+ 1902295.3488111356,
+ 2002948.8264528697,
+ 2105723.6679099784,
+ 2210447.758156687,
+ 2316940.2461408074,
+ 2425012.996869253,
+ 2534471.9531783885,
+ 2645118.713026125,
+ 2756751.8441781844,
+ 2869168.440277809,
+ 2982165.4309753384,
+ 3095540.9198091724,
+ 3209095.535627261,
+ 3322633.485232032,
+ 3435963.746723633,
+ 3548904.406828813,
+ 3661274.607561598,
+ 3772901.237685582,
+ 3883621.082668308,
+ 3993279.51143659,
+ 4101731.027144971,
+ 4208839.542291893,
+ 4314478.668059076,
+ 4418531.841795906,
+ 4520892.427679443,
+ 4621463.716299819,
+ 4720158.78415636,
+ 4816900.409340878,
+ 4911620.80796254,
+ 5004261.422094195,
+ 5094772.583239676,
+ 5183113.162616801,
+ 5269250.234491738,
+ 5353158.645119106,
+ 5434820.618175021,
+ 5514225.314109624,
+ 5591368.407651634,
+ 5666251.643182443,
+ 5738882.3707925305,
+ 5809273.161495088,
+ 5877441.340120579,
+ 5943408.591682677,
+ 6007200.515329759,
+ 6068846.311127089,
+ 6128378.312740362,
+ 6185831.708189282,
+ 6241244.1418844825,
+ 6294655.385905712,
+ 6346107.111966662,
+ 6395642.518902035,
+ 6443306.118805427,
+ 6489143.4314059075,
+ 6533200.829506674,
+ 6575525.270986898,
+ 6616164.092233446,
+ 6655164.89427008,
+ 6692575.279163696,
+ 6728442.694407392,
+ 6762814.329286974,
+ 6795737.335340715,
+ 6827258.228432123,
+ 6857422.965645077,
+ 6886276.833068685,
+ 6913864.435669005,
+ 6940229.566958312,
+ 6965415.187144678,
+ 6989463.413916613,
+ 7012415.368759321,
+ 7034311.272954711,
+ 7055190.338080873,
+ 7075090.793272931,
+ 7094049.833290375,
+ 7112103.614543278,
+ 7129287.29681578,
+ 7145634.973864277,
+ 7161179.732926623,
+ 7175953.608746651,
+ 7189987.629596161,
+ 7203311.823403726,
+ 7215955.222910218,
+ 7227945.884573181,
+ 7239310.885176149,
+ 7250076.380752132,
+ 7260267.580029734,
+ 7269908.81296078,
+ 7279023.497225329,
+ 7287634.200202345,
+ 7295762.6574449,
+ 7303429.782592609,
+ 7310655.664301383,
+ 7317459.684297547,
+ 7323860.396159016,
+ 7329875.705663031,
+ 7335522.739642086,
+ 7340818.009363841,
+ 7345777.309661405,
+ 7350415.843108907,
+ 7354748.154845227,
+ 7358788.250898356,
+ 7362549.51046329,
+ 7180737.62151424
+ ],
+ "vtor": [
+ 100000.0,
+ 99544.32023364124,
+ 98251.15453696062,
+ 96235.68685722632,
+ 93614.68356191639,
+ 90502.18847954353,
+ 87006.32501749854,
+ 83227.06508922808,
+ 79254.813872946,
+ 75169.66123127713,
+ 71041.16042746486,
+ 66928.50919629741,
+ 62881.02482158773,
+ 58938.821939433255,
+ 55133.61820859918,
+ 51489.60808192722,
+ 48024.35830839606,
+ 44749.69035052268,
+ 41672.524623402256,
+ 38795.66945343124,
+ 36118.54407642795,
+ 33637.83003375026,
+ 31348.04917610031,
+ 29242.06933764292,
+ 27311.54077408969,
+ 25547.26782590489,
+ 23939.521110407513,
+ 22478.295982958116,
+ 21153.523137258686,
+ 19955.237120191036,
+ 18873.708284120235,
+ 17899.54334214529,
+ 17023.759270761642,
+ 16237.834851443324,
+ 15533.743681380842,
+ 14903.972031120154,
+ 14341.524495030524,
+ 13839.919977172622,
+ 13393.180184865832,
+ 12995.812467288095,
+ 12642.788537234375,
+ 12329.520349892675,
+ 12051.83418147994,
+ 11805.94375056095,
+ 11588.423053275488,
+ 11396.179437797053,
+ 11226.42732039882,
+ 11076.662842842592,
+ 10944.639685904545,
+ 10828.34618435543,
+ 10725.983832469563,
+ 10635.94722420132,
+ 10556.805436804136,
+ 10487.284839339893,
+ 10426.253286892172,
+ 10372.705646187464,
+ 10325.750587737686,
+ 10284.598572685094,
+ 10248.550958525679,
+ 10216.990146193662,
+ 10189.370691092356,
+ 10165.211302127113,
+ 10144.087655281786,
+ 10125.625951492917,
+ 10109.49715228246,
+ 10095.411830623676,
+ 10083.115578687914,
+ 10072.384918337477,
+ 10063.023664403154,
+ 10054.85969484832,
+ 10047.742085826912,
+ 10041.538573356505,
+ 10036.133306828673,
+ 10031.424862854412,
+ 10027.3244909875,
+ 10023.75456568367,
+ 10020.647221443161,
+ 10017.943150456194,
+ 10015.59054423511,
+ 10013.544162684711,
+ 10011.764515845945,
+ 10010.217145160046,
+ 10008.871992553453,
+ 10007.702846950711,
+ 10006.686858995241,
+ 10005.804115808194,
+ 10005.037268554323,
+ 10004.371206421612,
+ 10003.792771367725,
+ 10003.29050865027,
+ 10002.85444874773,
+ 10002.475916801126,
+ 10002.14736617021,
+ 10001.86223310832,
+ 10001.614809922945,
+ 10001.400134309408,
+ 10001.213892828007,
+ 10001.052336744104,
+ 10000.912208670363,
+ 10000.790678643563,
+ 10000.68528843837,
+ 10000.593903069897,
+ 10000.514668568,
+ 10000.445975221452,
+ 10000.386425591105,
+ 10000.334806679686,
+ 10000.290065723417,
+ 10000.25128913859,
+ 10000.217684215675,
+ 10000.188563205464,
+ 10000.16332948734,
+ 10000.141465549392,
+ 10000.122522544827,
+ 10000.106111219531,
+ 10000.091894031972,
+ 10000.079578309811,
+ 10000.068910307727,
+ 10000.05967004848,
+ 10000.051666844598,
+ 10000.044735411424,
+ 10000.038732493818,
+ 10000.033533939033,
+ 10000.029032157028,
+ 10000.02513391718,
+ 10000.021758437058,
+ 10000.018835724715,
+ 10000.016305140998,
+ 10000.01411415281,
+ 10000.012217252064,
+ 10000.010575018385,
+ 10000.009153306504,
+ 10000.007922541854,
+ 10000.00685710995,
+ 10000.005934827166,
+ 10000.005136482061,
+ 10000.004445437868,
+ 10000.003847288048,
+ 10000.003329557814,
+ 10000.002881445527,
+ 10000.00249359863,
+ 10000.002157919536,
+ 10000.001867397486,
+ 10000.001615962863,
+ 10000.001398361033,
+ 10000.001210043049,
+ 10000.001047070993,
+ 10000.000906036008,
+ 10000.000783987294,
+ 10000.000678370623,
+ 10000.000586975104,
+ 10000.000507887078,
+ 10000.000439450198,
+ 10000.000380230858,
+ 10000.000328988277,
+ 10000.000284648579,
+ 10000.000246282361,
+ 10000.000213085277,
+ 10000.00018436122,
+ 10000.000159507772,
+ 10000.000138003594,
+ 10000.000119397531,
+ 10000.000103299173,
+ 10000.000089370667,
+ 10000.000077319659,
+ 10000.000066893168,
+ 10000.000057872281,
+ 10000.000050067574,
+ 10000.00004331514,
+ 10000.00003747315,
+ 10000.000032418886,
+ 10000.000028046165,
+ 10000.00002426311,
+ 10000.000020990228,
+ 10000.000018158735,
+ 10000.00001570912,
+ 10000.000013589894,
+ 10000.000011756505,
+ 10000.00001017041,
+ 10000.00000879826,
+ 10000.000007611205,
+ 10000.00000658428,
+ 10000.000005695889,
+ 10000.000004927346,
+ 10000.000004262487,
+ 10000.000003687326,
+ 10000.000003189763,
+ 10000.000002759334,
+ 10000.000002386978,
+ 10000.000002064864,
+ 10000.000001786213,
+ 10000.00000154516,
+ 10000.000001336637,
+ 10000.00000115625,
+ 10000.000001000204,
+ 10000.000000865217,
+ 10000.000000748445,
+ 10000.000000647431,
+ 10000.00000056005,
+ 10000.000000484462,
+ 10000.000000419075,
+ 10000.000000362512,
+ 10000.000000313583,
+ 10000.000000271257,
+ 10000.000000234644,
+ 10000.000000202972,
+ 10000.000000175574,
+ 10000.000000151877,
+ 10000.000000131377,
+ 10000.000000113641,
+ 10000.000000098302,
+ 10000.000000085032,
+ 10000.000000073554,
+ 10000.000000063626,
+ 10000.000000055037,
+ 10000.000000047608,
+ 10000.000000041182,
+ 10000.000000035621,
+ 10000.000000030814,
+ 10000.000000026654,
+ 10000.000000023056,
+ 10000.000000019943,
+ 10000.000000017251,
+ 10000.000000014923,
+ 10000.000000012908,
+ 10000.000000011165,
+ 10000.000000009659,
+ 10000.000000008355,
+ 10000.000000007227,
+ 10000.00000000625,
+ 10000.000000005406,
+ 10000.000000004677,
+ 10000.000000004045,
+ 10000.0000000035,
+ 10000.000000003027,
+ 10000.000000002618,
+ 10000.000000002265,
+ 10000.000000001959,
+ 10000.000000001695,
+ 10000.000000001466,
+ 10000.000000001268,
+ 10000.000000001097,
+ 10000.00000000095,
+ 10000.00000000082,
+ 10000.00000000071,
+ 10000.000000000615,
+ 10000.000000000531,
+ 10000.00000000046,
+ 10000.000000000397,
+ 10000.000000000344,
+ 10000.000000000296,
+ 10000.000000000256,
+ 10000.000000000222,
+ 10000.000000000193,
+ 10000.000000000167,
+ 10000.000000000144,
+ 10000.0
+ ],
+ "vpol": [
+ 18462.326927732716,
+ 18514.99979366994,
+ 18565.939231880784,
+ 18615.197379613106,
+ 18662.8251518226,
+ 18708.87224398403,
+ 18753.38713728863,
+ 18796.417106004,
+ 18838.008226787257,
+ 18878.20538975573,
+ 18917.052311132516,
+ 18954.591547296637,
+ 18990.864510079347,
+ 19025.91148315922,
+ 19059.7716394193,
+ 19092.483059139577,
+ 19124.08274890752,
+ 19154.60666113828,
+ 19184.089714104663,
+ 19212.565812384706,
+ 19240.067867642374,
+ 19266.627819663598,
+ 19292.27665757659,
+ 19317.044441191432,
+ 19340.960322399642,
+ 19364.052566579816,
+ 19386.34857396039,
+ 19407.874900895215,
+ 19428.65728101207,
+ 19448.720646198086,
+ 19468.08914739,
+ 19486.78617514046,
+ 19504.834379934928,
+ 19522.2556922367,
+ 19539.07134224024,
+ 19555.301879315663,
+ 19570.96719112952,
+ 19586.08652242914,
+ 19600.678493479918,
+ 19614.761118146518,
+ 19628.351821610984,
+ 19641.467457721887,
+ 19654.124325970388,
+ 19666.33818809011,
+ 19678.124284279074,
+ 19689.497349042842,
+ 19700.47162665909,
+ 19711.060886264648,
+ 19721.278436566783,
+ 19731.137140181316,
+ 19740.649427600623,
+ 19749.827310795343,
+ 19758.68239645382,
+ 19767.225898864108,
+ 19775.4686524434,
+ 19783.421123920307,
+ 19791.093424175622,
+ 19798.49531974744,
+ 19805.63624400677,
+ 19812.52530800986,
+ 19819.171311033715,
+ 19825.582750801284,
+ 19831.76783340299,
+ 19837.73448292125,
+ 19843.49035076469,
+ 19849.042824718887,
+ 19854.399037720275,
+ 19859.565876360022,
+ 19864.549989124593,
+ 19869.357794379575,
+ 19873.99548810352,
+ 19878.469051378208,
+ 19882.78425764191,
+ 19886.946679712015,
+ 19890.961696583312,
+ 19894.83450000816,
+ 19898.570100864654,
+ 19902.173335318803,
+ 19905.64887078662,
+ 19909.00121170188,
+ 19912.234705095303,
+ 19915.353545990587,
+ 19918.361782622906,
+ 19921.263321485007,
+ 19924.061932206263,
+ 19926.76125226966,
+ 19929.36479157172,
+ 19931.875936830187,
+ 19934.297955844206,
+ 19936.634001611572,
+ 19938.887116307546,
+ 19941.060235129582,
+ 19943.156190012254,
+ 19945.17771321644,
+ 19947.12744079687,
+ 19949.00791595186,
+ 19950.821592259108,
+ 19952.570836801166,
+ 19954.25793318425,
+ 19955.885084453774,
+ 19957.454415910102,
+ 19958.967977827684,
+ 19960.427748080827,
+ 19961.835634679162,
+ 19963.193478215824,
+ 19964.503054231183,
+ 19965.76607549503,
+ 19966.984194209857,
+ 19968.159004137942,
+ 19969.292042654735,
+ 19970.384792731096,
+ 19971.438684846682,
+ 19972.455098836952,
+ 19973.435365675872,
+ 19974.380769196654,
+ 19975.29254775252,
+ 19976.1718958196,
+ 19977.019965543906,
+ 19977.83786823432,
+ 19978.6266758034,
+ 19979.38742215782,
+ 19980.121104540183,
+ 19980.828684823875,
+ 19981.511090762506,
+ 19982.169217195635,
+ 19982.80392721215,
+ 19983.41605327286,
+ 19984.006398293674,
+ 19984.575736690727,
+ 19985.124815388765,
+ 19985.654354794107,
+ 19986.165049733347,
+ 19986.657570359053,
+ 19987.132563023555,
+ 19987.590651121973,
+ 19988.03243590553,
+ 19988.458497266216,
+ 19988.869394493737,
+ 19989.265667005842,
+ 19989.647835052798,
+ 19990.01640039704,
+ 19990.371846968832,
+ 19990.714641498744,
+ 19991.045234127785,
+ 19991.36405899601,
+ 19991.67153481026,
+ 19991.968065391884,
+ 19992.254040205054,
+ 19992.52983486641,
+ 19992.795811636643,
+ 19993.05231989471,
+ 19993.299696595244,
+ 19993.538266709777,
+ 19993.768343652326,
+ 19993.9902296899,
+ 19994.2042163385,
+ 19994.410584745023,
+ 19994.60960605568,
+ 19994.801541771343,
+ 19994.986644090288,
+ 19995.165156238767,
+ 19995.33731278991,
+ 19995.503339971237,
+ 19995.66345596134,
+ 19995.817871175987,
+ 19995.96678854407,
+ 19996.110403773815,
+ 19996.248905609486,
+ 19996.38247607898,
+ 19996.511290732687,
+ 19996.6355188738,
+ 19996.75532378048,
+ 19996.870862920143,
+ 19996.98228815611,
+ 19997.089745946923,
+ 19997.1933775386,
+ 19997.29331915003,
+ 19997.389702151813,
+ 19997.482653238705,
+ 19997.572294595982,
+ 19997.65874405985,
+ 19997.74211527218,
+ 19997.822517829743,
+ 19997.90005742811,
+ 19997.974836000485,
+ 19998.046951851553,
+ 19998.11649978661,
+ 19998.183571236077,
+ 19998.248254375594,
+ 19998.31063424184,
+ 19998.370792844253,
+ 19998.42880927274,
+ 19998.4847598016,
+ 19998.538717989708,
+ 19998.590754777182,
+ 19998.64093857857,
+ 19998.68933537273,
+ 19998.736008789543,
+ 19998.78102019351,
+ 19998.824428764387,
+ 19998.866291574945,
+ 19998.906663665974,
+ 19998.945598118597,
+ 19998.983146124054,
+ 19999.019357050955,
+ 19999.054278510157,
+ 19999.087956417356,
+ 19999.120435053414,
+ 19999.151757122556,
+ 19999.181963808518,
+ 19999.21109482865,
+ 19999.239188486128,
+ 19999.26628172031,
+ 19999.292410155274,
+ 19999.317608146655,
+ 19999.34190882679,
+ 19999.36534414829,
+ 19999.387944926013,
+ 19999.409740877607,
+ 19999.430760662537,
+ 19999.451031919776,
+ 19999.470581304155,
+ 19999.489434521372,
+ 19999.5076163618,
+ 19999.525150733072,
+ 19999.54206069153,
+ 19999.558368472495,
+ 19999.57409551955,
+ 19999.58926251268,
+ 19999.603889395497,
+ 19999.61799540144,
+ 19999.63159907907,
+ 19999.644718316464,
+ 19999.657370364694,
+ 19999.669571860562,
+ 19999.681338848437,
+ 19999.69268680136,
+ 19999.703630641383,
+ 19999.7141847592,
+ 19999.72436303305,
+ 19999.73417884697,
+ 19999.743645108418,
+ 19999.752774265195,
+ 19999.76157832185,
+ 19999.770068855447,
+ 19999.778257030794,
+ 19999.78615361512,
+ 19999.793768992236,
+ 19999.801113176174,
+ 19999.808195824375,
+ 19999.815026250366,
+ 19999.82161343603,
+ 19999.827966043387,
+ 19999.834092426012,
+ 19999.84000064,
+ 20000.0
+ ],
+ "vnorm": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "element": "carbon",
+ "charge": 1
+}
\ No newline at end of file
diff --git a/cherab/generomak/plasma/data/core/carbon2.json b/cherab/generomak/plasma/data/core/carbon2.json
new file mode 100644
index 00000000..c7f6d89a
--- /dev/null
+++ b/cherab/generomak/plasma/data/core/carbon2.json
@@ -0,0 +1,1294 @@
+{
+ "temperature": [
+ 2800.0,
+ 2795.6140361201715,
+ 2783.083337747409,
+ 2763.3003486616526,
+ 2737.094135213008,
+ 2705.2322750926364,
+ 2668.4232152414806,
+ 2627.3189416606197,
+ 2582.5178419123567,
+ 2534.5676700076638,
+ 2483.96854551181,
+ 2431.1759357517954,
+ 2376.6035832043513,
+ 2320.6263503869714,
+ 2263.5829625419237,
+ 2205.7786346035323,
+ 2147.4875737595085,
+ 2088.955352654985,
+ 2030.4011511730957,
+ 1972.019866937452,
+ 1913.9840963599631,
+ 1856.4459893126868,
+ 1799.5389814222144,
+ 1743.3794086390585,
+ 1688.0680091781107,
+ 1633.691318203845,
+ 1580.3229607811295,
+ 1528.0248486579108,
+ 1476.8482864126447,
+ 1426.8349924056063,
+ 1378.018039834137,
+ 1330.4227230192646,
+ 1284.0673538547676,
+ 1238.963993137122,
+ 1195.1191212721988,
+ 1152.5342526267314,
+ 1111.2064975634503,
+ 1071.1290759712253,
+ 1032.291785877979,
+ 994.6814305162284,
+ 958.2822070001829,
+ 923.0760595703174,
+ 889.0430001669228,
+ 856.1613989086177,
+ 824.4082468755387,
+ 793.759393429837,
+ 764.1897601482588,
+ 735.6735332927431,
+ 708.1843366049751,
+ 681.6953860793737,
+ 656.1796282458071,
+ 631.6098633780208,
+ 607.9588549360606,
+ 585.1994264504128,
+ 563.3045469619041,
+ 542.2474060441687,
+ 522.0014793543342,
+ 502.5405855822321,
+ 483.8389355984452,
+ 465.8711745366052,
+ 448.61241748523827,
+ 432.0382794087496,
+ 416.124899865624,
+ 400.8489630442867,
+ 386.1877135930409,
+ 372.11896867986945,
+ 358.6211266803817,
+ 345.67317285760663,
+ 333.2546823654665,
+ 321.34582087841227,
+ 309.927343122692,
+ 298.9805895598673,
+ 288.4874814503533,
+ 278.4305145037626,
+ 268.79275130356683,
+ 259.5578126759042,
+ 250.7098681561356,
+ 242.23362569190442,
+ 234.11432070782254,
+ 226.33770464446184,
+ 218.89003307292606,
+ 211.75805347586066,
+ 204.92899277624957,
+ 198.39054468665884,
+ 192.13085694367678,
+ 186.13851848507585,
+ 180.40254662065936,
+ 174.91237424177845,
+ 169.65783710907806,
+ 164.62916125309604,
+ 159.8169505178761,
+ 155.21217427370195,
+ 150.80615532139907,
+ 146.59055800733688,
+ 142.55737656528729,
+ 138.69892369858735,
+ 135.00781941365733,
+ 131.47698011372418,
+ 128.09960795968092,
+ 124.86918050324817,
+ 121.77944059606116,
+ 118.82438657692074,
+ 115.99826273821829,
+ 113.29555007145385,
+ 110.71095729082082,
+ 108.23941213297381,
+ 105.87605293038021,
+ 103.6162204549953,
+ 101.45545002847112,
+ 99.38946389462029,
+ 97.41416384945612,
+ 95.52562412379939,
+ 93.72008451315051,
+ 91.99394374930452,
+ 90.34375310799985,
+ 88.7662102467457,
+ 87.25815326688075,
+ 85.81655499383113,
+ 84.43851746950027,
+ 83.12126665071017,
+ 81.86214730760918,
+ 80.65861811600642,
+ 79.5082469376184,
+ 78.408706282292,
+ 77.35776894632689,
+ 76.35330382111951,
+ 75.39327186643368,
+ 74.47572224272074,
+ 73.59878859700572,
+ 72.76068549699494,
+ 71.95970500815942,
+ 71.19421340869229,
+ 70.46264803735373,
+ 69.7635142693571,
+ 69.0953826155724,
+ 68.45688594046604,
+ 67.84671679431725,
+ 67.26362485539421,
+ 66.70641447789761,
+ 66.17394234161189,
+ 65.6651151993376,
+ 65.1788877182984,
+ 64.7142604118468,
+ 64.27027765791827,
+ 63.84602580079542,
+ 63.440631332874815,
+ 63.05325915323381,
+ 62.68311089991544,
+ 62.32942335295714,
+ 61.9914669052981,
+ 61.66854409880293,
+ 61.359988222742814,
+ 61.065161972176995,
+ 60.78345616376737,
+ 60.51428850665944,
+ 60.2571024261477,
+ 60.01136593793548,
+ 59.776570570881596,
+ 59.55223033620793,
+ 59.33788074122536,
+ 59.13307784570519,
+ 58.937397359105915,
+ 58.75043377692946,
+ 58.571799554551646,
+ 58.40112431694312,
+ 58.23805410275451,
+ 58.08225064130303,
+ 57.93339066106313,
+ 57.7911652283102,
+ 57.65527911463285,
+ 57.525450192074885,
+ 57.40140885472106,
+ 57.28289746559213,
+ 57.16966982775895,
+ 57.06149067863122,
+ 56.95813520642253,
+ 56.85938858783372,
+ 56.765045546033065,
+ 56.674909928059456,
+ 56.588794300802036,
+ 56.50651956475268,
+ 56.427914584755875,
+ 56.35281583702141,
+ 56.281067071686564,
+ 56.21251899025332,
+ 56.14702893725086,
+ 56.08446060550164,
+ 56.02468375439783,
+ 55.96757394061782,
+ 55.91301226073971,
+ 55.8608851052287,
+ 55.81108392330204,
+ 55.76350499819346,
+ 55.718049232360165,
+ 55.67462194219673,
+ 55.63313266183696,
+ 55.593494955645,
+ 55.55562623901411,
+ 55.51944760710454,
+ 55.484883671174465,
+ 55.45186240216659,
+ 55.42031498123234,
+ 55.390175656886,
+ 55.361381608497936,
+ 55.333872815845915,
+ 55.307591934457406,
+ 55.282484176486456,
+ 55.258497196881336,
+ 55.23558098460842,
+ 55.21368775870917,
+ 55.19277186897538,
+ 55.17278970103895,
+ 55.153699585681665,
+ 55.13546171217539,
+ 55.11803804547773,
+ 55.101392247108336,
+ 55.08548959954608,
+ 55.070296933989404,
+ 55.05578256132999,
+ 55.04191620619953,
+ 55.028668943950365,
+ 55.01601314044173,
+ 55.003922394507015,
+ 54.99237148298145,
+ 54.98133630817787,
+ 54.970793847702375,
+ 54.96072210650347,
+ 54.951100071057624,
+ 54.941907665596375,
+ 54.93312571028218,
+ 54.9247358812481,
+ 54.91672067241873,
+ 54.90906335903125,
+ 54.90174796278291,
+ 54.8947592185312,
+ 54.888082542479076,
+ 54.881704001777535,
+ 54.87561028548313,
+ 54.869788676811275,
+ 54.86422702662521,
+ 54.858913728107794,
+ 54.85383769256265,
+ 54.84898832629396,
+ 54.8443555085177,
+ 54.83992957025756,
+ 54.83570127418218,
+ 54.83166179534185,
+ 54.82780270276455,
+ 54.824115941872016,
+ 54.82059381768116,
+ 54.81722897875463,
+ 54.81401440186672,
+ 54.81094337735412,
+ 54.80800949511986,
+ 54.80520663126194,
+ 54.7452478101525
+ ],
+ "density": [
+ 51.7269475194356,
+ 51.746952820624216,
+ 52.12388596214026,
+ 52.940163304633074,
+ 54.24294247848471,
+ 56.07509778838055,
+ 58.48625229633952,
+ 61.5368349714206,
+ 65.3030344598767,
+ 69.8785578386221,
+ 75.37529754084595,
+ 81.93078413627545,
+ 89.70164187223259,
+ 98.87428659903192,
+ 109.65942092421292,
+ 122.2933234051085,
+ 137.035367139739,
+ 154.16006793143808,
+ 173.94684809895617,
+ 196.66154529962796,
+ 222.53238297052988,
+ 251.7134046195229,
+ 284.2420121677726,
+ 319.983444861121,
+ 358.5598123137554,
+ 398.9683223412675,
+ 440.76433555850025,
+ 484.2490374594113,
+ 530.1044415099693,
+ 579.4915040302302,
+ 634.1713927433501,
+ 696.6820796978036,
+ 770.6142544227597,
+ 860.9672258522206,
+ 970.0620403589148,
+ 1099.2314423795724,
+ 1252.1185630618302,
+ 1432.9887166910512,
+ 1646.7948934705498,
+ 1899.2398766520157,
+ 2196.8166107464817,
+ 2546.8186480837194,
+ 2957.3244606006606,
+ 3437.1830720402863,
+ 3995.651317855098,
+ 4645.819288446255,
+ 5408.159661965817,
+ 6304.394233890673,
+ 7360.988631169922,
+ 8610.408235852314,
+ 10092.612861174073,
+ 11853.166711872651,
+ 13944.655327903243,
+ 16470.555060218794,
+ 19507.094824911295,
+ 23149.859879749787,
+ 27528.59209934883,
+ 32805.44146433598,
+ 39181.431974834195,
+ 46906.5301364389,
+ 56292.49024857901,
+ 67729.29859868562,
+ 81704.69552439438,
+ 98758.342767045,
+ 119563.79546648111,
+ 145008.98972599223,
+ 176209.22723183295,
+ 214569.82314126665,
+ 261867.1097143878,
+ 320353.5889126574,
+ 392894.6330259606,
+ 483146.86838287814,
+ 595791.405155585,
+ 736839.602081546,
+ 914034.8394921427,
+ 1137314.4676054649,
+ 1417795.5431438887,
+ 1770046.1195692741,
+ 2213501.0254945313,
+ 2773182.8952475805,
+ 3481388.8206957136,
+ 4379900.14495483,
+ 5522876.267226655,
+ 6980639.120267879,
+ 8844609.797864616,
+ 11234098.954064578,
+ 14292249.250883874,
+ 18171268.57400767,
+ 23102344.070654884,
+ 29391183.874651648,
+ 37439200.11924598,
+ 47773938.07168198,
+ 61088401.78943633,
+ 78290898.38971062,
+ 100252654.95122445,
+ 127678619.24781525,
+ 161848156.43389606,
+ 204348916.72694722,
+ 257122494.6832895,
+ 322522738.08793396,
+ 403373666.46606535,
+ 503023672.34567523,
+ 625393056.5647471,
+ 775013474.5069699,
+ 957060449.3713105,
+ 1177383070.8421464,
+ 1437802639.9565027,
+ 1734246225.369133,
+ 2068654420.0998182,
+ 2443569577.2558446,
+ 2862029131.1002626,
+ 3327664301.685319,
+ 3844746919.3145304,
+ 4418179733.538788,
+ 5053433114.860162,
+ 5756438161.127043,
+ 6533452755.5666065,
+ 7390922881.304381,
+ 8331837423.650323,
+ 9334354678.472628,
+ 10392166684.043266,
+ 11504279057.327274,
+ 12669790141.968946,
+ 13888035317.62539,
+ 15158729343.112686,
+ 16482091274.303825,
+ 17858939920.92599,
+ 19290752420.740105,
+ 20779851078.546913,
+ 22328898303.12378,
+ 23941318873.556976,
+ 25621068937.484055,
+ 27372541721.972637,
+ 29200132814.888065,
+ 31095452170.414516,
+ 33054347498.016705,
+ 35079589851.19578,
+ 37173581351.618835,
+ 39338307423.93913,
+ 41575301929.46964,
+ 43885622896.80891,
+ 46269837046.91366,
+ 48728011738.553474,
+ 51259713312.86814,
+ 53864011077.12315,
+ 56539486357.443695,
+ 59284246173.27229,
+ 62095941159.639656,
+ 64971787396.43695,
+ 67908591808.401474,
+ 70902780790.1204,
+ 73950431683.65508,
+ 77047306712.3454,
+ 80188888946.12115,
+ 83370419851.9303,
+ 86586937966.57417,
+ 89833318223.03227,
+ 93104311461.33716,
+ 96394583667.15906,
+ 99698754499.39764,
+ 103011434697.43271,
+ 106327261990.32256,
+ 109640935175.03737,
+ 112947246068.6951,
+ 116241109095.60986,
+ 119517588310.54092,
+ 122771921715.4813,
+ 125999542772.99667,
+ 129196099063.11314,
+ 132357468080.74841,
+ 135479838062.1428,
+ 138559536495.15198,
+ 141593161723.4288,
+ 144577614224.11197,
+ 147510062820.63623,
+ 150387945085.9323,
+ 153208965707.6481,
+ 155971093006.19897,
+ 158672553796.7852,
+ 161311826790.89548,
+ 163887634728.62924,
+ 166398935429.4681,
+ 168844911944.07657,
+ 171224961977.36823,
+ 173538686747.2005,
+ 175785879428.2105,
+ 177966513320.9635,
+ 180080729873.50775,
+ 182128826668.6315,
+ 184111245479.87717,
+ 186028560485.09735,
+ 187881466715.82117,
+ 189670768808.52518,
+ 191397370113.5591,
+ 193062262208.28482,
+ 194666514849.56927,
+ 196211266395.00525,
+ 197697714711.99057,
+ 199127108590.06726,
+ 200500739660.8907,
+ 201819934831.14236,
+ 203086049222.54807,
+ 204300459614.14108,
+ 205464558376.57272,
+ 206579747883.16934,
+ 207647435385.08353,
+ 208669028330.83698,
+ 209645930113.7524,
+ 210579536224.9345,
+ 211471230792.85892,
+ 212322383488.85797,
+ 213134346775.05908,
+ 213908449029.64093,
+ 214645996841.59247,
+ 215348286616.73877,
+ 216016580696.22003,
+ 216652114874.8826,
+ 217256097283.5322,
+ 217829707477.1932,
+ 218374095710.14105,
+ 218890382383.57236,
+ 219379657649.66318,
+ 219842981155.79706,
+ 220281381919.172,
+ 220695858314.53354,
+ 221087378166.2643,
+ 221456878931.67258,
+ 221805267966.18643,
+ 222133422860.92596,
+ 222442191842.04816,
+ 222732394226.20602,
+ 223004820922.12497,
+ 223260234973.31854,
+ 223499372134.43323,
+ 223722941475.72876,
+ 223931626010.58966,
+ 224126083341.021,
+ 224306946317.5971,
+ 224474823708.58456,
+ 224630300876.42337,
+ 224773940456.65158,
+ 224906283038.34857,
+ 225027847842.1965,
+ 225139133394.53152,
+ 225240618195.1795,
+ 225332761378.8069,
+ 225416003364.91315,
+ 225490766500.28265,
+ 225557455686.99042,
+ 225616459000.8862,
+ 225668148294.455,
+ 225712879788.01535,
+ 225750994644.923,
+ 225782819533.8887,
+ 225808667174.40283,
+ 214533479339.8047
+ ],
+ "vtor": [
+ 100000.0,
+ 99544.32023364124,
+ 98251.15453696062,
+ 96235.68685722632,
+ 93614.68356191639,
+ 90502.18847954353,
+ 87006.32501749854,
+ 83227.06508922808,
+ 79254.813872946,
+ 75169.66123127713,
+ 71041.16042746486,
+ 66928.50919629741,
+ 62881.02482158773,
+ 58938.821939433255,
+ 55133.61820859918,
+ 51489.60808192722,
+ 48024.35830839606,
+ 44749.69035052268,
+ 41672.524623402256,
+ 38795.66945343124,
+ 36118.54407642795,
+ 33637.83003375026,
+ 31348.04917610031,
+ 29242.06933764292,
+ 27311.54077408969,
+ 25547.26782590489,
+ 23939.521110407513,
+ 22478.295982958116,
+ 21153.523137258686,
+ 19955.237120191036,
+ 18873.708284120235,
+ 17899.54334214529,
+ 17023.759270761642,
+ 16237.834851443324,
+ 15533.743681380842,
+ 14903.972031120154,
+ 14341.524495030524,
+ 13839.919977172622,
+ 13393.180184865832,
+ 12995.812467288095,
+ 12642.788537234375,
+ 12329.520349892675,
+ 12051.83418147994,
+ 11805.94375056095,
+ 11588.423053275488,
+ 11396.179437797053,
+ 11226.42732039882,
+ 11076.662842842592,
+ 10944.639685904545,
+ 10828.34618435543,
+ 10725.983832469563,
+ 10635.94722420132,
+ 10556.805436804136,
+ 10487.284839339893,
+ 10426.253286892172,
+ 10372.705646187464,
+ 10325.750587737686,
+ 10284.598572685094,
+ 10248.550958525679,
+ 10216.990146193662,
+ 10189.370691092356,
+ 10165.211302127113,
+ 10144.087655281786,
+ 10125.625951492917,
+ 10109.49715228246,
+ 10095.411830623676,
+ 10083.115578687914,
+ 10072.384918337477,
+ 10063.023664403154,
+ 10054.85969484832,
+ 10047.742085826912,
+ 10041.538573356505,
+ 10036.133306828673,
+ 10031.424862854412,
+ 10027.3244909875,
+ 10023.75456568367,
+ 10020.647221443161,
+ 10017.943150456194,
+ 10015.59054423511,
+ 10013.544162684711,
+ 10011.764515845945,
+ 10010.217145160046,
+ 10008.871992553453,
+ 10007.702846950711,
+ 10006.686858995241,
+ 10005.804115808194,
+ 10005.037268554323,
+ 10004.371206421612,
+ 10003.792771367725,
+ 10003.29050865027,
+ 10002.85444874773,
+ 10002.475916801126,
+ 10002.14736617021,
+ 10001.86223310832,
+ 10001.614809922945,
+ 10001.400134309408,
+ 10001.213892828007,
+ 10001.052336744104,
+ 10000.912208670363,
+ 10000.790678643563,
+ 10000.68528843837,
+ 10000.593903069897,
+ 10000.514668568,
+ 10000.445975221452,
+ 10000.386425591105,
+ 10000.334806679686,
+ 10000.290065723417,
+ 10000.25128913859,
+ 10000.217684215675,
+ 10000.188563205464,
+ 10000.16332948734,
+ 10000.141465549392,
+ 10000.122522544827,
+ 10000.106111219531,
+ 10000.091894031972,
+ 10000.079578309811,
+ 10000.068910307727,
+ 10000.05967004848,
+ 10000.051666844598,
+ 10000.044735411424,
+ 10000.038732493818,
+ 10000.033533939033,
+ 10000.029032157028,
+ 10000.02513391718,
+ 10000.021758437058,
+ 10000.018835724715,
+ 10000.016305140998,
+ 10000.01411415281,
+ 10000.012217252064,
+ 10000.010575018385,
+ 10000.009153306504,
+ 10000.007922541854,
+ 10000.00685710995,
+ 10000.005934827166,
+ 10000.005136482061,
+ 10000.004445437868,
+ 10000.003847288048,
+ 10000.003329557814,
+ 10000.002881445527,
+ 10000.00249359863,
+ 10000.002157919536,
+ 10000.001867397486,
+ 10000.001615962863,
+ 10000.001398361033,
+ 10000.001210043049,
+ 10000.001047070993,
+ 10000.000906036008,
+ 10000.000783987294,
+ 10000.000678370623,
+ 10000.000586975104,
+ 10000.000507887078,
+ 10000.000439450198,
+ 10000.000380230858,
+ 10000.000328988277,
+ 10000.000284648579,
+ 10000.000246282361,
+ 10000.000213085277,
+ 10000.00018436122,
+ 10000.000159507772,
+ 10000.000138003594,
+ 10000.000119397531,
+ 10000.000103299173,
+ 10000.000089370667,
+ 10000.000077319659,
+ 10000.000066893168,
+ 10000.000057872281,
+ 10000.000050067574,
+ 10000.00004331514,
+ 10000.00003747315,
+ 10000.000032418886,
+ 10000.000028046165,
+ 10000.00002426311,
+ 10000.000020990228,
+ 10000.000018158735,
+ 10000.00001570912,
+ 10000.000013589894,
+ 10000.000011756505,
+ 10000.00001017041,
+ 10000.00000879826,
+ 10000.000007611205,
+ 10000.00000658428,
+ 10000.000005695889,
+ 10000.000004927346,
+ 10000.000004262487,
+ 10000.000003687326,
+ 10000.000003189763,
+ 10000.000002759334,
+ 10000.000002386978,
+ 10000.000002064864,
+ 10000.000001786213,
+ 10000.00000154516,
+ 10000.000001336637,
+ 10000.00000115625,
+ 10000.000001000204,
+ 10000.000000865217,
+ 10000.000000748445,
+ 10000.000000647431,
+ 10000.00000056005,
+ 10000.000000484462,
+ 10000.000000419075,
+ 10000.000000362512,
+ 10000.000000313583,
+ 10000.000000271257,
+ 10000.000000234644,
+ 10000.000000202972,
+ 10000.000000175574,
+ 10000.000000151877,
+ 10000.000000131377,
+ 10000.000000113641,
+ 10000.000000098302,
+ 10000.000000085032,
+ 10000.000000073554,
+ 10000.000000063626,
+ 10000.000000055037,
+ 10000.000000047608,
+ 10000.000000041182,
+ 10000.000000035621,
+ 10000.000000030814,
+ 10000.000000026654,
+ 10000.000000023056,
+ 10000.000000019943,
+ 10000.000000017251,
+ 10000.000000014923,
+ 10000.000000012908,
+ 10000.000000011165,
+ 10000.000000009659,
+ 10000.000000008355,
+ 10000.000000007227,
+ 10000.00000000625,
+ 10000.000000005406,
+ 10000.000000004677,
+ 10000.000000004045,
+ 10000.0000000035,
+ 10000.000000003027,
+ 10000.000000002618,
+ 10000.000000002265,
+ 10000.000000001959,
+ 10000.000000001695,
+ 10000.000000001466,
+ 10000.000000001268,
+ 10000.000000001097,
+ 10000.00000000095,
+ 10000.00000000082,
+ 10000.00000000071,
+ 10000.000000000615,
+ 10000.000000000531,
+ 10000.00000000046,
+ 10000.000000000397,
+ 10000.000000000344,
+ 10000.000000000296,
+ 10000.000000000256,
+ 10000.000000000222,
+ 10000.000000000193,
+ 10000.000000000167,
+ 10000.000000000144,
+ 10000.0
+ ],
+ "vpol": [
+ 18462.326927732716,
+ 18514.99979366994,
+ 18565.939231880784,
+ 18615.197379613106,
+ 18662.8251518226,
+ 18708.87224398403,
+ 18753.38713728863,
+ 18796.417106004,
+ 18838.008226787257,
+ 18878.20538975573,
+ 18917.052311132516,
+ 18954.591547296637,
+ 18990.864510079347,
+ 19025.91148315922,
+ 19059.7716394193,
+ 19092.483059139577,
+ 19124.08274890752,
+ 19154.60666113828,
+ 19184.089714104663,
+ 19212.565812384706,
+ 19240.067867642374,
+ 19266.627819663598,
+ 19292.27665757659,
+ 19317.044441191432,
+ 19340.960322399642,
+ 19364.052566579816,
+ 19386.34857396039,
+ 19407.874900895215,
+ 19428.65728101207,
+ 19448.720646198086,
+ 19468.08914739,
+ 19486.78617514046,
+ 19504.834379934928,
+ 19522.2556922367,
+ 19539.07134224024,
+ 19555.301879315663,
+ 19570.96719112952,
+ 19586.08652242914,
+ 19600.678493479918,
+ 19614.761118146518,
+ 19628.351821610984,
+ 19641.467457721887,
+ 19654.124325970388,
+ 19666.33818809011,
+ 19678.124284279074,
+ 19689.497349042842,
+ 19700.47162665909,
+ 19711.060886264648,
+ 19721.278436566783,
+ 19731.137140181316,
+ 19740.649427600623,
+ 19749.827310795343,
+ 19758.68239645382,
+ 19767.225898864108,
+ 19775.4686524434,
+ 19783.421123920307,
+ 19791.093424175622,
+ 19798.49531974744,
+ 19805.63624400677,
+ 19812.52530800986,
+ 19819.171311033715,
+ 19825.582750801284,
+ 19831.76783340299,
+ 19837.73448292125,
+ 19843.49035076469,
+ 19849.042824718887,
+ 19854.399037720275,
+ 19859.565876360022,
+ 19864.549989124593,
+ 19869.357794379575,
+ 19873.99548810352,
+ 19878.469051378208,
+ 19882.78425764191,
+ 19886.946679712015,
+ 19890.961696583312,
+ 19894.83450000816,
+ 19898.570100864654,
+ 19902.173335318803,
+ 19905.64887078662,
+ 19909.00121170188,
+ 19912.234705095303,
+ 19915.353545990587,
+ 19918.361782622906,
+ 19921.263321485007,
+ 19924.061932206263,
+ 19926.76125226966,
+ 19929.36479157172,
+ 19931.875936830187,
+ 19934.297955844206,
+ 19936.634001611572,
+ 19938.887116307546,
+ 19941.060235129582,
+ 19943.156190012254,
+ 19945.17771321644,
+ 19947.12744079687,
+ 19949.00791595186,
+ 19950.821592259108,
+ 19952.570836801166,
+ 19954.25793318425,
+ 19955.885084453774,
+ 19957.454415910102,
+ 19958.967977827684,
+ 19960.427748080827,
+ 19961.835634679162,
+ 19963.193478215824,
+ 19964.503054231183,
+ 19965.76607549503,
+ 19966.984194209857,
+ 19968.159004137942,
+ 19969.292042654735,
+ 19970.384792731096,
+ 19971.438684846682,
+ 19972.455098836952,
+ 19973.435365675872,
+ 19974.380769196654,
+ 19975.29254775252,
+ 19976.1718958196,
+ 19977.019965543906,
+ 19977.83786823432,
+ 19978.6266758034,
+ 19979.38742215782,
+ 19980.121104540183,
+ 19980.828684823875,
+ 19981.511090762506,
+ 19982.169217195635,
+ 19982.80392721215,
+ 19983.41605327286,
+ 19984.006398293674,
+ 19984.575736690727,
+ 19985.124815388765,
+ 19985.654354794107,
+ 19986.165049733347,
+ 19986.657570359053,
+ 19987.132563023555,
+ 19987.590651121973,
+ 19988.03243590553,
+ 19988.458497266216,
+ 19988.869394493737,
+ 19989.265667005842,
+ 19989.647835052798,
+ 19990.01640039704,
+ 19990.371846968832,
+ 19990.714641498744,
+ 19991.045234127785,
+ 19991.36405899601,
+ 19991.67153481026,
+ 19991.968065391884,
+ 19992.254040205054,
+ 19992.52983486641,
+ 19992.795811636643,
+ 19993.05231989471,
+ 19993.299696595244,
+ 19993.538266709777,
+ 19993.768343652326,
+ 19993.9902296899,
+ 19994.2042163385,
+ 19994.410584745023,
+ 19994.60960605568,
+ 19994.801541771343,
+ 19994.986644090288,
+ 19995.165156238767,
+ 19995.33731278991,
+ 19995.503339971237,
+ 19995.66345596134,
+ 19995.817871175987,
+ 19995.96678854407,
+ 19996.110403773815,
+ 19996.248905609486,
+ 19996.38247607898,
+ 19996.511290732687,
+ 19996.6355188738,
+ 19996.75532378048,
+ 19996.870862920143,
+ 19996.98228815611,
+ 19997.089745946923,
+ 19997.1933775386,
+ 19997.29331915003,
+ 19997.389702151813,
+ 19997.482653238705,
+ 19997.572294595982,
+ 19997.65874405985,
+ 19997.74211527218,
+ 19997.822517829743,
+ 19997.90005742811,
+ 19997.974836000485,
+ 19998.046951851553,
+ 19998.11649978661,
+ 19998.183571236077,
+ 19998.248254375594,
+ 19998.31063424184,
+ 19998.370792844253,
+ 19998.42880927274,
+ 19998.4847598016,
+ 19998.538717989708,
+ 19998.590754777182,
+ 19998.64093857857,
+ 19998.68933537273,
+ 19998.736008789543,
+ 19998.78102019351,
+ 19998.824428764387,
+ 19998.866291574945,
+ 19998.906663665974,
+ 19998.945598118597,
+ 19998.983146124054,
+ 19999.019357050955,
+ 19999.054278510157,
+ 19999.087956417356,
+ 19999.120435053414,
+ 19999.151757122556,
+ 19999.181963808518,
+ 19999.21109482865,
+ 19999.239188486128,
+ 19999.26628172031,
+ 19999.292410155274,
+ 19999.317608146655,
+ 19999.34190882679,
+ 19999.36534414829,
+ 19999.387944926013,
+ 19999.409740877607,
+ 19999.430760662537,
+ 19999.451031919776,
+ 19999.470581304155,
+ 19999.489434521372,
+ 19999.5076163618,
+ 19999.525150733072,
+ 19999.54206069153,
+ 19999.558368472495,
+ 19999.57409551955,
+ 19999.58926251268,
+ 19999.603889395497,
+ 19999.61799540144,
+ 19999.63159907907,
+ 19999.644718316464,
+ 19999.657370364694,
+ 19999.669571860562,
+ 19999.681338848437,
+ 19999.69268680136,
+ 19999.703630641383,
+ 19999.7141847592,
+ 19999.72436303305,
+ 19999.73417884697,
+ 19999.743645108418,
+ 19999.752774265195,
+ 19999.76157832185,
+ 19999.770068855447,
+ 19999.778257030794,
+ 19999.78615361512,
+ 19999.793768992236,
+ 19999.801113176174,
+ 19999.808195824375,
+ 19999.815026250366,
+ 19999.82161343603,
+ 19999.827966043387,
+ 19999.834092426012,
+ 19999.84000064,
+ 20000.0
+ ],
+ "vnorm": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "element": "carbon",
+ "charge": 2
+}
\ No newline at end of file
diff --git a/cherab/generomak/plasma/data/core/carbon3.json b/cherab/generomak/plasma/data/core/carbon3.json
new file mode 100644
index 00000000..d561f286
--- /dev/null
+++ b/cherab/generomak/plasma/data/core/carbon3.json
@@ -0,0 +1,1294 @@
+{
+ "temperature": [
+ 2800.0,
+ 2795.6140361201715,
+ 2783.083337747409,
+ 2763.3003486616526,
+ 2737.094135213008,
+ 2705.2322750926364,
+ 2668.4232152414806,
+ 2627.3189416606197,
+ 2582.5178419123567,
+ 2534.5676700076638,
+ 2483.96854551181,
+ 2431.1759357517954,
+ 2376.6035832043513,
+ 2320.6263503869714,
+ 2263.5829625419237,
+ 2205.7786346035323,
+ 2147.4875737595085,
+ 2088.955352654985,
+ 2030.4011511730957,
+ 1972.019866937452,
+ 1913.9840963599631,
+ 1856.4459893126868,
+ 1799.5389814222144,
+ 1743.3794086390585,
+ 1688.0680091781107,
+ 1633.691318203845,
+ 1580.3229607811295,
+ 1528.0248486579108,
+ 1476.8482864126447,
+ 1426.8349924056063,
+ 1378.018039834137,
+ 1330.4227230192646,
+ 1284.0673538547676,
+ 1238.963993137122,
+ 1195.1191212721988,
+ 1152.5342526267314,
+ 1111.2064975634503,
+ 1071.1290759712253,
+ 1032.291785877979,
+ 994.6814305162284,
+ 958.2822070001829,
+ 923.0760595703174,
+ 889.0430001669228,
+ 856.1613989086177,
+ 824.4082468755387,
+ 793.759393429837,
+ 764.1897601482588,
+ 735.6735332927431,
+ 708.1843366049751,
+ 681.6953860793737,
+ 656.1796282458071,
+ 631.6098633780208,
+ 607.9588549360606,
+ 585.1994264504128,
+ 563.3045469619041,
+ 542.2474060441687,
+ 522.0014793543342,
+ 502.5405855822321,
+ 483.8389355984452,
+ 465.8711745366052,
+ 448.61241748523827,
+ 432.0382794087496,
+ 416.124899865624,
+ 400.8489630442867,
+ 386.1877135930409,
+ 372.11896867986945,
+ 358.6211266803817,
+ 345.67317285760663,
+ 333.2546823654665,
+ 321.34582087841227,
+ 309.927343122692,
+ 298.9805895598673,
+ 288.4874814503533,
+ 278.4305145037626,
+ 268.79275130356683,
+ 259.5578126759042,
+ 250.7098681561356,
+ 242.23362569190442,
+ 234.11432070782254,
+ 226.33770464446184,
+ 218.89003307292606,
+ 211.75805347586066,
+ 204.92899277624957,
+ 198.39054468665884,
+ 192.13085694367678,
+ 186.13851848507585,
+ 180.40254662065936,
+ 174.91237424177845,
+ 169.65783710907806,
+ 164.62916125309604,
+ 159.8169505178761,
+ 155.21217427370195,
+ 150.80615532139907,
+ 146.59055800733688,
+ 142.55737656528729,
+ 138.69892369858735,
+ 135.00781941365733,
+ 131.47698011372418,
+ 128.09960795968092,
+ 124.86918050324817,
+ 121.77944059606116,
+ 118.82438657692074,
+ 115.99826273821829,
+ 113.29555007145385,
+ 110.71095729082082,
+ 108.23941213297381,
+ 105.87605293038021,
+ 103.6162204549953,
+ 101.45545002847112,
+ 99.38946389462029,
+ 97.41416384945612,
+ 95.52562412379939,
+ 93.72008451315051,
+ 91.99394374930452,
+ 90.34375310799985,
+ 88.7662102467457,
+ 87.25815326688075,
+ 85.81655499383113,
+ 84.43851746950027,
+ 83.12126665071017,
+ 81.86214730760918,
+ 80.65861811600642,
+ 79.5082469376184,
+ 78.408706282292,
+ 77.35776894632689,
+ 76.35330382111951,
+ 75.39327186643368,
+ 74.47572224272074,
+ 73.59878859700572,
+ 72.76068549699494,
+ 71.95970500815942,
+ 71.19421340869229,
+ 70.46264803735373,
+ 69.7635142693571,
+ 69.0953826155724,
+ 68.45688594046604,
+ 67.84671679431725,
+ 67.26362485539421,
+ 66.70641447789761,
+ 66.17394234161189,
+ 65.6651151993376,
+ 65.1788877182984,
+ 64.7142604118468,
+ 64.27027765791827,
+ 63.84602580079542,
+ 63.440631332874815,
+ 63.05325915323381,
+ 62.68311089991544,
+ 62.32942335295714,
+ 61.9914669052981,
+ 61.66854409880293,
+ 61.359988222742814,
+ 61.065161972176995,
+ 60.78345616376737,
+ 60.51428850665944,
+ 60.2571024261477,
+ 60.01136593793548,
+ 59.776570570881596,
+ 59.55223033620793,
+ 59.33788074122536,
+ 59.13307784570519,
+ 58.937397359105915,
+ 58.75043377692946,
+ 58.571799554551646,
+ 58.40112431694312,
+ 58.23805410275451,
+ 58.08225064130303,
+ 57.93339066106313,
+ 57.7911652283102,
+ 57.65527911463285,
+ 57.525450192074885,
+ 57.40140885472106,
+ 57.28289746559213,
+ 57.16966982775895,
+ 57.06149067863122,
+ 56.95813520642253,
+ 56.85938858783372,
+ 56.765045546033065,
+ 56.674909928059456,
+ 56.588794300802036,
+ 56.50651956475268,
+ 56.427914584755875,
+ 56.35281583702141,
+ 56.281067071686564,
+ 56.21251899025332,
+ 56.14702893725086,
+ 56.08446060550164,
+ 56.02468375439783,
+ 55.96757394061782,
+ 55.91301226073971,
+ 55.8608851052287,
+ 55.81108392330204,
+ 55.76350499819346,
+ 55.718049232360165,
+ 55.67462194219673,
+ 55.63313266183696,
+ 55.593494955645,
+ 55.55562623901411,
+ 55.51944760710454,
+ 55.484883671174465,
+ 55.45186240216659,
+ 55.42031498123234,
+ 55.390175656886,
+ 55.361381608497936,
+ 55.333872815845915,
+ 55.307591934457406,
+ 55.282484176486456,
+ 55.258497196881336,
+ 55.23558098460842,
+ 55.21368775870917,
+ 55.19277186897538,
+ 55.17278970103895,
+ 55.153699585681665,
+ 55.13546171217539,
+ 55.11803804547773,
+ 55.101392247108336,
+ 55.08548959954608,
+ 55.070296933989404,
+ 55.05578256132999,
+ 55.04191620619953,
+ 55.028668943950365,
+ 55.01601314044173,
+ 55.003922394507015,
+ 54.99237148298145,
+ 54.98133630817787,
+ 54.970793847702375,
+ 54.96072210650347,
+ 54.951100071057624,
+ 54.941907665596375,
+ 54.93312571028218,
+ 54.9247358812481,
+ 54.91672067241873,
+ 54.90906335903125,
+ 54.90174796278291,
+ 54.8947592185312,
+ 54.888082542479076,
+ 54.881704001777535,
+ 54.87561028548313,
+ 54.869788676811275,
+ 54.86422702662521,
+ 54.858913728107794,
+ 54.85383769256265,
+ 54.84898832629396,
+ 54.8443555085177,
+ 54.83992957025756,
+ 54.83570127418218,
+ 54.83166179534185,
+ 54.82780270276455,
+ 54.824115941872016,
+ 54.82059381768116,
+ 54.81722897875463,
+ 54.81401440186672,
+ 54.81094337735412,
+ 54.80800949511986,
+ 54.80520663126194,
+ 54.7452478101525
+ ],
+ "density": [
+ 1696833.2929320585,
+ 1695585.5346261703,
+ 1703034.1483737943,
+ 1721256.0083039757,
+ 1751174.826856844,
+ 1793462.9777274628,
+ 1848789.2681748066,
+ 1917932.0502929946,
+ 2001843.1487110062,
+ 2101691.8507644087,
+ 2218901.8049322264,
+ 2355187.4339219616,
+ 2512593.5720948935,
+ 2693541.143056974,
+ 2900880.7853058777,
+ 3137956.567619743,
+ 3408681.8389850566,
+ 3717629.590246343,
+ 4070140.147236769,
+ 4472449.503360834,
+ 4931842.339843194,
+ 5456834.574082767,
+ 6057391.4069654485,
+ 6745188.043835769,
+ 7533894.08882723,
+ 8438040.68619504,
+ 9474927.617135428,
+ 10666144.076443244,
+ 12037269.181392074,
+ 13618691.263185747,
+ 15446615.360481534,
+ 17564303.70763869,
+ 20023607.824385516,
+ 22886777.35580498,
+ 26222719.857324515,
+ 30112198.083528586,
+ 34654282.723995,
+ 39966924.52730038,
+ 46190732.40796578,
+ 53493550.959011845,
+ 62076004.239125356,
+ 72178217.79676005,
+ 84087979.04679102,
+ 98153684.12489405,
+ 114790268.27579233,
+ 134480496.8088131,
+ 157796732.52584448,
+ 185454477.7662331,
+ 218321063.70239368,
+ 257449759.17177022,
+ 304122403.0477343,
+ 359902414.63618606,
+ 426700895.5275371,
+ 506859421.1661952,
+ 603150803.3245813,
+ 718665327.1439896,
+ 857491337.6972063,
+ 1024713797.2305741,
+ 1226629970.51637,
+ 1471064146.446006,
+ 1767770494.5111785,
+ 2128950440.3712964,
+ 2569871178.013945,
+ 3107483535.2911277,
+ 3762666980.8892303,
+ 4562658718.166039,
+ 5541407710.59275,
+ 6741327176.803194,
+ 8215528044.0905075,
+ 10030670665.17434,
+ 12270612334.574423,
+ 15041080240.00464,
+ 18475666848.57919,
+ 22743531642.40487,
+ 28059304890.69837,
+ 34694130667.19102,
+ 42949504729.17792,
+ 53215803474.32276,
+ 66005843073.27365,
+ 81970232639.91074,
+ 101935947429.07399,
+ 126955857114.0498,
+ 158372211099.3084,
+ 197897781357.9156,
+ 247719125699.63535,
+ 310636487052.79944,
+ 389922612130.1703,
+ 488927829361.61676,
+ 612743572971.3516,
+ 767966754305.5444,
+ 963061978933.3938,
+ 1208880863704.0518,
+ 1519300911417.147,
+ 1911986213718.501,
+ 2402412088320.5693,
+ 3001219151011.2773,
+ 3730120534876.667,
+ 4615158784849.36,
+ 5686907738665.593,
+ 6980763900484.745,
+ 8537026859965.436,
+ 10400699753349.402,
+ 12620966467453.045,
+ 15250350343992.717,
+ 18343622207917.098,
+ 21956583495935.363,
+ 26064693092269.617,
+ 30544136400340.87,
+ 35377753295293.17,
+ 40555945070609.02,
+ 46074045244408.83,
+ 51933029405493.94,
+ 58139222942210.87,
+ 64703130552471.7,
+ 71637626192466.19,
+ 78955815493426.89,
+ 86668917902746.72,
+ 94784516303177.33,
+ 103263931645205.48,
+ 111787224185099.47,
+ 120246770335232.78,
+ 128605747496359.89,
+ 136833759942592.23,
+ 144907844298562.9,
+ 152813152835414.7,
+ 160543211765841.1,
+ 168099722187906.75,
+ 175491935454603.38,
+ 182735876734993.4,
+ 189852619551918.88,
+ 196867432542592.47,
+ 203808284935431.44,
+ 210704581917170.66,
+ 217583961405604.62,
+ 224394192250872.2,
+ 231116082117766.88,
+ 237773792771364.6,
+ 244387675489041.34,
+ 250974441603543.8,
+ 257547405498000.12,
+ 264116767501773.88,
+ 270689913774420.62,
+ 277271717683311.97,
+ 283864832683560.44,
+ 290469970659869.75,
+ 297086162435741.6,
+ 303710998999869.2,
+ 310340853188191.1,
+ 316971082286105.75,
+ 323596212423999.56,
+ 330210105837718.44,
+ 336806112130098.3,
+ 343377204653890.2,
+ 349916103076979.94,
+ 356415383111422.3,
+ 362867574303987.75,
+ 369265246706052.7,
+ 375601087170428.94,
+ 381867965963014.5,
+ 388058994328742.4,
+ 394167573613298.7,
+ 400187436512475.75,
+ 406112680998405.06,
+ 411937797455005.75,
+ 417657689540276.8,
+ 423267689282113.25,
+ 428763566902546.94,
+ 434141535854502.4,
+ 439398253542820.25,
+ 444530818187850.8,
+ 449536811414876.2,
+ 454414150553507.06,
+ 459161179124996.75,
+ 463776666728802.44,
+ 468259765082445.1,
+ 472609990374218.7,
+ 476827204446105.7,
+ 480911595099409.4,
+ 484863655789798.3,
+ 488684164954596.6,
+ 492374165189189.6,
+ 495934942466422.6,
+ 499368005568998.6,
+ 502675065882530.7,
+ 505858017676230.6,
+ 508918918977704.56,
+ 511859973130526.25,
+ 514683511105241.2,
+ 517391974619713.7,
+ 519987900109775.94,
+ 522473903578741.44,
+ 524852666342586.44,
+ 527126921677870.1,
+ 529299442370347.3,
+ 531373029154628.2,
+ 533350500028981.56,
+ 535234680423608.1,
+ 537028394196253.75,
+ 538734455425684.3,
+ 540355660970247.06,
+ 541894783756889.0,
+ 543354566764333.56,
+ 544737717663353.94,
+ 546046904076213.9,
+ 547284749417582.06,
+ 548453829279530.9,
+ 549556668323423.5,
+ 550595737642856.25,
+ 551573452562394.7,
+ 552492170838372.0,
+ 553354191229003.4,
+ 554161752403094.4,
+ 554917020632621.5,
+ 555622101348608.25,
+ 556279072705655.25,
+ 556889927902278.8,
+ 557456598671095.75,
+ 557980955650210.25,
+ 558464808917578.9,
+ 558909908669404.6,
+ 559317946024909.9,
+ 559690553941324.56,
+ 560029308223890.9,
+ 560335728617201.25,
+ 560611279965183.6,
+ 560857373428226.7,
+ 561075367746842.94,
+ 561266570542317.8,
+ 561432239645791.94,
+ 561573584447694.25,
+ 561691767260778.06,
+ 561787904690278.2,
+ 561863069005538.4,
+ 561918289508186.7,
+ 561954553892423.7,
+ 561972809593324.8,
+ 561973965120028.06,
+ 561958891370560.56,
+ 561928422925964.1,
+ 561883359321281.1,
+ 561824466291756.2,
+ 561752476992557.2,
+ 561668093190769.7,
+ 561571986428726.75,
+ 561464799157707.44,
+ 561347145841483.9,
+ 561219614029419.6,
+ 561082765398626.2,
+ 560937136765227.25,
+ 560783241064650.5,
+ 560621568301310.75,
+ 560452586467449.8,
+ 560276742431891.2,
+ 560094462798939.7,
+ 559906154737711.9,
+ 519569650787351.1
+ ],
+ "vtor": [
+ 100000.0,
+ 99544.32023364124,
+ 98251.15453696062,
+ 96235.68685722632,
+ 93614.68356191639,
+ 90502.18847954353,
+ 87006.32501749854,
+ 83227.06508922808,
+ 79254.813872946,
+ 75169.66123127713,
+ 71041.16042746486,
+ 66928.50919629741,
+ 62881.02482158773,
+ 58938.821939433255,
+ 55133.61820859918,
+ 51489.60808192722,
+ 48024.35830839606,
+ 44749.69035052268,
+ 41672.524623402256,
+ 38795.66945343124,
+ 36118.54407642795,
+ 33637.83003375026,
+ 31348.04917610031,
+ 29242.06933764292,
+ 27311.54077408969,
+ 25547.26782590489,
+ 23939.521110407513,
+ 22478.295982958116,
+ 21153.523137258686,
+ 19955.237120191036,
+ 18873.708284120235,
+ 17899.54334214529,
+ 17023.759270761642,
+ 16237.834851443324,
+ 15533.743681380842,
+ 14903.972031120154,
+ 14341.524495030524,
+ 13839.919977172622,
+ 13393.180184865832,
+ 12995.812467288095,
+ 12642.788537234375,
+ 12329.520349892675,
+ 12051.83418147994,
+ 11805.94375056095,
+ 11588.423053275488,
+ 11396.179437797053,
+ 11226.42732039882,
+ 11076.662842842592,
+ 10944.639685904545,
+ 10828.34618435543,
+ 10725.983832469563,
+ 10635.94722420132,
+ 10556.805436804136,
+ 10487.284839339893,
+ 10426.253286892172,
+ 10372.705646187464,
+ 10325.750587737686,
+ 10284.598572685094,
+ 10248.550958525679,
+ 10216.990146193662,
+ 10189.370691092356,
+ 10165.211302127113,
+ 10144.087655281786,
+ 10125.625951492917,
+ 10109.49715228246,
+ 10095.411830623676,
+ 10083.115578687914,
+ 10072.384918337477,
+ 10063.023664403154,
+ 10054.85969484832,
+ 10047.742085826912,
+ 10041.538573356505,
+ 10036.133306828673,
+ 10031.424862854412,
+ 10027.3244909875,
+ 10023.75456568367,
+ 10020.647221443161,
+ 10017.943150456194,
+ 10015.59054423511,
+ 10013.544162684711,
+ 10011.764515845945,
+ 10010.217145160046,
+ 10008.871992553453,
+ 10007.702846950711,
+ 10006.686858995241,
+ 10005.804115808194,
+ 10005.037268554323,
+ 10004.371206421612,
+ 10003.792771367725,
+ 10003.29050865027,
+ 10002.85444874773,
+ 10002.475916801126,
+ 10002.14736617021,
+ 10001.86223310832,
+ 10001.614809922945,
+ 10001.400134309408,
+ 10001.213892828007,
+ 10001.052336744104,
+ 10000.912208670363,
+ 10000.790678643563,
+ 10000.68528843837,
+ 10000.593903069897,
+ 10000.514668568,
+ 10000.445975221452,
+ 10000.386425591105,
+ 10000.334806679686,
+ 10000.290065723417,
+ 10000.25128913859,
+ 10000.217684215675,
+ 10000.188563205464,
+ 10000.16332948734,
+ 10000.141465549392,
+ 10000.122522544827,
+ 10000.106111219531,
+ 10000.091894031972,
+ 10000.079578309811,
+ 10000.068910307727,
+ 10000.05967004848,
+ 10000.051666844598,
+ 10000.044735411424,
+ 10000.038732493818,
+ 10000.033533939033,
+ 10000.029032157028,
+ 10000.02513391718,
+ 10000.021758437058,
+ 10000.018835724715,
+ 10000.016305140998,
+ 10000.01411415281,
+ 10000.012217252064,
+ 10000.010575018385,
+ 10000.009153306504,
+ 10000.007922541854,
+ 10000.00685710995,
+ 10000.005934827166,
+ 10000.005136482061,
+ 10000.004445437868,
+ 10000.003847288048,
+ 10000.003329557814,
+ 10000.002881445527,
+ 10000.00249359863,
+ 10000.002157919536,
+ 10000.001867397486,
+ 10000.001615962863,
+ 10000.001398361033,
+ 10000.001210043049,
+ 10000.001047070993,
+ 10000.000906036008,
+ 10000.000783987294,
+ 10000.000678370623,
+ 10000.000586975104,
+ 10000.000507887078,
+ 10000.000439450198,
+ 10000.000380230858,
+ 10000.000328988277,
+ 10000.000284648579,
+ 10000.000246282361,
+ 10000.000213085277,
+ 10000.00018436122,
+ 10000.000159507772,
+ 10000.000138003594,
+ 10000.000119397531,
+ 10000.000103299173,
+ 10000.000089370667,
+ 10000.000077319659,
+ 10000.000066893168,
+ 10000.000057872281,
+ 10000.000050067574,
+ 10000.00004331514,
+ 10000.00003747315,
+ 10000.000032418886,
+ 10000.000028046165,
+ 10000.00002426311,
+ 10000.000020990228,
+ 10000.000018158735,
+ 10000.00001570912,
+ 10000.000013589894,
+ 10000.000011756505,
+ 10000.00001017041,
+ 10000.00000879826,
+ 10000.000007611205,
+ 10000.00000658428,
+ 10000.000005695889,
+ 10000.000004927346,
+ 10000.000004262487,
+ 10000.000003687326,
+ 10000.000003189763,
+ 10000.000002759334,
+ 10000.000002386978,
+ 10000.000002064864,
+ 10000.000001786213,
+ 10000.00000154516,
+ 10000.000001336637,
+ 10000.00000115625,
+ 10000.000001000204,
+ 10000.000000865217,
+ 10000.000000748445,
+ 10000.000000647431,
+ 10000.00000056005,
+ 10000.000000484462,
+ 10000.000000419075,
+ 10000.000000362512,
+ 10000.000000313583,
+ 10000.000000271257,
+ 10000.000000234644,
+ 10000.000000202972,
+ 10000.000000175574,
+ 10000.000000151877,
+ 10000.000000131377,
+ 10000.000000113641,
+ 10000.000000098302,
+ 10000.000000085032,
+ 10000.000000073554,
+ 10000.000000063626,
+ 10000.000000055037,
+ 10000.000000047608,
+ 10000.000000041182,
+ 10000.000000035621,
+ 10000.000000030814,
+ 10000.000000026654,
+ 10000.000000023056,
+ 10000.000000019943,
+ 10000.000000017251,
+ 10000.000000014923,
+ 10000.000000012908,
+ 10000.000000011165,
+ 10000.000000009659,
+ 10000.000000008355,
+ 10000.000000007227,
+ 10000.00000000625,
+ 10000.000000005406,
+ 10000.000000004677,
+ 10000.000000004045,
+ 10000.0000000035,
+ 10000.000000003027,
+ 10000.000000002618,
+ 10000.000000002265,
+ 10000.000000001959,
+ 10000.000000001695,
+ 10000.000000001466,
+ 10000.000000001268,
+ 10000.000000001097,
+ 10000.00000000095,
+ 10000.00000000082,
+ 10000.00000000071,
+ 10000.000000000615,
+ 10000.000000000531,
+ 10000.00000000046,
+ 10000.000000000397,
+ 10000.000000000344,
+ 10000.000000000296,
+ 10000.000000000256,
+ 10000.000000000222,
+ 10000.000000000193,
+ 10000.000000000167,
+ 10000.000000000144,
+ 10000.0
+ ],
+ "vpol": [
+ 18462.326927732716,
+ 18514.99979366994,
+ 18565.939231880784,
+ 18615.197379613106,
+ 18662.8251518226,
+ 18708.87224398403,
+ 18753.38713728863,
+ 18796.417106004,
+ 18838.008226787257,
+ 18878.20538975573,
+ 18917.052311132516,
+ 18954.591547296637,
+ 18990.864510079347,
+ 19025.91148315922,
+ 19059.7716394193,
+ 19092.483059139577,
+ 19124.08274890752,
+ 19154.60666113828,
+ 19184.089714104663,
+ 19212.565812384706,
+ 19240.067867642374,
+ 19266.627819663598,
+ 19292.27665757659,
+ 19317.044441191432,
+ 19340.960322399642,
+ 19364.052566579816,
+ 19386.34857396039,
+ 19407.874900895215,
+ 19428.65728101207,
+ 19448.720646198086,
+ 19468.08914739,
+ 19486.78617514046,
+ 19504.834379934928,
+ 19522.2556922367,
+ 19539.07134224024,
+ 19555.301879315663,
+ 19570.96719112952,
+ 19586.08652242914,
+ 19600.678493479918,
+ 19614.761118146518,
+ 19628.351821610984,
+ 19641.467457721887,
+ 19654.124325970388,
+ 19666.33818809011,
+ 19678.124284279074,
+ 19689.497349042842,
+ 19700.47162665909,
+ 19711.060886264648,
+ 19721.278436566783,
+ 19731.137140181316,
+ 19740.649427600623,
+ 19749.827310795343,
+ 19758.68239645382,
+ 19767.225898864108,
+ 19775.4686524434,
+ 19783.421123920307,
+ 19791.093424175622,
+ 19798.49531974744,
+ 19805.63624400677,
+ 19812.52530800986,
+ 19819.171311033715,
+ 19825.582750801284,
+ 19831.76783340299,
+ 19837.73448292125,
+ 19843.49035076469,
+ 19849.042824718887,
+ 19854.399037720275,
+ 19859.565876360022,
+ 19864.549989124593,
+ 19869.357794379575,
+ 19873.99548810352,
+ 19878.469051378208,
+ 19882.78425764191,
+ 19886.946679712015,
+ 19890.961696583312,
+ 19894.83450000816,
+ 19898.570100864654,
+ 19902.173335318803,
+ 19905.64887078662,
+ 19909.00121170188,
+ 19912.234705095303,
+ 19915.353545990587,
+ 19918.361782622906,
+ 19921.263321485007,
+ 19924.061932206263,
+ 19926.76125226966,
+ 19929.36479157172,
+ 19931.875936830187,
+ 19934.297955844206,
+ 19936.634001611572,
+ 19938.887116307546,
+ 19941.060235129582,
+ 19943.156190012254,
+ 19945.17771321644,
+ 19947.12744079687,
+ 19949.00791595186,
+ 19950.821592259108,
+ 19952.570836801166,
+ 19954.25793318425,
+ 19955.885084453774,
+ 19957.454415910102,
+ 19958.967977827684,
+ 19960.427748080827,
+ 19961.835634679162,
+ 19963.193478215824,
+ 19964.503054231183,
+ 19965.76607549503,
+ 19966.984194209857,
+ 19968.159004137942,
+ 19969.292042654735,
+ 19970.384792731096,
+ 19971.438684846682,
+ 19972.455098836952,
+ 19973.435365675872,
+ 19974.380769196654,
+ 19975.29254775252,
+ 19976.1718958196,
+ 19977.019965543906,
+ 19977.83786823432,
+ 19978.6266758034,
+ 19979.38742215782,
+ 19980.121104540183,
+ 19980.828684823875,
+ 19981.511090762506,
+ 19982.169217195635,
+ 19982.80392721215,
+ 19983.41605327286,
+ 19984.006398293674,
+ 19984.575736690727,
+ 19985.124815388765,
+ 19985.654354794107,
+ 19986.165049733347,
+ 19986.657570359053,
+ 19987.132563023555,
+ 19987.590651121973,
+ 19988.03243590553,
+ 19988.458497266216,
+ 19988.869394493737,
+ 19989.265667005842,
+ 19989.647835052798,
+ 19990.01640039704,
+ 19990.371846968832,
+ 19990.714641498744,
+ 19991.045234127785,
+ 19991.36405899601,
+ 19991.67153481026,
+ 19991.968065391884,
+ 19992.254040205054,
+ 19992.52983486641,
+ 19992.795811636643,
+ 19993.05231989471,
+ 19993.299696595244,
+ 19993.538266709777,
+ 19993.768343652326,
+ 19993.9902296899,
+ 19994.2042163385,
+ 19994.410584745023,
+ 19994.60960605568,
+ 19994.801541771343,
+ 19994.986644090288,
+ 19995.165156238767,
+ 19995.33731278991,
+ 19995.503339971237,
+ 19995.66345596134,
+ 19995.817871175987,
+ 19995.96678854407,
+ 19996.110403773815,
+ 19996.248905609486,
+ 19996.38247607898,
+ 19996.511290732687,
+ 19996.6355188738,
+ 19996.75532378048,
+ 19996.870862920143,
+ 19996.98228815611,
+ 19997.089745946923,
+ 19997.1933775386,
+ 19997.29331915003,
+ 19997.389702151813,
+ 19997.482653238705,
+ 19997.572294595982,
+ 19997.65874405985,
+ 19997.74211527218,
+ 19997.822517829743,
+ 19997.90005742811,
+ 19997.974836000485,
+ 19998.046951851553,
+ 19998.11649978661,
+ 19998.183571236077,
+ 19998.248254375594,
+ 19998.31063424184,
+ 19998.370792844253,
+ 19998.42880927274,
+ 19998.4847598016,
+ 19998.538717989708,
+ 19998.590754777182,
+ 19998.64093857857,
+ 19998.68933537273,
+ 19998.736008789543,
+ 19998.78102019351,
+ 19998.824428764387,
+ 19998.866291574945,
+ 19998.906663665974,
+ 19998.945598118597,
+ 19998.983146124054,
+ 19999.019357050955,
+ 19999.054278510157,
+ 19999.087956417356,
+ 19999.120435053414,
+ 19999.151757122556,
+ 19999.181963808518,
+ 19999.21109482865,
+ 19999.239188486128,
+ 19999.26628172031,
+ 19999.292410155274,
+ 19999.317608146655,
+ 19999.34190882679,
+ 19999.36534414829,
+ 19999.387944926013,
+ 19999.409740877607,
+ 19999.430760662537,
+ 19999.451031919776,
+ 19999.470581304155,
+ 19999.489434521372,
+ 19999.5076163618,
+ 19999.525150733072,
+ 19999.54206069153,
+ 19999.558368472495,
+ 19999.57409551955,
+ 19999.58926251268,
+ 19999.603889395497,
+ 19999.61799540144,
+ 19999.63159907907,
+ 19999.644718316464,
+ 19999.657370364694,
+ 19999.669571860562,
+ 19999.681338848437,
+ 19999.69268680136,
+ 19999.703630641383,
+ 19999.7141847592,
+ 19999.72436303305,
+ 19999.73417884697,
+ 19999.743645108418,
+ 19999.752774265195,
+ 19999.76157832185,
+ 19999.770068855447,
+ 19999.778257030794,
+ 19999.78615361512,
+ 19999.793768992236,
+ 19999.801113176174,
+ 19999.808195824375,
+ 19999.815026250366,
+ 19999.82161343603,
+ 19999.827966043387,
+ 19999.834092426012,
+ 19999.84000064,
+ 20000.0
+ ],
+ "vnorm": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "element": "carbon",
+ "charge": 3
+}
\ No newline at end of file
diff --git a/cherab/generomak/plasma/data/core/carbon4.json b/cherab/generomak/plasma/data/core/carbon4.json
new file mode 100644
index 00000000..47ad77e9
--- /dev/null
+++ b/cherab/generomak/plasma/data/core/carbon4.json
@@ -0,0 +1,1294 @@
+{
+ "temperature": [
+ 2800.0,
+ 2795.6140361201715,
+ 2783.083337747409,
+ 2763.3003486616526,
+ 2737.094135213008,
+ 2705.2322750926364,
+ 2668.4232152414806,
+ 2627.3189416606197,
+ 2582.5178419123567,
+ 2534.5676700076638,
+ 2483.96854551181,
+ 2431.1759357517954,
+ 2376.6035832043513,
+ 2320.6263503869714,
+ 2263.5829625419237,
+ 2205.7786346035323,
+ 2147.4875737595085,
+ 2088.955352654985,
+ 2030.4011511730957,
+ 1972.019866937452,
+ 1913.9840963599631,
+ 1856.4459893126868,
+ 1799.5389814222144,
+ 1743.3794086390585,
+ 1688.0680091781107,
+ 1633.691318203845,
+ 1580.3229607811295,
+ 1528.0248486579108,
+ 1476.8482864126447,
+ 1426.8349924056063,
+ 1378.018039834137,
+ 1330.4227230192646,
+ 1284.0673538547676,
+ 1238.963993137122,
+ 1195.1191212721988,
+ 1152.5342526267314,
+ 1111.2064975634503,
+ 1071.1290759712253,
+ 1032.291785877979,
+ 994.6814305162284,
+ 958.2822070001829,
+ 923.0760595703174,
+ 889.0430001669228,
+ 856.1613989086177,
+ 824.4082468755387,
+ 793.759393429837,
+ 764.1897601482588,
+ 735.6735332927431,
+ 708.1843366049751,
+ 681.6953860793737,
+ 656.1796282458071,
+ 631.6098633780208,
+ 607.9588549360606,
+ 585.1994264504128,
+ 563.3045469619041,
+ 542.2474060441687,
+ 522.0014793543342,
+ 502.5405855822321,
+ 483.8389355984452,
+ 465.8711745366052,
+ 448.61241748523827,
+ 432.0382794087496,
+ 416.124899865624,
+ 400.8489630442867,
+ 386.1877135930409,
+ 372.11896867986945,
+ 358.6211266803817,
+ 345.67317285760663,
+ 333.2546823654665,
+ 321.34582087841227,
+ 309.927343122692,
+ 298.9805895598673,
+ 288.4874814503533,
+ 278.4305145037626,
+ 268.79275130356683,
+ 259.5578126759042,
+ 250.7098681561356,
+ 242.23362569190442,
+ 234.11432070782254,
+ 226.33770464446184,
+ 218.89003307292606,
+ 211.75805347586066,
+ 204.92899277624957,
+ 198.39054468665884,
+ 192.13085694367678,
+ 186.13851848507585,
+ 180.40254662065936,
+ 174.91237424177845,
+ 169.65783710907806,
+ 164.62916125309604,
+ 159.8169505178761,
+ 155.21217427370195,
+ 150.80615532139907,
+ 146.59055800733688,
+ 142.55737656528729,
+ 138.69892369858735,
+ 135.00781941365733,
+ 131.47698011372418,
+ 128.09960795968092,
+ 124.86918050324817,
+ 121.77944059606116,
+ 118.82438657692074,
+ 115.99826273821829,
+ 113.29555007145385,
+ 110.71095729082082,
+ 108.23941213297381,
+ 105.87605293038021,
+ 103.6162204549953,
+ 101.45545002847112,
+ 99.38946389462029,
+ 97.41416384945612,
+ 95.52562412379939,
+ 93.72008451315051,
+ 91.99394374930452,
+ 90.34375310799985,
+ 88.7662102467457,
+ 87.25815326688075,
+ 85.81655499383113,
+ 84.43851746950027,
+ 83.12126665071017,
+ 81.86214730760918,
+ 80.65861811600642,
+ 79.5082469376184,
+ 78.408706282292,
+ 77.35776894632689,
+ 76.35330382111951,
+ 75.39327186643368,
+ 74.47572224272074,
+ 73.59878859700572,
+ 72.76068549699494,
+ 71.95970500815942,
+ 71.19421340869229,
+ 70.46264803735373,
+ 69.7635142693571,
+ 69.0953826155724,
+ 68.45688594046604,
+ 67.84671679431725,
+ 67.26362485539421,
+ 66.70641447789761,
+ 66.17394234161189,
+ 65.6651151993376,
+ 65.1788877182984,
+ 64.7142604118468,
+ 64.27027765791827,
+ 63.84602580079542,
+ 63.440631332874815,
+ 63.05325915323381,
+ 62.68311089991544,
+ 62.32942335295714,
+ 61.9914669052981,
+ 61.66854409880293,
+ 61.359988222742814,
+ 61.065161972176995,
+ 60.78345616376737,
+ 60.51428850665944,
+ 60.2571024261477,
+ 60.01136593793548,
+ 59.776570570881596,
+ 59.55223033620793,
+ 59.33788074122536,
+ 59.13307784570519,
+ 58.937397359105915,
+ 58.75043377692946,
+ 58.571799554551646,
+ 58.40112431694312,
+ 58.23805410275451,
+ 58.08225064130303,
+ 57.93339066106313,
+ 57.7911652283102,
+ 57.65527911463285,
+ 57.525450192074885,
+ 57.40140885472106,
+ 57.28289746559213,
+ 57.16966982775895,
+ 57.06149067863122,
+ 56.95813520642253,
+ 56.85938858783372,
+ 56.765045546033065,
+ 56.674909928059456,
+ 56.588794300802036,
+ 56.50651956475268,
+ 56.427914584755875,
+ 56.35281583702141,
+ 56.281067071686564,
+ 56.21251899025332,
+ 56.14702893725086,
+ 56.08446060550164,
+ 56.02468375439783,
+ 55.96757394061782,
+ 55.91301226073971,
+ 55.8608851052287,
+ 55.81108392330204,
+ 55.76350499819346,
+ 55.718049232360165,
+ 55.67462194219673,
+ 55.63313266183696,
+ 55.593494955645,
+ 55.55562623901411,
+ 55.51944760710454,
+ 55.484883671174465,
+ 55.45186240216659,
+ 55.42031498123234,
+ 55.390175656886,
+ 55.361381608497936,
+ 55.333872815845915,
+ 55.307591934457406,
+ 55.282484176486456,
+ 55.258497196881336,
+ 55.23558098460842,
+ 55.21368775870917,
+ 55.19277186897538,
+ 55.17278970103895,
+ 55.153699585681665,
+ 55.13546171217539,
+ 55.11803804547773,
+ 55.101392247108336,
+ 55.08548959954608,
+ 55.070296933989404,
+ 55.05578256132999,
+ 55.04191620619953,
+ 55.028668943950365,
+ 55.01601314044173,
+ 55.003922394507015,
+ 54.99237148298145,
+ 54.98133630817787,
+ 54.970793847702375,
+ 54.96072210650347,
+ 54.951100071057624,
+ 54.941907665596375,
+ 54.93312571028218,
+ 54.9247358812481,
+ 54.91672067241873,
+ 54.90906335903125,
+ 54.90174796278291,
+ 54.8947592185312,
+ 54.888082542479076,
+ 54.881704001777535,
+ 54.87561028548313,
+ 54.869788676811275,
+ 54.86422702662521,
+ 54.858913728107794,
+ 54.85383769256265,
+ 54.84898832629396,
+ 54.8443555085177,
+ 54.83992957025756,
+ 54.83570127418218,
+ 54.83166179534185,
+ 54.82780270276455,
+ 54.824115941872016,
+ 54.82059381768116,
+ 54.81722897875463,
+ 54.81401440186672,
+ 54.81094337735412,
+ 54.80800949511986,
+ 54.80520663126194,
+ 54.7452478101525
+ ],
+ "density": [
+ 46350405566.4054,
+ 46284237625.31838,
+ 46377376549.137474,
+ 46670924446.71948,
+ 47180482713.78791,
+ 47915138259.74194,
+ 48882300889.21657,
+ 50089810565.15369,
+ 51547022732.33509,
+ 53265438570.25678,
+ 55259122012.65607,
+ 57545021624.12109,
+ 60143260320.84436,
+ 63077429051.469345,
+ 66374906777.00613,
+ 70067221925.64133,
+ 74190466880.22955,
+ 78785775449.38242,
+ 83899872865.75154,
+ 89585708209.65178,
+ 95903180036.86243,
+ 102919967269.99362,
+ 110712479034.47878,
+ 119366939061.52307,
+ 128980381012.53004,
+ 139650356255.3698,
+ 151493758818.3758,
+ 164655600080.99313,
+ 179302730877.29105,
+ 195627523788.2097,
+ 213852271426.5203,
+ 234234433172.45392,
+ 257072908865.32074,
+ 282714170388.7059,
+ 311476125733.1768,
+ 343728268938.59607,
+ 379948809932.3586,
+ 420690633544.8943,
+ 466594150949.36475,
+ 518402716039.77686,
+ 576981020112.0531,
+ 643337087885.5581,
+ 718648637928.0991,
+ 804309566656.8345,
+ 901936517731.6887,
+ 1013174699432.6936,
+ 1139774935542.7197,
+ 1284159542010.1714,
+ 1449192365214.294,
+ 1638263013716.838,
+ 1855394300765.4873,
+ 2105373695410.4524,
+ 2393914584397.565,
+ 2727854650178.9463,
+ 3114672632419.614,
+ 3561244443333.942,
+ 4078057118720.018,
+ 4678093148887.286,
+ 5377140773975.816,
+ 6194475953440.215,
+ 7153727019705.466,
+ 8283975395893.132,
+ 9620926371866.709,
+ 11198091896859.557,
+ 13056165093226.484,
+ 15251094943219.5,
+ 17851237199403.375,
+ 20940359891494.133,
+ 24621431200712.773,
+ 29021405474548.914,
+ 34297285209370.332,
+ 40643817115878.99,
+ 48303284204591.195,
+ 57577989916903.66,
+ 68846203133507.68,
+ 82575863200086.94,
+ 99191653487398.58,
+ 119279439872784.33,
+ 143654027332428.78,
+ 173346839323390.3,
+ 209668709470650.44,
+ 254291921482299.34,
+ 309357550616115.0,
+ 377616004551139.75,
+ 462610980484455.0,
+ 568935169243997.1,
+ 701805790886232.4,
+ 865973256198488.8,
+ 1069469897938848.2,
+ 1322843184955839.5,
+ 1639752367136081.5,
+ 2037895759219286.5,
+ 2540187857311035.5,
+ 3176220966949160.5,
+ 3974318084294743.5,
+ 4957628931592609.0,
+ 6166621547030046.0,
+ 7649980316205009.0,
+ 9465032414640132.0,
+ 1.167815021201937e+16,
+ 1.4364618692277636e+16,
+ 1.760776889672942e+16,
+ 2.149721890418564e+16,
+ 2.612615968793039e+16,
+ 3.158776631002165e+16,
+ 3.7970969353840856e+16,
+ 4.52687863954724e+16,
+ 5.335944463086585e+16,
+ 6.2229908295669816e+16,
+ 7.186462354298768e+16,
+ 8.224162698271402e+16,
+ 9.333233640328437e+16,
+ 1.051001076547748e+17,
+ 1.1749765655473509e+17,
+ 1.3046371799766349e+17,
+ 1.4391954758695259e+17,
+ 1.5776602862745238e+17,
+ 1.7188219580417078e+17,
+ 1.860924287861691e+17,
+ 2.0000578021076806e+17,
+ 2.1344414086257683e+17,
+ 2.2629718005560486e+17,
+ 2.384692421863735e+17,
+ 2.498824535514498e+17,
+ 2.604788577222335e+17,
+ 2.7022136553746403e+17,
+ 2.7909348028404227e+17,
+ 2.8709791375615872e+17,
+ 2.942534901122749e+17,
+ 3.005948389926677e+17,
+ 3.061667080728738e+17,
+ 3.1102163520002963e+17,
+ 3.1521700349012704e+17,
+ 3.188116802063171e+17,
+ 3.2183961044985395e+17,
+ 3.2435828220173325e+17,
+ 3.264375086754881e+17,
+ 3.2813887595373184e+17,
+ 3.295162754327499e+17,
+ 3.306165604397081e+17,
+ 3.3148025418647725e+17,
+ 3.321422598062225e+17,
+ 3.326325410056661e+17,
+ 3.32976754800993e+17,
+ 3.3319682689075654e+17,
+ 3.333114663703342e+17,
+ 3.333366204791668e+17,
+ 3.332858725073262e+17,
+ 3.331707873420125e+17,
+ 3.3300120975678624e+17,
+ 3.3278552069020934e+17,
+ 3.325308566056332e+17,
+ 3.322432966946062e+17,
+ 3.319280222669887e+17,
+ 3.315894522167183e+17,
+ 3.31231357998432e+17,
+ 3.308569611179469e+17,
+ 3.304690157406602e+17,
+ 3.300698786616609e+17,
+ 3.296615685611911e+17,
+ 3.2924581618800666e+17,
+ 3.288241068686598e+17,
+ 3.2839771652957235e+17,
+ 3.2796774223744435e+17,
+ 3.275351281085987e+17,
+ 3.271006873058874e+17,
+ 3.2666512072974803e+17,
+ 3.2622903291511296e+17,
+ 3.2579294556561664e+17,
+ 3.2535730908884525e+17,
+ 3.249224982684324e+17,
+ 3.244888569206653e+17,
+ 3.2405668223940326e+17,
+ 3.236262244858278e+17,
+ 3.2319769953504006e+17,
+ 3.227712934116456e+17,
+ 3.22347166191095e+17,
+ 3.219254553603287e+17,
+ 3.2150627871695424e+17,
+ 3.210897368740363e+17,
+ 3.2067591542741376e+17,
+ 3.202648868338333e+17,
+ 3.198567120409589e+17,
+ 3.19451441904167e+17,
+ 3.190491184198753e+17,
+ 3.186497758007563e+17,
+ 3.1825344141450534e+17,
+ 3.178601366046735e+17,
+ 3.174698774094042e+17,
+ 3.1708267519167014e+17,
+ 3.166985371926715e+17,
+ 3.1631746701840864e+17,
+ 3.1593946506808256e+17,
+ 3.1556452891173523e+17,
+ 3.151926536235753e+17,
+ 3.1482383207651834e+17,
+ 3.1445805520277523e+17,
+ 3.140953122246476e+17,
+ 3.1373559085913184e+17,
+ 3.1337887749952186e+17,
+ 3.130251573767114e+17,
+ 3.126744147026179e+17,
+ 3.123266327978007e+17,
+ 3.119817942051087e+17,
+ 3.1163988079097114e+17,
+ 3.113008738357073e+17,
+ 3.109647541141207e+17,
+ 3.106315019674411e+17,
+ 3.103010973675901e+17,
+ 3.099735199746016e+17,
+ 3.096487491879422e+17,
+ 3.0932676419239776e+17,
+ 3.0900753972786e+17,
+ 3.0869105054967526e+17,
+ 3.083772840437199e+17,
+ 3.080662189016621e+17,
+ 3.0775783376675834e+17,
+ 3.074521072573213e+17,
+ 3.071490179876445e+17,
+ 3.068485445867482e+17,
+ 3.0655066571506963e+17,
+ 3.0625536007936736e+17,
+ 3.0596260644602336e+17,
+ 3.056723836528408e+17,
+ 3.0538467061958035e+17,
+ 3.050994463572906e+17,
+ 3.048166899765865e+17,
+ 3.0453638069496154e+17,
+ 3.042584978432657e+17,
+ 3.039830208713851e+17,
+ 3.0370992935322266e+17,
+ 3.0343920299108154e+17,
+ 3.0317082161944416e+17,
+ 3.029047652082736e+17,
+ 3.0264101386582874e+17,
+ 3.0237954784109037e+17,
+ 3.021203475258075e+17,
+ 3.018633934561758e+17,
+ 3.0160866631429037e+17,
+ 3.013561469292451e+17,
+ 3.011058162780258e+17,
+ 3.0085765548619405e+17,
+ 3.0061164582834656e+17,
+ 3.003677687284272e+17,
+ 3.0012600575984256e+17,
+ 2.9988633864545626e+17,
+ 2.996487492574651e+17,
+ 2.994132196171548e+17,
+ 2.991797318945194e+17,
+ 2.989482684078314e+17,
+ 2.98718811623132e+17,
+ 2.9849134415361574e+17,
+ 2.982658487589408e+17,
+ 2.980423083445655e+17,
+ 2.9782070596092915e+17,
+ 2.7247030199525245e+17
+ ],
+ "vtor": [
+ 100000.0,
+ 99544.32023364124,
+ 98251.15453696062,
+ 96235.68685722632,
+ 93614.68356191639,
+ 90502.18847954353,
+ 87006.32501749854,
+ 83227.06508922808,
+ 79254.813872946,
+ 75169.66123127713,
+ 71041.16042746486,
+ 66928.50919629741,
+ 62881.02482158773,
+ 58938.821939433255,
+ 55133.61820859918,
+ 51489.60808192722,
+ 48024.35830839606,
+ 44749.69035052268,
+ 41672.524623402256,
+ 38795.66945343124,
+ 36118.54407642795,
+ 33637.83003375026,
+ 31348.04917610031,
+ 29242.06933764292,
+ 27311.54077408969,
+ 25547.26782590489,
+ 23939.521110407513,
+ 22478.295982958116,
+ 21153.523137258686,
+ 19955.237120191036,
+ 18873.708284120235,
+ 17899.54334214529,
+ 17023.759270761642,
+ 16237.834851443324,
+ 15533.743681380842,
+ 14903.972031120154,
+ 14341.524495030524,
+ 13839.919977172622,
+ 13393.180184865832,
+ 12995.812467288095,
+ 12642.788537234375,
+ 12329.520349892675,
+ 12051.83418147994,
+ 11805.94375056095,
+ 11588.423053275488,
+ 11396.179437797053,
+ 11226.42732039882,
+ 11076.662842842592,
+ 10944.639685904545,
+ 10828.34618435543,
+ 10725.983832469563,
+ 10635.94722420132,
+ 10556.805436804136,
+ 10487.284839339893,
+ 10426.253286892172,
+ 10372.705646187464,
+ 10325.750587737686,
+ 10284.598572685094,
+ 10248.550958525679,
+ 10216.990146193662,
+ 10189.370691092356,
+ 10165.211302127113,
+ 10144.087655281786,
+ 10125.625951492917,
+ 10109.49715228246,
+ 10095.411830623676,
+ 10083.115578687914,
+ 10072.384918337477,
+ 10063.023664403154,
+ 10054.85969484832,
+ 10047.742085826912,
+ 10041.538573356505,
+ 10036.133306828673,
+ 10031.424862854412,
+ 10027.3244909875,
+ 10023.75456568367,
+ 10020.647221443161,
+ 10017.943150456194,
+ 10015.59054423511,
+ 10013.544162684711,
+ 10011.764515845945,
+ 10010.217145160046,
+ 10008.871992553453,
+ 10007.702846950711,
+ 10006.686858995241,
+ 10005.804115808194,
+ 10005.037268554323,
+ 10004.371206421612,
+ 10003.792771367725,
+ 10003.29050865027,
+ 10002.85444874773,
+ 10002.475916801126,
+ 10002.14736617021,
+ 10001.86223310832,
+ 10001.614809922945,
+ 10001.400134309408,
+ 10001.213892828007,
+ 10001.052336744104,
+ 10000.912208670363,
+ 10000.790678643563,
+ 10000.68528843837,
+ 10000.593903069897,
+ 10000.514668568,
+ 10000.445975221452,
+ 10000.386425591105,
+ 10000.334806679686,
+ 10000.290065723417,
+ 10000.25128913859,
+ 10000.217684215675,
+ 10000.188563205464,
+ 10000.16332948734,
+ 10000.141465549392,
+ 10000.122522544827,
+ 10000.106111219531,
+ 10000.091894031972,
+ 10000.079578309811,
+ 10000.068910307727,
+ 10000.05967004848,
+ 10000.051666844598,
+ 10000.044735411424,
+ 10000.038732493818,
+ 10000.033533939033,
+ 10000.029032157028,
+ 10000.02513391718,
+ 10000.021758437058,
+ 10000.018835724715,
+ 10000.016305140998,
+ 10000.01411415281,
+ 10000.012217252064,
+ 10000.010575018385,
+ 10000.009153306504,
+ 10000.007922541854,
+ 10000.00685710995,
+ 10000.005934827166,
+ 10000.005136482061,
+ 10000.004445437868,
+ 10000.003847288048,
+ 10000.003329557814,
+ 10000.002881445527,
+ 10000.00249359863,
+ 10000.002157919536,
+ 10000.001867397486,
+ 10000.001615962863,
+ 10000.001398361033,
+ 10000.001210043049,
+ 10000.001047070993,
+ 10000.000906036008,
+ 10000.000783987294,
+ 10000.000678370623,
+ 10000.000586975104,
+ 10000.000507887078,
+ 10000.000439450198,
+ 10000.000380230858,
+ 10000.000328988277,
+ 10000.000284648579,
+ 10000.000246282361,
+ 10000.000213085277,
+ 10000.00018436122,
+ 10000.000159507772,
+ 10000.000138003594,
+ 10000.000119397531,
+ 10000.000103299173,
+ 10000.000089370667,
+ 10000.000077319659,
+ 10000.000066893168,
+ 10000.000057872281,
+ 10000.000050067574,
+ 10000.00004331514,
+ 10000.00003747315,
+ 10000.000032418886,
+ 10000.000028046165,
+ 10000.00002426311,
+ 10000.000020990228,
+ 10000.000018158735,
+ 10000.00001570912,
+ 10000.000013589894,
+ 10000.000011756505,
+ 10000.00001017041,
+ 10000.00000879826,
+ 10000.000007611205,
+ 10000.00000658428,
+ 10000.000005695889,
+ 10000.000004927346,
+ 10000.000004262487,
+ 10000.000003687326,
+ 10000.000003189763,
+ 10000.000002759334,
+ 10000.000002386978,
+ 10000.000002064864,
+ 10000.000001786213,
+ 10000.00000154516,
+ 10000.000001336637,
+ 10000.00000115625,
+ 10000.000001000204,
+ 10000.000000865217,
+ 10000.000000748445,
+ 10000.000000647431,
+ 10000.00000056005,
+ 10000.000000484462,
+ 10000.000000419075,
+ 10000.000000362512,
+ 10000.000000313583,
+ 10000.000000271257,
+ 10000.000000234644,
+ 10000.000000202972,
+ 10000.000000175574,
+ 10000.000000151877,
+ 10000.000000131377,
+ 10000.000000113641,
+ 10000.000000098302,
+ 10000.000000085032,
+ 10000.000000073554,
+ 10000.000000063626,
+ 10000.000000055037,
+ 10000.000000047608,
+ 10000.000000041182,
+ 10000.000000035621,
+ 10000.000000030814,
+ 10000.000000026654,
+ 10000.000000023056,
+ 10000.000000019943,
+ 10000.000000017251,
+ 10000.000000014923,
+ 10000.000000012908,
+ 10000.000000011165,
+ 10000.000000009659,
+ 10000.000000008355,
+ 10000.000000007227,
+ 10000.00000000625,
+ 10000.000000005406,
+ 10000.000000004677,
+ 10000.000000004045,
+ 10000.0000000035,
+ 10000.000000003027,
+ 10000.000000002618,
+ 10000.000000002265,
+ 10000.000000001959,
+ 10000.000000001695,
+ 10000.000000001466,
+ 10000.000000001268,
+ 10000.000000001097,
+ 10000.00000000095,
+ 10000.00000000082,
+ 10000.00000000071,
+ 10000.000000000615,
+ 10000.000000000531,
+ 10000.00000000046,
+ 10000.000000000397,
+ 10000.000000000344,
+ 10000.000000000296,
+ 10000.000000000256,
+ 10000.000000000222,
+ 10000.000000000193,
+ 10000.000000000167,
+ 10000.000000000144,
+ 10000.0
+ ],
+ "vpol": [
+ 18462.326927732716,
+ 18514.99979366994,
+ 18565.939231880784,
+ 18615.197379613106,
+ 18662.8251518226,
+ 18708.87224398403,
+ 18753.38713728863,
+ 18796.417106004,
+ 18838.008226787257,
+ 18878.20538975573,
+ 18917.052311132516,
+ 18954.591547296637,
+ 18990.864510079347,
+ 19025.91148315922,
+ 19059.7716394193,
+ 19092.483059139577,
+ 19124.08274890752,
+ 19154.60666113828,
+ 19184.089714104663,
+ 19212.565812384706,
+ 19240.067867642374,
+ 19266.627819663598,
+ 19292.27665757659,
+ 19317.044441191432,
+ 19340.960322399642,
+ 19364.052566579816,
+ 19386.34857396039,
+ 19407.874900895215,
+ 19428.65728101207,
+ 19448.720646198086,
+ 19468.08914739,
+ 19486.78617514046,
+ 19504.834379934928,
+ 19522.2556922367,
+ 19539.07134224024,
+ 19555.301879315663,
+ 19570.96719112952,
+ 19586.08652242914,
+ 19600.678493479918,
+ 19614.761118146518,
+ 19628.351821610984,
+ 19641.467457721887,
+ 19654.124325970388,
+ 19666.33818809011,
+ 19678.124284279074,
+ 19689.497349042842,
+ 19700.47162665909,
+ 19711.060886264648,
+ 19721.278436566783,
+ 19731.137140181316,
+ 19740.649427600623,
+ 19749.827310795343,
+ 19758.68239645382,
+ 19767.225898864108,
+ 19775.4686524434,
+ 19783.421123920307,
+ 19791.093424175622,
+ 19798.49531974744,
+ 19805.63624400677,
+ 19812.52530800986,
+ 19819.171311033715,
+ 19825.582750801284,
+ 19831.76783340299,
+ 19837.73448292125,
+ 19843.49035076469,
+ 19849.042824718887,
+ 19854.399037720275,
+ 19859.565876360022,
+ 19864.549989124593,
+ 19869.357794379575,
+ 19873.99548810352,
+ 19878.469051378208,
+ 19882.78425764191,
+ 19886.946679712015,
+ 19890.961696583312,
+ 19894.83450000816,
+ 19898.570100864654,
+ 19902.173335318803,
+ 19905.64887078662,
+ 19909.00121170188,
+ 19912.234705095303,
+ 19915.353545990587,
+ 19918.361782622906,
+ 19921.263321485007,
+ 19924.061932206263,
+ 19926.76125226966,
+ 19929.36479157172,
+ 19931.875936830187,
+ 19934.297955844206,
+ 19936.634001611572,
+ 19938.887116307546,
+ 19941.060235129582,
+ 19943.156190012254,
+ 19945.17771321644,
+ 19947.12744079687,
+ 19949.00791595186,
+ 19950.821592259108,
+ 19952.570836801166,
+ 19954.25793318425,
+ 19955.885084453774,
+ 19957.454415910102,
+ 19958.967977827684,
+ 19960.427748080827,
+ 19961.835634679162,
+ 19963.193478215824,
+ 19964.503054231183,
+ 19965.76607549503,
+ 19966.984194209857,
+ 19968.159004137942,
+ 19969.292042654735,
+ 19970.384792731096,
+ 19971.438684846682,
+ 19972.455098836952,
+ 19973.435365675872,
+ 19974.380769196654,
+ 19975.29254775252,
+ 19976.1718958196,
+ 19977.019965543906,
+ 19977.83786823432,
+ 19978.6266758034,
+ 19979.38742215782,
+ 19980.121104540183,
+ 19980.828684823875,
+ 19981.511090762506,
+ 19982.169217195635,
+ 19982.80392721215,
+ 19983.41605327286,
+ 19984.006398293674,
+ 19984.575736690727,
+ 19985.124815388765,
+ 19985.654354794107,
+ 19986.165049733347,
+ 19986.657570359053,
+ 19987.132563023555,
+ 19987.590651121973,
+ 19988.03243590553,
+ 19988.458497266216,
+ 19988.869394493737,
+ 19989.265667005842,
+ 19989.647835052798,
+ 19990.01640039704,
+ 19990.371846968832,
+ 19990.714641498744,
+ 19991.045234127785,
+ 19991.36405899601,
+ 19991.67153481026,
+ 19991.968065391884,
+ 19992.254040205054,
+ 19992.52983486641,
+ 19992.795811636643,
+ 19993.05231989471,
+ 19993.299696595244,
+ 19993.538266709777,
+ 19993.768343652326,
+ 19993.9902296899,
+ 19994.2042163385,
+ 19994.410584745023,
+ 19994.60960605568,
+ 19994.801541771343,
+ 19994.986644090288,
+ 19995.165156238767,
+ 19995.33731278991,
+ 19995.503339971237,
+ 19995.66345596134,
+ 19995.817871175987,
+ 19995.96678854407,
+ 19996.110403773815,
+ 19996.248905609486,
+ 19996.38247607898,
+ 19996.511290732687,
+ 19996.6355188738,
+ 19996.75532378048,
+ 19996.870862920143,
+ 19996.98228815611,
+ 19997.089745946923,
+ 19997.1933775386,
+ 19997.29331915003,
+ 19997.389702151813,
+ 19997.482653238705,
+ 19997.572294595982,
+ 19997.65874405985,
+ 19997.74211527218,
+ 19997.822517829743,
+ 19997.90005742811,
+ 19997.974836000485,
+ 19998.046951851553,
+ 19998.11649978661,
+ 19998.183571236077,
+ 19998.248254375594,
+ 19998.31063424184,
+ 19998.370792844253,
+ 19998.42880927274,
+ 19998.4847598016,
+ 19998.538717989708,
+ 19998.590754777182,
+ 19998.64093857857,
+ 19998.68933537273,
+ 19998.736008789543,
+ 19998.78102019351,
+ 19998.824428764387,
+ 19998.866291574945,
+ 19998.906663665974,
+ 19998.945598118597,
+ 19998.983146124054,
+ 19999.019357050955,
+ 19999.054278510157,
+ 19999.087956417356,
+ 19999.120435053414,
+ 19999.151757122556,
+ 19999.181963808518,
+ 19999.21109482865,
+ 19999.239188486128,
+ 19999.26628172031,
+ 19999.292410155274,
+ 19999.317608146655,
+ 19999.34190882679,
+ 19999.36534414829,
+ 19999.387944926013,
+ 19999.409740877607,
+ 19999.430760662537,
+ 19999.451031919776,
+ 19999.470581304155,
+ 19999.489434521372,
+ 19999.5076163618,
+ 19999.525150733072,
+ 19999.54206069153,
+ 19999.558368472495,
+ 19999.57409551955,
+ 19999.58926251268,
+ 19999.603889395497,
+ 19999.61799540144,
+ 19999.63159907907,
+ 19999.644718316464,
+ 19999.657370364694,
+ 19999.669571860562,
+ 19999.681338848437,
+ 19999.69268680136,
+ 19999.703630641383,
+ 19999.7141847592,
+ 19999.72436303305,
+ 19999.73417884697,
+ 19999.743645108418,
+ 19999.752774265195,
+ 19999.76157832185,
+ 19999.770068855447,
+ 19999.778257030794,
+ 19999.78615361512,
+ 19999.793768992236,
+ 19999.801113176174,
+ 19999.808195824375,
+ 19999.815026250366,
+ 19999.82161343603,
+ 19999.827966043387,
+ 19999.834092426012,
+ 19999.84000064,
+ 20000.0
+ ],
+ "vnorm": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "element": "carbon",
+ "charge": 4
+}
\ No newline at end of file
diff --git a/cherab/generomak/plasma/data/core/carbon5.json b/cherab/generomak/plasma/data/core/carbon5.json
new file mode 100644
index 00000000..b62ee60a
--- /dev/null
+++ b/cherab/generomak/plasma/data/core/carbon5.json
@@ -0,0 +1,1294 @@
+{
+ "temperature": [
+ 2800.0,
+ 2795.6140361201715,
+ 2783.083337747409,
+ 2763.3003486616526,
+ 2737.094135213008,
+ 2705.2322750926364,
+ 2668.4232152414806,
+ 2627.3189416606197,
+ 2582.5178419123567,
+ 2534.5676700076638,
+ 2483.96854551181,
+ 2431.1759357517954,
+ 2376.6035832043513,
+ 2320.6263503869714,
+ 2263.5829625419237,
+ 2205.7786346035323,
+ 2147.4875737595085,
+ 2088.955352654985,
+ 2030.4011511730957,
+ 1972.019866937452,
+ 1913.9840963599631,
+ 1856.4459893126868,
+ 1799.5389814222144,
+ 1743.3794086390585,
+ 1688.0680091781107,
+ 1633.691318203845,
+ 1580.3229607811295,
+ 1528.0248486579108,
+ 1476.8482864126447,
+ 1426.8349924056063,
+ 1378.018039834137,
+ 1330.4227230192646,
+ 1284.0673538547676,
+ 1238.963993137122,
+ 1195.1191212721988,
+ 1152.5342526267314,
+ 1111.2064975634503,
+ 1071.1290759712253,
+ 1032.291785877979,
+ 994.6814305162284,
+ 958.2822070001829,
+ 923.0760595703174,
+ 889.0430001669228,
+ 856.1613989086177,
+ 824.4082468755387,
+ 793.759393429837,
+ 764.1897601482588,
+ 735.6735332927431,
+ 708.1843366049751,
+ 681.6953860793737,
+ 656.1796282458071,
+ 631.6098633780208,
+ 607.9588549360606,
+ 585.1994264504128,
+ 563.3045469619041,
+ 542.2474060441687,
+ 522.0014793543342,
+ 502.5405855822321,
+ 483.8389355984452,
+ 465.8711745366052,
+ 448.61241748523827,
+ 432.0382794087496,
+ 416.124899865624,
+ 400.8489630442867,
+ 386.1877135930409,
+ 372.11896867986945,
+ 358.6211266803817,
+ 345.67317285760663,
+ 333.2546823654665,
+ 321.34582087841227,
+ 309.927343122692,
+ 298.9805895598673,
+ 288.4874814503533,
+ 278.4305145037626,
+ 268.79275130356683,
+ 259.5578126759042,
+ 250.7098681561356,
+ 242.23362569190442,
+ 234.11432070782254,
+ 226.33770464446184,
+ 218.89003307292606,
+ 211.75805347586066,
+ 204.92899277624957,
+ 198.39054468665884,
+ 192.13085694367678,
+ 186.13851848507585,
+ 180.40254662065936,
+ 174.91237424177845,
+ 169.65783710907806,
+ 164.62916125309604,
+ 159.8169505178761,
+ 155.21217427370195,
+ 150.80615532139907,
+ 146.59055800733688,
+ 142.55737656528729,
+ 138.69892369858735,
+ 135.00781941365733,
+ 131.47698011372418,
+ 128.09960795968092,
+ 124.86918050324817,
+ 121.77944059606116,
+ 118.82438657692074,
+ 115.99826273821829,
+ 113.29555007145385,
+ 110.71095729082082,
+ 108.23941213297381,
+ 105.87605293038021,
+ 103.6162204549953,
+ 101.45545002847112,
+ 99.38946389462029,
+ 97.41416384945612,
+ 95.52562412379939,
+ 93.72008451315051,
+ 91.99394374930452,
+ 90.34375310799985,
+ 88.7662102467457,
+ 87.25815326688075,
+ 85.81655499383113,
+ 84.43851746950027,
+ 83.12126665071017,
+ 81.86214730760918,
+ 80.65861811600642,
+ 79.5082469376184,
+ 78.408706282292,
+ 77.35776894632689,
+ 76.35330382111951,
+ 75.39327186643368,
+ 74.47572224272074,
+ 73.59878859700572,
+ 72.76068549699494,
+ 71.95970500815942,
+ 71.19421340869229,
+ 70.46264803735373,
+ 69.7635142693571,
+ 69.0953826155724,
+ 68.45688594046604,
+ 67.84671679431725,
+ 67.26362485539421,
+ 66.70641447789761,
+ 66.17394234161189,
+ 65.6651151993376,
+ 65.1788877182984,
+ 64.7142604118468,
+ 64.27027765791827,
+ 63.84602580079542,
+ 63.440631332874815,
+ 63.05325915323381,
+ 62.68311089991544,
+ 62.32942335295714,
+ 61.9914669052981,
+ 61.66854409880293,
+ 61.359988222742814,
+ 61.065161972176995,
+ 60.78345616376737,
+ 60.51428850665944,
+ 60.2571024261477,
+ 60.01136593793548,
+ 59.776570570881596,
+ 59.55223033620793,
+ 59.33788074122536,
+ 59.13307784570519,
+ 58.937397359105915,
+ 58.75043377692946,
+ 58.571799554551646,
+ 58.40112431694312,
+ 58.23805410275451,
+ 58.08225064130303,
+ 57.93339066106313,
+ 57.7911652283102,
+ 57.65527911463285,
+ 57.525450192074885,
+ 57.40140885472106,
+ 57.28289746559213,
+ 57.16966982775895,
+ 57.06149067863122,
+ 56.95813520642253,
+ 56.85938858783372,
+ 56.765045546033065,
+ 56.674909928059456,
+ 56.588794300802036,
+ 56.50651956475268,
+ 56.427914584755875,
+ 56.35281583702141,
+ 56.281067071686564,
+ 56.21251899025332,
+ 56.14702893725086,
+ 56.08446060550164,
+ 56.02468375439783,
+ 55.96757394061782,
+ 55.91301226073971,
+ 55.8608851052287,
+ 55.81108392330204,
+ 55.76350499819346,
+ 55.718049232360165,
+ 55.67462194219673,
+ 55.63313266183696,
+ 55.593494955645,
+ 55.55562623901411,
+ 55.51944760710454,
+ 55.484883671174465,
+ 55.45186240216659,
+ 55.42031498123234,
+ 55.390175656886,
+ 55.361381608497936,
+ 55.333872815845915,
+ 55.307591934457406,
+ 55.282484176486456,
+ 55.258497196881336,
+ 55.23558098460842,
+ 55.21368775870917,
+ 55.19277186897538,
+ 55.17278970103895,
+ 55.153699585681665,
+ 55.13546171217539,
+ 55.11803804547773,
+ 55.101392247108336,
+ 55.08548959954608,
+ 55.070296933989404,
+ 55.05578256132999,
+ 55.04191620619953,
+ 55.028668943950365,
+ 55.01601314044173,
+ 55.003922394507015,
+ 54.99237148298145,
+ 54.98133630817787,
+ 54.970793847702375,
+ 54.96072210650347,
+ 54.951100071057624,
+ 54.941907665596375,
+ 54.93312571028218,
+ 54.9247358812481,
+ 54.91672067241873,
+ 54.90906335903125,
+ 54.90174796278291,
+ 54.8947592185312,
+ 54.888082542479076,
+ 54.881704001777535,
+ 54.87561028548313,
+ 54.869788676811275,
+ 54.86422702662521,
+ 54.858913728107794,
+ 54.85383769256265,
+ 54.84898832629396,
+ 54.8443555085177,
+ 54.83992957025756,
+ 54.83570127418218,
+ 54.83166179534185,
+ 54.82780270276455,
+ 54.824115941872016,
+ 54.82059381768116,
+ 54.81722897875463,
+ 54.81401440186672,
+ 54.81094337735412,
+ 54.80800949511986,
+ 54.80520663126194,
+ 54.7452478101525
+ ],
+ "density": [
+ 161024132134966.47,
+ 160653503219502.1,
+ 160507242359572.56,
+ 160667836607887.75,
+ 161159174288638.38,
+ 161989547325367.2,
+ 163160868851305.97,
+ 164672538431461.94,
+ 166523370342109.3,
+ 168712636114736.53,
+ 171240653439960.9,
+ 174109128869520.62,
+ 177321363766464.66,
+ 180882384938404.34,
+ 184799035962934.97,
+ 189080051019599.56,
+ 193736124830517.1,
+ 198779987453727.56,
+ 204226489773322.7,
+ 210092703809260.47,
+ 216398040979350.88,
+ 223164390920621.16,
+ 230416283256009.7,
+ 238181074678749.84,
+ 246488677361616.25,
+ 255347696083510.9,
+ 264777740351847.78,
+ 274822297666057.56,
+ 285530597548920.0,
+ 296958209680815.56,
+ 309167755802187.0,
+ 322229722682802.0,
+ 336223391977405.75,
+ 351237037130031.44,
+ 367316468989557.44,
+ 384512645316222.44,
+ 402912558128665.9,
+ 422611765562034.25,
+ 443715236374775.9,
+ 466338364535512.5,
+ 490608107464424.5,
+ 516664263896114.6,
+ 544660909569018.25,
+ 574771346195028.4,
+ 607182200712998.2,
+ 641993775762799.1,
+ 679285757098039.9,
+ 719329437626251.1,
+ 762435817884073.2,
+ 808959351131308.6,
+ 859304387830781.4,
+ 913932717589034.6,
+ 973372418549912.6,
+ 1038228266498749.4,
+ 1108965758582219.4,
+ 1185530665811968.8,
+ 1268623485069471.2,
+ 1359148843563016.0,
+ 1458160473424394.8,
+ 1566887347887052.8,
+ 1686765177753372.5,
+ 1819474480244125.5,
+ 1966944277299036.2,
+ 2129644809721581.0,
+ 2308435409989728.5,
+ 2505507727432574.0,
+ 2723405054905318.5,
+ 2965083298551671.5,
+ 3233983555918746.0,
+ 3534118624816150.5,
+ 3870176221435777.5,
+ 4247642221714308.5,
+ 4672947861350066.0,
+ 5153645539587730.0,
+ 5698618664034045.0,
+ 6317959266999076.0,
+ 7015040256490839.0,
+ 7797878657778269.0,
+ 8680238046734384.0,
+ 9678419565046922.0,
+ 1.0811736328238992e+16,
+ 1.2103072275208854e+16,
+ 1.35795351531977e+16,
+ 1.5273210653384718e+16,
+ 1.7222019001933152e+16,
+ 1.9470878411506988e+16,
+ 2.206058988419503e+16,
+ 2.5010246550634016e+16,
+ 2.8374503295553108e+16,
+ 3.221862128793027e+16,
+ 3.6616618204665976e+16,
+ 4.1651074122496936e+16,
+ 4.74120543092295e+16,
+ 5.399462249641901e+16,
+ 6.143726358298171e+16,
+ 6.9713794415034904e+16,
+ 7.88602209992365e+16,
+ 8.889182371626213e+16,
+ 9.979072697762856e+16,
+ 1.1149427025010378e+17,
+ 1.2388317531927544e+17,
+ 1.3677125579435957e+17,
+ 1.4989901351691597e+17,
+ 1.6293374324877622e+17,
+ 1.7547842758551754e+17,
+ 1.8709055180135395e+17,
+ 1.9727096976715142e+17,
+ 2.055969980363844e+17,
+ 2.1184190259838147e+17,
+ 2.1585866802009814e+17,
+ 2.175780909076306e+17,
+ 2.1700505602378323e+17,
+ 2.142110900199348e+17,
+ 2.0932504552875306e+17,
+ 2.02523454416483e+17,
+ 1.940214986495018e+17,
+ 1.8406488653204474e+17,
+ 1.7292237180532278e+17,
+ 1.609070270228471e+17,
+ 1.485192170274923e+17,
+ 1.3607450007252114e+17,
+ 1.2380272018238762e+17,
+ 1.1189501743619742e+17,
+ 1.0050487014189278e+17,
+ 8.974958274849342e+16,
+ 7.971243093411478e+16,
+ 7.04455417952653e+16,
+ 6.197344649530697e+16,
+ 5.42978817655598e+16,
+ 4.7399830330996056e+16,
+ 4.124606771225955e+16,
+ 3.579255597379613e+16,
+ 3.098812762090215e+16,
+ 2.677841934624266e+16,
+ 2.313267459153055e+16,
+ 1.9995837148790244e+16,
+ 1.7299828713764886e+16,
+ 1.498424019897001e+16,
+ 1.2995976233140328e+16,
+ 1.1288719115750174e+16,
+ 9822303083643866.0,
+ 8562060401319240.0,
+ 7478179071658524.0,
+ 6545096357996279.0,
+ 5740941409601873.0,
+ 5047032901085019.0,
+ 4447432774883569.5,
+ 3928554174161130.5,
+ 3478819914604156.5,
+ 3088366959685935.5,
+ 2748792041830096.0,
+ 2452933605216769.0,
+ 2194685492053311.5,
+ 1968838156523490.2,
+ 1770943605623496.8,
+ 1597200692861872.5,
+ 1444357804385388.5,
+ 1309630363135666.2,
+ 1190630927952283.8,
+ 1085309978444810.6,
+ 991905753181653.0,
+ 908901750211121.1,
+ 834990707915531.6,
+ 769044064015345.5,
+ 710086044389402.1,
+ 657271664609963.1,
+ 609868038549173.2,
+ 567238482949368.1,
+ 528828986803599.75,
+ 494156681915552.7,
+ 462801819568105.44,
+ 434394305887636.3,
+ 408610314143343.06,
+ 385166603830043.2,
+ 363814226223222.2,
+ 344334005110715.2,
+ 326532652735273.4,
+ 310239427130823.75,
+ 295303251427072.06,
+ 281590227809429.2,
+ 268981489039979.28,
+ 257371339064654.56,
+ 246665641500495.62,
+ 236780420950391.28,
+ 227640647282167.97,
+ 219179177413892.6,
+ 211335832859303.44,
+ 204056594461261.25,
+ 197292898404320.6,
+ 191001019886732.9,
+ 185141532760857.62,
+ 179678835102545.62,
+ 174580732073686.62,
+ 169818068643664.22,
+ 165364405752635.5,
+ 161195734386968.4,
+ 157290222775333.8,
+ 153627992565845.03,
+ 150190920391755.9,
+ 146962461710962.6,
+ 143927494208912.38,
+ 141072178412878.78,
+ 138383833459875.8,
+ 135850826229914.27,
+ 133462472282759.86,
+ 131208947226407.88,
+ 129081207321019.44,
+ 127070918269517.56,
+ 125170391272622.27,
+ 123372525535675.33,
+ 121670756518192.75,
+ 120059009296409.5,
+ 118531668753453.81,
+ 117083525311571.0,
+ 115709710318728.34,
+ 114405725785893.33,
+ 113167389473178.39,
+ 111990809312097.34,
+ 110872360170072.14,
+ 109808662725540.33,
+ 108796564236592.3,
+ 107833121017659.64,
+ 106915582459347.52,
+ 106041376431703.06,
+ 105208095947617.9,
+ 104413486959420.16,
+ 103655437183194.61,
+ 102931965854681.19,
+ 102241214329040.6,
+ 101581437448067.73,
+ 100950995603730.38,
+ 100348347436377.56,
+ 99772043108404.7,
+ 99220718105874.52,
+ 98693087518270.73,
+ 98187940757455.16,
+ 97704136675393.52,
+ 97240599050432.17,
+ 96796312405593.72,
+ 96370318136411.11,
+ 95961710919354.02,
+ 95569635379466.4,
+ 95193282993472.34,
+ 94831889213877.6,
+ 94484730792535.0,
+ 94151123288018.19,
+ 93830418746832.02,
+ 93522003537859.14,
+ 93225296336143.55,
+ 92939746236089.92,
+ 92664830994011.1,
+ 92400055380555.25,
+ 92144949643312.14,
+ 91899068064388.0,
+ 91661987613690.53,
+ 80088749700966.69
+ ],
+ "vtor": [
+ 100000.0,
+ 99544.32023364124,
+ 98251.15453696062,
+ 96235.68685722632,
+ 93614.68356191639,
+ 90502.18847954353,
+ 87006.32501749854,
+ 83227.06508922808,
+ 79254.813872946,
+ 75169.66123127713,
+ 71041.16042746486,
+ 66928.50919629741,
+ 62881.02482158773,
+ 58938.821939433255,
+ 55133.61820859918,
+ 51489.60808192722,
+ 48024.35830839606,
+ 44749.69035052268,
+ 41672.524623402256,
+ 38795.66945343124,
+ 36118.54407642795,
+ 33637.83003375026,
+ 31348.04917610031,
+ 29242.06933764292,
+ 27311.54077408969,
+ 25547.26782590489,
+ 23939.521110407513,
+ 22478.295982958116,
+ 21153.523137258686,
+ 19955.237120191036,
+ 18873.708284120235,
+ 17899.54334214529,
+ 17023.759270761642,
+ 16237.834851443324,
+ 15533.743681380842,
+ 14903.972031120154,
+ 14341.524495030524,
+ 13839.919977172622,
+ 13393.180184865832,
+ 12995.812467288095,
+ 12642.788537234375,
+ 12329.520349892675,
+ 12051.83418147994,
+ 11805.94375056095,
+ 11588.423053275488,
+ 11396.179437797053,
+ 11226.42732039882,
+ 11076.662842842592,
+ 10944.639685904545,
+ 10828.34618435543,
+ 10725.983832469563,
+ 10635.94722420132,
+ 10556.805436804136,
+ 10487.284839339893,
+ 10426.253286892172,
+ 10372.705646187464,
+ 10325.750587737686,
+ 10284.598572685094,
+ 10248.550958525679,
+ 10216.990146193662,
+ 10189.370691092356,
+ 10165.211302127113,
+ 10144.087655281786,
+ 10125.625951492917,
+ 10109.49715228246,
+ 10095.411830623676,
+ 10083.115578687914,
+ 10072.384918337477,
+ 10063.023664403154,
+ 10054.85969484832,
+ 10047.742085826912,
+ 10041.538573356505,
+ 10036.133306828673,
+ 10031.424862854412,
+ 10027.3244909875,
+ 10023.75456568367,
+ 10020.647221443161,
+ 10017.943150456194,
+ 10015.59054423511,
+ 10013.544162684711,
+ 10011.764515845945,
+ 10010.217145160046,
+ 10008.871992553453,
+ 10007.702846950711,
+ 10006.686858995241,
+ 10005.804115808194,
+ 10005.037268554323,
+ 10004.371206421612,
+ 10003.792771367725,
+ 10003.29050865027,
+ 10002.85444874773,
+ 10002.475916801126,
+ 10002.14736617021,
+ 10001.86223310832,
+ 10001.614809922945,
+ 10001.400134309408,
+ 10001.213892828007,
+ 10001.052336744104,
+ 10000.912208670363,
+ 10000.790678643563,
+ 10000.68528843837,
+ 10000.593903069897,
+ 10000.514668568,
+ 10000.445975221452,
+ 10000.386425591105,
+ 10000.334806679686,
+ 10000.290065723417,
+ 10000.25128913859,
+ 10000.217684215675,
+ 10000.188563205464,
+ 10000.16332948734,
+ 10000.141465549392,
+ 10000.122522544827,
+ 10000.106111219531,
+ 10000.091894031972,
+ 10000.079578309811,
+ 10000.068910307727,
+ 10000.05967004848,
+ 10000.051666844598,
+ 10000.044735411424,
+ 10000.038732493818,
+ 10000.033533939033,
+ 10000.029032157028,
+ 10000.02513391718,
+ 10000.021758437058,
+ 10000.018835724715,
+ 10000.016305140998,
+ 10000.01411415281,
+ 10000.012217252064,
+ 10000.010575018385,
+ 10000.009153306504,
+ 10000.007922541854,
+ 10000.00685710995,
+ 10000.005934827166,
+ 10000.005136482061,
+ 10000.004445437868,
+ 10000.003847288048,
+ 10000.003329557814,
+ 10000.002881445527,
+ 10000.00249359863,
+ 10000.002157919536,
+ 10000.001867397486,
+ 10000.001615962863,
+ 10000.001398361033,
+ 10000.001210043049,
+ 10000.001047070993,
+ 10000.000906036008,
+ 10000.000783987294,
+ 10000.000678370623,
+ 10000.000586975104,
+ 10000.000507887078,
+ 10000.000439450198,
+ 10000.000380230858,
+ 10000.000328988277,
+ 10000.000284648579,
+ 10000.000246282361,
+ 10000.000213085277,
+ 10000.00018436122,
+ 10000.000159507772,
+ 10000.000138003594,
+ 10000.000119397531,
+ 10000.000103299173,
+ 10000.000089370667,
+ 10000.000077319659,
+ 10000.000066893168,
+ 10000.000057872281,
+ 10000.000050067574,
+ 10000.00004331514,
+ 10000.00003747315,
+ 10000.000032418886,
+ 10000.000028046165,
+ 10000.00002426311,
+ 10000.000020990228,
+ 10000.000018158735,
+ 10000.00001570912,
+ 10000.000013589894,
+ 10000.000011756505,
+ 10000.00001017041,
+ 10000.00000879826,
+ 10000.000007611205,
+ 10000.00000658428,
+ 10000.000005695889,
+ 10000.000004927346,
+ 10000.000004262487,
+ 10000.000003687326,
+ 10000.000003189763,
+ 10000.000002759334,
+ 10000.000002386978,
+ 10000.000002064864,
+ 10000.000001786213,
+ 10000.00000154516,
+ 10000.000001336637,
+ 10000.00000115625,
+ 10000.000001000204,
+ 10000.000000865217,
+ 10000.000000748445,
+ 10000.000000647431,
+ 10000.00000056005,
+ 10000.000000484462,
+ 10000.000000419075,
+ 10000.000000362512,
+ 10000.000000313583,
+ 10000.000000271257,
+ 10000.000000234644,
+ 10000.000000202972,
+ 10000.000000175574,
+ 10000.000000151877,
+ 10000.000000131377,
+ 10000.000000113641,
+ 10000.000000098302,
+ 10000.000000085032,
+ 10000.000000073554,
+ 10000.000000063626,
+ 10000.000000055037,
+ 10000.000000047608,
+ 10000.000000041182,
+ 10000.000000035621,
+ 10000.000000030814,
+ 10000.000000026654,
+ 10000.000000023056,
+ 10000.000000019943,
+ 10000.000000017251,
+ 10000.000000014923,
+ 10000.000000012908,
+ 10000.000000011165,
+ 10000.000000009659,
+ 10000.000000008355,
+ 10000.000000007227,
+ 10000.00000000625,
+ 10000.000000005406,
+ 10000.000000004677,
+ 10000.000000004045,
+ 10000.0000000035,
+ 10000.000000003027,
+ 10000.000000002618,
+ 10000.000000002265,
+ 10000.000000001959,
+ 10000.000000001695,
+ 10000.000000001466,
+ 10000.000000001268,
+ 10000.000000001097,
+ 10000.00000000095,
+ 10000.00000000082,
+ 10000.00000000071,
+ 10000.000000000615,
+ 10000.000000000531,
+ 10000.00000000046,
+ 10000.000000000397,
+ 10000.000000000344,
+ 10000.000000000296,
+ 10000.000000000256,
+ 10000.000000000222,
+ 10000.000000000193,
+ 10000.000000000167,
+ 10000.000000000144,
+ 10000.0
+ ],
+ "vpol": [
+ 18462.326927732716,
+ 18514.99979366994,
+ 18565.939231880784,
+ 18615.197379613106,
+ 18662.8251518226,
+ 18708.87224398403,
+ 18753.38713728863,
+ 18796.417106004,
+ 18838.008226787257,
+ 18878.20538975573,
+ 18917.052311132516,
+ 18954.591547296637,
+ 18990.864510079347,
+ 19025.91148315922,
+ 19059.7716394193,
+ 19092.483059139577,
+ 19124.08274890752,
+ 19154.60666113828,
+ 19184.089714104663,
+ 19212.565812384706,
+ 19240.067867642374,
+ 19266.627819663598,
+ 19292.27665757659,
+ 19317.044441191432,
+ 19340.960322399642,
+ 19364.052566579816,
+ 19386.34857396039,
+ 19407.874900895215,
+ 19428.65728101207,
+ 19448.720646198086,
+ 19468.08914739,
+ 19486.78617514046,
+ 19504.834379934928,
+ 19522.2556922367,
+ 19539.07134224024,
+ 19555.301879315663,
+ 19570.96719112952,
+ 19586.08652242914,
+ 19600.678493479918,
+ 19614.761118146518,
+ 19628.351821610984,
+ 19641.467457721887,
+ 19654.124325970388,
+ 19666.33818809011,
+ 19678.124284279074,
+ 19689.497349042842,
+ 19700.47162665909,
+ 19711.060886264648,
+ 19721.278436566783,
+ 19731.137140181316,
+ 19740.649427600623,
+ 19749.827310795343,
+ 19758.68239645382,
+ 19767.225898864108,
+ 19775.4686524434,
+ 19783.421123920307,
+ 19791.093424175622,
+ 19798.49531974744,
+ 19805.63624400677,
+ 19812.52530800986,
+ 19819.171311033715,
+ 19825.582750801284,
+ 19831.76783340299,
+ 19837.73448292125,
+ 19843.49035076469,
+ 19849.042824718887,
+ 19854.399037720275,
+ 19859.565876360022,
+ 19864.549989124593,
+ 19869.357794379575,
+ 19873.99548810352,
+ 19878.469051378208,
+ 19882.78425764191,
+ 19886.946679712015,
+ 19890.961696583312,
+ 19894.83450000816,
+ 19898.570100864654,
+ 19902.173335318803,
+ 19905.64887078662,
+ 19909.00121170188,
+ 19912.234705095303,
+ 19915.353545990587,
+ 19918.361782622906,
+ 19921.263321485007,
+ 19924.061932206263,
+ 19926.76125226966,
+ 19929.36479157172,
+ 19931.875936830187,
+ 19934.297955844206,
+ 19936.634001611572,
+ 19938.887116307546,
+ 19941.060235129582,
+ 19943.156190012254,
+ 19945.17771321644,
+ 19947.12744079687,
+ 19949.00791595186,
+ 19950.821592259108,
+ 19952.570836801166,
+ 19954.25793318425,
+ 19955.885084453774,
+ 19957.454415910102,
+ 19958.967977827684,
+ 19960.427748080827,
+ 19961.835634679162,
+ 19963.193478215824,
+ 19964.503054231183,
+ 19965.76607549503,
+ 19966.984194209857,
+ 19968.159004137942,
+ 19969.292042654735,
+ 19970.384792731096,
+ 19971.438684846682,
+ 19972.455098836952,
+ 19973.435365675872,
+ 19974.380769196654,
+ 19975.29254775252,
+ 19976.1718958196,
+ 19977.019965543906,
+ 19977.83786823432,
+ 19978.6266758034,
+ 19979.38742215782,
+ 19980.121104540183,
+ 19980.828684823875,
+ 19981.511090762506,
+ 19982.169217195635,
+ 19982.80392721215,
+ 19983.41605327286,
+ 19984.006398293674,
+ 19984.575736690727,
+ 19985.124815388765,
+ 19985.654354794107,
+ 19986.165049733347,
+ 19986.657570359053,
+ 19987.132563023555,
+ 19987.590651121973,
+ 19988.03243590553,
+ 19988.458497266216,
+ 19988.869394493737,
+ 19989.265667005842,
+ 19989.647835052798,
+ 19990.01640039704,
+ 19990.371846968832,
+ 19990.714641498744,
+ 19991.045234127785,
+ 19991.36405899601,
+ 19991.67153481026,
+ 19991.968065391884,
+ 19992.254040205054,
+ 19992.52983486641,
+ 19992.795811636643,
+ 19993.05231989471,
+ 19993.299696595244,
+ 19993.538266709777,
+ 19993.768343652326,
+ 19993.9902296899,
+ 19994.2042163385,
+ 19994.410584745023,
+ 19994.60960605568,
+ 19994.801541771343,
+ 19994.986644090288,
+ 19995.165156238767,
+ 19995.33731278991,
+ 19995.503339971237,
+ 19995.66345596134,
+ 19995.817871175987,
+ 19995.96678854407,
+ 19996.110403773815,
+ 19996.248905609486,
+ 19996.38247607898,
+ 19996.511290732687,
+ 19996.6355188738,
+ 19996.75532378048,
+ 19996.870862920143,
+ 19996.98228815611,
+ 19997.089745946923,
+ 19997.1933775386,
+ 19997.29331915003,
+ 19997.389702151813,
+ 19997.482653238705,
+ 19997.572294595982,
+ 19997.65874405985,
+ 19997.74211527218,
+ 19997.822517829743,
+ 19997.90005742811,
+ 19997.974836000485,
+ 19998.046951851553,
+ 19998.11649978661,
+ 19998.183571236077,
+ 19998.248254375594,
+ 19998.31063424184,
+ 19998.370792844253,
+ 19998.42880927274,
+ 19998.4847598016,
+ 19998.538717989708,
+ 19998.590754777182,
+ 19998.64093857857,
+ 19998.68933537273,
+ 19998.736008789543,
+ 19998.78102019351,
+ 19998.824428764387,
+ 19998.866291574945,
+ 19998.906663665974,
+ 19998.945598118597,
+ 19998.983146124054,
+ 19999.019357050955,
+ 19999.054278510157,
+ 19999.087956417356,
+ 19999.120435053414,
+ 19999.151757122556,
+ 19999.181963808518,
+ 19999.21109482865,
+ 19999.239188486128,
+ 19999.26628172031,
+ 19999.292410155274,
+ 19999.317608146655,
+ 19999.34190882679,
+ 19999.36534414829,
+ 19999.387944926013,
+ 19999.409740877607,
+ 19999.430760662537,
+ 19999.451031919776,
+ 19999.470581304155,
+ 19999.489434521372,
+ 19999.5076163618,
+ 19999.525150733072,
+ 19999.54206069153,
+ 19999.558368472495,
+ 19999.57409551955,
+ 19999.58926251268,
+ 19999.603889395497,
+ 19999.61799540144,
+ 19999.63159907907,
+ 19999.644718316464,
+ 19999.657370364694,
+ 19999.669571860562,
+ 19999.681338848437,
+ 19999.69268680136,
+ 19999.703630641383,
+ 19999.7141847592,
+ 19999.72436303305,
+ 19999.73417884697,
+ 19999.743645108418,
+ 19999.752774265195,
+ 19999.76157832185,
+ 19999.770068855447,
+ 19999.778257030794,
+ 19999.78615361512,
+ 19999.793768992236,
+ 19999.801113176174,
+ 19999.808195824375,
+ 19999.815026250366,
+ 19999.82161343603,
+ 19999.827966043387,
+ 19999.834092426012,
+ 19999.84000064,
+ 20000.0
+ ],
+ "vnorm": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "element": "carbon",
+ "charge": 5
+}
\ No newline at end of file
diff --git a/cherab/generomak/plasma/data/core/carbon6.json b/cherab/generomak/plasma/data/core/carbon6.json
new file mode 100644
index 00000000..4c824909
--- /dev/null
+++ b/cherab/generomak/plasma/data/core/carbon6.json
@@ -0,0 +1,1294 @@
+{
+ "temperature": [
+ 2800.0,
+ 2795.6140361201715,
+ 2783.083337747409,
+ 2763.3003486616526,
+ 2737.094135213008,
+ 2705.2322750926364,
+ 2668.4232152414806,
+ 2627.3189416606197,
+ 2582.5178419123567,
+ 2534.5676700076638,
+ 2483.96854551181,
+ 2431.1759357517954,
+ 2376.6035832043513,
+ 2320.6263503869714,
+ 2263.5829625419237,
+ 2205.7786346035323,
+ 2147.4875737595085,
+ 2088.955352654985,
+ 2030.4011511730957,
+ 1972.019866937452,
+ 1913.9840963599631,
+ 1856.4459893126868,
+ 1799.5389814222144,
+ 1743.3794086390585,
+ 1688.0680091781107,
+ 1633.691318203845,
+ 1580.3229607811295,
+ 1528.0248486579108,
+ 1476.8482864126447,
+ 1426.8349924056063,
+ 1378.018039834137,
+ 1330.4227230192646,
+ 1284.0673538547676,
+ 1238.963993137122,
+ 1195.1191212721988,
+ 1152.5342526267314,
+ 1111.2064975634503,
+ 1071.1290759712253,
+ 1032.291785877979,
+ 994.6814305162284,
+ 958.2822070001829,
+ 923.0760595703174,
+ 889.0430001669228,
+ 856.1613989086177,
+ 824.4082468755387,
+ 793.759393429837,
+ 764.1897601482588,
+ 735.6735332927431,
+ 708.1843366049751,
+ 681.6953860793737,
+ 656.1796282458071,
+ 631.6098633780208,
+ 607.9588549360606,
+ 585.1994264504128,
+ 563.3045469619041,
+ 542.2474060441687,
+ 522.0014793543342,
+ 502.5405855822321,
+ 483.8389355984452,
+ 465.8711745366052,
+ 448.61241748523827,
+ 432.0382794087496,
+ 416.124899865624,
+ 400.8489630442867,
+ 386.1877135930409,
+ 372.11896867986945,
+ 358.6211266803817,
+ 345.67317285760663,
+ 333.2546823654665,
+ 321.34582087841227,
+ 309.927343122692,
+ 298.9805895598673,
+ 288.4874814503533,
+ 278.4305145037626,
+ 268.79275130356683,
+ 259.5578126759042,
+ 250.7098681561356,
+ 242.23362569190442,
+ 234.11432070782254,
+ 226.33770464446184,
+ 218.89003307292606,
+ 211.75805347586066,
+ 204.92899277624957,
+ 198.39054468665884,
+ 192.13085694367678,
+ 186.13851848507585,
+ 180.40254662065936,
+ 174.91237424177845,
+ 169.65783710907806,
+ 164.62916125309604,
+ 159.8169505178761,
+ 155.21217427370195,
+ 150.80615532139907,
+ 146.59055800733688,
+ 142.55737656528729,
+ 138.69892369858735,
+ 135.00781941365733,
+ 131.47698011372418,
+ 128.09960795968092,
+ 124.86918050324817,
+ 121.77944059606116,
+ 118.82438657692074,
+ 115.99826273821829,
+ 113.29555007145385,
+ 110.71095729082082,
+ 108.23941213297381,
+ 105.87605293038021,
+ 103.6162204549953,
+ 101.45545002847112,
+ 99.38946389462029,
+ 97.41416384945612,
+ 95.52562412379939,
+ 93.72008451315051,
+ 91.99394374930452,
+ 90.34375310799985,
+ 88.7662102467457,
+ 87.25815326688075,
+ 85.81655499383113,
+ 84.43851746950027,
+ 83.12126665071017,
+ 81.86214730760918,
+ 80.65861811600642,
+ 79.5082469376184,
+ 78.408706282292,
+ 77.35776894632689,
+ 76.35330382111951,
+ 75.39327186643368,
+ 74.47572224272074,
+ 73.59878859700572,
+ 72.76068549699494,
+ 71.95970500815942,
+ 71.19421340869229,
+ 70.46264803735373,
+ 69.7635142693571,
+ 69.0953826155724,
+ 68.45688594046604,
+ 67.84671679431725,
+ 67.26362485539421,
+ 66.70641447789761,
+ 66.17394234161189,
+ 65.6651151993376,
+ 65.1788877182984,
+ 64.7142604118468,
+ 64.27027765791827,
+ 63.84602580079542,
+ 63.440631332874815,
+ 63.05325915323381,
+ 62.68311089991544,
+ 62.32942335295714,
+ 61.9914669052981,
+ 61.66854409880293,
+ 61.359988222742814,
+ 61.065161972176995,
+ 60.78345616376737,
+ 60.51428850665944,
+ 60.2571024261477,
+ 60.01136593793548,
+ 59.776570570881596,
+ 59.55223033620793,
+ 59.33788074122536,
+ 59.13307784570519,
+ 58.937397359105915,
+ 58.75043377692946,
+ 58.571799554551646,
+ 58.40112431694312,
+ 58.23805410275451,
+ 58.08225064130303,
+ 57.93339066106313,
+ 57.7911652283102,
+ 57.65527911463285,
+ 57.525450192074885,
+ 57.40140885472106,
+ 57.28289746559213,
+ 57.16966982775895,
+ 57.06149067863122,
+ 56.95813520642253,
+ 56.85938858783372,
+ 56.765045546033065,
+ 56.674909928059456,
+ 56.588794300802036,
+ 56.50651956475268,
+ 56.427914584755875,
+ 56.35281583702141,
+ 56.281067071686564,
+ 56.21251899025332,
+ 56.14702893725086,
+ 56.08446060550164,
+ 56.02468375439783,
+ 55.96757394061782,
+ 55.91301226073971,
+ 55.8608851052287,
+ 55.81108392330204,
+ 55.76350499819346,
+ 55.718049232360165,
+ 55.67462194219673,
+ 55.63313266183696,
+ 55.593494955645,
+ 55.55562623901411,
+ 55.51944760710454,
+ 55.484883671174465,
+ 55.45186240216659,
+ 55.42031498123234,
+ 55.390175656886,
+ 55.361381608497936,
+ 55.333872815845915,
+ 55.307591934457406,
+ 55.282484176486456,
+ 55.258497196881336,
+ 55.23558098460842,
+ 55.21368775870917,
+ 55.19277186897538,
+ 55.17278970103895,
+ 55.153699585681665,
+ 55.13546171217539,
+ 55.11803804547773,
+ 55.101392247108336,
+ 55.08548959954608,
+ 55.070296933989404,
+ 55.05578256132999,
+ 55.04191620619953,
+ 55.028668943950365,
+ 55.01601314044173,
+ 55.003922394507015,
+ 54.99237148298145,
+ 54.98133630817787,
+ 54.970793847702375,
+ 54.96072210650347,
+ 54.951100071057624,
+ 54.941907665596375,
+ 54.93312571028218,
+ 54.9247358812481,
+ 54.91672067241873,
+ 54.90906335903125,
+ 54.90174796278291,
+ 54.8947592185312,
+ 54.888082542479076,
+ 54.881704001777535,
+ 54.87561028548313,
+ 54.869788676811275,
+ 54.86422702662521,
+ 54.858913728107794,
+ 54.85383769256265,
+ 54.84898832629396,
+ 54.8443555085177,
+ 54.83992957025756,
+ 54.83570127418218,
+ 54.83166179534185,
+ 54.82780270276455,
+ 54.824115941872016,
+ 54.82059381768116,
+ 54.81722897875463,
+ 54.81401440186672,
+ 54.81094337735412,
+ 54.80800949511986,
+ 54.80520663126194,
+ 54.7452478101525
+ ],
+ "density": [
+ 4.9983892951576294e+17,
+ 4.983879497133105e+17,
+ 4.967755866140605e+17,
+ 4.9510985466990605e+17,
+ 4.9341581359634624e+17,
+ 4.9170556331941075e+17,
+ 4.89986255096533e+17,
+ 4.8826259422505344e+17,
+ 4.86537891784407e+17,
+ 4.848145870922532e+17,
+ 4.8309453749605005e+17,
+ 4.8137919232444864e+17,
+ 4.796697037214771e+17,
+ 4.7796700064309997e+17,
+ 4.762718401528628e+17,
+ 4.745848440962568e+17,
+ 4.7290652600562976e+17,
+ 4.71237311271517e+17,
+ 4.695775525472951e+17,
+ 4.6792754170000864e+17,
+ 4.6628751920653805e+17,
+ 4.646576816249229e+17,
+ 4.63038187590711e+17,
+ 4.6142916266522874e+17,
+ 4.598307037636062e+17,
+ 4.582429064892481e+17,
+ 4.5666583570714464e+17,
+ 4.5509951511611744e+17,
+ 4.535439474786944e+17,
+ 4.519991158057632e+17,
+ 4.504649841775356e+17,
+ 4.4894149825499296e+17,
+ 4.474285854993411e+17,
+ 4.4592615597774957e+17,
+ 4.4443415477814e+17,
+ 4.42952515097652e+17,
+ 4.414811279853572e+17,
+ 4.400198704534008e+17,
+ 4.3856860516097184e+17,
+ 4.3712717986695616e+17,
+ 4.356954267048369e+17,
+ 4.3427316126968966e+17,
+ 4.3286018150378886e+17,
+ 4.314562255858729e+17,
+ 4.3006107253038886e+17,
+ 4.28674584595776e+17,
+ 4.272966235432586e+17,
+ 4.259268569438572e+17,
+ 4.2456491049926803e+17,
+ 4.23210364386893e+17,
+ 4.218627468670139e+17,
+ 4.205215267547799e+17,
+ 4.191861045425703e+17,
+ 4.178558019143855e+17,
+ 4.165300783172122e+17,
+ 4.152089127552762e+17,
+ 4.138915252178627e+17,
+ 4.1257692847745683e+17,
+ 4.112639828847147e+17,
+ 4.099513696238169e+17,
+ 4.0863755841905824e+17,
+ 4.0732076842764634e+17,
+ 4.059989634281084e+17,
+ 4.046715679784462e+17,
+ 4.0333761021624723e+17,
+ 4.0199477060236544e+17,
+ 4.006403654855438e+17,
+ 3.992712831648083e+17,
+ 3.978839075577596e+17,
+ 3.9647402693668077e+17,
+ 3.950367246761433e+17,
+ 3.935662483399666e+17,
+ 3.920558527100581e+17,
+ 3.9049761151576006e+17,
+ 3.888821916572605e+17,
+ 3.871989618946227e+17,
+ 3.854440535692542e+17,
+ 3.83608792883725e+17,
+ 3.816785306952975e+17,
+ 3.7963586382173274e+17,
+ 3.774600978175744e+17,
+ 3.751266060486219e+17,
+ 3.726060693144332e+17,
+ 3.69863581102174e+17,
+ 3.668576069457651e+17,
+ 3.635385522314936e+17,
+ 3.5986031537030906e+17,
+ 3.557990082407581e+17,
+ 3.5129187163841626e+17,
+ 3.462630238193415e+17,
+ 3.406247132754573e+17,
+ 3.342765850451636e+17,
+ 3.2710558017180826e+17,
+ 3.189869600468432e+17,
+ 3.098538368048117e+17,
+ 2.997091691578431e+17,
+ 2.884763976878227e+17,
+ 2.7609146834775462e+17,
+ 2.6251483616307402e+17,
+ 2.4774269151380362e+17,
+ 2.318189253723286e+17,
+ 2.1484628655656454e+17,
+ 1.9699454486519517e+17,
+ 1.7850310137509254e+17,
+ 1.596756834262952e+17,
+ 1.4086575956198934e+17,
+ 1.2257942351734243e+17,
+ 1.0536119643932915e+17,
+ 8.945080677375304e+16,
+ 7.501077534396101e+16,
+ 6.213221597889738e+16,
+ 5.083876796328754e+16,
+ 4.109548571419219e+16,
+ 3.282073395211112e+16,
+ 2.58991771483556e+16,
+ 2.0194309163133372e+16,
+ 1.5559472132032808e+16,
+ 1.1846815437393852e+16,
+ 8918871356669974.0,
+ 6666488619767974.0,
+ 4952272490160231.0,
+ 3656693545661167.5,
+ 2684245219410593.0,
+ 1959293800683820.2,
+ 1422454462508854.5,
+ 1027495920737416.9,
+ 738735260847582.1,
+ 528869852835632.25,
+ 377246151542587.9,
+ 268208188769288.22,
+ 190158286219365.4,
+ 134519749871650.16,
+ 94999138095081.17,
+ 67016838139886.77,
+ 47388925728580.2,
+ 33655594842202.37,
+ 24010931117580.105,
+ 17211131680797.598,
+ 12397388136261.445,
+ 8975069389548.232,
+ 6531215810353.063,
+ 4778109970512.45,
+ 3514609743151.2197,
+ 2599594904029.761,
+ 1933687843450.649,
+ 1446636619284.179,
+ 1088581422766.1594,
+ 823990834577.6648,
+ 627438327748.4506,
+ 480650770721.95197,
+ 370438747494.49036,
+ 287240088062.0348,
+ 224091191132.38284,
+ 175897776716.16806,
+ 138915940488.82767,
+ 110381427410.77623,
+ 88243745695.27124,
+ 70974708829.00201,
+ 57430010951.75191,
+ 46748736133.543,
+ 38280102857.815254,
+ 31529840224.19217,
+ 26120769367.413773,
+ 21763705170.207542,
+ 18235884795.813892,
+ 15364908451.932526,
+ 13016733283.730207,
+ 11086658506.895058,
+ 9492528928.261642,
+ 8169588216.710768,
+ 7066704039.21469,
+ 6142970302.393482,
+ 5365759572.048553,
+ 4708966109.732259,
+ 4151558497.112541,
+ 3676522729.535672,
+ 3270038222.3734403,
+ 2920833184.218933,
+ 2619678032.075184,
+ 2358985990.8214483,
+ 2132496850.038897,
+ 1935025513.2003684,
+ 1762261779.2242439,
+ 1610609664.5842507,
+ 1477058481.0535715,
+ 1359078978.4888785,
+ 1254538959.6238554,
+ 1161635237.9576263,
+ 1078837828.5027132,
+ 1004844373.7736144,
+ 938543019.4518695,
+ 878981608.3420769,
+ 825342214.7196075,
+ 776920444.1419855,
+ 733107745.1355531,
+ 693376953.2984082,
+ 657270432.3485224,
+ 624389409.1422876,
+ 594385987.3914045,
+ 566955686.755834,
+ 541831025.8088642,
+ 518777281.941817,
+ 497587285.0481517,
+ 478077997.69254464,
+ 460087497.62123114,
+ 443471967.2421416,
+ 428103642.58286554,
+ 413868620.92078733,
+ 400665191.04849786,
+ 388402498.0855996,
+ 376998969.9038688,
+ 366381412.1133349,
+ 356484284.95387477,
+ 347248113.25952405,
+ 338619246.9022559,
+ 330549123.4969663,
+ 322993975.0574306,
+ 315913999.852501,
+ 309273169.99934995,
+ 303038445.91674054,
+ 297179891.09289044,
+ 291670181.76515394,
+ 286484267.6975641,
+ 281599400.4746377,
+ 276994518.5718484,
+ 272650410.9427122,
+ 268549411.96215296,
+ 264675181.73834926,
+ 261012759.79181898,
+ 257548445.94359872,
+ 254269423.21526513,
+ 251163844.2373063,
+ 248220801.75397795,
+ 245430340.81520307,
+ 242782931.8616595,
+ 240269948.92623258,
+ 237883261.9877548,
+ 235615478.3775228,
+ 233459505.95959592,
+ 231408820.5941001,
+ 229457393.87108496,
+ 227599572.65190783,
+ 225830024.39467406,
+ 224143772.6216756,
+ 222536269.81091282,
+ 221003094.60468093,
+ 219540278.05436647,
+ 218143888.0390999,
+ 216810518.66811267,
+ 215536728.0802908,
+ 214319215.59609443,
+ 213155316.59152457,
+ 212042071.98700914,
+ 210976871.09200314,
+ 209957208.5307115,
+ 173744949.17023906
+ ],
+ "vtor": [
+ 100000.0,
+ 99544.32023364124,
+ 98251.15453696062,
+ 96235.68685722632,
+ 93614.68356191639,
+ 90502.18847954353,
+ 87006.32501749854,
+ 83227.06508922808,
+ 79254.813872946,
+ 75169.66123127713,
+ 71041.16042746486,
+ 66928.50919629741,
+ 62881.02482158773,
+ 58938.821939433255,
+ 55133.61820859918,
+ 51489.60808192722,
+ 48024.35830839606,
+ 44749.69035052268,
+ 41672.524623402256,
+ 38795.66945343124,
+ 36118.54407642795,
+ 33637.83003375026,
+ 31348.04917610031,
+ 29242.06933764292,
+ 27311.54077408969,
+ 25547.26782590489,
+ 23939.521110407513,
+ 22478.295982958116,
+ 21153.523137258686,
+ 19955.237120191036,
+ 18873.708284120235,
+ 17899.54334214529,
+ 17023.759270761642,
+ 16237.834851443324,
+ 15533.743681380842,
+ 14903.972031120154,
+ 14341.524495030524,
+ 13839.919977172622,
+ 13393.180184865832,
+ 12995.812467288095,
+ 12642.788537234375,
+ 12329.520349892675,
+ 12051.83418147994,
+ 11805.94375056095,
+ 11588.423053275488,
+ 11396.179437797053,
+ 11226.42732039882,
+ 11076.662842842592,
+ 10944.639685904545,
+ 10828.34618435543,
+ 10725.983832469563,
+ 10635.94722420132,
+ 10556.805436804136,
+ 10487.284839339893,
+ 10426.253286892172,
+ 10372.705646187464,
+ 10325.750587737686,
+ 10284.598572685094,
+ 10248.550958525679,
+ 10216.990146193662,
+ 10189.370691092356,
+ 10165.211302127113,
+ 10144.087655281786,
+ 10125.625951492917,
+ 10109.49715228246,
+ 10095.411830623676,
+ 10083.115578687914,
+ 10072.384918337477,
+ 10063.023664403154,
+ 10054.85969484832,
+ 10047.742085826912,
+ 10041.538573356505,
+ 10036.133306828673,
+ 10031.424862854412,
+ 10027.3244909875,
+ 10023.75456568367,
+ 10020.647221443161,
+ 10017.943150456194,
+ 10015.59054423511,
+ 10013.544162684711,
+ 10011.764515845945,
+ 10010.217145160046,
+ 10008.871992553453,
+ 10007.702846950711,
+ 10006.686858995241,
+ 10005.804115808194,
+ 10005.037268554323,
+ 10004.371206421612,
+ 10003.792771367725,
+ 10003.29050865027,
+ 10002.85444874773,
+ 10002.475916801126,
+ 10002.14736617021,
+ 10001.86223310832,
+ 10001.614809922945,
+ 10001.400134309408,
+ 10001.213892828007,
+ 10001.052336744104,
+ 10000.912208670363,
+ 10000.790678643563,
+ 10000.68528843837,
+ 10000.593903069897,
+ 10000.514668568,
+ 10000.445975221452,
+ 10000.386425591105,
+ 10000.334806679686,
+ 10000.290065723417,
+ 10000.25128913859,
+ 10000.217684215675,
+ 10000.188563205464,
+ 10000.16332948734,
+ 10000.141465549392,
+ 10000.122522544827,
+ 10000.106111219531,
+ 10000.091894031972,
+ 10000.079578309811,
+ 10000.068910307727,
+ 10000.05967004848,
+ 10000.051666844598,
+ 10000.044735411424,
+ 10000.038732493818,
+ 10000.033533939033,
+ 10000.029032157028,
+ 10000.02513391718,
+ 10000.021758437058,
+ 10000.018835724715,
+ 10000.016305140998,
+ 10000.01411415281,
+ 10000.012217252064,
+ 10000.010575018385,
+ 10000.009153306504,
+ 10000.007922541854,
+ 10000.00685710995,
+ 10000.005934827166,
+ 10000.005136482061,
+ 10000.004445437868,
+ 10000.003847288048,
+ 10000.003329557814,
+ 10000.002881445527,
+ 10000.00249359863,
+ 10000.002157919536,
+ 10000.001867397486,
+ 10000.001615962863,
+ 10000.001398361033,
+ 10000.001210043049,
+ 10000.001047070993,
+ 10000.000906036008,
+ 10000.000783987294,
+ 10000.000678370623,
+ 10000.000586975104,
+ 10000.000507887078,
+ 10000.000439450198,
+ 10000.000380230858,
+ 10000.000328988277,
+ 10000.000284648579,
+ 10000.000246282361,
+ 10000.000213085277,
+ 10000.00018436122,
+ 10000.000159507772,
+ 10000.000138003594,
+ 10000.000119397531,
+ 10000.000103299173,
+ 10000.000089370667,
+ 10000.000077319659,
+ 10000.000066893168,
+ 10000.000057872281,
+ 10000.000050067574,
+ 10000.00004331514,
+ 10000.00003747315,
+ 10000.000032418886,
+ 10000.000028046165,
+ 10000.00002426311,
+ 10000.000020990228,
+ 10000.000018158735,
+ 10000.00001570912,
+ 10000.000013589894,
+ 10000.000011756505,
+ 10000.00001017041,
+ 10000.00000879826,
+ 10000.000007611205,
+ 10000.00000658428,
+ 10000.000005695889,
+ 10000.000004927346,
+ 10000.000004262487,
+ 10000.000003687326,
+ 10000.000003189763,
+ 10000.000002759334,
+ 10000.000002386978,
+ 10000.000002064864,
+ 10000.000001786213,
+ 10000.00000154516,
+ 10000.000001336637,
+ 10000.00000115625,
+ 10000.000001000204,
+ 10000.000000865217,
+ 10000.000000748445,
+ 10000.000000647431,
+ 10000.00000056005,
+ 10000.000000484462,
+ 10000.000000419075,
+ 10000.000000362512,
+ 10000.000000313583,
+ 10000.000000271257,
+ 10000.000000234644,
+ 10000.000000202972,
+ 10000.000000175574,
+ 10000.000000151877,
+ 10000.000000131377,
+ 10000.000000113641,
+ 10000.000000098302,
+ 10000.000000085032,
+ 10000.000000073554,
+ 10000.000000063626,
+ 10000.000000055037,
+ 10000.000000047608,
+ 10000.000000041182,
+ 10000.000000035621,
+ 10000.000000030814,
+ 10000.000000026654,
+ 10000.000000023056,
+ 10000.000000019943,
+ 10000.000000017251,
+ 10000.000000014923,
+ 10000.000000012908,
+ 10000.000000011165,
+ 10000.000000009659,
+ 10000.000000008355,
+ 10000.000000007227,
+ 10000.00000000625,
+ 10000.000000005406,
+ 10000.000000004677,
+ 10000.000000004045,
+ 10000.0000000035,
+ 10000.000000003027,
+ 10000.000000002618,
+ 10000.000000002265,
+ 10000.000000001959,
+ 10000.000000001695,
+ 10000.000000001466,
+ 10000.000000001268,
+ 10000.000000001097,
+ 10000.00000000095,
+ 10000.00000000082,
+ 10000.00000000071,
+ 10000.000000000615,
+ 10000.000000000531,
+ 10000.00000000046,
+ 10000.000000000397,
+ 10000.000000000344,
+ 10000.000000000296,
+ 10000.000000000256,
+ 10000.000000000222,
+ 10000.000000000193,
+ 10000.000000000167,
+ 10000.000000000144,
+ 10000.0
+ ],
+ "vpol": [
+ 18462.326927732716,
+ 18514.99979366994,
+ 18565.939231880784,
+ 18615.197379613106,
+ 18662.8251518226,
+ 18708.87224398403,
+ 18753.38713728863,
+ 18796.417106004,
+ 18838.008226787257,
+ 18878.20538975573,
+ 18917.052311132516,
+ 18954.591547296637,
+ 18990.864510079347,
+ 19025.91148315922,
+ 19059.7716394193,
+ 19092.483059139577,
+ 19124.08274890752,
+ 19154.60666113828,
+ 19184.089714104663,
+ 19212.565812384706,
+ 19240.067867642374,
+ 19266.627819663598,
+ 19292.27665757659,
+ 19317.044441191432,
+ 19340.960322399642,
+ 19364.052566579816,
+ 19386.34857396039,
+ 19407.874900895215,
+ 19428.65728101207,
+ 19448.720646198086,
+ 19468.08914739,
+ 19486.78617514046,
+ 19504.834379934928,
+ 19522.2556922367,
+ 19539.07134224024,
+ 19555.301879315663,
+ 19570.96719112952,
+ 19586.08652242914,
+ 19600.678493479918,
+ 19614.761118146518,
+ 19628.351821610984,
+ 19641.467457721887,
+ 19654.124325970388,
+ 19666.33818809011,
+ 19678.124284279074,
+ 19689.497349042842,
+ 19700.47162665909,
+ 19711.060886264648,
+ 19721.278436566783,
+ 19731.137140181316,
+ 19740.649427600623,
+ 19749.827310795343,
+ 19758.68239645382,
+ 19767.225898864108,
+ 19775.4686524434,
+ 19783.421123920307,
+ 19791.093424175622,
+ 19798.49531974744,
+ 19805.63624400677,
+ 19812.52530800986,
+ 19819.171311033715,
+ 19825.582750801284,
+ 19831.76783340299,
+ 19837.73448292125,
+ 19843.49035076469,
+ 19849.042824718887,
+ 19854.399037720275,
+ 19859.565876360022,
+ 19864.549989124593,
+ 19869.357794379575,
+ 19873.99548810352,
+ 19878.469051378208,
+ 19882.78425764191,
+ 19886.946679712015,
+ 19890.961696583312,
+ 19894.83450000816,
+ 19898.570100864654,
+ 19902.173335318803,
+ 19905.64887078662,
+ 19909.00121170188,
+ 19912.234705095303,
+ 19915.353545990587,
+ 19918.361782622906,
+ 19921.263321485007,
+ 19924.061932206263,
+ 19926.76125226966,
+ 19929.36479157172,
+ 19931.875936830187,
+ 19934.297955844206,
+ 19936.634001611572,
+ 19938.887116307546,
+ 19941.060235129582,
+ 19943.156190012254,
+ 19945.17771321644,
+ 19947.12744079687,
+ 19949.00791595186,
+ 19950.821592259108,
+ 19952.570836801166,
+ 19954.25793318425,
+ 19955.885084453774,
+ 19957.454415910102,
+ 19958.967977827684,
+ 19960.427748080827,
+ 19961.835634679162,
+ 19963.193478215824,
+ 19964.503054231183,
+ 19965.76607549503,
+ 19966.984194209857,
+ 19968.159004137942,
+ 19969.292042654735,
+ 19970.384792731096,
+ 19971.438684846682,
+ 19972.455098836952,
+ 19973.435365675872,
+ 19974.380769196654,
+ 19975.29254775252,
+ 19976.1718958196,
+ 19977.019965543906,
+ 19977.83786823432,
+ 19978.6266758034,
+ 19979.38742215782,
+ 19980.121104540183,
+ 19980.828684823875,
+ 19981.511090762506,
+ 19982.169217195635,
+ 19982.80392721215,
+ 19983.41605327286,
+ 19984.006398293674,
+ 19984.575736690727,
+ 19985.124815388765,
+ 19985.654354794107,
+ 19986.165049733347,
+ 19986.657570359053,
+ 19987.132563023555,
+ 19987.590651121973,
+ 19988.03243590553,
+ 19988.458497266216,
+ 19988.869394493737,
+ 19989.265667005842,
+ 19989.647835052798,
+ 19990.01640039704,
+ 19990.371846968832,
+ 19990.714641498744,
+ 19991.045234127785,
+ 19991.36405899601,
+ 19991.67153481026,
+ 19991.968065391884,
+ 19992.254040205054,
+ 19992.52983486641,
+ 19992.795811636643,
+ 19993.05231989471,
+ 19993.299696595244,
+ 19993.538266709777,
+ 19993.768343652326,
+ 19993.9902296899,
+ 19994.2042163385,
+ 19994.410584745023,
+ 19994.60960605568,
+ 19994.801541771343,
+ 19994.986644090288,
+ 19995.165156238767,
+ 19995.33731278991,
+ 19995.503339971237,
+ 19995.66345596134,
+ 19995.817871175987,
+ 19995.96678854407,
+ 19996.110403773815,
+ 19996.248905609486,
+ 19996.38247607898,
+ 19996.511290732687,
+ 19996.6355188738,
+ 19996.75532378048,
+ 19996.870862920143,
+ 19996.98228815611,
+ 19997.089745946923,
+ 19997.1933775386,
+ 19997.29331915003,
+ 19997.389702151813,
+ 19997.482653238705,
+ 19997.572294595982,
+ 19997.65874405985,
+ 19997.74211527218,
+ 19997.822517829743,
+ 19997.90005742811,
+ 19997.974836000485,
+ 19998.046951851553,
+ 19998.11649978661,
+ 19998.183571236077,
+ 19998.248254375594,
+ 19998.31063424184,
+ 19998.370792844253,
+ 19998.42880927274,
+ 19998.4847598016,
+ 19998.538717989708,
+ 19998.590754777182,
+ 19998.64093857857,
+ 19998.68933537273,
+ 19998.736008789543,
+ 19998.78102019351,
+ 19998.824428764387,
+ 19998.866291574945,
+ 19998.906663665974,
+ 19998.945598118597,
+ 19998.983146124054,
+ 19999.019357050955,
+ 19999.054278510157,
+ 19999.087956417356,
+ 19999.120435053414,
+ 19999.151757122556,
+ 19999.181963808518,
+ 19999.21109482865,
+ 19999.239188486128,
+ 19999.26628172031,
+ 19999.292410155274,
+ 19999.317608146655,
+ 19999.34190882679,
+ 19999.36534414829,
+ 19999.387944926013,
+ 19999.409740877607,
+ 19999.430760662537,
+ 19999.451031919776,
+ 19999.470581304155,
+ 19999.489434521372,
+ 19999.5076163618,
+ 19999.525150733072,
+ 19999.54206069153,
+ 19999.558368472495,
+ 19999.57409551955,
+ 19999.58926251268,
+ 19999.603889395497,
+ 19999.61799540144,
+ 19999.63159907907,
+ 19999.644718316464,
+ 19999.657370364694,
+ 19999.669571860562,
+ 19999.681338848437,
+ 19999.69268680136,
+ 19999.703630641383,
+ 19999.7141847592,
+ 19999.72436303305,
+ 19999.73417884697,
+ 19999.743645108418,
+ 19999.752774265195,
+ 19999.76157832185,
+ 19999.770068855447,
+ 19999.778257030794,
+ 19999.78615361512,
+ 19999.793768992236,
+ 19999.801113176174,
+ 19999.808195824375,
+ 19999.815026250366,
+ 19999.82161343603,
+ 19999.827966043387,
+ 19999.834092426012,
+ 19999.84000064,
+ 20000.0
+ ],
+ "vnorm": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "element": "carbon",
+ "charge": 6
+}
\ No newline at end of file
diff --git a/cherab/generomak/plasma/data/core/electrons.json b/cherab/generomak/plasma/data/core/electrons.json
new file mode 100644
index 00000000..7b5452e3
--- /dev/null
+++ b/cherab/generomak/plasma/data/core/electrons.json
@@ -0,0 +1,1292 @@
+{
+ "temperature": [
+ 3000.0,
+ 2998.52312403888,
+ 2992.7832506358122,
+ 2982.0621888623136,
+ 2966.1918094687762,
+ 2945.2429393424018,
+ 2919.419338214869,
+ 2889.003692058303,
+ 2854.3254277348515,
+ 2815.7398455505386,
+ 2773.6139136215174,
+ 2728.3163262527637,
+ 2680.2104553864137,
+ 2629.6493480144745,
+ 2576.972213977541,
+ 2522.5020223843676,
+ 2466.5439345047307,
+ 2409.3843734189736,
+ 2351.2905804738834,
+ 2292.5105439306594,
+ 2233.273210983751,
+ 2173.788913597856,
+ 2114.249953285668,
+ 2054.8313013065413,
+ 1995.6913796728331,
+ 1936.972895410661,
+ 1878.803706166504,
+ 1821.2976997951666,
+ 1764.5556742417446,
+ 1708.6662070172113,
+ 1653.7065059997449,
+ 1599.7432352775288,
+ 1546.8333113667693,
+ 1495.024666457186,
+ 1444.3569764096046,
+ 1394.8623520995304,
+ 1346.5659934019332,
+ 1299.4868056747446,
+ 1253.6379790455755,
+ 1209.0275311576331,
+ 1165.6588143030472,
+ 1123.5309880785605,
+ 1082.6394588511619,
+ 1042.9762874292182,
+ 1004.5305664061173,
+ 967.2887686849466,
+ 931.2350687100197,
+ 896.351637928748,
+ 862.6189159894875,
+ 830.0158591507654,
+ 798.5201673375811,
+ 768.1084912334692,
+ 738.7566207447438,
+ 710.4396561172668,
+ 683.1321629276453,
+ 656.8083121109125,
+ 631.4420061264298,
+ 607.0069923036725,
+ 583.4769643502522,
+ 560.8256529464521,
+ 539.0269062941003,
+ 518.0547614329445,
+ 497.88350708511757,
+ 478.4877387378806,
+ 459.84240662666764,
+ 441.9228572346464,
+ 424.7048688815144,
+ 408.16468193306855,
+ 392.2790241242251,
+ 377.0251314515118,
+ 362.3807650566294,
+ 348.3242244903237,
+ 334.83435771552126,
+ 321.890568180333,
+ 309.4728192650518,
+ 297.56163638257,
+ 286.1381069886319,
+ 275.1838787369333,
+ 264.68115599418036,
+ 254.6126949117557,
+ 244.96179723353092,
+ 235.71230300348657,
+ 226.84858232216044,
+ 218.35552628735832,
+ 210.21853724207088,
+ 202.42351844097678,
+ 194.95686323627902,
+ 187.8054438738336,
+ 180.95659998151527,
+ 174.3981268234994,
+ 168.11826338653523,
+ 162.10568035733561,
+ 156.34946804381812,
+ 150.8391242871043,
+ 145.56454240585458,
+ 140.51599920963352,
+ 135.6841431135791,
+ 131.0599823825858,
+ 126.63487352955082,
+ 122.40050988887697,
+ 118.3489103834026,
+ 114.47240850017948,
+ 110.76364148803557,
+ 107.21553978761827,
+ 103.82131670259133,
+ 100.57445831884021,
+ 97.46871367691406,
+ 94.49808520145595,
+ 91.65681939008829,
+ 88.93939776303986,
+ 86.34052807377111,
+ 83.8551357799498,
+ 81.47835577330721,
+ 79.20552436620889,
+ 77.03217153215161,
+ 74.95401339685759,
+ 72.9669449761771,
+ 71.06703315661875,
+ 69.25050991397345,
+ 67.51376576524152,
+ 65.85334344881281,
+ 64.26593182768406,
+ 62.74836001033597,
+ 61.2975916837819,
+ 59.91071965322365,
+ 58.58496058269206,
+ 57.31764993102628,
+ 56.10623707754045,
+ 54.948280631735244,
+ 53.84144392146098,
+ 52.78349065396557,
+ 51.77228074433782,
+ 50.805766305924465,
+ 49.88198779737891,
+ 48.999070321097264,
+ 48.15522006789341,
+ 47.348720902865914,
+ 46.57793108752631,
+ 45.841280133367995,
+ 45.137265782168555,
+ 44.46445110844881,
+ 43.82146173961798,
+ 43.206983189469376,
+ 42.61975830080557,
+ 42.05858479309852,
+ 41.522312911211856,
+ 41.00984317133116,
+ 40.520124200373346,
+ 40.05215066526151,
+ 39.604961288570934,
+ 39.17763694716649,
+ 38.7692988505653,
+ 38.379106795872445,
+ 38.00625749624137,
+ 37.64998297992401,
+ 37.30954905707338,
+ 36.98425385156884,
+ 36.67342639522852,
+ 36.37642528187246,
+ 36.09263737879576,
+ 35.82147659329382,
+ 35.56238269198415,
+ 35.314820170740816,
+ 35.07827717314717,
+ 34.852264455457785,
+ 34.63631439612891,
+ 34.42998004805659,
+ 34.23283423173999,
+ 34.044468667644786,
+ 33.864493146125206,
+ 33.69253473331596,
+ 33.52823701147538,
+ 33.371259352322355,
+ 33.221276221963834,
+ 33.07797651607301,
+ 32.94106292402577,
+ 32.81025132076462,
+ 32.685270185198156,
+ 32.56586004400546,
+ 32.45177293975274,
+ 32.34277192227911,
+ 32.23863056234819,
+ 32.13913248661057,
+ 32.04407093295307,
+ 31.953248325357347,
+ 31.866475867422928,
+ 31.783573153745696,
+ 31.704367798379554,
+ 31.62869507963904,
+ 31.556397600531596,
+ 31.48732496414222,
+ 31.421333463316515,
+ 31.3582857840232,
+ 31.298050721795224,
+ 31.24050291068117,
+ 31.18552256415908,
+ 31.132995227490305,
+ 31.082811541013847,
+ 31.034867013898335,
+ 30.98906180789872,
+ 30.94530053067335,
+ 30.903492038247204,
+ 30.863549246214866,
+ 30.82538894930257,
+ 30.788931648920514,
+ 30.754101388354496,
+ 30.720825595258578,
+ 30.68903493113094,
+ 30.658663147461834,
+ 30.62964694826175,
+ 30.60192585868675,
+ 30.575442099493,
+ 30.550140467063347,
+ 30.52596821875878,
+ 30.502874963360853,
+ 30.480812556378506,
+ 30.459735000005395,
+ 30.439598347523223,
+ 30.420360611949583,
+ 30.401981678749532,
+ 30.384423222424292,
+ 30.36764862680968,
+ 30.35162290891837,
+ 30.336312646168288,
+ 30.321685906848675,
+ 30.307712183679225,
+ 30.294362330325363,
+ 30.28160850073722,
+ 30.26942409119068,
+ 30.257783684906165,
+ 30.246662999132866,
+ 30.23603883458999,
+ 30.225889027158132,
+ 30.21619240172184,
+ 30.206928728068068,
+ 30.19807867874907,
+ 30.18962378882196,
+ 30.181546417381178,
+ 30.17382971080637,
+ 30.16645756764611,
+ 30.159414605066953,
+ 30.15268612679821,
+ 30.146258092504468,
+ 30.1401170885238,
+ 30.13425029990965,
+ 30.128645483719644,
+ 30.123290943494364,
+ 30.118175504875328,
+ 30.113288492308037,
+ 30.108619706785408,
+ 30.104159404583456,
+ 30.09989827694405,
+ 30.095827430664894,
+ 30.091938369554885,
+ 30.08822297671646,
+ 30.00874190034343
+ ],
+ "density": [
+ 5e+19,
+ 4.981243417835291e+19,
+ 4.960402826870333e+19,
+ 4.938876378646617e+19,
+ 4.916988294636239e+19,
+ 4.894895073575541e+19,
+ 4.872689168534975e+19,
+ 4.850431386174099e+19,
+ 4.82816450569505e+19,
+ 4.8059200450545025e+19,
+ 4.783722014076859e+19,
+ 4.761589167152264e+19,
+ 4.739536438387333e+19,
+ 4.7175758996665205e+19,
+ 4.6957174248046666e+19,
+ 4.673969164500353e+19,
+ 4.65233789497414e+19,
+ 4.630829279642529e+19,
+ 4.609448069324508e+19,
+ 4.588198258002084e+19,
+ 4.567083205796747e+19,
+ 4.546105737335663e+19,
+ 4.5252682213529305e+19,
+ 4.504572635781684e+19,
+ 4.484020621485682e+19,
+ 4.463613526993922e+19,
+ 4.443352446035942e+19,
+ 4.423238249261527e+19,
+ 4.403271611221671e+19,
+ 4.383453033457265e+19,
+ 4.3637828643671245e+19,
+ 4.34426131639279e+19,
+ 4.324888480953614e+19,
+ 4.305664341484428e+19,
+ 4.286588784864013e+19,
+ 4.2676616114717884e+19,
+ 4.248882544069383e+19,
+ 4.230251235670968e+19,
+ 4.2117672765396435e+19,
+ 4.193430200425467e+19,
+ 4.175239490142886e+19,
+ 4.157194582570674e+19,
+ 4.1392948731452695e+19,
+ 4.121539719908261e+19,
+ 4.103928447160288e+19,
+ 4.0864603487664456e+19,
+ 4.069134691152288e+19,
+ 4.051950716024378e+19,
+ 4.034907642845002e+19,
+ 4.018004671086943e+19,
+ 4.0012409822910185e+19,
+ 3.984615741946379e+19,
+ 3.968128101211149e+19,
+ 3.951777198489014e+19,
+ 3.935562160875532e+19,
+ 3.919482105486449e+19,
+ 3.903536140678914e+19,
+ 3.887723367175341e+19,
+ 3.872042879098642e+19,
+ 3.856493764926597e+19,
+ 3.841075108372399e+19,
+ 3.82578598919766e+19,
+ 3.810625483963539e+19,
+ 3.795592666725145e+19,
+ 3.780686609673816e+19,
+ 3.765906383731481e+19,
+ 3.751251059100921e+19,
+ 3.736719705775351e+19,
+ 3.7223113940105036e+19,
+ 3.708025194762049e+19,
+ 3.6938601800909865e+19,
+ 3.6798154235393765e+19,
+ 3.665890000478603e+19,
+ 3.652082988432173e+19,
+ 3.638393467374876e+19,
+ 3.6248205200099906e+19,
+ 3.611363232026088e+19,
+ 3.5980206923348574e+19,
+ 3.584791993291257e+19,
+ 3.5716762308972077e+19,
+ 3.55867250498995e+19,
+ 3.545779919416078e+19,
+ 3.532997582192232e+19,
+ 3.5203246056533017e+19,
+ 3.5077601065889927e+19,
+ 3.495303206369484e+19,
+ 3.4829530310609023e+19,
+ 3.470708711531262e+19,
+ 3.4585693835474727e+19,
+ 3.446534187864e+19,
+ 3.434602270303676e+19,
+ 3.422772781831188e+19,
+ 3.4110448786196742e+19,
+ 3.3994177221108638e+19,
+ 3.3878904790691725e+19,
+ 3.376462321630112e+19,
+ 3.3651324273433653e+19,
+ 3.3538999792108577e+19,
+ 3.3427641657201336e+19,
+ 3.331724180873318e+19,
+ 3.320779224211924e+19,
+ 3.3099285008377905e+19,
+ 3.299171221430335e+19,
+ 3.288506602260401e+19,
+ 3.277933865200853e+19,
+ 3.2674522377341583e+19,
+ 3.257060952957118e+19,
+ 3.246759249582918e+19,
+ 3.236546371940678e+19,
+ 3.22642156997264e+19,
+ 3.21638409922914e+19,
+ 3.2064332208615055e+19,
+ 3.1965682016130003e+19,
+ 3.1867883138079457e+19,
+ 3.1770928353391223e+19,
+ 3.1674810496535667e+19,
+ 3.157952245736852e+19,
+ 3.1485057180959785e+19,
+ 3.1391407667409125e+19,
+ 3.129856697164928e+19,
+ 3.1206528203237556e+19,
+ 3.1115284526136713e+19,
+ 3.1024829158485823e+19,
+ 3.093515537236158e+19,
+ 3.0846256493530964e+19,
+ 3.0758125901195686e+19,
+ 3.0670757027729146e+19,
+ 3.058414335840632e+19,
+ 3.049827843112693e+19,
+ 3.0413155836133044e+19,
+ 3.032876921572053e+19,
+ 3.0245112263945794e+19,
+ 3.016217872632765e+19,
+ 3.0079962399544726e+19,
+ 2.9998457131129012e+19,
+ 2.9917656819155902e+19,
+ 2.9837555411930575e+19,
+ 2.9758146907671814e+19,
+ 2.9679425354192785e+19,
+ 2.9601384848579527e+19,
+ 2.9524019536867484e+19,
+ 2.9447323613715747e+19,
+ 2.937129132207994e+19,
+ 2.9295916952883618e+19,
+ 2.922119484468826e+19,
+ 2.9147119383362347e+19,
+ 2.907368500174985e+19,
+ 2.9000886179337527e+19,
+ 2.8928717441922073e+19,
+ 2.885717336127708e+19,
+ 2.878624855481938e+19,
+ 2.8715937685275652e+19,
+ 2.8646235460349194e+19,
+ 2.857713663238656e+19,
+ 2.850863599804493e+19,
+ 2.844072839795962e+19,
+ 2.83734087164125e+19,
+ 2.830667188100075e+19,
+ 2.8240512862306402e+19,
+ 2.8174926673567138e+19,
+ 2.8109908370347393e+19,
+ 2.8045453050210898e+19,
+ 2.798155585239442e+19,
+ 2.7918211957482054e+19,
+ 2.7855416587081368e+19,
+ 2.779316500350069e+19,
+ 2.773145250942718e+19,
+ 2.7670274447607374e+19,
+ 2.7609626200527954e+19,
+ 2.7549503190099005e+19,
+ 2.748990087733828e+19,
+ 2.7430814762057028e+19,
+ 2.7372240382547927e+19,
+ 2.7314173315273884e+19,
+ 2.725660917455944e+19,
+ 2.719954361228283e+19,
+ 2.714297231757104e+19,
+ 2.7086891016495333e+19,
+ 2.7031295471769723e+19,
+ 2.697618148245014e+19,
+ 2.692154488363691e+19,
+ 2.686738154617714e+19,
+ 2.6813687376370782e+19,
+ 2.6760458315677737e+19,
+ 2.67076903404267e+19,
+ 2.665537946152642e+19,
+ 2.660352172417858e+19,
+ 2.65521132075925e+19,
+ 2.65011500247021e+19,
+ 2.645062832188477e+19,
+ 2.6400544278682247e+19,
+ 2.6350894107522163e+19,
+ 2.6301674053443994e+19,
+ 2.625288039382521e+19,
+ 2.620450943810967e+19,
+ 2.6156557527538237e+19,
+ 2.610902103488069e+19,
+ 2.6061896364171543e+19,
+ 2.6015179950445117e+19,
+ 2.5968868259474686e+19,
+ 2.5922957787512246e+19,
+ 2.5877445061031244e+19,
+ 2.5832326636470903e+19,
+ 2.578759909998139e+19,
+ 2.57432590671733e+19,
+ 2.5699303182867214e+19,
+ 2.5655728120845242e+19,
+ 2.561253058360556e+19,
+ 2.5569707302117368e+19,
+ 2.5527255035580244e+19,
+ 2.5485170571182055e+19,
+ 2.544345072386111e+19,
+ 2.54020923360703e+19,
+ 2.5361092277541216e+19,
+ 2.5320447445052424e+19,
+ 2.5280154762197893e+19,
+ 2.5240211179157164e+19,
+ 2.520061367247062e+19,
+ 2.5161359244810146e+19,
+ 2.5122444924759847e+19,
+ 2.5083867766590497e+19,
+ 2.5045624850041692e+19,
+ 2.500771328010387e+19,
+ 2.4970130186799833e+19,
+ 2.493287272497215e+19,
+ 2.489593807406909e+19,
+ 2.485932343793488e+19,
+ 2.482302604459721e+19,
+ 2.478704314606391e+19,
+ 2.475137201811416e+19,
+ 2.471600996009324e+19,
+ 2.4680954294713426e+19,
+ 2.464620236785044e+19,
+ 2.4611751548345704e+19,
+ 2.45775992278063e+19,
+ 2.4543742820412535e+19,
+ 2.451017976272195e+19,
+ 2.447690751347609e+19,
+ 2.444392355341035e+19,
+ 2.4411225385064636e+19,
+ 2.4378810532594893e+19,
+ 2.434667654158714e+19,
+ 2.4314820978872984e+19,
+ 2.4283241432347005e+19,
+ 2.42519355107831e+19,
+ 2.422090084365806e+19,
+ 2.419013508096743e+19,
+ 2.415963589305566e+19,
+ 2.4129400970434146e+19,
+ 2.4099428023610917e+19,
+ 2.406971478291697e+19,
+ 2.4040258998335894e+19,
+ 2.4011058439331717e+19,
+ 2.3982110894683005e+19,
+ 2.395341417231851e+19,
+ 2.0670269989725e+19
+ ],
+ "vtor": [
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10,
+ 1e-10
+ ],
+ "vpol": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "vnorm": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ]
+}
\ No newline at end of file
diff --git a/cherab/generomak/plasma/data/core/hydrogen0.json b/cherab/generomak/plasma/data/core/hydrogen0.json
new file mode 100644
index 00000000..754940c0
--- /dev/null
+++ b/cherab/generomak/plasma/data/core/hydrogen0.json
@@ -0,0 +1,1294 @@
+{
+ "temperature": [
+ 2240.0,
+ 2236.4504489807964,
+ 2226.309382068473,
+ 2210.299052071184,
+ 2189.0904205810994,
+ 2163.3046865525707,
+ 2133.515194552534,
+ 2100.249595432215,
+ 2063.992162943028,
+ 2025.1861932135298,
+ 1984.2364319190758,
+ 1941.5114877758033,
+ 1897.3462016693657,
+ 1852.0439490190533,
+ 1805.87885942599,
+ 1759.0979426720367,
+ 1711.9231140372276,
+ 1664.5531149286294,
+ 1617.1653271484834,
+ 1569.917480919263,
+ 1522.949258141365,
+ 1476.3837933749978,
+ 1430.3290757822574,
+ 1384.8792557946174,
+ 1340.1158606300705,
+ 1296.1089230088292,
+ 1252.9180275356005,
+ 1210.5932792532092,
+ 1169.1761988453034,
+ 1128.7005488900284,
+ 1089.193095453988,
+ 1050.674309176122,
+ 1013.1590098321976,
+ 976.6569581985458,
+ 941.1733988535289,
+ 906.7095573708474,
+ 873.2630951733505,
+ 840.828525131861,
+ 809.3975908125881,
+ 778.9596121003383,
+ 749.5017997540461,
+ 721.0095412868372,
+ 693.4666604055054,
+ 666.8556520941395,
+ 641.1578952839868,
+ 616.3538449164151,
+ 592.4232050780837,
+ 569.3450847669792,
+ 547.0981377346717,
+ 525.6606877437563,
+ 505.0108404797533,
+ 485.1265832634224,
+ 465.9858736222754,
+ 447.56671769870127,
+ 429.8472393962903,
+ 412.8057410953542,
+ 396.4207567029529,
+ 380.6710977417666,
+ 365.53589312550383,
+ 350.9946232160131,
+ 337.02714870861604,
+ 323.61373484709463,
+ 310.7350714280776,
+ 298.37228901601867,
+ 286.50697175433055,
+ 275.12116712535635,
+ 264.1973929815059,
+ 253.7186421419,
+ 243.66838482307517,
+ 234.0305691485461,
+ 224.78961996016457,
+ 215.93043613409628,
+ 207.4383865857546,
+ 199.29930513103795,
+ 191.4994843556246,
+ 184.02566862976738,
+ 176.86504639289873,
+ 170.00524182033894,
+ 163.43430597337053,
+ 157.14070752386905,
+ 151.113323135452,
+ 145.34142757467652,
+ 139.81468361812196,
+ 134.52313181416025,
+ 129.457180151816,
+ 124.60759368327163,
+ 119.96548414126156,
+ 115.52229958776202,
+ 111.26981412599169,
+ 107.20011770374389,
+ 103.30560603245968,
+ 99.57897064317038,
+ 96.01318909747529,
+ 92.60151536903889,
+ 89.33747040868218,
+ 86.21483290395201,
+ 83.22763024211139,
+ 80.37012968371364,
+ 77.63682975236918,
+ 75.02245184488561,
+ 72.52193206471382,
+ 70.13041328051168,
+ 67.84323741064236,
+ 65.6559379335423,
+ 63.564232623128014,
+ 61.56401650771693,
+ 59.65135505035933,
+ 57.82247754794227,
+ 56.07377074599886,
+ 54.40177266575983,
+ 52.80316663966101,
+ 51.27477555125246,
+ 49.81355627521912,
+ 48.416594313043035,
+ 47.081098619687594,
+ 45.80439661656459,
+ 44.5839293859712,
+ 43.417247042115314,
+ 42.302004273818525,
+ 41.23595605397633,
+ 40.216953510850516,
+ 39.24293995630613,
+ 38.311947066125406,
+ 37.422091207594626,
+ 36.571569909608,
+ 35.75865847061232,
+ 34.98170669978367,
+ 34.23913578692253,
+ 33.52943529662951,
+ 32.85116028243641,
+ 32.20292851664732,
+ 31.583417831760713,
+ 30.99136356943732,
+ 30.425556133091256,
+ 29.88483864028179,
+ 29.36810467119799,
+ 28.87429610962729,
+ 28.40240107291426,
+ 27.951451927516537,
+ 27.52052338687281,
+ 27.108730688404705,
+ 26.715227846572123,
+ 26.33920597900726,
+ 25.979891702853777,
+ 25.636545598528727,
+ 25.30846073823038,
+ 24.994961276600144,
+ 24.69540110104437,
+ 24.409162539308983,
+ 24.13565512198808,
+ 23.874314397731172,
+ 23.624600798996898,
+ 23.385998556284218,
+ 23.15801465884384,
+ 22.940177859954957,
+ 22.73203772492011,
+ 22.533163720006204,
+ 22.343144340625674,
+ 22.161586277118445,
+ 21.988113616562465,
+ 21.822367079097155,
+ 21.664003287311004,
+ 21.51269406729655,
+ 21.36812578003317,
+ 21.229998681815967,
+ 21.098026312495502,
+ 20.971934910344643,
+ 20.851462852421577,
+ 20.736360119335554,
+ 20.626387783375975,
+ 20.521317519002128,
+ 20.420931134733753,
+ 20.32502012552446,
+ 20.233385244735498,
+ 20.145836094864723,
+ 20.06219073622283,
+ 19.982275312781507,
+ 19.90592369444775,
+ 19.832977135057188,
+ 19.763283945401255,
+ 19.696699180637957,
+ 19.633084341458513,
+ 19.572307088415513,
+ 19.51424096883524,
+ 19.45876515576827,
+ 19.40576419845266,
+ 19.355127783786383,
+ 19.30675050832906,
+ 19.26053166037145,
+ 19.21637501163307,
+ 19.174188618164745,
+ 19.133884630054332,
+ 19.09537910954868,
+ 19.05859185722216,
+ 19.023446245839033,
+ 18.989869061570744,
+ 18.957790352245382,
+ 18.927143282320497,
+ 18.897863994281074,
+ 18.86989147618248,
+ 18.843167435065453,
+ 18.817636175985687,
+ 18.79324448640893,
+ 18.769941525736378,
+ 18.747678719732868,
+ 18.726409659641607,
+ 18.706090005778155,
+ 18.686677395406114,
+ 18.668131354704837,
+ 18.650413214648612,
+ 18.633486030623327,
+ 18.617314505615823,
+ 18.60186491681852,
+ 18.587105045495814,
+ 18.573004109970697,
+ 18.55953270159014,
+ 18.546662723539878,
+ 18.53436733238102,
+ 18.522620882187194,
+ 18.51139887116874,
+ 18.500677890671284,
+ 18.49043557644487,
+ 18.480650562082833,
+ 18.471302434532834,
+ 18.46237169158913,
+ 18.453839701278447,
+ 18.445688663053495,
+ 18.437901570715436,
+ 18.430462176988556,
+ 18.423354959672093,
+ 18.416565089300423,
+ 18.41007839824483,
+ 18.403881351191185,
+ 18.39796101693386,
+ 18.392305041426237,
+ 18.386901622033136,
+ 18.381739482930183,
+ 18.376807851599832,
+ 18.372096436376008,
+ 18.367595404988766,
+ 18.36329536406628,
+ 18.359187339550697,
+ 18.355262757987074,
+ 18.351513428646914,
+ 18.34793152644875,
+ 18.344509575640426,
+ 18.341240434209354,
+ 18.338117278988225,
+ 18.335133591424395,
+ 18.3322831439848,
+ 18.329559987167194,
+ 18.326958437090312,
+ 18.324473063638234,
+ 18.32209867913344,
+ 18.319830327515373,
+ 18.271305784128668
+ ],
+ "density": [
+ 204620001816.96503,
+ 203995340626.48117,
+ 203580415549.07077,
+ 203478214247.57297,
+ 203715877183.5095,
+ 204301348415.06805,
+ 205234420738.4918,
+ 206511241598.7883,
+ 208126529002.83133,
+ 210074752469.19244,
+ 212350782448.41467,
+ 214950246524.57938,
+ 217869717181.2876,
+ 221106800859.7011,
+ 224660168985.34265,
+ 228529555375.00076,
+ 232715734933.54498,
+ 237220492826.1153,
+ 242046589785.09818,
+ 247197727005.0989,
+ 252678512684.92447,
+ 258494431389.8997,
+ 264651816845.81558,
+ 271157828420.81525,
+ 278020413999.39655,
+ 285247320715.9104,
+ 292847439717.963,
+ 300831346075.9571,
+ 309210473286.05414,
+ 317997118815.822,
+ 327204455041.3841,
+ 336846543548.0578,
+ 346938352650.2804,
+ 357495722378.11005,
+ 368531748603.2294,
+ 380060992884.0296,
+ 392101369277.8834,
+ 404671758538.71185,
+ 417792030624.14746,
+ 431483075722.2703,
+ 445766837408.0821,
+ 460666347857.28577,
+ 476205765045.6582,
+ 492411668158.4271,
+ 509310082743.527,
+ 526922958785.0509,
+ 545270668436.08124,
+ 564382532826.562,
+ 584289351347.6514,
+ 605023347803.2103,
+ 626618224577.489,
+ 649109218441.2275,
+ 672533157882.3363,
+ 696928521829.5643,
+ 722330392907.0331,
+ 748761752833.0225,
+ 776263316106.7876,
+ 804879690534.3215,
+ 834657513313.9681,
+ 865645526272.6191,
+ 897894651906.1387,
+ 931458069962.6783,
+ 966390478339.3801,
+ 1002713570323.5283,
+ 1040458926521.3761,
+ 1079684516540.4954,
+ 1120450776084.2368,
+ 1162820677057.6262,
+ 1206859796754.8408,
+ 1252636384433.044,
+ 1300221424799.789,
+ 1349688697963.7998,
+ 1401114835449.2217,
+ 1454579371952.6218,
+ 1510164792644.5955,
+ 1567952481060.059,
+ 1627931114636.4526,
+ 1690139925687.1553,
+ 1754669353636.4456,
+ 1821613533247.6384,
+ 1891070371220.4712,
+ 1963141624989.376,
+ 2037932986753.0464,
+ 2115554176680.7764,
+ 2196119050183.666,
+ 2279748776152.387,
+ 2366500641895.066,
+ 2456287369484.3516,
+ 2549234395774.7485,
+ 2645490036768.047,
+ 2745210502439.3457,
+ 2848560231576.2715,
+ 2955712221053.107,
+ 3066848216768.975,
+ 3181983423138.0234,
+ 3300978418418.4097,
+ 3423964172116.361,
+ 3551081532136.3022,
+ 3682471863828.1035,
+ 3818274934361.4946,
+ 3958626240909.5186,
+ 4103653876103.972,
+ 4253475165354.2246,
+ 4408193462719.133,
+ 4567895603650.418,
+ 4732650517791.943,
+ 4902247847002.056,
+ 5076233402000.4795,
+ 5254598646625.475,
+ 5437349446630.464,
+ 5624489405383.76,
+ 5816019959574.812,
+ 6011939258098.727,
+ 6212239938237.438,
+ 6416906050351.422,
+ 6625909469387.242,
+ 6839206174537.927,
+ 7056732786183.625,
+ 7278311975421.752,
+ 7503119857298.018,
+ 7730869714380.9375,
+ 7961427820158.273,
+ 8194643345174.029,
+ 8430349935940.838,
+ 8668367358140.194,
+ 8908503068344.902,
+ 9150553621597.744,
+ 9394305867677.299,
+ 9639552766370.97,
+ 9886049104086.564,
+ 10133557734495.324,
+ 10381834826485.693,
+ 10630630439847.912,
+ 10879678469431.771,
+ 11128195788042.75,
+ 11375596059217.254,
+ 11621622648260.379,
+ 11866019968617.504,
+ 12108534650895.979,
+ 12348916749575.322,
+ 12586920956579.773,
+ 12822307795224.22,
+ 13054844772251.508,
+ 13284307469611.012,
+ 13510480561149.14,
+ 13733158742539.867,
+ 13952147565575.44,
+ 14167264170431.275,
+ 14378337911729.918,
+ 14585210876204.7,
+ 14787738291529.992,
+ 14985788827443.982,
+ 15179244791671.332,
+ 15368002224351.652,
+ 15551970895709.932,
+ 15731074212570.957,
+ 15905249040010.746,
+ 16074445444998.629,
+ 16238626369271.07,
+ 16397767238935.273,
+ 16551855518444.57,
+ 16700890216574.428,
+ 16844881351954.912,
+ 16983849385509.26,
+ 17117824626881.824,
+ 17246846621603.266,
+ 17370963525334.229,
+ 17490231471110.625,
+ 17604713935017.176,
+ 17714481105258.8,
+ 17819608453161.367,
+ 17920177950565.527,
+ 18016276628873.59,
+ 18107995459063.83,
+ 18195429156535.652,
+ 18278675646852.23,
+ 18357835555954.918,
+ 18433011726092.445,
+ 18504308758387.65,
+ 18571832582598.63,
+ 18635690054375.332,
+ 18695988580024.676,
+ 18752835768579.754,
+ 18806339110761.88,
+ 18856605684254.773,
+ 18903741884561.38,
+ 18947853180595.484,
+ 18989043894059.926,
+ 19027417001587.02,
+ 19063073958565.055,
+ 19096114543521.96,
+ 19126636721924.43,
+ 19154736528236.87,
+ 19180507965077.684,
+ 19204042918329.66,
+ 19225431087078.62,
+ 19244759927277.656,
+ 19262114608067.395,
+ 19277577979726.01,
+ 19291230552256.516,
+ 19303150483665.746,
+ 19313413577033.516,
+ 19322093285526.824,
+ 19329260724543.79,
+ 19334984690237.266,
+ 19339331683709.87,
+ 19342365940211.094,
+ 19344149462728.09,
+ 19344742059393.53,
+ 19344201384180.91,
+ 19342582980399.023,
+ 19339940326544.8,
+ 19336324363046.41,
+ 19331784091828.13,
+ 19326368145671.793,
+ 19320122234851.223,
+ 19313090256097.117,
+ 19305314345120.19,
+ 19296834929279.25,
+ 19287690780209.77,
+ 19277919066210.582,
+ 19267555404250.375,
+ 19256633911438.43,
+ 19245187255846.457,
+ 19233246706569.15,
+ 19220842182934.86,
+ 19208002302790.24,
+ 19194754429784.965,
+ 19181124719614.805,
+ 19167138165162.6,
+ 19152818640516.805,
+ 19138188943830.562,
+ 19123270839007.04,
+ 19108085096194.83,
+ 19092651531087.504,
+ 19076989043026.625,
+ 19061115651909.043,
+ 19045048533903.996,
+ 19028804056001.64,
+ 19012397809386.355,
+ 18995844641670.94,
+ 18979158687998.574,
+ 18962353401040.9,
+ 18945441579905.883,
+ 18928435397987.637,
+ 18911346429777.703,
+ 18894185676666.883,
+ 18876963591763.613,
+ 18859690103748.47,
+ 18842374639807.22,
+ 18825026147656.855,
+ 18807653116696.703,
+ 18790263598309.477,
+ 18772865225350.633,
+ 18755465230832.047,
+ 16384843817946.543
+ ],
+ "vtor": [
+ 100000.0,
+ 99544.32023364124,
+ 98251.15453696062,
+ 96235.68685722632,
+ 93614.68356191639,
+ 90502.18847954353,
+ 87006.32501749854,
+ 83227.06508922808,
+ 79254.813872946,
+ 75169.66123127713,
+ 71041.16042746486,
+ 66928.50919629741,
+ 62881.02482158773,
+ 58938.821939433255,
+ 55133.61820859918,
+ 51489.60808192722,
+ 48024.35830839606,
+ 44749.69035052268,
+ 41672.524623402256,
+ 38795.66945343124,
+ 36118.54407642795,
+ 33637.83003375026,
+ 31348.04917610031,
+ 29242.06933764292,
+ 27311.54077408969,
+ 25547.26782590489,
+ 23939.521110407513,
+ 22478.295982958116,
+ 21153.523137258686,
+ 19955.237120191036,
+ 18873.708284120235,
+ 17899.54334214529,
+ 17023.759270761642,
+ 16237.834851443324,
+ 15533.743681380842,
+ 14903.972031120154,
+ 14341.524495030524,
+ 13839.919977172622,
+ 13393.180184865832,
+ 12995.812467288095,
+ 12642.788537234375,
+ 12329.520349892675,
+ 12051.83418147994,
+ 11805.94375056095,
+ 11588.423053275488,
+ 11396.179437797053,
+ 11226.42732039882,
+ 11076.662842842592,
+ 10944.639685904545,
+ 10828.34618435543,
+ 10725.983832469563,
+ 10635.94722420132,
+ 10556.805436804136,
+ 10487.284839339893,
+ 10426.253286892172,
+ 10372.705646187464,
+ 10325.750587737686,
+ 10284.598572685094,
+ 10248.550958525679,
+ 10216.990146193662,
+ 10189.370691092356,
+ 10165.211302127113,
+ 10144.087655281786,
+ 10125.625951492917,
+ 10109.49715228246,
+ 10095.411830623676,
+ 10083.115578687914,
+ 10072.384918337477,
+ 10063.023664403154,
+ 10054.85969484832,
+ 10047.742085826912,
+ 10041.538573356505,
+ 10036.133306828673,
+ 10031.424862854412,
+ 10027.3244909875,
+ 10023.75456568367,
+ 10020.647221443161,
+ 10017.943150456194,
+ 10015.59054423511,
+ 10013.544162684711,
+ 10011.764515845945,
+ 10010.217145160046,
+ 10008.871992553453,
+ 10007.702846950711,
+ 10006.686858995241,
+ 10005.804115808194,
+ 10005.037268554323,
+ 10004.371206421612,
+ 10003.792771367725,
+ 10003.29050865027,
+ 10002.85444874773,
+ 10002.475916801126,
+ 10002.14736617021,
+ 10001.86223310832,
+ 10001.614809922945,
+ 10001.400134309408,
+ 10001.213892828007,
+ 10001.052336744104,
+ 10000.912208670363,
+ 10000.790678643563,
+ 10000.68528843837,
+ 10000.593903069897,
+ 10000.514668568,
+ 10000.445975221452,
+ 10000.386425591105,
+ 10000.334806679686,
+ 10000.290065723417,
+ 10000.25128913859,
+ 10000.217684215675,
+ 10000.188563205464,
+ 10000.16332948734,
+ 10000.141465549392,
+ 10000.122522544827,
+ 10000.106111219531,
+ 10000.091894031972,
+ 10000.079578309811,
+ 10000.068910307727,
+ 10000.05967004848,
+ 10000.051666844598,
+ 10000.044735411424,
+ 10000.038732493818,
+ 10000.033533939033,
+ 10000.029032157028,
+ 10000.02513391718,
+ 10000.021758437058,
+ 10000.018835724715,
+ 10000.016305140998,
+ 10000.01411415281,
+ 10000.012217252064,
+ 10000.010575018385,
+ 10000.009153306504,
+ 10000.007922541854,
+ 10000.00685710995,
+ 10000.005934827166,
+ 10000.005136482061,
+ 10000.004445437868,
+ 10000.003847288048,
+ 10000.003329557814,
+ 10000.002881445527,
+ 10000.00249359863,
+ 10000.002157919536,
+ 10000.001867397486,
+ 10000.001615962863,
+ 10000.001398361033,
+ 10000.001210043049,
+ 10000.001047070993,
+ 10000.000906036008,
+ 10000.000783987294,
+ 10000.000678370623,
+ 10000.000586975104,
+ 10000.000507887078,
+ 10000.000439450198,
+ 10000.000380230858,
+ 10000.000328988277,
+ 10000.000284648579,
+ 10000.000246282361,
+ 10000.000213085277,
+ 10000.00018436122,
+ 10000.000159507772,
+ 10000.000138003594,
+ 10000.000119397531,
+ 10000.000103299173,
+ 10000.000089370667,
+ 10000.000077319659,
+ 10000.000066893168,
+ 10000.000057872281,
+ 10000.000050067574,
+ 10000.00004331514,
+ 10000.00003747315,
+ 10000.000032418886,
+ 10000.000028046165,
+ 10000.00002426311,
+ 10000.000020990228,
+ 10000.000018158735,
+ 10000.00001570912,
+ 10000.000013589894,
+ 10000.000011756505,
+ 10000.00001017041,
+ 10000.00000879826,
+ 10000.000007611205,
+ 10000.00000658428,
+ 10000.000005695889,
+ 10000.000004927346,
+ 10000.000004262487,
+ 10000.000003687326,
+ 10000.000003189763,
+ 10000.000002759334,
+ 10000.000002386978,
+ 10000.000002064864,
+ 10000.000001786213,
+ 10000.00000154516,
+ 10000.000001336637,
+ 10000.00000115625,
+ 10000.000001000204,
+ 10000.000000865217,
+ 10000.000000748445,
+ 10000.000000647431,
+ 10000.00000056005,
+ 10000.000000484462,
+ 10000.000000419075,
+ 10000.000000362512,
+ 10000.000000313583,
+ 10000.000000271257,
+ 10000.000000234644,
+ 10000.000000202972,
+ 10000.000000175574,
+ 10000.000000151877,
+ 10000.000000131377,
+ 10000.000000113641,
+ 10000.000000098302,
+ 10000.000000085032,
+ 10000.000000073554,
+ 10000.000000063626,
+ 10000.000000055037,
+ 10000.000000047608,
+ 10000.000000041182,
+ 10000.000000035621,
+ 10000.000000030814,
+ 10000.000000026654,
+ 10000.000000023056,
+ 10000.000000019943,
+ 10000.000000017251,
+ 10000.000000014923,
+ 10000.000000012908,
+ 10000.000000011165,
+ 10000.000000009659,
+ 10000.000000008355,
+ 10000.000000007227,
+ 10000.00000000625,
+ 10000.000000005406,
+ 10000.000000004677,
+ 10000.000000004045,
+ 10000.0000000035,
+ 10000.000000003027,
+ 10000.000000002618,
+ 10000.000000002265,
+ 10000.000000001959,
+ 10000.000000001695,
+ 10000.000000001466,
+ 10000.000000001268,
+ 10000.000000001097,
+ 10000.00000000095,
+ 10000.00000000082,
+ 10000.00000000071,
+ 10000.000000000615,
+ 10000.000000000531,
+ 10000.00000000046,
+ 10000.000000000397,
+ 10000.000000000344,
+ 10000.000000000296,
+ 10000.000000000256,
+ 10000.000000000222,
+ 10000.000000000193,
+ 10000.000000000167,
+ 10000.000000000144,
+ 10000.0
+ ],
+ "vpol": [
+ 18462.326927732716,
+ 18514.99979366994,
+ 18565.939231880784,
+ 18615.197379613106,
+ 18662.8251518226,
+ 18708.87224398403,
+ 18753.38713728863,
+ 18796.417106004,
+ 18838.008226787257,
+ 18878.20538975573,
+ 18917.052311132516,
+ 18954.591547296637,
+ 18990.864510079347,
+ 19025.91148315922,
+ 19059.7716394193,
+ 19092.483059139577,
+ 19124.08274890752,
+ 19154.60666113828,
+ 19184.089714104663,
+ 19212.565812384706,
+ 19240.067867642374,
+ 19266.627819663598,
+ 19292.27665757659,
+ 19317.044441191432,
+ 19340.960322399642,
+ 19364.052566579816,
+ 19386.34857396039,
+ 19407.874900895215,
+ 19428.65728101207,
+ 19448.720646198086,
+ 19468.08914739,
+ 19486.78617514046,
+ 19504.834379934928,
+ 19522.2556922367,
+ 19539.07134224024,
+ 19555.301879315663,
+ 19570.96719112952,
+ 19586.08652242914,
+ 19600.678493479918,
+ 19614.761118146518,
+ 19628.351821610984,
+ 19641.467457721887,
+ 19654.124325970388,
+ 19666.33818809011,
+ 19678.124284279074,
+ 19689.497349042842,
+ 19700.47162665909,
+ 19711.060886264648,
+ 19721.278436566783,
+ 19731.137140181316,
+ 19740.649427600623,
+ 19749.827310795343,
+ 19758.68239645382,
+ 19767.225898864108,
+ 19775.4686524434,
+ 19783.421123920307,
+ 19791.093424175622,
+ 19798.49531974744,
+ 19805.63624400677,
+ 19812.52530800986,
+ 19819.171311033715,
+ 19825.582750801284,
+ 19831.76783340299,
+ 19837.73448292125,
+ 19843.49035076469,
+ 19849.042824718887,
+ 19854.399037720275,
+ 19859.565876360022,
+ 19864.549989124593,
+ 19869.357794379575,
+ 19873.99548810352,
+ 19878.469051378208,
+ 19882.78425764191,
+ 19886.946679712015,
+ 19890.961696583312,
+ 19894.83450000816,
+ 19898.570100864654,
+ 19902.173335318803,
+ 19905.64887078662,
+ 19909.00121170188,
+ 19912.234705095303,
+ 19915.353545990587,
+ 19918.361782622906,
+ 19921.263321485007,
+ 19924.061932206263,
+ 19926.76125226966,
+ 19929.36479157172,
+ 19931.875936830187,
+ 19934.297955844206,
+ 19936.634001611572,
+ 19938.887116307546,
+ 19941.060235129582,
+ 19943.156190012254,
+ 19945.17771321644,
+ 19947.12744079687,
+ 19949.00791595186,
+ 19950.821592259108,
+ 19952.570836801166,
+ 19954.25793318425,
+ 19955.885084453774,
+ 19957.454415910102,
+ 19958.967977827684,
+ 19960.427748080827,
+ 19961.835634679162,
+ 19963.193478215824,
+ 19964.503054231183,
+ 19965.76607549503,
+ 19966.984194209857,
+ 19968.159004137942,
+ 19969.292042654735,
+ 19970.384792731096,
+ 19971.438684846682,
+ 19972.455098836952,
+ 19973.435365675872,
+ 19974.380769196654,
+ 19975.29254775252,
+ 19976.1718958196,
+ 19977.019965543906,
+ 19977.83786823432,
+ 19978.6266758034,
+ 19979.38742215782,
+ 19980.121104540183,
+ 19980.828684823875,
+ 19981.511090762506,
+ 19982.169217195635,
+ 19982.80392721215,
+ 19983.41605327286,
+ 19984.006398293674,
+ 19984.575736690727,
+ 19985.124815388765,
+ 19985.654354794107,
+ 19986.165049733347,
+ 19986.657570359053,
+ 19987.132563023555,
+ 19987.590651121973,
+ 19988.03243590553,
+ 19988.458497266216,
+ 19988.869394493737,
+ 19989.265667005842,
+ 19989.647835052798,
+ 19990.01640039704,
+ 19990.371846968832,
+ 19990.714641498744,
+ 19991.045234127785,
+ 19991.36405899601,
+ 19991.67153481026,
+ 19991.968065391884,
+ 19992.254040205054,
+ 19992.52983486641,
+ 19992.795811636643,
+ 19993.05231989471,
+ 19993.299696595244,
+ 19993.538266709777,
+ 19993.768343652326,
+ 19993.9902296899,
+ 19994.2042163385,
+ 19994.410584745023,
+ 19994.60960605568,
+ 19994.801541771343,
+ 19994.986644090288,
+ 19995.165156238767,
+ 19995.33731278991,
+ 19995.503339971237,
+ 19995.66345596134,
+ 19995.817871175987,
+ 19995.96678854407,
+ 19996.110403773815,
+ 19996.248905609486,
+ 19996.38247607898,
+ 19996.511290732687,
+ 19996.6355188738,
+ 19996.75532378048,
+ 19996.870862920143,
+ 19996.98228815611,
+ 19997.089745946923,
+ 19997.1933775386,
+ 19997.29331915003,
+ 19997.389702151813,
+ 19997.482653238705,
+ 19997.572294595982,
+ 19997.65874405985,
+ 19997.74211527218,
+ 19997.822517829743,
+ 19997.90005742811,
+ 19997.974836000485,
+ 19998.046951851553,
+ 19998.11649978661,
+ 19998.183571236077,
+ 19998.248254375594,
+ 19998.31063424184,
+ 19998.370792844253,
+ 19998.42880927274,
+ 19998.4847598016,
+ 19998.538717989708,
+ 19998.590754777182,
+ 19998.64093857857,
+ 19998.68933537273,
+ 19998.736008789543,
+ 19998.78102019351,
+ 19998.824428764387,
+ 19998.866291574945,
+ 19998.906663665974,
+ 19998.945598118597,
+ 19998.983146124054,
+ 19999.019357050955,
+ 19999.054278510157,
+ 19999.087956417356,
+ 19999.120435053414,
+ 19999.151757122556,
+ 19999.181963808518,
+ 19999.21109482865,
+ 19999.239188486128,
+ 19999.26628172031,
+ 19999.292410155274,
+ 19999.317608146655,
+ 19999.34190882679,
+ 19999.36534414829,
+ 19999.387944926013,
+ 19999.409740877607,
+ 19999.430760662537,
+ 19999.451031919776,
+ 19999.470581304155,
+ 19999.489434521372,
+ 19999.5076163618,
+ 19999.525150733072,
+ 19999.54206069153,
+ 19999.558368472495,
+ 19999.57409551955,
+ 19999.58926251268,
+ 19999.603889395497,
+ 19999.61799540144,
+ 19999.63159907907,
+ 19999.644718316464,
+ 19999.657370364694,
+ 19999.669571860562,
+ 19999.681338848437,
+ 19999.69268680136,
+ 19999.703630641383,
+ 19999.7141847592,
+ 19999.72436303305,
+ 19999.73417884697,
+ 19999.743645108418,
+ 19999.752774265195,
+ 19999.76157832185,
+ 19999.770068855447,
+ 19999.778257030794,
+ 19999.78615361512,
+ 19999.793768992236,
+ 19999.801113176174,
+ 19999.808195824375,
+ 19999.815026250366,
+ 19999.82161343603,
+ 19999.827966043387,
+ 19999.834092426012,
+ 19999.84000064,
+ 20000.0
+ ],
+ "vnorm": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "element": "hydrogen",
+ "charge": 0
+}
\ No newline at end of file
diff --git a/cherab/generomak/plasma/data/core/hydrogen1.json b/cherab/generomak/plasma/data/core/hydrogen1.json
new file mode 100644
index 00000000..a23d3c11
--- /dev/null
+++ b/cherab/generomak/plasma/data/core/hydrogen1.json
@@ -0,0 +1,1294 @@
+{
+ "temperature": [
+ 2800.0,
+ 2795.6140361201715,
+ 2783.083337747409,
+ 2763.3003486616526,
+ 2737.094135213008,
+ 2705.2322750926364,
+ 2668.4232152414806,
+ 2627.3189416606197,
+ 2582.5178419123567,
+ 2534.5676700076638,
+ 2483.96854551181,
+ 2431.1759357517954,
+ 2376.6035832043513,
+ 2320.6263503869714,
+ 2263.5829625419237,
+ 2205.7786346035323,
+ 2147.4875737595085,
+ 2088.955352654985,
+ 2030.4011511730957,
+ 1972.019866937452,
+ 1913.9840963599631,
+ 1856.4459893126868,
+ 1799.5389814222144,
+ 1743.3794086390585,
+ 1688.0680091781107,
+ 1633.691318203845,
+ 1580.3229607811295,
+ 1528.0248486579108,
+ 1476.8482864126447,
+ 1426.8349924056063,
+ 1378.018039834137,
+ 1330.4227230192646,
+ 1284.0673538547676,
+ 1238.963993137122,
+ 1195.1191212721988,
+ 1152.5342526267314,
+ 1111.2064975634503,
+ 1071.1290759712253,
+ 1032.291785877979,
+ 994.6814305162284,
+ 958.2822070001829,
+ 923.0760595703174,
+ 889.0430001669228,
+ 856.1613989086177,
+ 824.4082468755387,
+ 793.759393429837,
+ 764.1897601482588,
+ 735.6735332927431,
+ 708.1843366049751,
+ 681.6953860793737,
+ 656.1796282458071,
+ 631.6098633780208,
+ 607.9588549360606,
+ 585.1994264504128,
+ 563.3045469619041,
+ 542.2474060441687,
+ 522.0014793543342,
+ 502.5405855822321,
+ 483.8389355984452,
+ 465.8711745366052,
+ 448.61241748523827,
+ 432.0382794087496,
+ 416.124899865624,
+ 400.8489630442867,
+ 386.1877135930409,
+ 372.11896867986945,
+ 358.6211266803817,
+ 345.67317285760663,
+ 333.2546823654665,
+ 321.34582087841227,
+ 309.927343122692,
+ 298.9805895598673,
+ 288.4874814503533,
+ 278.4305145037626,
+ 268.79275130356683,
+ 259.5578126759042,
+ 250.7098681561356,
+ 242.23362569190442,
+ 234.11432070782254,
+ 226.33770464446184,
+ 218.89003307292606,
+ 211.75805347586066,
+ 204.92899277624957,
+ 198.39054468665884,
+ 192.13085694367678,
+ 186.13851848507585,
+ 180.40254662065936,
+ 174.91237424177845,
+ 169.65783710907806,
+ 164.62916125309604,
+ 159.8169505178761,
+ 155.21217427370195,
+ 150.80615532139907,
+ 146.59055800733688,
+ 142.55737656528729,
+ 138.69892369858735,
+ 135.00781941365733,
+ 131.47698011372418,
+ 128.09960795968092,
+ 124.86918050324817,
+ 121.77944059606116,
+ 118.82438657692074,
+ 115.99826273821829,
+ 113.29555007145385,
+ 110.71095729082082,
+ 108.23941213297381,
+ 105.87605293038021,
+ 103.6162204549953,
+ 101.45545002847112,
+ 99.38946389462029,
+ 97.41416384945612,
+ 95.52562412379939,
+ 93.72008451315051,
+ 91.99394374930452,
+ 90.34375310799985,
+ 88.7662102467457,
+ 87.25815326688075,
+ 85.81655499383113,
+ 84.43851746950027,
+ 83.12126665071017,
+ 81.86214730760918,
+ 80.65861811600642,
+ 79.5082469376184,
+ 78.408706282292,
+ 77.35776894632689,
+ 76.35330382111951,
+ 75.39327186643368,
+ 74.47572224272074,
+ 73.59878859700572,
+ 72.76068549699494,
+ 71.95970500815942,
+ 71.19421340869229,
+ 70.46264803735373,
+ 69.7635142693571,
+ 69.0953826155724,
+ 68.45688594046604,
+ 67.84671679431725,
+ 67.26362485539421,
+ 66.70641447789761,
+ 66.17394234161189,
+ 65.6651151993376,
+ 65.1788877182984,
+ 64.7142604118468,
+ 64.27027765791827,
+ 63.84602580079542,
+ 63.440631332874815,
+ 63.05325915323381,
+ 62.68311089991544,
+ 62.32942335295714,
+ 61.9914669052981,
+ 61.66854409880293,
+ 61.359988222742814,
+ 61.065161972176995,
+ 60.78345616376737,
+ 60.51428850665944,
+ 60.2571024261477,
+ 60.01136593793548,
+ 59.776570570881596,
+ 59.55223033620793,
+ 59.33788074122536,
+ 59.13307784570519,
+ 58.937397359105915,
+ 58.75043377692946,
+ 58.571799554551646,
+ 58.40112431694312,
+ 58.23805410275451,
+ 58.08225064130303,
+ 57.93339066106313,
+ 57.7911652283102,
+ 57.65527911463285,
+ 57.525450192074885,
+ 57.40140885472106,
+ 57.28289746559213,
+ 57.16966982775895,
+ 57.06149067863122,
+ 56.95813520642253,
+ 56.85938858783372,
+ 56.765045546033065,
+ 56.674909928059456,
+ 56.588794300802036,
+ 56.50651956475268,
+ 56.427914584755875,
+ 56.35281583702141,
+ 56.281067071686564,
+ 56.21251899025332,
+ 56.14702893725086,
+ 56.08446060550164,
+ 56.02468375439783,
+ 55.96757394061782,
+ 55.91301226073971,
+ 55.8608851052287,
+ 55.81108392330204,
+ 55.76350499819346,
+ 55.718049232360165,
+ 55.67462194219673,
+ 55.63313266183696,
+ 55.593494955645,
+ 55.55562623901411,
+ 55.51944760710454,
+ 55.484883671174465,
+ 55.45186240216659,
+ 55.42031498123234,
+ 55.390175656886,
+ 55.361381608497936,
+ 55.333872815845915,
+ 55.307591934457406,
+ 55.282484176486456,
+ 55.258497196881336,
+ 55.23558098460842,
+ 55.21368775870917,
+ 55.19277186897538,
+ 55.17278970103895,
+ 55.153699585681665,
+ 55.13546171217539,
+ 55.11803804547773,
+ 55.101392247108336,
+ 55.08548959954608,
+ 55.070296933989404,
+ 55.05578256132999,
+ 55.04191620619953,
+ 55.028668943950365,
+ 55.01601314044173,
+ 55.003922394507015,
+ 54.99237148298145,
+ 54.98133630817787,
+ 54.970793847702375,
+ 54.96072210650347,
+ 54.951100071057624,
+ 54.941907665596375,
+ 54.93312571028218,
+ 54.9247358812481,
+ 54.91672067241873,
+ 54.90906335903125,
+ 54.90174796278291,
+ 54.8947592185312,
+ 54.888082542479076,
+ 54.881704001777535,
+ 54.87561028548313,
+ 54.869788676811275,
+ 54.86422702662521,
+ 54.858913728107794,
+ 54.85383769256265,
+ 54.84898832629396,
+ 54.8443555085177,
+ 54.83992957025756,
+ 54.83570127418218,
+ 54.83166179534185,
+ 54.82780270276455,
+ 54.824115941872016,
+ 54.82059381768116,
+ 54.81722897875463,
+ 54.81401440186672,
+ 54.81094337735412,
+ 54.80800949511986,
+ 54.80520663126194,
+ 54.7452478101525
+ ],
+ "density": [
+ 4.7000161116838035e+19,
+ 4.682128787215119e+19,
+ 4.662255270837901e+19,
+ 4.6417278208422126e+19,
+ 4.620855584730208e+19,
+ 4.5997877921630495e+19,
+ 4.5786126032580125e+19,
+ 4.557388001473378e+19,
+ 4.536154779862328e+19,
+ 4.514942993087138e+19,
+ 4.4937755363011396e+19,
+ 4.472670293288807e+19,
+ 4.451641505013135e+19,
+ 4.430700683219043e+19,
+ 4.409857243769369e+19,
+ 4.38911895956297e+19,
+ 4.368492293000609e+19,
+ 4.347982645523464e+19,
+ 4.327594548538098e+19,
+ 4.3073318119596106e+19,
+ 4.287197641493933e+19,
+ 4.267194732453969e+19,
+ 4.247325345683865e+19,
+ 4.227591369649927e+19,
+ 4.207994371652285e+19,
+ 4.18853563809563e+19,
+ 4.169216213518003e+19,
+ 4.150036932127918e+19,
+ 4.130998441718659e+19,
+ 4.1121012257462985e+19,
+ 4.093345622347993e+19,
+ 4.074731840811801e+19,
+ 4.056259975913072e+19,
+ 4.037930020368103e+19,
+ 4.019741870571682e+19,
+ 4.001695340964126e+19,
+ 3.983790175600905e+19,
+ 3.966026052904146e+19,
+ 3.948402592421399e+19,
+ 3.930919360878721e+19,
+ 3.91357587761679e+19,
+ 3.896371619490987e+19,
+ 3.879306025305037e+19,
+ 3.862378038885082e+19,
+ 3.8455872756913046e+19,
+ 3.828933304946574e+19,
+ 3.812415434913541e+19,
+ 3.796032969592534e+19,
+ 3.779785195844539e+19,
+ 3.763671385931872e+19,
+ 3.747690800145458e+19,
+ 3.731842689377711e+19,
+ 3.716126297679983e+19,
+ 3.700540864846064e+19,
+ 3.6850856060966724e+19,
+ 3.6697596750521393e+19,
+ 3.6545622931847754e+19,
+ 3.63949269560757e+19,
+ 3.624550126620646e+19,
+ 3.6097338433711747e+19,
+ 3.5950431200155054e+19,
+ 3.580477252521384e+19,
+ 3.5660355599881843e+19,
+ 3.551717212816437e+19,
+ 3.5375214199829737e+19,
+ 3.523447525545721e+19,
+ 3.509494910531205e+19,
+ 3.4956630001189454e+19,
+ 3.4819512721075306e+19,
+ 3.4683592669405524e+19,
+ 3.4548865996283527e+19,
+ 3.44153297397094e+19,
+ 3.4282981995701944e+19,
+ 3.4151822122170814e+19,
+ 3.402185098353278e+19,
+ 3.389307085841355e+19,
+ 3.3765477248415257e+19,
+ 3.36390706526775e+19,
+ 3.3513857808022893e+19,
+ 3.3389848457318638e+19,
+ 3.326705595137885e+19,
+ 3.3145497973701267e+19,
+ 3.3025197409857077e+19,
+ 3.2906183384364196e+19,
+ 3.27884924868037e+19,
+ 3.2672168857369743e+19,
+ 3.2557253870071173e+19,
+ 3.2443771047542505e+19,
+ 3.233178288004695e+19,
+ 3.222136754653978e+19,
+ 3.2112618260038386e+19,
+ 3.2005644930339512e+19,
+ 3.190057544359449e+19,
+ 3.179755610169293e+19,
+ 3.169667413331649e+19,
+ 3.1597941789312086e+19,
+ 3.1501468231219503e+19,
+ 3.1407358392679612e+19,
+ 3.1315701402899493e+19,
+ 3.122655976363501e+19,
+ 3.113995725177193e+19,
+ 3.1055866895317287e+19,
+ 3.0974201050364137e+19,
+ 3.0894806075100783e+19,
+ 3.0817464043937587e+19,
+ 3.074190310163784e+19,
+ 3.0667602748084875e+19,
+ 3.059388912084078e+19,
+ 3.0520502154565943e+19,
+ 3.0447256542588035e+19,
+ 3.0374032039505535e+19,
+ 3.0300769320810455e+19,
+ 3.0227459649422733e+19,
+ 3.0154130399978762e+19,
+ 3.0080828724751536e+19,
+ 3.00076055212318e+19,
+ 2.9934501515846365e+19,
+ 2.986153682499915e+19,
+ 2.9788666487587082e+19,
+ 2.9715601389175697e+19,
+ 2.9642293974170833e+19,
+ 2.9568746794147893e+19,
+ 2.9494953117879144e+19,
+ 2.942090418993194e+19,
+ 2.9346594991144505e+19,
+ 2.927202828423032e+19,
+ 2.919721694348071e+19,
+ 2.912218473740004e+19,
+ 2.9046961655055204e+19,
+ 2.897159522535346e+19,
+ 2.889613573005297e+19,
+ 2.8820638275299803e+19,
+ 2.8745160581640344e+19,
+ 2.866976018562403e+19,
+ 2.859446819509753e+19,
+ 2.8519338651384783e+19,
+ 2.8444437402203193e+19,
+ 2.8369821546424705e+19,
+ 2.8295540143670977e+19,
+ 2.822163499192403e+19,
+ 2.8148141418240123e+19,
+ 2.8075089045501837e+19,
+ 2.800250251202477e+19,
+ 2.7930402131116364e+19,
+ 2.785880448496708e+19,
+ 2.7787722952184242e+19,
+ 2.7717168171436e+19,
+ 2.764714844554494e+19,
+ 2.757767009134292e+19,
+ 2.750873774095989e+19,
+ 2.744035460018579e+19,
+ 2.7372522669268402e+19,
+ 2.730524293109751e+19,
+ 2.7238515511248703e+19,
+ 2.7172339813867467e+19,
+ 2.710671463689212e+19,
+ 2.704163826966439e+19,
+ 2.697710857556336e+19,
+ 2.6913123061929193e+19,
+ 2.684967893921741e+19,
+ 2.678677317103723e+19,
+ 2.6724402516482183e+19,
+ 2.666256356594527e+19,
+ 2.6601252771429528e+19,
+ 2.6540466472208925e+19,
+ 2.648020091656107e+19,
+ 2.642045228018025e+19,
+ 2.6361216681785897e+19,
+ 2.6302490196357964e+19,
+ 2.6244268866366194e+19,
+ 2.6186547167773954e+19,
+ 2.6129321911080337e+19,
+ 2.607258987087877e+19,
+ 2.6016347040942785e+19,
+ 2.596058941784374e+19,
+ 2.5905313005155705e+19,
+ 2.585051381702677e+19,
+ 2.5796187881207525e+19,
+ 2.5742331241620062e+19,
+ 2.568893996053235e+19,
+ 2.563601012039743e+19,
+ 2.5583537825404264e+19,
+ 2.5531519202783388e+19,
+ 2.5479950403901665e+19,
+ 2.5428827605176574e+19,
+ 2.5378147008834527e+19,
+ 2.5327904843536536e+19,
+ 2.5278097364889854e+19,
+ 2.522872085586001e+19,
+ 2.5179771627098292e+19,
+ 2.5131246017196376e+19,
+ 2.5083140392876634e+19,
+ 2.5035451149129798e+19,
+ 2.498817470930402e+19,
+ 2.4941307525154173e+19,
+ 2.4894846076854927e+19,
+ 2.484878687298473e+19,
+ 2.4803126450483405e+19,
+ 2.475786137458537e+19,
+ 2.4712988238736052e+19,
+ 2.466850366448876e+19,
+ 2.462440430138878e+19,
+ 2.4580686826843484e+19,
+ 2.4537347945982157e+19,
+ 2.4494384391507644e+19,
+ 2.445179292353768e+19,
+ 2.4409570329441386e+19,
+ 2.4367713423668306e+19,
+ 2.432621904757395e+19,
+ 2.428508406924054e+19,
+ 2.4244305383293637e+19,
+ 2.420387991071655e+19,
+ 2.4163804063775474e+19,
+ 2.4124074299375776e+19,
+ 2.4084688695258206e+19,
+ 2.4045644275574723e+19,
+ 2.4006938089881907e+19,
+ 2.3968567212948713e+19,
+ 2.393052874455778e+19,
+ 2.3892819809314083e+19,
+ 2.3855437556447207e+19,
+ 2.3818379159616664e+19,
+ 2.378164181671946e+19,
+ 2.374522274969222e+19,
+ 2.3709119204319965e+19,
+ 2.3673328450042348e+19,
+ 2.3637847779761213e+19,
+ 2.3602674509648167e+19,
+ 2.3567805978955555e+19,
+ 2.3533239549825778e+19,
+ 2.349897260710105e+19,
+ 2.346500255813818e+19,
+ 2.3431326832619577e+19,
+ 2.3397942882369196e+19,
+ 2.3364848181166285e+19,
+ 2.333204022456342e+19,
+ 2.3299516529704546e+19,
+ 2.326727463514042e+19,
+ 2.3235312100654547e+19,
+ 2.320362650708015e+19,
+ 2.3172215456123494e+19,
+ 2.3141076570189193e+19,
+ 2.3110207492203815e+19,
+ 2.3079605885444526e+19,
+ 2.3049269433364124e+19,
+ 2.3019195839420236e+19,
+ 2.2989382826907095e+19,
+ 2.295982813878743e+19,
+ 2.293052953752237e+19,
+ 2.290148480490682e+19,
+ 2.287269174190705e+19,
+ 2.2844148168495403e+19,
+ 2.2815851923484787e+19,
+ 2.278780086437519e+19,
+ 2.2759992867188072e+19,
+ 1.9578429198926516e+19
+ ],
+ "vtor": [
+ 100000.0,
+ 99544.32023364124,
+ 98251.15453696062,
+ 96235.68685722632,
+ 93614.68356191639,
+ 90502.18847954353,
+ 87006.32501749854,
+ 83227.06508922808,
+ 79254.813872946,
+ 75169.66123127713,
+ 71041.16042746486,
+ 66928.50919629741,
+ 62881.02482158773,
+ 58938.821939433255,
+ 55133.61820859918,
+ 51489.60808192722,
+ 48024.35830839606,
+ 44749.69035052268,
+ 41672.524623402256,
+ 38795.66945343124,
+ 36118.54407642795,
+ 33637.83003375026,
+ 31348.04917610031,
+ 29242.06933764292,
+ 27311.54077408969,
+ 25547.26782590489,
+ 23939.521110407513,
+ 22478.295982958116,
+ 21153.523137258686,
+ 19955.237120191036,
+ 18873.708284120235,
+ 17899.54334214529,
+ 17023.759270761642,
+ 16237.834851443324,
+ 15533.743681380842,
+ 14903.972031120154,
+ 14341.524495030524,
+ 13839.919977172622,
+ 13393.180184865832,
+ 12995.812467288095,
+ 12642.788537234375,
+ 12329.520349892675,
+ 12051.83418147994,
+ 11805.94375056095,
+ 11588.423053275488,
+ 11396.179437797053,
+ 11226.42732039882,
+ 11076.662842842592,
+ 10944.639685904545,
+ 10828.34618435543,
+ 10725.983832469563,
+ 10635.94722420132,
+ 10556.805436804136,
+ 10487.284839339893,
+ 10426.253286892172,
+ 10372.705646187464,
+ 10325.750587737686,
+ 10284.598572685094,
+ 10248.550958525679,
+ 10216.990146193662,
+ 10189.370691092356,
+ 10165.211302127113,
+ 10144.087655281786,
+ 10125.625951492917,
+ 10109.49715228246,
+ 10095.411830623676,
+ 10083.115578687914,
+ 10072.384918337477,
+ 10063.023664403154,
+ 10054.85969484832,
+ 10047.742085826912,
+ 10041.538573356505,
+ 10036.133306828673,
+ 10031.424862854412,
+ 10027.3244909875,
+ 10023.75456568367,
+ 10020.647221443161,
+ 10017.943150456194,
+ 10015.59054423511,
+ 10013.544162684711,
+ 10011.764515845945,
+ 10010.217145160046,
+ 10008.871992553453,
+ 10007.702846950711,
+ 10006.686858995241,
+ 10005.804115808194,
+ 10005.037268554323,
+ 10004.371206421612,
+ 10003.792771367725,
+ 10003.29050865027,
+ 10002.85444874773,
+ 10002.475916801126,
+ 10002.14736617021,
+ 10001.86223310832,
+ 10001.614809922945,
+ 10001.400134309408,
+ 10001.213892828007,
+ 10001.052336744104,
+ 10000.912208670363,
+ 10000.790678643563,
+ 10000.68528843837,
+ 10000.593903069897,
+ 10000.514668568,
+ 10000.445975221452,
+ 10000.386425591105,
+ 10000.334806679686,
+ 10000.290065723417,
+ 10000.25128913859,
+ 10000.217684215675,
+ 10000.188563205464,
+ 10000.16332948734,
+ 10000.141465549392,
+ 10000.122522544827,
+ 10000.106111219531,
+ 10000.091894031972,
+ 10000.079578309811,
+ 10000.068910307727,
+ 10000.05967004848,
+ 10000.051666844598,
+ 10000.044735411424,
+ 10000.038732493818,
+ 10000.033533939033,
+ 10000.029032157028,
+ 10000.02513391718,
+ 10000.021758437058,
+ 10000.018835724715,
+ 10000.016305140998,
+ 10000.01411415281,
+ 10000.012217252064,
+ 10000.010575018385,
+ 10000.009153306504,
+ 10000.007922541854,
+ 10000.00685710995,
+ 10000.005934827166,
+ 10000.005136482061,
+ 10000.004445437868,
+ 10000.003847288048,
+ 10000.003329557814,
+ 10000.002881445527,
+ 10000.00249359863,
+ 10000.002157919536,
+ 10000.001867397486,
+ 10000.001615962863,
+ 10000.001398361033,
+ 10000.001210043049,
+ 10000.001047070993,
+ 10000.000906036008,
+ 10000.000783987294,
+ 10000.000678370623,
+ 10000.000586975104,
+ 10000.000507887078,
+ 10000.000439450198,
+ 10000.000380230858,
+ 10000.000328988277,
+ 10000.000284648579,
+ 10000.000246282361,
+ 10000.000213085277,
+ 10000.00018436122,
+ 10000.000159507772,
+ 10000.000138003594,
+ 10000.000119397531,
+ 10000.000103299173,
+ 10000.000089370667,
+ 10000.000077319659,
+ 10000.000066893168,
+ 10000.000057872281,
+ 10000.000050067574,
+ 10000.00004331514,
+ 10000.00003747315,
+ 10000.000032418886,
+ 10000.000028046165,
+ 10000.00002426311,
+ 10000.000020990228,
+ 10000.000018158735,
+ 10000.00001570912,
+ 10000.000013589894,
+ 10000.000011756505,
+ 10000.00001017041,
+ 10000.00000879826,
+ 10000.000007611205,
+ 10000.00000658428,
+ 10000.000005695889,
+ 10000.000004927346,
+ 10000.000004262487,
+ 10000.000003687326,
+ 10000.000003189763,
+ 10000.000002759334,
+ 10000.000002386978,
+ 10000.000002064864,
+ 10000.000001786213,
+ 10000.00000154516,
+ 10000.000001336637,
+ 10000.00000115625,
+ 10000.000001000204,
+ 10000.000000865217,
+ 10000.000000748445,
+ 10000.000000647431,
+ 10000.00000056005,
+ 10000.000000484462,
+ 10000.000000419075,
+ 10000.000000362512,
+ 10000.000000313583,
+ 10000.000000271257,
+ 10000.000000234644,
+ 10000.000000202972,
+ 10000.000000175574,
+ 10000.000000151877,
+ 10000.000000131377,
+ 10000.000000113641,
+ 10000.000000098302,
+ 10000.000000085032,
+ 10000.000000073554,
+ 10000.000000063626,
+ 10000.000000055037,
+ 10000.000000047608,
+ 10000.000000041182,
+ 10000.000000035621,
+ 10000.000000030814,
+ 10000.000000026654,
+ 10000.000000023056,
+ 10000.000000019943,
+ 10000.000000017251,
+ 10000.000000014923,
+ 10000.000000012908,
+ 10000.000000011165,
+ 10000.000000009659,
+ 10000.000000008355,
+ 10000.000000007227,
+ 10000.00000000625,
+ 10000.000000005406,
+ 10000.000000004677,
+ 10000.000000004045,
+ 10000.0000000035,
+ 10000.000000003027,
+ 10000.000000002618,
+ 10000.000000002265,
+ 10000.000000001959,
+ 10000.000000001695,
+ 10000.000000001466,
+ 10000.000000001268,
+ 10000.000000001097,
+ 10000.00000000095,
+ 10000.00000000082,
+ 10000.00000000071,
+ 10000.000000000615,
+ 10000.000000000531,
+ 10000.00000000046,
+ 10000.000000000397,
+ 10000.000000000344,
+ 10000.000000000296,
+ 10000.000000000256,
+ 10000.000000000222,
+ 10000.000000000193,
+ 10000.000000000167,
+ 10000.000000000144,
+ 10000.0
+ ],
+ "vpol": [
+ 18462.326927732716,
+ 18514.99979366994,
+ 18565.939231880784,
+ 18615.197379613106,
+ 18662.8251518226,
+ 18708.87224398403,
+ 18753.38713728863,
+ 18796.417106004,
+ 18838.008226787257,
+ 18878.20538975573,
+ 18917.052311132516,
+ 18954.591547296637,
+ 18990.864510079347,
+ 19025.91148315922,
+ 19059.7716394193,
+ 19092.483059139577,
+ 19124.08274890752,
+ 19154.60666113828,
+ 19184.089714104663,
+ 19212.565812384706,
+ 19240.067867642374,
+ 19266.627819663598,
+ 19292.27665757659,
+ 19317.044441191432,
+ 19340.960322399642,
+ 19364.052566579816,
+ 19386.34857396039,
+ 19407.874900895215,
+ 19428.65728101207,
+ 19448.720646198086,
+ 19468.08914739,
+ 19486.78617514046,
+ 19504.834379934928,
+ 19522.2556922367,
+ 19539.07134224024,
+ 19555.301879315663,
+ 19570.96719112952,
+ 19586.08652242914,
+ 19600.678493479918,
+ 19614.761118146518,
+ 19628.351821610984,
+ 19641.467457721887,
+ 19654.124325970388,
+ 19666.33818809011,
+ 19678.124284279074,
+ 19689.497349042842,
+ 19700.47162665909,
+ 19711.060886264648,
+ 19721.278436566783,
+ 19731.137140181316,
+ 19740.649427600623,
+ 19749.827310795343,
+ 19758.68239645382,
+ 19767.225898864108,
+ 19775.4686524434,
+ 19783.421123920307,
+ 19791.093424175622,
+ 19798.49531974744,
+ 19805.63624400677,
+ 19812.52530800986,
+ 19819.171311033715,
+ 19825.582750801284,
+ 19831.76783340299,
+ 19837.73448292125,
+ 19843.49035076469,
+ 19849.042824718887,
+ 19854.399037720275,
+ 19859.565876360022,
+ 19864.549989124593,
+ 19869.357794379575,
+ 19873.99548810352,
+ 19878.469051378208,
+ 19882.78425764191,
+ 19886.946679712015,
+ 19890.961696583312,
+ 19894.83450000816,
+ 19898.570100864654,
+ 19902.173335318803,
+ 19905.64887078662,
+ 19909.00121170188,
+ 19912.234705095303,
+ 19915.353545990587,
+ 19918.361782622906,
+ 19921.263321485007,
+ 19924.061932206263,
+ 19926.76125226966,
+ 19929.36479157172,
+ 19931.875936830187,
+ 19934.297955844206,
+ 19936.634001611572,
+ 19938.887116307546,
+ 19941.060235129582,
+ 19943.156190012254,
+ 19945.17771321644,
+ 19947.12744079687,
+ 19949.00791595186,
+ 19950.821592259108,
+ 19952.570836801166,
+ 19954.25793318425,
+ 19955.885084453774,
+ 19957.454415910102,
+ 19958.967977827684,
+ 19960.427748080827,
+ 19961.835634679162,
+ 19963.193478215824,
+ 19964.503054231183,
+ 19965.76607549503,
+ 19966.984194209857,
+ 19968.159004137942,
+ 19969.292042654735,
+ 19970.384792731096,
+ 19971.438684846682,
+ 19972.455098836952,
+ 19973.435365675872,
+ 19974.380769196654,
+ 19975.29254775252,
+ 19976.1718958196,
+ 19977.019965543906,
+ 19977.83786823432,
+ 19978.6266758034,
+ 19979.38742215782,
+ 19980.121104540183,
+ 19980.828684823875,
+ 19981.511090762506,
+ 19982.169217195635,
+ 19982.80392721215,
+ 19983.41605327286,
+ 19984.006398293674,
+ 19984.575736690727,
+ 19985.124815388765,
+ 19985.654354794107,
+ 19986.165049733347,
+ 19986.657570359053,
+ 19987.132563023555,
+ 19987.590651121973,
+ 19988.03243590553,
+ 19988.458497266216,
+ 19988.869394493737,
+ 19989.265667005842,
+ 19989.647835052798,
+ 19990.01640039704,
+ 19990.371846968832,
+ 19990.714641498744,
+ 19991.045234127785,
+ 19991.36405899601,
+ 19991.67153481026,
+ 19991.968065391884,
+ 19992.254040205054,
+ 19992.52983486641,
+ 19992.795811636643,
+ 19993.05231989471,
+ 19993.299696595244,
+ 19993.538266709777,
+ 19993.768343652326,
+ 19993.9902296899,
+ 19994.2042163385,
+ 19994.410584745023,
+ 19994.60960605568,
+ 19994.801541771343,
+ 19994.986644090288,
+ 19995.165156238767,
+ 19995.33731278991,
+ 19995.503339971237,
+ 19995.66345596134,
+ 19995.817871175987,
+ 19995.96678854407,
+ 19996.110403773815,
+ 19996.248905609486,
+ 19996.38247607898,
+ 19996.511290732687,
+ 19996.6355188738,
+ 19996.75532378048,
+ 19996.870862920143,
+ 19996.98228815611,
+ 19997.089745946923,
+ 19997.1933775386,
+ 19997.29331915003,
+ 19997.389702151813,
+ 19997.482653238705,
+ 19997.572294595982,
+ 19997.65874405985,
+ 19997.74211527218,
+ 19997.822517829743,
+ 19997.90005742811,
+ 19997.974836000485,
+ 19998.046951851553,
+ 19998.11649978661,
+ 19998.183571236077,
+ 19998.248254375594,
+ 19998.31063424184,
+ 19998.370792844253,
+ 19998.42880927274,
+ 19998.4847598016,
+ 19998.538717989708,
+ 19998.590754777182,
+ 19998.64093857857,
+ 19998.68933537273,
+ 19998.736008789543,
+ 19998.78102019351,
+ 19998.824428764387,
+ 19998.866291574945,
+ 19998.906663665974,
+ 19998.945598118597,
+ 19998.983146124054,
+ 19999.019357050955,
+ 19999.054278510157,
+ 19999.087956417356,
+ 19999.120435053414,
+ 19999.151757122556,
+ 19999.181963808518,
+ 19999.21109482865,
+ 19999.239188486128,
+ 19999.26628172031,
+ 19999.292410155274,
+ 19999.317608146655,
+ 19999.34190882679,
+ 19999.36534414829,
+ 19999.387944926013,
+ 19999.409740877607,
+ 19999.430760662537,
+ 19999.451031919776,
+ 19999.470581304155,
+ 19999.489434521372,
+ 19999.5076163618,
+ 19999.525150733072,
+ 19999.54206069153,
+ 19999.558368472495,
+ 19999.57409551955,
+ 19999.58926251268,
+ 19999.603889395497,
+ 19999.61799540144,
+ 19999.63159907907,
+ 19999.644718316464,
+ 19999.657370364694,
+ 19999.669571860562,
+ 19999.681338848437,
+ 19999.69268680136,
+ 19999.703630641383,
+ 19999.7141847592,
+ 19999.72436303305,
+ 19999.73417884697,
+ 19999.743645108418,
+ 19999.752774265195,
+ 19999.76157832185,
+ 19999.770068855447,
+ 19999.778257030794,
+ 19999.78615361512,
+ 19999.793768992236,
+ 19999.801113176174,
+ 19999.808195824375,
+ 19999.815026250366,
+ 19999.82161343603,
+ 19999.827966043387,
+ 19999.834092426012,
+ 19999.84000064,
+ 20000.0
+ ],
+ "vnorm": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "element": "hydrogen",
+ "charge": 1
+}
\ No newline at end of file
diff --git a/cherab/generomak/plasma/data/core/psi_norm.json b/cherab/generomak/plasma/data/core/psi_norm.json
new file mode 100644
index 00000000..01760ebf
--- /dev/null
+++ b/cherab/generomak/plasma/data/core/psi_norm.json
@@ -0,0 +1,260 @@
+{
+ "psi_norm": [
+ 0.0,
+ 0.03561162084555414,
+ 0.06995505415186065,
+ 0.10307546213272856,
+ 0.13501639870233162,
+ 0.1658198667493661,
+ 0.19552637337158152,
+ 0.2241749831433214,
+ 0.25180336948611703,
+ 0.27844786420989853,
+ 0.3041435052899555,
+ 0.3289240829424859,
+ 0.35282218405932053,
+ 0.3758692350602538,
+ 0.3980955432193337,
+ 0.41953033651945604,
+ 0.44020180208767157,
+ 0.4601371232617498,
+ 0.47936251533674257,
+ 0.49790326003855345,
+ 0.5157837387698492,
+ 0.5330274646720292,
+ 0.5496571135454165,
+ 0.5656945536683295,
+ 0.581160874554252,
+ 0.5960764146849096,
+ 0.6104607882557274,
+ 0.6243329109688405,
+ 0.637711024907571,
+ 0.6506127225250871,
+ 0.663054969778784,
+ 0.6750541284408158,
+ 0.6866259776141095,
+ 0.6977857344821621,
+ 0.7085480743199009,
+ 0.7189271497919272,
+ 0.7289366095635164,
+ 0.7385896162488508,
+ 0.7478988637200875,
+ 0.7568765938000214,
+ 0.7655346123602946,
+ 0.7738843048463258,
+ 0.7819366512493673,
+ 0.7897022405453866,
+ 0.7971912846197539,
+ 0.8044136316960491,
+ 0.8113787792866483,
+ 0.8180958866821177,
+ 0.8245737869958408,
+ 0.8308209987797164,
+ 0.8368457372262026,
+ 0.842655924971439,
+ 0.8482592025136506,
+ 0.8536629382605364,
+ 0.8588742382188548,
+ 0.8638999553389449,
+ 0.8687466985264773,
+ 0.8734208413332797,
+ 0.8779285303386681,
+ 0.882275693232307,
+ 0.8864680466092238,
+ 0.8905111034872313,
+ 0.8944101805566421,
+ 0.8981704051718096,
+ 0.9017967220936874,
+ 0.9052938999922776,
+ 0.9086665377175137,
+ 0.9119190703468294,
+ 0.915055775017362,
+ 0.9180807765504632,
+ 0.9209980528759103,
+ 0.9238114402629539,
+ 0.9265246383650785,
+ 0.9291412150851113,
+ 0.931664611267077,
+ 0.9340981452209673,
+ 0.9364450170863771,
+ 0.9387083130407426,
+ 0.9408910093577201,
+ 0.9429959763210364,
+ 0.9450259819989626,
+ 0.9469836958843723,
+ 0.9488716924051706,
+ 0.9506924543097125,
+ 0.9524483759316599,
+ 0.954141766338572,
+ 0.9557748523683696,
+ 0.9573497815576658,
+ 0.9588686249658143,
+ 0.960333379898388,
+ 0.9617459725336712,
+ 0.9631082604556176,
+ 0.9644220350966051,
+ 0.9656890240932012,
+ 0.9669108935580351,
+ 0.9680892502707645,
+ 0.9692256437910194,
+ 0.9703215684960996,
+ 0.9713784655461073,
+ 0.9723977247790973,
+ 0.9733806865387387,
+ 0.9743286434368901,
+ 0.9752428420534066,
+ 0.9761244845754142,
+ 0.9769747303782067,
+ 0.9777946975498447,
+ 0.9785854643614604,
+ 0.9793480706852037,
+ 0.9800835193616915,
+ 0.9807927775187607,
+ 0.9814767778432588,
+ 0.9821364198075426,
+ 0.9827725708523005,
+ 0.9833860675272521,
+ 0.9839777165912252,
+ 0.9845482960730585,
+ 0.9850985562947225,
+ 0.9856292208580062,
+ 0.9861409875960662,
+ 0.9866345294910889,
+ 0.9871104955592747,
+ 0.9875695117043048,
+ 0.9880121815404163,
+ 0.9884390871861642,
+ 0.988850790029919,
+ 0.989247831468101,
+ 0.9896307336171266,
+ 0.99,
+ 0.9903561162084555,
+ 0.9906995505415186,
+ 0.9910307546213273,
+ 0.9913501639870234,
+ 0.9916581986674937,
+ 0.9919552637337158,
+ 0.9922417498314332,
+ 0.9925180336948611,
+ 0.992784478642099,
+ 0.9930414350528995,
+ 0.9932892408294248,
+ 0.9935282218405932,
+ 0.9937586923506025,
+ 0.9939809554321933,
+ 0.9941953033651946,
+ 0.9944020180208767,
+ 0.9946013712326175,
+ 0.9947936251533674,
+ 0.9949790326003856,
+ 0.9951578373876985,
+ 0.9953302746467203,
+ 0.9954965711354542,
+ 0.9956569455366833,
+ 0.9958116087455425,
+ 0.9959607641468491,
+ 0.9961046078825573,
+ 0.9962433291096884,
+ 0.9963771102490757,
+ 0.9965061272252509,
+ 0.9966305496977879,
+ 0.9967505412844082,
+ 0.9968662597761411,
+ 0.9969778573448216,
+ 0.997085480743199,
+ 0.9971892714979192,
+ 0.9972893660956351,
+ 0.9973858961624885,
+ 0.9974789886372009,
+ 0.9975687659380003,
+ 0.997655346123603,
+ 0.9977388430484633,
+ 0.9978193665124937,
+ 0.9978970224054539,
+ 0.9979719128461976,
+ 0.9980441363169605,
+ 0.9981137877928665,
+ 0.9981809588668211,
+ 0.9982457378699584,
+ 0.9983082099877971,
+ 0.998368457372262,
+ 0.9984265592497144,
+ 0.9984825920251366,
+ 0.9985366293826053,
+ 0.9985887423821885,
+ 0.9986389995533894,
+ 0.9986874669852648,
+ 0.9987342084133328,
+ 0.9987792853033867,
+ 0.998822756932323,
+ 0.9988646804660922,
+ 0.9989051110348723,
+ 0.9989441018055665,
+ 0.998981704051718,
+ 0.9990179672209368,
+ 0.9990529389999228,
+ 0.9990866653771752,
+ 0.9991191907034683,
+ 0.9991505577501736,
+ 0.9991808077655047,
+ 0.9992099805287591,
+ 0.9992381144026296,
+ 0.9992652463836508,
+ 0.9992914121508512,
+ 0.9993166461126708,
+ 0.9993409814522096,
+ 0.9993644501708637,
+ 0.9993870831304075,
+ 0.9994089100935772,
+ 0.9994299597632104,
+ 0.9994502598199896,
+ 0.9994698369588437,
+ 0.9994887169240517,
+ 0.9995069245430971,
+ 0.9995244837593166,
+ 0.9995414176633857,
+ 0.9995577485236837,
+ 0.9995734978155767,
+ 0.9995886862496581,
+ 0.9996033337989839,
+ 0.9996174597253367,
+ 0.9996310826045561,
+ 0.999644220350966,
+ 0.999656890240932,
+ 0.9996691089355804,
+ 0.9996808925027076,
+ 0.9996922564379102,
+ 0.999703215684961,
+ 0.9997137846554611,
+ 0.9997239772477909,
+ 0.9997338068653874,
+ 0.9997432864343689,
+ 0.999752428420534,
+ 0.9997612448457541,
+ 0.9997697473037821,
+ 0.9997779469754985,
+ 0.9997858546436146,
+ 0.999793480706852,
+ 0.999800835193617,
+ 0.9998079277751876,
+ 0.9998147677784326,
+ 0.9998213641980754,
+ 0.999827725708523,
+ 0.9998338606752725,
+ 0.9998397771659122,
+ 0.9998454829607306,
+ 0.9998509855629473,
+ 0.9998562922085801,
+ 0.9998614098759606,
+ 0.9998663452949109,
+ 0.9998711049555927,
+ 0.999875695117043,
+ 0.9998801218154042,
+ 0.9998843908718617,
+ 0.9998885079002992,
+ 0.999892478314681,
+ 0.9998963073361713,
+ 0.9999,
+ 1.0
+ ]
+}
\ No newline at end of file
diff --git a/cherab/generomak/plasma/data/edge/carbon0.json b/cherab/generomak/plasma/data/edge/carbon0.json
index beee5028..cc58c95c 100644
--- a/cherab/generomak/plasma/data/edge/carbon0.json
+++ b/cherab/generomak/plasma/data/edge/carbon0.json
@@ -36,52 +36,52 @@
0.8826349542181627,
0.8899903230020518,
0.8899903230020518,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7047757257456048,
0.7047757257456048,
0.7072344434153071,
@@ -94,10 +94,10 @@
0.771280502896162,
0.7378957943285048,
0.7378957943285048,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6668202352525383,
0.6668202352525383,
0.6939803492353266,
@@ -114,56 +114,56 @@
0.7550529537931084,
0.6698586018699858,
0.6698586018699858,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.8777104035584131,
0.8777104035584131,
0.8904284769390789,
@@ -232,52 +232,52 @@
0.8826349542181627,
0.8899903230020518,
0.8899903230020518,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7047757257456048,
0.7047757257456048,
0.7072344434153071,
@@ -290,10 +290,10 @@
0.771280502896162,
0.7378957943285048,
0.7378957943285048,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6668202352525383,
0.6668202352525383,
0.6939803492353266,
@@ -310,56 +310,56 @@
0.7550529537931084,
0.6698586018699858,
0.6698586018699858,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.8777104035584131,
0.8777104035584131,
0.8904284769390789,
@@ -428,52 +428,52 @@
0.9488695364408866,
0.9776952595352856,
0.9776952595352856,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7381857748401043,
0.7381857748401043,
0.7252051835877666,
@@ -486,10 +486,10 @@
0.6707223018957097,
0.6653150953392322,
0.6653150953392322,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6712374760547157,
0.6712374760547157,
0.6863147774504369,
@@ -506,62 +506,62 @@
0.7169300660266651,
0.7016922330175489,
0.7016922330175489,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 0.989668471223005,
- 0.989668471223005,
- 0.9084402862412485,
- 0.9084402862412485,
- 0.9888120737628983,
- 0.9888120737628983,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 0.989668471223005,
+ 0.989668471223005,
+ 0.9084402862412485,
+ 0.9084402862412485,
+ 0.9888120737628983,
+ 0.9888120737628983,
0.9238193646007199,
0.9238193646007199,
0.9402302268252902,
@@ -624,52 +624,52 @@
1.0141940442254633,
1.0314660474570372,
1.0314660474570372,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7425897836430437,
0.7425897836430437,
0.7658060128718618,
@@ -682,10 +682,10 @@
0.671465665626478,
0.6819424130985049,
0.6819424130985049,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7291516897755482,
0.7291516897755482,
0.7241049927832115,
@@ -702,56 +702,56 @@
0.7451781374562225,
0.6630318889047037,
0.6630318889047037,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
1.041544898725567,
1.041544898725567,
0.9741726142287506,
@@ -820,52 +820,52 @@
1.0599891197764155,
1.0291050094043501,
1.0291050094043501,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7562683004400875,
0.7562683004400875,
0.7327700174161945,
@@ -878,10 +878,10 @@
0.6702462619986006,
0.7024151245985529,
0.7024151245985529,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.697839411880975,
0.697839411880975,
0.7256309169217358,
@@ -898,56 +898,56 @@
0.7184151082807516,
0.6821155525602305,
0.6821155525602305,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.9521070696129001,
0.9521070696129001,
0.875934444566366,
@@ -1016,52 +1016,52 @@
0.9521600600249424,
0.9985453326739754,
0.9985453326739754,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7107102149886928,
0.7107102149886928,
0.6925560368645347,
@@ -1074,10 +1074,10 @@
0.7163705771532305,
0.7085061508892283,
0.7085061508892283,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6568431829970128,
0.6568431829970128,
0.6666301188861303,
@@ -1094,56 +1094,56 @@
0.6694595197797648,
0.7170387931147423,
0.7170387931147423,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
20.447996996565863,
20.447996996565863,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.9327311785025072,
0.9327311785025072,
0.9597158436652123,
@@ -1212,52 +1212,52 @@
1.0298700935866976,
0.9528687209652565,
0.9528687209652565,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6387338189080094,
0.6387338189080094,
0.6234247702803535,
@@ -1270,10 +1270,10 @@
0.6924896272079825,
0.6741197425302109,
0.6741197425302109,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7490929991929967,
0.7490929991929967,
0.7573533243775917,
@@ -1290,56 +1290,56 @@
0.6863972902004013,
0.7098833398665082,
0.7098833398665082,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
29.736571479671202,
29.736571479671202,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
41.119296463288705,
41.119296463288705,
20.70607715528574,
20.70607715528574,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
20.447996996565863,
20.447996996565863,
11.907214594917132,
11.907214594917132,
11.053179545995052,
11.053179545995052,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.9374114989121731,
0.9374114989121731,
1.0162759619923405,
@@ -1408,52 +1408,52 @@
0.9172602251294597,
1.034558340712888,
1.034558340712888,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7698504483370217,
0.7698504483370217,
0.6974013203590386,
@@ -1466,10 +1466,10 @@
0.7918775452569733,
0.6937161461562047,
0.6937161461562047,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6507337442545676,
0.6507337442545676,
0.6520238017651679,
@@ -1486,60 +1486,60 @@
0.668291795847024,
0.715565672142988,
0.715565672142988,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
29.736571479671202,
29.736571479671202,
28.954414273401518,
28.954414273401518,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
41.119296463288705,
41.119296463288705,
20.70607715528574,
20.70607715528574,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
20.436121901400792,
20.436121901400792,
22.917604227150402,
22.917604227150402,
11.053179545995052,
11.053179545995052,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 1.0904314561361903,
- 1.0904314561361903,
- 1.085821664779066,
- 1.085821664779066,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 1.0904314561361903,
+ 1.0904314561361903,
+ 1.085821664779066,
+ 1.085821664779066,
1.0145245945460468,
1.0145245945460468,
0.9934922693423827,
@@ -1606,50 +1606,50 @@
1.078138055032951,
0.6426753943036221,
0.6426753943036221,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7200699195816633,
0.7200699195816633,
0.755049895453662,
@@ -1662,10 +1662,10 @@
0.6385266008067373,
0.6417090838687141,
0.6417090838687141,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6539603547857009,
0.6539603547857009,
0.6483565406933778,
@@ -1682,30 +1682,30 @@
0.6835863641736272,
0.6922198691857843,
0.6922198691857843,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
29.736571479671202,
29.736571479671202,
28.954414273401518,
28.954414273401518,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
12.009592819963695,
12.009592819963695,
20.87818801631581,
20.87818801631581,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
20.462200798766613,
20.462200798766613,
23.184476175552565,
@@ -1714,22 +1714,22 @@
11.053179545995052,
40.216868497908706,
40.216868497908706,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
47.12362569631633,
47.12362569631633,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
1.271636695208476,
1.271636695208476,
1.077981642815545,
@@ -1802,50 +1802,50 @@
1.6613708772886773,
1.8250934621981263,
1.8250934621981263,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6754564865286883,
0.6754564865286883,
0.6830080259427875,
@@ -1858,10 +1858,10 @@
0.6935655385422379,
0.6392340134452367,
0.6392340134452367,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6822174139883256,
0.6822174139883256,
0.6678244940626191,
@@ -1878,30 +1878,30 @@
0.7375110677091551,
0.6868580384002779,
0.6868580384002779,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
29.736571479671202,
29.736571479671202,
28.954414273401518,
28.954414273401518,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
11.486304075009997,
11.486304075009997,
21.400253425490913,
21.400253425490913,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
20.46202541236162,
20.46202541236162,
28.1268806720096,
@@ -1910,22 +1910,22 @@
11.053179545995052,
40.216868497908706,
40.216868497908706,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
47.12362569631633,
47.12362569631633,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
4.073020328419045,
4.073020328419045,
1.5613878937645274,
@@ -1990,58 +1990,58 @@
1.9632484541651354,
2.1295862313767837,
2.1295862313767837,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
32.071443253865354,
32.071443253865354,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6763005882159183,
0.6763005882159183,
0.7898026179802595,
@@ -2054,10 +2054,10 @@
0.6937591501537277,
0.7556495172304454,
0.7556495172304454,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.648692521126856,
0.648692521126856,
0.681328248605578,
@@ -2074,18 +2074,18 @@
0.6840589712407453,
0.7241738366283028,
0.7241738366283028,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
29.736571479671202,
29.736571479671202,
28.592746909327357,
@@ -2110,38 +2110,38 @@
10.298871329064708,
47.12362569631633,
47.12362569631633,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 4.25838478430837,
- 4.25838478430837,
- 2.2399058404942385,
- 2.2399058404942385,
- 1.6997660820960394,
- 1.6997660820960394,
- 1.4481581186260142,
- 1.4481581186260142,
- 1.6029574676720695,
- 1.6029574676720695,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 4.25838478430837,
+ 4.25838478430837,
+ 2.2399058404942385,
+ 2.2399058404942385,
+ 1.6997660820960394,
+ 1.6997660820960394,
+ 1.4481581186260142,
+ 1.4481581186260142,
+ 1.6029574676720695,
+ 1.6029574676720695,
1.4764963798616977,
1.4764963798616977,
1.0559663423477441,
@@ -2180,64 +2180,64 @@
2.054170888626254,
3.687400861196182,
3.687400861196182,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
32.071443253865354,
32.071443253865354,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7016610254721765,
0.7016610254721765,
0.7150149213822576,
@@ -2250,10 +2250,10 @@
0.7040376672975498,
0.7555713111217425,
0.7555713111217425,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6900798429694239,
0.6900798429694239,
0.7153411650615797,
@@ -2270,18 +2270,18 @@
0.6640386443184142,
0.6994095259037463,
0.6994095259037463,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
27.739809741851474,
27.739809741851474,
38.84926023705824,
@@ -2306,38 +2306,38 @@
10.298871329064708,
47.12362569631633,
47.12362569631633,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
12.78479636097352,
12.78479636097352,
3.6748473139947193,
@@ -2368,72 +2368,72 @@
3.527400649883651,
19.403170249953853,
19.403170249953853,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
32.071443253865354,
32.071443253865354,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.691325710595777,
0.691325710595777,
0.6673680525040038,
@@ -2446,10 +2446,10 @@
0.7359544353459845,
0.6783759523982673,
0.6783759523982673,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6720141694439417,
0.6720141694439417,
0.6500762012735732,
@@ -2466,18 +2466,18 @@
0.6696363417318444,
0.6958262131290076,
0.6958262131290076,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
27.613459752902624,
27.613459752902624,
50.56896491975679,
@@ -2502,42 +2502,42 @@
9.900632466719646,
47.12362569631633,
47.12362569631633,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
12.102842213837954,
12.102842213837954,
1.7662817818874772,
@@ -2564,72 +2564,72 @@
4.423797944365727,
5.186650225483191,
5.186650225483191,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
6.087607566495069,
6.087607566495069,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
32.071443253865354,
32.071443253865354,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6851429341217069,
0.6851429341217069,
0.6554378448138072,
@@ -2642,10 +2642,10 @@
0.7649226520925533,
0.6514028964424405,
0.6514028964424405,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.674137093925438,
0.674137093925438,
0.6775360949372078,
@@ -2662,14 +2662,14 @@
0.6772589719343018,
0.6916349149553257,
0.6916349149553257,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
10.416500681534718,
10.416500681534718,
36.59624148531928,
@@ -2700,40 +2700,40 @@
47.12362569631633,
7.919889561939525,
7.919889561939525,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
3.4987177325168757,
3.4987177325168757,
1.6479893314933964,
@@ -2758,74 +2758,74 @@
1.2275594077849972,
5.494688671136869,
5.494688671136869,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
6.087607566495069,
6.087607566495069,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
32.071443253865354,
32.071443253865354,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7292143545266557,
0.7292143545266557,
0.6891375623444526,
@@ -2838,10 +2838,10 @@
0.7586520575858056,
0.6745911012955143,
0.6745911012955143,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6433718218861504,
0.6433718218861504,
0.6992843212317127,
@@ -2858,14 +2858,14 @@
0.6969783957041531,
0.7316343748400964,
0.7316343748400964,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
10.685891702999333,
10.685891702999333,
36.59624148531928,
@@ -2896,36 +2896,36 @@
8.577289612376159,
7.137119439478731,
7.137119439478731,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
9.916620092213877,
9.916620092213877,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
6.42574718762251,
6.42574718762251,
3.179734301380406,
@@ -2956,72 +2956,72 @@
2.9325974429358705,
23.358836476453074,
23.358836476453074,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
33.60428485689675,
33.60428485689675,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
6.087607566495069,
6.087607566495069,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
32.071443253865354,
32.071443253865354,
15.43404108838102,
15.43404108838102,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7621497992711334,
0.7621497992711334,
0.7179255867240416,
@@ -3034,10 +3034,10 @@
0.767890115166915,
0.7059415772256232,
0.7059415772256232,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.636204010449949,
0.636204010449949,
0.6790766242069662,
@@ -3054,14 +3054,14 @@
0.6941961806191215,
0.649713319935984,
0.649713319935984,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
12.239578698037612,
12.239578698037612,
19.242109356589207,
@@ -3094,20 +3094,20 @@
5.711142083726083,
6.620745038277721,
6.620745038277721,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
13.11318150205903,
13.11318150205903,
6.593562642107537,
@@ -3156,50 +3156,50 @@
33.669584773135576,
33.49419462323778,
33.49419462323778,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
8.171498524051001,
8.171498524051001,
38.45923270405153,
38.45923270405153,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
15.860288098546818,
15.860288098546818,
32.071443253865354,
@@ -3208,16 +3208,16 @@
15.43404108838102,
18.948368959923304,
18.948368959923304,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7029588848691198,
0.7029588848691198,
0.6739359300879681,
@@ -3230,10 +3230,10 @@
0.7166222347991128,
0.7328946603524116,
0.7328946603524116,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6357189827797727,
0.6357189827797727,
0.6683781783326145,
@@ -3250,14 +3250,14 @@
0.6741188063038498,
0.7088372005305378,
0.7088372005305378,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
12.229961156704775,
12.229961156704775,
18.50145319245743,
@@ -3354,42 +3354,42 @@
30.909596326069007,
27.39453570136138,
27.39453570136138,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
5.20877762345397,
5.20877762345397,
6.623242890209321,
6.623242890209321,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
4.480751652255091,
4.480751652255091,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
9.424871565066152,
9.424871565066152,
25.002127199915215,
@@ -3404,16 +3404,16 @@
15.43404108838102,
18.948368959923304,
18.948368959923304,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
15.397359739550415,
15.397359739550415,
15.397359739550415,
15.397359739550415,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6738766357517608,
0.6738766357517608,
0.6770712897564328,
@@ -3426,10 +3426,10 @@
0.7541213461486544,
0.6783959252273055,
0.6783959252273055,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6463107612640417,
0.6463107612640417,
0.666387511428406,
@@ -3446,14 +3446,14 @@
0.6821862064429534,
0.7122229695430697,
0.7122229695430697,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
23.867441447158193,
23.867441447158193,
18.074834812501706,
@@ -3550,38 +3550,38 @@
27.39453570136138,
35.695627926627225,
35.695627926627225,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
59.91215073481093,
59.91215073481093,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
5.20877762345397,
5.20877762345397,
6.623242890209321,
6.623242890209321,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
6.289243511711331,
6.289243511711331,
6.692733355640737,
@@ -3604,12 +3604,12 @@
24.511241873472486,
8.926741719040699,
8.926741719040699,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6638601995739754,
0.6638601995739754,
0.6726811995187293,
@@ -3622,10 +3622,10 @@
0.7778953790434571,
0.6578610482968759,
0.6578610482968759,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6443494918675741,
0.6443494918675741,
1.0633255808672593,
@@ -3642,12 +3642,12 @@
0.6765483137110837,
0.6952242195787759,
0.6952242195787759,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
5.307164528277598,
5.307164528277598,
20.442098770490496,
@@ -3746,34 +3746,34 @@
1.2827860276983667,
35.69119083782619,
35.69119083782619,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
59.91215073481093,
59.91215073481093,
59.91215073481093,
59.91215073481093,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
5.20877762345397,
5.20877762345397,
6.623242890209321,
6.623242890209321,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
0.6666763684683721,
0.6666763684683721,
0.7227419720315307,
@@ -3802,10 +3802,10 @@
6.311529444012602,
1.1100967036072755,
1.1100967036072755,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6891511064191441,
0.6891511064191441,
0.6774362932071071,
@@ -3818,10 +3818,10 @@
0.7280618598760566,
0.7217131216756966,
0.7217131216756966,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.702498199084334,
0.702498199084334,
0.8427326122145906,
@@ -3838,12 +3838,12 @@
0.6723606980277558,
0.6898971539988143,
0.6898971539988143,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
13.651777548017844,
13.651777548017844,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
7.851858361329716,
7.851858361329716,
18.578210646904243,
@@ -3942,26 +3942,26 @@
1.2281109075268166,
28.424399054118275,
28.424399054118275,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
47.648711995883474,
47.648711995883474,
52.974239043858134,
52.974239043858134,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
38.28753003771493,
38.28753003771493,
7.8610140309910435,
7.8610140309910435,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
0.6666763684683721,
0.6666763684683721,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
33.80948695073779,
33.80948695073779,
5.20877762345397,
@@ -4014,10 +4014,10 @@
0.7272484039983822,
0.6604385418842652,
0.6604385418842652,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6681542954021136,
0.6681542954021136,
0.8068853162416049,
@@ -4154,8 +4154,8 @@
0.6666763684683721,
0.6666763684683721,
0.6666763684683721,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
33.80948695073779,
33.80948695073779,
33.80948695073779,
@@ -4210,10 +4210,10 @@
0.743756196858879,
0.6876543925430885,
0.6876543925430885,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7303031233696048,
0.7303031233696048,
0.7414673730661835,
@@ -4348,8 +4348,8 @@
2.796235137205228,
0.6666763684683721,
0.6666763684683721,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
33.80948695073779,
33.80948695073779,
21.166854066104175,
@@ -4406,10 +4406,10 @@
0.7093227899365309,
0.6636280778514962,
0.6636280778514962,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.726225420661078,
0.726225420661078,
0.703051009543059,
@@ -4602,10 +4602,10 @@
0.7129741351601812,
0.6611613086350877,
0.6611613086350877,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6949256881997445,
0.6949256881997445,
0.6979661769302773,
@@ -4798,10 +4798,10 @@
0.6918136717752184,
0.7215496565530365,
0.7215496565530365,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6959255779534731,
0.6959255779534731,
0.6880125303337811,
@@ -4994,10 +4994,10 @@
0.6835688879482187,
0.7268541902852392,
0.7268541902852392,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6848245547438186,
0.6848245547438186,
0.679257503139944,
@@ -5190,10 +5190,10 @@
0.683777479181487,
0.7169371189319192,
0.7169371189319192,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6898697537739775,
0.6898697537739775,
0.688960740392373,
@@ -5386,10 +5386,10 @@
0.6829814371141303,
0.714735239360631,
0.714735239360631,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6944113878520088,
0.6944113878520088,
0.6889494432609483,
@@ -5582,10 +5582,10 @@
0.6810513128479442,
0.7179132285360741,
0.7179132285360741,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7000713755260022,
0.7000713755260022,
0.6947092950801328,
@@ -5778,10 +5778,10 @@
0.6677305593510484,
0.7192147080082807,
0.7192147080082807,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6944829155460022,
0.6944829155460022,
0.6939876518009437,
@@ -5974,10 +5974,10 @@
0.6723199409734995,
0.7051740588547367,
0.7051740588547367,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6991042536949145,
0.6991042536949145,
0.6833483130175272,
@@ -6170,10 +6170,10 @@
0.6985494459532857,
0.684618210453817,
0.684618210453817,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.6994964077100628,
0.6994964077100628,
0.7044508551982791,
@@ -6366,10 +6366,10 @@
0.6881025953097255,
0.7203669529985169,
0.7203669529985169,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7151509862800808,
0.7151509862800808,
0.747833337831589,
@@ -6562,10 +6562,10 @@
0.6867911294229997,
0.7382354572523369,
0.7382354572523369,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7029822905281491,
0.7029822905281491,
0.7433765258618795,
@@ -6758,10 +6758,10 @@
0.705876852776521,
0.7732053842947257,
0.7732053842947257,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7010752598455384,
0.7010752598455384,
0.7448947105291513,
@@ -6954,10 +6954,10 @@
0.7567317324888662,
0.7563844549239631,
0.7563844549239631,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.7127471938902338,
0.7127471938902338,
0.7629452796026733,
@@ -7150,10 +7150,10 @@
0.7424246333129336,
0.8932101927033845,
0.8932101927033845,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.8063032955204114,
0.8063032955204114,
0.7377027444528318,
@@ -7346,10 +7346,10 @@
0.7424246333129336,
0.8932101927033845,
0.8932101927033845,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
+ 152.00613642203447,
0.8063032955204114,
0.8063032955204114,
0.7377027444528318,
@@ -14901,4 +14901,4 @@
0.0,
0.0
]
-}
\ No newline at end of file
+}
diff --git a/cherab/generomak/plasma/data/edge/hydrogen0.json b/cherab/generomak/plasma/data/edge/hydrogen0.json
index 50252db1..b255b8b3 100644
--- a/cherab/generomak/plasma/data/edge/hydrogen0.json
+++ b/cherab/generomak/plasma/data/edge/hydrogen0.json
@@ -36,22 +36,22 @@
1.972944700927401,
2.1469916156572784,
2.1469916156572784,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 1060.8616203299343,
- 1060.8616203299343,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
237.02952717009856,
237.02952717009856,
510.5159897120308,
@@ -94,10 +94,10 @@
3.2178661145048255,
3.0058149630960105,
3.0058149630960105,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.228549122630633,
4.228549122630633,
4.632909532245744,
@@ -114,8 +114,8 @@
3.701953002018378,
3.344396295820652,
3.344396295820652,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
390.9182712497354,
390.9182712497354,
368.29180845487235,
@@ -160,10 +160,10 @@
327.66094502911096,
224.2842595343954,
224.2842595343954,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
2.28095818054478,
2.28095818054478,
2.2121432336404925,
@@ -232,22 +232,22 @@
1.972944700927401,
2.1469916156572784,
2.1469916156572784,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 1060.8616203299343,
- 1060.8616203299343,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
237.02952717009856,
237.02952717009856,
510.5159897120308,
@@ -290,10 +290,10 @@
3.2178661145048255,
3.0058149630960105,
3.0058149630960105,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.228549122630633,
4.228549122630633,
4.632909532245744,
@@ -310,8 +310,8 @@
3.701953002018378,
3.344396295820652,
3.344396295820652,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
390.9182712497354,
390.9182712497354,
368.29180845487235,
@@ -356,10 +356,10 @@
327.66094502911096,
224.2842595343954,
224.2842595343954,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
2.28095818054478,
2.28095818054478,
2.2121432336404925,
@@ -432,14 +432,14 @@
773.3934409631391,
773.3934409631391,
773.3934409631391,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
1060.8616203299343,
1060.8616203299343,
172.10538098510307,
@@ -486,10 +486,10 @@
3.032072679696813,
3.370428818774048,
3.370428818774048,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
5.3896244750752,
5.3896244750752,
4.462110574008034,
@@ -624,14 +624,14 @@
2.147574884680287,
2.194014083967723,
2.194014083967723,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
773.3934409631391,
773.3934409631391,
773.3934409631391,
773.3934409631391,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
298.78233138681514,
298.78233138681514,
59.11285621707551,
@@ -682,10 +682,10 @@
3.1739117848101137,
3.592521996547854,
3.592521996547854,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.050162985962009,
4.050162985962009,
4.408568162903317,
@@ -748,10 +748,10 @@
223.31419795253365,
240.54622431848549,
240.54622431848549,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
2.3245336506386725,
2.3245336506386725,
2.224360425917933,
@@ -820,10 +820,10 @@
2.2302022287512653,
2.315271438417445,
2.315271438417445,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
69.51090013212614,
69.51090013212614,
492.924708325262,
@@ -878,10 +878,10 @@
2.9181949735012807,
3.2768293386558027,
3.2768293386558027,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.324206553120909,
4.324206553120909,
4.620829840413214,
@@ -946,8 +946,8 @@
156.99101750849775,
232.87885497898233,
232.87885497898233,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
2.2079833302574556,
2.2079833302574556,
2.2547071423586873,
@@ -1016,10 +1016,10 @@
2.1893738964614062,
2.04235408915594,
2.04235408915594,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
52.38173633232502,
52.38173633232502,
101.12902445436613,
@@ -1074,10 +1074,10 @@
3.4798216262090365,
3.1222993731414017,
3.1222993731414017,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.816413082204519,
4.816413082204519,
4.044458683573587,
@@ -1142,8 +1142,8 @@
92.01574712267337,
270.2239009185301,
270.2239009185301,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
2.2063231512587396,
2.2063231512587396,
2.1501370865704437,
@@ -1212,8 +1212,8 @@
2.3205649246785858,
2.1310041774083195,
2.1310041774083195,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
100.91711897977912,
100.91711897977912,
44.17568980724506,
@@ -1270,10 +1270,10 @@
2.962358144089624,
2.6885652983502446,
2.6885652983502446,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.510954002590953,
4.510954002590953,
5.1300036622553815,
@@ -1466,10 +1466,10 @@
3.091068609355341,
3.595791860736873,
3.595791860736873,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.758281560358844,
3.758281560358844,
4.7689404762596235,
@@ -1662,10 +1662,10 @@
3.178992185951452,
3.0699698744951243,
3.0699698744951243,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.2251648103863184,
3.2251648103863184,
4.289231195965626,
@@ -1858,10 +1858,10 @@
2.525787178593943,
2.825822761312346,
2.825822761312346,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.9410852499050995,
3.9410852499050995,
3.3806876751642854,
@@ -2054,10 +2054,10 @@
3.019009700524693,
2.3753950839355458,
2.3753950839355458,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.197689853464683,
4.197689853464683,
3.755099077296867,
@@ -2250,10 +2250,10 @@
2.877357840683626,
3.041679111143497,
3.041679111143497,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.5308683699103307,
3.5308683699103307,
3.276232088652468,
@@ -2446,10 +2446,10 @@
2.7262409819915026,
4.0978295780089375,
4.0978295780089375,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.0636950981772966,
3.0636950981772966,
3.487733612772186,
@@ -2642,10 +2642,10 @@
2.8434261886757737,
2.888884534812159,
2.888884534812159,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
2.965325731994167,
2.965325731994167,
3.2970243030020376,
@@ -2838,10 +2838,10 @@
2.6858381957903403,
2.9947567566386066,
2.9947567566386066,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
2.707415654396568,
2.707415654396568,
3.4228154272283566,
@@ -3034,10 +3034,10 @@
3.1050752422844288,
2.5827768999906664,
2.5827768999906664,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.3679896994428393,
3.3679896994428393,
3.7827563898925267,
@@ -3230,10 +3230,10 @@
3.2214229008659983,
3.112208101269813,
3.112208101269813,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.079169463159205,
4.079169463159205,
4.373918362861358,
@@ -3426,10 +3426,10 @@
3.182294755648022,
3.540194869675025,
3.540194869675025,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.426191958807458,
3.426191958807458,
3.890835422082432,
@@ -3622,10 +3622,10 @@
2.9324045178903795,
3.031484542296727,
3.031484542296727,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.048504929076378,
4.048504929076378,
4.101542214851699,
@@ -3818,10 +3818,10 @@
3.1031142849634143,
3.186577866420189,
3.186577866420189,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
5.138463029164361,
5.138463029164361,
4.226479438221542,
@@ -4014,10 +4014,10 @@
2.9823071305632336,
3.301914899852422,
3.301914899852422,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.230204495667361,
4.230204495667361,
3.7793528325791326,
@@ -4210,10 +4210,10 @@
2.7946538508812133,
3.6766072947235355,
3.6766072947235355,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.347594361434184,
4.347594361434184,
3.2985799991388465,
@@ -4406,10 +4406,10 @@
2.9905828098601517,
3.2936387212347777,
3.2936387212347777,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.6020830522235667,
3.6020830522235667,
3.408852235202427,
@@ -4602,10 +4602,10 @@
2.990016392911645,
2.251912069764962,
2.251912069764962,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.33474979388571,
3.33474979388571,
3.552615972053928,
@@ -4798,10 +4798,10 @@
3.1068532609744706,
2.035272972280783,
2.035272972280783,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.346502929963464,
3.346502929963464,
3.4188598084373263,
@@ -4994,10 +4994,10 @@
3.050768558393544,
2.5736518761388956,
2.5736518761388956,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.719975297055793,
3.719975297055793,
3.6058544216667188,
@@ -5190,10 +5190,10 @@
2.9544671289969644,
2.6266115175413303,
2.6266115175413303,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.621674275397029,
3.621674275397029,
3.7044403682147324,
@@ -5386,10 +5386,10 @@
2.7672878919291497,
2.397112914080858,
2.397112914080858,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.811473760389393,
3.811473760389393,
3.8450036464581223,
@@ -5582,10 +5582,10 @@
2.630605459198078,
2.492375257046721,
2.492375257046721,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.876404241706099,
3.876404241706099,
3.662145218877284,
@@ -5778,10 +5778,10 @@
2.8051830270294658,
2.551368128365802,
2.551368128365802,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.877623582918886,
3.877623582918886,
4.0914143677369355,
@@ -5974,10 +5974,10 @@
2.6751353808596363,
2.908345372861055,
2.908345372861055,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.916432724608066,
3.916432724608066,
4.1287282310971465,
@@ -6170,10 +6170,10 @@
2.6903946222448782,
2.7719752652440692,
2.7719752652440692,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
3.539496944130319,
3.539496944130319,
4.011383928346568,
@@ -6366,10 +6366,10 @@
2.4393379088563094,
2.553484436847679,
2.553484436847679,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.608095663939136,
4.608095663939136,
4.553307572453338,
@@ -6562,10 +6562,10 @@
2.4487560963893076,
2.596682670133111,
2.596682670133111,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.667622184284084,
4.667622184284084,
4.634387022273851,
@@ -6758,10 +6758,10 @@
2.540889570856143,
3.099676149689748,
3.099676149689748,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.975413715838775,
4.975413715838775,
4.372279592238767,
@@ -6954,10 +6954,10 @@
2.8814299260339857,
2.778316014312814,
2.778316014312814,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
4.494170272614275,
4.494170272614275,
4.624706129623908,
@@ -7150,10 +7150,10 @@
3.1383402387080377,
3.087223090784384,
3.087223090784384,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
5.0891368198545335,
5.0891368198545335,
4.804279214073222,
@@ -7346,10 +7346,10 @@
3.1383402387080377,
3.087223090784384,
3.087223090784384,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
- 6241509074460.763,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
+ 1060.8616203299343,
5.0891368198545335,
5.0891368198545335,
4.804279214073222,
@@ -14901,4 +14901,4 @@
0.0,
0.0
]
-}
\ No newline at end of file
+}
diff --git a/cherab/generomak/plasma/plasma.py b/cherab/generomak/plasma/plasma.py
index 53e5142a..45c5ed3e 100644
--- a/cherab/generomak/plasma/plasma.py
+++ b/cherab/generomak/plasma/plasma.py
@@ -1,7 +1,7 @@
-# Copyright 2016-2021 Euratom
-# Copyright 2016-2021 United Kingdom Atomic Energy Authority
-# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
#
# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
# European Commission - subsequent versions of the EUPL (the "Licence");
@@ -24,22 +24,28 @@
from raysect.core import Vector3D, translate
from raysect.core.math.function.float.function2d.interpolate import Discrete2DMesh
+from raysect.core.math.function.float import Arg1D, Exp1D, Constant1D, Interpolator1DArray, Blend2D
+from raysect.core.math.function.vector3d import Constant2D as ConstantVector2D, Blend2D as BlendVector2D
from raysect.primitive import Cylinder, Subtract
from cherab.core import AtomicData, Plasma, Maxwellian, Species
from cherab.core.atomic.elements import hydrogen, carbon, lookup_isotope, lookup_element
from cherab.core.utility import RecursiveDict
from cherab.core.math.mappers import AxisymmetricMapper, VectorAxisymmetricMapper
+from cherab.core.math.clamp import ClampInput1D
+
+from cherab.tools.plasmas.ionisation_balance import interpolators1d_from_elementdensity, interpolators1d_match_plasma_neutrality
from cherab.openadas import OpenADAS
from cherab.generomak.equilibrium import load_equilibrium
+
def load_edge_profiles():
"""
Loads Generomak edge plasma profiles
- Return a single dictionary with available edge and plasma species temperature and
+ Return a single dictionary with available edge and plasma species temperature and
density profiles. The profiles are saved on a 2D triangular mesh.
:return: dictionary with mesh, electron and plasma composition profiles
@@ -51,7 +57,7 @@ def load_edge_profiles():
>>>
>>>
>>> data = load_edge_profiles()
- >>>
+ >>>
>>> # create electron temperature 2D mesh interpolator
>>> te = Discrete2DMesh(data["mesh"]["vertex_coords"],
data["mesh"]["triangles"],
@@ -60,7 +66,7 @@ def load_edge_profiles():
>>> # create hydrogen 0+ density 2D mesh interpolator
>>> n_h0 = Discrete2DMesh.instance(te, data["composition"]["hydrogen"][0]["temperature"])
"""
- profiles_dir = os.path.join(os.path.dirname(__file__), "/data/plasma/edge")
+ profiles_dir = os.path.join(os.path.dirname(__file__), "data/edge")
edge_data = RecursiveDict()
path = os.path.join(profiles_dir, "mesh.json")
@@ -86,6 +92,7 @@ def load_edge_profiles():
return edge_data.freeze()
+
def get_edge_interpolators():
"""
Provides Generomak edge profiles 2d interpolator
@@ -101,81 +108,79 @@ def get_edge_interpolators():
te = Discrete2DMesh(profiles["mesh"]["vertex_coords"],
profiles["mesh"]["triangles"],
profiles["electron"]["temperature"], limit=False)
- ne = Discrete2DMesh.instance(te, profiles["electron"]["temperature"], limit=False)
+ ne = Discrete2DMesh.instance(te, profiles["electron"]["density"], limit=False)
+ ve = ConstantVector2D(Vector3D(0, 1.e-10, 0)) # avoid zero-length vectors for blending
mesh_interp["electron"]["temperature"] = te
mesh_interp["electron"]["density"] = ne
+ mesh_interp["electron"]["velocity"] = ve
for elem_name, elem_data in profiles["composition"].items():
for stage, stage_data in elem_data.items():
t = Discrete2DMesh.instance(te, stage_data["temperature"], limit=False)
n = Discrete2DMesh.instance(te, stage_data["density"], limit=False)
+ v = ConstantVector2D(Vector3D(0, 1.e-10, 0)) # avoid zero-length vectors for blending
mesh_interp["composition"][elem_name][stage]["temperature"] = t
mesh_interp["composition"][elem_name][stage]["density"] = n
- mesh_interp["composition"][elem_name][stage]["element"] = stage_data["element"]
+ mesh_interp["composition"][elem_name][stage]["velocity"] = v
-
return mesh_interp.freeze()
-
-def get_edge_distributions():
+
+
+def get_2d_distributions(profiles_2d=None):
"""
- Provides Generomak edge Maxwellian distribution of plasma species
+ Provides Generomak Maxwellian distribution of plasma species for 2d profiles
+ :param profiles_2d: Dictionary with 2D profile interpolators in the shape
+ returned by the get_edge_interpolators() or get_full_profiles() functions.
+ If not specified, will use the value returned by get_edge_interpolators().
:return: Dictionary holding instances of Maxwellian distributions for plasma species.
"""
- mesh_interp = get_edge_interpolators()
-
- zero_vector = Vector3D(0, 0, 0)
+ profiles_2d = profiles_2d or get_edge_interpolators()
dists = RecursiveDict()
- n3d = AxisymmetricMapper(mesh_interp["electron"]["density"])
- t3d = AxisymmetricMapper(mesh_interp["electron"]["temperature"])
+ n3d = AxisymmetricMapper(profiles_2d["electron"]["density"])
+ t3d = AxisymmetricMapper(profiles_2d["electron"]["temperature"])
+ v3d = VectorAxisymmetricMapper(profiles_2d["electron"]["velocity"])
- dists["electron"] = Maxwellian(n3d, t3d, zero_vector, electron_mass)
+ dists["electron"] = Maxwellian(n3d, t3d, v3d, electron_mass)
- for elem_name, elem_data in mesh_interp["composition"].items():
+ for elem_name, elem_data in profiles_2d["composition"].items():
for stage, stage_data in elem_data.items():
- # get element or isotope
- try:
- element = lookup_isotope(elem_name)
- except ValueError:
- element = lookup_element(elem_name)
-
+ spec_cherab = _get_cherab_element(elem_name)
+
n3d = AxisymmetricMapper(stage_data["density"])
t3d = AxisymmetricMapper(stage_data["temperature"])
- mass = element.atomic_weight * atomic_mass
- dists["composition"][elem_name][stage]["distribution"] = Maxwellian(n3d, t3d, zero_vector, mass)
- dists["composition"][elem_name][stage]["element"] = element
+ v3d = VectorAxisymmetricMapper(stage_data["velocity"])
+ mass = spec_cherab.atomic_weight * atomic_mass
+ dists["composition"][elem_name][stage] = Maxwellian(n3d, t3d, v3d, mass)
return dists.freeze()
+
def get_edge_plasma(atomic_data=None, parent=None, name="Generomak edge plasma"):
"""
- Provides Generomak Edge plasma.
+ Provides Generomak default edge plasma.
- :param atomic_data: Instance of AtomicData, default isOpenADAS()
+ :param atomic_data: Instance of AtomicData, default is OpenADAS()
:param parent: parent of the plasma node, defaults None
:param name: name of the plasma node, defaults "Generomak edge plasma"
:return: populated Plasma object
"""
-
+
# load Generomak equilibrium
equilibrium = load_equilibrium()
- # create or check atomic_data
- if atomic_data is not None:
- if not isinstance(atomic_data, AtomicData):
- raise ValueError("atomic_data has to be of type AtomicData")
- else:
- atomic_data = OpenADAS()
+ # get edge distributions
+ distributions = get_2d_distributions()
# base plasma geometry on mesh vertices
- profiles_dir = os.path.join(os.path.dirname(__file__), "data/plasma/edge")
+ profiles_dir = os.path.join(os.path.dirname(__file__), "data/edge")
path = os.path.join(profiles_dir, "mesh.json")
with open(path, "r") as fhl:
mesh = json.load(fhl)
@@ -183,25 +188,504 @@ def get_edge_plasma(atomic_data=None, parent=None, name="Generomak edge plasma")
vertex_coords = np.asarray(mesh["vertex_coords"])
r_range = (vertex_coords[:, 0].min(), vertex_coords[:, 0].max())
z_range = (vertex_coords[:, 1].min(), vertex_coords[:, 1].max())
- plasma_height = z_range[1] - z_range[0]
- padding = 1e-3 #enlarge for safety
+ return get_plasma(equilibrium=equilibrium, distributions=distributions,
+ r_range=r_range, z_range=z_range, atomic_data=atomic_data,
+ parent=parent, name=name)
+
+
+def load_core_profiles():
+ """
+ Loads Generomak default core plasma profiles.
+
+ Return a single dictionary with available core plasma species temperature and
+ density profiles on a magnetic surface coordinate grid.
+
+ :return: dictionary with electron and plasma composition profiles
+ """
+ profiles_dir = os.path.join(os.path.dirname(__file__), "data/core")
+
+ core_data = RecursiveDict()
+ path = os.path.join(profiles_dir, "psi_norm.json")
+ with open(path, "r") as fhl:
+ core_data["psi_norm"] = json.load(fhl)["psi_norm"]
+
+ path = os.path.join(profiles_dir, "electrons.json")
+ with open(path, "r") as fhl:
+ core_data["electron"] = json.load(fhl)
+
+ saved_elements = (hydrogen, carbon)
+
+ for element in saved_elements:
+ for chrg in range(element.atomic_number + 1):
+ path = os.path.join(profiles_dir, "{}{:d}.json".format(element.name, chrg))
+
+ with open(path, "r") as fhl:
+ file_data = json.load(fhl)
+ element_name = file_data["element"]
+ charge = file_data["charge"]
+
+ core_data["composition"][element_name][charge] = file_data
+
+ return core_data.freeze()
+
+
+def get_core_interpolators():
+ """
+ Provides 1d interpolators for Generomak default core profiles.
+
+ :return: dictionary holding 1D interpolators of density,
+ temperature and velocity for plasma species
+ """
+
+ profiles = load_core_profiles()
+
+ core_interp = RecursiveDict()
+
+ te = Interpolator1DArray(profiles["psi_norm"], profiles["electron"]["temperature"], 'cubic', 'nearest', 1.e-5)
+ ne = Interpolator1DArray(profiles["psi_norm"], profiles["electron"]["density"], 'cubic', 'nearest', 1.e-5)
+ ve_tor = Interpolator1DArray(profiles["psi_norm"], profiles["electron"]["vtor"], 'cubic', 'nearest', 1.e-5)
+ ve_pol = Interpolator1DArray(profiles["psi_norm"], profiles["electron"]["vpol"], 'cubic', 'nearest', 1.e-5)
+ ve_norm = Interpolator1DArray(profiles["psi_norm"], profiles["electron"]["vnorm"], 'cubic', 'nearest', 1.e-5)
+
+ core_interp["electron"]["f1d_temperature"] = te
+ core_interp["electron"]["f1d_density"] = ne
+ core_interp["electron"]["f1d_vtor"] = ve_tor
+ core_interp["electron"]["f1d_vpol"] = ve_pol
+ core_interp["electron"]["f1d_vnorm"] = ve_norm
+
+ for elem_name, elem_data in profiles["composition"].items():
+ for stage, stage_data in elem_data.items():
+
+ t = Interpolator1DArray(profiles["psi_norm"], stage_data["temperature"], 'cubic', 'nearest', 1.e-5)
+ n = Interpolator1DArray(profiles["psi_norm"], stage_data["density"], 'cubic', 'nearest', 1.e-5)
+ vtor = Interpolator1DArray(profiles["psi_norm"], stage_data["vtor"], 'cubic', 'nearest', 1.e-5)
+ vpol = Interpolator1DArray(profiles["psi_norm"], stage_data["vpol"], 'cubic', 'nearest', 1.e-5)
+ vnorm = Interpolator1DArray(profiles["psi_norm"], stage_data["vnorm"], 'cubic', 'nearest', 1.e-5)
+
+ core_interp["composition"][elem_name][stage]["f1d_temperature"] = t
+ core_interp["composition"][elem_name][stage]["f1d_density"] = n
+ core_interp["composition"][elem_name][stage]["f1d_vtor"] = vtor
+ core_interp["composition"][elem_name][stage]["f1d_vpol"] = vpol
+ core_interp["composition"][elem_name][stage]["f1d_vnorm"] = vnorm
+
+ return core_interp.freeze()
+
+
+def get_double_parabola(v_min, v_max, convexity, concavity, xmin=0, xmax=1):
+ """
+ Returns a 1d double-quadratic Function1D
+
+ The retuned Function1D is of the form
+
+ .. math:: f(x) = ((v_{max} - v_{min}) * ((1 - ((1 - x_{norm}) ** convexity)) ** concavity) + v_min)
+
+ where the :math: `x_norm` is calculated as
+
+ .. math:: x_{norm} = (x - xmin) / (xmax - xmin).
+
+ The returned function is decreasing and monotonous and its domain is [xmin, xmax].
+
+ :param v_min: The minimum value of the profile at xmax.
+ :param v_max: The maximum value of the profile at xmin.
+ :param convexity: Controls the convexity of the profile in the lower values part of the profile.
+ :param concavity: Controls the concavity of the profile in the higher values part of the profile.
+ :param xmin: The lower edge of the function domain. Defaults to 0.
+ :param xmax: The upper edge of the function domain Defaults to 1.
+ :return: Function1D
+ """
+
+ x = Arg1D() # the free parameter
+
+ # funciton for the normalised free variable
+ x_norm = ClampInput1D((x - xmin) / (xmax - xmin), 0, 1)
+
+ # profile function
+ return (v_max - v_min) * ((1 - ((1 - x_norm) ** convexity)) ** concavity) + v_min
+
+
+def get_exponential_growth(initial_value, growth_rate, initial_position=1):
+ """
+ returns exponentially growing Function1D
+
+ The returned Function1D is of the form:
+
+ ::math::
+ v_0 \exp((x - x_0) * \lambda)
+
+ where v_0 is the initial_value, x_0 is the initial_position and lambda is the growth_rate.
+
+ :param initial_value: The value of the function at the initial position.
+ :param growth_rate: Growth constant of the profile.
+ :param initial_position: The initial position of the profile. Defaults to 1.
+ :return: Function1D
+ """
+
+ x = Arg1D() # the free parameter
+ return initial_value * Exp1D((x - initial_position) * growth_rate)
+
+
+def get_maxwellian_distribution(equilibrium, f1d_density, f1d_temperature, f1d_vtor, f1d_vpol, f1d_vnorm, rest_mass):
+ """ Returns Maxwellian distribution for equilibrium mapped 1d profiles
+
+ :param equilibrium: Instance of EFITEquilibrium
+ :param f1d_density: Function1D describing density profile.
+ :param f1d_temperature: Function1D describing temperature profile.
+ :param f1d_vtor: Function1D describing bulk toroidal rotation velocity profile.
+ :param f1d_vpol: Function1D describing bulk poloidal rotation velocity profile.
+ :param f1d_vnorm: Function1D describing bulk velocity normal to magnetic surfaces.
+ :rest_mass: Rest mass of the distribution species.
+ :return: Maxwellian distribution
+ """
+
+ # map profiles to 3D
+ f3d_te = equilibrium.map3d(f1d_temperature)
+ f3d_ne = equilibrium.map3d(f1d_density)
+ f3d_v = equilibrium.map_vector3d(f1d_vtor, f1d_vpol, f1d_vnorm)
+
+ # return Maxwellian distribution
+ return Maxwellian(f3d_ne, f3d_te, f3d_v, rest_mass)
+
+def get_edge_profile_values(r, z, edge_interpolators=None):
+ """
+ Evalueate edge plasma profiles at the position [r, z]
+
+ :param r: Radial distance in cylindrical cordinates in m.
+ :param z: Elevation in cylindrical coordinates in m.
+ :param edge_interpolators: Dictionary with edge interpolators in the shape
+ returned by the get_edge_interpolators function.
+ :return: Dictionary of edge values at [R, Z]
+ """
+
+ # load edge interpolators if not passed as argument
+ if edge_interpolators is None:
+ edge_interp = get_edge_interpolators()
+ else:
+ edge_interp = edge_interpolators
+ # create recursive dictionary to store profile values
+ values = RecursiveDict()
+
+ # add electron values
+ values["electron"]["temperature"] = edge_interp["electron"]["temperature"](r, z)
+ values["electron"]["density"] = edge_interp["electron"]["density"](r, z)
+
+ # add species values
+ for spec, desc in edge_interp['composition'].items():
+ for chrg, chrg_desc in desc.items():
+ for prop, val in chrg_desc.items():
+ if prop in ["temperature", "density"]:
+ values["composition"][spec][chrg][prop] = val(r, z)
+ else:
+ values["composition"][spec][chrg][prop] = val
+
+ return values.freeze()
+
+
+def get_core_profiles_arguments(**kwargs):
+ """
+ Returns dictionary with core profile arguments
+
+ The function compares the passed keyword arguments with the list of core profile arguments (listed below).
+ If there is a match, the default value is overwritten by th passed value, the default value is kept
+ otherwise.
+
+ List of core parameters, their meaning and default values
+ ne_core: (default 5e19) core electron density
+ ne_convexity: (default 1.09) (default ) convexity of the electron density profile
+ ne_concavity: (default 0.24) concavity of the electron density profile
+ te_core core: (default 3e3) electron temperature
+ te_convexity: (default 2.35) convexity of the electron temperature profile
+ te_concavity: (default 1.26) concavity of the electron temperature profile
+ th_core: (default 2.8e3) H1+ temperature
+ th_convexity: (default 2) convexity of H1+ temperature profile
+ th_concavity: (default 1.26) concavity of H1+ temperature profile
+ th0_fraction: (default 0.8) H0 temperature factor
+ timp_core: (default 2.8e3) core impurity temperature
+ timp_convexity: (default 2) convexity of impurity temperature profile
+ timp_concavity: (default 1.26) concavity of impurity temperature profile
+ nimp_core: (default 5e17) impurity density
+ nimp_convexity: (default 1.09) convexity of impurity density profile
+ nimp_concavity: (default 0.24) concavity of impurity density profile
+ vtor_core: (default 1e5) toroidal rotation velocity m/s
+ vtor_edge: (default 1e4) toroidal rotation velocity at the edge m/s
+ vtor_convexity: (default 2) convexity of the toroidal rotation profile
+ vtor_concavity: (default 4) concavity of the toroidal rotation profile
+ vpol_lcfs: (default 2e4) Bulk poloidal rotation velocity in m/s
+ vpol_decay: (default 0.08) Decay rate of poloidal rotation velocity
+
+ :return: dictionary of profile arguments
+ """
+
+ core_args = {"ne_core": 5e19, "ne_convexity": 1.09, "ne_concavity": 0.24,
+ "te_core": 3e3, "te_convexity": 2.35, "te_concavity": 1.26,
+ "th_core": 2.8e3, "th_convexity": 2, "th_concavity": 1.26,
+ "th0_fraction": 0.8,
+ "timp_core": 2.8e3, "timp_convexity": 2, "timp_concavity": 1.26,
+ "nimp_core": 5e17, "nimp_convexity": 1.09, "nimp_concavity": 0.24,
+ "vtor_core": 1e5, "vtor_edge": 1e4, "vtor_convexity": 2, "vtor_concavity": 4,
+ "vpol_lcfs": 2e4, "vpol_decay": 0.08}
+
+ if not kwargs:
+ return core_args
+
+ # change passed values of core args
+ for key, item in kwargs.items():
+ core_args[key] = item
+
+ return core_args
+
+
+def get_core_profiles_description(lcfs_values=None, core_args=None):
+ """
+ Returns dictionary of core profile functions and species descriptions
+
+ :param lcfs_values: Dictionary of profile values at the separatrix on outer midplane.
+ The dictionary has to have the same format as the one returned by
+ the function get_edge_profile_values. The default value is the
+ dictionary returned by the call get_edge_profile_values for r, z
+ on last closed flux surface on outer midplane.
+ :param core_args: Dictionary with arguments describing the core profiles. The dictionary
+ has to have the same shape as the one returned by the funciton
+ get_core_profiles_description. The default value is the dictionary
+ returned by the get_core_profiles() call.
+ :return: dictionary of Function1D profiles
+ """
+ if lcfs_values is None:
+ # get edge profiles and calculate profile values at midplane outer lcfs
+ equilibrium = load_equilibrium()
+ r = equilibrium.psin_to_r(1)
+ z = 0
+ lcfs_values = get_edge_profile_values(r, z)
+
+ # total carbon impurity density at lcfs
+ nimp_lcfs = sum([value["density"] for _, value in lcfs_values["composition"]["carbon"].items()])
+
+ if core_args is None:
+ core_args = get_core_profiles_arguments()
+
+ # toroidal rotation profile
+ f1d_vtor = get_double_parabola(core_args["vtor_edge"], core_args["vtor_core"],
+ core_args["vtor_convexity"], core_args["vtor_concavity"], xmin=1, xmax=0)
+
+ # poloidal rotation profile
+ f1d_vpol = get_exponential_growth(core_args["vpol_lcfs"], core_args["vpol_decay"])
+
+ # velocity normal to magnetic surfaces
+ f1d_vnorm = Constant1D(0)
+
+ # construct dictionary with 1D profile functions
+ profiles = RecursiveDict()
+
+ # Setup electron profiles with double parabola shapes
+ profiles["electron"]["f1d_temperature"] = get_double_parabola(lcfs_values["electron"]["temperature"],
+ core_args["te_core"], core_args["te_convexity"],
+ core_args["te_concavity"], xmin=1, xmax=0)
+ profiles["electron"]["f1d_density"] = get_double_parabola(lcfs_values["electron"]["density"],
+ core_args["ne_core"], core_args["ne_convexity"],
+ core_args["ne_concavity"], xmin=1, xmax=0)
+ profiles["electron"]["f1d_vtor"] = Constant1D(1.e-10) # avoid zero-length vectors for blending
+ profiles["electron"]["f1d_vpol"] = Constant1D(0)
+ profiles["electron"]["f1d_vnorm"] = Constant1D(0)
+
+ # total carbon density
+ carbon_total_density = get_double_parabola(nimp_lcfs, core_args["nimp_core"],
+ core_args["nimp_convexity"], core_args["nimp_concavity"], xmin=1, xmax=0)
+
+ # solve ionisation balance
+ openadas = OpenADAS(permit_extrapolation=True)
+ psin_1d = np.append(1. - np.geomspace(1.e-4, 1, 1023)[::-1], [1.]) # density profiles are sharp near psin=1
+ density_profiles = {}
+ density_profiles["carbon"] = interpolators1d_from_elementdensity(openadas, carbon, psin_1d, carbon_total_density,
+ profiles["electron"]["f1d_density"],
+ profiles["electron"]["f1d_temperature"])
+
+ density_profiles["hydrogen"] = interpolators1d_match_plasma_neutrality(openadas, hydrogen, psin_1d, [density_profiles["carbon"]],
+ profiles["electron"]["f1d_density"],
+ profiles["electron"]["f1d_temperature"])
+
+ # Setup ion profiles
+ for element, prefix in ((hydrogen, "h"), (carbon, "imp")):
+ name = element.name
+ for chrg in range(element.atomic_number + 1):
+ profiles["composition"][name][chrg]["f1d_temperature"] = get_double_parabola(lcfs_values["composition"][name][chrg]["temperature"],
+ core_args["t{}_core".format(prefix)],
+ core_args["t{}_convexity".format(prefix)],
+ core_args["t{}_concavity".format(prefix)],
+ xmin=1, xmax=0)
+ profiles["composition"][name][chrg]["f1d_density"] = density_profiles[name][chrg]
+ profiles["composition"][name][chrg]["f1d_vtor"] = f1d_vtor
+ profiles["composition"][name][chrg]["f1d_vpol"] = f1d_vpol
+ profiles["composition"][name][chrg]["f1d_vnorm"] = f1d_vnorm
+
+ # multiply H0 temperature by th0_fraction
+ profiles["composition"]["hydrogen"][0]["f1d_temperature"] *= core_args["th0_fraction"]
+
+ return profiles.freeze()
+
+
+def get_core_distributions(profiles=None, equilibrium=None):
+ """
+ Returns a dictionary of core plasma species Maxwellian distributions.
+
+ :param profiles: Dictionary with core interpolators. The dictionary has to have
+ the same form as the one returned by the function
+ get_core_profiles_description or get_core_interpolators.
+ The default value is the value returned by the call
+ get_core_interpolators().
+ :param equilibrium: an instance of EFITEquilibrium.
+ :return: dictionary of core plasma species with Maxwellian distribution
+ """
+ # get core profile data if not passed sa argument
+ if profiles is None:
+ profiles = get_core_interpolators()
+
+ # load plasma equilibrium if not passed as argument
+ if equilibrium is None:
+ equilibrium = load_equilibrium()
+
+ # build a dictionary with Maxwellian distributions
+ species = RecursiveDict()
+ species["electron"] = get_maxwellian_distribution(equilibrium, rest_mass=electron_mass,
+ **profiles["electron"])
+ for name, spec in profiles["composition"].items():
+ spec_cherab = _get_cherab_element(name)
+ for chrg, desc in spec.items():
+ rest_mass = atomic_mass * spec_cherab.atomic_weight
+ species["composition"][name][chrg] = get_maxwellian_distribution(equilibrium, rest_mass=rest_mass, **desc)
+
+ return species.freeze()
+
+
+def get_core_plasma(atomic_data=None, parent=None, name="Generomak core plasma"):
+ """
+ Provides Generomak default core plasma.
+
+ :param atomic_data: Instance of AtomicData, default is OpenADAS()
+ :param parent: parent of the plasma node, defaults None
+ :param name: name of the plasma node, defaults "Generomak edge plasma"
+ :return: populated Plasma object
+ """
+
+ # load Generomak equilibrium
+ equilibrium = load_equilibrium()
+
+ # load core distributions
+ distributions = get_core_distributions(equilibrium=equilibrium)
+
+ return get_plasma(equilibrium=equilibrium, distributions=distributions,
+ atomic_data=atomic_data, parent=parent, name=name)
+
+
+def get_full_profiles(equilibrium=None, core_profiles=None, edge_profiles=None, mask=None):
+ """
+ Blends core and edge profiles using the mask function as a modulator.
+
+ :param equilibrium: an instance of EFITEquilibrium. The default value is the value returned by
+ load_equilibrium().
+ :param core_profiles: Dictionary with core interpolators. The dictionary has to have
+ the same form as the one returned by the function
+ get_core_profiles_description or get_core_interpolators.
+ The default value is the value returned by the call
+ get_core_interpolators().
+ :param edge_profiles: Dictionary with edge interpolators in the shape
+ returned by the get_edge_interpolators function.
+ If not specified, will use the value returned by
+ get_edge_interpolators().
+ :param Function2D mask: Scalar 2D function returning a value in the range [0, 1].
+ If not specified, will use core profiles for psi_normal < 0.94,
+ the edge profiles for psi_normal > 1 and a weighted sum of core and
+ edge profiles for 0.94 < psi_normal < 1, with the edge profile weight
+ increasing from 0 to 1 linearly.
+
+ :return: dictionary of blended plasma profiles with the sturcture identical to edge_profiles.
+ """
+
+ equilibrium = equilibrium or load_equilibrium()
+
+ core_profiles = core_profiles or get_core_interpolators()
+
+ edge_profiles = edge_profiles or get_edge_interpolators()
+
+ mask = mask or equilibrium.map2d(Interpolator1DArray([0, 0.94, 1.0, 1.1], [1, 1, 0, 0], 'linear', 'none', 0))
+
+ # blended core and edge profiles
+ blended_profiles = RecursiveDict()
+
+ # map core profiles to 2D using the equilibrium
+ te_core = equilibrium.map2d(core_profiles["electron"]["f1d_temperature"])
+ ne_core = equilibrium.map2d(core_profiles["electron"]["f1d_density"])
+ ve_core = equilibrium.map_vector2d(core_profiles["electron"]["f1d_vtor"],
+ core_profiles["electron"]["f1d_vpol"],
+ core_profiles["electron"]["f1d_vnorm"])
+
+ blended_profiles["electron"]["temperature"] = Blend2D(edge_profiles["electron"]["temperature"], te_core, mask)
+ blended_profiles["electron"]["density"] = Blend2D(edge_profiles["electron"]["density"], ne_core, mask)
+ blended_profiles["electron"]["velocity"] = BlendVector2D(edge_profiles["electron"]["velocity"], ve_core, mask)
+
+ for element, states in core_profiles["composition"].items():
+ for charge, state in states.items():
+ t_core = equilibrium.map2d(state["f1d_temperature"])
+ n_core = equilibrium.map2d(state["f1d_density"])
+ v_core = equilibrium.map_vector2d(state["f1d_vtor"], state["f1d_vpol"], state["f1d_vnorm"])
+
+ edge_state = edge_profiles["composition"][element][charge]
+
+ blended_profiles["composition"][element][charge]["temperature"] = Blend2D(edge_state["temperature"], t_core, mask)
+ blended_profiles["composition"][element][charge]["density"] = Blend2D(edge_state["density"], n_core, mask)
+ blended_profiles["composition"][element][charge]["velocity"] = BlendVector2D(edge_state["velocity"], v_core, mask)
+
+ return blended_profiles.freeze()
+
+
+def get_plasma(equilibrium=None, distributions=None, r_range=None, z_range=None, atomic_data=None, parent=None, name="Generomak plasma"):
+ """
+ Provides Generomak plasma. The full (core + edge) plasma is returned by default.
+
+ :param equilibrium: an instance of EFITEquilibrium. The default value is the value returned by load_equilibrium().
+ :param distributions: A dictionary of plasma distributions. Has to have the same format as the
+ dictionary returned by get_core_distributions or get_2d_distributions.
+ The default value is the value returned by the call:
+ get_2d_distributions(get_full_profiles(equilibrium)).
+ :param r_range: Plasma domain range (min, max) in R direction in meters.
+ :param z_range: Plasma domain range (min, max) in Z direction in meters.
+ :param atomic_data: Instance of AtomicData, default is OpenADAS()
+ :param parent: parent of the plasma node, defaults None
+ :param name: name of the plasma node, defaults "Generomak plasma"
+ :return: populated Plasma object
+ """
+
+ equilibrium = equilibrium or load_equilibrium()
+
+ distributions = distributions or get_2d_distributions(get_full_profiles(equilibrium=equilibrium))
+
+ r_range = r_range or equilibrium.r_range
+ z_range = z_range or equilibrium.z_range
+
+ # create or check atomic_data
+ if atomic_data is not None:
+ if not isinstance(atomic_data, AtomicData):
+ raise ValueError("atomic_data has to be of type AtomicData")
+ else:
+ atomic_data = OpenADAS()
+
+ # construct plasma primitive shape
+ padding = 1e-3 # enlarge for safety
+ plasma_height = z_range[1] - z_range[0]
outer_column = Cylinder(radius=r_range[1], height=plasma_height)
inner_column = Cylinder(radius=r_range[0], height=plasma_height + 2 * padding)
inner_column.transform = translate(0, 0, -padding)
-
plasma_geometry = Subtract(outer_column, inner_column)
- geometry_transform = translate(0, 0, -outer_column.height / 2)
-
- # get distributions
- dists = get_edge_distributions()
+
+ # coordinate transform of the plasma frame
+ geometry_transform = translate(0, 0, z_range[0])
# create plasma composition list
plasma_composition = []
- for elem_name, elem_data in dists["composition"].items():
+ for elem_name, elem_data in distributions["composition"].items():
for stage, stage_data in elem_data.items():
- species = Species(stage_data["element"], stage, stage_data["distribution"])
+ elem = _get_cherab_element(elem_name)
+ species = Species(elem, stage, stage_data)
plasma_composition.append(species)
# Populate plasma
@@ -209,9 +693,24 @@ def get_edge_plasma(atomic_data=None, parent=None, name="Generomak edge plasma")
plasma.name = name
plasma.geometry = plasma_geometry
plasma.atomic_data = atomic_data
- plasma.electron_distribution = dists["electron"]
+ plasma.electron_distribution = distributions["electron"]
plasma.composition = plasma_composition
plasma.geometry_transform = geometry_transform
plasma.b_field = VectorAxisymmetricMapper(equilibrium.b_field)
return plasma
+
+
+def _get_cherab_element(name):
+ """Returns cherab element instance
+
+ :param name: Name or label of the element Cherab has to know.
+ :return: Cherab element
+ """
+ try:
+ return lookup_isotope(name)
+ except ValueError:
+ try:
+ return lookup_element(name)
+ except ValueError:
+ raise ValueError("Unknown element name '{}' by Cherab".format(name))
diff --git a/cherab/tools/emitters/radiation_function.pxd b/cherab/tools/emitters/radiation_function.pxd
new file mode 100644
index 00000000..8c9ac3b0
--- /dev/null
+++ b/cherab/tools/emitters/radiation_function.pxd
@@ -0,0 +1,25 @@
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+from raysect.optical.material.emitter cimport InhomogeneousVolumeEmitter
+from cherab.core.math.function cimport Function3D
+
+
+cdef class RadiationFunction(InhomogeneousVolumeEmitter):
+ cdef:
+ readonly Function3D radiation_function
diff --git a/cherab/tools/emitters/radiation_function.pyx b/cherab/tools/emitters/radiation_function.pyx
index c9cd414b..a9b0800d 100644
--- a/cherab/tools/emitters/radiation_function.pyx
+++ b/cherab/tools/emitters/radiation_function.pyx
@@ -1,6 +1,6 @@
-# Copyright 2016-2018 Euratom
-# Copyright 2016-2018 United Kingdom Atomic Energy Authority
-# Copyright 2016-2018 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
#
# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
# European Commission - subsequent versions of the EUPL (the "Licence");
@@ -20,7 +20,7 @@ from raysect.optical cimport Point3D, Vector3D, Spectrum, World, Ray, Primitive,
from raysect.optical.material.emitter cimport InhomogeneousVolumeEmitter, NumericalIntegrator
from cherab.core.math.function cimport Function3D, autowrap_function3d
from libc.math cimport M_PI
-import cython
+cimport cython
cdef class RadiationFunction(InhomogeneousVolumeEmitter):
@@ -51,10 +51,6 @@ cdef class RadiationFunction(InhomogeneousVolumeEmitter):
>>> def rad_function_3d(x, y, z): return 0
>>> radiation_emitter = RadiationFunction(rad_function_3d)
"""
-
- cdef:
- readonly Function3D radiation_function
-
def __init__(self, radiation_function, step=0.1):
super().__init__(NumericalIntegrator(step=step))
@@ -68,7 +64,7 @@ cdef class RadiationFunction(InhomogeneousVolumeEmitter):
AffineMatrix3D world_to_local, AffineMatrix3D local_to_world):
cdef int index
- cdef double wvl_range = ray.max_wavelength - ray.min_wavelength
+ cdef double wvl_range = ray.get_max_wavelength() - ray.get_min_wavelength()
cdef double emission
emission = self.radiation_function.evaluate(point.x, point.y, point.z) / (4 * M_PI * wvl_range)
diff --git a/cherab/tools/equilibrium/efit.pxd b/cherab/tools/equilibrium/efit.pxd
index c074d92d..5aff5b55 100644
--- a/cherab/tools/equilibrium/efit.pxd
+++ b/cherab/tools/equilibrium/efit.pxd
@@ -43,9 +43,8 @@ cdef class EFITEquilibrium:
readonly double time
readonly np.ndarray lcfs_polygon, limiter_polygon
readonly np.ndarray psi_data, r_data, z_data
- readonly Function1D q
+ readonly Function1D q, f_profile
double _b_vacuum_magnitude, _b_vacuum_radius
- Function1D _f_profile
Function2D _dpsidr, _dpsidz
diff --git a/cherab/tools/equilibrium/efit.pyx b/cherab/tools/equilibrium/efit.pyx
index 955f6d39..cb23496a 100644
--- a/cherab/tools/equilibrium/efit.pyx
+++ b/cherab/tools/equilibrium/efit.pyx
@@ -73,6 +73,7 @@ cdef class EFITEquilibrium:
:ivar Function2D psi: The poloidal flux in the r-z plane, :math:`\psi(r,z)`.
:ivar Function2D psi_normalised: The normalised poloidal flux in the r-z plane, :math:`\psi_n(r,z)`.
+ :ivar Function1D f_profile: The current flux at the specified normalised poloidal flux, :math:`F(\psi_n)`.
:ivar Function1D q: The safety factor :math:`q` at the specified normalised poloidal flux, :math:`q(\psi_n)`.
:ivar VectorFunction2D b_field: A 2D function that returns the magnetic field vector at the specified
point in the r-z plane, :math:`B(r, z)`.
@@ -119,7 +120,7 @@ cdef class EFITEquilibrium:
self.z_range = z.min(), z.max()
self._b_vacuum_magnitude = b_vacuum_magnitude
self._b_vacuum_radius = b_vacuum_radius
- self._f_profile = Interpolator1DArray(f_profile[0, :], f_profile[1, :], 'cubic', 'none', 0)
+ self.f_profile = Interpolator1DArray(f_profile[0, :], f_profile[1, :], 'cubic', 'none', 0)
self.q = Interpolator1DArray(q_profile[0, :], q_profile[1, :], 'cubic', 'none', 0)
# populate points
@@ -130,7 +131,7 @@ cdef class EFITEquilibrium:
# calculate b-field
dpsi_dr, dpsi_dz = self._calculate_differentials(r, z, psi)
- self.b_field = MagneticField(self.psi_normalised, dpsi_dr, dpsi_dz, self._f_profile, b_vacuum_radius, b_vacuum_magnitude, self.inside_lcfs)
+ self.b_field = MagneticField(self.psi_normalised, dpsi_dr, dpsi_dz, self.f_profile, b_vacuum_radius, b_vacuum_magnitude, self.inside_lcfs)
# populate flux coordinate attributes
self.toroidal_vector = ConstantVector2D(Vector3D(0, 1, 0))
diff --git a/cherab/tools/inversions/opencl/opencl_utils.py b/cherab/tools/inversions/opencl/opencl_utils.py
index ae8122ab..51747a93 100644
--- a/cherab/tools/inversions/opencl/opencl_utils.py
+++ b/cherab/tools/inversions/opencl/opencl_utils.py
@@ -17,10 +17,7 @@
#
# See the Licence for the specific language governing permissions and limitations
# under the Licence.
-#
-# The following code is created by Vladislav Neverov (NRC "Kurchatov Institute") for Cherab Spectroscopy Modelling Framework
-from __future__ import print_function
import warnings
try:
import pyopencl as cl
@@ -32,7 +29,7 @@
def get_flops(device, verbose=False):
"""
- Returns the theoretical peak performance of specified OpenCL-compatible GPU or accelerator.
+ Returns the theoretical peak performance of specified OpenCL-compatible GPU or ACCELERATOR.
Currently supports only Nvidia, AMD, Intel or Mali GPUs.
:param pyopencl.Device device: OpenCL device.
@@ -40,16 +37,23 @@ def get_flops(device, verbose=False):
:return: Theoretical peak performance in GFLOPs.
"""
+
if not _has_pyopencl:
raise RuntimeError("The pyopencl module is required to run get_flops() function.")
+
+ device_type = device.get_info(cl.device_info.TYPE)
+ if not (device_type & (cl.device_type.GPU | cl.device_type.ACCELERATOR)):
+ raise ValueError("Unsupported device type: {}.".format(cl.device_type.to_string(device_type)))
+
comp_units = device.get_info(cl.device_info.MAX_COMPUTE_UNITS)
gpu_clock = device.get_info(cl.device_info.MAX_CLOCK_FREQUENCY)
vendor = device.get_info(cl.device_info.VENDOR).lower()
gflops = 0
+
if "nvidia" in vendor:
cc_maj = device.get_info(cl.device_info.COMPUTE_CAPABILITY_MAJOR_NV)
cc_min = device.get_info(cl.device_info.COMPUTE_CAPABILITY_MINOR_NV)
- alu_lanes = 128
+ alu_lanes = 128 # default (as in 8.6)
if cc_maj == 1:
alu_lanes = 8
elif cc_maj == 2:
@@ -62,81 +66,108 @@ def get_flops(device, verbose=False):
alu_lanes = 64 if cc_min == 0 else 128
elif cc_maj == 7:
alu_lanes = 64
+ elif cc_maj == 8:
+ # For the devices with CUDA CC 8.6, the same ALUs can do both integer and float32 math.
+ # Theoreticaly this doubles the peak float32 performance as it double the number of ALU lanes with float32 support.
+ alu_lanes = 64 if cc_min == 0 else 128
gflops = comp_units * alu_lanes * 2 * gpu_clock / 1000.
+
elif "amd" in vendor or "advanced" in vendor:
try:
ww = device.get_info(cl.device_info.WAVEFRONT_WIDTH_AMD)
except:
ww = 64
gflops = comp_units * ww * 2 * gpu_clock / 1000.
+
elif "intel" in vendor:
gflops = comp_units * 16 * gpu_clock / 1000.
+
elif "arm" in vendor:
gflops = comp_units * 2 * 16 * gpu_clock / 1000.
+
else:
- warnings.warn('Unsupported device vendor: %s. Unable to estimate theoretical peak performance.' % vendor)
+ warnings.warn('Unsupported device vendor: {}. Unable to estimate theoretical peak performance.'.format(vendor))
return 0
+
if verbose:
- print("Number of compute units: %d" % comp_units)
- print("GPU maximum clock rate: %d MHz" % gpu_clock)
- print("Estimated theoretical peak performance: %g GFLOPS" % gflops)
+ print("Number of compute units: {}".format(comp_units))
+ print("GPU maximum clock rate: {} MHz".format(gpu_clock))
+ print("Estimated theoretical peak performance: {} GFLOPS".format(gflops))
return gflops
def get_best_gpu(platforms=None, device_type=None, verbose=False):
"""
- Finds the fastest (in terms of theoretical peak performance) GPU and/or accelerator available in specified OpenCL platforms
+ Finds the fastest (in terms of theoretical peak performance) GPU and/or accelerator
+ available in specified OpenCL platforms
- :param list platforms: List of pyopencl.Platform instances. Default value: `platforms=None` (all available OpenCL platfroms).
+ :param list platforms: List of pyopencl.Platform instances. Default value: `platforms=None`
+ (all available OpenCL platfroms).
:param pyopencl.device_type device_type: OpenCL device type (GPU, ACCELERATOR, or both).
- Default value: `device_type=None` (GPU or accelerator).
+ Default value: `device_type=None` (GPU or accelerator).
+ If device_type is ALL or DEFAULT, all non-GPU/ACCELERATOR
+ devices will be skipped.
:param bool verbose: Verbose output, defaults to `verbose=False`.
- :return: The pyopencl.Device instance corresponding to the fastest GPU or accelerator available in the specified OpenCL platforms.
+ :return: The pyopencl.Device instance corresponding to the fastest GPU or accelerator available
+ in the specified OpenCL platforms.
"""
+
if not _has_pyopencl:
raise RuntimeError("The pyopencl module is required to run get_best_gpu() function.")
+
device_type = device_type or cl.device_type.GPU | cl.device_type.ACCELERATOR
- if device_type == cl.device_type.DEFAULT:
+ if device_type == cl.device_type.DEFAULT or device_type == cl.device_type.ALL:
device_type = cl.device_type.GPU | cl.device_type.ACCELERATOR
- if not (cl.device_type.GPU | cl.device_type.ACCELERATOR) & device_type:
- raise ValueError('This function works with GPU devices only')
+
+ if not ((cl.device_type.GPU | cl.device_type.ACCELERATOR) & device_type):
+ raise ValueError('This function works with GPU devices only.')
+
+ if verbose:
+ print("Selecting best GPU...")
+
if platforms is None:
platforms = cl.get_platforms()
- if verbose:
- print("Selecting best GPU")
device_best = None
max_gflops = 0
for iplat, platform in enumerate(platforms):
if verbose:
- print("\nOpenCL platform %d: %s" % (iplat, platform.get_info(cl.platform_info.NAME)))
+ print("\nOpenCL platform {}: {}.".format(iplat, platform.get_info(cl.platform_info.NAME)))
devices = platform.get_devices(device_type=device_type)
for idev, device in enumerate(devices):
if verbose:
- print("\nDevice %d: %s %s" % (idev, device.get_info(cl.device_info.VENDOR), device.get_info(cl.device_info.NAME)))
+ print("\nDevice {}: {} {}.".format(idev, device.get_info(cl.device_info.VENDOR),
+ device.get_info(cl.device_info.NAME)))
gflops = get_flops(device, verbose)
if gflops > max_gflops:
device_best = device
+
if device_best is None:
- print("No supported GPUs found\n")
+ warnings.warn("No supported GPUs found.")
return None
- print("\nSelected OpenCL device: %s %s\n" % (device_best.get_info(cl.device_info.VENDOR), device_best.get_info(cl.device_info.NAME)))
+
+ if verbose:
+ print("\nSelected OpenCL device: {} {}.\n".format(device_best.get_info(cl.device_info.VENDOR),
+ device_best.get_info(cl.device_info.NAME)))
return device_best
-def get_first_device(platforms=None, device_type=None):
+def get_first_device(platforms=None, device_type=None, verbose=False):
"""
Returns the first OpenCL device of specified type available in specified OpenCL platforms
:param list platforms: List of pyopencl.Platform instances. Default value: `platforms=None` (all available OpenCL platfroms).
- :param pyopencl.device_type device_type: OpenCL device type (GPU, ACCELERATOR, or both).
+ :param pyopencl.device_type device_type: OpenCL device type (GPU, ACCELERATOR, CPU, ALL, etc.).
Default value: `device_type=None` (GPU or accelerator).
+ :param bool verbose: Verbose output, defaults to `verbose=False`.
:return: The pyopencl.Device instance corresponding to the first device available in the specified OpenCL platforms.
"""
+
if not _has_pyopencl:
raise RuntimeError("The pyopencl module is required to run get_first_device() function.")
+
device_type = device_type or cl.device_type.GPU | cl.device_type.ACCELERATOR
if platforms is None:
platforms = cl.get_platforms()
@@ -144,56 +175,68 @@ def get_first_device(platforms=None, device_type=None):
devices = platform.get_devices(device_type=device_type)
if len(devices):
device = devices[0]
- print("Selected OpenCL device: %s %s\n" % (device.get_info(cl.device_info.VENDOR), device.get_info(cl.device_info.NAME)))
+ if verbose:
+ print("Selected OpenCL device: {} {}.\n".format(device.get_info(cl.device_info.VENDOR),
+ device.get_info(cl.device_info.NAME)))
return device
- print("\nThere are no devices of specified type\n")
+
+ warnings.warn("Unable to find OpenCL devices of specified type.")
return None
def device_select(platfrom_id=None, device_id=None, device_type=None, verbose=False):
"""
- OpenCL device selector. Returns the most powerfull OpenCL device availabe if device_type is GPU or accelerator
- or the first OpenCL device available if device_type is CPU.
+ OpenCL device selector. Returns the most powerfull OpenCL device availabe
+ if device_type is GPU or ACCELERATOR or the first OpenCL device available
+ if device_type is CPU, ALL or CUSTOM.
:param int platfrom_id: OpenCL platform ID, defaults to `platfrom_id=None`.
- :param int device_id: OpenCL device ID (in the selected OpenCL platform), defaults to `device_id=None`.
+ :param int device_id: OpenCL device ID (in the selected OpenCL platform),
+ defaults to `device_id=None`.
:param pyopencl.device_type device_type: OpenCL device type (GPU, ACCELERATOR, etc.).
- Default value: `device_type=None` (GPU or accelerator).
+ Default value: `device_type=None` (GPU | ACCELERATOR).
:param bool verbose: Verbose output, defaults to `verbose=False`.
:return: The pyopencl.Device instance corresponding to the selected OpenCL device.
"""
+
if not _has_pyopencl:
raise RuntimeError("The pyopencl module is required to run device_select() function.")
+
device_type = device_type or cl.device_type.GPU | cl.device_type.ACCELERATOR
- platforms = cl.get_platforms()
- n_platforms = len(platforms)
if device_type == cl.device_type.DEFAULT:
device_type = cl.device_type.GPU | cl.device_type.ACCELERATOR
- non_gpu_device = not (cl.device_type.GPU | cl.device_type.ACCELERATOR) & device_type
+
+ non_gpu_device = (device_type == cl.device_type.ALL) or not ((cl.device_type.GPU | cl.device_type.ACCELERATOR) & device_type)
+
+ platforms = cl.get_platforms()
+ n_platforms = len(platforms)
+
+ if platfrom_id is not None and platfrom_id >= n_platforms:
+ raise ValueError('The platform_id {} exceeds the number of OpenCL platforms ({}) found in the system.'.format(platfrom_id, n_platforms))
+
if platfrom_id is None:
if non_gpu_device:
- return get_first_device(platforms, device_type)
- return get_best_gpu(platforms, device_type, verbose)
- if platfrom_id < n_platforms:
- platform = platforms[platfrom_id]
- devices = platform.get_devices(device_type=device_type)
- n_devices = len(devices)
- if device_id is None:
- if non_gpu_device:
- return get_first_device([platform], device_type)
- return get_best_gpu([platform], device_type, verbose)
- if device_id < n_devices:
- device = devices[device_id]
- print("Selected OpenCL device: %s %s" % (device.get_info(cl.device_info.VENDOR), device.get_info(cl.device_info.NAME)))
- return device
- warnings.warn('%s platform has %d devices of specified type\n' % (platform.get_info(cl.platform_info.NAME), n_platforms))
+ return get_first_device(platforms, device_type, verbose)
+ # get_best_gpu() returns None for unsupported devices, if so return the first device
+ return get_best_gpu(platforms, device_type, verbose) or get_first_device(platforms, device_type, verbose)
+
+ platform = platforms[platfrom_id]
+ devices = platform.get_devices(device_type=device_type)
+ n_devices = len(devices)
+
+ if device_id is not None and device_id >= n_devices:
+ platform_name = platform.get_info(cl.platform_info.NAME)
+ raise ValueError('The device_id {} exceeds the number of devices ({}) of specified type in the {} platform.'.format(device_id, n_devices, platform_name))
+
+ if device_id is None:
if non_gpu_device:
- return get_first_device([platform], device_type)
- return get_best_gpu([platform], device_type, verbose)
- warnings.warn('System has only %d OpenCL platforms\n' % n_platforms)
- if non_gpu_device:
- return get_first_device(platforms, device_type)
+ return get_first_device([platform], device_type, verbose)
+ # get_best_gpu() returns None for unsupported devices, if so return the first device
+ return get_best_gpu([platform], device_type, verbose) or get_first_device([platform], device_type, verbose)
- return get_best_gpu(platforms, device_type, verbose)
+ device = devices[device_id]
+ if verbose:
+ print("Selected OpenCL device: {} {}.".format(device.get_info(cl.device_info.VENDOR), device.get_info(cl.device_info.NAME)))
+ return device
diff --git a/cherab/tools/inversions/opencl/sart_kernels.cl b/cherab/tools/inversions/opencl/sart_kernels.cl
index c73b0e7d..63265b29 100644
--- a/cherab/tools/inversions/opencl/sart_kernels.cl
+++ b/cherab/tools/inversions/opencl/sart_kernels.cl
@@ -15,8 +15,6 @@
//
// See the Licence for the specific language governing permissions and limitations
// under the Licence.
-//
-// The following code is created by Vladislav Neverov (NRC "Kurchatov Institute") for Cherab Spectroscopy Modelling Framework
#ifndef BLOCK_SIZE
#define BLOCK_SIZE 256
diff --git a/cherab/tools/inversions/opencl/sart_kernels_atomic.cl b/cherab/tools/inversions/opencl/sart_kernels_atomic.cl
index e9b6afc9..47307a15 100644
--- a/cherab/tools/inversions/opencl/sart_kernels_atomic.cl
+++ b/cherab/tools/inversions/opencl/sart_kernels_atomic.cl
@@ -15,8 +15,6 @@
//
// See the Licence for the specific language governing permissions and limitations
// under the Licence.
-//
-// The following code is created by Vladislav Neverov (NRC "Kurchatov Institute") for Cherab Spectroscopy Modelling Framework
#ifndef BLOCK_SIZE
#define BLOCK_SIZE 256
diff --git a/cherab/tools/inversions/opencl/sart_opencl.py b/cherab/tools/inversions/opencl/sart_opencl.py
index afcf726d..4bd1d65f 100644
--- a/cherab/tools/inversions/opencl/sart_opencl.py
+++ b/cherab/tools/inversions/opencl/sart_opencl.py
@@ -17,10 +17,7 @@
#
# See the Licence for the specific language governing permissions and limitations
# under the Licence.
-#
-# The following code is created by Vladislav Neverov (NRC "Kurchatov Institute") for Cherab Spectroscopy Modelling Framework
-from __future__ import print_function
import os
import numpy as np
from timeit import default_timer as timer
@@ -44,29 +41,37 @@ class SartOpencl:
performed with single precision.
:param np.ndarray geometry_matrix: The sensitivity matrix describing the coupling between
- the detectors and the voxels. Must be an array with shape :math:`(N_d, N_s)`.
+ the detectors and the voxels. Must be an array
+ with shape :math:`(N_d, N_s)`.
:param np.ndarray laplacian_matrix: The laplacian regularisation matrix of
- shape :math:`(N_s, N_s)`. Default value: `laplacian_matrix=None`.
+ shape :math:`(N_s, N_s)`.
+ Default value: `laplacian_matrix=None`.
:param pyopencl.Device device: OpenCL device which will be used for computations.
- Default value: `device=None` (autoselect).
+ Default value: `device=None` (autoselect).
:param int block_size: Number of GPU threads per block. Must be the power of 2.
- For the best performance try from 256 to 1024 for Nvidia (use 1024 on high-end GPUs),
- from 64 to 256 for AMD and from 16 to 64 for Intel GPUs. Default value: `block_size=256`.
+ For the best performance try from 256 to 1024 for Nvidia
+ (use 1024 on high-end GPUs), from 64 to 256 for AMD and from 16 to 64
+ for Intel GPUs. Default value: `block_size=256`.
:param bool copy_column_major: If True, the two copies of geometry matrix will be stored in
- GPU memory. One in row-major order and the other one in column-major order. This
- provides much better performance of the inversions but requires twice as much GPU memory.
- Default value: `copy_column_major=True`.
+ GPU memory. One in row-major order and the other one in
+ column-major order. This provides much better performance
+ of the inversions but requires twice as much GPU memory.
+ Default value: `copy_column_major=True`.
:param int block_size_row_maj: If `copy_column_major` is set to False, this parameter defines
- the number of GPU threads per block in mat_vec_mult_row_maj() kernel used to calculate
- y_hat. Must be lower than `block_size`. Default value: `block_size_row_maj=64` (optimal
- value for Nvidia GPUs).
+ the number of GPU threads per block in mat_vec_mult_row_maj()
+ kernel used to calculate y_hat. Must be lower than
+ `block_size`. Default value: `block_size_row_maj=64` (optimal
+ value for Nvidia GPUs).
:param bool use_atomic: If True, increases the number of thread blocks that can run in
- parallel with the help of atomic operations (custom atomic add on floats). Set this
- to False, if the atomic operations are running slow on your device (Nvidia GPUs before
- Kepler, some AMD APUs, some Intel GPUs). Default value: `use_atomic=True`.
+ parallel with the help of atomic operations (custom atomic add on floats).
+ Set this to False, if the atomic operations are running slow on your device
+ (Nvidia GPUs before Kepler, some AMD APUs, some Intel GPUs).
+ Default value: `use_atomic=True`.
:param int steps_per_thread: If `use_atomic` is set to True, this parameters defines the
- maximum number of loop steps performed by the parallel threads in a single thread block.
- Default value: `steps_per_thread=64` (optimal for Nvidia GPUs).
+ maximum number of loop steps performed by the parallel threads
+ in a single thread block. Default value: `steps_per_thread=64`
+ (optimal for Nvidia GPUs).
+ :param bool verbose: Verbose output, defaults to `verbose=False`.
.. code-block:: pycon
@@ -79,92 +84,99 @@ class SartOpencl:
"""
def __init__(self, geometry_matrix, laplacian_matrix=None, device=None, block_size=256, copy_column_major=True, block_size_row_maj=64,
- use_atomic=True, steps_per_thread=64):
+ use_atomic=True, steps_per_thread=64, verbose=False):
if not _has_pyopencl:
raise RuntimeError("The pyopencl module is required to use the SartOpencl() inversion class.")
+
+ self._verbose = verbose
+
if geometry_matrix.dtype != np.float32: # converting geometry_matrix to float32 if needed
geometry_matrix = geometry_matrix.astype(np.float32)
- self.m_detectors, self.n_sources = geometry_matrix.shape
+
+ self._m_detectors, self._n_sources = geometry_matrix.shape
cell_ray_densities = geometry_matrix.sum(0)
ray_lengths = geometry_matrix.sum(1)
- device = device or device_select()
- self.use_atomic = use_atomic
+ device = device or device_select(verbose=verbose)
+ self._use_atomic = use_atomic
steps_per_thread = min(block_size, steps_per_thread)
steps_per_thread_row_maj = min(block_size_row_maj, steps_per_thread)
# creating OpenCL context
- self.cl_context = cl.Context([device])
+ self._cl_context = cl.Context([device])
# reading and compiling OpenCL kernels
kernels_filename = 'sart_kernels_atomic.cl' if use_atomic else 'sart_kernels.cl'
kernel_source_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), kernels_filename)
with open(kernel_source_file) as f_kernel:
kernel_source = f_kernel.read()
- compile_options = ['-DBLOCK_SIZE=%d' % block_size, '-DSTEPS_PER_THREAD=%d' % steps_per_thread,
- '-DSTEPS_PER_THREAD_ROW_MAJ=%d' % steps_per_thread_row_maj,
- '-DBLOCK_SIZE_ROW_MAJ=%d' % block_size_row_maj, '-cl-fast-relaxed-math']
- self.cl_prog = cl.Program(self.cl_context, kernel_source).build(options=compile_options)
+ compile_options = ['-DBLOCK_SIZE={}'.format(block_size), '-DSTEPS_PER_THREAD={}'.format(steps_per_thread),
+ '-DSTEPS_PER_THREAD_ROW_MAJ={}'.format(steps_per_thread_row_maj),
+ '-DBLOCK_SIZE_ROW_MAJ={}'.format(block_size_row_maj), '-cl-fast-relaxed-math']
+ self._cl_prog = cl.Program(self._cl_context, kernel_source).build(options=compile_options)
# creating buffers in device memory
mf = cl.mem_flags
- self.geometry_matrix_device = cl.Buffer(self.cl_context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=geometry_matrix)
+
+ self._geometry_matrix_device = cl.Buffer(self._cl_context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=geometry_matrix)
if copy_column_major:
geometry_matric_col_maj = geometry_matrix.flatten(order='F')
- self.geometry_matric_col_maj_device = cl.Buffer(self.cl_context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=geometry_matric_col_maj)
+ self._geometry_matric_col_maj_device = cl.Buffer(self._cl_context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=geometry_matric_col_maj)
else:
- self.geometry_matric_col_maj_device = None
+ self._geometry_matric_col_maj_device = None
+
if laplacian_matrix is not None:
laplacian_matrix = laplacian_matrix.flatten(order='F').astype(np.float32)
- self.laplacian_matrix_device = cl.Buffer(self.cl_context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=laplacian_matrix)
+ self._laplacian_matrix_device = cl.Buffer(self._cl_context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=laplacian_matrix)
else:
- self.laplacian_matrix_device = None
- self.cell_ray_densities_device = cl.Buffer(self.cl_context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=cell_ray_densities)
- self.ray_lengths_device = cl.Buffer(self.cl_context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=ray_lengths)
- grad_penalty = np.zeros(self.n_sources, dtype=np.float32)
- self.grad_penalty_device = cl.Buffer(self.cl_context, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=grad_penalty)
- self.solution_device = cl.Buffer(self.cl_context, mf.READ_WRITE, cell_ray_densities.nbytes)
- self.detectors_device = cl.Buffer(self.cl_context, mf.READ_ONLY, ray_lengths.nbytes)
- self.y_hat_device = cl.Buffer(self.cl_context, mf.READ_WRITE, ray_lengths.nbytes)
+ self._laplacian_matrix_device = None
+
+ self._cell_ray_densities_device = cl.Buffer(self._cl_context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=cell_ray_densities)
+ self._ray_lengths_device = cl.Buffer(self._cl_context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=ray_lengths)
+ grad_penalty = np.zeros(self._n_sources, dtype=np.float32)
+ self._grad_penalty_device = cl.Buffer(self._cl_context, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=grad_penalty)
+ self._solution_device = cl.Buffer(self._cl_context, mf.READ_WRITE, cell_ray_densities.nbytes)
+ self._detectors_device = cl.Buffer(self._cl_context, mf.READ_ONLY, ray_lengths.nbytes)
+ self._y_hat_device = cl.Buffer(self._cl_context, mf.READ_WRITE, ray_lengths.nbytes)
# calculating global and local work sizes
- nrem = self.n_sources % block_size
- gws_sources_x = self.n_sources + bool(nrem) * (block_size - nrem)
- mrem = self.m_detectors % block_size
- gws_detectors_x = self.m_detectors + bool(mrem) * (block_size - mrem)
- mrem_rm = self.m_detectors % block_size_row_maj
- gws_detectors_row_maj_x = self.m_detectors + bool(mrem_rm) * (block_size - mrem_rm)
+ nrem = self._n_sources % block_size
+ gws_sources_x = self._n_sources + bool(nrem) * (block_size - nrem)
+ mrem = self._m_detectors % block_size
+ gws_detectors_x = self._m_detectors + bool(mrem) * (block_size - mrem)
+ mrem_rm = self._m_detectors % block_size_row_maj
+ gws_detectors_row_maj_x = self._m_detectors + bool(mrem_rm) * (block_size - mrem_rm)
if use_atomic:
- gws_sources_row_maj_y = self.n_sources // steps_per_thread_row_maj + bool(self.n_sources % steps_per_thread_row_maj)
- gws_sources_y = self.n_sources // steps_per_thread + bool(self.n_sources % steps_per_thread)
- gws_detectors_y = self.m_detectors // steps_per_thread + bool(self.m_detectors % steps_per_thread)
+ gws_sources_row_maj_y = self._n_sources // steps_per_thread_row_maj + bool(self._n_sources % steps_per_thread_row_maj)
+ gws_sources_y = self._n_sources // steps_per_thread + bool(self._n_sources % steps_per_thread)
+ gws_detectors_y = self._m_detectors // steps_per_thread + bool(self._m_detectors % steps_per_thread)
else:
gws_sources_row_maj_y = gws_sources_y = gws_detectors_y = 1
- self.global_work_size = {}
- self.local_work_size = {'default': (block_size, 1)}
- self.global_work_size['trivial_sources'] = (gws_sources_x, 1)
- self.global_work_size['trivial_detectors'] = (gws_detectors_x, 1)
- self.global_work_size['iter'] = (gws_sources_x, gws_detectors_y)
+ self._global_work_size = {}
+ self._local_work_size = {'default': (block_size, 1)}
+ self._global_work_size['trivial_sources'] = (gws_sources_x, 1)
+ self._global_work_size['trivial_detectors'] = (gws_detectors_x, 1)
+ self._global_work_size['iter'] = (gws_sources_x, gws_detectors_y)
if copy_column_major:
- self.local_work_size['mult'] = self.local_work_size['default']
- self.global_work_size['mult'] = (gws_detectors_x, gws_sources_y)
+ self._local_work_size['mult'] = self._local_work_size['default']
+ self._global_work_size['mult'] = (gws_detectors_x, gws_sources_y)
else:
- self.local_work_size['mult'] = (block_size_row_maj, 1)
- self.global_work_size['mult'] = (gws_detectors_row_maj_x, gws_sources_row_maj_y)
- self.global_work_size['grad'] = (gws_sources_x, gws_sources_y)
+ self._local_work_size['mult'] = (block_size_row_maj, 1)
+ self._global_work_size['mult'] = (gws_detectors_row_maj_x, gws_sources_row_maj_y)
+ self._global_work_size['grad'] = (gws_sources_x, gws_sources_y)
def clean(self):
""" Releases GPU buffers"""
- self.geometry_matrix_device.release()
- if self.geometry_matric_col_maj_device is not None:
- self.geometry_matric_col_maj_device.release()
- if self.laplacian_matrix_device is not None:
- self.laplacian_matrix_device.release()
- self.cell_ray_densities_device.release()
- self.ray_lengths_device.release()
- self.solution_device.release()
- self.grad_penalty_device.release()
- self.detectors_device.release()
- self.y_hat_device.release()
+ self._geometry_matrix_device.release()
+ if self._geometry_matric_col_maj_device is not None:
+ self._geometry_matric_col_maj_device.release()
+ if self._laplacian_matrix_device is not None:
+ self._laplacian_matrix_device.release()
+ self._cell_ray_densities_device.release()
+ self._ray_lengths_device.release()
+ self._solution_device.release()
+ self._grad_penalty_device.release()
+ self._detectors_device.release()
+ self._y_hat_device.release()
def __enter__(self):
return self
@@ -179,14 +191,14 @@ def update_laplacian_matrix(self, laplacian_matrix):
:param np.ndarray laplacian_matrix: The laplacian regularisation matrix of
shape :math:`(N_s, N_s)`.
"""
- if self.laplacian_matrix_device is not None:
+ if self._laplacian_matrix_device is not None:
laplacian_matrix = laplacian_matrix.flatten(order='F').astype(np.float32)
- queue = cl.CommandQueue(self.cl_context)
- cl.enqueue_copy(queue, self.laplacian_matrix_device, laplacian_matrix)
+ queue = cl.CommandQueue(self._cl_context)
+ cl.enqueue_copy(queue, self._laplacian_matrix_device, laplacian_matrix)
def __call__(self, measurement_vector, initial_guess=None, max_iterations=250, relaxation=1.0,
beta_laplace=0.01, conv_tol=1.e-4, time_limit=None):
- """
+ r"""
Performs the inversion for a given measurement vector.
:param np.ndarray measurement_vector: The measured power/radiance vector with
@@ -211,12 +223,13 @@ def __call__(self, measurement_vector, initial_guess=None, max_iterations=250, r
shape :math:`(N_s)`, and the list of convergence values achieved after each iteration
step.
"""
+
time_start = timer()
time_limit = time_limit or 1.e7
if initial_guess is None:
- solution = np.zeros(self.n_sources, dtype=np.float32) + 1 / np.e
+ solution = np.zeros(self._n_sources, dtype=np.float32) + 1 / np.e
elif isinstance(initial_guess, (float, int)):
- solution = np.zeros(self.n_sources, dtype=np.float32) + initial_guess
+ solution = np.zeros(self._n_sources, dtype=np.float32) + initial_guess
else:
solution = initial_guess.astype(np.float32) # making a copy even if initial_guess is in float32 already
measurement_max = measurement_vector.max()
@@ -224,11 +237,11 @@ def __call__(self, measurement_vector, initial_guess=None, max_iterations=250, r
measurement_vector = (measurement_vector / measurement_max).astype(np.float32)
measurement_squared = np.dot(measurement_vector, measurement_vector)
y_hat_vector = np.empty_like(measurement_vector) # host y_hat
- queue = cl.CommandQueue(self.cl_context)
+ queue = cl.CommandQueue(self._cl_context)
# copying initial guess and measurement_vector to device
- cl.enqueue_copy(queue, self.solution_device, solution)
- cl.enqueue_copy(queue, self.detectors_device, measurement_vector)
+ cl.enqueue_copy(queue, self._solution_device, solution)
+ cl.enqueue_copy(queue, self._detectors_device, measurement_vector)
# calculating y_hat on device
self._calc_y_hat(queue)
@@ -238,7 +251,6 @@ def __call__(self, measurement_vector, initial_guess=None, max_iterations=250, r
conv_tol = np.float32(conv_tol)
success = False
for k in range(max_iterations):
- # print('Iteration: %d' % k)
# making one iteration on device
self._make_iteration(queue, relaxation, beta_laplace)
@@ -246,7 +258,7 @@ def __call__(self, measurement_vector, initial_guess=None, max_iterations=250, r
self._calc_y_hat(queue)
# copying y_hat to host
- cl.enqueue_copy(queue, y_hat_vector, self.y_hat_device)
+ cl.enqueue_copy(queue, y_hat_vector, self._y_hat_device)
# calculating convergence
y_hat_squared = np.dot(y_hat_vector, y_hat_vector)
@@ -256,48 +268,51 @@ def __call__(self, measurement_vector, initial_guess=None, max_iterations=250, r
# checking conditions
if k > 0 and np.abs(convergence[k] - convergence[k - 1]) < conv_tol:
success = True
- print('Convergence limit is reached in %.4f s with %d iterations' % (time_passed, k + 1))
+ if self._verbose:
+ print('Convergence limit is reached in {:.4f} s with {} iterations.'.format(time_passed, k + 1))
break
if time_passed > time_limit:
- print('Time limit is exceeded')
+ # if no success, the user must be informed even if verbose is False
+ print('The time limit has been exceeded, but the convergence limit has not been reached.')
break
if (not success) and k == max_iterations - 1:
- print('Maximum number of iterations is reached. Time passed: %.4f s' % time_passed)
+ # if no success, the user must be informed even if verbose is False
+ print('Maximum number of iterations is reached. Time passed: {:.4f} s.'.format(time_passed))
# copying solution to host
- cl.enqueue_copy(queue, solution, self.solution_device)
+ cl.enqueue_copy(queue, solution, self._solution_device)
return solution * measurement_max, convergence
def _calc_y_hat(self, queue):
- if self.use_atomic:
- self.cl_prog.zero_all(queue, self.global_work_size['trivial_detectors'], self.local_work_size['default'],
- self.y_hat_device, np.uint32(self.m_detectors))
- if self.geometry_matric_col_maj_device is None:
- self.cl_prog.mat_vec_mult_row_major(queue, self.global_work_size['mult'], self.local_work_size['mult'],
- self.geometry_matrix_device, self.solution_device, self.y_hat_device,
- np.uint32(self.m_detectors), np.uint32(self.n_sources))
+ if self._use_atomic:
+ self._cl_prog.zero_all(queue, self._global_work_size['trivial_detectors'], self._local_work_size['default'],
+ self._y_hat_device, np.uint32(self._m_detectors))
+ if self._geometry_matric_col_maj_device is None:
+ self._cl_prog.mat_vec_mult_row_major(queue, self._global_work_size['mult'], self._local_work_size['mult'],
+ self._geometry_matrix_device, self._solution_device, self._y_hat_device,
+ np.uint32(self._m_detectors), np.uint32(self._n_sources))
else:
- self.cl_prog.mat_vec_mult_col_major(queue, self.global_work_size['mult'], self.local_work_size['mult'],
- self.geometry_matric_col_maj_device, self.solution_device, self.y_hat_device,
- np.uint32(self.m_detectors), np.uint32(self.n_sources))
+ self._cl_prog.mat_vec_mult_col_major(queue, self._global_work_size['mult'], self._local_work_size['mult'],
+ self._geometry_matric_col_maj_device, self._solution_device, self._y_hat_device,
+ np.uint32(self._m_detectors), np.uint32(self._n_sources))
def _make_iteration(self, queue, relaxation, beta_laplace):
- if self.laplacian_matrix_device is not None:
- if self.use_atomic:
- self.cl_prog.zero_all(queue, self.global_work_size['trivial_sources'], self.local_work_size['default'],
- self.grad_penalty_device, np.uint32(self.n_sources))
- self.cl_prog.mat_vec_mult_col_major(queue, self.global_work_size['grad'], self.local_work_size['default'],
- self.laplacian_matrix_device, self.solution_device, self.grad_penalty_device,
- np.uint32(self.n_sources), np.uint32(self.n_sources))
- self.cl_prog.vec_scalar_mult(queue, self.global_work_size['trivial_sources'], self.local_work_size['default'],
- self.grad_penalty_device, np.float32(beta_laplace), np.uint32(self.n_sources))
+ if self._laplacian_matrix_device is not None:
+ if self._use_atomic:
+ self._cl_prog.zero_all(queue, self._global_work_size['trivial_sources'], self._local_work_size['default'],
+ self._grad_penalty_device, np.uint32(self._n_sources))
+ self._cl_prog.mat_vec_mult_col_major(queue, self._global_work_size['grad'], self._local_work_size['default'],
+ self._laplacian_matrix_device, self._solution_device, self._grad_penalty_device,
+ np.uint32(self._n_sources), np.uint32(self._n_sources))
+ self._cl_prog.vec_scalar_mult(queue, self._global_work_size['trivial_sources'], self._local_work_size['default'],
+ self._grad_penalty_device, np.float32(beta_laplace), np.uint32(self._n_sources))
# grad_penalty is just an all-zero array if laplacian_matrix is not provided on initialisation
- self.cl_prog.sart_iteration(queue, self.global_work_size['iter'], self.local_work_size['default'],
- self.geometry_matrix_device, self.cell_ray_densities_device, self.ray_lengths_device,
- self.y_hat_device, self.detectors_device, self.solution_device, self.grad_penalty_device,
- np.float32(relaxation), np.uint32(self.n_sources), np.uint32(self.m_detectors))
- if self.use_atomic:
- self.cl_prog.zero_negative(queue, self.global_work_size['trivial_sources'], self.local_work_size['default'],
- self.solution_device, np.uint32(self.n_sources))
+ self._cl_prog.sart_iteration(queue, self._global_work_size['iter'], self._local_work_size['default'],
+ self._geometry_matrix_device, self._cell_ray_densities_device, self._ray_lengths_device,
+ self._y_hat_device, self._detectors_device, self._solution_device, self._grad_penalty_device,
+ np.float32(relaxation), np.uint32(self._n_sources), np.uint32(self._m_detectors))
+ if self._use_atomic:
+ self._cl_prog.zero_negative(queue, self._global_work_size['trivial_sources'], self._local_work_size['default'],
+ self._solution_device, np.uint32(self._n_sources))
diff --git a/cherab/tools/observers/__init__.py b/cherab/tools/observers/__init__.py
index e3b24bc2..d134ef63 100644
--- a/cherab/tools/observers/__init__.py
+++ b/cherab/tools/observers/__init__.py
@@ -21,4 +21,4 @@
from .calcam import load_calcam_calibration
from .intersections import find_wall_intersection
from .spectroscopy import SpectroscopicSightLine, SpectroscopicFibreOptic
-from .group import SightLineGroup, FibreOpticGroup
+from .group import PixelGroup, TargettedPixelGroup, SightLineGroup, FibreOpticGroup, SpectroscopicFibreOpticGroup, SpectroscopicSightLineGroup
diff --git a/cherab/tools/observers/group/__init__.py b/cherab/tools/observers/group/__init__.py
index 00ae7613..eca93585 100644
--- a/cherab/tools/observers/group/__init__.py
+++ b/cherab/tools/observers/group/__init__.py
@@ -1,4 +1,3 @@
-
# Copyright 2016-2021 Euratom
# Copyright 2016-2021 United Kingdom Atomic Energy Authority
# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
@@ -19,3 +18,6 @@
from .fibreoptic import FibreOpticGroup
from .sightline import SightLineGroup
+from .targettedpixel import TargettedPixelGroup
+from .pixel import PixelGroup
+from .spectroscopic import SpectroscopicFibreOpticGroup, SpectroscopicSightLineGroup
diff --git a/cherab/tools/observers/group/base.py b/cherab/tools/observers/group/base.py
index feac823c..7fc6c54d 100644
--- a/cherab/tools/observers/group/base.py
+++ b/cherab/tools/observers/group/base.py
@@ -1,4 +1,3 @@
-
# Copyright 2016-2021 Euratom
# Copyright 2016-2021 United Kingdom Atomic Energy Authority
# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
@@ -18,485 +17,420 @@
# under the Licence.
from numpy import ndarray
-import matplotlib.pyplot as plt
from raysect.core import Node
from raysect.core.workflow import RenderEngine
-from raysect.optical import Spectrum
-from raysect.optical.observer import SpectralRadiancePipeline0D, SpectralPowerPipeline0D, RadiancePipeline0D
+from raysect.optical.observer import Observer0D
class Observer0DGroup(Node):
"""
- A base class for a group of 0D spectroscopic observers under a single scene-graph node.
+ A base class for handling groups of nonimaging observers as one Node.
A scene-graph object regrouping a series of observers as a scene-graph parent.
Allows combined observation and display control simultaneously.
Note that for any property except `names` and `pipelines`, the same value can be shared between
- all sight lines, or each sight line can be assigned with individual value.
+ all observers, or each observer can be assigned with individual value.
- :ivar list names: A list of sight-line names.
- :ivar list pipelines: A list of all pipelines connected to each sight-line in the group.
- :ivar list/Point3D origin: The origin points for the sight lines.
- :ivar list/Vector3D direction: The observation directions for the sight lines.
- :ivar list/RenderEngine render_engine: Rendering engine used by the sight lines.
+ :ivar list names: A list of observer names.
+ :ivar list/RenderEngine render_engine: Rendering engine used by the observers.
Note that if the engine is shared, changing its
- parameters for one sight line in a group will affect
- all sight lines.
- :ivar list/bool display_progress: Toggles the display of live render progress.
- :ivar list/bool accumulate: Toggles whether to accumulate samples with subsequent
- observations.
- :ivar list/float min_wavelength: Lower wavelength bound for sampled spectral range.
- :ivar list/float max_wavelength: Upper wavelength bound for sampled spectral range.
+ parameters for one observer in a group will affect
+ all observers.
:ivar list/int spectral_bins: The number of spectral samples over the wavelength range.
- :ivar list/float ray_extinction_prob: Probability of ray extinction after every material
- intersection.
- :ivar list/float ray_extinction_min_depth: Minimum number of paths before russian roulette
- style ray extinction.
+ :ivar list/int spectral_rays: The number of smaller sub-spectrum rays the full spectrum will be divided into.
+ :ivar list/float max_wavelength: Upper wavelength bound for sampled spectral range.
+ :ivar list/float min_wavelength: Lower wavelength bound for sampled spectral range.
+ :ivar list/float ray_extinction_prob: Probability of ray extinction after every material intersection.
:ivar list/int ray_max_depth: Maximum number of Ray paths before terminating Ray.
+ :ivar list/float ray_extinction_min_depth: Minimum number of paths before russian roulette style ray extinction.
+ :ivar list/bool ray_importance_sampling: Toggle importance sampling behaviour (default=True).
:ivar list/float ray_important_path_weight: Relative weight of important path sampling.
:ivar list/int pixel_samples: The number of samples to take per pixel.
:ivar list/int samples_per_task: Minimum number of samples to request per task.
+ :ivar list pipelines: A list of all pipelines connected to each observer in the group.
"""
+ _OBSERVER_TYPE = Observer0D
- def __init__(self, parent=None, transform=None, name=None):
+ def __init__(self, parent=None, transform=None, name=None, observers=None):
super().__init__(parent=parent, transform=transform, name=name)
-
- self._sight_lines = tuple()
+ self._observers = tuple()
+ if observers is not None:
+ for observer in observers:
+ self.add_observer(observer)
def __getitem__(self, item):
+ try:
+ selected = self._observers[item]
+ except IndexError:
+ raise IndexError("observer number {} not available in this {} "
+ "with only {} observers.".format(item, self.__class__.__name__, len(self._observers)))
+ except TypeError:
+ if isinstance(item, str):
+ observers = [observer for observer in self._observers if observer.name == item]
+ if len(observers) == 1:
+ return observers[0]
+
+ if len(observers) == 0:
+ raise ValueError("observer '{}' was not found in this {}.".format(item, self.__class__.__name__))
+
+ raise ValueError("Found {} observers with name {} in this {}.".format(len(observers), item, self.__class__.__name__))
+ else:
+ raise TypeError("{} key must be of type int, slice or str.".format(self.__class__.__name__))
+ return selected
- if isinstance(item, int):
- try:
- return self._sight_lines[item]
- except IndexError:
- raise IndexError("Sight-line number {} not available in this {} "
- "with only {} sight-lines.".format(item, self.__class__.__name__, len(self._sight_lines)))
- elif isinstance(item, str):
- sightlines = [sight_line for sight_line in self._sight_lines if sight_line.name == item]
- if len(sightlines) == 1:
- return sightlines[0]
-
- if len(sightlines) == 0:
- raise ValueError("Sight-line '{}' was not found in this {}.".format(item, self.__class__.__name__))
-
- raise ValueError("Found {} sight-lines with name {} in this {}.".format(len(sightlines), item, self.__class__.__name__))
- else:
- raise TypeError("{} key must be of type int or str.".format(self.__class__.__name__))
+ def __len__(self):
+ return len(self._observers)
+
+ @property
+ def observers(self):
+ """
+ A list of all observer object assigned to the group.
+ The group is set as a parent to any added observer.
+
+ :rtype: tuple
+ """
+ return self._observers
+
+ @observers.setter
+ def observers(self, value):
+ if not isinstance(value, (list, tuple)):
+ raise TypeError("The observers attribute must be a list or tuple of {}.".format(self._OBSERVER_TYPE))
+ if not all(isinstance(val, self._OBSERVER_TYPE) for val in value):
+ raise ValueError('All observers assigned to the group must be of type {}'.format(self._OBSERVER_TYPE))
+ for observer in value:
+ observer.parent = self
+ self._observers = tuple(value)
+
+ def add_observer(self, observer):
+ """Adds new observer to the group."""
+ if not isinstance(observer, self._OBSERVER_TYPE):
+ raise ValueError("Can only add {} objects".format(self._OBSERVER_TYPE))
+ observer.parent = self
+ self._observers = self._observers + (observer, )
@property
def names(self):
- # A list of sight-line names.
- return [sight_line.name for sight_line in self._sight_lines]
+ """
+ A list of observer names.
+ """
+ return [observer.name for observer in self._observers]
@names.setter
def names(self, value):
if isinstance(value, (list, tuple)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.name = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.name = v
else:
raise ValueError("The length of 'names' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
raise TypeError("The names attribute must be a list or tuple.")
- @property
- def origin(self):
- # The origin points for the sight lines.
- return [sight_line.origin for sight_line in self._sight_lines]
-
- @origin.setter
- def origin(self, value):
- if isinstance(value, (list, tuple)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.origin = v
- else:
- raise ValueError("The length of 'origin' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
- else:
- for sight_line in self._sight_lines:
- sight_line.origin = value
-
- @property
- def direction(self):
- # The observation directions for the sight lines.
- return [sight_line.direction for sight_line in self._sight_lines]
-
- @direction.setter
- def direction(self, value):
- if isinstance(value, (list, tuple)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.direction = v
- else:
- raise ValueError("The length of 'direction' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
- else:
- for sight_line in self._sight_lines:
- sight_line.direction = value
+ def observe(self):
+ """
+ Starts the observation.
+ """
+ for observer in self._observers:
+ observer.observe()
+ # _ObserverBase attributes and properties
@property
def render_engine(self):
- # Rendering engine used by the sight lines.
- return [sight_line.render_engine for sight_line in self._sight_lines]
+ """
+ Rendering engine used by the observers.
+ :rtype: list
+ """
+ return [observer.render_engine for observer in self._observers]
@render_engine.setter
def render_engine(self, value):
if isinstance(value, (list, tuple)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
if isinstance(v, RenderEngine):
- sight_line.render_engine = v
+ observer.render_engine = v
else:
raise TypeError("The list 'render_engine' must contain only RenderEngine instances.")
else:
raise ValueError("The length of 'render_engine' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
if not isinstance(value, RenderEngine):
raise TypeError("The list 'render_engine' must contain only RenderEngine instances.")
- for sight_line in self._sight_lines:
- sight_line.render_engine = value
-
- @property
- def display_progress(self):
- # Toggles the display of live render progress.
- return [sight_line.display_progress for sight_line in self._sight_lines]
-
- @display_progress.setter
- def display_progress(self, value):
- if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.display_progress = v
- else:
- raise ValueError("The length of 'display_progress' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
- else:
- for sight_line in self._sight_lines:
- sight_line.display_progress = value
+ for observer in self._observers:
+ observer.render_engine = value
@property
- def accumulate(self):
- # Toggles whether to accumulate samples with subsequent calls to observe().
- return [sight_line.accumulate for sight_line in self._sight_lines]
+ def spectral_bins(self):
+ # The number of spectral samples over the wavelength range.
+ return [observer.spectral_bins for observer in self._observers]
- @accumulate.setter
- def accumulate(self, value):
+ @spectral_bins.setter
+ def spectral_bins(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.accumulate = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.spectral_bins = v
else:
- raise ValueError("The length of 'accumulate' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ raise ValueError("The length of 'spectral_bins' ({}) "
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.accumulate = value
+ for observer in self._observers:
+ observer.spectral_bins = value
@property
- def min_wavelength(self):
- # Lower wavelength bound for sampled spectral range.
- return [sight_line.min_wavelength for sight_line in self._sight_lines]
+ def spectral_rays(self):
+ # The number of spectral samples over the wavelength range.
+ return [observer.spectral_rays for observer in self._observers]
- @min_wavelength.setter
- def min_wavelength(self, value):
+ @spectral_rays.setter
+ def spectral_rays(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.min_wavelength = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.spectral_rays = v
else:
- raise ValueError("The length of 'min_wavelength' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ raise ValueError("The length of 'spectral_rays' ({}) "
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.min_wavelength = value
+ for observer in self._observers:
+ observer.spectral_rays = value
@property
def max_wavelength(self):
# Upper wavelength bound for sampled spectral range.
- return [sight_line.max_wavelength for sight_line in self._sight_lines]
+ return [observer.max_wavelength for observer in self._observers]
@max_wavelength.setter
def max_wavelength(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.max_wavelength = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.max_wavelength = v
else:
raise ValueError("The length of 'max_wavelength' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.max_wavelength = value
+ for observer in self._observers:
+ observer.max_wavelength = value
@property
- def spectral_bins(self):
- # The number of spectral samples over the wavelength range.
- return [sight_line.spectral_bins for sight_line in self._sight_lines]
+ def min_wavelength(self):
+ # Lower wavelength bound for sampled spectral range.
+ return [observer.min_wavelength for observer in self._observers]
- @spectral_bins.setter
- def spectral_bins(self, value):
+ @min_wavelength.setter
+ def min_wavelength(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.spectral_bins = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.min_wavelength = v
else:
- raise ValueError("The length of 'spectral_bins' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ raise ValueError("The length of 'min_wavelength' ({}) "
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.spectral_bins = value
+ for observer in self._observers:
+ observer.min_wavelength = value
@property
def ray_extinction_prob(self):
# Probability of ray extinction after every material intersection.
- return [sight_line.ray_extinction_prob for sight_line in self._sight_lines]
+ return [observer.ray_extinction_prob for observer in self._observers]
@ray_extinction_prob.setter
def ray_extinction_prob(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.ray_extinction_prob = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.ray_extinction_prob = v
else:
raise ValueError("The length of 'ray_extinction_prob' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.ray_extinction_prob = value
+ for observer in self._observers:
+ observer.ray_extinction_prob = value
+
+ @property
+ def ray_max_depth(self):
+ # Maximum number of Ray paths before terminating Ray.
+ return [observer.ray_max_depth for observer in self._observers]
+
+ @ray_max_depth.setter
+ def ray_max_depth(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.ray_max_depth = v
+ else:
+ raise ValueError("The length of 'ray_max_depth' ({}) "
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
+ else:
+ for observer in self._observers:
+ observer.ray_max_depth = value
@property
def ray_extinction_min_depth(self):
# Minimum number of paths before russian roulette style ray extinction.
- return [sight_line.ray_extinction_min_depth for sight_line in self._sight_lines]
+ return [observer.ray_extinction_min_depth for observer in self._observers]
@ray_extinction_min_depth.setter
def ray_extinction_min_depth(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.ray_extinction_min_depth = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.ray_extinction_min_depth = v
else:
raise ValueError("The length of 'ray_extinction_min_depth' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.ray_extinction_min_depth = value
+ for observer in self._observers:
+ observer.ray_extinction_min_depth = value
@property
- def ray_max_depth(self):
- # Maximum number of Ray paths before terminating Ray.
- return [sight_line.ray_max_depth for sight_line in self._sight_lines]
+ def ray_importance_sampling(self):
+ # Relative weight of important path sampling.
+ return [observer.ray_importance_sampling for observer in self._observers]
- @ray_max_depth.setter
- def ray_max_depth(self, value):
+ @ray_importance_sampling.setter
+ def ray_importance_sampling(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.ray_max_depth = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.ray_importance_sampling = v
else:
- raise ValueError("The length of 'ray_max_depth' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ raise ValueError("The length of 'ray_importance_sampling' ({}) "
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.ray_max_depth = value
+ for observer in self._observers:
+ observer.ray_importance_sampling = value
@property
def ray_important_path_weight(self):
# Relative weight of important path sampling.
- return [sight_line.ray_important_path_weight for sight_line in self._sight_lines]
+ return [observer.ray_important_path_weight for observer in self._observers]
@ray_important_path_weight.setter
def ray_important_path_weight(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.ray_important_path_weight = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.ray_important_path_weight = v
else:
raise ValueError("The length of 'ray_important_path_weight' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.ray_important_path_weight = value
+ for observer in self._observers:
+ observer.ray_important_path_weight = value
+ @property
+ def quiet(self):
+ return [observer.quiet for observer in self._observers]
+
+ @quiet.setter
+ def quiet(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.quiet = v
+ else:
+ raise ValueError("The length of 'quiet' ({}) "
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
+ else:
+ for observer in self._observers:
+ observer.quiet = value
+
+
+ # Observer0D attributes and properties
@property
def pixel_samples(self):
# The number of samples to take per pixel.
- return [sight_line.pixel_samples for sight_line in self._sight_lines]
+ return [observer.pixel_samples for observer in self._observers]
@pixel_samples.setter
def pixel_samples(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.pixel_samples = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.pixel_samples = v
else:
raise ValueError("The length of 'pixel_samples' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.pixel_samples = value
+ for observer in self._observers:
+ observer.pixel_samples = value
@property
def samples_per_task(self):
# Minimum number of samples to request per task.
- return [sight_line.samples_per_task for sight_line in self._sight_lines]
+ return [observer.samples_per_task for observer in self._observers]
@samples_per_task.setter
def samples_per_task(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.samples_per_task = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.samples_per_task = v
else:
raise ValueError("The length of 'samples_per_task' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.samples_per_task = value
+ for observer in self._observers:
+ observer.samples_per_task = value
@property
def pipelines(self):
- # A list of all pipelines connected to each sight-line in the group.
- return [sight_line.pipelines for sight_line in self._sight_lines]
-
- def connect_pipelines(self, properties=[(SpectralRadiancePipeline0D, None, None)]):
- """
- Connects pipelines of given kinds and names to each sight-line in the group.
- Connected pipelines are non-accumulating by default.
-
- :param list properties: 3-tuple list of pipeline properties in order (class, name, filter).
- Default is [(SpectralRadiancePipeline0D, None, None)].
- The following pipeline classes are supported:
- SpectralRadiacnePipeline0D,
- SpectralPowerPipeline0D,
- RadiacnePipeline0D,
- PowerPipeline0D.
- Filters are applied to the mono pipelines only, namely,
- PowerPipeline0D or RadiacnePipeline0D. The values provided for spectral
- pipelines will be ignored. The filter must be an instance of
- SpectralFunction or None.
-
- """
-
- for sight_line in self._sight_lines:
- sight_line.connect_pipelines(properties)
-
- def observe(self):
- """
- Starts the observation.
"""
- for sight_line in self._sight_lines:
- sight_line.observe()
-
- def _get_same_pipelines(self, item):
- pipelines = []
- sight_lines = []
- for sight_line in self._sight_lines:
- try:
- pipelines.append(sight_line.get_pipeline(item))
- except (ValueError, IndexError):
- continue
- else:
- sight_lines.append(sight_line)
-
- if len(pipelines) == 0:
- raise ValueError("Pipeline {} was not found for any sight-line in this {}.".format((item, self.__class__.__name__)))
-
- pipeline_types = set(type(pipeline) for pipeline in pipelines)
- if len(pipeline_types) > 1:
- raise ValueError("Pipelines {} have different types for different sight-lines.".format(item))
-
- return pipelines, sight_lines
-
- def plot_total_signal(self, item=0, ax=None):
+ A list of all pipelines connected to each observer in the group
+
+ :param list pipelist: list of lists/tuples of already instantiated pipelines
+ :rtype: list
"""
- Plots total (wavelength-integrated) signal for each sight line in the group.
-
- :param str/int item: The index or name of the pipeline. Default: 0.
- :param Axes ax: Existing matplotlib axes.
-
- """
-
- pipelines, sight_lines = self._get_same_pipelines(item)
-
- if ax is None:
- _, ax = plt.subplots(constrained_layout=True)
-
- signal = []
- tick_labels = []
- for pipeline, sight_line in zip(pipelines, sight_lines):
- if isinstance(pipeline, SpectralPowerPipeline0D):
- spectrum = Spectrum(pipeline.min_wavelength, pipeline.max_wavelength, pipeline.bins)
- spectrum.samples = pipeline.samples.mean
- signal.append(spectrum.total())
- else:
- signal.append(pipeline.value.mean)
-
- if sight_line.name and len(sight_line.name):
- tick_labels.append(sight_line.name)
- else:
- tick_labels.append(self._sight_lines.index(sight_line))
+ return [observer.pipelines for observer in self._observers]
- if isinstance(pipeline, (SpectralRadiancePipeline0D, RadiancePipeline0D)):
- ylabel = 'Radiance (W/m^2/str)'
- else: # SpectralPowerPipeline0D or PowerPipeline0D
- ylabel = 'Power (W)'
-
- ax.bar(list(range(len(signal))), signal, tick_label=tick_labels, label=item)
-
- if isinstance(item, int):
- # check if pipelines share the same name
- if len(set(pipeline.name for pipeline in pipelines)) == 1 and pipelines[0].name and len(pipelines[0].name):
- ax.set_title('{}: {}'.format(self.name, pipelines[0].name))
- else:
- # pipelines have different names or name is not set
- ax.set_title('{}: pipeline {}'.format(self.name, item))
- elif isinstance(item, str):
- ax.set_title('{}: {}'.format(self.name, item))
-
- ax.set_ylabel(ylabel)
- ax.set_xlabel('Line of sight')
-
- return ax
+ @pipelines.setter
+ def pipelines(self, pipelist):
+ if len(pipelist) == len(self._observers):
+ for observer, pipelines in zip(self._observers, pipelist):
+ observer.pipelines = pipelines
+ else:
+ raise ValueError('Length of pipelines list do not match number of observers in the group.')
- def plot_spectra(self, item=0, in_photons=False, ax=None):
+ def connect_pipelines(self, pipeline_classes, keywords_list=None, suppress_display_progress=True):
"""
- Plot the spectra observed by each line of sight in the group for a given pipeline.
-
- :param str/int item: The index or name of the pipeline. Default: 0.
- :param bool in_photons: If True, plots the spectrum in photon/s/nm instead of W/nm.
- Default is False.
- :param Axes ax: Existing matplotlib axes.
+ Creates and connects a new set of given pipelines to each observer in the group.
+
+ Pipeline classes are instantiated using parameters specified in appropriate dict from keywords list.
+ If keywords list is provided, it length must match the number of provided pipeline classes.
+
+ :param list pipeline_classes: list of pipeline classes to be connected with observers
+ :param list keywords_list: list of dicts with keywords passed to init methods of pipeline classes
+ its length must match the number of pipeline classes
+ for default parameters place an empty dict to appropriate place in the list
+ :param bool suppress_display_progress: Toggles setting display_progress to False for each compatible pipeline (default=True)
+
+ .. code-block:: pycon
+
+ ...
+ >>> pipelines = [SpectralRadiancePipeline0D, RadiancePipeline0D]
+ >>> keywords = [{'name': 'MySpectralPipeline'}, {}]
+ >>> group.connect_pipelines(pipeline_classes=pipelines, keywords_list=keywords)
+
"""
-
- pipelines, sight_lines = self._get_same_pipelines(item)
-
- if ax is None:
- _, ax = plt.subplots(constrained_layout=True)
-
- for sight_line in sight_lines:
- sight_line.plot_spectrum(item=item, in_photons=in_photons, ax=ax, extras=False)
-
- if isinstance(pipelines[0], SpectralRadiancePipeline0D):
- ylabel = 'Spectral radiance (photon/s/m^2/str/nm)' if in_photons else 'Spectral radiance (W/m^2/str/nm)'
- else: # SpectralPowerPipeline0D
- ylabel = 'Spectral power (photon/s/nm)' if in_photons else 'Spectral power (W/nm)'
-
- if isinstance(item, int):
- # check if pipelines share the same name
- if len(set(pipeline.name for pipeline in pipelines)) == 1 and pipelines[0].name and len(pipelines[0].name):
- ax.set_title('{}: {}'.format(self.name, pipelines[0].name))
- else:
- # pipelines have different names or name is not set
- ax.set_title('{}: pipeline {}'.format(self.name, item))
- elif isinstance(item, str):
- ax.set_title('{}: {}'.format(self.name, item))
-
- ax.set_xlabel('Wavelength (nm)')
- ax.set_ylabel(ylabel)
- ax.legend()
-
- return ax
+ if keywords_list is None:
+ keywords_list = [dict() for ppln in pipeline_classes]
+ if len(pipeline_classes) !=len (keywords_list):
+ raise ValueError('The number of given pipeline classes does not match the number of dicts in keyword list.\
+ For each pipeline class there must be a parameter dict.')
+ for observer in self._observers:
+ pipelines = []
+ for PipelineClass, kwargs in zip(pipeline_classes, keywords_list):
+ pipeline = PipelineClass(**kwargs)
+ if suppress_display_progress:
+ try:
+ pipeline.display_progress = False
+ except AttributeError:
+ pass
+ pipelines.append(pipeline)
+ observer.pipelines = pipelines
+ return
diff --git a/cherab/tools/observers/group/fibreoptic.py b/cherab/tools/observers/group/fibreoptic.py
index ab9e7678..571948f7 100644
--- a/cherab/tools/observers/group/fibreoptic.py
+++ b/cherab/tools/observers/group/fibreoptic.py
@@ -1,4 +1,3 @@
-
# Copyright 2016-2021 Euratom
# Copyright 2016-2021 United Kingdom Atomic Energy Authority
# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
@@ -18,7 +17,8 @@
# under the Licence.
from numpy import ndarray
-from cherab.tools.observers.spectroscopy import SpectroscopicFibreOptic
+from raysect.optical.observer import FibreOptic
+
from .base import Observer0DGroup
@@ -26,117 +26,91 @@ class FibreOpticGroup(Observer0DGroup):
"""
A group of fibre optics under a single scene-graph node.
- A scene-graph object regrouping a series of 'SpectroscopicFibreOptic'
+ A scene-graph object regrouping a series of 'FibreOptic'
observers as a scene-graph parent. Allows combined observation and display
control simultaneously.
- :ivar list sight_lines: A list of fibre optics (SpectroscopicFibreOptic instances) in this
- group.
:ivar list/float acceptance_angle: The angle in degrees between the z axis and the cone
surface which defines the fibres solid angle sampling
- area. The same value can be shared between all sight lines,
- or each sight line can be assigned with individual value.
+ area. The same value can be shared between all observers,
+ or each observer can be assigned with individual value.
:ivar list/float radius: The radius of the fibre tip in metres. This radius defines a circular
area at the fibre tip which will be sampled over. The same value
- can be shared between all sight lines, or each sight line can be
+ can be shared between all observers, or each observer can be
assigned with individual value.
.. code-block:: pycon
>>> from math import cos, sin, pi
- >>> from matplotlib import pyplot as plt
+ >>>
+ >>> import matplotlib.pyplot as plt
+ >>> from raysect.core import translate, rotate_basis, Point3D, Vector3D
>>> from raysect.optical import World
- >>> from raysect.optical.observer import SpectralPowerPipeline0D, PowerPipeline0D
- >>> from raysect.core.math import Point3D, Vector3D
- >>> from cherab.tools.observers import SpectroscopicFibreOptic, FibreOpticGroup
+ >>> from raysect.optical.observer import RadiancePipeline0D, SpectralRadiancePipeline0D, PowerPipeline0D, SpectralPowerPipeline0D, FibreOptic
+ >>>
+ >>> from cherab.tools.observers import FibreOpticGroup
+ >>> from cherab.tools.observers.group.plotting import plot_group_total, plot_group_spectra
>>>
>>> world = World()
- ...
- >>> group = FibreOpticGroup(parent=world)
- >>> group.add_sight_line(SpectroscopicFibreOptic(Point3D(3., 0, 0), Vector3D(-cos(pi/10), 0, sin(pi/10)), name="Fibre 1"))
- >>> group.add_sight_line(SpectroscopicFibreOptic(Point3D(3., 0, 0), Vector3D(-1, 0, 0), name="Fibre 2"))
- >>> group.add_sight_line(SpectroscopicFibreOptic(Point3D(3., 0, 0), Vector3D(-cos(pi/10), 0, -sin(pi/10)), name="Fibre 3"))
- >>> group.connect_pipelines([(SpectralPowerPipeline0D, 'MySpectralPipeline', None),
- (PowerPipeline0D, 'MyMonoPipeline', None)]) # add pipelines to all fibres in the group
+ >>>
+ >>> transform1 = translate(3., 0, 0) * rotate_basis(Vector3D(-cos(pi/10), 0, sin(pi/10)), Vector3D(0, 1, 0))
+ >>> fibre1 = FibreOptic(transform=transform1, name="Fibre 1")
+ >>> transform2 = translate(3, 0 ,0) * rotate_basis(Vector3D(-1, 0, 0), Vector3D(0, 1, 0))
+ >>> fibre2 = FibreOptic(transform=transform2, name="Fibre 2")
+ >>> transform3 = translate(3, 0, 0) * rotate_basis(Vector3D(-cos(pi/10), 0, -sin(pi/10)), Vector3D(0, 1, 0))
+ >>> fibre3 = FibreOptic(transform=transform3, name="Fibre 3")
+ >>>
+ >>> group = FibreOpticGroup(name='MyFibreGroup', parent=world, observers=[fibre1, fibre2])
+ >>> group.add_observer(fibre3)
+ >>> pipelines = [SpectralRadiancePipeline0D, RadiancePipeline0D]
+ >>> keywords = [{'name': 'MySpectralPipeline'}, {'name': 'MyMonoPipeline'}]
+ >>> group.connect_pipelines(pipelines, keywords) # add pipelines to all observers in the group
>>> group.acceptance_angle = 2 # same value for all fibres in the group
>>> group.radius = 2.e-3
>>> group.spectral_bins = 512
>>> group.pixel_samples = [2000, 1000, 2000] # individual value for each fibre in the group
- >>> group.display_progress = False # control pipeline parameters through the group observer
>>> group.observe() # combined observation
- >>> group.plot_spectra(item='MySpectralPipeline', in_photons=True) # plot the spectra
- >>> group.plot_total_signal(item='MyMonoPipeline') # plot the total signals
+ >>>
+ >>> plot_group_spectra(group, item='MySpectralPipeline', in_photons=True) # plot the spectra
+ >>> plot_group_total(group, item='MyMonoPipeline') # plot the total signals
>>> plt.show()
"""
-
- @property
- def sight_lines(self):
- return self._sight_lines
-
- @sight_lines.setter
- def sight_lines(self, value):
-
- if not isinstance(value, (list, tuple)):
- raise TypeError("The sight_lines attribute of FibreOpticGroup must be a list or tuple of SpectroscopicFibreOptics.")
-
- for sight_line in value:
- if not isinstance(sight_line, SpectroscopicFibreOptic):
- raise TypeError("The sight_lines attribute of FibreOpticGroup must be a list or tuple of "
- "SpectroscopicFibreOptics. Value {} is not a SpectroscopicFibreOptic.".format(sight_line))
-
- # Prevent external changes being made to this list
- for sight_line in value:
- sight_line.parent = self
-
- self._sight_lines = tuple(value)
-
- def add_sight_line(self, sight_line):
- """
- Adds new fibre optic to the group.
-
- :param SpectroscopicFibreOptic sight_line: Fibre optic to add.
- """
-
- if not isinstance(sight_line, SpectroscopicFibreOptic):
- raise TypeError("The sightline argument must be of type SpectroscopicFibreOptic.")
-
- sight_line.parent = self
- self._sight_lines = self._sight_lines + (sight_line,)
+ _OBSERVER_TYPE = FibreOptic
@property
def acceptance_angle(self):
# The angle in degrees between the z axis and the cone surface which defines the fibres
# solid angle sampling area.
- return [sight_line.acceptance_angle for sight_line in self._sight_lines]
+ return [observer.acceptance_angle for observer in self._observers]
@acceptance_angle.setter
def acceptance_angle(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.acceptance_angle = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.acceptance_angle = v
else:
raise ValueError("The length of 'acceptance_angle' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.acceptance_angle = value
+ for observer in self._observers:
+ observer.acceptance_angle = value
@property
def radius(self):
# The radius of the fibre tip in metres. This radius defines a circular area at the fibre tip
# which will be sampled over.
- return [sight_line.radius for sight_line in self._sight_lines]
+ return [observer.radius for observer in self._observers]
@radius.setter
def radius(self, value):
if isinstance(value, (list, tuple, ndarray)):
- if len(value) == len(self._sight_lines):
- for sight_line, v in zip(self._sight_lines, value):
- sight_line.radius = v
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.radius = v
else:
raise ValueError("The length of 'radius' ({}) "
- "mismatches the number of sight-lines ({}).".format(len(value), len(self._sight_lines)))
+ "mismatches the number of observers ({}).".format(len(value), len(self._observers)))
else:
- for sight_line in self._sight_lines:
- sight_line.radius = value
+ for observer in self._observers:
+ observer.radius = value
diff --git a/cherab/tools/observers/group/pixel.py b/cherab/tools/observers/group/pixel.py
new file mode 100644
index 00000000..c8979d22
--- /dev/null
+++ b/cherab/tools/observers/group/pixel.py
@@ -0,0 +1,70 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+from numpy import ndarray
+from raysect.optical.observer import Pixel
+
+from .base import Observer0DGroup
+
+
+class PixelGroup(Observer0DGroup):
+ """
+ A group of pixels under a single scene-graph node.
+
+ A scene-graph object regrouping a series of 'Pixel'
+ observers as a scene-graph parent. Allows combined observation and display
+ control simultaneously.
+
+ :ivar list x_width: Width of pixel along local x axis
+ :ivar list y_width: Width of pixel along local y axis
+ """
+ _OBSERVER_TYPE = Pixel
+
+ @property
+ def x_width(self):
+ return [pixel.x_width for pixel in self._observers]
+
+ @x_width.setter
+ def x_width(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for pixel, v in zip(self._observers, value):
+ pixel.x_width = v
+ else:
+ raise ValueError("The length of 'x_width' ({}) "
+ "mismatches the number of pixels ({}).".format(len(value), len(self._observers)))
+ else:
+ for pixel in self._observers:
+ pixel.x_width = value
+
+ @property
+ def y_width(self):
+ return [pixel.y_width for pixel in self._observers]
+
+ @y_width.setter
+ def y_width(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for pixel, v in zip(self._observers, value):
+ pixel.y_width = v
+ else:
+ raise ValueError("The length of 'y_width' ({}) "
+ "mismatches the number of pixels ({}).".format(len(value), len(self._observers)))
+ else:
+ for pixel in self._observers:
+ pixel.y_width = value
diff --git a/cherab/tools/observers/group/plotting.py b/cherab/tools/observers/group/plotting.py
new file mode 100644
index 00000000..097d52fa
--- /dev/null
+++ b/cherab/tools/observers/group/plotting.py
@@ -0,0 +1,170 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+import warnings
+
+import matplotlib.pyplot as plt
+from raysect.optical import Spectrum
+from raysect.optical.observer import RadiancePipeline0D, PowerPipeline0D, SpectralRadiancePipeline0D, SpectralPowerPipeline0D
+
+
+def select_pipelines(group, item):
+ """
+ Selects pipelines of the same type based on index or name from the provided group.
+
+ If name is used, error is raised when more than one pipeline is found in an observer.
+ An ValueError is also raised if found pipelines are not of the same type.
+
+ :param Observer0DGroup group: Observer group from which to select pipelines.
+ :param str/int item: The index or name of the pipeline to be selected.
+ :return list pipelines: matching pipelines
+ :return list observers: observers with matching pipelines
+ """
+ pipelines = []
+ observers = []
+ for observer in group.observers:
+ if isinstance(item, int):
+ try:
+ pipelines.append(observer.pipelines[item])
+ observers.append(observer)
+ except IndexError:
+ warnings.warn('Invalid pipeline index {} for observer {} with {} pipelines'.format(
+ item, observer, len(observer.pipelines)))
+ elif isinstance(item, str):
+ matching_pipelines = [pipeline for pipeline in observer.pipelines if pipeline.name == item]
+ pipelines_num = len(matching_pipelines)
+ if pipelines_num == 0:
+ warnings.warn('Found no matching pipelines for name {} in observer {}'.format(item, observer))
+ elif pipelines_num == 1:
+ pipelines.append(matching_pipelines[0])
+ observers.append(observer)
+ else:
+ raise ValueError("Found {} matching pipelines for name {} in observer {}.".format(
+ pipelines_num, item, observer))
+
+ pipeline_types = set(type(pipeline) for pipeline in pipelines)
+ if len(pipeline_types) > 1:
+ raise ValueError("Pipelines {} have different types for different observers.".format(item))
+
+ return pipelines, observers
+
+
+def plot_group_total(group, item=0, ax=None):
+ """
+ Plots total (wavelength-integrated) signal for each observer in the group.
+
+ :param Observer0DGroup group: Group class with observers hodling data to be plotted.
+ :param str/int item: The index or name of the pipeline. Default: 0.
+ :param Axes ax: Existing matplotlib axes.
+ :return Axes ax: Matplotlib axes with plotted spectra
+ """
+ pipelines, observers = select_pipelines(group, item)
+
+ if ax is None:
+ _, ax = plt.subplots(constrained_layout=True)
+
+ signal = []
+ tick_labels = []
+ for pipeline, observer in zip(pipelines, observers):
+ if isinstance(pipeline, SpectralPowerPipeline0D):
+ spectrum = Spectrum(pipeline.min_wavelength, pipeline.max_wavelength, pipeline.bins)
+ spectrum.samples[:] = pipeline.samples.mean
+ signal.append(spectrum.total())
+ else:
+ signal.append(pipeline.value.mean)
+
+ if observer.name and len(observer.name):
+ tick_labels.append(observer.name)
+ else:
+ tick_labels.append(group.observers.index(observer))
+
+ if isinstance(pipeline, (SpectralRadiancePipeline0D, RadiancePipeline0D)):
+ ylabel = 'Radiance [W/m^2/str]'
+ else: # SpectralPowerPipeline0D or PowerPipeline0D
+ ylabel = 'Power [W]'
+
+ ax.bar(list(range(len(signal))), signal, tick_label=tick_labels, label=item)
+
+ if isinstance(item, int):
+ # check if pipelines share the same name
+ if len(set(pipeline.name for pipeline in pipelines)) == 1 and pipelines[0].name and len(pipelines[0].name):
+ ax.set_title('{}: {}'.format(group.name, pipelines[0].name))
+ else:
+ # pipelines have different names or name is not set
+ ax.set_title('{}: pipeline {}'.format(group.name, item))
+ elif isinstance(item, str):
+ ax.set_title('{}: {}'.format(group.name, item))
+
+ ax.set_ylabel(ylabel)
+ ax.set_xlabel('Observer')
+
+ return ax
+
+
+def plot_group_spectra(group, item=0, in_photons=False, ax=None):
+ """
+ Plot the spectra observed by each observer in the group for a given pipeline.
+
+ :param Observer0DGroup group: Group class with observers hodling data to be plotted.
+ :param str/int item: The index or name of the pipeline. Default: 0.
+ :param bool in_photons: If True, plots the spectrum in photon/s/nm instead of W/nm.
+ Default is False.
+ :param Axes ax: Existing matplotlib axes.
+ :return Axes ax: Matplotlib axes with plotted spectra
+ """
+ pipelines, observers = select_pipelines(group, item)
+
+ if ax is None:
+ _, ax = plt.subplots(constrained_layout=True)
+
+ for pipeline, observer in zip(pipelines, observers):
+ spectrum_observed = Spectrum(pipeline.min_wavelength, pipeline.max_wavelength, pipeline.bins)
+ spectrum_observed.samples[:] = pipeline.samples.mean
+ if in_photons:
+ # turn the samples into photon/s
+ spectrum = spectrum_observed.new_spectrum()
+ spectrum.samples[:] = spectrum_observed.to_photons()
+ else:
+ spectrum = spectrum_observed
+
+ label = observer.name if observer.name and len(observer.name) else group.observers.index(observer)
+
+ if spectrum.samples.size > 1:
+ ax.plot(spectrum.wavelengths, spectrum.samples, label=label)
+ else:
+ ax.plot(spectrum.wavelengths, spectrum.samples, marker='o', ls='none', label=label)
+ if isinstance(pipelines[0], SpectralRadiancePipeline0D):
+ ylabel = 'Spectral radiance [photon/s/m^2/str/nm]' if in_photons else 'Spectral radiance [W/m^2/str/nm]'
+ else: # SpectralPowerPipeline0D
+ ylabel = 'Spectral power [photon/s/nm]' if in_photons else 'Spectral power [W/nm]'
+
+ if isinstance(item, int):
+ # check if pipelines share the same name
+ if len(set(pipeline.name for pipeline in pipelines)) == 1 and pipelines[0].name and len(pipelines[0].name):
+ ax.set_title('{}: {}'.format(group.name, pipelines[0].name))
+ else:
+ # pipelines have different names or name is not set
+ ax.set_title('{}: pipeline {}'.format(group.name, item))
+ elif isinstance(item, str):
+ ax.set_title('{}: {}'.format(group.name, item))
+
+ ax.set_xlabel('Wavelength [nm]')
+ ax.set_ylabel(ylabel)
+ ax.legend()
+
+ return ax
\ No newline at end of file
diff --git a/cherab/tools/observers/group/sightline.py b/cherab/tools/observers/group/sightline.py
index 14e026cb..94f3cddc 100644
--- a/cherab/tools/observers/group/sightline.py
+++ b/cherab/tools/observers/group/sightline.py
@@ -1,4 +1,3 @@
-
# Copyright 2016-2021 Euratom
# Copyright 2016-2021 United Kingdom Atomic Energy Authority
# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
@@ -17,77 +16,74 @@
# See the Licence for the specific language governing permissions and limitations
# under the Licence.
-from cherab.tools.observers.spectroscopy import SpectroscopicSightLine
+from numpy import ndarray
+from raysect.optical.observer import SightLine
+
from .base import Observer0DGroup
class SightLineGroup(Observer0DGroup):
"""
- A group of spectroscopic sight-lines under a single scene-graph node.
+ A group of SightLine under a single scene-graph node.
- A scene-graph object regrouping a series of 'SpectroscopicSightLine'
+ A scene-graph object regrouping a series of 'SightLine'
observers as a scene-graph parent. Allows combined observation and display
control simultaneously.
- :ivar list sight_lines: A list of lines of sight (SpectroscopicSightLine instances)
- in this group.
+ :ivar list observers: A list of sight lines (SightLine instances) in this group.
.. code-block:: pycon
>>> from math import cos, sin, pi
- >>> from matplotlib import pyplot as plt
+ >>>
+ >>> import matplotlib.pyplot as plt
+ >>> from raysect.core import translate, rotate_basis, Point3D, Vector3D
>>> from raysect.optical import World
- >>> from raysect.optical.observer import SpectralRadiancePipeline0D, RadiancePipeline0D
- >>> from raysect.core.math import Point3D, Vector3D
- >>> from cherab.tools.observers import SpectroscopicSightLine, SightLineGroup
+ >>> from raysect.optical.observer import RadiancePipeline0D, SpectralRadiancePipeline0D, PowerPipeline0D, SpectralPowerPipeline0D, SightLine
+ >>>
+ >>> from cherab.tools.observers import SightLineGroup
+ >>> from cherab.tools.observers.group.plotting import plot_group_total, plot_group_spectra
>>>
>>> world = World()
- ...
- >>> group = SightLineGroup(parent=world)
- >>> group.add_sight_line(SpectroscopicSightLine(Point3D(3., 0, 0), Vector3D(-cos(pi/10), 0, sin(pi/10)), name="SightLine 1"))
- >>> group.add_sight_line(SpectroscopicSightLine(Point3D(3., 0, 0), Vector3D(-1, 0, 0), name="SightLine 2"))
- >>> group.add_sight_line(SpectroscopicSightLine(Point3D(3., 0, 0), Vector3D(-cos(pi/10), 0, -sin(pi/10)), name="SightLine 3"))
- >>> group.connect_pipelines([(SpectralRadiancePipeline0D, 'MySpectralPipeline', None),
- (RadiancePipeline0D, 'MyMonoPipeline', None)]) # add pipelines to all sight lines in the group
- >>> group.spectral_bins = 512 # same value for all sight lines in the group
- >>> group.pixel_samples = [2000, 1000, 2000] # individual value for each sight line in the group
- >>> group.display_progress = False # control pipeline parameters through the group observer
+ >>>
+ >>> transform1 = translate(3., 0, 0) * rotate_basis(Vector3D(-cos(pi/10), 0, sin(pi/10)), Vector3D(0, 1, 0))
+ >>> sightline_1 = SightLine(transform=transform1, name="SightLine 1")
+ >>> transform2 = translate(3, 0 ,0) * rotate_basis(Vector3D(-1, 0, 0), Vector3D(0, 1, 0))
+ >>> sightline_2 = SightLine(transform=transform2, name="SightLine 2")
+ >>> transform3 = translate(3, 0, 0) * rotate_basis(Vector3D(-cos(pi/10), 0, -sin(pi/10)), Vector3D(0, 1, 0))
+ >>> sightline_3 = SightLine(transform=transform3, name="SightLine 3")
+ >>>
+ >>> group = SightLineGroup(name='MySightLineGroup', parent=world, observers=[sightline_1, sightline_2])
+ >>> group.add_observer(sightline_3)
+ >>> pipelines = [SpectralRadiancePipeline0D, RadiancePipeline0D]
+ >>> keywords = [{'name': 'MySpectralPipeline'}, {'name': 'MyMonoPipeline'}]
+ >>> group.connect_pipelines(pipelines, keywords) # add pipelines to all observers in the group
+ >>> group.acceptance_angle = 2 # same value for all sightlines in the group
+ >>> group.radius = 2.e-3
+ >>> group.spectral_bins = 512
+ >>> group.pixel_samples = [2000, 1000, 2000] # individual value for each sightline in the group
>>> group.observe() # combined observation
- >>> group.plot_spectra(item='MySpectralPipeline', in_photons=True) # plot the spectra
- >>> group.plot_total_signal(item='MyMonoPipeline') # plot the total signals
+ >>>
+ >>> plot_group_spectra(group, item='MySpectralPipeline', in_photons=True) # plot the spectra
+ >>> plot_group_total(group, item='MyMonoPipeline') # plot the total signals
>>> plt.show()
"""
+ _OBSERVER_TYPE = SightLine
@property
- def sight_lines(self):
- return self._sight_lines
-
- @sight_lines.setter
- def sight_lines(self, value):
-
- if not isinstance(value, (list, tuple)):
- raise TypeError("The sight_lines attribute of LineOfSightGroup must be a list or tuple of SpectroscopicSightLines.")
-
- for sight_line in value:
- if not isinstance(sight_line, SpectroscopicSightLine):
- raise TypeError("The sight_lines attribute of LineOfSightGroup must be a list or tuple of "
- "SpectroscopicSightLines. Value {} is not a SpectroscopicSightLine.".format(sight_line))
-
- # Prevent external changes being made to this list
- for sight_line in value:
- sight_line.parent = self
-
- self._sight_lines = tuple(value)
-
- def add_sight_line(self, sight_line):
- """
- Adds new line of sight to the group.
-
- :param SpectroscopicSightLine sight_line: Sight line to add.
- """
-
- if not isinstance(sight_line, SpectroscopicSightLine):
- raise TypeError("The sight_line argument must be of type SpectroscopicSightLine.")
-
- sight_line.parent = self
- self._sight_lines = self._sight_lines + (sight_line,)
+ def sensitivity(self):
+ # A list of observer sensitivities.
+ return [observer.sensitivity for observer in self._observers]
+
+ @sensitivity.setter
+ def sensitivity(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.sensitivity = v
+ else:
+ raise ValueError("The length of 'sensitivity' ({}) ".format(len(value)) +
+ "mismatches the number of observers ({}).".format(len(self._observers)))
+ else:
+ for observer in self._observers:
+ observer.sensitivity = value
diff --git a/cherab/tools/observers/group/spectroscopic.py b/cherab/tools/observers/group/spectroscopic.py
new file mode 100644
index 00000000..0f20eff9
--- /dev/null
+++ b/cherab/tools/observers/group/spectroscopic.py
@@ -0,0 +1,420 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+import matplotlib.pyplot as plt
+from numpy import ndarray
+from raysect.optical import Spectrum
+from raysect.optical.observer import SpectralRadiancePipeline0D, SpectralPowerPipeline0D, RadiancePipeline0D
+
+from .base import Observer0DGroup
+from cherab.tools.observers.spectroscopy import SpectroscopicFibreOptic, SpectroscopicSightLine
+
+
+class SpectroscopicObserver0DGroup(Observer0DGroup):
+ """
+ .. deprecated:: 1.4.0
+ Use SightLineGroup or FibreOpticGroup based on Raysect's observers instead.
+
+ A base class for a group of 0D spectroscopic observers under a single scene-graph node.
+
+ A scene-graph object regrouping a series of observers as a scene-graph parent.
+ Allows combined observation and display control simultaneously.
+ Note that for any property except `names` and `pipelines`, the same value can be shared between
+ all sight lines, or each sight line can be assigned with individual value.
+
+ :ivar list/Point3D origin: The origin points for the sight lines.
+ :ivar list/Vector3D direction: The observation directions for the sight lines.
+ :ivar list/bool display_progress: Toggles the display of live render progress.
+ :ivar list/bool accumulate: Toggles whether to accumulate samples with subsequent
+ observations.
+ """
+
+ def __init__(self, parent=None, transform=None, name=None, observers=None):
+ super().__init__(parent=parent, transform=transform, name=name, observers=observers)
+
+ @property
+ def sight_lines(self):
+ return self._observers
+
+ @sight_lines.setter
+ def sight_lines(self, value):
+ self.observers = value
+
+ def add_sight_line(self, sight_line):
+ """
+ Adds new fibre optic to the group.
+
+ :param SpectroscopicFibreOptic sight_line: Fibre optic to add.
+ """
+ self.add_observer(sight_line)
+
+ @property
+ def origin(self):
+ # The origin points for the sight lines.
+ return [sight_line.origin for sight_line in self._observers]
+
+ @origin.setter
+ def origin(self, value):
+ if isinstance(value, (list, tuple)):
+ if len(value) == len(self._observers):
+ for sight_line, v in zip(self._observers, value):
+ sight_line.origin = v
+ else:
+ raise ValueError("The length of 'origin' ({}) "
+ "mismatches the number of sight-lines ({}).".format(len(value), len(self._observers)))
+ else:
+ for sight_line in self._observers:
+ sight_line.origin = value
+
+ @property
+ def direction(self):
+ # The observation directions for the sight lines.
+ return [sight_line.direction for sight_line in self._observers]
+
+ @direction.setter
+ def direction(self, value):
+ if isinstance(value, (list, tuple)):
+ if len(value) == len(self._observers):
+ for sight_line, v in zip(self._observers, value):
+ sight_line.direction = v
+ else:
+ raise ValueError("The length of 'direction' ({}) "
+ "mismatches the number of sight-lines ({}).".format(len(value), len(self._observers)))
+ else:
+ for sight_line in self._observers:
+ sight_line.direction = value
+
+
+ @property
+ def display_progress(self):
+ # Toggles the display of live render progress.
+ return [observer.display_progress for observer in self._observers]
+
+ @display_progress.setter
+ def display_progress(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.display_progress = v
+ else:
+ raise ValueError("The length of 'display_progress' ({}) "
+ "mismatches the number of sight-lines ({}).".format(len(value), len(self._observers)))
+ else:
+ for observer in self._observers:
+ observer.display_progress = value
+
+ @property
+ def accumulate(self):
+ # Toggles whether to accumulate samples with subsequent calls to observe().
+ return [observer.accumulate for observer in self._observers]
+
+ @accumulate.setter
+ def accumulate(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.accumulate = v
+ else:
+ raise ValueError("The length of 'accumulate' ({}) "
+ "mismatches the number of sight-lines ({}).".format(len(value), len(self._observers)))
+ else:
+ for observer in self._observers:
+ observer.accumulate = value
+
+
+ def connect_pipelines(self, properties=[(SpectralRadiancePipeline0D, None, None)]):
+ """
+ Connects pipelines of given kinds and names to each sight-line in the group.
+ Connected pipelines are non-accumulating by default.
+
+ :param list properties: 3-tuple list of pipeline properties in order (class, name, filter).
+ Default is [(SpectralRadiancePipeline0D, None, None)].
+ The following pipeline classes are supported:
+ SpectralRadiacnePipeline0D,
+ SpectralPowerPipeline0D,
+ RadiacnePipeline0D,
+ PowerPipeline0D.
+ Filters are applied to the mono pipelines only, namely,
+ PowerPipeline0D or RadiacnePipeline0D. The values provided for spectral
+ pipelines will be ignored. The filter must be an instance of
+ SpectralFunction or None.
+
+ """
+
+ for sight_line in self._observers:
+ sight_line.connect_pipelines(properties)
+
+ def _get_same_pipelines(self, item):
+ pipelines = []
+ sight_lines = []
+ for sight_line in self._observers:
+ try:
+ pipelines.append(sight_line.get_pipeline(item))
+ except (ValueError, IndexError):
+ continue
+ else:
+ sight_lines.append(sight_line)
+
+ if len(pipelines) == 0:
+ raise ValueError("Pipeline {} was not found for any sight-line in this {}.".format((item, self.__class__.__name__)))
+
+ pipeline_types = set(type(pipeline) for pipeline in pipelines)
+ if len(pipeline_types) > 1:
+ raise ValueError("Pipelines {} have different types for different sight-lines.".format(item))
+
+ return pipelines, sight_lines
+
+ def plot_total_signal(self, item=0, ax=None):
+ """
+ Plots total (wavelength-integrated) signal for each sight line in the group.
+
+ :param str/int item: The index or name of the pipeline. Default: 0.
+ :param Axes ax: Existing matplotlib axes.
+
+ """
+
+ pipelines, sight_lines = self._get_same_pipelines(item)
+
+ if ax is None:
+ _, ax = plt.subplots(constrained_layout=True)
+
+ signal = []
+ tick_labels = []
+ for pipeline, sight_line in zip(pipelines, sight_lines):
+ if isinstance(pipeline, SpectralPowerPipeline0D):
+ spectrum = Spectrum(pipeline.min_wavelength, pipeline.max_wavelength, pipeline.bins)
+ spectrum.samples = pipeline.samples.mean
+ signal.append(spectrum.total())
+ else:
+ signal.append(pipeline.value.mean)
+
+ if sight_line.name and len(sight_line.name):
+ tick_labels.append(sight_line.name)
+ else:
+ tick_labels.append(self._observers.index(sight_line))
+
+ if isinstance(pipeline, (SpectralRadiancePipeline0D, RadiancePipeline0D)):
+ ylabel = 'Radiance (W/m^2/str)'
+ else: # SpectralPowerPipeline0D or PowerPipeline0D
+ ylabel = 'Power (W)'
+
+ ax.bar(list(range(len(signal))), signal, tick_label=tick_labels, label=item)
+
+ if isinstance(item, int):
+ # check if pipelines share the same name
+ if len(set(pipeline.name for pipeline in pipelines)) == 1 and pipelines[0].name and len(pipelines[0].name):
+ ax.set_title('{}: {}'.format(self.name, pipelines[0].name))
+ else:
+ # pipelines have different names or name is not set
+ ax.set_title('{}: pipeline {}'.format(self.name, item))
+ elif isinstance(item, str):
+ ax.set_title('{}: {}'.format(self.name, item))
+
+ ax.set_ylabel(ylabel)
+ ax.set_xlabel('Line of sight')
+
+ return ax
+
+ def plot_spectra(self, item=0, in_photons=False, ax=None):
+ """
+ Plot the spectra observed by each line of sight in the group for a given pipeline.
+
+ :param str/int item: The index or name of the pipeline. Default: 0.
+ :param bool in_photons: If True, plots the spectrum in photon/s/nm instead of W/nm.
+ Default is False.
+ :param Axes ax: Existing matplotlib axes.
+ """
+
+ pipelines, sight_lines = self._get_same_pipelines(item)
+
+ if ax is None:
+ _, ax = plt.subplots(constrained_layout=True)
+
+ for sight_line in sight_lines:
+ sight_line.plot_spectrum(item=item, in_photons=in_photons, ax=ax, extras=False)
+
+ if isinstance(pipelines[0], SpectralRadiancePipeline0D):
+ ylabel = 'Spectral radiance (photon/s/m^2/str/nm)' if in_photons else 'Spectral radiance (W/m^2/str/nm)'
+ else: # SpectralPowerPipeline0D
+ ylabel = 'Spectral power (photon/s/nm)' if in_photons else 'Spectral power (W/nm)'
+
+ if isinstance(item, int):
+ # check if pipelines share the same name
+ if len(set(pipeline.name for pipeline in pipelines)) == 1 and pipelines[0].name and len(pipelines[0].name):
+ ax.set_title('{}: {}'.format(self.name, pipelines[0].name))
+ else:
+ # pipelines have different names or name is not set
+ ax.set_title('{}: pipeline {}'.format(self.name, item))
+ elif isinstance(item, str):
+ ax.set_title('{}: {}'.format(self.name, item))
+
+ ax.set_xlabel('Wavelength (nm)')
+ ax.set_ylabel(ylabel)
+ ax.legend()
+
+ return ax
+
+
+class SpectroscopicFibreOpticGroup(SpectroscopicObserver0DGroup):
+ """
+ .. deprecated:: 1.4.0
+ Use FibreOpticGroup based on Raysect's FibreOptic observer instead.
+
+ A group of fibre optics under a single scene-graph node.
+
+ A scene-graph object regrouping a series of 'SpectroscopicFibreOptic'
+ observers as a scene-graph parent. Allows combined observation and display
+ control simultaneously.
+
+ :ivar list sight_lines: A list of fibre optics (SpectroscopicFibreOptic instances) in this
+ group.
+ :ivar list/float acceptance_angle: The angle in degrees between the z axis and the cone
+ surface which defines the fibres solid angle sampling
+ area. The same value can be shared between all sight lines,
+ or each sight line can be assigned with individual value.
+ :ivar list/float radius: The radius of the fibre tip in metres. This radius defines a circular
+ area at the fibre tip which will be sampled over. The same value
+ can be shared between all sight lines, or each sight line can be
+ assigned with individual value.
+
+ .. code-block:: pycon
+
+ >>> from math import cos, sin, pi
+ >>> from matplotlib import pyplot as plt
+ >>> from raysect.optical import World
+ >>> from raysect.optical.observer import SpectralPowerPipeline0D, PowerPipeline0D
+ >>> from raysect.core.math import Point3D, Vector3D
+ >>> from cherab.tools.observers import SpectroscopicFibreOptic, FibreOpticGroup
+ >>>
+ >>> world = World()
+ ...
+ >>> group = FibreOpticGroup(parent=world)
+ >>> group.add_sight_line(SpectroscopicFibreOptic(Point3D(3., 0, 0), Vector3D(-cos(pi/10), 0, sin(pi/10)), name="Fibre 1"))
+ >>> group.add_sight_line(SpectroscopicFibreOptic(Point3D(3., 0, 0), Vector3D(-1, 0, 0), name="Fibre 2"))
+ >>> group.add_sight_line(SpectroscopicFibreOptic(Point3D(3., 0, 0), Vector3D(-cos(pi/10), 0, -sin(pi/10)), name="Fibre 3"))
+ >>> group.connect_pipelines([(SpectralPowerPipeline0D, 'MySpectralPipeline', None),
+ (PowerPipeline0D, 'MyMonoPipeline', None)]) # add pipelines to all fibres in the group
+ >>> group.acceptance_angle = 2 # same value for all fibres in the group
+ >>> group.radius = 2.e-3
+ >>> group.spectral_bins = 512
+ >>> group.pixel_samples = [2000, 1000, 2000] # individual value for each fibre in the group
+ >>> group.display_progress = False # control pipeline parameters through the group observer
+ >>> group.observe() # combined observation
+ >>> group.plot_spectra(item='MySpectralPipeline', in_photons=True) # plot the spectra
+ >>> group.plot_total_signal(item='MyMonoPipeline') # plot the total signals
+ >>> plt.show()
+ """
+ _OBSERVER_TYPE = SpectroscopicFibreOptic
+
+ @property
+ def acceptance_angle(self):
+ # The angle in degrees between the z axis and the cone surface which defines the fibres
+ # solid angle sampling area.
+ return [sight_line.acceptance_angle for sight_line in self._observers]
+
+ @acceptance_angle.setter
+ def acceptance_angle(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for sight_line, v in zip(self._observers, value):
+ sight_line.acceptance_angle = v
+ else:
+ raise ValueError("The length of 'acceptance_angle' ({}) "
+ "mismatches the number of sight-lines ({}).".format(len(value), len(self._observers)))
+ else:
+ for sight_line in self._observers:
+ sight_line.acceptance_angle = value
+
+ @property
+ def radius(self):
+ # The radius of the fibre tip in metres. This radius defines a circular area at the fibre tip
+ # which will be sampled over.
+ return [sight_line.radius for sight_line in self._observers]
+
+ @radius.setter
+ def radius(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for sight_line, v in zip(self._observers, value):
+ sight_line.radius = v
+ else:
+ raise ValueError("The length of 'radius' ({}) "
+ "mismatches the number of sight-lines ({}).".format(len(value), len(self._observers)))
+ else:
+ for sight_line in self._observers:
+ sight_line.radius = value
+
+
+class SpectroscopicSightLineGroup(SpectroscopicObserver0DGroup):
+ """
+ .. deprecated:: 1.4.0
+ Use SightLineGroup based on Raysect's SightLine observer instead.
+
+ A group of spectroscopic sight-lines under a single scene-graph node.
+
+ A scene-graph object regrouping a series of 'SpectroscopicSightLine'
+ observers as a scene-graph parent. Allows combined observation and display
+ control simultaneously.
+
+ :ivar list sight_lines: A list of lines of sight (SpectroscopicSightLine instances)
+ in this group.
+
+ .. code-block:: pycon
+
+ >>> from math import cos, sin, pi
+ >>> from matplotlib import pyplot as plt
+ >>> from raysect.optical import World
+ >>> from raysect.optical.observer import SpectralRadiancePipeline0D, RadiancePipeline0D
+ >>> from raysect.core.math import Point3D, Vector3D
+ >>> from cherab.tools.observers import SpectroscopicSightLine, SightLineGroup
+ >>>
+ >>> world = World()
+ ...
+ >>> group = SightLineGroup(parent=world)
+ >>> group.add_sight_line(SpectroscopicSightLine(Point3D(3., 0, 0), Vector3D(-cos(pi/10), 0, sin(pi/10)), name="SightLine 1"))
+ >>> group.add_sight_line(SpectroscopicSightLine(Point3D(3., 0, 0), Vector3D(-1, 0, 0), name="SightLine 2"))
+ >>> group.add_sight_line(SpectroscopicSightLine(Point3D(3., 0, 0), Vector3D(-cos(pi/10), 0, -sin(pi/10)), name="SightLine 3"))
+ >>> group.connect_pipelines([(SpectralRadiancePipeline0D, 'MySpectralPipeline', None),
+ (RadiancePipeline0D, 'MyMonoPipeline', None)]) # add pipelines to all sight lines in the group
+ >>> group.spectral_bins = 512 # same value for all sight lines in the group
+ >>> group.pixel_samples = [2000, 1000, 2000] # individual value for each sight line in the group
+ >>> group.display_progress = False # control pipeline parameters through the group observer
+ >>> group.observe() # combined observation
+ >>> group.plot_spectra(item='MySpectralPipeline', in_photons=True) # plot the spectra
+ >>> group.plot_total_signal(item='MyMonoPipeline') # plot the total signals
+ >>> plt.show()
+ """
+ _OBSERVER_TYPE = SpectroscopicSightLine
+
+ @property
+ def sensitivity(self):
+ # A list of observer sensitivities.
+ return [observer.sensitivity for observer in self._observers]
+
+ @sensitivity.setter
+ def names(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for observer, v in zip(self._observers, value):
+ observer.sensitivity = v
+ else:
+ raise ValueError("The length of 'sensitivity' ({}) ".format(len(value)) +
+ "mismatches the number of observers ({}).".format(len(self._observers)))
+ else:
+ for observer in self._observers:
+ observer.sensitivity = value
diff --git a/cherab/tools/observers/group/targettedpixel.py b/cherab/tools/observers/group/targettedpixel.py
new file mode 100644
index 00000000..07d13e7f
--- /dev/null
+++ b/cherab/tools/observers/group/targettedpixel.py
@@ -0,0 +1,116 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+from numpy import ndarray
+from raysect.optical.observer import TargettedPixel
+
+from .base import Observer0DGroup
+
+
+class TargettedPixelGroup(Observer0DGroup):
+ """
+ A group of targetted pixel under a single scene-graph node.
+
+ A scene-graph object regrouping a series of 'TargettedPixel'
+ observers as a scene-graph parent. Allows combined observation and display
+ control simultaneously.
+
+ :ivar list x_width: Width of pixel along local x axis
+ :ivar list y_width: Width of pixel along local y axis
+ :ivar list targets: Targets for preferential sampling
+ :ivar list targetted_path_prob: Probability of ray being casted at the target
+ """
+ _OBSERVER_TYPE = TargettedPixel
+
+ @property
+ def x_width(self):
+ return [pixel.x_width for pixel in self._observers]
+
+ @x_width.setter
+ def x_width(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for pixel, v in zip(self._observers, value):
+ pixel.x_width = v
+ else:
+ raise ValueError("The length of 'x_width' ({}) "
+ "mismatches the number of pixels ({}).".format(len(value), len(self._observers)))
+ else:
+ for pixel in self._observers:
+ pixel.x_width = value
+
+ @property
+ def y_width(self):
+ return [pixel.y_width for pixel in self._observers]
+
+ @y_width.setter
+ def y_width(self, value):
+ if isinstance(value, (list, tuple, ndarray)):
+ if len(value) == len(self._observers):
+ for pixel, v in zip(self._observers, value):
+ pixel.y_width = v
+ else:
+ raise ValueError("The length of 'y_width' ({}) "
+ "mismatches the number of pixels ({}).".format(len(value), len(self._observers)))
+ else:
+ for pixel in self._observers:
+ pixel.y_width = value
+
+ @property
+ def targets(self):
+ """
+ List of target lists used by pixels for preferential sampling
+
+ :param list value: List of primitives to be set to each pixel or
+ list of lists containing targets specific for each pixel
+ in this case the number of lists must match number of pixels
+
+ :rtype: list
+ """
+ return [pixel.targets for pixel in self._observers]
+
+ @targets.setter
+ def targets(self, value):
+ if all(isinstance(v, (list, tuple)) for v in value):
+ if len(value) == len(self._observers):
+ for pixel, v in zip(self._observers, value):
+ pixel.targets = v
+ else:
+ raise ValueError("The number of provided target lists' ({}) "
+ "mismatches the number of pixels ({}).".format(len(value), len(self._observers)))
+ else:
+ # assuming a list of primitives, the pixel's setter will throw an error if not
+ for pixel in self._observers:
+ pixel.targets = value
+
+ @property
+ def targetted_path_prob(self):
+ return [pixel.targetted_path_prob for pixel in self._observers]
+
+ @targetted_path_prob.setter
+ def targetted_path_prob(self, value):
+ if isinstance(value, (list, tuple)):
+ if len(value) == len(self._observers):
+ for pixel, v in zip(self._observers, value):
+ pixel.targetted_path_prob = v
+ else:
+ raise ValueError("The length of 'value' ({}) "
+ "mismatches the number of pixels ({}).".format(len(value), len(self._observers)))
+ else:
+ for pixel in self._observers:
+ pixel.targetted_path_prob = value
diff --git a/cherab/tools/observers/spectroscopy/base.py b/cherab/tools/observers/spectroscopy/base.py
index db552e2a..8186d002 100644
--- a/cherab/tools/observers/spectroscopy/base.py
+++ b/cherab/tools/observers/spectroscopy/base.py
@@ -25,6 +25,9 @@
class _SpectroscopicObserver0DBase:
"""
+ .. deprecated:: 1.4.0
+ Use Raysect's observer classes instead.
+
A base class for spectroscopic 0D observers.
The observer allows to control some of the pipeline properties
diff --git a/cherab/tools/observers/spectroscopy/fibreoptic.py b/cherab/tools/observers/spectroscopy/fibreoptic.py
index ea697a73..59911ff9 100644
--- a/cherab/tools/observers/spectroscopy/fibreoptic.py
+++ b/cherab/tools/observers/spectroscopy/fibreoptic.py
@@ -27,6 +27,9 @@
class SpectroscopicFibreOptic(FibreOptic, _SpectroscopicObserver0DBase):
"""
+ .. deprecated:: 1.4.0
+ Use Raysect's FibreOptic observer instead.
+
An optic fibre spectroscopic observer with non-zero acceptance angle.
Rays are sampled over a circular area at the fibre tip and a conical solid angle
diff --git a/cherab/tools/observers/spectroscopy/sightline.py b/cherab/tools/observers/spectroscopy/sightline.py
index a8393d31..6b52847b 100644
--- a/cherab/tools/observers/spectroscopy/sightline.py
+++ b/cherab/tools/observers/spectroscopy/sightline.py
@@ -27,6 +27,9 @@
class SpectroscopicSightLine(SightLine, _SpectroscopicObserver0DBase):
"""
+ .. deprecated:: 1.4.0
+ Use Raysect's SightLine observer instead.
+
A simple line of sight observer.
Multiple `SpectroscopicSightLine` observers can be combined into `SightLineGroup`.
diff --git a/cherab/tools/primitives/__init__.py b/cherab/tools/primitives/__init__.py
index 8cf9e184..e4afae9d 100644
--- a/cherab/tools/primitives/__init__.py
+++ b/cherab/tools/primitives/__init__.py
@@ -1,6 +1,6 @@
-# Copyright 2016-2018 Euratom
-# Copyright 2016-2018 United Kingdom Atomic Energy Authority
-# Copyright 2016-2018 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
#
# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
# European Commission - subsequent versions of the EUPL (the "Licence");
@@ -17,4 +17,5 @@
# under the Licence.
from .annulus_mesh import generate_annulus_mesh_segments
+from .toroidal_mesh import toroidal_mesh_from_polygon
from .axisymmetric_mesh import axisymmetric_mesh_from_polygon
diff --git a/cherab/tools/primitives/axisymmetric_mesh.pxd b/cherab/tools/primitives/axisymmetric_mesh.pxd
index b2502d9a..8ab28503 100644
--- a/cherab/tools/primitives/axisymmetric_mesh.pxd
+++ b/cherab/tools/primitives/axisymmetric_mesh.pxd
@@ -1,7 +1,7 @@
-# Copyright 2016-2018 Euratom
-# Copyright 2016-2018 United Kingdom Atomic Energy Authority
-# Copyright 2016-2018 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
#
# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
# European Commission - subsequent versions of the EUPL (the "Licence");
@@ -17,7 +17,6 @@
# See the Licence for the specific language governing permissions and limitations
# under the Licence.
-cimport numpy as np
from raysect.primitive.mesh cimport Mesh
-cpdef Mesh axisymmetric_mesh_from_polygon(np.ndarray polygon, int num_toroidal_segments=*)
+cpdef Mesh axisymmetric_mesh_from_polygon(object polygon, int num_toroidal_segments=*)
diff --git a/cherab/tools/primitives/axisymmetric_mesh.pyx b/cherab/tools/primitives/axisymmetric_mesh.pyx
index b1e55689..81533cb0 100644
--- a/cherab/tools/primitives/axisymmetric_mesh.pyx
+++ b/cherab/tools/primitives/axisymmetric_mesh.pyx
@@ -1,24 +1,38 @@
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
-import numpy as np
-cimport numpy as np
-from libc.math cimport cos, sin
from raysect.primitive.mesh.mesh cimport Mesh
+from .toroidal_mesh import toroidal_mesh_from_polygon
-cdef double DEG2RAD = 2 * np.pi / 360
-
-cpdef Mesh axisymmetric_mesh_from_polygon(np.ndarray polygon, int num_toroidal_segments=500):
+cpdef Mesh axisymmetric_mesh_from_polygon(object polygon, int num_toroidal_segments=500):
"""
Generates an Raysect Mesh primitive from the specified 2D polygon.
- :param np.ndarray polygon: A numpy array with shape [N,2] specifying the wall outline polygon
- in the R-Z plane. The polygon should not be closed, i.e. vertex i = 0 and i = N should not
- be the same vertex, but neighbours.
+ :param object polygon: An object which can be converted to a numpy array with shape [N,2]
+ specifying the wall outline polygon in the R-Z plane. The polygon
+ should not be closed, i.e. vertex i = 0 and i = N should not be the
+ same vertex, but neighbours.
:param int num_toroidal_segments: The number of repeating toroidal segments that will be used
- to construct the mesh.
+ to construct the mesh.
:return: A Raysect Mesh primitive constructed from the R-Z polygon using symmetry.
-
+
.. code-block:: pycon
>>> from cherab.tools.primitives import axisymmetric_mesh_from_polygon
@@ -27,63 +41,4 @@ cpdef Mesh axisymmetric_mesh_from_polygon(np.ndarray polygon, int num_toroidal_s
>>> mesh = axisymmetric_mesh_from_polygon(wall_polygon)
"""
- cdef:
- int num_poloidal_vertices
- int i, j, vid, v1_id, v2_id, v3_id, v4_id
- float theta, r, x, y, z
- np.ndarray vertices
- list triangles
- double[:,:] polygon_mv, vertices_mv
-
- num_poloidal_vertices = len(polygon)
- theta = 360 / num_toroidal_segments
- vertices = np.zeros((num_poloidal_vertices * num_toroidal_segments, 3))
- vertices_mv = vertices
- polygon_mv = polygon
-
- for i in range(num_toroidal_segments):
- for j in range(num_poloidal_vertices):
-
- r = polygon_mv[j, 0]
- z = polygon_mv[j, 1]
- x = r * cos(i * theta * DEG2RAD)
- y = r * sin(i * theta * DEG2RAD)
-
- vid = i * num_poloidal_vertices + j
- vertices_mv[vid, 0] = x
- vertices_mv[vid, 1] = y
- vertices_mv[vid, 2] = z
-
- # assemble mesh triangles
- triangles = []
- for i in range(num_toroidal_segments):
- for j in range(num_poloidal_vertices):
-
- if i == num_toroidal_segments - 1 and j == num_poloidal_vertices - 1:
- v1_id = i * num_poloidal_vertices + j
- v2_id = i * num_poloidal_vertices + 0
- v3_id = j
- v4_id = 0
-
- elif i == num_toroidal_segments - 1:
- v1_id = i * num_poloidal_vertices + j
- v2_id = i * num_poloidal_vertices + j + 1
- v3_id = j
- v4_id = j + 1
-
- elif j == num_poloidal_vertices - 1:
- v1_id = i * num_poloidal_vertices + j
- v2_id = i * num_poloidal_vertices
- v3_id = i * num_poloidal_vertices + num_poloidal_vertices + j
- v4_id = i * num_poloidal_vertices + num_poloidal_vertices
-
- else:
- v1_id = i * num_poloidal_vertices + j
- v2_id = i * num_poloidal_vertices + j + 1
- v3_id = i * num_poloidal_vertices + num_poloidal_vertices + j
- v4_id = i * num_poloidal_vertices + num_poloidal_vertices + j + 1
-
- triangles.append([v1_id, v2_id, v4_id])
- triangles.append([v4_id, v3_id, v1_id])
-
- return Mesh(vertices=vertices, triangles=triangles, smoothing=False)
+ return toroidal_mesh_from_polygon(polygon, toroidal_extent=360, num_toroidal_segments=num_toroidal_segments)
diff --git a/cherab/tools/primitives/toroidal_mesh.pxd b/cherab/tools/primitives/toroidal_mesh.pxd
new file mode 100644
index 00000000..f7c90758
--- /dev/null
+++ b/cherab/tools/primitives/toroidal_mesh.pxd
@@ -0,0 +1,22 @@
+
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+from raysect.primitive.mesh cimport Mesh
+
+cpdef Mesh toroidal_mesh_from_polygon(object polygon, double toroidal_extent, object polygon_triangles=*, int num_toroidal_segments=*)
diff --git a/cherab/tools/primitives/toroidal_mesh.pyx b/cherab/tools/primitives/toroidal_mesh.pyx
new file mode 100644
index 00000000..62cfa721
--- /dev/null
+++ b/cherab/tools/primitives/toroidal_mesh.pyx
@@ -0,0 +1,169 @@
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+import numpy as np
+cimport numpy as np
+from libc.math cimport cos, sin
+from raysect.primitive.mesh.mesh cimport Mesh
+from raysect.core.math.polygon import triangulate2d
+from raysect.core.math.cython cimport winding2d
+
+
+cdef double DEG2RAD = 2 * np.pi / 360
+
+
+cpdef Mesh toroidal_mesh_from_polygon(object polygon, double toroidal_extent, object polygon_triangles=None, int num_toroidal_segments=500):
+ """
+ Generates a watertight Raysect Mesh primitive from the specified 2D polygon in R-Z plane
+ by extending it in toroidal direction by a given angle and closing the
+ poloidal faces with triangulated polygons.
+
+ :param object polygon: An object which can be converted to a numpy array with shape
+ [N,2] specifying the wall outline polygon in the R-Z plane.
+ The polygon should not be closed, i.e. vertex i = 0 and i = N
+ should not be the same vertex, but neighbours.
+ :param object polygon_triangles: An object which can be converted to a numpy array
+ with shape [M,3] specifying the triangulation
+ of a polygon (polygon_triangles = [[v1, v2, v3],...),
+ where v1, v2, v3 are the vertex array indices specifying
+ the triangle’s vertices. Should be with clockwise winding.
+ Defaults to None.
+ If not provided, the triangulation will be performed using
+ `triangulate2d(polygon)` from raysect.core.math.polygon.
+ :param float toroidal_extent: Angular extention of an element in toroidal direction (in degrees).
+ Note that in the case of toroidal_extent=360 produces
+ an axisymmetric mesh which has no end faces
+ :param int num_toroidal_segments: The number of repeating toroidal segments
+ per given `toroidal_extent` that will be used to construct
+ the mesh. Defaults to 500.
+
+ :return: A watertight Raysect Mesh primitive constructed from the R-Z polygon.
+
+ .. code-block:: pycon
+
+ >>> from cherab.tools.primitives import toroidal_mesh_from_polygon
+ >>>
+ >>> # wall_polygon is your (N, 2) ndarray describing the polygon
+ >>> mesh = toroidal_mesh_from_polygon(wall_polygon, toroidal_extent = 50)
+ """
+
+ cdef:
+ int num_poloidal_vertices, num_toroidal_segments_loop
+ int i, j, vid, v1_id, v2_id, v3_id, v4_id
+ double theta, r, x, y, z
+ list triangles
+ double[:, :] polygon_mv, vertices_mv
+
+ polygon = np.array(polygon, dtype=np.float64)
+
+ if polygon.ndim != 2:
+ raise ValueError("The 'polygon' must be a two-dimensional array.")
+
+ if polygon.shape[0] < 2:
+ raise ValueError("The 'polygon' must contain at least two vertices.")
+
+ if polygon.shape[1] != 2:
+ raise ValueError("The 'polygon' must have [N, 2] shape.")
+
+ if (toroidal_extent<=0) or (toroidal_extent>360):
+ raise ValueError("The 'toroidal_extent' should be in the range 0 < 'toroidal_extent' <= 360.")
+
+ num_poloidal_vertices = polygon.shape[0]
+ theta = toroidal_extent / num_toroidal_segments # toroidal step
+
+ vertices = np.zeros((num_poloidal_vertices * num_toroidal_segments, 3))
+ vertices_mv = vertices
+ polygon_mv = polygon
+
+ for i in range(num_toroidal_segments):
+ for j in range(num_poloidal_vertices):
+
+ r = polygon_mv[j, 0]
+ z = polygon_mv[j, 1]
+ x = r * cos(i * theta * DEG2RAD)
+ y = r * sin(i * theta * DEG2RAD)
+
+ vid = i * num_poloidal_vertices + j
+ vertices_mv[vid, 0] = x
+ vertices_mv[vid, 1] = y
+ vertices_mv[vid, 2] = z
+
+ # assemble mesh triangles
+ triangles = []
+
+ if toroidal_extent != 360.:
+ if polygon_triangles is None:
+ # triangulating initial polygon in case of not full axisymmetric mesh
+ polygon_triangles = triangulate2d(polygon)
+
+ else:
+ # user-defined triangulation
+ polygon_triangles = np.array(polygon_triangles, dtype=np.int32)
+ # check data sanity
+ _check_polygon_triangulation(polygon, polygon_triangles)
+
+ triangles = triangles + polygon_triangles[:, [1, 0, 2]].tolist()
+
+ num_toroidal_segments_loop = num_toroidal_segments if toroidal_extent == 360. else num_toroidal_segments - 1
+
+ for i in range(num_toroidal_segments_loop):
+ for j in range(num_poloidal_vertices):
+
+ if i == num_toroidal_segments - 1 and j == num_poloidal_vertices - 1:
+ v1_id = i * num_poloidal_vertices + j
+ v2_id = i * num_poloidal_vertices + 0
+ v3_id = j
+ v4_id = 0
+
+ elif i == num_toroidal_segments - 1:
+ v1_id = i * num_poloidal_vertices + j
+ v2_id = i * num_poloidal_vertices + j + 1
+ v3_id = j
+ v4_id = j + 1
+
+ elif j == num_poloidal_vertices - 1:
+ v1_id = i * num_poloidal_vertices + j
+ v2_id = i * num_poloidal_vertices
+ v3_id = i * num_poloidal_vertices + num_poloidal_vertices + j
+ v4_id = i * num_poloidal_vertices + num_poloidal_vertices
+
+ else:
+ v1_id = i * num_poloidal_vertices + j
+ v2_id = i * num_poloidal_vertices + j + 1
+ v3_id = i * num_poloidal_vertices + num_poloidal_vertices + j
+ v4_id = i * num_poloidal_vertices + num_poloidal_vertices + j + 1
+
+ triangles.append([v1_id, v2_id, v4_id])
+ triangles.append([v4_id, v3_id, v1_id])
+
+ if toroidal_extent != 360.:
+ triangles = triangles + ((num_toroidal_segments - 1) * num_poloidal_vertices + polygon_triangles).tolist()
+
+ return Mesh(vertices=vertices, triangles=triangles, smoothing=False)
+
+
+cdef _check_polygon_triangulation(np.ndarray polygon, np.ndarray polygon_triangles):
+
+
+ # check consistency
+ if not np.array_equal(np.unique(polygon_triangles), np.arange(polygon.shape[0], dtype=np.int32)):
+ raise ValueError("The data in 'polygon_triangles' does not match a given 'polygon'.")
+ # check winding
+ triangles = np.ascontiguousarray(polygon[polygon_triangles])
+ if not all(winding2d(triangle) for triangle in triangles):
+ raise ValueError("All triangles in 'polygon_triangles' must be wound clockwise.")
diff --git a/cherab/tools/spectroscopy/__init__.py b/cherab/tools/spectroscopy/__init__.py
new file mode 100644
index 00000000..23bbbe1f
--- /dev/null
+++ b/cherab/tools/spectroscopy/__init__.py
@@ -0,0 +1,22 @@
+
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+from .instrument import SpectroscopicInstrument
+from .polychromator import PolychromatorFilter, TrapezoidalFilter, Polychromator
+from .spectrometer import Spectrometer, CzernyTurnerSpectrometer
diff --git a/cherab/tools/spectroscopy/instrument.py b/cherab/tools/spectroscopy/instrument.py
new file mode 100644
index 00000000..0e0d666c
--- /dev/null
+++ b/cherab/tools/spectroscopy/instrument.py
@@ -0,0 +1,118 @@
+
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+class SpectroscopicInstrument:
+ """
+ Base class for spectroscopic instruments (spectrometers, polychromators, etc.).
+ This is an abstract class.
+
+ :param str name: Instrument name.
+
+ :ivar list pipeline_classes: The list of pipeline classes used with this instrument.
+ :ivar list pipeline_kwargs: The list of dicts with keywords passed to init methods of
+ pipeline classes used with this instrument.
+ :ivar float min_wavelength: Lower wavelength bound for spectral range.
+ :ivar float max_wavelength: Upper wavelength bound for spectral range.
+ :ivar int spectral_bins: The number of spectral samples over the wavelength range.
+ """
+
+ def __init__(self, name=''):
+ self._pipeline_classes = None
+ self.name = name
+ self._clear_spectral_settings()
+
+ @property
+ def name(self):
+ # Instrument name.
+ return self._name
+
+ @name.setter
+ def name(self, value):
+ self._name = str(value)
+ self._pipeline_kwargs = None
+
+ @property
+ def pipeline_classes(self):
+ # The list of pipeline classes used with this instrument.
+ if self._pipeline_classes is None:
+ self._update_pipeline_classes()
+
+ return self._pipeline_classes
+
+ @property
+ def pipeline_kwargs(self):
+ # The list of dicts with keywords passed to init methods of
+ # pipeline classes used with this instrument.
+ if self._pipeline_kwargs is None:
+ self._update_pipeline_kwargs()
+
+ return self._pipeline_kwargs
+
+ def create_pipelines(self):
+ """ Returns a list of new pipelines created according to `pipeline_classes`
+ and keyword arguments."""
+ if self._pipeline_classes is None:
+ self._update_pipeline_classes()
+ if self._pipeline_kwargs is None:
+ self._update_pipeline_kwargs()
+
+ pipelines = []
+ for PipelineClass, kwargs in zip(self._pipeline_classes, self._pipeline_kwargs):
+ pipeline = PipelineClass(**kwargs)
+ pipelines.append(pipeline)
+
+ return pipelines
+
+ @property
+ def min_wavelength(self):
+ # Lower wavelength bound for spectral range.
+ if self._min_wavelength is None:
+ self._update_spectral_settings()
+
+ return self._min_wavelength
+
+ @property
+ def max_wavelength(self):
+ # Upper wavelength bound for spectral range.
+ if self._max_wavelength is None:
+ self._update_spectral_settings()
+
+ return self._max_wavelength
+
+ @property
+ def spectral_bins(self):
+ # The number of spectral samples over the wavelength range.
+ if self._spectral_bins is None:
+ self._update_spectral_settings()
+
+ return self._spectral_bins
+
+ def _clear_spectral_settings(self):
+ self._min_wavelength = None
+ self._max_wavelength = None
+ self._spectral_bins = None
+
+ def _update_spectral_settings(self):
+ raise NotImplementedError("To be defined in subclass.")
+
+ def _update_pipeline_classes(self):
+ raise NotImplementedError("To be defined in subclass.")
+
+ def _update_pipeline_kwargs(self):
+ raise NotImplementedError("To be defined in subclass.")
diff --git a/cherab/tools/spectroscopy/polychromator.py b/cherab/tools/spectroscopy/polychromator.py
new file mode 100644
index 00000000..56fb6e18
--- /dev/null
+++ b/cherab/tools/spectroscopy/polychromator.py
@@ -0,0 +1,221 @@
+
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+import numpy as np
+from raysect.optical import InterpolatedSF
+from raysect.optical.observer import RadiancePipeline0D
+
+from .instrument import SpectroscopicInstrument
+
+
+class PolychromatorFilter(InterpolatedSF):
+ """
+ Defines a polychromator filter as a Raysect's InterpolatedSF.
+
+ :param object wavelengths: 1D array of wavelengths in nanometers.
+ :param object samples: 1D array of spectral samples.
+ :param bool normalise: True/false toggle for whether to normalise the
+ spectral function so its integral equals 1.
+ :param str name: Filter name (e.g. "H-alpha filter"). Default is ''.
+
+ :ivar float min_wavelength: Lower wavelength bound of the filter's spectral range in nm.
+ :ivar float max_wavelength: Upper wavelength bound of the filter's spectral range in nm.
+ """
+
+ def __init__(self, wavelengths, samples, normalise=False, name=''):
+
+ wavelengths = np.array(wavelengths, dtype=np.float64)
+ samples = np.array(samples, dtype=np.float64)
+
+ if wavelengths.ndim != 1:
+ raise ValueError("Wavelength array must be 1D.")
+
+ if samples.shape[0] != wavelengths.shape[0]:
+ raise ValueError("Wavelength and sample arrays must be the same length.")
+
+ indices = np.argsort(wavelengths)
+ wavelengths = wavelengths[indices]
+ samples = samples[indices]
+
+ self._min_wavelength = wavelengths[0]
+ self._max_wavelength = wavelengths[-1]
+ self._window = self._max_wavelength - self._min_wavelength
+ self._central_wavelength = 0.5 * (self._max_wavelength + self._min_wavelength)
+
+ # setting the ends of the filter to zero, if they are not
+ if samples[0] != 0:
+ wavelengths = np.insert(wavelengths, 0, wavelengths[0] * (1. - 1.e-15))
+ samples = np.insert(samples, 0, 0)
+ if samples[-1] != 0:
+ wavelengths = np.append(wavelengths, wavelengths[-1] * (1. + 1.e-15))
+ samples = np.append(samples, 0)
+
+ super().__init__(wavelengths, samples, normalise)
+ self._name = str(name)
+
+ @property
+ def name(self):
+ # Filter name.
+ return self._name
+
+ @property
+ def min_wavelength(self):
+ # Lower wavelength bound of the filter's spectral range in nm.
+ return self._min_wavelength
+
+ @property
+ def max_wavelength(self):
+ # Upper wavelength bound of the filter's spectral range in nm.
+ return self._max_wavelength
+
+ @property
+ def window(self):
+ # Size of the filtering window in nm.
+ return self._window
+
+ @property
+ def central_wavelength(self):
+ # Central wavelength of the filter in nm.
+ return self._central_wavelength
+
+
+class TrapezoidalFilter(PolychromatorFilter):
+ """
+ Symmetrical trapezoidal polychromator filter.
+
+ :param float wavelength: Central wavelength of the filter in nm.
+ :param float window: Size of the filtering window in nm. Default is 3.
+ :param float flat_top: Size of the flat top part of the filter in nm.
+ Default is None (equal to window).
+ :param str name: Filter name (e.g. "H-alpha filter"). Default is ''.
+ """
+
+ def __init__(self, central_wavelength, window=3., flat_top=None, name=''):
+
+ if central_wavelength <= 0:
+ raise ValueError("Argument 'central_wavelength' must be positive.")
+
+ if window <= 0:
+ raise ValueError("Argument 'window' must be positive.")
+
+ flat_top = flat_top or window
+
+ if flat_top <= 0:
+ raise ValueError("Argument 'flat_top' must be positive.")
+ if flat_top > window:
+ raise ValueError("Argument 'flat_top' must be less or equal than 'window'.")
+
+ self._flat_top = flat_top
+
+ if flat_top == window:
+ flat_top -= flat_top * 1.e-15
+
+ wavelengths = [central_wavelength - 0.5 * window,
+ central_wavelength - 0.5 * flat_top,
+ central_wavelength + 0.5 * flat_top,
+ central_wavelength + 0.5 * window]
+ samples = [0, 1, 1, 0]
+ super().__init__(wavelengths, samples, normalise=False, name=name)
+
+ @property
+ def flat_top(self):
+ # Size of the flat top part of the filter in nm.
+ return self._flat_top
+
+
+class Polychromator(SpectroscopicInstrument):
+ """
+ A polychromator assembly with a set of different filters.
+
+ :param list filters: List of the `PolychromatorFilter` instances.
+ :param int min_bins_per_window: Minimal number of spectral bins
+ per filtering window. Default is 10.
+ :param str name: Polychromator name.
+
+ .. code-block:: pycon
+
+ >>> from raysect.optical import World
+ >>> from raysect.optical.observer import FibreOptic
+ >>> from cherab.tools.spectroscopy import Polychromator, TrapezoidalFilter
+ >>>
+ >>> world = World()
+ >>> h_alpha_filter = TrapezoidalFilter(656.1, name='H-alpha filter')
+ >>> ciii_465nm_filter = TrapezoidalFilter(464.8, name='CIII 465 nm filter')
+ >>> polychromator = Polychromator([h_alpha_filter, ciii_465nm_filter], name='MyPolychromator')
+ >>> fibreoptic = FibreOptic(name="MyFibreOptic", parent=world)
+ >>> fibreoptic.min_wavelength = polychromator.min_wavelength
+ >>> fibreoptic.max_wavelength = polychromator.max_wavelength
+ >>> fibreoptic.spectral_bins = polychromator.spectral_bins
+ >>> fibreoptic.pipelines = polychromator.create_pipelines()
+ """
+
+ def __init__(self, filters, min_bins_per_window=10, name=''):
+ super().__init__(name)
+ self.min_bins_per_window = min_bins_per_window
+ self.filters = filters
+
+ @property
+ def min_bins_per_window(self):
+ # Minimal number of spectral bins per filtering window.
+ return self._min_bins_per_window
+
+ @min_bins_per_window.setter
+ def min_bins_per_window(self, value):
+ value = int(value)
+ if value <= 0:
+ raise ValueError("Attribute 'min_bins_per_window' must be positive.")
+
+ self._min_bins_per_window = value
+ self._clear_spectral_settings()
+
+ @property
+ def filters(self):
+ # List of the PolychromatorFilter instances.
+ return self._filters
+
+ @filters.setter
+ def filters(self, value):
+ for poly_filter in value:
+ if not isinstance(poly_filter, PolychromatorFilter):
+ raise TypeError('Property filters must contain only PolychromatorFilter instances.')
+
+ self._filters = value
+ self._clear_spectral_settings()
+ self._pipeline_classes = None
+ self._pipeline_kwargs = None
+
+ def _update_pipeline_classes(self):
+ self._pipeline_classes = [RadiancePipeline0D for poly_filter in self._filters]
+
+ def _update_pipeline_kwargs(self):
+ self._pipeline_kwargs = [{'name': self._name + ': ' + poly_filter.name, 'filter': poly_filter} for poly_filter in self._filters]
+
+ def _update_spectral_settings(self):
+
+ min_wavelength = np.inf
+ max_wavelength = 0
+ step = np.inf
+ for poly_filter in self._filters:
+ step = min(step, poly_filter.window / self._min_bins_per_window)
+ min_wavelength = min(min_wavelength, poly_filter.min_wavelength)
+ max_wavelength = max(max_wavelength, poly_filter.max_wavelength)
+
+ self._min_wavelength = min_wavelength
+ self._max_wavelength = max_wavelength
+ self._spectral_bins = int(np.ceil((max_wavelength - min_wavelength) / step))
diff --git a/cherab/tools/spectroscopy/spectrometer.py b/cherab/tools/spectroscopy/spectrometer.py
new file mode 100644
index 00000000..585ac3f4
--- /dev/null
+++ b/cherab/tools/spectroscopy/spectrometer.py
@@ -0,0 +1,351 @@
+
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+import numpy as np
+from raysect.optical import Spectrum
+from raysect.optical.observer import SpectralRadiancePipeline0D
+
+from .instrument import SpectroscopicInstrument
+
+
+class Spectrometer(SpectroscopicInstrument):
+ """
+ Spectrometer that can accommodate multiple spectra.
+
+ Spectrometer is initialized with a sequence of calibration arrays (one array per accommodated
+ spectrum) containing the wavelengths of the pixel borders. Namely, the values
+ :math:`w_{k}^{i}` and :math:`w_{k}^{i+1}` define the spectral range of the pixel :math:`p_i`
+ of the `k`-th spectrum. After the spectrum is ray-traced, it can be recalibrated with
+ `spectrometer.calibrate(spectrum)`.
+
+ Note that Raysect cannot raytrace the spectra with non-constant spectral resolution.
+ Thus, the actual number of spectral bins of raytraced spectrum is defined with
+ `min_bins_per_pixel` attribute.
+
+ :param tuple wavelength_to_pixel: Wavelength-to-pixel calibration arrays.
+ :param int min_bins_per_pixel: Minimal number of spectral bins
+ per pixel. Default is 1.
+ :param str name: Spectrometer name.
+
+ :ivar tuple wavelengths: Central wavelengths of the pixels.
+
+ .. code-block:: pycon
+
+ >>> from raysect.optical import World, Spectrum
+ >>> from raysect.optical.observer import FibreOptic
+ >>> from cherab.tools.spectroscopy import Spectrometer
+ >>> from matplotlib import pyplot as plt
+ >>>
+ >>> wavelength_to_pixel = ([400., 400.5, 401.5, 402., 404.],
+ >>> [600., 600.5, 601.5, 602., 604., 607.])
+ >>> spectrometer = Spectrometer(wavelength_to_pixel, min_bins_per_pixel=5,
+ >>> name='MySpectrometer')
+ >>>
+ >>> world = World()
+ >>> fibreoptic = FibreOptic(name="MyFibreOptic", parent=world)
+ >>> fibreoptic.min_wavelength = spectrometer.min_wavelength
+ >>> fibreoptic.max_wavelength = spectrometer.max_wavelength
+ >>> fibreoptic.spectral_bins = spectrometer.spectral_bins
+ >>> fibreoptic.pipelines = spectrometer.create_pipelines()
+ >>> ...
+ >>> fibreoptic.observe()
+ >>> spectrum = Spectrum(fibreoptic.min_wavelength, fibreoptic.max_wavelength, fibreoptic.spectral_bins)
+ >>> spectrum.samples[:] = fibreoptic.pipelines[0].mean
+ >>> calibrated_spectra = spectrometer.calibrate(spectrum)
+ >>> wavelengths = spectrometer.wavelengths
+ >>>
+ >>> plt.plot(wavelengths[0], calibrated_spectra[0])
+ >>> plt.show()
+ """
+
+ def __init__(self, wavelength_to_pixel, min_bins_per_pixel=1, name=''):
+
+ self.min_bins_per_pixel = min_bins_per_pixel
+ self.wavelength_to_pixel = wavelength_to_pixel
+ super().__init__(name)
+
+ @property
+ def wavelength_to_pixel(self):
+ # Wavelength-to-pixel calibration arrays.
+ return self._wavelength_to_pixel
+
+ @wavelength_to_pixel.setter
+ def wavelength_to_pixel(self, value):
+ _wavelength_to_pixel = []
+ _wavelengths = []
+ for wl2pix in value:
+ wl2pix = np.array(wl2pix, dtype=float)
+ if wl2pix.ndim != 1:
+ raise ValueError('Attribute wavelength_to_pixel must only contain one-dimensional arrays.')
+ if wl2pix.size < 2:
+ raise ValueError('Attribute wavelength_to_pixel must only contain arrays of at least 2 elements.')
+ if np.any(np.diff(wl2pix) <= 0):
+ raise ValueError('Attribute wavelength_to_pixel must only contain monotonically increasing arrays.')
+ wl2pix.flags.writeable = False
+ _wavelength_to_pixel.append(wl2pix)
+ wl_center = 0.5 * (wl2pix[1:] + wl2pix[:-1])
+ wl_center.flags.writeable = False
+ _wavelengths.append(wl_center)
+ self._wavelength_to_pixel = tuple(_wavelength_to_pixel)
+ self._wavelengths = tuple(_wavelengths)
+ self._clear_spectral_settings()
+
+ @property
+ def wavelengths(self):
+ # Central wavelengths of the pixels.
+ return self._wavelengths
+
+ @property
+ def min_bins_per_pixel(self):
+ # Minimal number of spectral bins per pixel.
+ return self._min_bins_per_pixel
+
+ @min_bins_per_pixel.setter
+ def min_bins_per_pixel(self, value):
+ value = int(value)
+ if value <= 0:
+ raise ValueError("Attribute 'min_bins_per_pixel' must be positive.")
+
+ self._min_bins_per_pixel = value
+ self._clear_spectral_settings()
+
+ def _update_pipeline_classes(self):
+ self._pipeline_classes = [SpectralRadiancePipeline0D]
+
+ def _update_pipeline_kwargs(self):
+ self._pipeline_kwargs = [{'name': self._name}]
+
+ def _update_spectral_settings(self):
+ self._min_wavelength = min(wl2pix[0] for wl2pix in self._wavelength_to_pixel)
+ self._max_wavelength = max(wl2pix[-1] for wl2pix in self._wavelength_to_pixel)
+ step = min(np.diff(wl2pix).min() for wl2pix in self._wavelength_to_pixel) / self._min_bins_per_pixel
+ self._spectral_bins = int(np.ceil((self._max_wavelength - self._min_wavelength) / step))
+
+ def calibrate(self, spectrum):
+ """
+ Calibrates the spectrum according to the `wavelength_to_pixel` arrays
+ by averaging it over the pixel widths.
+
+ :param Spectrum spectrum: Spectrum to calibrate.
+
+ :returns: A tuple of calibrated spectra as ndarrays.
+ """
+ if not isinstance(spectrum, Spectrum):
+ raise TypeError('Argument spectrum must be a Spectrum instance.')
+ if spectrum.min_wavelength > self.min_wavelength or spectrum.max_wavelength < self.max_wavelength:
+ raise ValueError('Unable to calibrate the spectrum. '
+ 'The spectrum has narrower range ({}, {}) than the spectrometer ({}, {}).'.format(spectrum.min_wavelength,
+ spectrum.max_wavelength,
+ self.min_wavelength,
+ self.max_wavelength))
+ calibrated_spectra = []
+ for wl2pix in self.wavelength_to_pixel:
+ calibrated_spectrum = np.zeros(wl2pix.size - 1)
+ for i in range(wl2pix.size - 1):
+ calibrated_spectrum[i] = spectrum.integrate(wl2pix[i], wl2pix[i + 1]) / (wl2pix[i + 1] - wl2pix[i])
+ calibrated_spectra.append(calibrated_spectrum)
+
+ return calibrated_spectra
+
+
+class CzernyTurnerSpectrometer(Spectrometer):
+ """
+ Czerny-Turner spectrometer.
+
+ The Czerny-Turner spectrometer is initialized with the parameters of the diffraction scheme
+ and a sequence of accommodated spectra, each of which is determined by the lower wavelength
+ bound and the number of pixels.
+
+ This spectrometer automatically fills the wavelength-to-pixel calibration arrays
+ according to the parameters of the diffraction scheme.
+
+ :param int diffraction_order: Diffraction order.
+ :param float grating: Diffraction grating in nm-1.
+ :param float focal_length: Focal length in nm.
+ :param float pixel_spacing: Pixel to pixel spacing on CCD in nm.
+ :param float diffraction_angle: Angle between incident and diffracted light in degrees.
+ :param tuple accommodated_spectra: A sequence of (`min_wavelength`, `pixels`) pairs, specifying
+ the lower wavelength bound and the number of pixels
+ of accommodated spectra.
+ :param int min_bins_per_pixel: Minimal number of spectral bins
+ per pixel. Default is 1.
+ :param str name: Spectrometer name.
+
+ :ivar tuple wavelength_to_pixel: Wavelength-to-pixel calibration arrays.
+
+ .. code-block:: pycon
+
+ >>> from raysect.optical import World
+ >>> from raysect.optical.observer import FibreOptic
+ >>> from cherab.tools.spectroscopy import CzernyTurnerSpectrometer
+ >>>
+ >>> world = World()
+ >>> hires_spectrometer = CzernyTurnerSpectrometer(1, 2.e-3, 1.e9, 2.e4, 10.,
+ >>> ((600., 512), (700., 128)),
+ >>> name='MySpectrometer')
+ >>> fibreoptic = FibreOptic(name="MyFibreOptic", parent=world)
+ >>> fibreoptic.min_wavelength = hires_spectrometer.min_wavelength
+ >>> fibreoptic.max_wavelength = hires_spectrometer.max_wavelength
+ >>> fibreoptic.spectral_bins = hires_spectrometer.spectral_bins
+ >>> fibreoptic.pipelines = hires_spectrometer.create_pipelines()
+ """
+
+ def __init__(self, diffraction_order, grating, focal_length, pixel_spacing, diffraction_angle,
+ accommodated_spectra, min_bins_per_pixel=1, name=''):
+ self._accommodated_spectra = None
+ self.diffraction_order = diffraction_order
+ self.grating = grating
+ self.focal_length = focal_length
+ self.pixel_spacing = pixel_spacing
+ self.diffraction_angle = diffraction_angle
+ self.accommodated_spectra = accommodated_spectra
+ self.min_bins_per_pixel = min_bins_per_pixel
+ self.name = name
+
+ @property
+ def diffraction_order(self):
+ # Diffraction order.
+ return self._diffraction_order
+
+ @diffraction_order.setter
+ def diffraction_order(self, value):
+ value = int(value)
+ if value <= 0:
+ raise ValueError("Attribute 'diffraction_order' must be positive.")
+
+ self._diffraction_order = value
+ # resolution has changed, recalculating wavelength_to_pixel
+ self._update_wavelength_to_pixel()
+
+ @property
+ def grating(self):
+ # Diffraction grating in nm-1.
+ return self._grating
+
+ @grating.setter
+ def grating(self, value):
+ if value <= 0:
+ raise ValueError("Attribute 'grating' must be positive.")
+
+ self._grating = value
+ # resolution has changed, recalculating wavelength_to_pixel
+ self._update_wavelength_to_pixel()
+
+ @property
+ def focal_length(self):
+ # Focal length in nm.
+ return self._focal_length
+
+ @focal_length.setter
+ def focal_length(self, value):
+ if value <= 0:
+ raise ValueError("Attribute 'focal_length' must be positive.")
+
+ self._focal_length = value
+ # resolution has changed, recalculating wavelength_to_pixel
+ self._update_wavelength_to_pixel()
+
+ @property
+ def pixel_spacing(self):
+ # Pixel to pixel spacing on CCD in nm.
+ return self._pixel_spacing
+
+ @pixel_spacing.setter
+ def pixel_spacing(self, value):
+ if value <= 0:
+ raise ValueError("Attribute 'pixel_spacing' must be positive.")
+
+ self._pixel_spacing = value
+ # resolution has changed, recalculating wavelength_to_pixel
+ self._update_wavelength_to_pixel()
+
+ @property
+ def diffraction_angle(self):
+ # Angle between incident and diffracted light in degrees.
+ return np.rad2deg(self._diffraction_angle)
+
+ @diffraction_angle.setter
+ def diffraction_angle(self, value):
+ if value <= 0:
+ raise ValueError("Attribute 'diffraction_angle' must be positive.")
+
+ self._diffraction_angle = np.deg2rad(value)
+ # resolution has changed, recalculating wavelength_to_pixel
+ self._update_wavelength_to_pixel()
+
+ @property
+ def accommodated_spectra(self):
+ return self._accommodated_spectra
+
+ @accommodated_spectra.setter
+ def accommodated_spectra(self, value):
+ for min_wavelength, pixels in value:
+ if min_wavelength <= 0:
+ raise ValueError('The value of min_wavelength in accommodated_spectra must be positive.')
+ if pixels <= 0:
+ raise ValueError('The value of pixels in accommodated_spectra must be positive.')
+ self._accommodated_spectra = value
+ self._update_wavelength_to_pixel()
+
+ def _update_wavelength_to_pixel(self):
+
+ if self._accommodated_spectra is None:
+ return
+
+ _wavelength_to_pixel = []
+ _wavelengths = []
+ for min_wavelength, pixels in self._accommodated_spectra:
+ pixels = int(pixels)
+ wl2pix = np.zeros(pixels + 1)
+ wl2pix[0] = min_wavelength
+ for i in range(1, pixels + 1):
+ wl2pix[i] = wl2pix[i - 1] + self.resolution(wl2pix[i - 1])
+ wl2pix.flags.writeable = False
+ _wavelength_to_pixel.append(wl2pix)
+ wl_center = 0.5 * (wl2pix[1:] + wl2pix[:-1])
+ wl_center.flags.writeable = False
+ _wavelengths.append(wl_center)
+ self._wavelength_to_pixel = tuple(_wavelength_to_pixel)
+ self._wavelengths = tuple(_wavelengths)
+
+ self._clear_spectral_settings()
+
+ @property
+ def wavelength_to_pixel(self):
+ # Wavelength-to-pixel calibration arrays.
+ return self._wavelength_to_pixel
+
+ def resolution(self, wavelength):
+ """
+ Calculates spectral resolution in nm for a given wavelength.
+
+ :param wavelength: Wavelength in nm.
+
+ :returns: Resolution in nm.
+ """
+ grating = self._grating
+ m = self._diffraction_order
+ dxdp = self._pixel_spacing
+ angle = self._diffraction_angle
+ fl = self._focal_length
+
+ p = 0.5 * m * grating * wavelength
+ _resolution = dxdp * (np.sqrt(np.cos(angle)**2 - p * p) - p * np.tan(angle)) / (m * fl * grating)
+
+ return _resolution
diff --git a/cherab/tools/tests/test_observer_groups.py b/cherab/tools/tests/test_observer_groups.py
new file mode 100644
index 00000000..1f5b7cb0
--- /dev/null
+++ b/cherab/tools/tests/test_observer_groups.py
@@ -0,0 +1,388 @@
+import unittest
+
+from raysect.core.workflow import RenderEngine
+from raysect.optical.observer import Observer0D, SightLine, FibreOptic, Pixel, TargettedPixel, PowerPipeline0D, SpectralPowerPipeline0D
+from raysect.primitive import Sphere
+
+from cherab.tools.observers.group.base import Observer0DGroup
+from cherab.tools.observers.group import SightLineGroup, FibreOpticGroup, PixelGroup, TargettedPixelGroup
+from cherab.tools.raytransfer import pipelines
+
+
+class Observer0DGroupTestCase(unittest.TestCase):
+ _GROUP_CLASS = Observer0DGroup
+ _NUM = 3
+
+ def setUp(self):
+ ObserverClass = self._GROUP_CLASS._OBSERVER_TYPE
+ self.observers = [ObserverClass(pipelines=[PowerPipeline0D()]) for _ in range(self._NUM)]
+
+ def test_get_item(self):
+ """Tests all inputs for the __get_item__ method"""
+ group = self._GROUP_CLASS(observers=self.observers)
+ names = ['zero', 'one', 'two']
+ group.names = names
+
+ idx = slice(1, 3, 1)
+ for observer, input_observer in zip(group[idx], self.observers[idx]):
+ self.assertIs(observer, input_observer)
+
+ for i, name in enumerate(names):
+ self.assertIs(group[name], self.observers[i])
+
+ with self.assertRaises(IndexError):
+ group[len(group)]
+
+ with self.assertRaises(TypeError):
+ group[1.2]
+
+ with self.assertRaises(ValueError):
+ group['fail']
+
+ group.names = ['fail'] * len(group)
+ with self.assertRaises(ValueError):
+ group['fail']
+
+ def test_assignments(self):
+ """Test assignments of all supported attributes of Observer0DGroup"""
+ group = self._GROUP_CLASS()
+ group.observers = self.observers
+
+ for grouped_observer, input_observer in zip(group.observers, self.observers):
+ self.assertIs(grouped_observer, input_observer, msg='Observers do not match')
+
+ with self.assertRaises(ValueError):
+ group.observers = [Sphere()]
+
+ with self.assertRaises(TypeError):
+ group.observers = Sphere()
+
+ # names
+ names = ['zero', 'one', 'two']
+ group.names = names
+ for grouped_observer, input_name in zip(group.observers, names):
+ self.assertEqual(grouped_observer.name, input_name, msg='Observer name do not match')
+ with self.assertRaises(ValueError):
+ group.names = ['fail']
+ with self.assertRaises(TypeError):
+ group.names = 'fail'
+
+ # pipelines
+ ppln_0 = PowerPipeline0D(name='pipeline zero, observer zero')
+ ppln_1 = PowerPipeline0D(name='pipeline one, observer one')
+ ppln_2 = PowerPipeline0D(name='pipeline two, observer two')
+ ppln_3 = PowerPipeline0D(name='pipeline three, observer two')
+
+ pipelist = [[ppln_0], [ppln_1], [ppln_2, ppln_3]]
+ group.pipelines = pipelist
+ self.assertIs(group[0].pipelines[0], ppln_0, 'non matching pipeline')
+ self.assertIs(group[1].pipelines[0], ppln_1, 'non matching pipeline')
+ self.assertIs(group[2].pipelines[0], ppln_2, 'non matching pipeline')
+ self.assertIs(group[2].pipelines[1], ppln_3, 'non matching pipeline')
+
+ with self.assertRaises(ValueError):
+ group.pipelines = [ppln_0]
+
+ # render_engine
+ engine = RenderEngine()
+ group.render_engine = engine
+ for group_engine in group.render_engine:
+ self.assertIs(group_engine, engine)
+
+ with self.assertRaises(TypeError):
+ group.render_engine = Sphere()
+
+ engines = [RenderEngine() for _ in group.observers]
+ group.render_engine = engines
+ for group_engine, input_engine in zip(group.render_engine, engines):
+ self.assertIs(group_engine, input_engine)
+
+ with self.assertRaises(TypeError):
+ group.render_engine = [RenderEngine() for _ in range(len(group) - 1)] + [Sphere()]
+ with self.assertRaises(ValueError):
+ group.render_engine = [RenderEngine() for _ in range(len(group) - 1)]
+
+ # wavelengths
+ wvl = 500
+ group.min_wavelength = wvl - 100
+ group.max_wavelength = wvl + 100
+ self.assertListEqual(group.min_wavelength, [wvl - 100] * len(group))
+ self.assertListEqual(group.max_wavelength, [wvl + 100] * len(group))
+
+ min_wvls = [90 + 10*i for i in range(len(group))]
+ max_wvls = [100 + 10*i for i in range(len(group))]
+ group.min_wavelength = min_wvls
+ group.max_wavelength = max_wvls
+ self.assertListEqual(group.min_wavelength, min_wvls)
+ self.assertListEqual(group.max_wavelength, max_wvls)
+
+ with self.assertRaises(ValueError):
+ group.max_wavelength = [100] * (len(group) - 1)
+ with self.assertRaises(ValueError):
+ group.min_wavelength = [90] * (len(group) - 1)
+
+ # spectral
+ bins = [200 + i*100 for i in range(len(group))]
+ rays = [2] * len(group)
+ group.spectral_bins = bins
+ group.spectral_rays = rays
+ self.assertListEqual(group.spectral_bins, bins)
+
+ bins = 300
+ rays = 1
+ group.spectral_bins = bins
+ group.spectral_rays = rays
+ for observer in group.observers:
+ self.assertEqual(observer.spectral_bins, bins)
+ self.assertEqual(observer.spectral_rays, rays)
+
+ with self.assertRaises(ValueError):
+ group.spectral_bins = [1000] * (len(group) + 1)
+
+ # quiet
+ quiet = [True] * len(group)
+ group.quiet = quiet
+ self.assertListEqual(group.quiet, quiet)
+
+ quiet = False
+ group.quiet = quiet
+ for observer in group.observers:
+ self.assertEqual(observer.quiet, quiet)
+
+ with self.assertRaises(ValueError):
+ group.quiet = [False] * (len(group) + 1)
+
+ # rays
+ probs = [0.2 + i*0.1 for i in range(len(group))]
+ max_depths = [5 + i for i in range(len(group))]
+ min_depths = [2 + i for i in range(len(group))]
+ sampling = [False] * len(group)
+ weights = [0.5 + i * 0.1 for i in range(len(group))]
+ group.ray_extinction_prob = probs
+ group.ray_max_depth = max_depths
+ group.ray_extinction_min_depth = min_depths
+ group.ray_importance_sampling = sampling
+ group.ray_important_path_weight = weights
+ self.assertListEqual(group.ray_extinction_prob, probs)
+ self.assertListEqual(group.ray_max_depth, max_depths)
+ self.assertListEqual(group.ray_extinction_min_depth, min_depths)
+ self.assertListEqual(group.ray_importance_sampling, sampling)
+ self.assertListEqual(group.ray_important_path_weight, weights)
+
+ probs = 0.3
+ max_depths = 6
+ min_depths = 3
+ sampling = True
+ weights = 0.7
+ group.ray_extinction_prob = probs
+ group.ray_max_depth = max_depths
+ group.ray_extinction_min_depth = min_depths
+ group.ray_importance_sampling = sampling
+ group.ray_important_path_weight = weights
+ for observer in group.observers:
+ self.assertEqual(observer.ray_extinction_prob, probs)
+ self.assertEqual(observer.ray_max_depth, max_depths)
+ self.assertEqual(observer.ray_extinction_min_depth, min_depths)
+ self.assertEqual(observer.ray_importance_sampling, sampling)
+ self.assertEqual(observer.ray_important_path_weight, weights)
+
+ with self.assertRaises(ValueError):
+ group.ray_extinction_prob = [0.5] * (len(group) + 1)
+ with self.assertRaises(ValueError):
+ group.ray_max_depth = [8] * (len(group) + 1)
+ with self.assertRaises(ValueError):
+ group.ray_extinction_min_depth = [4] * (len(group) + 1)
+ with self.assertRaises(ValueError):
+ group.ray_importance_sampling = [False] * (len(group) + 1)
+ with self.assertRaises(ValueError):
+ group.ray_important_path_weight = [0.7] * (len(group) + 1)
+
+ # samples
+ pixel_samples = [2000 + i*500 for i in range(len(group))]
+ per_task = [5000 + i*100 for i in range(len(group))]
+ group.pixel_samples = pixel_samples
+ group.samples_per_task = per_task
+ self.assertListEqual(group.pixel_samples, pixel_samples)
+ self.assertListEqual(group.samples_per_task, per_task)
+
+ pixel_samples = 10000
+ per_task = 30000
+ group.pixel_samples = pixel_samples
+ group.samples_per_task = per_task
+ for observer in group.observers:
+ self.assertEqual(observer.pixel_samples, pixel_samples)
+ self.assertEqual(observer.samples_per_task, per_task)
+
+ with self.assertRaises(ValueError):
+ group.pixel_samples = [5000] * (len(group) + 1)
+ with self.assertRaises(ValueError):
+ group.samples_per_task = [4000] * (len(group) + 1)
+
+ def test_add_observer(self):
+ group = self._GROUP_CLASS()
+ for i in range(len(group)):
+ group.add_observer(observer=self.observers[i])
+ self.assertIs(group.observers[i], self.observers[i], "Added observer is not the observer passed")
+
+ def test_connect_pipelines(self):
+ group = self._GROUP_CLASS(observers=self.observers)
+
+ ppln_classes = [PowerPipeline0D, SpectralPowerPipeline0D]
+ names = ['power', 'spectral']
+ keywords = [
+ dict(name=names[0]),
+ dict(name=names[1], display_progress=True),
+ ]
+
+ with self.assertRaises(ValueError):
+ group.connect_pipelines(ppln_classes, keywords_list=[{}])
+
+ group.connect_pipelines(ppln_classes)
+ for pipelines in group.pipelines:
+ for i, pipeline in enumerate(pipelines):
+ self.assertIsInstance(pipeline, ppln_classes[i])
+ self.assertIs(pipelines[1].display_progress, False)
+
+ group.connect_pipelines(pipeline_classes=ppln_classes, keywords_list=keywords, suppress_display_progress=True)
+ for pipelines in group.pipelines:
+ for i, pipeline in enumerate(pipelines):
+ self.assertIsInstance(pipeline, ppln_classes[i])
+ self.assertEqual(pipeline.name, names[i])
+ self.assertIs(pipelines[1].display_progress, False)
+
+ group.connect_pipelines(pipeline_classes=ppln_classes, keywords_list=keywords, suppress_display_progress=False)
+ for pipelines in group.pipelines:
+ for i, pipeline in enumerate(pipelines):
+ self.assertIsInstance(pipeline, ppln_classes[i])
+ self.assertEqual(pipeline.name, names[i])
+ self.assertIs(pipelines[1].display_progress, True)
+
+ keywords2 = [
+ dict(name=names[0]),
+ dict(name=names[1], display_progress=False),
+ ]
+ group.connect_pipelines(pipeline_classes=ppln_classes, keywords_list=keywords2, suppress_display_progress=False)
+ for pipelines in group.pipelines:
+ for i, pipeline in enumerate(pipelines):
+ self.assertIsInstance(pipeline, ppln_classes[i])
+ self.assertEqual(pipeline.name, names[i])
+ self.assertIs(pipelines[1].display_progress, False)
+
+
+class SightLineGroupTestCase(Observer0DGroupTestCase):
+ _GROUP_CLASS = SightLineGroup
+
+ def test_sensitivity(self):
+ sensitivities = [0.9, 0.8, 0.7]
+
+ group = SightLineGroup(observers=self.observers)
+ group.sensitivity = sensitivities
+ self.assertListEqual(group.sensitivity, sensitivities)
+
+ group.sensitivity = 1
+ for sightline in group.observers:
+ self.assertEqual(sightline.sensitivity, 1)
+
+ with self.assertRaises(ValueError):
+ group.sensitivity = [1] * (len(group) + 1)
+
+
+class FibreOpticTestCase(Observer0DGroupTestCase):
+ _GROUP_CLASS = FibreOpticGroup
+
+ def test_radius(self):
+ group = self._GROUP_CLASS(observers=self.observers)
+
+ radius = [1e-2 for _ in group.observers]
+ group.radius = radius
+ self.assertListEqual(group.radius, radius)
+
+ radius = 1e-3
+ group.radius = radius
+ for group_radius in group.radius:
+ self.assertEqual(group_radius, radius)
+
+ with self.assertRaises(ValueError):
+ group.radius = [1e-1 for _ in range(len(group) + 1)]
+
+ def test_acceptance_angle(self):
+ group = self._GROUP_CLASS(observers=self.observers)
+
+ acceptance_angle = [10] * len(group)
+ group.acceptance_angle = acceptance_angle
+ self.assertListEqual(group.acceptance_angle, acceptance_angle)
+
+ acceptance_angle = 11
+ group.acceptance_angle = acceptance_angle
+ for group_acceptance_angle in group.acceptance_angle:
+ self.assertEqual(group_acceptance_angle, acceptance_angle)
+
+ with self.assertRaises(ValueError):
+ group.acceptance_angle = [12] * (len(group) + 1)
+
+
+class PixelGroupTestCase(Observer0DGroupTestCase):
+ _GROUP_CLASS = PixelGroup
+
+ def test_widths(self):
+ group = self._GROUP_CLASS(observers=self.observers)
+
+ x_width = [1e-2 for _ in group.observers]
+ y_width = [1e-2 for _ in group.observers]
+ group.x_width = x_width
+ group.y_width = y_width
+ self.assertListEqual(group.x_width, x_width)
+ self.assertListEqual(group.y_width, y_width)
+
+ x_width = 1e-3
+ y_width = 1e-3
+ group.x_width = x_width
+ group.y_width = y_width
+ for observer in group.observers:
+ self.assertEqual(observer.x_width, x_width)
+ self.assertEqual(observer.y_width, y_width)
+
+ with self.assertRaises(ValueError):
+ group.x_width = [1e-1] * (len(group) + 1)
+ with self.assertRaises(ValueError):
+ group.y_width = [1e-1] * (len(group) + 1)
+
+
+class TargettedPixelGroupTestCase(PixelGroupTestCase):
+ _GROUP_CLASS = TargettedPixelGroup
+
+ def setUp(self):
+ self.observers = [TargettedPixel(targets=[Sphere()], pipelines=[PowerPipeline0D()]) for _ in range(self._NUM)]
+
+ def test_targets(self):
+ group = self._GROUP_CLASS(observers=self.observers)
+
+ targets = [Sphere(), Sphere()]
+ group.targets = targets
+ for observer in group:
+ self.assertEqual(len(targets), len(observer.targets))
+ for observer_target, input_target in zip(observer.targets, targets):
+ self.assertIs(observer_target, input_target)
+
+ targets = [[Sphere()] for _ in group.observers]
+ group.targets = targets
+ for observer, input_targets in zip(group.observers, targets):
+ for group_target, input_target in zip(observer.targets, input_targets):
+ self.assertIs(group_target, input_target)
+
+ targets = [[Sphere()] for _ in range(len(group) + 1)]
+ with self.assertRaises(ValueError):
+ group.targets = targets
+
+ # targetted path prob
+ prob = [0.9, 0.95, 1]
+ group.targetted_path_prob = prob
+ self.assertListEqual(group.targetted_path_prob, prob)
+
+ prob = 0.8
+ group.targetted_path_prob = prob
+ for group_targetted_path_prob in group.targetted_path_prob:
+ self.assertEqual(group_targetted_path_prob, prob)
+
+ with self.assertRaises(ValueError):
+ group.targetted_path_prob = [0.7] * (len(group) + 1)
diff --git a/cherab/tools/tests/test_sart_opencl.py b/cherab/tools/tests/test_sart_opencl.py
index 794bf605..37be1cfd 100644
--- a/cherab/tools/tests/test_sart_opencl.py
+++ b/cherab/tools/tests/test_sart_opencl.py
@@ -16,10 +16,12 @@
# See the Licence for the specific language governing permissions and limitations
# under the Licence.
+import gc
import unittest
import os
import numpy as np
from cherab.tools.inversions import SartOpencl
+from cherab.tools.inversions.opencl import device_select
try:
import pyopencl as cl
except ImportError:
@@ -47,16 +49,24 @@ def setUp(self):
# true emissivity in float32, shape: (11, 8)
true_emissivity = np.load(os.path.join(os.path.dirname(__file__), 'data/true_emissivity.npy'))
self.true_emissivity = true_emissivity.flatten()
+ # Any OpenCL device, including a CPU, will do for the tests. This enables
+ # POCL to be installed as an OpenCL driver for testing.
+ self.device = device_select(device_type=cl.device_type.ALL)
+
+ def tearDown(self):
+ # Ensure the OpenCL device is properly released between tests.
+ self.device = None
+ gc.collect()
def test_inversion(self):
with SartOpencl(self.gm, block_size=256, copy_column_major=True, use_atomic=False,
- steps_per_thread=64, block_size_row_maj=64) as inv_sart:
+ steps_per_thread=64, block_size_row_maj=64, device=self.device) as inv_sart:
solution, residual = inv_sart(self.receiver)
self.assertTrue(np.allclose(solution, self.true_emissivity, atol=1.e-2))
def test_inversion_atomic(self):
with SartOpencl(self.gm, block_size=256, copy_column_major=True, use_atomic=True,
- steps_per_thread=64, block_size_row_maj=64) as inv_sart:
+ steps_per_thread=64, block_size_row_maj=64, device=self.device) as inv_sart:
solution, residual = inv_sart(self.receiver)
self.assertTrue(np.allclose(solution, self.true_emissivity, atol=1.e-2))
@@ -65,6 +75,6 @@ def test_inversion_constrained(self):
# The beta_laplace parameter is set to just 0.001 to reduce the impact of regularisation. This is a technical test only.
laplacian_matrix = np.identity(self.gm.shape[1], dtype=np.float32)
with SartOpencl(self.gm, laplacian_matrix=laplacian_matrix, block_size=256, copy_column_major=True, use_atomic=False,
- steps_per_thread=64, block_size_row_maj=64) as inv_sart:
+ steps_per_thread=64, block_size_row_maj=64, device=self.device) as inv_sart:
solution, residual = inv_sart(self.receiver, beta_laplace=0.001)
self.assertTrue(np.allclose(solution / solution.max(), self.true_emissivity, atol=1.e-2))
diff --git a/cherab/tools/tests/test_spectroscopic_instruments.py b/cherab/tools/tests/test_spectroscopic_instruments.py
new file mode 100644
index 00000000..211f7830
--- /dev/null
+++ b/cherab/tools/tests/test_spectroscopic_instruments.py
@@ -0,0 +1,170 @@
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+import unittest
+import numpy as np
+
+from raysect.optical import Spectrum
+from raysect.optical.observer.pipeline import RadiancePipeline0D, SpectralRadiancePipeline0D
+from cherab.tools.spectroscopy import TrapezoidalFilter, PolychromatorFilter, Polychromator, CzernyTurnerSpectrometer, Spectrometer
+
+
+class TestPolychromatorFilter(unittest.TestCase):
+ """
+ Test for PolychromatorFilter class.
+ """
+
+ def test_spectrum(self):
+ wavelengths = [658, 654, 656] # unsorted
+ samples = [0.5, 0.5, 1] # non-zero at the ends
+ poly_filter = PolychromatorFilter(wavelengths, samples, name='test_filter')
+ wavelengths = np.linspace(653., 659., 7)
+ spectrum_true = np.array([0, 0.5, 0.75, 1., 0.75, 0.5, 0])
+ spectrum_test = np.array([poly_filter(wvl) for wvl in wavelengths])
+ self.assertTrue(np.all(spectrum_true == spectrum_test))
+
+
+class TestTrapezoidalFilter(unittest.TestCase):
+ """
+ Test for TrapezoidalFilter class.
+ """
+
+ def test_spectrum(self):
+ wavelength = 500.
+ window = 6.
+ flat_top = 2.
+ poly_filter = TrapezoidalFilter(wavelength, window, flat_top, 'test_filter')
+ wavelengths = np.linspace(496., 504., 9)
+ spectrum_true = np.array([0, 0, 0.5, 1., 1., 1., 0.5, 0, 0])
+ spectrum_test = np.array([poly_filter(wvl) for wvl in wavelengths])
+ self.assertTrue(np.all(spectrum_true == spectrum_test))
+
+
+class TestPolychromator(unittest.TestCase):
+ """
+ Test cases for Polychromator class.
+ """
+
+ poly_filters_default = (TrapezoidalFilter(400., 6., 2., 'filter 1'),
+ TrapezoidalFilter(700., 8., 4., 'filter 2'))
+ min_bins_per_window_default = 10
+
+ def test_pipeline_classes(self):
+ polychromator = Polychromator(self.poly_filters_default, self.min_bins_per_window_default, 'test polychromator')
+ pipeline_classes_true = [RadiancePipeline0D, RadiancePipeline0D]
+ self.assertSequenceEqual(pipeline_classes_true, polychromator.pipeline_classes)
+
+ def test_pipeline_kwargs(self):
+ polychromator = Polychromator(self.poly_filters_default, self.min_bins_per_window_default, 'test polychromator')
+ pipeline_kwargs_true = [{'name': 'test polychromator: filter 1', 'filter': self.poly_filters_default[0]},
+ {'name': 'test polychromator: filter 2', 'filter': self.poly_filters_default[1]}]
+ self.assertSequenceEqual(pipeline_kwargs_true, polychromator.pipeline_kwargs)
+
+ def test_spectral_properties(self):
+ polychromator = Polychromator(self.poly_filters_default, self.min_bins_per_window_default)
+ min_wavelength_true = 397.
+ max_wavelength_true = 704.
+ spectral_bins_true = 512
+ self.assertTrue(polychromator.min_wavelength == min_wavelength_true and
+ polychromator.max_wavelength == max_wavelength_true and
+ polychromator.spectral_bins == spectral_bins_true)
+
+ def test_filter_change(self):
+ """ Checks if the spectral properties are updated correctly when the filters are replaced."""
+ polychromator = Polychromator(self.poly_filters_default, self.min_bins_per_window_default)
+ polychromator.min_bins_per_window = 20
+ polychromator.filters = [TrapezoidalFilter(500., 5., 2., 'filter 1'),
+ TrapezoidalFilter(600., 7., 4., 'filter 2')]
+ min_wavelength_true = 497.5
+ max_wavelength_true = 603.5
+ spectral_bins_true = 424
+ self.assertTrue(polychromator.min_wavelength == min_wavelength_true and
+ polychromator.max_wavelength == max_wavelength_true and
+ polychromator.spectral_bins == spectral_bins_true)
+
+
+class TestSpectrometer(unittest.TestCase):
+ """
+ Test cases for Spectrometer class.
+ """
+
+ def test_pipeline_classes(self):
+ wavelength_to_pixel = ([400., 400.5],)
+ spectrometer = Spectrometer(wavelength_to_pixel, name='test spectrometer')
+ self.assertSequenceEqual([SpectralRadiancePipeline0D], spectrometer.pipeline_classes)
+
+ def test_pipeline_kwargs(self):
+ wavelength_to_pixel = ([400., 400.5],)
+ spectrometer = Spectrometer(wavelength_to_pixel, name='test spectrometer')
+ self.assertSequenceEqual([{'name': 'test spectrometer'}], spectrometer.pipeline_kwargs)
+
+ def test_spectral_properties(self):
+ wavelength_to_pixel = ([400., 400.5, 401.5, 402., 404.], [600., 600.5, 601.5, 602., 604., 607.])
+ spectrometer = Spectrometer(wavelength_to_pixel, min_bins_per_pixel=2, name='test spectrometer')
+ min_wavelength_true = 400.
+ max_wavelength_true = 607.
+ spectra_bins_true = 828
+ self.assertTrue(spectrometer.min_wavelength == min_wavelength_true and
+ spectrometer.max_wavelength == max_wavelength_true and
+ spectrometer.spectral_bins == spectra_bins_true)
+
+ def test_calibration(self):
+ wavelength_to_pixel = ([400., 400.5, 401.5, 402., 404.],)
+ spectrometer = Spectrometer(wavelength_to_pixel, name='test spectrometer')
+ spectrum = Spectrum(399, 405, 12)
+ s, ds = np.linspace(0, 6., 13, retstep=True)
+ spectrum.samples[:] = s[:-1] + 0.5 * ds
+ calibrated_spectra = spectrometer.calibrate(spectrum)
+ self.assertTrue(np.all(calibrated_spectra[0] == np.array([1.25, 2., 2.75, 4.])))
+
+
+class TestCzernyTurnerSpectrometer(unittest.TestCase):
+ """
+ Test cases for CzernyTurnerSpectrometer class.
+ """
+
+ diffraction_order = 1
+ grating = 2.e-3
+ focal_length = 1.e9
+ pixel_spacing = 2.e4
+ diffraction_angle = 10.
+ accommodated_spectra = ((400., 64), (500., 32))
+ min_bins_per_pixel = 2
+
+ def test_resolution(self):
+ wavelengths = np.array([350., 550., 750.])
+ resolutions_true = np.array([8.587997e-3, 7.199328e-3, 5.0599164e-3])
+ spectrometer = CzernyTurnerSpectrometer(self.diffraction_order, self.grating, self.focal_length, self.pixel_spacing,
+ self.diffraction_angle, self.accommodated_spectra, name='test spectrometer')
+ resolutions = spectrometer.resolution(wavelengths)
+ self.assertTrue(np.all(np.abs(resolutions / resolutions_true - 1.) < 1.e-7))
+
+ def test_spectral_properties(self):
+ min_wavelength_true = 400
+ max_wavelength_true = 500.24326
+ spectra_bins_true = 26377
+ spectrometer = CzernyTurnerSpectrometer(self.diffraction_order, self.grating, self.focal_length, self.pixel_spacing,
+ self.diffraction_angle, self.accommodated_spectra,
+ min_bins_per_pixel=self.min_bins_per_pixel, name='test spectrometer')
+ self.assertTrue(spectrometer.min_wavelength == min_wavelength_true and
+ spectrometer.spectral_bins == spectra_bins_true and
+ abs(spectrometer.max_wavelength - max_wavelength_true) < 1.e-5)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/demos/emission_models/bremsstrahlung.py b/demos/emission_models/bremsstrahlung.py
new file mode 100755
index 00000000..b1da93f6
--- /dev/null
+++ b/demos/emission_models/bremsstrahlung.py
@@ -0,0 +1,84 @@
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+
+# External imports
+import matplotlib.pyplot as plt
+from scipy.constants import electron_mass, atomic_mass
+from raysect.optical import World, Vector3D, Point3D, Ray
+from raysect.primitive import Sphere
+from raysect.optical.material.emitter.inhomogeneous import NumericalIntegrator
+
+# Cherab imports
+from cherab.core import Species, Maxwellian, Plasma
+from cherab.core.atomic.elements import deuterium, nitrogen
+from cherab.core.model import Bremsstrahlung
+from cherab.openadas import OpenADAS
+from cherab.tools.plasmas import GaussianVolume
+
+
+# tunables
+ion_density = 1e20
+sigma = 1.
+
+# setup scenegraph
+world = World()
+
+# create atomic data source
+adas = OpenADAS(permit_extrapolation=True)
+
+# PLASMA ----------------------------------------------------------------------
+plasma = Plasma(parent=world)
+plasma.atomic_data = adas
+plasma.geometry = Sphere(sigma)
+plasma.geometry_transform = None
+plasma.integrator = NumericalIntegrator(step=0.01 * sigma)
+
+# define basic distributions
+d_density = GaussianVolume(ion_density, sigma)
+n_density = d_density * 0.01
+e_density = GaussianVolume(ion_density, sigma)
+temperature = GaussianVolume(1000, sigma)
+bulk_velocity = Vector3D(0, 0, 0)
+
+deuterium_mass = deuterium.atomic_weight * atomic_mass
+d_distribution = Maxwellian(d_density, temperature, bulk_velocity, deuterium_mass)
+nitrogen_mass = nitrogen.atomic_weight * atomic_mass
+n_distribution = Maxwellian(n_density, temperature, bulk_velocity, nitrogen_mass)
+e_distribution = Maxwellian(e_density, temperature, bulk_velocity, electron_mass)
+
+d1_species = Species(deuterium, 1, d_distribution)
+n1_species = Species(nitrogen, 1, n_distribution)
+
+# define species
+plasma.b_field = Vector3D(1.0, 1.0, 1.0)
+plasma.electron_distribution = e_distribution
+plasma.composition = [d1_species, n1_species]
+
+# add Bremsstrahlung to the plasma
+plasma.models = [Bremsstrahlung()]
+
+# Ray-trace and plot the results
+r = Ray(origin=Point3D(0, 0, -5), direction=Vector3D(0, 0, 1),
+ min_wavelength=380, max_wavelength=800, bins=256)
+s = r.trace(world)
+plt.plot(s.wavelengths, s.samples)
+plt.xlabel('Wavelength (nm)')
+plt.ylabel('Radiance (W/m^2/str/nm)')
+plt.title('Observed Bremsstrahlung spectrum')
+plt.show()
diff --git a/demos/generomak/plasma/plot_2d_plasma.py b/demos/generomak/plasma/plot_2d_plasma.py
new file mode 100755
index 00000000..12f58866
--- /dev/null
+++ b/demos/generomak/plasma/plot_2d_plasma.py
@@ -0,0 +1,128 @@
+
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+"""
+This demo does the same plots as the plot_2d_profiles.py demo, but samples the profiles from the Plasma objects.
+"""
+
+import numpy as np
+from matplotlib.colors import SymLogNorm
+from matplotlib import pyplot as plt
+
+from cherab.core.math import sample3d
+from cherab.core.atomic.elements import hydrogen, carbon
+
+from cherab.generomak.plasma import get_core_plasma, get_edge_plasma, get_plasma
+
+
+def plot_profiles(core_profile, edge_profile, full_profile, r_range, z_range, label):
+
+ # Sample core profile on a regular grid
+ _, _, _, core_profile_samples = sample3d(core_profile, r_range, (0, 0, 1), z_range)
+ core_profile_samples = core_profile_samples.squeeze()
+
+ # Sample edge profile on a regular grid
+ _, _, _, edge_profile_samples = sample3d(edge_profile, r_range, (0, 0, 1), z_range)
+ edge_profile_samples = edge_profile_samples.squeeze()
+
+ # Sample blended profile on a regular grid
+ _, _, _, full_profile_samples = sample3d(full_profile, r_range, (0, 0, 1), z_range)
+ full_profile_samples = full_profile_samples.squeeze()
+
+ fig = plt.figure(figsize=(9.5, 5.), tight_layout=True)
+
+ vmax = full_profile_samples.max()
+ linthresh = 0.01 * min(core_profile_samples.max(), edge_profile_samples.max())
+ color_norm = SymLogNorm(linthresh, vmin=0, vmax=vmax)
+
+ core_profile_samples[core_profile_samples == 0] = np.nan
+ edge_profile_samples[edge_profile_samples == 0] = np.nan
+ full_profile_samples[full_profile_samples == 0] = np.nan
+
+ ax_core = fig.add_subplot(131)
+ ax_core.imshow(core_profile_samples.T, extent=[r_range[0], r_range[1], z_range[0], z_range[1]], origin='lower', norm=color_norm, cmap='gnuplot')
+ ax_core.text(0.99, 0.99, 'Core', ha='right', va='top', transform=ax_core.transAxes)
+ ax_core.set_xlim(r_range[0], r_range[1])
+ ax_core.set_ylim(z_range[0], z_range[1])
+ ax_core.set_xlabel('R, m')
+ ax_core.set_ylabel('Z, m')
+
+ ax_edge = fig.add_subplot(132, sharex=ax_core, sharey=ax_core)
+ img = ax_edge.imshow(edge_profile_samples.T, extent=[r_range[0], r_range[1], z_range[0], z_range[1]], origin='lower', norm=color_norm, cmap='gnuplot')
+ ax_edge.text(0.99, 0.99, 'Edge', ha='right', va='top', transform=ax_edge.transAxes)
+ ax_edge.set_xlabel('R, m')
+
+ ax_blend = fig.add_subplot(133, sharex=ax_core, sharey=ax_core)
+ img = ax_blend.imshow(full_profile_samples.T, extent=[r_range[0], r_range[1], z_range[0], z_range[1]], origin='lower', norm=color_norm, cmap='gnuplot')
+ ax_blend.text(0.99, 0.99, 'Blended', ha='right', va='top', transform=ax_blend.transAxes)
+ ax_blend.set_xlabel('R, m')
+
+ fig.colorbar(img, label=label)
+
+ return fig
+
+
+# get Generomak core plasma
+core_plasma = get_core_plasma()
+
+# get Generomak edge plasma
+edge_plasma = get_edge_plasma()
+
+# get Generomak full plasma (blended core and edge profiles)
+full_plasma = get_plasma()
+
+# plasma domain
+r_range = (0.78, 2.23, 290)
+z_range = (-1.74, 1.49, 647)
+
+# Plotting plasma profiles
+plot_profiles(core_plasma.electron_distribution.density,
+ edge_plasma.electron_distribution.density,
+ full_plasma.electron_distribution.density,
+ r_range, z_range, 'Electron density, m-3')
+
+plot_profiles(core_plasma.electron_distribution.effective_temperature,
+ edge_plasma.electron_distribution.effective_temperature,
+ full_plasma.electron_distribution.effective_temperature,
+ r_range, z_range, 'Electron temperature, eV')
+
+plot_profiles(core_plasma.composition.get(hydrogen, 1).distribution.effective_temperature,
+ edge_plasma.composition.get(hydrogen, 1).distribution.effective_temperature,
+ full_plasma.composition.get(hydrogen, 1).distribution.effective_temperature,
+ r_range, z_range, 'Ion temperature, eV')
+
+for element, charges in ((hydrogen, (0, 1)), (carbon, (0, 1, 2, 3, 4, 5, 6))):
+ for charge in charges:
+ state_str = ' {}+'.format(charge) if charge else ' 0'
+ plot_profiles(core_plasma.composition.get(element, charge).distribution.density,
+ edge_plasma.composition.get(element, charge).distribution.density,
+ full_plasma.composition.get(element, charge).distribution.density,
+ r_range, z_range, '{} density, m-3'.format(element.name + state_str))
+
+plot_profiles(core_plasma.composition.get(hydrogen, 0).distribution.effective_temperature,
+ edge_plasma.composition.get(hydrogen, 0).distribution.effective_temperature,
+ full_plasma.composition.get(hydrogen, 0).distribution.effective_temperature,
+ r_range, z_range, 'neutral hydrogen effective temperature, eV')
+
+plot_profiles(core_plasma.composition.get(carbon, 0).distribution.effective_temperature,
+ edge_plasma.composition.get(carbon, 0).distribution.effective_temperature,
+ full_plasma.composition.get(carbon, 0).distribution.effective_temperature,
+ r_range, z_range, 'neutral carbon effective temperature, eV')
+
+plt.show()
diff --git a/demos/generomak/plasma/plot_2d_profiles.py b/demos/generomak/plasma/plot_2d_profiles.py
new file mode 100755
index 00000000..07fb7683
--- /dev/null
+++ b/demos/generomak/plasma/plot_2d_profiles.py
@@ -0,0 +1,144 @@
+
+# Copyright 2016-2022 Euratom
+# Copyright 2016-2022 United Kingdom Atomic Energy Authority
+# Copyright 2016-2022 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+"""
+This demo plots core, edge and blended Generomak 2D plasma profiles.
+"""
+
+import numpy as np
+from matplotlib.colors import SymLogNorm
+from matplotlib.collections import PolyCollection
+from matplotlib import pyplot as plt
+
+from cherab.core.math import sample2d
+from cherab.core.utility import RecursiveDict
+
+from cherab.generomak.equilibrium import load_equilibrium
+from cherab.generomak.plasma.plasma import get_core_interpolators, load_edge_profiles, get_full_profiles
+
+
+def plot_profiles(core_profile, edge_mesh, edge_data, full_profile, label):
+
+ # get grid parameters
+ vertex_coords = np.asarray(edge_mesh["vertex_coords"])
+ triangles = np.asarray(edge_mesh["triangles"])
+ rl, ru = (vertex_coords[:, 0].min(), vertex_coords[:, 0].max())
+ zl, zu = (vertex_coords[:, 1].min(), vertex_coords[:, 1].max())
+ nr = 288
+ nz = 647
+
+ edge_data = np.asarray(edge_data)
+
+ # Sample core profile on a regular grid
+ _, _, core_profile_samples = sample2d(core_profile, (rl, ru, nr), (zl, zu, nz))
+
+ # Sample blended profile on a regular grid
+ _, _, profile_samples = sample2d(full_profile, (rl, ru, nr), (zl, zu, nz))
+
+ fig = plt.figure(figsize=(9.5, 5.), tight_layout=True)
+
+ vmax = profile_samples.max()
+ linthresh = 0.01 * min(core_profile_samples.max(), edge_data.max())
+ color_norm = SymLogNorm(linthresh, vmin=0, vmax=vmax)
+
+ core_profile_samples[core_profile_samples == 0] = np.nan
+ profile_samples[profile_samples == 0] = np.nan
+
+ ax_core = fig.add_subplot(131)
+ ax_core.imshow(core_profile_samples.T, extent=[rl, ru, zl, zu], origin='lower', norm=color_norm, cmap='gnuplot')
+ ax_core.text(0.99, 0.99, 'Core', ha='right', va='top', transform=ax_core.transAxes)
+ ax_core.set_xlim(rl, ru)
+ ax_core.set_ylim(zl, zu)
+ ax_core.set_xlabel('R, m')
+ ax_core.set_ylabel('Z, m')
+
+ ax_edge = fig.add_subplot(132, sharex=ax_core, sharey=ax_core)
+ collection = PolyCollection(vertex_coords[triangles], norm=color_norm, cmap='gnuplot')
+ collection.set_array(edge_data)
+ ax_edge.add_collection(collection)
+ ax_edge.text(0.99, 0.99, 'Edge', ha='right', va='top', transform=ax_edge.transAxes)
+ ax_edge.set_aspect(1)
+ ax_edge.set_xlabel('R, m')
+
+ ax_blend = fig.add_subplot(133, sharex=ax_core, sharey=ax_core)
+ img = ax_blend.imshow(profile_samples.T, extent=[rl, ru, zl, zu], origin='lower', norm=color_norm, cmap='gnuplot')
+ ax_blend.text(0.99, 0.99, 'Blended', ha='right', va='top', transform=ax_blend.transAxes)
+ ax_blend.set_xlabel('R, m')
+
+ fig.colorbar(img, label=label)
+
+ return fig
+
+
+# load Generomak equilibrium
+equilibrium = load_equilibrium()
+
+# load 1D core profiles, f(psi_norm)
+core_profiles_1d = get_core_interpolators()
+
+# load 2D edge profiles defined on a quadrilateral mesh
+edge_data = load_edge_profiles()
+
+# load 2D plasma profiles covering both core and edge regions
+# see the source code for the get_full_profiles() to learn how to blend core and edge profiles using a mask function
+full_profiles = get_full_profiles(equilibrium, core_profiles_1d)
+
+# map core profiles to 2D using the equilibrium
+core_profiles_2d = RecursiveDict()
+
+core_profiles_2d["electron"]["temperature"] = equilibrium.map2d(core_profiles_1d["electron"]["f1d_temperature"])
+core_profiles_2d["electron"]["density"] = equilibrium.map2d(core_profiles_1d["electron"]["f1d_density"])
+
+for element, states in core_profiles_1d["composition"].items():
+ for charge, state in states.items():
+ core_profiles_2d["composition"][element][charge]["density"] = equilibrium.map2d(state["f1d_density"])
+ core_profiles_2d["composition"][element][charge]["temperature"] = equilibrium.map2d(state["f1d_temperature"])
+
+core_profiles_2d = core_profiles_2d.freeze()
+
+# Plotting plasma profiles
+plot_profiles(core_profiles_2d["electron"]["density"], edge_data["mesh"],
+ edge_data["electron"]["density"], full_profiles["electron"]["density"],
+ 'Electron density, m-3')
+
+plot_profiles(core_profiles_2d["electron"]["temperature"], edge_data["mesh"],
+ edge_data["electron"]["temperature"], full_profiles["electron"]["temperature"],
+ 'Electron temperature, eV')
+
+plot_profiles(core_profiles_2d["composition"]["hydrogen"][1]["temperature"], edge_data["mesh"],
+ edge_data["composition"]["hydrogen"][1]["temperature"],
+ full_profiles["composition"]["hydrogen"][1]["temperature"], 'Ion temperature, eV')
+
+for element, states in core_profiles_2d["composition"].items():
+ for charge, state in states.items():
+ state_str = ' {}+'.format(charge) if charge else ' 0'
+ plot_profiles(state["density"], edge_data["mesh"],
+ edge_data["composition"][element][charge]["density"],
+ full_profiles["composition"][element][charge]["density"],
+ '{} density, m-3'.format(element + state_str))
+
+plot_profiles(core_profiles_2d["composition"]["hydrogen"][0]["temperature"], edge_data["mesh"],
+ edge_data["composition"]["hydrogen"][0]["temperature"],
+ full_profiles["composition"]["hydrogen"][0]["temperature"], 'neutral hydrogen effective temperature, eV')
+
+plot_profiles(core_profiles_2d["composition"]["carbon"][0]["temperature"], edge_data["mesh"],
+ edge_data["composition"]["carbon"][0]["temperature"],
+ full_profiles["composition"]["carbon"][0]["temperature"], 'neutral carbon effective temperature, eV')
+
+plt.show()
diff --git a/demos/generomak/plasma/plot_core_profiles.py b/demos/generomak/plasma/plot_core_profiles.py
new file mode 100644
index 00000000..23fd4486
--- /dev/null
+++ b/demos/generomak/plasma/plot_core_profiles.py
@@ -0,0 +1,66 @@
+
+# Copyright 2016-2021 Euratom
+# Copyright 2016-2021 United Kingdom Atomic Energy Authority
+# Copyright 2016-2021 Centro de Investigaciones Energéticas, Medioambientales y Tecnológicas
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+import numpy as np
+
+import matplotlib.pyplot as plt
+
+from cherab.core.math.samplers import sample1d_points
+from cherab.generomak.plasma.plasma import get_core_interpolators
+
+profiles = get_core_interpolators()
+
+# setup temperature plot
+_, ax_t = plt.subplots()
+ax_t.set_title("Species Core Temperature Profiles")
+ax_t.set_xlabel("Psin")
+ax_t.set_ylabel("eV")
+
+# setup density plot
+_, ax_n = plt.subplots()
+ax_n.set_yscale("log")
+ax_n.set_ylim(1.e-1, 1.e21)
+ax_n.set_title("Species Core Density Profiles")
+ax_n.set_xlabel("psin")
+ax_n.set_ylabel("m^-3")
+
+psin = np.append(1. - np.geomspace(1.e-4, 1, 127)[::-1], [1.])
+# add hydrogen curves
+for chrg, desc in profiles["composition"]["hydrogen"].items():
+ vals = sample1d_points(desc["f1d_temperature"], psin)
+ ax_t.plot(psin, vals, label="H{:d}+".format(chrg))
+ vals = sample1d_points(desc["f1d_density"], psin)
+ ax_n.plot(psin, vals, label="H{:d}+".format(chrg))
+
+# add carbon curves
+for chrg, desc in profiles["composition"]["carbon"].items():
+ vals = sample1d_points(desc["f1d_temperature"], psin)
+ ax_t.plot(psin, vals, label="C{:d}+".format(chrg))
+ vals = sample1d_points(desc["f1d_density"], psin)
+ ax_n.plot(psin, vals, label="C{:d}+".format(chrg))
+
+# add electrons
+vals = sample1d_points(profiles["electron"]["f1d_temperature"], psin)
+ax_t.plot(psin, vals, label="electron", ls="dashed")
+vals = sample1d_points(profiles["electron"]["f1d_density"], psin)
+ax_n.plot(psin, vals, label="electron", ls="dashed")
+
+ax_t.legend()
+ax_n.legend(ncol=2)
+plt.show()
diff --git a/demos/laser/laser_profile.py b/demos/laser/laser_profile.py
new file mode 100644
index 00000000..fd5a08ad
--- /dev/null
+++ b/demos/laser/laser_profile.py
@@ -0,0 +1,86 @@
+from random import gauss
+from raysect.core import Vector3D
+
+from cherab.core.math.samplers import sample3d_grid
+from cherab.core.model.laser.profile import (UniformEnergyDensity, ConstantBivariateGaussian,
+ TrivariateGaussian, GaussianBeamAxisymmetric)
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+def plot_profiles(profile, title=""):
+ """Plot the laser profile
+
+ Produces 2d energy density plot in the x-z plane at y=0.
+ Produces plots of energy density profiles along x, y and z
+ directions.
+ """
+
+ # set coordinate grid and zero indices
+ x = np.linspace(-0.01, 0.01, 31)
+ z = np.linspace(-1, 1, 101)
+ x_zero = np.abs(x).argmin()
+ z_zero = np.abs(z).argmin()
+
+ e_xz_profile = sample3d_grid(profile.get_energy_density, x, [0], z)[:, 0, :]
+ e_y_profile = sample3d_grid(profile.get_energy_density, [0], x, [0])[0, :, 0]
+
+ # plot
+ fig = plt.figure(constrained_layout=True)
+ fig.suptitle(title)
+ spec = fig.add_gridspec(4, 3)
+
+ # profile along y at z=0
+ axz = fig.add_subplot(spec[0, 0:2])
+ axz.plot(x, e_y_profile, color="C2", ls="dashed")
+ axz.set_xlabel("y [m]")
+ axz.set_ylabel("Energy [J/m^3]")
+
+ # x-y plane
+ ax2d = fig.add_subplot(spec[1:3, 0:2])
+ im = ax2d.pcolormesh(x, z, e_xz_profile.T)
+ fig.colorbar(im, ax=ax2d, label="Energy [J/m^3]")
+ ax2d.axhline(z[z_zero], color="C0", ls="dashed")
+ ax2d.axvline(x[x_zero], color="C1", ls="dashed")
+ ax2d.plot([x[x_zero]], z[z_zero], marker="x", color="C2")
+ ax2d.set_xlabel("x [m]")
+ ax2d.set_ylabel("z [m]")
+
+ # profile along z at x=0
+ axz = fig.add_subplot(spec[1:3, -1])
+ axz.plot(e_xz_profile[x_zero, :], z, color="C0", ls="dashed")
+ axz.set_ylabel("z [m]")
+ axz.set_xlabel("Energy [J/m^3]")
+
+ # profile along x at z=0
+ axz = fig.add_subplot(spec[-1, 0:2])
+ axz.plot(x, e_xz_profile[:, z_zero].T, color="C1", ls="dashed")
+ axz.set_xlabel("x [m]")
+ axz.set_ylabel("Energy [J/m^3]")
+
+# UniformEnergyDensity profile has constant parameters in the whole x, y, z space
+uniform = UniformEnergyDensity(energy_density=1e3, laser_length=2., laser_radius=0.005,
+ polarization=Vector3D(0, 1, 0))
+plot_profiles(uniform, "Uniform Energy Profile")
+
+# Example of ConstantBivariteGaussian. With energy 2J, pulse temporal length 5 ns
+# and different standard deviations in the x and y plane. The mean value in both
+# dimensions is equal to 0. There is no correlation between x and y.
+
+gauss2d = ConstantBivariateGaussian(pulse_energy=2, pulse_length=5e-9,
+ stddev_x=2e-3, stddev_y=4e-3)
+plot_profiles(gauss2d, "ConstantBivariateGaussian Energy Profile")
+
+# Example of TrivariageGaussian profile. With the pulse mean at z=0.2
+gauss3d = TrivariateGaussian(pulse_energy=2, pulse_length=2e-9,
+ mean_z=0.2, stddev_x=2e-3, stddev_y=4e-3 )
+plot_profiles(gauss3d, "TrivariateGaussian Energy Profile")
+
+# Example of GaussianBeamModel with wavelength 1e4 nm and 1 mm standard deviation
+# in the waist. The wavelength is too high
+# but was selected to produce nice plots in the defined x, y, z dimensions.
+
+gaussbeam = GaussianBeamAxisymmetric(stddev_waist=1e-3, waist_z=0.2, laser_wavelength=1e4)
+plot_profiles(gaussbeam, "GaussianBeam Energy Profile")
+
+plt.show()
\ No newline at end of file
diff --git a/demos/laser/laser_spectrum.py b/demos/laser/laser_spectrum.py
new file mode 100644
index 00000000..7904bbdc
--- /dev/null
+++ b/demos/laser/laser_spectrum.py
@@ -0,0 +1,34 @@
+from cherab.core.model.laser import ConstantSpectrum, GaussianSpectrum
+
+import matplotlib.pyplot as plt
+
+
+# construct a ConstantSpectrum with 10 spectral bins
+constant_wide = ConstantSpectrum(min_wavelength=1059.9, max_wavelength=1060.1, bins=10)
+
+# plot the power_spectral_density attribute of the laser
+_, ax = plt.subplots()
+ax.plot(constant_wide.wavelengths, constant_wide.power_spectral_density)
+
+ax.set_xlabel("Wavelength [nm]")
+ax.set_ylabel("W / nm")
+
+ax.set_title("Energy Spectral Density")
+plt.show()
+
+# construct a narrow laser spectrum
+constant_narrow = ConstantSpectrum(min_wavelength=1059.999, max_wavelength=1060.001, bins=1)
+print("narow spectrum wavelengths: {}, power spectral density: {}".format(constant_narrow.wavelengths,
+ constant_narrow.power_spectral_density))
+
+# construct a GaussianSpectrum with 20 bins
+gaussian = GaussianSpectrum(min_wavelength=1059, max_wavelength=1061, bins=30,
+ mean=1060, stddev=0.3)
+
+_, ax = plt.subplots()
+ax.plot(gaussian.wavelengths, gaussian.power_spectral_density)
+ax.set_xlabel("Wavelength [nm]")
+ax.set_ylabel("W / nm")
+
+ax.set_title("Energy Spectral Density")
+plt.show()
diff --git a/demos/laser/model_seldenmatoba.py b/demos/laser/model_seldenmatoba.py
new file mode 100644
index 00000000..0491cd66
--- /dev/null
+++ b/demos/laser/model_seldenmatoba.py
@@ -0,0 +1,72 @@
+import matplotlib.pyplot as plt
+
+from raysect.optical.spectrum import Spectrum
+
+from cherab.core.model.laser import SeldenMatobaThomsonSpectrum
+from cherab.core.utility import RecursiveDict
+
+
+density = 3e19 # electron density
+temperatures = [100, 2.e3] # electron temperatures in eV
+laser_wavelength = 1060 # wavelength of the laser light in nm
+laser_energy = 1 # energy density of the laser light in J/m^3
+
+# angle between observation direction and electric field
+angles_pol = [90, 45]
+
+# angles between propagation direction and observation direction
+angles_obs = [45, 90, 135, 120]
+
+# define spectrum of observed scattering
+min_wavelength = 650
+max_wavelength = 1300
+bins = 1000
+
+
+# calculate Thomson scattered spectra for the specified combinations of el. properties and observation
+model = SeldenMatobaThomsonSpectrum()
+scattered = RecursiveDict()
+
+for te in temperatures:
+ for ap in angles_pol:
+ for ao in angles_obs:
+ spectrum = Spectrum(min_wavelength, max_wavelength, bins)
+ scattered[te][ap][ao] = model.calculate_spectrum(density, te, laser_energy, laser_wavelength,
+ ao, ap, spectrum).samples
+scattered = scattered.freeze()
+
+wvls = spectrum.wavelengths
+
+# plot temperature influence on scattered spectra
+ap, ao = 90, 90
+_, ax = plt.subplots()
+ax.set_title("Scattered spectrum, pol. angl.={:d}, obs. angl = {:d}".format(ap, ao))
+for te in temperatures:
+ rad = scattered[te][ap][ao]
+ ax.plot(wvls, rad, label="Te = {:3.1f} eV".format(te))
+ax.set_xlabel("Wavelength [nm]")
+ax.set_ylabel("Spectral Radiance [W/m^3/sr]")
+ax.legend()
+
+# plot influence of angle between polarisation and observation on scattered spectra
+te, ao = 100, 90
+_, ax = plt.subplots()
+ax.set_title("Scattered spectrum, te = {:3.1f}, obs. angl = {:d}".format(te, ao))
+for ap in angles_pol:
+ rad = scattered[te][ap][ao]
+ ax.plot(wvls, rad, label="pol. angl. = {:d} deg".format(ap))
+ax.set_xlabel("Wavelength [nm]")
+ax.set_ylabel("Spectral Radiance [W/m^3/sr]")
+ax.legend()
+
+# plot influence of observation angle on scattered spectra
+te, ap = 2e3, 90
+_, ax = plt.subplots()
+ax.set_title("Scattered spectrum, te = {:3.1f}, obs. angl = {:d}".format(te, ao))
+for ao in angles_obs:
+ rad = scattered[te][ap][ao]
+ ax.plot(wvls, rad, label="obs. angl. = {:d} deg".format(ao))
+ax.set_xlabel("Wavelength [nm]")
+ax.set_ylabel("Spectral Radiance [W/m^3/sr]")
+ax.legend()
+plt.show()
diff --git a/demos/laser/thomson_scattering.py b/demos/laser/thomson_scattering.py
new file mode 100644
index 00000000..f9198d8e
--- /dev/null
+++ b/demos/laser/thomson_scattering.py
@@ -0,0 +1,61 @@
+import numpy as np
+
+from raysect.optical import World, translate, Point3D, rotate_basis, Vector3D
+from raysect.optical.observer import FibreOptic
+
+from cherab.core.model.laser import ConstantBivariateGaussian, ConstantSpectrum, SeldenMatobaThomsonSpectrum
+from cherab.core.laser import Laser
+
+from cherab.generomak.plasma import get_core_plasma
+from cherab.generomak.equilibrium import load_equilibrium
+
+import matplotlib.pyplot as plt
+
+world = World()
+
+plasma = get_core_plasma(parent=world)
+equilibrium = load_equilibrium()
+
+# set up the laser
+laser = Laser(name="Thomson Scattering laser", parent=world)
+laser.transform = translate(equilibrium.magnetic_axis[0], 0, -2)
+laser.plasma = plasma
+laser.laser_profile = ConstantBivariateGaussian(pulse_energy=2, pulse_length=1e-8,
+ laser_length=4, laser_radius=1e-2,
+ stddev_x=3e-3, stddev_y=2e-3)
+laser.laser_spectrum = ConstantSpectrum(min_wavelength=1059.9, max_wavelength=1060.1, bins=1)
+laser.models = [SeldenMatobaThomsonSpectrum()]
+
+# generate points on laser in world space to measure on
+laser_points = [Point3D(0, 0, round(z, 2)).transform(laser.to_root()) for z in np.linspace(2, 2.8, 5)]
+te = [plasma.electron_distribution.effective_temperature(*point) for point in laser_points]
+ne = [plasma.electron_distribution.density(*point) for point in laser_points]
+
+# place fibres 0.1m outside sep on lfs
+fibre_position = Point3D(equilibrium.psin_to_r(1) + 0.1, 0, 0)
+
+# generate fibres list and observe
+fibres = {}
+for point in laser_points:
+
+ direction = fibre_position.vector_to(point)
+ transform = translate(*fibre_position) * rotate_basis(direction, Vector3D(0, 0, 1))
+
+ fibre = FibreOptic(radius=1e-3, acceptance_angle=0.25,
+ parent=world, transform=transform,
+ min_wavelength=800, max_wavelength=1200,
+ spectral_bins=1000,
+ pixel_samples=1000)
+
+ fibre.pipelines[0].display_progress = False
+ fibre.observe()
+ fibres[point.z] = fibre
+
+_, ax = plt.subplots()
+for z, fibre in fibres.items():
+ pipeline = fibre.pipelines[0]
+ ax.plot(pipeline.wavelengths, pipeline.samples.mean, label="z={:1.2f}m".format(z))
+ax.set_xlabel("wavelength [nm]")
+ax.set_ylabel("spectral power W/nm")
+ax.legend()
+plt.show()
diff --git a/demos/observers/groups.py b/demos/observers/groups.py
new file mode 100644
index 00000000..5db127e1
--- /dev/null
+++ b/demos/observers/groups.py
@@ -0,0 +1,90 @@
+# Copyright 2014-2021 United Kingdom Atomic Energy Authority
+#
+# Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the
+# European Commission - subsequent versions of the EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+#
+# https://joinup.ec.europa.eu/software/page/eupl5
+#
+# Unless required by applicable law or agreed to in writing, software distributed
+# under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied.
+#
+# See the Licence for the specific language governing permissions and limitations
+# under the Licence.
+
+"""
+Simple group observer use demonstartion. Includes also example use of plotting routines.
+"""
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+from raysect.core.math import Point3D, Vector3D, rotate_z, rotate_basis, translate
+from raysect.optical import World
+from raysect.optical.observer import SpectralRadiancePipeline0D, FibreOptic
+
+from cherab.core.model import ExcitationLine, RecombinationLine
+from cherab.core.atomic import Line, hydrogen
+from cherab.openadas import OpenADAS
+from cherab.generomak.machine import load_first_wall
+from cherab.tools.observers import FibreOpticGroup
+from cherab.tools.observers.group.plotting import plot_group_spectra, plot_group_total
+from cherab.generomak.plasma import get_edge_plasma
+
+###############################################################################
+# Load the simulation and create a plasma object from it.
+###############################################################################
+plasma = get_edge_plasma()
+
+# Adding H-alpha excitation and recombination models
+plasma.atomic_data = OpenADAS(permit_extrapolation=True)
+h_alpha = Line(hydrogen, 0, (3, 2))
+plasma.models = [ExcitationLine(h_alpha), RecombinationLine(h_alpha)]
+
+
+###############################################################################
+# Observe the plasma with a group of optical fibres.
+###############################################################################
+world = World()
+plasma.parent = world
+
+# Load the generomak first wall.
+load_first_wall(world)
+
+# Create a group of optical fibres observing the divertor.
+group = FibreOpticGroup(parent=world, name='Divertor Fibre Optic Array')
+group.transform = rotate_z(22.5)
+origin = Point3D(2.3, 0, 1.25)
+angles = [-63.8, -66.5, -69.2, -71.9, -74.6]
+direction_r = -np.cos(np.deg2rad(angles))
+direction_z = np.sin(np.deg2rad(angles))
+for i in range(len(angles)):
+ trans = translate(*origin)
+ rot = rotate_basis(Vector3D(direction_r[i], 0, direction_z[i]), Vector3D(0, 1, 0))
+ fibre = FibreOptic(name='{}'.format(i + 1), transform=trans*rot)
+ group.add_observer(fibre)
+group.connect_pipelines([SpectralRadiancePipeline0D], [{'name': 'SpectralRadiance'}])
+
+# Set observer parameters for all observers in group
+group.acceptance_angle = 1.4
+group.radius = 0.001
+group.pixel_samples = 5000
+group.min_wavelength = 655.5
+group.max_wavelength = 656.9
+group.spectral_bins = 256
+
+# Observe.
+print('Observing plasma...')
+group.observe()
+
+###############################################################################
+# Plot results using the plotting functions for groups
+###############################################################################
+
+plt.ion()
+plot_group_spectra(group, item='SpectralRadiance', in_photons=True)
+plot_group_total(group, item='SpectralRadiance')
+plt.ioff()
+plt.show()
diff --git a/dev/pypi_notes.md b/dev/pypi_notes.md
new file mode 100644
index 00000000..c79e6fe8
--- /dev/null
+++ b/dev/pypi_notes.md
@@ -0,0 +1,80 @@
+Building wheels for publishing on PyPI
+======================================
+
+Linux wheels published on PyPI must be for one of the manylinux variants.
+This means they should be built inside a manylinux Docker container.
+
+For Cherab versions 1.4 and earlier (which depend on raysect 0.7.1 or earlier),
+the procedure varies slightly depending on whether there is a raysect wheel
+available for the Python version or not.
+
+When Raysect wheels are available
+---------------------------------
+
+1. Retrieve the appropriate manylinux container (we'll use manylinux1 here as
+ an example, but any appropriate version works the same way).
+ ```bash
+ sudo docker run -ti -v :/cherab_core quay.io/pypa/manylinux1_x86_64 /bin/bash
+ ```
+ Or, if using singularity instead of Docker (where sudo rights are not available):
+ ```bash
+ singularity pull docker://quay.io/pypa/manylinux1_x86_64
+ singularity run -B :/cherab_core -W /tmp -c ./manylinux1_x86_64_latest.sif
+ ```
+2. Inside the container, change to the top level directory of this repository.
+ ```bash
+ cd /cherab_core
+ ```
+3. Configure pip to prefer older binary wheels over newer sdists. This is because
+ the manylinux images have very few libraries installed so fail to build many
+ packages.
+ ```bash
+ export PIP_PREFER_BINARY=1
+ ```
+4. (Optional) Configure a cache directory for pip that doesn't have a small quota.
+ This will prevent `No space left on device` errors when collecting dependencies,
+ or when pip does have to build certain packages (Numpy for example does successfully
+ build on certain manylinux versions for certain Python versions).
+ ```bash
+ export PIP_CACHE_DIR=/tmp/pipcache
+ ```
+5. Use PyPA's `build` package to build the sdists and wheels, for each Python version
+ we're building the wheels for. For example, for Python 3.8:
+ ```bash
+ /opt/python/cp38-cp38/bin/python -m build .
+ ```
+ Ensure you've done step 3 above before running this command!
+6. Once the build has finished, repair the wheel to give it the correct manylinux tag.
+ Once again, using Python 3.8 as an example:
+ ```bash
+ auditwheel repair ./dist/cherab-1.4.0rc1-cp38-cp38-linux_x86_64.whl
+ ```
+ This will produce a wheel in the `./wheelhouse` directory which can be uploaded to PyPI.
+
+When Raysect wheels aren't available
+------------------------------------
+
+For Raysect 0.8 and later, the same procedure applies as above.
+For Raysect 0.7.1 and below, a couple of additional steps are required.
+
+1. Follow steps 1-4 above to set up the container environment.
+2. Create a virtual environment for building the wheel. For example, for Python 3.10:
+ ```bash
+ /opt/python/cp310-cp310/bin/python -m venv /tmp/cp310
+ . /tmp/cp310/bin/activate
+ ```
+3. Install build, wheel Cython and the oldest supported Numpy into this environment.
+ ```bash
+ pip install build wheel cython oldest-supported-numpy
+ ```
+4. Install the required Raysect version.
+ ```bash
+ pip install raysect==0.7.1
+ ```
+5. Use PyPA's `build` to build the wheel, but tell it to use this virtual
+ environment rather than creating a new isolated one.
+ ```bash
+ python -m build -n .
+ ```
+6. Run the auditwheel command as given in step 6 above to produce wheels with
+ the correct tag for uploading to PyPI.
diff --git a/docs/source/atomic/atomic_data.rst b/docs/source/atomic/atomic_data.rst
index df3bc2db..650d89b4 100644
--- a/docs/source/atomic/atomic_data.rst
+++ b/docs/source/atomic/atomic_data.rst
@@ -6,3 +6,4 @@ Atomic Data
elements_and_isotopes
emission_lines
rate_coefficients
+ gaunt_factors
diff --git a/docs/source/atomic/gaunt_factors.rst b/docs/source/atomic/gaunt_factors.rst
new file mode 100644
index 00000000..b7950ff9
--- /dev/null
+++ b/docs/source/atomic/gaunt_factors.rst
@@ -0,0 +1,23 @@
+
+Gaunt factors
+-------------
+
+This includes classes for temperature-averaged Gaunt factors used to calculate Bremsstrahlung (free-free Gaunt factor)
+and radiative recombination continuum (bound-free Gaunt factor) emission.
+
+
+Free-free Gaunt factors
+^^^^^^^^^^^^^^^^^^^^^^^
+
+.. autoclass:: cherab.core.atomic.gaunt.FreeFreeGauntFactor
+ :members:
+ :special-members: __call__
+
+.. autoclass:: cherab.core.atomic.gaunt.InterpolatedFreeFreeGauntFactor
+ :show-inheritance:
+ :members:
+
+.. autoclass:: cherab.core.atomic.gaunt.MaxwellianFreeFreeGauntFactor
+ :show-inheritance:
+ :members:
+
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 7dfb5f04..60589037 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -55,16 +55,16 @@
# General information about the project.
project = 'Cherab'
-copyright = '2021, Cherab Team'
+copyright = '2022, Cherab Team'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = '1.3'
+version = '1.4'
# The full version, including alpha/beta/rc tags.
-release = '1.3.0'
+release = '1.4.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/source/installation_and_structure.rst b/docs/source/installation_and_structure.rst
index 9d544184..3af9d3ad 100644
--- a/docs/source/installation_and_structure.rst
+++ b/docs/source/installation_and_structure.rst
@@ -39,7 +39,7 @@ that Cherab can calculate. This package is strictly managed by the Cherab develo
require some type of atomic data for their calculations. The base types of reaction rates and
photon emissivity coefficients are defined in the Core API Module,
`cherab `_. A default atomic data source module based on
- the `OpenADAS project `_, is included in the package. In future
+the `OpenADAS project `_, is included in the package. In future
other atomic data sources, such as the ALADDIN database for example, could be made available
through additional packages.
@@ -78,7 +78,9 @@ The easiest way to install Cherab with OpenADAS is using `pip `_ to avoid the risk of
+conflicting versions of packages in your Python environment.
Installing from source
@@ -94,17 +96,29 @@ If all the required dependencies are present (cython, numpy, scipy, matplotlib a
start the Cherab compilation and installation process. If you don't have administrator access to install
the package, add the ``--user`` flag to the above line to install the package under your own user account.
-When developing cherab it is usually preferred that the packages be installed in "develop" mode::
+As all the Cherab packages are dependent on the core ``cherab`` package, this package must be installed first.
+Note that other packages may have their own inter-dependencies, see the specific package documentation for
+more information.
+
+Installing for development
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+When developing cherab it is usually preferred that the packages be installed in "develop" mode.
+Clone the project from the development repository, locate the folder containing setup.py and run::
+
+ pip install -e .
+
+The alternative command if pip is not available is::
python setup.py develop
-This will cause the original installation folder to be added to the site-package path. Modifications to
-the code will therefore be visible to python next time the code is imported. The ``--user`` flag should be
-used if you do not have administrative permission for your python installation.
+Either command will cause the original installation folder to be added to the
+site-package path. Modifications to the code will therefore be visible to python next
+time the code is imported. If you are modifying Cython source files then run
+``./dev/build.sh`` to re-build those files in order for the changes to be visible. A
+virtual environment, or the ``--user`` flag, should be used if you do not have
+administrative permission for your python installation.
-As all the Cherab packages are dependent on the core ``cherab`` package, this package must be installed first.
-Note that other packages may have their own inter-dependencies, see the specific package documentation for
-more information.
When developing new features for Cherab, the development branch should be used as the base.
@@ -128,9 +142,9 @@ Testing
~~~~~~~
A selection of test scripts can be run with the `nose` testing framework. These are routinely
-run on the development version. Running ``nosetests`` at the terminal in the source directory
+run on the development version. Running ``./dev/test.sh`` at the terminal in the source directory
should run all of these tests to completion without errors or failures.
-Many of the demos used throughout the Raysect documentation are distributed with the source code in
+Many of the demos used throughout the documentation are distributed with the source code in
the ``demo`` folder.
diff --git a/docs/source/models/emission_models.rst b/docs/source/models/emission_models.rst
index 73f76cc2..3a2c3b9c 100644
--- a/docs/source/models/emission_models.rst
+++ b/docs/source/models/emission_models.rst
@@ -13,3 +13,4 @@ Cherab contains a number of independent physics models for spectroscopic emissio
brem/bremsstrahlung
basic_line/basic_line_emission
line_shapes/spectral_line_shapes
+ laser/laser
diff --git a/docs/source/models/laser/laser.rst b/docs/source/models/laser/laser.rst
new file mode 100644
index 00000000..da9f7f79
--- /dev/null
+++ b/docs/source/models/laser/laser.rst
@@ -0,0 +1,28 @@
+Laser
+======
+
+Laser Spectrum
+--------------
+
+.. autoclass:: cherab.core.model.laser.laserspectrum.ConstantSpectrum
+ :members:
+.. autoclass:: cherab.core.model.laser.laserspectrum.GaussianSpectrum
+ :members:
+
+Laser Profile
+-------------
+
+.. autoclass:: cherab.core.model.laser.profile.UniformEnergyDensity
+ :members:
+.. autoclass:: cherab.core.model.laser.profile.ConstantBivariateGaussian
+ :members:
+.. autoclass:: cherab.core.model.laser.profile.TrivariateGaussian
+ :members:
+.. autoclass:: cherab.core.model.laser.profile.GaussianBeamAxisymmetric
+ :members:
+
+Laser Model
+-------------
+
+.. autoclass:: cherab.core.model.laser.model.SeldenMatobaThomsonSpectrum
+ :members:
diff --git a/docs/source/plasmas/laser.rst b/docs/source/plasmas/laser.rst
new file mode 100644
index 00000000..6c94c6d8
--- /dev/null
+++ b/docs/source/plasmas/laser.rst
@@ -0,0 +1,20 @@
+Laser
+======
+
+Laser Spectrum
+--------------
+
+.. autoclass:: cherab.core.laser.laserspectrum.LaserSpectrum
+ :members:
+
+Laser Profile
+-------------
+
+.. autoclass:: cherab.core.laser.profile.LaserProfile
+ :members:
+
+Laser Model
+-------------
+
+.. autoclass:: cherab.core.laser.model.LaserModel
+ :members:
diff --git a/docs/source/plasmas/plasmas.rst b/docs/source/plasmas/plasmas.rst
index 07198e71..98e3d9c8 100644
--- a/docs/source/plasmas/plasmas.rst
+++ b/docs/source/plasmas/plasmas.rst
@@ -7,3 +7,4 @@ Plasmas
core_plasma_classes
equilibrium
particle_beams
+ laser
diff --git a/docs/source/tools/observers.rst b/docs/source/tools/observers.rst
index 5946cbac..e93e2057 100644
--- a/docs/source/tools/observers.rst
+++ b/docs/source/tools/observers.rst
@@ -88,6 +88,9 @@ for the :class:`BolometerFoil`.
Spectroscopic lines of sight
----------------------------
+.. deprecated:: 1.4.0
+ Use Raysect's observer classes instead
+
Spectroscopic line of sight allows to control main parameters of the pipeline
without accessing the pipeline directly. Multiple spectroscopic line of sight can be
combined into a group.
@@ -106,10 +109,11 @@ combined into a group.
Group observers
---------------
-Group observer is a collection of observers of the same type, for example an array of line of
-sight. The parameters of individual observers in a group may differ.
-Group observer allows combined observation, namely, calling the observe function for a group
-leads to a sequential call of this function for each observer in the group.
+Group observer is a collection of observers of the same type. All Observer0D classes
+defined in Raysect are supoorted. The parameters of individual observers in a group
+may differ. Group observer allows combined observation, namely, calling the observe
+function for a group leads to a sequential call of this function for each observer
+in the group.
.. autoclass:: cherab.tools.observers.group.base.Observer0DGroup
:members:
@@ -119,3 +123,27 @@ leads to a sequential call of this function for each observer in the group.
.. autoclass:: cherab.tools.observers.group.FibreOpticGroup
:members:
+
+.. autoclass:: cherab.tools.observers.group.PixelGroup
+ :members:
+
+.. autoclass:: cherab.tools.observers.group.TargettedPixelGroup
+ :members:
+
+Spectroscopic Groups
+^^^^^^^^^^^^^^^^^^^^
+
+.. deprecated:: 1.4.0
+ Use groups based on Raysect's observer classes instead
+
+These groups take control of spectroscopic lines of sight observers. They support
+direction and origin positioning and contain methods for plotting the power and
+spectrum. Originally, these were called group observers and did not include the
+Spectroscopic prefix in class name.
+
+.. autoclass:: cherab.tools.observers.SpectroscopicSightLine
+ :members
+
+.. autoclass:: cherab.tools.observers.SpectroscopicFibreOptic
+ :members
+
diff --git a/docs/source/tools/primitives.rst b/docs/source/tools/primitives.rst
index 95026722..bf634b80 100644
--- a/docs/source/tools/primitives.rst
+++ b/docs/source/tools/primitives.rst
@@ -7,3 +7,4 @@ A few useful utilities for creating primitives particularly relevant for fusion.
.. autofunction:: cherab.tools.primitives.axisymmetric_mesh.axisymmetric_mesh_from_polygon
+.. autofunction:: cherab.tools.primitives.toroidal_mesh.toroidal_mesh_from_polygon
\ No newline at end of file
diff --git a/docs/source/tools/spectroscopy.rst b/docs/source/tools/spectroscopy.rst
new file mode 100644
index 00000000..a116dd77
--- /dev/null
+++ b/docs/source/tools/spectroscopy.rst
@@ -0,0 +1,42 @@
+
+Spectroscopy
+============
+
+The tools for plasma spectroscopy.
+
+.. _spectroscopy_instruments:
+
+Spectroscopic instruments
+-------------------------
+
+Spectroscopic instruments such as polychromators and spectrometers
+simplify the setup of properties of the observers and rendering pipelines. The instruments
+are not connected to the scenegraph, so they cannot observe the world. However, the instruments
+have properties, such as `min_wavelength`, `max_wavelength`, `spectral_bins`,
+`pipeline_properties`, with which the observer can be configured.
+The Cherab core package provides base classes for spectroscopic instruments,
+so machine-specific packages can build more advance instruments from them, such as instruments
+with spectral properties based on the actual experimental setup for a given shot/pulse.
+
+.. autoclass:: cherab.tools.spectroscopy.SpectroscopicInstrument
+ :members:
+
+.. autoclass:: cherab.tools.spectroscopy.PolychromatorFilter
+ :members:
+
+.. autoclass:: cherab.tools.spectroscopy.TrapezoidalFilter
+ :show-inheritance:
+ :members:
+
+.. autoclass:: cherab.tools.spectroscopy.Polychromator
+ :show-inheritance:
+ :members:
+
+.. autoclass:: cherab.tools.spectroscopy.Spectrometer
+ :show-inheritance:
+ :members:
+
+.. autoclass:: cherab.tools.spectroscopy.CzernyTurnerSpectrometer
+ :show-inheritance:
+ :members:
+
diff --git a/docs/source/tools/tools.rst b/docs/source/tools/tools.rst
index 3b356121..19f58e95 100644
--- a/docs/source/tools/tools.rst
+++ b/docs/source/tools/tools.rst
@@ -8,6 +8,7 @@ Tools
materials
primitives
observers
+ spectroscopy
tomography
utility
diff --git a/pyproject.toml b/pyproject.toml
index 8c92c2a1..f896f8f0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,2 +1,3 @@
[build-system]
-requires = ["setuptools", "wheel", "numpy>=1.14", "cython>=0.28", "raysect==0.7.1"]
+requires = ["setuptools", "wheel", "oldest-supported-numpy", "cython>=0.28", "raysect==0.7.1"]
+build-backend="setuptools.build_meta"
diff --git a/setup.py b/setup.py
index db4bb706..d7810f52 100644
--- a/setup.py
+++ b/setup.py
@@ -4,19 +4,15 @@
import os
import os.path as path
import multiprocessing
+from Cython.Build import cythonize
multiprocessing.set_start_method('fork')
-use_cython = True
force = False
profile = False
line_profile = False
install_rates = False
-if "--skip-cython" in sys.argv:
- use_cython = False
- del sys.argv[sys.argv.index("--skip-cython")]
-
if "--force" in sys.argv:
force = True
del sys.argv[sys.argv.index("--force")]
@@ -43,57 +39,34 @@
compilation_args.append("-DCYTHON_TRACE=1")
compilation_args.append("-DCYTHON_TRACE_NOGIL=1")
cython_directives["linetrace"] = True
-
-if use_cython:
-
- from Cython.Build import cythonize
-
- # build .pyx extension list
- extensions = []
- for package in source_paths:
- for root, dirs, files in os.walk(path.join(setup_path, package)):
- for file in files:
- if path.splitext(file)[1] == ".pyx":
- pyx_file = path.relpath(path.join(root, file), setup_path)
- module = path.splitext(pyx_file)[0].replace("/", ".")
- extensions.append(
- Extension(
- module,
- [pyx_file],
- include_dirs=compilation_includes,
- extra_compile_args=compilation_args,
- ),
- )
-
- if profile:
- cython_directives["profile"] = True
-
- # generate .c files from .pyx
- extensions = cythonize(
- extensions,
- nthreads=multiprocessing.cpu_count(),
- force=force,
- compiler_directives=cython_directives,
- )
-
-else:
-
- # build .c extension list
- extensions = []
- for package in source_paths:
- for root, dirs, files in os.walk(path.join(setup_path, package)):
- for file in files:
- if path.splitext(file)[1] == ".c":
- c_file = path.relpath(path.join(root, file), setup_path)
- module = path.splitext(c_file)[0].replace("/", ".")
- extensions.append(
- Extension(
- module,
- [c_file],
- include_dirs=compilation_includes,
- extra_compile_args=compilation_args,
- ),
- )
+if profile:
+ cython_directives["profile"] = True
+
+
+extensions = []
+for package in source_paths:
+ for root, dirs, files in os.walk(path.join(setup_path, package)):
+ for file in files:
+ if path.splitext(file)[1] == ".pyx":
+ pyx_file = path.relpath(path.join(root, file), setup_path)
+ module = path.splitext(pyx_file)[0].replace("/", ".")
+ extensions.append(
+ Extension(
+ module,
+ [pyx_file],
+ include_dirs=compilation_includes,
+ extra_compile_args=compilation_args,
+ ),
+ )
+
+
+# generate .c files from .pyx
+extensions = cythonize(
+ extensions,
+ nthreads=multiprocessing.cpu_count(),
+ force=force,
+ compiler_directives=cython_directives,
+)
# parse the package version number
with open(path.join(path.dirname(__file__), "cherab/core/VERSION")) as version_file:
@@ -131,7 +104,6 @@
"scipy",
"matplotlib",
"raysect==0.7.1",
- "cython>=0.28",
],
packages=find_packages(),
include_package_data=True,