Skip to content

Commit cf20bb1

Browse files
committed
Interpolate when making excitation convolution
1 parent f1e0816 commit cf20bb1

2 files changed

Lines changed: 72 additions & 28 deletions

File tree

include/hydroc/wave_types.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Eigen::VectorXd JONSWAPSpectrumHz(Eigen::VectorXd& f, double Hs, double Tp, doub
1717

1818
std::vector<double> FreeSurfaceElevation(const Eigen::VectorXd& freqs_hz,
1919
const Eigen::VectorXd& spectral_densities,
20-
const Eigen::VectorXd& time_index,
20+
const Eigen::VectorXd& time_array,
2121
double water_depth,
2222
int seed = 1);
2323

@@ -330,7 +330,8 @@ class IrregularWaves : public WaveBase {
330330
int seed_;
331331
std::vector<double> spectrum_;
332332
std::vector<double> time_data_;
333-
std::vector<double> free_surface_elevation_;
333+
std::vector<double> free_surface_elevation_sampled_;
334+
std::vector<double> free_surface_time_sampled_;
334335
bool spectrumCreated_;
335336

336337
const WaveMode mode_ = WaveMode::irregular;

src/wave_types.cpp

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ std::vector<double> IrregularWaves::GetSpectrum() {
541541
}
542542

543543
std::vector<double> IrregularWaves::GetFreeSurfaceElevation() {
544-
return free_surface_elevation_;
544+
return free_surface_elevation_sampled_;
545545
}
546546

547547
std::vector<double> IrregularWaves::GetEtaTimeData() {
@@ -565,7 +565,7 @@ void IrregularWaves::ReadEtaFromFile() {
565565
throw std::runtime_error("Could not parse line: " + line);
566566
}
567567
time_data_.push_back(time);
568-
free_surface_elevation_.push_back(eta);
568+
free_surface_elevation_sampled_.push_back(eta);
569569
}
570570
}
571571

@@ -733,11 +733,14 @@ void IrregularWaves::CreateFreeSurfaceElevation() {
733733
// UpdateNumTimesteps();
734734
int num_timesteps = static_cast<int>(simulation_duration_ / simulation_dt_) + 1;
735735

736-
Eigen::VectorXd time_index = Eigen::VectorXd::LinSpaced(num_timesteps, 0, simulation_duration_);
736+
auto time_array = Eigen::VectorXd::LinSpaced(num_timesteps, 0, simulation_duration_);
737+
// save time array as a std::vector
738+
free_surface_time_sampled_.resize(time_array.size());
739+
Eigen::VectorXd::Map(&free_surface_time_sampled_[0], time_array.size()) = time_array;
737740

738741
// Calculate the free surface elevation
739-
free_surface_elevation_ =
740-
FreeSurfaceElevation(spectrum_frequencies_, spectral_densities_, time_index, sim_data_.water_depth, seed_);
742+
free_surface_elevation_sampled_ =
743+
FreeSurfaceElevation(spectrum_frequencies_, spectral_densities_, time_array, sim_data_.water_depth, seed_);
741744

742745
// Apply ramp if ramp_duration is greater than 0
743746
if (ramp_duration_ > 0.0) {
@@ -746,7 +749,7 @@ void IrregularWaves::CreateFreeSurfaceElevation() {
746749
Eigen::VectorXd ramp = Eigen::VectorXd::LinSpaced(ramp_timesteps, 0.0, 1.0);
747750

748751
for (size_t i = 0; i < ramp.size(); ++i) {
749-
free_surface_elevation_[i] *= ramp[i];
752+
free_surface_elevation_sampled_[i] *= ramp[i];
750753
}
751754
}
752755

@@ -755,8 +758,8 @@ void IrregularWaves::CreateFreeSurfaceElevation() {
755758
// Check if the file stream is open
756759
if (eta_output.is_open()) {
757760
// Write the spectral densities and their corresponding frequencies to the file
758-
for (size_t i = 0; i < free_surface_elevation_.size(); ++i) {
759-
eta_output << time_index[i] << " : " << free_surface_elevation_[i] << std::endl;
761+
for (size_t i = 0; i < free_surface_elevation_sampled_.size(); ++i) {
762+
eta_output << free_surface_time_sampled_[i] << " : " << free_surface_elevation_sampled_[i] << std::endl;
760763
}
761764
// Close the file stream
762765
eta_output.close();
@@ -771,24 +774,64 @@ void IrregularWaves::CreateFreeSurfaceElevation() {
771774
}
772775

773776
double IrregularWaves::ExcitationConvolution(int body, int dof, double time) {
774-
double f_ex = 0.0;
775-
double width = ex_irf_time_resampled_[body][1] - ex_irf_time_resampled_[body][0];
776-
// std::cout << "width=" << width << std::endl;
777-
for (size_t j = 0; j < ex_irf_time_resampled_[0].size(); ++j) {
778-
double tau = ex_irf_time_resampled_[0][j];
779-
double t_tau = time - tau;
780-
781-
double ex_irf_val = ex_irf_resampled_[body](dof, j);
782-
783-
if (0.0 < t_tau && t_tau < free_surface_elevation_.size() * width) {
784-
size_t eta_index = static_cast<size_t>(t_tau / width);
785-
double eta_val = free_surface_elevation_[eta_index - 1];
786-
787-
// std::cout << "ex_irf_val = " << ex_irf_val << std::endl;
788-
// std::cout << "eta_val = " << eta_val << std::endl;
789-
// std::cout << "width = " << width << std::endl;
777+
double f_ex = 0.0;
778+
auto& irf_time_array = ex_irf_time_resampled_[body];
779+
auto& irf_val_mat = ex_irf_resampled_[body];
780+
781+
// asumptions: irf_time_array in ascending order, free_surface_time_sampled_ in ascending order
782+
// get initial index
783+
auto tmin = free_surface_time_sampled_.front();
784+
auto tmax = free_surface_time_sampled_.back();
785+
double t_tau = time - irf_time_array[0];
786+
int idx = 0;
787+
if (t_tau <= tmin) {
788+
idx = 0;
789+
} else if (t_tau >= tmax) {
790+
idx = free_surface_time_sampled_.size() - 2;
791+
} else {
792+
idx = get_lower_index(t_tau, free_surface_time_sampled_);
793+
}
790794

791-
f_ex += ex_irf_val * eta_val * width; // eta is wave elevation
795+
// loop for all irf time values
796+
for (size_t j = 0; j < irf_time_array.size(); ++j) {
797+
double tau = irf_time_array[j];
798+
double t_tau = time - tau;
799+
if (tmin <= t_tau && t_tau <= tmax) {
800+
// find next index if current lower bound > t_tau
801+
while (free_surface_time_sampled_[idx] > t_tau) {
802+
idx -= 1;
803+
}
804+
805+
// linearly interpolate free surface elevation between bounds
806+
// free surface time values
807+
auto t1 = free_surface_time_sampled_[idx];
808+
auto t2 = free_surface_time_sampled_[idx + 1];
809+
// double check that t_tau is between bounds
810+
if (t_tau < t1 || t_tau > t2) {
811+
throw std::runtime_error("Excitation convolution: wrong tau value " + std::to_string(tau) +
812+
" not between " + std::to_string(t1) + " and " + std::to_string(t2) + ".");
813+
}
814+
// free surface elevation values
815+
auto eta1 = free_surface_elevation_sampled_[idx];
816+
auto eta2 = free_surface_elevation_sampled_[idx + 1];
817+
// weights
818+
auto w1 = (t2 - t_tau) / (t2 - t1);
819+
auto w2 = 1.0 - w1;
820+
// weighted value
821+
auto eta_val = w1 * eta1 + w2 * eta2;
822+
823+
// calculate width
824+
double width = 0;
825+
if (j > 0) {
826+
width += 0.5 * (irf_time_array[j] - irf_time_array[j - 1]);
827+
}
828+
if (j < irf_time_array.size() - 1) {
829+
width += 0.5 * (irf_time_array[j + 1] - irf_time_array[j]);
830+
}
831+
832+
double ex_irf_val = irf_val_mat(dof, j);
833+
834+
f_ex += ex_irf_val * eta_val * width;
792835
}
793836
}
794837

@@ -800,7 +843,7 @@ void IrregularWaves::SetUpWaveMesh(std::string filename) {
800843
int num_timesteps = static_cast<int>(simulation_duration_ / simulation_dt_) + 1;
801844
Eigen::VectorXd time_index = Eigen::VectorXd::LinSpaced(num_timesteps, 0, simulation_duration_);
802845
std::vector<std::array<double, 3>> free_surface_3d_pts =
803-
CreateFreeSurface3DPts(free_surface_elevation_, time_index);
846+
CreateFreeSurface3DPts(free_surface_elevation_sampled_, time_index);
804847
std::vector<std::array<size_t, 3>> free_surface_triangles = CreateFreeSurfaceTriangles(time_index.size());
805848

806849
WriteFreeSurfaceMeshObj(free_surface_3d_pts, free_surface_triangles, mesh_file_name_);

0 commit comments

Comments
 (0)