10 #ifndef MUELU_GENERALGEOMETRICPFACTORY_DEF_HPP
11 #define MUELU_GENERALGEOMETRICPFACTORY_DEF_HPP
21 #include <Xpetra_CrsMatrixWrap.hpp>
24 #include <Xpetra_MapFactory.hpp>
25 #include <Xpetra_MultiVectorFactory.hpp>
36 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
45 validParamList->
set<std::string>(
"Coarsen",
"{2}",
46 "Coarsening rate in all spatial dimensions");
47 validParamList->
set<
int>(
"order", 1,
48 "Order of the interpolation scheme used");
50 "Generating factory of the matrix A");
52 "Generating factory of the nullspace");
54 "Generating factory for coorindates");
56 "Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
58 "Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
59 validParamList->
set<std::string>(
"meshLayout",
"Global Lexicographic",
60 "Type of mesh ordering");
62 "Mesh ordering associated data");
64 return validParamList;
67 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
70 Input(fineLevel,
"A");
71 Input(fineLevel,
"Nullspace");
72 Input(fineLevel,
"Coordinates");
80 "gNodesPerDim was not provided by the user on level0!");
83 Input(fineLevel,
"gNodesPerDim");
93 "lNodesPerDim was not provided by the user on level0!");
96 Input(fineLevel,
"lNodesPerDim");
100 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
102 Level& coarseLevel)
const {
103 return BuildP(fineLevel, coarseLevel);
106 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
108 Level& coarseLevel)
const {
114 RCP<MultiVector> fineNullspace = Get<RCP<MultiVector> >(fineLevel,
"Nullspace");
115 RCP<xdMV> fineCoords = Get<RCP<xdMV> >(fineLevel,
"Coordinates");
122 const LO blkSize = A->GetFixedBlockSize();
127 myGeometry->meshLayout = pL.
get<std::string>(
"meshLayout");
128 if (fineLevel.GetLevelID() == 0) {
129 if (myGeometry->meshLayout ==
"Local Lexicographic") {
133 "The meshData array is empty, somehow the input for geometric"
134 " multigrid are not captured correctly.");
135 myGeometry->meshData.resize(rowMap->getComm()->getSize());
136 for (
int i = 0; i < rowMap->getComm()->getSize(); ++i) {
137 myGeometry->meshData[i].resize(10);
138 for (
int j = 0; j < 10; ++j) {
139 myGeometry->meshData[i][j] = meshData[10 * i + j];
146 "Coordinates cannot be accessed from fine level!");
147 myGeometry->numDimensions = fineCoords->getNumVectors();
150 if (fineLevel.GetLevelID() == 0) {
155 myGeometry->gFineNodesPerDir = Get<Array<GO> >(fineLevel,
"gNodesPerDim");
158 myGeometry->lFineNodesPerDir = Get<Array<LO> >(fineLevel,
"lNodesPerDim");
160 myGeometry->gNumFineNodes10 = myGeometry->gFineNodesPerDir[1] * myGeometry->gFineNodesPerDir[0];
161 myGeometry->gNumFineNodes = myGeometry->gFineNodesPerDir[2] * myGeometry->gNumFineNodes10;
162 myGeometry->lNumFineNodes10 = myGeometry->lFineNodesPerDir[1] * myGeometry->lFineNodesPerDir[0];
163 myGeometry->lNumFineNodes = myGeometry->lFineNodesPerDir[2] * myGeometry->lNumFineNodes10;
167 "The local number of elements in Coordinates is not equal to the"
168 " number of nodes given by: lNodesPerDim!");
171 "The global number of elements in Coordinates is not equal to the"
172 " number of nodes given by: gNodesPerDim!");
175 std::string coarsenRate = pL.
get<std::string>(
"Coarsen");
178 crates = Teuchos::fromStringToArray<LO>(coarsenRate);
180 GetOStream(
Errors, -1) <<
" *** Coarsen must be a string convertible into an array! *** "
186 "Coarsen must have at least as many components as the number of"
187 " spatial dimensions in the problem.");
189 for (LO i = 0; i < 3; ++i) {
190 if (i < myGeometry->numDimensions) {
191 if (crates.size() == 1) {
192 myGeometry->coarseRate[i] = crates[0];
193 }
else if (crates.size() == myGeometry->numDimensions) {
194 myGeometry->coarseRate[i] = crates[i];
197 myGeometry->coarseRate[i] = 1;
201 int interpolationOrder = pL.
get<
int>(
"order");
204 "The interpolation order can only be set to 0 or 1.");
208 for (LO i = 0; i < myGeometry->numDimensions; ++i) {
211 for (LO i = 0; i < myGeometry->numDimensions; ++i) {
212 TEUCHOS_TEST_FOR_EXCEPTION(mapDirG2L[i] > myGeometry->numDimensions,
214 "axis permutation values must all be less than"
215 " the number of spatial dimensions.");
216 mapDirL2G[mapDirG2L[i]] = i;
223 if ((fineLevel.GetLevelID() == 0) && (myGeometry->meshLayout !=
"Global Lexicographic")) {
224 MeshLayoutInterface(interpolationOrder, blkSize, fineCoordsMap, myGeometry,
225 ghostedCoarseNodes, lCoarseNodesGIDs);
230 GetCoarsePoints(interpolationOrder, blkSize, fineCoordsMap, myGeometry, ghostedCoarseNodes,
245 GO lnnzP = Teuchos::as<LO>(std::pow(interpolationOrder + 1, myGeometry->numDimensions)) * (myGeometry->lNumFineNodes - myGeometry->lNumCoarseNodes) + myGeometry->lNumCoarseNodes;
246 lnnzP = lnnzP * blkSize;
247 GO gnnzP = Teuchos::as<LO>(std::pow(interpolationOrder + 1, myGeometry->numDimensions)) * (myGeometry->gNumFineNodes - myGeometry->gNumCoarseNodes) + myGeometry->gNumCoarseNodes;
248 gnnzP = gnnzP * blkSize;
250 GetOStream(
Runtime1) <<
"P size = " << blkSize * myGeometry->gNumFineNodes
251 <<
" x " << blkSize * myGeometry->gNumCoarseNodes << std::endl;
252 GetOStream(
Runtime1) <<
"P Fine grid : " << myGeometry->gFineNodesPerDir[0] <<
" -- "
253 << myGeometry->gFineNodesPerDir[1] <<
" -- "
254 << myGeometry->gFineNodesPerDir[2] << std::endl;
255 GetOStream(
Runtime1) <<
"P Coarse grid : " << myGeometry->gCoarseNodesPerDir[0] <<
" -- "
256 << myGeometry->gCoarseNodesPerDir[1] <<
" -- "
257 << myGeometry->gCoarseNodesPerDir[2] << std::endl;
258 GetOStream(
Runtime1) <<
"P nnz estimate: " << gnnzP << std::endl;
260 MakeGeneralGeometricP(myGeometry, fineCoords, lnnzP, blkSize, stridedDomainMapP,
261 A, P, coarseCoords, ghostedCoarseNodes, lCoarseNodesGIDs,
265 if (A->IsView(
"stridedMaps") ==
true) {
266 P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedDomainMapP);
268 P->CreateView(
"stridedMaps", P->getRangeMap(), stridedDomainMapP);
272 Set(coarseLevel,
"P", P);
273 Set(coarseLevel,
"coarseCoordinates", coarseCoords);
274 Set<Array<GO> >(coarseLevel,
"gCoarseNodesPerDim", myGeometry->gCoarseNodesPerDir);
275 Set<Array<LO> >(coarseLevel,
"lCoarseNodesPerDim", myGeometry->lCoarseNodesPerDir);
279 RCP<MultiVector> coarseNullspace = MultiVectorFactory::Build(P->getDomainMap(),
280 fineNullspace->getNumVectors());
283 Set(coarseLevel,
"Nullspace", coarseNullspace);
286 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
297 int numRanks = fineCoordsMap->getComm()->getSize();
298 int myRank = fineCoordsMap->getComm()->getRank();
300 myGeo->myBlock = myGeo->meshData[myRank][2];
301 myGeo->startIndices[0] = myGeo->meshData[myRank][3];
302 myGeo->startIndices[1] = myGeo->meshData[myRank][5];
303 myGeo->startIndices[2] = myGeo->meshData[myRank][7];
304 myGeo->startIndices[3] = myGeo->meshData[myRank][4];
305 myGeo->startIndices[4] = myGeo->meshData[myRank][6];
306 myGeo->startIndices[5] = myGeo->meshData[myRank][8];
307 std::sort(myGeo->meshData.begin(), myGeo->meshData.end(),
308 [](
const std::vector<GO>& a,
const std::vector<GO>& b) ->
bool {
312 }
else if (a[2] == b[2]) {
315 }
else if (a[7] == b[7]) {
318 }
else if (a[5] == b[5]) {
328 myGeo->numBlocks = myGeo->meshData[numRanks - 1][2] + 1;
330 auto myBlockStart = std::lower_bound(myGeo->meshData.begin(), myGeo->meshData.end(),
332 [](
const std::vector<GO>& vec,
const GO val) ->
bool {
333 return (vec[2] < val) ?
true :
false;
335 auto myBlockEnd = std::upper_bound(myGeo->meshData.begin(), myGeo->meshData.end(),
337 [](
const GO val,
const std::vector<GO>& vec) ->
bool {
338 return (val < vec[2]) ?
true :
false;
343 auto myKEnd = std::upper_bound(myBlockStart, myBlockEnd, (*myBlockStart)[3],
344 [](
const GO val,
const std::vector<GO>& vec) ->
bool {
345 return (val < vec[7]) ?
true :
false;
347 auto myJEnd = std::upper_bound(myBlockStart, myKEnd, (*myBlockStart)[3],
348 [](
const GO val,
const std::vector<GO>& vec) ->
bool {
349 return (val < vec[5]) ?
true :
false;
351 LO pi = std::distance(myBlockStart, myJEnd);
352 LO pj = std::distance(myBlockStart, myKEnd) / pi;
353 LO pk = std::distance(myBlockStart, myBlockEnd) / (pj * pi);
356 LO myRankIndex = std::distance(myGeo->meshData.begin(),
357 std::find_if(myBlockStart, myBlockEnd,
358 [myRank](
const std::vector<GO>& vec) ->
bool {
359 return (vec[0] == myRank) ?
true :
false;
362 for (
int dim = 0; dim < 3; ++dim) {
363 if (dim < myGeo->numDimensions) {
364 myGeo->offsets[dim] = Teuchos::as<LO>(myGeo->startIndices[dim]) % myGeo->coarseRate[dim];
365 myGeo->offsets[dim + 3] = Teuchos::as<LO>(myGeo->startIndices[dim]) % myGeo->coarseRate[dim];
371 for (
int dim = 0; dim < 3; ++dim) {
372 if (dim < myGeo->numDimensions && (myGeo->startIndices[dim] % myGeo->coarseRate[dim] != 0 ||
373 myGeo->startIndices[dim] == myGeo->gFineNodesPerDir[dim] - 1)) {
374 myGeo->ghostInterface[2 * dim] =
true;
376 if (dim < myGeo->numDimensions && myGeo->startIndices[dim + 3] != myGeo->gFineNodesPerDir[dim] - 1 && (myGeo->lFineNodesPerDir[dim] == 1 || myGeo->startIndices[dim + 3] % myGeo->coarseRate[dim] != 0)) {
377 myGeo->ghostInterface[2 * dim + 1] =
true;
393 for (
int i = 0; i < 3; ++i) {
394 if (i < myGeo->numDimensions) {
397 myGeo->gCoarseNodesPerDir[i] = (myGeo->gFineNodesPerDir[i] - 1) / myGeo->coarseRate[i];
398 myGeo->endRate[i] = Teuchos::as<LO>((myGeo->gFineNodesPerDir[i] - 1) % myGeo->coarseRate[i]);
399 if (myGeo->endRate[i] == 0) {
400 myGeo->endRate[i] = myGeo->coarseRate[i];
401 ++myGeo->gCoarseNodesPerDir[i];
403 myGeo->gCoarseNodesPerDir[i] += 2;
406 myGeo->endRate[i] = 1;
407 myGeo->gCoarseNodesPerDir[i] = 1;
411 myGeo->gNumCoarseNodes = myGeo->gCoarseNodesPerDir[0] * myGeo->gCoarseNodesPerDir[1] * myGeo->gCoarseNodesPerDir[2];
413 for (
LO i = 0; i < 3; ++i) {
414 if (i < myGeo->numDimensions) {
418 if ((myGeo->startIndices[i] + myGeo->lFineNodesPerDir[i]) == myGeo->gFineNodesPerDir[i]) {
419 myGeo->lCoarseNodesPerDir[i] = (myGeo->lFineNodesPerDir[i] - myGeo->endRate[i] + myGeo->offsets[i] - 1) / myGeo->coarseRate[i] + 1;
420 if (myGeo->offsets[i] == 0) {
421 ++myGeo->lCoarseNodesPerDir[i];
424 myGeo->lCoarseNodesPerDir[i] = (myGeo->lFineNodesPerDir[i] + myGeo->offsets[i] - 1) / myGeo->coarseRate[i];
425 if (myGeo->offsets[i] == 0) {
426 ++myGeo->lCoarseNodesPerDir[i];
430 myGeo->lCoarseNodesPerDir[i] = 1;
434 if (myGeo->lFineNodesPerDir[i] < 1) {
435 myGeo->lCoarseNodesPerDir[i] = 0;
442 myGeo->lNumCoarseNodes = myGeo->lCoarseNodesPerDir[0] * myGeo->lCoarseNodesPerDir[1] * myGeo->lCoarseNodesPerDir[2];
445 for (
int dim = 0; dim < 3; ++dim) {
449 if (myGeo->startIndices[dim] == myGeo->gFineNodesPerDir[dim] - 1 &&
450 myGeo->startIndices[dim] % myGeo->coarseRate[dim] == 0) {
451 myGeo->startGhostedCoarseNode[dim] = myGeo->startIndices[dim] / myGeo->coarseRate[dim] - 1;
453 myGeo->startGhostedCoarseNode[dim] = myGeo->startIndices[dim] / myGeo->coarseRate[dim];
455 myGeo->ghostedCoarseNodesPerDir[dim] = myGeo->lCoarseNodesPerDir[dim];
457 if (myGeo->ghostInterface[2 * dim]) {
458 myGeo->ghostedCoarseNodesPerDir[dim] += 1;
461 if (myGeo->ghostInterface[2 * dim + 1]) {
462 myGeo->ghostedCoarseNodesPerDir[dim] += 1;
465 myGeo->lNumGhostedNodes = myGeo->ghostedCoarseNodesPerDir[2] * myGeo->ghostedCoarseNodesPerDir[1] * myGeo->ghostedCoarseNodesPerDir[0];
466 myGeo->lNumGhostNodes = myGeo->lNumGhostedNodes - myGeo->lNumCoarseNodes;
467 ghostedCoarseNodes->PIDs.resize(myGeo->lNumGhostedNodes);
468 ghostedCoarseNodes->LIDs.resize(myGeo->lNumGhostedNodes);
469 ghostedCoarseNodes->GIDs.resize(myGeo->lNumGhostedNodes);
470 ghostedCoarseNodes->coarseGIDs.resize(myGeo->lNumGhostedNodes);
471 ghostedCoarseNodes->colInds.resize(myGeo->lNumGhostedNodes);
472 lCoarseNodesGIDs[0].resize(myGeo->lNumCoarseNodes);
473 lCoarseNodesGIDs[1].resize(myGeo->lNumCoarseNodes);
480 Array<LO> coarseNodeCoarseIndices(3), coarseNodeFineIndices(3);
481 LO currentIndex = -1, countCoarseNodes = 0;
482 for (
int k = 0; k < myGeo->ghostedCoarseNodesPerDir[2]; ++k) {
483 for (
int j = 0; j < myGeo->ghostedCoarseNodesPerDir[1]; ++j) {
484 for (
int i = 0; i < myGeo->ghostedCoarseNodesPerDir[0]; ++i) {
485 currentIndex = k * myGeo->ghostedCoarseNodesPerDir[1] * myGeo->ghostedCoarseNodesPerDir[0] + j * myGeo->ghostedCoarseNodesPerDir[0] + i;
486 coarseNodeCoarseIndices[0] = myGeo->startGhostedCoarseNode[0] + i;
487 coarseNodeFineIndices[0] = coarseNodeCoarseIndices[0] * myGeo->coarseRate[0];
488 if (coarseNodeFineIndices[0] > myGeo->gFineNodesPerDir[0] - 1) {
489 coarseNodeFineIndices[0] = myGeo->gFineNodesPerDir[0] - 1;
491 coarseNodeCoarseIndices[1] = myGeo->startGhostedCoarseNode[1] + j;
492 coarseNodeFineIndices[1] = coarseNodeCoarseIndices[1] * myGeo->coarseRate[1];
493 if (coarseNodeFineIndices[1] > myGeo->gFineNodesPerDir[1] - 1) {
494 coarseNodeFineIndices[1] = myGeo->gFineNodesPerDir[1] - 1;
496 coarseNodeCoarseIndices[2] = myGeo->startGhostedCoarseNode[2] + k;
497 coarseNodeFineIndices[2] = coarseNodeCoarseIndices[2] * myGeo->coarseRate[2];
498 if (coarseNodeFineIndices[2] > myGeo->gFineNodesPerDir[2] - 1) {
499 coarseNodeFineIndices[2] = myGeo->gFineNodesPerDir[2] - 1;
501 GO myGID = -1, myCoarseGID = -1;
502 LO myLID = -1, myPID = -1;
503 GetGIDLocalLexicographic(i, j, k, coarseNodeFineIndices, myGeo, myRankIndex, pi, pj, pk,
504 myBlockStart, myBlockEnd, myGID, myPID, myLID);
505 myCoarseGID = coarseNodeCoarseIndices[0] + coarseNodeCoarseIndices[1] * myGeo->gCoarseNodesPerDir[0] + coarseNodeCoarseIndices[2] * myGeo->gCoarseNodesPerDir[1] * myGeo->gCoarseNodesPerDir[0];
506 ghostedCoarseNodes->PIDs[currentIndex] = myPID;
507 ghostedCoarseNodes->LIDs[currentIndex] = myLID;
508 ghostedCoarseNodes->GIDs[currentIndex] = myGID;
509 ghostedCoarseNodes->coarseGIDs[currentIndex] = myCoarseGID;
510 if (myPID == myRank) {
511 lCoarseNodesGIDs[0][countCoarseNodes] = myCoarseGID;
512 lCoarseNodesGIDs[1][countCoarseNodes] = myGID;
521 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
534 myGeo->startIndices[2] = fineCoordsMap->getMinGlobalIndex() / (myGeo->gFineNodesPerDir[1] * myGeo->gFineNodesPerDir[0]);
535 tmp = fineCoordsMap->getMinGlobalIndex() % (myGeo->gFineNodesPerDir[1] * myGeo->gFineNodesPerDir[0]);
536 myGeo->startIndices[1] = tmp / myGeo->gFineNodesPerDir[0];
537 myGeo->startIndices[0] = tmp % myGeo->gFineNodesPerDir[0];
539 for (
int dim = 0; dim < 3; ++dim) {
540 myGeo->startIndices[dim + 3] = myGeo->startIndices[dim] + myGeo->lFineNodesPerDir[dim] - 1;
543 for (
int dim = 0; dim < 3; ++dim) {
544 if (dim < myGeo->numDimensions) {
545 myGeo->offsets[dim] = Teuchos::as<LO>(myGeo->startIndices[dim]) % myGeo->coarseRate[dim];
546 myGeo->offsets[dim + 3] = Teuchos::as<LO>(myGeo->startIndices[dim]) % myGeo->coarseRate[dim];
552 for (
int dim = 0; dim < 3; ++dim) {
553 if (dim < myGeo->numDimensions && (myGeo->startIndices[dim] % myGeo->coarseRate[dim] != 0 ||
554 myGeo->startIndices[dim] == myGeo->gFineNodesPerDir[dim] - 1)) {
555 myGeo->ghostInterface[2 * dim] =
true;
557 if (dim < myGeo->numDimensions && myGeo->startIndices[dim + 3] != myGeo->gFineNodesPerDir[dim] - 1 && (myGeo->lFineNodesPerDir[dim] == 1 || myGeo->startIndices[dim + 3] % myGeo->coarseRate[dim] != 0)) {
558 myGeo->ghostInterface[2 * dim + 1] =
true;
574 for (
int i = 0; i < 3; ++i) {
575 if (i < myGeo->numDimensions) {
578 myGeo->gCoarseNodesPerDir[i] = (myGeo->gFineNodesPerDir[i] - 1) / myGeo->coarseRate[i];
579 myGeo->endRate[i] = Teuchos::as<LO>((myGeo->gFineNodesPerDir[i] - 1) % myGeo->coarseRate[i]);
580 if (myGeo->endRate[i] == 0) {
581 myGeo->endRate[i] = myGeo->coarseRate[i];
582 ++myGeo->gCoarseNodesPerDir[i];
584 myGeo->gCoarseNodesPerDir[i] += 2;
587 myGeo->endRate[i] = 1;
588 myGeo->gCoarseNodesPerDir[i] = 1;
592 myGeo->gNumCoarseNodes = myGeo->gCoarseNodesPerDir[0] * myGeo->gCoarseNodesPerDir[1] * myGeo->gCoarseNodesPerDir[2];
594 for (
LO i = 0; i < 3; ++i) {
595 if (i < myGeo->numDimensions) {
599 if ((myGeo->startIndices[i] + myGeo->lFineNodesPerDir[i]) == myGeo->gFineNodesPerDir[i]) {
600 myGeo->lCoarseNodesPerDir[i] = (myGeo->lFineNodesPerDir[i] - myGeo->endRate[i] + myGeo->offsets[i] - 1) / myGeo->coarseRate[i] + 1;
601 if (myGeo->offsets[i] == 0) {
602 ++myGeo->lCoarseNodesPerDir[i];
605 myGeo->lCoarseNodesPerDir[i] = (myGeo->lFineNodesPerDir[i] + myGeo->offsets[i] - 1) / myGeo->coarseRate[i];
606 if (myGeo->offsets[i] == 0) {
607 ++myGeo->lCoarseNodesPerDir[i];
611 myGeo->lCoarseNodesPerDir[i] = 1;
615 if (myGeo->lFineNodesPerDir[i] < 1) {
616 myGeo->lCoarseNodesPerDir[i] = 0;
623 myGeo->lNumCoarseNodes = myGeo->lCoarseNodesPerDir[0] * myGeo->lCoarseNodesPerDir[1] * myGeo->lCoarseNodesPerDir[2];
626 bool ghostedDir[6] = {
false};
627 for (
int dim = 0; dim < 3; ++dim) {
631 if (myGeo->startIndices[dim] == myGeo->gFineNodesPerDir[dim] - 1 &&
632 myGeo->startIndices[dim] % myGeo->coarseRate[dim] == 0) {
633 myGeo->startGhostedCoarseNode[dim] = myGeo->startIndices[dim] / myGeo->coarseRate[dim] - 1;
635 myGeo->startGhostedCoarseNode[dim] = myGeo->startIndices[dim] / myGeo->coarseRate[dim];
637 myGeo->ghostedCoarseNodesPerDir[dim] = myGeo->lCoarseNodesPerDir[dim];
639 if (myGeo->ghostInterface[2 * dim]) {
640 myGeo->ghostedCoarseNodesPerDir[dim] += 1;
641 ghostedDir[2 * dim] =
true;
644 if (myGeo->ghostInterface[2 * dim + 1]) {
645 myGeo->ghostedCoarseNodesPerDir[dim] += 1;
646 ghostedDir[2 * dim + 1] =
true;
649 myGeo->lNumGhostedNodes = myGeo->ghostedCoarseNodesPerDir[2] * myGeo->ghostedCoarseNodesPerDir[1] * myGeo->ghostedCoarseNodesPerDir[0];
650 myGeo->lNumGhostNodes = myGeo->lNumGhostedNodes - myGeo->lNumCoarseNodes;
651 ghostedCoarseNodes->PIDs.resize(myGeo->lNumGhostedNodes);
652 ghostedCoarseNodes->LIDs.resize(myGeo->lNumGhostedNodes);
653 ghostedCoarseNodes->GIDs.resize(myGeo->lNumGhostedNodes);
654 ghostedCoarseNodes->coarseGIDs.resize(myGeo->lNumGhostedNodes);
655 ghostedCoarseNodes->colInds.resize(myGeo->lNumGhostedNodes);
656 lCoarseNodesGIDs[0].resize(myGeo->lNumCoarseNodes);
657 lCoarseNodesGIDs[1].resize(myGeo->lNumCoarseNodes);
664 Array<LO> coarseNodeCoarseIndices(3), coarseNodeFineIndices(3), ijk(3);
665 LO currentIndex = -1, countCoarseNodes = 0;
666 for (ijk[2] = 0; ijk[2] < myGeo->ghostedCoarseNodesPerDir[2]; ++ijk[2]) {
667 for (ijk[1] = 0; ijk[1] < myGeo->ghostedCoarseNodesPerDir[1]; ++ijk[1]) {
668 for (ijk[0] = 0; ijk[0] < myGeo->ghostedCoarseNodesPerDir[0]; ++ijk[0]) {
669 currentIndex = ijk[2] * myGeo->ghostedCoarseNodesPerDir[1] * myGeo->ghostedCoarseNodesPerDir[0] + ijk[1] * myGeo->ghostedCoarseNodesPerDir[0] + ijk[0];
670 coarseNodeCoarseIndices[0] = myGeo->startGhostedCoarseNode[0] + ijk[0];
671 coarseNodeFineIndices[0] = coarseNodeCoarseIndices[0] * myGeo->coarseRate[0];
672 if (coarseNodeFineIndices[0] > myGeo->gFineNodesPerDir[0] - 1) {
673 coarseNodeFineIndices[0] = myGeo->gFineNodesPerDir[0] - 1;
675 coarseNodeCoarseIndices[1] = myGeo->startGhostedCoarseNode[1] + ijk[1];
676 coarseNodeFineIndices[1] = coarseNodeCoarseIndices[1] * myGeo->coarseRate[1];
677 if (coarseNodeFineIndices[1] > myGeo->gFineNodesPerDir[1] - 1) {
678 coarseNodeFineIndices[1] = myGeo->gFineNodesPerDir[1] - 1;
680 coarseNodeCoarseIndices[2] = myGeo->startGhostedCoarseNode[2] + ijk[2];
681 coarseNodeFineIndices[2] = coarseNodeCoarseIndices[2] * myGeo->coarseRate[2];
682 if (coarseNodeFineIndices[2] > myGeo->gFineNodesPerDir[2] - 1) {
683 coarseNodeFineIndices[2] = myGeo->gFineNodesPerDir[2] - 1;
685 GO myGID = 0, myCoarseGID = -1;
687 factor[2] = myGeo->gNumFineNodes10;
688 factor[1] = myGeo->gFineNodesPerDir[0];
690 for (
int dim = 0; dim < 3; ++dim) {
691 if (dim < myGeo->numDimensions) {
692 if (myGeo->startIndices[dim] - myGeo->offsets[dim] + ijk[dim] * myGeo->coarseRate[dim] < myGeo->gFineNodesPerDir[dim] - 1) {
693 myGID += (myGeo->startIndices[dim] - myGeo->offsets[dim] + ijk[dim] * myGeo->coarseRate[dim]) * factor[dim];
695 myGID += (myGeo->startIndices[dim] - myGeo->offsets[dim] + (ijk[dim] - 1) * myGeo->coarseRate[dim] + myGeo->endRate[dim]) * factor[dim];
699 myCoarseGID = coarseNodeCoarseIndices[0] + coarseNodeCoarseIndices[1] * myGeo->gCoarseNodesPerDir[0] + coarseNodeCoarseIndices[2] * myGeo->gCoarseNodesPerDir[1] * myGeo->gCoarseNodesPerDir[0];
700 ghostedCoarseNodes->GIDs[currentIndex] = myGID;
701 ghostedCoarseNodes->coarseGIDs[currentIndex] = myCoarseGID;
702 if ((!ghostedDir[0] || ijk[0] != 0) && (!ghostedDir[2] || ijk[1] != 0) && (!ghostedDir[4] || ijk[2] != 0) && (!ghostedDir[1] || ijk[0] != myGeo->ghostedCoarseNodesPerDir[0] - 1) && (!ghostedDir[3] || ijk[1] != myGeo->ghostedCoarseNodesPerDir[1] - 1) && (!ghostedDir[5] || ijk[2] != myGeo->ghostedCoarseNodesPerDir[2] - 1)) {
703 lCoarseNodesGIDs[0][countCoarseNodes] = myCoarseGID;
704 lCoarseNodesGIDs[1][countCoarseNodes] = myGID;
710 Array<int> ghostsPIDs(myGeo->lNumGhostedNodes);
711 Array<LO> ghostsLIDs(myGeo->lNumGhostedNodes);
712 fineCoordsMap->getRemoteIndexList(ghostedCoarseNodes->GIDs(),
713 ghostedCoarseNodes->PIDs(),
714 ghostedCoarseNodes->LIDs());
717 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
721 const LO nnzP,
const LO dofsPerNode,
725 int interpolationOrder)
const {
747 LO myRank = Amat->getRowMap()->getComm()->getRank();
748 GO numGloCols = dofsPerNode * myGeo->gNumCoarseNodes;
768 std::vector<NodeID> colMapOrdering(myGeo->lNumGhostedNodes);
769 for (LO ind = 0; ind < myGeo->lNumGhostedNodes; ++ind) {
770 colMapOrdering[ind].GID = ghostedCoarseNodes->GIDs[ind];
771 if (ghostedCoarseNodes->PIDs[ind] == myRank) {
772 colMapOrdering[ind].PID = -1;
774 colMapOrdering[ind].PID = ghostedCoarseNodes->PIDs[ind];
776 colMapOrdering[ind].LID = ghostedCoarseNodes->LIDs[ind];
777 colMapOrdering[ind].lexiInd = ind;
779 std::sort(colMapOrdering.begin(), colMapOrdering.end(),
781 return ((a.
PID < b.PID) || ((a.
PID == b.PID) && (a.
GID < b.GID)));
784 Array<GO> colGIDs(dofsPerNode * myGeo->lNumGhostedNodes);
785 for (LO ind = 0; ind < myGeo->lNumGhostedNodes; ++ind) {
787 ghostedCoarseNodes->colInds[colMapOrdering[ind].lexiInd] = ind;
788 for (LO dof = 0; dof < dofsPerNode; ++dof) {
789 colGIDs[dofsPerNode * ind + dof] = dofsPerNode * colMapOrdering[ind].GID + dof;
794 colGIDs.view(0, dofsPerNode *
795 myGeo->lNumCoarseNodes),
796 rowMapP->getIndexBase(),
800 colGIDs.view(0, colGIDs.size()),
801 rowMapP->getIndexBase(),
805 std::vector<size_t> strideInfo(1);
806 strideInfo[0] = dofsPerNode;
812 RCP<const Map> coarseCoordsMap = MapFactory::Build(fineCoords->getMap()->lib(),
813 myGeo->gNumCoarseNodes,
814 coarseNodesGIDs[0](),
815 fineCoords->getMap()->getIndexBase(),
816 fineCoords->getMap()->getComm());
817 RCP<const Map> coarseCoordsFineMap = MapFactory::Build(fineCoords->getMap()->lib(),
818 myGeo->gNumCoarseNodes,
819 coarseNodesGIDs[1](),
820 fineCoords->getMap()->getIndexBase(),
821 fineCoords->getMap()->getComm());
824 coarseCoordsFineMap);
826 myGeo->numDimensions);
827 coarseCoords->doImport(*fineCoords, *coarseImporter,
Xpetra::INSERT);
828 coarseCoords->replaceMap(coarseCoordsMap);
833 ghostedCoarseNodes->GIDs(),
834 fineCoords->getMap()->getIndexBase(),
835 fineCoords->getMap()->getComm());
836 RCP<const Import> ghostImporter = ImportFactory::Build(fineCoords->getMap(), ghostMap);
838 myGeo->numDimensions);
839 ghostCoords->doImport(*fineCoords, *ghostImporter,
Xpetra::INSERT);
841 P =
rcp(
new CrsMatrixWrap(rowMapP, colMapP, 0));
842 RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
848 PCrs->allocateAllValues(nnzP, iaP, jaP, valP);
858 for (
int dim = 0; dim < 3; ++dim) {
859 if (dim < myGeo->numDimensions) {
860 ghostedCoords[dim] = ghostCoords->getDataNonConst(dim);
862 ghostedCoords[dim] = tmp;
871 for (
int dim = 0; dim < 3; ++dim) {
872 if (dim < myGeo->numDimensions) {
873 lFineCoords[dim] = fineCoords->getDataNonConst(dim);
875 lFineCoords[dim] = zeros->getDataNonConst(0);
880 for (
int currentIndex = 0; currentIndex < myGeo->lNumFineNodes; ++currentIndex) {
881 Array<GO> ghostedIndices(3), firstInterpolationIndices(3);
882 Array<LO> interpolationPIDs(8), interpolationLIDs(8), interpolationGIDs(8);
884 interpolationCoords[0].
resize(3);
885 GO firstInterpolationNodeIndex;
887 for (
int dim = 0; dim < 3; ++dim) {
888 interpolationCoords[0][dim] = lFineCoords[dim][currentIndex];
894 ghostedIndices[2] = currentIndex / (myGeo->lFineNodesPerDir[1] * myGeo->lFineNodesPerDir[0]);
895 LO tmp = currentIndex % (myGeo->lFineNodesPerDir[1] * myGeo->lFineNodesPerDir[0]);
896 ghostedIndices[1] = tmp / myGeo->lFineNodesPerDir[0];
897 ghostedIndices[0] = tmp % myGeo->lFineNodesPerDir[0];
898 for (
int dim = 0; dim < 3; ++dim) {
899 ghostedIndices[dim] += myGeo->offsets[dim];
908 for (
int dim = 0; dim < 3; ++dim) {
909 firstInterpolationIndices[dim] = ghostedIndices[dim] / myGeo->coarseRate[dim];
912 if (firstInterpolationIndices[dim] == myGeo->ghostedCoarseNodesPerDir[dim] - 1 && myGeo->ghostedCoarseNodesPerDir[dim] > 1) {
913 firstInterpolationIndices[dim] -= 1;
916 firstInterpolationNodeIndex =
917 firstInterpolationIndices[2] * myGeo->ghostedCoarseNodesPerDir[1] * myGeo->ghostedCoarseNodesPerDir[0] + firstInterpolationIndices[1] * myGeo->ghostedCoarseNodesPerDir[0] + firstInterpolationIndices[0];
923 for (
int k = 0; k < 2; ++k) {
924 for (
int j = 0; j < 2; ++j) {
925 for (
int i = 0; i < 2; ++i) {
926 ind = k * 4 + j * 2 + i;
927 interpolationLIDs[ind] = firstInterpolationNodeIndex + k * myGeo->ghostedCoarseNodesPerDir[1] * myGeo->ghostedCoarseNodesPerDir[0] + j * myGeo->ghostedCoarseNodesPerDir[0] + i;
928 if (ghostedCoarseNodes->PIDs[interpolationLIDs[ind]] == rowMapP->getComm()->getRank()) {
929 interpolationPIDs[ind] = -1;
931 interpolationPIDs[ind] = ghostedCoarseNodes->PIDs[interpolationLIDs[ind]];
933 interpolationGIDs[ind] = ghostedCoarseNodes->coarseGIDs[interpolationLIDs[ind]];
935 interpolationCoords[ind + 1].
resize(3);
936 for (
int dim = 0; dim < 3; ++dim) {
937 interpolationCoords[ind + 1][dim] = ghostedCoords[dim][interpolationLIDs[ind]];
946 std::vector<double> stencil(8);
949 for (
int dim = 0; dim < 3; ++dim) {
950 firstCoarseNodeFineIndices[dim] = firstInterpolationIndices[dim] * myGeo->coarseRate[dim];
951 if ((myGeo->startIndices[dim + 3] == myGeo->gFineNodesPerDir[dim] - 1) && (ghostedIndices[dim] >=
952 (myGeo->ghostedCoarseNodesPerDir[dim] - 2) * myGeo->coarseRate[dim])) {
953 rate[dim] = myGeo->endRate[dim];
955 rate[dim] = myGeo->coarseRate[dim];
962 for (
int dim = 0; dim < 3; ++dim) {
963 if (myGeo->startIndices[dim] == myGeo->gFineNodesPerDir[dim] - 1) {
964 trueGhostedIndices[dim] = ghostedIndices[dim] + rate[dim];
966 trueGhostedIndices[dim] = ghostedIndices[dim];
969 ComputeStencil(myGeo->numDimensions, trueGhostedIndices, firstCoarseNodeFineIndices, rate,
970 interpolationCoords, interpolationOrder, stencil);
975 Array<LO> nzIndStencil(8), permutation(8);
976 for (LO k = 0; k < 8; ++k) {
979 if (interpolationOrder == 0) {
981 for (LO k = 0; k < 8; ++k) {
982 nzIndStencil[k] =
static_cast<LO
>(stencil[0]);
985 stencil[nzIndStencil[0]] = 1.0;
986 }
else if (interpolationOrder == 1) {
987 Array<GO> currentNodeGlobalFineIndices(3);
988 for (
int dim = 0; dim < 3; ++dim) {
989 currentNodeGlobalFineIndices[dim] = ghostedIndices[dim] - myGeo->offsets[dim] + myGeo->startIndices[dim];
991 if (((ghostedIndices[0] % myGeo->coarseRate[0] == 0) || currentNodeGlobalFineIndices[0] == myGeo->gFineNodesPerDir[0] - 1) && ((ghostedIndices[1] % myGeo->coarseRate[1] == 0) || currentNodeGlobalFineIndices[1] == myGeo->gFineNodesPerDir[1] - 1) && ((ghostedIndices[2] % myGeo->coarseRate[2] == 0) || currentNodeGlobalFineIndices[2] == myGeo->gFineNodesPerDir[2] - 1)) {
992 if ((currentNodeGlobalFineIndices[0] == myGeo->gFineNodesPerDir[0] - 1) ||
993 (ghostedIndices[0] / myGeo->coarseRate[0] == myGeo->ghostedCoarseNodesPerDir[0] - 1)) {
994 nzIndStencil[0] += 1;
996 if (((currentNodeGlobalFineIndices[1] == myGeo->gFineNodesPerDir[1] - 1) ||
997 (ghostedIndices[1] / myGeo->coarseRate[1] == myGeo->ghostedCoarseNodesPerDir[1] - 1)) &&
998 (myGeo->numDimensions > 1)) {
999 nzIndStencil[0] += 2;
1001 if (((currentNodeGlobalFineIndices[2] == myGeo->gFineNodesPerDir[2] - 1) ||
1002 (ghostedIndices[2] / myGeo->coarseRate[2] == myGeo->ghostedCoarseNodesPerDir[2] - 1)) &&
1003 myGeo->numDimensions > 2) {
1004 nzIndStencil[0] += 4;
1007 for (LO k = 0; k < 8; ++k) {
1008 nzIndStencil[k] = nzIndStencil[0];
1012 for (LO k = 0; k < 8; ++k) {
1013 nzIndStencil[k] = k;
1025 sh_sort2(interpolationPIDs.begin(), interpolationPIDs.end(),
1026 permutation.
begin(), permutation.
end());
1029 for (LO j = 0; j < dofsPerNode; ++j) {
1030 ia[currentIndex * dofsPerNode + j + 1] = ia[currentIndex * dofsPerNode + j] + nStencil;
1031 for (LO k = 0; k < nStencil; ++k) {
1032 colInd = ghostedCoarseNodes->colInds[interpolationLIDs[nzIndStencil[permutation[k]]]];
1033 ja[ia[currentIndex * dofsPerNode + j] + k] = colInd * dofsPerNode + j;
1034 val[ia[currentIndex * dofsPerNode + j] + k] = stencil[nzIndStencil[permutation[k]]];
1037 tStencil += nStencil;
1050 PCrs->setAllValues(iaP, jaP, valP);
1051 PCrs->expertStaticFillComplete(domainMapP, rowMapP);
1529 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1531 const LO numDimensions,
const Array<GO> currentNodeIndices,
1532 const Array<GO> coarseNodeIndices,
const LO rate[3],
1534 std::vector<double>& stencil)
const {
1537 "The interpolation order can be set to 0 or 1 only.");
1539 if (interpolationOrder == 0) {
1540 ComputeConstantInterpolationStencil(numDimensions, currentNodeIndices, coarseNodeIndices,
1542 }
else if (interpolationOrder == 1) {
1543 ComputeLinearInterpolationStencil(numDimensions, coord, stencil);
1548 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1551 const Array<GO> coarseNodeIndices,
const LO rate[3],
1552 std::vector<double>& stencil)
const {
1554 if (numDimensions > 2) {
1555 if ((currentNodeIndices[2] - coarseNodeIndices[2]) > (rate[2] / 2)) {
1559 if (numDimensions > 1) {
1560 if ((currentNodeIndices[1] - coarseNodeIndices[1]) > (rate[1] / 2)) {
1564 if ((currentNodeIndices[0] - coarseNodeIndices[0]) > (rate[0] / 2)) {
1567 stencil[0] = coarseNode;
1571 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1574 std::vector<double>& stencil)
1596 LO numTerms = std::pow(2, numDimensions),
iter = 0, max_iter = 5;
1597 double functions[4][8], norm_ref = 1, norm2 = 1, tol = 1e-5;
1598 paramCoords.
size(numDimensions);
1600 while ((
iter < max_iter) && (norm2 > tol * norm_ref)) {
1603 solutionDirection.
size(numDimensions);
1604 residual.
size(numDimensions);
1608 GetInterpolationFunctions(numDimensions, paramCoords, functions);
1609 for (
LO i = 0; i < numDimensions; ++i) {
1610 residual(i) = coord[0][i];
1611 for (
LO k = 0; k < numTerms; ++k) {
1612 residual(i) -= functions[0][k] * coord[k + 1][i];
1615 norm_ref += residual(i) * residual(i);
1616 if (i == numDimensions - 1) {
1617 norm_ref = std::sqrt(norm_ref);
1621 for (
LO j = 0; j < numDimensions; ++j) {
1622 for (
LO k = 0; k < numTerms; ++k) {
1623 Jacobian(i, j) += functions[j + 1][k] * coord[k + 1][i];
1635 for (
LO i = 0; i < numDimensions; ++i) {
1636 paramCoords(i) = paramCoords(i) + solutionDirection(i);
1640 GetInterpolationFunctions(numDimensions, paramCoords, functions);
1641 for (
LO i = 0; i < numDimensions; ++i) {
1642 double tmp = coord[0][i];
1643 for (
LO k = 0; k < numTerms; ++k) {
1644 tmp -= functions[0][k] * coord[k + 1][i];
1649 norm2 = std::sqrt(norm2);
1653 for (
LO i = 0; i < 8; ++i) {
1654 stencil[i] = functions[0][i];
1659 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1663 double functions[4][8])
const {
1664 double xi = 0.0, eta = 0.0, zeta = 0.0, denominator = 0.0;
1665 if (numDimensions == 1) {
1668 }
else if (numDimensions == 2) {
1670 eta = parameters[1];
1672 }
else if (numDimensions == 3) {
1674 eta = parameters[1];
1675 zeta = parameters[2];
1679 functions[0][0] = (1.0 - xi) * (1.0 - eta) * (1.0 - zeta) / denominator;
1680 functions[0][1] = (1.0 + xi) * (1.0 - eta) * (1.0 - zeta) / denominator;
1681 functions[0][2] = (1.0 - xi) * (1.0 + eta) * (1.0 - zeta) / denominator;
1682 functions[0][3] = (1.0 + xi) * (1.0 + eta) * (1.0 - zeta) / denominator;
1683 functions[0][4] = (1.0 - xi) * (1.0 - eta) * (1.0 + zeta) / denominator;
1684 functions[0][5] = (1.0 + xi) * (1.0 - eta) * (1.0 + zeta) / denominator;
1685 functions[0][6] = (1.0 - xi) * (1.0 + eta) * (1.0 + zeta) / denominator;
1686 functions[0][7] = (1.0 + xi) * (1.0 + eta) * (1.0 + zeta) / denominator;
1688 functions[1][0] = -(1.0 - eta) * (1.0 - zeta) / denominator;
1689 functions[1][1] = (1.0 - eta) * (1.0 - zeta) / denominator;
1690 functions[1][2] = -(1.0 + eta) * (1.0 - zeta) / denominator;
1691 functions[1][3] = (1.0 + eta) * (1.0 - zeta) / denominator;
1692 functions[1][4] = -(1.0 - eta) * (1.0 + zeta) / denominator;
1693 functions[1][5] = (1.0 - eta) * (1.0 + zeta) / denominator;
1694 functions[1][6] = -(1.0 + eta) * (1.0 + zeta) / denominator;
1695 functions[1][7] = (1.0 + eta) * (1.0 + zeta) / denominator;
1697 functions[2][0] = -(1.0 - xi) * (1.0 - zeta) / denominator;
1698 functions[2][1] = -(1.0 + xi) * (1.0 - zeta) / denominator;
1699 functions[2][2] = (1.0 - xi) * (1.0 - zeta) / denominator;
1700 functions[2][3] = (1.0 + xi) * (1.0 - zeta) / denominator;
1701 functions[2][4] = -(1.0 - xi) * (1.0 + zeta) / denominator;
1702 functions[2][5] = -(1.0 + xi) * (1.0 + zeta) / denominator;
1703 functions[2][6] = (1.0 - xi) * (1.0 + zeta) / denominator;
1704 functions[2][7] = (1.0 + xi) * (1.0 + zeta) / denominator;
1706 functions[3][0] = -(1.0 - xi) * (1.0 - eta) / denominator;
1707 functions[3][1] = -(1.0 + xi) * (1.0 - eta) / denominator;
1708 functions[3][2] = -(1.0 - xi) * (1.0 + eta) / denominator;
1709 functions[3][3] = -(1.0 + xi) * (1.0 + eta) / denominator;
1710 functions[3][4] = (1.0 - xi) * (1.0 - eta) / denominator;
1711 functions[3][5] = (1.0 + xi) * (1.0 - eta) / denominator;
1712 functions[3][6] = (1.0 - xi) * (1.0 + eta) / denominator;
1713 functions[3][7] = (1.0 + xi) * (1.0 + eta) / denominator;
1717 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1723 typedef typename std::iterator_traits<typename Teuchos::Array<LocalOrdinal>::iterator>::difference_type DT;
1724 DT n = last1 - first1;
1729 for (DT j = 0; j < max; j++) {
1730 for (DT k = j; k >= 0; k -= m) {
1731 if (first1[first2[k + m]] >= first1[first2[k]])
1733 std::swap(first2[k + m], first2[k]);
1740 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1746 typedef typename std::iterator_traits<typename Teuchos::Array<LocalOrdinal>::iterator>::difference_type DT;
1747 DT n = last1 - first1;
1752 for (DT j = 0; j < max; j++) {
1753 for (DT k = j; k >= 0; k -= m) {
1754 if (first1[k + m] >= first1[k])
1756 std::swap(first1[k + m], first1[k]);
1757 std::swap(first2[k + m], first2[k]);
1764 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1768 const LO myRankIndex,
const LO pi,
const LO pj,
const LO ,
1769 const typename std::vector<std::vector<GO> >::iterator blockStart,
1770 const typename std::vector<std::vector<GO> >::iterator blockEnd,
1771 GO& myGID,
LO& myPID,
LO& myLID)
const {
1772 LO ni = -1, nj = -1, li = -1, lj = -1, lk = -1;
1773 LO myRankGuess = myRankIndex;
1775 if (i == 0 && myGeo->ghostInterface[0]) {
1777 }
else if ((i == myGeo->ghostedCoarseNodesPerDir[0] - 1) && myGeo->ghostInterface[1]) {
1780 if (j == 0 && myGeo->ghostInterface[2]) {
1782 }
else if ((j == myGeo->ghostedCoarseNodesPerDir[1] - 1) && myGeo->ghostInterface[3]) {
1785 if (k == 0 && myGeo->ghostInterface[4]) {
1786 myRankGuess -= pj * pi;
1787 }
else if ((k == myGeo->ghostedCoarseNodesPerDir[2] - 1) && myGeo->ghostInterface[5]) {
1788 myRankGuess += pj * pi;
1790 if (coarseNodeFineIndices[0] >= myGeo->meshData[myRankGuess][3] && coarseNodeFineIndices[0] <= myGeo->meshData[myRankGuess][4] && coarseNodeFineIndices[1] >= myGeo->meshData[myRankGuess][5] && coarseNodeFineIndices[1] <= myGeo->meshData[myRankGuess][6] && coarseNodeFineIndices[2] >= myGeo->meshData[myRankGuess][7] && coarseNodeFineIndices[2] <= myGeo->meshData[myRankGuess][8]) {
1791 myPID = myGeo->meshData[myRankGuess][0];
1792 ni = myGeo->meshData[myRankGuess][4] - myGeo->meshData[myRankGuess][3] + 1;
1793 nj = myGeo->meshData[myRankGuess][6] - myGeo->meshData[myRankGuess][5] + 1;
1794 li = coarseNodeFineIndices[0] - myGeo->meshData[myRankGuess][3];
1795 lj = coarseNodeFineIndices[1] - myGeo->meshData[myRankGuess][5];
1796 lk = coarseNodeFineIndices[2] - myGeo->meshData[myRankGuess][7];
1797 myLID = lk * nj * ni + lj * ni + li;
1798 myGID = myGeo->meshData[myRankGuess][9] + myLID;
1802 auto nodeRank = std::find_if(blockStart, blockEnd,
1803 [coarseNodeFineIndices](
const std::vector<GO>& vec) {
1804 if (coarseNodeFineIndices[0] >= vec[3] && coarseNodeFineIndices[0] <= vec[4] && coarseNodeFineIndices[1] >= vec[5] && coarseNodeFineIndices[1] <= vec[6] && coarseNodeFineIndices[2] >= vec[7] && coarseNodeFineIndices[2] <= vec[8]) {
1810 myPID = (*nodeRank)[0];
1811 ni = (*nodeRank)[4] - (*nodeRank)[3] + 1;
1812 nj = (*nodeRank)[6] - (*nodeRank)[5] + 1;
1813 li = coarseNodeFineIndices[0] - (*nodeRank)[3];
1814 lj = coarseNodeFineIndices[1] - (*nodeRank)[5];
1815 lk = coarseNodeFineIndices[2] - (*nodeRank)[7];
1816 myLID = lk * nj * ni + lj * ni + li;
1817 myGID = (*nodeRank)[9] + myLID;
1823 #define MUELU_GENERALGEOMETRICPFACTORY_SHORT
1824 #endif // MUELU_GENERALGEOMETRICPFACTORY_DEF_HPP
void ComputeLinearInterpolationStencil(const LO numDimension, const Array< Array< typename Teuchos::ScalarTraits< Scalar >::coordinateType > > coord, std::vector< double > &stencil) const
void GetCoarsePoints(const int interpolationOrder, const LO blkSize, RCP< const Map > fineCoordsMap, RCP< GeometricData > myGeometry, RCP< NodesIDs > ghostedCoarseNodes, Array< Array< GO > > &lCoarseNodesGIDs) const
void MakeGeneralGeometricP(RCP< GeometricData > myGeo, const RCP< Xpetra::MultiVector< typename Teuchos::ScalarTraits< Scalar >::coordinateType, LO, GO, NO > > &fCoords, const LO nnzP, const LO dofsPerNode, RCP< const Map > &stridedDomainMapP, RCP< Matrix > &Amat, RCP< Matrix > &P, RCP< Xpetra::MultiVector< typename Teuchos::ScalarTraits< Scalar >::coordinateType, LO, GO, NO > > &cCoords, RCP< NodesIDs > ghostedCoarseNodes, Array< Array< GO > > coarseNodesGIDs, int interpolationOrder) const
T & get(const std::string &name, T def_value)
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
static const NoFactory * get()
void resize(const size_type n, const T &val=T())
void MeshLayoutInterface(const int interpolationOrder, const LO blkSize, RCP< const Map > fineCoordsMap, RCP< GeometricData > myGeometry, RCP< NodesIDs > ghostedCoarseNodes, Array< Array< GO > > &lCoarseNodesGIDs) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
static Teuchos::RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, const Teuchos::RCP< const Teuchos::Comm< int >> &comm, LocalGlobal lg=Xpetra::GloballyDistributed)
void factorWithEquilibration(bool flag)
void sh_sort2(const typename Teuchos::Array< LocalOrdinal >::iterator &first1, const typename Teuchos::Array< LocalOrdinal >::iterator &last1, const typename Teuchos::Array< LocalOrdinal >::iterator &first2, const typename Teuchos::Array< LocalOrdinal >::iterator &last2) const
void ComputeStencil(const LO numDimension, const Array< GO > currentNodeIndices, const Array< GO > coarseNodeIndices, const LO rate[3], const Array< Array< typename Teuchos::ScalarTraits< Scalar >::coordinateType > > coord, const int interpolationOrder, std::vector< double > &stencil) const
void GetGIDLocalLexicographic(const GO i, const GO j, const GO k, const Array< LO > coarseNodeFineIndices, const RCP< GeometricData > myGeo, const LO myRankIndex, const LO pi, const LO pj, const LO pk, const typename std::vector< std::vector< GO > >::iterator blockStart, const typename std::vector< std::vector< GO > >::iterator blockEnd, GO &myGID, LO &myPID, LO &myLID) const
void resize(size_type new_size, const value_type &x=value_type())
void GetInterpolationFunctions(const LO numDimension, const Teuchos::SerialDenseVector< LO, double > parameters, double functions[4][8]) const
void ComputeConstantInterpolationStencil(const LO numDimension, const Array< GO > currentNodeIndices, const Array< GO > coarseNodeIndices, const LO rate[3], std::vector< double > &stencil) const
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
void sh_sort_permute(const typename Teuchos::Array< LocalOrdinal >::iterator &first1, const typename Teuchos::Array< LocalOrdinal >::iterator &last1, const typename Teuchos::Array< LocalOrdinal >::iterator &first2, const typename Teuchos::Array< LocalOrdinal >::iterator &last2) const
int size(OrdinalType length_in)
int setVectors(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &X, const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &B)
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
static RCP< Xpetra::StridedMap< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, std::vector< size_t > &stridingInfo, const Teuchos::RCP< const Teuchos::Comm< int >> &comm, LocalOrdinal stridedBlockId=-1, GlobalOrdinal offset=0, LocalGlobal lg=Xpetra::GloballyDistributed)
int GetLevelID() const
Return level number.
void residual(const Operator< SC, LO, GO, NO > &Aop, const MultiVector< SC, LO, GO, NO > &X_in, const MultiVector< SC, LO, GO, NO > &B_in, MultiVector< SC, LO, GO, NO > &R_in)
Exception throws to report errors in the internal logical of the program.
Description of what is happening (more verbose)
std::vector< T >::iterator iterator
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
int setMatrix(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &A)