Comparison with DREAM

This page compares Runes2P with DREAM, the code whose design it follows (M. Hoppe, O. Embréus and T. Fülöp, Comput. Phys. Commun. 268, 108098 (2021), doi:10.1016/j.cpc.2021.108098). The comparison is with DREAM release v26.5 and its branch boltzmann-eqterm at commit 93d27e1, the builds of the Reference data. The file and line citations of DREAM's source refer to commit 93d27e1 unless they name another version.

Features of DREAM

✅ implemented🚧 partial➖ not implementedfeatures
761747140

The tables follow the groups of DREAM's settings (py/DREAM/Settings). The column "DREAM" names the setting, class or unknown. The column "Runes2P" gives the state, the names that implement the feature and, for a partial feature, the part that is in the code. A cell that ends with "(note)" has a note under its table, which gives the detail.

StateMeaning
✅ implementedDREAM's feature is in the code, possibly next to other options
🚧 partiala part of the feature is in the code, and the cell names that part
➖ not implementedthe code has no counterpart

Runes2P is cylindrical: a straight magnetic field, constant on each flux surface, so no trapping and no flux-surface averages (cylindrical_grid). Every toroidal feature of DREAM is therefore not implemented.

Run modes

Runes2P has no switch of the run mode. A run is an EquationSystem of the terms the caller chooses, so a mode is a choice of unknowns and terms.

ModeDREAMRunes2P
fully kinetichot-tail grid with COLLFREQ_MODE_FULL, the bulk inside f_hot✅ mode = :full of CollisionSettings, total_energy_equation
superthermalhot-tail grid with COLLFREQ_MODE_SUPERTHERMAL, a fluid cold population✅ mode = :superthermal of CollisionSettings, ConductivityTerm, FrictionEnergyTransferTerm (note)
isotropicone pitch cell, the pitch-averaged equation➖ a grid of one pitch cell is refused by fokker_planck_operator
fluidno kinetic grid🚧 the field, the cold electrons and the ions, but no Dreicer or avalanche term that feeds $n_\mathrm{re}$

Grids

FeatureDREAMRunes2P
cylindrical radial grid, custom facesRadialGrid.TYPE_CYLINDRICAL, setCustomGridPoints✅ RadialGrid, uniform_r_faces
minor radiussetMinorRadius✅ the last face of a RadialGrid
major radiussetMajorRadius➖ (note)
inner radiussetInnerRadius🚧 a RadialGrid may start above the axis, with no comparison with DREAM's inner boundary (note)
magnetic field on the axissetB0✅ the magnetic field of a PlasmaState, one value per radius
wall radiussetWallRadius✅ wall_radius of induction_equations
analytic toroidal equilibrium, shapingTYPE_ANALYTIC_TOROIDAL, setShaping, setShapeParameter➖
numerical equilibriumTYPE_NUMERICAL, FILE_FORMAT_LUKE, setNumerical➖
poloidal-angle resolution of the averagessetNtheta, setNthetaOut➖
momentum grid in $(p, \xi)$MomentumGrid.TYPE_PXI✅ MomentumGrid
momentum grid in $(p_\parallel, p_\perp)$TYPE_PPARPPERP➖
uniform momentum gridPGrid.TYPE_UNIFORM✅ uniform_p_faces
biuniform momentum gridPGrid.TYPE_BIUNIFORM✅ biuniform_p_faces
custom momentum faces, $p_\mathrm{min}$PGrid.TYPE_CUSTOM, setPmin✅ MomentumGrid from its faces
uniform pitch gridXiGrid.TYPE_UNIFORM✅ uniform_xi_faces
biuniform in the pitch angleXiGrid.TYPE_BIUNIFORM_THETA✅ biuniform_theta_xi_faces
biuniform in $\xi$, uniform in the pitch angleXiGrid.TYPE_BIUNIFORM, TYPE_UNIFORM_THETA✅ as custom faces of a MomentumGrid
custom pitch facesXiGrid.TYPE_CUSTOM✅ MomentumGrid from its faces
trapped-passing boundary layerXiGrid.TYPE_TRAPPED, setTrappedPassingBoundaryLayerGrid➖
hot-tail and runaway grids, the flux between themhottailgrid, runawaygrid✅ runaway_grid, MomentumInterfaceTerm

Collisions

