114 RCP<const Matrix> A = Get<RCP<Matrix> >(fineLevel,
"A");
115 RCP<const Map> ownedCoarseMap = Get<RCP<const Map> >(fineLevel,
"CoarseMap");
116 RCP<const LocalOrdinalVector> owned_fc_splitting = Get<RCP<LocalOrdinalVector> >(fineLevel,
"FC Splitting");
117 RCP<const LWGraph> graph = Get<RCP<LWGraph> >(fineLevel,
"Graph");
120 RCP<const Import> Importer = A->getCrsGraph()->getImporter();
121 Xpetra::UnderlyingLib lib = ownedCoarseMap->lib();
126 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
129 const ParameterList& pL = GetParameterList();
132 TEUCHOS_TEST_FOR_EXCEPTION(A->GetFixedBlockSize() != 1,
Exceptions::RuntimeError,
"ClassicalPFactory: Multiple PDEs per node not supported yet");
135 TEUCHOS_TEST_FOR_EXCEPTION(!A->getRowMap()->isSameAs(*A->getDomainMap()),
Exceptions::RuntimeError,
"ClassicalPFactory: MPI Ranks > 1 not supported yet");
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;
153 RCP<const LocalOrdinalVector> fc_splitting;
154 ArrayRCP<const LO> myPointType;
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);
165 RCP<const Matrix> Aghost;
166 RCP<const LocalOrdinalVector> fc_splitting_ghost;
167 ArrayRCP<const LO> myPointType_ghost;
168 RCP<const Import> remoteOnlyImporter;
169 if (need_ghost_rows && !Importer.is_null()) {
170 ArrayView<const LO> remoteLIDs = Importer->getRemoteLIDs();
171 size_t numRemote = Importer->getNumRemoteIDs();
172 Array<GO> remoteRows(numRemote);
173 for (
size_t i = 0; i < numRemote; i++)
174 remoteRows[i] = Importer->getTargetMap()->getGlobalElement(remoteLIDs[i]);
176 RCP<const Map> remoteRowMap = MapFactory::Build(lib, Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), remoteRows(),
177 A->getDomainMap()->getIndexBase(), A->getDomainMap()->getComm());
179 remoteOnlyImporter = Importer->createRemoteOnlyImport(remoteRowMap);
180 RCP<const CrsMatrix> Acrs = rcp_dynamic_cast<const CrsMatrixWrap>(A)->getCrsMatrix();
181 RCP<CrsMatrix> Aghost_crs = CrsMatrixFactory::Build(Acrs, *remoteOnlyImporter, A->getDomainMap(), remoteOnlyImporter->getTargetMap());
182 Aghost = rcp(
new CrsMatrixWrap(Aghost_crs));
195 RCP<const Map> coarseMap;
196 if (Importer.is_null())
197 coarseMap = ownedCoarseMap;
200 GhostCoarseMap(*A, *Importer, myPointType, ownedCoarseMap, coarseMap);
204 RCP<LocalOrdinalVector> BlockNumber;
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") {
207 RCP<LocalOrdinalVector> OwnedBlockNumber;
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)
219 RCP<const CrsMatrix> Acrs = rcp_dynamic_cast<const CrsMatrixWrap>(A)->getCrsMatrix();
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);
226 RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(ofs));
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");
232 using real_type =
typename Teuchos::ScalarTraits<SC>::magnitudeType;
233 using RealValuedMultiVector =
typename Xpetra::MultiVector<real_type, LO, GO, NO>;
234 typedef Xpetra::MultiVectorFactory<real_type, LO, GO, NO> RealValuedMultiVectorFactory;
236 RCP<RealValuedMultiVector> mv = RealValuedMultiVectorFactory::Build(fc_splitting->getMap(), 1);
237 ArrayRCP<real_type> mv_data = mv->getDataNonConst(0);
240 ArrayRCP<const LO> fc_data = fc_splitting->getData(0);
241 for (LO i = 0; i < (LO)fc_data.size(); i++)
242 mv_data[i] = Teuchos::as<real_type>(fc_data[i]);
243 Xpetra::IO<real_type, LO, GO, NO>::Write(out_fc, *mv);
246 if (!BlockNumber.is_null()) {
247 RCP<RealValuedMultiVector> mv2 = RealValuedMultiVectorFactory::Build(BlockNumber->getMap(), 1);
248 ArrayRCP<real_type> mv_data2 = mv2->getDataNonConst(0);
249 ArrayRCP<const LO> b_data = BlockNumber->getData(0);
250 for (LO i = 0; i < (LO)b_data.size(); i++) {
251 mv_data2[i] = Teuchos::as<real_type>(b_data[i]);
253 Xpetra::IO<real_type, LO, GO, NO>::Write(out_block, *mv2);
265 Array<LO> cpoint2pcol(myPointType.size(), LO_INVALID);
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;
283 Teuchos::Array<size_t> eis_rowptr;
284 Teuchos::Array<bool> edgeIsStrong;
287 GenerateStrengthFlags(*A, *graph, eis_rowptr, edgeIsStrong);
291 RCP<const Map> coarseColMap = coarseMap;
292 RCP<const Map> coarseDomainMap = ownedCoarseMap;
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);
306 Xpetra::IO<SC, LO, GO, NO>::Write(
"classical_p.mat." + std::to_string(coarseLevel.
GetLevelID()), *P);
311 Set(coarseLevel,
"P", P);
312 RCP<const CrsGraph> pg = P->getCrsGraph();
313 Set(coarseLevel,
"P Graph", pg);
320 RCP<ParameterList> params = rcp(
new ParameterList());
321 params->set(
"printLoadBalancingInfo",
true);
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 {
366 using STS =
typename Teuchos::ScalarTraits<SC>;
367 LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
369 SC SC_ZERO = STS::zero();
371 int rank = A.getRowMap()->getComm()->getRank();
375 ArrayRCP<const LO> block_id;
376 if (!BlockNumber.is_null())
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)));
389 Array<size_t> tmp_rowptr(Nrows + 1);
390 Array<LO> tmp_colind(nnz_est);
396 for (LO row = 0; row < (LO)Nrows; row++) {
397 size_t row_start = eis_rowptr[row];
398 ArrayView<const LO> indices;
399 ArrayView<const SC> vals;
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);
430 ArrayRCP<size_t> P_rowptr;
431 ArrayRCP<LO> P_colind;
432 ArrayRCP<SC> P_values;
434 if (A.getRowMap()->lib() == Xpetra::UseTpetra) {
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());
450 RCP<const CrsGraph> Pgraph;
451 RCP<const CrsGraph> Pghost;
454 ArrayRCP<const size_t> Pghost_rowptr;
455 ArrayRCP<const LO> Pghost_colind;
456 if (!remoteOnlyImporter.is_null()) {
457 if (A.getRowMap()->lib() == Xpetra::UseTpetra) {
458 RCP<CrsGraph> tempPgraph = CrsGraphFactory::Build(A.getRowMap(), coarseColMap, P_rowptr, P_colind);
459 tempPgraph->fillComplete(coarseDomainMap, A.getDomainMap());
463 Pgraph = Pcrs->getCrsGraph();
465 TEUCHOS_ASSERT(!Pgraph.is_null());
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);
474 ArrayRCP<LO> Pghostcol_to_Pcol;
475 if (!Pghost.is_null()) {
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));
482 ArrayRCP<LO> Aghostcol_to_Acol;
483 if (!Aghost.is_null()) {
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) {
499 P_values[P_rowptr[i]] = Teuchos::ScalarTraits<SC>::one();
502 printf(
"[%d] ** A(%d,:) is a C-Point.\n", rank, i);
508 printf(
"[%d] ** A(%d,:) is a F-Point.\n", rank, i);
512 ArrayView<const LO> A_indices_i, A_indices_k;
513 ArrayView<const SC> A_vals_i, A_vals_k;
514 A.getLocalRowView(i, A_indices_i, A_vals_i);
515 size_t row_start = eis_rowptr[i];
517 ArrayView<const LO> P_indices_i = P_colind.view(P_rowptr[i], P_rowptr[i + 1] - P_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));
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 {
760 using STS =
typename Teuchos::ScalarTraits<SC>;
761 using MT =
typename STS::magnitudeType;
762 using MTS =
typename Teuchos::ScalarTraits<MT>;
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();
772 Array<size_t> tmp_rowptr(Nrows + 1);
773 Array<LO> tmp_colind(nnz_est);
779 for (LO row = 0; row < (LO)Nrows; row++) {
780 size_t row_start = eis_rowptr[row];
781 ArrayView<const LO> indices;
782 ArrayView<const SC> vals;
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 = toCrsMatrix(P);
815 ArrayRCP<size_t> P_rowptr;
816 ArrayRCP<LO> P_colind;
817 ArrayRCP<SC> P_values;
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);
823 TEUCHOS_TEST_FOR_EXCEPTION(tmp_rowptr.size() != P_rowptr.size(),
Exceptions::RuntimeError,
"ClassicalPFactory: Allocation size error (rowptr)");
824 TEUCHOS_TEST_FOR_EXCEPTION(tmp_colind.size() != P_colind.size(),
Exceptions::RuntimeError,
"ClassicalPFactory: Allocation size error (colind)");
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) {
841 P_values[P_rowptr[i]] = Teuchos::ScalarTraits<SC>::one();
844 printf(
"** A(%d,:) is a C-Point.\n", i);
852 ArrayView<const LO> A_indices_i, A_incides_k;
853 ArrayView<const SC> A_vals_i, A_indices_k;
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());