MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_LocalOrdinalTransferFactory_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_LOCALORDINALTRANSFER_FACTORY_DEF_HPP
11 #define MUELU_LOCALORDINALTRANSFER_FACTORY_DEF_HPP
12 
13 #include "Xpetra_ImportFactory.hpp"
14 #include "Xpetra_VectorFactory.hpp"
15 #include "Xpetra_MapFactory.hpp"
16 #include "Xpetra_CrsGraph.hpp"
17 
18 #include "Xpetra_IO.hpp"
19 
20 #include "MueLu_Aggregates.hpp"
22 
23 #include "MueLu_Level.hpp"
24 #include "MueLu_Monitor.hpp"
25 
26 namespace MueLu {
27 
28 template <class LocalOrdinal, class GlobalOrdinal, class Node>
30  RCP<ParameterList> validParamList = rcp(new ParameterList());
31 
32  validParamList->set<RCP<const FactoryBase> >(TransferVecName_, Teuchos::null, "Factory for TransferVec generation");
33  validParamList->set<RCP<const FactoryBase> >("P Graph", Teuchos::null, "Factory for P generation");
34  validParamList->set<RCP<const FactoryBase> >("Aggregates", Teuchos::null, "Factory for aggregates generation");
35  validParamList->set<RCP<const FactoryBase> >("CoarseMap", Teuchos::null, "Generating factory of the coarse map");
36 
37  return validParamList;
38 }
39 
40 template <class LocalOrdinal, class GlobalOrdinal, class Node>
42  static bool isAvailableXfer = false;
43  if (coarseLevel.GetRequestMode() == Level::REQUEST) {
44  isAvailableXfer = coarseLevel.IsAvailable(TransferVecName_, this);
45  if (isAvailableXfer == false) {
46  Input(fineLevel, TransferVecName_);
47  Input(fineLevel, "CoarseMap");
48 
49  if (useAggregatesMode_)
50  Input(fineLevel, "Aggregates");
51  else {
52  Input(coarseLevel, "P Graph");
53  }
54  }
55  }
56 }
57 
58 template <class LocalOrdinal, class GlobalOrdinal, class Node>
60  if (useAggregatesMode_)
61  BuildAggregates(fineLevel, coarseLevel);
62  else
63  BuildFC(fineLevel, coarseLevel);
64 }
65 
66 template <class LocalOrdinal, class GlobalOrdinal, class Node>
68  FactoryMonitor m(*this, "Build", coarseLevel);
69 
70  GetOStream(Runtime0) << "Transferring " << TransferVecName_ << std::endl;
72 
73  if (coarseLevel.IsAvailable(TransferVecName_, this)) {
74  GetOStream(Runtime0) << "Reusing " << TransferVecName_ << std::endl;
75  return;
76  }
77 
78  // Get everything we need
79  RCP<const CrsGraph> P = Get<RCP<const CrsGraph> >(coarseLevel, "P Graph");
80  RCP<LocalOrdinalVector> fineTV = Get<RCP<LocalOrdinalVector> >(fineLevel, TransferVecName_);
81  RCP<const Map> coarseMap = Get<RCP<const Map> >(fineLevel, "CoarseMap");
82  RCP<const Map> uniqueMap = fineTV->getMap();
83  ArrayRCP<const LO> fineData = fineTV->getData(0);
84 
85  // Allocate new LO Vector
86  RCP<LocalOrdinalVector> coarseTV = LocalOrdinalVectorFactory::Build(coarseMap, 1);
87  ArrayRCP<LO> coarseData = coarseTV->getDataNonConst(0);
88 
89  // Invalidate everything first, to check for errors
90  for (LO i = 0; i < coarseData.size(); i++)
91  coarseData[i] = LO_INVALID;
92 
93  // Fill in coarse TV
94  LO domMapNumElements = P->getDomainMap()->getLocalNumElements();
95  for (LO row = 0; row < (LO)P->getLocalNumRows(); row++) {
96  LO fineNumber = fineData[row];
97  ArrayView<const LO> indices;
98  P->getLocalRowView(row, indices);
99 
100  for (LO j = 0; j < (LO)indices.size(); j++) {
101  LO col = indices[j];
102  if (col >= domMapNumElements) {
103  // skip off rank entries of P
104  } else {
105  coarseData[col] = fineNumber;
106  }
107  }
108  }
109 
110 #ifdef HAVE_MUELU_DEBUG
111  size_t error_count = 0;
112  {
113  RCP<LocalOrdinalVector> coarseTVghosted;
114  RCP<const Import> importer = P->getImporter();
115  if (!importer.is_null()) {
116  coarseTVghosted = LocalOrdinalVectorFactory::Build(P->getColMap(), 1);
117  coarseTVghosted->doImport(*coarseTV, *importer, Xpetra::INSERT);
118  } else {
119  coarseTVghosted = coarseTV;
120  }
121  ArrayRCP<LO> coarseDataGhosted = coarseTVghosted->getDataNonConst(0);
122  for (LO col = 0; col < (LO)P->getColMap()->getLocalNumElements(); col++) {
123  if (coarseDataGhosted[col] == LO_INVALID)
124  error_count++;
125  }
126  for (LO row = 0; row < (LO)P->getLocalNumRows(); row++) {
127  LO fineNumber = fineData[row];
128  ArrayView<const LO> indices;
129  P->getLocalRowView(row, indices);
130  for (LO j = 0; j < (LO)indices.size(); j++) {
131  if (coarseDataGhosted[indices[j]] != fineNumber)
132  error_count++;
133  }
134  }
135  }
136 
137  // Error checking: All nodes in an aggregate must share a local ordinal
138  if (error_count > 0) {
139  std::ostringstream ofs;
140  ofs << "LocalOrdinalTransferFactory(" << TransferVecName_ << "): ERROR: Each coarse dof must have a unique LO value. We had " << std::to_string(error_count) << " unknowns that did not match.";
141  throw std::runtime_error(ofs.str());
142  }
143 #endif
144 
145  Set<RCP<LocalOrdinalVector> >(coarseLevel, TransferVecName_, coarseTV);
146 }
147 
148 template <class LocalOrdinal, class GlobalOrdinal, class Node>
150  FactoryMonitor m(*this, "Build", coarseLevel);
151 
152  GetOStream(Runtime0) << "Transferring " << TransferVecName_ << std::endl;
153  RCP<LocalOrdinalVector> coarseTV;
156 
157  if (coarseLevel.IsAvailable(TransferVecName_, this)) {
158  GetOStream(Runtime0) << "Reusing " << TransferVecName_ << std::endl;
159  return;
160  }
161 
162  RCP<Aggregates> aggregates = Get<RCP<Aggregates> >(fineLevel, "Aggregates");
163  fineTV = Get<RCP<LocalOrdinalVector> >(fineLevel, TransferVecName_);
164  RCP<const Map> coarseMap = Get<RCP<const Map> >(fineLevel, "CoarseMap");
165  RCP<const Map> uniqueMap = fineTV->getMap();
166 
167  ArrayView<const GO> elementAList = coarseMap->getLocalElementList();
168 
169  coarseTV = LocalOrdinalVectorFactory::Build(coarseMap, 1);
170 
171  // Create overlapped fine TV to reduce global communication
172  RCP<LocalOrdinalVector> ghostedTV = fineTV;
173  if (aggregates->AggregatesCrossProcessors()) {
174  RCP<const Map> nonUniqueMap = aggregates->GetMap();
175  RCP<const Import> importer = ImportFactory::Build(uniqueMap, nonUniqueMap);
176 
177  ghostedTV = LocalOrdinalVectorFactory::Build(nonUniqueMap, 1);
178  ghostedTV->doImport(*fineTV, *importer, Xpetra::INSERT);
179  }
180 
181  // Get some info about aggregates
182  int myPID = uniqueMap->getComm()->getRank();
183  ArrayRCP<LO> aggSizes = aggregates->ComputeAggregateSizesArrayRCP();
184  const ArrayRCP<const LO> vertex2AggID = aggregates->GetVertex2AggId()->getData(0);
185  const ArrayRCP<const LO> procWinner = aggregates->GetProcWinner()->getData(0);
186 
187  ArrayRCP<const LO> fineData = ghostedTV->getData(0);
188  ArrayRCP<LO> coarseData = coarseTV->getDataNonConst(0);
189 
190  // Invalidate everything first, to check for errors
191  for (LO i = 0; i < coarseData.size(); i++)
192  coarseData[i] = LO_INVALID;
193 
194  // Fill in coarse TV
195  size_t error_count = 0;
196  for (LO lnode = 0; lnode < vertex2AggID.size(); lnode++) {
197  if (procWinner[lnode] == myPID &&
198  // lnode < vertex2AggID.size() &&
199  lnode < fineData.size() && // TAW do not access off-processor data
200  vertex2AggID[lnode] < coarseData.size()) {
201  if (coarseData[vertex2AggID[lnode]] == LO_INVALID)
202  coarseData[vertex2AggID[lnode]] = fineData[lnode];
203  if (coarseData[vertex2AggID[lnode]] != fineData[lnode])
204  error_count++;
205  }
206  }
207 
208  // Error checking: All nodes in an aggregate must share a local ordinal
209  if (error_count > 0) {
210  std::ostringstream ofs;
211  ofs << "LocalOrdinalTransferFactory: ERROR: Each aggregate must have a unique LO value. We had " << std::to_string(error_count) << " unknowns that did not match.";
212  throw std::runtime_error(ofs.str());
213  }
214 
215  Set<RCP<LocalOrdinalVector> >(coarseLevel, TransferVecName_, coarseTV);
216 }
217 
218 } // namespace MueLu
219 
220 #endif // MUELU_LOCALORDINALTRANSFER_FACTORY_DEF_HPP
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
const RCP< LOVector > & GetProcWinner() const
Returns constant vector that maps local node IDs to owning processor IDs.
void BuildFC(Level &fineLevel, Level &coarseLevel) const
void DeclareInput(Level &finelevel, Level &coarseLevel) const
Specifies the data that this class needs, and the factories that generate that data.
Timer to be used in factories. Similar to Monitor but with additional timers.
size_type size() const
const RCP< const Map > GetMap() const
returns (overlapping) map of aggregate/node distribution
LocalOrdinal LO
One-liner description of what is happening.
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
size_type size() const
RequestMode GetRequestMode() const
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
void BuildAggregates(Level &fineLevel, Level &coarseLevel) const
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
Teuchos::ArrayRCP< LocalOrdinal > ComputeAggregateSizesArrayRCP(bool forceRecompute=false) const
Compute sizes of aggregates.
const RCP< LOMultiVector > & GetVertex2AggId() const
Returns constant vector that maps local node IDs to local aggregates IDs.
KOKKOS_INLINE_FUNCTION void AggregatesCrossProcessors(const bool &flag)
Record whether aggregates include DOFs from other processes.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need&#39;s value has been saved.
bool is_null() const