Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit tests #42

Merged
merged 1 commit into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@ script:
- mkdir build && pushd build &&
cmake -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
-DCMAKE_PREFIX_PATH="$HOME/Cabana;$HOME/kokkos"
-DCabanaMD_ENABLE_TESTING=ON
-DCabanaMD_ENABLE_Serial=OFF
-DCabanaMD_ENABLE_NNP=${NNP}
-DN2P2_DIR=$HOME/build/n2p2
${CABANAMD_OPTS[@]}
.. &&
make -j4 VERBOSE=1 &&
make test CTEST_OUTPUT_ON_FAILURE=1 &&
make format && git diff --exit-code &&
popd

Expand Down
23 changes: 21 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,25 @@ include(GNUInstallDirs)

set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

##---------------------------------------------------------------------------##
# Download and unpack googletest
##---------------------------------------------------------------------------##
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.10.0
)
FetchContent_GetProperties(googletest)
if(NOT googletest_POPULATED)
FetchContent_Populate(googletest)
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
endif()

# Prevent GoogleTest from overriding our compiler/linker options
# when building with Visual Studio
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)

##---------------------------------------------------------------------------##
# Set up main options (inherit from Kokkos and Cabana CMake)
##---------------------------------------------------------------------------##
Expand Down Expand Up @@ -67,7 +86,7 @@ add_subdirectory(src)
add_subdirectory(bin)

