Process reference: kinetic_closure

Generated from the docstrings of vaft.process.kinetic_closure: 4 public functions. Each entry is what vaft.process.describe("kinetic_closure.<name>") prints. All process categories

Overview

Connects pieces VAFT already has – Thomson n_e and T_e, a T_i/T_e policy, an impurity composition (#1565), the per-species pressure law – into one pressure construction that does not assume n_i = n_e, and adds a lightweight fast-ion baseline (vaft.formula.fast_ion) for when no NUBEAM run exists. Thermal and fast pressure stay separate quantities.

The chain::

core_profiles slice (matched by time): n_e, T_e, T_i or T_i/T_e policy
+ impurity composition (vaft.process.impurity.resolve_impurity_composition)
    -> species densities n_s = n_e (n_s/n_e), main ion diluted   [dilution="species"]
       or n_i = n_e, one hydrogenic ion                           [dilution="none", the old form]
    -> p_e = e n_e T_e,  p_i = e sum_s n_s T_s,  p_thermal = p_e + p_i
+ optional fast-ion source (fast_ion_slowing_down_estimate)
    -> p_fast = 2 W_f / 3
-> PressureAssembly: p_e, p_i_thermal, p_thermal, p_fast, p_total
SymbolMeaningUnit
p_e, p_ielectron and summed ion thermal pressurePa
p_fastscalar fast-ion pressurePa
p_totalp_thermal + p_fastPa
Sfast-ion birth rate per unit volumem^-3 s^-1

Thermal and fast never share a field. p_thermal holds Maxwellian species only; p_total adds p_fast. Writing fast pressure into a thermal field is what #1606 Sec. 5 forbids.

Every assumed number is recorded. The T_i source (measured or a ratio with its record), the composition’s kind and source, the dilution mode and the fast-ion inputs are in provenance.

Functions

assemble_pressureElectron, per-species ion, thermal, fast and total pressure, each kept separate. Convention
fast_ion_slowing_down_estimateClassical slowing-down density, energy and pressure of one fast-ion source on a grid.
infer_kinetic_closureDensities, temperatures and separated pressures of one core_profiles slice, dilution-aware. Convention
infer_ti_pressure_partitionIon temperature from the equilibrium pressure partition, T_i = p_eq / (e f n_e) - T_e / f. Convention

assemble_pressure

Machine-independentConvention-sensitive source
assemble_pressure(n_e, T_e, ion_densities, ion_temperatures, *, p_fast=None, provenance=None)
Show source vaft/process/kinetic_closure.py, lines 140–213
def assemble_pressure(
    n_e: Any,
    T_e: Any,
    ion_densities: Mapping[str, Any],
    ion_temperatures: Mapping[str, Any],
    *,
    p_fast: Any = None,
    provenance: Optional[Mapping[str, Any]] = None,
) -> PressureAssembly:
    """Electron, per-species ion, thermal, fast and total pressure, each kept separate.

    Parameters
    ----------
    n_e : array-like
        Electron density [m^-3].
    T_e : array-like
        Electron temperature [eV].
    ion_densities : mapping
        Thermal density of each ion species by label [m^-3].
    ion_temperatures : mapping
        Temperature of each ion species, same labels [eV].
    p_fast : array-like, optional
        Scalar pressure of non-thermal populations; ``None`` when there is none
        to add [Pa].
    provenance : mapping, optional
        Record carried into the result [any].

    Returns
    -------
    PressureAssembly
        ``p_e = e n_e T_e``, ``p_i_species`` and their sum ``p_i_thermal``,
        ``p_thermal = p_e + p_i_thermal``, ``p_fast`` and
        ``p_total = p_thermal + p_fast`` [Pa].

    Raises
    ------
    ValueError
        Labels that differ between densities and temperatures, or negative
        densities, temperatures or fast pressure.

    Convention
    ----------
    Thermal and fast pressure are never merged into one field; ``p_total`` is
    the only sum of the two.  Uses :func:`vaft.formula.equilibrium.electron_pressure`
    and :func:`~vaft.formula.equilibrium.ion_pressure` per species.

    Applicability
    -------------
    Machine-independent.

    Provenance
    ----------
    .. [issue] #1606 Sec. 2 and 5.
    """
    from vaft.formula.equilibrium import electron_pressure, ion_pressure

    if set(ion_densities) != set(ion_temperatures):
        raise ValueError("ion_densities and ion_temperatures must name the same species")
    ne = _finite_non_negative(n_e, "n_e")
    te = _finite_non_negative(T_e, "T_e", ne.shape)
    p_e = np.asarray(electron_pressure(np.nan_to_num(ne), np.nan_to_num(te)), dtype=float)
    p_e = np.where(np.isfinite(ne) & np.isfinite(te), p_e, np.nan)
    p_species = {}
    for label, density in ion_densities.items():
        n = _finite_non_negative(density, f"density of {label}", ne.shape)
        t = _finite_non_negative(ion_temperatures[label], f"temperature of {label}", ne.shape)
        ok = np.isfinite(n) & np.isfinite(t)
        p_species[label] = np.where(ok, np.asarray(ion_pressure(np.where(ok, n, 0.0), np.where(ok, t, 0.0))), np.nan)
    p_i = np.sum(list(p_species.values()), axis=0) if p_species else np.zeros_like(p_e)
    p_thermal = p_e + p_i
    fast = None if p_fast is None else _finite_non_negative(p_fast, "p_fast", ne.shape)
    return PressureAssembly(p_e=p_e, p_i_species=p_species, p_i_thermal=p_i, p_thermal=p_thermal,
                            p_fast=fast, p_total=p_thermal + (0.0 if fast is None else fast),
                            provenance=dict(provenance or {}))

Electron, per-species ion, thermal, fast and total pressure, each kept separate.

NameTypeUnitDescription
n_earray-likem^-3

Electron density.

T_earray-likeeV

Electron temperature.

ion_densitiesmappingm^-3

Thermal density of each ion species by label.

ion_temperaturesmappingeV

Temperature of each ion species, same labels.

p_fastarray-like, optionalPa

Scalar pressure of non-thermal populations; None when there is none to add.

provenancemapping, optionalany

Record carried into the result.

Returns
—PressureAssemblyPa

p_e = e n_e T_e, p_i_species and their sum p_i_thermal, p_thermal = p_e + p_i_thermal, p_fast and p_total = p_thermal + p_fast.

Convention

Thermal and fast pressure are never merged into one field; p_total is the only sum of the two. Uses vaft.formula.equilibrium.electron_pressure and vaft.formula.equilibrium.ion_pressure per species.

Raises

  • ValueError Labels that differ between densities and temperatures, or negative densities, temperatures or fast pressure.
Applicability · Provenance

Applicability

Machine-independent.

Provenance

  1. #1606 Sec. 2 and 5.

fast_ion_slowing_down_estimate

Machine-independent source
fast_ion_slowing_down_estimate(n_e, T_e, field_ions, source_rate, beam_energy_eV, *, A_b, Z_b=1.0, ln_Lambda=None, time=None, rho=None)

Classical slowing-down density, energy and pressure of one fast-ion source on a grid.

NameTypeUnitDescription
n_earray-likem^-3

Electron density.

T_earray-likeeV

Electron temperature.

field_ionsmappingany

label -> (density, Z, A) of every thermal ion species.

source_ratearray-likem^-3 s^-1

Fast-ion birth rate per unit volume on the grid.

beam_energy_eVfloateV

Birth energy of the fast ions.

A_bfloat-

Mass number of the fast ion.

Z_bfloat, optional-

Charge of the fast ion.

ln_Lambdaarray-like, optional-

Electron Coulomb logarithm; default the NRL form of n_e, T_e.

timefloat, optionals

Time of the profiles; infer_kinetic_closure refuses the estimate for a slice further away than its tolerance.

rhoarray-like, optional-

Radial grid of the profiles; checked against the slice grid.

Returns
—FastIonEstimateany

v_c, E_c, tau_s, the thermalisation time, n_fast, W_fast and the isotropic p_fast = 2 W_fast / 3.

Raises

  • ValueError Non-positive beam energy, mass or charge, or a negative source rate.
Processing steps · Assumptions · Applicability · Limitations · Provenance

Processing steps

  1. v_c from the field ions (vaft.formula.fast_ion.critical_velocity_from_T_e_n_species).
  2. tau_s on electrons with ln Lambda.
  3. Steady slowing-down density and energy density from source_rate.
  4. p_fast = 2 W_fast / 3.

Assumptions

Steady state, a single birth energy, classical drag, local deposition (no orbit width), an isotropic population, no charge-exchange loss. Points with a non-positive or non-finite n_e or T_e (the zero edge of a fitted profile) have no defined drag and are returned as NaN.

Applicability

Machine-independent.

Limitations

A baseline, not NUBEAM: orbit losses, anisotropy and charge exchange – large in a small device like VEST – are absent, so it bounds the fast pressure from above where those losses matter. On the packaged VEST NUBEAM case (10 keV H, 200 kW), given NUBEAM’s own birth rate and plasma, it gives 1.32x NUBEAM’s fast-ion number and 1.26x its energy; NUBEAM loses 13 % of the deposited power to bad orbits and CX, and with that removed the totals agree to 10-15 % (1.14x, 1.10x). Radial profiles differ more, most at the edge, where orbit losses concentrate (test/test_kinetic_closure_nubeam.py).

Provenance

  1. T. H. Stix, Plasma Phys. 14 (1972) 367.
  2. #1606 Sec. 3-4.

infer_kinetic_closure

Machine-independentConvention-sensitive source
infer_kinetic_closure(ods, *, time=None, tolerance=0.0005, dilution='species', composition=None, machine_preset=None, shot=None, ti_te_ratio=None, ti_record=None, use_stored_inferred_ti=False, fast_ion=None)

Densities, temperatures and separated pressures of one core_profiles slice, dilution-aware.

NameTypeUnitDescription
odsODSany

Source of n_e, T_e and (when stored) the main-ion T_i; read without creating paths.

timefloat, optionals

Slice time; required when the IDS holds several slices.

tolerancefloat, optionals

Largest |t_slice - time| accepted.

dilutionstr, optional-

species (composition-resolved ion densities) or none (the legacy n_i = n_e single hydrogenic ion, keyed by the stored main-ion label, H+ when none is stored).

compositionImpurityComposition, optionalany

Explicit composition for vaft.process.impurity.resolve_impurity_composition.

machine_presetstr or mapping, optionalany

Machine preset for the same resolver ("vest").

shotint, optional-

Shot whose preset era applies.

ti_te_ratiofloat, optional-

T_i = ratio T_e for every ion when the slice stores no measured T_i: none at all, or one whose temperature_fit.parameters record says it was assumed (ti_te_ratio=...; status=assumed) or inferred (origin=inferred).

ti_recordstr, optional-

Provenance text for that ratio (e.g. the VEST policy record).

use_stored_inferred_tibool, optional-

Take a stored T_i whose record says origin=inferred (a lane K pressure partition) as the ion temperature, recorded as inferred; off by default, as in vaft.process.transport_state.build_transport_state.

fast_ionFastIonEstimate, optionalany

A fast-ion estimate on the same grid, added as p_fast.

Returns
—KineticClosureany

Composition, ion densities and temperatures, the PressureAssembly and the provenance of every input.

Convention

dilution="none" reproduces pressure_thermal = e n_e (T_e + T_i) of vaft.process.profile.core_profiles_from_eq_ratio exactly; the species mode differs from it by e n_e T_i (sum_s n_s/n_e - 1).

Raises

  • ValueError An unknown dilution mode, no slice at the time, no n_e or T_e, no measured T_i and no ratio (an inferred one needs the opt-in or a ratio), an ion-temperature record in no known grammar, several hydrogenic ions, a composition that cannot be resolved, a composition resolved on another grid than n_e, or a fast-ion estimate from another grid or time.
Processing steps · Input semantics · Output semantics · Applicability · Limitations · Provenance

Processing steps

  1. Match the slice by time; read n_e, T_e and the main-ion T_i if stored.
  2. species: resolve the composition (stored ions, explicit, preset; #1565 precedence) and form n_s = n_e (n_s/n_e) with the diluted main ion; none: one hydrogenic ion with n_i = n_e.
  3. Ion temperatures for every ion: the stored main-ion T_i when its temperature_fit.parameters record classifies as measured (vaft.machine_mapping.core_profiles.classify_ti_record); a stored T_i the product itself assumed or inferred is not a measurement and is outranked by the caller’s ratio (recorded as assumed) – an inferred one is used only on use_stored_inferred_ti (recorded as inferred); provenance["ti"] carries status and lineage.
  4. Assemble p_e, p_i, p_thermal; add fast_ion as p_fast.

Input semantics

A fitted core_profiles slice (Thomson n_e, T_e; T_i measured or not).

Output semantics

Derived kinetic densities and separated pressures; nothing is written.

Applicability

Machine-independent. A machine preset reaches it only as machine_preset.

Limitations

Impurities share the main-ion temperature, read from the one hydrogenic ion[] entry (by element.0.z_n, not position). A measured record is taken at its word: whether the measurement itself is sound (CX coverage, fit span) is the profile stage’s finding, not re-examined here. The fast-ion pressure is the caller’s estimate; it must share the slice’s grid (and its time and rho when the estimate records them). No deposition model is run here.

Provenance

  1. #1606 Sec. 1-2 and 5; #1565 (composition); #1526 (the T_i record grammar, cold review 0.8.0 delta-absorb-19 physics F1).

infer_ti_pressure_partition

Machine-independentConvention-sensitive source
infer_ti_pressure_partition(p_eq, n_e, t_e, *, composition, sigma_p_eq, sigma_n_e, sigma_t_e, equilibrium_lineage)

Ion temperature from the equilibrium pressure partition, T_i = p_eq / (e f n_e) - T_e / f.

NameTypeUnitDescription
p_eqarray-likePa

Equilibrium total pressure on the points.

n_earray-likem^-3

Electron density on the same points.

t_earray-likeeV

Electron temperature on the same points.

compositionmapping-

ion_density_per_electron – f = sum_s n_s / n_e, a number or an array on the points [-] – and composition_source, a description of where it came from.

sigma_p_eqarray-likePa

One-sigma uncertainty of p_eq.

sigma_n_earray-likem^-3

One-sigma uncertainty of n_e; NaN where unknown.

sigma_t_earray-likeeV

One-sigma uncertainty of t_e; NaN where unknown.

equilibrium_lineagestr-

Where p_eq was reconstructed, one of the lineages the caller derived from the product’s stage; the inference is refused unless it is in INDEPENDENT_LINEAGES.

Returns
—dictany

Refused (eligible = False): origin, method and the reason. Otherwise eligible = True, origin = "inferred", method, equilibrium_lineage, assumptions, p_e and p_i [Pa], sigma_p_i [Pa], t_i and sigma_t_i [eV], ti_te [-] and flags, one list per point [any]. t_i, sigma_t_i and ti_te are NaN where a point carries a flag of TI_FLAGS.

Convention

The uncertainty is propagated through T_i = p_eq / (e f n_e) - T_e / f, which keeps the n_e correlation between p_e and the ion density::

dT_i/dp_eq = 1/(e f n_e), dT_i/dn_e = -p_eq/(e f n_e^2), dT_i/dT_e = -1/f

Points are flagged, never filled. Scalars broadcast against arrays; every input is brought to one shape. f is taken as exact, and p_eq is the caller’s pressure with the caller’s uncertainty.

Raises

  • KeyError composition lacks ion_density_per_electron or composition_source.
Processing steps · Assumptions · Applicability · Limitations · Provenance

Processing steps

  1. Refuse a lineage outside INDEPENDENT_LINEAGES.
  2. p_e = e n_e T_e and p_i = p_eq - p_e.
  3. T_i = p_i / (e f n_e) for one common ion temperature of n_i = f n_e ions.
  4. Propagate the one-sigma inputs linearly (below).
  5. Void p_i <= 0 (p_i_nonpositive), p_i < sigma(p_i) (p_i_not_significant) and non-finite or non-positive inputs (non_finite_input); a missing input uncertainty only adds the note sigma_unavailable and skips the significance test at that point.

Assumptions

A single ion temperature for every ion species; f from a composition the caller names. The result is an inferred quantity, never a measurement.

Applicability

Machine-independent.

Limitations

The guard trusts the declared lineage. Equilibrium products carry no machine-readable record of one, so a caller must derive equilibrium_lineage from where the pressure came from (the FileDB stage it loaded), never from intent. An electron_kinetic pressure was fitted with an assumed T_i/T_e and is refused as circular.

Provenance

  1. #1426 (pressure-partition T_i); moved here from vaft.validation.kinetic_state by #1842.

results matching ""

    No results matching ""