XGC-Analysis package

xgc_analysis.AnalyticDiffusionProfiles module

class xgc_analysis.AnalyticDiffusionProfiles.AnalyticDiffusionProfiles(psi, time, S, Vol, grad_avg, psi_norm)[source]

Bases: object

Creates diffusion profile data using analytic functions.

Attributes:

density : A 3D array (shape (n_species, n_samples, n_surf)) of the diffusion density. flow : A 3D array (shape (n_species, n_samples, n_surf) of the parallel mean flow. temp : A 3D array (shape (n_species, n_samples, n_surf)) of temperature (in eV). n_samples : An integer (n_samples) representing the number of time samples. n_species : An integer (default 2) representing the number of particle species. n_surf : An integer (n_surf) representing the number of ψ-surfaces. psi : A 1D array (shape (n_surf,)) containing the poloidal magnetic flux values. steps : A 1D array (shape (n_samples,)) of time step indices. time : A 1D array (shape (n_samples,)) of simulation times (in seconds).

xgc_analysis.DiffusionCoefficients module

class xgc_analysis.DiffusionCoefficients.DiffusionCoefficients(adios: Adios, *, timeout=10.0, nspecies=2, npsi=100)[source]

Bases: object

Stores the profiles of diffusion model coefficients defined as functions of the poloidal magnetic flux ψ.

The four diffusion coefficients are:
  • ptl_diffusivity (m^2/s)

  • momentum_diffusivity (m^2/s)

  • heat_conductivity (m^2/s)

  • ptl_pinch_velocity (m/s)

The data layout of each coefficient is (nspecies, npsi) where the second dimension (the ψ-grid) is contiguous in memory. Also the ψ–grid is stored as a 1D NumPy array of length npsi.

Parameters:

nspecies: Number of particle species (default: 2). npsi: Number of points in the ψ–grid.

close() None[source]

Close the underlying stream.

write_to_file(filename='xgc.diffusion_coeff.bp', gstep=-1)[source]

Writes the diffusion coefficient profiles and the ψ–grid to an Adios BP file as a new step.

For each diffusion coefficient, the data for each species is split into an individual variable using a species suffix. The species suffixes (for species indices 0 through 6) are:

0: _elec 1: _ion 2: _imp1 3: _imp2 4: _imp3 5: _imp4 6: _imp5

In addition, the file will store:
  • n_species: a scalar integer (int64).

  • psi: a 1D array (of length npsi).

The method opens the specified file (filename) using the Adios2 FileWriter in append mode, writes all the individual diffusion profiles, and then ends the step.

xgc_analysis.DiffusionProfiles module

class xgc_analysis.DiffusionProfiles.DiffusionProfiles(adios: adios2.Adios, *, bp_dir: os.PathLike | str = './xgc.diffusion_profiles.bp', wait_interval: float = 1.0, timeout: float | None = None)[source]

Bases: object

Live reader for xgc.diffusion_profiles.bp.

Reads diffusion profile data from an Adios BP file (directory) xgc.diffusion_profiles.bp. The constructor waits for a file called “xgc.diffusion_profiles.py” to be created. Once it is found, it opens it as a persistent adios2.Stream, drains all existing steps while retaining only the final one. The Stream is left open until it is closed with the member method close(). A blocking request for a new step can be posted with the member method read_next_step.

The file xgc.diffusion_profiles.bp has the following structure:

double density n_steps*{n_species, n_samples, n_surf} double flow n_steps*{n_species, n_samples, n_surf} double temp n_steps*{n_species, n_samples, n_surf} int32_t n_samples n_steps*scalar int32_t n_species n_steps*scalar int32_t n_surf n_steps*scalar double psi n_steps*{n_surf} int32_t steps n_steps*{n_samples} double time n_steps*{n_samples}

That is, there are (for example) n_steps steps recorded in the BP file. The constructor of this class reads only the last step (i.e. the most recent one).

The property latest_step_data returns a dictionary with the following keys:

density : A 3D array (shape (n_species, n_samples, n_surf)) of the diffusion density. flow : A 3D array (shape (n_species, n_samples, n_surf) of the parallel mean flow. temp : A 3D array (shape (n_species, n_samples, n_surf)) of temperature (in eV). n_samples : An integer (n_samples) representing the number of time samples. n_species : An integer (default 2) representing the number of particle species. n_surf : An integer (n_surf) representing the number of ψ-surfaces. psi : A 1D array (shape (n_surf,)) containing the poloidal magnetic flux values. steps : A 1D array (shape (n_samples,)) of time step indices. time : A 1D array (shape (n_samples,)) of simulation times (in seconds).

Parameters:
  • bp_dir (str | os.PathLike) – Path to the BP directory written by XGC. The constructor blocks until the directory exists (subject to timeout).

  • wait_interval (float, optional) – Polling interval in seconds while waiting for the directory. Defaults to 1.0 s.

  • timeout (float | None, optional) – Abort after this many seconds if the directory still does not exist. None (default) means wait indefinitely.

Notes

The object keeps exactly one snapshot in memory. Callers needing to store a history must copy out the data returned by latest_step_data.

close() None[source]

Close the underlying stream.

property latest_step_data: Dict[str, ndarray]

Return a shallow copy of the dictionary holding the current step.

Raises:

RuntimeError – If no step has been read yet (e.g., the writer hasn’t flushed a step to disk).

property n_samples: int | None

Number of (time) samples per species in snapshot, else None.

property n_species: int | None

Number of species in the current snapshot (or None).

property n_surf: int | None

Radial surface count (psi grid size) in snapshot, else None.

read_next_step(*, my_timeout: float = 10.0, poll_delay: float = 0.5) bool[source]

Advance the stream by one time step.

Examples

>>> prof = DiffusionProfiles("xgc.diffusion_profiles.bp")
>>> prof.read_next_step(block=False)
False  # no new data yet
>>> # ... later
>>> prof.read_next_step()
True   # newest snapshot now loaded
Parameters:
  • my_timeout – Maximum wait time for a new step; if no new step is found within my_timeout seconds, return False.

  • poll_delay – Sleep duration (seconds) between availability checks when block is True.

Returns:

True if a new step was successfully read, False otherwise.

Return type:

bool

xgc_analysis.accessor_mixin module

class xgc_analysis.accessor_mixin.ArrayAccessorMixin[source]

Bases: object

Mixin class to provide access to data arrays in various formats. This class should be used with classes that have a data attribute structured as a dictionary of dictionaries, where the outer key is the variable name and the inner key is the step index.

Design note

This mixin provides generic access helpers that only assume the common self.data[var_name][step_index] storage layout. Reader classes should add thin semantic wrappers (for example get_mesh_data or get_distribution) on top of these methods.

get_array(var_name)[source]

Returns the raw NumPy array for all steps of a given variable.

Args:
var_name (str):

Name of the variable to extract (e.g., “eden”, “time”, etc.).

steps: (list, optional):

List of specific steps to include in the output. If None, all available steps will be used.

Returns:n
np.ndarray: The raw NumPy array for the specified variable across all steps.
  • For scalar variables (e.g., time), the shape will be (n_steps,).

  • For mesh-based variables, the shape will be (n_steps, n_planes, n_vertices).

  • For plane-based variables, the shape will be (n_steps, n_nodes). (Or something similar.)

get_as(var_name, step_index, expected_type)[source]

Return a stored item and validate its type.

Parameters:

expected_type (type | tuple[type, ...]) – Allowed Python class/type(s).

get_item(var_name, step_index)[source]

Return the raw stored object for var_name at step_index.

has_var(var_name)[source]

Return True if var_name exists in self.data.

list_step_indices(var_name=None)[source]

Return sorted step/file-index keys.

Parameters:

var_name (str or None) – If provided, return keys only for that variable. If None, return the sorted union of keys across all variables.

list_vars()[source]

Return sorted variable names stored in self.data.

xgc_analysis.adios_stream module

Shared ADIOS stream helpers.

xgc_analysis.adios_stream.iter_stream_steps(stream, step_timeout_secs=None)[source]

Iterate ADIOS stream steps with optional timeout-as-EOF handling.

Parameters:
  • stream – ADIOS stream object exposing either normal iteration or steps(timeout=...).

  • step_timeout_secs (int, float, or None, optional) – Timeout passed to stream.steps. When the timeout expires, ADIOS raises a runtime error; this helper treats the expected “no new step” message as end-of-stream for offline files.

Yields:

object – ADIOS step objects from the stream.

xgc_analysis.adios_stream.open_adios_stream(filename, open_timeout_secs=None, *, force_file_stream=True)[source]

Open an ADIOS stream with optional OpenTimeoutSecs configuration.

Parameters:
  • filename (str) – ADIOS-readable source path.

  • open_timeout_secs (int, float, or None, optional) – Open timeout for FileStream mode. If omitted, the default ADIOS opening path is used.

  • force_file_stream (bool, optional) – If True and open_timeout_secs is provided, open with a declared IO using FileStream. Campaign .aca sources should normally leave this False or use adios2.FileReader instead.

Yields:

adios2.Stream – Open stream context.

xgc_analysis.adios_file_reader module

Reusable ADIOS FileReader helpers for finite BP and ACA reads.

class xgc_analysis.adios_file_reader.AdiosFileSourceReader(file_reader=None, *, qualify_with_source_id: bool = False, owns_reader: bool = False)[source]

Bases: object

Callable source-reader backend for finite catalog reads.

The same callable shape is used for directory-backed local BP products and campaign-backed ACA products. Directory catalogs construct this class without an open reader, so each physical BP source is opened once per batched read request. Campaign catalogs pass a persistent FileReader handle and enable source-id qualification, avoiding repeated ACA opens.

close() None[source]

Close the persistent FileReader handle when this reader owns it.

static qualified_variable_name(source_id: str | None, variable: str) str[source]

Return source_id/variable unless the name is already qualified.

Parameters:
  • source_id (str or None) – Catalog source id.

  • variable (str) – Reader-facing variable name.

xgc_analysis.adios_file_reader.available_step_count(reader) int[source]

Return the maximum AvailableStepsCount advertised by an open FileReader.

Parameters:

reader (adios2.FileReader) – Open FileReader handle.

xgc_analysis.adios_file_reader.available_steps_count_for_variable(info) int[source]

Return AvailableStepsCount from one ADIOS variable metadata record.

Parameters:

info (dict) – Raw metadata for one ADIOS variable.

xgc_analysis.adios_file_reader.available_variable_names(reader) list[str][source]

Return sorted variable names advertised by an open FileReader.

Parameters:

reader (adios2.FileReader) – Open FileReader handle.

xgc_analysis.adios_file_reader.read_adios_file_steps(source_path: Path, variables: Sequence[str], adios_steps: Sequence[int], *, source_id: str | None = None, file_reader=None, qualify_with_source_id: bool = False) Mapping[int, Mapping[str, object]][source]

Read selected variables and ADIOS steps through adios2.FileReader.

Parameters:
  • source_path (pathlib.Path) – ADIOS-readable BP source. This path is opened when file_reader is omitted.

  • variables (sequence[str]) – Reader-facing variable names to read at each selected step.

  • adios_steps (sequence[int]) – Physical ADIOS step ids to read.

  • source_id (str or None, optional) – Source id used to qualify campaign variables, for example xgc.f3d.00010.bp/e_den.

  • file_reader (adios2.FileReader or None, optional) – Existing open FileReader handle. Supplying this avoids reopening expensive campaign files for every read batch.

  • qualify_with_source_id (bool, optional) – If True, qualify unqualified variable names as source_id/variable.

Returns:

Values keyed by ADIOS step and original reader-facing variable name.

Return type:

dict[int, dict[str, object]]

xgc_analysis.bp_reader_mixin module

Shared helpers for BP-based diagnostic readers.

class xgc_analysis.bp_reader_mixin.BPReaderMixin[source]

Bases: object

Mixin for readers that load ADIOS BP files into self.data.

This mixin handles: - optional explicit variable selection, - optional all-step vs last-step file reads, - first-step variable validation for explicit requests, - step-index bookkeeping and - zero-filling of later-step missing requested variables.

get_step_info(step_index)[source]

Return file/ADIOS-step metadata for one internal step index.

Parameters:

step_index (int) – Internal sequential index used as second key in self.data.

Returns:

Dictionary with keys: - file_index: integer file index from filename - bp_step: integer ADIOS step id inside that file

Return type:

dict[str, int]

Raises:

KeyError – If step_index is not present in self.step_index_info.

xgc_analysis.catalog.directory_catalog module

Directory-backed catalog for XGC ADIOS output discovery.

This module scans one dataset root, groups XGC *.bp outputs into logical products, collects ADIOS metadata when requested, and builds read plans that map user-facing logical steps to concrete ADIOS source/step pairs. It does not read payload arrays; readers execute the returned ReadPlan objects.

class xgc_analysis.catalog.directory_catalog.SimulationCatalog(root_dir: Path, products: Iterable[DataProduct], *, refresh_func: Callable[[], Iterable[DataProduct]] | None = None, state_key_func: Callable[[], Tuple[Tuple[str, str, int, int], ...]] | None = None, state_key: Tuple[Tuple[str, str, int, int], ...] | None = None, source_reader=None)[source]

Bases: object

Catalog of ADIOS-readable XGC products in one dataset root.

The catalog is intentionally independent of Simulation so GUI code and automation scripts can inspect available products without constructing mesh or field objects. A Simulation may hold a catalog instance when heavier analysis context is needed.

available_steps(product_key: str, variable: str | None = None) List[StepInfo][source]

Return deduplicated logical steps for one product and optional variable.

Parameters:
  • product_key (str) – Catalog product key.

  • variable (str or None, optional) – If provided, only sources that advertise the variable contribute steps. If omitted, all sources for the product contribute.

Returns:

Logical steps in ascending order. When several sources advertise the same logical step, the selected fragment follows the newer_source_wins policy and other candidates are retained as duplicates.

Return type:

list[StepInfo]

close() None[source]

Release backend resources held by this catalog.

Directory-backed catalogs normally do not hold open files. Campaign catalogs may keep an ACA FileReader open so repeated read-plan execution does not reopen an expensive archive. If the installed source_reader exposes close(), this method delegates to it.

get_product(product_key: str) DataProduct[source]

Return one product entry by key.

Parameters:

product_key (str) – Catalog key such as xgc.3d.bp or xgc.oneddiag.bp.

Raises:

KeyError – If the product is not present in the catalog.

list_products() List[DataProduct][source]

Return all discovered products ordered by product key.

Returns:

Stable, alphabetically ordered product list for UI display or scripted inspection.

Return type:

list[DataProduct]

list_variables(product_key: str) List[VariableInfo][source]

Return variables available for one product.

Parameters:

product_key (str) – Catalog key for the product to inspect.

Returns:

Variable metadata ordered by native variable name.

Return type:

list[VariableInfo]

plan_read(product_key: str, variable: str, steps: Iterable[int], missing: str | MissingStepPolicy = MissingStepPolicy.RAISE) ReadPlan[source]

Resolve a variable read over logical steps into ADIOS source fragments.

Parameters:
  • product_key (str) – Catalog product key.

  • variable (str) – Native XGC/ADIOS variable name to read.

  • steps (iterable[int]) – Requested logical step values, typically XGC gstep values or filename-derived indices when no explicit step variable exists.

  • missing ({"raise", "skip", "zero"} or MissingStepPolicy, optional) – Policy for requested logical steps that are not available.

Returns:

Source fragments grouped by ADIOS-readable source.

Return type:

ReadPlan

Raises:
  • KeyError – If a requested step is unavailable and missing is "raise".

  • ValueError – If missing is not a supported missing-step policy.

read_arrays(product_key: str, variables: Iterable[str] | str | None = None, steps: Iterable[int] | int | None = None, *, missing: str | MissingStepPolicy = MissingStepPolicy.RAISE, source_reader=None) CatalogArrayRead[source]

Read catalog variables into plain NumPy arrays.

Parameters:
  • product_key (str) – Catalog product key such as "xgc.2d.bp".

  • variables (iterable[str], str, or None, optional) – Variables to read. If omitted, all variables advertised by the product are read.

  • steps (iterable[int], int, or None, optional) – Logical XGC steps to read. If omitted, each variable is read over the logical steps available for that variable.

  • missing ({"raise", "skip", "zero"} or MissingStepPolicy, optional) – Missing-step policy for explicit steps. "zero" records missing steps but does not synthesize zero arrays.

  • source_reader (callable or None, optional) – Optional read-plan source backend. If omitted, self.source_reader is used when present, otherwise the regular FileReader-backed local BP backend is used.

Returns:

Variable-first array mapping plus read provenance.

Return type:

CatalogArrayRead

refresh() SimulationCatalog[source]

Rebuild this catalog from its backend and update it in place.

Directory-backed catalogs created by open_catalog() rescan the dataset root, regroup products, reread ADIOS metadata when configured to do so, and replace self.products with the refreshed product map. Existing ReadPlan objects are not mutated; callers should request new read plans after refreshing.

Returns:

self, for convenient chaining.

Return type:

SimulationCatalog

Raises:

RuntimeError – If the catalog was constructed without a refresh backend.

refresh_if_changed() bool[source]

Refresh this catalog only if the backend state key has changed.

This is intended for polling running simulations from scripts or the GUI. The directory backend keeps the state-key computation cheap by stat-ing BP paths and their contents rather than opening ADIOS files. When a change is detected, this method calls refresh().

Returns:

True if the catalog was refreshed, False if the current state key matches self.state_key.

Return type:

bool

Raises:

RuntimeError – If the catalog was constructed without a state-key backend.

xgc_analysis.catalog.directory_catalog.classify_product(product_key: str) Tuple[ProductType, str][source]

Classify an XGC product key by established filename conventions.

Parameters:

product_key (str) – Logical product key after sequence grouping, for example xgc.3d.bp rather than xgc.3d.00010.bp.

Returns:

Product type and coarse product family. Unknown products return (ProductType.UNKNOWN, "") so callers can still inspect them.

Return type:

tuple[ProductType, str]

xgc_analysis.catalog.directory_catalog.directory_state_key(root_dir: str | Path) Tuple[Tuple[str, str, int, int], ...][source]

Return a cheap filesystem signature for directory-backed catalog contents.

The signature covers top-level *.bp files/directories and all entries beneath BP directories. It intentionally uses only relative path, path type, modification time, and size, so it can be used for frequent GUI polling without opening ADIOS metadata. A changed key means callers should call SimulationCatalog.refresh(); an unchanged key means the catalog can usually be reused.

Parameters:

root_dir (str or pathlib.Path) – Dataset root scanned by the directory backend.

Returns:

Stable, sorted records (relative_path, kind, mtime_ns, size). The tuple is empty when the root does not exist or is not a directory.

Return type:

tuple

xgc_analysis.catalog.directory_catalog.discover_directory_products(root_dir: Path, *, collect_metadata: bool = True, metadata_reader: Callable[[Path], Tuple[Dict[str, VariableInfo], List[int], List[float], int]] | None = None) List[DataProduct][source]

Discover BP products directly contained in root_dir.

Files are grouped using XGC naming conventions. A sequence such as xgc.3d.00010.bp and xgc.3d.00012.bp becomes one product keyed as xgc.3d.bp with two sources. Non-sequence files such as xgc.oneddiag.bp become single-source products.

Parameters:
  • root_dir (pathlib.Path) – Directory to scan. The scan is non-recursive.

  • collect_metadata (bool, optional) – Whether to open ADIOS sources and collect variables/steps.

  • metadata_reader (callable or None, optional) – Optional metadata reader override, mainly for tests.

Returns:

Discovered products sorted by product key.

Return type:

list[DataProduct]

xgc_analysis.catalog.directory_catalog.open_catalog(root_dir: str | Path, *, collect_metadata: bool = True, metadata_reader: Callable[[Path], Tuple[Dict[str, VariableInfo], List[int], List[float], int]] | None = None) SimulationCatalog[source]

Discover XGC products in a directory and return a catalog.

Parameters:
  • root_dir (str or pathlib.Path) – Directory containing XGC output files.

  • collect_metadata (bool, optional) – If True, open each ADIOS source to collect variable and step metadata. If False, only filenames, product grouping, and basic source metadata are collected.

  • metadata_reader (callable or None, optional) – Test or backend hook with signature reader(path) -> (variables, step_values, time_values, adios_step_count).

Returns:

Directory-backed catalog for root_dir. Missing or non-directory roots produce an empty catalog.

Return type:

SimulationCatalog

xgc_analysis.catalog.campaign_catalog module

HPC-Campaign-backed catalog discovery for XGC ADIOS outputs.

xgc_analysis.catalog.campaign_catalog.campaign_state_key(campaign_path: Path)[source]

Return a cheap state key for one campaign file.

Parameters:

campaign_path (pathlib.Path) – Campaign file path.

xgc_analysis.catalog.campaign_catalog.discover_campaign_products(campaign_path: Path, *, collect_metadata: bool = True, file_reader=None) List[DataProduct][source]

Discover XGC products advertised by a campaign .aca file.

Parameters:
  • campaign_path (pathlib.Path) – Campaign file to inspect.

  • collect_metadata (bool, optional) – If False, return no products. Campaign discovery currently depends on the campaign’s ADIOS metadata because there is no filesystem listing to scan.

  • file_reader (adios2.FileReader or None, optional) – Existing open campaign reader. Supplying this avoids reopening the ACA file during catalog construction and refresh.

xgc_analysis.catalog.campaign_catalog.open_campaign_catalog(campaign_path: str | Path, *, collect_metadata: bool = True) SimulationCatalog[source]

Open an HPC-Campaign-backed XGC catalog.

Parameters:
  • campaign_path (str or pathlib.Path) – Path to an ADIOS-readable campaign .aca file.

  • collect_metadata (bool, optional) – Whether to inspect campaign variable metadata. The initial campaign backend requires metadata collection to build useful product records.

Returns:

Catalog populated from campaign-qualified ADIOS variable names.

Return type:

xgc_analysis.catalog.SimulationCatalog

xgc_analysis.catalog.campaign_source_reader module

Campaign source-reader backend built on the shared FileReader reader.

class xgc_analysis.catalog.campaign_source_reader.CampaignSourceReader(file_reader=None, *, owns_reader: bool = False)[source]

Bases: AdiosFileSourceReader

Read selected variables and steps from an HPC-Campaign .aca file.

Campaign files expose product variables as qualified ADIOS names such as xgc.f2d.00010.bp/e_den. Product readers use unqualified names such as e_den. The read-plan executor passes source_id from the selected source fragment, and this reader combines it with each requested variable to form the campaign-qualified ADIOS name.

xgc_analysis.catalog.read_plan_executor module

Execution helpers for catalog ReadPlan objects.

class xgc_analysis.catalog.read_plan_executor.BatchedReadPlanExecution(plans: ~typing.List[~xgc_analysis.catalog.types.ReadPlan], records: ~typing.List[~xgc_analysis.catalog.read_plan_executor.ReadPlanRecord] = <factory>, missing_steps_by_variable: ~typing.Dict[str, ~typing.List[int]] = <factory>)[source]

Bases: object

Values produced by executing several ReadPlan objects together.

The batch executor groups fragments by physical source and opens each source once for the union of requested variables and ADIOS steps. Records are then emitted in read-plan order so reader-local step indexing remains stable.

missing_steps_by_variable: Dict[str, List[int]]
plans: List[ReadPlan]
records: List[ReadPlanRecord]
class xgc_analysis.catalog.read_plan_executor.ReadPlanExecution(plan: ~xgc_analysis.catalog.types.ReadPlan, records: ~typing.List[~xgc_analysis.catalog.read_plan_executor.ReadPlanRecord] = <factory>, missing_steps: ~typing.List[int] = <factory>)[source]

Bases: object

Values produced by executing one ReadPlan.

plan

Original read plan.

Type:

ReadPlan

records

Values read from all plan fragments. Fragment order is preserved.

Type:

list[ReadPlanRecord]

missing_steps

Logical steps that the catalog could not resolve. The executor does not synthesize zero values; callers decide how to handle these based on the plan’s missing-step policy and variable-specific shape information.

Type:

list[int]

missing_steps: List[int]
plan: ReadPlan
records: List[ReadPlanRecord]
records_by_logical_step() Dict[int, ReadPlanRecord][source]

Return read records keyed by logical step.

Later records overwrite earlier records for duplicate logical steps. Normal plans are already deduplicated by SimulationCatalog before execution, so overwriting only matters for hand-built test plans.

records_in_requested_order() List[ReadPlanRecord][source]

Return records ordered like plan.requested_steps.

Missing steps are omitted. If requested_steps contains duplicate logical steps, the same record appears more than once in the returned list.

values_by_logical_step() Dict[int, object][source]

Return read values keyed by logical step.

class xgc_analysis.catalog.read_plan_executor.ReadPlanRecord(logical_step: int, source_id: str, source_path: Path, adios_step: int, variable: str, value: object, file_index: int | None = None)[source]

Bases: object

One value read from a catalog plan fragment.

A record keeps the logical XGC step next to the physical ADIOS source coordinates. Reader classes can store values under their own sequential step indices while retaining enough metadata to map those indices back to catalog/source coordinates.

file_index

Filename-derived source index when available. Internal-step sources may leave this unset; readers should use logical_step and source_id for unambiguous provenance.

Type:

int or None

adios_step: int
file_index: int | None = None
logical_step: int
source_id: str
source_path: Path
value: object
variable: str
xgc_analysis.catalog.read_plan_executor.execute_read_plan(plan: ReadPlan, source_reader: Callable[[...], Mapping[int, Mapping[str, object]]] | None = None) ReadPlanExecution[source]

Execute a catalog ReadPlan and return logical-step records.

Parameters:
  • plan (ReadPlan) – Single-variable plan returned by SimulationCatalog.plan_read.

  • source_reader (callable or None, optional) – Backend hook with signature reader(source_path, variables, adios_steps). If omitted, regular local BP files are read with the FileReader-backed read_regular_bp_steps().

Returns:

Read records and the unresolved logical steps copied from plan.

Return type:

ReadPlanExecution

Raises:
  • KeyError – If a plan fragment points to an ADIOS step or variable that cannot be read from the selected source.

  • ValueError – If a fragment has mismatched logical-step and ADIOS-step lists.

xgc_analysis.catalog.read_plan_executor.execute_read_plans(plans: Iterable[ReadPlan], source_reader: Callable[[...], Mapping[int, Mapping[str, object]]] | None = None) BatchedReadPlanExecution[source]

Execute several single-variable ReadPlan objects as one batched read.

Parameters:
  • plans (iterable[ReadPlan]) – Plans to execute together. Plans are expected to use the same product but may request different variables.

  • source_reader (callable or None, optional) – Backend hook with signature reader(source_path, variables, adios_steps). If omitted, regular local BP files are read with the FileReader-backed read_regular_bp_steps().

Returns:

Read records and missing-step lists keyed by variable name.

Return type:

BatchedReadPlanExecution

Raises:
  • KeyError – If a planned ADIOS step or variable cannot be read from its source.

  • ValueError – If any fragment has mismatched logical-step and ADIOS-step lists.

xgc_analysis.catalog.read_plan_executor.read_regular_bp_steps(source_path: Path, variables: Sequence[str], adios_steps: Sequence[int], *, source_id: str | None = None) Mapping[int, Mapping[str, object]][source]

Read selected ADIOS steps from one regular local BP source.

Parameters:
  • source_path (pathlib.Path) – ADIOS-readable BP file or directory.

  • variables (sequence[str]) – Variable names to read from each selected ADIOS step.

  • adios_steps (sequence[int]) – Physical ADIOS step ids required by a read-plan fragment.

  • source_id (str or None, optional) – Accepted for source-reader API compatibility. Regular BP paths do not need it.

Returns:

{adios_step: {variable_name: value}} for the requested step span.

Return type:

mapping

Notes

This is the default finite-read backend for directory-backed catalogs. It opens the source with adios2.FileReader, reads the exact requested steps with step_selection, and closes the source when the batch is done. Campaign-backed catalogs use the same source-reader interface with a persistent FileReader handle.

xgc_analysis.catalog.static_product_reader module

Helpers for reading static catalog products.

xgc_analysis.catalog.static_product_reader.has_static_product(catalog, product_key: str, variables: Iterable[str] | None = None) bool[source]

Return whether catalog advertises a static product and optional variables.

Parameters:
  • catalog (xgc_analysis.catalog.SimulationCatalog) – Catalog to inspect.

  • product_key (str) – Product key to check.

  • variables (iterable[str] or None, optional) – Variables that must be advertised by the product. If omitted, only the product itself is checked.

xgc_analysis.catalog.static_product_reader.read_static_variables(catalog, product_key: str, variables: Sequence[str], *, source_reader: Callable[[...], Mapping[int, Mapping[str, object]]] | None = None, missing: str | MissingStepPolicy = MissingStepPolicy.RAISE, logical_step: int = 0) Mapping[str, object][source]

Read variables from one static catalog product.

Parameters:
  • catalog (xgc_analysis.catalog.SimulationCatalog) – Catalog containing product_key.

  • product_key (str) – Static product key such as "xgc.mesh.bp" or "xgc.f0.mesh.bp".

  • variables (sequence[str]) – ADIOS variable names to read.

  • source_reader (callable or None, optional) – Optional read backend with the standard SourceReader signature. None uses catalog.source_reader when present, otherwise the FileReader-backed regular BP backend.

  • missing ({"raise", "skip", "zero"} or MissingStepPolicy, optional) – Missing-variable or missing-step policy. "zero" is treated like "skip" here because static readers do not have enough context to synthesize product-specific zero values.

  • logical_step (int, optional) – Logical step used for static products. Directory-backed static products normally expose logical step 0.

Returns:

Values keyed by variable name. Missing values are omitted when missing is "skip" or "zero".

Return type:

dict[str, object]

Raises:

KeyError – If the product or a required variable/step is unavailable.

xgc_analysis.catalog.static_product_reader.static_product_source_path(catalog, product_key: str) Path[source]

Return the selected path for a static catalog product.

Parameters:
  • catalog (xgc_analysis.catalog.SimulationCatalog) – Catalog containing product_key.

  • product_key (str) – Static product key to resolve.

Returns:

Path for the newest source advertised by the product.

Return type:

pathlib.Path

Notes

This is a compatibility helper for code paths that still require a local BP path, such as lazy sparse-matrix wrappers. New readers should prefer read_static_variables() so the same code can later use a campaign-backed SourceReader.

xgc_analysis.catalog.types module

Data structures for XGC dataset discovery and read planning.

class xgc_analysis.catalog.types.CatalogArrayRead(arrays: Dict[str, Dict[int, object]], records: List[object], missing_steps_by_variable: Dict[str, List[int]])[source]

Bases: object

Plain-array result returned by catalog raw-array reads.

arrays

Variable-first mapping keyed by logical step. Values are plain arrays or scalar array values, not product-specific wrapper objects.

Type:

dict[str, dict[int, object]]

records

Raw read-plan records with source id, source path, ADIOS step, and logical step provenance.

Type:

list

missing_steps_by_variable

Missing logical steps reported by read planning for each variable.

Type:

dict[str, list[int]]

arrays: Dict[str, Dict[int, object]]
missing_steps_by_variable: Dict[str, List[int]]
records: List[object]
class xgc_analysis.catalog.types.DataProduct(key: str, label: str, product_type: ~xgc_analysis.catalog.types.ProductType, layout: ~xgc_analysis.catalog.types.ProductLayout, sources: ~typing.List[~xgc_analysis.catalog.types.SourceInfo] = <factory>, variables: ~typing.Dict[str, ~xgc_analysis.catalog.types.VariableInfo] = <factory>, product_family: str = '')[source]

Bases: object

Catalog entry for one logical XGC product.

A product groups one or more physical sources behind the name a reader or GUI should use, for example xgc.3d.bp for the sequence xgc.3d.XXXXX.bp.

key

Catalog key used in queries and read planning.

Type:

str

label

Human-readable label, initially equal to key.

Type:

str

product_type

Reader-level product category.

Type:

ProductType

layout

Physical source/step layout.

Type:

ProductLayout

sources

Sources contributing to this product.

Type:

list[SourceInfo]

variables

Merged variable metadata, with newer sources taking precedence.

Type:

dict[str, VariableInfo]

product_family

Coarse grouping such as mesh, field, or diagnostic.

Type:

str

key: str
label: str
layout: ProductLayout
product_family: str = ''
product_type: ProductType
sources: List[SourceInfo]
variables: Dict[str, VariableInfo]
class xgc_analysis.catalog.types.MissingStepPolicy(value)[source]

Bases: str, Enum

Policy used when a requested logical step is unavailable.

RAISE reports missing steps as errors during read planning. SKIP omits unavailable logical steps from the returned fragments. ZERO records the missing steps so callers can insert zero-filled values using variable-specific shape and dtype information.

RAISE = 'raise'
SKIP = 'skip'
ZERO = 'zero'
class xgc_analysis.catalog.types.ProductLayout(value)[source]

Bases: str, Enum

Physical layout used by one product.

A layout describes how logical steps map onto ADIOS-readable sources. It is informational metadata for read planning; readers should use ReadPlan fragments rather than branching directly on this enum.

FILE_SEQUENCE = 'file_sequence'
INTERNAL_STEPS = 'internal_steps'
MIXED = 'mixed'
STATIC = 'static'
class xgc_analysis.catalog.types.ProductType(value)[source]

Bases: str, Enum

Known XGC data product categories.

Product types describe the reader-level role of a discovered product, not an external schema conversion. Most entries correspond to an existing XGC-Analysis reader or to a static support bundle used by those readers.

ANALYSIS = 'analysis'
DIFFUSION_COEFFICIENTS = 'diffusion_coefficients'
DIFFUSION_PROFILES = 'diffusion_profiles'
DISTRIBUTION_FUNCTION = 'distribution_function'
EQUILIBRIUM = 'equilibrium'
FIELD_2D = 'field_2d'
FIELD_3D = 'field_3d'
FMOMENT_2D = 'fmoment_2d'
FMOMENT_3D = 'fmoment_3d'
FSOURCE_DIAG = 'fsource_diag'
HEAT_DIAG = 'heat_diag'
MAGNETIC_FIELD = 'magnetic_field'
MESH_GEOMETRY = 'mesh_geometry'
NEUTRAL_DIAG = 'neutral_diag'
ONE_D_DIAG = 'one_d_diag'
SHEATH_DIAG = 'sheath_diag'
UNKNOWN = 'unknown'
class xgc_analysis.catalog.types.ReadFragment(source_id: str, source_path: Path, variable: str, logical_steps: List[int], adios_steps: List[int], file_index: int | None = None)[source]

Bases: object

Read request against one ADIOS-readable source.

logical_steps and adios_steps are parallel lists. The caller opens source_path once and reads variable at the listed ADIOS step ids, then maps those values back to the corresponding logical step ids.

file_index

Filename-derived source index when available. This is carried through execution so converted readers can preserve legacy step_index_info metadata while also recording logical XGC steps.

Type:

int or None

adios_steps: List[int]
file_index: int | None = None
logical_steps: List[int]
source_id: str
source_path: Path
variable: str
class xgc_analysis.catalog.types.ReadPlan(product_key: str, variable: str, requested_steps: ~typing.List[int], fragments: ~typing.List[~xgc_analysis.catalog.types.ReadFragment] = <factory>, missing_steps: ~typing.List[int] = <factory>, missing_policy: ~xgc_analysis.catalog.types.MissingStepPolicy = MissingStepPolicy.RAISE)[source]

Bases: object

Resolved source fragments needed to satisfy a logical-step request.

A ReadPlan is the interface between catalog discovery and concrete data readers. It hides whether requested logical steps are stored in one append-only BP file, several one-step files, a mixed layout, or eventually an ADIOS-readable campaign source.

fragments: List[ReadFragment]
missing_policy: MissingStepPolicy = 'raise'
missing_steps: List[int]
product_key: str
requested_steps: List[int]
variable: str
class xgc_analysis.catalog.types.SourceInfo(source_id: str, path: ~pathlib.Path, file_index: int | None = None, mtime: float = 0.0, variables: ~typing.Dict[str, ~xgc_analysis.catalog.types.VariableInfo] = <factory>, step_values: ~typing.List[int] = <factory>, time_values: ~typing.List[float] = <factory>, adios_step_count: int = 0)[source]

Bases: object

One physical ADIOS-readable source for a product.

A source is usually one *.bp directory/file, but campaign backends may also use an ADIOS-readable campaign selector. Source metadata is kept separate from product metadata so multiple sources can contribute to one logical product.

source_id

Stable catalog-local identifier, currently the filename for directory sources.

Type:

str

path

Filesystem path to the ADIOS-readable source.

Type:

pathlib.Path

file_index

Index parsed from names such as xgc.3d.00010.bp.

Type:

int or None

mtime

Source modification time used by the newer-source deduplication policy.

Type:

float

variables

Variables advertised by this source.

Type:

dict[str, VariableInfo]

step_values

Logical step values read from gstep, step, or timestep variables.

Type:

list[int]

time_values

Optional time coordinate values read from a time variable.

Type:

list[float]

adios_step_count

Number of ADIOS steps observed or inferred for this source.

Type:

int

adios_step_count: int = 0
file_index: int | None = None
mtime: float = 0.0
path: Path
source_id: str
step_values: List[int]
time_values: List[float]
variables: Dict[str, VariableInfo]
class xgc_analysis.catalog.types.StepFragment(source_id: str, source_path: Path, logical_step: int, adios_step: int, file_index: int | None = None, time: float | None = None, selected: bool = True)[source]

Bases: object

A candidate source fragment for one logical step.

Multiple fragments can represent the same logical step when outputs are duplicated or regenerated. SimulationCatalog.available_steps marks the selected fragment according to its deduplication policy.

adios_step: int
file_index: int | None = None
logical_step: int
selected: bool = True
source_id: str
source_path: Path
time: float | None = None
class xgc_analysis.catalog.types.StepInfo(logical_step: int, selected_fragment: ~xgc_analysis.catalog.types.StepFragment, duplicate_fragments: ~typing.List[~xgc_analysis.catalog.types.StepFragment] = <factory>, dedup_policy: str = 'newer_source_wins')[source]

Bases: object

Selected and duplicate fragments for one logical step.

logical_step

XGC/user-facing step value.

Type:

int

selected_fragment

Fragment chosen by the catalog deduplication policy.

Type:

StepFragment

duplicate_fragments

Other fragments that advertise the same logical step.

Type:

list[StepFragment]

dedup_policy

Name of the policy used to select the fragment.

Type:

str

dedup_policy: str = 'newer_source_wins'
duplicate_fragments: List[StepFragment]
logical_step: int
selected_fragment: StepFragment
class xgc_analysis.catalog.types.VariableInfo(name: str, dtype: str = '', shape: str = '', shape_dims: ~typing.List[int] = <factory>, is_scalar: bool = False, step_count: int = 0, metadata: ~xgc_analysis.catalog.types.VariableMetadata = <factory>)[source]

Bases: object

ADIOS-native and optional XGC semantic metadata for one variable.

name

Native ADIOS/XGC variable name.

Type:

str

dtype

ADIOS type string when available.

Type:

str

shape

Raw ADIOS shape string, including stepped forms such as 10*{150}.

Type:

str

shape_dims

Parsed payload dimensions excluding the leading ADIOS step count.

Type:

list[int]

is_scalar

True when metadata indicates a scalar payload.

Type:

bool

step_count

Number of ADIOS steps inferred from the variable shape, if present.

Type:

int

metadata

Optional semantic metadata from ADIOS attributes.

Type:

VariableMetadata

dtype: str = ''
is_scalar: bool = False
metadata: VariableMetadata
name: str
shape: str = ''
shape_dims: List[int]
step_count: int = 0
class xgc_analysis.catalog.types.VariableMetadata(description: str = '', units: str = '', axes: ~typing.List[str] = <factory>, mesh_context: str = '', coordinate_context: str = '', species_context: str = '', time_context: str = '', centering: str = '', normalization: str = '')[source]

Bases: object

Optional semantic metadata attached to a variable.

These fields mirror the metadata conventions used by the XGC output I/O wrapper. Older outputs may leave most fields empty; callers should treat the metadata as advisory and sparse.

description

Human-readable meaning of the variable.

Type:

str

units

Physical units, or a controlled string such as dimensionless.

Type:

str

axes

Optional semantic axis labels such as mesh_node or time_sample.

Type:

list[str]

mesh_context, coordinate_context, species_context, time_context

Optional context strings describing how to interpret the variable.

Type:

str

centering

Optional placement/centering hint.

Type:

str

normalization

Optional normalization convention when units are not sufficient.

Type:

str

axes: List[str]
centering: str = ''
coordinate_context: str = ''
description: str = ''
mesh_context: str = ''
normalization: str = ''
species_context: str = ''
time_context: str = ''
units: str = ''

xgc_analysis.constants module

Physical constants and CGS-to-SI conversion factors for plasma physics.

Values based on the 2019 NRL Plasma Formulary.

All constants are in SI units unless otherwise noted.

xgc_analysis.csr_matrix module

class xgc_analysis.csr_matrix.SparseMatrixCSR(reader_function)[source]

Bases: object

A class for storing a sparse matrix in CSR format (using SciPy’s csr_matrix).

The constructor takes a reader function as input. This reader function should return the matrix data as:

(ncols, nrows, nelement, width, col_indices, values)

where:
  • ncols (int): Number of columns.

  • nrows (int): Number of rows.

  • nelement (np.ndarray): A 1D array (length nrows) with the number of nonzeros in each row.

  • width (int): The maximal number of nonzeros in any row.

  • col_indices (np.ndarray): A 2D array (nrows x width) with 0-based column indices.

  • values (np.ndarray): A 2D array (nrows x width) with the nonzero values.

The constructor reformats this data and stores the matrix in SciPy’s CSR format.

get_csr_matrix()[source]
Returns:

csr_matrix: The sparse matrix in CSR format.

multiply_left(vector)[source]

Multiplies the CSR matrix from the left by a 1D NumPy array (i.e. computes vector * A).

Args:

vector (np.ndarray): 1D array with length equal to the number of rows of the matrix.

Returns:

np.ndarray: 1D array of length equal to the number of columns of the matrix.

Raises:

ValueError: if the length of vector does not match the number of rows.

multiply_transpose_left(vector)[source]

Multiplies the transpose of the CSR matrix from the left by a 1D NumPy array (i.e. computes vector * A^T).

Args:

vector (np.ndarray): 1D array with length equal to the number of columns of the matrix.

Returns:

np.ndarray: 1D array of length equal to the number of rows of the matrix.

Raises:

ValueError: if the length of vector does not match the number of columns.

xgc_analysis.csr_matrix.sparse_matrix_reader(filename, var_names)[source]

Read the sparse‑matrix variables stored in an ADIOS2 BP directory.

Parameters:
  • filename (str) – Path to the *.bp directory.

  • var_names (list[str]) –

    The six variable names in this exact order:

    • ncols_name – number of columns

    • nrows_name – number of rows

    • width_name – max. non‑zeros per row

    • nelement_name – 1‑D array of non‑zeros per row

    • col_indices_name – 2‑D array of 1‑based column indices

    • values_name – 2‑D array of non‑zero values

Returns:

(ncols, nrows, nelement, width, col_indices, values), where col_indices has been converted to 0‑based indices.

Return type:

tuple

xgc_analysis.distribution_function_data module

class xgc_analysis.distribution_function_data.DistributionFunctionData(mesh=None, work_dir='.', file_indices=None, *, simulation=None, velocity_grid=None, f0_mesh_filename='xgc.f0.mesh.bp', ignored_vars=None, variables=None, catalog=None, steps=None, read_all_steps=False, source_reader=None, missing='raise')[source]

Bases: BPReaderMixin, ArrayAccessorMixin

Reader for XGC xgc.f0.XXXXX.bp distribution-function files.

Data layout matches other XGC-Analysis readers:

self.data[var_name][file_step_index] = object

where object is usually:
  • DistributionFunctionField for species *_f arrays

  • PlaneData / MeshData for configuration-space arrays

  • scalar / np.ndarray for metadata

DEFAULT_IGNORED_VARS = {'eden_f0', 'iden_f0_approx', 'imu1m1', 'inode1m1', 'iphi', 'mudata', 'ndata', 'nmup1', 'nnode', 'nphi', 'vpdata'}
distribution_variables()[source]

Return sorted variable names that store distribution-function data.

get_distribution(var_name, step_index=0)[source]

Return var_name at step_index as DistributionFunctionField.

get_mesh_data(var_name, step_index=0)[source]

Return var_name at step_index as MeshData.

get_plane_data(var_name, step_index=0)[source]

Return var_name at step_index as PlaneData.

get_scalar(var_name, step_index=0)[source]

Return var_name at step_index as a scalar numeric value.

class xgc_analysis.distribution_function_data.DistributionFunctionField(mesh, velocity_grid, data_array, *, name=None)[source]

Bases: object

Wrapper for one XGC distribution-function variable on a mesh and velocity grid.

Python-facing storage order:
  • canonical: (phi, node, vpar, vperp)

Axisymmetric files that omit the toroidal dimension are normalized to phi=1 on read, so self.data is always 4D.

compute_f0_moments(inputs, *, calculator=None)[source]

Compute electrostatic f0 moments using distribution_moments.F0MomentCalculator.

Parameters:
  • inputs (F0MomentInputs) – Geometry/field inputs for the requested moments.

  • calculator (F0MomentCalculator or None, optional) – Reuse an existing calculator instance. If omitted, a new one is created from this field’s velocity_grid.

get_data()[source]

Return the underlying NumPy array in XGC storage order.

property is_axisymmetric_storage

Return True when the array is stored with a single toroidal plane.

node_slice(inode, *, iphi=0)[source]

Return a view with shape (vpar, vperp) for one configuration-space node.

property nphi

Return the stored toroidal dimension length.

plane_slice(iphi=0)[source]

Return a view with shape (node, vpar, vperp).

velocity_integral(*, data_includes_vperp=True, include_gyroangle=True)[source]

Integrate over velocity space and return config-space data.

Returns:

Axisymmetric: shape (n_node,) 3D: shape (nphi, n_node)

Return type:

np.ndarray

velocity_integral_data(*, data_includes_vperp=True, include_gyroangle=True)[source]

Velocity-integrated result packaged as PlaneData or MeshData.

This is intentionally a thin wrapper around velocity_integral().

xgc_analysis.distribution_moments module

class xgc_analysis.distribution_moments.F0MomentCalculator(velocity_grid)[source]

Bases: object

Electrostatic f0 moment calculator (first-pass Python port of f0_sum.F90).

Notes

  • Assumes distribution data are stored in canonical order (phi, node, vpar, vperp).

  • Adiabatic/non-adiabatic split follows the XGC diagnostics strategy: compute local density/temperature from f, apply mesh-level flux_avg_to_from_surf to obtain background fields, build adiabatic Maxwellian + Boltzmann response, then split moments.

  • For non-axisymmetric simulations, an additional branch decomposition is available: n0 (toroidally averaged) and turb (deviation from n0). This is controlled by F0MomentInputs.split_n0_turb.

compute(distribution_field, inputs: F0MomentInputs) F0MomentResult[source]

Compute a first set of electrostatic f0 moments (f0_sum-style split).

Implemented moments (semantic names)

  • density

  • mean parallel flow

  • parallel energy flux (new; linear moment)

  • radial particle flux split into drift, exb, optional delta_b

  • radial energy flux split into drift, exb, optional delta_b

returns:

result.n0 always populated. result.turb populated only when inputs.split_n0_turb is true and the input distribution has more than one toroidal plane.

rtype:

F0MomentResult

Notes

  • Basic moments (density, flow, temperatures) are reported as branch totals (n0 and optional turb), not adiabatic/non-adiabatic sub-splits.

  • Flux-like moments retain adiabatic/non-adiabatic decomposition.

class xgc_analysis.distribution_moments.F0MomentComponent(density: ndarray, mean_parallel_flow: ndarray, parallel_temperature: ndarray, perpendicular_temperature: ndarray, parallel_energy_flux: SplitMoment, radial_particle_flux: FluxSplit, radial_energy_flux: FluxSplit)[source]

Bases: object

Moment set for one component branch (n0 or turb).

Notes

Basic moments (density, flow, temperatures) are stored as plain arrays for this branch and are not split into adiabatic/non-adiabatic parts. Flux-like moments keep the adiabatic/non-adiabatic split.

density: ndarray
mean_parallel_flow: ndarray
parallel_energy_flux: SplitMoment
parallel_temperature: ndarray
perpendicular_temperature: ndarray
radial_energy_flux: FluxSplit
radial_particle_flux: FluxSplit
class xgc_analysis.distribution_moments.F0MomentInputs(mass_kg: float, charge_C: float, temp_node_ev: np.ndarray, den_node_m3: np.ndarray, bfield: np.ndarray, epsi: np.ndarray, etheta: np.ndarray, gradpsi: np.ndarray, nb_curl_nb: np.ndarray, v_gradb: np.ndarray, v_curv: np.ndarray, dpot: np.ndarray | None = None, flux_surface_avg_project: callable | None = None, f_3d_re: np.ndarray | None = None, f_3d_im: np.ndarray | None = None, dbre: np.ndarray | None = None, dbim: np.ndarray | None = None, species_index: int | None = None, split_n0_turb: bool = False, sim_is_axisymmetric: bool | None = None)[source]

Bases: object

Geometry / field inputs required by electrostatic f0 moments (f0_sum-style).

Arrays are expected in axisymmetric-compatible shapes:
  • node arrays: (n_node,) or (1, n_node)

  • vector arrays: (n_node, n_comp) or (1, n_node, n_comp)

Parameters:
  • mass_kg (float) – Species mass and charge.

  • charge_C (float) – Species mass and charge.

  • temp_node_ev (ndarray) – Reference local temperature used for velocity normalization (temp_node in the legacy/C++ diagnostics path, typically f0_fg_T_ev for the species).

  • den_node_m3 (ndarray) – Reference local density (f0_den for the species).

  • bfield (ndarray) – Magnetic field components in cylindrical ordering (R, Z, phi).

  • epsi (ndarray) – Electric-field components used by the electrostatic ExB velocity terms.

  • etheta (ndarray) – Electric-field components used by the electrostatic ExB velocity terms.

  • gradpsi (ndarray) – Gradient of poloidal flux with shape (..., 2) (R,Z components).

  • nb_curl_nb (ndarray) – Scalar b x curl(b) factor used in the denominator D.

  • v_gradb (ndarray) – Drift vectors with the legacy XGC ordering; component 0 is the radial-like (flux) component, component 1 is Z, component 2 is toroidal.

  • v_curv (ndarray) – Drift vectors with the legacy XGC ordering; component 0 is the radial-like (flux) component, component 1 is Z, component 2 is toroidal.

  • dpot (ndarray | None) – Electrostatic potential perturbation (V) for the Boltzmann term.

  • flux_surface_avg_project (callable | None) – Optional callback mapping a node-array to its flux-surface-averaged projection back on the nodes (Fortran mat_transpose_mult + interpolation path analogue). Signature: arr_node -> arr_node.

  • f_3d_re (ndarray | None) – Optional real/imaginary non-axisymmetric distribution components for delta-B radial flux moments. Same shape as the primary distribution.

  • f_3d_im (ndarray | None) – Optional real/imaginary non-axisymmetric distribution components for delta-B radial flux moments. Same shape as the primary distribution.

  • dbre (ndarray | None) – Optional real/imaginary magnetic perturbation vectors (R,Z,phi comps).

  • dbim (ndarray | None) – Optional real/imaginary magnetic perturbation vectors (R,Z,phi comps).

  • species_index (int | None) – Species index used for species-dependent velocity-volume normalization (f0_grid_vol_vonly) when available.

  • split_n0_turb (bool, default False) – Enable decomposition into toroidally averaged (n0) and non-axisymmetric (turb) branches.

  • sim_is_axisymmetric (bool | None) – Simulation-level symmetry flag (distinct from mesh symmetry). Used to choose default branch behavior in from_simulation().

Notes

Moment definitions follow the standard velocity integrals used in XGC analysis: n = f d^3v, u_parallel = (1/n) v_parallel f d^3v, T_parallel = (m/en) (v_parallel-u_parallel)^2 f d^3v, T_perp = (m/2en) v_perp^2 f d^3v.

bfield: np.ndarray
charge_C: float
dbim: np.ndarray | None = None
dbre: np.ndarray | None = None
den_node_m3: np.ndarray
dpot: np.ndarray | None = None
epsi: np.ndarray
etheta: np.ndarray
f_3d_im: np.ndarray | None = None
f_3d_re: np.ndarray | None = None
flux_surface_avg_project: callable | None = None
classmethod from_simulation(*, simulation, species_index: int, epsi, etheta, dpot=None, flux_surface_avg_geometry=None, f_3d_re=None, f_3d_im=None, dbre=None, dbim=None, bfield=None, gradpsi=None, nb_curl_nb=None, v_gradb=None, v_curv=None, temp_node_ev=None, den_node_m3=None, split_n0_turb=None, sim_is_axisymmetric=None)[source]

Convenience constructor using Simulation and VelocityGrid metadata.

This helper auto-populates most inputs needed by the f0-moment calculator: species mass/charge from simulation.species[species_index], local reference profiles from simulation.velocity_grid, and the equilibrium magnetic field from simulation.magnetic_field.

epsi and etheta are still required explicit inputs because they are time-dependent field quantities.

Parameters:
  • simulation (Simulation) – XGC-Analysis simulation object with species, velocity_grid, mesh, and magnetic_field attributes.

  • species_index (int) – Index into simulation.species and species-indexed arrays in simulation.velocity_grid.

  • flux_surface_avg_geometry (Mesh | None, optional) – Mesh object providing flux_avg_to_from_surf. If omitted, simulation.mesh is used.

  • split_n0_turb (bool | None, optional) – If None, defaults to not simulation.sim_is_axisymmetric.

  • sim_is_axisymmetric (bool | None, optional) – Explicit simulation-level symmetry override. This is intentionally separate from mesh.is_axisymmetric because tokamak turbulence runs can have an axisymmetric mesh but non-axisymmetric dynamics.

  • *overrides* – Any of bfield, gradpsi, nb_curl_nb, v_gradb, v_curv, temp_node_ev, or den_node_m3 may be supplied to override values taken from simulation.

classmethod from_species(*, species, species_index=None, temp_node_ev, den_node_m3, bfield, epsi, etheta, gradpsi, nb_curl_nb, v_gradb, v_curv, dpot=None, flux_surface_avg_project=None, f_3d_re=None, f_3d_im=None, dbre=None, dbim=None, split_n0_turb=False, sim_is_axisymmetric=None)[source]
gradpsi: np.ndarray
static make_flux_surface_avg_projector(geometry)[source]

Build a flux_surface_avg_project callback from a Mesh.

The returned callable performs the same conceptual operation as the legacy mat_transpose_mult + interpolation path in f0_sum.F90: flux-surface average followed by projection back to nodal values.

For non-axisymmetric meshes, the mesh-level implementation performs per-plane FSA, toroidal averaging, and nodal back-projection. This is the required path for 3D XGC diagnostics and keeps axisymmetric/3D behavior unified.

Supported input shapes to the callback

  • (n_node,) -> (n_node,)

  • (1, n_node) -> (1, n_node)

  • (nphi, n_node) -> (nphi, n_node)

mass_kg: float
nb_curl_nb: np.ndarray
sim_is_axisymmetric: bool | None = None
species_index: int | None = None
split_n0_turb: bool = False
temp_node_ev: np.ndarray
v_curv: np.ndarray
v_gradb: np.ndarray
class xgc_analysis.distribution_moments.F0MomentResult(n0: F0MomentComponent, turb: F0MomentComponent | None = None)[source]

Bases: object

Common output structure for axisymmetric and non-axisymmetric runs.

n0 is always present. turb is present only for non-axisymmetric simulations when split_n0_turb is enabled.

n0: F0MomentComponent
turb: F0MomentComponent | None = None
class xgc_analysis.distribution_moments.FluxSplit(drift: SplitMoment, exb: SplitMoment, delta_b: SplitMoment | None = None)[source]

Bases: object

Flux moment split by physical mechanism.

delta_b: SplitMoment | None = None
drift: SplitMoment
exb: SplitMoment
class xgc_analysis.distribution_moments.SplitMoment(adiabatic: ndarray | None = None, nonadiabatic: ndarray | None = None)[source]

Bases: object

Linear moment split into adiabatic / non-adiabatic pieces.

adiabatic: ndarray | None = None
nonadiabatic: ndarray | None = None
property total
xgc_analysis.distribution_moments.compare_f0_moments_to_fmoment(result: F0MomentResult, fmoment_data, *, species_prefix: str, step_index: int = 0, atol: float = 0.0, rtol: float = 0.001, rel_floor_frac: float = 0.001)[source]

Compare selected computed moments against FMomentData reference arrays.

Parameters:
  • result (F0MomentResult) – Output from F0MomentCalculator.compute().

  • fmoment_data (FMomentData) – Reader containing XGC-written moment diagnostics.

  • species_prefix ({"e", "i", "i2", ...}) – Species prefix used by the distribution variable. This helper currently supports the primary XGC fmoment prefixes e and i.

  • step_index (int, default 0) – Index into the FMomentData nested-dict storage.

  • atol (float) – Absolute/relative tolerances for np.allclose checks.

  • rtol (float) – Absolute/relative tolerances for np.allclose checks.

  • rel_floor_frac (float, default 1e-3) – Relative-denominator floor as a fraction of a robust reference scale (95th percentile of abs(ref)). This prevents near-zero reference values from producing uninformative, arbitrarily large relative errors.

Returns:

Per-moment comparison summary containing ok, max_abs, and max_rel.

Return type:

dict[str, dict]

Notes

This helper is intentionally simple and targets quick validation. It checks the moments most likely to be present in xgc.fmoment diagnostics. The comparison currently targets the n0 branch of F0MomentResult.

xgc_analysis.diffusion_data module

Read-only readers for XGC diffusion workflow BP products.

These readers intentionally do not inherit from BPReaderMixin for now. Diffusion products have product-specific indexing rules: coefficient files use species-suffixed variables that may eventually need a project-wide species handling policy, and profile files contain multiple XGC sample steps inside one ADIOS step. Keeping the BP handling explicit here avoids baking those rules into the generic BP-reader mixin before the broader reader/catalog interface is settled.

class xgc_analysis.diffusion_data.DiffusionCoefficientData(data_dir: str = './', filename: str = 'xgc.diffusion_coeff.bp', read_all_steps: bool = True)[source]

Bases: ArrayAccessorMixin

Read xgc.diffusion_coeff.bp as an analysis data product.

This class is intentionally read-only and independent of the existing workflow-oriented DiffusionCoefficients class, which opens an append stream for live coefficient updates. Each ADIOS step is stored as one reader-local step_index. Species-suffixed coefficient variables are stacked into arrays with shape (n_species, npsi) and exposed under the base coefficient names:

  • ptl_diffusivity

  • momentum_diffusivity

  • heat_conductivity

  • ptl_pinch_velocity

Metadata variables such as psi, n_species, and gstep are stored in the same self.data[var_name][step_index] layout.

COEFFICIENT_NAMES = ('ptl_diffusivity', 'momentum_diffusivity', 'heat_conductivity', 'ptl_pinch_velocity')
SPECIES_SUFFIXES = ('_elec', '_ion', '_imp1', '_imp2', '_imp3', '_imp4', '_imp5')
get_coefficient(name: str, step_index: int = 0) ndarray[source]

Return one aggregated coefficient array with shape (n_species, npsi).

get_scalar(name: str, step_index: int = 0)[source]

Return one scalar metadata value such as n_species or gstep.

get_step_info(step_index: int) Dict[str, object][source]

Return ADIOS-step metadata for one reader-local step index.

class xgc_analysis.diffusion_data.DiffusionProfileData(data_dir: str = './', filename: str = 'xgc.diffusion_profiles.bp', read_all_steps: bool = True)[source]

Bases: ArrayAccessorMixin

Read xgc.diffusion_profiles.bp as buffered profile snapshots.

Each ADIOS step contains multiple XGC simulation samples. The profile variables density, flow, and temp therefore have shape (n_species, n_samples, n_surf) for each ADIOS step. This reader keeps that native layout in self.data[var_name][step_index] and provides helpers to address an inner sample by sample_index or by the XGC sample step stored in the steps variable.

PROFILE_VARIABLES = ('density', 'flow', 'temp')
SAMPLE_STEP_NAMES = ('steps', 'sample_steps', 'gsteps')
available_samples() List[Dict[str, object]][source]

Return all buffered sample coordinates in ADIOS-step order.

Returns:

Each entry contains step_index, sample_index, gstep and time. gstep or time may be None when absent from the file.

Return type:

list[dict]

get_profile(var_name: str, step_index: int = 0, *, sample_index: int | None = None, gstep: int | None = None) ndarray[source]

Return a diffusion profile variable or one buffered sample.

Parameters:
  • var_name (str) – Profile variable name, usually density, flow, or temp.

  • step_index (int, optional) – Reader-local ADIOS step index used when gstep is not provided.

  • sample_index (int or None, optional) – Buffered sample index inside the ADIOS step. If omitted, the full native array with shape (n_species, n_samples, n_surf) is returned.

  • gstep (int or None, optional) – XGC sample step to select from the buffered steps array. When provided, it overrides step_index and sample_index.

Returns:

Full native profile array or one sample with shape (n_species, n_surf).

Return type:

np.ndarray

get_step_info(step_index: int) Dict[str, object][source]

Return ADIOS-step and buffered-sample metadata for one step index.

xgc_analysis.divertor_eich module

Divertor heatdiag profile mapping and Eich-width fitting helpers.

This module converts XGC wall heat diagnostic data from xgc.heatdiag2.bp into upstream/midplane flux-density profiles suitable for Eich heat-load-width fits. The main entry point is compute_divertor_eich_profiles(), which can be called by scripts, notebooks, or thin GUI plugins.

The workflow implemented here is:

  1. Create or reuse a Simulation and its Plane mesh.

  2. Read heatdiag particle and energy totals through HeatDiag.

  3. Average one selected ADIOS frame, or a requested time window, to rates.

  4. Split lower divertor wall points into inner and outer target branches using the private-region poloidal-flux minimum.

  5. Map target-wall psi_N values to inner/outer midplane radius maps built from exact Plane flux-surface crossings with Z=0. The plotted Delta_sep coordinate is therefore a midplane radial distance, not distance along the target.

  6. Estimate a uniform Delta_sep grid spacing from the heatdiag psi_N resolution mapped through the flux-surface midplane map, and remap particle and energy loads with a locally conservative interval-overlap method.

  7. Optionally smooth the remapped loads with total-load renormalization, convert loads to toroidal-surface flux densities, and fit the total particle and energy channels with the Eich functional form.

The helper is deliberately conservative about units and transformations: heatdiag inputs are particle counts and energy in joules accumulated over diagnostic intervals, rates are produced by dividing by interval duration, and energy flux densities are displayed in MW m^-2 only in the plotting layer.

class xgc_analysis.divertor_eich.DivertorEichProfile(label: str, x_mm: ndarray, particle_i: ndarray, particle_e: ndarray, energy_i: ndarray, energy_e: ndarray, fit_particle: tuple[ndarray, ndarray] | None, fit_energy: tuple[ndarray, ndarray] | None)[source]

Bases: object

Mapped profile and optional Eich fits for one divertor target.

The profile stores a human-readable target label, a mapped Delta_sep grid x_mm in millimeters, ion/electron particle and energy flux-density arrays, and optional Eich fit results. Fit tuples contain the fitted parameter vector (q0, q_bg, lambda_q, S, s0) in SI units and a two-column (x_mm, fitted_y) array for plotting.

energy_e: ndarray
energy_i: ndarray
fit_energy: tuple[ndarray, ndarray] | None
fit_particle: tuple[ndarray, ndarray] | None
label: str
particle_e: ndarray
particle_i: ndarray
x_mm: ndarray
xgc_analysis.divertor_eich.compute_divertor_eich_profiles(data_dir: str | Path, *, simulation: Any | None = None, include_sheath: bool = False, time_window: tuple[float, float] | None = None, selected_frame_index: int | None = None, psi_window: tuple[float, float] = (0.97, 1.12), fit_window_mm: tuple[float, float] = (-2.0, 20.0), smoothing_sigma_mm: float = 0.0, show_outer: bool = True, show_inner: bool = True) list[DivertorEichProfile][source]

Compute toroidally averaged divertor particle/energy flux-density profiles.

Parameters:
  • data_dir (str | Path) – XGC output directory containing xgc.heatdiag2.bp and the mesh files.

  • simulation (Simulation | None) – Optional pre-built Simulation. If omitted, a Simulation is created from data_dir.

  • include_sheath (bool) – Include [i,e]_potential in the energy channel if available.

  • time_window (tuple[float, float] | None) – Optional heatdiag interval averaging window in seconds. If set, this takes precedence over selected_frame_index.

  • selected_frame_index (int | None) – Optional GUI-selected heatdiag frame. When time_window is omitted, the selected sample is converted to the diagnostic interval ending at that frame.

  • psi_window (tuple[float, float]) – Normalized-poloidal-flux range used to select divertor wall points.

  • fit_window_mm (tuple[float, float]) – Delta_sep window used for the Eich fit.

  • smoothing_sigma_mm (float) – Gaussian smoothing sigma, in millimeters, applied to the displayed particle/energy component profiles before fitting.

  • show_outer (bool) – Select which target profiles to compute.

  • show_inner (bool) – Select which target profiles to compute.

Returns:

One profile for each requested target.

Return type:

list[DivertorEichProfile]

xgc_analysis.divertor_eich.eich_model(x_m: ndarray, q0: float, q_bg: float, lambda_q: float, s: float, s0: float) ndarray[source]

Eich profile model from Eich et al. NF 53, 093031, Eq. 1 without f_x.

The omitted target flux-expansion factor is appropriate when x_m is the already mapped upstream/midplane radius coordinate.

Parameters are in SI units: x_m, lambda_q, S and s0 are meters, while q0 and q_bg have the same units as the profile being fitted.

xgc_analysis.divertor_eich.fit_eich_profile(x_m: ndarray, y: ndarray, fit_window_mm, smoothing_sigma_mm: float = 0.0) tuple[ndarray, ndarray] | None[source]

Fit y(x_m) with eich_model() and return parameters plus curve.

The fit uses positive finite points, optionally restricted to fit_window_mm. The fitted lambda_q and S parameters are in meters in the returned parameter vector; plotting text converts them to millimeters.

xgc_analysis.divertor_eich.plot_divertor_eich_profiles(profiles: list[DivertorEichProfile], *, show_particle: bool = True, show_energy: bool = True, show_ions: bool = True, show_electrons: bool = True, show_total: bool = True, xlim: tuple[float, float] | None = None, ylim: tuple[float, float] | None = None)[source]

Plot divertor particle/energy profiles with optional Eich fit overlays.

Parameters:
  • profiles (list[DivertorEichProfile]) – Profiles returned by compute_divertor_eich_profiles().

  • show_particle (bool) – Select which physical channels are shown. At least one must be enabled.

  • show_energy (bool) – Select which physical channels are shown. At least one must be enabled.

  • show_ions (bool) – Select species/component curves. Eich fits are only overlaid for total profiles.

  • show_electrons (bool) – Select species/component curves. Eich fits are only overlaid for total profiles.

  • show_total (bool) – Select species/component curves. Eich fits are only overlaid for total profiles.

  • xlim (tuple[float, float] | None) – Optional display limits. xlim is in millimeters. ylim applies to whichever axes are displayed.

  • ylim (tuple[float, float] | None) – Optional display limits. xlim is in millimeters. ylim applies to whichever axes are displayed.

Returns:

Figure owned by the caller. GUI code can save it to PNG; scripts can display or further customize it.

Return type:

matplotlib.figure.Figure

xgc_analysis.field_data module

class xgc_analysis.field_data.FieldData(mesh, work_dir='./', file_indices=None, is_axisymmetric=False, split_n0_turb=False, variables=None, read_all_steps=False, catalog=None, steps=None, missing='raise', source_reader=None)[source]

Bases: BPReaderMixin, ArrayAccessorMixin

Reader for XGC xgc.2d.XXXXX.bp and xgc.3d.XXXXX.bp field files.

Data are stored in self.data with the structure:

self.data[var_name][step_index] = PlaneData | MeshData | scalar | np.ndarray

step_index is a sequential internal index over loaded (file_index, bp_step) pairs. Use get_step_info(step_index) to recover the source file index and ADIOS step id.

FieldData inherits ArrayAccessorMixin, which provides get_array(var_name) for converting stored values to plain NumPy arrays for plotting and analysis.

export_vtu(mesh)[source]

Export loaded field data to .vtu files for visualization.

Parameters:

mesh (Mesh) – Mesh object providing geometry/connectivity for the exported grid.

Returns:

Writes one .vtu file per loaded internal step to <work_dir>/vtus.

Return type:

None

get_field(var_name, step_index=0)[source]

Return the raw stored field item for a variable/time selection.

get_mesh_data(var_name, step_index=0)[source]

Return var_name at step_index as MeshData.

get_plane_data(var_name, step_index=0)[source]

Return var_name at step_index as PlaneData.

get_scalar(var_name, step_index=0)[source]

Return var_name at step_index as a scalar numeric value.

xgc_analysis.fieldline_mapping module

xgc_analysis.fieldline_mapping.compute_fieldline_mapping(mesh, magnetic_field, *, rk4_substeps=2, n_int=250, direction='forward')[source]

Build a magnetic‑field‑line mapping between adjacent planes.

Parameters:
  • mesh (Mesh) – Instance of the Mesh defined in mesh.py.

  • magnetic_field (MagneticField) – Instance of MagneticField (see magnetic_field.py).

  • rk4_substeps (int, optional) – Number of RK4 sub‑steps per plane‑to‑plane advance (default 2).

  • n_int (int, optional) – Interpolation‑grid resolution used when creating a matplotlib.tri.TriFinder (default 250).

  • direction ({"forward", "backward"}, optional) – Direction of tracing; forward increases φ, backward decreases φ.

Returns:

triangle_index(n_vert, n_steps) int32

Triangle hosting each intersection.

bary_weights(n_vert, n_steps, 3) float64

Barycentric weights inside that triangle.

plane_index(n_steps,) int32

Index of the target plane within mesh.planes.

delta_phifloat

Toroidal separation between neighbouring planes (positive).

directionstr

Copy of the direction argument.

Return type:

dict

xgc_analysis.fieldline_mapping2 module

xgc_analysis.fieldline_mapping2.compute_fieldline_mapping(mesh, magnetic_field, *, tor_turns: float = 1.0, rk4_substeps: int = 2, n_int: int = 250, direction: str = 'forward')[source]

Trace mesh vertices along B and return interpolation meta‑data.

Parameters:
  • tor_turns (float, optional) – How many toroidal turns (2π each) to follow. Fractional values are allowed; the actual number of steps is rounded to the nearest multiple of stored planes so the trace always lands on a plane.

  • direction ({'forward', 'backward'}) – Sign of dφ. forward ⇒ increasing φ, backward ⇒ decreasing.

xgc_analysis.fmoment_data module

class xgc_analysis.fmoment_data.FMomentData(mesh, work_dir='.', file_indices=None, is_axisymmetric=False, split_n0_turb=False, variables=None, read_all_steps=False, catalog=None, steps=None, missing='raise', source_reader=None)[source]

Bases: BPReaderMixin, ArrayAccessorMixin

Reader for XGC f2d / f3d moment diagnostics.

Data are stored in self.data with the common XGC-Analysis layout:

self.data[var_name][step_index] = PlaneData | MeshData | scalar

step_index is a sequential internal index over loaded (file_index, bp_step) pairs. Use get_step_info(step_index) to recover the source file index and ADIOS step id.

FMomentData inherits ArrayAccessorMixin, so get_array(var) is available for converting stored values to plain NumPy arrays.

export_vtu(mesh)[source]

Export loaded FMoment data to VTK-compatible structures.

Parameters:

mesh (Mesh) – Mesh object providing connectivity and coordinates.

Returns:

Creates output directory metadata and prepares VTK structures.

Return type:

None

get_mesh_data(var_name, step_index=0)[source]

Return var_name at step_index as MeshData.

get_moment(var_name, step_index=0)[source]

Return the raw stored moment item for var_name and step_index.

get_plane_data(var_name, step_index=0)[source]

Return var_name at step_index as PlaneData.

get_scalar(var_name, step_index=0)[source]

Return var_name at step_index as a scalar numeric value.

read_from_campaign(mesh)[source]

Reads the campaign file and loads the mesh data.

xgc_analysis.fsource_data module

class xgc_analysis.fsource_data.FsourceData(mesh, work_dir='./', file_indices=None, variables=None, read_all_steps=False, catalog=None, steps=None, missing='raise', source_reader=None)[source]

Bases: BPReaderMixin, ArrayAccessorMixin

Reader for xgc.fsourcediag.XXXXX.bp source diagnostic files.

Data are stored in self.data using the common XGC-Analysis pattern:

self.data[var_name][step_index] = PlaneData | scalar

step_index is a sequential internal index over loaded (file_index, bp_step) pairs. Use get_step_info(step_index) to recover the source file index and ADIOS step id.

Mesh-based variables are wrapped as PlaneData on mesh.get_plane(0). Scalar variables (for example time) are stored as raw NumPy/Python values.

Notes

This diagnostic is currently treated as poloidal-plane data (axisymmetric storage on a single plane). For a 3D version, a MeshData branch can be added following FieldData / FMomentData.

get_plane_data(var_name, step_index=0)[source]

Return var_name at step_index as PlaneData.

get_scalar(var_name, step_index=0)[source]

Return var_name at step_index as a scalar numeric value.

get_source(var_name, step_index=0)[source]

Return the raw stored source-diagnostic item for var_name.

xgc_analysis.heatdiag module

Reader for XGC wall heat/particle impact diagnostics (xgc.heatdiag2.bp).

class xgc_analysis.heatdiag.HeatDiag(simulation=None, data_dir: str = './', filename: str = 'xgc.heatdiag2.bp', step_range: Tuple[int, int] | None = None, variables: Iterable[str] | None = None, catalog=None, steps: Iterable[int] | None = None, missing: str = 'raise', source_reader=None)[source]

Bases: BPReaderMixin, ArrayAccessorMixin

Read wall heat diagnostic data from xgc.heatdiag2.bp.

Time-dependent data are stored in self.data with the structure:

self.data[variable_name][step_idx] = 2D numpy array

where step_idx is the ADIOS step index in the BP file. Variables with an extra “garbage bin” (first segment entry) are split into:

  • <var>: wall-segment data excluding the garbage bin

  • <var>_garbage: garbage-bin values with shape (nphi, 1)

Static wall geometry/metadata are stored in self.wall_data as:

self.wall_data[variable_name] = 2D numpy array

The class can be constructed stand-alone using data_dir or using a Simulation instance (it will use simulation.data_directory by default). A catalog must be supplied directly or through simulation; direct local filename reads are disabled.

DEFAULT_VARS = ('ds', 'e_number', 'e_para_energy', 'e_perp_energy', 'e_potential', 'gstep', 'i_number', 'i_para_energy', 'i_perp_energy', 'i_potential', 'nphi', 'nseg', 'nseg1', 'psi', 'r', 'strike_angle', 'time', 'tindex', 'z')
GARBAGE_BIN_VARS = {'e_number', 'e_para_energy', 'e_perp_energy', 'e_potential', 'i_number', 'i_para_energy', 'i_perp_energy', 'i_potential'}
STATIC_VARS = {'ds', 'nphi', 'nseg', 'nseg1', 'psi', 'r', 'strike_angle', 'z'}
TIME_VARS = {'e_number', 'e_para_energy', 'e_perp_energy', 'e_potential', 'gstep', 'i_number', 'i_para_energy', 'i_perp_energy', 'i_potential', 'time', 'tindex'}
get_heat_array(var_name: str, step_index: int)[source]

Return time-dependent heatdiag variable var_name as np.ndarray.

get_scalar(var_name: str, step_index: int)[source]

Return var_name at step_index as a scalar numeric value.

get_time_mask() ndarray[source]

Return indices that sort and de-duplicate the diagnostic history.

This mirrors OneDDiag.get_time_mask() and is useful when heatdiag output contains overlapping time ranges. The returned indices apply to arrays returned by get_array(...) (stacked over available_steps).

get_wall_array(var_name: str) ndarray[source]

Return a static wall variable from self.wall_data.

get_wall_curve(*, phi_index: int = 0, verify_clockwise: bool = True, auto_reverse: bool = False, set_inboard_origin: bool = False, r_axis: float | None = None)[source]

Build a WallCurve from the HeatDiag wall polygon.

Parameters:
  • phi_index (int) – Toroidal index for selecting one wall polygon from heatdiag arrays.

  • verify_clockwise (bool) – Validate clockwise ordering of wall points.

  • auto_reverse (bool) – Reverse point order automatically if not clockwise.

  • set_inboard_origin (bool) – If True, set arclength origin at Z=0 with R<R_axis.

  • r_axis (float | None) – Magnetic-axis R used when set_inboard_origin=True. If omitted, use simulation.mesh.get_plane(0).axis_r when available.

xgc_analysis.loop_voltage_data module

Reader for XGC loop-voltage source output (xgc.loop_vol.bp).

class xgc_analysis.loop_voltage_data.LoopVoltageData(mesh, data_dir: str = './', filename: str = 'xgc.loop_vol.bp', variables: Iterable[str] | str | None = None, read_all_steps: bool = True, catalog=None, steps: Iterable[int] | None = None, missing: str = 'raise', source_reader=None)[source]

Bases: BPReaderMixin, ArrayAccessorMixin

Read axisymmetric loop-voltage source fields from xgc.loop_vol.bp.

xgc.loop_vol.bp is a single BP product with ADIOS steps. Its main payload variables are node-centered 2D fields on the poloidal mesh, so this reader wraps one-dimensional node arrays as PlaneData using mesh.get_plane(0). Scalar time-coordinate variables such as time, gstep, tindex, and legacy step are stored directly.

Data are stored with the common XGC-Analysis layout:

self.data[var_name][step_index] = PlaneData | scalar | np.ndarray

where step_index is a sequential reader-local index over the selected ADIOS steps. Use get_step_info() to map it back to the source ADIOS step id.

TIME_COORDINATES = {'gstep', 'step', 'time', 'timestep', 'tindex'}
get_field(var_name: str, step_index: int = 0)[source]

Return one stored loop-voltage item without type conversion.

get_plane_data(var_name: str, step_index: int = 0) PlaneData[source]

Return a loop-voltage field as PlaneData.

get_scalar(var_name: str, step_index: int = 0)[source]

Return a scalar loop-voltage metadata value.

xgc_analysis.magnetic_field module

class xgc_analysis.magnetic_field.MagneticField(plane_instance, data_dir='.', catalog=None, source_reader=None)[source]

Bases: object

compute_background_field(R, Z)[source]

Return the magnetic-field components (B_R, B_Z, B_t) at the given cylindrical coordinates.

Parameters:
  • R (float or ndarray) – Cylindrical coordinates. Scalars and arbitrary-shaped NumPy arrays are both accepted; broadcasting is supported as long as R and Z have compatible shapes.

  • Z (float or ndarray) – Cylindrical coordinates. Scalars and arbitrary-shaped NumPy arrays are both accepted; broadcasting is supported as long as R and Z have compatible shapes.

Returns:

B_R, B_Z, B_t – Radial, vertical (poloidal) and toroidal components. Their type/shape matches the broadcasted shape of R and Z.

Return type:

float or ndarray

xgc_analysis.mesh module

class xgc_analysis.mesh.Mesh(is_axisymmetric, data_dir='.', catalog=None, source_reader=None)[source]

Bases: object

A general mesh class that consists of an array of “plane” objects.

The mesh data for all planes comes from the same BP file (“xgc.mesh.bp”). The file also contains the variables “delta_phi” and “wedge_angle”. The number of wedges is computed as:

wedge_n = 2*pi / wedge_angle,

and the number of planes is computed as:

nphi = wedge_angle / delta_phi.

If the input flag is_axisymmetric is True, then the mesh is axisymmetric and only one plane is set up. Otherwise, nphi planes are created (all identical in this version).

apply_fieldline_mapping(meshdata, *, ref_plane: int = 0)[source]

Pull the data of every plane onto the vertices of ref_plane along magnetic-field lines.

Returns:

If the stored field is scalar:

shape (n_steps, n_vert)

If the stored field is vector:

shape (n_steps, n_vert, n_components)

Axis-0 walks along the field line (φ = φ₀ + (s+1)Δφ); Axis-1 enumerates the vertices of the reference plane.

Return type:

np.ndarray

evaluate_grad_par(field_2d: ndarray, bt_sign: int) ndarray[source]

Compute b·∇(field) on an axisymmetric mesh.

Parameters:
  • field_2d (np.ndarray, shape (nphi, n_n)) – Scalar field values on the full mesh (first index = poloidal plane, second = node).

  • bt_sign (int, sign of the toroidal magnetic field ( +1 or -1 ).)

Returns:

Same shape as field_2d with the parallel derivative.

Return type:

np.ndarray

Notes

Uses the centred, 2-nd-order accurate stencil

b·∇f ≈ sgn * [ -l_r/(l_l l_tot) f_{i-1}
  • (l_r-l_l)/(l_l l_r) f_i

  • l_l/(l_r l_tot) f_{i+1} ]

where the forward / reverse projection matrices ff_1dp_fwd and ff_1dp_rev as well as the parallel arc-lengths dl_par_1dp_fwd and dl_par_1dp_rev are taken from planes[0] (valid only when self.is_axisymmetric is True).

evaluate_scalar_gradients(field_2d: ndarray) ndarray[source]

Apply per-plane gradient operators to a scalar field on the full 3-D mesh.

Parameters:

field_2d (np.ndarray, shape (nphi, n_n)) – field_2d[i_phi, i_node] holds the scalar value at node i_node on poloidal plane i_phi.

Returns:

gradsgrads[i_phi] is the (n_n, 2) array returned by the corresponding plane’s evaluate_scalar_gradients.

Return type:

np.ndarray, shape (nphi, n_n, 2)

ff_map_real2ff(meshdata: ndarray) ndarray[source]

Maps mesh data from the regular representation of data on planes (points with the same index on different planes are connected toroidally) to field-following representation (vertices with the same index are connected along the magnetic field). The output format is list of MeshData objects of the same type, one for the left, one for the right plane.

flux_avg_from_surf(flux_avg: ndarray) ndarray[source]

Map flux‑surface averaged data back to vertices on every plane (producing a representative PlaneData).

flux_avg_to_from_surf(meshdata: ndarray) ndarray[source]

Compute flux-surface average on each plane and project back to the vertices φ.

flux_avg_to_surf(meshdata: ndarray) ndarray[source]

Flux‑surface average (⟨f⟩_ψ) of a 3‑D field, averaged over φ.

Returns:

Shape (nsurf,) for scalar, or (nsurf, n_components) for vector data.

Return type:

ndarray

flux_avg_to_surf_norm(meshdata: ndarray) ndarray[source]

Flux‑surface average of vector‑norm, averaged over the toroidal direction.

get_plane(index=0)[source]

Returns the plane at the specified index. If the mesh is axisymmetric, index is ignored.

get_vertex_counts()[source]

Returns a list of the number of vertices on each of the mesh’s planes.

For an axisymmetric mesh (is_axisymmetric=True), the same number of vertices (from the single plane stored) is repeated for each plane (nphi times).

For a non-axisymmetric mesh, the function returns the number of vertices for each plane.

get_wall_curve(*, plane_index: int = 0, verify_clockwise: bool = True, auto_reverse: bool = False, set_inboard_origin: bool = True)[source]

Build a WallCurve from a selected plane’s wall polygon.

setup_fieldline_mapping(magnetic_field, *, direction='forward', rk4_substeps: int = 2, n_int: int = 250)[source]

Trace all mesh vertices along B and build one CSR propagator matrix for every stored toroidal step. The objects are cached as

self.fl_mapping – raw dict from compute_fieldline_mapping self.fl_csr_matrices – list[CSR] (length = n_steps)

Call this after construction if the mapping was not required earlier.

toroidal_average(meshdata: ndarray) ndarray[source]

Simple arithmetic mean over the toroidal direction (returns vertex‑shaped ndarray).

property wall_phi

Return toroidal angle for each plane in radians.

property wall_rz

Return wall node coordinates per plane as a list of arrays.

xgc_analysis.mesh_data module

class xgc_analysis.mesh_data.MeshData(mesh, data_array=None, field_type='scalar', n_components=1, dtype=<class 'numpy.float64'>, mesh_is_axisym=False)[source]

Bases: object

Stores field data for a mesh as a list of PlaneData instances (one per plane).

The constructor accepts:
  • vertex_counts: a list of integers indicating the number of vertices on each plane.

  • field_type: ‘scalar’ or ‘vector’.

  • n_components: for vector fields (2 or 3); for scalar fields this should be 1.

  • dtype: the NumPy data type for the stored data.

  • mesh_is_axisym (bool): True if the mesh is axisymmetric (i.e. all planes have the same number of vertices

    and the same (R,Z) coordinates), False otherwise.

The data for each plane is stored as a separate PlaneData instance.

apply_fieldline_mapping(*, ref_plane: int = 0)[source]

Pull the data of every plane onto the vertices of ref_plane along magnetic-field lines.

Returns:

If the stored field is scalar:

shape (n_steps, n_vert)

If the stored field is vector:

shape (n_steps, n_vert, n_components)

Axis-0 walks along the field line (φ = φ₀ + (s+1)Δφ); Axis-1 enumerates the vertices of the reference plane.

Return type:

np.ndarray

evaluate_full_gradients(bt_sign: int) MeshData[source]

Return a 3-component gradient vector field as a new MeshData:

grads[…, 0] = ∂f/∂ψ grads[…, 1] = ∂f/∂θ grads[…, 2] = b·∇f

Parameters:

bt_sign (int) – Sign of the toroidal magnetic field Bᵗ (±1).

Return type:

MeshData # field_type = ‘vector’

evaluate_grad_par(bt_sign: int) MeshData[source]

Parallel derivative b·∇(f) returned as a new scalar MeshData.

Parameters:

bt_sign (int) – Sign of the toroidal magnetic field (±1).

Return type:

MeshData # field_type = ‘scalar’

evaluate_scalar_gradients() MeshData[source]

Return (R,Z)/(psi,theta)-gradients as a new MeshData object (vector field).

Return type:

MeshData # field_type = ‘vector’

extract_component(component_index)[source]

For vector fields only.

Returns a new MeshData instance where each plane contains only the specified component of the original vector field (i.e. a scalar field).

ff_map_real2ff()[source]

Maps mesh data from the regular representation of data on planes (points with the same index on different planes are connected toroidally) to field-following representation (vertices with the same index are connected along the magnetic field). The output format is list of MeshData objects of the same type, one for the left, one for the right plane.

Returns:

MeshData (vector-type): Field on a mesh mapped to field-aligned representation.

flux_avg_from_surf()[source]

Project the flux-surface average data back to vertices and package into PlaneData.

flux_avg_to_from_surf()[source]

Compute the flux-surface average of self.get_data() and project back to the plane in self.flux_avg_plane.

flux_avg_to_surf()[source]

Compute the flux-surface average and store in self.flux_avg_psi.

flux_avg_to_surf_norm()[source]

Flux‑surface average of vector‑norm, averaged over the toroidal direction.

get_data()[source]

Returns the data from all planes as a 2D NumPy array with shape (nphi, n_vertices).

get_plane(plane_index)[source]

Returns the PlaneData instance for the specified plane.

toroidal_average()[source]

Return toroidal average as PlaneData (also cached on Mesh).

xgc_analysis.neutral_data module

Reader for xgc.neutrals.XXXXX.bp neutral diagnostic files.

class xgc_analysis.neutral_data.NeutralData(mesh, work_dir='./', file_indices=None, is_axisymmetric=None, variables=None, read_all_steps=False, catalog=None, steps=None, missing='raise', source_reader=None)[source]

Bases: BPReaderMixin, ArrayAccessorMixin

Read neutral Monte-Carlo diagnostic data from xgc.neutrals.XXXXX.bp files.

The data layout follows the pattern used by FieldData/FsourceData:

self.data[var_name][file_step_index] = PlaneData | MeshData | scalar

For axisymmetric data, mesh fields are stored as PlaneData. For non-axisymmetric data, mesh fields are stored as MeshData.

Axisymmetry is inferred from the shape of the variables in the neutrals file (not from the mesh geometry):

  • axisymmetric neutrals: (n_n,) or (1, n_n)

  • non-axisymmetric neutrals: (nphi, n_n)

The inferred mode is tracked in self.is_axisymmetric. If multiple files are loaded, all neutrals fields are required to use the same axisymmetry mode.

get_mesh_data(var_name, step_index=0)[source]

Return var_name at step_index as MeshData.

get_neutral_field(var_name, step_index=0)[source]

Return the raw stored neutral field item for var_name.

get_plane_data(var_name, step_index=0)[source]

Return var_name at step_index as PlaneData.

get_scalar(var_name, step_index=0)[source]

Return var_name at step_index as a scalar numeric value.

required_vars = ['den_neut', 'rel_std', 'temp_neut']

xgc_analysis.oneddiag module

Reader and utilities for XGC 1D diagnostics (xgc.oneddiag.bp).

This module refactors the 1D diagnostic reader to follow the common XGC-Analysis data layout used by other readers:

self.data[var_name][step_index] = scalar | np.ndarray

Key conventions

  • Species-resolved variables are normalized to standardized dotted keys such as "e.gc_density_df_1d" and "i2.parallel_flow_df_1d".

  • Static arrays that are effectively constant in time (for example psi) are stored in self.static_data and exposed via compatibility aliases self.psi, self.psi00, and self.psi_mks.

  • Derived quantities are stored separately in self.derived_data / self.derived_static_data and accessed through od.derived.

The module also provides lightweight species views (od.e, od.i, …) for backward-compatible attribute access in notebooks.

class xgc_analysis.oneddiag.OneDDiag(path: str = './', filename: str = 'xgc.oneddiag.bp', simulation=None, catalog=None, steps=None, missing: str = 'raise', source_reader=None)[source]

Bases: BPReaderMixin, ArrayAccessorMixin

Reader for XGC 1D diagnostics with standard nested-dict storage layout.

Parameters:
  • path (str, default "./") – Directory containing the oneddiag BP file.

  • filename (str, default "xgc.oneddiag.bp") – Diagnostic filename.

  • simulation (Simulation or None, optional) – If provided, simulation.species is used to attach Species objects and species masses to standardized prefixes detected from the file.

  • catalog (SimulationCatalog or None, optional) – Optional catalog used to resolve logical steps into BP sources. If omitted, simulation.catalog is used when present. Direct local filename reads are disabled when no catalog is available.

  • steps (iterable[int] or None, optional) – Logical XGC steps to read from catalog. If omitted, all available oneddiag steps are read.

  • missing ({"raise", "skip", "zero"}, optional) – Missing-step policy for catalog read planning.

  • source_reader (callable or None, optional) – Optional read-plan backend hook.

data

Time-dependent raw variables in the common reader layout.

Type:

dict[str, dict[int, object]]

static_data

Time-independent arrays promoted out of data (for example psi).

Type:

dict[str, np.ndarray]

derived_data

Time-dependent derived quantities (e.g. "e.T", "shear_r").

Type:

dict[str, dict[int, object]]

species_by_prefix

Mapping from standardized prefixes (e, i, i2, …) to Species objects when available.

Type:

dict[str, Species | None]

mass_by_prefix

Species masses in atomic mass units, from Species metadata or internal fallback defaults.

Type:

dict[str, float | None]

SPECIES_PREFIXES = ['e', 'i', 'i2', 'i3', 'i4', 'i5', 'i6', 'i7', 'i8', 'i9']
d_dpsi(var, psi)[source]

Compute d(var)/d(psi) on a non-uniform 1D grid.

Parameters:
  • var (np.ndarray) – Array of shape (n_step, n_psi).

  • psi (np.ndarray) – 1D non-uniform coordinate array of length n_psi.

Returns:

Numerical derivative with the same shape as var.

Return type:

np.ndarray

echarge = 1.6022e-19
get_derived_array(var_name)[source]

Return a derived variable stacked over steps, or a derived static array.

get_derived_item(var_name, step_index)[source]

Return one derived item for a specific step_index.

get_profile(var_name, step_index=0)[source]

Return a time-dependent oneddiag variable as an ndarray for one step.

get_scalar(var_name, step_index=0)[source]

Return a scalar time-dependent oneddiag variable for one step.

get_species_by_prefix(prefix)[source]

Return the associated Species object (if available) for prefix.

get_species_view(prefix)[source]

Return the lightweight species view object for a standardized prefix.

get_static_array(var_name)[source]

Return a static array from self.static_data (for example psi).

get_time_mask()[source]

Build a mask selecting the last occurrence of each diagnostic step.

This is a legacy helper kept for compatibility with older notebook workflows that expect self.tmask to index a monotonic subset of the stored time history. Overlapping diagnostic segments are resolved by keeping the last occurrence for each repeated step value.

has_derived_var(var_name)[source]

Return True if a derived variable exists in dynamic or static storage.

list_species()[source]

Return active species prefixes detected in the file.

load_data()[source]

Disabled legacy direct-file reader.

One-dimensional diagnostic data must be read through catalog read plans so the same code path works for directory and campaign backends.

load_data_from_catalog()[source]

Read the oneddiag product through catalog read plans.

All variables advertised by the catalog product are read unless they are ignored by this reader. The resulting raw step-major data are then normalized by the same path used for direct BP reads.

mu0 = 1.2566370614359173e-06
plot1d_if(var, time=None, varstr=None, psi=None, xlim=None, initial=True)[source]

Plot first/last profiles from a time-series array (legacy helper).

Parameters:
  • var (np.ndarray) – Array of shape (n_step, n_psi).

  • time (np.ndarray or None, optional) – Time array aligned with var for labels. If omitted, labels are Initial / Final.

  • varstr (str or None, optional) – Label/title string.

  • psi (np.ndarray or None, optional) – X-axis coordinate. Defaults to self.psi.

  • xlim (tuple[float, float] or None, optional) – Restrict plotting to a psi interval.

  • initial (bool, default True) – Whether to also plot the first time slice.

post_process()[source]

Compute commonly used derived quantities and store them in od.derived.

Derived quantities currently include: - species temperatures <prefix>.T - species gradient scale lengths <prefix>.Ln and <prefix>.Lt - reference density and Ln - grad_psi_sqr and shear_r

Notes

The reference species for density / shear_r is electrons if present, otherwise the main ion prefix i when available.

protmass = 1.6726e-27
report_profiles(sp_names=None, init_idx=0, end_idx=-1, edge_lim=[0.85, 1.05], show_edge=True)[source]

Generate a small set of legacy profile plots for quick inspection.

This method is retained for backward compatibility and is a candidate for migration into plotting.py in a future cleanup.

xgc_analysis.periodic_table module

xgc_analysis.periodic_table.get_element_name_by_mass(mass_au, tolerance=0.5)[source]

Returns the name of the element with atomic mass closest to the given mass_au.

Parameters:
  • mass_aufloat

    Mass in atomic mass units.

  • tolerancefloat

    Maximum allowed deviation to consider a match.

Returns:
  • str: Element symbol or ‘Unknown’ if no match is found.

xgc_analysis.plane module

class xgc_analysis.plane.Plane(filename='xgc.mesh.bp', data_dir='.', setup_ff2real_mapping=False, catalog=None, source_reader=None)[source]

Bases: object

A class to represent a planar unstructured triangle mesh (in cylindrical coordinates at constant toroidal angle) read from an Adios BP (BP version 5) file using the Adios2 Python FileReader API (v2.10.2+).

The BP file (e.g., ‘xgc.mesh.bp’) is assumed to contain the following variables:

Scalars:
  • n_n : Number of mesh vertices.

  • n_t : Number of triangles.

  • nsurf : Number of psi contour surfaces.

  • surf_maxlen : Maximum number of vertices on any psi surface.

Arrays:
  • rz : (n_n, 2) coordinates (R, Z) of vertices.

  • nd_connect_list : (n_t, 3) triangle connectivity (1-based indices).

  • tr_area : (n_t,) triangle areas.

  • node_vol : (n_n,) Voronoi volume (measure 1).

  • node_vol_nearest: (n_n,) Voronoi volume (nearest neighbor measure).

  • psi : (n_n,) poloidal magnetic flux.

  • theta : (n_n,) straight field-line poloidal angle.

  • region : (n_n,) region index of the vertices (1) core, (2) SOL, (3) privat flux, (100) wall

  • surf_len : (nsurf,) number of vertices on each psi surface.

  • surf_idx : (nsurf, surf_maxlen) 1-based vertex indices on each psi surface.

  • rmin : (nsurf,) minor radius of each surface.

  • rmaj : (nsurf,) major radius of each surface.

  • epsilon : (nsurf,) inverse aspect ratio.

  • m_max_surf : (nsurf,) Fourier space resolution limit.

  • psi_surf : (nsurf,) psi value on each surface.

  • qsafety : (nsurf,) safety factor.

  • trapped : (nsurf,) trapped particle fraction.

Plotting functionality:
  • triObjMatplotlib triangulation object for unstructured meshes.

    This is needed for plotting fields defined on the planar mesh

Matrices:
  • cnv_to_surf : …

  • cnv_from_surf : …

  • grad_r_psi : …

  • grad_z_theta : …

Diagnostic functions:
  • plot_vertices_with_wall : …

  • plot surfaces : …

  • plot_triangles : …

calculate_flux_surface_area()[source]

Calculates the surface area of each flux surface assuming that the 2D ψ-surfaces are rotated around the Z-axis by 2π.

For each ψ-surface, the routine:
  • Loops over its vertices.

  • For each segment between adjacent vertices, computes the midpoint (R_m, Z_m) and the distance l_seg.

  • If the surface is closed (i.e. self.surf_region[i] == 1), the last vertex connects to the first; if open (region==2 or 3), the last vertex is skipped.

  • The area of each segment is 2π * R_m * l_seg.

Returns:

A list of surface areas (one per ψ-surface).

Assumes that the Plane class has the following attributes:
  • self.nsurf: total number of ψ-surfaces.

  • self.surf_len: 1D array of length nsurf (number of vertices per surface).

  • self.surf_idx: 2D array (nsurf × surf_maxlen) of 0-based vertex indices.

  • self.rz: 2D array (n_n × 2) with (R,Z) coordinates.

  • self.surf_region: 1D array (length nsurf) with region codes (1 for closed, 2 or 3 for open).

compute_core_sol_geometry_blocks(sep_tol: float = 1e-05) dict[str, ndarray | float | int][source]

Build mapped geometry blocks for default, core-side, and SOL-side discretizations.

This helper computes flux-surface area and shell-volume arrays on the mapped surface index set (surf_map) that are suitable for transport discretizations requiring different separatrix treatment on core and SOL sides.

Construction summary

  1. Compute default mapped areas from calculate_flux_surface_area()[surf_map].

  2. Split separatrix area into above-X and below-X contributions by integrating segment lengths in the (R, Z) surface polyline.

  3. Build area_core_block using only separatrix-above-X area at the separatrix index, and area_sol_block using total separatrix area.

  4. Reconstruct shell volumes from vertex volumes in two passes. The first pass loops over all full-grid surfaces and directly accumulates vertex volumes while marking used vertices. The second pass distributes remaining unused vertices to mapped surfaces by linear interpolation in psi.

  5. At the separatrix full-surface index, split candidate vertices by region tag: region == 1 for volume_core_block and region == 2 for volume_sol_block.

param sep_tol:

Reserved separatrix tolerance (dimensionless). Kept for API compatibility; not currently used in this implementation.

type sep_tol:

float

returns:

Geometry dictionary with the following entries:

psi_mapnp.ndarray

Psi values on mapped surfaces, shape (n_map,) (units: psi).

area_defaultnp.ndarray

Default mapped flux-surface areas, shape (n_map,) (units: m^2).

area_core_blocknp.ndarray

Core-side area block; separatrix uses above-X contribution only (units: m^2).

area_sol_blocknp.ndarray

SOL-side area block; separatrix uses full area (units: m^2).

volume_defaultnp.ndarray

Default mapped shell volumes reconstructed from node_vol (units: m^3).

volume_core_blocknp.ndarray

Core-side shell-volume block with separatrix region-1 selection (units: m^3).

volume_sol_blocknp.ndarray

SOL-side shell-volume block with separatrix region-2 selection (units: m^3).

i_sep_mapint

Separatrix index in mapped-surface arrays.

i_sep_fullint

Separatrix index in full-surface arrays.

sep_area_abovefloat

Separatrix area above X-point (units: m^2).

sep_area_belowfloat

Separatrix area below X-point (units: m^2).

rtype:

dict[str, np.ndarray | float | int]

Notes

volume_* arrays are shell volumes per mapped surface index, not cumulative enclosed volume. Cumulative volume can be formed with np.cumsum(volume_default) (or corresponding core/SOL block).

evaluate_scalar_gradients(field_1d: ndarray) ndarray[source]

Evaluate the radial and poloidal gradients of a scalar field. (Note that it depends on the value of self.basis whether the derivatives are (R,Z) or (psi,theta) directonal derivatives!)

Parameters:

field_1d (np.ndarray, shape (n_n,)) – Nodal values of the scalar field on this plane.

Returns:

grads – Column 0 → ∂f/∂ψ (gradient_r_psi ⋅ f) Column 1 → ∂f/∂θ (gradient_z_theta ⋅ f)

Return type:

np.ndarray, shape (n_n, 2)

flux_avg_from_surf(flux_avg: ndarray) ndarray[source]

Map a flux-surface averaged quantity <f>(psi) back to vertices.

flux_avg_to_from_surf(vertex_data: ndarray) ndarray[source]

Smooth vertex_data by averaging on ψ and mapping back to vertices.

flux_avg_to_surf(vertex_data: ndarray) ndarray[source]

Return the flux-surface average ⟨f⟩ for a vertex‑defined scalar or vector field f.

flux_avg_to_surf_norm(field: ndarray) ndarray[source]

Flux-surface average of the Euclidean norm of a vertex-centred field on this poloidal plane.

Parameters:

field (np.ndarray) –

  • If shape == (n_n,) → treated as a scalar field.

  • If shape == (n_n, n_comp) → treated as a vector field; the norm is computed along the last axis.

Returns:

1-D array of length n_psi (the number of flux-surfaces on the plane) containing the volume-weighted flux-surface averages.

Return type:

np.ndarray

Raises:
  • RuntimeError – If the conversion matrix cnv_to_surf is unavailable because its backing .bp file was missing when the Plane was constructed.

  • ValueError – If the input array does not have the required first dimension n_n.

gen_ff2real_mapping()[source]
get_psi_surface_index_map(tol=0.0001)[source]

Identify the ψ‑surfaces that are valid for subsequent analysis.

Strategy

For every surface i (whose length is surf_len[i]):

  1. Single‑vertex surface

    • If the surface contains exactly one vertex and that vertex’s coordinates (R, Z) are within tol of the magnetic‑axis position (axis_r, axis_z), accept the surface.

  2. Multi‑vertex surface

    • Restrict to vertices with R >= axis_r.

    • Among them, find • the vertex whose Z is largest below the axis • the vertex whose Z is smallest above the axis.

    • Accept the surface only if both vertices exist.

param tol:

Tolerance that defines “close to the magnetic axis”, measured in the same units as R and Z. Default is 1e‑4.

type tol:

float, optional

returns:

Zero‑based indices of the ψ‑surfaces that satisfy the above criteria.

rtype:

list[int]

get_surface_indices()[source]
Returns:

np.ndarray: 2D array (shape: (nsurf, surf_maxlen)) containing 1-based vertex indices on each surface.

get_surface_lengths()[source]
Returns:

np.ndarray: 1D array of length nsurf indicating the number of vertices on each surface.

get_surface_properties()[source]
Returns:
dict: A dictionary of surface properties with keys:
  • ‘rmin’ : Minor radius (np.ndarray of shape (nsurf,))

  • ‘rmaj’ : Major radius (np.ndarray of shape (nsurf,))

  • ‘epsilon’ : Inverse aspect ratio (np.ndarray of shape (nsurf,))

  • ‘m_max_surf’ : Fourier space resolution limit (np.ndarray of shape (nsurf,))

  • ‘psi_surf’ : Psi value on each surface (np.ndarray of shape (nsurf,))

  • ‘qsafety’ : Safety factor (np.ndarray of shape (nsurf,))

  • ‘trapped’ : Trapped particle fraction (np.ndarray of shape (nsurf,))

get_surface_vertex_indices(surface_index)[source]

Returns the vertex indices for a given psi surface.

Args:

surface_index (int): The index of the surface (0-based).

Returns:

np.ndarray: An array of vertex indices (0-based) corresponding to the given surface.

get_triangle_areas()[source]
Returns:

np.ndarray: Array of triangle areas with shape (n_t,).

get_triangle_connectivity()[source]
Returns:

np.ndarray: Array of triangle connectivity indices (1-based) with shape (n_t, 3).

get_triangulation_data(n_int: int = 200, R_bounds: tuple[float, float] | None = None, Z_bounds: tuple[float, float] | None = None)[source]

Build a regular (R,Z) interpolation grid and a Matplotlib Triangulation that matches the unstructured mesh.

Parameters:
  • n_int (int, default 200) – Number of grid points in each dimension (R and Z).

  • R_bounds ((min, max) tuple or None, optional) – Explicit coordinate limits for the interpolation grid. If None (default) the routine uses the min/max of the vertex coordinates.

  • Z_bounds ((min, max) tuple or None, optional) – Explicit coordinate limits for the interpolation grid. If None (default) the routine uses the min/max of the vertex coordinates.

Returns:

Object containing (RI, ZI, triObj).

Return type:

TriangulationData

get_vertex_coordinates()[source]
Returns:

np.ndarray: Array of vertex coordinates with shape (n_n, 2) representing (R,Z) pairs.

get_voronoi_volumes()[source]
Returns:
tuple: Two np.ndarray objects representing the vertex Voronoi volumes

(node_vol and node_vol_nearest), each with shape (n_n,).

get_wall_curve(*, verify_clockwise: bool = True, auto_reverse: bool = False, set_inboard_origin: bool = True)[source]

Build a WallCurve from this plane’s wall polygon.

Parameters:
  • verify_clockwise (bool) – Validate clockwise ordering of wall nodes.

  • auto_reverse (bool) – Reverse node order automatically if not clockwise.

  • set_inboard_origin (bool) – If True, set arclength origin at Z=0 with R<R_axis.

plot_contour(values_in: ndarray, *, n_int: int = 200, plot_norm: bool = False, i_comp: int = 0, var_name: str = '', title: str = '', levels: int | None = 60, lower: float | None = None, upper: float | None = None, R_bounds: tuple[float, float] | None = None, Z_bounds: tuple[float, float] | None = None, filename: str | None = None)[source]

Plot the field stored in this PlaneData instance as a filled-contour map in the (R,Z) plane.

Parameters:
  • values_in (np.ndarray) – 1-D array of length self.n_n (= number of vertices). If you pass a 2-D array, its Euclidean norm is taken or a single component (convenient for vector data), controlled by plot_norm and i_comp.

  • n_int (int, default 200) – Grid resolution in both R and Z used for interpolation.

  • plot_norm (bool, default False) – In case of vector data, whether to plot the norm | v | of the vector.

  • i_comp (int, default 0) – In case of vector data, which component to plot.

  • var_name (str, optional) – Label for the colour-bar (e.g. "nₑ (m⁻³)"). Defaults to "".

  • title (str, optional) – Header for the plot window. Defaults to "".

  • levels (int or sequence, optional) – If an int, the number of evenly-spaced contour levels (Matplotlib default is fine). If an explicit 1-D sequence, those values are used as contour levels. Defaults to 60.

  • lower (float or None, optional) – Explicit lower/upper bounds for the colour-map. If either is None the routine uses the corresponding data extreme.

  • upper (float or None, optional) – Explicit lower/upper bounds for the colour-map. If either is None the routine uses the corresponding data extreme.

  • R_bounds ((min, max) tuple or None, optional) – Explicit limits for the interpolation grid. Passed straight through to plane.get_triangulation_data. None ⇒ auto-limits.

  • Z_bounds ((min, max) tuple or None, optional) – Explicit limits for the interpolation grid. Passed straight through to plane.get_triangulation_data. None ⇒ auto-limits.

plot_fieldline_contour(data: ndarray, surf_idx: int, *, var_name: str = '', title: str = '', levels: int | ndarray | None = 60, lower: float | None = None, upper: float | None = None, filename: str | None = None)[source]

Filled-contour plot of data along the magnetic field on the requested ψ-surface.

Parameters:
  • data (ndarray) – Result of MeshData.apply_fieldline_mapping, shape (n_steps, n_vertices). Axis-0 = distance along B, axis-1 = vertex index on this plane.

  • surf_idx (int) – Which ψ-surface to plot (index into self.surf_* arrays).

  • var_name (str) – Labels for colour-bar and figure title.

  • title (str) – Labels for colour-bar and figure title.

  • levels (int or 1-D array or None) – Passed to contourf, like in plot_contour.

  • lower (float or None) – Manual colour limits (None → data min/max).

  • upper (float or None) – Manual colour limits (None → data min/max).

plot_surfaces()[source]

Plot all psi surfaces.

plot_triangles()[source]

Plots all the triangles of the mesh. For each triangle, the 3 vertex indices from nd_connect_list are used to get the corresponding (R, Z) coordinates from rz. The first vertex is appended to close the triangle, and the outline is plotted.

plot_vertices_with_wall()[source]

Plots the mesh vertices as dots and overlays the wall as a closed line in the background. The wall is defined by the grid_wall_nodes variable.

property wall_rz

Return (R, Z) coordinates of wall nodes for this plane.

class xgc_analysis.plane.TriangulationData(RI, ZI, triObj)[source]

Bases: object

A simple container class to hold interpolation grid data and a Matplotlib Triangulation object.

Attributes:

RI (np.ndarray): 2D array of R coordinates of the interpolation grid. ZI (np.ndarray): 2D array of Z coordinates of the interpolation grid. triObj (Triangulation): A Matplotlib Triangulation object for the mesh.

xgc_analysis.plane_data module

class xgc_analysis.plane_data.PlaneData(plane, data_array=None, n_components=1, dtype=<class 'numpy.float64'>)[source]

Bases: object

Stores field data for a single plane.

For a scalar field, data is a 1D NumPy array of shape (n,). For a vector field, data is a 2D NumPy array of shape (n, n_components), where for each vertex the vector components are stored contiguously in memory.

Attributes:
  • n: number of vertices in this plane.

  • field_type: ‘scalar’ or ‘vector’.

  • n_components: number of components (1 for scalar, 2 or 3 for vector fields).

  • dtype: data type for the array.

  • data: the NumPy array storing the field data.

evaluate_scalar_gradients() PlaneData[source]

Compute ∇_{R,Z}f and return the result as a new PlaneData instance (two-component vector on the same plane).

Return type:

PlaneData # field_type = ‘vector’

extract_component(component_index)[source]

For vector fields only.

Returns a new PlaneData instance (a scalar field) containing the specified component from the vector.

flux_avg_from_surf()[source]

Back‑project flux_avg_psi and store result in self.flux_avg_plane.

flux_avg_to_from_surf()[source]

Compute the flux-surface average of self.data and project back to the plane in self.flux_avg_plane.

flux_avg_to_surf()[source]

Compute flux-surface-average and store it in self.flux_avg_psi.

flux_avg_to_surf_norm()[source]

Compute flux-surface-average of the norm of a vector field and store it in self.flux_avg_norm_psi.

get_data()[source]

Returns the underlying NumPy array.

plot_contour(plane: Plane, **kwargs)[source]

Convenience wrapper that forwards to Plane.plot_contour using this instance’s data.

Any keyword arguments accepted by Plane.plot_contour can be supplied.

xgc_analysis.plotting module

xgc_analysis.plotting.plot_grid_contour(Z: ndarray, X: ndarray | None = None, Y: ndarray | None = None, *, x_label: str, y_label: str, var_name: str = '', title: str = '', filename: str | None = None, levels: int | ndarray | None = 60, lower: float | None = None, upper: float | None = None)[source]

General filled-contour plot for any 2-D NumPy array Z defined on the rectangular mesh (X, Y).

All keyword arguments after the literal * are the same as in the wrapper routines; only x_label and y_label are required so the caller can supply axis text appropriate to its own context.

xgc_analysis.read_bp_file module

Standalone ADIOS FileReader-based BP reader.

xgc_analysis.read_bp_file.ReadBPFile(filename, variables: Sequence[str] | str | None = None, step_range: tuple[int, int] | None = None, *, steps: Iterable[int] | int | None = None, open_timeout_secs=None, step_timeout_secs=None)[source]

Read selected variables and ADIOS steps from a BP file with FileReader.

Parameters:
  • filename (str or pathlib.Path) – ADIOS-readable BP file or BP directory.

  • variables (sequence[str], str, or None, optional) – Variable names to read. If omitted, all variables advertised by the file are read.

  • step_range (tuple[int, int] or None, optional) – Legacy half-open ADIOS step range (start, end). This path clips the requested range to the currently available steps, preserving the old ReadBPFile(..., step_range=(0, huge)) “read all available” behavior.

  • steps (iterable[int], int, or None, optional) – Explicit ADIOS step ids to read. This path is strict: unavailable steps raise IndexError and unavailable variables raise KeyError. If both steps and step_range are omitted, the last available ADIOS step is read.

  • open_timeout_secs – Accepted for compatibility with the previous Stream-based implementation. FileReader is a finite snapshot API and does not use open/step wait timeouts.

  • step_timeout_secs – Accepted for compatibility with the previous Stream-based implementation. FileReader is a finite snapshot API and does not use open/step wait timeouts.

Returns:

Step-major mapping {adios_step: {variable_name: value}}.

Return type:

dict[int, dict[str, object]]

Raises:
  • FileNotFoundError – If filename does not exist.

  • KeyError – If an explicitly requested variable is not available.

  • IndexError – If an explicitly requested ADIOS step is outside the available range.

  • ValueError – If both steps and step_range are supplied.

xgc_analysis.read_bp_file.read_bp_file(filename, variables: Sequence[str] | str | None = None, steps: Iterable[int] | int | None = None)[source]

Strict standalone BP reader using explicit ADIOS step ids.

Parameters:
  • filename (str or pathlib.Path) – ADIOS-readable BP file or BP directory.

  • variables (sequence[str], str, or None, optional) – Variable names to read. If omitted, all available variables are read.

  • steps (iterable[int], int, or None, optional) – ADIOS step ids to read. If omitted, the last available step is read.

Returns:

Step-major mapping {adios_step: {variable_name: value}}.

Return type:

dict[int, dict[str, object]]

xgc_analysis.sheath_data module

Sheath diagnostics reader integrated with Simulation mesh data.

class xgc_analysis.sheath_data.SheathData(steps, simulation, sheath_file='xgc.sheathdiag.bp', data_dir='./', catalog=None, missing='raise', source_reader=None)[source]

Bases: BPReaderMixin, ArrayAccessorMixin

Class to handle / construct sheath data utilizing xgc.mesh.bp and xgc.sheathdiag.bp files.

Mesh data are accessed via the Simulation instance (mesh/plane).

xgc.sheathdiag.bp - nwall : Integer representing the number of wall nodes. - sheath_pot : Sheath Potential - sheath_ilost : Sheath Ion Loss - sheath_lost : Sheath Electron Loss - sheath_nphi : Sheath Electron Density

simulation

Simulation instance providing mesh and magnetic field data.

Type:

Simulation

data

Nested dictionary storing time-dependent sheath diagnostics in the common XGC-Analysis layout: self.data[var_name][step_idx] = ndarray.

Type:

dict[str, dict[int, np.ndarray]]

wall_data

Static wall-related geometry/derived arrays: wall_rz, wall_phi, wall_psi.

Type:

dict[str, np.ndarray]

Returns

SheathData: An instance of the SheathData class.

TIME_VARS = ['sheath_pot', 'sheath_ilost', 'sheath_lost', 'sheath_nphi']
get_scalar(var_name: str, step_index: int)[source]

Return var_name at step_index as a scalar numeric value.

get_sheath_array(var_name: str, step_index: int)[source]

Return time-dependent sheath diagnostic var_name as np.ndarray.

get_wall_array(var_name: str) ndarray[source]

Return a static wall-related array from self.wall_data.

property wall_phi: array

Return toroidal angle(s) corresponding to wall planes.

property wall_psi: array

Returns poloidal magnetic flux (psi) at wall nodes for plane 0.

property wall_rz

Return wall node (R, Z) coordinates for each mesh plane.

xgc_analysis.simulation module

class xgc_analysis.simulation.Simulation(directories=None, is_stellarator=False, sim_is_axisymmetric=False, catalog=None, initialize=True)[source]

Bases: object

REQUIRED_CATALOG_PRODUCTS = ('xgc.mesh.bp', 'xgc.equil.bp', 'xgc.bfield.bp')
convert_fortran_value(val)[source]

xgc_analysis.sol_wall_loss_rates module

Compute SOL wall-loss source rates on the 1D flux-surface grid.

class xgc_analysis.sol_wall_loss_rates.SOLWallLossRatesResult(lower_surface: ndarray, upper_surface: ndarray, psi_lower: ndarray, psi_upper: ndarray, psi_center: ndarray, psi_center_norm: ndarray, volume_shell: ndarray, segment_to_bin: ndarray, time_left: ndarray, time_right: ndarray, dt: ndarray, interval_mask_used: ndarray, particle_rate_e: ndarray, particle_rate_i: ndarray, energy_rate_e: ndarray, energy_rate_i: ndarray, particle_rate_e_avg: ndarray, particle_rate_i_avg: ndarray, energy_rate_e_avg: ndarray, energy_rate_i_avg: ndarray)[source]

Bases: object

Wall-loss source rates mapped to adjacent SOL surface-pair volumes.

dt: ndarray
energy_rate_e: ndarray
energy_rate_e_avg: ndarray
energy_rate_i: ndarray
energy_rate_i_avg: ndarray
interval_mask_used: ndarray
lower_surface: ndarray
particle_rate_e: ndarray
particle_rate_e_avg: ndarray
particle_rate_i: ndarray
particle_rate_i_avg: ndarray
psi_center: ndarray
psi_center_norm: ndarray
psi_lower: ndarray
psi_upper: ndarray
segment_to_bin: ndarray
time_left: ndarray
time_right: ndarray
upper_surface: ndarray
volume_shell: ndarray
xgc_analysis.sol_wall_loss_rates.compute_sol_wall_loss_rates(plane, heatdiag, *, phi_index: int = 0, psi_norm_min: float = 1.0, psi_norm_max: float | None = None, interval_sample: str = 'right', time_window: tuple[float, float] | None = None) SOLWallLossRatesResult[source]

Compute SOL wall-loss source rates on adjacent-surface shell volumes.

Parameters:
  • plane (Plane) – Plane object with surf_map, psi_surf, x_psi, vol_1d and wall data.

  • heatdiag (HeatDiag) – HeatDiag reader with wall polygon and time-dependent wall loads.

  • phi_index (int) – Toroidal index for selecting one heatdiag wall curve.

  • psi_norm_min (float) – Lower normalized-psi cutoff for SOL pairing (default: 1.0).

  • psi_norm_max (float | None) – Optional upper normalized-psi cutoff for SOL pairing.

  • interval_sample (str) – Which time sample to use for interval-accumulated wall loads: "right" uses sample k+1 for [k,k+1], "left" uses sample k.

  • time_window (tuple[float, float] | None) – Optional averaging window [t0, t1] in seconds. If provided, only heatdiag intervals overlapping this window contribute to time averages.

Returns:

Per-interval volumetric particle/energy loss rates [m^-3 s^-1, W m^-3] for electrons and ions, and their dt-weighted averages.

Return type:

SOLWallLossRatesResult

xgc_analysis.sol_wall_loss_rates.interpolate_wall_loss_rates_to_surf_map(plane, result: SOLWallLossRatesResult, *, use_time_average: bool = True) dict[str, ndarray][source]

Interpolate SOL wall-loss rates from bin centers to plane.surf_map psi grid.

Core surfaces (psi/psi_x < 1) are set to zero.

Returns:

Keys particle_e, particle_i, energy_e, energy_i. If use_time_average=True, each value has shape (npsi,). Otherwise each value has shape (n_time_intervals, npsi).

Return type:

dict[str, np.ndarray]

xgc_analysis.sol_wall_mapping module

Map SOL flux-surface pairs to wall arclength intervals.

class xgc_analysis.sol_wall_mapping.SOLVolumeWallBounds(lower_surface: int, upper_surface: int, psi_lower: float, psi_upper: float, lower_wall_nodes: tuple[int, int], upper_wall_nodes: tuple[int, int], intervals: tuple[tuple[float, float, bool], tuple[float, float, bool]])[source]

Bases: object

Wall-boundary information for one adjacent SOL surface pair.

intervals: tuple[tuple[float, float, bool], tuple[float, float, bool]]
lower_surface: int
lower_wall_nodes: tuple[int, int]
psi_lower: float
psi_upper: float
upper_surface: int
upper_wall_nodes: tuple[int, int]
class xgc_analysis.sol_wall_mapping.SOLWallVolumeMap(plane, wall_curve: WallCurve)[source]

Bases: object

Identify wall ranges that bound volumes between adjacent SOL surfaces.

build_from_surf_map(*, psi_norm_min: float = 1.0, psi_norm_max: float | None = None) list[SOLVolumeWallBounds][source]

Build adjacent-surface wall bounds from plane.surf_map.

Parameters:
  • psi_norm_min (float) – Minimum normalized psi for surfaces to include (default: SOL only, >=1).

  • psi_norm_max (float | None) – Optional maximum normalized psi cutoff (e.g., diff_bd_out).

xgc_analysis.species module

class xgc_analysis.species.Species(sim, index)[source]

Bases: object

Class representing a plasma species with basic physical properties.

interpolate_profile(name: str, psi_new: ndarray, *, fill: str | float | None = 'edge') ndarray[source]

Interpolate one of this species’ initial profiles onto a new ψ grid.

Parameters:
  • name (str) – Profile key in self.initial_profiles (“density”, “temperature”, “flow”, …).

  • psi_new (ndarray) – Target ψ‑grid (1‑D NumPy array).

  • fill ({"edge", None, float}, default "edge") –

    How to handle ψ outside the original range:
    • ”edge” – use nearest edge value (default)

    • None – raise ValueError if extrapolation needed

    • float – fill with that scalar

Returns:

Interpolated profile values at psi_new.

Return type:

ndarray

xgc_analysis.time_step_utils module

Utilities for handling diagnostic time-step sequences with overlaps.

xgc_analysis.time_step_utils.build_last_occurrence_step_mask(step_values) ndarray[source]

Return indices that sort by step value and keep the last duplicate occurrence.

This is useful for diagnostics that may contain overlapping sections in time.

Parameters:

step_values (array-like) – 1D or broadcastable array of step indices / timestamps.

Returns:

Integer indices into the original sequence, ordered by increasing step value, with duplicate step values reduced to their last occurrence.

Return type:

np.ndarray

xgc_analysis.utils.file_waiter module

class xgc_analysis.utils.file_waiter.FileWaiter(required_files: Sequence[str | Path], run_dir: str | Path, poll_interval: float = 5.0, grace_period: float = 3.0, timeout: float | None = 600.0)[source]

Bases: object

Block execution until all files in required_files exist inside run_dir.

Parameters:
  • required_files – Relative paths (strings or pathlib.Path) that must appear inside run_dir.

  • run_dir – Directory expected to contain the files.

  • poll_interval – Delay in seconds between successive checks (default 5.0).

  • grace_period – Maximum time in seconds to wait before raising TimeoutError. None (default) means “wait forever”.

Notes

Prints a short status line on every poll. Switch to the missing_files() method if you want to plug this into a custom logging setup.

missing_files() list[str][source]

Return a list of relative paths that are still absent.

wait() None[source]

Block until all files are present (plus grace_period) or until timeout elapses.

xgc_analysis.utils.file_waiter.wait_for_files(run_dir: str | Path, required_files: Sequence[str | Path], poll_interval: float = 5.0, grace_period: float = 3.0, timeout: float | None = 600.0) None[source]

Convenience wrapper around FileWaiter.

Examples

>>> wait_for_files("/scratch/run42",
...               ["xgc.mesh.bp", "input"],
...               poll_interval=1.0,
...               grace_period=0.0)         # proceed immediately once ready

xgc_analysis.velocity_grid module

class xgc_analysis.velocity_grid.VelocityGrid(work_dir='.', filename='xgc.f0.mesh.bp', catalog=None, source_reader=None)[source]

Bases: object

Velocity-space grid metadata for XGC distribution functions.

The XGC f0 mesh file stores a cylindrical velocity grid in (v_perp, v_parallel) normalized to a reference thermal speed, with the gyrophase angle removed. XGC distribution data on this grid already includes the factor v_perp from the cylindrical Jacobian.

OPTIONAL_VARIABLES = ('gradpsi', 'nb_curl_nb', 'v_curv', 'v_gradb', 'f0_grid_vol_vonly')
REQUIRED_VARIABLES = ('f0_nmu', 'f0_nvp', 'f0_smu_max', 'f0_vp_max', 'f0_dsmu', 'f0_dvp', 'f0_fg_T_ev', 'f0_T_ev', 'f0_den', 'f0_flow')
integrate_over_velocity(values, *, axis_mu=-3, axis_vp=-1, node_axis=None, data_includes_vperp=True, include_gyroangle=True, apply_grid_vol_vonly=False, species_index=None)[source]

Integrate an array over (v_perp, v_parallel) in normalized coordinates.

Parameters:
  • values (np.ndarray) – Array containing velocity-grid data.

  • axis_mu (int) – Indices of the v_perp and v_parallel axes in values.

  • axis_vp (int) – Indices of the v_perp and v_parallel axes in values.

  • node_axis (int | None) – Index of the configuration-space node axis in values. Required when apply_grid_vol_vonly=True.

  • data_includes_vperp (bool) – True for XGC distribution data (*_f), which already includes the v_perp Jacobian factor.

  • include_gyroangle (bool) – Multiply by 2*pi if the gyrophase angle has been integrated out.

  • apply_grid_vol_vonly (bool) – If True, multiply by species/node-dependent f0_grid_vol_vonly before integrating over velocity.

  • species_index (int | None) – Species index into f0_grid_vol_vonly. Required when apply_grid_vol_vonly=True and multiple species are present.

integration_weights_2d(*, data_includes_vperp=True, include_gyroangle=True)[source]

2D velocity-space integration weights in normalized coordinates.

Returns weights for arrays shaped (..., n_mu, ..., n_vp) after axes are aligned, with optional 2*pi gyrophase factor.

mu_edge_factors()[source]
mu_integration_weights(*, data_includes_vperp=True)[source]

1D weights for the v_perp axis (normalized units).

If data_includes_vperp=True (XGC default), only trapezoidal weights and dsmu are applied because the stored values already carry the cylindrical Jacobian factor v_perp.

property shape

(n_mu, n_vp).

Type:

Velocity-grid point shape in XGC storage order

vp_edge_factors()[source]
vp_integration_weights()[source]

1D trapezoidal weights for the v_parallel axis (normalized units).

xgc_analysis.wall_curve module

Wall-polygon arclength utilities.

class xgc_analysis.wall_curve.WallCurve(points_rz: ndarray, *, verify_clockwise: bool = True, auto_reverse: bool = False)[source]

Bases: object

Closed wall polygon with arclength coordinate.

Parameters:
  • points_rz (np.ndarray) – Wall vertices as shape (n, 2) in clockwise order. The first vertex should not be repeated at the end.

  • verify_clockwise (bool) – Validate clockwise orientation and raise ValueError if violated.

  • auto_reverse (bool) – If True and orientation is counter-clockwise, reverse order instead of raising.

circular_distance(s1: float, s2: float) float[source]

Shortest arclength distance between two arclength values.

find_z0_crossings(*, z_tol: float = 1e-10) list[ZeroCrossing][source]

Find intersections of the closed curve with Z=0.

property n_vertices: int

Number of wall vertices.

property points: ndarray

Wall vertices (R,Z) in the stored order.

property s_vertex: ndarray

Arclength at each vertex (origin-shifted, modulo total length).

set_origin_at_inboard_midplane(r_axis: float, *, z_tol: float = 1e-10) float[source]

Set s=0 at the intersection with Z=0 and R<R_axis.

Returns:

The selected crossing arclength in the original coordinate.

Return type:

float

shortest_interval(s1: float, s2: float) tuple[float, float, bool][source]

Return shortest directed interval from s1 to s2.

Returns:

Interval on [0,L) where wraps=True means it crosses L->0.

Return type:

(s_start, s_end, wraps)

property total_length: float

Total closed-curve length.

class xgc_analysis.wall_curve.ZeroCrossing(s: float, r: float, segment_index: int)[source]

Bases: object

A crossing of the line Z=0 by the wall curve.

r: float
s: float
segment_index: int

Module contents