##---------------------------------------------------------------------------##
## Enable Tests?
## Unit tests
##---------------------------------------------------------------------------##
option(CabanaMD_ENABLE_TESTING "Build tests" OFF)
if(CabanaMD_ENABLE_TESTING)
Expand All @@ -80,7 +99,7 @@ endif()
##---------------------------------------------------------------------------##
find_package(CLANG_FORMAT)
if(CLANG_FORMAT_FOUND)
file(GLOB_RECURSE FORMAT_SOURCES src/*.cpp src/*.h bin/*.cpp)
file(GLOB_RECURSE FORMAT_SOURCES src/*.cpp src/*.h bin/*.cpp unit_test/*.cpp unit_test/*.hpp)
add_custom_target(format
COMMAND ${CLANG_FORMAT_EXECUTABLE} -i -style=file ${FORMAT_SOURCES}
DEPENDS ${FORMAT_SOURCES})
Expand Down
49 changes: 49 additions & 0 deletions unit_test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
set(gtest_args --gtest_color=yes)

##--------------------------------------------------------------------------##
## On-node tests
##--------------------------------------------------------------------------##
macro(CabanaMD_add_tests)
cmake_parse_arguments(CABANAMD_UNIT_TEST "MPI" "" "NAMES" ${ARGN})
set(CABANAMD_UNIT_TEST_MPIEXEC_NUMPROCS 1 2)
if(MPIEXEC_MAX_NUMPROCS GREATER 2)
list(APPEND CABANAMD_UNIT_TEST_MPIEXEC_NUMPROCS ${MPIEXEC_MAX_NUMPROCS})
endif()
set(CABANAMD_UNIT_TEST_NUMTHREADS 1 2)
set(CABANAMD_UNIT_TEST_MAIN unit_test_main.cpp)

foreach(_device Serial OpenMP Cuda)
if(CabanaMD_ENABLE_${_device})
string(TOUPPER ${_device} _uppercase_device)
set(_dir ${CMAKE_CURRENT_BINARY_DIR}/${_uppercase_device})
file(MAKE_DIRECTORY ${_dir})
foreach(_test ${CABANAMD_UNIT_TEST_NAMES})
set(_file ${_dir}/tst${_test}_${_uppercase_device}.cpp)
file(WRITE ${_file}
"#include <Test${_uppercase_device}_Category.hpp>\n"
"#include <tst${_test}.hpp>\n"
)
set(_target ${_test}_test_${_uppercase_device})
add_executable(${_target} ${_file} ${CABANAMD_UNIT_TEST_MAIN})
target_include_directories(${_target} PRIVATE ${_dir} ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(${_target} PRIVATE CabanaMD gtest CabanaMD)

foreach(_np ${CABANAMD_UNIT_TEST_MPIEXEC_NUMPROCS})
if(_device STREQUAL THREADS OR _device STREQUAL OpenMP)
foreach(_thread ${CABANAMD_UNIT_TEST_NUMTHREADS})
add_test(NAME ${_target}_${_np}_${_thread} COMMAND
${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${_np} ${MPIEXEC_PREFLAGS}
${_target} ${MPIEXEC_POSTFLAGS} ${gtest_args} --kokkos-threads=${_thread})
endforeach()
else()
add_test(NAME ${_target}_${_np} COMMAND
${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${_np} ${MPIEXEC_PREFLAGS}
${_target} ${MPIEXEC_POSTFLAGsS} ${gtest_args})
endif()
endforeach()
endforeach()
endif()
endforeach()
endmacro()

CabanaMD_add_tests(MPI NAMES Integrator)
19 changes: 19 additions & 0 deletions unit_test/TestCUDA_Category.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/****************************************************************************
* Copyright (c) 2018-2019 by the Cabana authors *
streeve marked this conversation as resolved.
Show resolved Hide resolved
* All rights reserved. *
* *
* This file is part of the Cabana library. Cabana is distributed under a *
* BSD 3-clause license. For the licensing terms see the LICENSE file in *
* the top-level directory. *
* *
* SPDX-License-Identifier: BSD-3-Clause *
****************************************************************************/

#ifndef CABANA_TEST_CUDA_CATEGORY_HPP
#define CABANA_TEST_CUDA_CATEGORY_HPP

#define TEST_CATEGORY cuda
#define TEST_EXECSPACE Kokkos::Cuda
#define TEST_MEMSPACE Kokkos::CudaSpace

#endif // end CABANA_TEST_CUDA_CATEGORY_HPP
23 changes: 23 additions & 0 deletions unit_test/TestCUDA_UVM_Category.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/****************************************************************************
* Copyright (c) 2018-2019 by the Cabana authors *
* All rights reserved. *
* *
* This file is part of the Cabana library. Cabana is distributed under a *
* BSD 3-clause license. For the licensing terms see the LICENSE file in *
* the top-level directory. *
* *
* SPDX-License-Identifier: BSD-3-Clause *
****************************************************************************/

#ifndef CABANA_TEST_CUDAUVM_CATEGORY_HPP
#define CABANA_TEST_CUDAUVM_CATEGORY_HPP

#include <Kokkos_Cuda.hpp>

#include <gtest/gtest.h>

#define TEST_CATEGORY cuda_uvm
#define TEST_EXECSPACE Kokkos::Cuda
#define TEST_MEMSPACE Kokkos::CudaUVMSpace

#endif // end CABANA_TEST_CUDAUVM_CATEGORY_HPP
19 changes: 19 additions & 0 deletions unit_test/TestOPENMP_Category.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/****************************************************************************
* Copyright (c) 2018-2019 by the Cabana authors *
* All rights reserved. *
* *
* This file is part of the Cabana library. Cabana is distributed under a *
* BSD 3-clause license. For the licensing terms see the LICENSE file in *
* the top-level directory. *
* *
* SPDX-License-Identifier: BSD-3-Clause *
****************************************************************************/

#ifndef CABANA_TEST_OPENMP_CATEGORY_HPP
#define CABANA_TEST_OPENMP_CATEGORY_HPP

#define TEST_CATEGORY openmp
#define TEST_EXECSPACE Kokkos::OpenMP
#define TEST_MEMSPACE Kokkos::HostSpace

#endif // end CABANA_TEST_OPENMP_CATEGORY_HPP
19 changes: 19 additions & 0 deletions unit_test/TestSERIAL_Category.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/****************************************************************************
* Copyright (c) 2018-2019 by the Cabana authors *
* All rights reserved. *
* *
* This file is part of the Cabana library. Cabana is distributed under a *
* BSD 3-clause license. For the licensing terms see the LICENSE file in *
* the top-level directory. *
* *
* SPDX-License-Identifier: BSD-3-Clause *
****************************************************************************/

#ifndef CABANA_TEST_SERIAL_CATEGORY_HPP
#define CABANA_TEST_SERIAL_CATEGORY_HPP

#define TEST_CATEGORY serial
#define TEST_EXECSPACE Kokkos::Serial
#define TEST_MEMSPACE Kokkos::HostSpace

#endif // end CABANA_TEST_SERIAL_CATEGORY_HPP
144 changes: 144 additions & 0 deletions unit_test/tstIntegrator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/****************************************************************************
* Copyright (c) 2018-2019 by the Cabana authors *
* All rights reserved. *
* *
* This file is part of the Cabana library. Cabana is distributed under a *
* BSD 3-clause license. For the licensing terms see the LICENSE file in *
* the top-level directory. *
* *
* SPDX-License-Identifier: BSD-3-Clause *
****************************************************************************/

#include <integrator_nve.h>
#include <system.h>

#include <Cabana_Core.hpp>
#include <Kokkos_Core.hpp>
#include <Kokkos_Random.hpp>

#include <gtest/gtest.h>

#include <algorithm>
#include <vector>

namespace Test
{
//---------------------------------------------------------------------------//
// Create particles.
template <class t_System>
t_System createParticles( const int num_particle, const int num_ghost,
const double box_min, const double box_max )
{
t_System system;
system.init();

// Manually setup what would be done in input
system.dt = 0.005;
system.mvv2e = 1.0;
system.mass( 0 ) = 1.0;

system.resize( num_particle );
system.N_local = num_particle - num_ghost;
system.N_ghost = num_ghost;

auto box = box_max - box_min;
system.domain_x = system.domain_y = system.domain_z = box;
system.domain_lo_x = system.domain_lo_y = system.domain_lo_z = box_min;
system.domain_hi_x = system.domain_hi_y = system.domain_hi_z = box_max;

system.slice_integrate();
auto x = system.x;
auto v = system.v;
auto f = system.f;
auto type = system.type;

using PoolType = Kokkos::Random_XorShift64_Pool<TEST_EXECSPACE>;
using RandomType = Kokkos::Random_XorShift64<TEST_EXECSPACE>;
PoolType pool( 342343901 );
auto random_coord_op = KOKKOS_LAMBDA( const int p )
{
auto gen = pool.get_state();
for ( int d = 0; d < 3; ++d )
{
x( p, d ) =
Kokkos::rand<RandomType, double>::draw( gen, box_min, box_max );
v( p, d ) =
Kokkos::rand<RandomType, double>::draw( gen, -1.0, 1.0 );
f( p, d ) =
Kokkos::rand<RandomType, double>::draw( gen, -1.0, 1.0 );
type( p ) = 0;
}
pool.free_state( gen );
};
Kokkos::RangePolicy<TEST_EXECSPACE> exec_policy( 0, num_particle );
Kokkos::parallel_for( exec_policy, random_coord_op );
Kokkos::fence();

return system;
}

//---------------------------------------------------------------------------//
template <class t_System>
void testIntegratorReversibility( int steps )
{
// Create the AoSoA and fill with random particle positions
int num_particle = 1e3;
int num_ghost = 200;
double test_radius = 2.32;
double box_min = -5.3 * test_radius;
double box_max = 4.7 * test_radius;

t_System system =
createParticles<t_System>( num_particle, num_ghost, box_min, box_max );
Integrator<t_System> integrator( &system );

// Keep a copy of initial positions on the host
using DataTypes = Cabana::MemberTypes<double[3]>;
using AoSoA_t = Cabana::AoSoA<DataTypes, Kokkos::HostSpace>;
AoSoA_t x_aosoa_init( "x_init_host", num_particle );
auto x_init = Cabana::slice<0>( x_aosoa_init );
system.slice_x();
Cabana::deep_copy( x_init, system.x );

// Integrate one step
for ( int s = 0; s < steps; ++s )
{
integrator.initial_integrate( &system );
integrator.final_integrate( &system );
}

// Reverse system
system.slice_v();
for ( int p = 0; p < num_particle; ++p )
for ( int d = 0; d < 3; ++d )
system.v( p, d ) *= -1.0;

// Integrate back
for ( int s = 0; s < steps; ++s )
{
integrator.initial_integrate( &system );
integrator.final_integrate( &system );
}

// Make a copy of final results on the host
AoSoA_t x_aosoa_final( "x_final_host", num_particle );
auto x_final = Cabana::slice<0>( x_aosoa_final );
Cabana::deep_copy( x_final, system.x );

// Check the results
for ( int p = 0; p < num_particle; ++p )
for ( int d = 0; d < 3; ++d )
EXPECT_FLOAT_EQ( x_final( p, d ), x_init( p, d ) );
}

//---------------------------------------------------------------------------//
// TESTS
//---------------------------------------------------------------------------//
TEST( TEST_CATEGORY, reversibility_test )
{
testIntegratorReversibility<System<AoSoA6>>( 100 );
}

//---------------------------------------------------------------------------//

} // end namespace Test
28 changes: 28 additions & 0 deletions unit_test/unit_test_main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/****************************************************************************
* Copyright (c) 2018-2019 by the Cabana authors *
* All rights reserved. *
* *
* This file is part of the Cabana library. Cabana is distributed under a *
* BSD 3-clause license. For the licensing terms see the LICENSE file in *
* the top-level directory. *
* *
* SPDX-License-Identifier: BSD-3-Clause *
****************************************************************************/

#include <gtest/gtest.h>

#include <Cabana_Core.hpp>
#include <Kokkos_Core.hpp>

#include <mpi.h>

int main( int argc, char *argv[] )
{
MPI_Init( &argc, &argv );
Kokkos::initialize( argc, argv );
::testing::InitGoogleTest( &argc, argv );
int return_val = RUN_ALL_TESTS();
Kokkos::finalize();
MPI_Finalize();
return return_val;
}