FeatureDREAMRunes2P
collision frequency modeCOLLFREQ_MODE_SUPERTHERMAL, FULL, ULTRA_RELATIVISTIC✅ mode of CollisionSettings
screeningCOLLFREQ_TYPE_COMPLETELY_SCREENED, NON_SCREENED, PARTIALLY_SCREENED✅ screening
Walkowiak screeningCOLLFREQ_TYPE_WALKOWIAK➖
Coulomb logarithmLNLAMBDA_CONSTANT, ENERGY_DEPENDENT, THERMAL✅ coulomb_logarithm (:relativistic is CONSTANT)
energy diffusion with screeningSCREENED_DIFFUSION_MODE_ZERO, MAXWELLIAN✅ screened_diffusion
bremsstrahlung stopping powerBREMSSTRAHLUNG_MODE_NEGLECT, STOPPING_POWER✅ bremsstrahlung, bremsstrahlung_cross_section
critical momentum $p_\star$ without and with trappingPSTAR_MODE_COLLISIONAL, COLLISIONLESS✅ avalanche_critical_momentum, the two modes coincide in a cylinder
linearized test-particle operatorSlowingDownTerm, PitchScatterTerm, EnergyDiffusionTerm✅ fokker_planck_operator

Electric field and current

FeatureDREAMRunes2P
prescribed fieldElectricField.TYPE_PRESCRIBED✅ the field of a PlasmaState
self-consistent field, poloidal flux, plasma currentTYPE_SELFCONSISTENT, psi_p, I_p✅ induction_equations, induction_unknowns
initial current profileOhmicCurrent.setInitialProfile✅ initial_poloidal_flux
field from a prescribed ohmic currentTYPE_PRESCRIBED_OHMIC_CURRENT➖
loop voltage prescribed at the wallBC_TYPE_PRESCRIBED✅ loop_voltage_at_wall
resistive wall with a wall timeBC_TYPE_SELFCONSISTENT, inverse_wall_time➖
transformer, initial wall currentBC_TYPE_TRANSFORMER, setInitialWallCurrent➖
hyperresistivityHYPERRESISTIVITY_MODE_PRESCRIBED, ADAPTIVE, ADAPTIVE_LOCAL➖
Braams–Karney conductivityCONDUCTIVITY_MODE_BRAAMS✅ braams_karney_conductivity, ConductivityModel
Sauter conductivityCONDUCTIVITY_MODE_SAUTER_COLLISIONLESS, SAUTER_COLLISIONAL✅ in a cylinder, where it is the Braams–Karney conductivity
corrected conductivity of the fully kinetic modeCORRECTED_CONDUCTIVITY_ENABLED✅ kinetic = :dream_fit of ConductivityModel
current profile of a torusPROFILE_TYPE_J_PARALLEL, J_DOT_GRADPHI, JTOR_OVER_R, CORSICA➖
bootstrap currentBOOTSTRAP_MODE_REDL➖
current of a distributionunknowns j_hot, j_re✅ CurrentMomentTerm, current_density

Temperature and energy

FeatureDREAMRunes2P
prescribed cold temperatureColdElectronTemperature.TYPE_PRESCRIBED✅ PrescribedPlasma
self-consistent cold temperatureTYPE_SELFCONSISTENT✅ thermal_energy_equation, PlasmaFromUnknowns
ohmic heatingTcold_ohmic✅ ohmic_heating_term
collisional heating by $f_\mathrm{hot}$ and $f_\mathrm{re}$Tcold_fhot_coll, Tcold_fre_coll✅ DREAM's moment, FrictionEnergyTransferTerm (note)
collisional heating by fluid runawaysCollisionalEnergyTransferREFluidTerm✅ RunawayFluidEnergyTransferTerm
line radiation, ionization energy, Gould's bremsstrahlungRECOMBINATION_RADIATION_NEGLECTED✅ radiation = :dream of RadiatedPowerTerm, with bremsstrahlung_corrections = :dream
recombination radiationRECOMBINATION_RADIATION_INCLUDED✅ radiation = :recombination of RadiatedPowerTerm, with the energy of the recombined state at every radius
halo region lossesHALO_REGION_LOSSES_INCLUDED➖
neutral beam heatingsetNBI, NBI_PROFILE_*➖
ion temperatures, energy exchangeIONS_T_I_INCLUDE✅ IonEnergyExchangeTerm
  • Collisional heating by $f_\mathrm{hot}$ and $f_\mathrm{re}$. For the hot tail, Runes2P takes DREAM's moment. For the runaway grid, Runes2P's default is free_electron_energy_transfer_term, the energy change of the electron-electron operator (KineticEnergyLossTerm). DREAM's moment is the option for the runaway grid (Defaults that differ). The moment is compared with DREAM's saved heating of both grids (test_collisional_heating_dream.jl). It is also compared in a run of the runaway grid with the cold temperature self-consistent against DREAM's run (test_runaway_heating_dream.jl).

