This page was generated from docs/notebooks/plasma/edge_plasma.ipynb.
Download notebook.

Edge Plasma profiles

This notebook demonstrates how to load and visualize edge plasma profiles using the cherab.imas interface. Here, we propose how to visualize edge plasmas with grid meshes defined in the IMAS data structure.

The example test data was calculated by JINTRAC for an ITER 15 MA H-mode scenario.

Prerequisites: Pooch must be installed to download the example data.

[1]:
import numpy as np
from imas import DBEntry
from matplotlib import pyplot as plt
from matplotlib.colors import SymLogNorm
from rich import print as rprint

from cherab.imas.datasets import iter_jintrac
from cherab.imas.ids.common import get_ids_time_slice
from cherab.imas.ids.common.ggd import load_grid
from cherab.imas.ids.edge_profiles import load_edge_species

# Set dark background for plots
plt.style.use("dark_background")
22:32:21 CRITICAL Could not import 'imas_core': No module named 'imas_core'. Some functionality is not available. @imas_interface.py:34

Define a function to plot edge plasma profiles

[2]:
def plot_grid_quantity(
    grid,
    quantity,
    title="",
    clabel="",
    logscale=False,
    symmetric=False,
):
    """Plot a quantity defined on a grid."""
    ax = grid.plot_mesh(data=quantity)

    if logscale:
        # Plot lowest values (mainly 0's) on linear map, as log(0) = -inf.
        linthresh = np.percentile(np.unique(quantity), 1)
        norm = SymLogNorm(
            linthresh=float(max(linthresh, 1.0e-10 * quantity.max())),
            base=10,
        )
        ax.collections[0].set_norm(norm)

    if symmetric:
        vmax = np.abs(quantity.max())
        ax.collections[0].set_clim(-vmax, vmax)
        ax.collections[0].set_cmap("berlin")
    else:
        ax.collections[0].set_cmap("gnuplot")

    ax.set_title(title)
    ax.set_xlabel("$R$ [m]")
    ax.set_ylabel("$Z$ [m]")
    cbar = plt.colorbar(ax.collections[0], ax=ax, aspect=40)
    cbar.set_label(clabel)
    fig = ax.get_figure()
    fig.set_size_inches((4, 6))

    return fig

Retrieve ITER JINTRAC sample data

[3]:
path = iter_jintrac()
Downloading file 'iter_scenario_53298_seq1_DD4.nc' from 'doi:10.5281/zenodo.17062699/iter_scenario_53298_seq1_DD4.nc' to '/home/runner/.cache/cherab/imas'.

Load grid and species data

Select grid subset

In “edge_profiles” IDS, there are multiple grid subsets defined. Here, we choose the "cells" subset to visualize the edge plasma profiles.

[4]:
# Load edge_profiles IDs
with DBEntry(path, "r") as entry:
    ids = get_ids_time_slice(
        entry,
        "edge_profiles",
        time=0,
    )

# Load grid object
grid, subsets, subset_id = load_grid(
    ids.grid_ggd[0],
    with_subsets=True,
)

# Print available grid subsets
rprint("Available grid subsets:", subset_id)

