Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include README.md CHANGELOG.md LICENSE.txt MANIFEST.in setup.py .gitignore
recursive-include cherab *.py *.pyx *.pxd *.json
recursive-include demos *.py *.pyx *.pxd

442 changes: 442 additions & 0 deletions cherab/openadas/ADF11Xarray.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion cherab/openadas/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def _check_for_adf_file(open_adas_root_path, relative_adf_file_path, download_pa
for element, ionisation, relative_adf_path, download_path in DEFAULT_ADF15_FILES:
print(relative_adf_path)
_check_for_adf_file(ROOT_DATA_PATH, relative_adf_path, download_path)
add_adf15_to_atomic_data(default, element, ionisation, os.path.join(ROOT_DATA_PATH, relative_adf_path))
default = add_adf15_to_atomic_data(default, element, ionisation, os.path.join(ROOT_DATA_PATH, relative_adf_path))

# TODO: there are concerns about the accuracy of this data
# Data from NIST Atomic Spectra Database - http://www.nist.gov/pml/data/asd.cfm
Expand Down
18 changes: 18 additions & 0 deletions cherab/openadas/library/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2014-2017 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.


from .library import ADF11_PLT_FILES, ADF11_PRB_FILES
87 changes: 87 additions & 0 deletions cherab/openadas/library/adf11.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"Description": "Recommended set of ADF11 files for PLT coefficients",
"adf11_plt_files": {
"H": {
"ADAS_Path": "adf11/plt12/plt12_h.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/plt12/plt12_h.dat"
},
"He": {
"ADAS_Path": "adf11/plt96/plt96_he.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/plt96/plt96_he.dat"
},
"Li": {
"ADAS_Path": "adf11/plt96/plt96_li.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/plt96/plt96_li.dat"
},
"Be": {
"ADAS_Path": "adf11/plt96/plt96_be.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/plt96/plt96_be.dat"
},
"C": {
"ADAS_Path": "adf11/plt96/plt96_c.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/plt96/plt96_c.dat"
},
"N": {
"ADAS_Path": "adf11/plt96/plt96_n.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/plt96/plt96_n.dat"
},
"O": {
"ADAS_Path": "adf11/plt96/plt96_o.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/plt96/plt96_o.dat"
},
"Ne": {
"ADAS_Path": "adf11/plt96/plt96_ne.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/plt96/plt96_ne.dat"
},
"Ar": {
"ADAS_Path": "adf11/plt40/plt40_ar.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/plt40/plt40_ar.dat"
},
"Kr": {
"ADAS_Path": "adf11/plt89/plt89_kr.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/plt89/plt89_kr.dat"
}
},
"adf11_prb_files": {
"H": {
"ADAS_Path": "adf11/prb12/prb12_h.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/prb12/prb12_h.dat"
},
"He": {
"ADAS_Path": "adf11/prb96/prb96_he.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/prb96/prb96_he.dat"
},
"Li": {
"ADAS_Path": "adf11/prb96/prb96_li.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/prb96/prb96_li.dat"
},
"Be": {
"ADAS_Path": "adf11/prb96/prb96_be.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/prb96/prb96_be.dat"
},
"C": {
"ADAS_Path": "adf11/prb96/prb96_c.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/prb96/prb96_c.dat"
},
"N": {
"ADAS_Path": "adf11/prb96/prb96_n.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/prb96/prb96_n.dat"
},
"O": {
"ADAS_Path": "adf11/prb96/prb96_o.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/prb96/prb96_o.dat"
},
"Ne": {
"ADAS_Path": "adf11/prb96/prb96_ne.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/prb96/prb96_ne.dat"
},
"Ar": {
"ADAS_Path": "adf11/prb89/prb89_ar.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/prb89/prb89_ar.dat"
},
"Kr": {
"ADAS_Path": "adf11/prb89/prb89_kr.dat",
"Download_URL": "http://open.adas.ac.uk/download/adf11/prb89/prb89_kr.dat"
}
}
}
29 changes: 29 additions & 0 deletions cherab/openadas/library/library.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright 2014-2017 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.


