10 #ifndef MUELU_CLASSICALPFACTORY_DEF_HPP
11 #define MUELU_CLASSICALPFACTORY_DEF_HPP
13 #include <Xpetra_MultiVectorFactory.hpp>
17 #include <Xpetra_Map.hpp>
18 #include <Xpetra_MapFactory.hpp>
21 #include <Xpetra_ImportUtils.hpp>
23 #include <Xpetra_StridedMapFactory.hpp>
29 #include "MueLu_PerfUtils.hpp"
31 #include "MueLu_ClassicalMapFactory.hpp"
32 #include "MueLu_AmalgamationInfo.hpp"
33 #include "MueLu_LWGraph.hpp"
44 if (STS::real(val) > MT_ZERO)
46 else if (STS::real(val) < MT_ZERO)
56 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
59 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
70 #undef SET_VALID_ENTRY
74 validParamList->
set<
RCP<const FactoryBase> >(
"DofsPerNode", null,
"Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
80 return validParamList;
83 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
85 Input(fineLevel,
"A");
86 Input(fineLevel,
"Graph");
87 Input(fineLevel,
"DofsPerNode");
89 Input(fineLevel,
"CoarseMap");
90 Input(fineLevel,
"FC Splitting");
93 std::string drop_algo = pL.
get<std::string>(
"aggregation: drop scheme");
94 if (drop_algo.find(
"block diagonal") != std::string::npos || drop_algo ==
"signed classical") {
95 Input(fineLevel,
"BlockNumber");
99 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
101 return BuildP(fineLevel, coarseLevel);
104 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
115 RCP<const Map> ownedCoarseMap = Get<RCP<const Map> >(fineLevel,
"CoarseMap");
138 std::string scheme = pL.
get<std::string>(
"aggregation: classical scheme");
139 bool need_ghost_rows =
false;
140 if (scheme ==
"ext+i")
141 need_ghost_rows =
true;
142 else if (scheme ==
"direct")
143 need_ghost_rows =
false;
144 else if (scheme ==
"classical modified")
145 need_ghost_rows =
true;
149 GetOStream(
Statistics1) <<
"ClassicalPFactory: scheme = " << scheme << std::endl;
155 if (Importer.is_null()) {
156 fc_splitting = owned_fc_splitting;
158 RCP<LocalOrdinalVector> fc_splitting_nonconst = LocalOrdinalVectorFactory::Build(A->getCrsGraph()->getColMap());
159 fc_splitting_nonconst->doImport(*owned_fc_splitting, *Importer,
Xpetra::INSERT);
160 fc_splitting = fc_splitting_nonconst;
162 myPointType = fc_splitting->getData(0);
169 if (need_ghost_rows && !Importer.is_null()) {
171 size_t numRemote = Importer->getNumRemoteIDs();
173 for (
size_t i = 0; i < numRemote; i++)
174 remoteRows[i] = Importer->getTargetMap()->getGlobalElement(remoteLIDs[i]);
177 A->getDomainMap()->getIndexBase(), A->getDomainMap()->getComm());
179 remoteOnlyImporter = Importer->createRemoteOnlyImport(remoteRowMap);
181 RCP<CrsMatrix> Aghost_crs = CrsMatrixFactory::Build(Acrs, *remoteOnlyImporter, A->getDomainMap(), remoteOnlyImporter->getTargetMap());
182 Aghost =
rcp(
new CrsMatrixWrap(Aghost_crs));
196 if (Importer.is_null())
197 coarseMap = ownedCoarseMap;
200 GhostCoarseMap(*A, *Importer, myPointType, ownedCoarseMap, coarseMap);
205 std::string drop_algo = pL.
get<std::string>(
"aggregation: drop scheme");
206 if (drop_algo.find(
"block diagonal") != std::string::npos || drop_algo ==
"signed classical") {
208 OwnedBlockNumber = Get<RCP<LocalOrdinalVector> >(fineLevel,
"BlockNumber");
209 if (Importer.is_null())
210 BlockNumber = OwnedBlockNumber;
212 BlockNumber = LocalOrdinalVectorFactory::Build(A->getColMap());
213 BlockNumber->doImport(*OwnedBlockNumber, *Importer,
Xpetra::INSERT);
217 #if defined(CMS_DEBUG) || defined(CMS_DUMP)
220 int rank = A->getRowMap()->getComm()->getRank();
221 printf(
"[%d] A local size = %dx%d\n", rank, (
int)Acrs->getRowMap()->getLocalNumElements(), (int)Acrs->getColMap()->getLocalNumElements());
223 printf(
"[%d] graph local size = %dx%d\n", rank, (
int)graph->GetDomainMap()->getLocalNumElements(), (int)graph->GetImportMap()->getLocalNumElements());
225 std::ofstream ofs(std::string(
"dropped_graph_") + std::to_string(fineLevel.GetLevelID()) + std::string(
"_") + std::to_string(rank) + std::string(
".dat"), std::ofstream::out);
227 graph->print(*fancy,
Debug);
228 std::string out_fc = std::string(
"fc_splitting_") + std::to_string(fineLevel.GetLevelID()) + std::string(
"_") + std::to_string(rank) + std::string(
".dat");
229 std::string out_block = std::string(
"block_number_") + std::to_string(fineLevel.GetLevelID()) + std::string(
"_") + std::to_string(rank) + std::string(
".dat");
241 for (
LO i = 0; i < (
LO)fc_data.
size(); i++)
242 mv_data[i] = Teuchos::as<real_type>(fc_data[i]);
250 for (
LO i = 0; i < (
LO)b_data.
size(); i++) {
251 mv_data2[i] = Teuchos::as<real_type>(b_data[i]);
266 Array<LO> pcol2cpoint(coarseMap->getLocalNumElements(), LO_INVALID);
269 for (
LO i = 0; i < (
LO)myPointType.
size(); i++) {
270 if (myPointType[i] == C_PT) {
271 cpoint2pcol[i] = num_c_points;
273 }
else if (myPointType[i] == F_PT)
276 for (
LO i = 0; i < (
LO)cpoint2pcol.size(); i++) {
277 if (cpoint2pcol[i] != LO_INVALID)
278 pcol2cpoint[cpoint2pcol[i]] = i;
287 GenerateStrengthFlags(*A, *graph, eis_rowptr, edgeIsStrong);
293 if (scheme ==
"ext+i") {
295 Coarsen_Ext_Plus_I(*A, Aghost, *graph, coarseColMap, coarseDomainMap, num_c_points, num_f_points, myPointType(), myPointType_ghost(), cpoint2pcol, pcol2cpoint, eis_rowptr, edgeIsStrong, BlockNumber, P);
296 }
else if (scheme ==
"direct") {
298 Coarsen_Direct(*A, Aghost, *graph, coarseColMap, coarseDomainMap, num_c_points, num_f_points, myPointType(), myPointType_ghost(), cpoint2pcol, pcol2cpoint, eis_rowptr, edgeIsStrong, BlockNumber, P);
299 }
else if (scheme ==
"classical modified") {
301 Coarsen_ClassicalModified(*A, Aghost, *graph, coarseColMap, coarseDomainMap, num_c_points, num_f_points, myPointType(), myPointType_ghost(), cpoint2pcol, pcol2cpoint, eis_rowptr, edgeIsStrong, BlockNumber, remoteOnlyImporter, P);
311 Set(coarseLevel,
"P", P);
313 Set(coarseLevel,
"P Graph", pg);
321 params->
set(
"printLoadBalancingInfo",
true);
326 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
328 Coarsen_ClassicalModified(
const Matrix& A,
const RCP<const Matrix>& Aghost,
const LWGraph& graph,
RCP<const Map>& coarseColMap,
RCP<const Map>& coarseDomainMap,
LO num_c_points,
LO num_f_points,
const Teuchos::ArrayView<const LO>& myPointType,
const Teuchos::ArrayView<const LO>& myPointType_ghost,
const Teuchos::Array<LO>& cpoint2pcol,
const Teuchos::Array<LO>& pcol2cpoint,
Teuchos::Array<size_t>& eis_rowptr,
Teuchos::Array<bool>& edgeIsStrong,
RCP<LocalOrdinalVector>& BlockNumber,
RCP<const Import> remoteOnlyImporter,
RCP<Matrix>& P)
const {
369 SC SC_ZERO = STS::zero();
371 int rank = A.getRowMap()->getComm()->getRank();
377 block_id = BlockNumber->getData(0);
382 size_t Nrows = A.getLocalNumRows();
383 double c_point_density = (double)num_c_points / (num_c_points + num_f_points);
386 double nnz_per_row_est = c_point_density * mean_strong_neighbors_per_row;
388 size_t nnz_est = std::max(Nrows, std::min((
size_t)A.getLocalNumEntries(), (size_t)(nnz_per_row_est * Nrows)));
396 for (
LO row = 0; row < (
LO)Nrows; row++) {
397 size_t row_start = eis_rowptr[row];
401 if (myPointType[row] == DIRICHLET_PT) {
403 }
else if (myPointType[row] == C_PT) {
405 C_hat.insert(cpoint2pcol[row]);
410 A.getLocalRowView(row, indices, vals);
411 for (
LO j = 0; j < indices.
size(); j++)
412 if (myPointType[indices[j]] == C_PT && edgeIsStrong[row_start + j])
413 C_hat.insert(cpoint2pcol[indices[j]]);
417 if (ct + (
size_t)C_hat.size() > (size_t)tmp_colind.
size()) {
418 tmp_colind.
resize(std::max(ct + (
size_t)C_hat.size(), (size_t)2 * tmp_colind.
size()));
422 std::copy(C_hat.begin(), C_hat.end(), tmp_colind.
begin() + ct);
424 tmp_rowptr[row + 1] = tmp_rowptr[row] + C_hat.
size();
427 tmp_colind.
resize(tmp_rowptr[Nrows]);
429 RCP<CrsMatrix> Pcrs = CrsMatrixFactory::Build(A.getRowMap(), coarseColMap, 0);
435 P_rowptr = Teuchos::arcpFromArray(tmp_rowptr);
436 P_colind = Teuchos::arcpFromArray(tmp_colind);
437 P_values.
resize(P_rowptr[Nrows]);
442 Pcrs->allocateAllValues(tmp_rowptr[Nrows], P_rowptr, P_colind, P_values);
443 std::copy(tmp_rowptr.
begin(), tmp_rowptr.
end(), P_rowptr.begin());
444 std::copy(tmp_colind.
begin(), tmp_colind.
end(), P_colind.
begin());
445 Pcrs->setAllValues(P_rowptr, P_colind, P_values);
446 Pcrs->expertStaticFillComplete( coarseDomainMap, A.getDomainMap());
456 if (!remoteOnlyImporter.
is_null()) {
458 RCP<CrsGraph> tempPgraph = CrsGraphFactory::Build(A.getRowMap(), coarseColMap, P_rowptr, P_colind);
459 tempPgraph->fillComplete(coarseDomainMap, A.getDomainMap());
463 Pgraph = Pcrs->getCrsGraph();
466 Pghost = CrsGraphFactory::Build(Pgraph, *remoteOnlyImporter, Pgraph->getDomainMap(), remoteOnlyImporter->getTargetMap());
467 Pghost->getAllIndices(Pghost_rowptr, Pghost_colind);
471 ArrayRCP<LO> Acol_to_Pcol(A.getColMap()->getLocalNumElements(), LO_INVALID);
476 Pghostcol_to_Pcol.
resize(Pghost->getColMap()->getLocalNumElements(), LO_INVALID);
477 for (
LO i = 0; i < (
LO)Pghost->getColMap()->getLocalNumElements(); i++)
478 Pghostcol_to_Pcol[i] = Pgraph->getColMap()->getLocalElement(Pghost->getColMap()->getGlobalElement(i));
484 Aghostcol_to_Acol.
resize(Aghost->getColMap()->getLocalNumElements(), LO_INVALID);
485 for (
LO i = 0; i < (
LO)Aghost->getColMap()->getLocalNumElements(); i++)
486 Aghostcol_to_Acol[i] = A.getColMap()->getLocalElement(Aghost->getColMap()->getGlobalElement(i));
490 for (
LO i = 0; i < (
LO)Nrows; i++) {
491 if (myPointType[i] == DIRICHLET_PT) {
495 printf(
"[%d] ** A(%d,:) is a Dirichlet-Point.\n", rank, i);
497 }
else if (myPointType[i] == C_PT) {
502 printf(
"[%d] ** A(%d,:) is a C-Point.\n", rank, i);
508 printf(
"[%d] ** A(%d,:) is a F-Point.\n", rank, i);
514 A.getLocalRowView(i, A_indices_i, A_vals_i);
515 size_t row_start = eis_rowptr[i];
518 ArrayView<SC> P_vals_i = P_values.
view(P_rowptr[i], P_rowptr[i + 1] - P_rowptr[i]);
521 for (
LO j = 0; j < (
LO)P_vals_i.
size(); j++)
522 P_vals_i[j] = SC_ZERO;
526 for (
LO j = 0; j < (
LO)P_indices_i.
size(); j++) {
527 Acol_to_Pcol[pcol2cpoint[P_indices_i[j]]] = P_rowptr[i] + j;
531 SC first_denominator = SC_ZERO;
535 for (
LO k0 = 0; k0 < (
LO)A_indices_i.
size(); k0++) {
536 LO k = A_indices_i[k0];
537 SC a_ik = A_vals_i[k0];
538 LO pcol_k = Acol_to_Pcol[k];
543 first_denominator += a_ik;
546 printf(
"- A(%d,%d) is the diagonal\n", i, k);
549 }
else if (myPointType[k] == DIRICHLET_PT) {
552 printf(
"- A(%d,%d) is a Dirichlet point\n", i, k);
555 }
else if (pcol_k != LO_INVALID && pcol_k >= (
LO)P_rowptr[i]) {
557 P_values[pcol_k] += a_ik;
559 printf(
"- A(%d,%d) is a strong C-Point\n", i, k);
561 }
else if (!edgeIsStrong[row_start + k0]) {
563 if (block_id.
size() == 0 || block_id[i] == block_id[k]) {
564 first_denominator += a_ik;
566 printf(
"- A(%d,%d) is weak adding to diagonal(%d,%d) (%6.4e)\n", i, k, block_id[i], block_id[k], a_ik);
568 printf(
"- A(%d,%d) is weak but does not match blocks (%d,%d), discarding\n", i, k, block_id[i], block_id[k]);
576 printf(
"- A(%d,%d) is a strong F-Point\n", i, k);
580 SC second_denominator = SC_ZERO;
585 A.getLocalRowView(k, A_indices_k, A_vals_k);
586 for (
LO m0 = 0; m0 < (
LO)A_indices_k.
size(); m0++) {
587 LO m = A_indices_k[m0];
595 sign_akk = Sign(a_kk);
596 for (
LO m0 = 0; m0 < (
LO)A_indices_k.
size(); m0++) {
597 LO m = A_indices_k[m0];
598 if (m != k && Acol_to_Pcol[A_indices_k[m0]] >= (
LO)P_rowptr[i]) {
599 SC a_km = A_vals_k[m0];
600 second_denominator += (Sign(a_km) == sign_akk ? SC_ZERO : a_km);
606 if (second_denominator != SC_ZERO) {
607 for (
LO j0 = 0; j0 < (
LO)A_indices_k.
size(); j0++) {
608 LO j = A_indices_k[j0];
611 if (Acol_to_Pcol[j] >= (
LO)P_rowptr[i]) {
612 SC a_kj = A_vals_k[j0];
613 SC sign_akj_val = sign_akk == Sign(a_kj) ? SC_ZERO : a_kj;
614 P_values[Acol_to_Pcol[j]] += a_ik * sign_akj_val / second_denominator;
616 printf(
"- - Unscaled P(%d,A-%d) += %6.4e = %5.4e\n", i, j, a_ik * sign_akj_val / second_denominator, P_values[Acol_to_Pcol[j]]);
623 printf(
"- - A(%d,%d) second denominator is zero\n", i, k);
625 if (block_id.
size() == 0 || block_id[i] == block_id[k])
626 first_denominator += a_ik;
631 LO kless = k - Nrows;
635 Aghost->getLocalRowView(kless, A_indices_k, A_vals_k);
636 GO k_g = Aghost->getRowMap()->getGlobalElement(kless);
637 for (
LO m0 = 0; m0 < (
LO)A_indices_k.
size(); m0++) {
638 GO m_g = Aghost->getColMap()->getGlobalElement(A_indices_k[m0]);
646 sign_akk = Sign(a_kk);
647 for (
LO m0 = 0; m0 < (
LO)A_indices_k.
size(); m0++) {
648 GO m_g = Aghost->getColMap()->getGlobalElement(A_indices_k[m0]);
649 LO mghost = A_indices_k[m0];
650 LO m = Aghostcol_to_Acol[mghost];
651 if (m_g != k_g && m != LO_INVALID && Acol_to_Pcol[m] >= (
LO)P_rowptr[i]) {
652 SC a_km = A_vals_k[m0];
653 second_denominator += (Sign(a_km) == sign_akk ? SC_ZERO : a_km);
659 if (second_denominator != SC_ZERO) {
660 for (
LO j0 = 0; j0 < (
LO)A_indices_k.
size(); j0++) {
661 LO jghost = A_indices_k[j0];
662 LO j = Aghostcol_to_Acol[jghost];
664 if ((j != LO_INVALID) && (Acol_to_Pcol[j] >= (
LO)P_rowptr[i])) {
665 SC a_kj = A_vals_k[j0];
666 SC sign_akj_val = sign_akk == Sign(a_kj) ? SC_ZERO : a_kj;
667 P_values[Acol_to_Pcol[j]] += a_ik * sign_akj_val / second_denominator;
669 printf(
"- - Unscaled P(%d,A-%d) += %6.4e\n", i, j, a_ik * sign_akj_val / second_denominator);
677 printf(
"- - A(%d,%d) second denominator is zero\n", i, k);
679 if (block_id.
size() == 0 || block_id[i] == block_id[k])
680 first_denominator += a_ik;
688 if (first_denominator != SC_ZERO) {
689 for (
LO j0 = 0; j0 < (
LO)P_indices_i.
size(); j0++) {
691 SC old_pij = P_vals_i[j0];
692 P_vals_i[j0] /= -first_denominator;
693 printf(
"P(%d,%d) = %6.4e = %6.4e / (%6.4e + %6.4e)\n", i, P_indices_i[j0], P_vals_i[j0], old_pij, a_ii, first_denominator - a_ii);
695 P_vals_i[j0] /= -first_denominator;
705 Pcrs->setAllValues(P_rowptr, P_colind, P_values);
706 Pcrs->expertStaticFillComplete( coarseDomainMap, A.getDomainMap());
708 P =
rcp(
new CrsMatrixWrap(Pcrs));
713 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
715 Coarsen_Direct(
const Matrix& A,
const RCP<const Matrix>& Aghost,
const LWGraph& graph,
RCP<const Map>& coarseColMap,
RCP<const Map>& coarseDomainMap,
LO num_c_points,
LO num_f_points,
const Teuchos::ArrayView<const LO>& myPointType,
const Teuchos::ArrayView<const LO>& myPointType_ghost,
const Teuchos::Array<LO>& cpoint2pcol,
const Teuchos::Array<LO>& pcol2cpoint,
Teuchos::Array<size_t>& eis_rowptr,
Teuchos::Array<bool>& edgeIsStrong,
RCP<LocalOrdinalVector>& BlockNumber,
RCP<Matrix>& P)
const {
761 using MT =
typename STS::magnitudeType;
763 size_t Nrows = A.getLocalNumRows();
764 double c_point_density = (double)num_c_points / (num_c_points + num_f_points);
767 double nnz_per_row_est = c_point_density * mean_strong_neighbors_per_row;
769 size_t nnz_est = std::max(Nrows, std::min((
size_t)A.getLocalNumEntries(), (size_t)(nnz_per_row_est * Nrows)));
770 SC SC_ZERO = STS::zero();
771 MT MT_ZERO = MTS::zero();
779 for (
LO row = 0; row < (
LO)Nrows; row++) {
780 size_t row_start = eis_rowptr[row];
784 if (myPointType[row] == DIRICHLET_PT) {
786 }
else if (myPointType[row] == C_PT) {
788 C_hat.insert(cpoint2pcol[row]);
793 A.getLocalRowView(row, indices, vals);
794 for (
LO j = 0; j < indices.
size(); j++)
795 if (myPointType[indices[j]] == C_PT && edgeIsStrong[row_start + j])
796 C_hat.insert(cpoint2pcol[indices[j]]);
800 if (ct + (
size_t)C_hat.size() > (size_t)tmp_colind.
size()) {
801 tmp_colind.
resize(std::max(ct + (
size_t)C_hat.size(), (size_t)2 * tmp_colind.
size()));
805 std::copy(C_hat.begin(), C_hat.end(), tmp_colind.
begin() + ct);
807 tmp_rowptr[row + 1] = tmp_rowptr[row] + C_hat.
size();
810 tmp_colind.
resize(tmp_rowptr[Nrows]);
813 P =
rcp(
new CrsMatrixWrap(A.getRowMap(), coarseColMap, 0));
814 RCP<CrsMatrix> PCrs = rcp_dynamic_cast<CrsMatrixWrap>(P)->getCrsMatrix();
820 printf(
"CMS: Allocating P w/ %d nonzeros\n", (
int)tmp_rowptr[Nrows]);
822 PCrs->allocateAllValues(tmp_rowptr[Nrows], P_rowptr, P_colind, P_values);
826 for (
LO i = 0; i < (
LO)Nrows + 1; i++)
827 P_rowptr[i] = tmp_rowptr[i];
828 for (
LO i = 0; i < (
LO)tmp_rowptr[Nrows]; i++)
829 P_colind[i] = tmp_colind[i];
832 for (
LO i = 0; i < (
LO)Nrows; i++) {
833 if (myPointType[i] == DIRICHLET_PT) {
837 printf(
"** A(%d,:) is a Dirichlet-Point.\n", i);
839 }
else if (myPointType[i] == C_PT) {
844 printf(
"** A(%d,:) is a C-Point.\n", i);
854 A.getLocalRowView(i, A_indices_i, A_vals_i);
855 size_t row_start = eis_rowptr[i];
857 ArrayView<LO> P_indices_i = P_colind.
view(P_rowptr[i], P_rowptr[i + 1] - P_rowptr[i]);
858 ArrayView<SC> P_vals_i = P_values.
view(P_rowptr[i], P_rowptr[i + 1] - P_rowptr[i]);
863 char mylabel[5] =
"FUCD";
865 printf(
"** A(%d,:) = ", i);
866 for (
LO j = 0; j < (
LO)A_indices_i.
size(); j++) {
867 printf(
"%6.4e(%d-%c%c) ", A_vals_i[j], A_indices_i[j], mylabel[1 + myPointType[A_indices_i[j]]], sw[(
int)edgeIsStrong[row_start + j]]);
874 SC pos_numerator = SC_ZERO, neg_numerator = SC_ZERO;
875 SC pos_denominator = SC_ZERO, neg_denominator = SC_ZERO;
877 for (
LO j = 0; j < (
LO)A_indices_i.
size(); j++) {
878 SC a_ik = A_vals_i[j];
879 LO k = A_indices_i[j];
886 if (myPointType[k] == C_PT && edgeIsStrong[row_start + j]) {
887 if (STS::real(a_ik) > MT_ZERO)
888 pos_denominator += a_ik;
890 neg_denominator += a_ik;
896 if (STS::real(a_ik) > MT_ZERO)
897 pos_numerator += a_ik;
899 neg_numerator += a_ik;
902 SC alpha = (neg_denominator == MT_ZERO) ? SC_ZERO : (neg_numerator / neg_denominator);
903 SC beta = (pos_denominator == MT_ZERO) ? SC_ZERO : (pos_numerator / pos_denominator);
908 for (
LO p_j = 0; p_j < (
LO)P_indices_i.
size(); p_j++) {
909 LO P_col = pcol2cpoint[P_indices_i[p_j]];
914 for (
LO a_j = 0; a_j < (
LO)A_indices_i.
size(); a_j++) {
915 if (A_indices_i[a_j] == P_col) {
916 a_ij = A_vals_i[a_j];
920 SC w_ij = (STS::real(a_ij) < 0) ? (alpha * a_ij) : (beta * a_ij);
922 SC alpha_or_beta = (STS::real(a_ij) < 0) ? alpha : beta;
923 printf(
"P(%d,%d/%d) = - %6.4e * %6.4e = %6.4e\n", i, P_indices_i[p_j], pcol2cpoint[P_indices_i[p_j]], alpha_or_beta, a_ij, w_ij);
925 P_vals_i[p_j] = w_ij;
931 PCrs->setAllValues(P_rowptr, P_colind, P_values);
932 PCrs->expertStaticFillComplete( coarseDomainMap, A.getDomainMap());
936 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
938 Coarsen_Ext_Plus_I(
const Matrix& A,
const RCP<const Matrix>& Aghost,
const LWGraph& graph,
RCP<const Map>& coarseColMap,
RCP<const Map>& coarseDomainMap,
LO num_c_points,
LO num_f_points,
const Teuchos::ArrayView<const LO>& myPointType,
const Teuchos::ArrayView<const LO>& myPointType_ghost,
const Teuchos::Array<LO>& cpoint2pcol,
const Teuchos::Array<LO>& pcol2cpoint,
Teuchos::Array<size_t>& eis_rowptr,
Teuchos::Array<bool>& edgeIsStrong,
RCP<LocalOrdinalVector>& BlockNumber,
RCP<Matrix>& P)
const {
977 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
983 size_t Nrows = A.getLocalNumRows();
984 eis_rowptr.
resize(Nrows + 1);
986 if (edgeIsStrong.
size() == 0) {
988 edgeIsStrong.
resize(A.getLocalNumEntries(),
false);
990 edgeIsStrong.
resize(A.getLocalNumEntries(),
false);
991 edgeIsStrong.
assign(A.getLocalNumEntries(),
false);
995 for (
LO i = 0; i < (
LO)Nrows; i++) {
996 LO rowstart = eis_rowptr[i];
999 A.getLocalRowView(i, A_indices, A_values);
1003 LO G_size = (
LO)G_indices.length;
1007 for (
LO j = 0; j < A_size - 1; j++)
1008 if (A_indices[j] >= A_indices[j + 1]) {
1012 for (
LO j = 0; j < G_size - 1; j++)
1013 if (G_indices(j) >= G_indices(j + 1)) {
1020 for (
LO g_idx = 0, a_idx = 0; g_idx < G_size; g_idx++) {
1021 LO col = G_indices(g_idx);
1022 while (A_indices[a_idx] != col && a_idx < A_size) a_idx++;
1023 if (a_idx == A_size) {
1027 edgeIsStrong[rowstart + a_idx] =
true;
1030 eis_rowptr[i + 1] = eis_rowptr[i] + A_size;
1035 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1044 for (
LO i = 0; i < (
LO)d_data.size(); i++) {
1045 if (myPointType[i] == C_PT) {
1046 d_data[i] = coarseMap->getGlobalElement(ct);
1049 d_data[i] = GO_INVALID;
1064 for (
LO i = 0; i < (
LO)c_data.
size(); i++) {
1065 if (c_data[i] != GO_INVALID) {
1066 c_gids[count] = c_data[i];
1071 std::vector<size_t> stridingInfo_(1);
1072 stridingInfo_[0] = 1;
1073 GO domainGIDOffset = 0;
1075 coarseColMap = StridedMapFactory::Build(coarseMap->lib(),
1077 c_gids.view(0, count),
1078 coarseMap->getIndexBase(),
1080 coarseMap->getComm(),
1086 #define MUELU_CLASSICALPFACTORY_SHORT
1087 #endif // MUELU_CLASSICALPFACTORY_DEF_HPP
void GenerateStrengthFlags(const Matrix &A, const LWGraph &graph, Teuchos::Array< size_t > &eis_rowptr, Teuchos::Array< bool > &edgeIsStrong) const
void setValidator(RCP< const ParameterEntryValidator > const &validator)
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)
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
static void Write(const std::string &fileName, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &M)
void GhostCoarseMap(const Matrix &A, const Import &Importer, const ArrayRCP< const LO > myPointType, const RCP< const Map > &coarseMap, RCP< const Map > &coarseColMap) const
Print additional debugging information.
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
void Coarsen_ClassicalModified(const Matrix &A, const RCP< const Matrix > &Aghost, const LWGraph &graph, RCP< const Map > &coarseColMap, RCP< const Map > &coarseDomainMap, LO num_c_points, LO num_f_points, const Teuchos::ArrayView< const LO > &myPointType, const Teuchos::ArrayView< const LO > &myPointType_ghost, const Teuchos::Array< LO > &cpoint2pcol, const Teuchos::Array< LO > &pcol2cpoint, Teuchos::Array< size_t > &eis_rowptr, Teuchos::Array< bool > &edgeIsStrong, RCP< LocalOrdinalVector > &BlockNumber, RCP< const Import > remoteOnlyImporter, RCP< Matrix > &P) const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
KOKKOS_INLINE_FUNCTION size_type GetNodeNumVertices() const
Return number of graph vertices.
KOKKOS_INLINE_FUNCTION size_type GetNodeNumEdges() const
Return number of graph edges.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
void resize(const size_type n, const T &val=T())
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
void Coarsen_Ext_Plus_I(const Matrix &A, const RCP< const Matrix > &Aghost, const LWGraph &graph, RCP< const Map > &coarseColMap, RCP< const Map > &coarseDomainMap, LO num_c_points, LO num_f_points, const Teuchos::ArrayView< const LO > &myPointType, const Teuchos::ArrayView< const LO > &myPointType_ghost, const Teuchos::Array< LO > &cpoint2pcol, const Teuchos::Array< LO > &pcol2cpoint, Teuchos::Array< size_t > &eis_rowptr, Teuchos::Array< bool > &edgeIsStrong, RCP< LocalOrdinalVector > &BlockNumber, RCP< Matrix > &P) const
void resize(size_type new_size, const value_type &x=value_type())
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
KOKKOS_INLINE_FUNCTION neighbor_vertices_type getNeighborVertices(LO i) const
Return the list of vertices adjacent to the vertex 'v'.
#define SET_VALID_ENTRY(name)
Lightweight MueLu representation of a compressed row storage graph.
void Coarsen_Direct(const Matrix &A, const RCP< const Matrix > &Aghost, const LWGraph &graph, RCP< const Map > &coarseColMap, RCP< const Map > &coarseDomainMap, LO num_c_points, LO num_f_points, const Teuchos::ArrayView< const LO > &myPointType, const Teuchos::ArrayView< const LO > &myPointType_ghost, const Teuchos::Array< LO > &cpoint2pcol, const Teuchos::Array< LO > &pcol2cpoint, Teuchos::Array< size_t > &eis_rowptr, Teuchos::Array< bool > &edgeIsStrong, RCP< LocalOrdinalVector > &BlockNumber, RCP< Matrix > &P) const
int GetLevelID() const
Return level number.
typename ClassicalMapFactory::point_type point_type
Exception throws to report errors in the internal logical of the program.
#define TEUCHOS_ASSERT(assertion_test)
void assign(size_type n, const value_type &val)
ParameterEntry & getEntry(const std::string &name)
ArrayView< T > view(size_type lowerOffset, size_type size) const