MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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_ */
Exception indicating invalid cast attempted.
MueLu::DefaultLocalOrdinal LocalOrdinal
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access). Usage: Level-&gt;Get&lt; RCP&lt;Matrix&gt; &gt;(&quot;A&quot;, factory) if factory == NULL =&gt; use default factory.
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.
bool CheckForUserSpecifiedBlockInfo(bool bRange, std::vector< size_t > &stridingInfo, LocalOrdinal &stridedBlockId) const
void DeclareInput(Level &currentLevel) const
Specifies the data that this class needs, and the factories that generate that data.
void Build(Level &currentLevel) const
Build an object with this factory.
Print even more statistics.
bool isParameter(const std::string &name) const
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
RCP< const ParameterList > GetValidParameterList() const
Input.
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
Exception throws to report errors in the internal logical of the program.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
bool is_null() const