Ions and ionization

FeatureDREAMRunes2P
prescribed charge statesIONS_PRESCRIBED, _NEUTRAL, _FULLY_IONIZED✅ the ions of a PlasmaState
dynamic charge statesIONS_DYNAMIC✅ IonRateTerm, ion_densities_unknown
dynamic, neutral or fully ionized at the startIONS_DYNAMIC_NEUTRAL, _FULLY_IONIZED✅ deposit_neutrals!, set_ion_densities!
start in coronal equilibriuminit_equil✅ fill_coronal_equilibrium!, coronal_equilibrium (note)
charge states held in coronal equilibriumIONS_EQUILIBRIUM➖
ADAS rate coefficientsAtomics, ADF11✅ read_adas, adas_coefficient
ADAS interpolationADAS_INTERP_BICUBIC, ADAS_INTERP_BILINEAR🚧 the bicubic interpolation, DREAM's default
fluid ionizationIONIZATION_MODE_FLUID✅ IonRateTerm
kinetic ionization by $f$IONIZATION_MODE_KINETIC✅ KineticIonizationTerm
kinetic ionization with an approximate JacobianIONIZATION_MODE_KINETIC_APPROX_JAC➖ the Jacobian is exact
ionization by fluid runawaysIONIZATION_MODE_FLUID_RE, reioniz_scale➖
DREAM's kinetic cross sectionsIonKineticIonizationTerm, Burgess–Chidichimo fits✅ form = :dream of ionization_cross_section
opacity to line radiationION_OPACITY_MODE_GROUND_STATE_OPAQUE➖
prescribed ion source, volumetric sourceION_SOURCE_PRESCRIBED, PRESCRIBED_VOLUMETRIC➖
shattered pellet injectionSPI➖
isotopesisotope of IonSpecies🚧 H, D and T as elements of an IonSpecies, ion_mass
  • Start in coronal equilibrium. fill_coronal_equilibrium! is DREAM's fixed point of the free-electron density over the species started in equilibrium. It takes the charge states of coronal_equilibrium. It is compared with DREAM's examples/ionequil (test_initial_state_dream.jl).

Runaway generation

FeatureDREAMRunes2P
fluid runaway densityunknown n_re🚧 a radial unknown, fed by ExternalAvalancheTerm, MomentumBoundaryFluxTerm or InterfaceParticleFluxTerm (note)
Connor–Hastie Dreicer rateDREICER_RATE_CONNOR_HASTIE, _NOCORR🚧 the rate as a function (connor_hastie_rate), no source term
Dreicer rate of the neural networkDREICER_RATE_NEURAL_NETWORK➖
extrapolation of the Dreicer ratesetExtrapolateDreicer➖
fluid avalancheAVALANCHE_MODE_FLUID🚧 the rates as functions (fluid_avalanche_growth_rate, avalanche_growth_rate), no term in a run without a kinetic grid (note)
fluid avalanche with DREAM's alternative $p_\star$AVALANCHE_MODE_FLUID_HESSLOW, pStarFunctionAlt➖
kinetic Rosenbluth–Putvinski source, external avalancheAVALANCHE_MODE_KINETIC, pCutAvalanche✅ RosenbluthPutvinskiSourceTerm, ExternalAvalancheTerm
Boltzmann knock-on operatorAVALANCHE_MODE_BOLTZMANN_KNOCK_ON (boltzmann-eqterm)✅ KnockOnOperator, KnockOnTerm
effective critical fieldCOLLQTY_ECEFF_MODE_FULL, SIMPLE, CYLINDRICAL, EC_TOT🚧 mode FULL in a cylinder, effective_critical_field
Compton sourceCOMPTON_MODE_FLUID, KINETIC, COMPTON_RATE_ITER_DMS➖
tritium sourceTRITIUM_MODE_FLUID, KINETIC➖
hot-tail rateHOTTAIL_MODE_ANALYTIC, ANALYTIC_ALT_PC➖
losses through the last closed flux surfaceLCFS_LOSS_MODE_FLUID, KINETIC, setLCFSLossTime, setPsiEdgeFromOutput🚧 a prescribed loss rate of $f$ (LossRateTerm), not the edge flux from an output file (setPsiEdgeFromOutput)
negative runaway densitysetNegativeRunaways➖

