46 #ifndef MUELU_GENERALGEOMETRICPFACTORY_DEF_HPP
47 #define MUELU_GENERALGEOMETRICPFACTORY_DEF_HPP
58 #include <Xpetra_CrsMatrixWrap.hpp>
59 #include <Xpetra_ImportFactory.hpp>
60 #include <Xpetra_Matrix.hpp>
61 #include <Xpetra_MapFactory.hpp>
62 #include <Xpetra_MultiVectorFactory.hpp>
63 #include <Xpetra_VectorFactory.hpp>
65 #include <Xpetra_IO.hpp>
75 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
84 validParamList->
set<std::string > (
"Coarsen",
"{2}",
85 "Coarsening rate in all spatial dimensions");
86 validParamList->
set<
int> (
"order", 1,
87 "Order of the interpolation scheme used");
89 "Generating factory of the matrix A");
91 "Generating factory of the nullspace");
93 "Generating factory for coorindates");
95 "Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
97 "Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
98 validParamList->
set<std::string > (
"meshLayout",
"Global Lexicographic",
99 "Type of mesh ordering");
101 "Mesh ordering associated data");
103 return validParamList;
106 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
109 Input(fineLevel,
"A");
110 Input(fineLevel,
"Nullspace");
111 Input(fineLevel,
"Coordinates");
119 "gNodesPerDim was not provided by the user on level0!");
122 Input(fineLevel,
"gNodesPerDim");
132 "lNodesPerDim was not provided by the user on level0!");
135 Input(fineLevel,
"lNodesPerDim");
139 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
141 Level& coarseLevel)
const {
142 return BuildP(fineLevel, coarseLevel);
145 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
147 Level& coarseLevel)
const {
151 using xdMV = Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::coordinateType,LO,GO,NO>;
152 RCP<Matrix> A = Get< RCP<Matrix> > (fineLevel,
"A");
153 RCP<MultiVector> fineNullspace = Get< RCP<MultiVector> > (fineLevel,
"Nullspace");
154 RCP<xdMV> fineCoords = Get< RCP<xdMV> >(fineLevel,
"Coordinates");
161 const LO blkSize = A->GetFixedBlockSize();
166 myGeometry->meshLayout = pL.
get<std::string>(
"meshLayout");
167 if(fineLevel.GetLevelID() == 0) {
168 if(myGeometry->meshLayout ==
"Local Lexicographic") {
172 "The meshData array is empty, somehow the input for geometric"
173 " multigrid are not captured correctly.");
174 myGeometry->meshData.resize(rowMap->getComm()->getSize());
175 for(
int i = 0; i < rowMap->getComm()->getSize(); ++i) {
176 myGeometry->meshData[i].resize(10);
177 for(
int j = 0; j < 10; ++j) {
178 myGeometry->meshData[i][j] = meshData[10*i + j];
185 "Coordinates cannot be accessed from fine level!");
186 myGeometry->numDimensions = fineCoords->getNumVectors();
189 if(fineLevel.GetLevelID() == 0) {
194 myGeometry->gFineNodesPerDir = Get<Array<GO> >(fineLevel,
"gNodesPerDim");
197 myGeometry->lFineNodesPerDir = Get<Array<LO> >(fineLevel,
"lNodesPerDim");
199 myGeometry->gNumFineNodes10 = myGeometry->gFineNodesPerDir[1]*myGeometry->gFineNodesPerDir[0];
200 myGeometry->gNumFineNodes = myGeometry->gFineNodesPerDir[2]*myGeometry->gNumFineNodes10;
201 myGeometry->lNumFineNodes10 = myGeometry->lFineNodesPerDir[1]*myGeometry->lFineNodesPerDir[0];
202 myGeometry->lNumFineNodes = myGeometry->lFineNodesPerDir[2]*myGeometry->lNumFineNodes10;
205 !=
static_cast<size_t>(myGeometry->lNumFineNodes),
207 "The local number of elements in Coordinates is not equal to the"
208 " number of nodes given by: lNodesPerDim!");
210 !=
static_cast<size_t>(myGeometry->gNumFineNodes),
212 "The global number of elements in Coordinates is not equal to the"
213 " number of nodes given by: gNodesPerDim!");
216 std::string coarsenRate = pL.
get<std::string>(
"Coarsen");
219 crates = Teuchos::fromStringToArray<LO>(coarsenRate);
221 GetOStream(
Errors,-1) <<
" *** Coarsen must be a string convertible into an array! *** "
227 "Coarsen must have at least as many components as the number of"
228 " spatial dimensions in the problem.");
230 for(LO i = 0; i < 3; ++i) {
231 if(i < myGeometry->numDimensions) {
232 if(crates.size()==1) {
233 myGeometry->coarseRate[i] = crates[0];
234 }
else if(crates.size() == myGeometry->numDimensions) {
235 myGeometry->coarseRate[i] = crates[i];
238 myGeometry->coarseRate[i] = 1;
242 int interpolationOrder = pL.
get<
int>(
"order");
245 "The interpolation order can only be set to 0 or 1.");
249 for(LO i = 0; i < myGeometry->numDimensions; ++i) {
252 for(LO i = 0; i < myGeometry->numDimensions; ++i) {
253 TEUCHOS_TEST_FOR_EXCEPTION(mapDirG2L[i] > myGeometry->numDimensions,
255 "axis permutation values must all be less than"
256 " the number of spatial dimensions.");
257 mapDirL2G[mapDirG2L[i]] = i;
264 if((fineLevel.GetLevelID() == 0) && (myGeometry->meshLayout !=
"Global Lexicographic")) {
265 MeshLayoutInterface(interpolationOrder, blkSize, fineCoordsMap, myGeometry,
266 ghostedCoarseNodes, lCoarseNodesGIDs);
271 GetCoarsePoints(interpolationOrder, blkSize, fineCoordsMap, myGeometry, ghostedCoarseNodes,
286 GO lnnzP = Teuchos::as<LO>(std::pow(interpolationOrder + 1, myGeometry->numDimensions))
287 *(myGeometry->lNumFineNodes - myGeometry->lNumCoarseNodes) + myGeometry->lNumCoarseNodes;
288 lnnzP = lnnzP*blkSize;
289 GO gnnzP = Teuchos::as<LO>(std::pow(interpolationOrder + 1, myGeometry->numDimensions))
290 *(myGeometry->gNumFineNodes - myGeometry->gNumCoarseNodes) + myGeometry->gNumCoarseNodes;
291 gnnzP = gnnzP*blkSize;
293 GetOStream(
Runtime1) <<
"P size = " << blkSize*myGeometry->gNumFineNodes
294 <<
" x " << blkSize*myGeometry->gNumCoarseNodes << std::endl;
295 GetOStream(
Runtime1) <<
"P Fine grid : " << myGeometry->gFineNodesPerDir[0] <<
" -- "
296 << myGeometry->gFineNodesPerDir[1] <<
" -- "
297 << myGeometry->gFineNodesPerDir[2] << std::endl;
298 GetOStream(
Runtime1) <<
"P Coarse grid : " << myGeometry->gCoarseNodesPerDir[0] <<
" -- "
299 << myGeometry->gCoarseNodesPerDir[1] <<
" -- "
300 << myGeometry->gCoarseNodesPerDir[2] << std::endl;
301 GetOStream(
Runtime1) <<
"P nnz estimate: " << gnnzP << std::endl;
303 MakeGeneralGeometricP(myGeometry, fineCoords, lnnzP, blkSize, stridedDomainMapP,
304 A, P, coarseCoords, ghostedCoarseNodes, lCoarseNodesGIDs,
308 if (A->IsView(
"stridedMaps") ==
true) {
309 P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedDomainMapP);
311 P->CreateView(
"stridedMaps", P->getRangeMap(), stridedDomainMapP);
315 Set(coarseLevel,
"P", P);
316 Set(coarseLevel,
"coarseCoordinates", coarseCoords);
317 Set<Array<GO> >(coarseLevel,
"gCoarseNodesPerDim", myGeometry->gCoarseNodesPerDir);
318 Set<Array<LO> >(coarseLevel,
"lCoarseNodesPerDim", myGeometry->lCoarseNodesPerDir);
322 RCP<MultiVector> coarseNullspace = MultiVectorFactory::Build(P->getDomainMap(),
323 fineNullspace->getNumVectors());
326 Set(coarseLevel,
"Nullspace", coarseNullspace);
330 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
341 int numRanks = fineCoordsMap->getComm()->getSize();
342 int myRank = fineCoordsMap->getComm()->getRank();
344 myGeo->myBlock = myGeo->meshData[myRank][2];
345 myGeo->startIndices[0] = myGeo->meshData[myRank][3];
346 myGeo->startIndices[1] = myGeo->meshData[myRank][5];
347 myGeo->startIndices[2] = myGeo->meshData[myRank][7];
348 myGeo->startIndices[3] = myGeo->meshData[myRank][4];
349 myGeo->startIndices[4] = myGeo->meshData[myRank][6];
350 myGeo->startIndices[5] = myGeo->meshData[myRank][8];
351 std::sort(myGeo->meshData.begin(), myGeo->meshData.end(),
352 [](
const std::vector<GO>& a,
const std::vector<GO>& b)->
bool {
356 }
else if(a[2] == b[2]) {
359 }
else if(a[7] == b[7]) {
362 }
else if(a[5] == b[5]) {
363 if(a[3] < b[3]) {
return true;}
370 myGeo->numBlocks = myGeo->meshData[numRanks - 1][2] + 1;
372 auto myBlockStart = std::lower_bound(myGeo->meshData.begin(), myGeo->meshData.end(),
374 [](
const std::vector<GO>& vec,
const GO val)->
bool{
375 return (vec[2] < val) ?
true :
false;
377 auto myBlockEnd = std::upper_bound(myGeo->meshData.begin(), myGeo->meshData.end(),
379 [](
const GO val,
const std::vector<GO>& vec)->
bool{
380 return (val < vec[2]) ?
true :
false;
385 auto myKEnd = std::upper_bound(myBlockStart, myBlockEnd, (*myBlockStart)[3],
386 [](
const GO val,
const std::vector<GO>& vec)->
bool{
387 return (val < vec[7]) ?
true :
false;
389 auto myJEnd = std::upper_bound(myBlockStart, myKEnd, (*myBlockStart)[3],
390 [](
const GO val,
const std::vector<GO>& vec)->
bool{
391 return (val < vec[5]) ?
true :
false;
393 LO pi = std::distance(myBlockStart, myJEnd);
394 LO pj = std::distance(myBlockStart, myKEnd) / pi;
395 LO pk = std::distance(myBlockStart, myBlockEnd) / (pj*pi);
398 LO myRankIndex = std::distance(myGeo->meshData.begin(),
399 std::find_if(myBlockStart, myBlockEnd,
400 [myRank](
const std::vector<GO>& vec)->
bool{
401 return (vec[0] == myRank) ?
true :
false;
405 for(
int dim = 0; dim < 3; ++dim) {
406 if(dim < myGeo->numDimensions) {
407 myGeo->offsets[dim]= Teuchos::as<LO>(myGeo->startIndices[dim]) % myGeo->coarseRate[dim];
408 myGeo->offsets[dim + 3]= Teuchos::as<LO>(myGeo->startIndices[dim]) % myGeo->coarseRate[dim];
414 for(
int dim = 0; dim < 3; ++dim) {
415 if(dim < myGeo->numDimensions && (myGeo->startIndices[dim] % myGeo->coarseRate[dim] != 0 ||
416 myGeo->startIndices[dim] == myGeo->gFineNodesPerDir[dim]-1)) {
417 myGeo->ghostInterface[2*dim] =
true;
419 if(dim < myGeo->numDimensions
420 && myGeo->startIndices[dim + 3] != myGeo->gFineNodesPerDir[dim] - 1
421 && (myGeo->lFineNodesPerDir[dim] == 1 ||
422 myGeo->startIndices[dim + 3] % myGeo->coarseRate[dim] != 0)) {
423 myGeo->ghostInterface[2*dim+1] =
true;
439 for(
int i = 0; i < 3; ++i) {
440 if(i < myGeo->numDimensions) {
443 myGeo->gCoarseNodesPerDir[i] = (myGeo->gFineNodesPerDir[i] - 1) / myGeo->coarseRate[i];
444 myGeo->endRate[i] = Teuchos::as<LO>((myGeo->gFineNodesPerDir[i] - 1) %myGeo->coarseRate[i]);
445 if(myGeo->endRate[i] == 0) {
446 myGeo->endRate[i] = myGeo->coarseRate[i];
447 ++myGeo->gCoarseNodesPerDir[i];
449 myGeo->gCoarseNodesPerDir[i] += 2;
452 myGeo->endRate[i] = 1;
453 myGeo->gCoarseNodesPerDir[i] = 1;
457 myGeo->gNumCoarseNodes = myGeo->gCoarseNodesPerDir[0]*myGeo->gCoarseNodesPerDir[1]
458 *myGeo->gCoarseNodesPerDir[2];
460 for(LO i = 0; i < 3; ++i) {
461 if(i < myGeo->numDimensions) {
465 if( (myGeo->startIndices[i] + myGeo->lFineNodesPerDir[i]) == myGeo->gFineNodesPerDir[i] ) {
466 myGeo->lCoarseNodesPerDir[i] = (myGeo->lFineNodesPerDir[i] - myGeo->endRate[i]
467 + myGeo->offsets[i] - 1) / myGeo->coarseRate[i] + 1;
468 if(myGeo->offsets[i] == 0) {++myGeo->lCoarseNodesPerDir[i];}
470 myGeo->lCoarseNodesPerDir[i] = (myGeo->lFineNodesPerDir[i] + myGeo->offsets[i] - 1)
471 / myGeo->coarseRate[i];
472 if(myGeo->offsets[i] == 0) {++myGeo->lCoarseNodesPerDir[i];}
475 myGeo->lCoarseNodesPerDir[i] = 1;
479 if(myGeo->lFineNodesPerDir[i] < 1) {myGeo->lCoarseNodesPerDir[i] = 0;}
485 myGeo->lNumCoarseNodes = myGeo->lCoarseNodesPerDir[0]*myGeo->lCoarseNodesPerDir[1]
486 *myGeo->lCoarseNodesPerDir[2];
489 for(
int dim = 0; dim < 3; ++dim) {
493 if(myGeo->startIndices[dim] == myGeo->gFineNodesPerDir[dim] - 1 &&
494 myGeo->startIndices[dim] % myGeo->coarseRate[dim] == 0) {
495 myGeo->startGhostedCoarseNode[dim] = myGeo->startIndices[dim] / myGeo->coarseRate[dim] - 1;
497 myGeo->startGhostedCoarseNode[dim] = myGeo->startIndices[dim] / myGeo->coarseRate[dim];
499 myGeo->ghostedCoarseNodesPerDir[dim] = myGeo->lCoarseNodesPerDir[dim];
501 if(myGeo->ghostInterface[2*dim]) {myGeo->ghostedCoarseNodesPerDir[dim] += 1;}
503 if(myGeo->ghostInterface[2*dim + 1]) {myGeo->ghostedCoarseNodesPerDir[dim] += 1;}
505 myGeo->lNumGhostedNodes = myGeo->ghostedCoarseNodesPerDir[2]*myGeo->ghostedCoarseNodesPerDir[1]
506 *myGeo->ghostedCoarseNodesPerDir[0];
507 myGeo->lNumGhostNodes = myGeo->lNumGhostedNodes - myGeo->lNumCoarseNodes;
508 ghostedCoarseNodes->PIDs.resize(myGeo->lNumGhostedNodes);
509 ghostedCoarseNodes->LIDs.resize(myGeo->lNumGhostedNodes);
510 ghostedCoarseNodes->GIDs.resize(myGeo->lNumGhostedNodes);
511 ghostedCoarseNodes->coarseGIDs.resize(myGeo->lNumGhostedNodes);
512 ghostedCoarseNodes->colInds.resize(myGeo->lNumGhostedNodes);
513 lCoarseNodesGIDs[0].resize(myGeo->lNumCoarseNodes);
514 lCoarseNodesGIDs[1].resize(myGeo->lNumCoarseNodes);
521 Array<LO> coarseNodeCoarseIndices(3), coarseNodeFineIndices(3);
522 LO currentIndex = -1, countCoarseNodes = 0;
523 for(
int k = 0; k < myGeo->ghostedCoarseNodesPerDir[2]; ++k) {
524 for(
int j = 0; j < myGeo->ghostedCoarseNodesPerDir[1]; ++j) {
525 for(
int i = 0; i < myGeo->ghostedCoarseNodesPerDir[0]; ++i) {
526 currentIndex = k*myGeo->ghostedCoarseNodesPerDir[1]*myGeo->ghostedCoarseNodesPerDir[0]
527 + j*myGeo->ghostedCoarseNodesPerDir[0] + i;
528 coarseNodeCoarseIndices[0] = myGeo->startGhostedCoarseNode[0] + i;
529 coarseNodeFineIndices[0] = coarseNodeCoarseIndices[0]*myGeo->coarseRate[0];
530 if(coarseNodeFineIndices[0] > myGeo->gFineNodesPerDir[0] - 1) {
531 coarseNodeFineIndices[0] = myGeo->gFineNodesPerDir[0] - 1;
533 coarseNodeCoarseIndices[1] = myGeo->startGhostedCoarseNode[1] + j;
534 coarseNodeFineIndices[1] = coarseNodeCoarseIndices[1]*myGeo->coarseRate[1];
535 if(coarseNodeFineIndices[1] > myGeo->gFineNodesPerDir[1] - 1) {
536 coarseNodeFineIndices[1] = myGeo->gFineNodesPerDir[1] - 1;
538 coarseNodeCoarseIndices[2] = myGeo->startGhostedCoarseNode[2] + k;
539 coarseNodeFineIndices[2] = coarseNodeCoarseIndices[2]*myGeo->coarseRate[2];
540 if(coarseNodeFineIndices[2] > myGeo->gFineNodesPerDir[2] - 1) {
541 coarseNodeFineIndices[2] = myGeo->gFineNodesPerDir[2] - 1;
543 GO myGID = -1, myCoarseGID = -1;
544 LO myLID = -1, myPID = -1;
545 GetGIDLocalLexicographic(i, j, k, coarseNodeFineIndices, myGeo, myRankIndex, pi, pj, pk,
546 myBlockStart, myBlockEnd, myGID, myPID, myLID);
547 myCoarseGID = coarseNodeCoarseIndices[0]
548 + coarseNodeCoarseIndices[1]*myGeo->gCoarseNodesPerDir[0]
549 + coarseNodeCoarseIndices[2]*myGeo->gCoarseNodesPerDir[1]*myGeo->gCoarseNodesPerDir[0];
550 ghostedCoarseNodes->PIDs[currentIndex] = myPID;
551 ghostedCoarseNodes->LIDs[currentIndex] = myLID;
552 ghostedCoarseNodes->GIDs[currentIndex] = myGID;
553 ghostedCoarseNodes->coarseGIDs[currentIndex] = myCoarseGID;
555 lCoarseNodesGIDs[0][countCoarseNodes] = myCoarseGID;
556 lCoarseNodesGIDs[1][countCoarseNodes] = myGID;
565 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
578 myGeo->startIndices[2] = fineCoordsMap->getMinGlobalIndex()
579 / (myGeo->gFineNodesPerDir[1]*myGeo->gFineNodesPerDir[0]);
580 tmp = fineCoordsMap->getMinGlobalIndex()
581 % (myGeo->gFineNodesPerDir[1]*myGeo->gFineNodesPerDir[0]);
582 myGeo->startIndices[1] = tmp / myGeo->gFineNodesPerDir[0];
583 myGeo->startIndices[0] = tmp % myGeo->gFineNodesPerDir[0];
585 for(
int dim = 0; dim < 3; ++dim) {
586 myGeo->startIndices[dim + 3] = myGeo->startIndices[dim] + myGeo->lFineNodesPerDir[dim] - 1;
589 for(
int dim = 0; dim < 3; ++dim) {
590 if(dim < myGeo->numDimensions) {
591 myGeo->offsets[dim]= Teuchos::as<LO>(myGeo->startIndices[dim]) % myGeo->coarseRate[dim];
592 myGeo->offsets[dim + 3]= Teuchos::as<LO>(myGeo->startIndices[dim]) % myGeo->coarseRate[dim];
598 for(
int dim = 0; dim < 3; ++dim) {
599 if(dim < myGeo->numDimensions && (myGeo->startIndices[dim] % myGeo->coarseRate[dim] != 0 ||
600 myGeo->startIndices[dim] == myGeo->gFineNodesPerDir[dim]-1)) {
601 myGeo->ghostInterface[2*dim] =
true;
603 if(dim < myGeo->numDimensions
604 && myGeo->startIndices[dim + 3] != myGeo->gFineNodesPerDir[dim] - 1
605 && (myGeo->lFineNodesPerDir[dim] == 1 ||
606 myGeo->startIndices[dim + 3] % myGeo->coarseRate[dim] != 0)) {
607 myGeo->ghostInterface[2*dim + 1] =
true;
623 for(
int i = 0; i < 3; ++i) {
624 if(i < myGeo->numDimensions) {
627 myGeo->gCoarseNodesPerDir[i] = (myGeo->gFineNodesPerDir[i] - 1) / myGeo->coarseRate[i];
628 myGeo->endRate[i] = Teuchos::as<LO>((myGeo->gFineNodesPerDir[i] - 1) %myGeo->coarseRate[i]);
629 if(myGeo->endRate[i] == 0) {
630 myGeo->endRate[i] = myGeo->coarseRate[i];
631 ++myGeo->gCoarseNodesPerDir[i];
633 myGeo->gCoarseNodesPerDir[i] += 2;
636 myGeo->endRate[i] = 1;
637 myGeo->gCoarseNodesPerDir[i] = 1;
641 myGeo->gNumCoarseNodes = myGeo->gCoarseNodesPerDir[0]*myGeo->gCoarseNodesPerDir[1]
642 *myGeo->gCoarseNodesPerDir[2];
644 for(LO i = 0; i < 3; ++i) {
645 if(i < myGeo->numDimensions) {
649 if( (myGeo->startIndices[i] + myGeo->lFineNodesPerDir[i]) == myGeo->gFineNodesPerDir[i] ) {
650 myGeo->lCoarseNodesPerDir[i] = (myGeo->lFineNodesPerDir[i] - myGeo->endRate[i]
651 + myGeo->offsets[i] - 1) / myGeo->coarseRate[i] + 1;
652 if(myGeo->offsets[i] == 0) {++myGeo->lCoarseNodesPerDir[i];}
654 myGeo->lCoarseNodesPerDir[i] = (myGeo->lFineNodesPerDir[i] + myGeo->offsets[i] - 1)
655 / myGeo->coarseRate[i];
656 if(myGeo->offsets[i] == 0) {++myGeo->lCoarseNodesPerDir[i];}
659 myGeo->lCoarseNodesPerDir[i] = 1;
663 if(myGeo->lFineNodesPerDir[i] < 1) {myGeo->lCoarseNodesPerDir[i] = 0;}
669 myGeo->lNumCoarseNodes = myGeo->lCoarseNodesPerDir[0]*myGeo->lCoarseNodesPerDir[1]
670 *myGeo->lCoarseNodesPerDir[2];
673 bool ghostedDir[6] = {
false};
674 for(
int dim = 0; dim < 3; ++dim) {
678 if(myGeo->startIndices[dim] == myGeo->gFineNodesPerDir[dim] - 1 &&
679 myGeo->startIndices[dim] % myGeo->coarseRate[dim] == 0) {
680 myGeo->startGhostedCoarseNode[dim] = myGeo->startIndices[dim] / myGeo->coarseRate[dim] - 1;
682 myGeo->startGhostedCoarseNode[dim] = myGeo->startIndices[dim] / myGeo->coarseRate[dim];
684 myGeo->ghostedCoarseNodesPerDir[dim] = myGeo->lCoarseNodesPerDir[dim];
686 if(myGeo->ghostInterface[2*dim]) {
687 myGeo->ghostedCoarseNodesPerDir[dim] += 1;
688 ghostedDir[2*dim] =
true;
691 if(myGeo->ghostInterface[2*dim + 1]) {
692 myGeo->ghostedCoarseNodesPerDir[dim] += 1;
693 ghostedDir[2*dim + 1] =
true;
696 myGeo->lNumGhostedNodes = myGeo->ghostedCoarseNodesPerDir[2]*myGeo->ghostedCoarseNodesPerDir[1]
697 *myGeo->ghostedCoarseNodesPerDir[0];
698 myGeo->lNumGhostNodes = myGeo->lNumGhostedNodes - myGeo->lNumCoarseNodes;
699 ghostedCoarseNodes->PIDs.resize(myGeo->lNumGhostedNodes);
700 ghostedCoarseNodes->LIDs.resize(myGeo->lNumGhostedNodes);
701 ghostedCoarseNodes->GIDs.resize(myGeo->lNumGhostedNodes);
702 ghostedCoarseNodes->coarseGIDs.resize(myGeo->lNumGhostedNodes);
703 ghostedCoarseNodes->colInds.resize(myGeo->lNumGhostedNodes);
704 lCoarseNodesGIDs[0].resize(myGeo->lNumCoarseNodes);
705 lCoarseNodesGIDs[1].resize(myGeo->lNumCoarseNodes);
712 Array<LO> coarseNodeCoarseIndices(3), coarseNodeFineIndices(3), ijk(3);
713 LO currentIndex = -1, countCoarseNodes = 0;
714 for(ijk[2] = 0; ijk[2] < myGeo->ghostedCoarseNodesPerDir[2]; ++ijk[2]) {
715 for(ijk[1] = 0; ijk[1] < myGeo->ghostedCoarseNodesPerDir[1]; ++ijk[1]) {
716 for(ijk[0] = 0; ijk[0] < myGeo->ghostedCoarseNodesPerDir[0]; ++ijk[0]) {
717 currentIndex = ijk[2]*myGeo->ghostedCoarseNodesPerDir[1]*myGeo->ghostedCoarseNodesPerDir[0]
718 + ijk[1]*myGeo->ghostedCoarseNodesPerDir[0] + ijk[0];
719 coarseNodeCoarseIndices[0] = myGeo->startGhostedCoarseNode[0] + ijk[0];
720 coarseNodeFineIndices[0] = coarseNodeCoarseIndices[0]*myGeo->coarseRate[0];
721 if(coarseNodeFineIndices[0] > myGeo->gFineNodesPerDir[0] - 1) {
722 coarseNodeFineIndices[0] = myGeo->gFineNodesPerDir[0] - 1;
724 coarseNodeCoarseIndices[1] = myGeo->startGhostedCoarseNode[1] + ijk[1];
725 coarseNodeFineIndices[1] = coarseNodeCoarseIndices[1]*myGeo->coarseRate[1];
726 if(coarseNodeFineIndices[1] > myGeo->gFineNodesPerDir[1] - 1) {
727 coarseNodeFineIndices[1] = myGeo->gFineNodesPerDir[1] - 1;
729 coarseNodeCoarseIndices[2] = myGeo->startGhostedCoarseNode[2] + ijk[2];
730 coarseNodeFineIndices[2] = coarseNodeCoarseIndices[2]*myGeo->coarseRate[2];
731 if(coarseNodeFineIndices[2] > myGeo->gFineNodesPerDir[2] - 1) {
732 coarseNodeFineIndices[2] = myGeo->gFineNodesPerDir[2] - 1;
734 GO myGID = 0, myCoarseGID = -1;
736 factor[2] = myGeo->gNumFineNodes10;
737 factor[1] = myGeo->gFineNodesPerDir[0];
739 for(
int dim = 0; dim < 3; ++dim) {
740 if(dim < myGeo->numDimensions) {
741 if(myGeo->startIndices[dim] - myGeo->offsets[dim] + ijk[dim]*myGeo->coarseRate[dim]
742 < myGeo->gFineNodesPerDir[dim] - 1) {
743 myGID += (myGeo->startIndices[dim] - myGeo->offsets[dim]
744 + ijk[dim]*myGeo->coarseRate[dim])*factor[dim];
746 myGID += (myGeo->startIndices[dim] - myGeo->offsets[dim]
747 + (ijk[dim] - 1)*myGeo->coarseRate[dim] + myGeo->endRate[dim])*factor[dim];
751 myCoarseGID = coarseNodeCoarseIndices[0]
752 + coarseNodeCoarseIndices[1]*myGeo->gCoarseNodesPerDir[0]
753 + coarseNodeCoarseIndices[2]*myGeo->gCoarseNodesPerDir[1]*myGeo->gCoarseNodesPerDir[0];
754 ghostedCoarseNodes->GIDs[currentIndex] = myGID;
755 ghostedCoarseNodes->coarseGIDs[currentIndex] = myCoarseGID;
756 if((!ghostedDir[0] || ijk[0] != 0)
757 && (!ghostedDir[2] || ijk[1] != 0)
758 && (!ghostedDir[4] || ijk[2] != 0)
759 && (!ghostedDir[1] || ijk[0] != myGeo->ghostedCoarseNodesPerDir[0] - 1)
760 && (!ghostedDir[3] || ijk[1] != myGeo->ghostedCoarseNodesPerDir[1] - 1)
761 && (!ghostedDir[5] || ijk[2] != myGeo->ghostedCoarseNodesPerDir[2] - 1)){
762 lCoarseNodesGIDs[0][countCoarseNodes] = myCoarseGID;
763 lCoarseNodesGIDs[1][countCoarseNodes] = myGID;
769 Array<int> ghostsPIDs(myGeo->lNumGhostedNodes);
770 Array<LO> ghostsLIDs(myGeo->lNumGhostedNodes);
771 fineCoordsMap->getRemoteIndexList(ghostedCoarseNodes->GIDs(),
772 ghostedCoarseNodes->PIDs(),
773 ghostedCoarseNodes->LIDs());
776 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
780 const LO nnzP,
const LO dofsPerNode,
784 int interpolationOrder)
const {
804 using xdMV = Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::coordinateType,LO,GO,NO>;
807 LO myRank = Amat->getRowMap()->getComm()->getRank();
808 GO numGloCols = dofsPerNode*myGeo->gNumCoarseNodes;
828 std::vector<NodeID> colMapOrdering(myGeo->lNumGhostedNodes);
829 for(LO ind = 0; ind < myGeo->lNumGhostedNodes; ++ind) {
830 colMapOrdering[ind].GID = ghostedCoarseNodes->GIDs[ind];
831 if(ghostedCoarseNodes->PIDs[ind] == myRank) {
832 colMapOrdering[ind].PID = -1;
834 colMapOrdering[ind].PID = ghostedCoarseNodes->PIDs[ind];
836 colMapOrdering[ind].LID = ghostedCoarseNodes->LIDs[ind];
837 colMapOrdering[ind].lexiInd = ind;
839 std::sort(colMapOrdering.begin(), colMapOrdering.end(),
841 return ( (a.
PID < b.PID) || ((a.
PID == b.PID) && (a.
GID < b.GID)) );
844 Array<GO> colGIDs(dofsPerNode*myGeo->lNumGhostedNodes);
845 for(LO ind = 0; ind < myGeo->lNumGhostedNodes; ++ind) {
847 ghostedCoarseNodes->colInds[colMapOrdering[ind].lexiInd] = ind;
848 for(LO dof = 0; dof < dofsPerNode; ++dof) {
849 colGIDs[dofsPerNode*ind + dof] = dofsPerNode*colMapOrdering[ind].GID + dof;
852 domainMapP = Xpetra::MapFactory<LO,GO,NO>::Build(rowMapP->lib(),
854 colGIDs.view(0,dofsPerNode*
855 myGeo->lNumCoarseNodes),
856 rowMapP->getIndexBase(),
858 colMapP = Xpetra::MapFactory<LO,GO,NO>::Build(rowMapP->lib(),
860 colGIDs.view(0, colGIDs.size()),
861 rowMapP->getIndexBase(),
865 std::vector<size_t> strideInfo(1);
866 strideInfo[0] = dofsPerNode;
867 stridedDomainMapP = Xpetra::StridedMapFactory<LO,GO,NO>::Build(domainMapP, strideInfo);
872 RCP<const Map> coarseCoordsMap = MapFactory::Build (fineCoords->getMap()->lib(),
873 myGeo->gNumCoarseNodes,
874 coarseNodesGIDs[0](),
875 fineCoords->getMap()->getIndexBase(),
876 fineCoords->getMap()->getComm());
877 RCP<const Map> coarseCoordsFineMap = MapFactory::Build (fineCoords->getMap()->lib(),
878 myGeo->gNumCoarseNodes,
879 coarseNodesGIDs[1](),
880 fineCoords->getMap()->getIndexBase(),
881 fineCoords->getMap()->getComm());
884 coarseCoordsFineMap);
885 coarseCoords = Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::coordinateType,LO,GO,NO>::Build(coarseCoordsFineMap,
886 myGeo->numDimensions);
887 coarseCoords->doImport(*fineCoords, *coarseImporter, Xpetra::INSERT);
888 coarseCoords->replaceMap(coarseCoordsMap);
891 RCP<const Map> ghostMap = Xpetra::MapFactory<LO,GO,NO>::Build(fineCoords->getMap()->lib(),
893 ghostedCoarseNodes->GIDs(),
894 fineCoords->getMap()->getIndexBase(),
895 fineCoords->getMap()->getComm());
896 RCP<const Import> ghostImporter = ImportFactory::Build(fineCoords->getMap(), ghostMap);
897 RCP<xdMV> ghostCoords = Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::coordinateType,LO,GO,NO>::Build(ghostMap,
898 myGeo->numDimensions);
899 ghostCoords->doImport(*fineCoords, *ghostImporter, Xpetra::INSERT);
901 P =
rcp(
new CrsMatrixWrap(rowMapP, colMapP, 0));
902 RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
908 PCrs->allocateAllValues(nnzP, iaP, jaP, valP);
918 for(
int dim = 0; dim < 3; ++dim) {
919 if(dim < myGeo->numDimensions) {
920 ghostedCoords[dim] = ghostCoords->getDataNonConst(dim);
922 ghostedCoords[dim] = tmp;
930 = Xpetra::VectorFactory<typename Teuchos::ScalarTraits<Scalar>::coordinateType,LO,GO,NO>::Build(fineCoords->getMap(),
true);
932 for(
int dim = 0; dim < 3; ++dim) {
933 if(dim < myGeo->numDimensions) {
934 lFineCoords[dim] = fineCoords->getDataNonConst(dim);
936 lFineCoords[dim] = zeros->getDataNonConst(0);
941 for(
int currentIndex = 0; currentIndex < myGeo->lNumFineNodes; ++currentIndex) {
942 Array<GO> ghostedIndices(3), firstInterpolationIndices(3);
943 Array<LO> interpolationPIDs(8), interpolationLIDs(8), interpolationGIDs(8);
945 interpolationCoords[0].
resize(3);
946 GO firstInterpolationNodeIndex;
948 for(
int dim = 0; dim < 3; ++dim) {
949 interpolationCoords[0][dim] = lFineCoords[dim][currentIndex];
955 ghostedIndices[2] = currentIndex / (myGeo->lFineNodesPerDir[1]*myGeo->lFineNodesPerDir[0]);
956 LO tmp = currentIndex % (myGeo->lFineNodesPerDir[1]*myGeo->lFineNodesPerDir[0]);
957 ghostedIndices[1] = tmp / myGeo->lFineNodesPerDir[0];
958 ghostedIndices[0] = tmp % myGeo->lFineNodesPerDir[0];
959 for(
int dim = 0; dim < 3; ++dim) {
960 ghostedIndices[dim] += myGeo->offsets[dim];
969 for(
int dim = 0; dim < 3; ++dim) {
970 firstInterpolationIndices[dim] = ghostedIndices[dim] / myGeo->coarseRate[dim];
973 if(firstInterpolationIndices[dim] == myGeo->ghostedCoarseNodesPerDir[dim] - 1
974 && myGeo->ghostedCoarseNodesPerDir[dim] > 1) {
975 firstInterpolationIndices[dim] -= 1;
978 firstInterpolationNodeIndex =
979 firstInterpolationIndices[2]*myGeo->ghostedCoarseNodesPerDir[1]*myGeo->ghostedCoarseNodesPerDir[0]
980 + firstInterpolationIndices[1]*myGeo->ghostedCoarseNodesPerDir[0]
981 + firstInterpolationIndices[0];
987 for(
int k = 0; k < 2; ++k) {
988 for(
int j = 0; j < 2; ++j) {
989 for(
int i = 0; i < 2; ++i) {
991 interpolationLIDs[ind] = firstInterpolationNodeIndex
992 + k*myGeo->ghostedCoarseNodesPerDir[1]*myGeo->ghostedCoarseNodesPerDir[0]
993 + j*myGeo->ghostedCoarseNodesPerDir[0] + i;
994 if(ghostedCoarseNodes->PIDs[interpolationLIDs[ind]] == rowMapP->getComm()->getRank()){
995 interpolationPIDs[ind] = -1;
997 interpolationPIDs[ind] = ghostedCoarseNodes->PIDs[interpolationLIDs[ind]];
999 interpolationGIDs[ind] = ghostedCoarseNodes->coarseGIDs[interpolationLIDs[ind]];
1001 interpolationCoords[ind + 1].
resize(3);
1002 for(
int dim = 0; dim < 3; ++dim) {
1003 interpolationCoords[ind + 1][dim]
1004 = ghostedCoords[dim][interpolationLIDs[ind]];
1013 std::vector<double> stencil(8);
1014 Array<GO> firstCoarseNodeFineIndices(3);
1016 for(
int dim = 0; dim < 3; ++dim) {
1017 firstCoarseNodeFineIndices[dim] = firstInterpolationIndices[dim]*myGeo->coarseRate[dim];
1018 if((myGeo->startIndices[dim + 3] == myGeo->gFineNodesPerDir[dim] - 1)
1019 && (ghostedIndices[dim] >=
1020 (myGeo->ghostedCoarseNodesPerDir[dim] - 2)*myGeo->coarseRate[dim])) {
1021 rate[dim] = myGeo->endRate[dim];
1023 rate[dim] = myGeo->coarseRate[dim];
1030 for(
int dim = 0; dim < 3; ++dim) {
1031 if (myGeo->startIndices[dim] == myGeo->gFineNodesPerDir[dim] - 1) {
1032 trueGhostedIndices[dim] = ghostedIndices[dim] + rate[dim];
1034 trueGhostedIndices[dim] = ghostedIndices[dim];
1037 ComputeStencil(myGeo->numDimensions, trueGhostedIndices, firstCoarseNodeFineIndices, rate,
1038 interpolationCoords, interpolationOrder, stencil);
1043 Array<LO> nzIndStencil(8), permutation(8);
1044 for(LO k = 0; k < 8; ++k) {permutation[k] = k;}
1045 if(interpolationOrder == 0) {
1047 for(LO k = 0; k < 8; ++k) {
1048 nzIndStencil[k] =
static_cast<LO
>(stencil[0]);
1051 stencil[nzIndStencil[0]] = 1.0;
1052 }
else if(interpolationOrder == 1) {
1053 Array<GO> currentNodeGlobalFineIndices(3);
1054 for(
int dim = 0; dim < 3; ++dim) {
1055 currentNodeGlobalFineIndices[dim] = ghostedIndices[dim] - myGeo->offsets[dim]
1056 + myGeo->startIndices[dim];
1058 if( ((ghostedIndices[0] % myGeo->coarseRate[0] == 0)
1059 || currentNodeGlobalFineIndices[0] == myGeo->gFineNodesPerDir[0] - 1)
1060 && ((ghostedIndices[1] % myGeo->coarseRate[1] == 0)
1061 || currentNodeGlobalFineIndices[1] == myGeo->gFineNodesPerDir[1] - 1)
1062 && ((ghostedIndices[2] % myGeo->coarseRate[2] == 0)
1063 || currentNodeGlobalFineIndices[2] == myGeo->gFineNodesPerDir[2] - 1) ) {
1064 if((currentNodeGlobalFineIndices[0] == myGeo->gFineNodesPerDir[0] - 1) ||
1065 (ghostedIndices[0] / myGeo->coarseRate[0] == myGeo->ghostedCoarseNodesPerDir[0] - 1)) {
1066 nzIndStencil[0] += 1;
1068 if(((currentNodeGlobalFineIndices[1] == myGeo->gFineNodesPerDir[1] - 1) ||
1069 (ghostedIndices[1] / myGeo->coarseRate[1] == myGeo->ghostedCoarseNodesPerDir[1] - 1))
1070 && (myGeo->numDimensions > 1)){
1071 nzIndStencil[0] += 2;
1073 if(((currentNodeGlobalFineIndices[2] == myGeo->gFineNodesPerDir[2] - 1) ||
1074 (ghostedIndices[2] / myGeo->coarseRate[2] == myGeo->ghostedCoarseNodesPerDir[2] - 1))
1075 && myGeo->numDimensions > 2) {
1076 nzIndStencil[0] += 4;
1079 for(LO k = 0; k < 8; ++k) {
1080 nzIndStencil[k] = nzIndStencil[0];
1084 for(LO k = 0; k < 8; ++k) {
1085 nzIndStencil[k] = k;
1098 sh_sort2(interpolationPIDs.begin(),interpolationPIDs.end(),
1099 permutation.
begin(), permutation.
end());
1102 for(LO j = 0; j < dofsPerNode; ++j) {
1103 ia[currentIndex*dofsPerNode + j + 1] = ia[currentIndex*dofsPerNode + j] + nStencil;
1104 for(LO k = 0; k < nStencil; ++k) {
1105 colInd = ghostedCoarseNodes->colInds[interpolationLIDs[nzIndStencil[permutation[k]]]];
1106 ja[ia[currentIndex*dofsPerNode + j] + k] = colInd*dofsPerNode + j;
1107 val[ia[currentIndex*dofsPerNode + j] + k] = stencil[nzIndStencil[permutation[k]]];
1110 tStencil += nStencil;
1114 if (rowMapP->lib() == Xpetra::UseTpetra) {
1123 PCrs->setAllValues(iaP, jaP, valP);
1124 PCrs->expertStaticFillComplete(domainMapP,rowMapP);
1602 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1604 const LO numDimensions,
const Array<GO> currentNodeIndices,
1605 const Array<GO> coarseNodeIndices,
const LO rate[3],
1607 std::vector<double>& stencil)
const {
1611 "The interpolation order can be set to 0 or 1 only.");
1613 if(interpolationOrder == 0) {
1614 ComputeConstantInterpolationStencil(numDimensions, currentNodeIndices, coarseNodeIndices,
1616 }
else if(interpolationOrder == 1) {
1617 ComputeLinearInterpolationStencil(numDimensions, coord, stencil);
1622 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1625 const Array<GO> coarseNodeIndices,
const LO rate[3],
1626 std::vector<double>& stencil)
const {
1629 if(numDimensions > 2) {
1630 if((currentNodeIndices[2] - coarseNodeIndices[2]) > (rate[2] / 2)) {
1634 if(numDimensions > 1) {
1635 if((currentNodeIndices[1] - coarseNodeIndices[1]) > (rate[1] / 2)) {
1639 if((currentNodeIndices[0] - coarseNodeIndices[0]) > (rate[0] / 2)) {
1642 stencil[0] = coarseNode;
1646 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1649 std::vector<double>& stencil)
1672 LO numTerms = std::pow(2,numDimensions),
iter = 0, max_iter = 5;
1673 double functions[4][8], norm_ref = 1, norm2 = 1, tol = 1e-5;
1674 paramCoords.
size(numDimensions);
1676 while( (
iter < max_iter) && (norm2 > tol*norm_ref) ) {
1679 solutionDirection.
size(numDimensions);
1680 residual.
size(numDimensions);
1684 GetInterpolationFunctions(numDimensions, paramCoords, functions);
1685 for(LO i = 0; i < numDimensions; ++i) {
1686 residual(i) = coord[0][i];
1687 for(LO k = 0; k < numTerms; ++k) {
1688 residual(i) -= functions[0][k]*coord[k+1][i];
1691 norm_ref += residual(i)*residual(i);
1692 if(i == numDimensions - 1) {
1693 norm_ref = std::sqrt(norm_ref);
1697 for(LO j = 0; j < numDimensions; ++j) {
1698 for(LO k = 0; k < numTerms; ++k) {
1699 Jacobian(i,j) += functions[j+1][k]*coord[k+1][i];
1711 for(LO i = 0; i < numDimensions; ++i) {
1712 paramCoords(i) = paramCoords(i) + solutionDirection(i);
1716 GetInterpolationFunctions(numDimensions, paramCoords, functions);
1717 for(LO i = 0; i < numDimensions; ++i) {
1718 double tmp = coord[0][i];
1719 for(LO k = 0; k < numTerms; ++k) {
1720 tmp -= functions[0][k]*coord[k+1][i];
1725 norm2 = std::sqrt(norm2);
1729 for(LO i = 0; i < 8; ++i) {
1730 stencil[i] = functions[0][i];
1735 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1739 double functions[4][8])
const {
1740 double xi = 0.0, eta = 0.0, zeta = 0.0, denominator = 0.0;
1741 if(numDimensions == 1) {
1744 }
else if(numDimensions == 2) {
1746 eta = parameters[1];
1748 }
else if(numDimensions == 3) {
1750 eta = parameters[1];
1751 zeta = parameters[2];
1755 functions[0][0] = (1.0 - xi)*(1.0 - eta)*(1.0 - zeta) / denominator;
1756 functions[0][1] = (1.0 + xi)*(1.0 - eta)*(1.0 - zeta) / denominator;
1757 functions[0][2] = (1.0 - xi)*(1.0 + eta)*(1.0 - zeta) / denominator;
1758 functions[0][3] = (1.0 + xi)*(1.0 + eta)*(1.0 - zeta) / denominator;
1759 functions[0][4] = (1.0 - xi)*(1.0 - eta)*(1.0 + zeta) / denominator;
1760 functions[0][5] = (1.0 + xi)*(1.0 - eta)*(1.0 + zeta) / denominator;
1761 functions[0][6] = (1.0 - xi)*(1.0 + eta)*(1.0 + zeta) / denominator;
1762 functions[0][7] = (1.0 + xi)*(1.0 + eta)*(1.0 + zeta) / denominator;
1764 functions[1][0] = -(1.0 - eta)*(1.0 - zeta) / denominator;
1765 functions[1][1] = (1.0 - eta)*(1.0 - zeta) / denominator;
1766 functions[1][2] = -(1.0 + eta)*(1.0 - zeta) / denominator;
1767 functions[1][3] = (1.0 + eta)*(1.0 - zeta) / denominator;
1768 functions[1][4] = -(1.0 - eta)*(1.0 + zeta) / denominator;
1769 functions[1][5] = (1.0 - eta)*(1.0 + zeta) / denominator;
1770 functions[1][6] = -(1.0 + eta)*(1.0 + zeta) / denominator;
1771 functions[1][7] = (1.0 + eta)*(1.0 + zeta) / denominator;
1773 functions[2][0] = -(1.0 - xi)*(1.0 - zeta) / denominator;
1774 functions[2][1] = -(1.0 + xi)*(1.0 - zeta) / denominator;
1775 functions[2][2] = (1.0 - xi)*(1.0 - zeta) / denominator;
1776 functions[2][3] = (1.0 + xi)*(1.0 - zeta) / denominator;
1777 functions[2][4] = -(1.0 - xi)*(1.0 + zeta) / denominator;
1778 functions[2][5] = -(1.0 + xi)*(1.0 + zeta) / denominator;
1779 functions[2][6] = (1.0 - xi)*(1.0 + zeta) / denominator;
1780 functions[2][7] = (1.0 + xi)*(1.0 + zeta) / denominator;
1782 functions[3][0] = -(1.0 - xi)*(1.0 - eta) / denominator;
1783 functions[3][1] = -(1.0 + xi)*(1.0 - eta) / denominator;
1784 functions[3][2] = -(1.0 - xi)*(1.0 + eta) / denominator;
1785 functions[3][3] = -(1.0 + xi)*(1.0 + eta) / denominator;
1786 functions[3][4] = (1.0 - xi)*(1.0 - eta) / denominator;
1787 functions[3][5] = (1.0 + xi)*(1.0 - eta) / denominator;
1788 functions[3][6] = (1.0 - xi)*(1.0 + eta) / denominator;
1789 functions[3][7] = (1.0 + xi)*(1.0 + eta) / denominator;
1793 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1800 typedef typename std::iterator_traits<typename Teuchos::Array<LocalOrdinal>::iterator>::difference_type DT;
1801 DT n = last1 - first1;
1807 for (DT j = 0; j < max; j++)
1809 for (DT k = j; k >= 0; k-=m)
1811 if (first1[first2[k+m]] >= first1[first2[k]])
1813 std::swap(first2[k+m], first2[k]);
1820 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1827 typedef typename std::iterator_traits<typename Teuchos::Array<LocalOrdinal>::iterator>::difference_type DT;
1828 DT n = last1 - first1;
1834 for (DT j = 0; j < max; j++)
1836 for (DT k = j; k >= 0; k-=m)
1838 if (first1[k+m] >= first1[k])
1840 std::swap(first1[k+m], first1[k]);
1841 std::swap(first2[k+m], first2[k]);
1848 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1852 const LO myRankIndex,
const LO pi,
const LO pj,
const LO ,
1853 const typename std::vector<std::vector<GO> >::iterator blockStart,
1854 const typename std::vector<std::vector<GO> >::iterator blockEnd,
1855 GO& myGID, LO& myPID, LO& myLID)
const {
1857 LO ni = -1, nj = -1, li = -1, lj = -1, lk = -1;
1858 LO myRankGuess = myRankIndex;
1860 if(i == 0 && myGeo->ghostInterface[0]) {
1862 }
else if((i == myGeo->ghostedCoarseNodesPerDir[0] - 1) && myGeo->ghostInterface[1]) {
1865 if(j == 0 && myGeo->ghostInterface[2]) {
1867 }
else if((j == myGeo->ghostedCoarseNodesPerDir[1] - 1) && myGeo->ghostInterface[3]) {
1870 if(k == 0 && myGeo->ghostInterface[4]) {
1871 myRankGuess -= pj*pi;
1872 }
else if((k == myGeo->ghostedCoarseNodesPerDir[2] - 1) && myGeo->ghostInterface[5]) {
1873 myRankGuess += pj*pi;
1875 if(coarseNodeFineIndices[0] >= myGeo->meshData[myRankGuess][3]
1876 && coarseNodeFineIndices[0] <= myGeo->meshData[myRankGuess][4]
1877 && coarseNodeFineIndices[1] >= myGeo->meshData[myRankGuess][5]
1878 && coarseNodeFineIndices[1] <= myGeo->meshData[myRankGuess][6]
1879 && coarseNodeFineIndices[2] >= myGeo->meshData[myRankGuess][7]
1880 && coarseNodeFineIndices[2] <= myGeo->meshData[myRankGuess][8]) {
1881 myPID = myGeo->meshData[myRankGuess][0];
1882 ni = myGeo->meshData[myRankGuess][4] - myGeo->meshData[myRankGuess][3] + 1;
1883 nj = myGeo->meshData[myRankGuess][6] - myGeo->meshData[myRankGuess][5] + 1;
1884 li = coarseNodeFineIndices[0] - myGeo->meshData[myRankGuess][3];
1885 lj = coarseNodeFineIndices[1] - myGeo->meshData[myRankGuess][5];
1886 lk = coarseNodeFineIndices[2] - myGeo->meshData[myRankGuess][7];
1887 myLID = lk*nj*ni + lj*ni + li;
1888 myGID = myGeo->meshData[myRankGuess][9] + myLID;
1892 auto nodeRank = std::find_if(blockStart, blockEnd,
1893 [coarseNodeFineIndices](
const std::vector<GO>& vec){
1894 if(coarseNodeFineIndices[0] >= vec[3]
1895 && coarseNodeFineIndices[0] <= vec[4]
1896 && coarseNodeFineIndices[1] >= vec[5]
1897 && coarseNodeFineIndices[1] <= vec[6]
1898 && coarseNodeFineIndices[2] >= vec[7]
1899 && coarseNodeFineIndices[2] <= vec[8]) {
1905 myPID = (*nodeRank)[0];
1906 ni = (*nodeRank)[4] - (*nodeRank)[3] + 1;
1907 nj = (*nodeRank)[6] - (*nodeRank)[5] + 1;
1908 li = coarseNodeFineIndices[0] - (*nodeRank)[3];
1909 lj = coarseNodeFineIndices[1] - (*nodeRank)[5];
1910 lk = coarseNodeFineIndices[2] - (*nodeRank)[7];
1911 myLID = lk*nj*ni + lj*ni + li;
1912 myGID = (*nodeRank)[9] + myLID;
1918 #define MUELU_GENERALGEOMETRICPFACTORY_SHORT
1919 #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.
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
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.
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.
int GetLevelID() const
Return level number.
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)