MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_BlockedRAPFactory_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 #ifndef MUELU_BLOCKEDRAPFACTORY_DEF_HPP
47 #define MUELU_BLOCKEDRAPFACTORY_DEF_HPP
48 
50 #include <Xpetra_MatrixFactory.hpp>
51 #include <Xpetra_Matrix.hpp>
52 #include <Xpetra_MatrixMatrix.hpp>
53 
55 
56 #include "MueLu_MasterList.hpp"
57 #include "MueLu_Monitor.hpp"
58 #include "MueLu_PerfUtils.hpp"
60 
61 namespace MueLu {
62 
63 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
65  : checkAc_(false)
66  , repairZeroDiagonals_(false) {}
67 
68 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
70  RCP<ParameterList> validParamList = rcp(new ParameterList());
71 
72 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
73  SET_VALID_ENTRY("transpose: use implicit");
74 #undef SET_VALID_ENTRY
75  validParamList->set<RCP<const FactoryBase> >("A", null, "Generating factory of the matrix A used during the prolongator smoothing process");
76  validParamList->set<RCP<const FactoryBase> >("P", null, "Prolongator factory");
77  validParamList->set<RCP<const FactoryBase> >("R", null, "Restrictor factory");
78 
79  return validParamList;
80 }
81 
82 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
84  const Teuchos::ParameterList &pL = GetParameterList();
85  if (pL.get<bool>("transpose: use implicit") == false)
86  Input(coarseLevel, "R");
87 
88  Input(fineLevel, "A");
89  Input(coarseLevel, "P");
90 
91  // call DeclareInput of all user-given transfer factories
92  for (std::vector<RCP<const FactoryBase> >::const_iterator it = transferFacts_.begin(); it != transferFacts_.end(); ++it)
93  (*it)->CallDeclareInput(coarseLevel);
94 }
95 
96 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
97 void BlockedRAPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(Level &fineLevel, Level &coarseLevel) const { // FIXME make fineLevel const!!
98  FactoryMonitor m(*this, "Computing Ac (block)", coarseLevel);
99 
100  const ParameterList &pL = GetParameterList();
101 
102  RCP<Matrix> A = Get<RCP<Matrix> >(fineLevel, "A");
103  RCP<Matrix> P = Get<RCP<Matrix> >(coarseLevel, "P");
104 
105  RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(A);
106  RCP<BlockedCrsMatrix> bP = rcp_dynamic_cast<BlockedCrsMatrix>(P);
107  TEUCHOS_TEST_FOR_EXCEPTION(bA.is_null() || bP.is_null(), Exceptions::BadCast, "Matrices A and P must be of type BlockedCrsMatrix.");
108 
111  {
112  SubFactoryMonitor subM(*this, "MxM: A x P", coarseLevel);
113 
114  // Triple matrix product for BlockedCrsMatrixClass
115  TEUCHOS_TEST_FOR_EXCEPTION((bA->Cols() != bP->Rows()), Exceptions::BadCast,
116  "Block matrix dimensions do not match: "
117  "A is "
118  << bA->Rows() << "x" << bA->Cols() << "P is " << bP->Rows() << "x" << bP->Cols());
119 
120  bAP = MatrixMatrix::TwoMatrixMultiplyBlock(*bA, false, *bP, false, GetOStream(Statistics2), true, true);
121  }
122 
123  // If we do not modify matrix later, allow optimization of storage.
124  // This is necessary for new faster Epetra MM kernels.
125  bool doOptimizeStorage = !checkAc_;
126 
127  const bool doTranspose = true;
128  const bool doFillComplete = true;
129  if (pL.get<bool>("transpose: use implicit") == true) {
130  SubFactoryMonitor m2(*this, "MxM: P' x (AP) (implicit)", coarseLevel);
131  bAc = MatrixMatrix::TwoMatrixMultiplyBlock(*bP, doTranspose, *bAP, !doTranspose, GetOStream(Statistics2), doFillComplete, doOptimizeStorage);
132 
133  } else {
134  RCP<Matrix> R = Get<RCP<Matrix> >(coarseLevel, "R");
135  RCP<BlockedCrsMatrix> bR = rcp_dynamic_cast<BlockedCrsMatrix>(R);
136  TEUCHOS_TEST_FOR_EXCEPTION(bR.is_null(), Exceptions::BadCast, "Matrix R must be of type BlockedCrsMatrix.");
137 
138  TEUCHOS_TEST_FOR_EXCEPTION(bA->Rows() != bR->Cols(), Exceptions::BadCast,
139  "Block matrix dimensions do not match: "
140  "R is "
141  << bR->Rows() << "x" << bR->Cols() << "A is " << bA->Rows() << "x" << bA->Cols());
142 
143  SubFactoryMonitor m2(*this, "MxM: R x (AP) (explicit)", coarseLevel);
144  bAc = MatrixMatrix::TwoMatrixMultiplyBlock(*bR, !doTranspose, *bAP, !doTranspose, GetOStream(Statistics2), doFillComplete, doOptimizeStorage);
145  }
146 
147  if (checkAc_)
148  CheckMainDiagonal(bAc);
149 
150  GetOStream(Statistics1) << PerfUtils::PrintMatrixInfo(*bAc, "Ac (blocked)");
151 
152  Set<RCP<Matrix> >(coarseLevel, "A", bAc);
153 
154  if (transferFacts_.begin() != transferFacts_.end()) {
155  SubFactoryMonitor m1(*this, "Projections", coarseLevel);
156 
157  // call Build of all user-given transfer factories
158  for (std::vector<RCP<const FactoryBase> >::const_iterator it = transferFacts_.begin(); it != transferFacts_.end(); ++it) {
159  RCP<const FactoryBase> fac = *it;
160 
161  GetOStream(Runtime0) << "BlockRAPFactory: call transfer factory: " << fac->description() << std::endl;
162 
163  fac->CallBuild(coarseLevel);
164 
165  // AP (11/11/13): I am not sure exactly why we need to call Release, but we do need it to get rid
166  // of dangling data for CoordinatesTransferFactory
167  coarseLevel.Release(*fac);
168  }
169  }
170 }
171 
172 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
174  RCP<Matrix> c00 = bAc->getMatrix(0, 0);
175  RCP<Matrix> Aout = MatrixFactory::Build(c00->getRowMap(), c00->getGlobalMaxNumRowEntries());
176 
177  RCP<Vector> diagVec = VectorFactory::Build(c00->getRowMap());
178  c00->getLocalDiagCopy(*diagVec);
179  ArrayRCP<SC> diagVal = diagVec->getDataNonConst(0);
180 
181  // loop over local rows
182  for (size_t row = 0; row < c00->getLocalNumRows(); row++) {
183  // get global row id
184  GO grid = c00->getRowMap()->getGlobalElement(row); // global row id
185 
186  ArrayView<const LO> indices;
187  ArrayView<const SC> vals;
188  c00->getLocalRowView(row, indices, vals);
189 
190  // just copy all values in output
193 
194  // just copy values
195  for (size_t i = 0; i < as<size_t>(indices.size()); i++) {
196  GO gcid = c00->getColMap()->getGlobalElement(indices[i]); // LID -> GID (column)
197  indout[i] = gcid;
198  valout[i] = vals[i];
199  }
200 
201  Aout->insertGlobalValues(grid, indout.view(0, indout.size()), valout.view(0, valout.size()));
202  if (diagVal[row] == Teuchos::ScalarTraits<SC>::zero() && repairZeroDiagonals) {
203  // always overwrite diagonal entry
204  Aout->insertGlobalValues(grid, Teuchos::tuple<GO>(grid), Teuchos::tuple<SC>(1.0));
205  }
206  }
207 
208  Aout->fillComplete(c00->getDomainMap(), c00->getRangeMap());
209 
210  bAc->setMatrix(0, 0, Aout);
211 }
212 
213 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
215  // check if it's a TwoLevelFactoryBase based transfer factory
216  TEUCHOS_TEST_FOR_EXCEPTION(rcp_dynamic_cast<const TwoLevelFactoryBase>(factory) == Teuchos::null, Exceptions::BadCast,
217  "Transfer factory is not derived from TwoLevelFactoryBase. This is very strange. "
218  "(Note: you can remove this exception if there's a good reason for)");
219  transferFacts_.push_back(factory);
220 }
221 
222 } // namespace MueLu
223 
224 #define MUELU_BLOCKEDRAPFACTORY_SHORT
225 #endif // MUELU_BLOCKEDRAPFACTORY_DEF_HPP
226 
227 // TODO add plausibility check
228 // TODO add CheckMainDiagonal for Blocked operator
229 // Avoid copying block matrix!
230 // create new empty Operator
Exception indicating invalid cast attempted.
virtual void CallBuild(Level &requestedLevel) const =0
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)
Print more statistics.
size_type size() const
One-liner description of what is happening.
RCP< const ParameterList > GetValidParameterList() const override
Return a const parameter list of valid parameters that setParameterList() will accept.
Print even more statistics.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
void Build(Level &fineLevel, Level &coarseLevel) const override
Build an object with this factory.
void AddTransferFactory(const RCP< const FactoryBase > &factory)
Add transfer factory in the end of list of transfer factories in RepartitionAcFactory.
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
static void CheckMainDiagonal(RCP< BlockedCrsMatrix > &bAc, bool repairZeroDiagonals=false)
#define SET_VALID_ENTRY(name)
void DeclareInput(Level &fineLevel, Level &coarseLevel) const override
Input.
virtual std::string description() const
Return a simple one-line description of this object.