MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_IsorropiaInterface_def.hpp
Go to the documentation of this file.
1/*
2 * MueLu_IsorropiaInterface_def.hpp
3 *
4 * Created on: Jun 10, 2013
5 * Author: tobias
6 */
7
8#ifndef MUELU_ISORROPIAINTERFACE_DEF_HPP_
9#define MUELU_ISORROPIAINTERFACE_DEF_HPP_
10
12
13#include <Teuchos_Utils.hpp>
14//#include <Teuchos_DefaultMpiComm.hpp> //TODO: fwd decl.
15//#include <Teuchos_OpaqueWrapper.hpp> //TODO: fwd decl.
16
17#include <Xpetra_MapFactory.hpp>
18#include <Xpetra_CrsGraphFactory.hpp>
19#include <Xpetra_BlockedMap.hpp>
20#include <Xpetra_BlockedCrsMatrix.hpp>
21
22#ifdef HAVE_MUELU_ISORROPIA
23#include <Isorropia_Exception.hpp>
24
25
26#ifdef HAVE_MUELU_EPETRA
27#include <Xpetra_EpetraCrsGraph.hpp>
28#include <Epetra_CrsGraph.h>
29#include <Isorropia_EpetraPartitioner.hpp>
30#endif
31
32#include <Xpetra_TpetraCrsGraph.hpp>
33#endif // ENDIF HAVE_MUELU_ISORROPIA
34
35#include "MueLu_Level.hpp"
36#include "MueLu_Exceptions.hpp"
37#include "MueLu_Monitor.hpp"
38#include "MueLu_Graph.hpp"
39#include "MueLu_AmalgamationInfo.hpp"
40
41namespace MueLu {
42
43 template <class LocalOrdinal, class GlobalOrdinal, class Node>
45 RCP<ParameterList> validParamList = rcp(new ParameterList());
46
47 validParamList->set< RCP<const FactoryBase> >("A", Teuchos::null, "Factory of the matrix A");
48 validParamList->set< RCP<const FactoryBase> >("number of partitions", Teuchos::null, "Instance of RepartitionHeuristicFactory.");
49 validParamList->set< RCP<const FactoryBase> >("UnAmalgamationInfo", Teuchos::null, "Generating factory of UnAmalgamationInfo");
50
51 return validParamList;
52 }
53
54
55 template <class LocalOrdinal, class GlobalOrdinal, class Node>
57 Input(currentLevel, "A");
58 Input(currentLevel, "number of partitions");
59 Input(currentLevel, "UnAmalgamationInfo");
60 }
61
62 template <class LocalOrdinal, class GlobalOrdinal, class Node>
64 FactoryMonitor m(*this, "Build", level);
65 typedef Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node> BlockMap;
66
67 RCP<Matrix> A = Get< RCP<Matrix> >(level, "A");
68 RCP<AmalgamationInfo> amalInfo = Get< RCP<AmalgamationInfo> >(level, "UnAmalgamationInfo");
69 GO numParts = Get< int >(level, "number of partitions");
70
71 RCP<const Map> rowMap = A->getRowMap();
72 RCP<const Map> colMap = A->getColMap();
73
74 if (numParts == 1 || numParts == -1) {
75 // Running on one processor, so decomposition is the trivial one, all zeros.
76 RCP<Xpetra::Vector<GO, LO, GO, NO> > decomposition = Xpetra::VectorFactory<GO, LO, GO, NO>::Build(rowMap, true);
77 Set(level, "AmalgamatedPartition", decomposition);
78 return;
79 }
80
81 // ok, reconstruct graph information of matrix A
82 // Note, this is the non-rebalanced matrix A and we need the graph
83 // of the non-rebalanced matrix A. We cannot make use of the "Graph"
84 // that is/will be built for the aggregates later for several reasons
85 // 1) the "Graph" for the aggregates is meant to be based on the rebalanced matrix A
86 // 2) we cannot call a CoalesceDropFactory::Build here since this is very complicated and
87 // completely messes up the whole factory chain
88 // 3) CoalesceDropFactory is meant to provide some minimal Graph information for the aggregation
89 // (LWGraph), but here we need the full CrsGraph for Isorropia as input
90
91 // That is, why this code is somewhat redundant to CoalesceDropFactory
92
93 LO blockdim = 1; // block dim for fixed size blocks
94 GO indexBase = rowMap->getIndexBase(); // index base of maps
95 GO offset = 0;
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 = blockdim; // size of strided block id "blockid" (default = fullblocksize, only if blockid!=-1 stridedblocksize <= fullblocksize)
99
100 // 1) check for blocking/striding information
101 // fill above variables
102 if(A->IsView("stridedMaps") &&
103 Teuchos::rcp_dynamic_cast<const StridedMap>(A->getRowMap("stridedMaps")) != Teuchos::null) {
104 Xpetra::viewLabel_t oldView = A->SwitchToView("stridedMaps"); // note: "stridedMaps are always non-overlapping (correspond to range and domain maps!)
105 RCP<const StridedMap> strMap = Teuchos::rcp_dynamic_cast<const StridedMap>(A->getRowMap());
106 TEUCHOS_TEST_FOR_EXCEPTION(strMap == Teuchos::null,Exceptions::BadCast,"MueLu::IsorropiaInterface::Build: cast to strided row map failed.");
107 blockdim = strMap->getFixedBlockSize();
108 offset = strMap->getOffset();
109 blockid = strMap->getStridedBlockId();
110 if (blockid > -1) {
111 std::vector<size_t> stridingInfo = strMap->getStridingData();
112 for (size_t j = 0; j < Teuchos::as<size_t>(blockid); j++)
113 nStridedOffset += stridingInfo[j];
114 //stridedblocksize = Teuchos::as<LocalOrdinal>(stridingInfo[blockid]);
115
116 }// else {
117 // stridedblocksize = blockdim;
118 //}
119 oldView = A->SwitchToView(oldView);
120 //GetOStream(Statistics0) << "IsorropiaInterface::Build():" << " found blockdim=" << blockdim << " from strided maps (blockid=" << blockid << ", strided block size=" << stridedblocksize << "). offset=" << offset << std::endl;
121 } else GetOStream(Statistics0) << "IsorropiaInterface::Build(): no striding information available. Use blockdim=1 with offset=0" << std::endl;
122
123 // 2) get row map for amalgamated matrix (graph of A)
124 // with same distribution over all procs as row map of A
125 RCP<const Map> nodeMap= amalInfo->getNodeRowMap();
126 RCP<const BlockedMap> bnodeMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(nodeMap);
127 if(!bnodeMap.is_null()) nodeMap=bnodeMap->getMap();
128
129 GetOStream(Statistics0) << "IsorropiaInterface:Build(): nodeMap " << nodeMap->getLocalNumElements() << "/" << nodeMap->getGlobalNumElements() << " elements" << std::endl;
130
131
132 // 3) create graph of amalgamated matrix
133 RCP<CrsGraph> crsGraph = CrsGraphFactory::Build(nodeMap, A->getLocalMaxNumRowEntries()*blockdim);
134
135 // 4) do amalgamation. generate graph of amalgamated matrix
136 for(LO row=0; row<Teuchos::as<LO>(A->getRowMap()->getLocalNumElements()); row++) {
137 // get global DOF id
138 GO grid = rowMap->getGlobalElement(row);
139
140 // translate grid to nodeid
141 // JHU 2019-20-May this is identical to AmalgamationFactory::DOFGid2NodeId(), and is done
142 // to break a circular dependence when libraries are built statically
143 GO nodeId = (grid - offset - indexBase) / blockdim + indexBase;
144
145 size_t nnz = A->getNumEntriesInLocalRow(row);
146 Teuchos::ArrayView<const LO> indices;
147 Teuchos::ArrayView<const SC> vals;
148 A->getLocalRowView(row, indices, vals);
149
150 RCP<std::vector<GO> > cnodeIds = Teuchos::rcp(new std::vector<GO>); // global column block ids
151 LO realnnz = 0;
152 for(LO col=0; col<Teuchos::as<LO>(nnz); col++) {
153 GO gcid = colMap->getGlobalElement(indices[col]); // global column id
154
155 if(vals[col]!=0.0) {
156 // JHU 2019-20-May this is identical to AmalgamationFactory::DOFGid2NodeId(), and is done
157 // to break a circular dependence when libraries are built statically
158 GO cnodeId = (gcid - offset - indexBase) / blockdim + indexBase;
159 cnodeIds->push_back(cnodeId);
160 realnnz++; // increment number of nnz in matrix row
161 }
162 }
163
164 Teuchos::ArrayRCP<GO> arr_cnodeIds = Teuchos::arcp( cnodeIds );
165
166 if(arr_cnodeIds.size() > 0 )
167 crsGraph->insertGlobalIndices(nodeId, arr_cnodeIds());
168 }
169 // fill matrix graph
170 crsGraph->fillComplete(nodeMap,nodeMap);
171
172#ifdef HAVE_MPI
173#ifdef HAVE_MUELU_ISORROPIA
174
175 // prepare parameter list for Isorropia
176 Teuchos::ParameterList paramlist;
177 paramlist.set("NUM PARTS", toString(numParts));
178
179 /*STRUCTURALLY SYMMETRIC [NO/yes] (is symmetrization required?)
180 PARTITIONING METHOD [block/cyclic/random/rcb/rib/hsfc/graph/HYPERGRAPH]
181 NUM PARTS [int k] (global number of parts)
182 IMBALANCE TOL [float tol] (1.0 is perfect balance)
183 BALANCE OBJECTIVE [ROWS/nonzeros]
184 */
185 Teuchos::ParameterList& sublist = paramlist.sublist("Zoltan");
186 sublist.set("LB_APPROACH", "PARTITION");
187
188
189
190#ifdef HAVE_MUELU_EPETRA
191 RCP< Xpetra::EpetraCrsGraphT<GO, Node> > epCrsGraph = Teuchos::rcp_dynamic_cast<Xpetra::EpetraCrsGraphT<GO, Node> >(crsGraph);
192 if(epCrsGraph != Teuchos::null) {
193 RCP< const Epetra_CrsGraph> epetraCrsGraph = epCrsGraph->getEpetra_CrsGraph();
194
195 RCP<Isorropia::Epetra::Partitioner> isoPart = Teuchos::rcp(new Isorropia::Epetra::Partitioner(epetraCrsGraph,paramlist));
196
197 int size = 0;
198 const int* array = NULL;
199 isoPart->extractPartsView(size,array);
200
201 TEUCHOS_TEST_FOR_EXCEPTION(size != Teuchos::as<int>(nodeMap->getLocalNumElements()), Exceptions::RuntimeError, "length of array returned from extractPartsView does not match local length of rowMap");
202
203 RCP<Xpetra::Vector<GO, LO, GO, NO> > decomposition = Xpetra::VectorFactory<GO, LO, GO, NO>::Build(nodeMap, false);
204 ArrayRCP<GO> decompEntries = decomposition->getDataNonConst(0);
205
206 // fill vector with amalgamated information about partitioning
207 for(int i = 0; i<size; i++) {
208 decompEntries[i] = Teuchos::as<GO>(array[i]);
209 }
210
211 Set(level, "AmalgamatedPartition", decomposition);
212
213 }
214#endif // ENDIF HAVE_MUELU_EPETRA
215
216#ifdef HAVE_MUELU_INST_DOUBLE_INT_INT
217 RCP< Xpetra::TpetraCrsGraph<LO, GO, Node> > tpCrsGraph = Teuchos::rcp_dynamic_cast<Xpetra::TpetraCrsGraph<LO, GO, Node> >(crsGraph);
218 TEUCHOS_TEST_FOR_EXCEPTION(tpCrsGraph != Teuchos::null, Exceptions::RuntimeError, "Tpetra is not supported with Isorropia.");
219#else
220 TEUCHOS_TEST_FOR_EXCEPTION(false, Exceptions::RuntimeError, "Isorropia is an interface to Zoltan which only has support for LO=GO=int and SC=double.");
221#endif // ENDIF HAVE_MUELU_INST_DOUBLE_INT_INT
222#endif // HAVE_MUELU_ISORROPIA
223#else // if we don't have MPI
224
225
226 // Running on one processor, so decomposition is the trivial one, all zeros.
227 RCP<Xpetra::Vector<GO, LO, GO, NO> > decomposition = Xpetra::VectorFactory<GO, LO, GO, NO>::Build(rowMap, true);
228 Set(level, "AmalgamatedPartition", decomposition);
229
230#endif // HAVE_MPI
231 // throw a more helpful error message if something failed
232 //TEUCHOS_TEST_FOR_EXCEPTION(!level.IsAvailable("AmalgamatedPartition"), Exceptions::RuntimeError, "IsorropiaInterface::Build : no \'Partition\' vector available on level. Isorropia failed to build a partition of the non-repartitioned graph of A. Please make sure, that Isorropia is correctly compiled (Epetra/Tpetra).");
233
234 } //Build()
235
236
237
238} //namespace MueLu
239
240//#endif //if defined(HAVE_MUELU_ISORROPIA) && defined(HAVE_MPI)
241
242
243#endif /* MUELU_ISORROPIAINTERFACE_DEF_HPP_ */
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.
void Input(Level &level, const std::string &varName) const
T Get(Level &level, const std::string &varName) const
void Set(Level &level, const std::string &varName, const T &data) const
void DeclareInput(Level &level) const
Specifies the data that this class needs, and the factories that generate that data.
void Build(Level &level) const
Build an object with this factory.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
Class that holds all level-specific information.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
Namespace for MueLu classes and methods.
@ Statistics0
Print statistics that do not involve significant additional computation.
std::string toString(const T &what)
Little helper function to convert non-string types to strings.