Transport

FeatureDREAMRunes2P
Rechester–Rosenbluth transport of $f$TRANSPORT_RECHESTER_ROSENBLUTH✅ add_rechester_rosenbluth_diffusion!, RechesterRosenbluthUpdate
prescribed transport coefficients of $f$TRANSPORT_PRESCRIBED🚧 advection_r and diffusion_r_r of AdvectionDiffusion, constant in time (note)
Svensson transportTRANSPORT_SVENSSON➖
MHD-like transportTRANSPORT_MHD_LIKE, MHD_LIKE_LOCAL➖
frozen-current transportTRANSPORT_FROZEN_CURRENT➖
interpolation of the coefficients in timeINTERP1D_*, INTERP3D_*🚧 the coefficients at the start of each step, from a PiecewiseConstant or a function of time
boundary of the transport of $f$BC_CONSERVATIVE, BC_F_0✅ r_boundary = :zero_flux, :absorbing_dream
boundary with a constant gradientBC_DF_CONST🚧 for the heat transport alone, edge = :constant_gradient_dream of HeatTransportTerm
Kiramov boundaryBC_KIRAMOV➖
heat transport of the cold electronsColdElectronTemperature.transport✅ HeatTransportTerm
transport of the fluid runawaysRunawayElectrons.transport➖
diffusion of the charge statesION_CHARGED_DIFFUSION_MODE_PRESCRIBED, ION_NEUTRAL_DIFFUSION_MODE_PRESCRIBED✅ IonDiffusionTerm, states = :charged or :all
advection of the charge statesION_CHARGED_ADVECTION_MODE_PRESCRIBED, ION_NEUTRAL_ADVECTION_MODE_PRESCRIBED➖
  • Prescribed transport coefficients of $f$. The caller sets them on the faces of the grid. There are no coefficients given in time, radius and momentum and interpolated to the grid.

Kinetic options

FeatureDREAMRunes2P
interpolation of the advectionAD_INTERP_CENTRED, UPWIND, UPWIND_2ND_ORDER, QUICK, SMART, MUSCL, OSPRE, TCDF✅ scheme of AdvectionDiffusion
downwind interpolationAD_INTERP_DOWNWIND➖
a scheme per directionad_int_r, ad_int_p1, ad_int_p2✅ r_scheme, p_scheme, xi_scheme
Jacobian of a flux limiterAD_INTERP_JACOBIAN_LINEAR, FULL, UPWIND✅ jacobian of FokkerPlanckTerm
boundary at $p_\mathrm{max}$BC_F_0, BC_PHI_CONST, BC_DPHI_CONST✅ p_upper_boundary of AdvectionDiffusion
boundary at $p = 0$AD_BC_MIRRORED with the internal boundary condition of $f_\mathrm{hot}$, AD_BC_DIRICHLET on $f_\mathrm{re}$✅ p_zero_boundary of AdvectionDiffusion, :outflow and :zero_flux
threshold of the hot regionHOT_REGION_P_MODE_THERMAL, THERMAL_SMOOTH, MC✅ ThermalMomentum, MomentumRegion
particle sourcePARTICLE_SOURCE_ZERO, IMPLICIT, EXPLICIT🚧 zero and implicit, ParticleSourceTerm with a Constraint (note)
shape of the particle sourcePARTICLE_SOURCE_SHAPE_MAXWELLIAN, DELTA✅ shape of ParticleSourceTerm
synchrotron lossSYNCHROTRON_MODE_INCLUDE✅ add_synchrotron!
ion columns in the Jacobian of $f$enableIonJacobian✅ lagged of FokkerPlanckTerm
magnetic rippleRIPPLE_MODE_BOX, GAUSSIAN➖
time-varying magnetic fieldTIME_VARYING_B_MODE_INCLUDE➖
analytic or prescribed distributionDISTRIBUTION_MODE_ANALYTICAL, PRESCRIBED➖
non-relativistic hot-tail equationF_HOT_DIST_MODE_NONREL➖
initial distributionsetInitialProfiles, setInitialValue🚧 a state array of the caller or DREAM's Maxwellian (fill_maxwellian!), no interpolation from another grid (note)
initial runaway distributionsINIT_FORWARD, XI_NEGATIVE, XI_POSITIVE, ISOTROPIC, AVALANCHE, PRESCRIBED🚧 four of DREAM's shapes (fill_runaway_distribution!) or a state array of the caller, not the analytic avalanche shape (note)
  • Particle source. The explicit source has no packaged form. The disruption case builds it from an unknown of the source with its own row (test/example_disruption.jl).
  • Initial distribution. A run takes any state array of the caller on the grid of the run. DREAM's Maxwellian is built from profiles of $n$ and $T$.
  • Initial runaway distributions. fill_runaway_distribution! gives the four shapes in the first momentum cell. They are compared with DREAM's (test_initial_state_dream.jl).

