@@ -207,19 +207,18 @@ double IrregularWaves::GetElevation(const Eigen::Vector3d& position, double time
207207 // x = position along wave propagation direction [m]
208208 // t = time [s]
209209 //
210- // Performance: amplitudes_ and angular_freqs_ are pre-computed to avoid
211- // repeated sqrt () and multiplication calls (critical for visualization) .
210+ // Performance: Uses Eigen's vectorized operations (SIMD) for the summation.
211+ // The cos () is applied element-wise and the dot product sums the result .
212212 // -------------------------------------------------------------------------
213213 const double x = position.x ();
214- double eta = 0.0 ;
215214
216- const Eigen::Index num_components = amplitudes_.size ();
217- for (Eigen::Index i = 0 ; i < num_components; ++i) {
218- const double phase = wavenumbers_[i] * x - angular_freqs_[i] * time + wave_phases_[i];
219- eta += amplitudes_[i] * std::cos (phase);
220- }
215+ // Vectorized phase computation: phase_i = k_i*x - ω_i*t + φ_i
216+ const Eigen::ArrayXd phases = wavenumbers_.array () * x
217+ - angular_freqs_.array () * time
218+ + wave_phases_.array ();
221219
222- return eta;
220+ // Vectorized elevation: η = Σ A_i * cos(phase_i)
221+ return (amplitudes_.array () * phases.cos ()).sum ();
223222}
224223
225224Eigen::Vector2d IrregularWaves::GetElevationGradientXY (const Eigen::Vector3d& position, double time) const {
@@ -240,19 +239,46 @@ Eigen::Vector2d IrregularWaves::GetElevationGradientXY(const Eigen::Vector3d& po
240239 //
241240 // Since waves propagate only in the +X direction, ∂η/∂y = 0.
242241 // The surface normal can be computed as: n = normalize(-∂η/∂x, -∂η/∂y, 1)
242+ //
243+ // Performance: Uses Eigen's vectorized operations (SIMD) for the summation.
243244 // -------------------------------------------------------------------------
244245 const double x = position.x ();
245- double deta_dx = 0.0 ;
246246
247- const Eigen::Index num_components = amplitudes_.size ();
248- for (Eigen::Index i = 0 ; i < num_components; ++i) {
249- const double phase = wavenumbers_[i] * x - angular_freqs_[i] * time + wave_phases_[i];
250- deta_dx -= amplitudes_[i] * wavenumbers_[i] * std::sin (phase);
251- }
247+ // Vectorized phase computation: phase_i = k_i*x - ω_i*t + φ_i
248+ const Eigen::ArrayXd phases = wavenumbers_.array () * x
249+ - angular_freqs_.array () * time
250+ + wave_phases_.array ();
251+
252+ // Vectorized gradient: ∂η/∂x = -Σ A_i * k_i * sin(phase_i)
253+ const double deta_dx = -(amplitudes_.array () * wavenumbers_.array () * phases.sin ()).sum ();
252254
253255 return Eigen::Vector2d (deta_dx, 0.0 );
254256}
255257
258+ double IrregularWaves::GetElevationForVisualization (const Eigen::Vector3d& position,
259+ double time,
260+ int max_components) const {
261+ // If no pre-computed amplitudes or max_components covers all, use full calculation.
262+ const Eigen::Index num_total = amplitudes_.size ();
263+ if (num_total == 0 ) {
264+ return GetEtaIrregular (position, time, spectrum_frequencies_, spectral_densities_,
265+ spectral_widths_, wave_phases_, wavenumbers_);
266+ }
267+
268+ // Determine how many components to use.
269+ const Eigen::Index n = (max_components <= 0 || max_components >= num_total)
270+ ? num_total
271+ : static_cast <Eigen::Index>(max_components);
272+
273+ // Use Eigen head() to get first n elements - still vectorized (SIMD).
274+ const double x = position.x ();
275+ const Eigen::ArrayXd phases = wavenumbers_.head (n).array () * x
276+ - angular_freqs_.head (n).array () * time
277+ + wave_phases_.head (n).array ();
278+
279+ return (amplitudes_.head (n).array () * phases.cos ()).sum ();
280+ }
281+
256282Eigen::VectorXd IrregularWaves::GetForceAtTime (double t) {
257283 unsigned int total_dofs = params_.num_bodies_ * 6 ;
258284 Eigen::VectorXd f (total_dofs);
0 commit comments