46 #ifndef MUELU_GEOMETRICINTERPOLATIONPFACTORY_KOKKOS_DEF_HPP
47 #define MUELU_GEOMETRICINTERPOLATIONPFACTORY_KOKKOS_DEF_HPP
54 #include "MueLu_IndexManager_kokkos.hpp"
56 #include "Xpetra_TpetraCrsMatrix.hpp"
63 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
67 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
69 #undef SET_VALID_ENTRY
73 "Generating factory of the matrix A");
75 "Graph generated by StructuredAggregationFactory used to construct a piece-linear prolongator.");
77 "Fine level coordinates used to construct piece-wise linear prolongator and coarse level coordinates.");
79 "Fine level nullspace used to construct the coarse level nullspace.");
81 "Number of spacial dimensions in the problem.");
83 "Number of nodes per spatial dimension on the coarse grid.");
85 "The index manager associated with the local mesh.");
87 "Interpolation order for constructing the prolongator.");
89 return validParamList;
92 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
97 Input(fineLevel,
"A");
98 Input(fineLevel,
"Nullspace");
99 Input(fineLevel,
"numDimensions");
100 Input(fineLevel,
"prolongatorGraph");
101 Input(fineLevel,
"lCoarseNodesPerDim");
102 Input(fineLevel,
"structuredInterpolationOrder");
104 if (pL.
get<
bool>(
"interp: build coarse coordinates") ||
105 Get<int>(fineLevel,
"structuredInterpolationOrder") == 1) {
106 Input(fineLevel,
"Coordinates");
107 Input(fineLevel,
"indexManager");
111 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
114 return BuildP(fineLevel, coarseLevel);
117 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
124 if (
const char* dbg = std::getenv(
"MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
125 out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
131 *out <<
"Starting GeometricInterpolationPFactory_kokkos::BuildP." << std::endl;
135 const bool buildCoarseCoordinates = pL.
get<
bool>(
"interp: build coarse coordinates");
136 const int interpolationOrder = Get<int>(fineLevel,
"structuredInterpolationOrder");
137 const int numDimensions = Get<int>(fineLevel,
"numDimensions");
147 if (buildCoarseCoordinates || (interpolationOrder == 1)) {
152 fineCoordinates = Get<RCP<realvaluedmultivector_type> >(fineLevel,
"Coordinates");
155 RCP<const Map> coarseCoordsMap = MapFactory::Build(fineCoordinates->getMap()->lib(),
158 fineCoordinates->getMap()->getIndexBase(),
159 fineCoordinates->getMap()->getComm());
161 Build(coarseCoordsMap, fineCoordinates->getNumVectors());
166 fineCoordinates->getDeviceLocalView(Xpetra::Access::ReadWrite),
167 coarseCoordinates->getDeviceLocalView(Xpetra::Access::OverwriteAll));
168 Kokkos::parallel_for(
"GeometricInterpolation: build coarse coordinates",
170 myCoarseCoordinatesBuilder);
172 Set(coarseLevel,
"Coordinates", coarseCoordinates);
175 *out <<
"Fine and coarse coordinates have been loaded from the fine level and set on the coarse level." << std::endl;
177 if (interpolationOrder == 0) {
180 BuildConstantP(P, prolongatorGraph, A);
181 }
else if (interpolationOrder == 1) {
185 fineCoordinates->getNumVectors());
186 RCP<const Import> ghostImporter = ImportFactory::Build(coarseCoordinates->getMap(),
187 prolongatorGraph->getColMap());
188 ghostCoordinates->doImport(*coarseCoordinates, *ghostImporter,
Xpetra::INSERT);
191 BuildLinearP(A, prolongatorGraph, fineCoordinates, ghostCoordinates, numDimensions, P);
194 *out <<
"The prolongator matrix has been built." << std::endl;
199 RCP<MultiVector> fineNullspace = Get<RCP<MultiVector> >(fineLevel,
"Nullspace");
200 RCP<MultiVector> coarseNullspace = MultiVectorFactory::Build(P->getDomainMap(),
201 fineNullspace->getNumVectors());
204 Set(coarseLevel,
"Nullspace", coarseNullspace);
207 *out <<
"The coarse nullspace is constructed and set on the coarse level." << std::endl;
209 Array<LO> lNodesPerDir = Get<Array<LO> >(fineLevel,
"lCoarseNodesPerDim");
210 Set(coarseLevel,
"numDimensions", numDimensions);
211 Set(coarseLevel,
"lNodesPerDim", lNodesPerDir);
212 Set(coarseLevel,
"P", P);
214 *out <<
"GeometricInterpolationPFactory_kokkos::BuildP has completed." << std::endl;
218 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
223 if (
const char* dbg = std::getenv(
"MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
224 out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
230 *out <<
"BuildConstantP" << std::endl;
232 std::vector<size_t> strideInfo(1);
233 strideInfo[0] = A->GetFixedBlockSize();
235 StridedMapFactory::Build(prolongatorGraph->getDomainMap(), strideInfo);
237 *out <<
"Call prolongator constructor" << std::endl;
239 if (helpers::isTpetraBlockCrs(A)) {
240 LO NSDim = A->GetStorageBlockSize();
247 for (
LO i = 0, ct = 0; i < block_dofs.
size(); i++) {
248 for (
LO j = 0; j < NSDim; j++) {
249 point_dofs[ct] = block_dofs[i] * NSDim + j;
255 BlockMap->getGlobalNumElements() * NSDim,
257 BlockMap->getIndexBase(),
258 BlockMap->getComm());
259 strideInfo[0] = A->GetFixedBlockSize();
264 if (P_tpetra.is_null())
throw std::runtime_error(
"BuildConstantP: Matrix factory did not return a Tpetra::BlockCrsMatrix");
267 const LO stride = strideInfo[0] * strideInfo[0];
268 const LO in_stride = strideInfo[0];
269 typename CrsMatrix::local_graph_type localGraph = prolongatorGraph->getLocalGraphDevice();
270 auto rowptr = localGraph.row_map;
271 auto indices = localGraph.entries;
272 auto values = P_tpetra->getTpetra_BlockCrsMatrix()->getValuesDeviceNonConst();
277 const Kokkos::TeamPolicy<execution_space> policy(prolongatorGraph->getLocalNumRows(), 1);
279 Kokkos::parallel_for(
280 "MueLu:GeoInterpFact::BuildConstantP::fill", policy,
281 KOKKOS_LAMBDA(
const typename Kokkos::TeamPolicy<execution_space>::member_type& thread) {
282 auto row = thread.league_rank();
283 for (
LO j = (
LO)rowptr[row]; j < (
LO)rowptr[row + 1]; j++) {
284 LO block_offset = j * stride;
285 for (
LO k = 0; k < in_stride; k++)
286 values[block_offset + k * (in_stride + 1)] = one;
291 if (A->IsView(
"stridedMaps") ==
true) {
292 P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedPointMap);
294 P->CreateView(
"stridedMaps", P->getRangeMap(), PointMap);
299 P =
rcp(
new CrsMatrixWrap(prolongatorGraph, dummyList));
300 RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
301 PCrs->setAllToScalar(1.0);
302 PCrs->fillComplete();
305 if (A->IsView(
"stridedMaps") ==
true) {
306 P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedDomainMap);
308 P->CreateView(
"stridedMaps", P->getRangeMap(), stridedDomainMap);
314 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
322 if (
const char* dbg = std::getenv(
"MUELU_GEOMETRICINTERPOLATIONPFACTORY_DEBUG")) {
323 out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
329 *out <<
"Entering BuildLinearP" << std::endl;
332 const LO numFineNodes = fineCoordinates->getLocalLength();
333 const LO numGhostNodes = ghostCoordinates->getLocalLength();
336 const real_type realZero = Teuchos::as<real_type>(0.0);
339 for (
int dim = 0; dim < 3; ++dim) {
340 if (dim < numDimensions) {
341 fineCoords[dim] = fineCoordinates->getData(dim);
342 ghostCoords[dim] = ghostCoordinates->getData(dim);
344 fineCoords[dim] = fineZero;
345 ghostCoords[dim] = ghostZero;
349 *out <<
"Coordinates extracted from the multivectors!" << std::endl;
352 const int numInterpolationPoints = 1 << numDimensions;
353 const int dofsPerNode = A->GetFixedBlockSize();
355 std::vector<size_t> strideInfo(1);
356 strideInfo[0] = dofsPerNode;
358 StridedMapFactory::Build(prolongatorGraph->getDomainMap(), strideInfo);
360 *out <<
"The maps of P have been computed" << std::endl;
363 P =
rcp(
new CrsMatrixWrap(prolongatorGraph, dummyList));
364 RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
367 LO interpolationNodeIdx = 0, rowIdx = 0;
372 for (
LO nodeIdx = 0; nodeIdx < numFineNodes; ++nodeIdx) {
373 if (PCrs->getNumEntriesInLocalRow(nodeIdx * dofsPerNode) == 1) {
376 for (
LO dof = 0; dof < dofsPerNode; ++dof) {
377 rowIdx = nodeIdx * dofsPerNode + dof;
378 prolongatorGraph->getLocalRowView(rowIdx, colIndices);
379 PCrs->replaceLocalValues(rowIdx, colIndices, values());
385 for (
int dim = 0; dim < 3; ++dim) {
386 coords[0][dim] = fineCoords[dim][nodeIdx];
388 prolongatorGraph->getLocalRowView(nodeIdx * dofsPerNode, colIndices);
389 for (
int interpolationIdx = 0; interpolationIdx < numInterpolationPoints; ++interpolationIdx) {
390 coords[interpolationIdx + 1].
resize(3);
391 interpolationNodeIdx = colIndices[interpolationIdx] / dofsPerNode;
392 for (
int dim = 0; dim < 3; ++dim) {
393 coords[interpolationIdx + 1][dim] = ghostCoords[dim][interpolationNodeIdx];
396 ComputeLinearInterpolationStencil(numDimensions, numInterpolationPoints, coords, stencil);
397 values.
resize(numInterpolationPoints);
398 for (
LO valueIdx = 0; valueIdx < numInterpolationPoints; ++valueIdx) {
399 values[valueIdx] = Teuchos::as<SC>(stencil[valueIdx]);
403 for (
LO dof = 0; dof < dofsPerNode; ++dof) {
404 rowIdx = nodeIdx * dofsPerNode + dof;
405 prolongatorGraph->getLocalRowView(rowIdx, colIndices);
406 PCrs->replaceLocalValues(rowIdx, colIndices, values());
411 *out <<
"The calculation of the interpolation stencils has completed." << std::endl;
413 PCrs->fillComplete();
415 *out <<
"All values in P have been set and expertStaticFillComplete has been performed." << std::endl;
418 if (A->IsView(
"stridedMaps") ==
true) {
419 P->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), stridedDomainMap);
421 P->CreateView(
"stridedMaps", P->getRangeMap(), stridedDomainMap);
426 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
451 int iter = 0, max_iter = 5;
452 real_type functions[4][8], norm_ref = 1.0, norm2 = 1.0, tol = 1.0e-5;
453 paramCoords.
size(numDimensions);
455 while ((iter < max_iter) && (norm2 > tol * norm_ref)) {
458 solutionDirection.
size(numDimensions);
459 residual.
size(numDimensions);
463 GetInterpolationFunctions(numDimensions, paramCoords, functions);
464 for (
LO i = 0; i < numDimensions; ++i) {
465 residual(i) = coord[0][i];
466 for (
LO k = 0; k < numInterpolationPoints; ++k) {
467 residual(i) -= functions[0][k] * coord[k + 1][i];
470 norm_ref += residual(i) * residual(i);
471 if (i == numDimensions - 1) {
472 norm_ref = std::sqrt(norm_ref);
476 for (
LO j = 0; j < numDimensions; ++j) {
477 for (
LO k = 0; k < numInterpolationPoints; ++k) {
478 Jacobian(i, j) += functions[j + 1][k] * coord[k + 1][i];
491 for (
LO i = 0; i < numDimensions; ++i) {
492 paramCoords(i) = paramCoords(i) + solutionDirection(i);
496 GetInterpolationFunctions(numDimensions, paramCoords, functions);
497 for (
LO i = 0; i < numDimensions; ++i) {
499 for (
LO k = 0; k < numInterpolationPoints; ++k) {
500 tmp -= functions[0][k] * coord[k + 1][i];
505 norm2 = std::sqrt(norm2);
509 for (
LO i = 0; i < numInterpolationPoints; ++i) {
510 stencil[i] = functions[0][i];
515 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
520 real_type xi = 0.0, eta = 0.0, zeta = 0.0, denominator = 0.0;
521 if (numDimensions == 1) {
522 xi = parametricCoordinates[0];
524 }
else if (numDimensions == 2) {
525 xi = parametricCoordinates[0];
526 eta = parametricCoordinates[1];
528 }
else if (numDimensions == 3) {
529 xi = parametricCoordinates[0];
530 eta = parametricCoordinates[1];
531 zeta = parametricCoordinates[2];
535 functions[0][0] = (1.0 - xi) * (1.0 - eta) * (1.0 - zeta) / denominator;
536 functions[0][1] = (1.0 + xi) * (1.0 - eta) * (1.0 - zeta) / denominator;
537 functions[0][2] = (1.0 - xi) * (1.0 + eta) * (1.0 - zeta) / denominator;
538 functions[0][3] = (1.0 + xi) * (1.0 + eta) * (1.0 - zeta) / denominator;
539 functions[0][4] = (1.0 - xi) * (1.0 - eta) * (1.0 + zeta) / denominator;
540 functions[0][5] = (1.0 + xi) * (1.0 - eta) * (1.0 + zeta) / denominator;
541 functions[0][6] = (1.0 - xi) * (1.0 + eta) * (1.0 + zeta) / denominator;
542 functions[0][7] = (1.0 + xi) * (1.0 + eta) * (1.0 + zeta) / denominator;
544 functions[1][0] = -(1.0 - eta) * (1.0 - zeta) / denominator;
545 functions[1][1] = (1.0 - eta) * (1.0 - zeta) / denominator;
546 functions[1][2] = -(1.0 + eta) * (1.0 - zeta) / denominator;
547 functions[1][3] = (1.0 + eta) * (1.0 - zeta) / denominator;
548 functions[1][4] = -(1.0 - eta) * (1.0 + zeta) / denominator;
549 functions[1][5] = (1.0 - eta) * (1.0 + zeta) / denominator;
550 functions[1][6] = -(1.0 + eta) * (1.0 + zeta) / denominator;
551 functions[1][7] = (1.0 + eta) * (1.0 + zeta) / denominator;
553 functions[2][0] = -(1.0 - xi) * (1.0 - zeta) / denominator;
554 functions[2][1] = -(1.0 + xi) * (1.0 - zeta) / denominator;
555 functions[2][2] = (1.0 - xi) * (1.0 - zeta) / denominator;
556 functions[2][3] = (1.0 + xi) * (1.0 - zeta) / denominator;
557 functions[2][4] = -(1.0 - xi) * (1.0 + zeta) / denominator;
558 functions[2][5] = -(1.0 + xi) * (1.0 + zeta) / denominator;
559 functions[2][6] = (1.0 - xi) * (1.0 + zeta) / denominator;
560 functions[2][7] = (1.0 + xi) * (1.0 + zeta) / denominator;
562 functions[3][0] = -(1.0 - xi) * (1.0 - eta) / denominator;
563 functions[3][1] = -(1.0 + xi) * (1.0 - eta) / denominator;
564 functions[3][2] = -(1.0 - xi) * (1.0 + eta) / denominator;
565 functions[3][3] = -(1.0 + xi) * (1.0 + eta) / denominator;
566 functions[3][4] = (1.0 - xi) * (1.0 - eta) / denominator;
567 functions[3][5] = (1.0 + xi) * (1.0 - eta) / denominator;
568 functions[3][6] = (1.0 - xi) * (1.0 + eta) / denominator;
569 functions[3][7] = (1.0 + xi) * (1.0 + eta) / denominator;
573 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
579 , fineCoordView_(fineCoordView)
580 , coarseCoordView_(coarseCoordView) {
583 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
587 LO nodeCoarseTuple[3] = {0, 0, 0};
588 LO nodeFineTuple[3] = {0, 0, 0};
589 auto coarseningRate = geoData_.getCoarseningRates();
590 auto fineNodesPerDir = geoData_.getLocalFineNodesPerDir();
591 auto coarseNodesPerDir = geoData_.getCoarseNodesPerDir();
592 geoData_.getCoarseLID2CoarseTuple(coarseNodeIdx, nodeCoarseTuple);
593 for (
int dim = 0; dim < 3; ++dim) {
594 if (nodeCoarseTuple[dim] == coarseNodesPerDir(dim) - 1) {
595 nodeFineTuple[dim] = fineNodesPerDir(dim) - 1;
597 nodeFineTuple[dim] = nodeCoarseTuple[dim] * coarseningRate(dim);
601 fineNodeIdx = nodeFineTuple[2] * fineNodesPerDir(1) * fineNodesPerDir(0) + nodeFineTuple[1] * fineNodesPerDir(0) + nodeFineTuple[0];
603 for (
int dim = 0; dim < fineCoordView_.extent_int(1); ++dim) {
604 coarseCoordView_(coarseNodeIdx, dim) = fineCoordView_(fineNodeIdx, dim);
610 #endif // MUELU_GEOMETRICINTERPOLATIONPFACTORY_KOKKOS_DEF_HPP
typename BMV::impl_scalar_type impl_scalar_type
static Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node >> &map, size_t NumVectors, bool zeroOut=true)
basic_FancyOStream & setShowProcRank(const bool showProcRank)
coarseCoordinatesBuilderFunctor(RCP< IndexManager_kokkos > geoData, coord_view_type fineCoordView, coord_view_type coarseCoordView)
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Timer to be used in factories. Similar to Monitor but with additional timers.
LO getNumCoarseNodes() const
void GetInterpolationFunctions(const LO numDimensions, const Teuchos::SerialDenseVector< LO, real_type > parametricCoordinates, real_type functions[4][8]) const
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
typename Teuchos::ScalarTraits< SC >::coordinateType real_type
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
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)
typename Kokkos::View< impl_scalar_type **, Kokkos::LayoutLeft, device_type > coord_view_type
void BuildConstantP(RCP< Matrix > &P, RCP< const CrsGraph > &prolongatorGraph, RCP< Matrix > &A) const
#define SET_VALID_ENTRY(name)
basic_FancyOStream & setShowAllFrontMatter(const bool showAllFrontMatter)
void resize(size_type new_size, const value_type &x=value_type())
int size(OrdinalType length_in)
int setVectors(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &X, const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &B)
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
void BuildLinearP(RCP< Matrix > &A, RCP< const CrsGraph > &prolongatorGraph, RCP< realvaluedmultivector_type > &fineCoordinates, RCP< realvaluedmultivector_type > &ghostCoordinates, const int numDimensions, RCP< Matrix > &P) const
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)
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
KOKKOS_INLINE_FUNCTION void operator()(const LO nodeIdx) const
int setMatrix(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &A)