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

Create particles with existing particles #693

Merged
merged 3 commits into from
Sep 21, 2023
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
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
Loading