Source code for idstools.compute.wall

import logging
import time

import numpy as np

from idstools.utils.utility_functions import get_slice_from_array

logger = logging.getLogger(f"module.{__name__}")


[docs]def timeit_decorator(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() elapsed_time = end_time - start_time print(f"Function {func.__name__} took {elapsed_time:.4f} seconds") return result return wrapper
[docs]class WallCompute: def __init__(self, ids_object): self.ids_object = ids_object
[docs] def get_vessel_units(self, select_description2d=":", select_unit=":", name_filter=None): """ Retrieve vessel units information from the IDS object. Parameters ---------- select_description2d : str, optional A slice notation string to filter the description_2d list. Default is ":". select_unit : str, optional A slice notation string to filter the units list. Default is ":". name_filter : str, optional A string to filter units by name or identifier. Default is None. Returns ------- dict A dictionary containing information about the vessel units. The keys are the indices of the description_2d elements, and the values are dictionaries containing the name, description, and vessel units information. """ description_2ds = list(self.ids_object.description_2d) if select_description2d is not None: description_2ds = get_slice_from_array(description_2ds, select_description2d) description2d_infos = {} for description2d_index, description2d in enumerate(description_2ds): description2d_info = {} description2d_info["name"] = description2d.type.name description2d_info["description"] = description2d.type.description units = list(description2d.vessel.unit) if select_unit is not None: units = get_slice_from_array(units, select_unit) unit_infos = {} if units: for v_unit_index, v_unit in enumerate(units): unit_info = {} unit_info["name"] = v_unit.name if hasattr(v_unit, "identifier"): unit_info["identifier"] = v_unit.identifier else: unit_info["identifier"] = "" if hasattr(v_unit, "description"): unit_info["description"] = v_unit.description else: unit_info["description"] = "" if not v_unit.annular.centreline.r.has_value: logger.warning( f"{description2d_info['name']}-{unit_info['name']} has empty annular.centreline.r" ) unit_info["r"] = v_unit.annular.centreline.r if not v_unit.annular.centreline.z.has_value: logger.warning( f"{description2d_info['name']}-{unit_info['name']} has empty annular.centreline.z" ) unit_info["z"] = v_unit.annular.centreline.z if not v_unit.annular.thickness.has_value: logger.warning(f"{description2d_info['name']}-{unit_info['name']} has empty annular.thickness") unit_info["h"] = v_unit.annular.thickness if hasattr(v_unit.annular.centreline, "closed"): unit_info["closed"] = v_unit.annular.centreline.closed if v_unit.annular.centreline.closed: unit_info["r"] = np.append(unit_info["r"], unit_info["r"][0]) unit_info["z"] = np.append(unit_info["z"], unit_info["z"][0]) else: unit_info["closed"] = False unit_info["resistivity"] = v_unit.annular.resistivity unit_info["rectangle_coordinates"] = self.get_rectangle_coordinates( v_unit.annular.centreline.r, v_unit.annular.centreline.z, v_unit.annular.thickness, unit_info["closed"], ) if name_filter is not None: if ( name_filter.lower() in v_unit.name.lower() or name_filter.lower() in v_unit.identifier.lower() ): unit_infos[v_unit_index] = unit_info else: unit_infos[v_unit_index] = unit_info description2d_info["vesselunits"] = unit_infos description2d_infos[description2d_index] = description2d_info return description2d_infos
[docs] def get_limiter_units(self, select_description2d=":", select_unit=":"): """ Retrieve information about limiter units from the IDS object. Parameters: ----------- select_description2d : str, optional A slice notation string to select specific description_2d entries. Default is ":" (select all). select_unit : str, optional A slice notation string to select specific units within each description_2d. Default is ":" (select all). Returns: -------- description2d_infos : dict A dictionary where keys are indices of description_2d entries and values are dictionaries containing: - "name" : str The name of the description_2d type. - "description" : str The description of the description_2d type. - "limiterunits" : dict A dictionary where keys are indices of units and values are dictionaries containing: - "name" : str The name of the unit. - "description" : str The description of the unit (empty string if not available). - "r" : numpy.ndarray The r-coordinates of the unit's outline. - "z" : numpy.ndarray The z-coordinates of the unit's outline. - "closed" : bool Indicates if the unit is closed (default is False if not available). - "resistivity" : float The resistivity of the unit. """ description_2ds = list(self.ids_object.description_2d) if select_description2d is not None: description_2ds = get_slice_from_array(description_2ds, select_description2d) description2d_infos = {} for description2d_index, description2d in enumerate(description_2ds): description2d_info = {} description2d_info["name"] = description2d.type.name description2d_info["description"] = description2d.type.description units = list(description2d.limiter.unit) if select_unit is not None: units = get_slice_from_array(units, select_unit) unit_infos = {} if units: for l_unit_index, l_unit in enumerate(units): unit_info = {} unit_info["name"] = l_unit.name if hasattr(l_unit, "description"): unit_info["description"] = l_unit.description else: unit_info["description"] = "" unit_info["r"] = l_unit.outline.r unit_info["z"] = l_unit.outline.z if hasattr(l_unit, "closed"): unit_info["closed"] = l_unit.closed if l_unit.closed: unit_info["r"] = np.append(unit_info["r"], unit_info["r"][0]) unit_info["z"] = np.append(unit_info["z"], unit_info["z"][0]) else: unit_info["closed"] = False unit_info["resistivity"] = l_unit.resistivity if unit_info["closed"] is True: unit_info["r"] = np.append(unit_info["r"], unit_info["r"][0]) unit_info["z"] = np.append(unit_info["z"], unit_info["z"][0]) unit_infos[l_unit_index] = unit_info description2d_info["limiterunits"] = unit_infos description2d_infos[description2d_index] = description2d_info return description2d_infos
[docs] def get_inner_wall(self): """ Retrieves the inner wall coordinates from the IDS object. This method extracts the radial (r) and vertical (z) coordinates of the inner wall outline from the first limiter unit in the IDS object's 2D description. It appends the first coordinate to the end of the array to close the loop of the wall outline. Returns: tuple: A tuple containing two numpy arrays: rw (numpy.ndarray): Radial coordinates of the inner wall. zw (numpy.ndarray): Vertical coordinates of the inner wall. If an error occurs during extraction, returns None. """ try: rw = self.ids_object.description_2d[0].limiter.unit[0].outline.r zw = self.ids_object.description_2d[0].limiter.unit[0].outline.z if not hasattr(rw, "has_value") or not rw.has_value or len(rw) == 0: logger.warning("Inner wall r coordinates are empty") return None if not hasattr(zw, "has_value") or not zw.has_value or len(zw) == 0: logger.warning("Inner wall z coordinates are empty") return None rw = np.array(rw) zw = np.array(zw) if len(rw) != len(zw): logger.error(f"Mismatched array lengths: r={len(rw)}, z={len(zw)}") return None rw = np.concatenate((rw, [rw[0]])) zw = np.concatenate((zw, [zw[0]])) except Exception as e: logger.error(f"Exception occurred, detailed error {e}") return None return rw, zw
[docs] @staticmethod def get_rectangle_coordinates(r, z, h, closed=False): """ The function `get_rectangle_coordinates` calculates the coordinates of rectangles based on input parameters. Args: r: The parameter `r` in the `get_rectangle_coordinates` function represents the x-coordinates of the corners of the rectangles. z: The `z` parameter in the `get_rectangle_coordinates` function represents the vertical coordinates of the corners of rectangles. It is used to define the vertical positions of the rectangle vertices in the 3D space. h: The `h` parameter in the `get_rectangle_coordinates` function represents the height of the rectangle at each point. It is a list containing the height values for each rectangle. closed: The `closed` parameter in the `get_rectangle_coordinates` function is a boolean parameter that determines whether the rectangle should be closed or not. If `closed` is set to `True`, the function will close the rectangle by connecting the last point to the first point. If `closed` is set. Defaults to False Returns: The function `get_rectangle_coordinates` returns a list of tuples, where each tuple contains two lists. The two lists in each tuple represent the x and y coordinates of the vertices of a rectangle in 2D space. """ if len(r) == 0 or len(z) == 0 or len(h) == 0: return None rectangle_coordinates = [] if closed == 1: r = np.append(r, r[0]) z = np.append(z, z[0]) h = np.append(h, h[0]) for i in range(len(r) - 1): x1 = r[i + 1] - r[i] y1 = z[i + 1] - z[i] d = np.sqrt(x1**2 + y1**2) cs = x1 / d sn = y1 / d r1 = np.array([[cs, sn], [-sn, cs]]) a1 = np.dot(r1, (x1, y1)) half_h = h[i] * 0.5 p = [ (0.0, -half_h), (0.0, half_h), (a1[0], half_h), (a1[0], -half_h), ] rw = [] zw = [] r2 = np.array([[cs, -sn], [sn, cs]]) for item in p: w = np.dot(r2, item) + np.array([r[i], z[i]]) rw.append(w[0]) zw.append(w[1]) rw.append(rw[0]) zw.append(zw[0]) rectangle_coordinates.append((rw, zw)) return rectangle_coordinates