MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_MapTransferFactory_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_MAPTRANSFERFACTORY_DEF_HPP_
11#define MUELU_MAPTRANSFERFACTORY_DEF_HPP_
12
14
15#include <Xpetra_Map.hpp>
16#include <Xpetra_MapFactory.hpp>
17#include <Xpetra_Matrix.hpp>
18
19#include "MueLu_Level.hpp"
21#include "MueLu_Monitor.hpp"
22
23namespace MueLu {
24
25template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
27 RCP<ParameterList> validParamList = rcp(new ParameterList());
28
29 validParamList->setEntry("map: name", Teuchos::ParameterEntry(std::string("")));
30 validParamList->setEntry("map: factory", Teuchos::ParameterEntry(std::string("null")));
31
32 validParamList->set<RCP<const FactoryBase>>("P", Teuchos::null, "Tentative prolongator factory");
33 validParamList->set<std::string>("nullspace vectors: limit to", "all", "Limit the number of nullspace vectors to be used for the map transfer (especially to exclude rotational vectors).");
34
35 return validParamList;
36}
37
38template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
40 const ParameterList& pL = GetParameterList();
41 const std::string mapFactName = pL.get<std::string>("map: factory");
42 const std::string mapName = pL.get<std::string>("map: name");
43
44 if (fineLevel.GetLevelID() == 0) {
45 // Not needed, if the map is provided as user data
46 fineLevel.DeclareInput(mapName, NoFactory::get(), this);
47 } else {
48 // check whether user has provided a specific name for the MapFactory
49 if (mapFactName == "" || mapFactName == "NoFactory")
50 mapFact_ = MueLu::NoFactory::getRCP();
51 else if (mapFactName != "null")
52 mapFact_ = coarseLevel.GetFactoryManager()->GetFactory(mapFactName);
53
54 // request map generated by mapFact_
55 fineLevel.DeclareInput(mapName, mapFact_.get(), this);
56 }
57
58 // request Ptent
59 // note that "P" provided by the user (through XML file) is supposed to be of type TentativePFactory
60 Teuchos::RCP<const FactoryBase> tentPFact = GetFactory("P");
61 if (tentPFact == Teuchos::null)
62 tentPFact = coarseLevel.GetFactoryManager()->GetFactory("Ptent");
63 coarseLevel.DeclareInput("P", tentPFact.get(), this);
64}
65
66template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
68 Monitor m(*this, "MapTransferFactory");
69
70 const ParameterList& pL = GetParameterList();
71 const std::string mapName = pL.get<std::string>("map: name");
72 const int maxNumProlongCols = GetLimitOfProlongatorColumns(pL);
73
74 // fetch map from level
75 RCP<const Map> transferMap = Teuchos::null;
76 if (fineLevel.GetLevelID() == 0) {
77 transferMap = fineLevel.Get<RCP<const Map>>(mapName, NoFactory::get());
78 } else {
79 if (fineLevel.IsAvailable(mapName, mapFact_.get()) == false)
80 GetOStream(Runtime0) << "MapTransferFactory::Build: User provided map \"" << mapName << "\" not found in Level class on level " << fineLevel.GetLevelID() << "." << std::endl;
81 transferMap = fineLevel.Get<RCP<const Map>>(mapName, mapFact_.get());
82 }
83
84 // Get default tentative prolongator factory
85 // Getting it that way ensures that the same factory instance will be used for both SaPFactory and NullspaceFactory.
86 RCP<const FactoryBase> tentPFact = GetFactory("P");
87 if (tentPFact == Teuchos::null)
88 tentPFact = coarseLevel.GetFactoryManager()->GetFactory("Ptent");
89 TEUCHOS_TEST_FOR_EXCEPTION(!coarseLevel.IsAvailable("P", tentPFact.get()), Exceptions::RuntimeError,
90 "MueLu::MapTransferFactory::Build(): P (generated by TentativePFactory) not available.");
91 RCP<Matrix> Ptent = coarseLevel.Get<RCP<Matrix>>("P", tentPFact.get());
92
93 // loop over local rows of Ptent and figure out the corresponding coarse GIDs
94 Array<GO> coarseMapGids;
95 RCP<const Map> prolongColMap = Ptent->getColMap();
96 GO gRowID = -1;
97 int numColEntries = 0;
98 for (size_t row = 0; row < Ptent->getLocalNumRows(); ++row) {
99 gRowID = Ptent->getRowMap()->getGlobalElement(row);
100
101 if (transferMap->isNodeGlobalElement(gRowID)) {
102 Teuchos::ArrayView<const LO> indices;
103 Teuchos::ArrayView<const SC> vals;
104 Ptent->getLocalRowView(row, indices, vals);
105
106 numColEntries = as<int>(indices.size());
107 if (maxNumProlongCols > 0)
108 numColEntries = std::min(numColEntries, maxNumProlongCols);
109
110 for (size_t col = 0; col < as<size_t>(numColEntries); ++col) {
111 // mark all (selected) columns in Ptent(gRowID,*) to be coarse Dofs of next level transferMap
112 GO gcid = prolongColMap->getGlobalElement(indices[col]);
113 coarseMapGids.push_back(gcid);
114 }
115 }
116 }
117
118 // build coarse version of the input map
119 const GO INVALID = Teuchos::OrdinalTraits<GlobalOrdinal>::invalid();
120 std::sort(coarseMapGids.begin(), coarseMapGids.end());
121 coarseMapGids.erase(std::unique(coarseMapGids.begin(), coarseMapGids.end()), coarseMapGids.end());
122 RCP<const Map> coarseTransferMap = MapFactory::Build(prolongColMap->lib(), INVALID, coarseMapGids(),
123 prolongColMap->getIndexBase(), prolongColMap->getComm());
124
125 // store map in coarse level
126 if (fineLevel.GetLevelID() == 0) {
127 const std::string mapFactName = pL.get<std::string>("map: factory");
128 RCP<const FactoryBase> mapFact = coarseLevel.GetFactoryManager()->GetFactory(mapFactName);
129 coarseLevel.Set(mapName, coarseTransferMap, mapFact.get());
130 } else
131 coarseLevel.Set(mapName, coarseTransferMap, mapFact_.get());
132}
133
134template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
136 const std::string useTheseNspVectors = pL.get<std::string>("nullspace vectors: limit to");
137
138 // Leave right away, if no limit is prescribed by the user
139 if (useTheseNspVectors == "all" || useTheseNspVectors == "")
140 return -1;
141
142 // Simplify? Maybe replace by boolean flag "nullspace: exclude rotations"
143 int maxNumProlongCols = -1;
144 if (useTheseNspVectors == "translations")
145 maxNumProlongCols = 1;
146 else
147 TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::InvalidArgument, "Unknown subset of nullspace vectors to be used, when performing a map transfer.")
148
149 return maxNumProlongCols;
150}
151
152} // namespace MueLu
153
154#endif /* MUELU_MAPTRANSFERFACTORY_DEF_HPP_ */
Exception throws to report invalid user entry.
Exception throws to report errors in the internal logical of the program.
Class that holds all level-specific information.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
const RCP< const FactoryManagerBase > GetFactoryManager()
returns the current factory manager
int GetLevelID() const
Return level number.
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
int GetLimitOfProlongatorColumns(const ParameterList &pL) const
Get the max number of entries per row of P to be considered for map transfer.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const override
Input.
void Build(Level &fineLevel, Level &coarseLevel) const override
Build an object with this factory.
RCP< const ParameterList > GetValidParameterList() const override
Input.
Timer to be used in non-factories.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
static const NoFactory * get()
Namespace for MueLu classes and methods.
@ Runtime0
One-liner description of what is happening.