376 {
377 TRACE();
378
379
380
382
384
386
387
390
391
395 &hilbertInfo[0]);
398
399 m_log <<
"Initializing DG Slice " << sliceSeries.
m_fileNo <<
" ...";
400
402
403 if(
m_solver.grid().raw().treeb().noSolvers() > 1) {
405 cellIds[i] =
m_solver.grid().tree().grid2solver(cellIds[i]);
406 }
407 }
408
409
412
413
415
419
420
422
423 const MInt noMaxNodes = pow(
425 + 1,
426 2);
428
429
430 std::array<MFloat, m_dim> nodeCoord;
431
432
433 MInt noElementsSlice = 0;
434 for(
MInt h = 0, cellSum = 0, noNodes = 0, prevNoNodes = 0, sumElements = 0; h < sliceSeries.
m_noHilbertIds; h++) {
435 for(
MInt c = cellSum, e = 0; (c - cellSum) < hilbertInfo[h * 3 + 1]; e++) {
436
437
438
439
440 if(cellIds[c] <
m_solver.m_elements.cellId(e)) {
441
443
444 c++;
445
446 e--;
447 continue;
448 }
449
450 if(cellIds[c] ==
m_solver.m_elements.cellId(e)) {
451
452 const MInt noNodes1D =
m_solver.m_elements.polyDeg(e) + 1;
453
454
455 const MFloatTensor nodeCoordinates(&
m_solver.m_elements.nodeCoordinates(e), noNodes1D, noNodes1D, noNodes1D,
457
458 for(
MInt i = 0; i < noNodes1D; i++) {
459 for(
MInt j = 0; j < noNodes1D; j++) {
460 if(sliceSeries.
m_axis ==
"x") {
462 nodeCoord[1] = nodeCoordinates(0, i, j, 1);
463 nodeCoord[2] = nodeCoordinates(0, i, j, 2);
464 }
else if(sliceSeries.
m_axis ==
"y") {
465 nodeCoord[0] = nodeCoordinates(i, 0, j, 0);
467 nodeCoord[2] = nodeCoordinates(i, 0, j, 2);
468 }
else if(sliceSeries.
m_axis ==
"z") {
469 nodeCoord[0] = nodeCoordinates(i, j, 0, 0);
470 nodeCoord[1] = nodeCoordinates(i, j, 0, 1);
472 }
473
474 std::copy_n(&nodeCoord[0],
m_dim, &coordinates[noCoords]);
476 }
477 }
478 elementIds[noElementsSlice] = e;
479
480
481 elementOffset[noElementsSlice] = noNodes - prevNoNodes;
482
483
485 noNodes += noNodesXD;
486
487
488 elementNodes[noElementsSlice] = noNodesXD;
489 noElementsSlice++;
490
491
493
494 c++;
495 }
496 }
497
499
500
503
504 cellSum += hilbertInfo[h * 3 + 1];
505 prevNoNodes = noNodes;
506 sumElements = noElementsSlice;
507 }
508
513
514 std::copy_n(&elementIds[0], noElementsSlice, &sliceSeries.
m_elementIds[0]);
515 std::copy_n(&elementNodes[0], noElementsSlice, &sliceSeries.
m_elementNodes[0]);
516 std::copy_n(&elementOffset[0], noElementsSlice, &sliceSeries.
m_elementOffset[0]);
517 std::copy_n(&coordinates[0], noCoords, &sliceSeries.
m_coordinates[0]);
518 }
519
520
521
524 }
525
527
529
530 using namespace maia;
531
532
534
535
538 MPI_Comm_rank(
mpiComm(), &rank);
539 }
540
541
543 AT_, "rank", "sliceScratch[0]");
544
545
546 const MInt noSliceDomains =
547 std::count_if(sliceScratch.begin(), sliceScratch.end(), [](
const MInt a) { return a != -1; });
550 for(
MInt i : sliceScratch) {
551 if(i != -1) {
552 sliceDomains[position] = i;
553 position++;
554 }
555 }
556
557
558 MPI_Group globalGroup, localGroup;
560 MPI_Group_incl(globalGroup, noSliceDomains, &sliceDomains[0], &localGroup, AT_);
561
562
564
567
569
571
573
574 MInt sliceDomain = -1;
575 MPI_Comm_rank(sliceSeries.
m_mpiComm, &sliceDomain);
576
577
578
579
580
581 MIntScratchSpace noLocalHilbertIds(noSliceDomains, AT_,
"noLocalHilbertIds");
583
585 "MPI_IN_PLACE", "noLocalHilbertIds[0]");
586
587
589 offsetsRecvData[0] = 0;
590 for(
MInt i = 1; i < noSliceDomains; i++) {
591 offsetsRecvData[i] = offsetsRecvData[i - 1] + noLocalHilbertIds[i - 1] * 3;
592 }
593 MInt noTotalRecvData = offsetsRecvData[noSliceDomains - 1] + noLocalHilbertIds[noSliceDomains - 1] * 3;
594
595
596 MIntScratchSpace sendHilbertData(noLocalHilbertIds[sliceDomain] * 3, AT_,
"sendHilbertData");
597
599 sendHilbertData[i * 3] = hilbertInfo[i * 3];
600 sendHilbertData[i * 3 + 1] =
domainId();
602 }
603
604
607 for(
MInt i = 0; i < noSliceDomains; i++) {
608 noRecvData[i] = noLocalHilbertIds[i] * 3;
609 }
610
611
612 MPI_Allgatherv(&sendHilbertData[0], sendHilbertData.size(), MPI_INT, &recvHilbertData[0], &noRecvData[0],
613 &offsetsRecvData[0], MPI_INT, sliceSeries.
m_mpiComm, AT_,
"sendHilbertData[0]",
614 "recvHilbertData[0]");
615
616
618 for(
MInt i = 0; i < noTotalRecvData / 3; i++) {
619
620
621 sliceGlobalHilbertInfo[i][0] = recvHilbertData[i * 3];
622 sliceGlobalHilbertInfo[i][1] = recvHilbertData[i * 3 + 1];
623 sliceGlobalHilbertInfo[i][2] = recvHilbertData[i * 3 + 2];
624 }
625
626 std::stable_sort(sliceGlobalHilbertInfo.begin(), sliceGlobalHilbertInfo.end(),
627 [](
const std::array<MInt, 3>&
a,
const std::array<MInt, 3>&
b) { return a[1] < b[1]; });
628
629 std::stable_sort(sliceGlobalHilbertInfo.begin(), sliceGlobalHilbertInfo.end(),
630 [](
const std::array<MInt, 3>&
a,
const std::array<MInt, 3>&
b) { return a[0] < b[0]; });
631
632
633 MInt maxNoHilbertIds = *std::max_element(noLocalHilbertIds.begin(), noLocalHilbertIds.end());
637
638
639
640
641
642
643
644
645
646
647
648
649 for(
MInt i = 0, j = 0; i < noLocalHilbertIds[sliceDomain]; i++) {
651 j = 0;
652
653 while(sliceGlobalHilbertInfo[j][0] < hilbertInfo[i * 3]) {
654 offset += sliceGlobalHilbertInfo[j][2];
655 j++;
656 }
657
658 while(sliceGlobalHilbertInfo[j][1] <
domainId()) {
659 offset += sliceGlobalHilbertInfo[j][2];
660 j++;
661 }
662
664
666
668 }
669 }
670
671
672 MBool optimizedSliceIo =
true;
673 optimizedSliceIo = Context::getBasicProperty<MBool>("optimizedSliceIo", AT_, &optimizedSliceIo);
674
675
677
678 std::vector<MInt> bufferElementIdsPerHilbertId;
679 std::vector<MInt> bufferElementNodesPerHilbertIds;
680
683 back_inserter(bufferElementIdsPerHilbertId));
686 back_inserter(bufferElementNodesPerHilbertIds));
687
688 MInt noHilbertIdChunks = 0;
689
690
692
698
700
701
702 MInt startIdx = std::accumulate(&bufferElementIdsPerHilbertId[0], &bufferElementIdsPerHilbertId[h], 0);
703 MInt endIdx = std::accumulate(&bufferElementIdsPerHilbertId[0], &bufferElementIdsPerHilbertId[h + 1], 0);
704 offsetSum += bufferElementNodesPerHilbertIds[h - 1];
705 for(
MInt j = startIdx; j < endIdx; j++) {
707 }
708 } else {
709 i++;
713
716
717
718 offsetSum = 0;
719 }
720 }
721
722
724 i++;
725 noHilbertIdChunks = i;
726
728 0);
730 0);
732
735 }
736 }
737
738 MInt maxNoHilbertIdChunks = -1;
740 sliceSeries.
m_mpiComm, AT_,
"noHilbertIdChunks",
"maxNoHilbertIdChunks");
742
748 }
749
751 m_log <<
"done!" << std::endl;
752}
std::vector< MInt > m_elementOffset
std::vector< MInt > m_elementNodes
std::vector< MFloat > m_coordinates
std::vector< MInt > m_elementNodesHilbertOffset
std::vector< MInt > m_elementNodesPerHilbertIds
std::vector< MInt > m_polyDegs
std::vector< MInt > m_cellIdsPerHilbertId
std::vector< MInt > m_cellIdsOffset
std::vector< MInt > m_elementIds
std::vector< MInt > m_elementIdsPerHilbertId
static constexpr const MInt m_dim
This class is a ScratchSpace.
MInt ipow(MInt base, MInt exp)
Integer exponent function for non-negative exponents.
MInt globalNoDomains()
Return global number of domains.
std::basic_string< char > MString
int MPI_Allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgatherv
int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newcomm, const MString &name, const MString &varname)
same as MPI_Comm_create, but updates the number of MPI communicators
int MPI_Group_incl(MPI_Group group, int n, const int ranks[], MPI_Group *newgroup, const MString &name)
same as MPI_Group_incl
int MPI_Comm_group(MPI_Comm comm, MPI_Group *group, const MString &name, const MString &varname)
same as MPI_Comm_group
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgather
int MPI_Group_free(MPI_Group *group, const MString &name)
same as MPI_Group_free
Namespace for auxiliary functions/classes.