|
1 | | -function S=jonswap_spectrum(frequency,Tp,Hs,varargin) |
| 1 | +function S = jonswap_spectrum(frequency, Tp, Hs, gamma) |
2 | 2 |
|
3 | 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
4 | | -% Calculates JONSWAP spectrum from Hasselmann et al (1973) |
| 4 | +% |
| 5 | +% Calculates JONSWAP Spectrum from IEC TS 62600-2 ED2 Annex C.2 (2019) |
5 | 6 | % |
6 | 7 | % Parameters |
7 | 8 | % ------------ |
8 | | -% |
9 | | -% Frequency: float |
10 | | -% Wave frequency (Hz) |
| 9 | +% frequency: vector |
| 10 | +% Frequency [Hz] |
11 | 11 | % |
12 | 12 | % Tp: float |
13 | | -% Peak Period (s) |
| 13 | +% Peak period [s] |
14 | 14 | % |
15 | 15 | % Hs: float |
16 | | -% Significant Wave Height (s) |
| 16 | +% Significant wave height [m] |
17 | 17 | % |
18 | 18 | % gamma: float (optional) |
19 | | -% Gamma |
| 19 | +% Peak enhancement factor |
20 | 20 | % |
21 | 21 | % Returns |
22 | 22 | % --------- |
23 | | -% S: structure |
24 | | -% |
25 | | -% |
26 | | -% S.spectrum=Spectral Density (m^2/Hz) |
27 | | -% |
28 | | -% S.type=String of the spectra type, i.e. Bretschneider, |
29 | | -% time series, date stamp etc. |
| 23 | +% S: structure with fields |
| 24 | +% .spectrum = Spectral density [m^2/Hz] |
| 25 | +% .frequency = Frequency [Hz] |
| 26 | +% .type = 'JONSWAP (Hs,Tp)' |
30 | 27 | % |
31 | | -% S.frequency= frequency (Hz) |
32 | | -% |
33 | | -% S.Te |
34 | | -% |
35 | | -% S.Hm0 |
36 | | -% |
37 | | -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 28 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
38 | 29 |
|
39 | | -if (isa(frequency,'py.numpy.ndarray') ~= 1) |
40 | | - frequency = py.numpy.array(frequency); |
| 30 | +arguments |
| 31 | + frequency {mustBeNumeric, mustBeFinite} |
| 32 | + Tp {mustBeNumeric, mustBeFinite, mustBePositive} |
| 33 | + Hs {mustBeNumeric, mustBeFinite, mustBePositive} |
| 34 | + gamma {mustBeNumeric, mustBeFinite, mustBePositive} = [] |
41 | 35 | end |
42 | 36 |
|
43 | | -if nargin == 3 |
44 | | - S_py=py.mhkit.wave.resource.jonswap_spectrum(frequency,Tp,Hs); |
45 | | -elseif nargin == 4 |
46 | | - S_py=py.mhkit.wave.resource.jonswap_spectrum(frequency, Tp, Hs, pyargs('gamma', varargin{1})); |
| 37 | +% Ensure column vector and sort (match MHKiT-Python behavior) |
| 38 | +frequency = frequency(:); |
| 39 | +f = sort(frequency); |
| 40 | + |
| 41 | +% Constants (same as MHKiT-Python) |
| 42 | +B_PM = (5 / 4) * (1 / Tp)^4; |
| 43 | +A_PM = B_PM * (Hs / 2)^2; |
| 44 | + |
| 45 | +% Avoid divide by zero if the 0 frequency is provided |
| 46 | +% The zero frequency should always have 0 amplitude, otherwise |
| 47 | +% we end up with a mean offset when computing the surface elevation. |
| 48 | +S_f = zeros(size(f)); |
| 49 | +if f(1) == 0.0 |
| 50 | + inds = 2:length(f); % Skip first element like MHKiT-Python |
| 51 | +else |
| 52 | + inds = 1:length(f); % Use all elements |
| 53 | +end |
| 54 | + |
| 55 | +S_f(inds) = A_PM * f(inds).^(-5) .* exp(-B_PM * f(inds).^(-4)); |
| 56 | + |
| 57 | +% Gamma computation (match MHKiT-Python logic) |
| 58 | +if isempty(gamma) |
| 59 | + TpsqrtHs = Tp / sqrt(Hs); |
| 60 | + if TpsqrtHs <= 3.6 |
| 61 | + gamma = 5; |
| 62 | + elseif TpsqrtHs > 5 |
| 63 | + gamma = 1; |
| 64 | + else |
| 65 | + gamma = exp(5.75 - 1.15 * TpsqrtHs); |
| 66 | + end |
47 | 67 | end |
48 | 68 |
|
49 | | -S_py = typecast_from_mhkit_python(S_py); |
| 69 | +% Cutoff frequencies for gamma function (match MHKiT-Python) |
| 70 | +siga = 0.07; |
| 71 | +sigb = 0.09; |
| 72 | + |
| 73 | +% Peak frequency |
| 74 | +fp = 1 / Tp; |
| 75 | +lind = f <= fp; |
| 76 | +hind = f > fp; |
| 77 | +Gf = zeros(size(f)); |
| 78 | +Gf(lind) = gamma .^ exp(-((f(lind) - fp).^2) ./ (2 * siga^2 * fp^2)); |
| 79 | +Gf(hind) = gamma .^ exp(-((f(hind) - fp).^2) ./ (2 * sigb^2 * fp^2)); |
50 | 80 |
|
51 | | -S = struct(); |
| 81 | +C = 1 - 0.287 * log(gamma); |
| 82 | +Sf = C * S_f .* Gf; |
52 | 83 |
|
53 | | -S.frequency = S_py.index.data; |
54 | | -S.spectrum = S_py.data; |
55 | | -S.type = S_py.columns{1}; |
| 84 | +% Output structure (match MHKiT-Python naming style) |
| 85 | +name = sprintf('JONSWAP (%.1fm,%.1fs)', Hs, Tp); |
| 86 | +S.frequency = f; |
| 87 | +S.spectrum = Sf; |
| 88 | +S.type = name; |
| 89 | + |
| 90 | +end |
0 commit comments