@@ -541,7 +541,7 @@ std::vector<double> IrregularWaves::GetSpectrum() {
541541}
542542
543543std::vector<double > IrregularWaves::GetFreeSurfaceElevation () {
544- return free_surface_elevation_ ;
544+ return free_surface_elevation_sampled_ ;
545545}
546546
547547std::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
773776double 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