MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_SegregatedAFactory_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_SEGREGATEDAFACTORY_DEF_HPP
11 #define MUELU_SEGREGATEDAFACTORY_DEF_HPP
12 
13 #include <Xpetra_Matrix.hpp>
14 #include <Xpetra_MatrixFactory.hpp>
15 
17 
18 #include "MueLu_Level.hpp"
19 #include "MueLu_Monitor.hpp"
20 #include "MueLu_Utilities_decl.hpp"
21 
22 namespace MueLu {
23 
24 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
26  RCP<ParameterList> validParamList = rcp(new ParameterList());
27 
28  validParamList->set<RCP<const FactoryBase>>("A", Teuchos::null, "Generating factory of the matrix A to be filtered");
29  validParamList->set<std::string>("droppingScheme", "vague", "Strategy to drop entries from matrix A based on the input of some map(s) [blockmap, map-pair]");
30 
31  validParamList->set<RCP<const FactoryBase>>("dropMap1", Teuchos::null, "Generating factory for dropMap1");
32  validParamList->set<RCP<const FactoryBase>>("dropMap2", Teuchos::null, "Generating factory for dropMap2'");
33 
34  return validParamList;
35 } // GetValidParameterList
36 
37 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
39  const ParameterList &pL = GetParameterList();
40 
42  "Please specify a generating factory for the matrix \"A\" to be filtered.")
43  TEUCHOS_TEST_FOR_EXCEPTION(pL.get<std::string>("droppingScheme") == "vague", Exceptions::InvalidArgument,
44  "Input map type not selected. Please select one of the available strategies.")
46  (pL.get<std::string>("droppingScheme") != "blockmap" && pL.get<std::string>("droppingScheme") != "map-pair"),
48  "Unknown User Input: droppingScheme (=" << pL.get<std::string>("droppingScheme") << ")")
49 
50  Input(currentLevel, "A");
51 
52  if (pL.get<std::string>("droppingScheme") == "blockmap") {
53  if (currentLevel.GetLevelID() == 0) {
54  currentLevel.DeclareInput("dropMap1", NoFactory::get(), this);
55  } else {
56  Input(currentLevel, "dropMap1");
57  }
58  } else if (pL.get<std::string>("droppingScheme") == "map-pair") {
59  if (currentLevel.GetLevelID() == 0) {
60  currentLevel.DeclareInput("dropMap1", NoFactory::get(), this);
61  currentLevel.DeclareInput("dropMap2", NoFactory::get(), this);
62  } else {
63  Input(currentLevel, "dropMap1");
64  Input(currentLevel, "dropMap2");
65  }
66  } else
67  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::InvalidArgument, "Unknown droppingScheme.")
68 
69 } // DeclareInput
70 
71 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
73  // Call a specialized build routine based on the format of user-given input
74  const ParameterList &pL = GetParameterList();
75  const std::string parameterName = "droppingScheme";
76  if (pL.get<std::string>(parameterName) == "blockmap") {
77  BuildBasedOnBlockmap(currentLevel);
78  } else if (pL.get<std::string>(parameterName) == "map-pair") {
79  BuildBasedOnMapPair(currentLevel);
80  } else {
82  "MueLu::SegregatedAFactory::Build(): Unknown map type of user input. "
83  "Set a valid value for the parameter \""
84  << parameterName << "\".")
85  }
86 } // Build
87 
88 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
90  FactoryMonitor m(*this, "Matrix filtering (segregation, blockmap)", currentLevel);
91 
92  RCP<Matrix> Ain = Get<RCP<Matrix>>(currentLevel, "A");
93  RCP<const Map> dropMap1 = Teuchos::null;
94  const std::string dropMap1Name = "dropMap1";
95 
96  // fetch maps from level
97  if (currentLevel.GetLevelID() == 0) {
98  dropMap1 = currentLevel.Get<RCP<const Map>>(dropMap1Name, NoFactory::get());
99  GetOStream(Statistics0) << "User provided dropMap1 \"" << dropMap1Name << "\": length dimension=" << dropMap1->getGlobalNumElements() << std::endl;
100  } else {
101  dropMap1 = Get<RCP<const Map>>(currentLevel, dropMap1Name);
102  }
103  TEUCHOS_ASSERT(!dropMap1.is_null());
104 
105  // create new empty Operator
106  Teuchos::RCP<Matrix> Aout = MatrixFactory::Build(Ain->getRowMap(), Ain->getGlobalMaxNumRowEntries());
107 
108  size_t numLocalRows = Ain->getLocalNumRows();
109  for (size_t row = 0; row < numLocalRows; row++) {
110  GlobalOrdinal grid = Ain->getRowMap()->getGlobalElement(row); // global row id
111  bool isInMap = dropMap1->isNodeGlobalElement(grid);
112 
113  // extract row information from input matrix
114  auto lclMat = Ain->getLocalMatrixHost();
115  auto rowView = lclMat.row(row);
116 
117  // just copy all values in output
118  Teuchos::ArrayRCP<GO> indout(rowView.length, Teuchos::ScalarTraits<GO>::zero());
119  Teuchos::ArrayRCP<SC> valout(rowView.length, Teuchos::ScalarTraits<SC>::zero());
120 
121  size_t nNonzeros = 0;
122  for (LO jj = 0; jj < rowView.length; ++jj) {
123  LO lcid = rowView.colidx(jj);
124  GO gcid = Ain->getColMap()->getGlobalElement(lcid);
125  auto val = rowView.value(jj);
126  bool isInMap2 = dropMap1->isNodeGlobalElement(gcid);
127 
128  if (isInMap == isInMap2) {
129  indout[nNonzeros] = gcid;
130  valout[nNonzeros] = val;
131  nNonzeros++;
132  }
133  }
134  indout.resize(nNonzeros);
135  valout.resize(nNonzeros);
136 
137  Aout->insertGlobalValues(Ain->getRowMap()->getGlobalElement(row), indout.view(0, indout.size()), valout.view(0, valout.size()));
138  }
139 
140  Aout->fillComplete(Ain->getDomainMap(), Ain->getRangeMap());
141 
142  // copy block size information
143  Aout->SetFixedBlockSize(Ain->GetFixedBlockSize());
144 
145  GetOStream(Statistics0, 0) << "Nonzeros in A (input): " << Ain->getGlobalNumEntries() << ", Nonzeros after filtering A: " << Aout->getGlobalNumEntries() << std::endl;
146 
147  Set(currentLevel, "A", Aout);
148 } // BuildBasedOnBlockmap
149 
150 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
152  FactoryMonitor m(*this, "Matrix filtering (segregation, map-pair)", currentLevel);
153 
154  RCP<Matrix> Ain = Get<RCP<Matrix>>(currentLevel, "A");
155 
156  // fetch maps from level
157  RCP<const Map> dropMap1 = Teuchos::null;
158  RCP<const Map> dropMap2 = Teuchos::null;
159 
160  const std::string dropMap1Name = "dropMap1";
161  const std::string dropMap2Name = "dropMap2";
162 
163  if (currentLevel.GetLevelID() == 0) {
164  dropMap1 = currentLevel.Get<RCP<const Map>>(dropMap1Name, NoFactory::get());
165  dropMap2 = currentLevel.Get<RCP<const Map>>(dropMap2Name, NoFactory::get());
166  GetOStream(Statistics0) << "User provided dropMap1 \"" << dropMap1Name << "\": length dimension=" << dropMap1->getGlobalNumElements() << std::endl;
167  GetOStream(Statistics0) << "User provided dropMap2 \"" << dropMap2Name << "\": length dimension=" << dropMap2->getGlobalNumElements() << std::endl;
168  } else {
169  dropMap1 = Get<RCP<const Map>>(currentLevel, dropMap1Name);
170  dropMap2 = Get<RCP<const Map>>(currentLevel, dropMap2Name);
171  }
172 
173  TEUCHOS_ASSERT(!dropMap1.is_null());
174  TEUCHOS_ASSERT(!dropMap2.is_null());
175 
176  // create new empty Operator
177  Teuchos::RCP<Matrix> Aout = MatrixFactory::Build(Ain->getRowMap(), Ain->getGlobalMaxNumRowEntries());
178 
179  // import the dropping information from other procs for off Rank entries
180  Teuchos::RCP<const Map> finalDropMap1 = Teuchos::null;
181  Teuchos::RCP<const Map> finalDropMap2 = Teuchos::null;
182 
183  finalDropMap1 = MueLu::importOffRankDroppingInfo(dropMap1, Ain);
184  finalDropMap2 = MueLu::importOffRankDroppingInfo(dropMap2, Ain);
185 
186  // Start copying the matrix row by row and dropping any entries that are contained as a combination of entries of
187  // dropMap1 and dropMap2
188  size_t numLocalMatrixRows = Ain->getLocalNumRows();
189 
190  for (size_t row = 0; row < numLocalMatrixRows; row++) {
191  GO grid = Ain->getRowMap()->getGlobalElement(row); // global row id
192  bool rowIsInMap1 = finalDropMap1->isNodeGlobalElement(grid);
193  bool rowIsInMap2 = finalDropMap2->isNodeGlobalElement(grid);
194 
195  // extract row information from input matrix
196  auto lclMat = Ain->getLocalMatrixHost();
197  auto rowView = lclMat.row(row);
198 
199  // just copy all values in output
200  Teuchos::ArrayRCP<GO> indout(rowView.length, Teuchos::ScalarTraits<GO>::zero());
201  Teuchos::ArrayRCP<SC> valout(rowView.length, Teuchos::ScalarTraits<SC>::zero());
202 
203  size_t nNonzeros = 0;
204  for (LO jj = 0; jj < rowView.length; ++jj) {
205  LO lcid = rowView.colidx(jj);
206  GO gcid = Ain->getColMap()->getGlobalElement(lcid); // global column id
207  auto val = rowView.value(jj);
208  bool colIsInMap1 = finalDropMap1->isNodeGlobalElement(gcid);
209  bool colIsInMap2 = finalDropMap2->isNodeGlobalElement(gcid);
210 
211  if ((rowIsInMap1 && colIsInMap2) || (rowIsInMap2 && colIsInMap1)) {
212  // do nothing == drop this entry
213  } else {
214  indout[nNonzeros] = gcid;
215  valout[nNonzeros] = val;
216  nNonzeros++;
217  }
218  }
219  indout.resize(nNonzeros);
220  valout.resize(nNonzeros);
221  Aout->insertGlobalValues(Ain->getRowMap()->getGlobalElement(row), indout.view(0, indout.size()), valout.view(0, valout.size()));
222  }
223 
224  Aout->fillComplete(Ain->getDomainMap(), Ain->getRangeMap());
225 
226  // copy block size information
227  Aout->SetFixedBlockSize(Ain->GetFixedBlockSize());
228 
229  GetOStream(Statistics0, 0) << "Nonzeros in A (input): " << Ain->getGlobalNumEntries() << ", Nonzeros after filtering A: " << Aout->getGlobalNumEntries() << std::endl;
230 
231  currentLevel.Set("A", Aout, this);
232 } // BuildBasedOnMapPair
233 
234 } // namespace MueLu
235 
236 #endif // MUELU_SEGREGATEDAFACTORY_DEF_HPP
GlobalOrdinal GO
T & get(const std::string &name, T def_value)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
LocalOrdinal LO
void Build(Level &currentLevel) const override
Build method.
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
size_type size() const
static const NoFactory * get()
void BuildBasedOnBlockmap(Level &currentLevel) const
void resize(const size_type n, const T &val=T())
Print statistics that do not involve significant additional computation.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
MueLu::DefaultGlobalOrdinal GlobalOrdinal
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:63
void DeclareInput(Level &currentLevel) const override
Specifies the data that this class needs, and the factories that generate that data.
RCP< const ParameterList > GetValidParameterList() const override
Input.
Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > importOffRankDroppingInfo(Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node >> &localDropMap, Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &Ain)
void BuildBasedOnMapPair(Level &currentLevel) const
int GetLevelID() const
Return level number.
Definition: MueLu_Level.cpp:51
#define TEUCHOS_ASSERT(assertion_test)
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
Exception throws to report invalid user entry.
bool is_null() const
ArrayView< T > view(size_type lowerOffset, size_type size) const