MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_MultiVectorTransferFactory_def.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// MueLu: A package for multigrid based preconditioning
4//
5// Copyright 2012 NTESS and the MueLu contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef MUELU_MULTIVECTORTRANSFER_FACTORY_DEF_HPP
11#define MUELU_MULTIVECTORTRANSFER_FACTORY_DEF_HPP
12
14#include "Tpetra_Access.hpp"
15#include "Xpetra_MultiVectorFactory.hpp"
16
17#include "MueLu_Aggregates.hpp"
18#include "MueLu_AmalgamationInfo.hpp"
19#include "MueLu_AmalgamationFactory.hpp"
20#include "MueLu_Level.hpp"
21#include "MueLu_UncoupledAggregationFactory.hpp"
22#include "MueLu_Monitor.hpp"
23
24namespace MueLu {
25
26template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
28 RCP<ParameterList> validParamList = rcp(new ParameterList());
29
30 validParamList->set<std::string>("Vector name", "undefined", "Name of the vector that will be transferred on the coarse grid (level key)"); // TODO: how to set a validator without default value?
31 validParamList->set<std::string>("Transfer name", "R", "Name of the operator that will be used to transfer data");
32 validParamList->set<bool>("Normalize", false, "If a row sum normalization should be applied to preserve the mean value of the vector.");
33 validParamList->set<RCP<const FactoryBase>>("Vector factory", Teuchos::null, "Factory of the vector");
34 validParamList->set<RCP<const FactoryBase>>("Transfer factory", Teuchos::null, "Factory of the transfer operator");
35 validParamList->set<RCP<const FactoryBase>>("CoarseMap", Teuchos::null, "Generating factory of the coarse map");
36
37 return validParamList;
38}
39
40template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
42 const ParameterList &pL = GetParameterList();
43 std::string vectorName = pL.get<std::string>("Vector name");
44 std::string transferName = pL.get<std::string>("Transfer name");
45
46 fineLevel.DeclareInput(vectorName, GetFactory("Vector factory").get(), this);
47 auto transferFact = GetFactory("Transfer factory");
48 const bool isUncoupledAggFact = !Teuchos::rcp_dynamic_cast<const UncoupledAggregationFactory>(transferFact).is_null();
49 if (isUncoupledAggFact) {
50 fineLevel.DeclareInput(transferName, transferFact.get(), this);
51 Input(fineLevel, "CoarseMap");
52 } else
53 coarseLevel.DeclareInput(transferName, transferFact.get(), this);
54}
55
56template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
58 FactoryMonitor m(*this, "Build", coarseLevel);
59
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");
64
65 auto transferFact = GetFactory("Transfer factory");
66 const bool isUncoupledAggFact = !Teuchos::rcp_dynamic_cast<const UncoupledAggregationFactory>(transferFact).is_null();
67
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.");
71
72 RCP<MultiVector> fineVector = fineLevel.Get<RCP<MultiVector>>(vectorName, GetFactory("Vector factory").get());
73 RCP<MultiVector> coarseVector;
74
75 if (!isUncoupledAggFact) {
76 RCP<Matrix> transferOp = coarseLevel.Get<RCP<Matrix>>(transferName, GetFactory("Transfer factory").get());
77 Teuchos::ETransp transp;
78
79 if (transferOp->getGlobalNumRows() <= transferOp->getGlobalNumCols()) {
80 // R mode
81 coarseVector = MultiVectorFactory::Build(transferOp->getRangeMap(), fineVector->getNumVectors());
82 transp = Teuchos::NO_TRANS;
83 } else {
84 // P mode
85 coarseVector = MultiVectorFactory::Build(transferOp->getDomainMap(), fineVector->getNumVectors());
86 transp = Teuchos::TRANS;
87 }
88
89 transferOp->apply(*fineVector, *coarseVector, transp);
90
91 if (normalize) {
92 // Do constant row sum normalization
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);
97
98 RCP<Vector> rowSumReciprocalVector = VectorFactory::Build(coarseVector->getMap(), 1);
99 rowSumReciprocalVector->reciprocal(*rowSumVector);
100
101 RCP<MultiVector> coarseVectorNormalized = MultiVectorFactory::Build(coarseVector->getMap(), fineVector->getNumVectors());
102 coarseVectorNormalized->elementWiseMultiply(1.0, *rowSumReciprocalVector, *coarseVector, 0.0);
103
104 Set<RCP<MultiVector>>(coarseLevel, vectorName, coarseVectorNormalized);
105 } else {
106 Set<RCP<MultiVector>>(coarseLevel, vectorName, coarseVector);
107 }
108 } else {
109 using execution_space = typename Node::execution_space;
110#if KOKKOS_VERSION >= 40799
111 using ATS = KokkosKernels::ArithTraits<Scalar>;
112#else
113 using ATS = Kokkos::ArithTraits<Scalar>;
114#endif
115 using impl_scalar_type = typename ATS::val_type;
116
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");
120
121 auto aggGraph = aggregates->GetGraph();
122 auto numAggs = aggGraph.numRows();
123
124 RCP<const Map> coarseVectorMap;
125
126 LO blkSize = 1;
127 if (rcp_dynamic_cast<const StridedMap>(coarseMap) != Teuchos::null)
128 blkSize = rcp_dynamic_cast<const StridedMap>(coarseMap)->getFixedBlockSize();
129
130 if (blkSize == 1) {
131 // Scalar system
132 // No amalgamation required, we can use the coarseMap
133 coarseVectorMap = coarseMap;
134 } else {
135 // Vector system
136 AmalgamationFactory<SC, LO, GO, NO>::AmalgamateMap(rcp_dynamic_cast<const StridedMap>(coarseMap), coarseVectorMap);
137 }
138
139 coarseVector = MultiVectorFactory::Build(coarseVectorMap, fineVector->getNumVectors());
140
141 auto lcl_fineVector = fineVector->getLocalViewDevice(Tpetra::Access::ReadOnly);
142 auto lcl_coarseVector = coarseVector->getLocalViewDevice(Tpetra::Access::OverwriteAll);
143
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);
153 if (normalize)
154 lcl_coarseVector(i, j) = sum / aggregate.length;
155 else
156 lcl_coarseVector(i, j) = sum;
157 }
158 });
159 Set<RCP<MultiVector>>(coarseLevel, vectorName, coarseVector);
160 }
161} // Build
162
163} // namespace MueLu
164
165#endif // MUELU_MULTIVECTORTRANSFER_FACTORY_DEF_HPP
static void AmalgamateMap(const Map &sourceMap, const Matrix &A, RCP< const Map > &amalgamatedMap, Array< LO > &translation)
Method to create merged map for systems of PDEs.
Exception throws to report errors in the internal logical of the program.
void Input(Level &level, const std::string &varName) const
T Get(Level &level, const std::string &varName) const
void Set(Level &level, const std::string &varName, const T &data) const
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Default implementation of FactoryAcceptor::GetFactory().
Timer to be used in factories. Similar to Monitor but with additional timers.
Class that holds all level-specific information.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput().
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
void DeclareInput(Level &finelevel, Level &coarseLevel) const
Specifies the data that this class needs, and the factories that generate that data.
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
virtual const Teuchos::ParameterList & GetParameterList() const
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
Namespace for MueLu classes and methods.
@ Runtime0
One-liner description of what is happening.