DFT-FE 1.1.0-pre
Density Functional Theory With Finite-Elements
Loading...
Searching...
No Matches
MPIPatternP2P.t.cc
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (c) 2017-2025 The Regents of the University of Michigan and DFT-FE
4// authors.
5//
6// This file is part of the DFT-FE code.
7//
8// The DFT-FE code is free software; you can use it, redistribute
9// it, and/or modify it under the terms of the GNU Lesser General
10// Public License as published by the Free Software Foundation; either
11// version 2.1 of the License, or (at your option) any later version.
12// The full text of the license can be found in the file LICENSE at
13// the top level of the DFT-FE distribution.
14//
15// ---------------------------------------------------------------------
16//
17
18/*
19 * @author Bikash Kanungo
20 */
21
22#include <Exceptions.h>
23#include <MPITags.h>
24#include <MPIRequestersBase.h>
25#include <MPIRequestersNBX.h>
26#include <string>
27#include <map>
28#include <set>
29#include <iostream>
30#include <memory>
31#include <numeric>
32#include <TypeConfig.h>
33#include <dftfeDataTypes.h>
34namespace dftfe
35{
36 namespace utils
37 {
38 namespace mpi
39 {
40 namespace
41 {
42 void
43 getAllOwnedRanges(const dftfe::uInt ownedRangeStart,
44 const dftfe::uInt ownedRangeEnd,
45 std::vector<dftfe::uInt> &allOwnedRanges,
46 const MPI_Comm &mpiComm)
47 {
48 int nprocs = 1;
49 int err = MPI_Comm_size(mpiComm, &nprocs);
50 std::string errMsg = "Error occured while using MPI_Comm_size. "
51 "Error code: " +
52 std::to_string(err);
53 throwException(err == MPI_SUCCESS, errMsg);
54 std::vector<int> recvCounts(nprocs, 2);
55 std::vector<int> displs(nprocs, 0);
56 allOwnedRanges.resize(2 * nprocs);
57 for (int i = 0; i < nprocs; ++i)
58 displs[i] = 2 * i;
59
60 std::vector<dftfe::uInt> ownedRanges = {ownedRangeStart,
61 ownedRangeEnd};
62 MPI_Allgatherv(&ownedRanges[0],
63 2,
64 dftfe::dataTypes::mpi_type_id(ownedRanges.data()),
65 &allOwnedRanges[0],
66 &recvCounts[0],
67 &displs[0],
68 dftfe::dataTypes::mpi_type_id(allOwnedRanges.data()),
69 mpiComm);
70 }
71
72 void
73 getGhostProcIdToLocalGhostIndicesMap(
74 const std::vector<dftfe::uInt> &ghostIndices,
75 const dftfe::uInt nGlobalIndices,
76 const std::vector<dftfe::uInt> &allOwnedRanges,
77 std::map<dftfe::uInt, std::vector<dftfe::uInt>>
78 &ghostProcIdToLocalGhostIndices,
79 const MPI_Comm &mpiComm)
80 {
81 int nprocs = 1;
82 int err = MPI_Comm_size(mpiComm, &nprocs);
83 std::string errMsg = "Error occured while using MPI_Comm_size. "
84 "Error code: " +
85 std::to_string(err);
86 throwException(err == MPI_SUCCESS, errMsg);
87
88 //
89 // NOTE: The locally owned ranges need not be ordered as per the
90 // processor ranks. That is ranges for processor 0, 1, ...., P-1 given
91 // by [N_0,N_1), [N_1, N_2), [N_2, N_3), ..., [N_{P-1},N_P) need not
92 // honor the fact that N_0, N_1, ..., N_P are increasing. However, it
93 // is more efficient to perform search operations in a sorted vector.
94 // Thus, we perform a sort on the end of each locally owned range and
95 // also keep track of the indices during the sort
96 //
97
98 // vector to store the end of each locally owned ranges
99 std::vector<dftfe::uInt> locallyOwnedRangesEnd(nprocs);
100
101 //
102 // Vector to keep track of the indices of locallyOwnedRangesEnd
103 // during sort
104 std::vector<dftfe::uInt> locallyOwnedRangesEndProcIds(nprocs);
105 for (dftfe::uInt i = 0; i < nprocs; ++i)
106 {
107 locallyOwnedRangesEnd[i] = allOwnedRanges[2 * i + 1];
108
109 // this is required for handing trivial ranges [Nt, Nt)
110 // where Nt can be arbitrary integer >=0
111 if (allOwnedRanges[2 * i + 1] == allOwnedRanges[2 * i])
112 locallyOwnedRangesEnd[i] = (nGlobalIndices + 1 + i);
113 locallyOwnedRangesEndProcIds[i] = i;
114 }
115
116 std::sort(locallyOwnedRangesEndProcIds.begin(),
117 locallyOwnedRangesEndProcIds.end(),
118 [&locallyOwnedRangesEnd](dftfe::uInt x, dftfe::uInt y) {
119 return locallyOwnedRangesEnd[x] <
120 locallyOwnedRangesEnd[y];
121 });
122
123 std::sort(locallyOwnedRangesEnd.begin(), locallyOwnedRangesEnd.end());
124
125 const dftfe::uInt numGhosts = ghostIndices.size();
126 for (dftfe::uInt iGhost = 0; iGhost < numGhosts; ++iGhost)
127 {
128 dftfe::uInt ghostIndex = ghostIndices[iGhost];
129 auto up = std::upper_bound(locallyOwnedRangesEnd.begin(),
130 locallyOwnedRangesEnd.end(),
131 ghostIndex);
132 std::string msg = "Ghost index " + std::to_string(ghostIndex) +
133 " not found in any of the processors";
134 throwException(up != locallyOwnedRangesEnd.end(), msg);
135 dftfe::uInt upPos =
136 std::distance(locallyOwnedRangesEnd.begin(), up);
137 dftfe::uInt procId = locallyOwnedRangesEndProcIds[upPos];
138 ghostProcIdToLocalGhostIndices[procId].push_back(iGhost);
139 }
140 }
141
142 bool
143 checkContiguity(const std::vector<dftfe::uInt> &v)
144 {
145 const dftfe::uInt N = v.size();
146 bool returnValue = true;
147 for (dftfe::uInt i = 1; i < N; ++i)
148 {
149 if ((v[i] - 1) != v[i - 1])
150 {
151 returnValue = false;
152 break;
153 }
154 }
155 return returnValue;
156 }
157
158 struct RangeMetaData
159 {
160 dftfe::uInt Id;
161 dftfe::uInt rangeId;
162 bool isRangeStart;
163 };
164
165 bool
166 compareRangeMetaData(const RangeMetaData &x, const RangeMetaData &y)
167 {
168 if (x.Id == y.Id)
169 return (!x.isRangeStart);
170 else
171 return x.Id < y.Id;
172 }
173 std::vector<dftfe::uInt>
174 getOverlappingRangeIds(const std::vector<dftfe::uInt> &ranges)
175 {
176 dftfe::uInt numRanges = ranges.size() / 2;
177 std::vector<RangeMetaData> rangeMetaDataVec(0);
178 for (dftfe::uInt i = 0; i < numRanges; ++i)
179 {
180 RangeMetaData left;
181 left.Id = ranges[2 * i];
182 left.rangeId = i;
183 left.isRangeStart = true;
184
185 RangeMetaData right;
186 right.Id = ranges[2 * i + 1];
187 right.rangeId = i;
188 right.isRangeStart = false;
189
190 // This check is required to ignore ranges with 0 elements
191 if (left.Id != right.Id)
192 {
193 rangeMetaDataVec.push_back(left);
194 rangeMetaDataVec.push_back(right);
195 }
196 }
197 std::sort(rangeMetaDataVec.begin(),
198 rangeMetaDataVec.end(),
199 compareRangeMetaData);
200 dftfe::Int currentOpen = -1;
201 bool added = false;
202 std::vector<dftfe::uInt> returnValue(0);
203 for (dftfe::uInt i = 0; i < rangeMetaDataVec.size(); ++i)
204 {
205 dftfe::uInt rangeId = rangeMetaDataVec[i].rangeId;
206 if (rangeMetaDataVec[i].isRangeStart)
207 {
208 if (currentOpen == -1)
209 {
210 currentOpen = rangeId;
211 added = false;
212 }
213 else
214 {
215 if (!added)
216 {
217 returnValue.push_back(currentOpen);
218 added = true;
219 }
220 returnValue.push_back(rangeId);
221 if (ranges[2 * rangeId + 1] > ranges[2 * currentOpen + 1])
222 {
223 currentOpen = rangeId;
224 added = true;
225 }
226 }
227 }
228 else
229 {
230 if (rangeId == currentOpen)
231 {
232 currentOpen = -1;
233 added = false;
234 }
235 }
236 }
237 return returnValue;
238 }
239
240 } // namespace
241
242 ///
243 /// Constructor with MPI
244 ///
245 template <dftfe::utils::MemorySpace memorySpace>
247 const std::pair<dftfe::uInt, dftfe::uInt> &locallyOwnedRange,
248 const std::vector<dftfe::uInt> &ghostIndices,
249 const MPI_Comm &mpiComm)
250 : d_locallyOwnedRange(locallyOwnedRange)
251 , d_mpiComm(mpiComm)
253 , d_ghostIndices(0)
256 , d_numGhostProcs(0)
257 , d_ghostProcIds(0)
262 , d_targetProcIds(0)
266 {
267 d_myRank = 0;
268 d_nprocs = 1;
269 int err = MPI_Comm_size(d_mpiComm, &d_nprocs);
270 std::string errMsg = "Error occured while using MPI_Comm_size. "
271 "Error code: " +
272 std::to_string(err);
273 throwException(err == MPI_SUCCESS, errMsg);
274
275 err = MPI_Comm_rank(d_mpiComm, &d_myRank);
276 errMsg = "Error occured while using MPI_Comm_rank. "
277 "Error code: " +
278 std::to_string(err);
279 throwException(err == MPI_SUCCESS, errMsg);
280
283 "In processor " + std::to_string(d_myRank) +
284 ", invalid locally owned range found "
285 "(i.e., the second value in the range is less than the first value).");
288 ///////////////////////////////////////////////////
289 //////////// Ghost Data Evaluation Begin //////////
290 ///////////////////////////////////////////////////
291
292 //
293 // check if the ghostIndices is strictly increasing or nor
294 //
295 bool isStrictlyIncreasing = std::is_sorted(ghostIndices.begin(),
296 ghostIndices.end(),
297 std::less_equal<>());
299 isStrictlyIncreasing,
300 "In processor " + std::to_string(d_myRank) +
301 ", the ghost indices passed to MPIPatternP2P is not a strictly increasing set.");
302
303 d_ghostIndices = ghostIndices;
304
305 // copy the ghostIndices to d_ghostIndicesSetSTL
306 d_ghostIndicesSetSTL.clear();
307 std::copy(ghostIndices.begin(),
308 ghostIndices.end(),
309 std::inserter(d_ghostIndicesSetSTL,
310 d_ghostIndicesSetSTL.end()));
313
314 d_numGhostIndices = ghostIndices.size();
315
317
318 d_allOwnedRanges.clear();
319 getAllOwnedRanges(d_locallyOwnedRange.first,
320 d_locallyOwnedRange.second,
322 d_mpiComm);
323
324 std::vector<dftfe::uInt> overlappingRangeIds =
325 getOverlappingRangeIds(d_allOwnedRanges);
327 overlappingRangeIds.size() == 0,
328 "Detected overlapping ranges among the locallyOwnedRanges passed "
329 "to MPIPatternP2P");
330
332 for (dftfe::uInt i = 0; i < d_nprocs; ++i)
333 {
335 d_allOwnedRanges[2 * i + 1] - d_allOwnedRanges[2 * i];
336 }
337
338 if (ghostIndices.size() > 0)
339 {
341 ghostIndices.back() < d_nGlobalIndices,
342 "Detected global ghost index to be larger than (nGlobalIndices-1)");
343 }
344
345 std::map<dftfe::uInt, std::vector<dftfe::uInt>>
346 ghostProcIdToLocalGhostIndices;
347 getGhostProcIdToLocalGhostIndicesMap(ghostIndices,
350 ghostProcIdToLocalGhostIndices,
351 d_mpiComm);
352
353 d_numGhostProcs = ghostProcIdToLocalGhostIndices.size();
357
358 std::vector<dftfe::uInt> flattenedLocalGhostIndicesTmp(0);
359 auto it = ghostProcIdToLocalGhostIndices.begin();
360 dftfe::uInt iGhostProc = 0;
361 for (; it != ghostProcIdToLocalGhostIndices.end(); ++it)
362 {
363 d_ghostProcIds[iGhostProc] = it->first;
364 const std::vector<dftfe::uInt> localGhostIndicesInGhostProc =
365 it->second;
366 bool isContiguous = checkContiguity(localGhostIndicesInGhostProc);
367 std::string msg = "In rank " + std::to_string(d_myRank) +
368 ", the local ghost indices that are owned"
369 " by rank " +
370 std::to_string(d_ghostProcIds[iGhostProc]) +
371 " does not form a contiguous set.";
372 throwException<LogicError>(isContiguous, msg);
374 localGhostIndicesInGhostProc.size();
375
376 d_localGhostIndicesRanges[2 * iGhostProc] =
377 *(localGhostIndicesInGhostProc.begin());
378 d_localGhostIndicesRanges[2 * iGhostProc + 1] =
379 *(localGhostIndicesInGhostProc.end() - 1) + 1;
380 //
381 // Append localGhostIndicesInGhostProc to
382 // flattenedLocalGhostIndicesTmp
383 //
384 std::copy(localGhostIndicesInGhostProc.begin(),
385 localGhostIndicesInGhostProc.end(),
386 back_inserter(flattenedLocalGhostIndicesTmp));
387 ++iGhostProc;
388 }
389
390 std::string msg = "In rank " + std::to_string(d_myRank) +
391 " mismatch of"
392 " the sizes of ghost indices. Expected size: " +
393 std::to_string(d_numGhostIndices) +
394 " Received size: " +
395 std::to_string(flattenedLocalGhostIndicesTmp.size());
396 throwException<DomainError>(flattenedLocalGhostIndicesTmp.size() ==
398 msg);
399
400
402 if (d_numGhostIndices > 0)
403 memoryTransfer.copy(d_numGhostIndices,
405 &flattenedLocalGhostIndicesTmp[0]);
406 ///////////////////////////////////////////////////
407 //////////// Ghost Data Evaluation End / //////////
408 ///////////////////////////////////////////////////
409
410
411 ///////////////////////////////////////////////////
412 //////////// Target Data Evaluation Begin ////////
413 ///////////////////////////////////////////////////
415 d_targetProcIds = mpirequesters.getRequestingRankIds();
418
419 std::vector<MPI_Request> sendRequests(d_numGhostProcs);
420 std::vector<MPI_Status> sendStatuses(d_numGhostProcs);
421 std::vector<MPI_Request> recvRequests(d_numTargetProcs);
422 std::vector<MPI_Status> recvStatuses(d_numTargetProcs);
423 const dftfe::Int tag =
425 for (dftfe::uInt iGhost = 0; iGhost < d_numGhostProcs; ++iGhost)
426 {
427 const dftfe::Int ghostProcId = d_ghostProcIds[iGhost];
428 err = MPI_Isend(&d_numGhostIndicesInGhostProcs[iGhost],
429 1,
432 ghostProcId,
433 tag,
434 d_mpiComm,
435 &sendRequests[iGhost]);
436 std::string errMsg = "Error occured while using MPI_Isend. "
437 "Error code: " +
438 std::to_string(err);
439 throwException(err == MPI_SUCCESS, errMsg);
440 }
441
442 for (dftfe::uInt iTarget = 0; iTarget < d_numTargetProcs; ++iTarget)
443 {
444 const dftfe::Int targetProcId = d_targetProcIds[iTarget];
445 err = MPI_Irecv(&d_numOwnedIndicesForTargetProcs[iTarget],
446 1,
449 targetProcId,
450 tag,
451 d_mpiComm,
452 &recvRequests[iTarget]);
453 std::string errMsg = "Error occured while using MPI_Irecv. "
454 "Error code: " +
455 std::to_string(err);
456 throwException(err == MPI_SUCCESS, errMsg);
457 }
458
459 if (sendRequests.size() > 0)
460 {
461 err = MPI_Waitall(d_numGhostProcs,
462 sendRequests.data(),
463 sendStatuses.data());
464 errMsg = "Error occured while using MPI_Waitall. "
465 "Error code: " +
466 std::to_string(err);
467 throwException(err == MPI_SUCCESS, errMsg);
468 }
469
470 if (recvRequests.size() > 0)
471 {
472 err = MPI_Waitall(d_numTargetProcs,
473 recvRequests.data(),
474 recvStatuses.data());
475 errMsg = "Error occured while using MPI_Waitall. "
476 "Error code: " +
477 std::to_string(err);
478 throwException(err == MPI_SUCCESS, errMsg);
479 }
480
481
482 dftfe::uInt totalOwnedIndicesForTargetProcs =
483 std::accumulate(d_numOwnedIndicesForTargetProcs.begin(),
485 0);
486
487
488 std::vector<dftfe::uInt> flattenedLocalTargetIndicesTmp(
489 totalOwnedIndicesForTargetProcs, 0);
490
491 std::vector<dftfe::uInt> localIndicesForGhostProc(d_numGhostIndices, 0);
492
493 dftfe::uInt startIndex = 0;
494 for (dftfe::uInt iGhost = 0; iGhost < d_numGhostProcs; ++iGhost)
495 {
496 const dftfe::Int numGhostIndicesInProc =
498 const dftfe::Int ghostProcId = d_ghostProcIds[iGhost];
499
500 // We need to send what is the local index in the ghost processor
501 // (i.e., the processor that owns the current processor's ghost
502 // index)
503 for (dftfe::uInt iIndex = 0; iIndex < numGhostIndicesInProc;
504 ++iIndex)
505 {
506 const dftfe::uInt ghostLocalIndex =
507 flattenedLocalGhostIndicesTmp[startIndex + iIndex];
508
509 throwException<LogicError>(ghostLocalIndex <
510 ghostIndices.size(),
511 "BUG1");
512
513 const dftfe::uInt ghostGlobalIndex =
514 ghostIndices[ghostLocalIndex];
515 const dftfe::uInt ghostProcOwnedIndicesStart =
516 d_allOwnedRanges[2 * ghostProcId];
517 localIndicesForGhostProc[startIndex + iIndex] =
518 (dftfe::uInt)(ghostGlobalIndex - ghostProcOwnedIndicesStart);
519
521 localIndicesForGhostProc[startIndex + iIndex] <
522 (d_allOwnedRanges[2 * ghostProcId + 1] -
523 d_allOwnedRanges[2 * ghostProcId]),
524 "BUG2");
525 }
526
527 err = MPI_Isend(&localIndicesForGhostProc[startIndex],
528 numGhostIndicesInProc,
530 localIndicesForGhostProc.data()),
531 ghostProcId,
532 tag,
533 d_mpiComm,
534 &sendRequests[iGhost]);
535 std::string errMsg = "Error occured while using MPI_Isend. "
536 "Error code: " +
537 std::to_string(err);
538 throwException(err == MPI_SUCCESS, errMsg);
539 startIndex += numGhostIndicesInProc;
540 }
541
542 startIndex = 0;
543 for (dftfe::uInt iTarget = 0; iTarget < d_numTargetProcs; ++iTarget)
544 {
545 const dftfe::Int targetProcId = d_targetProcIds[iTarget];
546 const dftfe::Int numOwnedIndicesForTarget =
548 err = MPI_Irecv(&flattenedLocalTargetIndicesTmp[startIndex],
549 numOwnedIndicesForTarget,
551 flattenedLocalTargetIndicesTmp.data()),
552 targetProcId,
553 tag,
554 d_mpiComm,
555 &recvRequests[iTarget]);
556 std::string errMsg = "Error occured while using MPI_Irecv. "
557 "Error code: " +
558 std::to_string(err);
559 throwException(err == MPI_SUCCESS, errMsg);
560 startIndex += numOwnedIndicesForTarget;
561 }
562
563 if (sendRequests.size() > 0)
564 {
565 err = MPI_Waitall(d_numGhostProcs,
566 sendRequests.data(),
567 sendStatuses.data());
568 errMsg = "Error occured while using MPI_Waitall. "
569 "Error code: " +
570 std::to_string(err);
571 throwException(err == MPI_SUCCESS, errMsg);
572 }
573
574 if (recvRequests.size() > 0)
575 {
576 err = MPI_Waitall(d_numTargetProcs,
577 recvRequests.data(),
578 recvStatuses.data());
579 errMsg = "Error occured while using MPI_Waitall. "
580 "Error code: " +
581 std::to_string(err);
582 throwException(err == MPI_SUCCESS, errMsg);
583 }
584
585 for (dftfe::uInt i = 0; i < totalOwnedIndicesForTargetProcs; ++i)
586 {
588 flattenedLocalTargetIndicesTmp[i] < d_numLocallyOwnedIndices,
589 "Detected local owned target index to be larger than (nLocallyOwnedIndices-1)");
590 }
591
592 d_flattenedLocalTargetIndices.resize(totalOwnedIndicesForTargetProcs);
593 if (totalOwnedIndicesForTargetProcs > 0)
594 memoryTransfer.copy(totalOwnedIndicesForTargetProcs,
596 &flattenedLocalTargetIndicesTmp[0]);
597
598 ///////////////////////////////////////////////////
599 //////////// Target Data Evaluation End ////////
600 ///////////////////////////////////////////////////
601 }
602
603
604 ///
605 /// Constructor for a serial case
606 ///
607 template <dftfe::utils::MemorySpace memorySpace>
609 : d_locallyOwnedRange(std::make_pair(0, (dftfe::uInt)size))
610 , d_mpiComm(MPI_COMM_SELF)
614 , d_ghostIndices(0)
615 , d_numGhostProcs(0)
616 , d_ghostProcIds(0)
621 , d_targetProcIds(0)
625 {
626 d_myRank = 0;
627 d_nprocs = 1;
630 "In processor " + std::to_string(d_myRank) +
631 ", invalid locally owned range found "
632 "(i.e., the second value in the range is less than the first value).");
635 std::vector<dftfe::uInt> d_allOwnedRanges = {
637 for (dftfe::uInt i = 0; i < d_nprocs; ++i)
639 d_allOwnedRanges[2 * i + 1] - d_allOwnedRanges[2 * i];
640
641 // set the d_ghostIndicesSetSTL to be of size zero
642 d_ghostIndicesSetSTL.clear();
645 }
646
647 template <dftfe::utils::MemorySpace memorySpace>
648 std::pair<dftfe::uInt, dftfe::uInt>
653
654 template <dftfe::utils::MemorySpace memorySpace>
655 const std::vector<dftfe::uInt> &
660
661 template <dftfe::utils::MemorySpace memorySpace>
662 const std::vector<dftfe::uInt> &
667
668 template <dftfe::utils::MemorySpace memorySpace>
669 const std::vector<dftfe::uInt> &
674
675
676 template <dftfe::utils::MemorySpace memorySpace>
677 const std::vector<dftfe::uInt> &
682
683 template <dftfe::utils::MemorySpace memorySpace>
686 const dftfe::uInt procId) const
687 {
688 auto itProcIds = d_ghostProcIds.begin();
689 auto itNumGhostIndices = d_numGhostIndicesInGhostProcs.begin();
690 dftfe::uInt numGhostIndicesInProc = 0;
691 for (; itProcIds != d_ghostProcIds.end(); ++itProcIds)
692 {
693 numGhostIndicesInProc = *itNumGhostIndices;
694 if (procId == *itProcIds)
695 break;
696
697 ++itNumGhostIndices;
698 }
699
700 std::string msg =
701 "The processor Id " + std::to_string(procId) +
702 " does not contain any ghost indices for the current processor"
703 " (i.e., processor Id " +
704 std::to_string(d_myRank) + ")";
705 throwException<InvalidArgument>(itProcIds != d_ghostProcIds.end(), msg);
706
707 return numGhostIndicesInProc;
708 }
709
710 template <dftfe::utils::MemorySpace memorySpace>
713 const dftfe::uInt procId) const
714 {
715 dftfe::uInt cumulativeIndices = 0;
716 dftfe::uInt numGhostIndicesInProc = 0;
717 auto itProcIds = d_ghostProcIds.begin();
718 auto itNumGhostIndices = d_numGhostIndicesInGhostProcs.begin();
719 for (; itProcIds != d_ghostProcIds.end(); ++itProcIds)
720 {
721 numGhostIndicesInProc = *itNumGhostIndices;
722 if (procId == *itProcIds)
723 break;
724
725 cumulativeIndices += numGhostIndicesInProc;
726 ++itNumGhostIndices;
727 }
728
729 std::string msg =
730 "The processor Id " + std::to_string(procId) +
731 " does not contain any ghost indices for the current processor"
732 " (i.e., processor Id " +
733 std::to_string(d_myRank) + ")";
734 throwException<InvalidArgument>(itProcIds != d_ghostProcIds.end(), msg);
735
736 SizeTypeVector returnValue(numGhostIndicesInProc);
738 numGhostIndicesInProc,
739 returnValue.begin(),
740 d_flattenedLocalGhostIndices.begin() + cumulativeIndices);
741
742 return returnValue;
743 }
744
745 template <dftfe::utils::MemorySpace memorySpace>
746 const std::vector<dftfe::uInt> &
751
752 template <dftfe::utils::MemorySpace memorySpace>
753 const std::vector<dftfe::uInt> &
758
759 template <dftfe::utils::MemorySpace memorySpace>
765
766 template <dftfe::utils::MemorySpace memorySpace>
769 const dftfe::uInt procId) const
770 {
771 auto itProcIds = d_targetProcIds.begin();
772 auto itNumOwnedIndices = d_numOwnedIndicesForTargetProcs.begin();
773 dftfe::uInt numOwnedIndicesForProc = 0;
774 for (; itProcIds != d_targetProcIds.end(); ++itProcIds)
775 {
776 numOwnedIndicesForProc = *itNumOwnedIndices;
777 if (procId == *itProcIds)
778 break;
779
780 ++itNumOwnedIndices;
781 }
782
783 std::string msg = "There are no owned indices for "
784 " target processor Id " +
785 std::to_string(procId) +
786 " in the current processor"
787 " (i.e., processor Id " +
788 std::to_string(d_myRank) + ")";
790 msg);
791 return numOwnedIndicesForProc;
792 }
793
794 template <dftfe::utils::MemorySpace memorySpace>
797 const dftfe::uInt procId) const
798 {
799 dftfe::uInt cumulativeIndices = 0;
800 dftfe::uInt numOwnedIndicesForProc = 0;
801 auto itProcIds = d_targetProcIds.begin();
802 auto itNumOwnedIndices = d_numOwnedIndicesForTargetProcs.begin();
803 for (; itProcIds != d_targetProcIds.end(); ++itProcIds)
804 {
805 numOwnedIndicesForProc = *itNumOwnedIndices;
806 if (procId == *itProcIds)
807 break;
808
809 cumulativeIndices += numOwnedIndicesForProc;
810 ++itNumOwnedIndices;
811 }
812
813 std::string msg = "There are no owned indices for "
814 " target processor Id " +
815 std::to_string(procId) +
816 " in the current processor"
817 " (i.e., processor Id " +
818 std::to_string(d_myRank) + ")";
820 msg);
821
822 SizeTypeVector returnValue(numOwnedIndicesForProc);
824 numOwnedIndicesForProc,
825 returnValue.begin(),
826 d_flattenedLocalTargetIndices.begin() + cumulativeIndices);
827
828 return returnValue;
829 }
830
831
832
833 template <dftfe::utils::MemorySpace memorySpace>
834 const MPI_Comm &
839
840 template <dftfe::utils::MemorySpace memorySpace>
846
847 template <dftfe::utils::MemorySpace memorySpace>
853
854 template <dftfe::utils::MemorySpace memorySpace>
860
861 template <dftfe::utils::MemorySpace memorySpace>
867
868 template <dftfe::utils::MemorySpace memorySpace>
874
875
876 template <dftfe::utils::MemorySpace memorySpace>
879 {
880 dftfe::uInt returnValue = 0;
881 if (localId < d_numLocallyOwnedIndices)
882 {
883 returnValue = d_locallyOwnedRange.first + localId;
884 }
885 else if (localId < (d_numLocallyOwnedIndices + d_numGhostIndices))
886 {
887 auto it =
888 d_ghostIndices.begin() + (localId - d_numLocallyOwnedIndices);
889 returnValue = *it;
890 }
891 else
892 {
893 std::string msg =
894 "In processor " + std::to_string(d_myRank) +
895 ", the local index " + std::to_string(localId) +
896 " passed to localToGlobal() in MPIPatternP2P is"
897 " larger than number of locally owned plus ghost indices.";
899 }
900 return returnValue;
901 }
902
903 template <dftfe::utils::MemorySpace memorySpace>
906 const dftfe::uInt globalId) const
907 {
908 dftfe::uInt returnValue = 0;
909 if (globalId >= d_locallyOwnedRange.first &&
910 globalId < d_locallyOwnedRange.second)
911 {
912 returnValue = globalId - d_locallyOwnedRange.first;
913 }
914 else
915 {
916 bool found = false;
917 d_ghostIndicesOptimizedIndexSet.getPosition(globalId,
918 returnValue,
919 found);
920 std::string msg =
921 "In processor " + std::to_string(d_myRank) +
922 ", the global index " + std::to_string(globalId) +
923 " passed to globalToLocal() in MPIPatternP2P is"
924 " neither present in its locally owned range nor in its "
925 " ghost indices.";
927 returnValue += d_numLocallyOwnedIndices;
928 }
929
930 return returnValue;
931 }
932
933 template <dftfe::utils::MemorySpace memorySpace>
934 bool
936 const dftfe::uInt globalId) const
937 {
938 return (globalId >= d_locallyOwnedRange.first &&
939 globalId < d_locallyOwnedRange.second);
940 }
941
942 template <dftfe::utils::MemorySpace memorySpace>
943 bool
945 {
946 bool found = false;
947 dftfe::uInt localId;
948 d_ghostIndicesOptimizedIndexSet.getPosition(globalId, localId, found);
949 return found;
950 }
951
952 template <dftfe::utils::MemorySpace memorySpace>
953 bool
955 const MPIPatternP2P<memorySpace> &rhs) const
956 {
957 if (d_nprocs != rhs.d_nprocs)
958 return false;
959
960 else if (d_nGlobalIndices != rhs.d_nGlobalIndices)
961 return false;
962
964 return false;
965
966 else if (d_numGhostIndices != rhs.d_numGhostIndices)
967 return false;
968
969 else
972 }
973 } // end of namespace mpi
974 } // end of namespace utils
975} // end of namespace dftfe
iterator begin()
Return iterator pointing to the beginning of point data.
Definition MemoryStorage.t.cc:130
Definition MemoryTransfer.h:33
static void copy(std::size_t size, ValueType *dst, const ValueType *src)
Copy array from the memory space of source to the memory space of destination.
Definition OptimizedIndexSet.h:44
SizeTypeVector getGhostLocalIndices(const dftfe::uInt procId) const
Definition MPIPatternP2P.t.cc:712
dftfe::uInt localToGlobal(const dftfe::uInt localId) const
Definition MPIPatternP2P.t.cc:878
bool inLocallyOwnedRange(const dftfe::uInt globalId) const
Definition MPIPatternP2P.t.cc:935
OptimizedIndexSet< dftfe::uInt > d_ghostIndicesOptimizedIndexSet
Definition MPIPatternP2P.h:242
std::vector< dftfe::uInt > d_allOwnedRanges
Definition MPIPatternP2P.h:213
dftfe::uInt getNumGhostIndicesInProc(const dftfe::uInt procId) const
Definition MPIPatternP2P.t.cc:685
const std::vector< dftfe::uInt > & getNumGhostIndicesInProcs() const
Definition MPIPatternP2P.t.cc:670
std::vector< dftfe::uInt > d_localGhostIndicesRanges
A vector of size 2 times the number of ghost processors to store the range of local ghost indices tha...
Definition MPIPatternP2P.h:319
MPIPatternP2P(const std::pair< dftfe::uInt, dftfe::uInt > &locallyOwnedRange, const std::vector< dftfe::uInt > &ghostIndices, const MPI_Comm &mpiComm)
Constructor. This constructor is the typical way of creation of an MPI pattern.
Definition MPIPatternP2P.t.cc:246
const std::vector< dftfe::uInt > & getGhostLocalIndicesRanges() const
Definition MPIPatternP2P.t.cc:678
SizeTypeVector d_flattenedLocalTargetIndices
Definition MPIPatternP2P.h:363
dftfe::uInt d_numTargetProcs
Definition MPIPatternP2P.h:326
bool isGhostEntry(const dftfe::uInt globalId) const
Definition MPIPatternP2P.t.cc:944
int d_myRank
Rank of the current processor.
Definition MPIPatternP2P.h:369
int d_nprocs
Number of processors in the MPI Communicator.
Definition MPIPatternP2P.h:366
std::vector< dftfe::uInt > d_ghostProcIds
Definition MPIPatternP2P.h:255
std::vector< dftfe::uInt > d_numOwnedIndicesForTargetProcs
Definition MPIPatternP2P.h:341
dftfe::uInt getNumOwnedIndicesForTargetProc(const dftfe::uInt procId) const
Definition MPIPatternP2P.t.cc:768
std::pair< dftfe::uInt, dftfe::uInt > d_locallyOwnedRange
Definition MPIPatternP2P.h:202
const SizeTypeVector & getOwnedLocalIndicesForTargetProcs() const
Definition MPIPatternP2P.t.cc:761
dftfe::uInt nGlobalIndices() const
Definition MPIPatternP2P.t.cc:856
dftfe::uInt localOwnedSize() const
Definition MPIPatternP2P.t.cc:863
std::vector< dftfe::uInt > d_targetProcIds
Definition MPIPatternP2P.h:333
dftfe::uInt d_numGhostProcs
Definition MPIPatternP2P.h:249
std::vector< dftfe::uInt > d_ghostIndices
Definition MPIPatternP2P.h:229
dftfe::uInt thisProcessId() const
Definition MPIPatternP2P.t.cc:849
bool isCompatible(const MPIPatternP2P< memorySpace > &rhs) const
Definition MPIPatternP2P.t.cc:954
dftfe::uInt nmpiProcesses() const
Definition MPIPatternP2P.t.cc:842
SizeTypeVector d_flattenedLocalGhostIndices
Definition MPIPatternP2P.h:297
utils::MemoryStorage< dftfe::uInt, memorySpace > SizeTypeVector
Definition MPIPatternP2P.h:62
std::pair< dftfe::uInt, dftfe::uInt > getLocallyOwnedRange() const
Definition MPIPatternP2P.t.cc:649
dftfe::uInt localGhostSize() const
Definition MPIPatternP2P.t.cc:870
const MPI_Comm & mpiCommunicator() const
Definition MPIPatternP2P.t.cc:835
std::vector< dftfe::uInt > d_numGhostIndicesInGhostProcs
Definition MPIPatternP2P.h:261
dftfe::uInt globalToLocal(const dftfe::uInt globalId) const
Definition MPIPatternP2P.t.cc:905
SizeTypeVector getOwnedLocalIndices(const dftfe::uInt procId) const
Definition MPIPatternP2P.t.cc:796
const std::vector< dftfe::uInt > & getGhostIndices() const
Definition MPIPatternP2P.t.cc:656
dftfe::uInt d_nGlobalIndices
Definition MPIPatternP2P.h:374
MPI_Comm d_mpiComm
MPI Communicator object.
Definition MPIPatternP2P.h:377
const std::vector< dftfe::uInt > & getNumOwnedIndicesForTargetProcs() const
Definition MPIPatternP2P.t.cc:754
std::set< dftfe::uInt > d_ghostIndicesSetSTL
Definition MPIPatternP2P.h:234
const std::vector< dftfe::uInt > & getTargetProcIds() const
Definition MPIPatternP2P.t.cc:747
dftfe::uInt d_numGhostIndices
Definition MPIPatternP2P.h:223
dftfe::uInt d_numLocallyOwnedIndices
Definition MPIPatternP2P.h:218
const std::vector< dftfe::uInt > & getGhostProcIds() const
Definition MPIPatternP2P.t.cc:663
Definition MPIRequestersNBX.h:38
std::vector< dftfe::uInt > getRequestingRankIds() override
MPI_Datatype mpi_type_id(const int *)
Definition dftfeDataTypes.h:49
Definition MPICommunicatorP2P.h:46
@ MPI_P2P_PATTERN_TAG
Definition MPITags.h:41
Definition Cell.h:36
void throwException(bool condition, std::string msg="")
Definition pseudoPotentialToDftfeConverter.cc:34
std::uint32_t uInt
Definition TypeConfig.h:10
std::int32_t Int
Definition TypeConfig.h:11