Source code for mhkit.river.performance

"""
Computes device metrics such as equivalent diameter, tip speed ratio,
and capture area. Calculations are based on IEC TS 62600-300:2019 ED1.

"""

from typing import Union, Tuple, List
import numpy as np


[docs] def circular(diameter: Union[int, float]) -> Tuple[float, float]: """ Calculates the equivalent diameter and projected capture area of a circular turbine Parameters ------------ diameter : int/float Turbine diameter [m] Returns --------- equivalent_diameter : float Equivalent diameter [m] projected_capture_area : float Projected capture area [m^2] """ if not isinstance(diameter, (int, float)): raise TypeError(f"diameter must be of type int or float. Got: {type(diameter)}") equivalent_diameter = diameter projected_capture_area = (1 / 4) * np.pi * (equivalent_diameter**2) return equivalent_diameter, projected_capture_area
[docs] def ducted(duct_diameter: Union[int, float]) -> Tuple[float, float]: """ Calculates the equivalent diameter and projected capture area of a ducted turbine Parameters ------------ duct_diameter : int/float Duct diameter [m] Returns --------- equivalent_diameter : float Equivalent diameter [m] projected_capture_area : float Projected capture area [m^2] """ if not isinstance(duct_diameter, (int, float)): raise TypeError( f"duct_diameter must be of type int or float. Got: {type(duct_diameter)}" ) equivalent_diameter = duct_diameter projected_capture_area = (1 / 4) * np.pi * (equivalent_diameter**2) return equivalent_diameter, projected_capture_area
[docs] def rectangular(h: Union[int, float], w: Union[int, float]) -> Tuple[float, float]: """ Calculates the equivalent diameter and projected capture area of a retangular turbine Parameters ------------ h : int/float Turbine height [m] w : int/float Turbine width [m] Returns --------- equivalent_diameter : float Equivalent diameter [m] projected_capture_area : float Projected capture area [m^2] """ if not isinstance(h, (int, float)): raise TypeError(f"h must be of type int or float. Got: {type(h)}") if not isinstance(w, (int, float)): raise TypeError(f"w must be of type int or float. Got: {type(w)}") equivalent_diameter = np.sqrt(4.0 * h * w / np.pi) projected_capture_area = h * w return equivalent_diameter, projected_capture_area
[docs] def multiple_circular(diameters: List[Union[int, float]]) -> Tuple[float, float]: """ Calculates the equivalent diameter and projected capture area of a multiple circular turbine Parameters ------------ diameters: list List of device diameters [m] Returns --------- equivalent_diameter : float Equivalent diameter [m] projected_capture_area : float Projected capture area [m^2] """ if not isinstance(diameters, list): raise TypeError(f"diameters must be of type list. Got: {type(diameters)}") diameters_squared = [x**2 for x in diameters] equivalent_diameter = np.sqrt(sum(diameters_squared)) projected_capture_area = 0.25 * np.pi * sum(diameters_squared) return equivalent_diameter, projected_capture_area
[docs] def tip_speed_ratio( rotor_speed: Union[np.ndarray, List[Union[int, float]]], rotor_diameter: Union[int, float], inflow_speed: Union[np.ndarray, List[Union[int, float]]], ) -> np.ndarray: """ Function used to calculate the tip speed ratio (TSR) of a MEC device with rotor Parameters ----------- rotor_speed : numpy array Rotor speed [revolutions per second] rotor_diameter : float/int Diameter of rotor [m] inflow_speed : numpy array Velocity of inflow condition [m/s] Returns -------- tip_speed_ratio_values : numpy array Calculated tip speed ratio (TSR) """ try: rotor_speed = np.asarray(rotor_speed) except (ValueError, TypeError) as exc: raise TypeError("rotor_speed must be convertible to np.ndarray") from exc try: inflow_speed = np.asarray(inflow_speed) except (ValueError, TypeError) as exc: raise TypeError("inflow_speed must be convertible to np.ndarray") from exc if not isinstance(rotor_diameter, (float, int)): raise TypeError( f"rotor_diameter must be of type int or float. Got: {type(rotor_diameter)}" ) rotor_velocity = rotor_speed * np.pi * rotor_diameter tip_speed_ratio_values = rotor_velocity / inflow_speed return tip_speed_ratio_values
[docs] def power_coefficient( power: Union[np.ndarray, List[Union[int, float]]], inflow_speed: Union[np.ndarray, List[Union[int, float]]], capture_area: Union[int, float], rho: Union[int, float], ) -> np.ndarray: """ Function that calculates the power coefficient of MEC device Parameters ----------- power : numpy array Power output signal of device after losses [W] inflow_speed : numpy array Speed of inflow [m/s] capture_area : float/int Projected area of rotor normal to inflow [m^2] rho : float/int Density of environment [kg/m^3] Returns -------- power_coeff : numpy array Power coefficient of device [-] """ try: power = np.asarray(power) except (ValueError, TypeError) as exc: raise TypeError("power must be convertible to np.ndarray") from exc try: inflow_speed = np.asarray(inflow_speed) except (ValueError, TypeError) as exc: raise TypeError("inflow_speed must be convertible to np.ndarray") from exc if not isinstance(capture_area, (float, int)): raise TypeError( f"capture_area must be of type int or float. Got: {type(capture_area)}" ) if not isinstance(rho, (float, int)): raise TypeError(f"rho must be of type int or float. Got: {type(rho)}") # Predicted power from inflow power_in = 0.5 * rho * capture_area * inflow_speed**3 power_coeff = power / power_in return power_coeff