Updates between intervals

src/solvers/interval_updates.jl

Public

Runes2P.IntervalUpdate — Type
IntervalUpdate

Supertype of the updates integrate applies at the start of the run and after every accepted step (updates), at the state and the time where that step ends. An update implements

  • update_name(update): its name, unique among the updates of a run;
  • apply_update!(update, u, layout, t): apply it for the steps that start at the time t [s] with the state u; returns whether the setup changed;
  • update_state(update): the numbers the update has set, as a vector, stored with every saved state and in every checkpoint;
  • restore_update!(update, state): set the setup back to a stored state;
  • describe(update, context): its record in the settings of the run.

Optional: changes_continuously(update), whether its changes are continuous in time, so that StepController keeps its history across them; false by default, a change is a jump.

An update that writes radial coefficients (advection_r, diffusion_r_r) or cross coefficients (diffusion_p_xi, diffusion_xi_p) into an AdvectionDiffusion writes only those the operator declares (radial_transport, cross_diffusion). integrate does not check the declarations after an update, and the Jacobian of an undeclared coefficient would be added to declared entries without an error. RechesterRosenbluthUpdate checks them after its write, and check_stencil_pattern checks an operator in a test.

source
Runes2P.KnockOnCutoffUpdate — Type
KnockOnCutoffUpdate(operator, plasma_at; name="knockon_cutoff", placement=:energy_midpoint,
                    no_ceiling_factor=10, per_radius=true, thermal_factor=4,
                    critical_momentum_at=total_critical_momentum,
                    coulomb_logarithm=:thermal, linked=[], electric_field=nothing)

Knock-on cutoff that follows the plasma plasma_at(t) at the time t [s], or a PlasmaSource such as PlasmaFromUnknowns, which it reads at the state of the start of each step (a system whose bulk reads the temperature from an unknown refuses a prescribed temperature here): at the start of the run and after every accepted step the cutoff of each radius of operator is set to a face of the knock-on momentum grid. The cutoff per radius, in units of mₑc, is the state of the update. critical_momentum_at(plasma, ir) gives the runaway threshold, a momentum in units of mₑc.

coulomb_logarithm is the Coulomb logarithm of the collisions of the run, the field of the same name of CollisionSettings, whose default :thermal it shares. The default ceiling total_critical_momentum, and free_critical_momentum, take it: the thermal logarithm for :thermal and the relativistic one for :energy_dependent and :relativistic, as DREAM's Ec_tot and Ec_free do (RunawayFluid::CalculateDerivedQuantities, src/Equations/RunawayFluid.cpp:205-209). The update does not take the logarithm from the collisions of the run: a run whose CollisionSettings take another model passes it here, and the run refuses the default :thermal next to a Fokker-Planck term whose collisions take another model. :relativistic is allowed in any run. Another function given as critical_momentum_at is called without it.

  • placement = :energy_midpoint (the default, a choice of this package; see the docs page Choices of this package) takes the rule of cutoff_target: the logarithmic midpoint in energy between the temperature and the energy at the critical momentum, and no_ceiling_factor times the temperature where there is no threshold. The face is the nearest to that target in the logarithm of the energy, kept while the target lies between its neighbouring faces (choose_cutoff_face).
  • placement = :window takes a face inside thermal_factor · p_Te ≤ p_c < p_crit (cutoff_window), kept while it stays inside the window (choose_cutoff), which lets the cutoff come close to either bound. thermal_factor = 4 is a choice of this package (see the docs page Choices of this package).
  • per_radius = false gives every radius the cutoff of the largest temperature and the smallest critical momentum over the radii, the one value DREAM can take.

inside_window holds, per radius, whether the last choice was inside the window, policy the rule that gave the target (:log_midpoint, :no_ceiling, :closed, or :window), and rebuilds counts the kernel sets built.

The cutoff of the first interval replaces the one the operator was built with, unless that one is a face the rule keeps. Without the update the cutoff is fixed, as in DREAM (pCutAvalanche), where a run can change it only between restarts.

electric_field names the radial unknown of the electric field when the field is an unknown of the system: the runaway threshold then takes the field of the state at the start of the step in place of the field of the prescribed plasma.

linked lists further knock-on operators that take the cutoff of operator at every change. With a hot-tail and a runaway grid operator is the pairing hot-tail from hot-tail, whose knock-on grid holds the cutoff, and the pairings hot-tail from runaway and runaway from runaway are linked, so that every knock-on above the one cutoff is counted once, on one of the two grids.

source

Internal

Runes2P.check_update — Method
check_update(update, system)

Refuse an update that does not fit the equation system of the run, before the first step. Nothing by default.

source

src/solvers/transport_update.jl

Public

Runes2P.RechesterRosenbluthUpdate — Type
RechesterRosenbluthUpdate(operator, delta_b_over_b_at; major_radius, safety_factor=1,
                          name="radial_transport")

Radial diffusion of operator that follows the level of the magnetic perturbation in time: at the start of the run and after every accepted step, at the time t [s] where that step ends, operator.diffusion_r_r is set to the Rechester-Rosenbluth coefficient of delta_b_over_b_at(t) (add_rechester_rosenbluth_diffusion!): a number, one value per radial face, or a callable of r such as an interpolator, evaluated on the faces (radial_face_values). The major radius major_radius [m] enters the coefficient. A profile on points of its own that is constant in time is t -> profile. The safety factor takes the same forms and is evaluated once. Each step takes the level at its start, so a PiecewiseConstant whose switch times are among the time points gives every step from t_k to t_{k+1} the level at t_k. The levels of the faces are the state of the update, stored with the checkpoints and restored on resume.

operator is the operator of the radial transport alone: the update owns its diffusion_r_r, and the operator declares radial transport (radial_transport = true of AdvectionDiffusion, the default of an operator built by hand), so that its stencil holds the radial neighbours before the system is built. Build it with cross_diffusion = false, as add_rechester_rosenbluth_diffusion! advises, so that its stencil leaves out the corners of the 3×3 block in p and ξ. A PiecewiseConstant level needs its switch times among the time points of the run. DREAM interpolates the table of its dBB linearly in time and takes the value at the end of a step.

A level without forced_time_points, any function other than a PiecewiseConstant, is taken as continuous in time: its change at every step discards the stored Jacobian and leaves the history of StepController in place, whose predictor extrapolates across it. A level that jumps is given as a PiecewiseConstant, whose switches restart the estimate of the controller.

source