# Extract only "cells" subset
grid = grid.subset(subsets["cells"])
22:32:26 INFO     Parsing data dictionary version 4.1.0 @dd_zip.py:89
22:32:26 INFO     Parsing data dictionary version 4.0.0 @dd_zip.py:89
/tmp/ipykernel_15254/3942360383.py:3: RuntimeWarning: The 'get_slice' method is not implemented for the URI '/home/runner/.cache/cherab/imas/iter_scenario_53298_seq1_DD4.nc'. Falling back to 'get' method to retrieve the entire IDS.
  ids = get_ids_time_slice(
Warning! Unable to verify that the cell nodes are in the winging order.
Available grid subsets:
{
    'cells': np.int32(5),
    'core': np.int32(22),
    'sol': np.int32(23),
    'inner_divertor': np.int32(25),
    'outer_divertor': np.int32(24)
}

Load edge species data

[5]:
composition = load_edge_species(
    ids.ggd[0],
    grid_subset_index=subset_id["cells"],
)
Warning! Using average ion temperature for the DT ion.
Warning! Using average ion temperature for the He+1 ion.
Warning! Using average ion temperature for the He+2 ion.
Warning! Using average ion temperature for the Ne(bundle 1) ion.
Warning! Using average ion temperature for the Ne(bundle 5) ion.
Warning! Using average ion temperature for the W(bundle 1) ion.
Warning! Using average ion temperature for the W(bundle 6) ion.
Warning! Using average ion temperature for the Ne(bundle 2) ion_bundle.
Warning! Using average ion temperature for the Ne(bundle 3) ion_bundle.
Warning! Using average ion temperature for the Ne(bundle 4) ion_bundle.
Warning! Using average ion temperature for the W(bundle 2) ion_bundle.
Warning! Using average ion temperature for the W(bundle 3) ion_bundle.
Warning! Using average ion temperature for the W(bundle 4) ion_bundle.
Warning! Using average ion temperature for the W(bundle 5) ion_bundle.

Plot edge plasma profiles

Grid mesh

[6]:
fig, ax = plt.subplots(dpi=150, figsize=(4.0, 6.0), layout="constrained")
ax = grid.plot_mesh(ax=ax)
ax.set_xlabel("$R$ [m]")
ax.set_ylabel("$Z$ [m]");
../../_images/notebooks_plasma_edge_plasma_12_0.png

Electron profiles

[7]:
# Electron density
fig = plot_grid_quantity(
    grid,
    composition["electron"]["density"],
    title="Electron density, $n_\\mathrm{e}$ [m$^{-3}$]",
    logscale=True,
)

# Electron temperature
fig = plot_grid_quantity(
    grid,
    composition["electron"]["temperature"],
    title="Electron temperature, $T_\\mathrm{e}$ [eV]",
    logscale=True,
)
../../_images/notebooks_plasma_edge_plasma_14_0.png
../../_images/notebooks_plasma_edge_plasma_14_1.png

Species profiles

[8]:
for stype in {"ion", "molecule"}:
    for species_id, profiles in composition[stype].items():
        d = {first: second for first, second in species_id}
        charge = int(round(d["z"]))
        if stype == "ion":
            element = d["element"]
        else:
            element = d["elements"][0]

        if charge == 0:
            name = d["name"]
        elif charge == 1:
            if "+" or "bundle" in d["name"]:
                name = element.symbol
            else:
                name = d["name"]
            name = f"{name}$^+$"
        else:
            if "+" or "bundle" in d["name"]:
                name = element.symbol
            else:
                name = d["name"]
            name = f"{name}$^{{{charge}+}}$"

        # Plot density
        fig = plot_grid_quantity(
            grid,
            profiles["density"],
            title=f"{name} density [m$^{{-3}}$]",
            logscale=True,
        )

        if element.atomic_number == 1:
            # Plot temperature
            temperature = profiles["temperature"]
            if np.any(temperature):
                fig = plot_grid_quantity(
                    grid,
                    profiles["temperature"],
                    title=f"{name} temperature [eV]",
                    logscale=True,
                )

            if charge:
                # Plot velocity profiles
                vpar = profiles["velocity_parallel"]
                if np.any(vpar):
                    fig = plot_grid_quantity(
                        grid,
                        vpar,
                        title=f"{name} parallel velocity [m/s]",
                        symmetric=True,
                    )
            else:
                vrad = profiles["velocity_radial"]
                if np.any(vrad):
                    fig = plot_grid_quantity(
                        grid,
                        vrad,
                        title=f"{name} radial velocity [m/s]",
                        symmetric=True,
                    )
                vpol = profiles["velocity_poloidal"]
                if np.any(vpol):
                    fig = plot_grid_quantity(
                        grid,
                        vrad,
                        title=f"{name} poloidal velocity [m/s]",
                        symmetric=True,
                    )
                vtor = profiles["velocity_phi"]
                if np.any(vtor):
                    fig = plot_grid_quantity(
                        grid,
                        vtor,
                        title=f"{name} toroidal velocity [m/s]",
                        symmetric=True,
                    )
../../_images/notebooks_plasma_edge_plasma_16_0.png
../../_images/notebooks_plasma_edge_plasma_16_1.png
../../_images/notebooks_plasma_edge_plasma_16_2.png
../../_images/notebooks_plasma_edge_plasma_16_3.png
../../_images/notebooks_plasma_edge_plasma_16_4.png
../../_images/notebooks_plasma_edge_plasma_16_5.png
../../_images/notebooks_plasma_edge_plasma_16_6.png
../../_images/notebooks_plasma_edge_plasma_16_7.png
../../_images/notebooks_plasma_edge_plasma_16_8.png
../../_images/notebooks_plasma_edge_plasma_16_9.png
../../_images/notebooks_plasma_edge_plasma_16_10.png
../../_images/notebooks_plasma_edge_plasma_16_11.png
../../_images/notebooks_plasma_edge_plasma_16_12.png
../../_images/notebooks_plasma_edge_plasma_16_13.png
../../_images/notebooks_plasma_edge_plasma_16_14.png
../../_images/notebooks_plasma_edge_plasma_16_15.png
../../_images/notebooks_plasma_edge_plasma_16_16.png
../../_images/notebooks_plasma_edge_plasma_16_17.png