diff --git a/unit_test/CMakeLists.txt b/unit_test/CMakeLists.txt index b97153e..fa57558 100644 --- a/unit_test/CMakeLists.txt +++ b/unit_test/CMakeLists.txt @@ -48,6 +48,6 @@ macro(CabanaPD_add_tests) endforeach() endmacro() -CabanaPD_add_tests(NAMES Force Integrator) +CabanaPD_add_tests(NAMES Particles Force Integrator) CabanaPD_add_tests(MPI NAMES Comm) diff --git a/unit_test/tstParticles.hpp b/unit_test/tstParticles.hpp new file mode 100644 index 0000000..ea38387 --- /dev/null +++ b/unit_test/tstParticles.hpp @@ -0,0 +1,140 @@ +/**************************************************************************** + * Copyright (c) 2022 by Oak Ridge National Laboratory * + * All rights reserved. * + * * + * This file is part of CabanaPD. CabanaPD 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 + +#include +#include + +#include + +namespace Test +{ +template +void checkNumParticles( const ParticlesType& particles, + const std::size_t expected_frozen, + const std::size_t expected_local, + const std::size_t expected_ghost = 0 ) +{ + // Check the values. + auto frozen = particles.numFrozen(); + EXPECT_EQ( frozen, expected_frozen ); + auto local = particles.numLocal(); + EXPECT_EQ( local, expected_local ); + auto ghost = particles.numGhost(); + EXPECT_EQ( ghost, expected_ghost ); + + // Check the offsets. + EXPECT_EQ( particles.frozenOffset(), expected_frozen ); + EXPECT_EQ( particles.localOffset(), expected_frozen + expected_local ); + EXPECT_EQ( particles.referenceOffset(), + expected_frozen + expected_local + expected_ghost ); +} + +template +void checkParticlePositions( const ParticlesType& particles, + const std::array box_min, + const std::array box_max, + const std::size_t start, const std::size_t end ) +{ + using HostAoSoA = Cabana::AoSoA, + Kokkos::HostSpace>; + HostAoSoA aosoa_host( "host_aosoa", particles.referenceOffset() ); + auto x_host = Cabana::slice<0>( aosoa_host ); + auto x = particles.sliceReferencePosition(); + Cabana::deep_copy( x_host, x ); + + // Check the particles were created in the right box. + for ( std::size_t p = start; p < end; ++p ) + for ( int d = 0; d < 3; ++d ) + { + EXPECT_GE( x_host( p, d ), box_min[d] ); + EXPECT_LE( x_host( p, d ), box_max[d] ); + } +} + +//---------------------------------------------------------------------------// +void testCreateParticles() +{ + using exec_space = TEST_EXECSPACE; + + std::array box_min = { -1.0, -1.0, -1.0 }; + std::array box_max = { 1.0, 1.0, 1.0 }; + std::array num_cells = { 10, 10, 10 }; + + // Frozen or all particles first. + CabanaPD::Particles + particles( exec_space(), box_min, box_max, num_cells, 0 ); + + // Check expected values for each block of particles. + std::size_t expected_local = num_cells[0] * num_cells[1] * num_cells[2]; + std::size_t expected_frozen = 0; + + checkNumParticles( particles, expected_frozen, expected_local ); + checkParticlePositions( particles, box_min, box_max, + particles.frozenOffset(), particles.localOffset() ); +} + +void testCreateFrozenParticles() +{ + using exec_space = TEST_EXECSPACE; + + std::array box_min = { -1.0, -1.0, -1.0 }; + std::array box_max = { 1.0, 1.0, 1.0 }; + std::array num_cells = { 10, 10, 10 }; + + // Frozen in bottom half. + auto init_bottom = KOKKOS_LAMBDA( const int, const double x[3] ) + { + if ( x[2] < 0.0 ) + return true; + return false; + }; + CabanaPD::Particles + particles( exec_space(), box_min, box_max, num_cells, 0, init_bottom, 0, + true ); + + // Unfrozen in top half. + auto init_top = KOKKOS_LAMBDA( const int, const double x[3] ) + { + if ( x[2] > 0.0 ) + return true; + return false; + }; + // Create more, starting from the current number of frozen points. + particles.createParticles( exec_space{}, init_top, particles.numFrozen() ); + + // Check expected values for each block of particles. + std::size_t expected_local = num_cells[0] * num_cells[1] * num_cells[2] / 2; + std::size_t expected_frozen = expected_local; + checkNumParticles( particles, expected_frozen, expected_local ); + + // Check frozen and local separately. + box_max[2] = 0.0; + checkParticlePositions( particles, box_min, box_max, 0, + particles.frozenOffset() ); + box_min[2] = 0.0; + box_max[2] = 1.0; + checkParticlePositions( particles, box_min, box_max, + particles.frozenOffset(), particles.localOffset() ); +} + +//---------------------------------------------------------------------------// +// TESTS +//---------------------------------------------------------------------------// +TEST( TEST_CATEGORY, test_create_local ) { testCreateParticles(); } +TEST( TEST_CATEGORY, test_create_frozen ) { testCreateFrozenParticles(); } + +//---------------------------------------------------------------------------// + +} // end namespace Test