Solver and time stepping

FeatureDREAMRunes2P
linearly implicit solverSolver.LINEAR_IMPLICIT➖
Newton solverSolver.NONLINEAR, setMaxIterations✅ NewtonSolver
tolerances per unknownToleranceSettings✅ Tolerance
residual checksetCheckResidual✅ as a convergence criterion, with two exceptions (note)
damped Newton stepMaximalPhysicalStepLength✅ LowerLimit, max_reduction
direct linear solversLINEAR_SOLVER_LU, MUMPS, MKL, SUPERLU🚧 UMFPACK (SparseLU) and MKL PARDISO (MKLPardiso with using Pardiso)
GMRESLINEAR_SOLVER_GMRES✅ GMRES
backup solversetBackupSolver➖
scaling of the unknownsPreconditioner✅ unknown_scales
constant time stepTimeStepper.TYPE_CONSTANT, setNt, setDt✅ FixedSteps
saved stepssetNumberOfSaveSteps✅ save_times of RunOptions
adaptive time step by step doublingTYPE_ADAPTIVE, checkevery✅ StepDoubling
smallest time between saved stepssetMinSaveTimestep➖ the saved times are prescribed
ionization time stepperTYPE_IONIZATION➖
termination functionsetTerminationFunction➖ a segment stops only on a wall-time budget or a stop file (StopCondition)
restart from an output filefromOutput✅ read_state, read_checkpoint
solver statisticssetSaveStatistics, setSaveConvergenceInfo✅ SolverStatistics
verbose outputsetVerbose✅ ProgressLog
  • Residual check. The residual is a convergence criterion except for the linear steps that linear_acceptance of NewtonSolver accepts on the update. The steps at the round-off floor of the residual are the other exception.

Output

FeatureDREAMRunes2P
HDF5 output of the unknownsOutput.setFilename✅ write_output, read_output
settings in the outputsetSaveSettings✅ run_settings
timingsetTiming✅ the wall times of SolverStatistics
other quantitiesOtherQuantities🚧 computed from a saved state, such as radiated_power and interface_flux
DREAM's settings filesDREAMSettings➖
Python interface and plottingpy/DREAM➖ the Julia API

The disruption case

The page The disruption case compares the two codes in whole runs of DREAM's disruption case of examples/Disruptions/generate.py. It covers the reduced size of the tests and the whole quenches of scenarios 1 and 4 at full size.

What Runes2P has that DREAM does not

Departures from DREAM

The sections below list the defaults that differ from DREAM's and the behaviour without an option for DREAM's. The last three give the details of the extrapolated flux at the highest momentum, the approximate Jacobians and the line search.

Defaults that differ

Each row names the default of Runes2P and the option that gives DREAM's behaviour. The reasons of the defaults that are choices of this package are on Choices of this package.

