ElectricField

The ElectricField class holds settings for the parallel electric field solved for by DREAM, which is described by the unknown E_field. This quantity is defined as

\[\mathrm{E\_field} = \frac{\langle \boldsymbol{E}\cdot\boldsymbol{B} \rangle}{\sqrt{\langle B^2 \rangle}},\]

where angle brackets \(\langle\cdot\rangle\) denote a flux-surface average, \(\boldsymbol{E}\) denotes the electric field, \(\boldsymbol{B}\) the magnetic field and \(\varphi\) the toroidal angle.

The electric field can be solved for in three different ways:

  1. By prescribing the electric field profile in time \(E_\parallel = \tilde{E}(t,r)\) (TYPE_PRESCRIBED)

  2. By solving the induction equation (TYPE_SELFCONSISTENT):

  3. By requiring Ohm’s law to be satisfied, \(j_\Omega=\sigma E_\parallel\), and providing the ohmic current density profile \(j_\Omega\), along with the temperature and density required to determine the plasma conductivity \(\sigma\).

(1)\[\begin{split} \begin{cases} \frac{\partial\psi_{\rm p}}{\partial t} &= V_{\rm loop},\\ \mu_0\frac{j_\parallel}{B}\left\langle \boldsymbol{B}\cdot\nabla\varphi \right\rangle &= \frac{1}{V'}\frac{\partial}{\partial r}\left[ V'\left\langle \frac{\left|\nabla r\right|^2}{R^2} \right\rangle \frac{\partial\psi_{\rm p}}{\partial r} \right] \end{cases}\end{split}\]

