Skip to content

Commit 0c6bec7

Browse files
authored
Update WaveSpectrumShared.h
1 parent 5da5f16 commit 0c6bec7

1 file changed

Lines changed: 56 additions & 16 deletions

File tree

src/spectrum/WaveSpectrumShared.h

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,13 @@ inline double smoothstep01(double x) {
106106
inline double lowfreq_taper(double f, double f_cut) {
107107
if (!(f_cut > 0.0)) return 1.0;
108108

109-
const double f0 = 0.72 * f_cut;
110-
const double f1 = 1.20 * f_cut;
109+
// Gentler taper for medium/high seas.
110+
const double f0 = 0.45 * f_cut;
111+
const double f1 = 1.10 * f_cut;
111112

112113
if (f <= f0) {
113114
const double r = std::clamp(f / std::max(f0, 1e-12), 0.0, 1.0);
114-
return std::pow(r, 6.0);
115+
return std::pow(r, 3.0);
115116
}
116117
if (f >= f1) return 1.0;
117118

@@ -132,10 +133,13 @@ inline void smooth_logfreq_3tap_inplace(SpectrumLike& spectrum,
132133

133134
auto wpair = [&](int i) {
134135
const double eps = 1e-12;
136+
135137
const double x_im1 = (i > 0)
136138
? std::log(std::max(freqs[i - 1], eps))
137139
: std::log(std::max(freqs[i], eps));
140+
138141
const double x_i = std::log(std::max(freqs[i], eps));
142+
139143
const double x_ip1 = (i < Nfreq - 1)
140144
? std::log(std::max(freqs[i + 1], eps))
141145
: std::log(std::max(freqs[i], eps));
@@ -167,15 +171,41 @@ inline void smooth_logfreq_3tap_inplace(SpectrumLike& spectrum,
167171
}
168172

169173
template<int Nfreq>
170-
inline double estimate_lowfreq_cut_from_accel(const std::array<double, Nfreq>& S_aa_meas,
174+
inline double estimate_lowfreq_cut_from_accel(const std::array<double, Nfreq>& S_aa_true,
171175
const std::array<double, Nfreq>& freqs,
172176
double Tblk,
173177
double hp_f0_hz) {
178+
if (Nfreq < 4) {
179+
return std::max({
180+
1.10 * freqs[0],
181+
1.8 / std::max(Tblk, 1e-12),
182+
1.35 * hp_f0_hz
183+
});
184+
}
185+
186+
// Use partially integrated pseudo-velocity-like spectrum to avoid
187+
// right-shifting the cutoff in medium/high sea states.
188+
const double f_floor = std::max({
189+
1.10 * freqs[0],
190+
1.80 / std::max(Tblk, 1e-12),
191+
1.35 * hp_f0_hz
192+
});
193+
194+
const double f_pre = std::max({
195+
0.85 * hp_f0_hz,
196+
1.20 / std::max(Tblk, 1e-12),
197+
0.80 * f_floor
198+
});
199+
const double lam_pre = 2.0 * M_PI * f_pre;
200+
174201
std::array<double, Nfreq> E{};
175202
std::array<double, Nfreq> Es{};
176203

177204
for (int i = 0; i < Nfreq; ++i) {
178-
E[i] = std::max(0.0, S_aa_meas[i]) * std::max(freqs[i], 1e-12);
205+
const double f = std::max(freqs[i], 1e-12);
206+
const double w = 2.0 * M_PI * f;
207+
const double S_mid = std::max(0.0, S_aa_true[i]) / (w * w + lam_pre * lam_pre);
208+
E[i] = f * S_mid;
179209
}
180210

181211
Es[0] = 0.75 * E[0] + 0.25 * E[1];
@@ -184,12 +214,6 @@ inline double estimate_lowfreq_cut_from_accel(const std::array<double, Nfreq>& S
184214
}
185215
Es[Nfreq - 1] = 0.25 * E[Nfreq - 2] + 0.75 * E[Nfreq - 1];
186216

187-
const double f_floor = std::max({
188-
1.35 * freqs[0],
189-
2.8 / std::max(Tblk, 1e-12),
190-
2.2 * hp_f0_hz
191-
});
192-
193217
int i_floor = 0;
194218
while (i_floor + 1 < Nfreq && freqs[i_floor + 1] < f_floor) ++i_floor;
195219

@@ -215,16 +239,30 @@ inline double estimate_lowfreq_cut_from_accel(const std::array<double, Nfreq>& S
215239
}
216240
}
217241

242+
double f_left_half = freqs[i_floor];
243+
for (int i = i_peak; i >= i_floor; --i) {
244+
if (Es[i] <= 0.5 * e_peak) {
245+
f_left_half = freqs[i];
246+
break;
247+
}
248+
}
249+
250+
double left_width = std::log(std::max(freqs[i_peak], 1e-12) / std::max(f_left_half, 1e-12));
251+
left_width = std::clamp(left_width, 0.05, 1.50);
252+
253+
const double rel_cut = std::clamp(0.39 - 0.13 * left_width, 0.22, 0.38);
254+
218255
const bool valley_is_good =
219256
(i_valley > i_floor) &&
220257
(e_valley < 0.82 * e_peak) &&
221258
(freqs[i_valley] < 0.88 * freqs[i_peak]);
222259

223260
double f_cut = valley_is_good
224-
? freqs[i_valley]
225-
: std::max(f_floor, 0.58 * freqs[i_peak]);
261+
? std::max(f_floor, 0.85 * freqs[i_valley])
262+
: std::max(f_floor, rel_cut * freqs[i_peak]);
226263

227-
f_cut = std::clamp(f_cut, f_floor, 0.90 * freqs[i_peak]);
264+
f_cut = std::min(f_cut, 0.65 * freqs[i_peak]);
265+
f_cut = std::max(f_cut, f_floor);
228266
return f_cut;
229267
}
230268

@@ -236,6 +274,7 @@ inline void suppress_lowfreq_from_cut_inplace(SpectrumLike& spectrum,
236274

237275
int i_cut = 0;
238276
while (i_cut + 1 < Nfreq && freqs[i_cut + 1] <= f_cut_hz) ++i_cut;
277+
if (i_cut <= 0) return;
239278

240279
std::array<double, Nfreq> E{};
241280
for (int i = 0; i < Nfreq; ++i) {
@@ -247,9 +286,9 @@ inline void suppress_lowfreq_from_cut_inplace(SpectrumLike& spectrum,
247286
const double E_ref = std::max(E[i_ref], 1e-18);
248287

249288
double prev = E_ref;
250-
constexpr double shape_pow = 4.8;
289+
constexpr double shape_pow = 3.0;
251290

252-
for (int i = i_cut; i >= 0; --i) {
291+
for (int i = i_cut - 1; i >= 0; --i) {
253292
const double r = std::clamp(freqs[i] / f_ref, 0.0, 1.0);
254293
const double cap = E_ref * std::pow(r, shape_pow);
255294

@@ -289,6 +328,7 @@ inline double estimate_fp_with_guard(const SpectrumLike& spectrum,
289328
const double f0 = freqs[k - 1];
290329
const double f1 = freqs[k];
291330
const double f2 = freqs[k + 1];
331+
292332
if (f0 <= 0.0 || f1 <= 0.0 || f2 <= 0.0) return f1;
293333

294334
const double x0 = std::log(f0);

0 commit comments

Comments
 (0)