import os
import json


LIBRARY_PATH = os.path.split(__file__)[0]

ADF11_FILES = json.load(open(os.path.join(LIBRARY_PATH, 'adf11.json')))
ADF11_PLT_FILES = ADF11_FILES['adf11_plt_files']
ADF11_PRB_FILES = ADF11_FILES['adf11_prb_files']



79 changes: 74 additions & 5 deletions cherab/openadas/openadas.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@
# under the Licence.

import os
import urllib.request

from cherab.core import AtomicData, Isotope
from cherab.core import AtomicData
from cherab.core.atomic.elements import Isotope
from pkg_resources import resource_filename
from cherab.core.utility.recursivedict import RecursiveDict

from cherab.openadas.read import adf12, adf15, adf21, adf22
from cherab.openadas.library import *
from cherab.openadas.read import adf11, adf12, adf15, adf21, adf22
from cherab.openadas.read.adf15 import add_adf15_to_atomic_data
from . import config
from .rates import *
from cherab.openadas.rates.radiated_power import StageResolvedRadiation


class OpenADAS(AtomicData):
Expand All @@ -32,8 +36,7 @@ def __init__(self, data_path=None, config=config.default, permit_extrapolation=F
super().__init__()
self._data_path = data_path or self._setup_data_path()

# configuration is immutable, changes to ADAS state are not tracked
self._config = config.copy()
self._config = config

# if true informs interpolation objects to allow extrapolation beyond the limits of the tabulated data
self._permit_extrapolation = permit_extrapolation
Expand Down Expand Up @@ -208,3 +211,69 @@ def recombination_rate(self, ion, ionisation, transition):
data = adf15(os.path.join(self._data_path, filename), block_number)
return RecombinationRate(wavelength, data, extrapolate=self._permit_extrapolation)

def stage_resolved_line_radiation_rate(self, ion, ionisation):

# extract element from isotope
if isinstance(ion, Isotope):
ion = ion.element

try:
plt_files = ADF11_PLT_FILES[ion.symbol]
except KeyError:
raise ValueError("No ADF11 files set for Ion - {}".format(ion.symbol))

absolute_file_path = self._check_for_adf_file(plt_files['ADAS_Path'], plt_files['Download_URL'])

densities, temperatures, rate_data = adf11(absolute_file_path, ion, ionisation)

name = 'Stage Resolved Line Radiation - ({}, {})'.format(ion.symbol, ionisation)
return StageResolvedRadiation(ion, ionisation, densities, temperatures, rate_data,
name=name, extrapolate=self._permit_extrapolation)

def stage_resolved_continuum_radiation_rate(self, ion, ionisation):

# extract element from isotope
if isinstance(ion, Isotope):
ion = ion.element

try:
prb_files = ADF11_PRB_FILES[ion.symbol]
except KeyError:
raise ValueError("No ADF11 files set for Ion - {}".format(ion.symbol))

absolute_file_path = self._check_for_adf_file(prb_files['ADAS_Path'], prb_files['Download_URL'])

densities, temperatures, rate_data = adf11(absolute_file_path, ion, ionisation)

name = 'Stage Resolved Continuum Radiation - ({}, {})'.format(ion.symbol, ionisation)

return StageResolvedRadiation(ion, ionisation, densities, temperatures, rate_data,
name=name, extrapolate=self._permit_extrapolation)

def _check_for_adf_file(self, relative_adf_file_path, download_path):

relative_adf_directory, adf_file_name = os.path.split(relative_adf_file_path)
absolute_adf_directory = os.path.join(self._data_path, relative_adf_directory)
absolute_file_path = os.path.join(absolute_adf_directory, adf_file_name)

if not os.path.exists(absolute_adf_directory):
os.makedirs(absolute_adf_directory)

if os.path.isfile(absolute_file_path):
return absolute_file_path
else:
urllib.request.urlretrieve(download_path, absolute_file_path)

return absolute_file_path

def add_adf15_file(self, element, ionisation, adf_file_path):

if not os.path.isfile(adf_file_path):
new_path = os.path.join(os.path.expanduser('~/.cherab/openadas'), adf_file_path)
if not os.path.isfile(new_path):
raise ValueError("Could not find ADF15 file - '{}'".format(adf_file_path))
adf_file_path = new_path

atomic_data_dict = RecursiveDict.from_dict(self._config)
atomic_data_dict = add_adf15_to_atomic_data(atomic_data_dict, element, ionisation, adf_file_path)
self._config = atomic_data_dict.freeze()
18 changes: 16 additions & 2 deletions cherab/openadas/rates/pec.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,14 @@ cdef class ImpactExcitationRate(CoreImpactExcitationRate):
)