TopicRunes2P defaultDREAMOption for DREAM's behaviour
interpolation of $f$ in $p$ and $\xi$exponential fitting in fokker_planck_operatorcentred interpolationscheme = :central
boundary at $p_\mathrm{max}$p_upper_boundary = :f_zero in fokker_planck_operatorBC_PHI_CONSTp_upper_boundary = :constant_flux
synchrotron lossonoffsynchrotron = false
bremsstrahlung stopping poweronoffbremsstrahlung = :neglect
bremsstrahlung in the energy diffusiona pure dragthe whole $ν_s$ diffusedbremsstrahlung_diffusion = :dream
constant of the stopping power$4/3$ of the formula 4BN of Koch and Motz$1$bremsstrahlung_constant = :dream
ion sizes of partial screeningTable 1 of Hesslow et al. (note)a lookup that shifts the sizes from Ar¹⁷⁺ onion_size_table = :dream
momenta of partial screeningabove the excitation energy of each charge stateall momentascreening_window = :dream
knock-on pitchintegrated over the cell pair, primary averaged over its cellboth at the cell centresdream_compatible = true of KnockOnOperator
current of a distribution$f$ linear across a pitch cell$f$ constant over a pitch cellpitch_rule = :cell_center
flux between the two gridsby the overlap cells of the pitch gridsinterpolated in pitchpitch_mapping = :dream
flux through $p = 0$ on a runaway grid from $p = 0$p_zero_boundary = :outflow of fokker_planck_operator (note)nonep_zero_boundary = :zero_flux, set by the caller
Rechester–Rosenbluth coefficient $D = \pi q R_0 v_\parallel (\delta B/B)^2$safety factor and major radius as inputs$q = 1$ and $R_0 = 1$ m in a cylindersafety_factor = 1, major_radius = 1
heating of the cold electrons by a runaway gridfree_electron_energy_transfer_term (note)the moment $m_e c\, v p\, \nu_s f$ at the cell centresFrictionEnergyTransferTerm in place of the default
radiated power of the ionsline and recombination radiation, the binding energy of ionization and recombinationline radiation, the ionization loss and Gould's bremsstrahlungradiation = :dream of RadiatedPowerTerm, with bremsstrahlung_corrections = :dream for DREAM's corrections
relativistic corrections of Gould's bremsstrahlung, the coefficients of $T/m_ec^2$$11/24$ and $5(44 - 3\pi^2)/(24\sqrt{2})$ (GOULD_ION_CORRECTION, GOULD_ELECTRON_CORRECTION) (note)$19/24$ and $5(44 - 3\pi^2)/(8\sqrt{2})$bremsstrahlung_corrections = :dream
cross sections of the kinetic ionizationCHIANTI's for H, D, T, Ne and Ar, DREAM's for the other elementsDREAM's fitsform = :dream
ionization at the hot thresholdthe fluid coefficient below the threshold, kinetic_ionization of IonRateTermthe whole ADAS rate next to the kinetic termIonRateTerm without kinetic_ionization
Coulomb logarithm among the ionsthe ion-ion logarithm of the NRL Plasma Formulary, with the temperature of each speciesone logarithm with $T_e$ion_coulomb_logarithm = :dream of IonEnergyExchangeTerm
ion massesnuclear masses of H, D and T, standard atomic weights otherwisestandard atomic weights up to $Z = 40$, $2.3\,Z$ u beyondmass_table = :dream
charge states in the collisions of $f$those of the start of the step, lagged = :ionsthose of the iterate with their Jacobian columnslagged = ()
Newton matrix of a linear systemassembled and factorized once per stepevery iterationreuse_linear_matrix = false of NewtonSolver
negative entries of a kinetic unknown at convergenceone more Newton iteration for the schemes of POLISHED_SCHEMESnonepolish_negatives = false of NewtonSolver
iterative refinement of MKL PARDISOnone, refinement_steps = 0 of MKLPardisoup to 10 steps per solve (fvm/Solvers/MIMKL.cpp)MKLPardiso(refinement_steps = 10)
floor of a temperature unknownDEFAULT_TEMPERATURE_FLOOR (fluid_temperature_floors)damped towards zeroa lower floor of PlasmaFromUnknowns or a LowerLimit

The sources of the values of Runes2P in the table are these.

RowSource
constant of the stopping powerthe formula 4BN of H. W. Koch and J. W. Motz, Rev. Mod. Phys. 31, 920 (1959), doi:10.1103/RevModPhys.31.920
ion sizes of partial screeningTable 1 of L. Hesslow et al., J. Plasma Phys. 84, 905840605 (2018), doi:10.1017/S0022377818001113
relativistic corrections of Gould's bremsstrahlung, electron-electronthe ratio of eqs. (22) and (18) of R. J. Gould, Astrophys. J. 238, 1026 (1980), doi:10.1086/158068
relativistic corrections of Gould's bremsstrahlung, electron-ionthe erratum of the paper of 1980, Astrophys. J. 243, 677 (1981), doi:10.1086/158634
Coulomb logarithm among the ionsthe NRL Plasma Formulary, A. S. Richardson, NRL/PU/6770–19-652, Naval Research Laboratory, 2019

