59 const std::string vectorName = pL.get<std::string>(
"Vector name");
60 const std::string transferName = pL.get<std::string>(
"Transfer name");
61 const bool normalize = pL.get<
bool>(
"Normalize");
63 auto transferFact =
GetFactory(
"Transfer factory");
64 const bool isUncoupledAggFact = !Teuchos::rcp_dynamic_cast<const UncoupledAggregationFactory>(transferFact).is_null();
66 GetOStream(
Runtime0) <<
"Transferring multivector \"" << vectorName <<
"\" using operator \"" << transferName <<
"\"" << std::endl;
67 if (vectorName ==
"Coordinates")
68 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"Use CoordinatesTransferFactory to transfer coordinates instead of MultiVectorTransferFactory.");
70 RCP<MultiVector> fineVector = fineLevel.
Get<RCP<MultiVector>>(vectorName,
GetFactory(
"Vector factory").get());
71 RCP<MultiVector> coarseVector;
73 if (!isUncoupledAggFact) {
74 RCP<Matrix> transferOp = coarseLevel.
Get<RCP<Matrix>>(transferName,
GetFactory(
"Transfer factory").get());
75 Teuchos::ETransp transp;
77 if (transferOp->getGlobalNumRows() <= transferOp->getGlobalNumCols()) {
79 coarseVector = MultiVectorFactory::Build(transferOp->getRangeMap(), fineVector->getNumVectors());
80 transp = Teuchos::NO_TRANS;
83 coarseVector = MultiVectorFactory::Build(transferOp->getDomainMap(), fineVector->getNumVectors());
84 transp = Teuchos::TRANS;
87 transferOp->apply(*fineVector, *coarseVector, transp);
91 RCP<MultiVector> onesVector = MultiVectorFactory::Build(fineVector->getMap(), 1);
92 onesVector->putScalar(Teuchos::ScalarTraits<Scalar>::one());
93 RCP<MultiVector> rowSumVector = MultiVectorFactory::Build(coarseVector->getMap(), 1);
94 transferOp->apply(*onesVector, *rowSumVector, transp);
96 RCP<Vector> rowSumReciprocalVector = VectorFactory::Build(coarseVector->getMap(), 1);
97 rowSumReciprocalVector->reciprocal(*rowSumVector);
99 RCP<MultiVector> coarseVectorNormalized = MultiVectorFactory::Build(coarseVector->getMap(), fineVector->getNumVectors());
100 coarseVectorNormalized->elementWiseMultiply(1.0, *rowSumReciprocalVector, *coarseVector, 0.0);
107 using execution_space =
typename Node::execution_space;
108 using ATS = Kokkos::ArithTraits<Scalar>;
109 using impl_scalar_type =
typename ATS::val_type;
111 auto aggregates = fineLevel.
Get<RCP<Aggregates>>(transferName,
GetFactory(
"Transfer factory").get());
112 TEUCHOS_ASSERT(!aggregates->AggregatesCrossProcessors());
115 auto aggGraph = aggregates->GetGraph();
116 auto numAggs = aggGraph.numRows();
118 coarseVector = MultiVectorFactory::Build(coarseMap, fineVector->getNumVectors());
120 auto lcl_fineVector = fineVector->getDeviceLocalView(Xpetra::Access::ReadOnly);
121 auto lcl_coarseVector = coarseVector->getDeviceLocalView(Xpetra::Access::OverwriteAll);
123 Kokkos::parallel_for(
124 "MueLu:MultiVectorTransferFactory",
125 Kokkos::RangePolicy<LocalOrdinal, execution_space>(0, numAggs),
126 KOKKOS_LAMBDA(
const LO i) {
127 auto aggregate = aggGraph.rowConst(i);
128 for (
size_t j = 0; j < lcl_coarseVector.extent(1); j++) {
129 impl_scalar_type sum = 0.0;
130 for (
size_t colID = 0; colID < static_cast<size_t>(aggregate.length); colID++)
131 sum += lcl_fineVector(aggregate(colID), j);
133 lcl_coarseVector(i, j) = sum / aggregate.length;
135 lcl_coarseVector(i, j) = sum;