46 #ifndef MUELU_GENERALGEOMETRICPFACTORY_DEF_HPP 47 #define MUELU_GENERALGEOMETRICPFACTORY_DEF_HPP 54 #include <Teuchos_SerialDenseMatrix.hpp> 55 #include <Teuchos_SerialDenseVector.hpp> 56 #include <Teuchos_SerialDenseSolver.hpp> 58 #include <Xpetra_CrsMatrixWrap.hpp> 59 #include <Xpetra_ImportFactory.hpp> 60 #include <Xpetra_Matrix.hpp> 61 #include <Xpetra_MapFactory.hpp> 62 #include <Xpetra_MultiVectorFactory.hpp> 63 #include <Xpetra_VectorFactory.hpp> 65 #include <Xpetra_IO.hpp> 75 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
77 RCP<ParameterList> validParamList = rcp(
new ParameterList());
82 validParamList->set<std::string > (
"Coarsen",
"{2}",
"Coarsening rate in all spatial dimensions");
83 validParamList->set<
int> (
"order", 1,
"Order of the interpolation scheme used");
84 validParamList->set<RCP<const FactoryBase> >(
"A", Teuchos::null,
"Generating factory of the matrix A");
85 validParamList->set<RCP<const FactoryBase> >(
"Nullspace", Teuchos::null,
"Generating factory of the nullspace");
86 validParamList->set<RCP<const FactoryBase> >(
"Coordinates", Teuchos::null,
"Generating factory for coorindates");
87 validParamList->set<RCP<const FactoryBase> >(
"gNodesPerDim", Teuchos::null,
"Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
88 validParamList->set<RCP<const FactoryBase> >(
"lNodesPerDim", Teuchos::null,
"Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
89 validParamList->set<std::string >(
"axisPermutation",
"{0,1,2}",
"Assuming a global (x,y,z) orientation, local might be (z,y,x). This vector gives a permutation from global to local orientation.");
91 return validParamList;
94 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
96 Input(fineLevel,
"A");
97 Input(fineLevel,
"Nullspace");
98 Input(fineLevel,
"Coordinates");
106 "gNodesPerDim was not provided by the user on level0!");
109 Input(fineLevel,
"gNodesPerDim");
119 "lNodesPerDim was not provided by the user on level0!");
122 Input(fineLevel,
"lNodesPerDim");
126 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
128 return BuildP(fineLevel, coarseLevel);
131 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
136 using xdMV = Xpetra::MultiVector<double,LO,GO,NO>;
137 RCP<Matrix> A = Get< RCP<Matrix> > (fineLevel,
"A");
138 RCP<MultiVector> fineNullspace = Get< RCP<MultiVector> > (fineLevel,
"Nullspace");
139 RCP<xdMV> fineCoords = Get< RCP<xdMV> >(fineLevel,
"Coordinates");
140 RCP<xdMV> coarseCoords;
143 const ParameterList& pL = GetParameterList();
146 LO blkSize = A->GetFixedBlockSize();
147 RCP<const Map> rowMap = A->getRowMap();
148 LO numDimensions = 0;
149 Array<GO> gFineNodesPerDir(3);
150 Array<GO> gCoarseNodesPerDir(3);
152 Array<LO> lFineNodesPerDir(3);
153 Array<LO> lCoarseNodesPerDir(3);
154 Array<LO> mapDirL2G(3);
155 Array<LO> mapDirG2L(3);
157 TEUCHOS_TEST_FOR_EXCEPTION(fineCoords==Teuchos::null,
Exceptions::RuntimeError,
"Coordinates cannot be accessed from fine level!");
158 numDimensions = fineCoords->getNumVectors();
159 lNumFinePoints = fineCoords->getLocalLength();
162 if(fineLevel.GetLevelID() == 0) {
163 gFineNodesPerDir = fineLevel.Get<Array<GO> >(
"gNodesPerDim",
NoFactory::get());
164 lFineNodesPerDir = fineLevel.Get<Array<LO> >(
"lNodesPerDim",
NoFactory::get());
167 gFineNodesPerDir = Get<Array<GO> >(fineLevel,
"gNodesPerDim");
170 lFineNodesPerDir = Get<Array<LO> >(fineLevel,
"lNodesPerDim");
174 std::string coarsenRate = pL.get<std::string>(
"Coarsen");
175 ArrayRCP<LO> coarseRate = arcp<LO>(3);
176 Teuchos::Array<LO> crates;
178 crates = Teuchos::fromStringToArray<LO>(coarsenRate);
179 }
catch(
const Teuchos::InvalidArrayStringRepresentation e) {
180 GetOStream(
Errors,-1) <<
" *** Coarsen must be a string convertible into an array! *** " << std::endl;
183 TEUCHOS_TEST_FOR_EXCEPTION((crates.size()>1) && (crates.size()<numDimensions),
185 "Coarsen must have at least as many components as the number of spatial dimensions in the problem.");
186 for(LO i = 0; i < 3; ++i) {
187 if(i < numDimensions) {
188 if( crates.size()==1 ) {
189 coarseRate[i] = crates[0];
190 }
else if( crates.size()==numDimensions ) {
191 coarseRate[i] = crates[i];
198 int interpolationOrder = pL.get<
int>(
"order");
199 TEUCHOS_TEST_FOR_EXCEPTION((interpolationOrder < 0) || (interpolationOrder > 1),
201 "The interpolation order can only be set to 0 or 1.");
204 std::string axisPermutation = pL.get<std::string>(
"axisPermutation");
206 mapDirG2L = Teuchos::fromStringToArray<LO>(axisPermutation);
207 }
catch(
const Teuchos::InvalidArrayStringRepresentation e) {
208 GetOStream(
Errors,-1) <<
" *** axisPermutation must be a string convertible into an array! *** " << std::endl;
211 for(LO i = 0; i < numDimensions; ++i) {
212 TEUCHOS_TEST_FOR_EXCEPTION(mapDirG2L[i] > numDimensions,
214 "axis permutation values must all be less than the number of spatial dimensions.");
215 mapDirL2G[mapDirG2L[i]] = i;
232 GO minGlobalIndex, maxGlobalIndex, rem;
233 GO gIndices[6] = {0, 0, 0, 0, 0, 0};
234 LO offsets[6] = {0, 0, 0, 0, 0, 0};
235 RCP<const Map> fineCoordsMap = fineCoords->getMap();
236 minGlobalIndex = fineCoordsMap->getMinGlobalIndex();
237 maxGlobalIndex = fineCoordsMap->getMaxGlobalIndex();
238 if(numDimensions == 1) {
239 gIndices[0] = minGlobalIndex;
240 offsets[0] = Teuchos::as<LO>(gIndices[0]) % coarseRate[0];
242 gIndices[3] = maxGlobalIndex;
243 offsets[3] = Teuchos::as<LO>(gIndices[3]) % coarseRate[0];
244 }
else if(numDimensions == 2) {
245 gIndices[1] = minGlobalIndex / Teuchos::as<GO>(gFineNodesPerDir[0]);
246 offsets[1] = Teuchos::as<LO>(gIndices[1]) % coarseRate[1];
247 gIndices[0] = minGlobalIndex % Teuchos::as<GO>(gFineNodesPerDir[0]);
248 offsets[0] = Teuchos::as<LO>(gIndices[0]) % coarseRate[0];
250 gIndices[4] = maxGlobalIndex / Teuchos::as<GO>(gFineNodesPerDir[0]);
251 offsets[4] = Teuchos::as<LO>(gIndices[4]) % coarseRate[1];
252 gIndices[3] = maxGlobalIndex % Teuchos::as<GO>(gFineNodesPerDir[0]);
253 offsets[3] = Teuchos::as<LO>(gIndices[3]) % coarseRate[3];
254 }
else if(numDimensions == 3) {
255 gIndices[2] = minGlobalIndex / Teuchos::as<GO>(gFineNodesPerDir[0]*gFineNodesPerDir[1]);
256 rem = minGlobalIndex % Teuchos::as<GO>(gFineNodesPerDir[0]*gFineNodesPerDir[1]);
257 offsets[2] = Teuchos::as<LO>(gIndices[2]) % coarseRate[2];
258 gIndices[1] = rem / Teuchos::as<GO>(gFineNodesPerDir[0]);
259 offsets[1] = Teuchos::as<LO>(gIndices[1]) % coarseRate[1];
260 gIndices[0] = rem % Teuchos::as<GO>(gFineNodesPerDir[0]);
261 offsets[0] = Teuchos::as<LO>(gIndices[0]) % coarseRate[0];
263 gIndices[5] = maxGlobalIndex / Teuchos::as<GO>(gFineNodesPerDir[0]*gFineNodesPerDir[1]);
264 rem = maxGlobalIndex % Teuchos::as<GO>(gFineNodesPerDir[0]*gFineNodesPerDir[1]);
265 offsets[5] = Teuchos::as<LO>(gIndices[5]) % coarseRate[2];
266 gIndices[4] = rem / Teuchos::as<GO>(gFineNodesPerDir[0]);
267 offsets[4] = Teuchos::as<LO>(gIndices[4]) % coarseRate[1];
268 gIndices[3] = rem % Teuchos::as<GO>(gFineNodesPerDir[0]);
269 offsets[3] = Teuchos::as<LO>(gIndices[3]) % coarseRate[0];
277 bool ghostInterface[6] = {
false,
false,
false,
false,
false,
false};
278 for(LO i=0; i < numDimensions; ++i) {
279 if( gIndices[i] != 0) {
280 ghostInterface[2*i]=
true;
282 if( (gIndices[i]+lFineNodesPerDir[mapDirL2G[i]]) != gFineNodesPerDir[i] ) {
283 ghostInterface[2*i+1]=
true;
292 LO endRate[3] = {0, 0, 0};
297 for(LO i = 0; i < 3; ++i) {
298 if(i < numDimensions) {
300 gCoarseNodesPerDir[i] = (gFineNodesPerDir[i] - 1) / coarseRate[i];
301 endRate[i] = Teuchos::as<LO>((gFineNodesPerDir[i] - 1) % coarseRate[i]);
302 if(endRate[i] == 0) {
303 endRate[i] = coarseRate[i];
304 ++gCoarseNodesPerDir[i];
306 gCoarseNodesPerDir[i] += 2;
310 gCoarseNodesPerDir[i] = 1;
314 for(LO i = 0; i < 3; ++i) {
315 if(i < numDimensions) {
319 if( (gIndices[mapDirG2L[i]] + lFineNodesPerDir[i]) == gFineNodesPerDir[mapDirG2L[i]] ) {
320 lCoarseNodesPerDir[i] = (lFineNodesPerDir[i] - endRate[mapDirG2L[i]] + offsets[mapDirG2L[i]] - 1) / coarseRate[mapDirG2L[i]] + 1;
321 if(offsets[mapDirG2L[i]] == 0) {++lCoarseNodesPerDir[i];}
323 lCoarseNodesPerDir[i] = (lFineNodesPerDir[i] + offsets[mapDirG2L[i]] - 1) / coarseRate[mapDirG2L[i]];
324 if(offsets[mapDirG2L[i]] == 0) {++lCoarseNodesPerDir[i];}
327 lCoarseNodesPerDir[i] = 1;
329 if(lFineNodesPerDir[i] < 1) {lCoarseNodesPerDir[i] = 0;}
335 LO lNumCoarsePoints = lCoarseNodesPerDir[0]*lCoarseNodesPerDir[1]*lCoarseNodesPerDir[2];
336 LO nTerms = 8*lNumFinePoints - 7*lNumCoarsePoints;
337 nTerms=nTerms*blkSize;
341 const LO complementaryIndices[3][2] = {{1,2}, {0,2}, {0,1}};
342 for(LO i = 0; i < 3; ++i) {
345 if(ghostInterface[2*i] || ghostInterface[2*i+1]) {
346 if(i == 0) {tmp = lCoarseNodesPerDir[mapDirL2G[1]]*lCoarseNodesPerDir[mapDirL2G[2]];}
347 if(i == 1) {tmp = lCoarseNodesPerDir[mapDirL2G[0]]*lCoarseNodesPerDir[mapDirL2G[2]];}
348 if(i == 2) {tmp = lCoarseNodesPerDir[mapDirL2G[0]]*lCoarseNodesPerDir[mapDirL2G[1]];}
351 if(ghostInterface[2*i] && ghostInterface[2*i+1]) {tmp = 2*tmp;}
355 for(LO j = 0; j < 2; ++j) {
356 for(LO k = 0; k < 2; ++k) {
358 if(ghostInterface[2*complementaryIndices[i][0]+j] && ghostInterface[2*complementaryIndices[i][1]+k]) {
359 numGhosts += lCoarseNodesPerDir[mapDirL2G[i]];
362 if(ghostInterface[2*i] && (i == 0)) { numGhosts += 1; }
363 if(ghostInterface[2*i+1] && (i == 0)) { numGhosts += 1; }
375 Array<GO> ghostsGIDs(numGhosts);
378 GO startingGID = minGlobalIndex;
379 Array<GO> startingIndices(3);
382 if(ghostInterface[4] && (offsets[2] == 0)) {
383 if(gIndices[2] + coarseRate[2] > gFineNodesPerDir[2]) {
384 startingGID -= endRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
386 startingGID -= coarseRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
389 startingGID -= offsets[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
391 if(ghostInterface[2] && (offsets[1] == 0)) {
392 if(gIndices[1] + coarseRate[1] > gFineNodesPerDir[1]) {
393 startingGID -= endRate[1]*gFineNodesPerDir[0];
395 startingGID -= coarseRate[1]*gFineNodesPerDir[0];
398 startingGID -= offsets[1]*gFineNodesPerDir[0];
400 if(ghostInterface[0] && (offsets[0] == 0)) {
401 if(gIndices[0] + coarseRate[0] > gFineNodesPerDir[0]) {
402 startingGID -= endRate[0];
404 startingGID -= coarseRate[0];
407 startingGID -= offsets[0];
412 startingIndices[2] = startingGID / (gFineNodesPerDir[1]*gFineNodesPerDir[0]);
413 tmp = startingGID % (gFineNodesPerDir[1]*gFineNodesPerDir[0]);
414 startingIndices[1] = tmp / gFineNodesPerDir[0];
415 startingIndices[0] = tmp % gFineNodesPerDir[0];
418 GO ghostOffset[3] = {0, 0, 0};
419 LO lengthZero = lCoarseNodesPerDir[mapDirL2G[0]];
420 LO lengthOne = lCoarseNodesPerDir[mapDirL2G[1]];
421 LO lengthTwo = lCoarseNodesPerDir[mapDirL2G[2]];
422 if(ghostInterface[0]) {++lengthZero;}
423 if(ghostInterface[1]) {++lengthZero;}
424 if(ghostInterface[2]) {++lengthOne;}
425 if(ghostInterface[3]) {++lengthOne;}
426 if(ghostInterface[4]) {++lengthTwo;}
427 if(ghostInterface[5]) {++lengthTwo;}
430 if(ghostInterface[4]) {
431 ghostOffset[2] = startingGID;
432 for(LO j = 0; j < lengthOne; ++j) {
433 if( (j == lengthOne-1) && (startingIndices[1] + j*coarseRate[1] + 1 > gFineNodesPerDir[1]) ) {
434 ghostOffset[1] = ((j-1)*coarseRate[1] + endRate[1])*gFineNodesPerDir[0];
436 ghostOffset[1] = j*coarseRate[1]*gFineNodesPerDir[0];
438 for(LO k = 0; k < lengthZero; ++k) {
439 if( (k == lengthZero-1) && (startingIndices[0] + k*coarseRate[0] + 1 > gFineNodesPerDir[0]) ) {
440 ghostOffset[0] = (k-1)*coarseRate[0] + endRate[0];
442 ghostOffset[0] = k*coarseRate[0];
446 ghostsGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
454 for(LO i = 0; i < lengthTwo; ++i) {
457 if( !((i == lengthTwo-1) && ghostInterface[5]) && !((i == 0) && ghostInterface[4]) ) {
460 if( (i == lengthTwo-1) && !ghostInterface[5] ) {
461 ghostOffset[2] = startingGID + ((i-1)*coarseRate[2] + endRate[2])*gFineNodesPerDir[1]*gFineNodesPerDir[0];
463 ghostOffset[2] = startingGID + i*coarseRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
465 for(LO j = 0; j < lengthOne; ++j) {
466 if( (j == 0) && ghostInterface[2] ) {
467 for(LO k = 0; k < lengthZero; ++k) {
468 if( (k == lengthZero-1) && (startingIndices[0] + k*coarseRate[0] + 1 > gFineNodesPerDir[0]) ) {
470 ghostOffset[0] = endRate[0];
472 ghostOffset[0] = (k-1)*coarseRate[0] + endRate[0];
475 ghostOffset[0] = k*coarseRate[0];
478 ghostsGIDs[countGhosts] = ghostOffset[2] + ghostOffset[0];
481 }
else if( (j == lengthOne-1) && ghostInterface[3] ) {
484 if( (j == lengthOne-1) && (startingIndices[1] + j*coarseRate[1] + 1 > gFineNodesPerDir[1]) ) {
485 ghostOffset[1] = ((j-1)*coarseRate[1] + endRate[1])*gFineNodesPerDir[0];
487 ghostOffset[1] = j*coarseRate[1]*gFineNodesPerDir[0];
489 for(LO k = 0; k < lengthZero; ++k) {
490 if( (k == lengthZero-1) && (startingIndices[0] + k*coarseRate[0] + 1 > gFineNodesPerDir[0]) ) {
491 ghostOffset[0] = (k-1)*coarseRate[0] + endRate[0];
493 ghostOffset[0] = k*coarseRate[0];
495 ghostsGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
500 if( (j == lengthOne-1) && (startingIndices[1] + j*coarseRate[1] + 1 > gFineNodesPerDir[1]) ) {
501 ghostOffset[1] = ( (j-1)*coarseRate[1] + endRate[1] )*gFineNodesPerDir[0];
503 ghostOffset[1] = j*coarseRate[1]*gFineNodesPerDir[0];
507 if(ghostInterface[0]) {
508 ghostsGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1];
511 if(ghostInterface[1]) {
512 if( (startingIndices[0] + (lengthZero-1)*coarseRate[0]) > gFineNodesPerDir[0] - 1 ) {
514 ghostOffset[0] = (lengthZero-2)*coarseRate[0] + endRate[0];
516 ghostOffset[0] = endRate[0];
519 ghostOffset[0] = (lengthZero-1)*coarseRate[0];
521 ghostsGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
530 if(ghostInterface[5]) {
531 if( startingIndices[2] + (lengthTwo-1)*coarseRate[2] + 1 > gFineNodesPerDir[2] ) {
532 ghostOffset[2] = startingGID + ((lengthTwo-2)*coarseRate[2] + endRate[2])*gFineNodesPerDir[1]*gFineNodesPerDir[0];
534 ghostOffset[2] = startingGID + (lengthTwo-1)*coarseRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
536 for(LO j = 0; j < lengthOne; ++j) {
537 if( (j == lengthOne-1) && (startingIndices[1] + j*coarseRate[1] + 1 > gFineNodesPerDir[1]) ) {
538 ghostOffset[1] = ( (j-1)*coarseRate[1] + endRate[1] )*gFineNodesPerDir[0];
540 ghostOffset[1] = j*coarseRate[1]*gFineNodesPerDir[0];
542 for(LO k = 0; k < lengthZero; ++k) {
543 if( (k == lengthZero-1) && (startingIndices[0] + k*coarseRate[0] + 1 > gFineNodesPerDir[0]) ) {
544 ghostOffset[0] = (k-1)*coarseRate[0] + endRate[0];
546 ghostOffset[0] = k*coarseRate[0];
548 ghostsGIDs[countGhosts] = ghostOffset[2] + ghostOffset[1] + ghostOffset[0];
559 RCP<const Map> stridedDomainMapP;
561 MakeGeneralGeometricP(numDimensions, mapDirL2G, mapDirG2L, lFineNodesPerDir, lCoarseNodesPerDir, gCoarseNodesPerDir,
562 gFineNodesPerDir, coarseRate, endRate, offsets, ghostInterface, fineCoords, nTerms, blkSize,
563 stridedDomainMapP, A, P, coarseCoords, ghostsGIDs, interpolationOrder);
566 if (A->IsView(
"stridedMaps") ==
true) {
567 P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedDomainMapP);
569 P->CreateView(
"stridedMaps", P->getRangeMap(), stridedDomainMapP);
573 Set(coarseLevel,
"P", P);
574 Set(coarseLevel,
"coarseCoordinates", coarseCoords);
575 Set<Array<GO> >(coarseLevel,
"gCoarseNodesPerDim", gCoarseNodesPerDir);
576 Set<Array<LO> >(coarseLevel,
"lCoarseNodesPerDim", lCoarseNodesPerDir);
580 RCP<MultiVector> coarseNullspace = MultiVectorFactory::Build(P->getDomainMap(), fineNullspace->getNumVectors());
581 P->apply(*fineNullspace, *coarseNullspace, Teuchos::TRANS, Teuchos::ScalarTraits<SC>::one(), Teuchos::ScalarTraits<SC>::zero());
582 Set(coarseLevel,
"Nullspace", coarseNullspace);
586 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
587 void GeneralGeometricPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::MakeGeneralGeometricP(LO
const ndm,
const Array<LO> mapDirL2G,
const Array<LO> mapDirG2L,
const Array<LO> lFineNodesPerDir,
const Array<LO> lCoarseNodesPerDir, Array<GO> gCoarseNodesPerDir, Array<GO> gFineNodesPerDir, ArrayRCP<LO>
const coarseRate, LO
const endRate[3], LO
const offsets[6],
bool const ghostInterface[6],
const RCP<Xpetra::MultiVector<double,LO,GO,Node> >& fineCoords, LO
const nnzP, LO
const dofsPerNode, RCP<const Map>& stridedDomainMapP, RCP<Matrix> & Amat, RCP<Matrix>& P, RCP<Xpetra::MultiVector<double,LO,GO,Node> >& coarseCoords, Array<GO> ghostsGIDs,
int interpolationOrder)
const {
619 using xdMV = Xpetra::MultiVector<double,LO,GO,NO>;
621 LO lNumFineNodes = lFineNodesPerDir[0]*lFineNodesPerDir[1]*lFineNodesPerDir[2];
622 LO lNumCoarseNodes = lCoarseNodesPerDir[0]*lCoarseNodesPerDir[1]*lCoarseNodesPerDir[2];
623 GO gNumCoarseNodes = gCoarseNodesPerDir[0]*gCoarseNodesPerDir[1]*gCoarseNodesPerDir[2];
624 LO lNumGhostNodes = ghostsGIDs.size();
625 GO numGloCols = dofsPerNode*gNumCoarseNodes;
634 RCP<const Map> fineCoordsMap = fineCoords->getMap();
637 gStartIndices[2] = fineCoordsMap->getMinGlobalIndex() / (gFineNodesPerDir[1]*gFineNodesPerDir[0]);
638 GO dummy = fineCoordsMap->getMinGlobalIndex() % (gFineNodesPerDir[1]*gFineNodesPerDir[0]);
639 gStartIndices[1] = dummy / gFineNodesPerDir[0];
640 gStartIndices[0] = dummy % gFineNodesPerDir[0];
643 Array<GO> gCoarseNodesGIDs(lNumCoarseNodes);
644 LO currentNode, offset2, offset1, offset0;
646 for(LO ind2 = 0; ind2 < lCoarseNodesPerDir[mapDirL2G[2]]; ++ind2) {
647 if(offsets[2] == 0) {
648 offset2 = gStartIndices[2];
650 if(gStartIndices[2] + endRate[2] - offsets[2] == gFineNodesPerDir[2] - 1) {
651 offset2 = gStartIndices[2] + endRate[2] - offsets[2];
653 offset2 = gStartIndices[2] + coarseRate[2] - offsets[2];
656 if(offset2 + ind2*coarseRate[2] > gFineNodesPerDir[2] - 1) {
657 offset2 += (ind2 - 1)*coarseRate[2] + endRate[2];
659 offset2 += ind2*coarseRate[2];
661 offset2 = offset2*gFineNodesPerDir[1]*gFineNodesPerDir[0];
663 for(LO ind1 = 0; ind1 < lCoarseNodesPerDir[mapDirL2G[1]]; ++ind1) {
664 if(offsets[1] == 0) {
665 offset1 = gStartIndices[1];
667 if(gStartIndices[1] + endRate[1] - offsets[1] == gFineNodesPerDir[1] - 1) {
668 offset1 = gStartIndices[1] + endRate[1] - offsets[1];
670 offset1 = gStartIndices[1] + coarseRate[1] - offsets[1];
673 if(offset1 + ind1*coarseRate[1] > gFineNodesPerDir[1] - 1) {
674 offset1 += (ind1 - 1)*coarseRate[1] + endRate[1];
676 offset1 += ind1*coarseRate[1];
678 offset1 = offset1*gFineNodesPerDir[0];
679 for(LO ind0 = 0; ind0 < lCoarseNodesPerDir[mapDirL2G[0]]; ++ind0) {
680 offset0 = gStartIndices[0] - offsets[0];
681 if(offsets[0] == 0) {
682 offset0 += ind0*coarseRate[0];
684 offset0 += (ind0 + 1)*coarseRate[0];
686 if(offset0 > gFineNodesPerDir[0] - 1) {offset0 += endRate[0] - coarseRate[0];}
688 currentNode = ind2*lCoarseNodesPerDir[mapDirL2G[1]]*lCoarseNodesPerDir[mapDirL2G[0]]
689 + ind1*lCoarseNodesPerDir[mapDirL2G[0]]
691 gCoarseNodesGIDs[currentNode] = offset2 + offset1 + offset0;
698 Array<GO> colGIDs(dofsPerNode*(lNumCoarseNodes+lNumGhostNodes));
699 Array<GO> coarseNodesGIDs(lNumCoarseNodes);
700 GO fineNodesPerCoarseSlab = coarseRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
701 GO fineNodesEndCoarseSlab = endRate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0];
702 GO fineNodesPerCoarsePlane = coarseRate[1]*gFineNodesPerDir[0];
703 GO fineNodesEndCoarsePlane = endRate[1]*gFineNodesPerDir[0];
704 GO coarseNodesPerCoarseLayer = gCoarseNodesPerDir[1]*gCoarseNodesPerDir[0];
705 GO gCoarseNodeOnCoarseGridGID;
707 Array<int> ghostsPIDs (lNumGhostNodes);
708 Array<LO> ghostsLIDs (lNumGhostNodes);
709 Array<LO> ghostsPermut(lNumGhostNodes);
710 for(LO k = 0; k < lNumGhostNodes; ++k) {ghostsPermut[k] = k;}
711 fineCoordsMap->getRemoteIndexList(ghostsGIDs, ghostsPIDs, ghostsLIDs);
712 sh_sort_permute(ghostsPIDs.begin(),ghostsPIDs.end(), ghostsPermut.begin(),ghostsPermut.end());
715 GO tmpInds[3], tmpVars[2];
720 for(LO col = 0; col < lNumCoarseNodes; ++col) {
721 if((endRate[2] != coarseRate[2]) && (gCoarseNodesGIDs[col] > (gCoarseNodesPerDir[2] - 2)*fineNodesPerCoarseSlab + fineNodesEndCoarseSlab - 1)) {
722 tmpInds[2] = gCoarseNodesGIDs[col] / fineNodesPerCoarseSlab + 1;
723 tmpVars[0] = gCoarseNodesGIDs[col] - (tmpInds[2] - 1)*fineNodesPerCoarseSlab - fineNodesEndCoarseSlab;
725 tmpInds[2] = gCoarseNodesGIDs[col] / fineNodesPerCoarseSlab;
726 tmpVars[0] = gCoarseNodesGIDs[col] % fineNodesPerCoarseSlab;
728 if((endRate[1] != coarseRate[1]) && (tmpVars[0] > (gCoarseNodesPerDir[1] - 2)*fineNodesPerCoarsePlane + fineNodesEndCoarsePlane - 1)) {
729 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane + 1;
730 tmpVars[1] = tmpVars[0] - (tmpInds[1] - 1)*fineNodesPerCoarsePlane - fineNodesEndCoarsePlane;
732 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane;
733 tmpVars[1] = tmpVars[0] % fineNodesPerCoarsePlane;
735 if(tmpVars[1] == gFineNodesPerDir[0] - 1) {
736 tmpInds[0] = gCoarseNodesPerDir[0] - 1;
738 tmpInds[0] = tmpVars[1] / coarseRate[0];
740 gInd[2] = col / (lCoarseNodesPerDir[mapDirG2L[1]]*lCoarseNodesPerDir[mapDirG2L[0]]);
741 tmp = col % (lCoarseNodesPerDir[mapDirG2L[1]]*lCoarseNodesPerDir[mapDirG2L[0]]);
742 gInd[1] = tmp / lCoarseNodesPerDir[mapDirG2L[0]];
743 gInd[0] = tmp % lCoarseNodesPerDir[mapDirG2L[0]];
744 lCol = gInd[mapDirG2L[2]]*(lCoarseNodesPerDir[1]*lCoarseNodesPerDir[0]) + gInd[mapDirG2L[1]]*lCoarseNodesPerDir[0] + gInd[mapDirG2L[0]];
745 gCoarseNodeOnCoarseGridGID = tmpInds[2]*coarseNodesPerCoarseLayer + tmpInds[1]*gCoarseNodesPerDir[0] + tmpInds[0];
746 coarseNodesGIDs[lCol] = gCoarseNodeOnCoarseGridGID;
747 for(LO dof = 0; dof < dofsPerNode; ++dof) {
748 colGIDs[dofsPerNode*lCol + dof] = dofsPerNode*gCoarseNodeOnCoarseGridGID + dof;
753 for(LO col = lNumCoarseNodes; col < lNumCoarseNodes + lNumGhostNodes; ++col) {
754 if((endRate[2] != coarseRate[2]) && (ghostsGIDs[ghostsPermut[col - lNumCoarseNodes]] > (gCoarseNodesPerDir[2] - 2)*fineNodesPerCoarseSlab + fineNodesEndCoarseSlab - 1)) {
755 tmpInds[2] = ghostsGIDs[ghostsPermut[col - lNumCoarseNodes]] / fineNodesPerCoarseSlab + 1;
756 tmpVars[0] = ghostsGIDs[ghostsPermut[col - lNumCoarseNodes]] - (tmpInds[2] - 1)*fineNodesPerCoarseSlab - fineNodesEndCoarseSlab;
758 tmpInds[2] = ghostsGIDs[ghostsPermut[col - lNumCoarseNodes]] / fineNodesPerCoarseSlab;
759 tmpVars[0] = ghostsGIDs[ghostsPermut[col - lNumCoarseNodes]] % fineNodesPerCoarseSlab;
761 if((endRate[1] != coarseRate[1]) && (tmpVars[0] > (gCoarseNodesPerDir[1] - 2)*fineNodesPerCoarsePlane + fineNodesEndCoarsePlane - 1)) {
762 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane + 1;
763 tmpVars[1] = tmpVars[0] - (tmpInds[1] - 1)*fineNodesPerCoarsePlane - fineNodesEndCoarsePlane;
765 tmpInds[1] = tmpVars[0] / fineNodesPerCoarsePlane;
766 tmpVars[1] = tmpVars[0] % fineNodesPerCoarsePlane;
768 if(tmpVars[1] == gFineNodesPerDir[0] - 1) {
769 tmpInds[0] = gCoarseNodesPerDir[0] - 1;
771 tmpInds[0] = tmpVars[1] / coarseRate[0];
773 gCoarseNodeOnCoarseGridGID = tmpInds[2]*coarseNodesPerCoarseLayer + tmpInds[1]*gCoarseNodesPerDir[0] + tmpInds[0];
774 for(LO dof = 0; dof < dofsPerNode; ++dof) {
775 colGIDs[dofsPerNode*col + dof] = dofsPerNode*gCoarseNodeOnCoarseGridGID + dof;
782 RCP<const Map> rowMapP = Amat->getDomainMap();
784 RCP<const Map> domainMapP = Xpetra::MapFactory<LO,GO,NO>::Build(rowMapP->lib(),
786 colGIDs.view(0, dofsPerNode*lNumCoarseNodes),
787 rowMapP->getIndexBase(),
790 RCP<const Map> colMapP = Xpetra::MapFactory<LO,GO,NO>::Build(rowMapP->lib(),
791 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
792 colGIDs.view(0, colGIDs.size()),
793 rowMapP->getIndexBase(),
796 std::vector<size_t> strideInfo(1);
797 strideInfo[0] = dofsPerNode;
798 stridedDomainMapP = Xpetra::StridedMapFactory<LO,GO,NO>::Build(domainMapP, strideInfo);
801 RCP<const Map> coarseCoordsMap = MapFactory::Build (fineCoordsMap->lib(),
803 coarseNodesGIDs.view(0, lNumCoarseNodes),
804 fineCoordsMap->getIndexBase(),
808 RCP<const Map> ghostMap = Xpetra::MapFactory<LO,GO,NO>::Build(fineCoordsMap->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), ghostsGIDs.view(0, lNumGhostNodes),
809 fineCoordsMap->getIndexBase(), rowMapP->getComm());
810 RCP<const Import> importer = ImportFactory::Build(fineCoordsMap, ghostMap);
811 RCP<xdMV> ghostCoords = Xpetra::MultiVectorFactory<double,LO,GO,NO>::Build(ghostMap, ndm);
812 ghostCoords->doImport(*fineCoords, *importer, Xpetra::INSERT);
814 P = rcp(
new CrsMatrixWrap(rowMapP, colMapP, 0, Xpetra::StaticProfile));
815 RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
817 ArrayRCP<size_t> iaP;
821 PCrs->allocateAllValues(nnzP, iaP, jaP, valP);
823 ArrayView<size_t> ia = iaP();
824 ArrayView<LO> ja = jaP();
825 ArrayView<SC> val = valP();
827 LO nStencil = 0; LO tStencil = 0;
828 LO firstCoarseNodeIndex;
837 ArrayRCP< ArrayRCP<double> > lFineCoords(3);
838 ArrayRCP< ArrayRCP<double> > lGhostCoords(3);
839 RCP<const Map> ghostCoordsMap = ghostCoords->getMap();
840 RCP<Xpetra::Vector<double, LO, GO, NO> > zeros = Xpetra::VectorFactory<double, LO, GO, NO>::Build(fineCoordsMap,
true);
841 RCP<Xpetra::Vector<double, LO, GO, NO> > ghostZeros = Xpetra::VectorFactory<double, LO, GO, NO>::Build(ghostCoordsMap,
true);
844 coarseCoords = Xpetra::MultiVectorFactory<double,LO,GO,Node>::Build(coarseCoordsMap, Teuchos::as<size_t>(ndm));
845 ArrayRCP<double> xCoarseNodes; ArrayRCP<double> yCoarseNodes; ArrayRCP<double> zCoarseNodes;
848 lFineCoords[0] = fineCoords->getDataNonConst(0);
849 lFineCoords[1] = zeros->getDataNonConst(0);
850 lFineCoords[2] = zeros->getDataNonConst(0);
851 lGhostCoords[0] = ghostCoords->getDataNonConst(0);
852 lGhostCoords[1] = ghostZeros->getDataNonConst(0);
853 lGhostCoords[2] = ghostZeros->getDataNonConst(0);
855 xCoarseNodes = coarseCoords->getDataNonConst(0);
857 lFineCoords[0] = fineCoords->getDataNonConst(0);
858 lFineCoords[1] = fineCoords->getDataNonConst(1);
859 lFineCoords[2] = zeros->getDataNonConst(0);
860 lGhostCoords[0] = ghostCoords->getDataNonConst(0);
861 lGhostCoords[1] = ghostCoords->getDataNonConst(1);
862 lGhostCoords[2] = ghostZeros->getDataNonConst(0);
864 xCoarseNodes= coarseCoords->getDataNonConst(0);
865 yCoarseNodes= coarseCoords->getDataNonConst(1);
867 lFineCoords[0] = fineCoords->getDataNonConst(0);
868 lFineCoords[1] = fineCoords->getDataNonConst(1);
869 lFineCoords[2] = fineCoords->getDataNonConst(2);
870 lGhostCoords[0] = ghostCoords->getDataNonConst(0);
871 lGhostCoords[1] = ghostCoords->getDataNonConst(1);
872 lGhostCoords[2] = ghostCoords->getDataNonConst(2);
874 xCoarseNodes = coarseCoords->getDataNonConst(0);
875 yCoarseNodes = coarseCoords->getDataNonConst(1);
876 zCoarseNodes = coarseCoords->getDataNonConst(2);
886 GO currentCoarseNode = 0;
887 for(LO i = 0; i < lNumFineNodes; ++i) {
892 tmp=std::div(i,lFineNodesPerDir[0]*lFineNodesPerDir[1]);
893 indices[0][2] = tmp.quot;
894 tmp=std::div(tmp.rem,lFineNodesPerDir[0]);
895 indices[0][1] = tmp.quot;
896 indices[0][0] = tmp.rem;
899 tmp=std::div(indices[0][0] - offsets[0],coarseRate[0]);
900 indices[1][0] = tmp.quot;
901 tmp=std::div(indices[0][1] - offsets[1],coarseRate[1]);
902 indices[1][1] = tmp.quot;
903 tmp=std::div(indices[0][2] - offsets[2],coarseRate[2]);
904 indices[1][2] = tmp.quot;
909 indices[2][0] = (indices[0][0] + offsets[0]) % coarseRate[0];
910 indices[2][1] = (indices[0][1] + offsets[1]) % coarseRate[1];
911 indices[2][2] = (indices[0][2] + offsets[2]) % coarseRate[2];
914 indices[3][0] = indices[1][0]*coarseRate[0];
915 indices[3][1] = indices[1][1]*coarseRate[1];
916 indices[3][2] = indices[1][2]*coarseRate[2];
918 if( (indices[0][0] == lFineNodesPerDir[0]-1) && !ghostInterface[1] ) {
919 indices[1][0] = lCoarseNodesPerDir[0]-1;
921 indices[3][0] = lFineNodesPerDir[0]-1;
923 if( (indices[0][1] == lFineNodesPerDir[1]-1) && !ghostInterface[3] ) {
924 indices[1][1] = lCoarseNodesPerDir[1]-1;
926 indices[3][1] = lFineNodesPerDir[1]-1;
928 if( (indices[0][2] == lFineNodesPerDir[2]-1) && !ghostInterface[5] ) {
929 indices[1][2] = lCoarseNodesPerDir[2]-1;
931 indices[3][2] = lFineNodesPerDir[2]-1;
934 Array<GO> currentNodeIndices(3);
935 currentNodeIndices[0] = gStartIndices[0] + Teuchos::as<GO>(indices[0][mapDirL2G[0]]);
936 currentNodeIndices[1] = gStartIndices[1] + Teuchos::as<GO>(indices[0][mapDirL2G[1]]);
937 currentNodeIndices[2] = gStartIndices[2] + Teuchos::as<GO>(indices[0][mapDirL2G[2]]);
948 if(currentNodeIndices[0] >= gFineNodesPerDir[0] - endRate[0] - 1) {
949 rate[0] = endRate[0];
951 rate[0] = coarseRate[0];
953 if(currentNodeIndices[1] >= gFineNodesPerDir[1] - endRate[1] - 1) {
954 rate[1] = endRate[1];
956 rate[1] = coarseRate[1];
958 if(currentNodeIndices[2] >= gFineNodesPerDir[2] - endRate[2] - 1) {
959 rate[2] = endRate[2];
961 rate[2] = coarseRate[2];
963 if(ndm < 3) { rate[2] = 0;}
964 if(ndm < 2) { rate[1] = 0;}
967 firstCoarseNodeIndex = 0;
968 Array<GO> firstCoarseNodeIndices(3);
969 if((currentNodeIndices[2] == gFineNodesPerDir[2] -1) && (endRate[2] == coarseRate[2])) {
971 firstCoarseNodeIndices[2] = ((currentNodeIndices[2] / coarseRate[2]) - 1) * coarseRate[2];
973 firstCoarseNodeIndices[2] = (currentNodeIndices[2] / coarseRate[2]) * coarseRate[2];
975 if((currentNodeIndices[1] == gFineNodesPerDir[1] -1) && (endRate[1] == coarseRate[1])) {
976 firstCoarseNodeIndices[1] = ((currentNodeIndices[1] / coarseRate[1]) - 1) * coarseRate[1];
978 firstCoarseNodeIndices[1] = (currentNodeIndices[1] / coarseRate[1]) * coarseRate[1];
980 if((currentNodeIndices[0] == gFineNodesPerDir[0] -1) && (endRate[0] == coarseRate[0])) {
981 firstCoarseNodeIndices[0] = ((currentNodeIndices[0] / coarseRate[0]) - 1) * coarseRate[0];
983 firstCoarseNodeIndices[0] = (currentNodeIndices[0] / coarseRate[0]) * coarseRate[0];
985 firstCoarseNodeIndex += firstCoarseNodeIndices[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0]
986 + firstCoarseNodeIndices[1]*gFineNodesPerDir[0] + firstCoarseNodeIndices[0];
988 GO firstCoarseNodeOnCoarseGridIndex;
991 tmpInds[2] = firstCoarseNodeIndex / fineNodesPerCoarseSlab;
992 tmpInds[3] = firstCoarseNodeIndex % fineNodesPerCoarseSlab;
993 tmpInds[1] = tmpInds[3] / fineNodesPerCoarsePlane;
994 tmpInds[0] = (tmpInds[3] % fineNodesPerCoarsePlane) / coarseRate[0];
995 firstCoarseNodeOnCoarseGridIndex = tmpInds[2]*coarseNodesPerCoarseLayer + tmpInds[1]*gCoarseNodesPerDir[0] + tmpInds[0];
998 LO coarseGhosts[8] = {0, 0, 0, 0, 0, 0, 0, 0};
999 if( ghostInterface[0] ) {
1000 if( ((indices[0][mapDirG2L[0]] < rate[0] - offsets[0]) && offsets[0] != 0)
1001 || (((currentNodeIndices[0] == gFineNodesPerDir[0] -1) && (indices[0][mapDirG2L[0]] < rate[0] - offsets[0] + 1)) && offsets[0] != 0)
1002 || ((currentNodeIndices[0] == gFineNodesPerDir[0] -1) && lFineNodesPerDir[mapDirG2L[0]] == 1) ) {
1003 coarseGhosts[0] = 1;
1004 coarseGhosts[2] = 1;
1005 coarseGhosts[4] = 1;
1006 coarseGhosts[6] = 1;
1009 if( ghostInterface[1] && (indices[0][mapDirG2L[0]] > lFineNodesPerDir[mapDirG2L[0]] - offsets[3] - 2) ) {
1010 coarseGhosts[1] = 1;
1011 coarseGhosts[3] = 1;
1012 coarseGhosts[5] = 1;
1013 coarseGhosts[7] = 1;
1015 if( ghostInterface[2] ) {
1016 if( ((indices[0][mapDirG2L[1]] < rate[1] - offsets[1]) && offsets[1] != 0)
1017 || (((currentNodeIndices[1] == gFineNodesPerDir[1] -1) && (indices[0][mapDirG2L[1]] < rate[1] - offsets[1] + 1)) && offsets[1] != 0)
1018 || ((currentNodeIndices[1] == gFineNodesPerDir[1] -1) && lFineNodesPerDir[mapDirG2L[1]] == 1) ) {
1019 coarseGhosts[0] = 1;
1020 coarseGhosts[1] = 1;
1021 coarseGhosts[4] = 1;
1022 coarseGhosts[5] = 1;
1025 if( ghostInterface[3] && (indices[0][mapDirG2L[1]] > lFineNodesPerDir[mapDirG2L[1]] - offsets[4] - 2) ) {
1026 coarseGhosts[2] = 1;
1027 coarseGhosts[3] = 1;
1028 coarseGhosts[6] = 1;
1029 coarseGhosts[7] = 1;
1031 if( ghostInterface[4] ) {
1032 if( ((indices[0][mapDirG2L[2]] < rate[2] - offsets[2]) && offsets[2] != 0)
1033 || (((currentNodeIndices[2] == gFineNodesPerDir[2] -1) && (indices[0][mapDirG2L[2]] < rate[2] - offsets[2] + 1)) && offsets[2] != 0)
1034 || ((currentNodeIndices[2] == gFineNodesPerDir[2] -1) && lFineNodesPerDir[mapDirG2L[2]] == 1) ) {
1035 coarseGhosts[0] = 1;
1036 coarseGhosts[1] = 1;
1037 coarseGhosts[2] = 1;
1038 coarseGhosts[3] = 1;
1041 if( ghostInterface[5] && (indices[0][mapDirG2L[2]] > lFineNodesPerDir[mapDirG2L[2]] - offsets[5] - 2) ) {
1042 coarseGhosts[4] = 1;
1043 coarseGhosts[5] = 1;
1044 coarseGhosts[6] = 1;
1045 coarseGhosts[7] = 1;
1048 GO firstGhostNodeIndices[3], firstGhostNodeIndex;
1049 if(currentNodeIndices[0] == gFineNodesPerDir[0] - 1) {
1050 firstGhostNodeIndices[0] = (currentNodeIndices[0]-rate[0]) - (currentNodeIndices[0]-rate[0])%coarseRate[0];
1052 firstGhostNodeIndices[0] = currentNodeIndices[0] - currentNodeIndices[0]%coarseRate[0];
1054 if(currentNodeIndices[1] == gFineNodesPerDir[1] - 1) {
1055 firstGhostNodeIndices[1] = (currentNodeIndices[1]-rate[1]) - (currentNodeIndices[1]-rate[1])%coarseRate[1];
1057 firstGhostNodeIndices[1] = currentNodeIndices[1] - currentNodeIndices[1]%coarseRate[1];
1059 if(currentNodeIndices[2] == gFineNodesPerDir[2] - 1) {
1060 firstGhostNodeIndices[2] = (currentNodeIndices[2]-rate[2]) - (currentNodeIndices[2]-rate[2])%coarseRate[2];
1062 firstGhostNodeIndices[2] = currentNodeIndices[2] - currentNodeIndices[2]%coarseRate[2];
1064 firstGhostNodeIndex = firstGhostNodeIndices[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0] + firstGhostNodeIndices[1]*gFineNodesPerDir[0] + firstGhostNodeIndices[0];
1066 Array<GO> gCoarseNodesOnCoarseGridIndices(8);
1067 GO ghostNodeIndex, ghostNodeOnCoarseGridIndex;
1068 GO coarseNodeIndex, coarseNodeOnCoarseGridIndex;
1070 double connec[9][3];
1072 Array<LO> connecPIDs(8);
1073 Array<GO> connecLGIDs(8);
1075 for(LO dim = 0; dim < 3; ++dim) {connec[0][dim] = lFineCoords[dim][i];}
1078 for(LO ind2 = 0; ind2 < 2; ++ind2) {
1079 for(LO ind1 = 0; ind1 < 2; ++ind1) {
1080 for(LO ind0 = 0; ind0 < 2; ++ind0) {
1081 ind = 4*ind2 + 2*ind1 + ind0;
1083 if(coarseGhosts[ind] == 1) {
1085 ghostNodeIndex = firstGhostNodeIndex + Teuchos::as<GO>(ind2*rate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0]
1086 + ind1*rate[1]*gFineNodesPerDir[0]
1088 ghostNodeOnCoarseGridIndex = firstCoarseNodeOnCoarseGridIndex + Teuchos::as<GO>(ind2*gCoarseNodesPerDir[1]*gCoarseNodesPerDir[0]
1089 + ind1*gCoarseNodesPerDir[0]
1091 currentGhostLID = ghostMap->getLocalElement(ghostNodeIndex);
1092 connecPIDs[ind] = ghostsPIDs[currentGhostLID];
1093 connecLGIDs[ind] = ghostNodeIndex;
1094 for(LO dim = 0; dim < 3; ++dim) {connec[ind + 1][dim] = lGhostCoords[dim][currentGhostLID];}
1095 gCoarseNodesOnCoarseGridIndices[4*ind2 + 2*ind1 + ind0] = ghostNodeOnCoarseGridIndex;
1098 coarseNodeIndex = firstCoarseNodeIndex + Teuchos::as<GO>(ind2*rate[2]*gFineNodesPerDir[1]*gFineNodesPerDir[0]
1099 + ind1*rate[1]*gFineNodesPerDir[0]
1101 coarseNodeOnCoarseGridIndex = firstCoarseNodeOnCoarseGridIndex + Teuchos::as<GO>(ind2*gCoarseNodesPerDir[1]*gCoarseNodesPerDir[0]
1102 + ind1*gCoarseNodesPerDir[0]
1104 for(LO dim = 0; dim < 3; ++dim) {connec[ind + 1][dim] = lFineCoords[dim][fineCoordsMap->getLocalElement(coarseNodeIndex)];}
1105 gCoarseNodesOnCoarseGridIndices[4*ind2 + 2*ind1 + ind0] = coarseNodeOnCoarseGridIndex;
1106 connecPIDs[ind] = -1;
1107 connecLGIDs[ind] = coarseCoordsMap->getLocalElement(coarseNodeOnCoarseGridIndex);
1114 SC stencil[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
1115 ComputeStencil(ndm, currentNodeIndices, firstCoarseNodeIndices, rate, connec, interpolationOrder, stencil);
1120 LO nzIndStencil[8] = {0,0,0,0,0,0,0,0};
1121 if( ((currentNodeIndices[0] % coarseRate[0] == 0) || currentNodeIndices[0] == gFineNodesPerDir[0] - 1)
1122 && ((currentNodeIndices[1] % coarseRate[1] == 0) || currentNodeIndices[1] == gFineNodesPerDir[1] - 1)
1123 && ((currentNodeIndices[2] % coarseRate[2] == 0) || currentNodeIndices[2] == gFineNodesPerDir[2] - 1) ) {
1125 xCoarseNodes[currentCoarseNode] = lFineCoords[0][i];
1127 xCoarseNodes[currentCoarseNode] = lFineCoords[0][i];
1128 yCoarseNodes[currentCoarseNode] = lFineCoords[1][i];
1130 xCoarseNodes[currentCoarseNode] = lFineCoords[0][i];
1131 yCoarseNodes[currentCoarseNode] = lFineCoords[1][i];
1132 zCoarseNodes[currentCoarseNode] = lFineCoords[2][i];
1134 ++currentCoarseNode;
1136 if(currentNodeIndices[0] == gFineNodesPerDir[0] - 1) {
1137 nzIndStencil[0] += 1;
1139 if((currentNodeIndices[1] == gFineNodesPerDir[1] - 1) && (ndm > 1)) {
1140 nzIndStencil[0] += 2;
1142 if((currentNodeIndices[2] == gFineNodesPerDir[2] - 1) && (ndm > 2)) {
1143 nzIndStencil[0] += 4;
1146 for(LO k = 0; k < 8; ++k) {
1147 nzIndStencil[k] = nzIndStencil[0];
1151 for(LO k = 0; k < 8; ++k) {
1152 nzIndStencil[k] = k;
1162 Array<LO> permutation(8);
1163 for(LO k = 0; k < 8; ++k) {permutation[k] = k;}
1166 sh_sort2(connecPIDs.begin(),connecPIDs.end(), permutation.begin(), permutation.end());
1168 for(LO j = 0; j < dofsPerNode; ++j) {
1169 ia[i*dofsPerNode + j + 1] = ia[i*dofsPerNode + j] + nStencil;
1170 for(LO k = 0; k < nStencil; ++k) {
1171 ja [ia[i*dofsPerNode + j] + k] = colMapP->getLocalElement(gCoarseNodesOnCoarseGridIndices[nzIndStencil[permutation[k]]]*dofsPerNode + j);
1172 val[ia[i*dofsPerNode + j] + k] = stencil[nzIndStencil[permutation[k]]];
1175 tStencil += nStencil;
1179 if (rowMapP->lib() == Xpetra::UseTpetra) {
1183 jaP .resize(tStencil);
1184 valP.resize(tStencil);
1188 PCrs->setAllValues(iaP, jaP, valP);
1189 PCrs->expertStaticFillComplete(domainMapP,rowMapP);
1193 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1195 const LO numDimensions,
const Array<GO> currentNodeIndices,
1196 const Array<GO> coarseNodeIndices,
const LO rate[3],
1197 const double coord[9][3],
const int interpolationOrder,
1198 SC stencil[8])
const {
1200 TEUCHOS_TEST_FOR_EXCEPTION((interpolationOrder > 1) || (interpolationOrder < 0),
1202 "The interpolation order can be set to 0 or 1 only.");
1204 if(interpolationOrder == 0) {
1205 ComputeConstantInterpolationStencil(numDimensions, currentNodeIndices, coarseNodeIndices, rate, stencil);
1206 }
else if(interpolationOrder == 1) {
1207 ComputeLinearInterpolationStencil(numDimensions, coord, stencil);
1212 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1214 const LO numDimensions,
const Array<GO> currentNodeIndices,
1215 const Array<GO> coarseNodeIndices,
const LO rate[3], SC stencil[8])
const {
1218 if(numDimensions > 2) {
1219 if((currentNodeIndices[2] - coarseNodeIndices[2]) > (rate[2] / 2)) {
1223 if(numDimensions > 1) {
1224 if((currentNodeIndices[1] - coarseNodeIndices[1]) > (rate[1] / 2)) {
1228 if((currentNodeIndices[0] - coarseNodeIndices[0]) > (rate[0] / 2)) {
1231 stencil[coarseNode] = 1.0;
1235 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1237 const LO numDimensions,
const double coord[9][3], SC stencil[8])
const {
1254 Teuchos::SerialDenseMatrix<LO,double> Jacobian(numDimensions, numDimensions);
1255 Teuchos::SerialDenseVector<LO,double> residual(numDimensions);
1256 Teuchos::SerialDenseVector<LO,double> solutionDirection(numDimensions);
1257 Teuchos::SerialDenseVector<LO,double> paramCoords(numDimensions);
1258 Teuchos::SerialDenseSolver<LO,double> problem;
1259 LO numTerms = std::pow(2,numDimensions), iter = 0, max_iter = 5;
1260 double functions[4][8], norm_ref = 1, norm2 = 1, tol = 1e-5;
1261 paramCoords.size(numDimensions);
1263 while( (iter < max_iter) && (norm2 > tol*norm_ref) ) {
1266 solutionDirection.size(numDimensions);
1267 residual.size(numDimensions);
1271 GetInterpolationFunctions(numDimensions, paramCoords, functions);
1272 for(LO i = 0; i < numDimensions; ++i) {
1273 residual(i) = coord[0][i];
1274 for(LO k = 0; k < numTerms; ++k) {
1275 residual(i) -= functions[0][k]*coord[k+1][i];
1278 norm_ref += residual(i)*residual(i);
1279 if(i == numDimensions - 1) {
1280 norm_ref = std::sqrt(norm_ref);
1284 for(LO j = 0; j < numDimensions; ++j) {
1285 for(LO k = 0; k < numTerms; ++k) {
1286 Jacobian(i,j) += functions[j+1][k]*coord[k+1][i];
1292 problem.setMatrix(Teuchos::rcp(&Jacobian,
false));
1293 problem.setVectors(Teuchos::rcp(&solutionDirection,
false), Teuchos::rcp(&residual,
false));
1294 problem.factorWithEquilibration(
true);
1296 problem.unequilibrateLHS();
1298 for(LO i = 0; i < numDimensions; ++i) {
1299 paramCoords(i) = paramCoords(i) + solutionDirection(i);
1303 GetInterpolationFunctions(numDimensions, paramCoords, functions);
1304 for(LO i = 0; i < numDimensions; ++i) {
1305 double tmp = coord[0][i];
1306 for(LO k = 0; k < numTerms; ++k) {
1307 tmp -= functions[0][k]*coord[k+1][i];
1312 norm2 = std::sqrt(norm2);
1316 for(LO i = 0; i < 8; ++i) {
1317 stencil[i] = functions[0][i];
1322 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1324 double xi = 0.0, eta = 0.0, zeta = 0.0, denominator = 0.0;
1325 if(numDimensions == 1) {
1328 }
else if(numDimensions == 2) {
1330 eta = parameters[1];
1332 }
else if(numDimensions == 3) {
1334 eta = parameters[1];
1335 zeta = parameters[2];
1339 functions[0][0] = (1.0 - xi)*(1.0 - eta)*(1.0 - zeta) / denominator;
1340 functions[0][1] = (1.0 + xi)*(1.0 - eta)*(1.0 - zeta) / denominator;
1341 functions[0][2] = (1.0 - xi)*(1.0 + eta)*(1.0 - zeta) / denominator;
1342 functions[0][3] = (1.0 + xi)*(1.0 + eta)*(1.0 - zeta) / denominator;
1343 functions[0][4] = (1.0 - xi)*(1.0 - eta)*(1.0 + zeta) / denominator;
1344 functions[0][5] = (1.0 + xi)*(1.0 - eta)*(1.0 + zeta) / denominator;
1345 functions[0][6] = (1.0 - xi)*(1.0 + eta)*(1.0 + zeta) / denominator;
1346 functions[0][7] = (1.0 + xi)*(1.0 + eta)*(1.0 + zeta) / denominator;
1348 functions[1][0] = -(1.0 - eta)*(1.0 - zeta) / denominator;
1349 functions[1][1] = (1.0 - eta)*(1.0 - zeta) / denominator;
1350 functions[1][2] = -(1.0 + eta)*(1.0 - zeta) / denominator;
1351 functions[1][3] = (1.0 + eta)*(1.0 - zeta) / denominator;
1352 functions[1][4] = -(1.0 - eta)*(1.0 + zeta) / denominator;
1353 functions[1][5] = (1.0 - eta)*(1.0 + zeta) / denominator;
1354 functions[1][6] = -(1.0 + eta)*(1.0 + zeta) / denominator;
1355 functions[1][7] = (1.0 + eta)*(1.0 + zeta) / denominator;
1357 functions[2][0] = -(1.0 - xi)*(1.0 - zeta) / denominator;
1358 functions[2][1] = -(1.0 + xi)*(1.0 - zeta) / denominator;
1359 functions[2][2] = (1.0 - xi)*(1.0 - zeta) / denominator;
1360 functions[2][3] = (1.0 + xi)*(1.0 - zeta) / denominator;
1361 functions[2][4] = -(1.0 - xi)*(1.0 + zeta) / denominator;
1362 functions[2][5] = -(1.0 + xi)*(1.0 + zeta) / denominator;
1363 functions[2][6] = (1.0 - xi)*(1.0 + zeta) / denominator;
1364 functions[2][7] = (1.0 + xi)*(1.0 + zeta) / denominator;
1366 functions[3][0] = -(1.0 - xi)*(1.0 - eta) / denominator;
1367 functions[3][1] = -(1.0 + xi)*(1.0 - eta) / denominator;
1368 functions[3][2] = -(1.0 - xi)*(1.0 + eta) / denominator;
1369 functions[3][3] = -(1.0 + xi)*(1.0 + eta) / denominator;
1370 functions[3][4] = (1.0 - xi)*(1.0 - eta) / denominator;
1371 functions[3][5] = (1.0 + xi)*(1.0 - eta) / denominator;
1372 functions[3][6] = (1.0 - xi)*(1.0 + eta) / denominator;
1373 functions[3][7] = (1.0 + xi)*(1.0 + eta) / denominator;
1377 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1379 const typename Teuchos::Array<LocalOrdinal>::iterator& first1,
1380 const typename Teuchos::Array<LocalOrdinal>::iterator& last1,
1381 const typename Teuchos::Array<LocalOrdinal>::iterator& first2,
1382 const typename Teuchos::Array<LocalOrdinal>::iterator& last2)
const 1384 typedef typename std::iterator_traits<typename Teuchos::Array<LocalOrdinal>::iterator>::difference_type DT;
1385 DT n = last1 - first1;
1387 DT z = Teuchos::OrdinalTraits<DT>::zero();
1391 for (DT j = 0; j < max; j++)
1393 for (DT k = j; k >= 0; k-=m)
1395 if (first1[first2[k+m]] >= first1[first2[k]])
1397 std::swap(first2[k+m], first2[k]);
1404 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1406 const typename Teuchos::Array<LocalOrdinal>::iterator& first1,
1407 const typename Teuchos::Array<LocalOrdinal>::iterator& last1,
1408 const typename Teuchos::Array<LocalOrdinal>::iterator& first2,
1409 const typename Teuchos::Array<LocalOrdinal>::iterator& last2)
const 1411 typedef typename std::iterator_traits<typename Teuchos::Array<LocalOrdinal>::iterator>::difference_type DT;
1412 DT n = last1 - first1;
1414 DT z = Teuchos::OrdinalTraits<DT>::zero();
1418 for (DT j = 0; j < max; j++)
1420 for (DT k = j; k >= 0; k-=m)
1422 if (first1[k+m] >= first1[k])
1424 std::swap(first1[k+m], first1[k]);
1425 std::swap(first2[k+m], first2[k]);
1434 #define MUELU_GENERALGEOMETRICPFACTORY_SHORT 1435 #endif // MUELU_GENERALGEOMETRICPFACTORY_DEF_HPP void sh_sort2(const typename Teuchos::Array< LocalOrdinal >::iterator &first1, const typename Teuchos::Array< LocalOrdinal >::iterator &last1, const typename Teuchos::Array< LocalOrdinal >::iterator &first2, const typename Teuchos::Array< LocalOrdinal >::iterator &last2) const
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
Timer to be used in factories. Similar to Monitor but with additional timers.
void ComputeLinearInterpolationStencil(const LO numDimension, const double coord[9][3], SC stencil[8]) const
Namespace for MueLu classes and methods.
void sh_sort_permute(const typename Teuchos::Array< LocalOrdinal >::iterator &first1, const typename Teuchos::Array< LocalOrdinal >::iterator &last1, const typename Teuchos::Array< LocalOrdinal >::iterator &first2, const typename Teuchos::Array< LocalOrdinal >::iterator &last2) const
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
static const NoFactory * get()
int GetLevelID() const
Return level number.
void ComputeStencil(const LO numDimension, const Array< GO > currentNodeIndices, const Array< GO > coarseNodeIndices, const LO rate[3], const double coord[9][3], const int interpolationOrder, SC stencil[8]) const
void MakeGeneralGeometricP(LO const numDimension, const Array< LO > mapDirL2G, const Array< LO > mapDirG2L, const Array< LO > lFineNodesPerDir, const Array< LO > lCoarseNodesPerDir, Array< GO > gCoarseNodesPerDir, Array< GO > gFineNodesPerDir, ArrayRCP< LO > const coarseRate, LO const endRate[3], LO const offsets[6], bool const ghostInterface[6], const RCP< Xpetra::MultiVector< double, LO, GO, NO > > &fCoords, LO const nnzP, LO const dofsPerNode, RCP< const Map > &stridedDomainMapP, RCP< Matrix > &Amat, RCP< Matrix > &P, RCP< Xpetra::MultiVector< double, LO, GO, NO > > &cCoords, Array< GO > ghostsGIDs, int interpolationOrder) const
Class that holds all level-specific information.
void ComputeConstantInterpolationStencil(const LO numDimension, const Array< GO > currentNodeIndices, const Array< GO > coarseNodeIndices, const LO rate[3], SC stencil[8]) const
void GetInterpolationFunctions(const LO numDimension, const Teuchos::SerialDenseVector< LO, double > parameters, double functions[4][8]) const
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
Exception throws to report errors in the internal logical of the program.
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()