Ion sizes of partial screening. DREAM's lookup has a list of nuclear charges with 17 argon entries for 18 charge states. This shifts the sizes from Ar¹⁷⁺ on.

Flux through $p = 0$ on a runaway grid from $p = 0$. Runes2P takes the operator's default, p_zero_boundary = :outflow of fokker_planck_operator, as DREAM's hot-tail grid. The friction carries electrons out by $\lim_{p \to 0} p^3 ν_s$ (p3_slowing_down_frequency_at_zero). With it the runaway grid of the case heating of reference/dream/cases/initial_state.py loses 1.55e-4 of the density of $f_\mathrm{re}$ in the first step, where DREAM's stays constant to round-off.

The caller sets the option p_zero_boundary = :zero_flux for a runaway grid from $p = 0$, as both compat values of runaway_heating_example do (test_runaway_heating_dream.jl). In DREAM's source:

  • $f_\mathrm{re}$ has no internal boundary condition (src/Settings/Equations/f_re.cpp:87).
  • $f_\mathrm{re}$ keeps the Dirichlet lower boundary of its advection in $p$ (fvm/Equation/AdvectionTerm.cpp:36).
  • Unlike $f_\mathrm{re}$, $f_\mathrm{hot}$ has an internal boundary condition (src/Settings/Equations/f_hot.cpp:96). With it, the lower boundary of its advection in $p$ is mirrored (AD_BC_MIRRORED) in place of Dirichlet (src/Settings/Equations/distribution.cpp:234-237).

Heating of the cold electrons by a runaway grid. Runes2P's default is the energy change of the electron-electron operator of the grid, with a linear scheme of the operator. DREAM's moment, FrictionEnergyTransferTerm, also counts the energy that the friction carries out of the grid through $p = 0$ where that flux is applied (p_zero_boundary = :outflow). The test case runaway_heating_example (test/example_cases.jl) takes the option at compat = dream. It is compared with DREAM's run in test_runaway_heating_dream.jl.

Relativistic corrections of Gould's bremsstrahlung. The coefficients of $T/m_ec^2$ are these.

CoefficientRunes2PDREAM
electron-ion$11/24$ (GOULD_ION_CORRECTION)$19/24$
electron-electron$5(44 - 3\pi^2)/(24\sqrt{2})$ (GOULD_ELECTRON_CORRECTION)$5(44 - 3\pi^2)/(8\sqrt{2})$

Behaviour without an option for DREAM's

