Skip to content

Commit

Permalink
Merge pull request #693 from kwitaechong/cajita_particieinit
Browse files Browse the repository at this point in the history
Create particles with existing particles
  • Loading branch information
streeve authored Sep 21, 2023
2 parents 01d0469 + 251d124 commit c5fe5ef
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 102 deletions.
78 changes: 54 additions & 24 deletions cajita/src/Cajita_ParticleInit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ namespace Cajita
particles and resized to a size equal to the number of particles created.
\param particles_per_cell The number of particles to sample each cell with.
\param local_grid The LocalGrid over which particles will be created.
\param previous_num_particles Optionally specify how many particles are
already in the container (and should be unchanged).
\param shrink_to_fit Optionally remove unused allocated space after creation.
\param seed Optional random seed for generating particles.
*/
Expand All @@ -65,6 +67,7 @@ int createParticles(
Cabana::InitRandom, const ExecutionSpace& exec_space,
const InitFunctor& create_functor, ParticleListType& particle_list,
const int particles_per_cell, LocalGridType& local_grid,
const std::size_t previous_num_particles = 0,
const bool shrink_to_fit = true, const uint64_t seed = 123456,
typename std::enable_if<Cajita::is_particle_list<ParticleListType>::value,
int>::type* = 0 )
Expand Down Expand Up @@ -95,10 +98,11 @@ int createParticles(
// Allocate enough space for the case the particles consume the entire
// local grid.
int num_particles = particles_per_cell * owned_cells.size();
aosoa.resize( num_particles );
aosoa.resize( previous_num_particles + num_particles );

// Creation count.
// Creation count (start from previous).
auto count = Kokkos::View<int*, memory_space>( "particle_count", 1 );
Kokkos::deep_copy( count, previous_num_particles );

// Initialize particles.
Cajita::grid_parallel_for(
Expand Down Expand Up @@ -136,7 +140,8 @@ int createParticles(
for ( int p = 0; p < particles_per_cell; ++p )
{
// Local particle id.
int pid = cell_id * particles_per_cell + p;
int pid =
previous_num_particles + cell_id * particles_per_cell + p;

// Select a random point in the cell for the particle
// location. These coordinates are logical.
Expand Down Expand Up @@ -182,22 +187,24 @@ int createParticles(
particles and resized to a size equal to the number of particles created.
\param particles_per_cell The number of particles to sample each cell with.
\param local_grid The LocalGrid over which particles will be created.
\param previous_num_particles Optionally specify how many particles are
already in the container (and should be unchanged).
\param shrink_to_fit Optionally remove unused allocated space after creation.
\param seed Optional random seed for generating particles.
*/
template <class InitFunctor, class ParticleListType, class LocalGridType>
int createParticles(
Cabana::InitRandom tag, const InitFunctor& create_functor,
ParticleListType& particle_list, const int particles_per_cell,
LocalGridType& local_grid, const bool shrink_to_fit = true,
const uint64_t seed = 123456,
LocalGridType& local_grid, const std::size_t previous_num_particles = 0,
const bool shrink_to_fit = true, const uint64_t seed = 123456,
typename std::enable_if<Cajita::is_particle_list<ParticleListType>::value,
int>::type* = 0 )
{
using exec_space = typename ParticleListType::memory_space::execution_space;
return createParticles( tag, exec_space{}, create_functor, particle_list,
particles_per_cell, local_grid, shrink_to_fit,
seed );
particles_per_cell, local_grid,
previous_num_particles, shrink_to_fit, seed );
}

//---------------------------------------------------------------------------//
Expand All @@ -209,13 +216,16 @@ int createParticles(
the number of grid cells times particles_per_cell.s
\param particles_per_cell The number of particles to sample each cell with.
\param local_grid The LocalGrid over which particles will be created.
\param previous_num_particles Optionally specify how many particles are
already in the container (and should be unchanged).
\param seed Optional random seed for generating particles.
*/
template <class ExecutionSpace, class PositionType, class LocalGridType>
void createParticles(
Cabana::InitRandom, const ExecutionSpace& exec_space,
PositionType& positions, const int particles_per_cell,
LocalGridType& local_grid, const uint64_t seed = 123456,
LocalGridType& local_grid, const std::size_t previous_num_particles = 0,
const uint64_t seed = 123456,
typename std::enable_if<( Cabana::is_slice<PositionType>::value ||
Kokkos::is_view<PositionType>::value ),
int>::type* = 0 )
Expand All @@ -238,8 +248,9 @@ void createParticles(
pool.init( local_seed, owned_cells.size() );

// Ensure correct space for the particles.
assert( positions.size() == static_cast<std::size_t>(
particles_per_cell * owned_cells.size() ) );
assert( positions.size() == static_cast<std::size_t>( particles_per_cell *
owned_cells.size() ) +
previous_num_particles );

// Initialize particles.
Cajita::grid_parallel_for(
Expand Down Expand Up @@ -270,7 +281,8 @@ void createParticles(
for ( int p = 0; p < particles_per_cell; ++p )
{
// Local particle id.
int pid = cell_id * particles_per_cell + p;
int pid =
previous_num_particles + cell_id * particles_per_cell + p;

// Select a random point in the cell for the particle
// location. These coordinates are logical.
Expand All @@ -292,20 +304,22 @@ void createParticles(
the number of grid cells times particles_per_cell.s
\param particles_per_cell The number of particles to sample each cell with.
\param local_grid The LocalGrid over which particles will be created.
\param previous_num_particles Optionally specify how many particles are
already in the container (and should be unchanged).
\param seed Optional random seed for generating particles.
*/
template <class PositionType, class LocalGridType>
void createParticles(
Cabana::InitRandom tag, PositionType& positions,
const int particles_per_cell, LocalGridType& local_grid,
const uint64_t seed = 123456,
const std::size_t previous_num_particles = 0, const uint64_t seed = 123456,
typename std::enable_if<( Cabana::is_slice<PositionType>::value ||
Kokkos::is_view<PositionType>::value ),
int>::type* = 0 )
{
using exec_space = typename PositionType::execution_space;
createParticles( tag, exec_space{}, positions, particles_per_cell,
local_grid, seed );
local_grid, previous_num_particles, seed );
}

//---------------------------------------------------------------------------//
Expand All @@ -326,6 +340,8 @@ void createParticles(
\param particles_per_cell_dim The number of particles to populate each cell
dimension with.
\param local_grid The LocalGrid over which particles will be created.
\param previous_num_particles Optionally specify how many particles are
already in the container (and should be unchanged).
\param shrink_to_fit Optionally remove unused allocated space after creation.
*/
template <class ExecutionSpace, class InitFunctor, class ParticleListType,
Expand All @@ -334,6 +350,7 @@ int createParticles(
Cabana::InitUniform, const ExecutionSpace& exec_space,
const InitFunctor& create_functor, ParticleListType& particle_list,
const int particles_per_cell_dim, LocalGridType& local_grid,
const std::size_t previous_num_particles = 0,
const bool shrink_to_fit = true,
typename std::enable_if<Cajita::is_particle_list<ParticleListType>::value,
int>::type* = 0 )
Expand All @@ -355,10 +372,11 @@ int createParticles(
int particles_per_cell = particles_per_cell_dim * particles_per_cell_dim *
particles_per_cell_dim;
int num_particles = particles_per_cell * owned_cells.size();
aosoa.resize( num_particles );
aosoa.resize( previous_num_particles + num_particles );

// Creation count.
// Creation count (start from previous).
auto count = Kokkos::View<int*, memory_space>( "particle_count", 1 );
Kokkos::deep_copy( count, previous_num_particles );

// Initialize particles.
Cajita::grid_parallel_for(
Expand Down Expand Up @@ -403,7 +421,8 @@ int createParticles(
for ( int kp = 0; kp < particles_per_cell_dim; ++kp )
{
// Local particle id.
int pid = cell_id * particles_per_cell + ip +
int pid = previous_num_particles +
cell_id * particles_per_cell + ip +
particles_per_cell_dim *
( jp + particles_per_cell_dim * kp );

Expand Down Expand Up @@ -455,19 +474,23 @@ int createParticles(
\param particles_per_cell_dim The number of particles to populate each cell
dimension with.
\param local_grid The LocalGrid over which particles will be created.
\param shrink_to_fit Optionally remove unused allocated space after creation.
\param previous_num_particles Optionally specify how many particles are
already in the container (and should be unchanged).
\param shrink_to_fit Optionally remove unused allocated space after creation.
*/
template <class InitFunctor, class ParticleListType, class LocalGridType>
int createParticles(
Cabana::InitUniform tag, const InitFunctor& create_functor,
ParticleListType& particle_list, const int particles_per_cell_dim,
LocalGridType& local_grid, const bool shrink_to_fit = true,
LocalGridType& local_grid, const std::size_t previous_num_particles = 0,
const bool shrink_to_fit = true,
typename std::enable_if<Cajita::is_particle_list<ParticleListType>::value,
int>::type* = 0 )
{
using exec_space = typename ParticleListType::memory_space::execution_space;
return createParticles( tag, exec_space{}, create_functor, particle_list,
particles_per_cell_dim, local_grid, shrink_to_fit );
particles_per_cell_dim, local_grid,
previous_num_particles, shrink_to_fit );
}

//---------------------------------------------------------------------------//
Expand All @@ -480,12 +503,14 @@ int createParticles(
\param particles_per_cell_dim The number of particles to populate each cell
dimension with.
\param local_grid The LocalGrid over which particles will be created.
\param previous_num_particles Optionally specify how many particles are
already in the container (and should be unchanged).
*/
template <class ExecutionSpace, class PositionType, class LocalGridType>
void createParticles(
Cabana::InitUniform, const ExecutionSpace& exec_space,
PositionType& positions, const int particles_per_cell_dim,
LocalGridType& local_grid,
LocalGridType& local_grid, const std::size_t previous_num_particles = 0,
typename std::enable_if<( Cabana::is_slice<PositionType>::value ||
Kokkos::is_view<PositionType>::value ),
int>::type* = 0 )
Expand All @@ -501,8 +526,9 @@ void createParticles(
particles_per_cell_dim;

// Ensure correct space for the particles.
assert( positions.size() == static_cast<std::size_t>(
particles_per_cell * owned_cells.size() ) );
assert( positions.size() == static_cast<std::size_t>( particles_per_cell *
owned_cells.size() ) +
previous_num_particles );

// Initialize particles.
Cajita::grid_parallel_for(
Expand Down Expand Up @@ -540,7 +566,8 @@ void createParticles(
for ( int kp = 0; kp < particles_per_cell_dim; ++kp )
{
// Local particle id.
int pid = cell_id * particles_per_cell + ip +
int pid = previous_num_particles +
cell_id * particles_per_cell + ip +
particles_per_cell_dim *
( jp + particles_per_cell_dim * kp );

Expand Down Expand Up @@ -568,18 +595,21 @@ void createParticles(
\param particles_per_cell_dim The number of particles to populate each cell
dimension with.
\param local_grid The LocalGrid over which particles will be created.
\param previous_num_particles Optionally specify how many particles are
already in the container (and should be unchanged).
*/
template <class PositionType, class LocalGridType>
void createParticles(
Cabana::InitUniform tag, PositionType& positions,
const int particles_per_cell_dim, LocalGridType& local_grid,
const std::size_t previous_num_particles = 0,
typename std::enable_if<( Cabana::is_slice<PositionType>::value ||
Kokkos::is_view<PositionType>::value ),
int>::type* = 0 )
{
using exec_space = typename PositionType::execution_space;
createParticles( tag, exec_space{}, positions, particles_per_cell_dim,
local_grid );
local_grid, previous_num_particles );
}
} // namespace Cajita

Expand Down
59 changes: 42 additions & 17 deletions cajita/unit_test/tstParticleInit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ struct Bar : public Cabana::Field::Scalar<double>

//---------------------------------------------------------------------------//
template <class InitType>
void initParticleListTest( InitType init_type, int ppc )
void initParticleListTest( InitType init_type, int ppc,
const int multiplier = 1 )
{
// Global bounding box.
double cell_size = 0.23;
std::array<int, 3> global_num_cell = { 43, 32, 39 };
std::array<int, 3> global_num_cell = { 17, 10, 23 };
std::array<double, 3> global_low_corner = { 1.2, 3.3, -2.8 };
std::array<double, 3> global_high_corner = {
global_low_corner[0] + cell_size * global_num_cell[0],
Expand Down Expand Up @@ -105,19 +106,25 @@ void initParticleListTest( InitType init_type, int ppc )
}
};

// Initialize particles.
int num_p = Cajita::createParticles( init_type, TEST_EXECSPACE(), init_func,
particles, ppc, *local_grid );

// Initialize particles (potentially multiple times).
int created_particles = 0;
int prev_particle = 0;
for ( int m = 0; m < multiplier; ++m )
{
created_particles = Cajita::createParticles(
init_type, TEST_EXECSPACE(), init_func, particles, ppc, *local_grid,
prev_particle );
prev_particle = created_particles;
}
// Check that we made particles.
EXPECT_TRUE( num_p > 0 );
EXPECT_TRUE( created_particles > 0 );

// Compute the global number of particles.
int global_num_particle = particles.size();
MPI_Allreduce( MPI_IN_PLACE, &global_num_particle, 1, MPI_INT, MPI_SUM,
MPI_COMM_WORLD );
int expect_num_particle =
totalParticlesPerCell( init_type, ppc ) *
multiplier * totalParticlesPerCell( init_type, ppc ) *
( global_grid->globalNumEntity( Cajita::Cell(), Dim::I ) - 2 ) *
( global_grid->globalNumEntity( Cajita::Cell(), Dim::J ) - 2 ) *
( global_grid->globalNumEntity( Cajita::Cell(), Dim::K ) - 2 );
Expand All @@ -132,7 +139,7 @@ void initParticleListTest( InitType init_type, int ppc )
// Check that all particles are in the box and got initialized correctly.
auto host_particles =
Cabana::create_mirror_view_and_copy( Kokkos::HostSpace(), particles );
for ( int p = 0; p < num_p; ++p )
for ( int p = 0; p < created_particles; ++p )
{
auto particle = host_particles.getParticle( p );

Expand All @@ -149,11 +156,11 @@ void initParticleListTest( InitType init_type, int ppc )

//---------------------------------------------------------------------------//
template <class InitType>
void initSliceTest( InitType init_type, int ppc )
void initSliceTest( InitType init_type, int ppc, const int multiplier = 1 )
{
// Global bounding box.
double cell_size = 0.23;
std::array<int, 3> global_num_cell = { 43, 32, 39 };
std::array<int, 3> global_num_cell = { 21, 19, 7 };
std::array<double, 3> global_low_corner = { 1.2, 3.3, -2.8 };
std::array<double, 3> global_high_corner = {
global_low_corner[0] + cell_size * global_num_cell[0],
Expand Down Expand Up @@ -182,16 +189,23 @@ void initSliceTest( InitType init_type, int ppc )
global_low_corner[Dim::J], global_high_corner[Dim::J],
global_low_corner[Dim::K], global_high_corner[Dim::K] };

// Initialize all particles.
Cajita::createParticles( init_type, TEST_EXECSPACE(), positions, ppc,
*local_grid );
// Initialize all particles (potentially multiple times).
int prev_particle = 0;
for ( int m = 0; m < multiplier; ++m )
{
aosoa.resize( prev_particle + num_particle );
positions = Cabana::slice<0>( aosoa );
Cajita::createParticles( init_type, TEST_EXECSPACE(), positions, ppc,
*local_grid, prev_particle );
prev_particle += num_particle;
}

// Check that we created all particles.
int global_num_particle = positions.size();
MPI_Allreduce( MPI_IN_PLACE, &global_num_particle, 1, MPI_INT, MPI_SUM,
MPI_COMM_WORLD );
int expect_num_particle =
totalParticlesPerCell( init_type, ppc ) *
multiplier * totalParticlesPerCell( init_type, ppc ) *
global_grid->globalNumEntity( Cajita::Cell(), Dim::I ) *
global_grid->globalNumEntity( Cajita::Cell(), Dim::J ) *
global_grid->globalNumEntity( Cajita::Cell(), Dim::K );
Expand All @@ -217,15 +231,26 @@ void initSliceTest( InitType init_type, int ppc )
TEST( TEST_CATEGORY, random_init_test )
{
initParticleListTest( Cabana::InitRandom(), 17 );
initSliceTest( Cabana::InitRandom(), 17 );
initSliceTest( Cabana::InitRandom(), 12 );
}

TEST( TEST_CATEGORY, uniform_init_test )
{
initParticleListTest( Cabana::InitUniform(), 3 );
initSliceTest( Cabana::InitUniform(), 3 );
initSliceTest( Cabana::InitUniform(), 2 );
}

TEST( TEST_CATEGORY, multiple_random_init_test )
{
initParticleListTest( Cabana::InitRandom(), 5, 4 );
initSliceTest( Cabana::InitRandom(), 9, 3 );
}

TEST( TEST_CATEGORY, multiple_uniform_init_test )
{
initParticleListTest( Cabana::InitUniform(), 2, 5 );
initSliceTest( Cabana::InitRandom(), 2, 3 );
}
//---------------------------------------------------------------------------//

} // end namespace Test
Loading

0 comments on commit c5fe5ef

Please sign in to comment.