45 const MInt*
const sendSize,
const MPI_Comm comm, U*
const receiveBuffer,
46 const U*
const sendBuffer,
const MInt noDat = 1) {
52 ASSERT(tag < MPI_TAG_UB,
"");
53 ASSERT(noExDomains > 0,
"");
56 sendRequests.
fill(MPI_REQUEST_NULL);
57 recvRequests.
fill(MPI_REQUEST_NULL);
60 for(
MInt i = 0, receiveCount = 0; i < noExDomains; i++) {
61 MPI_Irecv(&(receiveBuffer[receiveCount]), noDat * recvSize[i], DTYPE, exDomainId[i], tag, comm, &recvRequests[i],
62 AT_,
"receiveBuffer");
63 receiveCount += noDat * recvSize[i];
67 for(
MInt i = 0, sendCount = 0; i < noExDomains; i++) {
68#if defined(HOST_Klogin)
69 MPI_Issend(
const_cast<U*
>(&sendBuffer[sendCount]), noDat * sendSize[i], DTYPE, exDomainId[i], tag, comm,
72 MPI_Isend(&sendBuffer[sendCount], noDat * sendSize[i], DTYPE, exDomainId[i], tag, comm, &sendRequests[i], AT_,
73 "&sendBuffer[sendCount]");
75 sendCount += noDat * sendSize[i];
79 MPI_Waitall(noExDomains, &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
80 MPI_Waitall(noExDomains, &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
96 const U*
const sendBuffer,
const MInt noDat = 1) {
101 const MInt tag = 612;
103 ASSERT(tag < MPI_TAG_UB,
"");
106 mpiRequest.
fill(MPI_REQUEST_NULL);
109 MPI_Allgather(&sendSize, 1, MPI_INT, &noToRecv[0], 1, MPI_INT, comm, AT_,
"sendSize",
"noToRecv");
110 const MInt totalNo = std::accumulate(noToRecv.
begin(), noToRecv.
end(), -sendSize);
112 std::copy(&sendBuffer[0], &sendBuffer[sendSize * noDat], &temp[0]);
116 for(
MInt i = 0; i < noDomains; i++) {
118 MPI_Ibcast(&temp[0], noDat * sendSize, DTYPE, i, comm, &mpiRequest[i], AT_,
"temp");
120 MPI_Ibcast(&receiveBuffer[recvCount], noDat * noToRecv[i], DTYPE, i, comm, &mpiRequest[i], AT_,
"receiveBuffer");
121 recvCount += noDat * noToRecv[i];
125 MPI_Waitall(noDomains, &mpiRequest[0], MPI_STATUSES_IGNORE, AT_);
145 const std::vector<std::vector<MInt>>& noValuesToRecv,
146 const std::vector<std::vector<MInt>>& noValuesToSend,
148 const U*
const sendBuffer,
149 U*
const receiveBuffer,
150 const MInt noDat = 1) {
154 const auto noNghbrDomains = exDomains.size();
155 ASSERT(noNghbrDomains > 0,
"");
158 for(
MUint i = 0; i < noNghbrDomains; i++) {
159 noHaloCells[i] = noValuesToRecv[i].
size();
160 noWindowCells[i] = noValuesToSend[i].
size();
164 exchangeBuffer(noNghbrDomains, exDomains.data(), &noHaloCells[0], &noWindowCells[0], comm, receiveBuffer, sendBuffer,
182 std::vector<MInt>& noValuesToRecv,
183 std::vector<MInt>& noValuesToSend,
185 const U*
const sendBuffer,
186 U*
const receiveBuffer,
187 const MInt noDat = 1) {
191 const auto noNghbrDomains = exDomains.size();
192 ASSERT(noNghbrDomains > 0,
"");
195 exchangeBuffer(noNghbrDomains, exDomains.data(), &noValuesToRecv[0], &noValuesToSend[0], comm, receiveBuffer,
213 const MInt*
const noValuesToSend,
214 const MInt*
const noValuesToRecv,
216 const U*
const sendBuffer,
217 U*
const receiveBuffer,
218 const MInt noDat = 1) {
222 const auto noNghbrDomains = exDomains.size();
223 ASSERT(noNghbrDomains > 0,
"");
226 exchangeBuffer(noNghbrDomains, exDomains.data(), &noValuesToRecv[0], &noValuesToSend[0], comm, receiveBuffer,
243 std::vector<MInt>& noValues,
245 const U*
const sendBuffer,
246 U*
const receiveBuffer,
247 const MInt noDat = 1) {
251 const auto noNghbrDomains = exDomains.size();
252 ASSERT(noNghbrDomains > 0,
"");
255 exchangeBuffer(noNghbrDomains, exDomains.data(), &noValues[0], &noValues[0], comm, receiveBuffer, sendBuffer, noDat);
271 const U*
const sendBuffer, U*
const receiveBuffer,
const MInt noDat = 1) {
275 const auto noNghbrDomains = exDomains.size();
276 ASSERT(noNghbrDomains > 0,
"");
282 exchangeBuffer(noNghbrDomains, exDomains.data(), &noV[0], &noV[0], comm, receiveBuffer, sendBuffer, noDat);
296 const MInt**
const ,
const MInt*
const noWindowCells,
const MInt**
const windowCells,
297 const MPI_Comm comm,
const U*
const data, U*
const haloBuffer,
const MInt noDat = 1) {
301 MInt sendCount = std::accumulate(noWindowCells, noWindowCells + noNghbrDomains, 0);
306 for(
MInt i = 0; i < noNghbrDomains; i++) {
307 for(
MInt j = 0; j < noWindowCells[i]; j++) {
308 for(
MInt k = 0; k < noDat; k++) {
309 windowBuffer[sendCount] = data[noDat * windowCells[i][j] + k];
316 exchangeBuffer(noNghbrDomains, nghbrDomains, noHaloCells, noWindowCells, comm, haloBuffer, &windowBuffer[0], noDat);
330 MInt*
const noWindowCells,
MInt**
const windowCells,
const MPI_Comm comm,
const U*
const data,
331 U*
const haloBuffer,
const MInt noDat = 1) {
333 exchangeData(nghbrDomains.size(), nghbrDomains.data(), noHaloCells, haloCells, noWindowCells, windowCells, comm, data,
348 const MInt**
const haloCells,
const MInt*
const noWindowCells,
const MInt**
const windowCells,
349 const MPI_Comm comm, U*
const data,
const MInt noDat = 1) {
353 MInt receiveCount = std::accumulate(noHaloCells, noHaloCells + noNghbrDomains, 0);
357 exchangeData(noNghbrDomains, nghbrDomains, noHaloCells, haloCells, noWindowCells, windowCells, comm, data,
358 &haloBuffer[0], noDat);
362 for(
MInt i = 0; i < noNghbrDomains; i++) {
363 for(
MInt j = 0; j < noHaloCells[i]; j++) {
364 for(
MInt k = 0; k < noDat; k++) {
365 data[noDat * haloCells[i][j] + k] = haloBuffer[receiveCount];
383 MInt*
const noWindowCells,
MInt**
const windowCells,
const MPI_Comm comm, U*
const data,
384 const MInt noDat = 1) {
386 exchangeData(nghbrDomains.size(), nghbrDomains.data(), noHaloCells, haloCells, noWindowCells, windowCells, comm, data,
401 const MInt**
const haloCells,
const MInt*
const noWindowCells,
402 const MInt**
const ,
const MPI_Comm comm,
const U*
const data,
403 U*
const windowBuffer,
const MInt noDat = 1) {
407 MInt receiveCount = std::accumulate(noHaloCells, noHaloCells + noNghbrDomains, 0);
412 for(
MInt i = 0; i < noNghbrDomains; i++) {
413 for(
MInt j = 0; j < noHaloCells[i]; j++) {
414 for(
MInt k = 0; k < noDat; k++) {
415 haloBuffer[receiveCount] = data[noDat * haloCells[i][j] + k];
422 exchangeBuffer(noNghbrDomains, nghbrDomains, noWindowCells, noHaloCells, comm, windowBuffer, &haloBuffer[0], noDat);
436 const std::vector<std::vector<MInt>>& haloCellVec,
437 const std::vector<std::vector<MInt>>& windowCellVec,
const MPI_Comm comm, U*
const data,
438 const MInt noDat = 1) {
440 ASSERT(noNghbrDomains == (
signed)windowCellVec.size() && noNghbrDomains == (
signed)haloCellVec.size(),
"");
445 for(
MInt i = 0; i < noNghbrDomains; i++) {
446 noHaloCells[i] = (signed)haloCellVec[i].size();
447 noWindowCells[i] = (signed)windowCellVec[i].size();
448 haloCells[i] = haloCellVec[i].
data();
449 windowCells[i] = windowCellVec[i].
data();
467 const std::vector<std::vector<MInt>>& haloCellVec,
468 const std::vector<std::vector<MInt>>& windowCellVec,
const MPI_Comm comm, U*
const data,
469 U*
const haloBuffer,
const MInt noDat = 1) {
471 ASSERT(noNghbrDomains == (
signed)windowCellVec.size() && noNghbrDomains == (
signed)haloCellVec.size(),
"");
476 for(
MInt i = 0; i < noNghbrDomains; i++) {
477 noHaloCells[i] = (signed)haloCellVec[i].size();
478 noWindowCells[i] = (signed)windowCellVec[i].size();
479 haloCells[i] = haloCellVec[i].
data();
480 windowCells[i] = windowCellVec[i].
data();
498void exchangeData(
const std::vector<MInt>& nghbrDomains,
const std::vector<std::vector<MInt>>& haloCellVec,
499 const std::vector<std::vector<MInt>>& windowCellVec,
const MPI_Comm comm, U*
const data,
500 const MInt noDat = 1) {
502 const MInt noNghbrDomains = (signed)nghbrDomains.size();
503 exchangeData(noNghbrDomains, nghbrDomains.data(), haloCellVec, windowCellVec, comm, data, noDat);
515template <std::
size_t N>
516void exchangeBitset(
const std::vector<MInt>& nghbrDomains,
const std::vector<std::vector<MInt>>& haloCellVec,
517 const std::vector<std::vector<MInt>>& windowCellVec,
const MPI_Comm comm,
518 std::bitset<N>*
const data,
const MInt noCells,
const MInt noDat = 1) {
520 static_assert(N <= 64,
"conversion to ulong not appropriate, change to ullong!");
521 const auto noNghbrDomains = (signed)nghbrDomains.size();
523 for(
MUint i = 0; i < nghbrDomains.size(); i++) {
524 for(
MInt windowCellId : windowCellVec[i]) {
525 tmp_data[windowCellId] = data[windowCellId].to_ulong();
528 exchangeData(noNghbrDomains, nghbrDomains.data(), haloCellVec, windowCellVec, comm, tmp_data.
data(), noDat);
529 for(
MUint i = 0; i < nghbrDomains.size(); i++) {
530 for(
MInt haloCellId : haloCellVec[i]) {
531 data[haloCellId] = std::bitset<N>(tmp_data[haloCellId]);
546void exchangeData(
const std::vector<MInt>& nghbrDomains, std::vector<std::vector<MInt>>& haloCellVec,
547 std::vector<std::vector<MInt>>& windowCellVec,
const MPI_Comm comm, U*
const data,
548 U*
const haloBuffer,
const MInt noDat = 1) {
550 const auto noNghbrDomains = (signed)nghbrDomains.size();
551 exchangeData(noNghbrDomains, nghbrDomains.data(), haloCellVec, windowCellVec, comm, data, haloBuffer, noDat);
565 const std::vector<std::vector<MInt>>& haloCellVec,
566 const std::vector<std::vector<MInt>>& windowCellVec,
const MPI_Comm comm,
const U*
const data,
567 U*
const windowBuffer,
const MInt noDat = 1) {
569 ASSERT(noNghbrDomains == (
signed)windowCellVec.size() && noNghbrDomains == (
signed)haloCellVec.size(),
"");
574 for(
MInt i = 0; i < noNghbrDomains; i++) {
575 noHaloCells[i] = (signed)haloCellVec[i].size();
576 noWindowCells[i] = (signed)windowCellVec[i].size();
577 haloCells[i] = haloCellVec[i].
data();
578 windowCells[i] = windowCellVec[i].
data();
595void reverseExchangeData(
const std::vector<MInt>& nghbrDomains,
const std::vector<std::vector<MInt>>& haloCellVec,
596 const std::vector<std::vector<MInt>>& windowCellVec,
const MPI_Comm comm,
const U*
const data,
597 U*
const windowBuffer,
const MInt noDat = 1) {
599 const auto noNghbrDomains = (signed)nghbrDomains.size();
600 reverseExchangeData(noNghbrDomains, nghbrDomains.data(), haloCellVec, windowCellVec, comm, data, windowBuffer, noDat);
613void exchangeScattered(
const std::vector<MInt>& nghbrDomains, std::vector<MInt>& sendDomainIndices,
614 std::vector<U>& sendData,
const MPI_Comm comm, std::vector<MInt>& recvOffsets,
615 std::vector<U>& recvBuffer,
const MInt noDat = 1) {
617 const auto noNghbrDomains = (signed)nghbrDomains.size();
618 if(sendDomainIndices.size() * ((unsigned)noDat) != sendData.size()) {
619 mTerm(1, AT_,
"Invalid exchange buffer sizes.");
627 for(
MInt sendDomainIndice : sendDomainIndices) {
628 ASSERT(sendDomainIndice > -1 && sendDomainIndice < noNghbrDomains,
"");
629 sendSize(sendDomainIndice)++;
632 exchangeBuffer(noNghbrDomains, nghbrDomains.data(), &unity[0], &unity[0], comm, &recvSize[0], &sendSize[0]);
636 for(
MInt i = 0; i < noNghbrDomains; i++) {
637 recvCnt += recvSize[i];
638 sendCnt += sendSize[i];
641 std::vector<MInt> sendOffsets;
643 sendOffsets.resize(noNghbrDomains + 1);
644 recvOffsets.resize(noNghbrDomains + 1);
648 for(
MInt i = 0; i < noNghbrDomains; i++) {
649 recvOffsets[i + 1] = recvOffsets[i] + recvSize[i];
650 sendOffsets[i + 1] = sendOffsets[i] + sendSize[i];
653 std::vector<U> sendBuffer;
655 sendBuffer.resize(sendCnt * noDat);
656 recvBuffer.resize(recvCnt * noDat);
658 std::fill(&sendSize[0], &sendSize[0] + noNghbrDomains, 0);
659 for(
MUint i = 0; i < sendDomainIndices.size(); i++) {
660 MInt idx = sendDomainIndices[i];
661 ASSERT(idx > -1 && idx < noNghbrDomains,
"");
662 for(
MInt j = 0; j < noDat; j++) {
663 sendBuffer[noDat * (sendOffsets[idx] + sendSize[idx]) + j] = sendData[noDat * i + j];
668 exchangeBuffer(noNghbrDomains, nghbrDomains.data(), &recvSize[0], &sendSize[0], comm, recvBuffer.
data(),
669 sendBuffer.data(), noDat);
682 return accumulate(exchangeCells.begin(), exchangeCells.end(), 0u,
683 [](
const MInt&
a,
const std::vector<MInt>&
b) { return a + static_cast<MInt>(b.size()); });
698template <
class dataType>
699void exchangeData(
const dataType*
const sendBuffer,
const MInt domainId,
const MInt noDomains,
const MPI_Comm mpiComm,
700 const MInt dataBlockSize,
const MInt*
const dataSizeSend,
const MInt*
const dataSizeRecv,
701 dataType*
const recvBuffer) {
704 using namespace maia;
715 for(
MInt i = 1; i < noDomains; i++) {
716 sendOffsets[i] = sendOffsets[i - 1] + dataBlockSize * dataSizeSend[i - 1];
717 recvOffsets[i] = recvOffsets[i - 1] + dataBlockSize * dataSizeRecv[i - 1];
722 for(
MInt i = 0; i < noDomains; i++) {
724 if(dataSizeRecv[i] > 0 && i != domainId) {
726 mpiComm, &recvRequests[recvCount], AT_,
"recvBuffer[recvOffsets[i]]");
733 for(
MInt i = 0; i < noDomains; i++) {
735 if(dataSizeSend[i] > 0) {
739 std::copy_n(&sendBuffer[sendOffsets[i]], dataBlockSize * dataSizeSend[i], &recvBuffer[recvOffsets[i]]);
741#if defined(HOST_Klogin)
742 MPI_Isend(
const_cast<dataType*
>(&sendBuffer[sendOffsets[i]]), dataBlockSize * dataSizeSend[i],
744 "const_cast<dataType*>(&sendBuffer[sendOffsets[i]])");
747 domainId, mpiComm, &sendRequests[sendCount], AT_,
"sendBuffer[sendOffsets[i]]");
756 MPI_Waitall(recvCount, &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
760 MPI_Waitall(sendCount, &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
766template <
class dataType>
768 const MInt*
const nghbrDomainIds,
const MPI_Comm mpiComm,
const MInt dataBlockSize,
769 const MInt*
const dataSizeSend,
const MInt*
const dataSizeRecv, dataType*
const recvBuffer) {
772 using namespace maia;
774 if(noNghbrDomains == 0) {
787 for(
MInt i = 1; i < noNghbrDomains; i++) {
788 sendOffsets[i] = sendOffsets[i - 1] + dataBlockSize * dataSizeSend[i - 1];
789 recvOffsets[i] = recvOffsets[i - 1] + dataBlockSize * dataSizeRecv[i - 1];
794 for(
MInt i = 0; i < noNghbrDomains; i++) {
795 const MInt nghbrDomainId = nghbrDomainIds[i];
797 if(dataSizeRecv[i] > 0 && nghbrDomainId != domainId) {
799 nghbrDomainId, nghbrDomainId, mpiComm, &recvRequests[recvCount], AT_,
"recvBuffer[recvOffsets[i]]");
806 for(
MInt i = 0; i < noNghbrDomains; i++) {
807 const MInt nghbrDomainId = nghbrDomainIds[i];
809 if(dataSizeSend[i] > 0) {
810 if(nghbrDomainId == domainId) {
813 std::copy_n(&sendBuffer[sendOffsets[i]], dataBlockSize * dataSizeSend[i], &recvBuffer[recvOffsets[i]]);
815#if defined(HOST_Klogin)
816 MPI_Isend(
const_cast<dataType*
>(&sendBuffer[sendOffsets[i]]), dataBlockSize * dataSizeSend[i],
818 "const_cast<dataType*>(&sendBuffer[sendOffsets[i]])");
821 nghbrDomainId, domainId, mpiComm, &sendRequests[sendCount], AT_,
"sendBuffer[sendOffsets[i]]");
830 MPI_Waitall(recvCount, &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
834 MPI_Waitall(sendCount, &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
840template <
typename DataType>
842 const MInt*
const sortedId, DataType*
const buffer) {
845 for(
MInt cellId = 0; cellId < noCells; cellId++) {
847 if(sortedId[cellId] < 0) {
851 std::copy_n(&data[dataBlockSize * cellId], dataBlockSize, &buffer[dataBlockSize * sortedId[cellId]]);
857template <
typename DataType>
859 const MInt noDomains,
const MInt domainId,
const MPI_Comm mpiComm,
860 const MInt*
const noCellsToSendByDomain,
const MInt*
const noCellsToReceiveByDomain,
861 const MInt dataBlockSize, DataType*
const buffer) {
864 ScratchSpace<DataType> sendBuffer(dataBlockSize * std::max(noCellsToSendByDomain[noDomains], 1), FUN_,
"sendBuffer");
868 noCellsToReceiveByDomain, buffer);
872template <std::
size_t N>
874 const MInt noDomains,
const MInt domainId,
const MPI_Comm mpiComm,
875 const MInt*
const noCellsToSendByDomain,
const MInt*
const noCellsToReceiveByDomain,
876 const MInt dataBlockSize, std::bitset<N>*
const buffer) {
880 ScratchSpace<MUlong> buffer2(dataBlockSize * noCellsToReceiveByDomain[noDomains], FUN_,
"buffer2");
882 for(
MInt i = 0; i < (signed)data2.
size(); i++) {
883 data2[i] = data[i].to_ulong();
886 communicateData(data2.
data(), noCells, sortedCellId, noDomains, domainId, mpiComm, noCellsToSendByDomain,
887 noCellsToReceiveByDomain, dataBlockSize, buffer2.
data());
889 for(
MInt i = 0; i < (signed)buffer2.
size(); i++) {
890 buffer[i] = std::bitset<N>(buffer2[i]);
918template <
typename DataType>
920 const MInt nRows,
const MInt nCols,
const MInt noDomains,
const MInt domainId,
928 globalToLocal.
fill(-1);
929 for(
MInt localId = 0; localId < noLocIds; localId++) {
930 MInt globalId = localToGlobal(localId);
931 globalToLocal(globalId) = localId;
932 for(
MLong dom = 0; dom < noDomains; dom++) {
933 if(globalId < dataOffsets(dom + 1) && globalId >= dataOffsets(dom)) {
934 sendIds[dom].push_back(globalId);
940 for(
MLong dom = 0; dom < noDomains; dom++) {
941 sendCount[dom] = sendIds[dom].
size();
942 sendIds[dom].shrink_to_fit();
944 MPI_Alltoall(&sendCount[0], 1, MPI_INT, &recvCount[0], 1, MPI_INT, mpiComm, AT_,
"sendCount[0]",
"recvCount[0]");
945 for(
MInt dom = 0; dom < noDomains; dom++) {
946 recvIds[dom].resize(recvCount[dom]);
947 recvIds[dom].shrink_to_fit();
951 sendReq.
fill(MPI_REQUEST_NULL);
952 for(
MInt dom = 0; dom < noDomains; dom++) {
953 if(sendCount[dom] == 0)
continue;
954 MPI_Issend(&sendIds[dom].front(), sendCount[dom], MPI_INT, dom, 78, mpiComm, &sendReq[mpiCount++], AT_,
955 "sendIds[dom].front()");
957 for(
MInt dom = 0; dom < noDomains; dom++) {
958 if(recvCount[dom] == 0)
continue;
959 MPI_Recv(&recvIds[dom].front(), recvCount[dom], MPI_INT, dom, 78, mpiComm, MPI_STATUS_IGNORE, AT_,
960 "recvIds[dom].front()");
962 if(mpiCount > 0)
MPI_Waitall(mpiCount, &sendReq[0], MPI_STATUSES_IGNORE, AT_);
965 for(
MInt dom = 0; dom < noDomains; dom++) {
966 sendDataBuf[dom].resize(nRows * nCols * sendCount[dom]);
967 sendDataBuf[dom].shrink_to_fit();
968 for(
MInt cnt = 0; cnt < sendCount[dom]; cnt++) {
969 MInt globalId = sendIds[dom][cnt];
970 MInt localId = globalToLocal(globalId);
972 std::cerr <<
"localId " << localId <<
" globalId " << globalId <<
" cnt " << cnt <<
" sendIds[dom].size() "
973 << sendIds[dom].
size() <<
" sendCount[dom] " << sendCount[dom] << std::endl;
974 mTerm(1, AT_,
"localId not found -> communication failed.");
976 for(
MInt row = 0; row < nRows; row++) {
977 for(
MInt col = 0; col < nCols; col++) {
978 sendDataBuf[dom][cnt * nRows * nCols + nCols * row + col] =
979 sendData[localId * nRows * nCols + nCols * row + col];
987 recvCount[0] = recvIds[0].
size() * nRows * nCols;
988 sendCount[0] = sendIds[0].
size() * nRows * nCols;
989 for(
MLong dom = 1; dom < noDomains; dom++) {
990 recvCount[dom] = recvIds[dom].
size() * nRows * nCols;
991 sendCount[dom] = sendIds[dom].
size() * nRows * nCols;
992 recvDispl[dom] = recvDispl[dom - 1] + recvCount[dom - 1];
994 recvDispl[noDomains] = recvDispl[noDomains - 1] + recvCount[noDomains - 1];
996 sendReq.
fill(MPI_REQUEST_NULL);
999 for(
MInt dom = 0; dom < noDomains; dom++) {
1000 if(sendCount[dom] == 0)
continue;
1002 &sendReq[mpiCount++], AT_,
"sendDataBuf[dom].front()");
1004 for(
MInt dom = 0; dom < noDomains; dom++) {
1005 if(recvCount[dom] == 0)
continue;
1007 MPI_STATUS_IGNORE, AT_,
"tmpData[recvDispl[dom]]");
1009 if(mpiCount > 0)
MPI_Waitall(mpiCount, &sendReq[0], MPI_STATUSES_IGNORE, AT_);
1012 for(
MLong dom = 1; dom < noDomains; dom++) {
1013 recvDispl[dom] = recvDispl[dom - 1] + recvIds[dom - 1].
size();
1016 for(
MInt dom = 0; dom < noDomains; dom++) {
1017 for(
MUint cnt = 0; cnt < recvIds[dom].
size(); cnt++) {
1018 MInt globalId = recvIds[dom][cnt];
1019 MInt recvId = globalId - dataOffsets(domainId);
1020 if(recvId < 0 || recvId >= (dataOffsets(domainId + 1) - dataOffsets(domainId))) {
1021 std::cerr <<
"recvId " << recvId <<
" globalId " << globalId <<
"dataOffsets(domainId) "
1022 << dataOffsets(domainId) << std::endl;
1023 mTerm(1, AT_,
"recvId exceeds array dimensions.");
1025 for(
MInt row = 0; row < nRows; row++) {
1026 for(
MInt col = 0; col < nCols; col++) {
1027 recvData[recvId * nCols * nRows + nCols * row + col] =
1028 tmpData[(recvDispl[dom] + cnt) * nCols * nRows + nCols * row + col];
1058 const MInt*
const snghbrs,
1059 const MInt nosnghbrs,
1060 const MInt*
const sendcounts,
1061 const MInt*
const rnghbrs,
1062 const MInt nornghbrs,
1063 const MPI_Comm& mpi_comm,
1064 const MInt domainId,
1065 const MInt dataBlockSize,
1066 MInt*
const recvcounts_ =
nullptr,
1067 MInt*
const rdispls_ =
nullptr) {
1076 std::set<MInt> s1(&snghbrs[0], &snghbrs[0] + nosnghbrs);
1077 ASSERT(s1.size() ==
static_cast<unsigned>(nosnghbrs),
"");
1078 std::set<MInt> s2(&rnghbrs[0], &rnghbrs[0] + nornghbrs);
1079 ASSERT(s2.size() ==
static_cast<unsigned>(nornghbrs),
"");
1087 MPI_Comm_size(mpi_comm, &noDomains);
1089 std::fill(isReceiveDomain.
begin(), isReceiveDomain.
end(), 0);
1090 for(
MInt d = 0; d < nosnghbrs; d++) {
1091 isReceiveDomain[snghbrs[d]] = 1;
1096 AT_,
"MPI_IN_PLACE",
"isReceiveDomain[0]");
1099 MInt nornghbrs_ = std::accumulate(isReceiveDomain.
begin(), isReceiveDomain.
end(), 0);
1100 if(nornghbrs != nornghbrs_) {
1101 TERMM(-1,
"True number of domains sending to current domain " + std::to_string(domainId)
1102 +
" differs from expected number " + std::to_string(nornghbrs));
1104 for(
MInt d = 0; d < nornghbrs; d++) {
1105 if(!isReceiveDomain[rnghbrs[d]]) {
1106 TERMM(1,
"Domain " + std::to_string(domainId) +
" has domain " + std::to_string(rnghbrs[d])
1107 +
" as a neighbor but domain " + std::to_string(rnghbrs[d])
1108 +
" has nothing to send to current domain.");
1117 if(nosnghbrs == 0 && nornghbrs == 0) {
1125 for(
MInt d = 0; d < nornghbrs; ++d) {
1132 for(
MInt d = 0; d < nosnghbrs; ++d) {
1137 MPI_Waitall(nornghbrs, &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
1138 MPI_Waitall(nosnghbrs, &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
1139 if(recvcounts_) std::copy_n(&recvcounts[0], nornghbrs, recvcounts_);
1157 const MInt totalBufferSize = std::accumulate(&recvcounts[0], &recvcounts[0] + nornghbrs, 0) * dataBlockSize;
1158 std::vector<T> receiveBuffer(totalBufferSize);
1161 std::vector<MInt> sdispls(nosnghbrs);
1162 std::vector<MInt> rdispls(nornghbrs);
1166 for(
MInt i = 1; i < nosnghbrs; i++) {
1167 sdispls[i] = sdispls[i - 1] + dataBlockSize * sendcounts[i - 1];
1169 for(
MInt i = 1; i < nornghbrs; i++) {
1170 rdispls[i] = rdispls[i - 1] + dataBlockSize * recvcounts[i - 1];
1172 if(rdispls_) std::copy_n(&rdispls[0], nornghbrs, rdispls_);
1175 std::fill(recvRequests.
begin(), recvRequests.
end(), MPI_REQUEST_NULL);
1176 for(
MInt d = 0; d < nornghbrs; ++d) {
1177 if(recvcounts[d] > 0) {
1179 rnghbrs[d], mpi_comm, &recvRequests[d], AT_,
"receiveBuffer[rdispls[d]]");
1183 std::fill(sendRequests.
begin(), sendRequests.
end(), MPI_REQUEST_NULL);
1184 for(
MInt d = 0; d < nosnghbrs; ++d) {
1185 if(sendcounts[d] > 0) {
1187 mpi_comm, &sendRequests[d], AT_,
"sendBuffer[sdispls[d]]");
1191 MPI_Waitall(nornghbrs, &recvRequests[0], MPI_STATUSES_IGNORE, AT_);
1192 MPI_Waitall(nosnghbrs, &sendRequests[0], MPI_STATUSES_IGNORE, AT_);
1194 return receiveBuffer;
1204template <
typename U>
1206 const std::vector<std::vector<MInt>>& windowCellVec,
const MPI_Comm comm, U**
const data,
1207 const MInt noDat = 1) {
1211 const MInt noNghbrDomains = (signed)nghbrDomains.size();
1213 ASSERT(noNghbrDomains == (
signed)windowCellVec.size() && noNghbrDomains == (
signed)haloCellVec.size(),
"");
1220 for(
MInt i = 0; i < noNghbrDomains; i++) {
1221 noHaloCells[i] = (signed)haloCellVec[i].size();
1222 noWindowCells[i] = (signed)windowCellVec[i].size();
1223 haloCells[i] = haloCellVec[i].
data();
1224 windowCells[i] = windowCellVec[i].
data();
1227 MInt receiveCount = std::accumulate(&noHaloCells[0], &noHaloCells[0] + noNghbrDomains, 0);
1230 MInt receiveSize = std::accumulate(&noWindowCells[0], &noWindowCells[0] + noNghbrDomains, 0);
1235 for(
MInt i = 0; i < noNghbrDomains; i++) {
1236 for(
MInt j = 0; j < noHaloCells[i]; j++) {
1237 for(
MInt k = 0; k < noDat; k++) {
1238 haloBuffer[receiveCount] = data[haloCells[i][j]][k];
1246 &windowBuffer[0], &haloBuffer[0], noDat);
1250 for(
MInt i = 0; i < noNghbrDomains; i++) {
1251 for(
MInt j = 0; j < noWindowCells[i]; j++) {
1252 for(
MInt k = 0; k < noDat; k++) {
1253 data[windowCells[i][j]][k] += windowBuffer[receiveSize];
1267template <
typename U>
1269 const std::vector<std::vector<MInt>>& windowCellVec,
const MPI_Comm comm, U*
const data,
1270 const MInt noDat = 1) {
1274 const MInt noNghbrDomains = (signed)nghbrDomains.size();
1276 ASSERT(noNghbrDomains == (
signed)windowCellVec.size() && noNghbrDomains == (
signed)haloCellVec.size(),
"");
1283 for(
MInt i = 0; i < noNghbrDomains; i++) {
1284 noHaloCells[i] = (signed)haloCellVec[i].size();
1285 noWindowCells[i] = (signed)windowCellVec[i].size();
1286 haloCells[i] = haloCellVec[i].
data();
1287 windowCells[i] = windowCellVec[i].
data();
1290 MInt receiveCount = std::accumulate(&noHaloCells[0], &noHaloCells[0] + noNghbrDomains, 0);
1293 MInt receiveSize = std::accumulate(&noWindowCells[0], &noWindowCells[0] + noNghbrDomains, 0);
1298 for(
MInt i = 0; i < noNghbrDomains; i++) {
1299 for(
MInt j = 0; j < noHaloCells[i]; j++) {
1300 for(
MInt k = 0; k < noDat; k++) {
1301 haloBuffer[receiveCount] = data[noDat * haloCells[i][j] + k];
1309 &windowBuffer[0], &haloBuffer[0], noDat);
1313 for(
MInt i = 0; i < noNghbrDomains; i++) {
1314 for(
MInt j = 0; j < noWindowCells[i]; j++) {
1315 for(
MInt k = 0; k < noDat; k++) {
1316 data[noDat * windowCells[i][j] + k] += windowBuffer[receiveSize];
This class is a ScratchSpace.
T * getPointer() const
Deprecated: use begin() instead!
void fill(T val)
fill the scratch with a given value
void mTerm(const MInt errorCode, const MString &location, const MString &message)
constexpr T mMax(const T &x, const T &y)
MInt globalNoDomains()
Return global number of domains.
MInt globalDomainId()
Return global domain id.
int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status, const MString &name, const MString &varname)
same as MPI_Recv
int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Isend
int MPI_Barrier(MPI_Comm comm, const MString &name)
same as MPI_Barrier
int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Irecv
int MPI_Issend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Issend
int MPI_Ibcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Ibcast
int MPI_Waitall(int count, MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Waitall
int MPI_Alltoall(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_Alltoall
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
void exchangeScattered(const std::vector< MInt > &nghbrDomains, std::vector< MInt > &sendDomainIndices, std::vector< U > &sendData, const MPI_Comm comm, std::vector< MInt > &recvOffsets, std::vector< U > &recvBuffer, const MInt noDat=1)
Generic exchange of data.
MUint getBufferSize(const std::vector< std::vector< MInt > > &exchangeCells)
Generic exchange of data.
void communicateData(const DataType *const data, const MInt noCells, const MInt *const sortedCellId, const MInt noDomains, const MInt domainId, const MPI_Comm mpiComm, const MInt *const noCellsToSendByDomain, const MInt *const noCellsToReceiveByDomain, const MInt dataBlockSize, DataType *const buffer)
Assemble given data in send buffer and communicate.
void exchangeData(const MInt noNghbrDomains, const MInt *const nghbrDomains, const MInt *const noHaloCells, const MInt **const, const MInt *const noWindowCells, const MInt **const windowCells, const MPI_Comm comm, const U *const data, U *const haloBuffer, const MInt noDat=1)
Generic exchange of data.
void assembleDataBuffer(const MInt noCells, const MInt dataBlockSize, const DataType *const data, const MInt *const sortedId, DataType *const buffer)
Assemble data buffer according to given sorting order.
void exchangeBuffer(const MInt noExDomains, const MInt *const exDomainId, const MInt *const recvSize, const MInt *const sendSize, const MPI_Comm comm, U *const receiveBuffer, const U *const sendBuffer, const MInt noDat=1)
Generic exchange of data.
MInt exchangeBufferAllToAll(const MInt sendSize, const MPI_Comm comm, U *const receiveBuffer, const U *const sendBuffer, const MInt noDat=1)
Generic exchange of data.
void reverseExchangeAddData(const std::vector< MInt > &nghbrDomains, const std::vector< std::vector< MInt > > &haloCellVec, const std::vector< std::vector< MInt > > &windowCellVec, const MPI_Comm comm, U **const data, const MInt noDat=1)
Generic exchange from halo to window cells, however in this case the value in the halo-cell is added ...
void communicateBitsetData(const std::bitset< N > *const data, const MInt noCells, const MInt *const sortedCellId, const MInt noDomains, const MInt domainId, const MPI_Comm mpiComm, const MInt *const noCellsToSendByDomain, const MInt *const noCellsToReceiveByDomain, const MInt dataBlockSize, std::bitset< N > *const buffer)
void exchangeValues(const std::vector< MInt > &exDomains, MInt noValues, const MPI_Comm comm, const U *const sendBuffer, U *const receiveBuffer, const MInt noDat=1)
Generic exchange of data (std::vector version)
std::vector< T > mpiExchangePointToPoint(const T *const sendBuffer, const MInt *const snghbrs, const MInt nosnghbrs, const MInt *const sendcounts, const MInt *const rnghbrs, const MInt nornghbrs, const MPI_Comm &mpi_comm, const MInt domainId, const MInt dataBlockSize, MInt *const recvcounts_=nullptr, MInt *const rdispls_=nullptr)
void reverseExchangeData(const MInt noNghbrDomains, const MInt *const nghbrDomains, const MInt *const noHaloCells, const MInt **const haloCells, const MInt *const noWindowCells, const MInt **const, const MPI_Comm comm, const U *const data, U *const windowBuffer, const MInt noDat=1)
Generic reverse exchange of data.
void exchangeBitset(const std::vector< MInt > &nghbrDomains, const std::vector< std::vector< MInt > > &haloCellVec, const std::vector< std::vector< MInt > > &windowCellVec, const MPI_Comm comm, std::bitset< N > *const data, const MInt noCells, const MInt noDat=1)
Generic exchange of data.
void communicateGlobalyOrderedData(DataType const *const sendData, const MInt noLocIds, const MInt noGlobalIds, const MInt nRows, const MInt nCols, const MInt noDomains, const MInt domainId, const MPI_Comm mpiComm, const MIntScratchSpace &localToGlobal, const MIntScratchSpace &dataOffsets, ScratchSpace< DataType > &recvData)
Communicate (optionally) solver-structured data sorted by a global Id.
Namespace for auxiliary functions/classes.