In these points Runes2P differs from DREAM, and no option gives DREAM's behaviour.

  • Newton's method converges on both the update and the scaled residual, except for the linear steps that linear_acceptance accepts on the update (NewtonSolver). A stiff step at the round-off floor of its residual is accepted on the update too, within the round-off bound of its rows or where the residual stopped decreasing. DREAM converges on the update. With setCheckResidual on, its default, DREAM warns when the residual is not converged (src/Solver/SolverNonLinear.cpp:305-310, py/DREAM/Settings/Solver.py:28).
  • A failed Newton step is reported as a status of NewtonResult. The time stepper retries it with a shorter step.
  • Each charge state has a lower limit relative to the density of its species (ion_densities_unknown). In DREAM the charge states have no limit of their own (src/Solver/SolverNonLinear.cpp:441-508). DREAM's MaximalPhysicalStepLength damps these quantities (src/Solver/SolverNonLinear.cpp:441-508):
    • $T_\mathrm{cold}$, $n_\mathrm{tot}$ and $n_\mathrm{cold}$.
    • $W_\mathrm{cold}$, $W_i$ and the species densities $N_i$, where they are unknowns.
    • $\sum Z_0^2 n$ per radius.
  • A lower limit shortens only steps towards the limit, never growth (LowerLimit).
  • A doubled step can fail on an unknown at zero with no absolute tolerance while every other unknown has no error. Such a step is retried with half its length (StepDoubling). DREAM's next step is unbounded there (src/TimeStepper/TimeStepperAdaptive.cpp:458-482).
  • The ion rows take the sign convention of every other row, so IonDiffusionTerm takes a positive coefficient (DREAM: src/Equations/Fluid/IonTransientTerm.cpp:78).
  • coronal_equilibrium multiplies the ratios of the rates in log space, where DREAM multiplies them directly (src/Settings/IonEquilibrium.cpp:100-137).
  • The derivatives of the ADAS coefficients are exact, without DREAM's floors in the Jacobian (adas_coefficient, IonRateTerm).
  • The Jacobian of ExternalAvalancheTerm holds every column of the rate, where DREAM's holds those of the field and of $n_\mathrm{tot}$.
  • The temperature column of ParticleSourceTerm holds the derivative of the normalization of its shape, which DREAM's column omits (src/Equations/Kinetic/ParticleSourceTerm.cpp).
  • The recombination gain of radiation = :recombination takes the ionization energy of the recombined state at every radius. DREAM's takes that of the recombining state from its second radial cell on (src/Equations/Fluid/RadiatedPowerTerm.cpp). test/test_adas_cache.jl checks the radiated power in coronal equilibrium, which detects this mismatch.
  • RechesterRosenbluthUpdate takes the level of the perturbation at the start of each step. DREAM interpolates its table linearly in time and takes the value at the end of the step.
  • StepDoubling reads the tolerances by unknown, for the acceptance and for the next step. DREAM's step update reads them by position in its list of non-trivial unknowns (GetErrorScale, src/ConvergenceChecker.cpp).
  • check_every of StepDoubling takes the steps between two checked steps at the current length, the documented intent of DREAM's checkevery. DREAM's code takes them from a stale start time, with other lengths and one step more (src/TimeStepper/TimeStepperAdaptive.cpp).
  • The :smooth envelope of a MomentumRegion whose limit lies at or above the last cell centre takes the width of the last cell. DREAM takes the limit minus the last centre (FindThresholdStep, fvm/Equation/MomentQuantity.cpp). That gives zero width and a NaN at that centre, and a jump of the envelope as the limit crosses it.

Extrapolated flux at the highest momentum

DREAM's BC_DPHI_CONST is defined by a constant $\mathrm{d}Φ/\mathrm{d}p$ at $p_\mathrm{max}$, with $Φ = \mathcal{V}' Γ^p$, the phase-space Jacobian $\mathcal{V}'$ times the momentum flux $Γ^p$. Its code (fvm/Equation/BoundaryConditions/PXiExternalLoss.cpp) shares the $\mathcal{V}'$ of the last interior face between the two terms of the extrapolation. It multiplies both terms by the advection coefficient $A^p$ of that face. The interpolation and the diffusion of the second term are those of the face before it. p_upper_boundary = :extrapolated_flux of AdvectionDiffusion ports this code literally, and the comparisons with DREAM use it. :extrapolated_flux_consistent extrapolates with the $\mathcal{V}'$ and the $Γ^p$ of each face, as the definition states. test/test_pmax_boundary.jl checks both. test/test_pmax_boundary_dream.jl compares the literal port with DREAM.

Approximate Jacobians

The residual of a FokkerPlanckTerm is always that of its scheme. jacobian selects the stored block alone:

  • :exact differentiates the limiter.
  • :frozen_limiter is DREAM's AD_INTERP_JACOBIAN_LINEAR.
  • A linear scheme name gives that scheme's Jacobian (with_scheme).

jacobian = :upwind with a central residual is DREAM's AD_INTERP_JACOBIAN_UPWIND, which makes some of DREAM's runs at high momentum resolution converge (DREAM issue #126). A term with an approximate block declares jacobian_kind(term) === :approximate. Newton's method on the stored matrix is then a quasi-Newton iteration. With GMRES(operator = :exact) the stored block only preconditions the exact Newton operator (jacobian_correction_product!). test/test_jacobian_strategies.jl checks the modes.

DREAM's nonlinear solver (src/Solver/SolverNonLinear.cpp) damps the Newton step. It has no line search. With line_search = true, NewtonSolver backtracks on $\tfrac{1}{2}\lVert F \rVert^2$ of the scaled residual $F$ with the Armijo condition. It starts from the step length that the lower limits allow. The default is off, DREAM's behaviour. test/test_time_stepping.jl checks it.