46 #ifndef MUELU_GENERALGEOMETRICPFACTORY_DEF_HPP 
   47 #define MUELU_GENERALGEOMETRICPFACTORY_DEF_HPP 
   58 #include <Xpetra_CrsMatrixWrap.hpp> 
   61 #include <Xpetra_MapFactory.hpp> 
   62 #include <Xpetra_MultiVectorFactory.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 {
 
  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 {
 
  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;
 
  854                                                        colGIDs.view(0,dofsPerNode*
 
  855                                                                     myGeo->lNumCoarseNodes),
 
  856                                                        rowMapP->getIndexBase(),
 
  860                                                     colGIDs.view(0, colGIDs.size()),
 
  861                                                     rowMapP->getIndexBase(),
 
  865     std::vector<size_t> strideInfo(1);
 
  866     strideInfo[0] = dofsPerNode;
 
  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);
 
  886                                                                       myGeo->numDimensions);
 
  887     coarseCoords->doImport(*fineCoords, *coarseImporter, 
Xpetra::INSERT);
 
  888     coarseCoords->replaceMap(coarseCoordsMap);
 
  893                                                                ghostedCoarseNodes->GIDs(),
 
  894                                                                fineCoords->getMap()->getIndexBase(),
 
  895                                                                fineCoords->getMap()->getComm());
 
  896     RCP<const Import> ghostImporter = ImportFactory::Build(fineCoords->getMap(), ghostMap);
 
  898                                                                               myGeo->numDimensions);
 
  899     ghostCoords->doImport(*fineCoords, *ghostImporter, 
Xpetra::INSERT);
 
  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;
 
  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;
 
 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. 
 
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. 
 
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)