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 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Ray Tuminaro (rstumin@sandia.gov)
41 // Tobias Wiesner (tawiesn@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_SEGREGATEDAFACTORY_DEF_HPP
47 #define MUELU_SEGREGATEDAFACTORY_DEF_HPP
48 
49 #include <Xpetra_Matrix.hpp>
50 #include <Xpetra_MatrixFactory.hpp>
51 
53 
54 #include "MueLu_Level.hpp"
55 #include "MueLu_Monitor.hpp"
56 #include "MueLu_Utilities_decl.hpp"
57 
58 namespace MueLu {
59 
60 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
62  RCP<ParameterList> validParamList = rcp(new ParameterList());
63 
64  validParamList->set<RCP<const FactoryBase>>("A", Teuchos::null, "Generating factory of the matrix A to be filtered");
65  validParamList->set<std::string>("droppingScheme", "vague", "Strategy to drop entries from matrix A based on the input of some map(s) [blockmap, map-pair]");
66 
67  validParamList->set<RCP<const FactoryBase>>("dropMap1", Teuchos::null, "Generating factory for dropMap1");
68  validParamList->set<RCP<const FactoryBase>>("dropMap2", Teuchos::null, "Generating factory for dropMap2'");
69 
70  return validParamList;
71 } // GetValidParameterList
72 
73 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
75  const ParameterList &pL = GetParameterList();
76 
78  "Please specify a generating factory for the matrix \"A\" to be filtered.")
79  TEUCHOS_TEST_FOR_EXCEPTION(pL.get<std::string>("droppingScheme") == "vague", Exceptions::InvalidArgument,
80  "Input map type not selected. Please select one of the available strategies.")
82  (pL.get<std::string>("droppingScheme") != "blockmap" && pL.get<std::string>("droppingScheme") != "map-pair"),
84  "Unknown User Input: droppingScheme (=" << pL.get<std::string>("droppingScheme") << ")")
85 
86  Input(currentLevel, "A");
87 
88  if (pL.get<std::string>("droppingScheme") == "blockmap") {
89  if (currentLevel.GetLevelID() == 0) {
90  currentLevel.DeclareInput("dropMap1", NoFactory::get(), this);
91  } else {
92  Input(currentLevel, "dropMap1");
93  }
94  } else if (pL.get<std::string>("droppingScheme") == "map-pair") {
95  if (currentLevel.GetLevelID() == 0) {
96  currentLevel.DeclareInput("dropMap1", NoFactory::get(), this);
97  currentLevel.DeclareInput("dropMap2", NoFactory::get(), this);
98  } else {
99  Input(currentLevel, "dropMap1");
100  Input(currentLevel, "dropMap2");
101  }
102  } else
103  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::InvalidArgument, "Unknown droppingScheme.")
104 
105 } // DeclareInput
106 
107 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
109  // Call a specialized build routine based on the format of user-given input
110  const ParameterList &pL = GetParameterList();
111  const std::string parameterName = "droppingScheme";
112  if (pL.get<std::string>(parameterName) == "blockmap") {
113  BuildBasedOnBlockmap(currentLevel);
114  } else if (pL.get<std::string>(parameterName) == "map-pair") {
115  BuildBasedOnMapPair(currentLevel);
116  } else {
118  "MueLu::SegregatedAFactory::Build(): Unknown map type of user input. "
119  "Set a valid value for the parameter \""
120  << parameterName << "\".")
121  }
122 } // Build
123 
124 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
126  FactoryMonitor m(*this, "Matrix filtering (segregation, blockmap)", currentLevel);
127 
128  RCP<Matrix> Ain = Get<RCP<Matrix>>(currentLevel, "A");
129  RCP<const Map> dropMap1 = Teuchos::null;
130  const std::string dropMap1Name = "dropMap1";
131 
132  // fetch maps from level
133  if (currentLevel.GetLevelID() == 0) {
134  dropMap1 = currentLevel.Get<RCP<const Map>>(dropMap1Name, NoFactory::get());
135  GetOStream(Statistics0) << "User provided dropMap1 \"" << dropMap1Name << "\": length dimension=" << dropMap1->getGlobalNumElements() << std::endl;
136  } else {
137  dropMap1 = Get<RCP<const Map>>(currentLevel, dropMap1Name);
138  }
139  TEUCHOS_ASSERT(!dropMap1.is_null());
140 
141  // create new empty Operator
142  Teuchos::RCP<Matrix> Aout = MatrixFactory::Build(Ain->getRowMap(), Ain->getGlobalMaxNumRowEntries());
143 
144  size_t numLocalRows = Ain->getLocalNumRows();
145  for (size_t row = 0; row < numLocalRows; row++) {
146  GlobalOrdinal grid = Ain->getRowMap()->getGlobalElement(row); // global row id
147  bool isInMap = dropMap1->isNodeGlobalElement(grid);
148 
149  // extract row information from input matrix
150  auto lclMat = Ain->getLocalMatrixHost();
151  auto rowView = lclMat.row(row);
152 
153  // just copy all values in output
154  Teuchos::ArrayRCP<GO> indout(rowView.length, Teuchos::ScalarTraits<GO>::zero());
155  Teuchos::ArrayRCP<SC> valout(rowView.length, Teuchos::ScalarTraits<SC>::zero());
156 
157  size_t nNonzeros = 0;
158  for (LO jj = 0; jj < rowView.length; ++jj) {
159  LO lcid = rowView.colidx(jj);
160  GO gcid = Ain->getColMap()->getGlobalElement(lcid);
161  auto val = rowView.value(jj);
162  bool isInMap2 = dropMap1->isNodeGlobalElement(gcid);
163 
164  if (isInMap == isInMap2) {
165  indout[nNonzeros] = gcid;
166  valout[nNonzeros] = val;
167  nNonzeros++;
168  }
169  }
170  indout.resize(nNonzeros);
171  valout.resize(nNonzeros);
172 
173  Aout->insertGlobalValues(Ain->getRowMap()->getGlobalElement(row), indout.view(0, indout.size()), valout.view(0, valout.size()));
174  }
175 
176  Aout->fillComplete(Ain->getDomainMap(), Ain->getRangeMap());
177 
178  // copy block size information
179  Aout->SetFixedBlockSize(Ain->GetFixedBlockSize());
180 
181  GetOStream(Statistics0, 0) << "Nonzeros in A (input): " << Ain->getGlobalNumEntries() << ", Nonzeros after filtering A: " << Aout->getGlobalNumEntries() << std::endl;
182 
183  Set(currentLevel, "A", Aout);
184 } // BuildBasedOnBlockmap
185 
186 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
188  FactoryMonitor m(*this, "Matrix filtering (segregation, map-pair)", currentLevel);
189 
190  RCP<Matrix> Ain = Get<RCP<Matrix>>(currentLevel, "A");
191 
192  // fetch maps from level
193  RCP<const Map> dropMap1 = Teuchos::null;
194  RCP<const Map> dropMap2 = Teuchos::null;
195 
196  const std::string dropMap1Name = "dropMap1";
197  const std::string dropMap2Name = "dropMap2";
198 
199  if (currentLevel.GetLevelID() == 0) {
200  dropMap1 = currentLevel.Get<RCP<const Map>>(dropMap1Name, NoFactory::get());
201  dropMap2 = currentLevel.Get<RCP<const Map>>(dropMap2Name, NoFactory::get());
202  GetOStream(Statistics0) << "User provided dropMap1 \"" << dropMap1Name << "\": length dimension=" << dropMap1->getGlobalNumElements() << std::endl;
203  GetOStream(Statistics0) << "User provided dropMap2 \"" << dropMap2Name << "\": length dimension=" << dropMap2->getGlobalNumElements() << std::endl;
204  } else {
205  dropMap1 = Get<RCP<const Map>>(currentLevel, dropMap1Name);
206  dropMap2 = Get<RCP<const Map>>(currentLevel, dropMap2Name);
207  }
208 
209  TEUCHOS_ASSERT(!dropMap1.is_null());
210  TEUCHOS_ASSERT(!dropMap2.is_null());
211 
212  // create new empty Operator
213  Teuchos::RCP<Matrix> Aout = MatrixFactory::Build(Ain->getRowMap(), Ain->getGlobalMaxNumRowEntries());
214 
215  // import the dropping information from other procs for off Rank entries
216  Teuchos::RCP<const Map> finalDropMap1 = Teuchos::null;
217  Teuchos::RCP<const Map> finalDropMap2 = Teuchos::null;
218 
219  finalDropMap1 = MueLu::importOffRankDroppingInfo(dropMap1, Ain);
220  finalDropMap2 = MueLu::importOffRankDroppingInfo(dropMap2, Ain);
221 
222  // Start copying the matrix row by row and dropping any entries that are contained as a combination of entries of
223  // dropMap1 and dropMap2
224  size_t numLocalMatrixRows = Ain->getLocalNumRows();
225 
226  for (size_t row = 0; row < numLocalMatrixRows; row++) {
227  GO grid = Ain->getRowMap()->getGlobalElement(row); // global row id
228  bool rowIsInMap1 = finalDropMap1->isNodeGlobalElement(grid);
229  bool rowIsInMap2 = finalDropMap2->isNodeGlobalElement(grid);
230 
231  // extract row information from input matrix
232  auto lclMat = Ain->getLocalMatrixHost();
233  auto rowView = lclMat.row(row);
234 
235  // just copy all values in output
236  Teuchos::ArrayRCP<GO> indout(rowView.length, Teuchos::ScalarTraits<GO>::zero());
237  Teuchos::ArrayRCP<SC> valout(rowView.length, Teuchos::ScalarTraits<SC>::zero());
238 
239  size_t nNonzeros = 0;
240  for (LO jj = 0; jj < rowView.length; ++jj) {
241  LO lcid = rowView.colidx(jj);
242  GO gcid = Ain->getColMap()->getGlobalElement(lcid); // global column id
243  auto val = rowView.value(jj);
244  bool colIsInMap1 = finalDropMap1->isNodeGlobalElement(gcid);
245  bool colIsInMap2 = finalDropMap2->isNodeGlobalElement(gcid);
246 
247  if ((rowIsInMap1 && colIsInMap2) || (rowIsInMap2 && colIsInMap1)) {
248  // do nothing == drop this entry
249  } else {
250  indout[nNonzeros] = gcid;
251  valout[nNonzeros] = val;
252  nNonzeros++;
253  }
254  }
255  indout.resize(nNonzeros);
256  valout.resize(nNonzeros);
257  Aout->insertGlobalValues(Ain->getRowMap()->getGlobalElement(row), indout.view(0, indout.size()), valout.view(0, valout.size()));
258  }
259 
260  Aout->fillComplete(Ain->getDomainMap(), Ain->getRangeMap());
261 
262  // copy block size information
263  Aout->SetFixedBlockSize(Ain->GetFixedBlockSize());
264 
265  GetOStream(Statistics0, 0) << "Nonzeros in A (input): " << Ain->getGlobalNumEntries() << ", Nonzeros after filtering A: " << Aout->getGlobalNumEntries() << std::endl;
266 
267  currentLevel.Set("A", Aout, this);
268 } // BuildBasedOnMapPair
269 
270 } // namespace MueLu
271 
272 #endif // MUELU_SEGREGATEDAFACTORY_DEF_HPP
GlobalOrdinal GO
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
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.
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:99
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:76
#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