#include "ocean.h" #include #include ocean::ocean() { // to be used for efficiency during fft init_wave_index_constants(); } // initializes static constants (aka they are not time dependent) void ocean::init_wave_index_constants(){ for (int i=0; i ocean::fast_fft(std::vector h) { int N = h.size(); std::vector H = std::vector(N); if (N == 1) { H[0] = h[0]; return H; } else { std::vector even = std::vector(N / 2); std::vector odd = std::vector(N / 2); for (int i = 0; i < N / 2; i++) { even[i] = h[2 * i]; odd[i] = h[2 * i + 1]; } std::vector even_fft = fast_fft(even); std::vector odd_fft = fast_fft(odd); for (int i = 0; i < N / 2; i++) { Eigen::Vector2d k = m_waveIndexConstants[i].k_vector; Eigen::Vector2d x = m_waveIndexConstants[i].base_horiz_pos; double k_dot_xz = k.dot(x); Eigen::Vector2d omega = complex_exp(k_dot_xz); Eigen::Vector2d omega_times_odd = Eigen::Vector2d(omega[0] * odd_fft[i][0] - omega[1] * odd_fft[i][1], omega[0] * odd_fft[i][1] + omega[1] * odd_fft[i][0]); H[i] = Eigen::Vector2d(even_fft[i][0] + omega_times_odd[0], even_fft[i][1] + omega_times_odd[1]); H[i + N / 2] = Eigen::Vector2d(even_fft[i][0] - omega_times_odd[0], even_fft[i][1] - omega_times_odd[1]); } return H; } } // fast fourier transform at time t void ocean::fft_prime(double t){ // // NON FFT // for (int i=0; i h_tildas = std::vector(); // find each h_tilda at each index, to be used for next for loop for (int i=0; i randoms = sample_complex_gaussian(); double random_r = randoms.first; double random_i = randoms.second; // seperate real and imag products double coeff = 0.707106781187 * sqrt(Ph_prime); double real_comp = coeff*random_r; double imag_comp = coeff*random_i; return Eigen::Vector2d(real_comp, imag_comp); } double ocean::phillips_prime(Eigen::Vector2d k){ double k_mag = k.norm(); k.normalize(); double dot_prod = k.dot(omega_wind); double output = 0.0; // l = 1 if (k_mag < .0001) return 0.0; if (k_mag > 1.0){ output = A*exp(-(k_mag*k_mag))*dot_prod*dot_prod/(k_mag*k_mag*k_mag*k_mag); } else { output = A*exp(-1.0/(k_mag*L*k_mag*L))*dot_prod*dot_prod/(k_mag*k_mag*k_mag*k_mag); } return output; } Eigen::Vector2d ocean::get_k_vector(int n_prime, int m_prime){ double n_ = (double)n_prime; double m_ = (double)m_prime; double N_ = (double)num_rows; double M_ = (double)num_cols; double k_x = (2.0*M_PI*n_ - M_PI*N_)/Lx; double k_z = (2.0*M_PI*m_ - M_PI*M_)/Lz; return Eigen::Vector2d(k_x, k_z); } Eigen::Vector2d ocean::get_horiz_pos(int i){ Eigen::Vector2i m_n = index_1d_to_2d(i); double n_prime = (double)m_n[0]; double m_prime = (double)m_n[1]; double N_ = (double)num_rows; double M_ = (double)num_cols; double x = (n_prime-.5*N_)*Lx / N_; double z = (m_prime-.5*M_)*Lz / M_; return Eigen::Vector2d(x, z); } Eigen::Vector2i ocean::index_1d_to_2d(int i){ int row = i/num_rows; // n' int col = i%num_rows; // m' return Eigen::Vector2i(row, col); } std::pair ocean::sample_complex_gaussian(){ double uniform_1 = (double)rand() / (RAND_MAX); double uniform_2 = (double)rand() / (RAND_MAX); // set a lower bound on zero to avoid undefined log(0) if (uniform_1 == 0) { uniform_1 = 1e-10; } if (uniform_2 == 0) { uniform_2 = 1e-10; } // real and imaginary parts of the complex number double real = sqrt(-2 * log(uniform_1)) * cos(2 * M_PI * uniform_2); double imag = sqrt(-2 * log(uniform_1)) * sin(2 * M_PI * uniform_2); return std::make_pair(real, imag); } Eigen::Vector2d ocean::complex_exp(double exponent){ double real = cos(exponent); double imag = sin(exponent); return Eigen::Vector2d(real, imag); } std::vector ocean::get_vertices() { std::vector vertices = std::vector(); for (int i = 0; i < N; i++){ Eigen::Vector2d horiz_pos = spacing*m_waveIndexConstants[i].base_horiz_pos; Eigen::Vector2d amplitude = m_current_h[i]; // calculate displacement Eigen::Vector2d disp = lambda*m_displacements[i]; // for final vertex position, use the real number component of amplitude vector vertices.push_back(Eigen::Vector3f(horiz_pos[0] + disp[0], amplitude[0], horiz_pos[1] + disp[1])); } return vertices; } std::vector ocean::get_faces() { // connect the vertices into faces std::vector faces = std::vector(); for (int i = 0; i < N; i++) { int x = i / num_rows; int z = i % num_rows; // connect the vertices into faces if (x < num_rows - 1 && z < num_cols - 1) { int i1 = i; int i2 = i + 1; int i3 = i + num_rows; int i4 = i + num_rows + 1; // faces.emplace_back(i2, i1, i3); // faces.emplace_back(i2, i3, i4); faces.emplace_back(i1, i2, i3); faces.emplace_back(i3, i2, i4); } } return faces; }