138 Level& coarseLevel)
const{
147 RCP<Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType,LO,GO,NO> > coordinates =
149 LO numDimensions = coordinates->getNumVectors();
150 LO BlkSize = A->GetFixedBlockSize();
153 Array<GO> gFineNodesPerDir(3);
154 Array<LO> lFineNodesPerDir(3);
161 gFineNodesPerDir =
Get<Array<GO> >(fineLevel,
"gNodesPerDim");
164 lFineNodesPerDir =
Get<Array<LO> >(fineLevel,
"lNodesPerDim");
166 for(LO i = 0; i < 3; ++i) {
167 if(gFineNodesPerDir[i] == 0) {
170 gFineNodesPerDir[i] = 1;
172 if(lFineNodesPerDir[i] == 0) {
175 lFineNodesPerDir[i] = 1;
178 GO gNumFineNodes = gFineNodesPerDir[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
179 LO lNumFineNodes = lFineNodesPerDir[2]*lFineNodesPerDir[1]*lFineNodesPerDir[0];
182 std::string coarsenRate = pL.get<std::string>(
"Coarsen");
183 Array<LO> coarseRate(3);
185 Teuchos::Array<LO> crates;
187 crates = Teuchos::fromStringToArray<LO>(coarsenRate);
188 }
catch(
const Teuchos::InvalidArrayStringRepresentation& e) {
189 GetOStream(
Errors,-1) <<
" *** Coarsen must be a string convertible into an array! *** "
193 TEUCHOS_TEST_FOR_EXCEPTION((crates.size() > 1) && (crates.size() < numDimensions),
195 "Coarsen must have at least as many components as the number of"
196 " spatial dimensions in the problem.");
197 for(LO i = 0; i < 3; ++i) {
198 if(i < numDimensions) {
199 if(crates.size() == 1) {
200 coarseRate[i] = crates[0];
201 }
else if(i < crates.size()) {
202 coarseRate[i] = crates[i];
204 GetOStream(
Errors,-1) <<
" *** Coarsen must be at least as long as the number of"
205 " spatial dimensions! *** " << std::endl;
207 " spatial dimensions! *** \n");
216 const std::string stencilType = pL.get<std::string>(
"stencil type");
217 if(stencilType !=
"full" && stencilType !=
"reduced") {
218 GetOStream(
Errors,-1) <<
" *** stencil type must be set to: full or reduced, any other value "
219 "is trated as an error! *** " << std::endl;
224 const std::string blockStrategy = pL.get<std::string>(
"block strategy");
225 if(blockStrategy !=
"coupled" && blockStrategy !=
"uncoupled") {
226 GetOStream(
Errors,-1) <<
" *** block strategy must be set to: coupled or uncoupled, any other "
227 "value is trated as an error! *** " << std::endl;
231 GO gNumCoarseNodes = 0;
232 LO lNumCoarseNodes = 0;
233 Array<GO> gIndices(3), gCoarseNodesPerDir(3), ghostGIDs, coarseNodesGIDs, colGIDs;
234 Array<LO> myOffset(3), lCoarseNodesPerDir(3), glCoarseNodesPerDir(3), endRate(3);
235 Array<bool> ghostInterface(6);
236 Array<int> boundaryFlags(3);
237 ArrayRCP<Array<typename Teuchos::ScalarTraits<Scalar>::magnitudeType> > coarseNodes(numDimensions);
238 Array<ArrayView<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> > fineNodes(numDimensions);
239 for(LO dim = 0; dim < numDimensions; ++dim) {fineNodes[dim] = coordinates->getData(dim)();}
242 RCP<NodesIDs> ghostedCoarseNodes = rcp(
new NodesIDs{});
244 GetGeometricData(coordinates, coarseRate, gFineNodesPerDir, lFineNodesPerDir, BlkSize,
245 gIndices, myOffset, ghostInterface, endRate, gCoarseNodesPerDir,
246 lCoarseNodesPerDir, glCoarseNodesPerDir, ghostGIDs, coarseNodesGIDs, colGIDs,
247 gNumCoarseNodes, lNumCoarseNodes, coarseNodes, boundaryFlags,
251 Xpetra::UnderlyingLib lib = coordinates->getMap()->lib();
252 RCP<const Map> coarseCoordsMap = MapFactory::Build (lib,
254 coarseNodesGIDs.view(0, lNumCoarseNodes),
255 coordinates->getMap()->getIndexBase(),
256 coordinates->getMap()->getComm());
257 Array<ArrayView<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> > coarseCoords(numDimensions);
258 for(LO dim = 0; dim < numDimensions; ++dim) {
259 coarseCoords[dim] = coarseNodes[dim]();
261 RCP<Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType,LO,GO,NO> > coarseCoordinates =
262 Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::magnitudeType,LO,GO,NO>
::Build(coarseCoordsMap, coarseCoords(),
295 Array<GO> ghostRowGIDs, ghostColGIDs, nodeSteps(3);
297 nodeSteps[1] = gFineNodesPerDir[0];
298 nodeSteps[2] = gFineNodesPerDir[0]*gFineNodesPerDir[1];
299 Array<LO> glFineNodesPerDir(3);
300 GO startingGID = A->getRowMap()->getMinGlobalIndex();
301 for(LO dim = 0; dim < 3; ++dim) {
302 LO numCoarseNodes = 0;
303 if(dim < numDimensions) {
304 startingGID -= myOffset[dim]*nodeSteps[dim];
305 numCoarseNodes = lCoarseNodesPerDir[dim];
306 if(ghostInterface[2*dim]) {++numCoarseNodes;}
307 if(ghostInterface[2*dim+1]) {++numCoarseNodes;}
308 if(gIndices[dim] + lFineNodesPerDir[dim] == gFineNodesPerDir[dim]) {
309 glFineNodesPerDir[dim] = (numCoarseNodes - 2)*coarseRate[dim] + endRate[dim] + 1;
311 glFineNodesPerDir[dim] = (numCoarseNodes - 1)*coarseRate[dim] + 1;
314 glFineNodesPerDir[dim] = 1;
317 ghostRowGIDs.resize(glFineNodesPerDir[0]*glFineNodesPerDir[1]*glFineNodesPerDir[2]*BlkSize);
318 for(LO k = 0; k < glFineNodesPerDir[2]; ++k) {
319 for(LO j = 0; j < glFineNodesPerDir[1]; ++j) {
320 for(LO i = 0; i < glFineNodesPerDir[0]; ++i) {
321 for(LO l = 0; l < BlkSize; ++l) {
322 ghostRowGIDs[(k*glFineNodesPerDir[1]*glFineNodesPerDir[0]
323 + j*glFineNodesPerDir[0] + i)*BlkSize + l] = startingGID
324 + (k*gFineNodesPerDir[1]*gFineNodesPerDir[0] + j*gFineNodesPerDir[0] + i)*BlkSize + l;
331 Array<GO> startingGlobalIndices(numDimensions), dimStride(numDimensions);
332 Array<GO> startingColIndices(numDimensions), finishingColIndices(numDimensions);
334 Array<LO> colRange(numDimensions);
336 for(
int dim = 1; dim < numDimensions; ++dim) {
337 dimStride[dim] = dimStride[dim - 1]*gFineNodesPerDir[dim - 1];
340 GO tmp = startingGID;
341 for(
int dim = numDimensions; dim > 0; --dim) {
342 startingGlobalIndices[dim - 1] = tmp / dimStride[dim - 1];
343 tmp = tmp % dimStride[dim - 1];
345 if(startingGlobalIndices[dim - 1] > 0) {
346 startingColIndices[dim - 1] = startingGlobalIndices[dim - 1] - 1;
348 if(startingGlobalIndices[dim - 1] + glFineNodesPerDir[dim - 1] < gFineNodesPerDir[dim - 1]){
349 finishingColIndices[dim - 1] = startingGlobalIndices[dim - 1]
350 + glFineNodesPerDir[dim - 1];
352 finishingColIndices[dim - 1] = startingGlobalIndices[dim - 1]
353 + glFineNodesPerDir[dim - 1] - 1;
355 colRange[dim - 1] = finishingColIndices[dim - 1] - startingColIndices[dim - 1] + 1;
356 colMinGID += startingColIndices[dim - 1]*dimStride[dim - 1];
359 ghostColGIDs.resize(colRange[0]*colRange[1]*colRange[2]*BlkSize);
360 for(LO k = 0; k < colRange[2]; ++k) {
361 for(LO j = 0; j < colRange[1]; ++j) {
362 for(LO i = 0; i < colRange[0]; ++i) {
363 for(LO l = 0; l < BlkSize; ++l) {
364 ghostColGIDs[(k*colRange[1]*colRange[0] + j*colRange[0] + i)*BlkSize + l] = colMinGID
365 + (k*gFineNodesPerDir[1]*gFineNodesPerDir[0] + j*gFineNodesPerDir[0] + i)*BlkSize + l;
371 RCP<const Map> ghostedRowMap = Xpetra::MapFactory<LO,GO,NO>::Build(A->getRowMap()->lib(),
372 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
374 A->getRowMap()->getIndexBase(),
375 A->getRowMap()->getComm());
376 RCP<const Map> ghostedColMap = Xpetra::MapFactory<LO,GO,NO>::Build(A->getRowMap()->lib(),
377 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
379 A->getRowMap()->getIndexBase(),
380 A->getRowMap()->getComm());
381 RCP<const Import> ghostImporter = Xpetra::ImportFactory<LO,GO,NO>::Build(A->getRowMap(),
383 RCP<const Matrix> Aghost = Xpetra::MatrixFactory<SC,LO,GO,NO>::Build(A, *ghostImporter,
388 RCP<const Map> rowMapP = A->getDomainMap();
390 RCP<const Map> domainMapP;
392 RCP<const Map> colMapP;
403 LO lNumGhostedNodes = ghostedCoarseNodes->GIDs.size();
405 std::vector<NodeID> colMapOrdering(lNumGhostedNodes);
406 for(LO ind = 0; ind < lNumGhostedNodes; ++ind) {
407 colMapOrdering[ind].GID = ghostedCoarseNodes->GIDs[ind];
408 if(ghostedCoarseNodes->PIDs[ind] == rowMapP->getComm()->getRank()) {
409 colMapOrdering[ind].PID = -1;
411 colMapOrdering[ind].PID = ghostedCoarseNodes->PIDs[ind];
413 colMapOrdering[ind].LID = ghostedCoarseNodes->LIDs[ind];
414 colMapOrdering[ind].lexiInd = ind;
416 std::sort(colMapOrdering.begin(), colMapOrdering.end(),
418 return ( (a.PID < b.PID) || ((a.PID == b.PID) && (a.GID < b.GID)) );
421 colGIDs.resize(BlkSize*lNumGhostedNodes);
422 for(LO ind = 0; ind < lNumGhostedNodes; ++ind) {
424 ghostedCoarseNodes->colInds[colMapOrdering[ind].lexiInd] = ind;
425 for(LO dof = 0; dof < BlkSize; ++dof) {
426 colGIDs[BlkSize*ind + dof] = BlkSize*colMapOrdering[ind].GID + dof;
429 domainMapP = Xpetra::MapFactory<LO,GO,NO>::Build(rowMapP->lib(),
430 BlkSize*gNumCoarseNodes,
431 colGIDs.view(0,BlkSize*lNumCoarseNodes),
432 rowMapP->getIndexBase(),
434 colMapP = Xpetra::MapFactory<LO,GO,NO>::Build(rowMapP->lib(),
435 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
436 colGIDs.view(0, colGIDs.size()),
437 rowMapP->getIndexBase(),
441 std::vector<size_t> strideInfo(1);
442 strideInfo[0] = BlkSize;
443 RCP<const Map> stridedDomainMapP = Xpetra::StridedMapFactory<LO,GO,NO>::Build(domainMapP,
449 gnnzP += gNumCoarseNodes;
450 lnnzP += lNumCoarseNodes;
452 gnnzP += (gNumFineNodes - gNumCoarseNodes)*std::pow(2, numDimensions);
453 lnnzP += (lNumFineNodes - lNumCoarseNodes)*std::pow(2, numDimensions);
455 gnnzP = gnnzP*BlkSize;
456 lnnzP = lnnzP*BlkSize;
460 P = rcp(
new CrsMatrixWrap(rowMapP, colMapP, 0));
461 RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
463 ArrayRCP<size_t> iaP;
467 PCrs->allocateAllValues(lnnzP, iaP, jaP, valP);
469 ArrayView<size_t> ia = iaP();
470 ArrayView<LO> ja = jaP();
471 ArrayView<SC> val = valP();
475 LO numCoarseElements = 1;
476 Array<LO> lCoarseElementsPerDir(3);
477 for(LO dim = 0; dim < numDimensions; ++dim) {
478 lCoarseElementsPerDir[dim] = lCoarseNodesPerDir[dim];
479 if(ghostInterface[2*dim]) {++lCoarseElementsPerDir[dim];}
480 if(!ghostInterface[2*dim+1]) {--lCoarseElementsPerDir[dim];}
481 numCoarseElements = numCoarseElements*lCoarseElementsPerDir[dim];
484 for(LO dim = numDimensions; dim < 3; ++dim) {
485 lCoarseElementsPerDir[dim] = 1;
489 Array<int> elementFlags(3);
490 Array<LO> elemInds(3), elementNodesPerDir(3), glElementRefTuple(3);
491 Array<LO> glElementRefTupleCG(3), glElementCoarseNodeCG(8);
492 const int numCoarseNodesInElement = std::pow(2, numDimensions);
493 const int nnzPerCoarseNode = (blockStrategy ==
"coupled") ? BlkSize : 1;
494 const int numRowsPerPoint = BlkSize;
495 for(elemInds[2] = 0; elemInds[2] < lCoarseElementsPerDir[2]; ++elemInds[2]) {
496 for(elemInds[1] = 0; elemInds[1] < lCoarseElementsPerDir[1]; ++elemInds[1]) {
497 for(elemInds[0] = 0; elemInds[0] < lCoarseElementsPerDir[0]; ++elemInds[0]) {
498 elementFlags[0] = 0; elementFlags[1] = 0; elementFlags[2] = 0;
499 for(
int dim = 0; dim < 3; ++dim) {
501 if(elemInds[dim] == 0 && elemInds[dim] == lCoarseElementsPerDir[dim] - 1) {
502 elementFlags[dim] = boundaryFlags[dim];
503 }
else if(elemInds[dim] == 0 && (boundaryFlags[dim] == 1 || boundaryFlags[dim] == 3)) {
504 elementFlags[dim] += 1;
505 }
else if((elemInds[dim] == lCoarseElementsPerDir[dim] - 1)
506 && (boundaryFlags[dim] == 2 || boundaryFlags[dim] == 3)) {
507 elementFlags[dim] += 2;
509 elementFlags[dim] = 0;
513 if(dim < numDimensions) {
514 if((elemInds[dim] == lCoarseElementsPerDir[dim])
515 && (gIndices[dim] + lFineNodesPerDir[dim] == gFineNodesPerDir[dim])) {
516 elementNodesPerDir[dim] = endRate[dim] + 1;
518 elementNodesPerDir[dim] = coarseRate[dim] + 1;
521 elementNodesPerDir[dim] = 1;
525 glElementRefTuple[dim] = elemInds[dim]*coarseRate[dim];
526 glElementRefTupleCG[dim] = elemInds[dim];
531 for(
typename Array<LO>::size_type elem = 0; elem < glElementCoarseNodeCG.size(); ++elem) {
532 glElementCoarseNodeCG[elem]
533 = glElementRefTupleCG[2]*glCoarseNodesPerDir[1]*glCoarseNodesPerDir[0]
534 + glElementRefTupleCG[1]*glCoarseNodesPerDir[0] + glElementRefTupleCG[0];
536 glElementCoarseNodeCG[4] += glCoarseNodesPerDir[1]*glCoarseNodesPerDir[0];
537 glElementCoarseNodeCG[5] += glCoarseNodesPerDir[1]*glCoarseNodesPerDir[0];
538 glElementCoarseNodeCG[6] += glCoarseNodesPerDir[1]*glCoarseNodesPerDir[0];
539 glElementCoarseNodeCG[7] += glCoarseNodesPerDir[1]*glCoarseNodesPerDir[0];
541 glElementCoarseNodeCG[2] += glCoarseNodesPerDir[0];
542 glElementCoarseNodeCG[3] += glCoarseNodesPerDir[0];
543 glElementCoarseNodeCG[6] += glCoarseNodesPerDir[0];
544 glElementCoarseNodeCG[7] += glCoarseNodesPerDir[0];
546 glElementCoarseNodeCG[1] += 1;
547 glElementCoarseNodeCG[3] += 1;
548 glElementCoarseNodeCG[5] += 1;
549 glElementCoarseNodeCG[7] += 1;
551 LO numNodesInElement = elementNodesPerDir[0]*elementNodesPerDir[1]*elementNodesPerDir[2];
556 Teuchos::SerialDenseMatrix<LO,SC> Pi, Pf, Pe;
557 Array<LO> dofType(numNodesInElement*BlkSize), lDofInd(numNodesInElement*BlkSize);
559 numDimensions, glFineNodesPerDir, gFineNodesPerDir, gIndices,
560 lCoarseNodesPerDir, ghostInterface, elementFlags, stencilType,
561 blockStrategy, elementNodesPerDir, numNodesInElement, colGIDs,
562 Pi, Pf, Pe, dofType, lDofInd);
566 Array<LO> lNodeLIDs(numNodesInElement);
568 Array<LO> lNodeTuple(3), nodeInd(3);
569 for(nodeInd[2] = 0; nodeInd[2] < elementNodesPerDir[2]; ++nodeInd[2]) {
570 for(nodeInd[1] = 0; nodeInd[1] < elementNodesPerDir[1]; ++nodeInd[1]) {
571 for(nodeInd[0] = 0; nodeInd[0] < elementNodesPerDir[0]; ++nodeInd[0]) {
572 int stencilLength = 0;
573 if((nodeInd[0] == 0 || nodeInd[0] == elementNodesPerDir[0] - 1) &&
574 (nodeInd[1] == 0 || nodeInd[1] == elementNodesPerDir[1] - 1) &&
575 (nodeInd[2] == 0 || nodeInd[2] == elementNodesPerDir[2] - 1)) {
578 stencilLength = std::pow(2, numDimensions);
580 LO nodeElementInd = nodeInd[2]*elementNodesPerDir[1]*elementNodesPerDir[1]
581 + nodeInd[1]*elementNodesPerDir[0] + nodeInd[0];
582 for(
int dim = 0; dim < 3; ++dim) {
583 lNodeTuple[dim] = glElementRefTuple[dim] - myOffset[dim] + nodeInd[dim];
585 if(lNodeTuple[0] < 0 || lNodeTuple[1] < 0 || lNodeTuple[2] < 0 ||
586 lNodeTuple[0] > lFineNodesPerDir[0] - 1 ||
587 lNodeTuple[1] > lFineNodesPerDir[1] - 1 ||
588 lNodeTuple[2] > lFineNodesPerDir[2] - 1) {
591 lNodeLIDs[nodeElementInd] = -1;
592 }
else if ((nodeInd[0] == 0 && elemInds[0] !=0) ||
593 (nodeInd[1] == 0 && elemInds[1] !=0) ||
594 (nodeInd[2] == 0 && elemInds[2] !=0)) {
598 lNodeLIDs[nodeElementInd] = -2;
604 lNodeLIDs[nodeElementInd] = lNodeTuple[2]*lFineNodesPerDir[1]*lFineNodesPerDir[0]
605 + lNodeTuple[1]*lFineNodesPerDir[0] + lNodeTuple[0];
611 Array<LO> refCoarsePointTuple(3);
612 for(
int dim = 2; dim > -1; --dim) {
614 refCoarsePointTuple[dim] = (lNodeTuple[dim] + myOffset[dim]) / coarseRate[dim];
615 if(myOffset[dim] == 0) {
616 ++refCoarsePointTuple[dim];
620 refCoarsePointTuple[dim] =
621 std::ceil(
static_cast<double>(lNodeTuple[dim] + myOffset[dim])
624 if((lNodeTuple[dim] + myOffset[dim]) % coarseRate[dim] > 0) {
break;}
626 const LO numCoarsePoints = refCoarsePointTuple[0]
627 + refCoarsePointTuple[1]*lCoarseNodesPerDir[0]
628 + refCoarsePointTuple[2]*lCoarseNodesPerDir[1]*lCoarseNodesPerDir[0];
629 const LO numFinePoints = lNodeLIDs[nodeElementInd] + 1;
633 size_t rowPtr = (numFinePoints - numCoarsePoints)*numRowsPerPoint
634 *numCoarseNodesInElement*nnzPerCoarseNode + numCoarsePoints*numRowsPerPoint;
635 if(dofType[nodeElementInd*BlkSize] == 0) {
637 rowPtr = rowPtr - numRowsPerPoint;
639 rowPtr = rowPtr - numRowsPerPoint*numCoarseNodesInElement*nnzPerCoarseNode;
642 for(
int dof = 0; dof < BlkSize; ++dof) {
646 switch(dofType[nodeElementInd*BlkSize + dof]) {
648 if(nodeInd[2] == elementNodesPerDir[2] - 1) {cornerInd += 4;}
649 if(nodeInd[1] == elementNodesPerDir[1] - 1) {cornerInd += 2;}
650 if(nodeInd[0] == elementNodesPerDir[0] - 1) {cornerInd += 1;}
651 ia[lNodeLIDs[nodeElementInd]*BlkSize + dof + 1] = rowPtr + dof + 1;
652 ja[rowPtr + dof] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[cornerInd]]*BlkSize + dof;
653 val[rowPtr + dof] = 1.0;
657 ia[lNodeLIDs[nodeElementInd]*BlkSize + dof + 1]
658 = rowPtr + (dof + 1)*numCoarseNodesInElement*nnzPerCoarseNode;
659 for(
int ind1 = 0; ind1 < stencilLength; ++ind1) {
660 if(blockStrategy ==
"coupled") {
661 for(
int ind2 = 0; ind2 < BlkSize; ++ind2) {
662 size_t lRowPtr = rowPtr + dof*numCoarseNodesInElement*nnzPerCoarseNode
663 + ind1*BlkSize + ind2;
664 ja[lRowPtr] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]]*BlkSize + ind2;
665 val[lRowPtr] = Pe(lDofInd[nodeElementInd*BlkSize + dof],
666 ind1*BlkSize + ind2);
668 }
else if(blockStrategy ==
"uncoupled") {
669 size_t lRowPtr = rowPtr + dof*numCoarseNodesInElement*nnzPerCoarseNode
671 ja[rowPtr + dof] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]]*BlkSize + dof;
672 val[lRowPtr] = Pe(lDofInd[nodeElementInd*BlkSize + dof],
679 ia[lNodeLIDs[nodeElementInd]*BlkSize + dof + 1]
680 = rowPtr + (dof + 1)*numCoarseNodesInElement*nnzPerCoarseNode;
681 for(
int ind1 = 0; ind1 < stencilLength; ++ind1) {
682 if(blockStrategy ==
"coupled") {
683 for(
int ind2 = 0; ind2 < BlkSize; ++ind2) {
684 size_t lRowPtr = rowPtr + dof*numCoarseNodesInElement*nnzPerCoarseNode
685 + ind1*BlkSize + ind2;
686 ja [lRowPtr] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]]*BlkSize + ind2;
687 val[lRowPtr] = Pf(lDofInd[nodeElementInd*BlkSize + dof],
688 ind1*BlkSize + ind2);
690 }
else if(blockStrategy ==
"uncoupled") {
691 size_t lRowPtr = rowPtr + dof*numCoarseNodesInElement*nnzPerCoarseNode
694 ja [lRowPtr] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]]*BlkSize + dof;
695 val[lRowPtr] = Pf(lDofInd[nodeElementInd*BlkSize + dof],
702 ia[lNodeLIDs[nodeElementInd]*BlkSize + dof + 1]
703 = rowPtr + (dof + 1)*numCoarseNodesInElement*nnzPerCoarseNode;
704 for(
int ind1 = 0; ind1 < stencilLength; ++ind1) {
705 if(blockStrategy ==
"coupled") {
706 for(
int ind2 = 0; ind2 < BlkSize; ++ind2) {
707 size_t lRowPtr = rowPtr + dof*numCoarseNodesInElement*nnzPerCoarseNode
708 + ind1*BlkSize + ind2;
709 ja [lRowPtr] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]]*BlkSize + ind2;
710 val[lRowPtr] = Pi(lDofInd[nodeElementInd*BlkSize + dof],
711 ind1*BlkSize + ind2);
713 }
else if(blockStrategy ==
"uncoupled") {
714 size_t lRowPtr = rowPtr + dof*numCoarseNodesInElement*nnzPerCoarseNode
716 ja [lRowPtr] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]]*BlkSize + dof;
717 val[lRowPtr] = Pi(lDofInd[nodeElementInd*BlkSize + dof],
734 Xpetra::CrsMatrixUtils<SC,LO,GO,NO>::sortCrsEntries(ia, ja, val, rowMapP->lib());
737 PCrs->setAllValues(iaP, jaP, valP);
738 PCrs->expertStaticFillComplete(domainMapP,rowMapP);
741 if (A->IsView(
"stridedMaps") ==
true) {
742 P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedDomainMapP);
744 P->CreateView(
"stridedMaps", P->getRangeMap(), stridedDomainMapP);
748 Set(coarseLevel,
"P", P);
749 Set(coarseLevel,
"coarseCoordinates", coarseCoordinates);
750 Set<Array<GO> >(coarseLevel,
"gCoarseNodesPerDim", gCoarseNodesPerDir);
751 Set<Array<LO> >(coarseLevel,
"lCoarseNodesPerDim", lCoarseNodesPerDir);
757 GetGeometricData(RCP<Xpetra::MultiVector<
typename Teuchos::ScalarTraits<Scalar>::magnitudeType,LO,GO,NO> >& coordinates,
758 const Array<LO> coarseRate,
const Array<GO> gFineNodesPerDir,
759 const Array<LO> lFineNodesPerDir,
const LO BlkSize, Array<GO>& gIndices,
760 Array<LO>& myOffset, Array<bool>& ghostInterface, Array<LO>& endRate,
761 Array<GO>& gCoarseNodesPerDir, Array<LO>& lCoarseNodesPerDir,
762 Array<LO>& glCoarseNodesPerDir, Array<GO>& ghostGIDs, Array<GO>& coarseNodesGIDs,
763 Array<GO>& colGIDs, GO& gNumCoarseNodes, LO& lNumCoarseNodes,
764 ArrayRCP<Array<
typename Teuchos::ScalarTraits<Scalar>::magnitudeType> > coarseNodes, Array<int>& boundaryFlags,
765 RCP<NodesIDs> ghostedCoarseNodes)
const {
772 RCP<const Map> coordinatesMap = coordinates->getMap();
773 LO numDimensions = coordinates->getNumVectors();
784 GO minGlobalIndex = coordinatesMap->getMinGlobalIndex();
787 gIndices[2] = minGlobalIndex / (gFineNodesPerDir[1]*gFineNodesPerDir[0]);
788 tmp = minGlobalIndex % (gFineNodesPerDir[1]*gFineNodesPerDir[0]);
789 gIndices[1] = tmp / gFineNodesPerDir[0];
790 gIndices[0] = tmp % gFineNodesPerDir[0];
792 myOffset[2] = gIndices[2] % coarseRate[2];
793 myOffset[1] = gIndices[1] % coarseRate[1];
794 myOffset[0] = gIndices[0] % coarseRate[0];
797 for(
int dim = 0; dim < 3; ++dim) {
798 if(gIndices[dim] == 0) {
799 boundaryFlags[dim] += 1;
801 if(gIndices[dim] + lFineNodesPerDir[dim] == gFineNodesPerDir[dim]) {
802 boundaryFlags[dim] += 2;
807 for(LO i=0; i < numDimensions; ++i) {
808 if((gIndices[i] != 0) && (gIndices[i] % coarseRate[i] > 0)) {
809 ghostInterface[2*i] =
true;
811 if(((gIndices[i] + lFineNodesPerDir[i]) != gFineNodesPerDir[i])
812 && ((gIndices[i] + lFineNodesPerDir[i] - 1) % coarseRate[i] > 0)) {
813 ghostInterface[2*i + 1] =
true;
817 for(LO i = 0; i < 3; ++i) {
818 if(i < numDimensions) {
819 lCoarseNodesPerDir[i] = (lFineNodesPerDir[i] + myOffset[i] - 1) / coarseRate[i];
820 if(myOffset[i] == 0) { ++lCoarseNodesPerDir[i]; }
821 gCoarseNodesPerDir[i] = (gFineNodesPerDir[i] - 1) / coarseRate[i];
822 endRate[i] = (gFineNodesPerDir[i] - 1) % coarseRate[i];
823 if(endRate[i] == 0) {
824 ++gCoarseNodesPerDir[i];
825 endRate[i] = coarseRate[i];
831 gCoarseNodesPerDir[i] = 1;
832 lCoarseNodesPerDir[i] = 1;
837 gNumCoarseNodes = gCoarseNodesPerDir[0]*gCoarseNodesPerDir[1]*gCoarseNodesPerDir[2];
838 lNumCoarseNodes = lCoarseNodesPerDir[0]*lCoarseNodesPerDir[1]*lCoarseNodesPerDir[2];
841 LO lNumGhostNodes = 0;
842 Array<GO> startGhostedCoarseNode(3);
844 const int complementaryIndices[3][2] = {{1,2}, {0,2}, {0,1}};
846 for(LO i = 0; i < 3; ++i) {
850 if((gIndices[i] == gFineNodesPerDir[i] - 1) && (gIndices[i] % coarseRate[i] == 0)) {
851 startGhostedCoarseNode[i] = gIndices[i] / coarseRate[i] - 1;
853 startGhostedCoarseNode[i] = gIndices[i] / coarseRate[i];
856 glCoarseNodesPerDir[i] = lCoarseNodesPerDir[i];
859 if(ghostInterface[2*i] || ghostInterface[2*i+1]) {
860 ++glCoarseNodesPerDir[i];
861 if(i == 0) {tmp = lCoarseNodesPerDir[1]*lCoarseNodesPerDir[2];}
862 if(i == 1) {tmp = lCoarseNodesPerDir[0]*lCoarseNodesPerDir[2];}
863 if(i == 2) {tmp = lCoarseNodesPerDir[0]*lCoarseNodesPerDir[1];}
866 if(ghostInterface[2*i] && ghostInterface[2*i+1]) {
867 ++glCoarseNodesPerDir[i];
870 lNumGhostNodes += tmp;
873 for(LO j = 0; j < 2; ++j) {
874 for(LO k = 0; k < 2; ++k) {
876 if(ghostInterface[2*complementaryIndices[i][0]+j]
877 && ghostInterface[2*complementaryIndices[i][1]+k]) {
878 lNumGhostNodes += lCoarseNodesPerDir[i];
881 if(ghostInterface[2*i] && (i == 0)) { lNumGhostNodes += 1; }
882 if(ghostInterface[2*i+1] && (i == 0)) { lNumGhostNodes += 1; }
890 const LO lNumGhostedNodes = glCoarseNodesPerDir[0]*glCoarseNodesPerDir[1]
891 *glCoarseNodesPerDir[2];
892 ghostedCoarseNodes->PIDs.resize(lNumGhostedNodes);
893 ghostedCoarseNodes->LIDs.resize(lNumGhostedNodes);
894 ghostedCoarseNodes->GIDs.resize(lNumGhostedNodes);
895 ghostedCoarseNodes->coarseGIDs.resize(lNumGhostedNodes);
896 ghostedCoarseNodes->colInds.resize(lNumGhostedNodes);
899 Array<LO> coarseNodeCoarseIndices(3), coarseNodeFineIndices(3), ijk(3);
900 LO currentIndex = -1;
901 for(ijk[2] = 0; ijk[2] < glCoarseNodesPerDir[2]; ++ijk[2]) {
902 for(ijk[1] = 0; ijk[1] < glCoarseNodesPerDir[1]; ++ijk[1]) {
903 for(ijk[0] = 0; ijk[0] < glCoarseNodesPerDir[0]; ++ijk[0]) {
904 currentIndex = ijk[2]*glCoarseNodesPerDir[1]*glCoarseNodesPerDir[0]
905 + ijk[1]*glCoarseNodesPerDir[0] + ijk[0];
906 coarseNodeCoarseIndices[0] = startGhostedCoarseNode[0] + ijk[0];
907 coarseNodeFineIndices[0] = coarseNodeCoarseIndices[0]*coarseRate[0];
908 if(coarseNodeFineIndices[0] > gFineNodesPerDir[0] - 1) {
909 coarseNodeFineIndices[0] = gFineNodesPerDir[0] - 1;
911 coarseNodeCoarseIndices[1] = startGhostedCoarseNode[1] + ijk[1];
912 coarseNodeFineIndices[1] = coarseNodeCoarseIndices[1]*coarseRate[1];
913 if(coarseNodeFineIndices[1] > gFineNodesPerDir[1] - 1) {
914 coarseNodeFineIndices[1] = gFineNodesPerDir[1] - 1;
916 coarseNodeCoarseIndices[2] = startGhostedCoarseNode[2] + ijk[2];
917 coarseNodeFineIndices[2] = coarseNodeCoarseIndices[2]*coarseRate[2];
918 if(coarseNodeFineIndices[2] > gFineNodesPerDir[2] - 1) {
919 coarseNodeFineIndices[2] = gFineNodesPerDir[2] - 1;
921 GO myGID = 0, myCoarseGID = -1;
923 factor[2] = gFineNodesPerDir[1]*gFineNodesPerDir[0];
924 factor[1] = gFineNodesPerDir[0];
926 for(
int dim = 0; dim < 3; ++dim) {
927 if(dim < numDimensions) {
928 if(gIndices[dim] - myOffset[dim] + ijk[dim]*coarseRate[dim]
929 < gFineNodesPerDir[dim] - 1) {
930 myGID += (gIndices[dim] - myOffset[dim]
931 + ijk[dim]*coarseRate[dim])*factor[dim];
933 myGID += (gIndices[dim] - myOffset[dim]
934 + (ijk[dim] - 1)*coarseRate[dim] + endRate[dim])*factor[dim];
938 myCoarseGID = coarseNodeCoarseIndices[0]
939 + coarseNodeCoarseIndices[1]*gCoarseNodesPerDir[0]
940 + coarseNodeCoarseIndices[2]*gCoarseNodesPerDir[1]*gCoarseNodesPerDir[0];
941 ghostedCoarseNodes->GIDs[currentIndex] = myGID;
942 ghostedCoarseNodes->coarseGIDs[currentIndex] = myCoarseGID;
946 coordinatesMap->getRemoteIndexList(ghostedCoarseNodes->GIDs(),
947 ghostedCoarseNodes->PIDs(),
948 ghostedCoarseNodes->LIDs());
959 ghostGIDs.resize(lNumGhostNodes);
962 GO startingGID = minGlobalIndex;
963 Array<GO> startingIndices(3);
966 if(ghostInterface[4] && (myOffset[2] == 0)) {
967 if(gIndices[2] + coarseRate[2] > gFineNodesPerDir[2]) {
968 startingGID -= endRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
970 startingGID -= coarseRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
973 startingGID -= myOffset[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
975 if(ghostInterface[2] && (myOffset[1] == 0)) {
976 if(gIndices[1] + coarseRate[1] > gFineNodesPerDir[1]) {
977 startingGID -= endRate[1]*gFineNodesPerDir[0];
979 startingGID -= coarseRate[1]*gFineNodesPerDir[0];
982 startingGID -= myOffset[1]*gFineNodesPerDir[0];
984 if(ghostInterface[0] && (myOffset[0] == 0)) {
985 if(gIndices[0] + coarseRate[0] > gFineNodesPerDir[0]) {
986 startingGID -= endRate[0];
988 startingGID -= coarseRate[0];
991 startingGID -= myOffset[0];
996 startingIndices[2] = startingGID / (gFineNodesPerDir[1]*gFineNodesPerDir[0]);
997 tmp = startingGID % (gFineNodesPerDir[1]*gFineNodesPerDir[0]);
998 startingIndices[1] = tmp / gFineNodesPerDir[0];
999 startingIndices[0] = tmp % gFineNodesPerDir[0];
1002 GO ghostOffset[3] = {0, 0, 0};
1003 LO lengthZero = lCoarseNodesPerDir[0];
1004 LO lengthOne = lCoarseNodesPerDir[1];
1005 LO lengthTwo = lCoarseNodesPerDir[2];
1006 if(ghostInterface[0]) {++lengthZero;}
1007 if(ghostInterface[1]) {++lengthZero;}
1008 if(ghostInterface[2]) {++lengthOne;}
1009 if(ghostInterface[3]) {++lengthOne;}
1010 if(ghostInterface[4]) {++lengthTwo;}
1011 if(ghostInterface[5]) {++lengthTwo;}
1014 if(ghostInterface[4]) {
1015 ghostOffset[2] = startingGID;
1016 for(LO j = 0; j < lengthOne; ++j) {
1017 if( (j == lengthOne-1)
1018 && (startingIndices[1] + j*coarseRate[1] + 1 > gFineNodesPerDir[1]) ) {
1019 ghostOffset[1] = ((j-1)*coarseRate[1] + endRate[1])*gFineNodesPerDir[0];
1021 ghostOffset[1] = j*coarseRate[1]*gFineNodesPerDir[0];
1023 for(LO k = 0; k < lengthZero; ++k) {
1024 if( (k == lengthZero-1)
1025 && (startingIndices[0] + k*coarseRate[0] + 1 > gFineNodesPerDir[0]) ) {
1026 ghostOffset[0] = (k-1)*coarseRate[0] + endRate[0];
1028 ghostOffset[0] = k*coarseRate[0];
1033 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
1041 for(LO i = 0; i < lengthTwo; ++i) {
1044 if( !((i == lengthTwo-1) && ghostInterface[5]) && !((i == 0) && ghostInterface[4]) ) {
1047 if( (i == lengthTwo-1) && !ghostInterface[5] ) {
1048 ghostOffset[2] = startingGID + ((i-1)*coarseRate[2] + endRate[2])
1049 *gFineNodesPerDir[1]*gFineNodesPerDir[0];
1051 ghostOffset[2] = startingGID + i*coarseRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
1053 for(LO j = 0; j < lengthOne; ++j) {
1054 if( (j == 0) && ghostInterface[2] ) {
1055 for(LO k = 0; k < lengthZero; ++k) {
1056 if( (k == lengthZero-1)
1057 && (startingIndices[0] + k*coarseRate[0] + 1 > gFineNodesPerDir[0]) ) {
1059 ghostOffset[0] = endRate[0];
1061 ghostOffset[0] = (k-1)*coarseRate[0] + endRate[0];
1064 ghostOffset[0] = k*coarseRate[0];
1067 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[0];
1070 }
else if( (j == lengthOne-1) && ghostInterface[3] ) {
1073 if( (j == lengthOne-1)
1074 && (startingIndices[1] + j*coarseRate[1] + 1 > gFineNodesPerDir[1]) ) {
1075 ghostOffset[1] = ((j-1)*coarseRate[1] + endRate[1])*gFineNodesPerDir[0];
1077 ghostOffset[1] = j*coarseRate[1]*gFineNodesPerDir[0];
1079 for(LO k = 0; k < lengthZero; ++k) {
1080 if( (k == lengthZero-1)
1081 && (startingIndices[0] + k*coarseRate[0] + 1 > gFineNodesPerDir[0]) ) {
1082 ghostOffset[0] = (k-1)*coarseRate[0] + endRate[0];
1084 ghostOffset[0] = k*coarseRate[0];
1086 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
1091 if( (j == lengthOne-1)
1092 && (startingIndices[1] + j*coarseRate[1] + 1 > gFineNodesPerDir[1]) ) {
1093 ghostOffset[1] = ( (j-1)*coarseRate[1] + endRate[1] )*gFineNodesPerDir[0];
1095 ghostOffset[1] = j*coarseRate[1]*gFineNodesPerDir[0];
1099 if(ghostInterface[0]) {
1100 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1];
1103 if(ghostInterface[1]) {
1104 if( (startingIndices[0] + (lengthZero-1)*coarseRate[0]) > gFineNodesPerDir[0] - 1 ) {
1105 if(lengthZero > 2) {
1106 ghostOffset[0] = (lengthZero-2)*coarseRate[0] + endRate[0];
1108 ghostOffset[0] = endRate[0];
1111 ghostOffset[0] = (lengthZero-1)*coarseRate[0];
1113 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
1122 if(ghostInterface[5]) {
1123 if( startingIndices[2] + (lengthTwo-1)*coarseRate[2] + 1 > gFineNodesPerDir[2] ) {
1124 ghostOffset[2] = startingGID
1125 + ((lengthTwo-2)*coarseRate[2] + endRate[2])*gFineNodesPerDir[1]*gFineNodesPerDir[0];
1127 ghostOffset[2] = startingGID
1128 + (lengthTwo-1)*coarseRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
1130 for(LO j = 0; j < lengthOne; ++j) {
1131 if( (j == lengthOne-1)
1132 && (startingIndices[1] + j*coarseRate[1] + 1 > gFineNodesPerDir[1]) ) {
1133 ghostOffset[1] = ( (j-1)*coarseRate[1] + endRate[1] )*gFineNodesPerDir[0];
1135 ghostOffset[1] = j*coarseRate[1]*gFineNodesPerDir[0];
1137 for(LO k = 0; k < lengthZero; ++k) {
1138 if( (k == lengthZero-1)
1139 && (startingIndices[0] + k*coarseRate[0] + 1 > gFineNodesPerDir[0]) ) {
1140 ghostOffset[0] = (k-1)*coarseRate[0] + endRate[0];
1142 ghostOffset[0] = k*coarseRate[0];
1144 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
1157 Array<GO> gCoarseNodesGIDs(lNumCoarseNodes);
1158 LO currentNode, offset2, offset1, offset0;
1160 for(LO ind2 = 0; ind2 < lCoarseNodesPerDir[2]; ++ind2) {
1161 if(myOffset[2] == 0) {
1162 offset2 = startingIndices[2] + myOffset[2];
1164 if(startingIndices[2] + endRate[2] == gFineNodesPerDir[2] - 1) {
1165 offset2 = startingIndices[2] + endRate[2];
1167 offset2 = startingIndices[2] + coarseRate[2];
1170 if(offset2 + ind2*coarseRate[2] > gFineNodesPerDir[2] - 1) {
1171 offset2 += (ind2 - 1)*coarseRate[2] + endRate[2];
1173 offset2 += ind2*coarseRate[2];
1175 offset2 = offset2*gFineNodesPerDir[1]*gFineNodesPerDir[0];
1177 for(LO ind1 = 0; ind1 < lCoarseNodesPerDir[1]; ++ind1) {
1178 if(myOffset[1] == 0) {
1179 offset1 = startingIndices[1] + myOffset[1];
1181 if(startingIndices[1] + endRate[1] == gFineNodesPerDir[1] - 1) {
1182 offset1 = startingIndices[1] + endRate[1];
1184 offset1 = startingIndices[1] + coarseRate[1];
1187 if(offset1 + ind1*coarseRate[1] > gFineNodesPerDir[1] - 1) {
1188 offset1 += (ind1 - 1)*coarseRate[1] + endRate[1];
1190 offset1 += ind1*coarseRate[1];
1192 offset1 = offset1*gFineNodesPerDir[0];
1193 for(LO ind0 = 0; ind0 < lCoarseNodesPerDir[0]; ++ind0) {
1194 offset0 = startingIndices[0];
1195 if(myOffset[0] == 0) {
1196 offset0 += ind0*coarseRate[0];
1198 offset0 += (ind0 + 1)*coarseRate[0];
1200 if(offset0 > gFineNodesPerDir[0] - 1) {offset0 += endRate[0] - coarseRate[0];}
1202 currentNode = ind2*lCoarseNodesPerDir[1]*lCoarseNodesPerDir[0]
1203 + ind1*lCoarseNodesPerDir[0]
1205 gCoarseNodesGIDs[currentNode] = offset2 + offset1 + offset0;
1212 colGIDs.resize(BlkSize*(lNumCoarseNodes+lNumGhostNodes));
1213 coarseNodesGIDs.resize(lNumCoarseNodes);
1214 for(LO i = 0; i < numDimensions; ++i) {coarseNodes[i].resize(lNumCoarseNodes);}
1215 GO fineNodesPerCoarseSlab = coarseRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
1216 GO fineNodesEndCoarseSlab = endRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
1217 GO fineNodesPerCoarsePlane = coarseRate[1]*gFineNodesPerDir[0];
1218 GO fineNodesEndCoarsePlane = endRate[1]*gFineNodesPerDir[0];
1219 GO coarseNodesPerCoarseLayer = gCoarseNodesPerDir[1]*gCoarseNodesPerDir[0];
1220 GO gCoarseNodeOnCoarseGridGID;
1222 Array<int> ghostPIDs (lNumGhostNodes);
1223 Array<LO> ghostLIDs (lNumGhostNodes);
1224 Array<LO> ghostPermut(lNumGhostNodes);
1225 for(LO k = 0; k < lNumGhostNodes; ++k) {ghostPermut[k] = k;}
1226 coordinatesMap->getRemoteIndexList(ghostGIDs, ghostPIDs, ghostLIDs);
1227 sh_sort_permute(ghostPIDs.begin(),ghostPIDs.end(), ghostPermut.begin(),ghostPermut.end());
1230 GO tmpInds[3], tmpVars[2];
1238 LO firstCoarseNodeInds[3], currentCoarseNode;
1239 for(LO dim = 0; dim < 3; ++dim) {
1240 if(myOffset[dim] == 0) {
1241 firstCoarseNodeInds[dim] = 0;
1243 firstCoarseNodeInds[dim] = coarseRate[dim] - myOffset[dim];
1246 Array<ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> > fineNodes(numDimensions);
1247 for(LO dim = 0; dim < numDimensions; ++dim) {fineNodes[dim] = coordinates->getData(dim);}
1248 for(LO k = 0; k < lCoarseNodesPerDir[2]; ++k) {
1249 for(LO j = 0; j < lCoarseNodesPerDir[1]; ++j) {
1250 for(LO i = 0; i < lCoarseNodesPerDir[0]; ++i) {
1251 col = k*lCoarseNodesPerDir[1]*lCoarseNodesPerDir[0] + j*lCoarseNodesPerDir[0] + i;
1254 currentCoarseNode = 0;
1255 if(firstCoarseNodeInds[0] + i*coarseRate[0] > lFineNodesPerDir[0] - 1) {
1256 currentCoarseNode += firstCoarseNodeInds[0] + (i-1)*coarseRate[0] + endRate[0];
1258 currentCoarseNode += firstCoarseNodeInds[0] + i*coarseRate[0];
1260 if(firstCoarseNodeInds[1] + j*coarseRate[1] > lFineNodesPerDir[1] - 1) {
1261 currentCoarseNode += (firstCoarseNodeInds[1] + (j-1)*coarseRate[1] + endRate[1])
1262 *lFineNodesPerDir[0];
1264 currentCoarseNode += (firstCoarseNodeInds[1] + j*coarseRate[1])*lFineNodesPerDir[0];
1266 if(firstCoarseNodeInds[2] + k*coarseRate[2] > lFineNodesPerDir[2] - 1) {
1267 currentCoarseNode += (firstCoarseNodeInds[2] + (k-1)*coarseRate[2] + endRate[2])
1268 *lFineNodesPerDir[1]*lFineNodesPerDir[0];
1270 currentCoarseNode += (firstCoarseNodeInds[2] + k*coarseRate[2])
1271 *lFineNodesPerDir[1]*lFineNodesPerDir[0];
1274 for(LO dim = 0; dim < numDimensions; ++dim) {
1275 coarseNodes[dim][col] = fineNodes[dim][currentCoarseNode];
1278 if((endRate[2] != coarseRate[2])
1279 && (gCoarseNodesGIDs[col] > (gCoarseNodesPerDir[2] - 2)*fineNodesPerCoarseSlab
1280 + fineNodesEndCoarseSlab - 1)) {
1281 tmpInds[2] = gCoarseNodesGIDs[col] / fineNodesPerCoarseSlab + 1;
1282 tmpVars[0] = gCoarseNodesGIDs[col] - (tmpInds[2] - 1)*fineNodesPerCoarseSlab
1283 - fineNodesEndCoarseSlab;
1285 tmpInds[2] = gCoarseNodesGIDs[col] / fineNodesPerCoarseSlab;
1286 tmpVars[0] = gCoarseNodesGIDs[col] % fineNodesPerCoarseSlab;
1288 if((endRate[1] != coarseRate[1])
1289 && (tmpVars[0] > (gCoarseNodesPerDir[1] - 2)*fineNodesPerCoarsePlane
1290 + fineNodesEndCoarsePlane - 1)) {
1291 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane + 1;
1292 tmpVars[1] = tmpVars[0] - (tmpInds[1] - 1)*fineNodesPerCoarsePlane
1293 - fineNodesEndCoarsePlane;
1295 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane;
1296 tmpVars[1] = tmpVars[0] % fineNodesPerCoarsePlane;
1298 if(tmpVars[1] == gFineNodesPerDir[0] - 1) {
1299 tmpInds[0] = gCoarseNodesPerDir[0] - 1;
1301 tmpInds[0] = tmpVars[1] / coarseRate[0];
1303 gInd[2] = col / (lCoarseNodesPerDir[1]*lCoarseNodesPerDir[0]);
1304 tmp = col % (lCoarseNodesPerDir[1]*lCoarseNodesPerDir[0]);
1305 gInd[1] = tmp / lCoarseNodesPerDir[0];
1306 gInd[0] = tmp % lCoarseNodesPerDir[0];
1307 lCol = gInd[2]*(lCoarseNodesPerDir[1]*lCoarseNodesPerDir[0])
1308 + gInd[1]*lCoarseNodesPerDir[0] + gInd[0];
1309 gCoarseNodeOnCoarseGridGID = tmpInds[2]*coarseNodesPerCoarseLayer
1310 + tmpInds[1]*gCoarseNodesPerDir[0] + tmpInds[0];
1311 coarseNodesGIDs[lCol] = gCoarseNodeOnCoarseGridGID;
1312 for(LO dof = 0; dof < BlkSize; ++dof) {
1313 colGIDs[BlkSize*lCol + dof] = BlkSize*gCoarseNodeOnCoarseGridGID + dof;
1320 for(col = lNumCoarseNodes; col < lNumCoarseNodes + lNumGhostNodes; ++col) {
1321 if((endRate[2] != coarseRate[2])
1322 && (ghostGIDs[ghostPermut[col - lNumCoarseNodes]] > (gCoarseNodesPerDir[2] - 2)
1323 *fineNodesPerCoarseSlab + fineNodesEndCoarseSlab - 1)) {
1324 tmpInds[2] = ghostGIDs[ghostPermut[col - lNumCoarseNodes]] / fineNodesPerCoarseSlab + 1;
1325 tmpVars[0] = ghostGIDs[ghostPermut[col - lNumCoarseNodes]]
1326 - (tmpInds[2] - 1)*fineNodesPerCoarseSlab - fineNodesEndCoarseSlab;
1328 tmpInds[2] = ghostGIDs[ghostPermut[col - lNumCoarseNodes]] / fineNodesPerCoarseSlab;
1329 tmpVars[0] = ghostGIDs[ghostPermut[col - lNumCoarseNodes]] % fineNodesPerCoarseSlab;
1331 if((endRate[1] != coarseRate[1])
1332 && (tmpVars[0] > (gCoarseNodesPerDir[1] - 2)*fineNodesPerCoarsePlane
1333 + fineNodesEndCoarsePlane - 1)) {
1334 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane + 1;
1335 tmpVars[1] = tmpVars[0] - (tmpInds[1] - 1)*fineNodesPerCoarsePlane
1336 - fineNodesEndCoarsePlane;
1338 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane;
1339 tmpVars[1] = tmpVars[0] % fineNodesPerCoarsePlane;
1341 if(tmpVars[1] == gFineNodesPerDir[0] - 1) {
1342 tmpInds[0] = gCoarseNodesPerDir[0] - 1;
1344 tmpInds[0] = tmpVars[1] / coarseRate[0];
1346 gCoarseNodeOnCoarseGridGID = tmpInds[2]*coarseNodesPerCoarseLayer
1347 + tmpInds[1]*gCoarseNodesPerDir[0] + tmpInds[0];
1348 for(LO dof = 0; dof < BlkSize; ++dof) {
1349 colGIDs[BlkSize*col + dof] = BlkSize*gCoarseNodeOnCoarseGridGID + dof;
1359 const Array<LO> ,
const LO BlkSize,
const Array<LO> elemInds,
1360 const Array<LO> ,
const LO numDimensions,
1361 const Array<LO> lFineNodesPerDir,
const Array<GO> ,
1362 const Array<GO> ,
const Array<LO> ,
1363 const Array<bool> ghostInterface,
const Array<int> elementFlags,
1364 const std::string stencilType,
const std::string ,
1365 const Array<LO> elementNodesPerDir,
const LO numNodesInElement,
1367 Teuchos::SerialDenseMatrix<LO,SC>& Pi, Teuchos::SerialDenseMatrix<LO,SC>& Pf,
1368 Teuchos::SerialDenseMatrix<LO,SC>& Pe, Array<LO>& dofType,
1369 Array<LO>& lDofInd)
const {
1380 LO countInterior=0, countFace=0, countEdge=0, countCorner =0;
1381 Array<LO> collapseDir(numNodesInElement*BlkSize);
1382 for(LO ke = 0; ke < elementNodesPerDir[2]; ++ke) {
1383 for(LO je = 0; je < elementNodesPerDir[1]; ++je) {
1384 for(LO ie = 0; ie < elementNodesPerDir[0]; ++ie) {
1386 if((ke == 0 || ke == elementNodesPerDir[2]-1)
1387 && (je == 0 || je == elementNodesPerDir[1]-1)
1388 && (ie == 0 || ie == elementNodesPerDir[0]-1)) {
1389 for(LO dof = 0; dof < BlkSize; ++dof) {
1390 dofType[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1391 + je*elementNodesPerDir[0] + ie) + dof] = 0;
1392 lDofInd[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1393 + je*elementNodesPerDir[0] + ie) + dof] = BlkSize*countCorner + dof;
1398 }
else if (((ke == 0 || ke == elementNodesPerDir[2]-1)
1399 && (je == 0 || je == elementNodesPerDir[1]-1))
1400 || ((ke == 0 || ke == elementNodesPerDir[2]-1)
1401 && (ie == 0 || ie == elementNodesPerDir[0]-1))
1402 || ((je == 0 || je == elementNodesPerDir[1]-1)
1403 && (ie == 0 || ie == elementNodesPerDir[0]-1))) {
1404 for(LO dof = 0; dof < BlkSize; ++dof) {
1405 dofType[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1406 + je*elementNodesPerDir[0] + ie) + dof] = 1;
1407 lDofInd[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1408 + je*elementNodesPerDir[0] + ie) + dof] = BlkSize*countEdge + dof;
1409 if((ke == 0 || ke == elementNodesPerDir[2]-1)
1410 && (je == 0 || je == elementNodesPerDir[1]-1)) {
1411 collapseDir[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1412 + je*elementNodesPerDir[0] + ie) + dof] = 0;
1413 }
else if((ke == 0 || ke == elementNodesPerDir[2]-1)
1414 && (ie == 0 || ie == elementNodesPerDir[0]-1)) {
1415 collapseDir[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1416 + je*elementNodesPerDir[0] + ie) + dof] = 1;
1417 }
else if((je == 0 || je == elementNodesPerDir[1]-1
1418 ) && (ie == 0 || ie == elementNodesPerDir[0]-1)) {
1419 collapseDir[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1420 + je*elementNodesPerDir[0] + ie) + dof] = 2;
1426 }
else if ((ke == 0 || ke == elementNodesPerDir[2]-1)
1427 || (je == 0 || je == elementNodesPerDir[1]-1)
1428 || (ie == 0 || ie == elementNodesPerDir[0]-1)) {
1429 for(LO dof = 0; dof < BlkSize; ++dof) {
1430 dofType[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1431 + je*elementNodesPerDir[0] + ie) + dof] = 2;
1432 lDofInd[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1433 + je*elementNodesPerDir[0] + ie) + dof] = BlkSize*countFace + dof;
1434 if(ke == 0 || ke == elementNodesPerDir[2]-1) {
1435 collapseDir[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1436 + je*elementNodesPerDir[0] + ie) + dof] = 2;
1437 }
else if(je == 0 || je == elementNodesPerDir[1]-1) {
1438 collapseDir[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1439 + je*elementNodesPerDir[0] + ie) + dof] = 1;
1440 }
else if(ie == 0 || ie == elementNodesPerDir[0]-1) {
1441 collapseDir[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1442 + je*elementNodesPerDir[0] + ie) + dof] = 0;
1449 for(LO dof = 0; dof < BlkSize; ++dof) {
1450 dofType[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1451 + je*elementNodesPerDir[0] + ie) + dof] = 3;
1452 lDofInd[BlkSize*(ke*elementNodesPerDir[1]*elementNodesPerDir[0]
1453 + je*elementNodesPerDir[0] + ie) + dof] = BlkSize*countInterior +dof;
1461 LO numInteriorNodes = 0, numFaceNodes = 0, numEdgeNodes = 0, numCornerNodes = 8;
1462 numInteriorNodes = (elementNodesPerDir[0] - 2)*(elementNodesPerDir[1] - 2)
1463 *(elementNodesPerDir[2] - 2);
1464 numFaceNodes = 2*(elementNodesPerDir[0] - 2)*(elementNodesPerDir[1] - 2)
1465 + 2*(elementNodesPerDir[0] - 2)*(elementNodesPerDir[2] - 2)
1466 + 2*(elementNodesPerDir[1] - 2)*(elementNodesPerDir[2] - 2);
1467 numEdgeNodes = 4*(elementNodesPerDir[0] - 2) + 4*(elementNodesPerDir[1] - 2)
1468 + 4*(elementNodesPerDir[2] - 2);
1470 Teuchos::SerialDenseMatrix<LO,SC> Aii(BlkSize*numInteriorNodes, BlkSize*numInteriorNodes);
1471 Teuchos::SerialDenseMatrix<LO,SC> Aff(BlkSize*numFaceNodes, BlkSize*numFaceNodes);
1472 Teuchos::SerialDenseMatrix<LO,SC> Aee(BlkSize*numEdgeNodes, BlkSize*numEdgeNodes);
1474 Teuchos::SerialDenseMatrix<LO,SC> Aif(BlkSize*numInteriorNodes, BlkSize*numFaceNodes);
1475 Teuchos::SerialDenseMatrix<LO,SC> Aie(BlkSize*numInteriorNodes, BlkSize*numEdgeNodes);
1476 Teuchos::SerialDenseMatrix<LO,SC> Afe(BlkSize*numFaceNodes, BlkSize*numEdgeNodes);
1478 Teuchos::SerialDenseMatrix<LO,SC> Aic(BlkSize*numInteriorNodes, BlkSize*numCornerNodes);
1479 Teuchos::SerialDenseMatrix<LO,SC> Afc(BlkSize*numFaceNodes, BlkSize*numCornerNodes);
1480 Teuchos::SerialDenseMatrix<LO,SC> Aec(BlkSize*numEdgeNodes, BlkSize*numCornerNodes);
1481 Pi.shape( BlkSize*numInteriorNodes, BlkSize*numCornerNodes);
1482 Pf.shape( BlkSize*numFaceNodes, BlkSize*numCornerNodes);
1483 Pe.shape( BlkSize*numEdgeNodes, BlkSize*numCornerNodes);
1485 ArrayView<const LO> rowIndices;
1486 ArrayView<const SC> rowValues;
1487 LO idof, iInd, jInd;
1488 int iType = 0, jType = 0;
1489 int orientation = -1;
1490 int collapseFlags[3] = {};
1491 Array<SC> stencil((std::pow(3,numDimensions))*BlkSize);
1495 for(LO ke = 0; ke < elementNodesPerDir[2]; ++ke) {
1496 for(LO je = 0; je < elementNodesPerDir[1]; ++je) {
1497 for(LO ie = 0; ie < elementNodesPerDir[0]; ++ie) {
1498 collapseFlags[0] = 0; collapseFlags[1] = 0; collapseFlags[2] = 0;
1499 if((elementFlags[0] == 1 || elementFlags[0] == 3) && ie == 0) {
1500 collapseFlags[0] += 1;
1502 if((elementFlags[0] == 2 || elementFlags[0] == 3) && ie == elementNodesPerDir[0] - 1) {
1503 collapseFlags[0] += 2;
1505 if((elementFlags[1] == 1 || elementFlags[1] == 3) && je == 0) {
1506 collapseFlags[1] += 1;
1508 if((elementFlags[1] == 2 || elementFlags[1] == 3) && je == elementNodesPerDir[1] - 1) {
1509 collapseFlags[1] += 2;
1511 if((elementFlags[2] == 1 || elementFlags[2] == 3) && ke == 0) {
1512 collapseFlags[2] += 1;
1514 if((elementFlags[2] == 2 || elementFlags[2] == 3) && ke == elementNodesPerDir[2] - 1) {
1515 collapseFlags[2] += 2;
1519 GetNodeInfo(ie, je, ke, elementNodesPerDir, &iType, iInd, &orientation);
1520 for(LO dof0 = 0; dof0 < BlkSize; ++dof0) {
1522 idof = ((elemInds[2]*coarseRate[2] + ke)*lFineNodesPerDir[1]*lFineNodesPerDir[0]
1523 + (elemInds[1]*coarseRate[1] + je)*lFineNodesPerDir[0]
1524 + elemInds[0]*coarseRate[0] + ie)*BlkSize + dof0;
1525 Aghost->getLocalRowView(idof, rowIndices, rowValues);
1526 FormatStencil(BlkSize, ghostInterface, ie, je, ke, rowValues,
1527 elementNodesPerDir, collapseFlags, stencilType, stencil);
1530 for(LO interactingNode = 0; interactingNode < 27; ++interactingNode) {
1532 ko = ke + (interactingNode / 9 - 1);
1534 LO tmp = interactingNode % 9;
1535 jo = je + (tmp / 3 - 1);
1536 io = ie + (tmp % 3 - 1);
1538 GetNodeInfo(io, jo, ko, elementNodesPerDir, &jType, jInd, &dummy);
1540 if((io > -1 && io < elementNodesPerDir[0]) &&
1541 (jo > -1 && jo < elementNodesPerDir[1]) &&
1542 (ko > -1 && ko < elementNodesPerDir[2])) {
1543 for(LO dof1 = 0; dof1 < BlkSize; ++dof1) {
1545 Aii(iInd*BlkSize + dof0, jInd*BlkSize + dof1) =
1546 stencil[interactingNode*BlkSize + dof1];
1547 }
else if(jType == 2) {
1548 Aif(iInd*BlkSize + dof0, jInd*BlkSize + dof1) =
1549 stencil[interactingNode*BlkSize + dof1];
1550 }
else if(jType == 1) {
1551 Aie(iInd*BlkSize + dof0, jInd*BlkSize + dof1) =
1552 stencil[interactingNode*BlkSize + dof1];
1553 }
else if(jType == 0) {
1554 Aic(iInd*BlkSize + dof0, jInd*BlkSize + dof1) =
1555 -stencil[interactingNode*BlkSize + dof1];
1560 }
else if(iType == 2) {
1562 for(LO interactingNode = 0; interactingNode < 27; ++interactingNode) {
1564 ko = ke + (interactingNode / 9 - 1);
1566 LO tmp = interactingNode % 9;
1567 jo = je + (tmp / 3 - 1);
1568 io = ie + (tmp % 3 - 1);
1570 GetNodeInfo(io, jo, ko, elementNodesPerDir, &jType, jInd, &dummy);
1572 if((io > -1 && io < elementNodesPerDir[0]) &&
1573 (jo > -1 && jo < elementNodesPerDir[1]) &&
1574 (ko > -1 && ko < elementNodesPerDir[2])) {
1575 for(LO dof1 = 0; dof1 < BlkSize; ++dof1) {
1577 Aff(iInd*BlkSize + dof0, jInd*BlkSize + dof1) =
1578 stencil[interactingNode*BlkSize + dof1];
1579 }
else if(jType == 1) {
1580 Afe(iInd*BlkSize + dof0, jInd*BlkSize + dof1) =
1581 stencil[interactingNode*BlkSize + dof1];
1582 }
else if(jType == 0) {
1583 Afc(iInd*BlkSize + dof0, jInd*BlkSize + dof1) =
1584 -stencil[interactingNode*BlkSize + dof1];
1589 }
else if(iType == 1) {
1591 for(LO interactingNode = 0; interactingNode < 27; ++interactingNode) {
1593 ko = ke + (interactingNode / 9 - 1);
1595 LO tmp = interactingNode % 9;
1596 jo = je + (tmp / 3 - 1);
1597 io = ie + (tmp % 3 - 1);
1599 GetNodeInfo(io, jo, ko, elementNodesPerDir, &jType, jInd, &dummy);
1601 if((io > -1 && io < elementNodesPerDir[0]) &&
1602 (jo > -1 && jo < elementNodesPerDir[1]) &&
1603 (ko > -1 && ko < elementNodesPerDir[2])) {
1604 for(LO dof1 = 0; dof1 < BlkSize; ++dof1) {
1606 Aee(iInd*BlkSize + dof0, jInd*BlkSize + dof1) =
1607 stencil[interactingNode*BlkSize + dof1];
1608 }
else if(jType == 0) {
1609 Aec(iInd*BlkSize + dof0, jInd*BlkSize + dof1) =
1610 -stencil[interactingNode*BlkSize + dof1];
1631 Teuchos::SerialDenseSolver<LO,SC> problem;
1632 problem.setMatrix(Teuchos::rcp(&Aee,
false));
1633 problem.setVectors(Teuchos::rcp(&Pe,
false), Teuchos::rcp(&Aec,
false));
1634 problem.factorWithEquilibration(
true);
1636 problem.unequilibrateLHS();
1642 Afc.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, -1.0, Afe, Pe, 1.0);
1644 Teuchos::SerialDenseSolver<LO,SC> problem;
1645 problem.setMatrix(Teuchos::rcp(&Aff,
false));
1646 problem.setVectors(Teuchos::rcp(&Pf,
false), Teuchos::rcp(&Afc,
false));
1647 problem.factorWithEquilibration(
true);
1649 problem.unequilibrateLHS();
1655 Aic.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, -1.0, Aie, Pe, 1.0);
1657 Aic.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, -1.0, Aif, Pf, 1.0);
1659 Teuchos::SerialDenseSolver<LO,SC> problem;
1660 problem.setMatrix(Teuchos::rcp(&Aii,
false));
1661 problem.setVectors(Teuchos::rcp(&Pi,
false), Teuchos::rcp(&Aic,
false));
1662 problem.factorWithEquilibration(
true);
1664 problem.unequilibrateLHS();