cpdef double evaluate(self, double density, double temperature) except? -1e999:
return self._pec.evaluate(density, temperature)

cdef double rate

rate = self._pec.evaluate(density, temperature)
if rate < 0:
return 0.0

return rate


# todo: evaluate it the interpolation can be done without the log10 operations? or if this should be ported to the cx rates.
Expand All @@ -66,7 +73,14 @@ cdef class RecombinationRate(CoreRecombinationRate):


cpdef double evaluate(self, double density, double temperature) except? -1e999:
return self._pec.evaluate(density, temperature)

cdef double rate

rate = self._pec.evaluate(density, temperature)
if rate < 0:
return 0.0

return rate


# cdef class ThermalCXRate(CoreThermalCXRate):
Expand Down
58 changes: 58 additions & 0 deletions cherab/openadas/rates/radiated_power.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

# Copyright 2014-2017 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.

import numpy as np
from numpy cimport ndarray
from cherab.core.math.interpolators.interpolators2d cimport Interpolate2DCubic
from cherab.core.atomic.rates cimport StageResolvedLineRadiation as CoreStageResolvedLineRadiation


cdef class StageResolvedRadiation(CoreStageResolvedLineRadiation):

cdef:
readonly bint extrapolate
readonly tuple density_range, temperature_range
readonly ndarray _electron_density, _electron_temperature, _radiated_power
readonly Interpolate2DCubic _power_func

def __init__(self, element, ionisation, electron_density, electron_temperature, radiated_power, name='', extrapolate=False):

super().__init__(element, ionisation, name=name)

self._electron_density = np.array(electron_density, dtype=np.float64)
self._electron_temperature = np.array(electron_temperature, dtype=np.float64)
self._radiated_power = np.array(radiated_power, dtype=np.float64)

if not all(j >= 0 for i in self._radiated_power for j in i):
raise ValueError("Can't have negative power values!")

self.density_range = (self._electron_density.min(), self._electron_density.max())
self.temperature_range = (self._electron_temperature.min(), self._electron_temperature.max())

self.extrapolate = extrapolate
self._power_func = Interpolate2DCubic(self._electron_density, self._electron_temperature, self._radiated_power,
extrapolate=extrapolate, extrapolation_type="nearest")

cdef double evaluate(self, double electron_density, double electron_temperature) except? -1e999:
cdef double rate
rate = self._power_func.evaluate(electron_density, electron_temperature)
if rate < 0:
print("Warning - negative power encountered!")
print("ne - {:.4G}, te - {:.3G}, rate - {:.4G}".format(electron_density, electron_temperature, rate))
return rate
# return self._power_func.evaluate(electron_density, electron_temperature)

1 change: 1 addition & 0 deletions cherab/openadas/read/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# under the Licence.


from .adf11 import adf11
from .adf12 import adf12
from .adf15 import adf15
from .adf21 import adf21
Expand Down
Loading