98 typedef Teuchos::ScalarTraits<SC> STS;
100 if (predrop_ != Teuchos::null)
101 GetOStream(
Parameters0) << predrop_->description();
103 RCP<Matrix> A = Get<RCP<Matrix> >(currentLevel,
"A");
105 const ParameterList& pL = GetParameterList();
107 LO nPDEs = A->GetFixedBlockSize();
109 RCP<MultiVector> testVecs;
110 RCP<MultiVector> nearNull;
113 testVecs = Xpetra::IO<SC, LO, GO, Node>::ReadMultiVector(
"TpetraTVecs.mm", A->getRowMap());
115 size_t numRandom = as<size_t>(pL.get<
int>(
"aggregation: number of random vectors"));
116 testVecs = MultiVectorFactory::Build(A->getRowMap(), numRandom,
true);
119 testVecs->randomize();
120 for (
size_t kk = 0; kk < testVecs->getNumVectors(); kk++) {
121 Teuchos::ArrayRCP<Scalar> curVec = testVecs->getDataNonConst(kk);
122 for (
size_t ii = kk; ii < as<size_t>(A->getRowMap()->getLocalNumElements()); ii++) curVec[ii] = Teuchos::ScalarTraits<SC>::magnitude(curVec[ii]);
124 nearNull = MultiVectorFactory::Build(A->getRowMap(), nPDEs,
true);
127 for (
size_t kk = 0; kk < nearNull->getNumVectors(); kk++) {
128 Teuchos::ArrayRCP<Scalar> curVec = nearNull->getDataNonConst(kk);
129 for (
size_t ii = kk; ii < as<size_t>(A->getRowMap()->getLocalNumElements()); ii += nearNull->getNumVectors()) curVec[ii] = Teuchos::ScalarTraits<Scalar>::one();
132 RCP<MultiVector> zeroVec_TVecs;
133 RCP<MultiVector> zeroVec_Null;
135 zeroVec_TVecs = MultiVectorFactory::Build(A->getRowMap(), testVecs->getNumVectors(),
true);
136 zeroVec_Null = MultiVectorFactory::Build(A->getRowMap(), nPDEs,
true);
137 zeroVec_TVecs->putScalar(Teuchos::ScalarTraits<Scalar>::zero());
138 zeroVec_Null->putScalar(Teuchos::ScalarTraits<Scalar>::zero());
140 size_t nInvokeSmoother = as<size_t>(pL.get<
int>(
"aggregation: number of times to pre or post smooth"));
142 RCP<SmootherBase> preSmoo = currentLevel.
Get<RCP<SmootherBase> >(
"PreSmoother");
143 for (
size_t ii = 0; ii < nInvokeSmoother; ii++) preSmoo->Apply(*testVecs, *zeroVec_TVecs,
false);
144 for (
size_t ii = 0; ii < nInvokeSmoother; ii++) preSmoo->Apply(*nearNull, *zeroVec_Null,
false);
145 }
else if (currentLevel.
IsAvailable(
"PostSmoother")) {
146 RCP<SmootherBase> postSmoo = currentLevel.
Get<RCP<SmootherBase> >(
"PostSmoother");
147 for (
size_t ii = 0; ii < nInvokeSmoother; ii++) postSmoo->Apply(*testVecs, *zeroVec_TVecs,
false);
148 for (
size_t ii = 0; ii < nInvokeSmoother; ii++) postSmoo->Apply(*nearNull, *zeroVec_Null,
false);
152 Teuchos::ArrayRCP<Scalar> penaltyPolyCoef(5);
153 Teuchos::ArrayView<const double> inputPolyCoef;
161 if (pL.isParameter(
"aggregation: penalty parameters") && pL.get<Teuchos::Array<double> >(
"aggregation: penalty parameters").size() > 0) {
162 if (pL.get<Teuchos::Array<double> >(
"aggregation: penalty parameters").size() > penaltyPolyCoef.size())
163 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"Number of penalty parameters must be " << penaltyPolyCoef.size() <<
" or less");
164 inputPolyCoef = pL.get<Teuchos::Array<double> >(
"aggregation: penalty parameters")();
166 for (
size_t i = 0; i < as<size_t>(inputPolyCoef.size()); i++) penaltyPolyCoef[i] = as<Scalar>(inputPolyCoef[i]);
167 for (
size_t i = as<size_t>(inputPolyCoef.size()); i < as<size_t>(penaltyPolyCoef.size()); i++) penaltyPolyCoef[i] = Teuchos::ScalarTraits<Scalar>::zero();
170 RCP<LWGraph> filteredGraph;
171 badGuysCoalesceDrop(*A, penaltyPolyCoef, nPDEs, *testVecs, *nearNull, filteredGraph);
176 FILE* fp = fopen(
"codeOutput",
"w");
177 fprintf(fp,
"%d %d %d\n", (
int)filteredGraph->GetNodeNumVertices(), (
int)filteredGraph->GetNodeNumVertices(),
178 (
int)filteredGraph->GetNodeNumEdges());
179 for (
size_t i = 0; i < filteredGraph->GetNodeNumVertices(); i++) {
180 auto inds = filteredGraph->getNeighborVertices(as<LO>(i));
181 for (
size_t j = 0; j < as<size_t>(inds.size()); j++) {
182 fprintf(fp,
"%d %d 1.00e+00\n", (
int)i + 1, (
int)inds[j] + 1);
189 Set<bool>(currentLevel,
"Filtering", (threshold != STS::zero()));
190 Set(currentLevel,
"Graph", filteredGraph);
191 Set(currentLevel,
"DofsPerNode", 1);
234 GO numMyNnz = Teuchos::as<GO>(Amat.getLocalNumEntries());
235 size_t nLoc = Amat.getRowMap()->getLocalNumElements();
237 size_t nBlks = nLoc / nPDEs;
238 if (nBlks * nPDEs != nLoc)
241 typename LWGraph::row_type::non_const_type newRowPtr(
"newRowPtr", nBlks + 1);
242 Teuchos::ArrayRCP<LO> newCols(numMyNnz);
244 Teuchos::ArrayRCP<LO> bcols(nBlks);
245 Teuchos::ArrayRCP<bool> keepOrNot(nBlks);
249 LO maxNzPerRow = 200;
250 Teuchos::ArrayRCP<Scalar> penalties(maxNzPerRow);
253 Teuchos::ArrayRCP<bool> keepStatus(nBlks,
true);
254 Teuchos::ArrayRCP<LO> bColList(nBlks);
264 Teuchos::ArrayRCP<bool> alreadyOnBColList(nBlks,
false);
270 Kokkos::deep_copy(boundaryNodes,
false);
272 for (LO i = 0; i < maxNzPerRow; i++)
276 (penaltyPolyCoef[
poly3rdOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i))) +
277 (penaltyPolyCoef[
poly4thOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i * i)));
279 LO nzTotal = 0, numBCols = 0, row = -1, Nbcols, bcol;
283 for (LO i = 0; i < as<LO>(nBlks); i++) {
284 newRowPtr[i + 1] = newRowPtr[i];
285 for (LO j = 0; j < nPDEs; j++) {
288 Teuchos::ArrayView<const LocalOrdinal> indices;
289 Teuchos::ArrayView<const Scalar> vals;
291 Amat.getLocalRowView(row, indices, vals);
293 if (indices.size() > maxNzPerRow) {
294 LO oldSize = maxNzPerRow;
295 maxNzPerRow = indices.size() + 100;
296 penalties.resize(as<size_t>(maxNzPerRow), 0.0);
297 for (LO k = oldSize; k < maxNzPerRow; k++)
301 (penaltyPolyCoef[
poly3rdOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i))) +
302 (penaltyPolyCoef[
poly4thOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i * i)));
304 badGuysDropfunc(row, indices, vals, testVecs, nPDEs, penalties, nearNull, bcols, keepOrNot, Nbcols, nLoc);
305 for (LO k = 0; k < Nbcols; k++) {
310 if (alreadyOnBColList[bcol] ==
false) {
311 bColList[numBCols++] = bcol;
312 alreadyOnBColList[bcol] =
true;
316 if (keepOrNot[k] ==
false) keepStatus[bcol] =
false;
324 if (numBCols < 2) boundaryNodes[i] =
true;
325 for (LO j = 0; j < numBCols; j++) {
327 if (keepStatus[bcol] ==
true) {
328 newCols[nzTotal] = bColList[j];
330 nzTotal = nzTotal + 1;
332 keepStatus[bcol] =
true;
333 alreadyOnBColList[bcol] =
false;
341 typename LWGraph::entries_type::non_const_type finalCols(
"finalCols", nzTotal);
342 for (LO i = 0; i < nzTotal; i++) finalCols(i) = newCols[i];
347 RCP<const Map> rowMap = Amat.getRowMap();
349 LO nAmalgNodesOnProc = rowMap->getLocalNumElements() / nPDEs;
350 Teuchos::Array<GO> nodalGIDs(nAmalgNodesOnProc);
351 typename Teuchos::ScalarTraits<Scalar>::coordinateType temp;
352 for (
size_t i = 0; i < as<size_t>(nAmalgNodesOnProc); i++) {
353 GO gid = rowMap->getGlobalElement(i * nPDEs);
354 temp = ((
typename Teuchos::ScalarTraits<Scalar>::coordinateType)(gid)) / ((
typename Teuchos::ScalarTraits<Scalar>::coordinateType)(nPDEs));
355 nodalGIDs[i] = as<GO>(floor(temp));
357 GO nAmalgNodesGlobal = rowMap->getGlobalNumElements();
358 GO nBlkGlobal = nAmalgNodesGlobal / nPDEs;
359 if (nBlkGlobal * nPDEs != nAmalgNodesGlobal)
362 Teuchos::RCP<Map> AmalgRowMap = MapFactory::Build(rowMap->lib(), nBlkGlobal,
363 nodalGIDs(), 0, rowMap->getComm());
365 filteredGraph = rcp(
new LWGraph(newRowPtr, finalCols, AmalgRowMap, AmalgRowMap,
"thresholded graph of A"));
366 filteredGraph->SetBoundaryNodeMap(boundaryNodes);
370void SmooVecCoalesceDropFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::badGuysDropfunc(LO row,
const Teuchos::ArrayView<const LocalOrdinal>& cols,
const Teuchos::ArrayView<const Scalar>& vals,
const MultiVector& testVecs, LO nPDEs, Teuchos::ArrayRCP<Scalar>& penalties,
const MultiVector& nearNull, Teuchos::ArrayRCP<LO>& Bcols, Teuchos::ArrayRCP<bool>& keepOrNot, LO& Nbcols, LO nLoc)
const {
371 using TST = Teuchos::ScalarTraits<Scalar>;
373 LO nLeng = cols.size();
374 typename TST::coordinateType temp;
375 temp = ((
typename TST::coordinateType)(row)) / ((
typename TST::coordinateType)(nPDEs));
376 LO blkRow = as<LO>(floor(temp));
377 Teuchos::ArrayRCP<Scalar> badGuy(nLeng, 0.0);
378 Teuchos::ArrayRCP<Scalar> subNull(nLeng, 0.0);
391 for (LO i = 0; i < nLeng; i++) keepOrNot[i] =
false;
395 LO rowDof = row - blkRow * nPDEs;
396 Teuchos::ArrayRCP<const Scalar> oneNull = nearNull.getData(as<size_t>(rowDof));
398 for (LO i = 0; i < nLeng; i++) {
399 if ((cols[i] < nLoc) && (TST::magnitude(vals[i]) != 0.0)) {
400 temp = ((
typename TST::coordinateType)(cols[i])) / ((
typename TST::coordinateType)(nPDEs));
401 LO colDof = cols[i] - (as<LO>(floor(temp))) * nPDEs;
402 if (colDof == rowDof) {
403 Bcols[Nbcols] = (cols[i] - colDof) / nPDEs;
404 subNull[Nbcols] = oneNull[cols[i]];
406 if (cols[i] != row) {
407 Scalar worstRatio = -TST::one();
408 Scalar targetRatio = subNull[Nbcols] / oneNull[row];
410 for (
size_t kk = 0; kk < testVecs.getNumVectors(); kk++) {
411 Teuchos::ArrayRCP<const Scalar> curVec = testVecs.getData(kk);
412 actualRatio = curVec[cols[i]] / curVec[row];
413 if (TST::magnitude(actualRatio - targetRatio) > TST::magnitude(worstRatio)) {
414 badGuy[Nbcols] = actualRatio;
415 worstRatio = Teuchos::ScalarTraits<SC>::magnitude(actualRatio - targetRatio);
420 keepOrNot[Nbcols] =
true;
431 Bcols[Nbcols] = (row - rowDof) / nPDEs;
432 subNull[Nbcols] = 1.;
434 keepOrNot[Nbcols] =
true;
439 Scalar currentRP = oneNull[row] * oneNull[row];
440 Scalar currentRTimesBadGuy = oneNull[row] * badGuy[diagInd];
441 Scalar currentScore = penalties[0];
452 LO nKeep = 1, flag = 1, minId;
453 Scalar minFit, minFitRP = 0., minFitRTimesBadGuy = 0.;
454 Scalar newRP, newRTimesBadGuy;
463 for (LO i = 0; i < Nbcols; i++) {
464 if (keepOrNot[i] ==
false) {
466 newRP = currentRP + subNull[i] * subNull[i];
467 newRTimesBadGuy = currentRTimesBadGuy + subNull[i] * badGuy[i];
468 Scalar ratio = newRTimesBadGuy / newRP;
471 for (LO k = 0; k < Nbcols; k++) {
472 if (keepOrNot[k] ==
true) {
473 Scalar diff = badGuy[k] - ratio * subNull[k];
474 newFit = newFit + diff * diff;
477 if (Teuchos::ScalarTraits<SC>::magnitude(newFit) < Teuchos::ScalarTraits<SC>::magnitude(minFit)) {
481 minFitRTimesBadGuy = newRTimesBadGuy;
483 keepOrNot[i] =
false;
489 minFit = sqrt(minFit);
490 Scalar newScore = penalties[nKeep] + minFit;
491 if (Teuchos::ScalarTraits<SC>::magnitude(newScore) < Teuchos::ScalarTraits<SC>::magnitude(currentScore)) {
493 keepOrNot[minId] =
true;
494 currentScore = newScore;
495 currentRP = minFitRP;
496 currentRTimesBadGuy = minFitRTimesBadGuy;