Newsletter #5, October 2024

Some six months have passed since the last issue of the newsletter, and a number of new features and bug fixes have made their way into DREAM.

Enjoy!
The DREAM Developer Council

I. New features

i. Runaway electron impact ionization in fluid mode

by Peter Halldestam

Ionization caused by collisions with non-thermal electrons is based on a cross-section given by Garland (2020), and has previously only been available in kinetic simulations as the electron distribution function is required to compute the corresponding rate of ionization (of an ion in charge state ). However, the cross-section is proportional to the logarithm of the electron momentum , and thus only weakly depends on it at runaway electron relevant energies. To include runaway electron impact ionization in fluid simulations, one could assume a mono-energetic runaway population , for some characteristic runaway momentum , and obtain the following expression for the ionization rate

To be consistent with the characteristic runaway momentum used in the collisional energy transfer from the fluid runaway population to the thermal bulk, the same value of is used.

Runaway electron impact ionization can be crucial to capture e.g. in the runaway plataeu phase of distruptions in the presence of a substantial runaway beam, as thermal ionization becomes sub-dominant at lower temperatures and high runaway densities.

The mode is available in both fluid and kinetic simulations, and is enables via the following lines of code:

import DREAM.Settings.Equations.IonSpecies as Ions

ds.eqsys.n_i.setIonization(Ions.IONIZATION_MODE_FLUID_RE)

This feature was added in pull request #298 and is now available on master.

ii. Save warnings to output file

by Mathias Hoppe

DREAM sometimes reports warnings when suspicious or invalid values/operations are encountered during the computation. When running long simulations, or a large number of simulations, it can be difficult to notice these warnings, which may sometimes contain valuable information.

To ensure that important warnings are not lost to the user, reported warnings are now saved to the output file together with the rest of the simulation output. Functionality has also been added to the DREAM output interface to display these warnings when an output file is opened.

No special option is needed to use this functionality – it is enabled by default.

This feature was added in pull request #311 and is now available on master.

iii. Compton photon spectrum fitting routine

by Mathias Hoppe and Ida Ekmark

With the new generalized Compton photon spectrum described in the April 2024 newsletter, the need for a companion fitting routine arose. Such a routine has now been developed and is available in the tools directory. The routine is distributed in the form of a command-line program with the following options:

usage: fit_compton_spectrum.py [-h] [-n] [-p] [-s [SCALE]]
       [--plot-data] [--skip [SKIP ...]]
       [--skip-below [SKIP_BELOW]] [--skip-above [SKIP_ABOVE]]
       spectrum

Fit function to numerical Compton photon spectrum. Fits a Compton
photon spectrum to the fit used in DREAM. The spectrum should be
given as a function of photon energy, in MeV units. The data should
be stored in a CSV or TSV file, with energies in the first column
and photon fluxes in the second column. By default, the script
assumes that photon fluxes are given as 'photons per energy bin'
and adjusts the fitting accordingly.

positional arguments:
  spectrum              File containing photon spectrum data.

options:
  -h, --help            show this help message and exit
  -n, --no-normalize-per-bin
                        Do not normalize the energy spectrum to the
                        energy bin size.
  -p, --plot            Plot the fit and numerical data.
  -s [SCALE], --scale [SCALE]
                        Factor by which to multiply the input data.
  --plot-data           Plot the numerical data with indices.
  --skip [SKIP ...]     Skip elements with the specified indices.
  --skip-below [SKIP_BELOW]
                        Skip all values below this index.
  --skip-above [SKIP_ABOVE]
                        Skip all values above this index.

This fitting routine was added in pull request #304 and is now available on master.

iv. Logarithmic interpolator

by Ida Ekmark

Some prescribed input quantities may vary over several orders of magnitude, making it difficult to appropriately interpolate them. With this new feature, the Interpolator1D and Interpolator3D objects have been generalized to allow interpolating linearly in the logarithm of data, rather than in the data directly. This option is now available for Svensson transport coefficients:

import DREAM.Settings.TransportSettings as Transport

ds.eqsys.n_re.setSvenssonAdvection(
    ...,
    interp1d=Transport.INTERP1D_LOGARITHMIC,
    interp3d=Transport.INTERP3D_LOGARITHMIC
)

since the Interpolator1D and Interpolator3D classes are used also for prescribed input data, we could also implement support for logarithmic interpolation of prescribed data, should the need arise.

