18 #include <Teuchos_RCP.hpp>
19 #include <Teuchos_ArrayView.hpp>
21 #include <unordered_map>
23 #include <Tpetra_Map.hpp>
24 #include <Tpetra_Vector.hpp>
28 #include <zoltan_dd_cpp.h>
29 #include <unordered_set>
38 std::ostream &ostr = std::cout)
40 ostr << msg << std::endl;
41 Teuchos::FancyOStream fancy(Teuchos::rcpFromRef(ostr));
42 thing.describe(fancy, Teuchos::VERB_EXTREME);
45 template <
typename vector_t>
47 std::ostream &ostr = std::cout)
49 if (vec.getGlobalLength() >
TOOMANY)
return;
50 printTpetraThing<vector_t>(vec, msg, ostr);
53 template <
typename map_t>
55 std::ostream &ostr = std::cout)
57 if (map.getGlobalNumElements() >
TOOMANY)
return;
58 printTpetraThing<map_t>(map, msg, ostr);
63 template <
typename id_t>
67 IDs(
size_t nIds_,
float fracShared_, id_t idBase_,
int idStride_,
68 Teuchos::RCP<
const Teuchos::Comm<int> > &comm_) :
70 nShared(std::ceil(nIds * fracShared_)),
71 nUnique(nIds - nShared),
74 contiguous(idStride_ == 1),
75 ids(nIds, 0), comm(comm_)
77 int me = comm->getRank();
78 int np = comm->getSize();
82 for (
size_t i = 0; i < nUnique; i++)
83 ids[cnt++] = idBase + ((me * nUnique + i) * idStride);
86 size_t gnUnique = nUnique * np;
89 for (
size_t i = 0; i < nShared; i++) {
90 size_t r = rand() % nShared;
91 ids[cnt++] = idBase + ((gnUnique + r) * idStride);
101 int me = comm->getRank();
103 std::cout << me <<
" nIds = " << nIds <<
"; nUnique = " << nUnique
104 <<
"; nShared = " << nShared << std::endl;
106 std::cout << me <<
" Unique: ";
107 for (
size_t i = 0; i < nUnique; i++) std::cout << ids[i] <<
" ";
108 std::cout << std::endl;
110 std::cout << me <<
" Shared: ";
111 for (
size_t i = 0; i < nShared; i++) std::cout << ids[nUnique+i] <<
" ";
112 std::cout << std::endl;
121 typedef int scalar_t;
132 std::vector<id_t> ids;
134 Teuchos::RCP<const Teuchos::Comm<int> > comm;
152 template <
typename id_t>
155 typedef typename Tpetra::Map<int, id_t>
map_t;
156 typedef typename Teuchos::RCP<const map_t> rcpmap_t;
158 typedef typename Tpetra::Vector<scalar_t, int, id_t> vector_t;
159 typedef typename Teuchos::ArrayRCP<scalar_t> vectordata_t;
166 id_t minId = std::numeric_limits<id_t>::max();
168 std::unordered_map<id_t, size_t> uniqueIds;
169 uniqueIds.reserve(nIds);
171 for (
size_t i = 0; i < nIds; i++) {
173 if (
id < minId) minId = id;
174 if (uniqueIds.find(
id) == uniqueIds.end())
183 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MIN, 1, &minId, &indexBase);
187 size_t nUniqueIds = uniqueIds.size();
188 Teuchos::Array<id_t> uniqueIdsList(nUniqueIds);
191 for (
auto it = uniqueIds.begin(); it != uniqueIds.end(); it++)
192 uniqueIdsList[cnt++] = it->first;
196 size_t dummy = Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid();
198 rcpmap_t idMap = Teuchos::rcp(
new map_t(dummy, uniqueIdsList(), indexBase,
204 vector_t idVec(idMap, 0.);
209 vectordata_t idData = idVec.getDataNonConst();
210 for (
auto it = uniqueIds.begin(); it != uniqueIds.end(); it++) {
211 id_t idx = idMap->getLocalElement(it->first);
212 idData[idx] = it->second;
227 id_t gnUnique = idMap->getMaxAllGlobalIndex() - indexBase + 1;
228 oto_idMap = Teuchos::rcp(
new map_t(gnUnique, indexBase, comm));
232 oto_idMap = Tpetra::createOneToOne(idMap);
235 vector_t oto_idVec(oto_idMap);
241 typedef Tpetra::Export<int, id_t> export_t;
243 export_t idExporter(idMap, oto_idMap);
254 oto_idVec.doExport(idVec, idExporter, Tpetra::ADD);
263 idVec.doImport(oto_idVec, idExporter, Tpetra::REPLACE);
268 size_t cntShared = 0;
270 auto idData = idVec.getDataNonConst();
271 for (
size_t i = 0; i < idVec.getLocalLength(); i++)
272 if (idData[i] > 1) cntShared++;
275 std::cout << comm->getRank() <<
" cntShared = " << cntShared
276 <<
"; nShared = " << nShared << std::endl;
278 return (cntShared == nShared);
288 template <
typename id_t>
292 if (nIds >
size_t(std::numeric_limits<int>::max()))
293 throw std::runtime_error(
"Problem too large for Zoltan_DD");
295 int inIds = int(nIds);
300 MPI_Comm mpicomm = Teuchos::getRawMpiComm(*comm);
304 MPI_Initialized(&flag);
308 MPI_Init(&narg, &argv);
311 MPI_Comm mpicomm = MPI_COMM_WORLD;
316 Zoltan_DD zz(mpicomm, nIdEnt, 0,
sizeof(scalar_t), inIds, 0);
324 std::vector<scalar_t> user(nIds, 1.);
329 ZOLTAN_ID_PTR zgids = NULL;
331 Teuchos::ArrayView<id_t> av(&(ids[0]), nIds);
338 zz.Update(zgids, NULL, (
char*)(nIds ? &(user[0]) : NULL), NULL, inIds);
341 zz.Find(zgids, NULL, (
char*)(nIds ? &(user[0]) : NULL), NULL, inIds, NULL);
345 size_t cntShared = 0;
346 std::unordered_set<id_t> alreadyCounted;
347 for (
size_t i = 0; i < nIds; i++) {
350 if (alreadyCounted.find(ids[i]) == alreadyCounted.end()) {
351 alreadyCounted.insert(ids[i]);
357 if ((nIds * comm->getSize()) <=
TOOMANY) zz.Print();
359 return (cntShared == nShared);
365 Tpetra::ScopeGuard tscope(&narg, &arg);
366 Teuchos::RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
371 float fracShared = 0.2;
375 typedef Tpetra::Map<>::global_ordinal_type
gno_t;
376 IDs<gno_t> myIds(nIds, fracShared, idBase, idStride, comm);
386 float fracShared = 0.2;
390 typedef Tpetra::Map<>::global_ordinal_type
gno_t;
391 IDs<gno_t> myIds(nIds, fracShared, idBase, idStride, comm);
398 #ifdef HAVE_TPETRA_INT_INT
402 float fracShared = 0.2;
406 IDs<int> myIds(nIds, fracShared, idBase, idStride, comm);
416 float fracShared = 0.2;
420 IDs<int> myIds(nIds, fracShared, idBase, idStride, comm);
428 #ifdef HAVE_TPETRA_INT_LONG_LONG
432 float fracShared = 0.4;
void printTpetraThing(T &thing, const std::string &msg, std::ostream &ostr=std::cout)
map_t::global_ordinal_type gno_t
int main(int narg, char **arg)
void printVector(vector_t &vec, const std::string &msg, std::ostream &ostr=std::cout)
void printMap(map_t &map, const std::string &msg, std::ostream &ostr=std::cout)
static const size_t TOOMANY
IDs(size_t nIds_, float fracShared_, id_t idBase_, int idStride_, Teuchos::RCP< const Teuchos::Comm< int > > &comm_)
Traits class to handle conversions between gno_t/lno_t and TPL data types (e.g., ParMETIS's idx_t...
static void ASSIGN_ARRAY(first_t **a, ArrayView< second_t > &b)