diff --git a/hw3-heat-fft/README.md b/hw3-heat-fft/README.md index 5c922c90..1c8f7de7 100644 --- a/hw3-heat-fft/README.md +++ b/hw3-heat-fft/README.md @@ -1,15 +1,21 @@ # Homework 3 - Heat Equation with FFT -### Important note: -The option USE_FFTW in CMake must be ON in order to use the FFT part of the code! +### Important notes: +The option USE_FFTW in CMake must be ON in order to use the FFT part of the code! + +Remember to add the googletest directory! ### Comment about the particle code organization: We now have a different type of "particle" in addition to Planet and PingPongBall. We call this type of particle a **MaterialPoint** (it derives from the Particle.hh class, just like Planet and PingPongBall) The MaterialPoint has two properties; **temperature** and **heat rate**, which are both obtainable through their respective get-functions. The **MaterialPointsFactory** derives from the general ParticlesFactoryInterface whcih hold the list/vector of particles (in this case MaterialPoints) and the simulation interface. The createSimulation function in MaterialPointsFactory calls **ComputeTemperature** which solves the heat equation on a square (NB!) grid of particles. The **Matrix** class (or struct to be precise) is a general C++ class for storing square matrices. The **FFT** class (or struct to be precise) contains our implemented wrapping interfaces to Forward DFT, Inverse DFT and for computing FFT frequencies. + +### Task division (subject to change) +Exercise 1, 2 and 3: Lars +Exercise 4: Bertil diff --git a/hw3-heat-fft/test_fft.cc b/hw3-heat-fft/test_fft.cc index cab18dd6..66e6ec87 100644 --- a/hw3-heat-fft/test_fft.cc +++ b/hw3-heat-fft/test_fft.cc @@ -1,110 +1,120 @@ #include "my_types.hh" #include "fft.hh" #include #include /*****************************************************************/ TEST(FFT, transform) { UInt N = 512; Matrix m(N); Real k = 2 * M_PI / N; for (auto&& entry : index(m)) { int i = std::get<0>(entry); int j = std::get<1>(entry); auto& val = std::get<2>(entry); val = cos(k * i); } Matrix res = FFT::transform(m); for (auto&& entry : index(res)) { int i = std::get<0>(entry); int j = std::get<1>(entry); auto& val = std::get<2>(entry); if (std::abs(val) > 1e-10) std::cout << i << "," << j << " = " << val << std::endl; if (i == 1 && j == 0) ASSERT_NEAR(std::abs(val), N * N / 2, 1e-10); else if (i == N - 1 && j == 0) ASSERT_NEAR(std::abs(val), N * N / 2, 1e-10); else ASSERT_NEAR(std::abs(val), 0, 1e-10); } } /*****************************************************************/ TEST(FFT, inverse_transform) { + // this test is based on that the inverse DFT of the forward FFT + // should give back the original input + // Create matrix (same as above test) UInt N = 512; Matrix m(N); Real k = 2 * M_PI / N; for (auto&& entry : index(m)) { int i = std::get<0>(entry); int j = std::get<1>(entry); auto& val = std::get<2>(entry); val = cos(k * i); } + // Forward DFT Matrix dft_m = FFT::transform(m); + + // Inverse DFT of forward DFT Matrix invdft_dft_m = FFT::itransform(dft_m); + // Check if equal! for (auto&& entry : index(invdft_dft_m)) { int i = std::get<0>(entry); int j = std::get<1>(entry); auto& val = std::get<2>(entry); ASSERT_NEAR(val.real(), cos(k*i), 1e-10); } } /*****************************************************************/ TEST(FFT, compute_frequencies){ - double tmp; - double val; + double tmp2; + UInt tmp; + UInt val; UInt N; // These tests are based on values produced by numpy.fft.fftfreq // which are saved in txt files // See the python script fft_generate_test_values.py /////////////// EVEN TEST /////////////////////// N = 20; Matrix> even_freqs = FFT::computeFrequencies(N); std::ifstream in_even("fftfreq_test_values_even.txt"); if (!in_even) { std::cout << "Cannot open even file.\n"; return; } for (int j = 0; j < N; j++) { for (int i = 0; i < N; i++) { // // DEBUG: // std::cout << "(i,j) = (" << i << "," << j << ")" << std::endl; - in_even >> tmp; + in_even >> tmp2; + tmp = int(tmp2); // because the output is stored in float format val = even_freqs(i,j).real(); - ASSERT_NEAR(val, tmp, 1e-10); + EXPECT_EQ(val, tmp); } } in_even.close(); /////////////// ODD TEST /////////////////////// N = 19; Matrix> odd_freqs = FFT::computeFrequencies(N); std::ifstream in_odd("fftfreq_test_values_odd.txt"); if (!in_odd) { std::cout << "Cannot open odd file.\n"; return; } for (int j = 0; j < N; j++) { for (int i = 0; i < N; i++) { // // DEBUG: // std::cout << "(i,j) = (" << i << "," << j << ")" << std::endl; - in_odd >> tmp; + in_odd >> tmp2; + tmp = int(tmp2); // because the output is stored in float format val = odd_freqs(i,j).real(); - ASSERT_NEAR(val, tmp, 1e-10); + EXPECT_EQ(val, tmp); } } in_odd.close(); }