This feature was added in pull request #300 and is now available on master.

v. Plasmoid drift model

by Liam Antonsson and Oskar Vallhagen

The plasmoid drift model derived in (Vallhagen (2023)) has now been implemented in DREAM. It describes the spatial drifting of the plasmoid cloud which forms around a shattered pellet as the material in the pellet shards ablate. An example of how to use the new plasmoid drift model is given in examples/SPI/SPI_Shift.py, and some documentation is available in the DREAM online documentation.

This feature was added in pull request #249 and is now available on master.

vi. IMAS input interface

by Soma Olasz

An interface to IMAS has been added which allows initializing DREAM simulations from IMAS data. The interface is implemented in the script py/DREAM/IMAS/IMAS.py, and example of how to use it is given in examples/imas_prescribed/imas_test_prescribed.py.

This feature was added in pull request #253 and is now available on master.

II. Interface changes

i. New default values for radial grid parameters

by Mathias Hoppe and Lorenzo Votta

When using a radial grid with custom grid point spacing (i.e. when using the ds.radialgrid.setCustomGridPoints() method), the radial grid parameters nr, a and r0 hold no meaning. Because of this, they used to be set to 0 when the custom radial grid was set.

Since these parameters could be valuable in other parts of the user’s script, the setCustomGridPoints() method has now been updated to set them according to the structure of the custom radial grid, i.e. given a custom radial flux grid r_f they are set to

nr = r_f.size
a  = max(r_f)
r0 = min(r_f)

This change was introduced in pull request #317 and is now default on master.

ii. Separate inelastic energy losses into two OtherQuantity objects

by Peter Halldestam

Previously, the OtherQuantity object Tcold_radiation has rather misleadingly not only been comprised of the radiated power density, but the entire energy loss due to all inelastic atomic process. This fix changes Tcold_radiation to only consist of the radiated power density, and introduces a new OtherQuantity object Tcold_binding_energy for the remaining term corresponding to the rate of change in potential energy due to ionization and recombination.

This change was introduced in pull request #354 and is now used on master.

III. Bug fixes

i. Handle functions not being saved to HDF5 files

by Ida Ekmark

When using dreampyface and the time steppers with a termination function, it has not been possible to save DREAMSettings objects to HDF5 files since the interface has not been able to serialize Python functions. With this bug fix, variables which are Python functions are simply ignored when saving the DREAMSettings object to an HDF5 file, allowing most settings to be saved. This is reasonable since dreampyface is strictly required to use the termination function functionality, in which HDF5 settings files need not be produced.

This bug was fixed in pull request #332 and is now available on master.

ii. Separate time vector for solver convergence information

by Ida Ekmark

Earlier this year, functionality was added to improve the possibility to monitor the convergence of the Newton solver (see January 2024 issue). Later, it was discovered that when saving a only some of the time steps in the simulation, an inconsistency between the time vector and saved convergence information (which is always saved in every time step) would arise in the Python output interface.

With this fix, a separate time vector is added for the convergence information, which should allow the convergence information to be plotted even in simulations where only some of the evaluated time steps are saved.

This bug was fixed in pull request #346 and is now available on master.

iii. Corrected settings for heat absorption into the pellet cloud

by Oskar Vallhagen

With the SPI module, as material ablates off the injected shards it can be deposited into the plasma as neutrals, singly ionized, or in an equilibrium distribution of charge states. In the two latter cases, the corresponding energy required to ionize the ablated material should be subtracted from the background plasma. A bug was discovered where this heat sink always removes as much energy needed to ionize to the equilibrium distribution, regardless how the material is deposited. This can have noticeable effects for heavy impurity injections in relatively small tokamaks, e.g. ASDEX Upgrade, and less so for larger devices such as ITER.

This bug was fixed in pull request #249 and is now available on master.

iv. Prescribing initial runaway distribution

by Ida Ekmark

For a long time, it has been possible to run DREAM with a distribution function which is initialized from a numerical function. Recently, however, it was realized that the runaway electron density n_re is not consistently initialized with f_re in this case, giving rise to an inconsistency between f_re and n_re which can affect runaway generation. With this fix, n_re is now consistently initialized with f_re when the do.eqsys.f_re.setInitialValue() function is used.

This bug was fixed in pull request #335 and is now available on master.

IV. Recent publications