#include <NonLTELineGasMix.hpp>

Classes | |
| struct | ColPartner |
Public Types | |
| enum class | InitialLevelPopsCase : int { LTE , CollisionallyExcited , Custom } |
| enum class | Species : int { Test , Hydroxyl , HydroxylHFS , Formyl , HydrogenCyanide , CarbonMonoxide , MolecularHydrogen , AtomicCarbon , IonizedCarbon , DoublyIonizedCarbon , TriplyIonizedCarbon , FourTimesIonizedCarbon , FiveTimesIonizedCarbon , AtomicNitrogen , IonizedNitrogen , DoublyIonizedNitrogen , TriplyIonizedNitrogen , FourTimesIonizedNitrogen , FiveTimesIonizedNitrogen , SixTimesIonizedNitrogen , AtomicOxygen , IonizedOxygen , DoublyIonizedOxygen , TriplyIonizedOxygen , FourTimesIonizedOxygen , FiveTimesIonizedOxygen , SixTimesIonizedOxygen , SevenTimesIonizedOxygen , AtomicNeon , IonizedNeon , DoublyIonizedNeon , TriplyIonizedNeon , FourTimesIonizedNeon , FiveTimesIonizedNeon , SixTimesIonizedNeon , SevenTimesIonizedNeon , EightTimesIonizedNeon , NineTimesIonizedNeon , IonizedSodium , DoublyIonizedSodium , TriplyIonizedSodium , FourTimesIonizedSodium , FiveTimesIonizedSodium , SixTimesIonizedSodium , SevenTimesIonizedSodium , EightTimesIonizedSodium , NineTimesIonizedSodium , TenTimesIonizedSodium , IonizedMagnesium , DoublyIonizedMagnesium , TriplyIonizedMagnesium , FourTimesIonizedMagnesium , FiveTimesIonizedMagnesium , SixTimesIonizedMagnesium , SevenTimesIonizedMagnesium , EightTimesIonizedMagnesium , NineTimesIonizedMagnesium , TenTimesIonizedMagnesium , AtomicSilicon , IonizedSilicon , DoublyIonizedSilicon , TriplyIonizedSilicon , FourTimesIonizedSilicon , FiveTimesIonizedSilicon , SixTimesIonizedSilicon , SevenTimesIonizedSilicon , EightTimesIonizedSilicon , NineTimesIonizedSilicon , TenTimesIonizedSilicon , AtomicSulfur , IonizedSulfur , DoublyIonizedSulfur , TriplyIonizedSulfur , FourTimesIonizedSulfur , FiveTimesIonizedSulfur , SixTimesIonizedSulfur , SevenTimesIonizedSulfur , EightTimesIonizedSulfur , NineTimesIonizedSulfur , TenTimesIonizedSulfur , DoublyIonizedArgon , TriplyIonizedArgon , FourTimesIonizedArgon , FiveTimesIonizedArgon , SixTimesIonizedArgon , SevenTimesIonizedArgon , EightTimesIonizedArgon , NineTimesIonizedArgon , TenTimesIonizedArgon , IonizedIron , DoublyIonizedIron , TriplyIonizedIron , FourTimesIonizedIron , FiveTimesIonizedIron , SixTimesIonizedIron , SevenTimesIonizedIron , EightTimesIonizedIron , NineTimesIonizedIron , TenTimesIonizedIron } |
| Public Types inherited from MaterialMix | |
| enum class | DynamicStateType { None , Primary , Secondary , PrimaryIfMergedIterations } |
| enum class | MaterialType { Dust , Electrons , Gas } |
Public Member Functions | |
| const vector< double > & | defaultCollisionPartnerRatios () const |
| double | defaultTemperature () const |
| double | defaultTurbulenceVelocity () const |
| bool | errorForGaussianIntegral () const |
| DynamicStateType | hasDynamicMediumState () const override |
| bool | hasExtraSpecificState () const override |
| bool | hasLineEmission () const override |
| bool | hasNegativeExtinction () const override |
| double | indicativeTemperature (const MaterialState *state, const Array &Jv) const override |
| void | initializeSpecificState (MaterialState *state, double metallicity, double temperature, const Array ¶ms) const override |
| InitialLevelPopsCase | initialLevelPopsCase () const |
| string | initialLevelPopsFilename () const |
| bool | isSpecificStateConverged (int numCells, int numUpdated, int numNotConverged, MaterialState *currentAggregate, MaterialState *previousAggregate) const override |
| Array | lineEmissionCenters () const override |
| Array | lineEmissionMasses () const override |
| Array | lineEmissionSpectrum (const MaterialState *state, const Array &Jv) const override |
| double | lowestBranchingRatio () const |
| double | lowestOpticalDepth () const |
| double | mass () const override |
| double | maxChangeInGlobalLevelPopulations () const |
| double | maxChangeInLevelPopulations () const |
| double | maxFractionNotConvergedCells () const |
| int | maxUpperLevelForRadiation () const |
| int | numEnergyLevels () const |
| double | opacityAbs (double lambda, const MaterialState *state, const PhotonPacket *pp) const override |
| double | opacityExt (double lambda, const MaterialState *state, const PhotonPacket *pp) const override |
| double | opacitySca (double lambda, const MaterialState *state, const PhotonPacket *pp) const override |
| vector< SnapshotParameter > | parameterInfo () const override |
| bool | peeloffScattering (double &I, double &Q, double &U, double &V, double &lambda, Direction bfkobs, Direction bfky, const MaterialState *state, const PhotonPacket *pp) const override |
| void | performScattering (double lambda, const MaterialState *state, PhotonPacket *pp) const override |
| double | sectionAbs (double lambda) const override |
| double | sectionExt (double lambda) const override |
| double | sectionSca (double lambda) const override |
| Species | species () const |
| vector< StateVariable > | specificStateVariableInfo () const override |
| bool | storeMeanIntensities () const |
| bool | updateDynamicStatesFlag () const |
| UpdateStatus | updateSpecificState (MaterialState *state, const Array &Jv) const override |
| Public Member Functions inherited from EmittingGasMix | |
| MaterialType | materialType () const override |
| double | sourceWeight () const |
| double | wavelengthBias () const |
| WavelengthDistribution * | wavelengthBiasDistribution () const |
| Range | wavelengthRange () const override |
| Public Member Functions inherited from MaterialMix | |
| virtual double | asymmpar (double lambda) const |
| virtual Array | emissionSpectrum (const MaterialState *state, const Array &Jv) const |
| virtual DisjointWavelengthGrid * | emissionWavelengthGrid () const |
| virtual Array | emissivity (const Array &Jv) const |
| virtual bool | hasContinuumEmission () const |
| virtual bool | hasPolarizedAbsorption () const |
| virtual bool | hasPolarizedEmission () const |
| virtual bool | hasPolarizedScattering () const |
| virtual bool | hasResonantScattering () const |
| virtual bool | hasScatteringDispersion () const |
| virtual bool | hasStochasticDustEmission () const |
| bool | isDust () const |
| bool | isElectrons () const |
| bool | isGas () const |
| virtual bool | scatteringEmulatesSecondaryEmission () const |
| virtual const Array & | sectionsAbs (double lambda) const |
| virtual const Array & | sectionsAbspol (double lambda) const |
| virtual const Array & | thetaGrid () const |
| Public Member Functions inherited from SimulationItem | |
| template<class T> | |
| T * | find (bool setup=true) const |
| template<class T> | |
| T * | interface (int upLevels, int downLevels, bool setup) const |
| virtual string | itemName () const |
| void | setup () |
| string | typeAndName () const |
| Public Member Functions inherited from Item | |
| Item (const Item &)=delete | |
| virtual | ~Item () |
| void | addChild (Item *child) |
| const vector< Item * > & | children () const |
| virtual void | clearItemListProperty (const PropertyDef *property) |
| void | destroyChild (Item *child) |
| virtual bool | getBoolProperty (const PropertyDef *property) const |
| virtual vector< double > | getDoubleListProperty (const PropertyDef *property) const |
| virtual double | getDoubleProperty (const PropertyDef *property) const |
| virtual string | getEnumProperty (const PropertyDef *property) const |
| virtual int | getIntProperty (const PropertyDef *property) const |
| virtual vector< Item * > | getItemListProperty (const PropertyDef *property) const |
| virtual Item * | getItemProperty (const PropertyDef *property) const |
| virtual string | getStringProperty (const PropertyDef *property) const |
| int | getUtilityProperty (string name) const |
| virtual void | insertIntoItemListProperty (const PropertyDef *property, int index, Item *item) |
| Item & | operator= (const Item &)=delete |
| Item * | parent () const |
| virtual void | removeFromItemListProperty (const PropertyDef *property, int index) |
| virtual void | setBoolProperty (const PropertyDef *property, bool value) |
| virtual void | setDoubleListProperty (const PropertyDef *property, vector< double > value) |
| virtual void | setDoubleProperty (const PropertyDef *property, double value) |
| virtual void | setEnumProperty (const PropertyDef *property, string value) |
| virtual void | setIntProperty (const PropertyDef *property, int value) |
| virtual void | setItemProperty (const PropertyDef *property, Item *item) |
| virtual void | setStringProperty (const PropertyDef *property, string value) |
| void | setUtilityProperty (string name, int value) |
| virtual string | type () const |
| Public Member Functions inherited from WavelengthRangeInterface | |
| virtual | ~WavelengthRangeInterface () |
Protected Member Functions | |
| NonLTELineGasMix () | |
| void | setupSelfBefore () override |
| Protected Member Functions inherited from EmittingGasMix | |
| EmittingGasMix () | |
| Protected Member Functions inherited from MaterialMix | |
| MaterialMix () | |
| Configuration * | config () const |
| Random * | random () const |
| Protected Member Functions inherited from SimulationItem | |
| SimulationItem () | |
| virtual bool | offersInterface (const std::type_info &interfaceTypeInfo) const |
| virtual void | setupSelfAfter () |
| Protected Member Functions inherited from Item | |
| Item () | |
| Protected Member Functions inherited from SourceWavelengthRangeInterface | |
| SourceWavelengthRangeInterface () | |
| Protected Member Functions inherited from WavelengthRangeInterface | |
| WavelengthRangeInterface () | |
Private Types | |
| using | BaseType |
| using | ItemType |
Private Member Functions | |
| double | solveLevelPopulations (MaterialState *state, const Array &Jv) const |
Private Attributes | |
| vector< double > | _branchRatio |
| Array | _center |
| vector< ColPartner > | _colPartner |
| vector< double > | _defaultCollisionPartnerRatios |
| double | _defaultTemperature |
| double | _defaultTurbulenceVelocity |
| Array | _dlambdav |
| vector< double > | _einsteinA |
| vector< double > | _einsteinBlu |
| vector< double > | _einsteinBul |
| vector< double > | _energy |
| bool | _errorForGaussianIntegral |
| int | _indexFirstColPartnerDensity |
| int | _indexFirstLevelPopulation |
| int | _indexFirstMeanIntensity |
| int | _indexKineticTemperature |
| vector< int > | _indexLowRad |
| vector< int > | _indexUpRad |
| InitialLevelPopsCase | _initialLevelPopsCase |
| string | _initialLevelPopsFilename |
| vector< Array > | _initLevelPops |
| Array | _lambdav |
| double | _lowestBranchingRatio |
| double | _lowestOpticalDepth |
| double | _mass |
| double | _maxChangeInGlobalLevelPopulations |
| double | _maxChangeInLevelPopulations |
| double | _maxFractionNotConvergedCells |
| int | _maxUpperLevelForRadiation |
| string | _name |
| int | _numColPartners |
| int | _numEnergyLevels |
| int | _numLevels |
| int | _numLines |
| int | _numWavelengths |
| Species | _species |
| bool | _storeMeanIntensities |
| bool | _updateDynamicStatesFlag |
| vector< double > | _weight |
Friends | |
| class | ItemRegistry |
The NonLTELineGasMix class describes the material properties related to selected transitions in selected molecules and atoms. For each supported species, the current implementation includes a number of rotational energy levels (quantum number \(J\)) at the base vibrational level (quantum number \(v=0\)) for molecules and electronic energy levels and hyperfine-split levels for atoms, and supports the allowed transitions between these levels. Vibrational energy levels and the corresponding rovibrational transitions may be added later. The class properties allow configuring the species and the number of transitions to be considered.
For each supported transition, the emission luminosity and absorption opacity in a given cell are determined from the gas properties defined in the input model and the local radiation field calculated by the simulation. The class performs an iterative, non-LTE calculation including the effects of collisional transitions (excitation and de-excitation with one or more types of interaction partners) and photonic transitions (spontaneous emission, absorption, and induced emission). This allows establishing the energy level distribution (population) for a wide range of material densities and radiation fields.
Supported species and transitions
The current implementation supports the following molecular or atomic species:
Molecules The properties relevant to the calculation of the level populations and collision partners of the following molecules are based on the LAMDA database ( https://home.strw.leidenuniv.nl/~moldata/; Schöier et al. 2005; van der Tak et al. 2020). According to the user's choice, the number of energy levels can be set by the maxEnergyLevels property within the range of supported energy levels for each species.
Two-level test molecule (TT): a fictive test molecule (called TT for our purposes) that has just two rotational energy levels with a corresponding transition line at 1666.67 \(\mu\mathrm{m}\). The single collisional interaction partner is molecular hydrogen. The properties of this molecule are defined by van Zadelhoff et al. 2002 for use with the first benchmark problem described there.Hydroxyl radical (OH): includes rotational energy levels up to \(J=25/2\) without hyperfine-split levels. The corresponding transition lines are at wavelengths from 10 \(\mu\mathrm{m}\) to 2 \(\mathrm{m}\). The collisional interaction partners include molecular and neutral atomic hydrogen and neutral atomic Helium.Hydroxyl radical (OHhfs): includes rotational energy levels up to \(J=5/2\) including hyperfine-split levels. The corresponding transition lines are at wavelengths from 34.6 \(\mu\mathrm{m}\) to 186 \(\mathrm{mm}\). The single collisional interaction partner is molecular hydrogen.Formyl cation (HCO+): includes rotational energy levels up to \(J=21\). The corresponding transition lines are at wavelengths from 160.3 to 3361 \(\mu\mathrm{m}\). The single collisional interaction partner is molecular hydrogen.HydrogenCyanide cation (HCN): includes rotational energy levels up to \(J=25\). The corresponding transition lines are at wavelengths from 135.6 to 3382 \(\mu\mathrm{m}\). The collisional interaction partners include molecular hydrogen and electrons.Carbon monoxide (CO): includes rotational energy levels up to \(J=40\). The corresponding transition lines are at wavelengths from 65.7 to 2601 \(\mu\mathrm{m}\). The single collisional interaction partner is molecular hydrogen.Molecular hydrogen (H2): includes rotational energy levels up to \(J=31\). The corresponding transition lines are at wavelengths from 28.2 to 3.3 \(\mu\mathrm{m}\). The collisional interaction partners include molecular hydrogen, neutral atomic hydrogen, ionized atomic hydrogen, and helium.An assumption of molecular hydrogen: Molecular hydrogen exists in ortho (J is odd) and para (J is even) flavors, and these flavors have different collisional coefficients. The current implementation assumes that the ratio of ortho to para is 3 to 1.
Atoms Atomic line emission from C, O, N, S, Si, Ne, Na, Mg, Fe, and Ar in ionization states ranging from neutral up to ten times ionized is included. The atomic data required for calculating level populations and electron collisional transition rates are adopted from the CHIANTI database (https://www.chiantidatabase.org/chianti_direct_access.html; Dere et al. 1997; Del Zanna et al. 2021).
In addition, collisional transition rates with other collision partners are available for CI, CII, OI, OIII, NII, SiI, and SI, based on the LAMDA database. The available collision partners are neutral, ionized, and molecular hydrogen, as well as neutral helium for CI and OI; atomic and molecular hydrogen for CII; and atomic hydrogen for OIII, NII, SiI, and SI.
Level populations can be calculated from the ground state up to the 20th excited level, including all hyperfine-split sublevels within each electronic state. The corresponding radiative transitions span wavelengths from the ultraviolet to the submillimeter regime. The maximum number of energy levels included in the calculation can be specified by the user through the maxEnergyLevels property, up to this limit. For example, users may be interested in only a famous following far-infrared line emission rather than UV and optical lines: CII (158 \(\mu\mathrm{m}\)), OI (63 and 145 \(\mu\mathrm{m}\)), NII (122 and 205 \(\mu\mathrm{m}\)), CI (370 and 609 \(\mu\mathrm{m}\)), OIII (52 and 88 \(\mu\mathrm{m}\)). maxEnergyLevels should be set to 2 for CII, 3 for OI, NII, CI, and OIII.
Note on highly ionized species: The current implementation does not include photoionization and recombination processes. Consequently, the level populations of highly ionized species may not be accurately determined in environments with strong ionizing radiation fields.
Neglecting irrelevant transitions: Transitions that have negligible impact on the level populations can be safely ignored to improve computational efficiency by setting the lowestBranchingRatio property to a value greater than zero. The default value of 0.0 includes all transitions, while a value of 0.001, for example, would exclude the calculation of emissivity and opacity of the transitions that have a branching ratio below 0.1% of the total decay rate from the upper level. This can reduce the number of transitions considered in the calculations and avoide unnecessary computations for transitions that have a negligible effect on the level populations. maxUpperLevelForRadiation can ignore radiative transitions from high upper levels. Radiative transitions are included up to the maxUpperLevelForRadiation-th level counted from the ground state (ground level = 1), and transitions from higher upper levels are excluded from the statistical-equilibrium equations and from emission/absorption calculations. For example, to include transitions up to the 10th level from the ground state, set maxUpperLevelForRadiation to 10. This property is useful when users keep many levels for accurate level populations but are interested mainly in emission/absorption from lower levels. The default value of 999 includes all transitions.
Configuring the simulation
Simulations that include gas represented by the NonLTELineGasMix often also include dust, although this is not a requirement. In any case, the simulation must have one or more primary sources that trigger the molecular lines directly (e.g. the cosmic microwave background) or indirectly (e.g. by heating the dust and thus causing thermal dust emission), or both. The simulationMode should be set to "GasEmission" or "DustAndGasEmission" correspondingly.
Because the secondary emission and the radiation field are calculated self-consistently, iterateSecondaryEmission should always be enabled. If the wavelength range of the primary source(s) significantly overlaps the emission lines of the species under consideration (in other words, if the opacity at the line wavelengths significantly affects the primary radiation field), then includePrimaryEmission in IterationOptions must be enabled as well. If not, this property can be left disabled. In both cases, iteratePrimaryEmission can be left disabled unless iteration is required for other media (for example, to self-consistently calculate radiative dust destruction).
The radiation field wavelength grid should properly resolve the UV, optical, and infrared wavelength range (in case the simulation includes dust) and the wavelength ranges of the supported transition lines. Separate instruments can be configured for the relevant wavelength ranges, e.g. using a logarithmic grid for the continuum spectrum and linear grids for the line profiles.
During the initial primary emission segment, the simulation determines the radiation field resulting from the primary sources, dust attenuation (if present) and molecular line absorption based on default equilibrium level populations. The resulting radiation field allows a first estimation of the level populations for each spatial grid cell; this calculation happens in the updateSpecificState() function.
During secondary emission, the simulation takes into account emission from all configured media in addition to absorption by these same media, including molecular lines in both cases. The previously stored level populations allow calculating the line emission spectrum and the line absorption cross sections. This results in an updated radiation field, which will in turn influence the level populations (and for high optical depths, possibly the dust temperature), which in turn influences the secondary emission spectra. In order to obtain a self-consistent result, the simulation must therefore iterate over secondary emission.
The input model must provide values for the spatial distribution of several medium properties, including the number density of the species under consideration, the number density of any relevant collisional partner species, the kinetic gas temperature, and the turbulence velocity. These values remain constant during the simulation. Most often, this information will be read from an input file by associating the NonLTELineGasMix with a subclass of ImportedMedium. For that medium component, the ski file attribute importTemperature must be set to 'true', and importMetallicity and importVariableMixParams must be left at 'false'. The additional columns required by the material mix are automatically imported and are expected after all other columns. For example, if bulk velocities are also imported for this medium component (i.e. importVelocity is 'true'), the column order would be
\[ ..., n_\mathrm{mol}, T_\mathrm{kin}, v_\mathrm{x}, v_\mathrm{y}, v_\mathrm{z}, n_\mathrm{col1} [, n_\mathrm{col1}, ...], v_\mathrm{turb}\]
For basic testing purposes, the NonLTELineGasMix can also be associated with a geometric medium component. The geometry then defines the spatial density distribution of the species under consideration (i.e. \(n_\mathrm{mol}\)), and the NonLTELineGasMix configuration properties specify a fixed default value for the other properties that will be used across the spatial domain. In this case, the number densities of the collisional partners are defined by a constant multiplier relative to \(n_\mathrm{mol}\).
Although the NonLTELineGasMix couples the level populations to the radiation field, in some cases the radiation field does not significantly affect the level populations (e.g., UV and optical lines from atomic species). In such cases, the user can disable updating the level populations by setting the updateDynamicStatesFlag property to 'false'.
Thermal motion and turbulence
The thermal velocity in a medium of particles with mass \(m\) at temperature \(T_\mathrm{kin}\) is defined as
\[ v_\mathrm{th} = \sqrt{\frac{2kT_\mathrm{kin}}{m}}. \]
This value corresponds to the most probable particle speed, i.e. the point where the probability distribution of the velocity vector norm reaches its maximum value. One often considers an additional source of line broadening caused by subgrid processes other than those corresponding to the kinetic temperature. This motion is characterized by the turbulent velocity \(v_\mathrm{turb}\). Assuming a Gaussian line profile, the total velocity dispersion \(v_\mathrm{s}\) (the standard deviation of the Gaussian in velocity space) is then defined through
\[ \sqrt{2}\,v_\mathrm{s} = \sqrt{v_\mathrm{th}^2 + v_\mathrm{turb}^2}. \]
We can artificially combine the effect of both thermal motion and turbulence into an effective temperature,
\[ T_\mathrm{eff} = T_\mathrm{kin} + \frac{m v_\mathrm{turb}^2}{2k}. \]
If the Gaussian profile is not expressed when convolving the radiation field with the Gaussian profile, the simulation may fail and output an error. Sometimes, the emission is not critical for estimating the level populations. In this case, the user can choose to take a warning instead of an error by setting the errorForGaussianIntegral property to 'false'.
Numerical convergence
As mentioned above, a simulation including this material mix performs iterations to self-consistently calculate the radiation field and the medium state (i.e. the energy level populations that drive the line emission). This class offers three user-configurable properties that specify the convergence criteria for this iterative process.
The first two properties configure a criterion based on statistics per spatial cell. The maxChangeInLevelPopulations property specifies the maximum relative change between consecutive iterations in the level populations for a given spatial cell for that cell to be considered converged. The maxFractionNotConvergedCells property then specifies the maximum fraction of cells (relative to the total number of cells in the simulation) that may be left not converged for the whole spatial domain to be considered converged.
The third property configures a global criterion. The maxChangeInGlobalLevelPopulations property specifies the maximum relative change between consecutive iterations in the global level populations, accumulated over the complete spatial domain, for the spatial domain to be considered converged. In other words, convergence has been reached if
\[ \epsilon = \underset{i}{\mathrm{max}} \left| \frac{N_i^{(k)} - N_i^{(k-1)}} {N_i^{(k-1)}} \right| \le \epsilon_\mathrm{max}\]
where \(N_i^{(k)}\) denotes the total population across the spatial domain for energy level \(i\) at iteration \(k\) and \(\epsilon_\mathrm{max}\) is the user-configured value of the maxChangeInGlobalLevelPopulations property.
Both criteria must be satisfied simultaneously. Howver, the user can effectively disable a criterion by specifying very liberal maximum values.
Level populations
We denote the populations for the \(N\) supported energy levels as \(n_i\), with indices \(i=0,N-1\) increasing from lowest to highest energy state, and with \(\sum_i n_i = n_\mathrm{mol}\). The level populations form the basis to calculate the emission luminosities and the absorption opacities at later stage. Their values are obtained by solving the set of statistical equilibrium equations given by
\[ \sum_{j>i} \Big[n_jA_{ji} + (n_jB_{ji} - n_iB_{ij})J_{\lambda,ji})\Big] - \sum_{j<i} \Big[n_iA_{ij} + (n_iB_{ij} - n_jB_{ji})J_{\lambda,ij})\Big] + \sum_{j\neq i} \Big[n_jC_{ji} - n_iC_{ij}\Big]=0, \quad i=0,N-1\]
where \(J_{\lambda,ul}\) is the mean radiation field intensity integrated over the line profile corresponding to the transition from upper energy level \(u\) to lower energy level \(l\). Furthermore, \(A_{ul}\), \(B_{ul}\), \(B_{lu}\) are the Einstein coefficients for spontaneous emission, induced emission, and absorption, and \(C_{ul}\), \(C_{lu}\) the coefficients for collisional excitation and de-excitation. These coefficients are taken from the literature.
The Einstein coefficients \(A_{ul}\), \(B_{ul}\), and \(B_{lu}\) are constant for each transition, and the \(B_{ul}\) and \(B_{lu}\) coefficients can be obtained from the \(A_{ul}\) coefficients through
\[ B_{ul} = \frac{\lambda_{ul}^5}{2 hc^2}A_{ul} \]
and
\[B_{lu} = \frac{g_u}{g_l} B_{ul} = \frac{g_u}{g_l} \frac{\lambda_{ul}^5}{2 hc^2}A_{ul}, \]
where \(g_u\) and \(g_l\) represent the degeneracy of the upper and lower energy levels, respectively. The collisional coefficients \(C_{ul}\) and \(C_{lu}\) depend on the number density of the collisional partner and on the kinetic temperature \(T_\mathrm{kin}\) of the gas. These coefficients are related by
\[ \frac{C_{lu}}{C_{ul}} = \frac{g_u}{g_l} \exp(-E_{ul}/kT_\mathrm{kin}).\]
Emission
The integrated line luminosity \(L_{ul}\) corresponding to the transition from upper energy level \(u\) to lower energy level \(l\) for a given spatial cell is given by
\[ L_{ul} = \frac{hc}{\lambda_{ul}} A_{ul} n_u V_\mathrm{cell}, \]
where \(\lambda_{ul}\) is the transition wavelength and \(V_\mathrm{cell}\) is the volume of the cell. The SKIRT framework automatically adds a Gaussian line profile assuming a thermal velocity corresponding to the effective temperature in the cell and the mass of a molecule, in addition to any Doppler shifts caused by the bulk velocity in the cell.
Absorption
The absorption opacity \(k^\text{abs}(\lambda)\) as a function of wavelength \(\lambda\) is given by
\[ k^\text{abs}(\lambda) = \sum_{ul} \, \frac{h c}{4\pi \lambda_{ul}} (n_l\,B_{lu}-n_u\,B_{ul}) \,\phi_{ul}(\lambda) \]
where the sum runs over all supported transitions, \(u\) and \(l\) are the indices of the energy levels before and after the transition, and \(\phi_{ul}(\lambda)\) is the Gaussian profile of the line corresponding to the transition.
The calculation explicitly includes the Gaussian line profile caused by thermal motion of the molecules in the local bulk velocity frame of the cell. Moreover, the absorption profiles of all supported lines are superposed on top of each other. In practice, the implementation includes just the terms that have a significant contribution at any given wavelength.
Limiting negative optical depth
The formula for the absorption opacity given in the previous section yields a negative value in case the medium exhibits stimulated emission. The explicit absorption technique (see the MonteCarloSimulation class) supports the corresponding negative optical depths along a photon path. However, numerical problems arise if the negative optical depth magnitude becomes too high. This may happen, for example, as a result of Monte Carlo noise, or in the early stages when a simulation has not yet converged.
Therefore, this class imposes a user-configurable lower limit on the (negative) optical depth along a cell diagonal before returning an absorption opacity. The default limit is -2.
Storing mean intensities
As discussed above, the mean radiation field intensity \(J_{\lambda,ul}\) is determined for each transition line as a prerequisite for calculating the level populations in a given cell. These values are obtained by integrating the radiation field, as discretized on the simulation's radiation field wavelength grid, over the appropriate Gaussian line profile. There is no need to keep these values around for the regular operation of the code. However, they can form a relevant diagnostic to assess the level of Monte Carlo noise in the simulation or to evaluate iterative convergence. Therefore, if the storeMeanIntensities flag is turned on, the mean radiation field intensity at each transition line is stored in the medium state for each cell, so that the information can be probed using the CustomStateProbe class.
Providing initial level populations The initialLevelPopsCase property specifies how the initial level populations are assigned. By default, the populations in each cell are initialized assuming a Boltzmann distribution at the local gas temperature (i.e., LTE conditions; initialLevelPopsCase="LTE"). This assumption may significantly differ from the final non-LTE solution, although it often provides a convenient starting point that accelerates convergence. For example, many optical and UV emission lines from the ionized gas originate from excited levels whose populations are determined by the balance between collisional transitions and spontaneous radiative decay. In such cases, the user can initialize the populations using the collisionally excited solution by specifying initialLevelPopsCase="CollisionallyExcited". Alternatively, the users can set custom initial level populations using a text file by specifying initialLevelPopsCase="Custom". This option is particularly useful when restarting a SKIRT simulation from a previously converged solution. If the initialLevelPopsFilename string is nonempty, it specifies the name of a text column file with a column for each energy level and a row for each spatial cell in the simulation. Specifically, the first column lists a cell index that is ignored, and remaining columns list the relative population for each energy level in units of number density (the values are scaled to the total number density in the cell, so the specific units don't really matter). The rows must exactly match the number and ordering of the cells in the simulation's spatial grid (see below).
This input format is designed such that the text file can easily be produced by a CustomStateProbe instance in a previous simulation. For example, assuming 9 energy levels, one could configure a probe as follows:
<CustomStateProbe probeName="populations" indices="2-10" probeAfter="Run">
<form type="Form">
<PerCellForm/>
</form>
</CustomStateProbe>
The requirement to have an identical spatial grid in both simulations is easily met for 1D, 2D and 3D grids with a regular mesh in each spatial direction. For octree and binary tree grids the precise cell hierarchy is usually determined based on random samples of the medium density distribution, resulting in a slightly different structure for each run. To work around this problem, one needs to output the topology of the hierarchical grid in the first simulation using a TreeSpatialGridTopologyProbe instance, and load this topology in subsequent simulations using a FileTreeSpatialGrid instance.
When an item of this type is used, the names provided by the conditional value expression "CustomMediumState,DynamicState" are inserted into the name sets used for evaluating Boolean expressions.
|
strong |
The enumeration type indicating the assumed initial level population.
LTE : "LTE (the detailed balance condition between collisional transitions)".
CollisionallyExcited : "the detailed balance condition between collisional transitions and spontaneous emission".
Custom : "custom level populations provided in a file".
|
strong |
The enumeration type indicating the molecular or atomic species represented by a given NonLTELineGasMix instance. See the class header for more information.
Test : "Fictive two-level test molecule (TT)".
Hydroxyl : "Hydroxyl radical (OH)".
HydroxylHFS : "Hydroxyl radical (OH) with hyperfine structure".
Formyl : "Formyl cation (HCO+)".
HydrogenCyanide : "Hydrogen cyanide (HCN)".
CarbonMonoxide : "Carbon monoxide (CO)".
MolecularHydrogen : "Molecular hydrogen (H2)".
AtomicCarbon : "Atomic carbon (CI)".
IonizedCarbon : "Ionized carbon (CII)".
DoublyIonizedCarbon : "Doubly Ionized Carbon (CIII)".
TriplyIonizedCarbon : "Triply Ionized Carbon (CIV)".
FourTimesIonizedCarbon : "Four times Ionized Carbon (CV)".
FiveTimesIonizedCarbon : "Five times Ionized Carbon (CVI)".
AtomicNitrogen : "Atomic nitrogen (NI)".
IonizedNitrogen : "Ionized nitrogen (NII)".
DoublyIonizedNitrogen : "Doubly Ionized Nitrogen (NIII)".
TriplyIonizedNitrogen : "Triply Ionized Nitrogen (NIV)".
FourTimesIonizedNitrogen : "Four times Ionized Nitrogen (NV)".
FiveTimesIonizedNitrogen : "Five times Ionized Nitrogen (NVI)".
SixTimesIonizedNitrogen : "Six times Ionized Nitrogen (NVII)".
AtomicOxygen : "Atomic oxygen (OI)".
IonizedOxygen : "Ionized oxygen (OII)".
DoublyIonizedOxygen : "Doubly Ionized Oxygen (OIII)".
TriplyIonizedOxygen : "Triply Ionized Oxygen (OIV)".
FourTimesIonizedOxygen : "Four times Ionized Oxygen (OV)".
FiveTimesIonizedOxygen : "Five times Ionized Oxygen (OVI)".
SixTimesIonizedOxygen : "Six times Ionized Oxygen (OVII)".
SevenTimesIonizedOxygen : "Seven times Ionized Oxygen (OVIII)".
AtomicNeon : "Atomic Neon (NeI)".
IonizedNeon : "Ionized Neon (NeII)".
DoublyIonizedNeon : "Doubly Ionized Neon (NeIII)".
TriplyIonizedNeon : "Triply Ionized Neon (NeIV)".
FourTimesIonizedNeon : "Four times Ionized Neon (NeV)".
FiveTimesIonizedNeon : "Five times Ionized Neon (NeVI)".
SixTimesIonizedNeon : "Six times Ionized Neon (NeVII)".
SevenTimesIonizedNeon : "Seven times Ionized Neon (NeVIII)".
EightTimesIonizedNeon : "Eight times Ionized Neon (NeIX)".
NineTimesIonizedNeon : "Nine times Ionized Neon (NeX)".
IonizedSodium : "Ionized Sodium (NaII)".
DoublyIonizedSodium : "Doubly Ionized Sodium (NaIII)".
TriplyIonizedSodium : "Triply Ionized Sodium (NaIV)".
FourTimesIonizedSodium : "Four times Ionized Sodium (NaV)".
FiveTimesIonizedSodium : "Five times Ionized Sodium (NaVI)".
SixTimesIonizedSodium : "Six times Ionized Sodium (NaVII)".
SevenTimesIonizedSodium : "Seven times Ionized Sodium (NaVIII)".
EightTimesIonizedSodium : "Eight times Ionized Sodium (NaIX)".
NineTimesIonizedSodium : "Nine times Ionized Sodium (NaX)".
TenTimesIonizedSodium : "Ten times Ionized Sodium (NaXI)".
IonizedMagnesium : "Ionized Magnesium (MgII)".
DoublyIonizedMagnesium : "Doubly Ionized Magnesium (MgIII)".
TriplyIonizedMagnesium : "Triply Ionized Magnesium (MgIV)".
FourTimesIonizedMagnesium : "Four times Ionized Magnesium (MgV)".
FiveTimesIonizedMagnesium : "Five times Ionized Magnesium (MgVI)".
SixTimesIonizedMagnesium : "Six times Ionized Magnesium (MgVII)".
SevenTimesIonizedMagnesium : "Seven times Ionized Magnesium (MgVIII)".
EightTimesIonizedMagnesium : "Eight times Ionized Magnesium (MgIX)".
NineTimesIonizedMagnesium : "Nine times Ionized Magnesium (MgX)".
TenTimesIonizedMagnesium : "Ten times Ionized Magnesium (MgXI)".
AtomicSilicon : "Atomic Silicon (SiI)".
IonizedSilicon : "Ionized Silicon (SiII)".
DoublyIonizedSilicon : "Doubly Ionized Silicon (SiIII)".
TriplyIonizedSilicon : "Triply Ionized Silicon (SiIV)".
FourTimesIonizedSilicon : "Four times Ionized Silicon (SiV)".
FiveTimesIonizedSilicon : "Five times Ionized Silicon (SiVI)".
SixTimesIonizedSilicon : "Six times Ionized Silicon (SiVII)".
SevenTimesIonizedSilicon : "Seven times Ionized Silicon (SiVIII)".
EightTimesIonizedSilicon : "Eight times Ionized Silicon (SiIX)".
NineTimesIonizedSilicon : "Nine times Ionized Silicon (SiX)".
TenTimesIonizedSilicon : "Ten times Ionized Silicon (SiXI)".
AtomicSulfur : "Atomic Sulfur (SI)".
IonizedSulfur : "Ionized Sulfur (SII)".
DoublyIonizedSulfur : "Doubly Ionized Sulfur (SIII)".
TriplyIonizedSulfur : "Triply Ionized Sulfur (SIV)".
FourTimesIonizedSulfur : "Four times Ionized Sulfur (SV)".
FiveTimesIonizedSulfur : "Five times Ionized Sulfur (SVI)".
SixTimesIonizedSulfur : "Six times Ionized Sulfur (SVII)".
SevenTimesIonizedSulfur : "Seven times Ionized Sulfur (SVIII)".
EightTimesIonizedSulfur : "Eight times Ionized Sulfur (SIX)".
NineTimesIonizedSulfur : "Nine times Ionized Sulfur (SIX)".
TenTimesIonizedSulfur : "Ten times Ionized Sulfur (SXI)".
DoublyIonizedArgon : "Doubly Ionized Argon (ArIII)".
TriplyIonizedArgon : "Triply Ionized Argon (ArIV)".
FourTimesIonizedArgon : "Four times Ionized Argon (ArV)".
FiveTimesIonizedArgon : "Five times Ionized Argon (ArVI)".
SixTimesIonizedArgon : "Six times Ionized Argon (ArVII)".
SevenTimesIonizedArgon : "Seven times Ionized Argon (ArVIII)".
EightTimesIonizedArgon : "Eight times Ionized Argon (ArIX)".
NineTimesIonizedArgon : "Nine times Ionized Argon (ArX)".
TenTimesIonizedArgon : "Ten times Ionized Argon (ArXI)".
IonizedIron : "Ionized Iron (FeII)".
DoublyIonizedIron : "Doubly Ionized Iron (FeIII)".
TriplyIonizedIron : "Triply Ionized Iron (FeIV)".
FourTimesIonizedIron : "Four times Ionized Iron (FeV)".
FiveTimesIonizedIron : "Five times Ionized Iron (FeVI)".
SixTimesIonizedIron : "Six times Ionized Iron (FeVII)".
SevenTimesIonizedIron : "Seven times Ionized Iron (FeVIII)".
EightTimesIonizedIron : "Eight times Ionized Iron (FeIX)".
NineTimesIonizedIron : "Nine times Ionized Iron (FeX)".
TenTimesIonizedIron : "Ten times Ionized Iron (FeXI)".
|
inlineprotected |
Default constructor for concrete Item subclass NonLTELineGasMix: "A gas mix supporting rotational transitions in specific molecules and atoms".
|
inline |
This function returns the value of the discoverable double list property defaultCollisionPartnerRatios: "the default relative abundances of the collisional partners".
The minimum value for this property is "[0".
The maximum value for this property is "1e50]".
The default value for this property is given by the conditional value expression "1e4".
This property is displayed only if the Boolean expression "Level2" evaluates to true after replacing the names by true or false depending on their presence.
|
inline |
This function returns the value of the discoverable double property defaultTemperature: "the default temperature of the gas".
This property represents a physical quantity of type "temperature".
The minimum value for this property is "[0".
The maximum value for this property is "1e9]".
The default value for this property is given by the conditional value expression "1000".
This property is displayed only if the Boolean expression "Level2" evaluates to true after replacing the names by true or false depending on their presence.
|
inline |
This function returns the value of the discoverable double property defaultTurbulenceVelocity: "the default (non-thermal) turbulence velocity".
This property represents a physical quantity of type "velocity".
The minimum value for this property is "[0 km/s".
The maximum value for this property is "100000 km/s]".
The default value for this property is given by the conditional value expression "0 km/s".
This property is displayed only if the Boolean expression "Level2" evaluates to true after replacing the names by true or false depending on their presence.
|
inline |
This function returns the value of the discoverable Boolean property errorForGaussianIntegral: "treat insufficient Gaussian-integral accuracy as a fatal error (otherwise issue a warning)".
The default value for this property is given by the conditional value expression "true".
This property is displayed only if the Boolean expression "Level3" evaluates to true after replacing the names by true or false depending on their presence.
|
overridevirtual |
This function returns DynamicStateType::PrimaryIfMergedIterations, indicating that this material mix has a dynamic medium state with updates that are considered to affect primary emission when the simulation has merged iterations, and only secondary emission if not.
Reimplemented from MaterialMix.
|
overridevirtual |
This function returns true, indicating that the cross sections returned by this material mix depend on the values of specific state variables other than the number density.
Reimplemented from MaterialMix.
|
overridevirtual |
This function returns true, indicating that this material supports secondary line emission from gas.
Reimplemented from MaterialMix.
|
overridevirtual |
This function returns true, indicating that this material may have a negative absorption cross section. This happens when inverted level populations cause net stimulated emission.
Reimplemented from MaterialMix.
|
overridevirtual |
This function returns an indicative temperature of the material mix when it would be embedded in a given radiation field. The implementation in this class ignores the radiation field and returns the temperature stored in the specific state for the relevant spatial cell and medium component. This value corresponds to the temperature defined by the input model at the start of the simulation.
Reimplemented from MaterialMix.
|
overridevirtual |
This function initializes the specific state variables requested by this material mix through the specificStateVariableInfo() function except for the number density of the species under consideration. For this class, the function uses the imported values, or if not available, the user-configured default values. The level populations are left at zero.
Reimplemented from MaterialMix.
|
inline |
This function returns the value of the discoverable InitialLevelPopsCase enumeration property initialLevelPopsCase: "the assumed initial level population".
The default value for this property is given by the conditional value expression "LTE".
This property is displayed only if the Boolean expression "Level2" evaluates to true after replacing the names by true or false depending on their presence.
|
inline |
This function returns the value of the discoverable string property initialLevelPopsFilename: "the name of the file with initial level populations".
This property is required only if the Boolean expression "false" evaluates to true after replacing the names by true or false depending on their presence.
This property is displayed only if the Boolean expression "Level3" evaluates to true after replacing the names by true or false depending on their presence.
|
overridevirtual |
This function returns true if the state of the medium component corresponding to this material mix can be considered to be converged based on the given spatial cell statistics and aggregate material states, and false otherwise. For more information on the convergence criteria, see the corresponding section in the class header.
Reimplemented from MaterialMix.
|
overridevirtual |
This function returns a list with the line centers of the supported transitions.
Reimplemented from MaterialMix.
|
overridevirtual |
This function returns a list with the masses of the particles emitting each of the lines, i.e. the mass of a molecule or atom of the species under consideration in each case.
Reimplemented from MaterialMix.
|
overridevirtual |
This function returns a list with the line luminosities for the supported transitions in the spatial cell and medium component represented by the specified material state and the receiving material mix when it would be embedded in the specified radiation field.
Reimplemented from MaterialMix.
|
inline |
This function returns the value of the discoverable double property lowestBranchingRatio: "the minimum branching ratio for a transition to be considered".
The minimum value for this property is "[0".
The maximum value for this property is "1]".
The default value for this property is given by the conditional value expression "0".
|
inline |
This function returns the value of the discoverable double property lowestOpticalDepth: "Lower limit of (negative) optical depth along a cell diagonal".
The minimum value for this property is "[-10".
The maximum value for this property is "0]".
The default value for this property is given by the conditional value expression "-2".
This property is displayed only if the Boolean expression "Level3" evaluates to true after replacing the names by true or false depending on their presence.
|
overridevirtual |
This function returns the mass of a molecule or atom of the species under consideration.
Implements MaterialMix.
|
inline |
This function returns the value of the discoverable double property maxChangeInGlobalLevelPopulations: "the maximum relative change for the global level populations to be considered converged".
The minimum value for this property is "[0".
The maximum value for this property is "1]".
The default value for this property is given by the conditional value expression "0.05".
This property is displayed only if the Boolean expression "Level2" evaluates to true after replacing the names by true or false depending on their presence.
|
inline |
This function returns the value of the discoverable double property maxChangeInLevelPopulations: "the maximum relative change for the level populations in a cell to be considered converged".
The minimum value for this property is "[0".
The maximum value for this property is "1]".
The default value for this property is given by the conditional value expression "0.05".
This property is displayed only if the Boolean expression "Level2" evaluates to true after replacing the names by true or false depending on their presence.
|
inline |
This function returns the value of the discoverable double property maxFractionNotConvergedCells: "the maximum fraction of not-converged cells for all cells to be considered converged".
The minimum value for this property is "[0".
The maximum value for this property is "1]".
The default value for this property is given by the conditional value expression "0.01".
This property is displayed only if the Boolean expression "Level2" evaluates to true after replacing the names by true or false depending on their presence.
|
inline |
This function returns the value of the discoverable integer property maxUpperLevelForRadiation: "include transitions up to this upper level counted from ground (ground = 1)".
The minimum value for this property is "[0".
The maximum value for this property is "999]".
The default value for this property is given by the conditional value expression "999".
|
inline |
This function returns the value of the discoverable integer property numEnergyLevels: "the number of energy levels used (or 999 for all supported)".
The minimum value for this property is "2".
The maximum value for this property is "999".
The default value for this property is given by the conditional value expression "999".
This property is displayed only if the Boolean expression "Level2" evaluates to true after replacing the names by true or false depending on their presence.
|
overridevirtual |
This function returns the absorption opacity \(k^\text{abs}= n_\mathrm{mol} \varsigma^\text{abs}\) for the given wavelength and material state. The photon packet properties are not used.
Implements MaterialMix.
|
overridevirtual |
This function returns the extinction opacity \(k^\text{ext}=k^\text{abs}\) for the given wavelength and material state, which equals the absorption opacity because the scattering opacity is zero. The photon packet properties are not used.
Implements MaterialMix.
|
overridevirtual |
This function returns the scattering opacity \(k^\text{sca}\) which is trivially zero at all wavelengths.
Implements MaterialMix.
|
overridevirtual |
This function returns the number and type of import parameters required by this particular material mix as a list of SnapshotParameter objects. For this class, the function returns a descriptor for the number densities of the collisional partners and for the turbulence velocity. Importing the kinetic gas temperature should be enabled through the corresponding standard configuration flag.
Reimplemented from MaterialMix.
|
overridevirtual |
This function does nothing because the lines under consideration do not scatter.
Reimplemented from MaterialMix.
|
overridevirtual |
This function does nothing because the lines under consideration do not scatter.
Reimplemented from MaterialMix.
|
overridevirtual |
This function should return the absorption cross section using default properties. Because this value is hard to calculate for this material mix, this function returns zero.
Implements MaterialMix.
|
overridevirtual |
This function should return the extinction cross section using default properties. Because this value is hard to calculate for this material mix, this function returns zero.
Implements MaterialMix.
|
overridevirtual |
This function should return the scattering cross section using default properties. Because this value is hard to calculate for this material mix, this function returns zero.
Implements MaterialMix.
|
overrideprotectedvirtual |
This function loads the required information on the configured species from resource files:
The last two items are repeated for each collisional interaction partner of the species.
In a second step, the function calculates and caches some further values, including for example the Einstein B coefficients.
Reimplemented from MaterialMix.
|
private |
This function solves the statistical equilibrium equations for the level populations of the given material state under the specified radiation field, and stores the result back into the state. It returns the average relative change in the level populations compared to their previous values, for use as a convergence indicator. Unlike updateSpecificState(), this function always performs the calculation regardless of the updateDynamicStatesFlag property, so that initializeSpecificState() can use it to establish the initial, collisionally excited level populations even when dynamic updates are disabled.
|
inline |
This function returns the value of the discoverable Species enumeration property species: "the molecular or atomic species being represented".
The default value for this property is given by the conditional value expression "CarbonMonoxide".
|
overridevirtual |
This function returns a list of StateVariable objects describing the specific state variables used by the receiving material mix. For this class, the function returns a list containing descriptors for the properties defined in the input model and for a number of variables to hold the level populations derived from the radiation field and related information.
Implements MaterialMix.
|
inline |
This function returns the value of the discoverable Boolean property storeMeanIntensities: "store the mean radiation field intensity at each transition line".
The default value for this property is given by the conditional value expression "false".
This property is displayed only if the Boolean expression "Level3" evaluates to true after replacing the names by true or false depending on their presence.
|
inline |
This function returns the value of the discoverable Boolean property updateDynamicStatesFlag: "update level populations from the initial one".
The default value for this property is given by the conditional value expression "true".
This property is displayed only if the Boolean expression "Level3" evaluates to true after replacing the names by true or false depending on their presence.
|
overridevirtual |
Based on the specified radiation field and the input model properties found in the given material state, this function determines the level populations for the supported transitions and stores these results back in the given material state. The function returns the update status as described for the UpdateStatus class.
Reimplemented from MaterialMix.