80 using Teuchos::arcp_const_cast;
81 using MT =
typename Teuchos::ScalarTraits<SC>::magnitudeType;
82 using XMM = Xpetra::MatrixMatrix<SC, LO, GO, NO>;
83 Teuchos::FancyOStream& out0 = GetBlackHole();
84 const ParameterList& pL = GetParameterList();
86 bool update_communicators = pL.get<
bool>(
"repartition: enable") && pL.get<
bool>(
"repartition: use subcommunicators");
89 bool nodal_p_is_all_ones = !pL.get<
bool>(
"tentative: constant column sums") && !pL.get<
bool>(
"tentative: calculate qr");
91 RCP<Matrix> EdgeMatrix = Get<RCP<Matrix> >(fineLevel,
"A");
92 RCP<Matrix> D0 = Get<RCP<Matrix> >(fineLevel,
"D0");
93 RCP<Matrix> NodeMatrix = Get<RCP<Matrix> >(fineLevel,
"NodeAggMatrix");
94 RCP<Matrix> Pn = Get<RCP<Matrix> >(coarseLevel,
"Pnodal");
96 const GO GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
97 const LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
100 RCP<Operator> CoarseNodeMatrix = Get<RCP<Operator> >(coarseLevel,
"NodeAggMatrix");
101 int MyPID = EdgeMatrix.is_null() ? -1 : EdgeMatrix->getRowMap()->getComm()->getRank();
104 RCP<ParameterList> mm_params = rcp(
new ParameterList);
106 if (pL.isSublist(
"matrixmatrix: kernel params"))
107 mm_params->sublist(
"matrixmatrix: kernel params") = pL.sublist(
"matrixmatrix: kernel params");
110 if (!nodal_p_is_all_ones) {
112 GetOStream(
Runtime0) <<
"ReitzingerPFactory::BuildP(): Assuming Pn is not normalized" << std::endl;
113 RCP<Matrix> Pn_old = Pn;
115 Pn = Xpetra::MatrixFactory<SC, LO, GO, NO>::Build(Pn->getCrsGraph());
116 Pn->setAllToScalar(Teuchos::ScalarTraits<SC>::one());
117 Pn->fillComplete(Pn->getDomainMap(), Pn->getRangeMap());
120 GetOStream(
Runtime0) <<
"ReitzingerPFactory::BuildP(): Assuming Pn is normalized" << std::endl;
128 RCP<Matrix> D0_Pn, PnT_D0T, D0_Pn_nonghosted;
129 Teuchos::Array<int> D0_Pn_col_pids;
133 D0_Pn = XMM::Multiply(*D0,
false, *Pn,
false, dummy, out0,
true,
true,
"D0*Pn", mm_params);
136 if (!mm_params.is_null()) mm_params->remove(
"importer",
false);
139 D0_Pn_nonghosted = D0_Pn;
142 if (!D0_Pn->getCrsGraph()->getImporter().is_null()) {
144 utils.
getPids(*D0_Pn->getCrsGraph()->getImporter(), D0_Pn_col_pids,
false);
146 D0_Pn_col_pids.resize(D0_Pn->getCrsGraph()->getColMap()->getLocalNumElements(), MyPID);
161 if (!PnT_D0T->getCrsGraph()->getImporter().is_null()) {
162 RCP<const Import> Importer = PnT_D0T->getCrsGraph()->getImporter();
163 RCP<const CrsMatrix> D0_Pn_crs = rcp_dynamic_cast<const CrsMatrixWrap>(D0_Pn)->getCrsMatrix();
164 RCP<Matrix> D0_Pn_new = rcp(
new CrsMatrixWrap(CrsMatrixFactory::Build(D0_Pn_crs, *Importer, D0_Pn->getDomainMap(), Importer->getTargetMap())));
167 if (!D0_Pn->getCrsGraph()->getImporter().is_null()) {
169 utils.
getPids(*D0_Pn->getCrsGraph()->getImporter(), D0_Pn_col_pids,
false);
171 D0_Pn_col_pids.resize(D0_Pn->getCrsGraph()->getColMap()->getLocalNumElements(), MyPID);
176 ArrayView<const LO> colind_E, colind_N;
177 ArrayView<const SC> values_E, values_N;
179 size_t Ne = EdgeMatrix->getLocalNumRows();
182 size_t max_edges = PnT_D0T->getLocalNumEntries();
183 ArrayRCP<size_t> D0_rowptr(Ne + 1);
184 ArrayRCP<LO> D0_colind(max_edges);
185 ArrayRCP<SC> D0_values(max_edges);
189 LO Nnc = PnT_D0T->getRowMap()->getLocalNumElements();
192 RCP<const Map> ownedCoarseNodeMap = Pn->getDomainMap();
193 RCP<const Map> ownedPlusSharedCoarseNodeMap = D0_Pn->getCrsGraph()->getColMap();
195 for (LO i = 0; i < (LO)Nnc; i++) {
196 LO local_column_i = ownedPlusSharedCoarseNodeMap->getLocalElement(PnT_D0T->getRowMap()->getGlobalElement(i));
199 using value_type = bool;
200 std::map<LO, value_type> ce_map;
203 PnT_D0T->getLocalRowView(i, colind_E, values_E);
205 for (LO j = 0; j < (LO)colind_E.size(); j++) {
215 GO edge_gid = PnT_D0T->getColMap()->getGlobalElement(colind_E[j]);
216 LO j_row = D0_Pn->getRowMap()->getLocalElement(edge_gid);
218 D0_Pn->getLocalRowView(j_row, colind_N, values_N);
221 if (colind_N.size() != 2)
continue;
223 pid0 = D0_Pn_col_pids[colind_N[0]];
224 pid1 = D0_Pn_col_pids[colind_N[1]];
230 bool zero_matches = pid0 == MyPID;
231 bool one_matches = pid1 == MyPID;
232 bool keep_shared_edge =
false, own_both_nodes =
false;
233 if (zero_matches && one_matches) {
234 own_both_nodes =
true;
236 bool sum_is_even = (pid0 + pid1) % 2 == 0;
237 bool i_am_smaller = MyPID == std::min(pid0, pid1);
238 if (sum_is_even && i_am_smaller) keep_shared_edge =
true;
239 if (!sum_is_even && !i_am_smaller) keep_shared_edge =
true;
242 if (!keep_shared_edge && !own_both_nodes)
continue;
248 for (LO k = 0; k < (LO)colind_N.size(); k++) {
249 LO my_colind = colind_N[k];
250 if (my_colind != LO_INVALID && ((keep_shared_edge && my_colind != local_column_i) || (own_both_nodes && my_colind > local_column_i))) {
251 ce_map.emplace(std::make_pair(my_colind,
true));
257 for (
auto iter = ce_map.begin(); iter != ce_map.end(); iter++) {
258 LO col = iter->first;
259 if (col == local_column_i) {
264 if (current + 1 >= Teuchos::as<LocalOrdinal>(max_edges)) {
266 D0_colind.resize(max_edges);
267 D0_values.resize(max_edges);
269 if (current / 2 + 1 >= D0_rowptr.size()) {
270 D0_rowptr.resize(2 * D0_rowptr.size() + 1);
274 D0_colind[current] = local_column_i;
275 D0_values[current] = -1;
277 D0_colind[current] = col;
278 D0_values[current] = 1;
280 D0_rowptr[current / 2] = current;
285 LO num_coarse_edges = current / 2;
286 D0_rowptr.resize(num_coarse_edges + 1);
287 D0_colind.resize(current);
288 D0_values.resize(current);
291 if (num_coarse_edges == 0) {
297 RCP<const Map> ownedCoarseEdgeMap = Xpetra::MapFactory<LO, GO, NO>::Build(EdgeMatrix->getRowMap()->lib(), GO_INVALID, num_coarse_edges, EdgeMatrix->getRowMap()->getIndexBase(), EdgeMatrix->getRowMap()->getComm());
300 RCP<CrsMatrix> D0_coarse;
305 D0_coarse = CrsMatrixFactory::Build(ownedCoarseEdgeMap, ownedPlusSharedCoarseNodeMap, 0);
306 TEUCHOS_TEST_FOR_EXCEPTION(D0_coarse.is_null(),
Exceptions::RuntimeError,
"MueLu::ReitzingerPFactory: CrsMatrixFatory failed.");
312 D0_coarse->allocateAllValues(current, ia, ja, val);
313 std::copy(D0_rowptr.begin(), D0_rowptr.end(), ia.begin());
314 std::copy(D0_colind.begin(), D0_colind.end(), ja.begin());
315 std::copy(D0_values.begin(), D0_values.end(), val.begin());
316 D0_coarse->setAllValues(ia, ja, val);
322 printf(
"[%d] Level %d D0: ia.size() = %d ja.size() = %d\n",MyPID,fine_level_id,(
int)ia.size(),(
int)ja.size());
323 printf(
"[%d] Level %d D0: ia :",MyPID,fine_level_id);
324 for(
int i=0; i<(int)ia.size(); i++)
325 printf(
"%d ",(
int)ia[i]);
326 printf(
"\n[%d] Level %d D0: global ja :",MyPID,fine_level_id);
327 for(
int i=0; i<(int)ja.size(); i++)
328 printf(
"%d ",(
int)ownedPlusSharedCoarseNodeMap->getGlobalElement(ja[i]));
329 printf(
"\n[%d] Level %d D0: local ja :",MyPID,fine_level_id);
330 for(
int i=0; i<(int)ja.size(); i++)
331 printf(
"%d ",(
int)ja[i]);
334 sprintf(fname,
"D0_global_ja_%d_%d.dat",MyPID,fine_level_id);
335 FILE * f = fopen(fname,
"w");
336 for(
int i=0; i<(int)ja.size(); i++)
337 fprintf(f,
"%d ",(
int)ownedPlusSharedCoarseNodeMap->getGlobalElement(ja[i]));
340 sprintf(fname,
"D0_local_ja_%d_%d.dat",MyPID,fine_level_id);
341 f = fopen(fname,
"w");
342 for(
int i=0; i<(int)ja.size(); i++)
343 fprintf(f,
"%d ",(
int)ja[i]);
348 D0_coarse->expertStaticFillComplete(ownedCoarseNodeMap, ownedCoarseEdgeMap);
350 RCP<Matrix> D0_coarse_m = rcp(
new CrsMatrixWrap(D0_coarse));
351 RCP<Teuchos::FancyOStream> fout = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
365 int rank = D0->getRowMap()->getComm()->getRank();
367 printf(
"[%d] Level %d Checkpoint #2 Pn = %d/%d/%d/%d D0c = %d/%d/%d/%d D0 = %d/%d/%d/%d\n",rank,fine_level,
368 Pn->getRangeMap()->getComm()->getSize(),
369 Pn->getRowMap()->getComm()->getSize(),
370 Pn->getColMap()->getComm()->getSize(),
371 Pn->getDomainMap()->getComm()->getSize(),
372 D0_coarse_m->getRangeMap()->getComm()->getSize(),
373 D0_coarse_m->getRowMap()->getComm()->getSize(),
374 D0_coarse_m->getColMap()->getComm()->getSize(),
375 D0_coarse_m->getDomainMap()->getComm()->getSize(),
376 D0->getRangeMap()->getComm()->getSize(),
377 D0->getRowMap()->getComm()->getSize(),
378 D0->getColMap()->getComm()->getSize(),
379 D0->getDomainMap()->getComm()->getSize());
381 D0->getRowMap()->getComm()->barrier();
385 RCP<Matrix> Pn_D0cT = XMM::Multiply(*Pn,
false, *D0_coarse_m,
true, dummy, out0,
true,
true,
"Pn*D0c'", mm_params);
388 if (!mm_params.is_null()) mm_params->remove(
"importer",
false);
390 Pe = XMM::Multiply(*D0,
false, *Pn_D0cT,
false, dummy, out0,
true,
true,
"D0*(Pn*D0c')", mm_params);
400 SC one = Teuchos::ScalarTraits<SC>::one();
401 MT two = 2 * Teuchos::ScalarTraits<MT>::one();
402 SC zero = Teuchos::ScalarTraits<SC>::zero();
405 RCP<const CrsMatrix> Pe_crs = rcp_dynamic_cast<const CrsMatrixWrap>(Pe)->getCrsMatrix();
406 TEUCHOS_TEST_FOR_EXCEPTION(Pe_crs.is_null(),
Exceptions::RuntimeError,
"MueLu::ReitzingerPFactory: Pe is not a crs matrix.");
407 ArrayRCP<const size_t> rowptr_const;
408 ArrayRCP<const LO> colind_const;
409 ArrayRCP<const SC> values_const;
410 Pe_crs->getAllValues(rowptr_const, colind_const, values_const);
411 ArrayRCP<size_t> rowptr = arcp_const_cast<size_t>(rowptr_const);
412 ArrayRCP<LO> colind = arcp_const_cast<LO>(colind_const);
413 ArrayRCP<SC> values = arcp_const_cast<SC>(values_const);
415 LO lower = rowptr[0];
416 for (LO i = 0; i < (LO)Ne; i++) {
417 for (
size_t j = lower; j < rowptr[i + 1]; j++) {
418 if (values[j] == one || values[j] == neg_one || values[j] == zero) {
421 colind[ct] = colind[j];
422 values[ct] = values[j] / two;
426 lower = rowptr[i + 1];
432 rcp_const_cast<CrsMatrix>(Pe_crs)->setAllValues(rowptr, colind, values);
434 Pe->fillComplete(Pe->getDomainMap(), Pe->getRangeMap());
438 CheckCommutingProperty(*Pe, *D0_coarse_m, *D0, *Pn);
443 if (update_communicators) {
445 RCP<const Teuchos::Comm<int> > newComm;
446 if (!CoarseNodeMatrix.is_null()) newComm = CoarseNodeMatrix->getDomainMap()->getComm();
447 RCP<const Map> newMap = Xpetra::MapFactory<LO, GO, NO>::copyMapWithNewComm(D0_coarse_m->getRowMap(), newComm);
448 D0_coarse_m->removeEmptyProcessesInPlace(newMap);
451 if (newMap.is_null()) D0_coarse_m = Teuchos::null;
453 Set(coarseLevel,
"InPlaceMap", newMap);
457 Set(coarseLevel,
"P", Pe);
458 Set(coarseLevel,
"Ptent", Pe);
460 Set(coarseLevel,
"D0", D0_coarse_m);
469 int numProcs = Pe->getRowMap()->getComm()->getSize();
472 sprintf(fname,
"Pe_%d_%d.mat",numProcs,fineLevel.
GetLevelID()); Xpetra::IO<SC,LO,GO,NO>::Write(fname,*Pe);
473 sprintf(fname,
"Pn_%d_%d.mat",numProcs,fineLevel.
GetLevelID()); Xpetra::IO<SC,LO,GO,NO>::Write(fname,*Pn);
474 sprintf(fname,
"D0c_%d_%d.mat",numProcs,fineLevel.
GetLevelID()); Xpetra::IO<SC,LO,GO,NO>::Write(fname,*D0_coarse_m);
475 sprintf(fname,
"D0f_%d_%d.mat",numProcs,fineLevel.
GetLevelID()); Xpetra::IO<SC,LO,GO,NO>::Write(fname,*D0);