100 Level& coarseLevel)
const {
104 const ParameterList& pL = GetParameterList();
107 RCP<Matrix> A = Get<RCP<Matrix> >(fineLevel,
"A");
108 RCP<MultiVector> fineNullspace = Get<RCP<MultiVector> >(fineLevel,
"Nullspace");
109 RCP<Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO> > coordinates =
110 Get<RCP<Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO> > >(fineLevel,
"Coordinates");
111 LO numDimensions = coordinates->getNumVectors();
112 LO BlkSize = A->GetFixedBlockSize();
115 Array<GO> gFineNodesPerDir(3);
116 Array<LO> lFineNodesPerDir(3);
123 gFineNodesPerDir = Get<Array<GO> >(fineLevel,
"gNodesPerDim");
126 lFineNodesPerDir = Get<Array<LO> >(fineLevel,
"lNodesPerDim");
128 for (LO i = 0; i < 3; ++i) {
129 if (gFineNodesPerDir[i] == 0) {
130 GetOStream(
Runtime0) <<
"gNodesPerDim in direction " << i <<
" is set to 1 from 0"
132 gFineNodesPerDir[i] = 1;
134 if (lFineNodesPerDir[i] == 0) {
135 GetOStream(
Runtime0) <<
"lNodesPerDim in direction " << i <<
" is set to 1 from 0"
137 lFineNodesPerDir[i] = 1;
140 GO gNumFineNodes = gFineNodesPerDir[2] * gFineNodesPerDir[1] * gFineNodesPerDir[0];
141 LO lNumFineNodes = lFineNodesPerDir[2] * lFineNodesPerDir[1] * lFineNodesPerDir[0];
144 std::string coarsenRate = pL.get<std::string>(
"Coarsen");
145 Array<LO> coarseRate(3);
147 Teuchos::Array<LO> crates;
149 crates = Teuchos::fromStringToArray<LO>(coarsenRate);
150 }
catch (
const Teuchos::InvalidArrayStringRepresentation& e) {
151 GetOStream(
Errors, -1) <<
" *** Coarsen must be a string convertible into an array! *** "
155 TEUCHOS_TEST_FOR_EXCEPTION((crates.size() > 1) && (crates.size() < numDimensions),
157 "Coarsen must have at least as many components as the number of"
158 " spatial dimensions in the problem.");
159 for (LO i = 0; i < 3; ++i) {
160 if (i < numDimensions) {
161 if (crates.size() == 1) {
162 coarseRate[i] = crates[0];
163 }
else if (i < crates.size()) {
164 coarseRate[i] = crates[i];
166 GetOStream(
Errors, -1) <<
" *** Coarsen must be at least as long as the number of"
167 " spatial dimensions! *** "
170 " *** Coarsen must be at least as long as the number of"
171 " spatial dimensions! *** \n");
180 const std::string stencilType = pL.get<std::string>(
"stencil type");
181 if (stencilType !=
"full" && stencilType !=
"reduced") {
182 GetOStream(
Errors, -1) <<
" *** stencil type must be set to: full or reduced, any other value "
183 "is trated as an error! *** "
189 const std::string blockStrategy = pL.get<std::string>(
"block strategy");
190 if (blockStrategy !=
"coupled" && blockStrategy !=
"uncoupled") {
191 GetOStream(
Errors, -1) <<
" *** block strategy must be set to: coupled or uncoupled, any other "
192 "value is trated as an error! *** "
197 GO gNumCoarseNodes = 0;
198 LO lNumCoarseNodes = 0;
199 Array<GO> gIndices(3), gCoarseNodesPerDir(3), ghostGIDs, coarseNodesGIDs, colGIDs;
200 Array<LO> myOffset(3), lCoarseNodesPerDir(3), glCoarseNodesPerDir(3), endRate(3);
201 Array<bool> ghostInterface(6);
202 Array<int> boundaryFlags(3);
203 ArrayRCP<Array<typename Teuchos::ScalarTraits<Scalar>::magnitudeType> > coarseNodes(numDimensions);
204 Array<ArrayView<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> > fineNodes(numDimensions);
205 for (LO dim = 0; dim < numDimensions; ++dim) {
206 fineNodes[dim] = coordinates->getData(dim)();
210 RCP<NodesIDs> ghostedCoarseNodes = rcp(
new NodesIDs{});
212 GetGeometricData(coordinates, coarseRate, gFineNodesPerDir, lFineNodesPerDir, BlkSize,
213 gIndices, myOffset, ghostInterface, endRate, gCoarseNodesPerDir,
214 lCoarseNodesPerDir, glCoarseNodesPerDir, ghostGIDs, coarseNodesGIDs, colGIDs,
215 gNumCoarseNodes, lNumCoarseNodes, coarseNodes, boundaryFlags,
219 Xpetra::UnderlyingLib lib = coordinates->getMap()->lib();
220 RCP<const Map> coarseCoordsMap = MapFactory::Build(lib,
222 coarseNodesGIDs.view(0, lNumCoarseNodes),
223 coordinates->getMap()->getIndexBase(),
224 coordinates->getMap()->getComm());
225 Array<ArrayView<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> > coarseCoords(numDimensions);
226 for (LO dim = 0; dim < numDimensions; ++dim) {
227 coarseCoords[dim] = coarseNodes[dim]();
229 RCP<Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO> > coarseCoordinates =
230 Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO>::Build(coarseCoordsMap, coarseCoords(),
263 Array<GO> ghostRowGIDs, ghostColGIDs, nodeSteps(3);
265 nodeSteps[1] = gFineNodesPerDir[0];
266 nodeSteps[2] = gFineNodesPerDir[0] * gFineNodesPerDir[1];
267 Array<LO> glFineNodesPerDir(3);
268 GO startingGID = A->getRowMap()->getMinGlobalIndex();
269 for (LO dim = 0; dim < 3; ++dim) {
270 LO numCoarseNodes = 0;
271 if (dim < numDimensions) {
272 startingGID -= myOffset[dim] * nodeSteps[dim];
273 numCoarseNodes = lCoarseNodesPerDir[dim];
274 if (ghostInterface[2 * dim]) {
277 if (ghostInterface[2 * dim + 1]) {
280 if (gIndices[dim] + lFineNodesPerDir[dim] == gFineNodesPerDir[dim]) {
281 glFineNodesPerDir[dim] = (numCoarseNodes - 2) * coarseRate[dim] + endRate[dim] + 1;
283 glFineNodesPerDir[dim] = (numCoarseNodes - 1) * coarseRate[dim] + 1;
286 glFineNodesPerDir[dim] = 1;
289 ghostRowGIDs.resize(glFineNodesPerDir[0] * glFineNodesPerDir[1] * glFineNodesPerDir[2] * BlkSize);
290 for (LO k = 0; k < glFineNodesPerDir[2]; ++k) {
291 for (LO j = 0; j < glFineNodesPerDir[1]; ++j) {
292 for (LO i = 0; i < glFineNodesPerDir[0]; ++i) {
293 for (LO l = 0; l < BlkSize; ++l) {
294 ghostRowGIDs[(k * glFineNodesPerDir[1] * glFineNodesPerDir[0] + j * glFineNodesPerDir[0] + i) * BlkSize + l] = startingGID + (k * gFineNodesPerDir[1] * gFineNodesPerDir[0] + j * gFineNodesPerDir[0] + i) * BlkSize + l;
301 Array<GO> startingGlobalIndices(numDimensions), dimStride(numDimensions);
302 Array<GO> startingColIndices(numDimensions), finishingColIndices(numDimensions);
304 Array<LO> colRange(numDimensions);
306 for (
int dim = 1; dim < numDimensions; ++dim) {
307 dimStride[dim] = dimStride[dim - 1] * gFineNodesPerDir[dim - 1];
310 GO tmp = startingGID;
311 for (
int dim = numDimensions; dim > 0; --dim) {
312 startingGlobalIndices[dim - 1] = tmp / dimStride[dim - 1];
313 tmp = tmp % dimStride[dim - 1];
315 if (startingGlobalIndices[dim - 1] > 0) {
316 startingColIndices[dim - 1] = startingGlobalIndices[dim - 1] - 1;
318 if (startingGlobalIndices[dim - 1] + glFineNodesPerDir[dim - 1] < gFineNodesPerDir[dim - 1]) {
319 finishingColIndices[dim - 1] = startingGlobalIndices[dim - 1] + glFineNodesPerDir[dim - 1];
321 finishingColIndices[dim - 1] = startingGlobalIndices[dim - 1] + glFineNodesPerDir[dim - 1] - 1;
323 colRange[dim - 1] = finishingColIndices[dim - 1] - startingColIndices[dim - 1] + 1;
324 colMinGID += startingColIndices[dim - 1] * dimStride[dim - 1];
327 ghostColGIDs.resize(colRange[0] * colRange[1] * colRange[2] * BlkSize);
328 for (LO k = 0; k < colRange[2]; ++k) {
329 for (LO j = 0; j < colRange[1]; ++j) {
330 for (LO i = 0; i < colRange[0]; ++i) {
331 for (LO l = 0; l < BlkSize; ++l) {
332 ghostColGIDs[(k * colRange[1] * colRange[0] + j * colRange[0] + i) * BlkSize + l] = colMinGID + (k * gFineNodesPerDir[1] * gFineNodesPerDir[0] + j * gFineNodesPerDir[0] + i) * BlkSize + l;
338 RCP<const Map> ghostedRowMap = Xpetra::MapFactory<LO, GO, NO>::Build(A->getRowMap()->lib(),
339 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
341 A->getRowMap()->getIndexBase(),
342 A->getRowMap()->getComm());
343 RCP<const Map> ghostedColMap = Xpetra::MapFactory<LO, GO, NO>::Build(A->getRowMap()->lib(),
344 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
346 A->getRowMap()->getIndexBase(),
347 A->getRowMap()->getComm());
348 RCP<const Import> ghostImporter = Xpetra::ImportFactory<LO, GO, NO>::Build(A->getRowMap(),
350 RCP<const Matrix> Aghost = Xpetra::MatrixFactory<SC, LO, GO, NO>::Build(A, *ghostImporter,
355 RCP<const Map> rowMapP = A->getDomainMap();
357 RCP<const Map> domainMapP;
359 RCP<const Map> colMapP;
370 LO lNumGhostedNodes = ghostedCoarseNodes->GIDs.size();
372 std::vector<NodeID> colMapOrdering(lNumGhostedNodes);
373 for (LO ind = 0; ind < lNumGhostedNodes; ++ind) {
374 colMapOrdering[ind].GID = ghostedCoarseNodes->GIDs[ind];
375 if (ghostedCoarseNodes->PIDs[ind] == rowMapP->getComm()->getRank()) {
376 colMapOrdering[ind].PID = -1;
378 colMapOrdering[ind].PID = ghostedCoarseNodes->PIDs[ind];
380 colMapOrdering[ind].LID = ghostedCoarseNodes->LIDs[ind];
381 colMapOrdering[ind].lexiInd = ind;
383 std::sort(colMapOrdering.begin(), colMapOrdering.end(),
385 return ((a.PID < b.PID) || ((a.PID == b.PID) && (a.GID < b.GID)));
388 colGIDs.resize(BlkSize * lNumGhostedNodes);
389 for (LO ind = 0; ind < lNumGhostedNodes; ++ind) {
391 ghostedCoarseNodes->colInds[colMapOrdering[ind].lexiInd] = ind;
392 for (LO dof = 0; dof < BlkSize; ++dof) {
393 colGIDs[BlkSize * ind + dof] = BlkSize * colMapOrdering[ind].GID + dof;
396 domainMapP = Xpetra::MapFactory<LO, GO, NO>::Build(rowMapP->lib(),
397 BlkSize * gNumCoarseNodes,
398 colGIDs.view(0, BlkSize * lNumCoarseNodes),
399 rowMapP->getIndexBase(),
401 colMapP = Xpetra::MapFactory<LO, GO, NO>::Build(rowMapP->lib(),
402 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
403 colGIDs.view(0, colGIDs.size()),
404 rowMapP->getIndexBase(),
408 std::vector<size_t> strideInfo(1);
409 strideInfo[0] = BlkSize;
410 RCP<const Map> stridedDomainMapP = Xpetra::StridedMapFactory<LO, GO, NO>::Build(domainMapP,
416 gnnzP += gNumCoarseNodes;
417 lnnzP += lNumCoarseNodes;
419 gnnzP += (gNumFineNodes - gNumCoarseNodes) * std::pow(2, numDimensions);
420 lnnzP += (lNumFineNodes - lNumCoarseNodes) * std::pow(2, numDimensions);
422 gnnzP = gnnzP * BlkSize;
423 lnnzP = lnnzP * BlkSize;
427 P = rcp(
new CrsMatrixWrap(rowMapP, colMapP, 0));
428 RCP<CrsMatrix> PCrs = toCrsMatrix(P);
430 ArrayRCP<size_t> iaP;
434 PCrs->allocateAllValues(lnnzP, iaP, jaP, valP);
436 ArrayView<size_t> ia = iaP();
437 ArrayView<LO> ja = jaP();
438 ArrayView<SC> val = valP();
441 LO numCoarseElements = 1;
442 Array<LO> lCoarseElementsPerDir(3);
443 for (LO dim = 0; dim < numDimensions; ++dim) {
444 lCoarseElementsPerDir[dim] = lCoarseNodesPerDir[dim];
445 if (ghostInterface[2 * dim]) {
446 ++lCoarseElementsPerDir[dim];
448 if (!ghostInterface[2 * dim + 1]) {
449 --lCoarseElementsPerDir[dim];
451 numCoarseElements = numCoarseElements * lCoarseElementsPerDir[dim];
454 for (LO dim = numDimensions; dim < 3; ++dim) {
455 lCoarseElementsPerDir[dim] = 1;
459 Array<int> elementFlags(3);
460 Array<LO> elemInds(3), elementNodesPerDir(3), glElementRefTuple(3);
461 Array<LO> glElementRefTupleCG(3), glElementCoarseNodeCG(8);
462 const int numCoarseNodesInElement = std::pow(2, numDimensions);
463 const int nnzPerCoarseNode = (blockStrategy ==
"coupled") ? BlkSize : 1;
464 const int numRowsPerPoint = BlkSize;
465 for (elemInds[2] = 0; elemInds[2] < lCoarseElementsPerDir[2]; ++elemInds[2]) {
466 for (elemInds[1] = 0; elemInds[1] < lCoarseElementsPerDir[1]; ++elemInds[1]) {
467 for (elemInds[0] = 0; elemInds[0] < lCoarseElementsPerDir[0]; ++elemInds[0]) {
471 for (
int dim = 0; dim < 3; ++dim) {
473 if (elemInds[dim] == 0 && elemInds[dim] == lCoarseElementsPerDir[dim] - 1) {
474 elementFlags[dim] = boundaryFlags[dim];
475 }
else if (elemInds[dim] == 0 && (boundaryFlags[dim] == 1 || boundaryFlags[dim] == 3)) {
476 elementFlags[dim] += 1;
477 }
else if ((elemInds[dim] == lCoarseElementsPerDir[dim] - 1) && (boundaryFlags[dim] == 2 || boundaryFlags[dim] == 3)) {
478 elementFlags[dim] += 2;
480 elementFlags[dim] = 0;
484 if (dim < numDimensions) {
485 if ((elemInds[dim] == lCoarseElementsPerDir[dim]) && (gIndices[dim] + lFineNodesPerDir[dim] == gFineNodesPerDir[dim])) {
486 elementNodesPerDir[dim] = endRate[dim] + 1;
488 elementNodesPerDir[dim] = coarseRate[dim] + 1;
491 elementNodesPerDir[dim] = 1;
495 glElementRefTuple[dim] = elemInds[dim] * coarseRate[dim];
496 glElementRefTupleCG[dim] = elemInds[dim];
501 for (
typename Array<LO>::size_type elem = 0; elem < glElementCoarseNodeCG.size(); ++elem) {
502 glElementCoarseNodeCG[elem] = glElementRefTupleCG[2] * glCoarseNodesPerDir[1] * glCoarseNodesPerDir[0] + glElementRefTupleCG[1] * glCoarseNodesPerDir[0] + glElementRefTupleCG[0];
504 glElementCoarseNodeCG[4] += glCoarseNodesPerDir[1] * glCoarseNodesPerDir[0];
505 glElementCoarseNodeCG[5] += glCoarseNodesPerDir[1] * glCoarseNodesPerDir[0];
506 glElementCoarseNodeCG[6] += glCoarseNodesPerDir[1] * glCoarseNodesPerDir[0];
507 glElementCoarseNodeCG[7] += glCoarseNodesPerDir[1] * glCoarseNodesPerDir[0];
509 glElementCoarseNodeCG[2] += glCoarseNodesPerDir[0];
510 glElementCoarseNodeCG[3] += glCoarseNodesPerDir[0];
511 glElementCoarseNodeCG[6] += glCoarseNodesPerDir[0];
512 glElementCoarseNodeCG[7] += glCoarseNodesPerDir[0];
514 glElementCoarseNodeCG[1] += 1;
515 glElementCoarseNodeCG[3] += 1;
516 glElementCoarseNodeCG[5] += 1;
517 glElementCoarseNodeCG[7] += 1;
519 LO numNodesInElement = elementNodesPerDir[0] * elementNodesPerDir[1] * elementNodesPerDir[2];
524 Teuchos::SerialDenseMatrix<LO, SC> Pi, Pf, Pe;
525 Array<LO> dofType(numNodesInElement * BlkSize), lDofInd(numNodesInElement * BlkSize);
526 ComputeLocalEntries(Aghost, coarseRate, endRate, BlkSize, elemInds, lCoarseElementsPerDir,
527 numDimensions, glFineNodesPerDir, gFineNodesPerDir, gIndices,
528 lCoarseNodesPerDir, ghostInterface, elementFlags, stencilType,
529 blockStrategy, elementNodesPerDir, numNodesInElement, colGIDs,
530 Pi, Pf, Pe, dofType, lDofInd);
534 Array<LO> lNodeLIDs(numNodesInElement);
536 Array<LO> lNodeTuple(3), nodeInd(3);
537 for (nodeInd[2] = 0; nodeInd[2] < elementNodesPerDir[2]; ++nodeInd[2]) {
538 for (nodeInd[1] = 0; nodeInd[1] < elementNodesPerDir[1]; ++nodeInd[1]) {
539 for (nodeInd[0] = 0; nodeInd[0] < elementNodesPerDir[0]; ++nodeInd[0]) {
540 int stencilLength = 0;
541 if ((nodeInd[0] == 0 || nodeInd[0] == elementNodesPerDir[0] - 1) &&
542 (nodeInd[1] == 0 || nodeInd[1] == elementNodesPerDir[1] - 1) &&
543 (nodeInd[2] == 0 || nodeInd[2] == elementNodesPerDir[2] - 1)) {
546 stencilLength = std::pow(2, numDimensions);
548 LO nodeElementInd = nodeInd[2] * elementNodesPerDir[1] * elementNodesPerDir[1] + nodeInd[1] * elementNodesPerDir[0] + nodeInd[0];
549 for (
int dim = 0; dim < 3; ++dim) {
550 lNodeTuple[dim] = glElementRefTuple[dim] - myOffset[dim] + nodeInd[dim];
552 if (lNodeTuple[0] < 0 || lNodeTuple[1] < 0 || lNodeTuple[2] < 0 ||
553 lNodeTuple[0] > lFineNodesPerDir[0] - 1 ||
554 lNodeTuple[1] > lFineNodesPerDir[1] - 1 ||
555 lNodeTuple[2] > lFineNodesPerDir[2] - 1) {
558 lNodeLIDs[nodeElementInd] = -1;
559 }
else if ((nodeInd[0] == 0 && elemInds[0] != 0) ||
560 (nodeInd[1] == 0 && elemInds[1] != 0) ||
561 (nodeInd[2] == 0 && elemInds[2] != 0)) {
565 lNodeLIDs[nodeElementInd] = -2;
571 lNodeLIDs[nodeElementInd] = lNodeTuple[2] * lFineNodesPerDir[1] * lFineNodesPerDir[0] + lNodeTuple[1] * lFineNodesPerDir[0] + lNodeTuple[0];
577 Array<LO> refCoarsePointTuple(3);
578 for (
int dim = 2; dim > -1; --dim) {
580 refCoarsePointTuple[dim] = (lNodeTuple[dim] + myOffset[dim]) / coarseRate[dim];
581 if (myOffset[dim] == 0) {
582 ++refCoarsePointTuple[dim];
586 refCoarsePointTuple[dim] =
587 std::ceil(
static_cast<double>(lNodeTuple[dim] + myOffset[dim]) / coarseRate[dim]);
589 if ((lNodeTuple[dim] + myOffset[dim]) % coarseRate[dim] > 0) {
593 const LO numCoarsePoints = refCoarsePointTuple[0] + refCoarsePointTuple[1] * lCoarseNodesPerDir[0] + refCoarsePointTuple[2] * lCoarseNodesPerDir[1] * lCoarseNodesPerDir[0];
594 const LO numFinePoints = lNodeLIDs[nodeElementInd] + 1;
598 size_t rowPtr = (numFinePoints - numCoarsePoints) * numRowsPerPoint * numCoarseNodesInElement * nnzPerCoarseNode + numCoarsePoints * numRowsPerPoint;
599 if (dofType[nodeElementInd * BlkSize] == 0) {
601 rowPtr = rowPtr - numRowsPerPoint;
603 rowPtr = rowPtr - numRowsPerPoint * numCoarseNodesInElement * nnzPerCoarseNode;
606 for (
int dof = 0; dof < BlkSize; ++dof) {
609 switch (dofType[nodeElementInd * BlkSize + dof]) {
611 if (nodeInd[2] == elementNodesPerDir[2] - 1) {
614 if (nodeInd[1] == elementNodesPerDir[1] - 1) {
617 if (nodeInd[0] == elementNodesPerDir[0] - 1) {
620 ia[lNodeLIDs[nodeElementInd] * BlkSize + dof + 1] = rowPtr + dof + 1;
621 ja[rowPtr + dof] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[cornerInd]] * BlkSize + dof;
622 val[rowPtr + dof] = 1.0;
626 ia[lNodeLIDs[nodeElementInd] * BlkSize + dof + 1] = rowPtr + (dof + 1) * numCoarseNodesInElement * nnzPerCoarseNode;
627 for (
int ind1 = 0; ind1 < stencilLength; ++ind1) {
628 if (blockStrategy ==
"coupled") {
629 for (
int ind2 = 0; ind2 < BlkSize; ++ind2) {
630 size_t lRowPtr = rowPtr + dof * numCoarseNodesInElement * nnzPerCoarseNode + ind1 * BlkSize + ind2;
631 ja[lRowPtr] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]] * BlkSize + ind2;
632 val[lRowPtr] = Pe(lDofInd[nodeElementInd * BlkSize + dof],
633 ind1 * BlkSize + ind2);
635 }
else if (blockStrategy ==
"uncoupled") {
636 size_t lRowPtr = rowPtr + dof * numCoarseNodesInElement * nnzPerCoarseNode + ind1;
637 ja[rowPtr + dof] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]] * BlkSize + dof;
638 val[lRowPtr] = Pe(lDofInd[nodeElementInd * BlkSize + dof],
639 ind1 * BlkSize + dof);
645 ia[lNodeLIDs[nodeElementInd] * BlkSize + dof + 1] = rowPtr + (dof + 1) * numCoarseNodesInElement * nnzPerCoarseNode;
646 for (
int ind1 = 0; ind1 < stencilLength; ++ind1) {
647 if (blockStrategy ==
"coupled") {
648 for (
int ind2 = 0; ind2 < BlkSize; ++ind2) {
649 size_t lRowPtr = rowPtr + dof * numCoarseNodesInElement * nnzPerCoarseNode + ind1 * BlkSize + ind2;
650 ja[lRowPtr] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]] * BlkSize + ind2;
651 val[lRowPtr] = Pf(lDofInd[nodeElementInd * BlkSize + dof],
652 ind1 * BlkSize + ind2);
654 }
else if (blockStrategy ==
"uncoupled") {
655 size_t lRowPtr = rowPtr + dof * numCoarseNodesInElement * nnzPerCoarseNode + ind1;
657 ja[lRowPtr] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]] * BlkSize + dof;
658 val[lRowPtr] = Pf(lDofInd[nodeElementInd * BlkSize + dof],
659 ind1 * BlkSize + dof);
665 ia[lNodeLIDs[nodeElementInd] * BlkSize + dof + 1] = rowPtr + (dof + 1) * numCoarseNodesInElement * nnzPerCoarseNode;
666 for (
int ind1 = 0; ind1 < stencilLength; ++ind1) {
667 if (blockStrategy ==
"coupled") {
668 for (
int ind2 = 0; ind2 < BlkSize; ++ind2) {
669 size_t lRowPtr = rowPtr + dof * numCoarseNodesInElement * nnzPerCoarseNode + ind1 * BlkSize + ind2;
670 ja[lRowPtr] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]] * BlkSize + ind2;
671 val[lRowPtr] = Pi(lDofInd[nodeElementInd * BlkSize + dof],
672 ind1 * BlkSize + ind2);
674 }
else if (blockStrategy ==
"uncoupled") {
675 size_t lRowPtr = rowPtr + dof * numCoarseNodesInElement * nnzPerCoarseNode + ind1;
676 ja[lRowPtr] = ghostedCoarseNodes->colInds[glElementCoarseNodeCG[ind1]] * BlkSize + dof;
677 val[lRowPtr] = Pi(lDofInd[nodeElementInd * BlkSize + dof],
678 ind1 * BlkSize + dof);
697 PCrs->setAllValues(iaP, jaP, valP);
698 PCrs->expertStaticFillComplete(domainMapP, rowMapP);
701 if (A->IsView(
"stridedMaps") ==
true) {
702 P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedDomainMapP);
704 P->CreateView(
"stridedMaps", P->getRangeMap(), stridedDomainMapP);
708 Set(coarseLevel,
"P", P);
709 Set(coarseLevel,
"coarseCoordinates", coarseCoordinates);
710 Set<Array<GO> >(coarseLevel,
"gCoarseNodesPerDim", gCoarseNodesPerDir);
711 Set<Array<LO> >(coarseLevel,
"lCoarseNodesPerDim", lCoarseNodesPerDir);
716 GetGeometricData(RCP<Xpetra::MultiVector<
typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO> >& coordinates,
717 const Array<LO> coarseRate,
const Array<GO> gFineNodesPerDir,
718 const Array<LO> lFineNodesPerDir,
const LO BlkSize, Array<GO>& gIndices,
719 Array<LO>& myOffset, Array<bool>& ghostInterface, Array<LO>& endRate,
720 Array<GO>& gCoarseNodesPerDir, Array<LO>& lCoarseNodesPerDir,
721 Array<LO>& glCoarseNodesPerDir, Array<GO>& ghostGIDs, Array<GO>& coarseNodesGIDs,
722 Array<GO>& colGIDs, GO& gNumCoarseNodes, LO& lNumCoarseNodes,
723 ArrayRCP<Array<
typename Teuchos::ScalarTraits<Scalar>::magnitudeType> > coarseNodes, Array<int>& boundaryFlags,
724 RCP<NodesIDs> ghostedCoarseNodes)
const {
731 RCP<const Map> coordinatesMap = coordinates->getMap();
732 LO numDimensions = coordinates->getNumVectors();
743 GO minGlobalIndex = coordinatesMap->getMinGlobalIndex();
746 gIndices[2] = minGlobalIndex / (gFineNodesPerDir[1] * gFineNodesPerDir[0]);
747 tmp = minGlobalIndex % (gFineNodesPerDir[1] * gFineNodesPerDir[0]);
748 gIndices[1] = tmp / gFineNodesPerDir[0];
749 gIndices[0] = tmp % gFineNodesPerDir[0];
751 myOffset[2] = gIndices[2] % coarseRate[2];
752 myOffset[1] = gIndices[1] % coarseRate[1];
753 myOffset[0] = gIndices[0] % coarseRate[0];
756 for (
int dim = 0; dim < 3; ++dim) {
757 if (gIndices[dim] == 0) {
758 boundaryFlags[dim] += 1;
760 if (gIndices[dim] + lFineNodesPerDir[dim] == gFineNodesPerDir[dim]) {
761 boundaryFlags[dim] += 2;
766 for (LO i = 0; i < numDimensions; ++i) {
767 if ((gIndices[i] != 0) && (gIndices[i] % coarseRate[i] > 0)) {
768 ghostInterface[2 * i] =
true;
770 if (((gIndices[i] + lFineNodesPerDir[i]) != gFineNodesPerDir[i]) && ((gIndices[i] + lFineNodesPerDir[i] - 1) % coarseRate[i] > 0)) {
771 ghostInterface[2 * i + 1] =
true;
775 for (LO i = 0; i < 3; ++i) {
776 if (i < numDimensions) {
777 lCoarseNodesPerDir[i] = (lFineNodesPerDir[i] + myOffset[i] - 1) / coarseRate[i];
778 if (myOffset[i] == 0) {
779 ++lCoarseNodesPerDir[i];
781 gCoarseNodesPerDir[i] = (gFineNodesPerDir[i] - 1) / coarseRate[i];
782 endRate[i] = (gFineNodesPerDir[i] - 1) % coarseRate[i];
783 if (endRate[i] == 0) {
784 ++gCoarseNodesPerDir[i];
785 endRate[i] = coarseRate[i];
791 gCoarseNodesPerDir[i] = 1;
792 lCoarseNodesPerDir[i] = 1;
797 gNumCoarseNodes = gCoarseNodesPerDir[0] * gCoarseNodesPerDir[1] * gCoarseNodesPerDir[2];
798 lNumCoarseNodes = lCoarseNodesPerDir[0] * lCoarseNodesPerDir[1] * lCoarseNodesPerDir[2];
801 LO lNumGhostNodes = 0;
802 Array<GO> startGhostedCoarseNode(3);
804 const int complementaryIndices[3][2] = {{1, 2}, {0, 2}, {0, 1}};
806 for (LO i = 0; i < 3; ++i) {
810 if ((gIndices[i] == gFineNodesPerDir[i] - 1) && (gIndices[i] % coarseRate[i] == 0)) {
811 startGhostedCoarseNode[i] = gIndices[i] / coarseRate[i] - 1;
813 startGhostedCoarseNode[i] = gIndices[i] / coarseRate[i];
816 glCoarseNodesPerDir[i] = lCoarseNodesPerDir[i];
819 if (ghostInterface[2 * i] || ghostInterface[2 * i + 1]) {
820 ++glCoarseNodesPerDir[i];
822 tmp = lCoarseNodesPerDir[1] * lCoarseNodesPerDir[2];
825 tmp = lCoarseNodesPerDir[0] * lCoarseNodesPerDir[2];
828 tmp = lCoarseNodesPerDir[0] * lCoarseNodesPerDir[1];
832 if (ghostInterface[2 * i] && ghostInterface[2 * i + 1]) {
833 ++glCoarseNodesPerDir[i];
836 lNumGhostNodes += tmp;
839 for (LO j = 0; j < 2; ++j) {
840 for (LO k = 0; k < 2; ++k) {
842 if (ghostInterface[2 * complementaryIndices[i][0] + j] && ghostInterface[2 * complementaryIndices[i][1] + k]) {
843 lNumGhostNodes += lCoarseNodesPerDir[i];
846 if (ghostInterface[2 * i] && (i == 0)) {
849 if (ghostInterface[2 * i + 1] && (i == 0)) {
859 const LO lNumGhostedNodes = glCoarseNodesPerDir[0] * glCoarseNodesPerDir[1] * glCoarseNodesPerDir[2];
860 ghostedCoarseNodes->PIDs.resize(lNumGhostedNodes);
861 ghostedCoarseNodes->LIDs.resize(lNumGhostedNodes);
862 ghostedCoarseNodes->GIDs.resize(lNumGhostedNodes);
863 ghostedCoarseNodes->coarseGIDs.resize(lNumGhostedNodes);
864 ghostedCoarseNodes->colInds.resize(lNumGhostedNodes);
867 Array<LO> coarseNodeCoarseIndices(3), coarseNodeFineIndices(3), ijk(3);
868 LO currentIndex = -1;
869 for (ijk[2] = 0; ijk[2] < glCoarseNodesPerDir[2]; ++ijk[2]) {
870 for (ijk[1] = 0; ijk[1] < glCoarseNodesPerDir[1]; ++ijk[1]) {
871 for (ijk[0] = 0; ijk[0] < glCoarseNodesPerDir[0]; ++ijk[0]) {
872 currentIndex = ijk[2] * glCoarseNodesPerDir[1] * glCoarseNodesPerDir[0] + ijk[1] * glCoarseNodesPerDir[0] + ijk[0];
873 coarseNodeCoarseIndices[0] = startGhostedCoarseNode[0] + ijk[0];
874 coarseNodeFineIndices[0] = coarseNodeCoarseIndices[0] * coarseRate[0];
875 if (coarseNodeFineIndices[0] > gFineNodesPerDir[0] - 1) {
876 coarseNodeFineIndices[0] = gFineNodesPerDir[0] - 1;
878 coarseNodeCoarseIndices[1] = startGhostedCoarseNode[1] + ijk[1];
879 coarseNodeFineIndices[1] = coarseNodeCoarseIndices[1] * coarseRate[1];
880 if (coarseNodeFineIndices[1] > gFineNodesPerDir[1] - 1) {
881 coarseNodeFineIndices[1] = gFineNodesPerDir[1] - 1;
883 coarseNodeCoarseIndices[2] = startGhostedCoarseNode[2] + ijk[2];
884 coarseNodeFineIndices[2] = coarseNodeCoarseIndices[2] * coarseRate[2];
885 if (coarseNodeFineIndices[2] > gFineNodesPerDir[2] - 1) {
886 coarseNodeFineIndices[2] = gFineNodesPerDir[2] - 1;
888 GO myGID = 0, myCoarseGID = -1;
890 factor[2] = gFineNodesPerDir[1] * gFineNodesPerDir[0];
891 factor[1] = gFineNodesPerDir[0];
893 for (
int dim = 0; dim < 3; ++dim) {
894 if (dim < numDimensions) {
895 if (gIndices[dim] - myOffset[dim] + ijk[dim] * coarseRate[dim] < gFineNodesPerDir[dim] - 1) {
896 myGID += (gIndices[dim] - myOffset[dim] + ijk[dim] * coarseRate[dim]) * factor[dim];
898 myGID += (gIndices[dim] - myOffset[dim] + (ijk[dim] - 1) * coarseRate[dim] + endRate[dim]) * factor[dim];
902 myCoarseGID = coarseNodeCoarseIndices[0] + coarseNodeCoarseIndices[1] * gCoarseNodesPerDir[0] + coarseNodeCoarseIndices[2] * gCoarseNodesPerDir[1] * gCoarseNodesPerDir[0];
903 ghostedCoarseNodes->GIDs[currentIndex] = myGID;
904 ghostedCoarseNodes->coarseGIDs[currentIndex] = myCoarseGID;
908 coordinatesMap->getRemoteIndexList(ghostedCoarseNodes->GIDs(),
909 ghostedCoarseNodes->PIDs(),
910 ghostedCoarseNodes->LIDs());
921 ghostGIDs.resize(lNumGhostNodes);
924 GO startingGID = minGlobalIndex;
925 Array<GO> startingIndices(3);
928 if (ghostInterface[4] && (myOffset[2] == 0)) {
929 if (gIndices[2] + coarseRate[2] > gFineNodesPerDir[2]) {
930 startingGID -= endRate[2] * gFineNodesPerDir[1] * gFineNodesPerDir[0];
932 startingGID -= coarseRate[2] * gFineNodesPerDir[1] * gFineNodesPerDir[0];
935 startingGID -= myOffset[2] * gFineNodesPerDir[1] * gFineNodesPerDir[0];
937 if (ghostInterface[2] && (myOffset[1] == 0)) {
938 if (gIndices[1] + coarseRate[1] > gFineNodesPerDir[1]) {
939 startingGID -= endRate[1] * gFineNodesPerDir[0];
941 startingGID -= coarseRate[1] * gFineNodesPerDir[0];
944 startingGID -= myOffset[1] * gFineNodesPerDir[0];
946 if (ghostInterface[0] && (myOffset[0] == 0)) {
947 if (gIndices[0] + coarseRate[0] > gFineNodesPerDir[0]) {
948 startingGID -= endRate[0];
950 startingGID -= coarseRate[0];
953 startingGID -= myOffset[0];
958 startingIndices[2] = startingGID / (gFineNodesPerDir[1] * gFineNodesPerDir[0]);
959 tmp = startingGID % (gFineNodesPerDir[1] * gFineNodesPerDir[0]);
960 startingIndices[1] = tmp / gFineNodesPerDir[0];
961 startingIndices[0] = tmp % gFineNodesPerDir[0];
964 GO ghostOffset[3] = {0, 0, 0};
965 LO lengthZero = lCoarseNodesPerDir[0];
966 LO lengthOne = lCoarseNodesPerDir[1];
967 LO lengthTwo = lCoarseNodesPerDir[2];
968 if (ghostInterface[0]) {
971 if (ghostInterface[1]) {
974 if (ghostInterface[2]) {
977 if (ghostInterface[3]) {
980 if (ghostInterface[4]) {
983 if (ghostInterface[5]) {
988 if (ghostInterface[4]) {
989 ghostOffset[2] = startingGID;
990 for (LO j = 0; j < lengthOne; ++j) {
991 if ((j == lengthOne - 1) && (startingIndices[1] + j * coarseRate[1] + 1 > gFineNodesPerDir[1])) {
992 ghostOffset[1] = ((j - 1) * coarseRate[1] + endRate[1]) * gFineNodesPerDir[0];
994 ghostOffset[1] = j * coarseRate[1] * gFineNodesPerDir[0];
996 for (LO k = 0; k < lengthZero; ++k) {
997 if ((k == lengthZero - 1) && (startingIndices[0] + k * coarseRate[0] + 1 > gFineNodesPerDir[0])) {
998 ghostOffset[0] = (k - 1) * coarseRate[0] + endRate[0];
1000 ghostOffset[0] = k * coarseRate[0];
1005 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
1013 for (LO i = 0; i < lengthTwo; ++i) {
1016 if (!((i == lengthTwo - 1) && ghostInterface[5]) && !((i == 0) && ghostInterface[4])) {
1019 if ((i == lengthTwo - 1) && !ghostInterface[5]) {
1020 ghostOffset[2] = startingGID + ((i - 1) * coarseRate[2] + endRate[2]) * gFineNodesPerDir[1] * gFineNodesPerDir[0];
1022 ghostOffset[2] = startingGID + i * coarseRate[2] * gFineNodesPerDir[1] * gFineNodesPerDir[0];
1024 for (LO j = 0; j < lengthOne; ++j) {
1025 if ((j == 0) && ghostInterface[2]) {
1026 for (LO k = 0; k < lengthZero; ++k) {
1027 if ((k == lengthZero - 1) && (startingIndices[0] + k * coarseRate[0] + 1 > gFineNodesPerDir[0])) {
1029 ghostOffset[0] = endRate[0];
1031 ghostOffset[0] = (k - 1) * coarseRate[0] + endRate[0];
1034 ghostOffset[0] = k * coarseRate[0];
1037 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[0];
1040 }
else if ((j == lengthOne - 1) && ghostInterface[3]) {
1043 if ((j == lengthOne - 1) && (startingIndices[1] + j * coarseRate[1] + 1 > gFineNodesPerDir[1])) {
1044 ghostOffset[1] = ((j - 1) * coarseRate[1] + endRate[1]) * gFineNodesPerDir[0];
1046 ghostOffset[1] = j * coarseRate[1] * gFineNodesPerDir[0];
1048 for (LO k = 0; k < lengthZero; ++k) {
1049 if ((k == lengthZero - 1) && (startingIndices[0] + k * coarseRate[0] + 1 > gFineNodesPerDir[0])) {
1050 ghostOffset[0] = (k - 1) * coarseRate[0] + endRate[0];
1052 ghostOffset[0] = k * coarseRate[0];
1054 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
1059 if ((j == lengthOne - 1) && (startingIndices[1] + j * coarseRate[1] + 1 > gFineNodesPerDir[1])) {
1060 ghostOffset[1] = ((j - 1) * coarseRate[1] + endRate[1]) * gFineNodesPerDir[0];
1062 ghostOffset[1] = j * coarseRate[1] * gFineNodesPerDir[0];
1066 if (ghostInterface[0]) {
1067 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1];
1070 if (ghostInterface[1]) {
1071 if ((startingIndices[0] + (lengthZero - 1) * coarseRate[0]) > gFineNodesPerDir[0] - 1) {
1072 if (lengthZero > 2) {
1073 ghostOffset[0] = (lengthZero - 2) * coarseRate[0] + endRate[0];
1075 ghostOffset[0] = endRate[0];
1078 ghostOffset[0] = (lengthZero - 1) * coarseRate[0];
1080 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
1089 if (ghostInterface[5]) {
1090 if (startingIndices[2] + (lengthTwo - 1) * coarseRate[2] + 1 > gFineNodesPerDir[2]) {
1091 ghostOffset[2] = startingGID + ((lengthTwo - 2) * coarseRate[2] + endRate[2]) * gFineNodesPerDir[1] * gFineNodesPerDir[0];
1093 ghostOffset[2] = startingGID + (lengthTwo - 1) * coarseRate[2] * gFineNodesPerDir[1] * gFineNodesPerDir[0];
1095 for (LO j = 0; j < lengthOne; ++j) {
1096 if ((j == lengthOne - 1) && (startingIndices[1] + j * coarseRate[1] + 1 > gFineNodesPerDir[1])) {
1097 ghostOffset[1] = ((j - 1) * coarseRate[1] + endRate[1]) * gFineNodesPerDir[0];
1099 ghostOffset[1] = j * coarseRate[1] * gFineNodesPerDir[0];
1101 for (LO k = 0; k < lengthZero; ++k) {
1102 if ((k == lengthZero - 1) && (startingIndices[0] + k * coarseRate[0] + 1 > gFineNodesPerDir[0])) {
1103 ghostOffset[0] = (k - 1) * coarseRate[0] + endRate[0];
1105 ghostOffset[0] = k * coarseRate[0];
1107 ghostGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
1120 Array<GO> gCoarseNodesGIDs(lNumCoarseNodes);
1121 LO currentNode, offset2, offset1, offset0;
1123 for (LO ind2 = 0; ind2 < lCoarseNodesPerDir[2]; ++ind2) {
1124 if (myOffset[2] == 0) {
1125 offset2 = startingIndices[2] + myOffset[2];
1127 if (startingIndices[2] + endRate[2] == gFineNodesPerDir[2] - 1) {
1128 offset2 = startingIndices[2] + endRate[2];
1130 offset2 = startingIndices[2] + coarseRate[2];
1133 if (offset2 + ind2 * coarseRate[2] > gFineNodesPerDir[2] - 1) {
1134 offset2 += (ind2 - 1) * coarseRate[2] + endRate[2];
1136 offset2 += ind2 * coarseRate[2];
1138 offset2 = offset2 * gFineNodesPerDir[1] * gFineNodesPerDir[0];
1140 for (LO ind1 = 0; ind1 < lCoarseNodesPerDir[1]; ++ind1) {
1141 if (myOffset[1] == 0) {
1142 offset1 = startingIndices[1] + myOffset[1];
1144 if (startingIndices[1] + endRate[1] == gFineNodesPerDir[1] - 1) {
1145 offset1 = startingIndices[1] + endRate[1];
1147 offset1 = startingIndices[1] + coarseRate[1];
1150 if (offset1 + ind1 * coarseRate[1] > gFineNodesPerDir[1] - 1) {
1151 offset1 += (ind1 - 1) * coarseRate[1] + endRate[1];
1153 offset1 += ind1 * coarseRate[1];
1155 offset1 = offset1 * gFineNodesPerDir[0];
1156 for (LO ind0 = 0; ind0 < lCoarseNodesPerDir[0]; ++ind0) {
1157 offset0 = startingIndices[0];
1158 if (myOffset[0] == 0) {
1159 offset0 += ind0 * coarseRate[0];
1161 offset0 += (ind0 + 1) * coarseRate[0];
1163 if (offset0 > gFineNodesPerDir[0] - 1) {
1164 offset0 += endRate[0] - coarseRate[0];
1167 currentNode = ind2 * lCoarseNodesPerDir[1] * lCoarseNodesPerDir[0] + ind1 * lCoarseNodesPerDir[0] + ind0;
1168 gCoarseNodesGIDs[currentNode] = offset2 + offset1 + offset0;
1175 colGIDs.resize(BlkSize * (lNumCoarseNodes + lNumGhostNodes));
1176 coarseNodesGIDs.resize(lNumCoarseNodes);
1177 for (LO i = 0; i < numDimensions; ++i) {
1178 coarseNodes[i].resize(lNumCoarseNodes);
1180 GO fineNodesPerCoarseSlab = coarseRate[2] * gFineNodesPerDir[1] * gFineNodesPerDir[0];
1181 GO fineNodesEndCoarseSlab = endRate[2] * gFineNodesPerDir[1] * gFineNodesPerDir[0];
1182 GO fineNodesPerCoarsePlane = coarseRate[1] * gFineNodesPerDir[0];
1183 GO fineNodesEndCoarsePlane = endRate[1] * gFineNodesPerDir[0];
1184 GO coarseNodesPerCoarseLayer = gCoarseNodesPerDir[1] * gCoarseNodesPerDir[0];
1185 GO gCoarseNodeOnCoarseGridGID;
1187 Array<int> ghostPIDs(lNumGhostNodes);
1188 Array<LO> ghostLIDs(lNumGhostNodes);
1189 Array<LO> ghostPermut(lNumGhostNodes);
1190 for (LO k = 0; k < lNumGhostNodes; ++k) {
1193 coordinatesMap->getRemoteIndexList(ghostGIDs, ghostPIDs, ghostLIDs);
1194 sh_sort_permute(ghostPIDs.begin(), ghostPIDs.end(), ghostPermut.begin(), ghostPermut.end());
1197 GO tmpInds[3], tmpVars[2];
1205 LO firstCoarseNodeInds[3], currentCoarseNode;
1206 for (LO dim = 0; dim < 3; ++dim) {
1207 if (myOffset[dim] == 0) {
1208 firstCoarseNodeInds[dim] = 0;
1210 firstCoarseNodeInds[dim] = coarseRate[dim] - myOffset[dim];
1213 Array<ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> > fineNodes(numDimensions);
1214 for (LO dim = 0; dim < numDimensions; ++dim) {
1215 fineNodes[dim] = coordinates->getData(dim);
1217 for (LO k = 0; k < lCoarseNodesPerDir[2]; ++k) {
1218 for (LO j = 0; j < lCoarseNodesPerDir[1]; ++j) {
1219 for (LO i = 0; i < lCoarseNodesPerDir[0]; ++i) {
1220 col = k * lCoarseNodesPerDir[1] * lCoarseNodesPerDir[0] + j * lCoarseNodesPerDir[0] + i;
1223 currentCoarseNode = 0;
1224 if (firstCoarseNodeInds[0] + i * coarseRate[0] > lFineNodesPerDir[0] - 1) {
1225 currentCoarseNode += firstCoarseNodeInds[0] + (i - 1) * coarseRate[0] + endRate[0];
1227 currentCoarseNode += firstCoarseNodeInds[0] + i * coarseRate[0];
1229 if (firstCoarseNodeInds[1] + j * coarseRate[1] > lFineNodesPerDir[1] - 1) {
1230 currentCoarseNode += (firstCoarseNodeInds[1] + (j - 1) * coarseRate[1] + endRate[1]) * lFineNodesPerDir[0];
1232 currentCoarseNode += (firstCoarseNodeInds[1] + j * coarseRate[1]) * lFineNodesPerDir[0];
1234 if (firstCoarseNodeInds[2] + k * coarseRate[2] > lFineNodesPerDir[2] - 1) {
1235 currentCoarseNode += (firstCoarseNodeInds[2] + (k - 1) * coarseRate[2] + endRate[2]) * lFineNodesPerDir[1] * lFineNodesPerDir[0];
1237 currentCoarseNode += (firstCoarseNodeInds[2] + k * coarseRate[2]) * lFineNodesPerDir[1] * lFineNodesPerDir[0];
1240 for (LO dim = 0; dim < numDimensions; ++dim) {
1241 coarseNodes[dim][col] = fineNodes[dim][currentCoarseNode];
1244 if ((endRate[2] != coarseRate[2]) && (gCoarseNodesGIDs[col] > (gCoarseNodesPerDir[2] - 2) * fineNodesPerCoarseSlab + fineNodesEndCoarseSlab - 1)) {
1245 tmpInds[2] = gCoarseNodesGIDs[col] / fineNodesPerCoarseSlab + 1;
1246 tmpVars[0] = gCoarseNodesGIDs[col] - (tmpInds[2] - 1) * fineNodesPerCoarseSlab - fineNodesEndCoarseSlab;
1248 tmpInds[2] = gCoarseNodesGIDs[col] / fineNodesPerCoarseSlab;
1249 tmpVars[0] = gCoarseNodesGIDs[col] % fineNodesPerCoarseSlab;
1251 if ((endRate[1] != coarseRate[1]) && (tmpVars[0] > (gCoarseNodesPerDir[1] - 2) * fineNodesPerCoarsePlane + fineNodesEndCoarsePlane - 1)) {
1252 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane + 1;
1253 tmpVars[1] = tmpVars[0] - (tmpInds[1] - 1) * fineNodesPerCoarsePlane - fineNodesEndCoarsePlane;
1255 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane;
1256 tmpVars[1] = tmpVars[0] % fineNodesPerCoarsePlane;
1258 if (tmpVars[1] == gFineNodesPerDir[0] - 1) {
1259 tmpInds[0] = gCoarseNodesPerDir[0] - 1;
1261 tmpInds[0] = tmpVars[1] / coarseRate[0];
1263 gInd[2] = col / (lCoarseNodesPerDir[1] * lCoarseNodesPerDir[0]);
1264 tmp = col % (lCoarseNodesPerDir[1] * lCoarseNodesPerDir[0]);
1265 gInd[1] = tmp / lCoarseNodesPerDir[0];
1266 gInd[0] = tmp % lCoarseNodesPerDir[0];
1267 lCol = gInd[2] * (lCoarseNodesPerDir[1] * lCoarseNodesPerDir[0]) + gInd[1] * lCoarseNodesPerDir[0] + gInd[0];
1268 gCoarseNodeOnCoarseGridGID = tmpInds[2] * coarseNodesPerCoarseLayer + tmpInds[1] * gCoarseNodesPerDir[0] + tmpInds[0];
1269 coarseNodesGIDs[lCol] = gCoarseNodeOnCoarseGridGID;
1270 for (LO dof = 0; dof < BlkSize; ++dof) {
1271 colGIDs[BlkSize * lCol + dof] = BlkSize * gCoarseNodeOnCoarseGridGID + dof;
1278 for (col = lNumCoarseNodes; col < lNumCoarseNodes + lNumGhostNodes; ++col) {
1279 if ((endRate[2] != coarseRate[2]) && (ghostGIDs[ghostPermut[col - lNumCoarseNodes]] > (gCoarseNodesPerDir[2] - 2) * fineNodesPerCoarseSlab + fineNodesEndCoarseSlab - 1)) {
1280 tmpInds[2] = ghostGIDs[ghostPermut[col - lNumCoarseNodes]] / fineNodesPerCoarseSlab + 1;
1281 tmpVars[0] = ghostGIDs[ghostPermut[col - lNumCoarseNodes]] - (tmpInds[2] - 1) * fineNodesPerCoarseSlab - fineNodesEndCoarseSlab;
1283 tmpInds[2] = ghostGIDs[ghostPermut[col - lNumCoarseNodes]] / fineNodesPerCoarseSlab;
1284 tmpVars[0] = ghostGIDs[ghostPermut[col - lNumCoarseNodes]] % fineNodesPerCoarseSlab;
1286 if ((endRate[1] != coarseRate[1]) && (tmpVars[0] > (gCoarseNodesPerDir[1] - 2) * fineNodesPerCoarsePlane + fineNodesEndCoarsePlane - 1)) {
1287 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane + 1;
1288 tmpVars[1] = tmpVars[0] - (tmpInds[1] - 1) * fineNodesPerCoarsePlane - fineNodesEndCoarsePlane;
1290 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane;
1291 tmpVars[1] = tmpVars[0] % fineNodesPerCoarsePlane;
1293 if (tmpVars[1] == gFineNodesPerDir[0] - 1) {
1294 tmpInds[0] = gCoarseNodesPerDir[0] - 1;
1296 tmpInds[0] = tmpVars[1] / coarseRate[0];
1298 gCoarseNodeOnCoarseGridGID = tmpInds[2] * coarseNodesPerCoarseLayer + tmpInds[1] * gCoarseNodesPerDir[0] + tmpInds[0];
1299 for (LO dof = 0; dof < BlkSize; ++dof) {
1300 colGIDs[BlkSize * col + dof] = BlkSize * gCoarseNodeOnCoarseGridGID + dof;
1310 const Array<LO> ,
const LO BlkSize,
const Array<LO> elemInds,
1311 const Array<LO> ,
const LO numDimensions,
1312 const Array<LO> lFineNodesPerDir,
const Array<GO> ,
1313 const Array<GO> ,
const Array<LO> ,
1314 const Array<bool> ghostInterface,
const Array<int> elementFlags,
1315 const std::string stencilType,
const std::string ,
1316 const Array<LO> elementNodesPerDir,
const LO numNodesInElement,
1318 Teuchos::SerialDenseMatrix<LO, SC>& Pi, Teuchos::SerialDenseMatrix<LO, SC>& Pf,
1319 Teuchos::SerialDenseMatrix<LO, SC>& Pe, Array<LO>& dofType,
1320 Array<LO>& lDofInd)
const {
1330 LO countInterior = 0, countFace = 0, countEdge = 0, countCorner = 0;
1331 Array<LO> collapseDir(numNodesInElement * BlkSize);
1332 for (LO ke = 0; ke < elementNodesPerDir[2]; ++ke) {
1333 for (LO je = 0; je < elementNodesPerDir[1]; ++je) {
1334 for (LO ie = 0; ie < elementNodesPerDir[0]; ++ie) {
1336 if ((ke == 0 || ke == elementNodesPerDir[2] - 1) && (je == 0 || je == elementNodesPerDir[1] - 1) && (ie == 0 || ie == elementNodesPerDir[0] - 1)) {
1337 for (LO dof = 0; dof < BlkSize; ++dof) {
1338 dofType[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = 0;
1339 lDofInd[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = BlkSize * countCorner + dof;
1344 }
else if (((ke == 0 || ke == elementNodesPerDir[2] - 1) && (je == 0 || je == elementNodesPerDir[1] - 1)) || ((ke == 0 || ke == elementNodesPerDir[2] - 1) && (ie == 0 || ie == elementNodesPerDir[0] - 1)) || ((je == 0 || je == elementNodesPerDir[1] - 1) && (ie == 0 || ie == elementNodesPerDir[0] - 1))) {
1345 for (LO dof = 0; dof < BlkSize; ++dof) {
1346 dofType[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = 1;
1347 lDofInd[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = BlkSize * countEdge + dof;
1348 if ((ke == 0 || ke == elementNodesPerDir[2] - 1) && (je == 0 || je == elementNodesPerDir[1] - 1)) {
1349 collapseDir[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = 0;
1350 }
else if ((ke == 0 || ke == elementNodesPerDir[2] - 1) && (ie == 0 || ie == elementNodesPerDir[0] - 1)) {
1351 collapseDir[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = 1;
1352 }
else if ((je == 0 || je == elementNodesPerDir[1] - 1) && (ie == 0 || ie == elementNodesPerDir[0] - 1)) {
1353 collapseDir[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = 2;
1359 }
else if ((ke == 0 || ke == elementNodesPerDir[2] - 1) || (je == 0 || je == elementNodesPerDir[1] - 1) || (ie == 0 || ie == elementNodesPerDir[0] - 1)) {
1360 for (LO dof = 0; dof < BlkSize; ++dof) {
1361 dofType[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = 2;
1362 lDofInd[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = BlkSize * countFace + dof;
1363 if (ke == 0 || ke == elementNodesPerDir[2] - 1) {
1364 collapseDir[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = 2;
1365 }
else if (je == 0 || je == elementNodesPerDir[1] - 1) {
1366 collapseDir[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = 1;
1367 }
else if (ie == 0 || ie == elementNodesPerDir[0] - 1) {
1368 collapseDir[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = 0;
1375 for (LO dof = 0; dof < BlkSize; ++dof) {
1376 dofType[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = 3;
1377 lDofInd[BlkSize * (ke * elementNodesPerDir[1] * elementNodesPerDir[0] + je * elementNodesPerDir[0] + ie) + dof] = BlkSize * countInterior + dof;
1385 LO numInteriorNodes = 0, numFaceNodes = 0, numEdgeNodes = 0, numCornerNodes = 8;
1386 numInteriorNodes = (elementNodesPerDir[0] - 2) * (elementNodesPerDir[1] - 2) * (elementNodesPerDir[2] - 2);
1387 numFaceNodes = 2 * (elementNodesPerDir[0] - 2) * (elementNodesPerDir[1] - 2) + 2 * (elementNodesPerDir[0] - 2) * (elementNodesPerDir[2] - 2) + 2 * (elementNodesPerDir[1] - 2) * (elementNodesPerDir[2] - 2);
1388 numEdgeNodes = 4 * (elementNodesPerDir[0] - 2) + 4 * (elementNodesPerDir[1] - 2) + 4 * (elementNodesPerDir[2] - 2);
1390 Teuchos::SerialDenseMatrix<LO, SC> Aii(BlkSize * numInteriorNodes, BlkSize * numInteriorNodes);
1391 Teuchos::SerialDenseMatrix<LO, SC> Aff(BlkSize * numFaceNodes, BlkSize * numFaceNodes);
1392 Teuchos::SerialDenseMatrix<LO, SC> Aee(BlkSize * numEdgeNodes, BlkSize * numEdgeNodes);
1394 Teuchos::SerialDenseMatrix<LO, SC> Aif(BlkSize * numInteriorNodes, BlkSize * numFaceNodes);
1395 Teuchos::SerialDenseMatrix<LO, SC> Aie(BlkSize * numInteriorNodes, BlkSize * numEdgeNodes);
1396 Teuchos::SerialDenseMatrix<LO, SC> Afe(BlkSize * numFaceNodes, BlkSize * numEdgeNodes);
1398 Teuchos::SerialDenseMatrix<LO, SC> Aic(BlkSize * numInteriorNodes, BlkSize * numCornerNodes);
1399 Teuchos::SerialDenseMatrix<LO, SC> Afc(BlkSize * numFaceNodes, BlkSize * numCornerNodes);
1400 Teuchos::SerialDenseMatrix<LO, SC> Aec(BlkSize * numEdgeNodes, BlkSize * numCornerNodes);
1401 Pi.shape(BlkSize * numInteriorNodes, BlkSize * numCornerNodes);
1402 Pf.shape(BlkSize * numFaceNodes, BlkSize * numCornerNodes);
1403 Pe.shape(BlkSize * numEdgeNodes, BlkSize * numCornerNodes);
1405 ArrayView<const LO> rowIndices;
1406 ArrayView<const SC> rowValues;
1407 LO idof, iInd, jInd;
1408 int iType = 0, jType = 0;
1409 int orientation = -1;
1410 int collapseFlags[3] = {};
1411 Array<SC> stencil((std::pow(3, numDimensions)) * BlkSize);
1415 for (LO ke = 0; ke < elementNodesPerDir[2]; ++ke) {
1416 for (LO je = 0; je < elementNodesPerDir[1]; ++je) {
1417 for (LO ie = 0; ie < elementNodesPerDir[0]; ++ie) {
1418 collapseFlags[0] = 0;
1419 collapseFlags[1] = 0;
1420 collapseFlags[2] = 0;
1421 if ((elementFlags[0] == 1 || elementFlags[0] == 3) && ie == 0) {
1422 collapseFlags[0] += 1;
1424 if ((elementFlags[0] == 2 || elementFlags[0] == 3) && ie == elementNodesPerDir[0] - 1) {
1425 collapseFlags[0] += 2;
1427 if ((elementFlags[1] == 1 || elementFlags[1] == 3) && je == 0) {
1428 collapseFlags[1] += 1;
1430 if ((elementFlags[1] == 2 || elementFlags[1] == 3) && je == elementNodesPerDir[1] - 1) {
1431 collapseFlags[1] += 2;
1433 if ((elementFlags[2] == 1 || elementFlags[2] == 3) && ke == 0) {
1434 collapseFlags[2] += 1;
1436 if ((elementFlags[2] == 2 || elementFlags[2] == 3) && ke == elementNodesPerDir[2] - 1) {
1437 collapseFlags[2] += 2;
1441 GetNodeInfo(ie, je, ke, elementNodesPerDir, &iType, iInd, &orientation);
1442 for (LO dof0 = 0; dof0 < BlkSize; ++dof0) {
1444 idof = ((elemInds[2] * coarseRate[2] + ke) * lFineNodesPerDir[1] * lFineNodesPerDir[0] + (elemInds[1] * coarseRate[1] + je) * lFineNodesPerDir[0] + elemInds[0] * coarseRate[0] + ie) * BlkSize + dof0;
1445 Aghost->getLocalRowView(idof, rowIndices, rowValues);
1446 FormatStencil(BlkSize, ghostInterface, ie, je, ke, rowValues,
1447 elementNodesPerDir, collapseFlags, stencilType, stencil);
1450 for (LO interactingNode = 0; interactingNode < 27; ++interactingNode) {
1452 ko = ke + (interactingNode / 9 - 1);
1454 LO tmp = interactingNode % 9;
1455 jo = je + (tmp / 3 - 1);
1456 io = ie + (tmp % 3 - 1);
1458 GetNodeInfo(io, jo, ko, elementNodesPerDir, &jType, jInd, &dummy);
1460 if ((io > -1 && io < elementNodesPerDir[0]) &&
1461 (jo > -1 && jo < elementNodesPerDir[1]) &&
1462 (ko > -1 && ko < elementNodesPerDir[2])) {
1463 for (LO dof1 = 0; dof1 < BlkSize; ++dof1) {
1465 Aii(iInd * BlkSize + dof0, jInd * BlkSize + dof1) =
1466 stencil[interactingNode * BlkSize + dof1];
1467 }
else if (jType == 2) {
1468 Aif(iInd * BlkSize + dof0, jInd * BlkSize + dof1) =
1469 stencil[interactingNode * BlkSize + dof1];
1470 }
else if (jType == 1) {
1471 Aie(iInd * BlkSize + dof0, jInd * BlkSize + dof1) =
1472 stencil[interactingNode * BlkSize + dof1];
1473 }
else if (jType == 0) {
1474 Aic(iInd * BlkSize + dof0, jInd * BlkSize + dof1) =
1475 -stencil[interactingNode * BlkSize + dof1];
1480 }
else if (iType == 2) {
1481 CollapseStencil(2, orientation, collapseFlags, stencil);
1482 for (LO interactingNode = 0; interactingNode < 27; ++interactingNode) {
1484 ko = ke + (interactingNode / 9 - 1);
1486 LO tmp = interactingNode % 9;
1487 jo = je + (tmp / 3 - 1);
1488 io = ie + (tmp % 3 - 1);
1490 GetNodeInfo(io, jo, ko, elementNodesPerDir, &jType, jInd, &dummy);
1492 if ((io > -1 && io < elementNodesPerDir[0]) &&
1493 (jo > -1 && jo < elementNodesPerDir[1]) &&
1494 (ko > -1 && ko < elementNodesPerDir[2])) {
1495 for (LO dof1 = 0; dof1 < BlkSize; ++dof1) {
1497 Aff(iInd * BlkSize + dof0, jInd * BlkSize + dof1) =
1498 stencil[interactingNode * BlkSize + dof1];
1499 }
else if (jType == 1) {
1500 Afe(iInd * BlkSize + dof0, jInd * BlkSize + dof1) =
1501 stencil[interactingNode * BlkSize + dof1];
1502 }
else if (jType == 0) {
1503 Afc(iInd * BlkSize + dof0, jInd * BlkSize + dof1) =
1504 -stencil[interactingNode * BlkSize + dof1];
1509 }
else if (iType == 1) {
1510 CollapseStencil(1, orientation, collapseFlags, stencil);
1511 for (LO interactingNode = 0; interactingNode < 27; ++interactingNode) {
1513 ko = ke + (interactingNode / 9 - 1);
1515 LO tmp = interactingNode % 9;
1516 jo = je + (tmp / 3 - 1);
1517 io = ie + (tmp % 3 - 1);
1519 GetNodeInfo(io, jo, ko, elementNodesPerDir, &jType, jInd, &dummy);
1521 if ((io > -1 && io < elementNodesPerDir[0]) &&
1522 (jo > -1 && jo < elementNodesPerDir[1]) &&
1523 (ko > -1 && ko < elementNodesPerDir[2])) {
1524 for (LO dof1 = 0; dof1 < BlkSize; ++dof1) {
1526 Aee(iInd * BlkSize + dof0, jInd * BlkSize + dof1) =
1527 stencil[interactingNode * BlkSize + dof1];
1528 }
else if (jType == 0) {
1529 Aec(iInd * BlkSize + dof0, jInd * BlkSize + dof1) =
1530 -stencil[interactingNode * BlkSize + dof1];
1551 Teuchos::SerialDenseSolver<LO, SC> problem;
1552 problem.setMatrix(Teuchos::rcp(&Aee,
false));
1553 problem.setVectors(Teuchos::rcp(&Pe,
false), Teuchos::rcp(&Aec,
false));
1554 problem.factorWithEquilibration(
true);
1556 problem.unequilibrateLHS();
1562 Afc.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, -1.0, Afe, Pe, 1.0);
1564 Teuchos::SerialDenseSolver<LO, SC> problem;
1565 problem.setMatrix(Teuchos::rcp(&Aff,
false));
1566 problem.setVectors(Teuchos::rcp(&Pf,
false), Teuchos::rcp(&Afc,
false));
1567 problem.factorWithEquilibration(
true);
1569 problem.unequilibrateLHS();
1575 Aic.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, -1.0, Aie, Pe, 1.0);
1577 Aic.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, -1.0, Aif, Pf, 1.0);
1579 Teuchos::SerialDenseSolver<LO, SC> problem;
1580 problem.setMatrix(Teuchos::rcp(&Aii,
false));
1581 problem.setVectors(Teuchos::rcp(&Pi,
false), Teuchos::rcp(&Aic,
false));
1582 problem.factorWithEquilibration(
true);
1584 problem.unequilibrateLHS();