Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F90839679
mpi_test_fft_engine.cc
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Nov 5, 06:05
Size
6 KB
Mime Type
text/x-c
Expires
Thu, Nov 7, 06:05 (2 d)
Engine
blob
Format
Raw Data
Handle
22141818
Attached To
rMUSPECTRE µSpectre
mpi_test_fft_engine.cc
View Options
/**
* @file mpi_test_fft_engine.cc
*
* @author Lars Pastewka <lars.pastewka@imtek.uni-freiburg.de>
*
* @date 06 Mar 2017
*
* @brief tests for MPI-parallel fft engine implementations
*
* Copyright © 2017 Till Junge
*
* µSpectre is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3, or (at
* your option) any later version.
*
* µSpectre is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with µSpectre; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* * Boston, MA 02111-1307, USA.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining it
* with proprietary FFT implementations or numerical libraries, containing parts
* covered by the terms of those libraries' licenses, the licensors of this
* Program grant you additional permission to convey the resulting work.
*/
#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
#define BOOST_MPL_LIMIT_LIST_SIZE 50
#include <boost/mpl/list.hpp>
#include "tests.hh"
#include "mpi_context.hh"
#include <libmufft/fftw_engine.hh>
#ifdef WITH_FFTWMPI
#include <libmufft/fftwmpi_engine.hh>
#endif
#ifdef WITH_PFFT
#include <libmufft/pfft_engine.hh>
#endif
#include <libmugrid/ccoord_operations.hh>
#include <libmugrid/field_collection.hh>
#include <libmugrid/field_map.hh>
#include <libmugrid/iterators.hh>
namespace muFFT {
using muSpectre::tol;
BOOST_AUTO_TEST_SUITE(mpi_fft_engine);
/* ---------------------------------------------------------------------- */
template <typename Engine, Dim_t resolution, bool serial = false>
struct FFTW_fixture {
constexpr static Dim_t box_resolution{resolution};
constexpr static Dim_t serial_engine{serial};
constexpr static Real box_length{4.5};
constexpr static Dim_t sdim{Engine::sdim};
constexpr static Dim_t nb_components{sdim * sdim};
constexpr static Ccoord_t<sdim> res() {
return muGrid::CcoordOps::get_cube<sdim>(box_resolution);
}
FFTW_fixture()
: engine(res(), nb_components, MPIContext::get_context().comm) {}
Engine engine;
};
template <typename Engine>
struct FFTW_fixture_python_segfault {
constexpr static Dim_t serial_engine{false};
constexpr static Dim_t dim{twoD};
constexpr static Dim_t sdim{twoD};
constexpr static Dim_t mdim{twoD};
constexpr static Dim_t nb_components{sdim * sdim};
constexpr static Ccoord_t<sdim> res() { return {6, 4}; }
FFTW_fixture_python_segfault()
: engine{res(), nb_components, MPIContext::get_context().comm} {}
Engine engine;
};
using fixlist = boost::mpl::list<
#ifdef WITH_FFTWMPI
FFTW_fixture<FFTWMPIEngine<twoD>, 3>,
FFTW_fixture<FFTWMPIEngine<threeD>, 3>,
FFTW_fixture<FFTWMPIEngine<twoD>, 4>,
FFTW_fixture<FFTWMPIEngine<threeD>, 4>,
FFTW_fixture_python_segfault<FFTWMPIEngine<twoD>>,
#endif
#ifdef WITH_PFFT
FFTW_fixture<PFFTEngine<twoD>, 3>, FFTW_fixture<PFFTEngine<threeD>, 3>,
FFTW_fixture<PFFTEngine<twoD>, 4>, FFTW_fixture<PFFTEngine<threeD>, 4>,
FFTW_fixture_python_segfault<PFFTEngine<twoD>>,
#endif
FFTW_fixture<FFTWEngine<twoD>, 3, true>>;
/* ---------------------------------------------------------------------- */
BOOST_FIXTURE_TEST_CASE_TEMPLATE(Constructor_test, Fix, fixlist, Fix) {
Communicator & comm = MPIContext::get_context().comm;
if (Fix::serial_engine && comm.size() > 1) {
return;
} else {
BOOST_CHECK_NO_THROW(Fix::engine.initialise(FFT_PlanFlags::estimate));
}
BOOST_CHECK_EQUAL(comm.sum(Fix::engine.size()),
muGrid::CcoordOps::get_size(Fix::res()));
}
/* ---------------------------------------------------------------------- */
BOOST_FIXTURE_TEST_CASE_TEMPLATE(fft_test, Fix, fixlist, Fix) {
if (Fix::serial_engine && Fix::engine.get_communicator().size() > 1) {
// dont test serial engies in parallel
return;
} else {
Fix::engine.initialise(FFT_PlanFlags::estimate);
}
constexpr Dim_t order{2};
using FC_t = muGrid::GlobalFieldCollection<Fix::sdim>;
FC_t fc;
auto & input{
muGrid::make_field<muGrid::TensorField<FC_t, Real, order, Fix::sdim>>(
"input", fc)};
auto & ref{
muGrid::make_field<muGrid::TensorField<FC_t, Real, order, Fix::sdim>>(
"reference", fc)};
auto & result{
muGrid::make_field<muGrid::TensorField<FC_t, Real, order, Fix::sdim>>(
"result", fc)};
fc.initialise(Fix::engine.get_subdomain_resolutions(),
Fix::engine.get_subdomain_locations());
using map_t = muGrid::MatrixFieldMap<FC_t, Real, Fix::sdim, Fix::sdim>;
map_t inmap{input};
auto refmap{map_t{ref}};
auto resultmap{map_t{result}};
size_t cntr{0};
for (auto tup : akantu::zip(inmap, refmap)) {
cntr++;
auto & in_{std::get<0>(tup)};
auto & ref_{std::get<1>(tup)};
in_.setRandom();
ref_ = in_;
}
auto & complex_field = Fix::engine.fft(input);
using cmap_t =
muGrid::MatrixFieldMap<muGrid::LocalFieldCollection<Fix::sdim>, Complex,
Fix::sdim, Fix::sdim>;
cmap_t complex_map(complex_field);
if (Fix::engine.get_subdomain_locations() ==
muGrid::CcoordOps::get_cube<Fix::sdim>(0)) {
// Check that 0,0 location has no imaginary part.
Real error = complex_map[0].imag().norm();
BOOST_CHECK_LT(error, tol);
}
/* make sure, the engine has not modified input (which is
unfortunately const-casted internally, hence this test) */
for (auto && tup : akantu::zip(inmap, refmap)) {
Real error{(std::get<0>(tup) - std::get<1>(tup)).norm()};
BOOST_CHECK_LT(error, tol);
}
/* make sure that the ifft of fft returns the original*/
Fix::engine.ifft(result);
for (auto && tup : akantu::zip(resultmap, refmap)) {
Real error{
(std::get<0>(tup) * Fix::engine.normalisation() - std::get<1>(tup))
.norm()};
BOOST_CHECK_LT(error, tol);
if (error > tol) {
std::cout << std::get<0>(tup).array() / std::get<1>(tup).array()
<< std::endl
<< std::endl;
}
}
}
BOOST_AUTO_TEST_SUITE_END();
} // namespace muFFT
Event Timeline
Log In to Comment