60 const ParameterList &pL = GetParameterList();
61 const std::string vectorName = pL.get<std::string>(
"Vector name");
62 const std::string transferName = pL.get<std::string>(
"Transfer name");
63 const bool normalize = pL.get<
bool>(
"Normalize");
65 auto transferFact = GetFactory(
"Transfer factory");
66 const bool isUncoupledAggFact = !Teuchos::rcp_dynamic_cast<const UncoupledAggregationFactory>(transferFact).is_null();
68 GetOStream(
Runtime0) <<
"Transferring multivector \"" << vectorName <<
"\" using operator \"" << transferName <<
"\"" << std::endl;
69 if (vectorName ==
"Coordinates")
70 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"Use CoordinatesTransferFactory to transfer coordinates instead of MultiVectorTransferFactory.");
72 RCP<MultiVector> fineVector = fineLevel.
Get<RCP<MultiVector>>(vectorName, GetFactory(
"Vector factory").get());
73 RCP<MultiVector> coarseVector;
75 if (!isUncoupledAggFact) {
76 RCP<Matrix> transferOp = coarseLevel.
Get<RCP<Matrix>>(transferName, GetFactory(
"Transfer factory").get());
77 Teuchos::ETransp transp;
79 if (transferOp->getGlobalNumRows() <= transferOp->getGlobalNumCols()) {
81 coarseVector = MultiVectorFactory::Build(transferOp->getRangeMap(), fineVector->getNumVectors());
82 transp = Teuchos::NO_TRANS;
85 coarseVector = MultiVectorFactory::Build(transferOp->getDomainMap(), fineVector->getNumVectors());
86 transp = Teuchos::TRANS;
89 transferOp->apply(*fineVector, *coarseVector, transp);
93 RCP<MultiVector> onesVector = MultiVectorFactory::Build(fineVector->getMap(), 1);
94 onesVector->putScalar(Teuchos::ScalarTraits<Scalar>::one());
95 RCP<MultiVector> rowSumVector = MultiVectorFactory::Build(coarseVector->getMap(), 1);
96 transferOp->apply(*onesVector, *rowSumVector, transp);
98 RCP<Vector> rowSumReciprocalVector = VectorFactory::Build(coarseVector->getMap(), 1);
99 rowSumReciprocalVector->reciprocal(*rowSumVector);
101 RCP<MultiVector> coarseVectorNormalized = MultiVectorFactory::Build(coarseVector->getMap(), fineVector->getNumVectors());
102 coarseVectorNormalized->elementWiseMultiply(1.0, *rowSumReciprocalVector, *coarseVector, 0.0);
104 Set<RCP<MultiVector>>(coarseLevel, vectorName, coarseVectorNormalized);
106 Set<RCP<MultiVector>>(coarseLevel, vectorName, coarseVector);
109 using execution_space =
typename Node::execution_space;
110 using ATS = KokkosKernels::ArithTraits<Scalar>;
111 using impl_scalar_type =
typename ATS::val_type;
113 auto aggregates = fineLevel.
Get<RCP<Aggregates>>(transferName, GetFactory(
"Transfer factory").get());
114 TEUCHOS_ASSERT(!aggregates->AggregatesCrossProcessors());
115 RCP<const Map> coarseMap = Get<RCP<const Map>>(fineLevel,
"CoarseMap");
117 auto aggGraph = aggregates->GetGraph();
118 auto numAggs = aggGraph.numRows();
120 RCP<const Map> coarseVectorMap;
123 if (rcp_dynamic_cast<const StridedMap>(coarseMap) != Teuchos::null)
124 blkSize = rcp_dynamic_cast<const StridedMap>(coarseMap)->getFixedBlockSize();
129 coarseVectorMap = coarseMap;
135 coarseVector = MultiVectorFactory::Build(coarseVectorMap, fineVector->getNumVectors());
137 auto lcl_fineVector = fineVector->getLocalViewDevice(Tpetra::Access::ReadOnly);
138 auto lcl_coarseVector = coarseVector->getLocalViewDevice(Tpetra::Access::OverwriteAll);
140 Kokkos::parallel_for(
141 "MueLu:MultiVectorTransferFactory",
142 Kokkos::RangePolicy<LocalOrdinal, execution_space>(0, numAggs),
143 KOKKOS_LAMBDA(
const LO i) {
144 auto aggregate = aggGraph.rowConst(i);
145 for (
size_t j = 0; j < lcl_coarseVector.extent(1); j++) {
146 impl_scalar_type sum = 0.0;
147 for (
size_t colID = 0; colID < static_cast<size_t>(aggregate.length); colID++)
148 sum += lcl_fineVector(aggregate(colID), j);
150 lcl_coarseVector(i, j) = sum / aggregate.length;
152 lcl_coarseVector(i, j) = sum;
155 Set<RCP<MultiVector>>(coarseLevel, vectorName, coarseVector);