10 #ifndef MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEF_HPP
11 #define MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEF_HPP
18 #include "MueLu_Aggregates.hpp"
19 #include "Xpetra_TpetraCrsMatrix.hpp"
26 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
30 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
32 #undef SET_VALID_ENTRY
36 "Generating factory of the matrix A");
38 "Aggregates generated by StructuredAggregationFactory used to construct a piece-constant prolongator.");
40 "Graph generated by StructuredAggregationFactory used to construct a piece-linear prolongator.");
42 "Fine level coordinates used to construct piece-wise linear prolongator and coarse level coordinates.");
44 "map of the coarse coordinates' GIDs as indexed on the fine mesh.");
46 "map of the coarse coordinates' GIDs as indexed on the coarse mesh.");
48 "Fine level nullspace used to construct the coarse level nullspace.");
50 "Number of spacial dimensions in the problem.");
52 "Number of nodes per spatial dimension on the coarse grid.");
54 "Interpolation order for constructing the prolongator.");
55 validParamList->
set<
bool>(
"keep coarse coords",
false,
"Flag to keep coordinates for special coarse grid solve");
56 validParamList->
set<
bool>(
"interp: remove small entries",
true,
"Remove small interpolation coeficient from prolongator to reduce fill-in on coarse level");
58 return validParamList;
61 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
66 Input(fineLevel,
"A");
67 Input(fineLevel,
"Nullspace");
68 Input(fineLevel,
"numDimensions");
69 Input(fineLevel,
"prolongatorGraph");
70 Input(fineLevel,
"lCoarseNodesPerDim");
71 Input(fineLevel,
"structuredInterpolationOrder");
73 if (pL.
get<
bool>(
"interp: build coarse coordinates") ||
74 Get<int>(fineLevel,
"structuredInterpolationOrder") == 1) {
75 Input(fineLevel,
"Coordinates");
76 Input(fineLevel,
"coarseCoordinatesFineMap");
77 Input(fineLevel,
"coarseCoordinatesMap");
81 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
84 return BuildP(fineLevel, coarseLevel);
87 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
94 if (
const char* dbg = std::getenv(
"MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
95 out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
101 *out <<
"Starting GeometricInterpolationPFactory::BuildP." << std::endl;
106 const bool buildCoarseCoordinates = pL.
get<
bool>(
"interp: build coarse coordinates");
107 const int interpolationOrder = Get<int>(fineLevel,
"structuredInterpolationOrder");
108 const int numDimensions = Get<int>(fineLevel,
"numDimensions");
118 if (buildCoarseCoordinates || (interpolationOrder == 1)) {
120 RCP<const Map> coarseCoordsFineMap = Get<RCP<const Map> >(fineLevel,
"coarseCoordinatesFineMap");
121 RCP<const Map> coarseCoordsMap = Get<RCP<const Map> >(fineLevel,
"coarseCoordinatesMap");
123 fineCoordinates = Get<RCP<realvaluedmultivector_type> >(fineLevel,
"Coordinates");
125 fineCoordinates->getNumVectors());
126 RCP<const Import> coordsImporter = ImportFactory::Build(fineCoordinates->getMap(),
127 coarseCoordsFineMap);
128 coarseCoordinates->doImport(*fineCoordinates, *coordsImporter,
Xpetra::INSERT);
129 coarseCoordinates->replaceMap(coarseCoordsMap);
131 Set(coarseLevel,
"Coordinates", coarseCoordinates);
133 if (pL.
get<
bool>(
"keep coarse coords")) {
138 *out <<
"Fine and coarse coordinates have been loaded from the fine level and set on the coarse level." << std::endl;
140 if (interpolationOrder == 0) {
143 BuildConstantP(P, prolongatorGraph, A);
144 }
else if (interpolationOrder == 1) {
149 const size_t dofsPerNode =
static_cast<size_t>(A->GetFixedBlockSize());
150 const size_t numColIndices = prolongatorColMap->getLocalNumElements();
153 "Something went wrong, the number of columns in the prolongator is not a multiple of dofsPerNode!");
154 const size_t numGhostCoords = numColIndices / dofsPerNode;
155 const GO indexBase = prolongatorColMap->getIndexBase();
156 const GO coordIndexBase = fineCoordinates->getMap()->getIndexBase();
159 Array<GO> ghostCoordIndices(numGhostCoords);
160 for (
size_t ghostCoordIdx = 0; ghostCoordIdx < numGhostCoords; ++ghostCoordIdx) {
161 ghostCoordIndices[ghostCoordIdx] = (prolongatorColIndices[ghostCoordIdx * dofsPerNode] - indexBase) / dofsPerNode + coordIndexBase;
163 RCP<Map> ghostCoordMap = MapFactory::Build(fineCoordinates->getMap()->lib(),
164 prolongatorColMap->getGlobalNumElements() / dofsPerNode,
167 fineCoordinates->getMap()->getComm());
170 fineCoordinates->getNumVectors());
171 RCP<const Import> ghostImporter = ImportFactory::Build(coarseCoordinates->getMap(),
173 ghostCoordinates->doImport(*coarseCoordinates, *ghostImporter,
Xpetra::INSERT);
175 BuildLinearP(coarseLevel, A, prolongatorGraph, fineCoordinates,
176 ghostCoordinates, numDimensions, removeSmallEntries, P);
179 *out <<
"The prolongator matrix has been built." << std::endl;
184 RCP<MultiVector> fineNullspace = Get<RCP<MultiVector> >(fineLevel,
"Nullspace");
185 RCP<MultiVector> coarseNullspace = MultiVectorFactory::Build(P->getDomainMap(),
186 fineNullspace->getNumVectors());
189 if (helpers::isTpetraBlockCrs(A)) {
199 Set(coarseLevel,
"Nullspace", coarseNullspace);
202 *out <<
"The coarse nullspace is constructed and set on the coarse level." << std::endl;
204 Set(coarseLevel,
"P", P);
206 *out <<
"GeometricInterpolationPFactory::BuildP has completed." << std::endl;
210 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
215 if (
const char* dbg = std::getenv(
"MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
216 out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
222 *out <<
"BuildConstantP" << std::endl;
224 std::vector<size_t> strideInfo(1);
225 strideInfo[0] = A->GetFixedBlockSize();
227 StridedMapFactory::Build(prolongatorGraph->getDomainMap(), strideInfo);
229 *out <<
"Call prolongator constructor" << std::endl;
232 if (helpers::isTpetraBlockCrs(A)) {
235 LO NSDim = A->GetStorageBlockSize();
241 for (
LO i = 0, ct = 0; i < block_dofs.
size(); i++) {
242 for (
LO j = 0; j < NSDim; j++) {
243 point_dofs[ct] = block_dofs[i] * NSDim + j;
249 BlockMap->getGlobalNumElements() * NSDim,
251 BlockMap->getIndexBase(),
252 BlockMap->getComm());
253 strideInfo[0] = A->GetFixedBlockSize();
258 if (P_tpetra.is_null())
throw std::runtime_error(
"BuildConstantP Matrix factory did not return a Tpetra::BlockCrsMatrix");
265 for (
LO i = 0; i < NSDim; i++)
266 block[i * NSDim + i] = one;
267 for (
LO i = 0; i < (int)prolongatorGraph->getLocalNumRows(); i++) {
268 prolongatorGraph->getLocalRowView(i, indices);
269 for (
LO j = 0; j < (
LO)indices.
size(); j++) {
270 temp[0] = indices[j];
271 P_tpetra->replaceLocalValues(i, temp(), block());
276 if (A->IsView(
"stridedMaps") ==
true) {
277 P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedPointMap);
279 P->CreateView(
"stridedMaps", P->getRangeMap(), PointMap);
284 P =
rcp(
new CrsMatrixWrap(prolongatorGraph, dummyList));
285 RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
286 PCrs->setAllToScalar(1.0);
287 PCrs->fillComplete();
290 if (A->IsView(
"stridedMaps") ==
true)
291 P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedDomainMap);
293 P->CreateView(
"stridedMaps", P->getRangeMap(), stridedDomainMap);
298 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
308 if (
const char* dbg = std::getenv(
"MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
309 out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
316 const int numInterpolationPoints = 1 << numDimensions;
317 const int dofsPerNode = A->GetFixedBlockSize() / A->GetStorageBlockSize();
321 P =
rcp(
new CrsMatrixWrap(prolongatorGraph, dummyList));
322 RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
326 *out <<
"Entering BuildLinearP" << std::endl;
330 const LO numFineNodes = fineCoordinates->getLocalLength();
331 const LO numGhostNodes = ghostCoordinates->getLocalLength();
334 const real_type realZero = Teuchos::as<real_type>(0.0);
337 for (
int dim = 0; dim < 3; ++dim) {
338 if (dim < numDimensions) {
339 fineCoords[dim] = fineCoordinates->getData(dim);
340 ghostCoords[dim] = ghostCoordinates->getData(dim);
342 fineCoords[dim] = fineZero;
343 ghostCoords[dim] = ghostZero;
347 *out <<
"Coordinates extracted from the multivectors!" << std::endl;
350 LO interpolationNodeIdx = 0, rowIdx = 0;
355 for (
LO nodeIdx = 0; nodeIdx < numFineNodes; ++nodeIdx) {
356 if (PCrs->getNumEntriesInLocalRow(nodeIdx * dofsPerNode) == 1) {
359 for (
LO dof = 0; dof < dofsPerNode; ++dof) {
360 rowIdx = nodeIdx * dofsPerNode + dof;
361 prolongatorGraph->getLocalRowView(rowIdx, colIndices);
362 PCrs->replaceLocalValues(rowIdx, colIndices, values());
368 for (
int dim = 0; dim < 3; ++dim) {
369 coords[0][dim] = fineCoords[dim][nodeIdx];
371 prolongatorGraph->getLocalRowView(nodeIdx * dofsPerNode, colIndices);
372 for (
int interpolationIdx = 0; interpolationIdx < numInterpolationPoints; ++interpolationIdx) {
373 coords[interpolationIdx + 1].
resize(3);
374 interpolationNodeIdx = colIndices[interpolationIdx] / dofsPerNode;
375 for (
int dim = 0; dim < 3; ++dim) {
376 coords[interpolationIdx + 1][dim] = ghostCoords[dim][interpolationNodeIdx];
380 ComputeLinearInterpolationStencil(numDimensions, numInterpolationPoints, coords, stencil);
382 values.
resize(numInterpolationPoints);
383 for (
LO valueIdx = 0; valueIdx < numInterpolationPoints; ++valueIdx) {
384 values[valueIdx] = Teuchos::as<SC>(stencil[valueIdx]);
388 for (
LO dof = 0; dof < dofsPerNode; ++dof) {
389 rowIdx = nodeIdx * dofsPerNode + dof;
390 prolongatorGraph->getLocalRowView(rowIdx, colIndices);
391 PCrs->replaceLocalValues(rowIdx, colIndices, values());
397 *out <<
"The calculation of the interpolation stencils has completed." << std::endl;
399 PCrs->fillComplete();
402 *out <<
"All values in P have been set and fillComplete has been performed." << std::endl;
410 if (removeSmallEntries) {
411 *out <<
"Entering remove small entries" << std::endl;
417 PCrs->getAllValues(rowptrOrig, colindOrig, valuesOrig);
419 const size_t numRows =
static_cast<size_t>(rowptrOrig.
size() - 1);
423 size_t countRemovedEntries = 0;
424 for (
size_t rowIdx = 0; rowIdx < numRows; ++rowIdx) {
425 for (
size_t entryIdx = rowptrOrig[rowIdx]; entryIdx < rowptrOrig[rowIdx + 1]; ++entryIdx) {
427 ++countRemovedEntries;
430 rowPtr[rowIdx + 1] = rowptrOrig[rowIdx + 1] - countRemovedEntries;
431 nnzOnRows[rowIdx] = rowPtr[rowIdx + 1] - rowPtr[rowIdx];
433 GetOStream(
Statistics1) <<
"interp: number of small entries removed= " << countRemovedEntries <<
" / " << rowptrOrig[numRows] << std::endl;
435 size_t countKeptEntries = 0;
438 for (
size_t entryIdx = 0; entryIdx < rowptrOrig[numRows]; ++entryIdx) {
440 colInd[countKeptEntries] = colindOrig[entryIdx];
441 values[countKeptEntries] = valuesOrig[entryIdx];
446 P =
rcp(
new CrsMatrixWrap(prolongatorGraph->getRowMap(),
447 prolongatorGraph->getColMap(),
449 RCP<CrsMatrix> PCrsSqueezed = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
450 PCrsSqueezed->resumeFill();
451 PCrsSqueezed->setAllValues(rowPtr, colInd, values);
452 PCrsSqueezed->expertStaticFillComplete(prolongatorGraph->getDomainMap(),
453 prolongatorGraph->getRangeMap());
456 std::vector<size_t> strideInfo(1);
457 strideInfo[0] = dofsPerNode;
459 StridedMapFactory::Build(prolongatorGraph->getDomainMap(), strideInfo);
461 *out <<
"The strided maps of P have been computed" << std::endl;
464 if (A->IsView(
"stridedMaps") ==
true) {
465 P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedDomainMap);
467 P->CreateView(
"stridedMaps", P->getRangeMap(), stridedDomainMap);
472 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
497 int iter = 0, max_iter = 5;
498 real_type functions[4][8], norm_ref = 1.0, norm2 = 1.0, tol = 1.0e-5;
499 paramCoords.
size(numDimensions);
501 while ((iter < max_iter) && (norm2 > tol * norm_ref)) {
504 solutionDirection.
size(numDimensions);
505 residual.
size(numDimensions);
509 GetInterpolationFunctions(numDimensions, paramCoords, functions);
510 for (
LO i = 0; i < numDimensions; ++i) {
511 residual(i) = coord[0][i];
512 for (
LO k = 0; k < numInterpolationPoints; ++k) {
513 residual(i) -= functions[0][k] * coord[k + 1][i];
516 norm_ref += residual(i) * residual(i);
517 if (i == numDimensions - 1) {
518 norm_ref = std::sqrt(norm_ref);
522 for (
LO j = 0; j < numDimensions; ++j) {
523 for (
LO k = 0; k < numInterpolationPoints; ++k) {
524 Jacobian(i, j) += functions[j + 1][k] * coord[k + 1][i];
537 for (
LO i = 0; i < numDimensions; ++i) {
538 paramCoords(i) = paramCoords(i) + solutionDirection(i);
542 GetInterpolationFunctions(numDimensions, paramCoords, functions);
543 for (
LO i = 0; i < numDimensions; ++i) {
545 for (
LO k = 0; k < numInterpolationPoints; ++k) {
546 tmp -= functions[0][k] * coord[k + 1][i];
551 norm2 = std::sqrt(norm2);
555 for (
LO i = 0; i < numInterpolationPoints; ++i) {
556 stencil[i] = functions[0][i];
561 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
566 real_type xi = 0.0, eta = 0.0, zeta = 0.0, denominator = 0.0;
567 if (numDimensions == 1) {
568 xi = parametricCoordinates[0];
570 }
else if (numDimensions == 2) {
571 xi = parametricCoordinates[0];
572 eta = parametricCoordinates[1];
574 }
else if (numDimensions == 3) {
575 xi = parametricCoordinates[0];
576 eta = parametricCoordinates[1];
577 zeta = parametricCoordinates[2];
581 functions[0][0] = (1.0 - xi) * (1.0 - eta) * (1.0 - zeta) / denominator;
582 functions[0][1] = (1.0 + xi) * (1.0 - eta) * (1.0 - zeta) / denominator;
583 functions[0][2] = (1.0 - xi) * (1.0 + eta) * (1.0 - zeta) / denominator;
584 functions[0][3] = (1.0 + xi) * (1.0 + eta) * (1.0 - zeta) / denominator;
585 functions[0][4] = (1.0 - xi) * (1.0 - eta) * (1.0 + zeta) / denominator;
586 functions[0][5] = (1.0 + xi) * (1.0 - eta) * (1.0 + zeta) / denominator;
587 functions[0][6] = (1.0 - xi) * (1.0 + eta) * (1.0 + zeta) / denominator;
588 functions[0][7] = (1.0 + xi) * (1.0 + eta) * (1.0 + zeta) / denominator;
590 functions[1][0] = -(1.0 - eta) * (1.0 - zeta) / denominator;
591 functions[1][1] = (1.0 - eta) * (1.0 - zeta) / denominator;
592 functions[1][2] = -(1.0 + eta) * (1.0 - zeta) / denominator;
593 functions[1][3] = (1.0 + eta) * (1.0 - zeta) / denominator;
594 functions[1][4] = -(1.0 - eta) * (1.0 + zeta) / denominator;
595 functions[1][5] = (1.0 - eta) * (1.0 + zeta) / denominator;
596 functions[1][6] = -(1.0 + eta) * (1.0 + zeta) / denominator;
597 functions[1][7] = (1.0 + eta) * (1.0 + zeta) / denominator;
599 functions[2][0] = -(1.0 - xi) * (1.0 - zeta) / denominator;
600 functions[2][1] = -(1.0 + xi) * (1.0 - zeta) / denominator;
601 functions[2][2] = (1.0 - xi) * (1.0 - zeta) / denominator;
602 functions[2][3] = (1.0 + xi) * (1.0 - zeta) / denominator;
603 functions[2][4] = -(1.0 - xi) * (1.0 + zeta) / denominator;
604 functions[2][5] = -(1.0 + xi) * (1.0 + zeta) / denominator;
605 functions[2][6] = (1.0 - xi) * (1.0 + zeta) / denominator;
606 functions[2][7] = (1.0 + xi) * (1.0 + zeta) / denominator;
608 functions[3][0] = -(1.0 - xi) * (1.0 - eta) / denominator;
609 functions[3][1] = -(1.0 + xi) * (1.0 - eta) / denominator;
610 functions[3][2] = -(1.0 - xi) * (1.0 + eta) / denominator;
611 functions[3][3] = -(1.0 + xi) * (1.0 + eta) / denominator;
612 functions[3][4] = (1.0 - xi) * (1.0 - eta) / denominator;
613 functions[3][5] = (1.0 + xi) * (1.0 - eta) / denominator;
614 functions[3][6] = (1.0 - xi) * (1.0 + eta) / denominator;
615 functions[3][7] = (1.0 + xi) * (1.0 + eta) / denominator;
621 #endif // MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEF_HPP
static Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node >> &map, size_t NumVectors, bool zeroOut=true)
Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > removeSmallEntries(Teuchos::RCP< Xpetra::CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &A, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType threshold, const bool keepDiagonal)
basic_FancyOStream & setShowProcRank(const bool showProcRank)
T & get(const std::string &name, T def_value)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void BuildLinearP(Level &coarseLevel, RCP< Matrix > &A, RCP< const CrsGraph > &prolongatorGraph, RCP< realvaluedmultivector_type > &fineCoordinates, RCP< realvaluedmultivector_type > &ghostCoordinates, const int numDimensions, const bool keepD2, RCP< Matrix > &P) const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
static const NoFactory * get()
void GetInterpolationFunctions(const LO numDimensions, const Teuchos::SerialDenseVector< LO, real_type > parametricCoordinates, real_type functions[4][8]) const
static RCP< Time > getNewTimer(const std::string &name)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
Class that holds all level-specific information.
void ComputeLinearInterpolationStencil(const int numDimensions, const int numInterpolationPoints, const Array< Array< real_type > > coord, Array< real_type > &stencil) const
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
void factorWithEquilibration(bool flag)
#define SET_VALID_ENTRY(name)
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Transpose(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, bool optimizeTranspose=false, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
basic_FancyOStream & setShowAllFrontMatter(const bool showAllFrontMatter)
void resize(size_type new_size, const value_type &x=value_type())
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
int size(OrdinalType length_in)
int setVectors(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &X, const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &B)
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void residual(const Operator< SC, LO, GO, NO > &Aop, const MultiVector< SC, LO, GO, NO > &X_in, const MultiVector< SC, LO, GO, NO > &B_in, MultiVector< SC, LO, GO, NO > &R_in)
Exception throws to report errors in the internal logical of the program.
void BuildConstantP(RCP< Matrix > &P, RCP< const CrsGraph > &prolongatorGraph, RCP< Matrix > &A) const
typename Teuchos::ScalarTraits< SC >::coordinateType real_type
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
int setMatrix(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &A)