Source code for torx.specializations.grillix.trunk.polars_m

"""Contains functionality to interface polars."""
import xarray as xr
import numpy as np
from pathlib import Path
from inspect import getmodule
from ..operators.csr_operators_m import csr_operator
import typing
from torx.autodoc_decorators_m import autodoc_class

[docs] @autodoc_class class Polars: """Low-level interface to the grillix/trunk/polars.nc file."""
[docs] @classmethod def from_filepath(cls, filepath: Path): """Initialize from top-level filepath.""" return cls(filepath / "trunk" / "polars.nc")
[docs] def __init__(self, polars_file): """Initialize the polars.""" self._dataset = xr.open_dataset(polars_file) self.grid = xr.open_dataset(polars_file, group="grid") self._cart_to_polar = xr.open_dataset(polars_file, group="cart_to_polar") self._surface_average = xr.open_dataset(polars_file, group="surface_average") self._flux_surface_average = xr.open_dataset( polars_file, group="flux_surface_average" )
@property def intorder(self) -> int: """Polar integration order.""" return self._dataset.intorder @property def phi(self) -> int: """Toroidal angle phi of this polar grid.""" return self.grid.phi @property def rhopol_min(self) -> float: """Minimum rho value of polar grid.""" return self.grid.rhopol_min @property def rhopol_max(self) -> float: """Maximum rho value of polar grid.""" return self.grid.rhopol_max @property def drho(self) -> float: """Radial spacing of polar grid (in units of rho).""" return self.grid.drho @property def dtheta(self) -> float: """Angular spacing of polar grid.""" return self.grid.dtheta @property def rho(self) -> xr.DataArray: """Rho values of polar grid.""" return self.grid["rho"] @property def theta(self) -> xr.DataArray: """Theta values of polar grid.""" return self.grid["theta"] @property def xpol(self) -> xr.DataArray: """R values of polar grid points.""" return self.grid["xpol"] @property def ypol(self) -> xr.DataArray: """Z values of polar grid points.""" return self.grid["ypol"]
[docs] def cart_to_polar( self, input_array: xr.DataArray = None ) -> typing.Union[xr.Dataset, xr.DataArray]: """Map the input array onto the polar grid.""" if input_array is None: return self._cart_to_polar return self.points_to_polars(csr_operator(self._cart_to_polar, input_array))
[docs] def surface_average( self, input_array: xr.DataArray = None ) -> typing.Union[xr.Dataset, xr.DataArray]: """Perform a surface integral.""" if input_array is None: return self._surface_average output_array = csr_operator(self._surface_average, input_array) return output_array.rename(points="rho").assign_coords(rho=self.rho.values)
[docs] def flux_surface_average( self, input_array: xr.DataArray = None ) -> typing.Union[xr.Dataset, xr.DataArray]: """ Perform a volume integral. For an infinitesimal volume centered on flux surface. This is useful is you want to look at fluxes through a surface """ if input_array is None: return self._flux_surface_average output_array = csr_operator(self._flux_surface_average, input_array) return output_array.rename(points="rho").assign_coords(rho=self.rho.values)
[docs] def points_to_polars(self, input_array) -> xr.DataArray: """ Reshapes points to polars. Output the polar operators is a 1D array of rho * theta. To visualize the result, we need to reshape our array. """ def reshape(array, rho_size, theta_size): return array.reshape(rho_size, theta_size) output_array = xr.apply_ufunc( reshape, input_array, kwargs=dict(rho_size=self.rho.size, theta_size=self.theta.size), keep_attrs=True, input_core_dims=[ ["points"], ], output_core_dims=[ ["rho", "theta"], ], vectorize=True, dask="parallelized", dask_gufunc_kwargs={ "output_sizes": dict(rho=self.rho.size, theta=self.theta.size) }, output_dtypes=[np.float64], ).assign_coords(rho=self.rho.values, theta=self.theta.values) return output_array