where \(\psi_{\rm p}\) is the poloidal flux, \(\mu_0\) is the vacuum permeability, \(V'\) the spatial Jacobian and \(r\) the minor radius in the outer midplane. The loop voltage \(V_{\rm loop}\) is defined by

\[V_{\rm loop} = 2\pi \frac{\langle \boldsymbol{E}\cdot\boldsymbol{B} \rangle}{\langle \nabla \varphi \cdot \boldsymbol{B} \rangle}.\]

Prescribed evolution

The electric field can be prescribed in both space and time. The full syntax for prescribing an electric field evolution is

ds.eqsys.E_field.setPrescribedData(efield=E_field, radius=E_field_r, times=E_field_t)

where E_field is an array of shape (nt, nr) specifying the parallel electric field strength in space and time, E_field_r is a vector with nr elements representing the radial grid on which the electric field is prescribed, and E_field_t is a vector with nt elements representing the time grid on which the electric field is prescribed.

For convenience, it is possible to prescribe a constant and radially uniform electric field by only specifying it as a scalar:

ds.eqsys.E_field.setPrescribedData(0.3)

This will cause the electric field to be \(E_\parallel = 0.3\,\mathrm{V/m}\) at every radius, in every time step, during the simulation.

Self-consistent evolution

In this mode the electric field is evolved by solving the system (1). The evolution of the electric field is thus coupled to the poloidal flux \(\psi_{\rm p}\) and, by extension, to the total plasma current density \(j_{\rm tot}\). To evolve the electric field self-consistently, the first thing one must do is to set the type of the electric field to TYPE_SELFCONSISTENT via a call to setType():

import DREAM.Settings.Equations.ElectricField as ElectricField

...

ds.eqsys.E_field.setType(ElectricField.TYPE_SELFCONSISTENT)

By default, the initial electric field profile will be identically zero. This is automatically overridden if the settings are loaded from an old output file (see restart), but the initial profile can also be set explicitly via a call to setInitialProfile():

ds.eqsys.E_field.setInitialProfile(efield=E_field, radius=E_field_r)

where E_field is a vector of size nr giving the initial electric field profile, and E_field_r is a vector representing the radial grid on which the initial electrc field profile is defined.

Alternatively, the electric field can be initialized such that it gives the desired ohmic current density profile (achieved by inverting Ohm’s law):

ds.eqsys.j_ohm.setInitialProfile(j=j_ohm, radius=j_ohm_r, Ip0=Ip0)

where j_ohm is the desired current density profile and j_ohm_r its grid. If the optional parameter Ip0 is provided, the given current density profile is rescaled such that the prescribed ohmic current density profile yields exactly a total plasma current Ip0 when integrated on the internal DREAM grid (which is not necessarily the same as the grid on which j_ohm is given).

Boundary condition

The second equation in (1) requires a boundary condition at \(r=r_{\rm wall}\) to be given. In DREAM, three different boundary conditions can be applied at the tokamak wall.

The first boundary condition, BC_TYPE_PRESCRIBED, prescribes the time evolution of the loop voltage \(V_{\rm loop,wall}\) on the tokamak wall (normalized to the tokamak major radius \(R_0\)). This is particularly useful for simulating experimental scenarios where the parameter \(V_{\rm loop,wall}\) has been measured.

import DREAM.Settings.Equations.ElectricField as ElectricField

ds = DREAMSettings()
...
# Tokamak major radius
R0        = 1.65
# Define evolution of V_loop/R0
Vmax      = 1
V_loop_t  = np.linspace(0, 1, 100)
V_loop_R0 = (Vmax/R0)*(1 - (1-t)**2)

ds.eqsys.E_field.setBoundaryCondition(bctype=ElectricField.BC_TYPE_PRESCRIBED,
                                      V_loop_wall_R0=V_loop_R0, times=V_loop_t, R0=R0)

The second boundary condition, BC_TYPE_SELFCONSISTENT, instead lets the user specify the (inverse) tokamak wall time, \(1/\tau_{\rm wall}\), which directly corresponds to the wall resistivity. The perfectly conducting limit \(\tau_{\rm wall} = \infty\) is supported, and is obtained by setting inverse_wall_time = 0. In case a cylindrical geometry is used, the major radius R0 can be explicitly set, independently of the geometry used, since the external inductance otherwise diverges for infinite major radius.

import DREAM.Settings.Equations.ElectricField as ElectricField

ds = DREAMSettings()
...
# Tokamak major radius
R0       = 1.65
# Wall time
tau_wall = .01   # (s)

ds.eqsys.E_field.setBoundaryCondition(bctype=ElectricField.BC_TYPE_SELFCONSISTENT,
                                      inverse_wall_time=1/tau_wall, R0=R0)

The third boundary condition, BC_TYPE_TRANSFORMER, can be seen as a combination of the two other boundary conditions, with a resistive wall and a prescribed loop voltage (although at the transformer, which passes through the axis of symmetry at \(R=0\)).

import DREAM.Settings.Equations.ElectricField as ElectricField

ds = DREAMSettings()
...
# Tokamak major radius
R0        = 1.65
# Define evolution of V_loop/R0
Vmax      = 1
V_loop_t  = np.linspace(0, 1, 100)
V_loop_R0 = (Vmax/R0)*(1 - (1-t)**2)
# Wall time
tau_wal   = .01  # (s)

ds.eqsys.E_field.setBoundaryCondition(bctype=ElectricField.BC_TYPE_PRESCRIBED,
                                      inverse_wall_time=1/tau_wall, R0=R0,
                                      V_loop_wall_R0=V_loop_R0, times=V_loop_t)

Note

With all boundary conditions, the tokamak wall location wall_radius must be specified. This parameter denotes the minor radial coordinate of the tokamak wall (i.e. the distance of the wall from the center of the plasma). This is done via the call ds.radialgrid.setWallRadius(b), where b is the desired wall radius.

Initial value

The initial value of the electric field can be set either using the setInitialProfile() method, as shown above, or by specifying the desired initial current density profile. The electric field will then be initialized to whatever profile gives the necessary ohmic current density profile, so that the prescribed total current density profile is obtained.

More details about how to initialize the electric field via a current density profile can be found on the page for the ohmic current density.

Prescribed ohmic current

If the desired ohmic current density profile \(j_\Omega\) is known, the corresponding electric field can be found by inverting Ohm’s law

\[\frac{j_\Omega}{B} = \sigma \frac{\left\langle\boldsymbol{E}\cdot\boldsymbol{B}\right\rangle}{\left\langle B^2 \right\rangle}\]

where \(\sigma\) denotes the plasma conductivity, which depends on primarily the electron density and temperature. To evaluate the electric field from this law, the following configuration can be made:

import DREAM.Settings.Equations.ElectricField as ElectricField

ds.eqsys.E_field.setType(ElectricField.TYPE_PRESCRIBED_OHMIC_CURRENT)
ds.eqsys.j_ohm.setCurrentProfile(j=j_ohm, radius=r, times=t, Ip0=Ip0)

where j_ohm is the desired current density profile, r is the radial grid on which the profile is specified, and t is its time grid. If no time evolving current density is needed, j_ohm can be given as a 1D array. If the optional scalar parameter Ip0 is given, the current density profile is rescaled such that, when integrated over the plasma cross-section, it yields exactly the total plasma current Ip0.

Class documentation