MueLu  Version of the Day
MueLu_SubBlockAFactory_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  * MueLu_SubBlockAFactory_def.hpp
48  *
49  * Created on: 02.01.2012
50  * Author: tobias
51  */
52 
53 #ifndef MUELU_SUBBLOCKAFACTORY_DEF_HPP_
54 #define MUELU_SUBBLOCKAFACTORY_DEF_HPP_
55 
56 
58 
59 #include <Xpetra_BlockedCrsMatrix.hpp>
60 #include <Xpetra_MapExtractor.hpp>
61 #include <Xpetra_Matrix.hpp>
62 #include <Xpetra_StridedMapFactory.hpp>
63 
64 #include "MueLu_Level.hpp"
65 #include "MueLu_Monitor.hpp"
66 
67 namespace MueLu {
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", MueLu::NoFactory::getRCP(), "Generating factory for A.");
74  validParamList->set< int > ("block row", 0, "Block row of subblock matrix A");
75  validParamList->set< int > ("block col", 0, "Block column of subblock matrix A");
76 
77  validParamList->set< std::string > ("Range map: Striding info", "{}", "Striding information for range map");
78  validParamList->set< LocalOrdinal > ("Range map: Strided block id", -1, "Strided block id for range map" );
79  validParamList->set< std::string > ("Domain map: Striding info", "{}", "Striding information for domain map");
80  validParamList->set< LocalOrdinal > ("Domain map: Strided block id", -1, "Strided block id for domain map" );
81 
82  return validParamList;
83  }
84 
85  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
87  Input(currentLevel, "A");
88  }
89 
90  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
92  FactoryMonitor m(*this, "Build", currentLevel);
93 
94  const ParameterList& pL = GetParameterList();
95  size_t row = Teuchos::as<size_t>(pL.get<int>("block row"));
96  size_t col = Teuchos::as<size_t>(pL.get<int>("block col"));
97 
98  RCP<Matrix> Ain = currentLevel.Get< RCP<Matrix> >("A",this->GetFactory("A").get());
99  RCP<BlockedCrsMatrix> A = rcp_dynamic_cast<BlockedCrsMatrix>(Ain);
100 
101  TEUCHOS_TEST_FOR_EXCEPTION(A.is_null(), Exceptions::BadCast, "Input matrix A is not a BlockedCrsMatrix.");
102  TEUCHOS_TEST_FOR_EXCEPTION(row > A->Rows(), Exceptions::RuntimeError, "row [" << row << "] > A.Rows() [" << A->Rows() << "].");
103  TEUCHOS_TEST_FOR_EXCEPTION(col > A->Cols(), Exceptions::RuntimeError, "col [" << col << "] > A.Cols() [" << A->Cols() << "].");
104 
105  // get sub-matrix
106  RCP<Matrix> Op = A->getMatrix(row, col);
107 
108  // Check if it is a BlockedCrsMatrix object
109  // If it is a BlockedCrsMatrix object (most likely a ReorderedBlockedCrsMatrix)
110  // we have to distinguish whether it is a 1x1 leaf block in the ReorderedBlockedCrsMatrix
111  // or a nxm block. If it is a 1x1 leaf block, we "unpack" it and return the underlying
112  // CrsMatrixWrap object.
113  RCP<BlockedCrsMatrix> bOp = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Op);
114  if (bOp != Teuchos::null) {
115  // check if it is a 1x1 leaf block
116  if (bOp->Rows() == 1 && bOp->Cols() == 1) {
117  // return the unwrapped CrsMatrixWrap object underneath
118  Op = bOp->getCrsMatrix();
119  TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<CrsMatrixWrap>(Op) == Teuchos::null, Exceptions::BadCast, "SubBlockAFactory::Build: sub block A[" << row << "," << col << "] must be a single block CrsMatrixWrap object!");
120  } else {
121  // If it is a regular nxm blocked operator, just return it.
122  // We do not set any kind of striding or blocking information as this
123  // usually would not make sense for general blocked operators
124  GetOStream(Statistics1) << "A(" << row << "," << col << ") is a " << bOp->Rows() << "x" << bOp->Cols() << " block matrix" << std::endl;
125  GetOStream(Statistics2) << "with altogether " << bOp->getGlobalNumRows() << "x" << bOp->getGlobalNumCols() << " rows and columns." << std::endl;
126  currentLevel.Set("A", Op, this);
127  return;
128  }
129  }
130 
131  // The sub-block is not a BlockedCrsMatrix object, that is, we expect
132  // it to be of type CrsMatrixWrap allowing direct access to the corresponding
133  // data. For a single block CrsMatrixWrap type matrix we can/should set the
134  // corresponding striding/blocking information for the algorithms to work
135  // properly
136  //
137  // TAW: In fact, a 1x1 BlockedCrsMatrix object also allows to access the data
138  // directly, but this feature is nowhere really used in the algorithms.
139  // So let's keep checking for the CrsMatrixWrap class to avoid skrewing
140  // things up
141  //
142  TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<CrsMatrixWrap>(Op) == Teuchos::null, Exceptions::BadCast, "SubBlockAFactory::Build: sub block A[" << row << "," << col << "] is NOT a BlockedCrsMatrix but also NOT a CrsMatrixWrap object? This cannot be.");
143 
144  // strided maps for range and domain map of sub matrix
145  RCP<const StridedMap> srangeMap = Teuchos::null;
146  RCP<const StridedMap> sdomainMap = Teuchos::null;
147 
148  // check for user-specified striding information from XML file
149 
150  std::vector<size_t> rangeStridingInfo;
151  std::vector<size_t> domainStridingInfo;
152  LocalOrdinal rangeStridedBlockId = 0;
153  LocalOrdinal domainStridedBlockId = 0;
154  bool bRangeUserSpecified = CheckForUserSpecifiedBlockInfo(true, rangeStridingInfo, rangeStridedBlockId);
155  bool bDomainUserSpecified = CheckForUserSpecifiedBlockInfo(false, domainStridingInfo, domainStridedBlockId);
156  TEUCHOS_TEST_FOR_EXCEPTION(bRangeUserSpecified != bDomainUserSpecified, Exceptions::RuntimeError, "MueLu::SubBlockAFactory[" << row << "," << col << "]: the user has to specify either both domain and range map or none.");
157 
158  // extract map information from MapExtractor
159  RCP<const MapExtractor> rangeMapExtractor = A->getRangeMapExtractor();
160  RCP<const MapExtractor> domainMapExtractor = A->getDomainMapExtractor();
161 
162  RCP<const Map> rangeMap = rangeMapExtractor ->getMap(row);
163  RCP<const Map> domainMap = domainMapExtractor->getMap(col);
164 
165  // use user-specified striding information if available. Otherwise try to use internal striding information from the submaps!
166  if(bRangeUserSpecified) srangeMap = Teuchos::rcp(new StridedMap(rangeMap,rangeStridingInfo,rangeMap->getIndexBase(),rangeStridedBlockId,0));
167  else srangeMap = rcp_dynamic_cast<const StridedMap>(rangeMap);
168 
169  if(bDomainUserSpecified) sdomainMap = Teuchos::rcp(new StridedMap(domainMap,domainStridingInfo,domainMap->getIndexBase(),domainStridedBlockId,0));
170  else sdomainMap = rcp_dynamic_cast<const StridedMap>(domainMap);
171 
172  // In case that both user-specified and internal striding information from the submaps
173  // does not contain valid striding information, try to extract it from the global maps
174  // in the map extractor.
175  if (srangeMap.is_null()) {
176  RCP<const Map> fullRangeMap = rangeMapExtractor->getFullMap();
177  RCP<const StridedMap> sFullRangeMap = rcp_dynamic_cast<const StridedMap>(fullRangeMap);
178  TEUCHOS_TEST_FOR_EXCEPTION(sFullRangeMap.is_null(), Exceptions::BadCast, "Full rangeMap is not a strided map.");
179 
180  std::vector<size_t> stridedData = sFullRangeMap->getStridingData();
181  if (stridedData.size() == 1 && row > 0) {
182  // We have block matrices. use striding block information 0
183  srangeMap = StridedMapFactory::Build(rangeMap, stridedData, 0, sFullRangeMap->getOffset());
184 
185  } else {
186  // We have strided matrices. use striding information of the corresponding block
187  srangeMap = StridedMapFactory::Build(rangeMap, stridedData, row, sFullRangeMap->getOffset());
188  }
189  }
190 
191  if (sdomainMap.is_null()) {
192  RCP<const Map> fullDomainMap = domainMapExtractor->getFullMap();
193  RCP<const StridedMap> sFullDomainMap = rcp_dynamic_cast<const StridedMap>(fullDomainMap);
194  TEUCHOS_TEST_FOR_EXCEPTION(sFullDomainMap.is_null(), Exceptions::BadCast, "Full domainMap is not a strided map");
195 
196  std::vector<size_t> stridedData = sFullDomainMap->getStridingData();
197  if (stridedData.size() == 1 && col > 0) {
198  // We have block matrices. use striding block information 0
199  sdomainMap = StridedMapFactory::Build(domainMap, stridedData, 0, sFullDomainMap->getOffset());
200 
201  } else {
202  // We have strided matrices. use striding information of the corresponding block
203  sdomainMap = StridedMapFactory::Build(domainMap, stridedData, col, sFullDomainMap->getOffset());
204  }
205  }
206 
207  TEUCHOS_TEST_FOR_EXCEPTION(srangeMap.is_null(), Exceptions::BadCast, "rangeMap " << row << " is not a strided map.");
208  TEUCHOS_TEST_FOR_EXCEPTION(sdomainMap.is_null(), Exceptions::BadCast, "domainMap " << col << " is not a strided map.");
209 
210  GetOStream(Statistics1) << "A(" << row << "," << col << ") is a single block and has strided maps:"
211  << "\n range map fixed block size = " << srangeMap ->getFixedBlockSize() << ", strided block id = " << srangeMap ->getStridedBlockId()
212  << "\n domain map fixed block size = " << sdomainMap->getFixedBlockSize() << ", strided block id = " << sdomainMap->getStridedBlockId() << std::endl;
213  GetOStream(Statistics2) << "A(" << row << "," << col << ") has " << Op->getGlobalNumRows() << "x" << Op->getGlobalNumCols() << " rows and columns." << std::endl;
214 
215  // TODO do we really need that? we moved the code to getMatrix...
216  if (Op->IsView("stridedMaps") == true)
217  Op->RemoveView("stridedMaps");
218  Op->CreateView("stridedMaps", srangeMap, sdomainMap);
219 
220  TEUCHOS_TEST_FOR_EXCEPTION(Op->IsView("stridedMaps") == false, Exceptions::RuntimeError, "Failed to set \"stridedMaps\" view.");
221 
222  currentLevel.Set("A", Op, this);
223  }
224 
225  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
226  bool SubBlockAFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::CheckForUserSpecifiedBlockInfo(bool bRange, std::vector<size_t>& stridingInfo, LocalOrdinal& stridedBlockId) const {
227  const ParameterList & pL = GetParameterList();
228 
229  if(bRange == true)
230  stridedBlockId = pL.get<LocalOrdinal>("Range map: Strided block id");
231  else
232  stridedBlockId = pL.get<LocalOrdinal>("Domain map: Strided block id");
233 
234  // read in stridingInfo from parameter list and fill the internal member variable
235  // read the data only if the parameter "Striding info" exists and is non-empty
236  std::string str;
237  if(bRange == true) str = std::string("Range map: Striding info");
238  else str = std::string("Domain map: Striding info");
239  if(pL.isParameter(str)) {
240  std::string strStridingInfo = pL.get<std::string>(str);
241  if(strStridingInfo.empty() == false) {
242  Teuchos::Array<size_t> arrayVal = Teuchos::fromStringToArray<size_t>(strStridingInfo);
243  stridingInfo = Teuchos::createVector(arrayVal);
244  }
245  }
246 
247  if(stridingInfo.size() > 0) return true;
248  return false;
249  }
250 
251 } // namespace MueLu
252 
253 #endif /* MUELU_SUBBLOCKAFACTORY_DEF_HPP_ */
MueLu::DefaultLocalOrdinal LocalOrdinal
Exception indicating invalid cast attempted.
Exception throws to report errors in the internal logical of the program.
Timer to be used in factories. Similar to Monitor but with additional timers.
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
static const RCP< const NoFactory > getRCP()
Static Get() functions.
void DeclareInput(Level &currentLevel) const
Specifies the data that this class needs, and the factories that generate that data.
bool CheckForUserSpecifiedBlockInfo(bool bRange, std::vector< size_t > &stridingInfo, LocalOrdinal &stridedBlockId) const
RCP< const ParameterList > GetValidParameterList() const
Input.
void Build(Level &currentLevel) const
Build an object with this factory.
Namespace for MueLu classes and methods.
@ Statistics2
Print even more statistics.
@ Statistics1
Print more statistics.