70 const InitFunctor& create_functor, ParticleListType& particle_list,
71 const int particles_per_cell, LocalGridType& local_grid,
72 const std::size_t previous_num_particles = 0,
73 const bool shrink_to_fit =
true,
const uint64_t seed = 123456,
78 using memory_space =
typename ParticleListType::memory_space;
84 const auto& global_grid = local_grid.globalGrid();
87 auto owned_cells = local_grid.indexSpace(
Own(),
Cell(),
Local() );
90 const auto local_seed =
91 global_grid.blockId() + ( seed % ( global_grid.blockId() + 1 ) );
92 using rnd_type = Kokkos::Random_XorShift64_Pool<ExecutionSpace>;
94 pool.init( local_seed, owned_cells.size() );
97 auto& aosoa = particle_list.aosoa();
101 int num_particles = particles_per_cell * owned_cells.size();
102 aosoa.resize( previous_num_particles + num_particles );
105 auto count = Kokkos::View<int*, memory_space>(
"particle_count", 1 );
106 Kokkos::deep_copy( count, previous_num_particles );
110 "Cabana::Grid::ParticleInit::Random", exec_space, owned_cells,
111 KOKKOS_LAMBDA(
const int i,
const int j,
const int k ) {
113 int i_own = i - owned_cells.min( Dim::I );
114 int j_own = j - owned_cells.min( Dim::J );
115 int k_own = k - owned_cells.min( Dim::K );
117 i_own + owned_cells.extent( Dim::I ) *
118 ( j_own + k_own * owned_cells.extent( Dim::J ) );
121 int low_node[3] = { i, j, k };
122 double low_coords[3];
123 local_mesh.coordinates(
Node(), low_node, low_coords );
126 int high_node[3] = { i + 1, j + 1, k + 1 };
127 double high_coords[3];
128 local_mesh.coordinates(
Node(), high_node, high_coords );
131 auto rand = pool.get_state( cell_id );
138 local_mesh.measure(
Cell(), low_node ) / particles_per_cell;
141 for (
int p = 0; p < particles_per_cell; ++p )
145 previous_num_particles + cell_id * particles_per_cell + p;
149 for (
int d = 0; d < 3; ++d )
151 px[d] = Kokkos::rand<
decltype( rand ),
double>::draw(
152 rand, low_coords[d], high_coords[d] );
156 auto particle = particle_list.getParticle( pid );
157 bool created = create_functor( pid, px, pv, particle );
162 auto c = Kokkos::atomic_fetch_add( &count( 0 ), 1 );
163 particle_list.setParticle( particle, c );
170 Kokkos::create_mirror_view_and_copy( Kokkos::HostSpace(), count );
171 aosoa.resize( count_host( 0 ) );
174 return count_host( 0 );
199 ParticleListType& particle_list,
const int particles_per_cell,
200 LocalGridType& local_grid,
const std::size_t previous_num_particles = 0,
201 const bool shrink_to_fit =
true,
const uint64_t seed = 123456,
205 using exec_space =
typename ParticleListType::memory_space::execution_space;
206 return createParticles( tag, exec_space{}, create_functor, particle_list,
207 particles_per_cell, local_grid,
208 previous_num_particles, shrink_to_fit, seed );
227 PositionType& positions,
const int particles_per_cell,
228 LocalGridType& local_grid,
const std::size_t previous_num_particles = 0,
229 const uint64_t seed = 123456,
231 Kokkos::is_view<PositionType>::value ),
238 const auto& global_grid = local_grid.globalGrid();
241 auto owned_cells = local_grid.indexSpace(
Own(),
Cell(),
Local() );
244 const auto local_seed =
245 global_grid.blockId() + ( seed % ( global_grid.blockId() + 1 ) );
246 using rnd_type = Kokkos::Random_XorShift64_Pool<ExecutionSpace>;
248 pool.init( local_seed, owned_cells.size() );
251 assert( positions.size() ==
static_cast<std::size_t
>( particles_per_cell *
252 owned_cells.size() ) +
253 previous_num_particles );
257 "Cabana::Grid::ParticleInit::Random", exec_space, owned_cells,
258 KOKKOS_LAMBDA(
const int i,
const int j,
const int k ) {
260 int i_own = i - owned_cells.min( Dim::I );
261 int j_own = j - owned_cells.min( Dim::J );
262 int k_own = k - owned_cells.min( Dim::K );
264 i_own + owned_cells.extent( Dim::I ) *
265 ( j_own + k_own * owned_cells.extent( Dim::J ) );
268 int low_node[3] = { i, j, k };
269 double low_coords[3];
270 local_mesh.coordinates(
Node(), low_node, low_coords );
273 int high_node[3] = { i + 1, j + 1, k + 1 };
274 double high_coords[3];
275 local_mesh.coordinates(
Node(), high_node, high_coords );
278 auto rand = pool.get_state( cell_id );
281 for (
int p = 0; p < particles_per_cell; ++p )
285 previous_num_particles + cell_id * particles_per_cell + p;
289 for (
int d = 0; d < 3; ++d )
291 positions( pid, d ) =
292 Kokkos::rand<
decltype( rand ),
double>::draw(
293 rand, low_coords[d], high_coords[d] );
314 const int particles_per_cell, LocalGridType& local_grid,
315 const std::size_t previous_num_particles = 0,
const uint64_t seed = 123456,
317 Kokkos::is_view<PositionType>::value ),
320 using exec_space =
typename PositionType::execution_space;
322 local_grid, previous_num_particles, seed );
351 const InitFunctor& create_functor, ParticleListType& particle_list,
352 const int particles_per_cell_dim, LocalGridType& local_grid,
353 const std::size_t previous_num_particles = 0,
354 const bool shrink_to_fit =
true,
359 using memory_space =
typename ParticleListType::memory_space;
365 auto owned_cells = local_grid.indexSpace(
Own(),
Cell(),
Local() );
368 auto& aosoa = particle_list.aosoa();
371 int particles_per_cell = particles_per_cell_dim * particles_per_cell_dim *
372 particles_per_cell_dim;
373 int num_particles = particles_per_cell * owned_cells.size();
374 aosoa.resize( previous_num_particles + num_particles );
377 auto count = Kokkos::View<int*, memory_space>(
"particle_count", 1 );
378 Kokkos::deep_copy( count, previous_num_particles );
382 "Cabana::Grid::ParticleInit::Uniform", exec_space, owned_cells,
383 KOKKOS_LAMBDA(
const int i,
const int j,
const int k ) {
385 int i_own = i - owned_cells.min( Dim::I );
386 int j_own = j - owned_cells.min( Dim::J );
387 int k_own = k - owned_cells.min( Dim::K );
389 i_own + owned_cells.extent( Dim::I ) *
390 ( j_own + k_own * owned_cells.extent( Dim::J ) );
393 int low_node[3] = { i, j, k };
394 double low_coords[3];
395 local_mesh.coordinates(
Node(), low_node, low_coords );
398 int high_node[3] = { i + 1, j + 1, k + 1 };
399 double high_coords[3];
400 local_mesh.coordinates(
Node(), high_node, high_coords );
403 double spacing[3] = { ( high_coords[Dim::I] - low_coords[Dim::I] ) /
404 particles_per_cell_dim,
405 ( high_coords[Dim::J] - low_coords[Dim::J] ) /
406 particles_per_cell_dim,
407 ( high_coords[Dim::K] - low_coords[Dim::K] ) /
408 particles_per_cell_dim };
415 local_mesh.measure(
Cell(), low_node ) / particles_per_cell;
418 for (
int ip = 0; ip < particles_per_cell_dim; ++ip )
419 for (
int jp = 0; jp < particles_per_cell_dim; ++jp )
420 for (
int kp = 0; kp < particles_per_cell_dim; ++kp )
423 int pid = previous_num_particles +
424 cell_id * particles_per_cell + ip +
425 particles_per_cell_dim *
426 ( jp + particles_per_cell_dim * kp );
429 px[Dim::I] = 0.5 * spacing[Dim::I] +
430 ip * spacing[Dim::I] + low_coords[Dim::I];
431 px[Dim::J] = 0.5 * spacing[Dim::J] +
432 jp * spacing[Dim::J] + low_coords[Dim::J];
433 px[Dim::K] = 0.5 * spacing[Dim::K] +
434 kp * spacing[Dim::K] + low_coords[Dim::K];
438 auto particle = particle_list.getParticle( pid );
439 bool created = create_functor( pid, px, pv, particle );
446 auto c = Kokkos::atomic_fetch_add( &count( 0 ), 1 );
447 particle_list.setParticle( particle, c );
454 Kokkos::create_mirror_view_and_copy( Kokkos::HostSpace(), count );
455 aosoa.resize( count_host( 0 ) );
458 return count_host( 0 );
483 ParticleListType& particle_list,
const int particles_per_cell_dim,
484 LocalGridType& local_grid,
const std::size_t previous_num_particles = 0,
485 const bool shrink_to_fit =
true,
489 using exec_space =
typename ParticleListType::memory_space::execution_space;
490 return createParticles( tag, exec_space{}, create_functor, particle_list,
491 particles_per_cell_dim, local_grid,
492 previous_num_particles, shrink_to_fit );
511 PositionType& positions,
const int particles_per_cell_dim,
512 LocalGridType& local_grid,
const std::size_t previous_num_particles = 0,
514 Kokkos::is_view<PositionType>::value ),
521 auto owned_cells = local_grid.indexSpace(
Own(),
Cell(),
Local() );
523 int particles_per_cell = particles_per_cell_dim * particles_per_cell_dim *
524 particles_per_cell_dim;
527 assert( positions.size() ==
static_cast<std::size_t
>( particles_per_cell *
528 owned_cells.size() ) +
529 previous_num_particles );
533 "Cabana::Grid::ParticleInit::Uniform", exec_space, owned_cells,
534 KOKKOS_LAMBDA(
const int i,
const int j,
const int k ) {
536 int i_own = i - owned_cells.min( Dim::I );
537 int j_own = j - owned_cells.min( Dim::J );
538 int k_own = k - owned_cells.min( Dim::K );
540 i_own + owned_cells.extent( Dim::I ) *
541 ( j_own + k_own * owned_cells.extent( Dim::J ) );
544 int low_node[3] = { i, j, k };
545 double low_coords[3];
546 local_mesh.coordinates(
Node(), low_node, low_coords );
549 int high_node[3] = { i + 1, j + 1, k + 1 };
550 double high_coords[3];
551 local_mesh.coordinates(
Node(), high_node, high_coords );
554 double spacing[3] = { ( high_coords[Dim::I] - low_coords[Dim::I] ) /
555 particles_per_cell_dim,
556 ( high_coords[Dim::J] - low_coords[Dim::J] ) /
557 particles_per_cell_dim,
558 ( high_coords[Dim::K] - low_coords[Dim::K] ) /
559 particles_per_cell_dim };
562 for (
int ip = 0; ip < particles_per_cell_dim; ++ip )
563 for (
int jp = 0; jp < particles_per_cell_dim; ++jp )
564 for (
int kp = 0; kp < particles_per_cell_dim; ++kp )
567 int pid = previous_num_particles +
568 cell_id * particles_per_cell + ip +
569 particles_per_cell_dim *
570 ( jp + particles_per_cell_dim * kp );
573 positions( pid, 0 ) = 0.5 * spacing[Dim::I] +
574 ip * spacing[Dim::I] +
576 positions( pid, 1 ) = 0.5 * spacing[Dim::J] +
577 jp * spacing[Dim::J] +
579 positions( pid, 2 ) = 0.5 * spacing[Dim::K] +
580 kp * spacing[Dim::K] +
602 const int particles_per_cell_dim, LocalGridType& local_grid,
603 const std::size_t previous_num_particles = 0,
605 Kokkos::is_view<PositionType>::value ),
608 using exec_space =
typename PositionType::execution_space;
610 local_grid, previous_num_particles );
void grid_parallel_for(const std::string &label, const ExecutionSpace &exec_space, const IndexSpace< N > &index_space, const FunctorType &functor)
Execute a functor in parallel with a multidimensional execution policy specified by the given index s...
Definition Cabana_Grid_Parallel.hpp:52
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< is_particle_list< ParticleListType >::value, int >::type *=0)
Initialize a random number of particles in each cell given an initialization functor.
Definition Cabana_Grid_ParticleInit.hpp:68
Application-level particle/mesh storage and single particle access.
Particle creation utilities.
ParticleList static type checker.
Definition Cabana_Grid_ParticleList.hpp:119