Skip to content

Commit

Permalink
Initial unit testing; add integrator test
Browse files Browse the repository at this point in the history
  • Loading branch information
streeve committed Apr 7, 2020
1 parent 74a470b commit 604e7ba
Show file tree
Hide file tree
Showing 10 changed files with 325 additions and 2 deletions.
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 @@ -62,7 +81,7 @@ add_subdirectory(src)
add_subdirectory(bin)

##---------------------------------------------------------------------------##
## Enable Tests?
## Unit tests
##---------------------------------------------------------------------------##
option(CabanaMD_ENABLE_TESTING "Build tests" OFF)
if(CabanaMD_ENABLE_TESTING)
Expand All @@ -75,7 +94,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
1 change: 1 addition & 0 deletions src/integrator_nve.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class Integrator
public:
Integrator( t_System *s );
~Integrator() {}

T_V_FLOAT timestep_size;

void initial_integrate( t_System *s );
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 *
* 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;
}

0 comments on commit 604e7ba

Please sign in to comment.