MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
23 namespace MueLu {
24 
25 template <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 
38 template <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 
66 template <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");
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)) {
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
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 
134 template <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_ */
ParameterList & setEntry(const std::string &name, U &&entry)
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access). Usage: Level-&gt;Get&lt; RCP&lt;Matrix&gt; &gt;(&quot;A&quot;, factory) if factory == NULL =&gt; use default factory.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const override
Input.
GlobalOrdinal GO
T & get(const std::string &name, T def_value)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
size_type size() const
One-liner description of what is happening.
T * get() const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
static const NoFactory * get()
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:63
RCP< const ParameterList > GetValidParameterList() const override
Input.
int GetLimitOfProlongatorColumns(const ParameterList &pL) const
Get the max number of entries per row of P to be considered for map transfer.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
Timer to be used in non-factories.
void Build(Level &fineLevel, Level &coarseLevel) const override
Build an object with this factory.
const RCP< const FactoryManagerBase > GetFactoryManager()
returns the current factory manager
Definition: MueLu_Level.cpp:73
int GetLevelID() const
Return level number.
Definition: MueLu_Level.cpp:51
Exception throws to report errors in the internal logical of the program.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need&#39;s value has been saved.
Exception throws to report invalid user entry.