@@ -2130,6 +2130,149 @@ def dirm(self, degrees=None):
21302130 return dirm
21312131
21322132
2133+ class WaveBinSpectrum (DisableComplexMixin , DirectionalBinSpectrum ):
2134+ """
2135+ Binned wave spectrum.
2136+
2137+ The ``WaveSpectrum`` class extends the :class:`~waveresponse.DirectionalBinSpectrum`
2138+ class, and is a two-dimentional frequency/(wave)direction grid. The spectrum values
2139+ represents spectrum density as a function of frequency, binned by direction.
2140+
2141+ Proper scaling is applied to ensure that the total "energy" remains constant at all times.
2142+
2143+ Parameters
2144+ ----------
2145+ freq : array-like
2146+ 1-D array of grid frequency coordinates. Positive and monotonically increasing.
2147+ dirs : array-like
2148+ 1-D array of grid direction coordinates. Positive and monotonically increasing.
2149+ Must cover the directional range [0, 360) degrees (or [0, 2 * numpy.pi) radians).
2150+ vals : array-like (N, M)
2151+ Spectrum density values associated with the grid. Should be a 2-D array
2152+ of shape (N, M), such that ``N=len(freq)`` and ``M=len(dirs)``.
2153+ freq_hz : bool
2154+ If frequency is given in 'Hz'. If ``False``, 'rad/s' is assumed.
2155+ degrees : bool
2156+ If direction is given in 'degrees'. If ``False``, 'radians' is assumed.
2157+ clockwise : bool
2158+ If positive directions are defined to be 'clockwise' (``True``) or 'counterclockwise'
2159+ (``False``). Clockwise means that the directions follow the right-hand rule
2160+ with an axis pointing downwards.
2161+ waves_coming_from : bool
2162+ If waves are 'coming from' the given directions. If ``False``, 'going towards'
2163+ convention is assumed.
2164+ """
2165+
2166+ def __init__ (self , * args , ** kwargs ):
2167+ super ().__init__ (* args , ** kwargs )
2168+
2169+ if np .any (np .iscomplex (self ._vals )):
2170+ raise ValueError ("Spectrum values can not be complex." )
2171+ elif np .any (self ._vals < 0.0 ):
2172+ raise ValueError ("Spectrum values must be positive." )
2173+
2174+ def __repr__ (self ):
2175+ return "WaveBinSpectrum"
2176+
2177+ @property
2178+ def hs (self ):
2179+ """
2180+ Significan wave height, Hs.
2181+
2182+ Calculated from the zeroth-order spectral moment according to:
2183+
2184+ ``hs = 4.0 * sqrt(m0)``
2185+
2186+ Notes
2187+ -----
2188+ The significant wave height is calculated according to equation (2.26) in
2189+ reference [1].
2190+
2191+ References
2192+ ----------
2193+ [1] 0. M. Faltinsen, (1990), "Sea loads on ships and offshore structures",
2194+ Cambridge University Press.
2195+ """
2196+ m0 = self .moment (0 )
2197+ return 4.0 * np .sqrt (m0 )
2198+
2199+ @property
2200+ def tp (self ):
2201+ """
2202+ Wave peak period in 'seconds'.
2203+
2204+ The period at which the 'non-directional' wave spectrum, ``S(f)``, has its maximum
2205+ value.
2206+ """
2207+ f , S = self .spectrum1d (axis = 1 , freq_hz = True )
2208+ fp = f [np .argmax (S )]
2209+ return 1.0 / fp
2210+
2211+ @staticmethod
2212+ def _mean_direction (dirs , spectrum ):
2213+ """
2214+ Mean spectrum direction.
2215+
2216+ Parameters
2217+ ----------
2218+ dirs : array-like
2219+ Directions in 'radians'.
2220+ spectrum : array-like
2221+ 1-D spectrum directional distribution.
2222+ """
2223+ sin = np .sum (np .sin (dirs ) * spectrum ) / len (dirs )
2224+ cos = np .sum (np .cos (dirs ) * spectrum ) / len (dirs )
2225+ return _robust_modulus (np .arctan2 (sin , cos ), 2.0 * np .pi )
2226+
2227+ def dirp (self , degrees = None ):
2228+ """
2229+ Wave peak direction.
2230+
2231+ Defined as the mean wave direction along the frequency corresponding to
2232+ the maximum value of the 'non-directional' spectrum.
2233+
2234+ Parameters
2235+ ----------
2236+ degrees : bool
2237+ If wave peak direction should be returned in 'degrees'. If ``False``,
2238+ the direction is returned in 'radians'. Defaults to original unit used
2239+ during initialization.
2240+ """
2241+
2242+ if degrees is None :
2243+ degrees = self ._degrees
2244+
2245+ _ , spectrum1d = self .spectrum1d (axis = 1 , freq_hz = False )
2246+
2247+ spectrum_peakfreq = self ._vals [np .argmax (spectrum1d ), :]
2248+
2249+ dirp = self ._mean_direction (self ._dirs , spectrum_peakfreq )
2250+
2251+ if degrees :
2252+ dirp = (180.0 / np .pi ) * dirp
2253+
2254+ return dirp
2255+
2256+ def dirm (self , degrees = None ):
2257+ """
2258+ Mean wave direction.
2259+
2260+ Parameters
2261+ ----------
2262+ degrees : bool
2263+ If mean wave direction should be returned in 'degrees'. If ``False``,
2264+ the direction is returned in 'radians'. Defaults to original unit used
2265+ during instantiation.
2266+ """
2267+
2268+ dirm = self ._mean_direction (* self .spectrum1d (axis = 0 , degrees = False ))
2269+
2270+ if degrees :
2271+ dirm = np .degrees (dirm )
2272+
2273+ return dirm
2274+
2275+
21332276def calculate_response (
21342277 rao , wave , heading , heading_degrees = False , coord_freq = "wave" , coord_dirs = "wave"
21352278):
0 commit comments