Source code for torx.analysis.lineouts.chord_lineouts_m

"""Provides functionality of chord/line segment lineouts."""
import numpy as np
import warnings
from numpy.polynomial import Polynomial
from torx.grid.grid_2d_m import Grid2D
from torx.equilibrium.equilibrium_m import EquilibriumBaseClass
from torx.analysis.lineouts.lineout_m import Lineout
from torx.analysis.lineouts.flux_surface_lineouts_m import FluxSurfaceLineout
from torx.geometry.line_geometry_m import intersect_lines
from torx.autodoc_decorators_m import autodoc_function

[docs] @autodoc_function def outboard_zaxis_chord( grid: Grid2D, equi: EquilibriumBaseClass, n_samples: int = 1000 ): """ Return equally spaced points along the outboard zaxis. It is a horizontal line from the magnetic axis outwards to large radius at geometric poloidal angle theta equals zero. """ r_start = equi.axis_r_norm z_start = equi.axis_z_norm r_end = grid.r_s.max() z_end = equi.axis_z_norm lineout = Lineout([r_start, r_end], [z_start, z_end]) lineout.find_points_on_grid(grid, n_samples=n_samples) return lineout
[docs] @autodoc_function def outboard_midplane_chord( grid: Grid2D, equi: EquilibriumBaseClass, n_samples: int = 1000, separatrix_index: int = None, ): """ Return equally spaced points at the outboard midplane. It is defined as a line going from the magnetic axis to the largest radial position of the separatrix. Shift very slightly inside to get just the confined-region separatrix. """ # TODO: Refactor the following block to be simpler matched_contours = equi.get_separatrix(grid.r_s, grid.z_s, level=0.999) if len(matched_contours) == 0: raise ValueError("No separatrix found") elif len(matched_contours) > 1: if separatrix_index is None: # Try auto find the correct separatrix closed = np.zeros(len(matched_contours), dtype=int) for i, _ in enumerate(matched_contours): # Checks if start and end point of the contour are the same if(np.abs(matched_contours[i][0,0] \ - matched_contours[i][-1,0]) < 1e-14 and np.abs(matched_contours[i][0,1] \ - matched_contours[i][-1,1]) < 1e-14): closed[i] = 1 # If single closed contour found close to the separatrix we take # that. Otherwise the choice is ambiguous and separatrix_index has # to be used. # NOTE: Even if multiple open contours and no closed one are found # it is not clear if get_separatrix failed or not. if np.sum(closed) == 1: idx_sep = np.where(closed == 1)[0][0] matched_contours = matched_contours[idx_sep] else: raise RuntimeError( f"Found {len(matched_contours)} contours for \ get_separatrix and could not auto-identify the correct \ one. Please identify which contour to use via the \ separatrix_index argument." ) else: matched_contours = matched_contours[separatrix_index] elif separatrix_index not in [0, None]: warnings.warn( "Only a single contour found. Ignoring separatrix_index argument", UserWarning, ) matched_contours = matched_contours[0] else: matched_contours = matched_contours[0] r_sep, z_sep = matched_contours.T i_omp = np.argmax(r_sep) r_start = equi.axis_r_norm z_start = equi.axis_z_norm # Linearly extrapolate to the end of the grid # NOTE: this will fail if you try to do it for a vertical line linear_extrap = Polynomial.fit( (r_start, r_sep[i_omp]), (z_start, z_sep[i_omp]), deg=1 ) lineout = Lineout( [r_start, grid.r_s.max()], [z_start, linear_extrap(grid.r_s.max())] ) lineout.find_points_on_grid(grid, n_samples=n_samples) return lineout
[docs] @autodoc_function def radial_line_chord(grid: Grid2D, equi: EquilibriumBaseClass, bounding_flux_surface: FluxSurfaceLineout, n_samples: int=100, theta=0.0): """ Return a radial lineout from the axis to a bounding flux surface. Creates a straight radial line along a poloidal angle starting from the magnetic axis. The end of the line is specified by a bounding flux surface lineout which can be either a closed or open flux surface. """ # Idea: Create a line that goes far from the starting point along the # specified poloidal angle. Then intersect with the bounding flux surface # to obtain a line from start to the flux surface. r_start = equi.axis_r_norm.values z_start = equi.axis_z_norm.values bounding_r = bounding_flux_surface.r_points bounding_z = bounding_flux_surface.z_points # Use twice the maximum distance of the bounding flux surface from the # magnetic axis for the far away point dist_from_axis = np.sqrt((bounding_r - r_start)**2 \ + (bounding_z - z_start)**2) radius = 2.0 * np.max(dist_from_axis) r_end = r_start + radius * np.cos(theta) z_end = z_start + radius * np.sin(theta) # Close the bounding line by adding the first element to the end # (required for correct intersection). Do only for closed flux surface. if(bounding_flux_surface.rho(equi)[0] <= 1.0): bounding_r = np.append(bounding_r, bounding_r[0]) bounding_z = np.append(bounding_z, bounding_z[0]) pint = intersect_lines(np.array([r_start, r_end]), np.array([z_start, z_end]), bounding_r, bounding_z, intersec_mode="closest") r_end = pint[0] z_end = pint[1] lineout = Lineout([r_start, r_end], [z_start, z_end]) lineout.find_points_on_grid(grid, n_samples=n_samples) return lineout