MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_AmalgamationFactory_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_AMALGAMATIONFACTORY_DEF_HPP
47 #define MUELU_AMALGAMATIONFACTORY_DEF_HPP
48 
49 #include <Xpetra_Matrix.hpp>
50 
52 
53 #include "MueLu_Level.hpp"
54 #include "MueLu_AmalgamationInfo.hpp"
55 #include "MueLu_Monitor.hpp"
56 
57 namespace MueLu {
58 
59 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
61  RCP<ParameterList> validParamList = rcp(new ParameterList());
62  validParamList->set<RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the matrix A");
63  return validParamList;
64 }
65 
66 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
68  Input(currentLevel, "A"); // sub-block from blocked A
69 }
70 
71 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
73  FactoryMonitor m(*this, "Build", currentLevel);
74 
75  RCP<Matrix> A = Get<RCP<Matrix> >(currentLevel, "A");
76 
77  /* NOTE: storageblocksize (from GetStorageBlockSize()) is the size of a block in the chosen storage scheme.
78  fullblocksize is the number of storage blocks that must kept together during the amalgamation process.
79 
80  Both of these quantities may be different than numPDEs (from GetFixedBlockSize()), but the following must always hold:
81 
82  numPDEs = fullblocksize * storageblocksize.
83 
84  If numPDEs==1
85  Matrix is point storage (classical CRS storage). storageblocksize=1 and fullblocksize=1
86  No other values makes sense.
87 
88  If numPDEs>1
89  If matrix uses point storage, then storageblocksize=1 and fullblockssize=numPDEs.
90  If matrix uses block storage, with block size of n, then storageblocksize=n, and fullblocksize=numPDEs/n.
91  Thus far, only storageblocksize=numPDEs and fullblocksize=1 has been tested.
92  */
93 
94  LO fullblocksize = 1; // block dim for fixed size blocks
95  GO offset = 0; // global offset of dof gids
96  LO blockid = -1; // block id in strided map
97  LO nStridedOffset = 0; // DOF offset for strided block id "blockid" (default = 0)
98  LO stridedblocksize = fullblocksize; // size of strided block id "blockid" (default = fullblocksize, only if blockid!=-1 stridedblocksize <= fullblocksize)
99  LO storageblocksize = A->GetStorageBlockSize();
100  // GO indexBase = A->getRowMap()->getIndexBase(); // index base for maps (unused)
101 
102  // 1) check for blocking/striding information
103 
104  if (A->IsView("stridedMaps") && Teuchos::rcp_dynamic_cast<const StridedMap>(A->getRowMap("stridedMaps")) != Teuchos::null) {
105  Xpetra::viewLabel_t oldView = A->SwitchToView("stridedMaps"); // NOTE: "stridedMaps are always non-overlapping (correspond to range and domain maps!)
106  RCP<const StridedMap> stridedRowMap = Teuchos::rcp_dynamic_cast<const StridedMap>(A->getRowMap());
107  TEUCHOS_TEST_FOR_EXCEPTION(stridedRowMap == Teuchos::null, Exceptions::BadCast, "MueLu::CoalesceFactory::Build: cast to strided row map failed.");
108  fullblocksize = stridedRowMap->getFixedBlockSize();
109  offset = stridedRowMap->getOffset();
110  blockid = stridedRowMap->getStridedBlockId();
111 
112  if (blockid > -1) {
113  std::vector<size_t> stridingInfo = stridedRowMap->getStridingData();
114  for (size_t j = 0; j < Teuchos::as<size_t>(blockid); j++)
115  nStridedOffset += stridingInfo[j];
116  stridedblocksize = Teuchos::as<LocalOrdinal>(stridingInfo[blockid]);
117 
118  } else {
119  stridedblocksize = fullblocksize;
120  }
121  // Correct for the storageblocksize
122  // NOTE: Before this point fullblocksize is actually numPDEs
123  TEUCHOS_TEST_FOR_EXCEPTION(fullblocksize % storageblocksize != 0, Exceptions::RuntimeError, "AmalgamationFactory: fullblocksize needs to be a multiple of A->GetStorageBlockSize()");
124  fullblocksize /= storageblocksize;
125  stridedblocksize /= storageblocksize;
126 
127  oldView = A->SwitchToView(oldView);
128  GetOStream(Runtime1) << "AmalagamationFactory::Build():"
129  << " found fullblocksize=" << fullblocksize << " and stridedblocksize=" << stridedblocksize << " from strided maps. offset=" << offset << std::endl;
130 
131  } else {
132  GetOStream(Warnings0) << "AmalagamationFactory::Build(): no striding information available. Use blockdim=1 with offset=0" << std::endl;
133  }
134 
135  // build node row map (uniqueMap) and node column map (nonUniqueMap)
136  // the arrays rowTranslation and colTranslation contain the local node id
137  // given a local dof id. They are only necessary for the CoalesceDropFactory if
138  // fullblocksize > 1
139  RCP<const Map> uniqueMap, nonUniqueMap;
140  RCP<AmalgamationInfo> amalgamationData;
141  RCP<Array<LO> > rowTranslation = Teuchos::null;
142  RCP<Array<LO> > colTranslation = Teuchos::null;
143 
144  if (fullblocksize > 1) {
145  // mfh 14 Apr 2015: These need to have different names than
146  // rowTranslation and colTranslation, in order to avoid
147  // shadowing warnings (-Wshadow with GCC). Alternately, it
148  // looks like you could just assign to the existing variables in
149  // this scope, rather than creating new ones.
150  RCP<Array<LO> > theRowTranslation = rcp(new Array<LO>);
151  RCP<Array<LO> > theColTranslation = rcp(new Array<LO>);
152  AmalgamateMap(*(A->getRowMap()), *A, uniqueMap, *theRowTranslation);
153  AmalgamateMap(*(A->getColMap()), *A, nonUniqueMap, *theColTranslation);
154 
155  amalgamationData = rcp(new AmalgamationInfo(theRowTranslation,
156  theColTranslation,
157  uniqueMap,
158  nonUniqueMap,
159  A->getColMap(),
160  fullblocksize,
161  offset,
162  blockid,
163  nStridedOffset,
164  stridedblocksize));
165  } else {
166  amalgamationData = rcp(new AmalgamationInfo(rowTranslation, // Teuchos::null
167  colTranslation, // Teuchos::null
168  A->getRowMap(), // unique map of graph
169  A->getColMap(), // non-unique map of graph
170  A->getColMap(), // column map of A
171  fullblocksize,
172  offset,
173  blockid,
174  nStridedOffset,
175  stridedblocksize));
176  }
177 
178  // store (un)amalgamation information on current level
179  Set(currentLevel, "UnAmalgamationInfo", amalgamationData);
180 }
181 
182 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
183 void AmalgamationFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::AmalgamateMap(const Map& sourceMap, const Matrix& A, RCP<const Map>& amalgamatedMap, Array<LO>& translation) {
184  typedef typename ArrayView<const GO>::size_type size_type;
185  typedef std::unordered_map<GO, size_type> container;
186 
187  GO indexBase = sourceMap.getIndexBase();
188  ArrayView<const GO> elementAList = sourceMap.getLocalElementList();
189  size_type numElements = elementAList.size();
190  container filter;
191 
192  GO offset = 0;
193  LO blkSize = A.GetFixedBlockSize() / A.GetStorageBlockSize();
194  if (A.IsView("stridedMaps") == true) {
195  Teuchos::RCP<const Map> myMap = A.getRowMap("stridedMaps");
196  Teuchos::RCP<const StridedMap> strMap = Teuchos::rcp_dynamic_cast<const StridedMap>(myMap);
197  TEUCHOS_TEST_FOR_EXCEPTION(strMap == null, Exceptions::RuntimeError, "Map is not of type StridedMap");
198  offset = strMap->getOffset();
199  blkSize = Teuchos::as<const LO>(strMap->getFixedBlockSize());
200  }
201 
202  Array<GO> elementList(numElements);
203  translation.resize(numElements);
204 
205  size_type numRows = 0;
206  for (size_type id = 0; id < numElements; id++) {
207  GO dofID = elementAList[id];
208  GO nodeID = AmalgamationFactory::DOFGid2NodeId(dofID, blkSize, offset, indexBase);
209 
210  typename container::iterator it = filter.find(nodeID);
211  if (it == filter.end()) {
212  filter[nodeID] = numRows;
213 
214  translation[id] = numRows;
215  elementList[numRows] = nodeID;
216 
217  numRows++;
218 
219  } else {
220  translation[id] = it->second;
221  }
222  }
223  elementList.resize(numRows);
224 
225  amalgamatedMap = MapFactory::Build(sourceMap.lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), elementList, indexBase, sourceMap.getComm());
226 }
227 
228 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
230  const GlobalOrdinal offset, const GlobalOrdinal indexBase) {
231  GlobalOrdinal globalblockid = ((GlobalOrdinal)gid - offset - indexBase) / blockSize + indexBase;
232  return globalblockid;
233 }
234 
235 } // namespace MueLu
236 
237 #endif /* MUELU_SUBBLOCKUNAMALGAMATIONFACTORY_DEF_HPP */
Important warning messages (one line)
void DeclareInput(Level &currentLevel) const override
Input.
Exception indicating invalid cast attempted.
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
static const GlobalOrdinal DOFGid2NodeId(GlobalOrdinal gid, LocalOrdinal blockSize, const GlobalOrdinal offset, const GlobalOrdinal indexBase)
Translate global (row/column) id to global amalgamation block id.
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
static void AmalgamateMap(const Map &sourceMap, const Matrix &A, RCP< const Map > &amalgamatedMap, Array< LO > &translation)
Method to create merged map for systems of PDEs.
void resize(size_type new_size, const value_type &x=value_type())
void Build(Level &currentLevel) const override
Build an object with this factory.
std::string viewLabel_t
RCP< const ParameterList > GetValidParameterList() const override
Return a const parameter list of valid parameters that setParameterList() will accept.
Exception throws to report errors in the internal logical of the program.
Description of what is happening (more verbose)
minimal container class for storing amalgamation information