|
7 | 7 | #include <hydroc/wave_types.h> |
8 | 8 | #include <unsupported/Eigen/Splines> |
9 | 9 |
|
| 10 | +double GetEta(const Eigen::Vector3d& position, |
| 11 | + double time, |
| 12 | + double omega, |
| 13 | + double amplitude, |
| 14 | + double phase, |
| 15 | + double wavenumber) { |
| 16 | + // assuming wave direction along global X axis |
| 17 | + auto x_pos = position.x(); |
| 18 | + |
| 19 | + auto eta = amplitude * cos(wavenumber * x_pos - omega * time + phase); |
| 20 | + return eta; |
| 21 | +}; |
| 22 | + |
| 23 | +double GetEtaIrregular(const Eigen::Vector3d& position, |
| 24 | + double time, |
| 25 | + const Eigen::VectorXd& freqs_hz, |
| 26 | + const Eigen::VectorXd& spectral_densities, |
| 27 | + const Eigen::VectorXd& spectral_widths, |
| 28 | + const Eigen::VectorXd& wave_phases, |
| 29 | + const Eigen::VectorXd& wavenumbers) { |
| 30 | + // x position assuming wave direction along global X axis |
| 31 | + double x_pos = position.x(); |
| 32 | + |
| 33 | + double eta = 0.0; |
| 34 | + for (size_t i = 0; i < freqs_hz.size(); ++i) { |
| 35 | + auto amplitude = std::sqrt(2 * spectral_densities[i] * spectral_widths[i]); |
| 36 | + auto omega = 2 * M_PI * freqs_hz[i]; |
| 37 | + eta += GetEta(position, time, omega, amplitude, wave_phases[i], wavenumbers[i]); |
| 38 | + } |
| 39 | + return eta; |
| 40 | +} |
| 41 | + |
| 42 | +std::vector<double> GetEtaIrregularTimeSeries(const Eigen::Vector3d& position, |
| 43 | + const Eigen::VectorXd& time_index, |
| 44 | + const Eigen::VectorXd& freqs_hz, |
| 45 | + const Eigen::VectorXd& spectral_densities, |
| 46 | + const Eigen::VectorXd& spectral_widths, |
| 47 | + const Eigen::VectorXd& wave_phases, |
| 48 | + const Eigen::VectorXd& wavenumbers) { |
| 49 | + std::vector<double> eta(time_index.size(), 0.0); |
| 50 | + for (size_t j = 0; j < time_index.size(); ++j) { |
| 51 | + eta[j] = GetEtaIrregular(position, time_index[j], freqs_hz, spectral_densities, spectral_widths, wave_phases, |
| 52 | + wavenumbers); |
| 53 | + } |
| 54 | + return eta; |
| 55 | +} |
| 56 | + |
| 57 | +double ComputeWaveNumber(double omega, |
| 58 | + double water_depth, |
| 59 | + double g, |
| 60 | + double tolerance = 1e-6, |
| 61 | + int max_iterations = 100) { |
| 62 | + // Initial guess for wave number (using deep water approximation) |
| 63 | + double k = omega * omega / g; |
| 64 | + |
| 65 | + int iterations = 0; |
| 66 | + double error = 1.0; |
| 67 | + while (error > tolerance && iterations < max_iterations) { |
| 68 | + double tanh_kh = std::tanh(k * water_depth); |
| 69 | + double f = omega * omega - g * k * tanh_kh; |
| 70 | + double df = -2.0 * g * tanh_kh - g * k * water_depth * (1.0 - tanh_kh * tanh_kh); |
| 71 | + |
| 72 | + double delta_k = f / df; |
| 73 | + k -= delta_k; |
| 74 | + error = std::abs(delta_k); |
| 75 | + iterations++; |
| 76 | + } |
| 77 | + |
| 78 | + return k; |
| 79 | +} |
| 80 | + |
10 | 81 | Eigen::VectorXd NoWave::GetForceAtTime(double t) { |
11 | 82 | unsigned int dof = num_bodies_ * 6; |
12 | 83 | Eigen::VectorXd f(dof); |
@@ -41,12 +112,20 @@ void RegularWave::Initialize() { |
41 | 112 | excitation_force_phase_[body_offset + rowEx] = GetExcitationPhaseInterp(b, rowEx, 0, freq_index_des); |
42 | 113 | } |
43 | 114 | } |
| 115 | + |
| 116 | + wavenumber_ = ComputeWaveNumber(regular_wave_omega_, sim_data_.water_depth, sim_data_.g); |
44 | 117 | } |
45 | 118 |
|
46 | | -void RegularWave::AddH5Data(std::vector<HydroData::RegularWaveInfo>& reg_h5_data) { |
| 119 | +void RegularWave::AddH5Data(std::vector<HydroData::RegularWaveInfo>& reg_h5_data, |
| 120 | + HydroData::SimulationParameters& sim_data) { |
47 | 121 | wave_info_ = reg_h5_data; |
| 122 | + sim_data_ = sim_data; |
48 | 123 | } |
49 | 124 |
|
| 125 | +double RegularWave::GetElevation(const Eigen::Vector3d& position, double time) { |
| 126 | + return GetEta(position, time, regular_wave_omega_, regular_wave_amplitude_, regular_wave_phase_, wavenumber_); |
| 127 | +}; |
| 128 | + |
50 | 129 | Eigen::VectorXd RegularWave::GetForceAtTime(double t) { |
51 | 130 | unsigned int dof = num_bodies_ * 6; |
52 | 131 | Eigen::VectorXd f(dof); |
@@ -92,68 +171,12 @@ Eigen::VectorXd ComputeWaveNumbers(const Eigen::VectorXd& omegas, |
92 | 171 | double tolerance = 1e-6, |
93 | 172 | int max_iterations = 100) { |
94 | 173 | Eigen::VectorXd wavenumbers(omegas.size()); |
95 | | - |
96 | 174 | for (size_t i = 0; i < omegas.size(); ++i) { |
97 | | - double omega = omegas[i]; |
98 | | - |
99 | | - // Initial guess for wave number (using deep water approximation) |
100 | | - double k = omega * omega / g; |
101 | | - |
102 | | - int iterations = 0; |
103 | | - double error = 1.0; |
104 | | - while (error > tolerance && iterations < max_iterations) { |
105 | | - double tanh_kh = std::tanh(k * water_depth); |
106 | | - double f = omega * omega - g * k * tanh_kh; |
107 | | - double df = -2.0 * g * tanh_kh - g * k * water_depth * (1.0 - tanh_kh * tanh_kh); |
108 | | - |
109 | | - double delta_k = f / df; |
110 | | - k -= delta_k; |
111 | | - error = std::abs(delta_k); |
112 | | - iterations++; |
113 | | - } |
114 | | - |
115 | | - wavenumbers[i] = k; |
| 175 | + wavenumbers[i] = ComputeWaveNumber(omegas[i], water_depth, g, tolerance, max_iterations); |
116 | 176 | } |
117 | | - |
118 | 177 | return wavenumbers; |
119 | 178 | } |
120 | 179 |
|
121 | | -double GetFreeSurfaceElevation(const Eigen::VectorXd& freqs_hz, |
122 | | - const Eigen::VectorXd& spectral_densities, |
123 | | - const Eigen::VectorXd& spectral_widths, |
124 | | - const Eigen::VectorXd& wave_phases, |
125 | | - const Eigen::VectorXd& wavenumbers, |
126 | | - const Eigen::Vector3d& position, |
127 | | - double time_value, |
128 | | - double water_depth) { |
129 | | - // x position assuming wave direction along global X axis |
130 | | - double x_pos = position.x(); |
131 | | - |
132 | | - double eta = 0.0; |
133 | | - for (size_t i = 0; i < freqs_hz.size(); ++i) { |
134 | | - eta += std::sqrt(2 * spectral_densities[i] * spectral_widths[i]) * |
135 | | - std::cos(wavenumbers[i] * x_pos - 2 * M_PI * freqs_hz[i] * time_value + wave_phases[i]); |
136 | | - } |
137 | | - return eta; |
138 | | -} |
139 | | - |
140 | | -std::vector<double> GetFreeSurfaceElevationTimeSeries(const Eigen::VectorXd& freqs_hz, |
141 | | - const Eigen::VectorXd& spectral_densities, |
142 | | - const Eigen::VectorXd& spectral_widths, |
143 | | - const Eigen::VectorXd& wave_phases, |
144 | | - const Eigen::VectorXd& wavenumbers, |
145 | | - const Eigen::Vector3d& position, |
146 | | - const Eigen::VectorXd& time_index, |
147 | | - double water_depth) { |
148 | | - std::vector<double> eta(time_index.size(), 0.0); |
149 | | - for (size_t j = 0; j < time_index.size(); ++j) { |
150 | | - eta[j] += GetFreeSurfaceElevation(freqs_hz, spectral_densities, spectral_widths, wave_phases, wavenumbers, |
151 | | - position, time_index[j], water_depth); |
152 | | - } |
153 | | - |
154 | | - return eta; |
155 | | -} |
156 | | - |
157 | 180 | std::vector<std::array<double, 3>> CreateFreeSurface3DPts(const std::vector<double>& eta, |
158 | 181 | const Eigen::VectorXd& t_vec) { |
159 | 182 | std::vector<std::array<double, 3>> surface(t_vec.size() * 2); |
@@ -300,6 +323,11 @@ void IrregularWaves::AddH5Data(std::vector<HydroData::IrregularWaveInfo>& irreg_ |
300 | 323 | InitializeIRFVectors(); |
301 | 324 | } |
302 | 325 |
|
| 326 | +double IrregularWaves::GetElevation(const Eigen::Vector3d& position, double time) { |
| 327 | + return GetEtaIrregular(position, time, spectrum_frequencies_, spectral_densities_, spectral_widths_, wave_phases_, |
| 328 | + wavenumbers_); |
| 329 | +}; |
| 330 | + |
303 | 331 | Eigen::VectorXd IrregularWaves::GetForceAtTime(double t) { |
304 | 332 | unsigned int total_dofs = params_.num_bodies_ * 6; |
305 | 333 | Eigen::VectorXd f(total_dofs); |
@@ -420,7 +448,7 @@ void IrregularWaves::CreateSpectrum() { |
420 | 448 | } |
421 | 449 |
|
422 | 450 | // precompute wavenumbers |
423 | | - auto omegas = 2 * M_PI * spectrum_frequencies_; |
| 451 | + auto omegas = 2 * M_PI * spectrum_frequencies_; |
424 | 452 | wavenumbers_ = ComputeWaveNumbers(omegas, sim_data_.water_depth, sim_data_.g); |
425 | 453 |
|
426 | 454 | // Open a file stream for writing |
@@ -519,9 +547,8 @@ void IrregularWaves::CreateFreeSurfaceElevation() { |
519 | 547 | // position assumed at (0.0, 0.0, 0.0) |
520 | 548 | auto position = Eigen::Vector3d(0.0, 0.0, 0.0); |
521 | 549 | // get timeseries |
522 | | - free_surface_elevation_sampled_ = |
523 | | - GetFreeSurfaceElevationTimeSeries(spectrum_frequencies_, spectral_densities_, spectral_widths_, wave_phases_, |
524 | | - wavenumbers_, position, time_array, sim_data_.water_depth); |
| 550 | + free_surface_elevation_sampled_ = GetEtaIrregularTimeSeries( |
| 551 | + position, time_array, spectrum_frequencies_, spectral_densities_, spectral_widths_, wave_phases_, wavenumbers_); |
525 | 552 |
|
526 | 553 | // Apply ramp if ramp_duration is greater than 0 |
527 | 554 | if (params_.ramp_duration_ > 0.0) { |
|
0 commit comments