From 9fac641e81b109457cbb4d17ccf1bcb3a9259fec Mon Sep 17 00:00:00 2001 From: munechika-koyo Date: Tue, 25 Aug 2026 15:55:36 +0200 Subject: [PATCH] Refactor documentation and code comments for clarity and consistency - Updated parameter descriptions in `build_constant_slab_plasma` to use proper formatting for units. - Changed class definitions in `pipelines.py` to remove unnecessary parentheses and improved unit formatting in comments. - Modified documentation in `custom_models.rst` to reference the correct class path for `InhomogeneousVolumeEmitter`. - Enhanced mathematical notation in `charge_exchange_calculation.rst` for better readability and consistency. - Corrected unit formatting across various documentation files to use LaTeX-style notation for clarity. --- cherab/core/atomic/interface.pyx | 38 ++-- cherab/core/atomic/rates.pyx | 58 +++--- cherab/core/beam/model.pyx | 11 +- cherab/core/beam/node.pyx | 40 +++-- cherab/core/distribution.pyx | 51 +++--- cherab/core/laser/profile.pyx | 32 ++-- cherab/core/model/attenuator/singleray.pyx | 33 ++-- cherab/core/model/beam/charge_exchange.pyx | 9 +- cherab/core/model/laser/laserspectrum.pyx | 12 +- cherab/core/model/laser/math_functions.pyx | 28 +-- cherab/core/model/laser/model.pyx | 55 +++--- cherab/core/model/laser/profile.pyx | 164 ++++++++--------- cherab/core/model/lineshape/gaussian.pyx | 2 +- cherab/core/model/lineshape/stark.pyx | 23 ++- cherab/core/model/lineshape/zeeman.pyx | 21 +-- cherab/core/model/plasma/bremsstrahlung.pyx | 26 +-- .../core/model/plasma/impact_excitation.pyx | 10 +- cherab/core/model/plasma/recombination.pyx | 10 +- cherab/core/model/plasma/thermal_cx.pyx | 16 +- .../model/plasma/total_radiated_power.pyx | 12 +- cherab/core/plasma/model.pyx | 14 +- cherab/core/plasma/node.pyx | 46 ++--- cherab/tools/emitters/radiation_function.pyx | 2 +- cherab/tools/inversions/sart.pyx | 50 +++--- cherab/tools/plasmas/ionisation_balance.py | 155 ++++++++-------- cherab/tools/plasmas/slab.pyx | 4 +- cherab/tools/raytransfer/pipelines.py | 34 ++-- docs/source/conf.py | 2 +- docs/source/models/custom_models.rst | 26 +-- .../cxs/charge_exchange_calculation.rst | 165 +++++++++--------- 30 files changed, 587 insertions(+), 562 deletions(-) diff --git a/cherab/core/atomic/interface.pyx b/cherab/core/atomic/interface.pyx index 52c396d6..9cdb736e 100644 --- a/cherab/core/atomic/interface.pyx +++ b/cherab/core/atomic/interface.pyx @@ -38,71 +38,71 @@ cdef class AtomicData: cpdef IonisationRate ionisation_rate(self, Element ion, int charge): """ - Electron impact ionisation rate for a given species in m^3/s. + Electron impact ionisation rate for a given species in m\\ :sup:`3`/s. """ raise NotImplementedError("The ionisation_rate() virtual method is not implemented for this atomic data source.") cpdef RecombinationRate recombination_rate(self, Element ion, int charge): """ - Recombination rate for a given species in m^3/s. + Recombination rate for a given species in m\\ :sup:`3`/s. """ raise NotImplementedError("The recombination_rate() virtual method is not implemented for this atomic data source.") cpdef ThermalCXRate thermal_cx_rate(self, Element donor_ion, int donor_charge, Element receiver_ion, int receiver_charge): """ - Thermal charge exchange effective rate coefficient for a given donor and receiver species in m^3/s. + Thermal charge exchange effective rate coefficient for a given donor and receiver species in m\\ :sup:`3`/s. """ raise NotImplementedError("The thermal_cx_rate() virtual method is not implemented for this atomic data source.") cpdef list beam_cx_pec(self, Element donor_ion, Element receiver_ion, int receiver_charge, tuple transition): """ - A list of Effective charge exchange photon emission coefficient for a given donor (beam) in W.m^3. + A list of Effective charge exchange photon emission coefficient for a given donor (beam) in W m\\ :sup:`3`. """ - raise NotImplementedError("The cxs_rates() virtual method is not implemented for this atomic data source.") + raise NotImplementedError("The beam_cx_pec() virtual method is not implemented for this atomic data source.") cpdef BeamStoppingRate beam_stopping_rate(self, Element beam_ion, Element plasma_ion, int charge): """ - Beam stopping coefficient for a given beam and target species in m^3/s. + Beam stopping coefficient for a given beam and target species in m\\ :sup:`3`/s. """ - raise NotImplementedError("The beam_stopping() virtual method is not implemented for this atomic data source.") + raise NotImplementedError("The beam_stopping_rate() virtual method is not implemented for this atomic data source.") cpdef BeamPopulationRate beam_population_rate(self, Element beam_ion, int metastable, Element plasma_ion, int charge): """ Dimensionless Beam population coefficient for a given beam and target species. """ - raise NotImplementedError("The beam_population() virtual method is not implemented for this atomic data source.") + raise NotImplementedError("The beam_population_rate() virtual method is not implemented for this atomic data source.") cpdef BeamEmissionPEC beam_emission_pec(self, Element beam_ion, Element plasma_ion, int charge, tuple transition): """ The beam photon emission coefficient for a given beam and target species - and a given transition in W.m^3. + and a given transition in W m\\ :sup:`3`. """ - raise NotImplementedError("The beam_emission() virtual method is not implemented for this atomic data source.") + raise NotImplementedError("The beam_emission_pec() virtual method is not implemented for this atomic data source.") cpdef ImpactExcitationPEC impact_excitation_pec(self, Element ion, int charge, tuple transition): """ - Electron impact excitation photon emission coefficient for a given species in W.m^3. + Electron impact excitation photon emission coefficient for a given species in W m\\ :sup:`3`. """ - raise NotImplementedError("The impact_excitation() virtual method is not implemented for this atomic data source.") + raise NotImplementedError("The impact_excitation_pec() virtual method is not implemented for this atomic data source.") cpdef RecombinationPEC recombination_pec(self, Element ion, int charge, tuple transition): """ - Recombination photon emission coefficient for a given species in W.m^3. + Recombination photon emission coefficient for a given species in W m\\ :sup:`3`. """ - raise NotImplementedError("The recombination() virtual method is not implemented for this atomic data source.") + raise NotImplementedError("The recombination_pec() virtual method is not implemented for this atomic data source.") cpdef ThermalCXPEC thermal_cx_pec(self, Element donor_ion, int donor_charge, Element receiver_ion, int receiver_charge, tuple transition): """ - Thermal charge exchange photon emission coefficient for given donor and receiver species in W.m^3. + Thermal charge exchange photon emission coefficient for given donor and receiver species in W m\\ :sup:`3`. """ raise NotImplementedError("The thermal_cx_pec() virtual method is not implemented for this atomic data source.") @@ -110,28 +110,28 @@ cdef class AtomicData: cpdef TotalRadiatedPower total_radiated_power(self, Element element): """ The total (summed over all charge states) radiated power - in equilibrium conditions for a given species in W.m^3. + in equilibrium conditions for a given species in W m\\ :sup:`3`. """ raise NotImplementedError("The total_radiated_power() virtual method is not implemented for this atomic data source.") cpdef LineRadiationPower line_radiated_power_rate(self, Element element, int charge): """ - Line radiated power coefficient for a given species in W.m^3. + Line radiated power coefficient for a given species in W m\\ :sup:`3`. """ raise NotImplementedError("The line_radiated_power_rate() virtual method is not implemented for this atomic data source.") cpdef ContinuumPower continuum_radiated_power_rate(self, Element element, int charge): """ - Continuum radiated power coefficient for a given species in W.m^3. + Continuum radiated power coefficient for a given species in W m\\ :sup:`3`. """ raise NotImplementedError("The continuum_radiated_power_rate() virtual method is not implemented for this atomic data source.") cpdef CXRadiationPower cx_radiated_power_rate(self, Element element, int charge): """ - Charge exchange radiated power coefficient for a given species in W.m^3. + Charge exchange radiated power coefficient for a given species in W m\\ :sup:`3`. """ raise NotImplementedError("The cx_radiated_power_rate() virtual method is not implemented for this atomic data source.") diff --git a/cherab/core/atomic/rates.pyx b/cherab/core/atomic/rates.pyx index 913ddde3..25e91430 100644 --- a/cherab/core/atomic/rates.pyx +++ b/cherab/core/atomic/rates.pyx @@ -35,9 +35,9 @@ cdef class IonisationRate: cpdef double evaluate(self, double density, double temperature) except? -1e999: """Returns an effective ionisation rate coefficient at the specified plasma conditions. - :param density: Electron density in m^-3. + :param density: Electron density in m\\ :sup:`-3`. :param temperature: Electron temperature in eV. - :return: The effective ionisation rate in m^3.s^-1. + :return: The effective ionisation rate in m\\ :sup:`3` s\\ :sup:`-1`. """ raise NotImplementedError("The evaluate() virtual method must be implemented.") @@ -57,9 +57,9 @@ cdef class RecombinationRate: cpdef double evaluate(self, double density, double temperature) except? -1e999: """Returns an effective recombination rate coefficient at the specified plasma conditions. - :param density: Electron density in m^-3. + :param density: Electron density in m\\ :sup:`-3`. :param temperature: Electron temperature in eV. - :return: The effective ionisation rate in m^3.s^-1. + :return: The effective ionisation rate in m\\ :sup:`3` s\\ :sup:`-1`. """ raise NotImplementedError("The evaluate() virtual method must be implemented.") @@ -79,9 +79,9 @@ cdef class ThermalCXRate: cpdef double evaluate(self, double density, double temperature) except? -1e999: """Returns an effective charge exchange rate coefficient at the specified plasma conditions. - :param density: Electron density in m^-3. + :param density: Electron density in m\\ :sup:`-3`. :param temperature: Electron temperature in eV. - :return: The effective charge exchange rate in m^3.s^-1. + :return: The effective charge exchange rate in m\\ :sup:`3` s\\ :sup:`-1`. """ raise NotImplementedError("The evaluate() virtual method must be implemented.") @@ -101,9 +101,9 @@ cdef class _PECRate: cpdef double evaluate(self, double density, double temperature) except? -1e999: """Returns a photon emissivity coefficient at given conditions. - :param density: Electron density in m^-3. + :param density: Electron density in m\\ :sup:`-3`. :param temperature: Electron temperature in eV. - :return: The effective PEC rate in W.m^3. + :return: The effective PEC rate in W m\\ :sup:`3`. """ raise NotImplementedError("The evaluate() virtual method must be implemented.") @@ -145,21 +145,21 @@ cdef class ThermalCXPEC: cpdef double evaluate(self, double electron_density, double electron_temperature, double donor_temperature) except? -1e999: """Returns a CX photon emissivity coefficient at given conditions. - :param electron_density: Electron density in m^-3. + :param electron_density: Electron density in m\\ :sup:`-3`. :param electron_temperature: Electron temperature in eV. :param donor_temperature: Donor temperature in eV. - :return: The effective CX PEC rate in W/m^3. + :return: The effective CX PEC rate in W/m\\ :sup:`3`. """ raise NotImplementedError("The evaluate() virtual method must be implemented.") cdef class BeamCXPEC: - r""":math:`q^{eff}_{n\rightarrow n'}` [:math:`W.m^{3}`] + r""":math:`q^\mathrm{eff}_{n\rightarrow n'}` [W/m\\ :sup:`3`] Effective emission coefficient (or rate) for a charge-exchange line corresponding to a transition :math:`n\rightarrow n'` of ion :math:`Z^{(\alpha+1)+}` with electron donor :math:`H^0` in metastable state :math:`m_{i}`. Equivalent to - :math:`q^{eff}_{n\rightarrow n'}` in `adf12 _`. + :math:`q^\mathrm{eff}_{n\rightarrow n'}` in `adf12 _`. :param donor_metastable: The metastable state of the donor species for which the rate data applies. """ @@ -179,7 +179,7 @@ cdef class BeamCXPEC: :param float energy: Interaction energy in eV/amu. :param float temperature: Receiver ion temperature in eV. - :param float density: Plasma total ion density in m^-3 + :param float density: Plasma total ion density in m\\ :sup:`-3` :param float z_effective: Plasma Z-effective. :param float b_field: Magnetic field magnitude in Tesla. :return: The effective rate @@ -197,7 +197,7 @@ cdef class _BeamRate: Returns the beam coefficient for the supplied parameters. :param energy: Interaction energy in eV/amu. - :param density: Target electron density in m^-3 + :param density: Target electron density in m\\ :sup:`-3` :param temperature: Target temperature in eV. :return: The beam coefficient """ @@ -208,34 +208,34 @@ cdef class _BeamRate: cdef class BeamStoppingRate(_BeamRate): - """:math:`S^{e, i}_{CR}` [:math:`m^3.s^{-1}`] + """:math:`S^{\\mathrm{e}, \\mathrm{i}}_\\mathrm{CR}` [m\\ :sup:`3` s\\ :sup:`-1`] - The effective collisional radiative stopping coefficient :math:`S^{e, i}_{CR}` - [:math:`m^3.s^{-1}`] for neutral atom :math:`X^0` in a mono-energetic beam by + The effective collisional radiative stopping coefficient :math:`S^{\\mathrm{e}, \\mathrm{i}}_\\mathrm{CR}` + [m\\ :sup:`3` s\\ :sup:`-1`] for neutral atom :math:`X^0` in a mono-energetic beam by fully stripped ions :math:`Y^i` and their electrons. - Equivalent to :math:`S^{e, i}_{CR}` as defined in ADAS `adf21 `_. + Equivalent to :math:`S^{\\mathrm{e}, \\mathrm{i}}_\\mathrm{CR}` as defined in ADAS `adf21 `_. """ pass cdef class BeamPopulationRate(_BeamRate): - """:math:`bmp(X^0(m_i))` [dimensionless] + """:math:`\\mathrm{bmp}(X^0(m_i))` [dimensionless] - Relative beam population of excited state :math:`m_i` over ground state for atom :math:`X^0`, :math:`bmp(X^0(m_i))`. + Relative beam population of excited state :math:`m_i` over ground state for atom :math:`X^0`, :math:`\\mathrm{bmp}(X^0(m_i))`. - The rate :math:`bmp(X^0(m_i))` is equivalent to the :math:`BMP` rate as defined in + The rate :math:`\\mathrm{bmp}(X^0(m_i))` is equivalent to the :math:`BMP` rate as defined in `adf22 `_ and is dimensionless. """ pass cdef class BeamEmissionPEC(_BeamRate): - """:math:`bme(X^0(m_i))` [:math:`W.m^3`] + """:math:`\\mathrm{bme}(X^0(m_i))` [W m\\ :sup:`3`] - The effective beam emission coefficient, :math:`bme(X^0(m_i))`. + The effective beam emission coefficient, :math:`\\mathrm{bme}(X^0(m_i))`. - The rate :math:`bme(X^0(m_i))` is equivalent to the :math:`BME` rate as defined in + The rate :math:`\\mathrm{bme}(X^0(m_i))` is equivalent to the :math:`BME` rate as defined in `adf22 `_. """ pass @@ -260,10 +260,10 @@ cdef class TotalRadiatedPower(): """ Evaluate the total radiated power rate at the given plasma conditions. - :param float electron_density: Electron density in m^-3. + :param float electron_density: Electron density in m\\ :sup:`-3`. :param float electron_temperature: Electron temperature in eV. - :return: The total radiated power rate in W.m^3. + :return: The total radiated power rate in W.m\\ :sup:`3`. """ raise NotImplementedError("The evaluate() virtual method must be implemented.") @@ -288,10 +288,10 @@ cdef class _RadiatedPower: """ Evaluate the radiated power at the given plasma conditions. - :param float density: Electron density in m^-3. + :param float density: Electron density in m\\ :sup:`-3`. :param float temperature: Electron temperature in eV. - :return: The radiated power rate in W.m^3. + :return: The radiated power rate in W m\\ :sup:`3`. """ raise NotImplementedError("The evaluate() virtual method must be implemented.") @@ -345,7 +345,7 @@ cdef class FractionalAbundance: """ Evaluate the fractional abundance of this ionisation stage at the given plasma conditions. - :param float electron_density: Electron density in m^-3. + :param float electron_density: Electron density in m\\ :sup:`-3`. :param float electron_temperature: Electron temperature in eV. :return: Fractional abundance. diff --git a/cherab/core/beam/model.pyx b/cherab/core/beam/model.pyx index 4c84508d..c8bc651f 100644 --- a/cherab/core/beam/model.pyx +++ b/cherab/core/beam/model.pyx @@ -89,7 +89,7 @@ cdef class BeamModel: Models implementing this method must add their spectral response to the supplied spectrum object. The spectrum units are spectral radiance per - meter (W/m^3/str/nm). + meter (W/m\\ :sup:`3`/str/nm). :param beam_point: Point in beam space. :param plasma_point: Point in plasma space. @@ -187,10 +187,11 @@ cdef class BeamAttenuator: The point is specified in beam space. - :param x: x coordinate in meters. - :param y: y coordinate in meters. - :param z: z coordinate in meters. - :return: Density in m^-3. + :param float x: x coordinate in meters. + :param float y: y coordinate in meters. + :param float z: z coordinate in meters. + :return: Density in m\\ :sup:`-3`. + :rtype: float """ raise NotImplementedError("Virtual function density not defined.") diff --git a/cherab/core/beam/node.pyx b/cherab/core/beam/node.pyx index 32d7291d..5fc11a18 100644 --- a/cherab/core/beam/node.pyx +++ b/cherab/core/beam/node.pyx @@ -124,7 +124,7 @@ cdef class Beam(Node): :ivar AtomicData atomic_data: The atomic data provider class for this beam. All beam emission and attenuation rates will be calculated from the same provider. :ivar BeamAttenuator attenuator: The method used for calculating the attenuation - of this beam into the plasma. Defaults to a SingleRayAttenuator(). + of this beam into the plasma. Defaults to a `.SingleRayAttenuator`. :ivar float divergence_x: The beam profile divergence in the x dimension in beam coordinates (degrees). :ivar float divergence_y: The beam profile divergence in the y dimension in beam @@ -133,7 +133,7 @@ cdef class Beam(Node): :ivar float energy: The beam energy in eV/amu. :ivar VolumeIntegrator integrator: The configurable method for doing volumetric integration through the beam along a Ray's path. Defaults to - a numerical integrator with 1mm step size, NumericalIntegrator(step=0.001). + a numerical integrator with 1mm step size, `NumericalIntegrator(step=0.001)`. :ivar float length: The approximate length of this beam from source to extinction in the plasma. This is used for setting the bounding geometry over which calculations will occur. Units of m. @@ -213,15 +213,16 @@ cdef class Beam(Node): cpdef double density(self, double x, double y, double z) except? -1e999: """ - Returns the bean density at the specified position in beam coordinates. - - Note: this function is only defined over the domain 0 < z < beam_length. + Return the beam density at the specified position in beam coordinates. + + Note: this function is only defined over the domain `0 < z < beam_length`. Outside of this range the density is clamped to zero. - - :param x: x coordinate in meters. - :param y: y coordinate in meters. - :param z: z coordinate in meters. - :return: Beam density in m^-3 + + :param float x: x coordinate in meters. + :param float y: y coordinate in meters. + :param float z: z coordinate in meters. + :return: Beam density in m\\ :sup:`-3`. + :rtype: float """ if self._attenuator is None: @@ -240,11 +241,11 @@ cdef class Beam(Node): The beam direction (non-normalised) is calculated as follows (z > 0): .. math:: - e_x = x\frac{(ztg(\alpha_x))^2}{\sigma^2 + (ztg(\alpha_x))^2}, + e_x &= x\frac{(\mathrm{ztg}(\alpha_x))^2}{\sigma^2 + (\mathrm{ztg}(\alpha_x))^2}, - e_y = y\frac{(ztg(\alpha_y))^2}{\sigma^2 + (ztg(\alpha_y))^2}, + e_y &= y\frac{(\mathrm{ztg}(\alpha_y))^2}{\sigma^2 + (\mathrm{ztg}(\alpha_y))^2}, - e_z = z, + e_z &= z, where :math:`\sigma` is the Gaussian beam deviation at origin, :math:`\alpha_x` and :math:`\alpha_y` are the beam divergence angles @@ -253,14 +254,15 @@ cdef class Beam(Node): For z <= 0 the beam direction is (0, 0, 1). The function returns normalised beam direction. - + Note the values of the beam outside of the beam envelope should be treated with caution. - - :param x: x coordinate in meters. - :param y: y coordinate in meters. - :param z: z coordinate in meters. + + :param float x: x coordinate in meters. + :param float y: y coordinate in meters. + :param float z: z coordinate in meters. :return: Direction vector. + :rtype: Vector3D """ # if behind the beam just return the beam axis (for want of a better value) @@ -416,7 +418,7 @@ cdef class Beam(Node): @property def attenuator(self): return self._attenuator - + @attenuator.setter def attenuator(self, BeamAttenuator value not None): diff --git a/cherab/core/distribution.pyx b/cherab/core/distribution.pyx index 6f8bad61..6926df50 100644 --- a/cherab/core/distribution.pyx +++ b/cherab/core/distribution.pyx @@ -56,21 +56,23 @@ cdef class DistributionFunction: :param float vx: velocity in meters per second :param float vy: velocity in meters per second :param float vz: velocity in meters per second - :return: phase space density in s^3/m^6 + :return: phase space density in s\\ :sup:`3`/m\\ :sup:`6` + :rtype: float """ return self.evaluate(x, y, z, vx, vy, vz) cdef double evaluate(self, double x, double y, double z, double vx, double vy, double vz) except? -1e999: """ Evaluates the phase space density at the specified point in 6D phase space. - + :param float x: position in meters :param float y: position in meters :param float z: position in meters :param float vx: velocity in meters per second :param float vy: velocity in meters per second :param float vz: velocity in meters per second - :return: phase space density in s^3/m^6 + :return: phase space density in s\\ :sup:`3`/m\\ :sup:`6` + :rtype: float """ raise NotImplementedError() @@ -105,7 +107,7 @@ cdef class DistributionFunction: :param float x: position in meters :param float y: position in meters :param float z: position in meters - :return: density in m^-3 + :return: density in m\\ :sup:`-3` :rtype: float """ raise NotImplementedError() @@ -133,21 +135,23 @@ cdef class ZeroDistribution(DistributionFunction): :param float vx: velocity in meters per second :param float vy: velocity in meters per second :param float vz: velocity in meters per second - :return: phase space density 0 s^3/m^6 + :return: phase space density 0 s\\ :sup:`3`/m\\ :sup:`6` + :rtype: float """ return self.evaluate(x, y, z, vx, vy, vz) cdef double evaluate(self, double x, double y, double z, double vx, double vy, double vz) except? -1e999: """ Evaluates the phase space density at the specified point in 6D phase space. - + :param float x: position in meters :param float y: position in meters :param float z: position in meters :param float vx: velocity in meters per second :param float vy: velocity in meters per second :param float vz: velocity in meters per second - :return: phase space density 0 s^3/m^6 + :return: phase space density 0 s\\ :sup:`3`/m\\ :sup:`6` + :rtype: float """ return 0.0 @@ -182,7 +186,7 @@ cdef class ZeroDistribution(DistributionFunction): :param float x: position in meters :param float y: position in meters :param float z: position in meters - :return: density 0 m^-3 + :return: density 0 m\\ :sup:`-3` :rtype: float """ return 0.0 @@ -235,7 +239,8 @@ cdef class Maxwellian(DistributionFunction): :param vx: velocity in meters per second :param vy: velocity in meters per second :param vz: velocity in meters per second - :return: phase space density in s^3/m^6 + :return: phase space density in s\\ :sup:`3`/m\\ :sup:`6` + :rtype: float """ cdef: @@ -260,7 +265,7 @@ cdef class Maxwellian(DistributionFunction): :param y: position in meters :param z: position in meters :return: velocity vector in m/s - + .. code-block:: pycon >>> d0_distribution.bulk_velocity(1, 0, 0) @@ -276,9 +281,9 @@ cdef class Maxwellian(DistributionFunction): :param y: position in meters :param z: position in meters :return: temperature in eV - + .. code-block:: pycon - + >>> d0_distribution.effective_temperature(1, 0, 0) 1.0 """ @@ -291,7 +296,8 @@ cdef class Maxwellian(DistributionFunction): :param x: position in meters :param y: position in meters :param z: position in meters - :return: density in m^-3 + :return: density in m\\ :sup:`-3` + :rtype: float .. code-block:: pycon @@ -307,15 +313,15 @@ cdef class GenericDistribution(DistributionFunction): A generic distribution function. This class implements a generic distribution function. The user supplies a 6D function - that provides the phase space density at a given point in 6D phase space, + that provides the phase space density at a given point in 6D phase space, a 3D function that provides the spatial density, a 3D function that provides the temperature, and a 3D vector function that provides the bulk velocity. .. warning:: The consistency of the provided functions is not checked and is the responsibilty of the user. - :param Function6D phase_space_density: 6D function defining the phase space density in s^3/m^6. - :param Function3D density: 3D function defining the spatial density in m^-3. + :param Function6D phase_space_density: 6D function defining the phase space density in s\\ :sup:`3`/m\\ :sup:`6`. + :param Function3D density: 3D function defining the spatial density in m\\ :sup:`-3`. :param Function3D temperature: 3D function defining the temperature in eV. :param VectorFunction3D velocity: 3D vector function defining the bulk velocity in meters per second. @@ -351,7 +357,8 @@ cdef class GenericDistribution(DistributionFunction): :param vx: velocity in meters per second :param vy: velocity in meters per second :param vz: velocity in meters per second - :return: phase space density in s^3/m^6 + :return: phase space density in s\\ :sup:`3`/m\\ :sup:`6` + :rtype: float """ return self._phase_space_density.evaluate(x, y, z, vx, vy, vz) @@ -364,7 +371,7 @@ cdef class GenericDistribution(DistributionFunction): :param y: position in meters :param z: position in meters :return: velocity vector in m/s - + .. code-block:: pycon >>> d0_distribution.bulk_velocity(1, 0, 0) @@ -380,9 +387,10 @@ cdef class GenericDistribution(DistributionFunction): :param y: position in meters :param z: position in meters :return: temperature in eV - + :rtype: float + .. code-block:: pycon - + >>> d0_distribution.effective_temperature(1, 0, 0) 1.0 """ @@ -395,7 +403,8 @@ cdef class GenericDistribution(DistributionFunction): :param x: position in meters :param y: position in meters :param z: position in meters - :return: density in m^-3 + :return: density in m\\ :sup:`-3` + :rtype: float .. code-block:: pycon diff --git a/cherab/core/laser/profile.pyx b/cherab/core/laser/profile.pyx index 6356d1cb..1693d961 100644 --- a/cherab/core/laser/profile.pyx +++ b/cherab/core/laser/profile.pyx @@ -31,11 +31,11 @@ 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 + 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 + 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 @@ -80,7 +80,7 @@ cdef class LaserProfile: of the Poynting vector. :param VectorFunction3D function: A 3D vector function describing - the laser light propagation direction + the laser light propagation direction """ self._pointing3d = function @@ -92,7 +92,7 @@ cdef class LaserProfile: 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. @@ -102,7 +102,7 @@ cdef class LaserProfile: :param x: x coordinate in meters. :param y: y coordinate in meters. :param z: z coordinate in meters. - :return: Intensity in m^-3. + :return: Intensity in m\\ :sup:`-3`. """ return self._pointing3d.evaluate(x, y, z) @@ -118,21 +118,21 @@ cdef class LaserProfile: :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: power density in ·m\\ :sup:`-3`. """ - return self._polarization3d(x, y, z) + return self._polarization3d.evaluate(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. - + Returns the volumetric energy density of the laser light in W·m\\ :sup:`-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: power density in W·m\\ :sup:`-3`. """ return self._energy_density3d.evaluate(x, y, z) @@ -140,17 +140,17 @@ cdef class LaserProfile: 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 + 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.") - + raise NotImplementedError("Virtual function `generate_geometry` not defined.") + def _change(self): """ Called if the laser properties change. diff --git a/cherab/core/model/attenuator/singleray.pyx b/cherab/core/model/attenuator/singleray.pyx index bfa7c701..58b4b1b9 100644 --- a/cherab/core/model/attenuator/singleray.pyx +++ b/cherab/core/model/attenuator/singleray.pyx @@ -110,33 +110,34 @@ cdef class SingleRayAttenuator(BeamAttenuator): The beam density is calculated as follows: .. math:: - n(x, y, z) = \frac{R}{2\pi v_0 \sigma_x\sigma_y} exp\left(-\frac{1}{2}\left(\frac{x^2}{\sigma_x^2}+\frac{y^2}{\sigma_y^2}\right)\right)exp\left(-\int_{0}^{z}\frac{S(z')}{v_0}dz'\right), + n(x, y, z) = \frac{R}{2\pi v_0 \sigma_x\sigma_y} \exp\left(-\frac{1}{2}\left(\frac{x^2}{\sigma_x^2}+\frac{y^2}{\sigma_y^2}\right)\right)\exp\left(-\int_{0}^{z}\frac{S(z')}{v_0}dz'\right), - \sigma_x = \sqrt{\sigma^2 + (ztg(\alpha_x))^2}\hspace{0.5cm}\sigma_y = \sqrt{\sigma^2 + (ztg(\alpha_y))^2}, + \sigma_x = \sqrt{\sigma^2 + (ztg(\alpha_x))^2},\quad\sigma_y = \sqrt{\sigma^2 + (ztg(\alpha_y))^2}, where :math:`R=\frac{P}{E}` is the particle rate of the beam defined as the power of the beam divided by the kinetic energy of the single particle, :math:`v_0=\sqrt{2E/m}` is the particle speed, :math:`\sigma` is the Gaussian beam deviation at origin, - :math:`\alpha_x` and :math:`\alpha_y` are the beam divergence angles in the x and y + :math:`\alpha_x` and :math:`\alpha_y` are the beam divergence angles in the :math:`x` and :math:`y` dimensions respectively, :math:`S(z)` is the composite beam attenuation coefficient due to collisional-radiative interaction with the plasma species: .. math:: - S(z) = \sum_{i=1}^{N}Z_i n_i S_i(E_{int}, n_{i,e}^{(eq)}, T_i), + S(z) = \sum_{i=1}^{N}Z_i n_i S_i(E_\mathrm{int}, n_{i,e}^{(\mathrm{eq})}, T_i), - n_{i,e}^{(eq)} = \frac{1}{Z_i}\sum_{j=1}^{N}Z_j^2 n_j. + n_{i,\mathrm{e}}^{(\mathrm{eq})} = \frac{1}{Z_i}\sum_{j=1}^{N}Z_j^2 n_j. - Here :math:`Z_i` is the charge of the i-th type of plasma ions, + Here :math:`Z_i` is the charge of the :math:`i` -th type of plasma ions, :math:`n_i` is density of the i-th type of plasma ions, :math:`N` is the number of type of plasma - ions, :math:`E_{int}` is the kinetic energy of the beam atoms in the frame of reference where + ions, :math:`E_\mathrm{int}` is the kinetic energy of the beam atoms in the frame of reference where ions of the i-th type are at rest, :math:`T_{i}` is the temperature of ions of the i-th type. The values of partial beam attenuation coefficients, :math:`S_i`, are provided by the atomic data source. - - :param x: x coordinate in meters. - :param y: y coordinate in meters. - :param z: z coordinate in meters. - :return: Density in m^-3. + + :param float x: x coordinate in meters. + :param float y: y coordinate in meters. + :param float z: z coordinate in meters. + :returns: Density in m\ :sup:`-3`. + :rtype: float """ cdef double sigma0_sqr, sigma_x, sigma_y, norm_radius_sqr, gaussian_sample @@ -182,9 +183,9 @@ cdef class SingleRayAttenuator(BeamAttenuator): cdef void _calc_attenuation(self): """ Attenuation is calculated along the beam axis and extrapolated across the beam. - + Fill attribute '_density' with a 1D function taking meters as argument - and returning a linear density in m^-1, calculated along the beam axis. + and returning a linear density in m\\ :sup:`-1`, calculated along the beam axis. """ cdef: @@ -239,7 +240,7 @@ cdef class SingleRayAttenuator(BeamAttenuator): :param power: beam power in W :param mass: atomic mass in amu :param direction: - :return: a list of linear densities in m^-1 + :return: a list of linear densities in m\\ :sup:`-1` """ cdef: @@ -271,7 +272,7 @@ cdef class SingleRayAttenuator(BeamAttenuator): :param y: position in meters :param z: position in meters :param beam_velocity: beam velocity in m/s - :return: a stopping coefficient in s^-1 + :return: a stopping coefficient in s\\ :sup:`-1` """ # see www.adas.ac.uk/man/chap3-04.pdf equation 4.4.7 diff --git a/cherab/core/model/beam/charge_exchange.pyx b/cherab/core/model/beam/charge_exchange.pyx index 4b5c292e..a512d0e1 100644 --- a/cherab/core/model/beam/charge_exchange.pyx +++ b/cherab/core/model/beam/charge_exchange.pyx @@ -45,15 +45,14 @@ cdef double ms_to_evamu(double x): cdef class BeamCXLine(BeamModel): """ - Calculates emission produced by charge-exchange of plasma ions - with beam species. + Calculates emission produced by charge-exchange of plasma ions with beam species. :param Line line: The emission line object. :param Beam beam: The beam object. :param Plasma plasma: The emitting plasma object. :param AtomicData atomic_data: The atomic data provider. - :param object lineshape: The spectral line shape class. Must be a subclass of `LineShapeModel`. - Defaults to `GaussianLine`. + :param object lineshape: The spectral line shape class. Must be a subclass of `.LineShapeModel`. + Defaults to `.GaussianLine`. :param object lineshape_args: The arguments of spectral line shape class. Defaults is None. :param object lineshape_kwargs: The keyword arguments of spectral line shape class. Defaults is None. @@ -189,7 +188,7 @@ cdef class BeamCXLine(BeamModel): :param interaction_energy: The donor-receiver interaction energy in eV/amu. :param donor_velocity: A Vector defining the donor particle velocity in m/s. :param receiver_temperature: The receiver species temperature in eV. - :return: The composite charge exchange rate in W.m^3. + :return: The composite charge exchange rate in W m\\ :sup:`3`. """ cdef: diff --git a/cherab/core/model/laser/laserspectrum.pyx b/cherab/core/model/laser/laserspectrum.pyx index 58c1cada..116ee3d0 100644 --- a/cherab/core/model/laser/laserspectrum.pyx +++ b/cherab/core/model/laser/laserspectrum.pyx @@ -26,13 +26,13 @@ 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 + between the `.min_wavelength` and `.max_wavelength`. The integral value of the power is 1 W. .. note:: - The ConstantSpectrum class is suitable for approximation + The `.ConstantSpectrum` class is suitable for approximation of an infinitely thin laser spectrum, e.g.: - ConstantSpectrum(1063.9, 1064.1, 1) + ``ConstantSpectrum(1063.9, 1064.1, 1)`` """ def __init__(self, double min_wavelength, double max_wavelength, int bins): @@ -45,7 +45,7 @@ cdef class ConstantSpectrum(LaserSpectrum): :param float x: Wavelength in nm. - :return: Power spectral density in W/nm. + :return: Power spectral density in W/nm. """ cdef: @@ -69,7 +69,7 @@ cdef class GaussianSpectrum(LaserSpectrum): 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 @@ -114,7 +114,7 @@ cdef class GaussianSpectrum(LaserSpectrum): :param float x: Wavelength in nm. - :return: Power spectral density in W/nm. + :return: Power spectral density in W/nm. """ return self._normalisation * exp(-0.5 * ((x - self._mean) * self._recip_stddev) ** 2) diff --git a/cherab/core/model/laser/math_functions.pyx b/cherab/core/model/laser/math_functions.pyx index 1ed73a61..8abccd54 100644 --- a/cherab/core/model/laser/math_functions.pyx +++ b/cherab/core/model/laser/math_functions.pyx @@ -26,14 +26,15 @@ from libc.math cimport sqrt, exp, pi cdef class ConstantAxisymmetricGaussian3D(Function3D): - """ + r""" 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) + + 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 + 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. @@ -67,11 +68,12 @@ cdef class ConstantAxisymmetricGaussian3D(Function3D): cdef class ConstantBivariateGaussian3D(Function3D): - """ + r""" 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) + + 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. @@ -130,11 +132,12 @@ cdef class ConstantBivariateGaussian3D(Function3D): cdef class TrivariateGaussian3D(Function3D): - """ + r""" 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) + + 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. @@ -221,21 +224,24 @@ cdef class TrivariateGaussian3D(Function3D): cdef class GaussianBeamModel(Function3D): - """ + r""" 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) + + 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} + + \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} + + z_R = \frac{\pi \omega_0^2 n}{\lambda_l} is the Rayleigh range. """ diff --git a/cherab/core/model/laser/model.pyx b/cherab/core/model/laser/model.pyx index 5c78a055..189f7a57 100644 --- a/cherab/core/model/laser/model.pyx +++ b/cherab/core/model/laser/model.pyx @@ -35,26 +35,29 @@ cdef class SeldenMatobaThomsonSpectrum(LaserModel): 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 + of the scattered laser light :math:`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 + c(\lambda) = c r_\mathrm{e}^2 n_\mathrm{e} \cos^2\theta \sum_{\lambda_\mathrm{L}} \frac{E_\mathrm{L}(\lambda_\mathrm{L}) S\left(\frac{\lambda}{\lambda_\mathrm{L}} - 1, \varphi, T_\mathrm{e}\right)}{\lambda_\mathrm{L}}, + + + where :math:`\lambda` is the spectrum's wavelength, :math:`r_\mathrm{e}` is the classical electron radius, :math:`n_\mathrm{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_\mathrm{L}` is the laser wavelength, :math:`E_\mathrm{L}` is the laser energy density, :math:`\varphi` is the scattering angle and :math:`T_\mathrm{e}` is the electron + temperature. The scattering function :math:`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 + The Prunty article provides a thorough introduction into the physics 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.` + + :Selden: Selden, A.C., 1980. "*Simple analytic form of the relativistic Thomson scattering spectrum*." + Physics Letters A, **79** (5-6), pp.405-406. `DOI: 10.1016/0375-9601(80)90276-5 `_ + :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. `DOI: 10.1143/JJAP.18.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. + `DOI: 10.1088/0031-8949/89/12/128001 `_ """ @@ -64,11 +67,11 @@ cdef class SeldenMatobaThomsonSpectrum(LaserModel): # 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 + # 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 @@ -107,13 +110,13 @@ cdef class SeldenMatobaThomsonSpectrum(LaserModel): # 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 @@ -145,7 +148,7 @@ cdef class SeldenMatobaThomsonSpectrum(LaserModel): bins = self._laser_spectrum.get_spectral_bins() for index in range(bins): - laser_energy = laser_spectrum_power_mv[index] * laser_energy_density + 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) @@ -167,8 +170,8 @@ cdef class SeldenMatobaThomsonSpectrum(LaserModel): 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 + + # pre-calculate constants for Selden-Matoba shape const_theta = 2 * (1 - cos_anglescat) nbins = spectrum.bins @@ -193,18 +196,18 @@ cdef class SeldenMatobaThomsonSpectrum(LaserModel): 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 ne: Plasma electron density in m\\ :sup:`-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_energy_density: Energy density of the laser light in J/m\\ :sup:`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 @@ -216,5 +219,3 @@ cdef class SeldenMatobaThomsonSpectrum(LaserModel): 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.pyx b/cherab/core/model/laser/profile.pyx index ed5f6024..4111a344 100644 --- a/cherab/core/model/laser/profile.pyx +++ b/cherab/core/model/laser/profile.pyx @@ -4,7 +4,7 @@ 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.model.laser.math_functions cimport ConstantAxisymmetricGaussian3D, ConstantBivariateGaussian3D, TrivariateGaussian3D, GaussianBeamModel from cherab.core.utility.constants cimport SPEED_OF_LIGHT @@ -22,20 +22,20 @@ cdef class UniformEnergyDensity(LaserProfile): 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: + and volumetric energy density of 5 J·m\\ :sup:`-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) @@ -108,10 +108,10 @@ cdef class UniformEnergyDensity(LaserProfile): cpdef list generate_geometry(self): return generate_segmented_cylinder(self.laser_radius, self.laser_length) - + cdef class ConstantBivariateGaussian(LaserProfile): - """ + r""" LaserProfile with a Gaussian-shaped volumetric energy density distribution in the xy plane and constant pulse intensity. @@ -120,36 +120,36 @@ cdef class ConstantBivariateGaussian(LaserProfile): 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. + .. math:: + E_{xy} = \frac{E_\mathrm{p}}{(c \cdot \tau)}, + + where :math:`E_\mathrm{p}` is the energy of the laser pulse, :math:`\tau` is the temporal pulse length and :math:`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). + E(x, y) = \frac{E_{xy}}{2 \pi \sigma_x \sigma_y} \exp\left(-\frac{x^2}{2 \sigma_x^2} - \frac{y^2}{2 \sigma_y^2}\right). - The sigma_x and sigma_y are standard deviations in x and y directions, respectively. + The :math:`\sigma_x` and :math:`\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 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 + + 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) outside 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 + + The following example shows how to create a laser with :math:`\sigma_x= 1` cm and :math:`\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 @@ -157,7 +157,7 @@ cdef class ConstantBivariateGaussian(LaserProfile): >>> 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) @@ -287,15 +287,15 @@ cdef class ConstantBivariateGaussian(LaserProfile): 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]. + """Energy density should be returned in units [J/m\\ :sup:`-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\\ :sup:`-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]. + of light `SPEED_OF_LIGHT` and the temporal duration of the pulse: + ``length = SPEED_OF_LIGHT * pulse_length``. Combining the normal distribution with the normalisation + ``pulse_energy / length`` gives the units [J / m\\ :sup:`3`]. """ self._distribution = ConstantBivariateGaussian3D(self._stddev_x, self._stddev_y) @@ -311,45 +311,45 @@ cdef class ConstantBivariateGaussian(LaserProfile): cdef class TrivariateGaussian(LaserProfile): - """ + r""" 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). + E(x, y, z) = \frac{E_\mathrm{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: + The :math:`\sigma_x` and :math:`\sigma_y` are standard deviations in x and y directions, respectively, and :math:`E_\mathrm{p}` is the energy delivered by laser in a + single laser pulse. The :math:`\mu_z` is the mean of the distribution in the z direction and controls the position of the laser pulse along the z direction. + The standard deviation in z direction :math:`\sigma_z` is calculated from the pulse length :math:`\tau_\mathrm{p}`, which is the + standard deviation of the Gaussian distributed output power of the laser within a single pulse: .. math:: - \\sigma_z = \\tau_p c. + \sigma_z = \tau_\mathrm{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 height of the cylinder, forming the laser beam, is given by `.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 + + 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) outside 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 + + The following example shows how to create a laser with :math:`\sigma_x = 1` cm and :math:`\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: + 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 - + >>> from cherab.core.model.laser import TrivariateGaussian + >>> radius = 3e-2 # laser radius in m >>> length = 2 # laser length in m >>> polarisation = Vector3D(0, 1, 0) # polarisation direction @@ -358,9 +358,9 @@ cdef class TrivariateGaussian(LaserProfile): >>> 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) + >>> laser_profile = TrivariateGaussian(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. @@ -505,14 +505,14 @@ cdef class TrivariateGaussian(LaserProfile): 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. + Energy density should be returned in units [J/m\\ :sup:`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 + normalisation = self._pulse_energy function = normalisation * self._distribution self.set_energy_density_function(function) @@ -522,7 +522,7 @@ cdef class TrivariateGaussian(LaserProfile): return generate_segmented_cylinder(self.laser_radius, self.laser_length) cdef class GaussianBeamAxisymmetric(LaserProfile): - """ + r""" 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 @@ -530,42 +530,42 @@ cdef class GaussianBeamAxisymmetric(LaserProfile): 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) \\\\ + 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}. + \sigma(z) = \sigma_0 \sqrt{1 + \left(\frac{z - z_0}{z_\mathrm{R}}\right)^2}. - The z_0 is the position of the beam focus and z_R is the Rayleigh length + The :math:`z_0` is the position of the beam focus and :math:`z_\mathrm{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: - + z_\mathrm{R} = \frac{\pi \omega_0^2 n}{\lambda_\mathrm{l}} + + where the :math:`\omega_0` is the standard deviation in the xy plane in the focal point (beam waist) and :math:`\lambda_\mathrm{l}` is the central wavelength of + the laser. The :math:`E_{xy}` stand for the laser energy in an xy plane and is calculated as: + .. math:: - E_{xy} = \\frac{E_p}{(c * \\tau)}, + E_{xy} = \frac{E_\mathrm{p}}{(c \cdot \tau)}, - where the E_p is the energy in a single laser pulse and tau is the temporal pulse length. + where the :math:`E_\mathrm{p}` is the energy in a single laser pulse and :math:`\tau` is the temporal pulse length. - .. note:: + .. 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 + 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) outside 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. + The following example shows how to create a laser with pulse energy 5 J, pulse length 10 ns and with the laser cylinder primitive + being 2 m long with 5 cm in diameter. The the standard deviation of the beam in the focal point (waist) is 5 mm and the position of the + waist is :math:`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 @@ -576,7 +576,7 @@ cdef class GaussianBeamAxisymmetric(LaserProfile): >>> 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) @@ -709,15 +709,15 @@ cdef class GaussianBeamAxisymmetric(LaserProfile): 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]. + """Energy density should be returned in units [J/m\\ :sup:`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\\ :sup:`-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]. + of light `SPEED_OF_LIGHT` and the temporal duration of the pulse: + ``length = SPEED_OF_LIGHT * pulse_length``. Combining the normal distribution with the normalisation + ``pulse_energy / length`` gives the units [J / m\\ :sup:`3`]. """ self._distribution = GaussianBeamModel(self._laser_wavelength, self._waist_z, self._stddev_waist) @@ -761,5 +761,5 @@ def generate_segmented_cylinder(radius, 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/lineshape/gaussian.pyx b/cherab/core/model/lineshape/gaussian.pyx index ef854ea9..bc0228ed 100644 --- a/cherab/core/model/lineshape/gaussian.pyx +++ b/cherab/core/model/lineshape/gaussian.pyx @@ -42,7 +42,7 @@ cpdef Spectrum add_gaussian_line(double radiance, double wavelength, double sigm Adds a Gaussian line to the given spectrum and returns the new spectrum. The formula used is based on the following definite integral: - :math:`\frac{1}{\sigma \sqrt{2 \pi}} \int_{\lambda_0}^{\lambda_1} \exp(-\frac{(x-\mu)^2}{2\sigma^2}) dx = \frac{1}{2} \left[ -Erf(\frac{a-\mu}{\sqrt{2}\sigma}) +Erf(\frac{b-\mu}{\sqrt{2}\sigma}) \right]` + :math:`\frac{1}{\sigma \sqrt{2 \pi}} \int_{\lambda_0}^{\lambda_1} \exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right) \mathrm{d}x = \frac{1}{2} \left[ -\mathrm{Erf}\left(\frac{a-\mu}{\sqrt{2}\sigma}\right) +\mathrm{Erf}\left(\frac{b-\mu}{\sqrt{2}\sigma}\right) \right]` :param float radiance: Intensity of the line in radiance. :param float wavelength: central wavelength of the line in nm. diff --git a/cherab/core/model/lineshape/stark.pyx b/cherab/core/model/lineshape/stark.pyx index 8b16f174..29206608 100644 --- a/cherab/core/model/lineshape/stark.pyx +++ b/cherab/core/model/lineshape/stark.pyx @@ -90,7 +90,7 @@ cpdef Spectrum add_lorentzian_line(double radiance, double wavelength, double la Adds a modified Lorentzian line to the given spectrum and returns the new spectrum. The modified Lorentzian: - :math:`L(\lambda-\lambda_0, \Delta\lambda_{1/2}^{(L)})=\frac{C_0(\Delta\lambda_{1/2}^{(L)})^{3/2}}{(\lambda-\lambda_0)^{5/2}+(\frac{\Delta\lambda_{1/2}^{(L)}}{2})^{5/2}},` + :math:`L(\lambda-\lambda_0, \Delta\lambda_{1/2}^{(L)})=\frac{C_0\left(\Delta\lambda_{1/2}^{(L)}\right)^{3/2}}{(\lambda-\lambda_0)^{5/2}+\left(\frac{\Delta\lambda_{1/2}^{(L)}}{2}\right)^{5/2}},` :math:`C_0=\frac{(1/2)^{3/2}}{4R{_2}F_1(\frac{2}{5},1,\frac{7}{5},-R^{5/2})},` @@ -107,7 +107,7 @@ cpdef Spectrum add_lorentzian_line(double radiance, double wavelength, double la :param Spectrum spectrum: the current spectrum to which the Lorentzian line is added. :param Integrator1D integrator: Integrator1D instance to integrate the line shape over the spectral bin. - :return: + :return: the updated Spectrum instance. """ cdef double cutoff_lower_wavelength, cutoff_upper_wavelength @@ -170,7 +170,7 @@ cdef class StarkBroadenedLine(ZeemanLineShapeModel): :math:`C_0=\frac{(1/2)^{3/2}}{4R{_2}F_1(\frac{2}{5},1,\frac{7}{5},-R^{5/2})},` where :math:`\Delta\lambda_{1/2}^{(L)}=c_{ij}\frac{n_e^{a_{ij}}}{T_e^{b_{ij}}}` is the line FWHM, - :math:`{_2}F_1` is the hypergeometric function and :math:`R=50`. + :math:`{_2}F_1` is the hypergeometric function and :math:`R=50`. The line shape is truncated at :math:`\lambdaR\Delta\lambda_{1/2}^{(L)}`. The :math:`a_{ij}`, :math:`b_{ij}` and :math:`c_{ij}` are the fitting coefficients. @@ -178,7 +178,7 @@ cdef class StarkBroadenedLine(ZeemanLineShapeModel): and Doppler (Gauss), :math:`G(\lambda'-\lambda_0, \Delta\lambda_{1/2}^{(G)})` profiles: :math:`\eta L(\lambda-\lambda_0, \Delta\lambda_{1/2}^{(V)}) + (1-\eta)G(\lambda-\lambda_0, \Delta\lambda_{1/2}^{(V)})`, - + with :math:`\Delta\lambda_{1/2}^{(V)}\equiv \Delta\lambda_{1/2}^{(V)}(\Delta\lambda_{1/2}^{(G)}, \Delta\lambda_{1/2}^{(L)})` and :math:`\eta\equiv \eta(\Delta\lambda_{1/2}^{(G)}, \Delta\lambda_{1/2}^{(L)})`. @@ -192,26 +192,25 @@ cdef class StarkBroadenedLine(ZeemanLineShapeModel): :math:`\Delta\lambda_{1/2}^{(V)}=\sum_{n=0}^{6}b_n(\frac{\Delta\lambda_{1/2}^{(G)}}{\Delta\lambda_{1/2}^{(L)}})^n` for :math:`\frac{\Delta\lambda_{1/2}^{(L)}}{\Delta\lambda_{1/2}^{(G)}} > 1` with - `a` = [1., 0.15882, 1.04388, -1.38281, 0.46251, 0.82325, -0.58026] and + :math:`a_n \in \{1, 0.15882, 1.04388, -1.38281, 0.46251, 0.82325, -0.58026\}` and - `b` = [1., 0, 0.57575, 0.37902, -0.42519, -0.31525, 0.31718]. + :math:`b_n \in \{1, 0, 0.57575, 0.37902, -0.42519, -0.31525, 0.31718\}`. While the :math:`\eta` function is fitted as: - :math:`\eta=exp(\sum_{n=0}^{5}c_n(ln(\frac{\Delta\lambda_{1/2}^{(L)}}{\Delta\lambda_{1/2}^{(V)}}))^n` + :math:`\eta=\exp\left(\sum_{n=0}^{5}c_n\left(\ln\left(\frac{\Delta\lambda_{1/2}^{(L)}}{\Delta\lambda_{1/2}^{(V)}}\right)\right)^n\right)` for :math:`0.01<\frac{\Delta\lambda_{1/2}^{(L)}}{\Delta\lambda_{1/2}^{(V)}}<0.999` with - `c` = [5.14820e-04, 1.38821e+00, -9.60424e-02, -3.83995e-02, -7.40042e-03, -5.47626e-04]. + :math:`c_n \in \{5.14820\times 10^{-4}, 1.38821, -9.60424\times 10^{-2}, -3.83995\times 10^{-2}, -7.40042\times 10^{-3}, -5.47626\times 10^{-4}\}`. :param Line line: The emission line object for this line shape. :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 AtomicData atomic_data: The atomic data provider. - :param tuple stark_model_coefficients: Stark model coefficients in the form (c_ij, a_ij, b_ij). - Default is None (will use - `atomic_data.stark_model_coefficients`). + :param tuple stark_model_coefficients: Stark model coefficients in the form (:math:`c_{ij}`, :math:`a_{ij}`, :math:`b_{ij}`). + Default is None (will use `~.AtomicData.stark_model_coefficients`). :param Integrator1D integrator: Integrator1D instance to integrate the line shape - over the spectral bin. Default is `GaussianQuadrature1D()`. + over the spectral bin. Default is `.GaussianQuadrature1D`. :param str polarisation: Leaves only :math:`\pi`-/:math:`\sigma`-polarised components: "pi" - leave only :math:`\pi`-polarised components, "sigma" - leave only :math:`\sigma`-polarised components, diff --git a/cherab/core/model/lineshape/zeeman.pyx b/cherab/core/model/lineshape/zeeman.pyx index 2be33020..cc9dd13a 100644 --- a/cherab/core/model/lineshape/zeeman.pyx +++ b/cherab/core/model/lineshape/zeeman.pyx @@ -163,18 +163,19 @@ cdef class ZeemanTriplet(ZeemanLineShapeModel): cdef class ParametrisedZeemanTriplet(ZeemanLineShapeModel): - r""" - Parametrised Doppler-Zeeman triplet. It takes into account additional broadening due to + r"""Parametrised Doppler-Zeeman triplet. + + It takes into account additional broadening due to the line's fine structure without resolving the individual components of the fine structure. The model is described with three parameters: :math:`\alpha`, :math:`\beta` and :math:`\gamma`. - The distance between :math:`\sigma^+` and :math:`\sigma^-` peaks: - :math:`\Delta \lambda_{\sigma} = \alpha B`, - where `B` is the magnetic field strength. - The ratio between Zeeman and thermal broadening line widths: - :math:`\frac{W_{Zeeman}}{W_{Doppler}} = \beta T^{\gamma}`, - where `T` is the species temperature in eV. + The distance between :math:`\sigma^+` and :math:`\sigma^-` peaks: + :math:`\Delta \lambda_{\sigma} = \alpha B`, + where :math:`B` is the magnetic field strength. + The ratio between Zeeman and thermal broadening line widths: + :math:`\frac{W_\mathrm{Zeeman}}{W_\mathrm{Doppler}} = \beta T^{\gamma}`, + where :math:`T` is the species temperature in eV. For details see A. Blom and C. Jupén, Parametrisation of the Zeeman effect for hydrogen-like spectra in high-temperature plasmas, @@ -187,7 +188,7 @@ cdef class ParametrisedZeemanTriplet(ZeemanLineShapeModel): :param Plasma plasma: The emitting plasma object. :param AtomicData atomic_data: The atomic data provider. :param tuple line_parameters: Parameters of the model in the form (alpha, beta, gamma). - Default is None (will use `atomic_data.zeeman_triplet_parameters`). + Default is None (will use `~.AtomicData.zeeman_triplet_parameters`). :param str polarisation: Leaves only :math:`\pi`-/:math:`\sigma`-polarised components: "pi" - leave central component, "sigma" - leave side components, @@ -286,7 +287,7 @@ cdef class ZeemanMultiplet(ZeemanLineShapeModel): :param zeeman_structure: A ``ZeemanStructure`` object that provides wavelengths and ratios of :math:`\pi`-/:math:`\sigma^{+}`-/:math:`\sigma^{-}`-polarised components for any given magnetic field strength. - Default is None (will use atomic_data.zeeman_structure). + Default is None (will use `~.AtomicData.zeeman_structure`). :param str polarisation: Leaves only :math:`\pi`-/:math:`\sigma`-polarised components: "pi" - leave only :math:`\pi`-polarised components, "sigma" - leave only :math:`\sigma`-polarised components, diff --git a/cherab/core/model/plasma/bremsstrahlung.pyx b/cherab/core/model/plasma/bremsstrahlung.pyx index 453489d5..71222e2e 100644 --- a/cherab/core/model/plasma/bremsstrahlung.pyx +++ b/cherab/core/model/plasma/bremsstrahlung.pyx @@ -92,7 +92,7 @@ cdef class BremsFunction(Function1D): # todo: doppler shift? cdef class Bremsstrahlung(PlasmaModel): - """ + r""" Emitter that calculates bremsstrahlung emission from a plasma object. The bremmstrahlung formula implemented is equation 5.3.40 @@ -100,22 +100,22 @@ cdef class Bremsstrahlung(PlasmaModel): Cambridge University Press, 2002, ISBN: 9780511613630, https://doi.org/10.1017/CBO9780511613630 - Note that in eq. 5.3.40, the emissivity :math:`j(\\nu)` is given in (W/m^3/sr/Hz) with respect - to frequency, :math:`\\nu`. Here, the emissivity :math:`\\epsilon_{\\mathrm{ff}}(\\lambda)` - is given in (W/m^3/nm/sr) with respect to wavelength, :math:`\\lambda = \\frac{10^{9} c}{\\nu}`, - and taking into account that :math:`d\\nu=-\\frac{10^{9} c}{\\lambda^2}d\\lambda`. + Note that in eq. 5.3.40, the emissivity :math:`j(\nu)` is given in (W/m\ :sup:`3`/sr/Hz) with respect + to frequency, :math:`\nu`. Here, the emissivity :math:`\epsilon_{\mathrm{ff}}(\lambda)` + is given in (W/m\ :sup:`3`/nm/sr) with respect to wavelength, :math:`\lambda = \frac{10^{9} c}{\nu}`, + and taking into account that :math:`\mathrm{d}\nu=-\frac{10^{9} c}{\lambda^2}\mathrm{d}\lambda`. .. math:: - \\epsilon_{\\mathrm{ff}}(\\lambda) = \\left( \\frac{e^2}{4 \\pi \\varepsilon_0} \\right)^3 - \\frac{32 \\pi^2}{3 \\sqrt{3} m_\\mathrm{e}^2 c^3} - \\sqrt{\\frac{2 m_\\mathrm{e}^3}{\\pi e T_\\mathrm{e}}} - \\frac{10^{9} c}{4 \\pi \\lambda^2} - n_\\mathrm{e} \\sum_i \\left( n_\\mathrm{i} g_\\mathrm{ff} (Z_\\mathrm{i}, T_\\mathrm{e}, \\lambda) Z_\\mathrm{i}^2 \\right) - \\mathrm{e}^{-\\frac{10^9 hc}{e T_\\mathrm{e} \\lambda}}\\,, + \epsilon_{\mathrm{ff}}(\lambda) = \left( \frac{e^2}{4 \pi \varepsilon_0} \right)^3 + \frac{32 \pi^2}{3 \sqrt{3} m_\mathrm{e}^2 c^3} + \sqrt{\frac{2 m_\mathrm{e}^3}{\pi e T_\mathrm{e}}} + \frac{10^{9} c}{4 \pi \lambda^2} + n_\mathrm{e} \sum_i \left( n_\mathrm{i} g_\mathrm{ff} (Z_\mathrm{i}, T_\mathrm{e}, \lambda) Z_\mathrm{i}^2 \right) + \exp\left(-\frac{10^9 hc}{e T_\mathrm{e} \lambda}\right)\,, - where :math:`T_\\mathrm{e}` is in eV and :math:`\\lambda` is in nm. + where :math:`T_\mathrm{e}` is in eV and :math:`\lambda` is in nm. - :math:`g_\\mathrm{ff} (Z_\\mathrm{i}, T_\\mathrm{e}, \\lambda)` is the free-free Gaunt factor. + :math:`g_\mathrm{ff} (Z_\mathrm{i}, T_\mathrm{e}, \lambda)` is the free-free Gaunt factor. :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. diff --git a/cherab/core/model/plasma/impact_excitation.pyx b/cherab/core/model/plasma/impact_excitation.pyx index 5c12d94f..3a68ad85 100644 --- a/cherab/core/model/plasma/impact_excitation.pyx +++ b/cherab/core/model/plasma/impact_excitation.pyx @@ -41,12 +41,12 @@ cdef class ExcitationLine(PlasmaModel): :param Line line: Spectroscopic emission line object. :param Plasma plasma: The plasma to which this emission model is attached. Default is None. :param AtomicData atomic_data: The atomic data provider for this model. Default is None. - :param object lineshape: Line shape model class. Default is None (GaussianLine). + :param object lineshape: Line shape model class. Default is None (`.GaussianLine`). :param object lineshape_args: A list of line shape model arguments. Default is None. :param object lineshape_kwargs: A dictionary of line shape model keyword arguments. Default is None. - :ivar Plasma plasma: See parameter 'plasma'. - :ivar AtomicData atomic_data: See parameter 'atomic_data'. + :ivar Plasma plasma: See parameter `.plasma`. + :ivar AtomicData atomic_data: See parameter `.atomic_data`. :ivar Line line: The emission line object. :ivar LineShapeModel lineshape: The line shape model. """ @@ -80,11 +80,11 @@ cdef class ExcitationLine(PlasmaModel): @property def line(self) -> Line: return self._line - + @property def lineshape(self) -> LineShapeModel: return self._lineshape - + cpdef Spectrum emission(self, Point3D point, Vector3D direction, Spectrum spectrum): cdef double ne, ni, te, radiance diff --git a/cherab/core/model/plasma/recombination.pyx b/cherab/core/model/plasma/recombination.pyx index 7f85dad8..2a0cb6d7 100644 --- a/cherab/core/model/plasma/recombination.pyx +++ b/cherab/core/model/plasma/recombination.pyx @@ -41,12 +41,12 @@ cdef class RecombinationLine(PlasmaModel): :param Line line: Spectroscopic emission line object. :param Plasma plasma: The plasma to which this emission model is attached. Default is None. :param AtomicData atomic_data: The atomic data provider for this model. Default is None. - :param object lineshape: Line shape model class. Default is None (GaussianLine). + :param object lineshape: Line shape model class. Default is None (`.GaussianLine`). :param object lineshape_args: A list of line shape model arguments. Default is None. :param object lineshape_kwargs: A dictionary of line shape model keyword arguments. Default is None. - :ivar Plasma plasma: See parameter 'plasma'. - :ivar AtomicData atomic_data: See parameter 'atomic_data'. + :ivar Plasma plasma: See parameter `.plasma`. + :ivar AtomicData atomic_data: See parameter `.atomic_data`. :ivar Line line: The emission line object. :ivar LineShapeModel lineshape: The line shape model. """ @@ -80,11 +80,11 @@ cdef class RecombinationLine(PlasmaModel): @property def line(self) -> Line: return self._line - + @property def lineshape(self) -> LineShapeModel: return self._lineshape - + cpdef Spectrum emission(self, Point3D point, Vector3D direction, Spectrum spectrum): cdef double ne, ni, te, radiance diff --git a/cherab/core/model/plasma/thermal_cx.pyx b/cherab/core/model/plasma/thermal_cx.pyx index e0943a14..5b79d3e9 100644 --- a/cherab/core/model/plasma/thermal_cx.pyx +++ b/cherab/core/model/plasma/thermal_cx.pyx @@ -30,25 +30,25 @@ cdef class ThermalCXLine(PlasmaModel): .. math:: \epsilon_{\mathrm{CX}}(\lambda) = \frac{1}{4 \pi} n_{Z_\mathrm{i} + 1} - \sum_j{n_{Z_\mathrm{j}} \mathrm{PEC}_{\mathrm{cx}}(n_\mathrm{e}, T_\mathrm{e}, T_{Z_\mathrm{j}})} + \sum_j{n_{Z_j} \mathrm{PEC}_{\mathrm{cx}}(n_\mathrm{e}, T_\mathrm{e}, T_{Z_j})} f(\lambda), where :math:`n_{Z_\mathrm{i} + 1}` is the receiver species density, - :math:`n_{Z_\mathrm{j}}` is the donor species density, + :math:`n_{Z_j}` is the donor species density, :math:`\mathrm{PEC}_{\mathrm{cx}}` is the thermal CX photon emission coefficient for the specified spectral line of the :math:`Z_\mathrm{i}` ion, - :math:`T_{Z_\mathrm{j}}` is the donor species temperature, + :math:`T_{Z_j}` is the donor species temperature, :math:`f(\lambda)` is the normalised spectral line shape, :param Line line: Spectroscopic emission line object. :param Plasma plasma: The plasma to which this emission model is attached. Default is None. :param AtomicData atomic_data: The atomic data provider for this model. Default is None. - :param object lineshape: Line shape model class. Default is None (GaussianLine). + :param object lineshape: Line shape model class. Default is None (`.GaussianLine`). :param object lineshape_args: A list of line shape model arguments. Default is None. :param object lineshape_kwargs: A dictionary of line shape model keyword arguments. Default is None. - :ivar Plasma plasma: See parameter 'plasma'. - :ivar AtomicData atomic_data: See parameter 'atomic_data'. + :ivar Plasma plasma: See parameter `.plasma`. + :ivar AtomicData atomic_data: See parameter `.atomic_data`. :ivar Line line: The emission line object. :ivar LineShapeModel lineshape: The line shape model. """ @@ -82,11 +82,11 @@ cdef class ThermalCXLine(PlasmaModel): @property def line(self) -> Line: return self._line - + @property def lineshape(self) -> LineShapeModel: return self._lineshape - + cpdef Spectrum emission(self, Point3D point, Vector3D direction, Spectrum spectrum): cdef: diff --git a/cherab/core/model/plasma/total_radiated_power.pyx b/cherab/core/model/plasma/total_radiated_power.pyx index f0c94281..b53da587 100644 --- a/cherab/core/model/plasma/total_radiated_power.pyx +++ b/cherab/core/model/plasma/total_radiated_power.pyx @@ -37,7 +37,7 @@ cdef class TotalRadiatedPower(PlasmaModel): .. math:: \epsilon_{\mathrm{total}} = \frac{1}{4 \pi \Delta\lambda} \left( - n_{Z_\mathrm{i}} n_\mathrm{e} C_{\mathrm{excit}}(n_\mathrm{e}, T_\mathrm{e}) + + n_{Z_\mathrm{i}} n_\mathrm{e} C_{\mathrm{excit}}(n_\mathrm{e}, T_\mathrm{e}) + n_{Z_\mathrm{i} + 1} n_\mathrm{e} C_{\mathrm{recomb}}(n_\mathrm{e}, T_\mathrm{e}) + n_{Z_\mathrm{i} + 1} n_\mathrm{hyd} C_{\mathrm{cx}}(n_\mathrm{e}, T_\mathrm{e}) \right) @@ -45,7 +45,7 @@ cdef class TotalRadiatedPower(PlasmaModel): :math:`n_{Z_\mathrm{i} + 1}` is the recombining species density; :math:`n_{\mathrm{hyd}}` is the total density of all hydrogen isotopes; :math:`C_{\mathrm{excit}}, C_{\mathrm{recomb}}, C_{\mathrm{cx}}` are the radiated power - coefficients in :math:`W m^3` due to electron impact excitation, recombination + coefficients in Wm\ :sup:`3` due to electron impact excitation, recombination + Bremsstrahlung and charge exchange with thermal neutral hydrogen, respectively; :math:`\Delta\lambda` is the observable spectral range. @@ -54,8 +54,8 @@ cdef class TotalRadiatedPower(PlasmaModel): :param Plasma plasma: The plasma to which this emission model is attached. Default is None. :param AtomicData atomic_data: The atomic data provider for this model. Default is None. - :ivar Element element: See parameter 'element'. - :ivar int charge: See parameter 'charge'. + :ivar Element element: See parameter `.element`. + :ivar int charge: See parameter `.charge`. """ def __init__(self, Element element, int charge, Plasma plasma=None, AtomicData atomic_data=None): @@ -71,11 +71,11 @@ cdef class TotalRadiatedPower(PlasmaModel): # ensure that cache is initialised self._change() - + @property def element(self) -> Element: return self._element - + @property def charge(self) -> int: return self._charge diff --git a/cherab/core/plasma/model.pyx b/cherab/core/plasma/model.pyx index 6d5b906b..f8cbf081 100644 --- a/cherab/core/plasma/model.pyx +++ b/cherab/core/plasma/model.pyx @@ -25,11 +25,11 @@ cdef class PlasmaModel: for a particular point and viewing orientation in plasma space. A new emission model is implemented by inheriting from this class and specifying - the emission() function. + the `emission()` function. If it is necessary to cache data to speed up the emission calculation and there is a risk the cached data may be made stale by changes to the - plasma, the _change() method must be implemented to reset the cache. The _change() + plasma, the `_change()` method must be implemented to reset the cache. The `_change()` function is automatically called when changes occur on the Plasma object. The plasma and atomic data provider attributes will be automatically populated @@ -45,7 +45,7 @@ cdef class PlasmaModel: self._plasma = plasma self._atomic_data = atomic_data - # setup change notification is we have been given a plasma object + # setup change notification if we have been given a plasma object if self._plasma: self._plasma.notifier.add(self._change) @@ -85,11 +85,11 @@ cdef class PlasmaModel: Models implementing this method must add their spectral response to the supplied spectrum object. The spectrum units are spectral radiance per - meter (W/m^3/str/nm). - + meter (W/m\\ :sup:`3`/str/nm). + If a model has a directional response, the model should pass through - its own reference axis e.g. Thomsen scattering laser direction. - + its own reference axis e.g. Thomsen scattering laser direction. + :param point: Point in plasma space. :param direction: Direction in plasma space. :param spectrum: Spectrum to which emission should be added. diff --git a/cherab/core/plasma/node.pyx b/cherab/core/plasma/node.pyx index 96f687ca..0fda8789 100644 --- a/cherab/core/plasma/node.pyx +++ b/cherab/core/plasma/node.pyx @@ -87,9 +87,9 @@ cdef class Composition: to the composition. :param Species species: A list containing the new species. - + .. code-block:: pycon - + >>> d0_species = Species(deuterium, 0, d0_distribution) >>> d1_species = Species(deuterium, 1, d1_distribution) >>> plasma.composition.set([d0_species, d1_species]) @@ -116,14 +116,14 @@ cdef class Composition: cpdef object add(self, Species species): """ Adds a species to the plasma composition. - + Replaces any existing species with the same element and charge state already in the composition. - + :param Species species: A Species object. - + .. code-block:: pycon - + >>> d1_species = Species(deuterium, 1, d1_distribution) >>> plasma.composition.add(d1_species) """ @@ -137,13 +137,13 @@ cdef class Composition: cpdef Species get(self, Element element, int charge): """ Get a specified plasma species. - + Raises a ValueError if the specified species is not found in the composition. - + :param Element element: The element object of the requested species. :param int charge: The charge state of the requested species. :return: The requested Species object. - + .. code-block:: pycon >>> plasma.composition.get(deuterium, 1) @@ -419,18 +419,19 @@ cdef class Plasma(Node): Calculates the effective Z of the plasma. .. math:: - Z_{eff} = \sum_{j=1}^N n_{i(j)} Z_j^2 / \sum_{k=1}^N n_{i(k)} Z_k + Z_\mathrm{eff} = \sum_{j=1}^N n_{\mathrm{i}(j)} Z_j^2 / \sum_{k=1}^N n_{\mathrm{i}(k)} Z_k where n is the species density and Z is the ionisation of the species. - :param x: x coordinate in meters. - :param y: y coordinate in meters. - :param z: z coordinate in meters. + :param float x: x coordinate in meters. + :param float y: y coordinate in meters. + :param float z: z coordinate in meters. :return: Calculated Z effective. + :rtype: float :raises ValueError: If plasma does not contain any ionised species. - + .. code-block:: pycon - + >>> # With an already initialised plasma object... >>> plasma.z_effective(1, 1, 1) 1.0 @@ -460,15 +461,16 @@ cdef class Plasma(Node): Calculates the total ion density of the plasma. .. math:: - n_I = \sum_{k=1}^N n_i(k) + n_I = \sum_{k=1}^N n_{\mathrm{i}(k)} + + :param float x: x coordinate in meters. + :param float y: y coordinate in meters. + :param float z: z coordinate in meters. + :return: Total ion density in m\ :sup:`-3`. + :rtype: float - :param x: x coordinate in meters. - :param y: y coordinate in meters. - :param z: z coordinate in meters. - :return: Total ion density in m^-3. - .. code-block:: pycon - + >>> # With an already initialised plasma object... >>> plasma.ion_density(1, 1, 1) 1.1e+18 diff --git a/cherab/tools/emitters/radiation_function.pyx b/cherab/tools/emitters/radiation_function.pyx index a4a89f63..976663e9 100644 --- a/cherab/tools/emitters/radiation_function.pyx +++ b/cherab/tools/emitters/radiation_function.pyx @@ -40,7 +40,7 @@ cdef class RadiationFunction(InhomogeneousVolumeEmitter): evaluation takes place in the correct coordinate system. :param Function3D radiation_function: A 3D radiation function that specifies the amount of radiation - to be radiated at a given point, :math:`\phi(x, y, z)` [W/m^3]. + to be radiated at a given point, :math:`\phi(x, y, z)` [W/m\\ :sup:`3`]. :param float step: The scale length for integration of the radiation function. .. code-block:: pycon diff --git a/cherab/tools/inversions/sart.pyx b/cherab/tools/inversions/sart.pyx index 12d28769..6dc95a47 100644 --- a/cherab/tools/inversions/sart.pyx +++ b/cherab/tools/inversions/sart.pyx @@ -27,29 +27,29 @@ cpdef invert_sart(geometry_matrix, measurement_vector, object initial_guess=None double relaxation=1.0, double conv_tol=1.0E-4): r""" Performs a SART inversion on the specified measurement vector. - + This function implements the Simultaneous Algebraic Reconstruction Technique (SART), as published in - A. Andersen, and A. Kak, Ultrasonic imaging 6, 81 (1984). The SART method is an iterative inversion + A. Andersen, and A. Kak, Ultrasonic imaging 6, 81 (1984). The SART method is an iterative inversion scheme where the source cells are updated with the formula .. math:: - x_l^{(i+1)} = f_{sart}(x_l^{(i)}) = x_l^{(i)} + \\frac{\omega}{W_{\oplus,l}} \sum_{k=1}^{N_d} \\frac{W_{k,l}}{W_{k,\oplus}} (\Phi_k - \hat{\Phi}_k), + x_l^{(i+1)} = f_\mathrm{sart}(x_l^{(i)}) = x_l^{(i)} + \frac{\omega}{W_{\oplus,l}} \sum_{k=1}^{N_d} \frac{W_{k,l}}{W_{k,\oplus}} (\Phi_k - \hat{\Phi}_k), where - + .. math:: W_{k,\oplus} = \sum_{l=1}^{N_s} W_{k,l}, \quad W_{\oplus, l} = \sum_{k=1}^{N_d} W_{k,l}. Here :math:`x_l^{(i)}` is the previous estimate for the emission at voxel :math:`l` in iteration :math:`i`. The SART method effectively updates each cell by the weighted average error between the forward modelled :math:`\hat{\Phi}_k` and observed :math:`\Phi_k` measurements. The observed errors are weighted by both - their proportion of the total ray length (:math:`W_{k,\oplus}`) and the sum of the effective ray paths + their proportion of the total ray length (:math:`W_{k,\oplus}`) and the sum of the effective ray paths crossing that cell (:math:`W_{\oplus, l}`). - + :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)`. - :param np.ndarray measurement_vector: The measured power/radiance vector with shape :math:`(N_d)`. + :param np.ndarray measurement_vector: The measured power/radiance vector with shape :math:`(N_d)`. :param initial_guess: An optional initial guess, can be an array of shape :math:`(N_s)` or a constant value that will be used to seed the algorithm. :param int max_iterations: The maximum number of iterations to run the SART algorithm before returning @@ -61,11 +61,11 @@ cpdef invert_sart(geometry_matrix, measurement_vector, object initial_guess=None between the measurement and solution vectors. :return: A tuple with the inverted solution vector :math:`\mathbf{x}` as an ndarray with shape :math:`(N_s)`, and the convergence achieved as a float. - + .. code-block:: pycon - + >>> from cherab.tools.inversions import invert_sart - >>> inverted_solution, conv = invert_sart(weight_matrix, observations, max_iterations=100) + >>> inverted_solution, conv = invert_sart(weight_matrix, observations, max_iterations=100) """ cdef: @@ -164,31 +164,31 @@ cpdef invert_constrained_sart(geometry_matrix, laplacian_matrix, measurement_vec r""" Performs a constrained SART inversion on the specified measurement vector. - - The core of the constrained SART algorithm is identical to the basic SART algorithm implemented in - `invert_sart()`. The only difference is that now the iterative update formula includes a + + The core of the constrained SART algorithm is identical to the basic SART algorithm implemented in + `invert_sart()`. The only difference is that now the iterative update formula includes a regularisation operator. .. math:: - x_l^{(i+1)} = f_{sart}(x_l^{(i)}) - \hat{\mathcal{L}}_{iso}(x_l^{(i)}). + x_l^{(i+1)} = f_\mathrm{sart}(x_l^{(i)}) - \hat{\mathcal{L}}_\mathrm{iso}(x_l^{(i)}). + + In this particular function we have implemented a isotropic Laplacian smoothness operator, - In this particular function we have implemented a isotropic Laplacian smoothness operator, - .. math:: - \hat{\mathcal{L}}_{iso}(x_l^{(i)}) = \\beta_L (Cx_l^{(i)} - \sum_{c=1}^C x_c^{(i)}). + \hat{\mathcal{L}}_\mathrm{iso}(x_l^{(i)}) = \beta_L (Cx_l^{(i)} - \sum_{c=1}^C x_c^{(i)}). - Here, :math:`c` is the index for the sum over the neighbouring voxels. The regularisation - hyperparameter :math:`\\beta_L` determines the amount of local smoothness imposed on the - solution vector. When :math:`\\beta_L = 0`, the solution is fully determined by the - measurements, and as :math:`\\beta_L \\rightarrow 1`, the solution is dominated by the + Here, :math:`c` is the index for the sum over the neighbouring voxels. The regularisation + hyperparameter :math:`\beta_L` determines the amount of local smoothness imposed on the + solution vector. When :math:`\beta_L = 0`, the solution is fully determined by the + measurements, and as :math:`\beta_L \rightarrow 1`, the solution is dominated by the smoothness operator. - + :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)`. :param np.ndarray laplacian_matrix: The laplacian regularisation matrix of shape :math:`(N_s, N_s)`. - :param np.ndarray measurement_vector: The measured power/radiance vector with shape :math:`(N_d)`. + :param np.ndarray measurement_vector: The measured power/radiance vector with shape :math:`(N_d)`. :param initial_guess: An optional initial guess, can be an array of shape :math:`(N_s)` or a constant value that will be used to seed the algorithm. :param int max_iterations: The maximum number of iterations to run the SART algorithm before returning @@ -202,9 +202,9 @@ cpdef invert_constrained_sart(geometry_matrix, laplacian_matrix, measurement_vec between the measurement and solution vectors. :return: A tuple with the inverted solution vector :math:`\mathbf{x}` as an ndarray with shape :math:`(N_s)`, and the convergence achieved as a float. - + .. code-block:: pycon - + >>> from cherab.tools.inversions import invert_constrained_sart >>> inverted_solution, conv = invert_constrained_sart(weight_matrix, laplacian, observations) """ diff --git a/cherab/tools/plasmas/ionisation_balance.py b/cherab/tools/plasmas/ionisation_balance.py index 07a7ea90..46658927 100644 --- a/cherab/tools/plasmas/ionisation_balance.py +++ b/cherab/tools/plasmas/ionisation_balance.py @@ -86,8 +86,8 @@ def _parameters_to_numpy(*parameters, free_variable=None): arrays.append(array) elif not isinstance(param, np.ndarray): # well there are types which should not be treated raise ValueError( - "Parameters can be Iterable, scalar, list, Function1D, Function2D or None, {0} passed".format( - type(param))) + f"Parameters can be Iterable, scalar, list, Function1D, Function2D or None, {type(param)} passed" + ) else: arrays.append(param) @@ -192,13 +192,13 @@ def _fractional_abundance_point(element: Element, n_e, t_e, coef_ion, coef_recom :param atomic_data: Any cherab AtomicData source :param element: Any cherab Element - :param n_e: Electron density in m^-3 to calculate the balance for + :param n_e: Electron density in m\\ :sup:`-3` to calculate the balance for :param t_e: Electron temperature in eV to calculate the balance for :param coef_ion: Dictionary with ionization rates :param coef_recom: Dictionary with recombination rates :param coef_tcx: Optional, dictionary with thermal cx rates :param tcx_donor: Optional, any cherab element. Specifies donating species in tcx collisions. - :param tcx_donor_density: Optional, mandatory if tcx_donor parameter passed. Specifies density of donors in m^-3 + :param tcx_donor_density: Optional, mandatory if tcx_donor parameter passed. Specifies density of donors in m\\ :sup:`-3` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :return: array with fractional abundances of ionic charges. Array indexes correspond to ion charge state. """ @@ -234,7 +234,7 @@ def _fractional_abundance_point(element: Element, n_e, t_e, coef_ion, coef_recom matbal = np.concatenate((matbal, np.ones((1, matbal.shape[1]))), axis=0) # construct RHS of the balance steady-state equation - rhs = np.zeros((matbal.shape[0])) + rhs = np.zeros(matbal.shape[0]) rhs[-1] = n_e abundance = lsq_linear(matbal, rhs, bounds=(0, n_e))["x"] @@ -253,20 +253,20 @@ def _from_element_density_point(atomic_data: AtomicData, element: Element, eleme electron density and absolute element density using steady state ionization balance. If tcx_donor is specified, the balance equation will take into account effects of charge exchange - with the specified donor. The results are returned as density in m^-3. + with the specified donor. The results are returned as density in m\\ :sup:`-3`. :param atomic_data: Any cherab AtomicData source :param element: Any cherab Element - :param element_density: Density of the element in m^-3 - :param n_e: Electron density in m^-3 to calculate the balance for + :param element_density: Density of the element in m\\ :sup:`-3` + :param n_e: Electron density in m\\ :sup:`-3` to calculate the balance for :param t_e: Electron temperature in eV to calculate the balance for :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. Specifies density of donors in m^-3 + :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. Specifies density of donors in m\\ :sup:`-3` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :param coef_ion: Optional, ionization rates. If not passed rates will be loaded (slow). :param coef_recom: Optional, recombination rates. If not passed rates will be loaded (slow). :param coef_tcx: Optional, thermal cx rates. If not passed rates will be loaded (slow). - :return: array with densities in m^-3 of ion charge states. Array indexes correspond to ion charge state. + :return: array with densities in m\\ :sup:`-3` of ion charge states. Array indexes correspond to ion charge state. """ # load atomic data for the element @@ -291,7 +291,7 @@ def _from_element_density_point(atomic_data: AtomicData, element: Element, eleme # warn user if plasma neutrality is violated due to too low electron density for the specified element density n_e_fromions = np.sum(abundance) if n_e_fromions > n_e: - print("Plasma neutrality violated, {0} density too large".format(element.name)) + print(f"Plasma neutrality violated, {element.name} density too large") return abundance @@ -314,15 +314,15 @@ def _match_element_density_point(atomic_data: AtomicData, element: Element, n_sp :param atomic_data: Any cherab AtomicData source :param element: Any cherab element to calculate matching density for :param n_species: list of arrays or dictionaries with ion densities of the rest of the plasma elements - :param n_e: electron density in m^-3 + :param n_e: electron density in m\\ :sup:`-3` :param t_e: electron temperature in eV :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_density: Optional, mandatory if tcx_donor parameter passed. Specifies density of donors in m^-3 + :param tcx_donor_density: Optional, mandatory if tcx_donor parameter passed. Specifies density of donors in m\\ :sup:`-3` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :param coef_ion: Optional, ionization rates. If not passed rates will be loaded (slow). :param coef_recom: Optional, recombination rates. If not passed rates will be loaded (slow). :param coef_tcx: Optional, thermal cx rates. If not passed rates will be loaded (slow). - :return: array with densities in m^-3 of ion charge states. Array indexes correspond to ion charge state. + :return: array with densities in m\\ :sup:`-3` of ion charge states. Array indexes correspond to ion charge state. """ # load atomic data for the element @@ -347,8 +347,7 @@ def _match_element_density_point(atomic_data: AtomicData, element: Element, n_sp element_n_e -= index * value # avoid negative densities due to passed n_e being too small - if element_n_e < 0: - element_n_e = 0 + element_n_e = max(element_n_e, 0) # calculate mean charge of the bulk element z_mean = 0 @@ -374,10 +373,10 @@ def _fractional_abundance(atomic_data: AtomicData, element: Element, n_e, :param atomic_data: Any cherab AtomicData source :param element: Any cherab element - :param n_e: numpy ndarray of values of electron density in m$^{-3}$ - :param t_e: numpy ndarray of values of electron temperature in [ev] + :param n_e: numpy ndarray of values of electron density in m\\ :sup:`-3` + :param t_e: numpy ndarray of values of electron temperature in eV :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. Numpy ndarray of values of electron density + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. Numpy ndarray of values of electron density :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :param coef_ion: Optional, ionization rates. If not passed rates will be loaded (slow). :param coef_recom: Optional, recombination rates. If not passed rates will be loaded (slow). @@ -413,13 +412,13 @@ def fractional_abundance(atomic_data: AtomicData, element: Element, n_e, :param atomic_data: Any cherab AtomicData source :param element: Any cherab element - :param n_e: Scalar, iterable or interpolating function of values of electron density in m$^{-3}$ - :param t_e: Scalar, iterable or interpolating function of values of electron temperature in [ev] + :param n_e: Scalar, iterable or interpolating function of values of electron density in m\\ :sup:`-3` + :param t_e: Scalar, iterable or interpolating function of values of electron temperature in eV :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. Scalar, iterable or interpolating function of values of electron density + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. Scalar, iterable or interpolating function of values of electron density :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. - :param free_variable: Mantadory if n_e, t_e or tcx_donor_n is an interpolating function. If 2D interpolator is passed - free_variable has to be list or tuple of 1D arrays with coordinates + :param free_variable: Mandatory if `n_e`, `t_e` or `tcx_donor_n` is an interpolating function. If 2D interpolator is passed + `free_variable` has to be list or tuple of 1D arrays with coordinates :return: Dictionary with values of fractional abundances in the form {charge: values} """ @@ -448,11 +447,11 @@ def _from_elementdensity(atomic_data: AtomicData, element: Element, element_dens :param atomic_data: Any cherab AtomicData source :param element: Any cherab element - :param element_density: Density profile of the element in m^-3 - :param n_e: numpy ndarray of values of electron density in m$^{-3}$ - :param t_e: numpy ndarray of values of electron temperature in [ev] + :param element_density: Density profile of the element in m\\ :sup:`-3` + :param n_e: numpy ndarray of values of electron density in m\\ :sup:`-3` + :param t_e: numpy ndarray of values of electron temperature in eV :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. numpy ndarray of values of electron density + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. numpy ndarray of values of electron density :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :return: dim 0 corresponds to element charge state, dim > 0 correspond to dimensions of provided values. """ @@ -484,14 +483,14 @@ def from_elementdensity(atomic_data: AtomicData, element: Element, element_densi :param atomic_data: Any cherab AtomicData source :param element: Any cherab element - :param element_density: Density profile of the element in m^-3 - :param n_e: Scalar or iterable of values of electron density in m$^{-3}$ - :param t_e: Scalar or iterable of values of electron temperature in [ev] + :param element_density: Density profile of the element in m\\ :sup:`-3` + :param n_e: Scalar or iterable of values of electron density in m\\ :sup:`-3` + :param t_e: Scalar or iterable of values of electron temperature in eV :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. Scalar or iterable of values of donor density + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. Scalar or iterable of values of donor density :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. - :param free_variable: Mantadory if n_e, t_e or tcx_donor_n is an interpolating function.If 2D interpolator is passed - free_variable has to be list or tuple of 1D arrays with coordinates + :param free_variable: Mandatory if `n_e`, `t_e` or `tcx_donor_n` is an interpolating function. If 2D interpolator is passed + `free_variable` has to be list or tuple of 1D arrays with coordinates :return: Dictionary with density profiles of charge states of the element in the form {charge: profile} """ @@ -523,11 +522,11 @@ def _match_plasma_neutrality(atomic_data: AtomicData, element: Element, n_specie :param atomic_data: Any cherab AtomicData source :param element: Any cherab element - :param element_density_profile: Density profile of the element in m^-3 - :param n_e: Scalar or iterable of values of electron density in m$^{-3}$ - :param t_e: Scalar or iterable of values of electron temperature in [ev] + :param n_species: List of density profiles of all species in m\\ :sup:`-3` + :param n_e_profile: Scalar or iterable of values of electron density in m\\ :sup:`-3` + :param t_e_profile: Scalar or iterable of values of electron temperature in eV :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. Scalar or iterable of values of donor density + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. Scalar or iterable of values of donor density :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :return: Density profiles of charge states of the element. Dim 0 corresponds to charge of charge states. """ @@ -566,14 +565,14 @@ def match_plasma_neutrality(atomic_data: AtomicData, element: Element, n_species :param atomic_data: Any cherab AtomicData source :param element: Any cherab element - :param element_density_profile: Density profile of the element in m^-3 + :param n_species: List of density profiles of all species in m\\ :sup:`-3` :param n_e: 1d profile giving values of electron density for free_variable - :param t_e: 1d profile giving values of electron density for free_variable + :param t_e: 1d profile giving values of electron temperature for free_variable :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. 1d profile giving density of donors in m^-3 + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. 1d profile giving density of donors in m\\ :sup:`-3` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. - :param free_variable: Mantadory if n_e, t_e or tcx_donor_n is an interpolating function. If 2D interpolator is passed - free_variable has to be list or tuple of 1D arrays with coordinates + :param free_variable: Mandatory if `n_e`, `t_e` or `tcx_donor_n` is an interpolating function. If 2D interpolator is passed + `free_variable` has to be list or tuple of 1D arrays with coordinates :return: Dictionary with density profiles of charge states of the element in the form {charge: profile} """ @@ -610,13 +609,13 @@ def interpolators1d_fractional(atomic_data: AtomicData, element: Element, free_v :param atomic_data: Any cherab AtomicData source :param element: Any cherab element - :param free_variable: Free variable (coordinate) to calculate the 1d fractional abundance interpolators from.If 2D interpolator is passed - free_variable has to be list or tuple of 1D arrays with coordinates - :param n_e_interpolator: 1d iterable or interpolator giving values of electron density for free_variable - :param t_e_interpolator: 1d iterable or interpolator giving values of electron density for free_variable + :param free_variable: Free variable (coordinate) to calculate the 1d fractional abundance interpolators from. If 2D interpolator is passed + `free_variable` has to be list or tuple of 1D arrays with coordinates + :param n_e: 1d iterable or interpolator giving values of electron density for `free_variable` + :param t_e: 1d iterable or interpolator giving values of electron temperature for `free_variable` :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n_interpolator: Optional, mandatory if tcx_donor parameter passed. 1d iterable interpolator giving - density of donors in m^-3 + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. 1d iterable interpolator giving + density of donors in m\\ :sup:`-3` for `free_variable` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :return: dictionary with 1d interpolators of fractional abundance of charge states of the element in the form {charge: density} """ @@ -635,19 +634,19 @@ def interpolators1d_fractional(atomic_data: AtomicData, element: Element, free_v def interpolators2d_fractional(atomic_data: AtomicData, element: Element, free_variable, n_e, t_e, tcx_donor: Element = None, tcx_donor_n=None, tcx_donor_charge=0): """ - Creates 1d linear interpolators of fractional abundance of the specified element + Creates 2d linear interpolators of fractional abundance of the specified element for the specified electron densities and temperatures. For more information see _fractional_abundance function. :param atomic_data: Any cherab AtomicData source :param element: Any cherab element - :param free_variable: Free variable (coordinate) to calculate the 1d fractional abundance interpolators from.If 2D interpolator is passed - free_variable has to be list or tuple of 1D arrays with coordinates - :param n_e_interpolator: 1d interpolator giving values of electron density for free_variable - :param t_e_interpolator: 1d interpolator giving values of electron density for free_variable + :param free_variable: Free variable (coordinate) to calculate the 2d fractional abundance interpolators from. If 2D interpolator is passed + `free_variable` has to be list or tuple of 1D arrays with coordinates + :param n_e: 1d iterable or interpolator giving values of electron density for `free_variable` + :param t_e: 1d iterable or interpolator giving values of electron temperature for `free_variable` :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n_interpolator: Optional, mandatory if tcx_donor parameter passed. 1d interpolator giving density of donors in m^-3 + :param tcx_donor_n_interpolator: Optional, mandatory if tcx_donor parameter passed. 1d interpolator giving density of donors in m\\ :sup:`-3` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :return: dictionary with 1d interpolators of fractional abundance of charge states of the element in the form {charge: density} """ @@ -676,11 +675,11 @@ def interpolators1d_from_elementdensity(atomic_data: AtomicData, element: Elemen :param atomic_data: Any cherab AtomicData source :param element: Any cherab element :param free_variable: Free variable (coordinate) to calculate the 1d fractional abundance interpolators from. - :param element_density: 1d iterable or an interpolator giving values of element density for free_variable in m^-3 - :param n_e_interpolator: 1d interpolator giving values of electron density for free_variable - :param t_e_interpolator: 1d interpolator giving values of electron density for free_variable + :param element_density: 1d iterable or an interpolator giving values of element density for free_variable in m\\ :sup:`-3` + :param n_e: 1d interpolator giving values of electron density for `free_variable` + :param t_e: 1d interpolator giving values of electron temperature for `free_variable` :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n_interpolator: Optional, mandatory if tcx_donor parameter passed. 1d interpolator giving density of donors in m^-3 + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. 1d interpolator giving density of donors in m\\ :sup:`-3` for `free_variable` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :return: dictionary with 1d interpolators of fractional abundance of charge states of the element in the form {charge: interpolator} """ @@ -710,11 +709,11 @@ def interpolators1d_match_plasma_neutrality(atomic_data: AtomicData, element: El :param atomic_data: Any cherab AtomicData source :param element: Any cherab element :param free_variable: Free variable (coordinate) to calculate the 1d fractional abundance interpolators from - :param species_density: 1d interpolator giving values of the element density for free_variable + :param species_density: 1d interpolator giving values of the element density for `free_variable` :param n_e: 1d interpolator giving values of electron density for free_variable - :param t_e: 1d interpolator giving values of electron density for free_variable + :param t_e: 1d interpolator giving values of electron temperature for `free_variable` :param tcx_donor: specifies donating species in tcx collisions. - :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. 1d interpolator giving density of donors in m^-3 + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. 1d interpolator giving density of donors in m\\ :sup:`-3` for `free_variable` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :return: dictionary with 1d interpolators of fractional abundance of charge states of the element in the form {charge: interpolator} """ @@ -735,7 +734,7 @@ def interpolators2d_from_elementdensity(atomic_data: AtomicData, element: Elemen element_density, n_e, t_e, tcx_donor: Element = None, tcx_donor_n=None, tcx_donor_charge=0): """ - Creates 1d linear interpolators of density profiles of the specified element + Creates 2d linear interpolators of density profiles of the specified element for the specified electron densities and temperatures. For more information see _from_element_density function. @@ -743,11 +742,11 @@ def interpolators2d_from_elementdensity(atomic_data: AtomicData, element: Elemen :param atomic_data: Any cherab AtomicData source :param element: Any cherab element :param free_variable: A tupple containing two 1D arrays of coordinate points - :param element_density_interpolator: 1d interpolator giving values of element density for free_variable in m^-3 - :param n_e_interpolator: 1d interpolator giving values of electron density for free_variable - :param t_e_interpolator: 1d interpolator giving values of electron density for free_variable + :param element_density: 1d interpolator giving values of element density for `free_variable` in m\\ :sup:`-3` + :param n_e: 1d interpolator giving values of electron density for `free_variable` + :param t_e: 1d interpolator giving values of electron temperature for `free_variable` :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n_interpolator: Optional, mandatory if tcx_donor parameter passed. 1d interpolator giving density of donors in m^-3 + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. 1d interpolator giving density of donors in m\\ :sup:`-3` for `free_variable` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :return: dictionary with 1d interpolators of fractional abundance of charge states of the element in the form {charge: interpolator} """ @@ -769,19 +768,19 @@ def interpolators2d_match_plasma_neutrality(atomic_data: AtomicData, element: El tcx_donor_n=None, tcx_donor_charge=0): """ - Creates 1d linear interpolators of density profiles of the specified element + Creates 2d linear interpolators of density profiles of the specified element for the specified electron densities and temperatures. For more information see _match_element_density function. :param atomic_data: Any cherab AtomicData source :param element: Any cherab element - :param free_variable: A tupple containing two 1D arrays of coordinate poitns + :param free_variable: A tuple containing two 1D arrays of coordinate points :param species_density: 1d interpolator giving values of the element density for free_variable :param n_e: 1d interpolator giving values of electron density for free_variable :param t_e: 1d interpolator giving values of electron density for free_variable :param tcx_donor: specifies donating species in tcx collisions. - :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. 1d interpolator giving density of donors in m^-3 + :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. 1d interpolator giving density of donors in m\\ :sup:`-3` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. :return: dictionary with 1d interpolators of fractional abundance of charge states of the element in the form {charge: interpolator} """ @@ -800,7 +799,7 @@ def interpolators2d_match_plasma_neutrality(atomic_data: AtomicData, element: El def abundance_axisymmetric_mapper(abundance): """ - Convert 2d abundance interpolators into AxisymmetricMapper. + Convert 2d abundance interpolators into `.AxisymmetricMapper`. :param abundance: Dictionary with 2d Abundace/fractional abundance interpolators """ @@ -827,8 +826,8 @@ def equilibrium_map3d_fractional(atomic_data: AtomicData, element: Element, equi :param n_e_profile: 1d iterable or interpolator giving values of electron density :param t_e_profile: 1d iterable or interpolator giving values of electron temperature :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. 1d iterable interpolator giving - density of donors in m^-3 + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. 1d iterable interpolator giving + density of donors in m\\ :sup:`-3` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. """ @@ -854,12 +853,12 @@ def equilibrium_map3d_from_elementdensity(atomic_data: AtomicData, element: Elem :param element: Any cherab element :param equilibrium: EFITEquilibrium object :param psin_1d:1D array with normalized poloidal flux coordinates - :param element_density: 1d iterable or an interpolator giving values of element density for free_variable in m^-3 + :param element_density: 1d iterable or an interpolator giving values of element density for `free_variable` in m\\ :sup:`-3` :param n_e_profile: 1d iterable or interpolator giving values of electron density :param t_e_profile: 1d iterable or interpolator giving values of electron temperature :param tcx_donor: Optional, specifies donating species in tcx collisions. :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. 1d iterable interpolator giving - density of donors in m^-3 + density of donors in m\\ :sup:`-3` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. """ @@ -885,12 +884,12 @@ def equilibrium_map3d_match_plasma_neutrality(atomic_data: AtomicData, element: :param element: Any cherab element :param equilibrium: EFITEquilibrium object :param psin_1d:1D array with normalized poloidal flux coordinates - :param species_density: list of 1d iterables interpolators giving values of element density for the values of psi in m^-3 + :param species_density: list of 1d iterables interpolators giving values of element density for the values of psi in m\\ :sup:`-3` :param n_e_profile: 1d iterable or interpolator giving values of electron density :param t_e_profile: 1d iterable or interpolator giving values of electron temperature :param tcx_donor: Optional, specifies donating species in tcx collisions. - :param tcx_donor_n: Optional, mandatory if tcx_donor parameter passed. 1d iterable interpolator giving - density of donors in m^-3 + :param tcx_donor_n: Optional, mandatory if `tcx_donor` parameter passed. 1d iterable interpolator giving + density of donors in m\\ :sup:`-3` :param tcx_donor_charge: Optional, specifies the charge of the donor. Default is 0. """ diff --git a/cherab/tools/plasmas/slab.pyx b/cherab/tools/plasmas/slab.pyx index 6ab5f962..1c3af890 100644 --- a/cherab/tools/plasmas/slab.pyx +++ b/cherab/tools/plasmas/slab.pyx @@ -215,13 +215,13 @@ def build_constant_slab_plasma(length=5, width=1, height=1, electron_density=1e1 If omitted, hydrogen distribution with properties equal to electrons is used: >>> plasma_species = [(hydrogen, 1, electron_density, electron_temperature, Vector3D(0, 0, 0))] - + If an empty list is passed, plasma contains only electrons. :param float length: the overall length of the slab along x. :param float width: the y width of the slab. :param float height: the z height of the slab. - :param float electron_density: the electron density in m^-3 . + :param float electron_density: the electron density in m\\ :sup:`-3` . :param float electron_temperature: the electron temperature in eV. :param list plasma_species: an optional list of impurities to include. :param Vector3D b_field: vector giving the magnetic field diff --git a/cherab/tools/raytransfer/pipelines.py b/cherab/tools/raytransfer/pipelines.py index e051e3f7..190db3ff 100644 --- a/cherab/tools/raytransfer/pipelines.py +++ b/cherab/tools/raytransfer/pipelines.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright 2016-2018 Euratom # Copyright 2016-2018 United Kingdom Atomic Energy Authority @@ -34,8 +33,7 @@ from raysect.optical.observer.base import Pipeline0D, Pipeline1D, Pipeline2D, PixelProcessor -class RayTransferPipelineBase(): - +class RayTransferPipelineBase: def __init__(self, name=None, kind='power'): self.name = name @@ -49,10 +47,10 @@ def kind(self): """ The kind of the pipeline. Can be 'power' or 'radiance'. In the case of 'power', the resulting matrix is multiplied by the sensitivity - of the detector, and the units of the matrix are [m^3 sr], which gives the units + of the detector, and the units of the matrix are [m\\ :sup:`3` sr], which gives the units of power [W] for the product of the ray transfer matrix and the emission profile. In case of 'radiance', the sensitivity is not taken into account and - the matrix is calculated in [m], which gives the units of radiance [W m^-2 sr^-1] + the matrix is calculated in [m], which gives the units of radiance [W m\\ :sup:`-2` sr\\ :sup:`-1`] for the product of the ray transfer matrix and the emission profile. """ return self._kind @@ -74,18 +72,18 @@ class RayTransferPipeline0D(Pipeline0D, RayTransferPipelineBase): """ Simple 0D pipeline for ray transfer matrix (geometry matrix) calculation. - :param str name: The name of the pipeline. Default is 'RayTransferPipeline0D'. + :param str name: The name of the pipeline. Default is ``"RayTransferPipeline0D"``. :param str kind: The kind of the pipeline. Can be 'power' (default) or 'radiance'. In the case of 'power', the resulting matrix is multiplied by the sensitivity - of the detector, and the units of the matrix are [m^3 sr], which gives the units + of the detector, and the units of the matrix are [m\\ :sup:`3` sr], which gives the units of power [W] for the product of the ray transfer matrix and the emission profile. In case of 'radiance', the sensitivity is not taken into account and - the matrix is calculated in [m], which gives the units of radiance [W m^-2 sr^-1] + the matrix is calculated in [m], which gives the units of radiance [W m\\ :sup:`-2` sr\\ :sup:`-1`] for the product of the ray transfer matrix and the emission profile. Note that if the sensitivity of the detector is 1 (e.g. `PinholeCamera`, `VectorCamera`), the 'power' and 'radiance' give the same results. - :ivar np.ndarray matrix: Ray transfer matrix, a 1D array of size :math:`N_{bin}`. + :ivar np.ndarray matrix: Ray transfer matrix, a 1D array of size :math:`N_\\mathrm{bin}`. .. code-block:: pycon @@ -120,18 +118,18 @@ class RayTransferPipeline1D(Pipeline1D, RayTransferPipelineBase): """ Simple 1D pipeline for ray transfer matrix (geometry matrix) calculation. - :param str name: The name of the pipeline. Default is 'RayTransferPipeline0D'. + :param str name: The name of the pipeline. Default is ``"RayTransferPipeline1D"``. :param str kind: The kind of the pipeline. Can be 'power' (default) or 'radiance'. In the case of 'power', the resulting matrix is multiplied by the sensitivity - of the detector, and the units of the matrix are [m^3 sr], which gives the units + of the detector, and the units of the matrix are [m\\ :sup:`3` sr], which gives the units of power [W] for the product of the ray transfer matrix and the emission profile. In case of 'radiance', the sensitivity is not taken into account and - the matrix is calculated in [m], which gives the units of radiance [W m^-2 sr^-1] + the matrix is calculated in [m], which gives the units of radiance [W m\\ :sup:`-2` sr\\ :sup:`-1`] for the product of the ray transfer matrix and the emission profile. Note that if the sensitivity of the detector is 1 (e.g. `PinholeCamera`, `VectorCamera`), the 'power' and 'radiance' give the same results. - :ivar np.ndarray matrix: Ray transfer matrix, a 2D array of shape :math:`(N_{pixel}, N_{bin})`. + :ivar np.ndarray matrix: Ray transfer matrix, a 2D array of shape :math:`(N_\\mathrm{pixel}, N_\\mathrm{bin})`. .. code-block:: pycon @@ -167,18 +165,18 @@ class RayTransferPipeline2D(Pipeline2D, RayTransferPipelineBase): """ Simple 2D pipeline for ray transfer matrix (geometry matrix) calculation. - :param str name: The name of the pipeline. Default is 'RayTransferPipeline0D'. + :param str name: The name of the pipeline. Default is ``"RayTransferPipeline2D"``. :param str kind: The kind of the pipeline. Can be 'power' (default) or 'radiance'. In the case of 'power', the resulting matrix is multiplied by the sensitivity - of the detector, and the units of the matrix are [m^3 sr], which gives the units + of the detector, and the units of the matrix are [m\\ :sup:`3` sr], which gives the units of power [W] for the product of the ray transfer matrix and the emission profile. In case of 'radiance', the sensitivity is not taken into account and - the matrix is calculated in [m], which gives the units of radiance [W m^-2 sr^-1] + the matrix is calculated in [m], which gives the units of radiance [W m\\ :sup:`-2` sr\\ :sup:`-1`] for the product of the ray transfer matrix and the emission profile. Note that if the sensitivity of the detector is 1 (e.g. `PinholeCamera`, `VectorCamera`), the 'power' and 'radiance' give the same results. - :ivar np.ndarray matrix: Ray transfer matrix, a 3D array of shape :math:`(N_x, N_y, N_{bin})`. + :ivar np.ndarray matrix: Ray transfer matrix, a 3D array of shape :math:`(N_x, N_y, N_\\mathrm{bin})`. .. code-block:: pycon @@ -233,7 +231,7 @@ def add_sample(self, spectrum, sensitivity): class PowerRayTransferPixelProcessor(RayTransferPixelProcessorBase): """ - PixelProcessor that stores ray transfer matrix in the units of [m^3 sr] for each pixel. + PixelProcessor that stores ray transfer matrix in the units of [m\\ :sup:`3` sr] for each pixel. """ def add_sample(self, spectrum, sensitivity): diff --git a/docs/source/conf.py b/docs/source/conf.py index b2f22c70..421732a3 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -83,7 +83,7 @@ # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +default_role = "obj" # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True diff --git a/docs/source/models/custom_models.rst b/docs/source/models/custom_models.rst index 03d3d8df..67124454 100644 --- a/docs/source/models/custom_models.rst +++ b/docs/source/models/custom_models.rst @@ -2,7 +2,7 @@ Custom emission models ---------------------- -Custom emitters are implemented as Raysect materials with the `VolumeEmitterInhomogeneous` class. +Custom emitters are implemented as Raysect materials with the `~raysect.optical.material.emitter.inhomogeneous.InhomogeneousVolumeEmitter` class. You model should inherit from this base class, only two methods need to be implemented, the `__init__()` and `emission_function()` methods. @@ -16,33 +16,33 @@ emission line. But this can change alot from application to application. We are some atomic data from ADAS. You could optionally pass in the atomic data you want to use in the `__init__()`. -The `step` parameter is the only parameter required by the parent `VolumeEmitterInhomogeneous` +The `step` parameter is the only parameter required by the parent `~raysect.optical.material.emitter.inhomogeneous.InhomogeneousVolumeEmitter` class. This parameter determines the integration step size for sampling and will need to be -adjusted based on your application's scale lengths. Make ure you call the parent init whith the +adjusted based on your application's scale lengths. Make sure you call the parent init with the super method, e.g. `super().__init__(step=step)`. All the magic happens in the `emission_function()` method. This method is called at every point in space where the ray-tracer would like to know the emission. The arguments are fixed and are as follows: -* `point` (`Point3D`) - current position in local primitive coordinates -* `direction` (`Vector3D`) - current ray direction in local primitive coordinates -* `spectrum` (`Spectrum`) - measured spectrum so far. Don't overwrite it. Add your local +- `point` (`Point3D`) - current position in local primitive coordinates +- `direction` (`Vector3D`) - current ray direction in local primitive coordinates +- `spectrum` (`Spectrum`) - measured spectrum so far. Don't overwrite it. Add your local emission to the measured spectrum. Units are in spectral radiance (W/m3/str/nm). -* `world` (`World`) - the world being ray-traced. You may have multiple worlds. -* `ray` (`Ray`) - the current ray being traced. -* `primitive` (`Primitive`) - the primitive container for this material. Could be a sphere, +- `world` (`World`) - the world being ray-traced. You may have multiple worlds. +- `ray` (`Ray`) - the current ray being traced. +- `primitive` (`Primitive`) - the primitive container for this material. Could be a sphere, cyliner, or CAD mesh for example. -* `to_local` (`AffineMatrix3D`) - Affine matrix for coordinate transformations to local coordinates. -* `to_world` (`AffineMatrix3D`) - Affine matrix for coordinate transformations to world coordinates. +- `to_local` (`AffineMatrix3D`) - Affine matrix for coordinate transformations to local coordinates. +- `to_world` (`AffineMatrix3D`) - Affine matrix for coordinate transformations to world coordinates. .. WARNING:: Don't override the spectrum parameter, you will loose all the previous ray samples. Instead you should add your local emission at the current point in space to the measured spectrum array. -Here is an example class implementation of an excitation line. :: +Here is an example class implementation of an excitation line. \: - class ExcitationLine(VolumeEmitterInhomogeneous): + class ExcitationLine(InhomogeneousVolumeEmitter): def __init__(self, line, electron_distribution, atom_species, step=0.005, block=0, filename=None): diff --git a/docs/source/models/cxs/charge_exchange_calculation.rst b/docs/source/models/cxs/charge_exchange_calculation.rst index a1d89600..ceaf37ad 100644 --- a/docs/source/models/cxs/charge_exchange_calculation.rst +++ b/docs/source/models/cxs/charge_exchange_calculation.rst @@ -9,7 +9,7 @@ Calculation of predicted charge-exchange spectra seen by a line-of-sight .. *Date: 24/11/2014* In this section, the calculation of a predicted spectral line -:math:`I_{obs}(\lambda)` resulting from a charge-exchange process is presented +:math:`I_\mathrm{obs}(\lambda)` resulting from a charge-exchange process is presented together with the different possible simplifications and details of what is currently implemented in Cherab. This documentation is not meant to be a course on charge-exchange but a concise compilation of the main aspects in @@ -21,12 +21,12 @@ order to understand the assumptions made in Cherab for an educated use. documentation manager. Thanks. .. NOTE:: - :math:`I_{obs}(\lambda)` in ray-tracer and therefore Cherab is in :math:`W.m^{-2}.str^{-1}.nm^{-1}`. + :math:`I_\mathrm{obs}(\lambda)` in ray-tracer and therefore Cherab is in W m\\ :sup:`-2` str\\ :sup:`-1` nm\\ :sup:`-1`. .. csv-table:: Notations for this section :header: "Notation", "Meaning", "Unit" - ":math:`n_e`", "Electron density", ":math:`m^{-3}`" + ":math:`n_\mathrm{e}`", "Electron density", "m\\ :sup:`-3`" Definition of charge-exchange coefficients @@ -35,10 +35,10 @@ Definition of charge-exchange coefficients The charge exchange reaction between an ion |impurity| and a donor :math:`H^0` (can be in this section deuterium, tritium, hydrogen or helium) is: -.. math:: H^0(m) + Z^{(\alpha +1)+} \longrightarrow H^+ + Z^{* \alpha+}(n, l, j) \longrightarrow H^+ + Z^{\alpha+} + h\nu_1 + h\nu_2 + ... +.. math:: H^0(m) + Z^{(\alpha +1)+} \longrightarrow H^+ + Z^{* \alpha+}(n, l, j) \longrightarrow H^+ + Z^{\alpha+} + h\nu_1 + h\nu_2 + \cdots Where |impurity| is the ion capturing the donor electron into a -specific shell (n,l,j). The excited ions, :math:`Z^{* \alpha+}(n, l, j)`, decay +specific shell (:math:`n,l,j`). The excited ions, :math:`Z^{* \alpha+}(n, l, j)`, decay in one or more steps to their ground state under photon emission. It is possible for the ion |impurity| to capture a donor electron from the ground-state :math:`H^0(m=1)` but also from high-lying shells if the @@ -50,22 +50,22 @@ the ion |impurity| which then will undergo a redistribution process and cascade process affecting the excited populations of the recombined ion :math:`Z^{* \alpha+}` in a thermal plasma. The quantity linking the fundamental cross-sections and the charge-exchange observations is the -effective emission coefficient. The effective emission coefficient :math:`q^{CX, Z^{(\alpha+1)+}, H^0(m)}_{n\rightarrow n'}` +effective emission coefficient. The effective emission coefficient :math:`q^{\mathrm{CX}, Z^{(\alpha+1)+}, H^0(m)}_{n\rightarrow n'}` for a particular charge-exchange line (such as CVI :math:`n=8\rightarrow n'=7`) incorporate these effects. The coefficient is defined such that the number of :math:`n\rightarrow n'` photons emitted per unit volume per second per -:math:`4\pi` steradian is :math:`q^{CX, Z^{(\alpha+1)+}, H^0(m)}_{n\rightarrow n'}.n_{Z^{(\alpha +1)+}}.n_{H^0(m)}` +:math:`q^{\mathrm{CX}, Z^{(\alpha+1)+}, H^0(m)}_{n\rightarrow n'}.n_{Z^{(\alpha +1)+}}.n_{H^0(m)}` with :math:`n_{Z^{(\alpha +1)+}}` the number density of impurity receiver ions of charge :math:`\alpha+1` in the plasma and :math:`n_{H^0(m)}` the number density of beam donor atoms in the state :math:`m`. For example for D(n=2) donors, m=2 and for the ground state D(n=1), m=1. The methods used to calculate -the effective emission coefficients, :math:`q^{CX, Z^{(\alpha+1)+}, H^0(m)}_{n\rightarrow n'}` +the effective emission coefficients, :math:`q^{\mathrm{CX}, Z^{(\alpha+1)+}, H^0(m)}_{n\rightarrow n'}` is calculated in a collisional-radiative nl-resolved l-mixing model of all the excited populations of the :math:`\alpha+1` times ionized receiver ion. The effective coefficients depend on the collision energy with the neutral beam -:math:`E_c`, plasma electron and ion temperatures, plasma impurity ion species +:math:`E_\mathrm{c}`, plasma electron and ion temperatures, plasma impurity ion species mix and number densities and electron density. The strongest dependences are on -collisional energy :math:`E_c` and ion density :math:`n_I`. (For more specific +collisional energy :math:`E_\mathrm{c}` and ion density :math:`n_I`. (For more specific use of ADAS effective charge-exchange coefficient look at Cherab atomic data note). For a mixed impurity plasma of known fractions with charge neutrality, the electron and ion densities are related and it is usual to use the electron @@ -75,19 +75,20 @@ The composite charge-exchange emission coefficient with both :math:`H^0(m=1)` and :math:`H^0(m=2)` beam donors is defined as: .. math:: - q^{CX, Z^{(\alpha+1)+}}_{n\rightarrow n'} &= \frac{n_{H^0(1)} q^{CX, Z^{(\alpha+1)+}, H^0(1)}_{n\rightarrow n'} + n_{H^0(2)}.q^{CX, Z^{(\alpha+1)+}, H^0(2)}_{n\rightarrow n'}}{n_{H^0(1)} + n_{H^0(2)}} \\ - &= \frac{q^{CX, Z^{(\alpha+1)+}, H^0(1)}_{n\rightarrow n'} + bmp(2).q^{CX, Z^{(\alpha+1)+}, H^0(2)}_{n\rightarrow n'}}{1 + bmp(2)} \quad \text{with} \quad bmp(m) = \frac{n_{H^0(m)}}{n_{H^0(1)}} + q^{\mathrm{CX}, Z^{(\alpha+1)+}}_{n\rightarrow n'} + &= \frac{n_{H^0(1)} q^{\mathrm{CX}, Z^{(\alpha+1)+}, H^0(1)}_{n\rightarrow n'} + n_{H^0(2)}.q^{\mathrm{CX}, Z^{(\alpha+1)+}, H^0(2)}_{n\rightarrow n'}}{n_{H^0(1)} + n_{H^0(2)}} \\ + &= \frac{q^{\mathrm{CX}, Z^{(\alpha+1)+}, H^0(1)}_{n\rightarrow n'} + \mathrm{bmp}(2).q^{\mathrm{CX}, Z^{(\alpha+1)+}, H^0(2)}_{n\rightarrow n'}}{1 + \mathrm{bmp}(2)} \quad \text{with} \quad \mathrm{bmp}(m) = \frac{n_{H^0(m)}}{n_{H^0(1)}} Or in a more general way: .. math:: - q^{CX, Z^{(\alpha+1)+}}_{n\rightarrow n'} = \frac{q^{CX, Z^{(\alpha+1)+}, H^0(1)}_{n\rightarrow n'} + \sum_{m=2}^M bmp(m).q^{CX, Z^{(\alpha+1)+}, H^0(m)}_{n\rightarrow n'}}{1 + \sum_{m=2}^M bmp(m)} + q^{\mathrm{CX}, Z^{(\alpha+1)+}}_{n\rightarrow n'} = \frac{q^{\mathrm{CX}, Z^{(\alpha+1)+}, H^0(1)}_{n\rightarrow n'} + \sum_{m=2}^M \mathrm{bmp}(m).q^{\mathrm{CX}, Z^{(\alpha+1)+}, H^0(m)}_{n\rightarrow n'}}{1 + \sum_{m=2}^M \mathrm{bmp}(m)} The ratio of population between :math:`n_{H^0(m)}` and :math:`n_{H^0(1)}` is -called :math:`bmp(m)`. The calculation of the donor population requires a +called :math:`\mathrm{bmp}(m)`. The calculation of the donor population requires a detailed collisional-radiative model including many ion and electron collisional processes. For information, the fraction of excited beam atoms -depends not only on the beam energy but also on :math:`Z_{eff}`, plasma +depends not only on the beam energy but also on :math:`Z_\mathrm{eff}`, plasma temperature and densities. Note that D(n=1) donor dominates at high beam energy and the small fraction of D(n=2) donor dominates at low beam energy [Hoekstra1998]. For more practical information, look at the Cherab atomic data @@ -100,7 +101,7 @@ As already mentioned above the number of :math:`n\rightarrow n'` photons emitted per unit volume per second per :math:`4\pi` steradian can be calculated by: -.. math:: I_{n\rightarrow n'} = n_{H^0}.n_{Z^{(\alpha +1)+}}.q^{CX, Z^{(\alpha+1)+}}_{n\rightarrow n'} +.. math:: I_{n\rightarrow n'} = n_{H^0}.n_{Z^{(\alpha +1)+}}.q^{\mathrm{CX}, Z^{(\alpha+1)+}}_{n\rightarrow n'} The light emitted by a specie :math:`Z^{\alpha+}` due to a transition of electron from quantum :math:`n\rightarrow n'` has a natural wavelength :math:`\lambda_n` @@ -108,21 +109,21 @@ associated and a natural line width :math:`\Delta\lambda_n`. It can be calculate that this width is small and can be neglected. The spectral line intensity as a function of wavelength is then given by: -.. math:: I_{n\rightarrow n'}(\lambda) = I_{n\rightarrow n'}.\delta(\lambda - \lambda_n) +.. math:: I_{n\rightarrow n'}(\lambda) = I_{n\rightarrow n'}\cdot\delta(\lambda - \lambda_n) **Assumption: natural width of the line neglected** An observer looking at a direction :math:`\vec{l}` (:math:`\|\vec{l}\|=1`) at a photon with a velocity -:math:`\vec{u}` will see this photon at a wavelength :math:`\lambda_D = \lambda_n + \Delta\lambda_D` -with a Doppler shift :math:`\Delta\lambda_D = \lambda_n \frac{\vec{u}.\vec{l}}{c}` +:math:`\vec{u}` will see this photon at a wavelength :math:`\lambda_\mathrm{D} = \lambda_n + \Delta\lambda_\mathrm{D}` +with a Doppler shift :math:`\Delta\lambda_\mathrm{D} = \lambda_n \frac{\vec{u}\cdot\vec{l}}{c}` with c the speed of light. The observed spectral line intensity can then be defined as (ignoring all effects but Doppler effect): .. math:: - I_{n\rightarrow n'}(\lambda) = I_{n\rightarrow n'}.\delta(\lambda - \lambda_D) - = I_{n\rightarrow n'}.\delta\left(\lambda - \lambda_n \left(1 + \frac{\vec{u}.\vec{l}}{c}\right)\right) + I_{n\rightarrow n'}(\lambda) = I_{n\rightarrow n'}\cdot\delta(\lambda - \lambda_\mathrm{D}) + = I_{n\rightarrow n'}\cdot\delta\left(\lambda - \lambda_n \left(1 + \frac{\vec{u}\cdot\vec{l}}{c}\right)\right) In more details charge-exchange cross-section --------------------------------------------- @@ -140,44 +141,48 @@ atomic hydrogen gas target and detecting scattered product ions of charge :math: separately from the primary ions of charge :math:`\alpha+1`. When charged ions :math:`Z^{(\alpha +1)+}` are thrown against an atomic hydrogen -gas, the cross-section :math:`\sigma^{CX}_{Z^{(\alpha+1)+}}` is a hypothetical +gas, the cross-section :math:`\sigma^\mathrm{CX}_{Z^{(\alpha+1)+}}` is a hypothetical area measure around the target particle of atoms that represents a surface. If an ion crosses this surface, there will be some kind of interaction. In the charge-exchange reaction, the cross-section is specific to a donor electron in the level :math:`H^0(m)` and capture in the shell (n,l) of the ion :math:`Z^{(\alpha+1)+}` -(abandoning j for now), hence :math:`\sigma^{CX}_{Z^{(\alpha +1)+}}(m,n,l)`. +(abandoning j for now), hence :math:`\sigma^\mathrm{CX}_{Z^{(\alpha +1)+}}(m,n,l)`. In general, the rate :math:`Q` at which a specific reaction occurs is a physical quantity measuring the number of reactions per unit of time which can be written as follow: -.. math:: Q = N.J.\sigma +.. math:: Q = N\cdot J\cdot \sigma^\mathrm{CX} with :math:`N` the number of target particles, illuminated by the beam containing :math:`n` particles per unit volume (number density of particles) travelling with the average velocity :math:`v` in the rest frame of the target and these two -quantities combine in the particle current density of the beam :math:`J=n.v`. +quantities combine in the particle current density of the beam :math:`J=n\cdot v`. So the rate can be rewritten as: -.. math:: Q = N.n.v.\sigma +.. math:: Q = N\cdot n\cdot v\cdot \sigma^\mathrm{CX} Now, we want to get back to the specific equation for the charge-exchange rate. For our charge-exchange reaction, the target ions :math:`Z^{(\alpha+1)+}` have a certain distribution :math:`f_{Z^{(\alpha+1)+}(n,l)}(\vec{x}, \vec{u}, t)` that needs to be taken into account in the calculation: -.. math:: Q^{CX, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n'}(E_c) = - n_{H^0(m)}.n_{Z^{(\alpha +1)+}}(n,l).\int_{\vec{u}}f_{Z^{(\alpha+1)+}(n,l)}(\vec{u}-\vec{v_B}) - .\|\vec{u}-\vec{v_B}\|.\sigma^{CX, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n'}(\|\vec{u}-\vec{v_B}\|).d\vec{u} +.. math:: + Q^{\mathrm{CX}, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n'}(E_\mathrm{c}) = + n_{H^0(m)}.n_{Z^{(\alpha +1)+}}(n,l) + \int_{\vec{u}}\mathrm{d}\vec{u}\; + f_{Z^{(\alpha+1)+}(n,l)}(\vec{u}-\vec{v_B}) + \|\vec{u}-\vec{v_B}\| + \sigma^{\mathrm{CX}, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n'}(\|\vec{u}-\vec{v_B}\|) -With the collision velocity between the impurity ion and the neutral atom :math:`E_c = \|\vec{u}-\vec{v_B}\|` +With the collision velocity between the impurity ion and the neutral atom :math:`E_\mathrm{c} = \|\vec{u}-\vec{v_B}\|` The above equation point out that the charge-exchange rate coefficient needs the distribution of the impurity. The general case is that a Maxwellian distribution function can be assumed in the velocity space, but there are cases such as for the He-ash where a Maxwellian distribution does not apply and a more general calculation of the charge-exchange rate would be needed and a new effective -emission coefficients would be needed :math:`q^{CX, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n', \text{non Max}}`. +emission coefficients would be needed :math:`q^{\mathrm{CX}, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n', \text{non Max}}`. As a result there are possibly three different calculations for the effective charge-exchange emission coefficient, of which only two are used in practise. @@ -185,11 +190,11 @@ charge-exchange emission coefficient, of which only two are used in practise. **Two different composite charge exchange emission coefficients:** 1. A Maxwellian distribution function in velocity space is assumed for the ion :math:`Z^{(\alpha+1)+}`: - :math:`q^{CX, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n'}` + :math:`q^{\mathrm{CX}, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n'}` 2. A Maxwellian distribution function in velocity space is not assumed for the ion :math:`Z^{(\alpha+1)+}`: this requires a new set of effective charge-exchange emission coefficient - :math:`q^{CX, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n', \text{non Max}}`, + :math:`q^{\mathrm{CX}, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n', \text{non Max}}`, additional parameters in respect to 1. will be needed. In more details calculation of excited level populations of impurity ions :math:`Z^{* \alpha+}(n, l, j)` @@ -212,7 +217,7 @@ There are: \longrightarrow Z^{\alpha+}(n,l',j') + \left\{\begin{array}{ll}e\\Z_{\mu} \end{array} \right\} * Transitions between nearly degenerate levels due to ion motion and magnetic field: -.. math:: Z^{\alpha+}(n,l,j) \overset{B_{mag}}{\longrightarrow} Z^{\alpha+}(n,l',j') +.. math:: Z^{\alpha+}(n,l,j) \overset{B_\mathrm{mag}}{\longrightarrow} Z^{\alpha+}(n,l',j') A statistical view of excited ion level populations is appropriate, the number densities of ions in various excited levels being determined by the balance of @@ -223,21 +228,21 @@ properly by collisional ionisation but in practise is mostly influenced by the decay with n of the primary capture processes. The main effect of the particle collisions and magnetic fields is to cause transitions between levels of the same principal quantum number and so these alone are included in the calculations. -For ions in high orbital angular momentum states l, induced transitions between -whole l state populations are of most importance. Whereas, at low l, the -transitions between separate j sublevels are important. For these reasons two +For ions in high orbital angular momentum states :math:`l`, induced transitions between +whole :math:`l` state populations are of most importance. Whereas, at low :math:`l`, the +transitions between separate :math:`j` sublevels are important. For these reasons two populations models are used, namely: -a. **the nl picture:** in which the populations of nl levels are calculated and - the populations of j sublevels are assumed to be in proportion to their statistical weights. +a. **the** :math:`nl` **picture:** in which the populations of :math:`nl` levels are calculated and + the populations of :math:`j` sublevels are assumed to be in proportion to their statistical weights. -b. **the nlj picture:** in which the populations of j sublevels are calculated - in full magnetic field effects are included only in the nlj picture. +b. **the** :math:`nlj` **picture:** in which the populations of :math:`j` sublevels are calculated + in full magnetic field effects are included only in the :math:`nlj` picture. **Two different composite charge exchange emission coefficients depending on the model chosen for the excited population model:** - 3. nl picture: :math:`q^{CX, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n'}` - 4. nlj picture: :math:`q^{CX, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n'}(\vec{B})` + 3. :math:`nl` picture: :math:`q^{\mathrm{CX}, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n'}` + 4. :math:`nlj` picture: :math:`q^{\mathrm{CX}, Z^{(\alpha+1)+}(n,l), H^0(m)}_{n\rightarrow n'}(\vec{B})` these coefficients exist in ADAS but are mostly not used. **Justification of assumption usually made on the excited population calculation:** @@ -247,8 +252,8 @@ b. **the nlj picture:** in which the populations of j sublevels are calculated Collisional transitions between nearly degenerate levels play a significant role for the densities, ions and principal quantum shells of concern in JET studies of charge exchange by visible spectroscopy. The transitions - are of the form :math:`nl\rightarrow nl\pm 1` in the nl picture and - :math:`nlj\rightarrow nl\pm 1, j\pm 1` in the nlj picture and are induced + are of the form :math:`nl\rightarrow nl\pm 1` in the :math:`nl` picture and + :math:`nlj\rightarrow nl\pm 1, j\pm 1` in the :math:`nlj` picture and are induced by both electron and positive ion impact. As the transition energies approach zero, ions become relatively more efficient than electrons in causing transitions. Detailed expressions for collisions rate coefficients @@ -258,19 +263,19 @@ b. **the nlj picture:** in which the populations of j sublevels are calculated the cross-section is essentially proportional to :math:`Z^2_{\mu}` where :math:`Z_{\mu}` is the impacting ion charge number, an error less than the intrinsic uncertainty in the cross-sections is introduced by considering - a single ion species to be present of charge :math:`Z_{eff}` (the usually + a single ion species to be present of charge :math:`Z_\mathrm{eff}` (the usually defined plasma effective ion charge). The rate expressions depend sensitively on the transition energies and so the latter must be evaluated quite precisely. - Rates are calculated in the nlj picture initially. Since at high l, where - the nl picture is often most useful, the transitions have line strengths + Rates are calculated in the :math:`nlj` picture initially. Since at high :math:`l`, where + the :math:`nl` picture is often most useful, the transitions have line strengths which tend to zero, it is suitable to sum and average over final and initial - j states to obtain rate coefficients in the nl picture. It is usual to + :math:`j` states to obtain rate coefficients in the :math:`nl` picture. It is usual to estimate approximately the levels at which mixing by magnetic fields matter by a simple consideration of static energy level shifts. This is not appropriate for a population treatment in which a detailed balance of rates is followed to obtain actual ion populations in cases where any process may not be fully dominant. It is evident that the field processes matter most for - low l un vuv and xuv measurements and then the nlj picture is appropriate. + low :math:`l` un vuv and xuv measurements and then the :math:`nlj` picture is appropriate. There is a critical plasma density at which a given transition is fully mixed: this is usually a problem for the edge densities of plasmas. @@ -283,22 +288,22 @@ b. **the nlj picture:** in which the populations of j sublevels are calculated account as they are found to be small, while the corrections due to the Zeeman effects are included. - Practically, the l-mixing and Zeeman effect correspond to a broadening + Practically, the :math:`l`-mixing and Zeeman effect correspond to a broadening of the charge-exchange line that is independent of ion temperature. Due to the fine structure each allowed transition has a slightly different wavelength, and the total emission spectrum consists of a set of lines instead of one line. - Collisional l-mixing: + Collisional :math:`l`-mixing: - Which of the l-levels ae populated in a charge-exchange reactions depends + Which of the :math:`l`-levels ae populated in a charge-exchange reactions depends on the beam energy. If the lifetime :math:`\tau` of the excited states is considerably larger than the ion-ion collision time, collisions will cause a transfer - between the different l-states of n=8 shell before the charge-exchange + between the different :math:`l`-states of :math:`n=8` shell before the charge-exchange electron drops to a lower level and emits a photon. This phenomenon is - called collisional l-mixing. It means that even if the population of the - l-levels would not be statistic, collisional l-mixing would make sure that - the l-levels are statistically populated. The spectrum of these lies can + called collisional :math:`l`-mixing. It means that even if the population of the + :math:`l`-levels would not be statistic, collisional :math:`l`-mixing would make sure that + the :math:`l`-levels are statistically populated. The spectrum of these lies can be calculated in ADAS. In the case of the C6+ CXRS lines, the line broadening would correspond to a Doppler broadening of 4eV. @@ -306,20 +311,20 @@ b. **the nlj picture:** in which the populations of j sublevels are calculated Without a magnetic field the energy levels within the same n shell differ slightly due to the fine-structure. The presence of a magnetic field will - cause Zeeman splitting of one j-level into 2J+1 energy levels separated. - This is a stronger effect than the collisional l-mixing. For the carbon + cause Zeeman splitting of one :math:`j`-level into :math:`2J+1` energy levels separated. + This is a stronger effect than the collisional :math:`l`-mixing. For the carbon lines, this correspond to a Doppler broadening of 90eV. - The total CX spectrum, where non-thermal broadening due to l-mixing and Zeeman + The total CX spectrum, where non-thermal broadening due to :math:`l`-mixing and Zeeman splitting is included, is the sum of the Doppler spectra for every emission line, where the relative intensity of every transition and the population of every sublevel is taken into account. When we treat every emission line separately the analysis of a CX spectrum gets quite complicated. Therefore the total profile of all transition lines is presented as a single, but broadened Gaussian, of - which the peak position depends on the l-mixing and Zeeman splitting. This + which the peak position depends on the :math:`l`-mixing and Zeeman splitting. This Gaussian replace the :math:`\delta`-function in equation. -**Assumption: at the moment the collisional l-mixing and Zeeman splitting is not taken into account** +**Assumption: at the moment the collisional** :math:`l`- **mixing and Zeeman splitting is not taken into account** It can however be easily done. @@ -339,13 +344,13 @@ is described by the Boltzmann equation :eq:`boltzman`: .. math:: :label: boltzman - \frac{\partial f_{Z^{\alpha+}}}{\partial t} + \vec{u}.\vec{\nabla} f_{Z^{\alpha+}} - + \frac{\vec{F}}{m_{Z^{\alpha+}}}.\vec{\nabla_{\vec{u}}} f_{Z^{\alpha+}} - = \left(\frac{\partial f_{Z^{\alpha+}}}{\partial t}\right)_{col} + \frac{\partial f_{Z^{\alpha+}}}{\partial t} + \vec{u}\cdot\vec{\nabla} f_{Z^{\alpha+}} + + \frac{\vec{F}}{m_{Z^{\alpha+}}}\cdot\vec{\nabla_{\vec{u}}} f_{Z^{\alpha+}} + = \left(\frac{\partial f_{Z^{\alpha+}}}{\partial t}\right)_\mathrm{col} The distribution function changes as a result of the forces :math:`F` and collisions -:math:`\left(\frac{\partial f_{Z^{\alpha+}}}{\partial t}\right)_{col}`. +:math:`\left(\frac{\partial f_{Z^{\alpha+}}}{\partial t}\right)_\mathrm{col}`. In a plasma the main forces are long-range Lorentz force :math:`\vec{F} = q_{\alpha}(\vec{E} + \vec{u}\times\vec{B})` @@ -354,29 +359,29 @@ reaction can be written as follows: .. math:: - \frac{\partial f_{Z^{*,\alpha+}}}{\partial t} + \vec{u}.\vec{\nabla} f_{Z^{*,\alpha+}} - + \frac{\vec{F}}{m_{Z^{*,\alpha+}}}.\vec{\nabla_{\vec{u}}} f_{Z^{*,\alpha+}} - = source\left(Z^{*,\alpha+}\right) - sink\left(Z^{*,\alpha+}\right) + \frac{\partial f_{Z^{*,\alpha+}}}{\partial t} + \vec{u}\cdot\vec{\nabla} f_{Z^{*,\alpha+}} + + \frac{\vec{F}}{m_{Z^{*,\alpha+}}}\cdot\vec{\nabla_{\vec{u}}} f_{Z^{*,\alpha+}} + = \mathrm{source}\left(Z^{*,\alpha+}\right) - \mathrm{sink}\left(Z^{*,\alpha+}\right) As source for ion :math:`Z^{*,\alpha+}`, the charge exchange reaction with a neutral is considered and for sink it is the re-ionisation taking place in the plasma. -**Assumption: we ignore the transport of ion in space:** :math:`\vec{u}.\vec{\nabla} f_{Z^{*,\alpha+}} \approx 0` **, local calculation.** +**Assumption: we ignore the transport of ion in space:** :math:`\vec{u}\cdot\vec{\nabla} f_{Z^{*,\alpha+}} \approx 0` **, local calculation.** - In the case of :math:`He^{*,+}` (plume), the transport in space cannot be ignored. + In the case of :math:`\mathrm{He}^{*,+}` (plume), the transport in space cannot be ignored. **Assumption: we neglect the electric field in the Lorentz force** :math:`q_{\alpha}\vec{E} \approx \vec{0}` .. math:: \frac{\partial f_{Z^{*,\alpha+}}}{\partial t} - + \frac{q_{\alpha}\vec{u}\times\vec{B}}{m_{Z^{*,\alpha+}}}.\vec{\nabla_{\vec{u}}} f_{Z^{*,\alpha+}} - = source\left(Z^{*,\alpha+}\right) - sink\left(Z^{*,\alpha+}\right) + + \frac{q_{\alpha}\vec{u}\times\vec{B}}{m_{Z^{*,\alpha+}}}\cdot\vec{\nabla_{\vec{u}}} f_{Z^{*,\alpha+}} + = \mathrm{source}\left(Z^{*,\alpha+}\right) - \mathrm{sink}\left(Z^{*,\alpha+}\right) -* With a sink :math:`sink\left(Z^{*,\alpha+}\right) = \frac{f_{Z^{*,\alpha+}}}{\tau_{Z^{*,\alpha+}}}` +* With a sink :math:`\mathrm{sink}\left(Z^{*,\alpha+}\right) = \frac{f_{Z^{*,\alpha+}}}{\tau_{Z^{*,\alpha+}}}` With :math:`\tau_{Z^{*,\alpha+}}` being the lifetime of the excited ion. -* And the source :math:`source\left(Z^{*,\alpha+}\right) = Q^{CX, Z^{(\alpha+1)+}, H^0}_{n\rightarrow n'}(E_c).f_{Z^{(\alpha+1)+}}.n_{H^0}` +* And the source :math:`\mathrm{source}\left(Z^{*,\alpha+}\right) = Q^{\mathrm{CX}, Z^{(\alpha+1)+}, H^0}_{n\rightarrow n'}(E_\mathrm{c})\cdot f_{Z^{(\alpha+1)+}}\cdot n_{H^0}` due to the charge-exchange reaction. **Assumption: no gyro-motion of excited ions** :math:`Z^{*,\alpha+}` @@ -398,10 +403,12 @@ The assumption here is that we have a distribution function in the velocity spac that the excited population of ion :math:`f_{Z^{*,\alpha+}}(\vec{u})` after the electron capture is of the same description. -The spectrum of light coming from a small volume dV and observed in the direction +The spectrum of light coming from a small volume :math:`\mathrm{d}V` and observed in the direction :math:`\vec{l}` can be written as: .. math:: - dI_{obs, n\rightarrow n'}(\lambda) = n_{H^0}.n_{Z^{(\alpha+1)+}}.\int_{\vec{u}} - f_{Z^{(\alpha+1)+}}(\vec{u}-\vec{v}).q^{CX, Z^{(\alpha+1)+}, H^0}_{n\rightarrow n'}(E_c). - \delta(\lambda-\lambda_D).d\vec{u} \ No newline at end of file + \mathrm{d}I_{\mathrm{obs}, n\rightarrow n'}(\lambda) = + n_{H^0}\cdot n_{Z^{(\alpha+1)+}}\cdot + \int_{\vec{u}}\mathrm{d}\vec{u}\; + f_{Z^{(\alpha+1)+}}(\vec{u}-\vec{v})\cdot q^{\mathrm{CX}, Z^{(\alpha+1)+}, H^0}_{n\rightarrow n'}(E_\mathrm{c}) + \cdot \delta(\lambda-\lambda_\mathrm{D}) \ No newline at end of file