Source code for torx.analysis.lineouts.xpoint_lineouts_m

"""Provides lineouts starting from the X-point."""
from torx.analysis.vector_field_tracer_m import VectorFieldTracer
from torx.analysis.lineouts import Lineout
from torx.autodoc_decorators_m import autodoc_class

[docs] @autodoc_class class XPointLineout(Lineout): """Interpolates to a line perpendicular to Bpol close to the X-Point."""
[docs] def __init__( self, grid, equi, direction: str="lfs", xpoint_dist: float=1e-3, t_max: float=1000.0, find_points_on_grid: bool=True, n_samples: int=200, tolerance: float=1e-4, **integrator_kwargs ): """ Initialize the X-point lineout. Uses the X-Point information stored in the equilibrium to perform a RZ-trace perpendicular to the poloidal magnetic field. Via the 'direction' keyword four different lineout types are available: 1) 'lfs': The lineout originates slightly right of the X-Point and extends into the low-field side. 2) 'hfs': The lineout originates slightly left of the X-Point and extends into the high-field side. 3) 'up': The lineout originates slightly above the X-Point and extends to lower values of rho_poloidal. 3) 'down': The lineout originates slightly below the X-Point and extends to lower values of rho_poloidal. Note ---- The above mentioned initialization methods are well defined only for a standard single null equilibrium. Note ---- Due to possible additional flip in Z-direction it is not possible to automatically distinguish the X-Point lineout going into the private flux and core region. Hence only 'up' and 'down' are available. """ self.xpt_r_norm = float(equi.x_point_r_norm.values) self.xpt_z_norm = float(equi.x_point_z_norm.values) self.boundary_polygon = equi.get_boundary_polygon() if direction in ["lfs", "hfs"]: self.z_initial = self.xpt_z_norm vecfield = equi.magfield_vector_radial(grid.r_s, grid.z_s) if direction == "lfs": self.r_initial = self.xpt_r_norm + xpoint_dist if direction == "hfs": self.r_initial = self.xpt_r_norm - xpoint_dist elif direction in ["up", "down"]: self.r_initial = self.xpt_r_norm vecfield = -equi.magfield_vector_radial(grid.r_s, grid.z_s) if direction == "up": self.z_initial = self.xpt_z_norm + xpoint_dist elif direction == "down": self.z_initial = self.xpt_z_norm - xpoint_dist else: raise ValueError("Invalid direction indication, see doc-string!") self._integrator = VectorFieldTracer(vecfield) self._tolerance = tolerance r, z = self._find_points_from_rz_trace(t_max=t_max, **integrator_kwargs) self.r_points = r self.z_points = z super().__init__(self.r_points, self.z_points) if find_points_on_grid: self.find_points_on_grid(grid, n_samples=n_samples)
def _find_points_from_rz_trace( self, t_max: float=1000.0, **integrator_kwargs ): """ Find points along the radial unit vector field. Uses parametric trace in the RZ-plane. """ def in_vessel(t, state): x, y = state[0], state[1] return +1.0 if self.boundary_polygon.point_inside(x, y) else -1.0 in_vessel.terminal = True assert t_max > 0.0, \ f"Should always use a positive value for timeout_trace" sol = self._integrator.rz_integration( self.r_initial, self.z_initial, t_max=t_max, events=in_vessel, tolerance=self._tolerance, **integrator_kwargs ) return sol.y[0], sol.y[1]