Skip to content

Commit e45a442

Browse files
committed
Unify eta calculations and add getters
1 parent b263343 commit e45a442

3 files changed

Lines changed: 101 additions & 64 deletions

File tree

include/hydroc/wave_types.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class WaveBase {
6565
*/
6666
virtual Eigen::VectorXd GetForceAtTime(double t) = 0;
6767
virtual WaveMode GetWaveMode() = 0;
68+
69+
virtual double GetElevation(const Eigen::Vector3d& position, double time) = 0;
6870
};
6971

7072
/**
@@ -87,6 +89,7 @@ class NoWave : public WaveBase {
8789
*/
8890
Eigen::VectorXd GetForceAtTime(double t) override;
8991
WaveMode GetWaveMode() override { return mode_; }
92+
double GetElevation(const Eigen::Vector3d& position, double time) override { return 0.0; };
9093

9194
private:
9295
unsigned int num_bodies_;
@@ -144,6 +147,7 @@ class RegularWave : public WaveBase {
144147
// user input variables
145148
double regular_wave_amplitude_;
146149
double regular_wave_omega_;
150+
double regular_wave_phase_ = 0.0;
147151

148152
/**
149153
* @brief Initializes other member variables for timestep calculations later.
@@ -153,15 +157,19 @@ class RegularWave : public WaveBase {
153157
*
154158
* @param reg_h5_data reference to chunk of h5 data needed for RegularWave calculations
155159
*/
156-
void AddH5Data(std::vector<HydroData::RegularWaveInfo>& reg_h5_data);
160+
void AddH5Data(std::vector<HydroData::RegularWaveInfo>& reg_h5_data, HydroData::SimulationParameters& sim_data);
161+
162+
double GetElevation(const Eigen::Vector3d& position, double time) override;
157163

158164
private:
159165
unsigned int num_bodies_;
160166
const WaveMode mode_ = WaveMode::regular;
161167
std::vector<HydroData::RegularWaveInfo> wave_info_;
168+
HydroData::SimulationParameters sim_data_;
162169
Eigen::VectorXd excitation_force_mag_;
163170
Eigen::VectorXd excitation_force_phase_;
164171
Eigen::VectorXd force_;
172+
double wavenumber_;
165173

166174
/**
167175
* @brief Finds omega_max and number of frequencies, then gets omega_max / num_freqs.
@@ -338,6 +346,8 @@ class IrregularWaves : public WaveBase {
338346
*/
339347
void AddH5Data(std::vector<HydroData::IrregularWaveInfo>& irreg_h5_data, HydroData::SimulationParameters& sim_data);
340348

349+
double GetElevation(const Eigen::Vector3d& position, double time) override;
350+
341351
private:
342352
IrregularWaveParams params_;
343353
std::vector<double> spectrum_;

src/hydro_forces.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ void TestHydro::AddWaves(std::shared_ptr<WaveBase> waves) {
237237
switch (user_waves_->GetWaveMode()) {
238238
case WaveMode::regular: {
239239
auto reg = std::static_pointer_cast<RegularWave>(user_waves_);
240-
reg->AddH5Data(file_info_.GetRegularWaveInfos());
240+
reg->AddH5Data(file_info_.GetRegularWaveInfos(), file_info_.GetSimulationInfo());
241241
break;
242242
}
243243
case WaveMode::irregular: {

src/wave_types.cpp

Lines changed: 89 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,77 @@
77
#include <hydroc/wave_types.h>
88
#include <unsupported/Eigen/Splines>
99

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+
1081
Eigen::VectorXd NoWave::GetForceAtTime(double t) {
1182
unsigned int dof = num_bodies_ * 6;
1283
Eigen::VectorXd f(dof);
@@ -41,12 +112,20 @@ void RegularWave::Initialize() {
41112
excitation_force_phase_[body_offset + rowEx] = GetExcitationPhaseInterp(b, rowEx, 0, freq_index_des);
42113
}
43114
}
115+
116+
wavenumber_ = ComputeWaveNumber(regular_wave_omega_, sim_data_.water_depth, sim_data_.g);
44117
}
45118

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) {
47121
wave_info_ = reg_h5_data;
122+
sim_data_ = sim_data;
48123
}
49124

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+
50129
Eigen::VectorXd RegularWave::GetForceAtTime(double t) {
51130
unsigned int dof = num_bodies_ * 6;
52131
Eigen::VectorXd f(dof);
@@ -92,68 +171,12 @@ Eigen::VectorXd ComputeWaveNumbers(const Eigen::VectorXd& omegas,
92171
double tolerance = 1e-6,
93172
int max_iterations = 100) {
94173
Eigen::VectorXd wavenumbers(omegas.size());
95-
96174
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);
116176
}
117-
118177
return wavenumbers;
119178
}
120179

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-
157180
std::vector<std::array<double, 3>> CreateFreeSurface3DPts(const std::vector<double>& eta,
158181
const Eigen::VectorXd& t_vec) {
159182
std::vector<std::array<double, 3>> surface(t_vec.size() * 2);
@@ -300,6 +323,11 @@ void IrregularWaves::AddH5Data(std::vector<HydroData::IrregularWaveInfo>& irreg_
300323
InitializeIRFVectors();
301324
}
302325

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+
303331
Eigen::VectorXd IrregularWaves::GetForceAtTime(double t) {
304332
unsigned int total_dofs = params_.num_bodies_ * 6;
305333
Eigen::VectorXd f(total_dofs);
@@ -420,7 +448,7 @@ void IrregularWaves::CreateSpectrum() {
420448
}
421449

422450
// precompute wavenumbers
423-
auto omegas = 2 * M_PI * spectrum_frequencies_;
451+
auto omegas = 2 * M_PI * spectrum_frequencies_;
424452
wavenumbers_ = ComputeWaveNumbers(omegas, sim_data_.water_depth, sim_data_.g);
425453

426454
// Open a file stream for writing
@@ -519,9 +547,8 @@ void IrregularWaves::CreateFreeSurfaceElevation() {
519547
// position assumed at (0.0, 0.0, 0.0)
520548
auto position = Eigen::Vector3d(0.0, 0.0, 0.0);
521549
// 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_);
525552

526553
// Apply ramp if ramp_duration is greater than 0
527554
if (params_.ramp_duration_ > 0.0) {

0 commit comments

Comments
 (0)