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#if KOKKOS_VERSION >= 40799
111 using ATS = KokkosKernels::ArithTraits<Scalar>;
113 using ATS = Kokkos::ArithTraits<Scalar>;
115 using impl_scalar_type =
typename ATS::val_type;
117 auto aggregates = fineLevel.
Get<RCP<Aggregates>>(transferName, GetFactory(
"Transfer factory").get());
118 TEUCHOS_ASSERT(!aggregates->AggregatesCrossProcessors());
119 RCP<const Map> coarseMap = Get<RCP<const Map>>(fineLevel,
"CoarseMap");
121 auto aggGraph = aggregates->GetGraph();
122 auto numAggs = aggGraph.numRows();
124 RCP<const Map> coarseVectorMap;
127 if (rcp_dynamic_cast<const StridedMap>(coarseMap) != Teuchos::null)
128 blkSize = rcp_dynamic_cast<const StridedMap>(coarseMap)->getFixedBlockSize();
133 coarseVectorMap = coarseMap;
139 coarseVector = MultiVectorFactory::Build(coarseVectorMap, fineVector->getNumVectors());
141 auto lcl_fineVector = fineVector->getLocalViewDevice(Tpetra::Access::ReadOnly);
142 auto lcl_coarseVector = coarseVector->getLocalViewDevice(Tpetra::Access::OverwriteAll);
144 Kokkos::parallel_for(
145 "MueLu:MultiVectorTransferFactory",
146 Kokkos::RangePolicy<LocalOrdinal, execution_space>(0, numAggs),
147 KOKKOS_LAMBDA(
const LO i) {
148 auto aggregate = aggGraph.rowConst(i);
149 for (
size_t j = 0; j < lcl_coarseVector.extent(1); j++) {
150 impl_scalar_type sum = 0.0;
151 for (
size_t colID = 0; colID < static_cast<size_t>(aggregate.length); colID++)
152 sum += lcl_fineVector(aggregate(colID), j);
154 lcl_coarseVector(i, j) = sum / aggregate.length;
156 lcl_coarseVector(i, j) = sum;
159 Set<RCP<MultiVector>>(coarseLevel, vectorName, coarseVector);