10 #ifndef MUELU_REITZINGERPFACTORY_DEF_HPP
11 #define MUELU_REITZINGERPFACTORY_DEF_HPP
13 #include <Xpetra_MapFactory.hpp>
14 #include <Xpetra_Map.hpp>
19 #include <Xpetra_MultiVectorFactory.hpp>
22 #include <Xpetra_ImportUtils.hpp>
24 #include <Xpetra_CrsMatrixWrap.hpp>
25 #include <Xpetra_StridedMap.hpp>
26 #include <Xpetra_StridedMapFactory.hpp>
33 #include "MueLu_Utilities.hpp"
37 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
41 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
46 #undef SET_VALID_ENTRY
50 validParamList->
set<
RCP<const FactoryBase> >(
"NodeAggMatrix", Teuchos::null,
"Generating factory of the matrix NodeAggMatrix");
52 validParamList->
set<
RCP<const FactoryBase> >(
"NodeImporter", Teuchos::null,
"Generating factory of the matrix NodeImporter");
56 norecurse.disableRecursiveValidation();
57 validParamList->
set<
ParameterList>(
"matrixmatrix: kernel params", norecurse,
"MatrixMatrix kernel parameters");
59 return validParamList;
62 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
64 Input(fineLevel,
"A");
65 Input(fineLevel,
"D0");
66 Input(fineLevel,
"NodeAggMatrix");
67 Input(coarseLevel,
"NodeAggMatrix");
68 Input(coarseLevel,
"Pnodal");
72 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
74 return BuildP(fineLevel, coarseLevel);
77 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
80 using Teuchos::arcp_const_cast;
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");
100 RCP<Operator> CoarseNodeMatrix = Get<RCP<Operator> >(coarseLevel,
"NodeAggMatrix");
101 int MyPID = EdgeMatrix.
is_null() ? -1 : EdgeMatrix->getRowMap()->getComm()->getRank();
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;
117 Pn->fillComplete(Pn->getDomainMap(), Pn->getRangeMap());
120 GetOStream(
Runtime0) <<
"ReitzingerPFactory::BuildP(): Assuming Pn is normalized" << std::endl;
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()) {
143 Xpetra::ImportUtils<LO, GO, NO> utils;
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()) {
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()) {
168 Xpetra::ImportUtils<LO, GO, NO> utils;
169 utils.getPids(*D0_Pn->getCrsGraph()->getImporter(), D0_Pn_col_pids,
false);
171 D0_Pn_col_pids.
resize(D0_Pn->getCrsGraph()->getColMap()->getLocalNumElements(), MyPID);
179 size_t Ne = EdgeMatrix->getLocalNumRows();
182 size_t max_edges = PnT_D0T->getLocalNumEntries();
189 LO Nnc = PnT_D0T->getRowMap()->getLocalNumElements();
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++) {
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()) {
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) {
305 D0_coarse = CrsMatrixFactory::Build(ownedCoarseEdgeMap, ownedPlusSharedCoarseNodeMap, 0);
312 D0_coarse->allocateAllValues(current, ia, ja, val);
313 std::copy(D0_rowptr.
begin(), D0_rowptr.
end(), ia.begin());
316 D0_coarse->setAllValues(ia, ja, val);
321 int fine_level_id = fineLevel.GetLevelID();
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);
365 int rank = D0->getRowMap()->getComm()->getRank();
366 int fine_level = fineLevel.GetLevelID();
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);
410 Pe_crs->getAllValues(rowptr_const, colind_const, 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) {
446 if (!CoarseNodeMatrix.
is_null()) newComm = CoarseNodeMatrix->getDomainMap()->getComm();
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();
481 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
492 RCP<Matrix> left = XMM::Multiply(Pe,
false, D0_c,
false, dummy, out0);
493 RCP<Matrix> right = XMM::Multiply(D0_f,
false, Pn,
false, dummy, out0);
496 RCP<CrsMatrix> sum_c = CrsMatrixFactory::Build(left->getRowMap(), left->getLocalMaxNumRowEntries() + right->getLocalMaxNumRowEntries());
498 XMM::TwoMatrixAdd(*left,
false, one, *summation, zero);
499 XMM::TwoMatrixAdd(*right,
false, -one, *summation, one);
501 MT norm = summation->getFrobeniusNorm();
502 GetOStream(
Statistics0) <<
"CheckCommutingProperty: ||Pe D0_c - D0_f Pn || = " << norm << std::endl;
509 #define MUELU_REITZINGERPFACTORY_SHORT
510 #endif // MUELU_REITZINGERPFACTORY_DEF_HPP
#define SET_VALID_ENTRY(name)
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
T & get(const std::string &name, T def_value)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
static void Write(const std::string &fileName, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &M)
User data are always kept. This flag is set automatically when Level::Set("data", data) is used...
One-liner description of what is happening.
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
static const NoFactory * get()
void resize(const size_type n, const T &val=T())
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
Print statistics that do not involve significant additional computation.
bool remove(std::string const &name, bool throwIfNotExists=true)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
static Teuchos::RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, const Teuchos::RCP< const Teuchos::Comm< int >> &comm, LocalGlobal lg=Xpetra::GloballyDistributed)
bool isSublist(const std::string &name) const
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
Keep data only for this run. Used to keep data useful for Hierarchy::Iterate(). Data will be deleted ...
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Transpose(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, bool optimizeTranspose=false, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
void resize(size_type new_size, const value_type &x=value_type())
void CheckCommutingProperty(const Matrix &Pe, const Matrix &D0_c, const Matrix &D0_f, const Matrix &Pn) const
Utility method.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
static RCP< Matrix > Build(const RCP< const Map > &rowMap, size_t maxNumEntriesPerRow, Xpetra::ProfileType pftype=Xpetra::DynamicProfile)
Exception throws to report errors in the internal logical of the program.
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.