244 const GridDataType& data,
246 boundary_send_buffers,
248 boundary_recv_buffers )
256 constexpr bool enable_local_comm =
true;
263 std::is_same_v< GridDataType, grid::Grid4DDataScalar< typename GridDataType::value_type > > ||
268 using ScalarType =
typename GridDataType::value_type;
273 std::vector< MPI_Request > data_send_requests;
285 int boundary_type = -1;
288 int local_subdomain_boundary;
289 int local_subdomain_id;
292 int neighbor_subdomain_boundary;
294 std::string to_string()
const
296 std::stringstream ss;
297 ss <<
"boundary_type: " << boundary_type <<
", ";
298 ss <<
"local_subdomain: " << local_subdomain <<
", ";
299 if ( boundary_type == 0 )
301 ss <<
"local_subdomain_boundary: " <<
static_cast< grid::BoundaryVertex >( local_subdomain_boundary )
304 else if ( boundary_type == 1 )
306 ss <<
"local_subdomain_boundary: " <<
static_cast< grid::BoundaryEdge >( local_subdomain_boundary )
309 else if ( boundary_type == 2 )
311 ss <<
"local_subdomain_boundary: " <<
static_cast< grid::BoundaryFace >( local_subdomain_boundary )
314 ss <<
"neighbor_subdomain: " << neighbor_subdomain <<
", ";
315 if ( boundary_type == 0 )
317 ss <<
"neighbor_subdomain_boundary: "
320 else if ( boundary_type == 1 )
322 ss <<
"neighbor_subdomain_boundary: "
325 else if ( boundary_type == 2 )
327 ss <<
"neighbor_subdomain_boundary: "
335 std::vector< SendRecvPair > send_recv_pairs;
337 for (
const auto& [local_subdomain_info, idx_and_neighborhood] : domain.
subdomains() )
339 const auto& [local_subdomain_id, neighborhood] = idx_and_neighborhood;
341 for (
const auto& [local_vertex_boundary, neighbors] : neighborhood.neighborhood_vertex() )
344 for (
const auto& neighbor : neighbors )
346 const auto& [neighbor_subdomain_info, neighbor_local_boundary, neighbor_rank] = neighbor;
348 SendRecvPair send_recv_pair{
351 .local_subdomain = local_subdomain_info,
352 .local_subdomain_boundary =
static_cast< int >( local_vertex_boundary ),
353 .local_subdomain_id = local_subdomain_id,
354 .neighbor_rank = neighbor_rank,
355 .neighbor_subdomain = neighbor_subdomain_info,
356 .neighbor_subdomain_boundary =
static_cast< int >( neighbor_local_boundary ) };
357 send_recv_pairs.push_back( send_recv_pair );
361 for (
const auto& [local_edge_boundary, neighbors] : neighborhood.neighborhood_edge() )
364 for (
const auto& neighbor : neighbors )
366 const auto& [neighbor_subdomain_info, neighbor_local_boundary, _, neighbor_rank] = neighbor;
368 SendRecvPair send_recv_pair{
371 .local_subdomain = local_subdomain_info,
372 .local_subdomain_boundary =
static_cast< int >( local_edge_boundary ),
373 .local_subdomain_id = local_subdomain_id,
374 .neighbor_rank = neighbor_rank,
375 .neighbor_subdomain = neighbor_subdomain_info,
376 .neighbor_subdomain_boundary =
static_cast< int >( neighbor_local_boundary ) };
377 send_recv_pairs.push_back( send_recv_pair );
381 for (
const auto& [local_face_boundary, neighbor] : neighborhood.neighborhood_face() )
384 const auto& [neighbor_subdomain_info, neighbor_local_boundary, _, neighbor_rank] = neighbor;
386 SendRecvPair send_recv_pair{
389 .local_subdomain = local_subdomain_info,
390 .local_subdomain_boundary =
static_cast< int >( local_face_boundary ),
391 .local_subdomain_id = local_subdomain_id,
392 .neighbor_rank = neighbor_rank,
393 .neighbor_subdomain = neighbor_subdomain_info,
394 .neighbor_subdomain_boundary =
static_cast< int >( neighbor_local_boundary ) };
395 send_recv_pairs.push_back( send_recv_pair );
404 std::sort( send_recv_pairs.begin(), send_recv_pairs.end(), [](
const SendRecvPair& a,
const SendRecvPair& b ) {
405 if ( a.boundary_type != b.boundary_type )
406 return a.boundary_type < b.boundary_type;
407 if ( a.neighbor_subdomain != b.neighbor_subdomain )
408 return a.neighbor_subdomain < b.neighbor_subdomain;
409 if ( a.neighbor_subdomain_boundary != b.neighbor_subdomain_boundary )
410 return a.neighbor_subdomain_boundary < b.neighbor_subdomain_boundary;
411 if ( a.local_subdomain != b.local_subdomain )
412 return a.local_subdomain < b.local_subdomain;
413 return a.local_subdomain_boundary < b.local_subdomain_boundary;
416 std::vector< MPI_Request > data_recv_requests;
418 for (
const auto& send_recv_pair : send_recv_pairs )
421 if ( enable_local_comm && send_recv_pair.local_rank == send_recv_pair.neighbor_rank )
426 ScalarType* recv_buffer_ptr =
nullptr;
427 int recv_buffer_size = 0;
429 if ( send_recv_pair.boundary_type == 0 )
431 const auto& recv_buffer = boundary_recv_buffers.buffer_vertex(
432 send_recv_pair.local_subdomain,
434 send_recv_pair.neighbor_subdomain,
437 recv_buffer_ptr = recv_buffer.data();
438 recv_buffer_size = recv_buffer.span();
440 else if ( send_recv_pair.boundary_type == 1 )
442 const auto& recv_buffer = boundary_recv_buffers.buffer_edge(
443 send_recv_pair.local_subdomain,
445 send_recv_pair.neighbor_subdomain,
448 recv_buffer_ptr = recv_buffer.data();
449 recv_buffer_size = recv_buffer.span();
451 else if ( send_recv_pair.boundary_type == 2 )
453 const auto& recv_buffer = boundary_recv_buffers.buffer_face(
454 send_recv_pair.local_subdomain,
456 send_recv_pair.neighbor_subdomain,
459 recv_buffer_ptr = recv_buffer.data();
460 recv_buffer_size = recv_buffer.span();
464 Kokkos::abort(
"Unknown boundary type" );
467 MPI_Request data_recv_request;
471 mpi::mpi_datatype< ScalarType >(),
472 send_recv_pair.neighbor_rank,
475 &data_recv_request );
476 data_recv_requests.push_back( data_recv_request );
484 std::sort( send_recv_pairs.begin(), send_recv_pairs.end(), [](
const SendRecvPair& a,
const SendRecvPair& b ) {
485 if ( a.boundary_type != b.boundary_type )
486 return a.boundary_type < b.boundary_type;
487 if ( a.local_subdomain != b.local_subdomain )
488 return a.local_subdomain < b.local_subdomain;
489 if ( a.local_subdomain_boundary != b.local_subdomain_boundary )
490 return a.local_subdomain_boundary < b.local_subdomain_boundary;
491 if ( a.neighbor_subdomain != b.neighbor_subdomain )
492 return a.neighbor_subdomain < b.neighbor_subdomain;
493 return a.neighbor_subdomain_boundary < b.neighbor_subdomain_boundary;
496 for (
const auto& send_recv_pair : send_recv_pairs )
498 const auto local_comm = enable_local_comm && send_recv_pair.local_rank == send_recv_pair.neighbor_rank;
502 const auto local_subdomain_id = send_recv_pair.local_subdomain_id;
506 ScalarType* send_buffer_ptr =
nullptr;
507 int send_buffer_size = 0;
509 if ( send_recv_pair.boundary_type == 0 )
511 const auto local_vertex_boundary =
517 const auto& recv_buffer = boundary_recv_buffers.buffer_vertex(
518 send_recv_pair.local_subdomain,
520 send_recv_pair.neighbor_subdomain,
523 if ( !domain.
subdomains().contains( send_recv_pair.neighbor_subdomain ) )
525 Kokkos::abort(
"Subdomain not found locally - but it should be there..." );
528 const auto local_subdomain_id_of_neighboring_subdomain =
529 std::get< 0 >( domain.
subdomains().at( send_recv_pair.neighbor_subdomain ) );
534 local_subdomain_id_of_neighboring_subdomain,
539 auto& send_buffer = boundary_send_buffers.buffer_vertex(
540 send_recv_pair.local_subdomain,
542 send_recv_pair.neighbor_subdomain,
545 send_buffer_ptr = send_buffer.data();
546 send_buffer_size = send_buffer.span();
548 copy_to_buffer( send_buffer, data, local_subdomain_id, local_vertex_boundary );
550 else if ( send_recv_pair.boundary_type == 1 )
552 const auto local_edge_boundary =
558 const auto& recv_buffer = boundary_recv_buffers.buffer_edge(
559 send_recv_pair.local_subdomain,
561 send_recv_pair.neighbor_subdomain,
564 if ( !domain.
subdomains().contains( send_recv_pair.neighbor_subdomain ) )
566 Kokkos::abort(
"Subdomain not found locally - but it should be there..." );
569 const auto local_subdomain_id_of_neighboring_subdomain =
570 std::get< 0 >( domain.
subdomains().at( send_recv_pair.neighbor_subdomain ) );
575 local_subdomain_id_of_neighboring_subdomain,
580 auto& send_buffer = boundary_send_buffers.buffer_edge(
581 send_recv_pair.local_subdomain,
583 send_recv_pair.neighbor_subdomain,
586 send_buffer_ptr = send_buffer.data();
587 send_buffer_size = send_buffer.span();
589 copy_to_buffer( send_buffer, data, local_subdomain_id, local_edge_boundary );
591 else if ( send_recv_pair.boundary_type == 2 )
593 const auto local_face_boundary =
599 const auto& recv_buffer = boundary_recv_buffers.buffer_face(
600 send_recv_pair.local_subdomain,
602 send_recv_pair.neighbor_subdomain,
605 if ( !domain.
subdomains().contains( send_recv_pair.neighbor_subdomain ) )
607 Kokkos::abort(
"Subdomain not found locally - but it should be there..." );
610 const auto local_subdomain_id_of_neighboring_subdomain =
611 std::get< 0 >( domain.
subdomains().at( send_recv_pair.neighbor_subdomain ) );
616 local_subdomain_id_of_neighboring_subdomain,
621 const auto& send_buffer = boundary_send_buffers.buffer_face(
622 send_recv_pair.local_subdomain,
624 send_recv_pair.neighbor_subdomain,
627 send_buffer_ptr = send_buffer.data();
628 send_buffer_size = send_buffer.span();
630 copy_to_buffer( send_buffer, data, local_subdomain_id, local_face_boundary );
634 Kokkos::abort(
"Unknown boundary type" );
637 Kokkos::fence(
"deep_copy_into_send_buffer" );
640 MPI_Request data_send_request;
644 mpi::mpi_datatype< ScalarType >(),
645 send_recv_pair.neighbor_rank,
648 &data_send_request );
649 data_send_requests.push_back( data_send_request );
656 MPI_Waitall( data_send_requests.size(), data_send_requests.data(), MPI_STATUSES_IGNORE );
657 MPI_Waitall( data_recv_requests.size(), data_recv_requests.data(), MPI_STATUSES_IGNORE );