MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_MatrixAnalysisFactory_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 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 
47 #ifndef MUELU_MATRIXANALYSISFACTORY_DEF_HPP_
48 #define MUELU_MATRIXANALYSISFACTORY_DEF_HPP_
49 
51 
52 #include <Xpetra_Map.hpp>
53 #include <Xpetra_StridedMap.hpp> // for nDofsPerNode...
54 #include <Xpetra_Vector.hpp>
55 #include <Xpetra_VectorFactory.hpp>
56 #include <Xpetra_Matrix.hpp>
57 
58 #include "MueLu_Level.hpp"
59 #include "MueLu_Utilities.hpp"
60 #include "MueLu_Monitor.hpp"
61 
62 namespace MueLu {
63 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
65 
66 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
68 
69 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
71  RCP<ParameterList> validParamList = rcp(new ParameterList());
72 
73  validParamList->set<RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the matrix A to be permuted.");
74 
75  return validParamList;
76 }
77 
78 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
80  Input(fineLevel, "A");
81 }
82 
83 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
85  FactoryMonitor m(*this, "MatrixAnalysis Factory ", fineLevel);
86 
87  Teuchos::RCP<Matrix> A = Get<Teuchos::RCP<Matrix> >(fineLevel, "A");
88  Teuchos::RCP<const Teuchos::Comm<int> > comm = A->getRangeMap()->getComm();
89 
90  // const ParameterList & pL = GetParameterList();
91 
92  // General information
93  {
94  GetOStream(Runtime0) << "~~~~~~~~ GENERAL INFORMATION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (Level " << fineLevel.GetLevelID() << ")" << std::endl;
95  GetOStream(Runtime0) << "A is a " << A->getRangeMap()->getGlobalNumElements() << " x " << A->getDomainMap()->getGlobalNumElements() << " matrix." << std::endl;
96 
97  if (A->IsView("stridedMaps") && Teuchos::rcp_dynamic_cast<const StridedMap>(A->getRowMap("stridedMaps")) != Teuchos::null) {
98  Teuchos::RCP<const StridedMap> strRowMap = Teuchos::rcp_dynamic_cast<const StridedMap>(A->getRowMap("stridedMaps"));
99  LocalOrdinal blockid = strRowMap->getStridedBlockId();
100  if (blockid > -1) {
101  std::vector<size_t> stridingInfo = strRowMap->getStridingData();
102  LO dofsPerNode = Teuchos::as<LocalOrdinal>(stridingInfo[blockid]);
103  GetOStream(Runtime0) << "Strided row: " << dofsPerNode << " dofs per node. Strided block id = " << blockid << std::endl;
104  } else {
105  GetOStream(Runtime0) << "Row: " << strRowMap->getFixedBlockSize() << " dofs per node" << std::endl;
106  }
107  }
108 
109  if (A->IsView("stridedMaps") && Teuchos::rcp_dynamic_cast<const StridedMap>(A->getColMap("stridedMaps")) != Teuchos::null) {
110  Teuchos::RCP<const StridedMap> strDomMap = Teuchos::rcp_dynamic_cast<const StridedMap>(A->getColMap("stridedMaps"));
111  LocalOrdinal blockid = strDomMap->getStridedBlockId();
112  if (blockid > -1) {
113  std::vector<size_t> stridingInfo = strDomMap->getStridingData();
114  LO dofsPerNode = Teuchos::as<LocalOrdinal>(stridingInfo[blockid]);
115  GetOStream(Runtime0) << "Strided column: " << dofsPerNode << " dofs per node. Strided block id = " << blockid << std::endl;
116  } else {
117  GetOStream(Runtime0) << "Column: " << strDomMap->getFixedBlockSize() << " dofs per node" << std::endl;
118  }
119  }
120 
121  GetOStream(Runtime0) << "A is distributed over " << comm->getSize() << " processors" << std::endl;
122 
123  // empty processors
124  std::vector<LO> lelePerProc(comm->getSize(), 0);
125  std::vector<LO> gelePerProc(comm->getSize(), 0);
126  lelePerProc[comm->getRank()] = A->getLocalNumEntries();
127  Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, comm->getSize(), &lelePerProc[0], &gelePerProc[0]);
128  if (comm->getRank() == 0) {
129  for (int i = 0; i < comm->getSize(); i++) {
130  if (gelePerProc[i] == 0) {
131  GetOStream(Runtime0) << "Proc " << i << " is empty." << std::endl;
132  }
133  }
134  }
135  }
136 
137  // Matrix diagonal
138  {
139  GetOStream(Runtime0) << "~~~~~~~~ MATRIX DIAGONAL ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (Level " << fineLevel.GetLevelID() << ")" << std::endl;
140  Teuchos::RCP<Vector> diagAVec = VectorFactory::Build(A->getRowMap(), true);
141  A->getLocalDiagCopy(*diagAVec);
142  Teuchos::ArrayRCP<const Scalar> diagAVecData = diagAVec->getData(0);
143  GlobalOrdinal lzerosOnDiagonal = 0;
144  GlobalOrdinal gzerosOnDiagonal = 0;
145  GlobalOrdinal lnearlyzerosOnDiagonal = 0;
146  GlobalOrdinal gnearlyzerosOnDiagonal = 0;
147  GlobalOrdinal lnansOnDiagonal = 0;
148  GlobalOrdinal gnansOnDiagonal = 0;
149 
150  for (size_t i = 0; i < diagAVec->getMap()->getLocalNumElements(); ++i) {
151  if (diagAVecData[i] == Teuchos::ScalarTraits<Scalar>::zero()) {
152  lzerosOnDiagonal++;
153  } else if (Teuchos::ScalarTraits<Scalar>::magnitude(diagAVecData[i]) < 1e-6) {
154  lnearlyzerosOnDiagonal++;
155  } else if (Teuchos::ScalarTraits<Scalar>::isnaninf(diagAVecData[i])) {
156  lnansOnDiagonal++;
157  }
158  }
159 
160  // sum up all entries in multipleColRequests over all processors
161  MueLu_sumAll(comm, lzerosOnDiagonal, gzerosOnDiagonal);
162  MueLu_sumAll(comm, lnearlyzerosOnDiagonal, gnearlyzerosOnDiagonal);
163  MueLu_sumAll(comm, lnansOnDiagonal, gnansOnDiagonal);
164 
165  if (gzerosOnDiagonal > 0) GetOStream(Runtime0) << "Found " << gzerosOnDiagonal << " zeros on diagonal of A" << std::endl;
166  if (gnearlyzerosOnDiagonal > 0) GetOStream(Runtime0) << "Found " << gnearlyzerosOnDiagonal << " entries with absolute value < 1.0e-6 on diagonal of A" << std::endl;
167  if (gnansOnDiagonal > 0) GetOStream(Runtime0) << "Found " << gnansOnDiagonal << " entries with NAN or INF on diagonal of A" << std::endl;
168  }
169 
170  // Diagonal dominance?
171  {
172  GetOStream(Runtime0) << "~~~~~~~~ DIAGONAL DOMINANCE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (Level " << fineLevel.GetLevelID() << ")" << std::endl;
173  // loop over all local rows in matrix A and keep diagonal entries if corresponding
174  // matrix rows are not contained in permRowMap
175  GlobalOrdinal lnumWeakDiagDomRows = 0;
176  GlobalOrdinal gnumWeakDiagDomRows = 0;
177  GlobalOrdinal lnumStrictDiagDomRows = 0;
178  GlobalOrdinal gnumStrictDiagDomRows = 0;
179  double worstRatio = 99999999.9;
180  for (size_t row = 0; row < A->getRowMap()->getLocalNumElements(); row++) {
181  GlobalOrdinal grow = A->getRowMap()->getGlobalElement(row);
182 
183  size_t nnz = A->getNumEntriesInLocalRow(row);
184 
185  // extract local row information from matrix
188  A->getLocalRowView(row, indices, vals);
189 
190  TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::as<size_t>(indices.size()) != nnz, Exceptions::RuntimeError, "MueLu::MatrixAnalysisFactory::Build: number of nonzeros not equal to number of indices? Error.");
191 
192  // find column entry with max absolute value
193  double norm1 = 0.0;
194  double normdiag = 0.0;
195  for (size_t j = 0; j < Teuchos::as<size_t>(indices.size()); j++) {
196  GO gcol = A->getColMap()->getGlobalElement(indices[j]);
197  if (gcol == grow)
198  normdiag = Teuchos::as<double>(Teuchos::ScalarTraits<Scalar>::magnitude(vals[j]));
199  else
200  norm1 += Teuchos::as<double>(Teuchos::ScalarTraits<Scalar>::magnitude(vals[j]));
201  }
202 
203  if (normdiag >= norm1)
204  lnumWeakDiagDomRows++;
205  else if (normdiag > norm1)
206  lnumStrictDiagDomRows++;
207 
208  if (norm1 != 0.0) {
209  if (normdiag / norm1 < worstRatio) worstRatio = normdiag / norm1;
210  }
211  }
212 
213  MueLu_sumAll(comm, lnumWeakDiagDomRows, gnumWeakDiagDomRows);
214  MueLu_sumAll(comm, lnumStrictDiagDomRows, gnumStrictDiagDomRows);
215 
216  GetOStream(Runtime0) << "A has " << gnumWeakDiagDomRows << "/" << A->getRangeMap()->getGlobalNumElements() << " weakly diagonal dominant rows. (" << Teuchos::as<Scalar>(gnumWeakDiagDomRows / A->getRangeMap()->getGlobalNumElements() * 100) << "%)" << std::endl;
217  GetOStream(Runtime0) << "A has " << gnumStrictDiagDomRows << "/" << A->getRangeMap()->getGlobalNumElements() << " strictly diagonal dominant rows. (" << Teuchos::as<Scalar>(gnumStrictDiagDomRows / A->getRangeMap()->getGlobalNumElements() * 100) << "%)" << std::endl;
218 
219  double gworstRatio;
220  Teuchos::reduceAll(*comm, Teuchos::REDUCE_MIN, comm->getSize(), &worstRatio, &gworstRatio);
221  GetOStream(Runtime0) << "The minimum of the ratio of diagonal element/ sum of off-diagonal elements is " << gworstRatio << ". Values about 1.0 are ok." << std::endl;
222  }
223 
225 
226  // multiply with one vector
227  {
228  GetOStream(Runtime0) << "~~~~~~~~ Av with one vector ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (Level " << fineLevel.GetLevelID() << ")" << std::endl;
229  Teuchos::RCP<Vector> ones = VectorFactory::Build(A->getDomainMap(), 1);
230  ones->putScalar(one);
231 
232  Teuchos::RCP<Vector> res1 = VectorFactory::Build(A->getRangeMap(), false);
233  A->apply(*ones, *res1, Teuchos::NO_TRANS, one, zero);
234  checkVectorEntries(res1, std::string("after applying the one vector to A"));
235  }
236 
237  {
238  GetOStream(Runtime0) << "~~~~~~~~ Av with random vector ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (Level " << fineLevel.GetLevelID() << ")" << std::endl;
239  Teuchos::RCP<Vector> randvec = VectorFactory::Build(A->getDomainMap(), 1);
240  randvec->randomize();
241 
242  Teuchos::RCP<Vector> resrand = VectorFactory::Build(A->getRangeMap(), false);
243  A->apply(*randvec, *resrand, Teuchos::NO_TRANS, one, zero);
244  checkVectorEntries(resrand, std::string("after applying random vector to A"));
245  }
246 
247  // apply Jacobi sweep
248  {
249  GetOStream(Runtime0) << "~~~~~~~~ Damped Jacobi sweep (one vector) ~~~~~~~~~~~~~~~~~~~~~~~ (Level " << fineLevel.GetLevelID() << ")" << std::endl;
250  Teuchos::RCP<Vector> ones = VectorFactory::Build(A->getDomainMap(), 1);
251  ones->putScalar(one);
252 
253  Teuchos::RCP<Vector> res1 = VectorFactory::Build(A->getRangeMap(), false);
254  A->apply(*ones, *res1, Teuchos::NO_TRANS, one, zero);
255  checkVectorEntries(res1, std::string("after applying one vector to A"));
256 
258  checkVectorEntries(invDiag, std::string("in invDiag"));
259 
260  Teuchos::RCP<Vector> res2 = VectorFactory::Build(A->getRangeMap(), false);
261  res2->elementWiseMultiply(0.8, *invDiag, *res1, 0.0);
262  checkVectorEntries(res2, std::string("after scaling Av with invDiag (with v the one vector)"));
263  res2->update(1.0, *ones, -1.0);
264 
265  checkVectorEntries(res2, std::string("after applying one damped Jacobi sweep (with one vector)"));
266  }
267 
268  // apply Jacobi sweep
269  {
270  GetOStream(Runtime0) << "~~~~~~~~ Damped Jacobi sweep (random vector) ~~~~~~~~~~~~~~~~~~~~ (Level " << fineLevel.GetLevelID() << ")" << std::endl;
271  Teuchos::RCP<Vector> ones = VectorFactory::Build(A->getDomainMap(), 1);
272  ones->randomize();
273 
274  Teuchos::RCP<Vector> res1 = VectorFactory::Build(A->getRangeMap(), false);
275  A->apply(*ones, *res1, Teuchos::NO_TRANS, one, zero);
276  checkVectorEntries(res1, std::string("after applying a random vector to A"));
277 
279  checkVectorEntries(invDiag, std::string("in invDiag"));
280 
281  Teuchos::RCP<Vector> res2 = VectorFactory::Build(A->getRangeMap(), false);
282  res2->elementWiseMultiply(0.8, *invDiag, *res1, 0.0);
283  checkVectorEntries(res2, std::string("after scaling Av with invDiag (with v a random vector)"));
284  res2->update(1.0, *ones, -1.0);
285 
286  checkVectorEntries(res2, std::string("after applying one damped Jacobi sweep (with v a random vector)"));
287  }
288 
289  GetOStream(Runtime0) << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (Level " << fineLevel.GetLevelID() << ")" << std::endl;
290 }
291 
292 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
295  Teuchos::RCP<const Teuchos::Comm<int> > comm = vec->getMap()->getComm();
296  Teuchos::ArrayRCP<const Scalar> vecData = vec->getData(0);
297  GO lzeros = 0;
298  GO gzeros = 0;
299  GO lnans = 0;
300  GO gnans = 0;
301 
302  for (size_t i = 0; i < vec->getMap()->getLocalNumElements(); ++i) {
303  if (vecData[i] == zero) {
304  lzeros++;
305  } else if (Teuchos::ScalarTraits<Scalar>::isnaninf(vecData[i])) {
306  lnans++;
307  }
308  }
309 
310  // sum up all entries in multipleColRequests over all processors
311  MueLu_sumAll(comm, lzeros, gzeros);
312  MueLu_sumAll(comm, lnans, gnans);
313 
314  if (gzeros > 0) GetOStream(Runtime0) << "Found " << gzeros << " zeros " << info << std::endl;
315  if (gnans > 0) GetOStream(Runtime0) << "Found " << gnans << " entries " << info << std::endl;
316 }
317 
318 } // namespace MueLu
319 
320 #endif /* MUELU_MATRIXANALYSISFACTORY_DEF_HPP_ */
#define MueLu_sumAll(rcpComm, in, out)
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
MueLu::DefaultLocalOrdinal LocalOrdinal
GlobalOrdinal GO
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)
size_type size() const
LocalOrdinal LO
One-liner description of what is happening.
void checkVectorEntries(const Teuchos::RCP< Vector > &vec, std::string info) const
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
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
static RCP< Vector > GetMatrixDiagonalInverse(const Matrix &A, Magnitude tol=Teuchos::ScalarTraits< Scalar >::eps()*100, Scalar valReplacement=Teuchos::ScalarTraits< Scalar >::zero(), const bool doLumped=false)
Extract Matrix Diagonal.
static magnitudeType magnitude(T a)
Scalar SC
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Specifies the data that this class needs, and the factories that generate that data.
Exception throws to report errors in the internal logical of the program.