97 typedef Teuchos::ScalarTraits<SC> STS;
99 if (predrop_ != Teuchos::null)
100 GetOStream(
Parameters0) << predrop_->description();
102 RCP<Matrix> A = Get<RCP<Matrix> >(currentLevel,
"A");
104 const ParameterList& pL = GetParameterList();
106 LO nPDEs = A->GetFixedBlockSize();
108 RCP<MultiVector> testVecs;
109 RCP<MultiVector> nearNull;
112 testVecs = Xpetra::IO<SC, LO, GO, Node>::ReadMultiVector(
"TpetraTVecs.mm", A->getRowMap());
114 size_t numRandom = as<size_t>(pL.get<
int>(
"aggregation: number of random vectors"));
115 testVecs = MultiVectorFactory::Build(A->getRowMap(), numRandom,
true);
118 testVecs->randomize();
119 for (
size_t kk = 0; kk < testVecs->getNumVectors(); kk++) {
120 Teuchos::ArrayRCP<Scalar> curVec = testVecs->getDataNonConst(kk);
121 for (
size_t ii = kk; ii < as<size_t>(A->getRowMap()->getLocalNumElements()); ii++) curVec[ii] = Teuchos::ScalarTraits<SC>::magnitude(curVec[ii]);
123 nearNull = MultiVectorFactory::Build(A->getRowMap(), nPDEs,
true);
126 for (
size_t kk = 0; kk < nearNull->getNumVectors(); kk++) {
127 Teuchos::ArrayRCP<Scalar> curVec = nearNull->getDataNonConst(kk);
128 for (
size_t ii = kk; ii < as<size_t>(A->getRowMap()->getLocalNumElements()); ii += nearNull->getNumVectors()) curVec[ii] = Teuchos::ScalarTraits<Scalar>::one();
131 RCP<MultiVector> zeroVec_TVecs;
132 RCP<MultiVector> zeroVec_Null;
134 zeroVec_TVecs = MultiVectorFactory::Build(A->getRowMap(), testVecs->getNumVectors(),
true);
135 zeroVec_Null = MultiVectorFactory::Build(A->getRowMap(), nPDEs,
true);
136 zeroVec_TVecs->putScalar(Teuchos::ScalarTraits<Scalar>::zero());
137 zeroVec_Null->putScalar(Teuchos::ScalarTraits<Scalar>::zero());
139 size_t nInvokeSmoother = as<size_t>(pL.get<
int>(
"aggregation: number of times to pre or post smooth"));
141 RCP<SmootherBase> preSmoo = currentLevel.
Get<RCP<SmootherBase> >(
"PreSmoother");
142 for (
size_t ii = 0; ii < nInvokeSmoother; ii++) preSmoo->Apply(*testVecs, *zeroVec_TVecs,
false);
143 for (
size_t ii = 0; ii < nInvokeSmoother; ii++) preSmoo->Apply(*nearNull, *zeroVec_Null,
false);
144 }
else if (currentLevel.
IsAvailable(
"PostSmoother")) {
145 RCP<SmootherBase> postSmoo = currentLevel.
Get<RCP<SmootherBase> >(
"PostSmoother");
146 for (
size_t ii = 0; ii < nInvokeSmoother; ii++) postSmoo->Apply(*testVecs, *zeroVec_TVecs,
false);
147 for (
size_t ii = 0; ii < nInvokeSmoother; ii++) postSmoo->Apply(*nearNull, *zeroVec_Null,
false);
151 Teuchos::ArrayRCP<Scalar> penaltyPolyCoef(5);
152 Teuchos::ArrayView<const double> inputPolyCoef;
160 if (pL.isParameter(
"aggregation: penalty parameters") && pL.get<Teuchos::Array<double> >(
"aggregation: penalty parameters").size() > 0) {
161 if (pL.get<Teuchos::Array<double> >(
"aggregation: penalty parameters").size() > penaltyPolyCoef.size())
162 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"Number of penalty parameters must be " << penaltyPolyCoef.size() <<
" or less");
163 inputPolyCoef = pL.get<Teuchos::Array<double> >(
"aggregation: penalty parameters")();
165 for (
size_t i = 0; i < as<size_t>(inputPolyCoef.size()); i++) penaltyPolyCoef[i] = as<Scalar>(inputPolyCoef[i]);
166 for (
size_t i = as<size_t>(inputPolyCoef.size()); i < as<size_t>(penaltyPolyCoef.size()); i++) penaltyPolyCoef[i] = Teuchos::ScalarTraits<Scalar>::zero();
169 RCP<LWGraph> filteredGraph;
170 badGuysCoalesceDrop(*A, penaltyPolyCoef, nPDEs, *testVecs, *nearNull, filteredGraph);
175 FILE* fp = fopen(
"codeOutput",
"w");
176 fprintf(fp,
"%d %d %d\n", (
int)filteredGraph->GetNodeNumVertices(), (
int)filteredGraph->GetNodeNumVertices(),
177 (
int)filteredGraph->GetNodeNumEdges());
178 for (
size_t i = 0; i < filteredGraph->GetNodeNumVertices(); i++) {
179 auto inds = filteredGraph->getNeighborVertices(as<LO>(i));
180 for (
size_t j = 0; j < as<size_t>(inds.size()); j++) {
181 fprintf(fp,
"%d %d 1.00e+00\n", (
int)i + 1, (
int)inds[j] + 1);
188 Set<bool>(currentLevel,
"Filtering", (threshold != STS::zero()));
189 Set(currentLevel,
"Graph", filteredGraph);
190 Set(currentLevel,
"DofsPerNode", 1);
233 GO numMyNnz = Teuchos::as<GO>(Amat.getLocalNumEntries());
234 size_t nLoc = Amat.getRowMap()->getLocalNumElements();
236 size_t nBlks = nLoc / nPDEs;
237 if (nBlks * nPDEs != nLoc)
240 typename LWGraph::row_type::non_const_type newRowPtr(
"newRowPtr", nBlks + 1);
241 Teuchos::ArrayRCP<LO> newCols(numMyNnz);
243 Teuchos::ArrayRCP<LO> bcols(nBlks);
244 Teuchos::ArrayRCP<bool> keepOrNot(nBlks);
248 LO maxNzPerRow = 200;
249 Teuchos::ArrayRCP<Scalar> penalties(maxNzPerRow);
252 Teuchos::ArrayRCP<bool> keepStatus(nBlks,
true);
253 Teuchos::ArrayRCP<LO> bColList(nBlks);
263 Teuchos::ArrayRCP<bool> alreadyOnBColList(nBlks,
false);
269 Kokkos::deep_copy(boundaryNodes,
false);
271 for (LO i = 0; i < maxNzPerRow; i++)
275 (penaltyPolyCoef[
poly3rdOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i))) +
276 (penaltyPolyCoef[
poly4thOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i * i)));
278 LO nzTotal = 0, numBCols = 0, row = -1, Nbcols, bcol;
282 for (LO i = 0; i < as<LO>(nBlks); i++) {
283 newRowPtr[i + 1] = newRowPtr[i];
284 for (LO j = 0; j < nPDEs; j++) {
287 Teuchos::ArrayView<const LocalOrdinal> indices;
288 Teuchos::ArrayView<const Scalar> vals;
290 Amat.getLocalRowView(row, indices, vals);
292 if (indices.size() > maxNzPerRow) {
293 LO oldSize = maxNzPerRow;
294 maxNzPerRow = indices.size() + 100;
295 penalties.resize(as<size_t>(maxNzPerRow), 0.0);
296 for (LO k = oldSize; k < maxNzPerRow; k++)
300 (penaltyPolyCoef[
poly3rdOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i))) +
301 (penaltyPolyCoef[
poly4thOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i * i)));
303 badGuysDropfunc(row, indices, vals, testVecs, nPDEs, penalties, nearNull, bcols, keepOrNot, Nbcols, nLoc);
304 for (LO k = 0; k < Nbcols; k++) {
309 if (alreadyOnBColList[bcol] ==
false) {
310 bColList[numBCols++] = bcol;
311 alreadyOnBColList[bcol] =
true;
315 if (keepOrNot[k] ==
false) keepStatus[bcol] =
false;
323 if (numBCols < 2) boundaryNodes[i] =
true;
324 for (LO j = 0; j < numBCols; j++) {
326 if (keepStatus[bcol] ==
true) {
327 newCols[nzTotal] = bColList[j];
329 nzTotal = nzTotal + 1;
331 keepStatus[bcol] =
true;
332 alreadyOnBColList[bcol] =
false;
340 typename LWGraph::entries_type::non_const_type finalCols(
"finalCols", nzTotal);
341 for (LO i = 0; i < nzTotal; i++) finalCols(i) = newCols[i];
346 RCP<const Map> rowMap = Amat.getRowMap();
348 LO nAmalgNodesOnProc = rowMap->getLocalNumElements() / nPDEs;
349 Teuchos::Array<GO> nodalGIDs(nAmalgNodesOnProc);
350 typename Teuchos::ScalarTraits<Scalar>::coordinateType temp;
351 for (
size_t i = 0; i < as<size_t>(nAmalgNodesOnProc); i++) {
352 GO gid = rowMap->getGlobalElement(i * nPDEs);
353 temp = ((
typename Teuchos::ScalarTraits<Scalar>::coordinateType)(gid)) / ((
typename Teuchos::ScalarTraits<Scalar>::coordinateType)(nPDEs));
354 nodalGIDs[i] = as<GO>(floor(temp));
356 GO nAmalgNodesGlobal = rowMap->getGlobalNumElements();
357 GO nBlkGlobal = nAmalgNodesGlobal / nPDEs;
358 if (nBlkGlobal * nPDEs != nAmalgNodesGlobal)
361 Teuchos::RCP<Map> AmalgRowMap = MapFactory::Build(rowMap->lib(), nBlkGlobal,
362 nodalGIDs(), 0, rowMap->getComm());
364 filteredGraph = rcp(
new LWGraph(newRowPtr, finalCols, AmalgRowMap, AmalgRowMap,
"thresholded graph of A"));
365 filteredGraph->SetBoundaryNodeMap(boundaryNodes);
369void 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 {
370 using TST = Teuchos::ScalarTraits<Scalar>;
372 LO nLeng = cols.size();
373 typename TST::coordinateType temp;
374 temp = ((
typename TST::coordinateType)(row)) / ((
typename TST::coordinateType)(nPDEs));
375 LO blkRow = as<LO>(floor(temp));
376 Teuchos::ArrayRCP<Scalar> badGuy(nLeng, 0.0);
377 Teuchos::ArrayRCP<Scalar> subNull(nLeng, 0.0);
390 for (LO i = 0; i < nLeng; i++) keepOrNot[i] =
false;
394 LO rowDof = row - blkRow * nPDEs;
395 Teuchos::ArrayRCP<const Scalar> oneNull = nearNull.getData(as<size_t>(rowDof));
397 for (LO i = 0; i < nLeng; i++) {
398 if ((cols[i] < nLoc) && (TST::magnitude(vals[i]) != 0.0)) {
399 temp = ((
typename TST::coordinateType)(cols[i])) / ((
typename TST::coordinateType)(nPDEs));
400 LO colDof = cols[i] - (as<LO>(floor(temp))) * nPDEs;
401 if (colDof == rowDof) {
402 Bcols[Nbcols] = (cols[i] - colDof) / nPDEs;
403 subNull[Nbcols] = oneNull[cols[i]];
405 if (cols[i] != row) {
406 Scalar worstRatio = -TST::one();
407 Scalar targetRatio = subNull[Nbcols] / oneNull[row];
409 for (
size_t kk = 0; kk < testVecs.getNumVectors(); kk++) {
410 Teuchos::ArrayRCP<const Scalar> curVec = testVecs.getData(kk);
411 actualRatio = curVec[cols[i]] / curVec[row];
412 if (TST::magnitude(actualRatio - targetRatio) > TST::magnitude(worstRatio)) {
413 badGuy[Nbcols] = actualRatio;
414 worstRatio = Teuchos::ScalarTraits<SC>::magnitude(actualRatio - targetRatio);
419 keepOrNot[Nbcols] =
true;
430 Bcols[Nbcols] = (row - rowDof) / nPDEs;
431 subNull[Nbcols] = 1.;
433 keepOrNot[Nbcols] =
true;
438 Scalar currentRP = oneNull[row] * oneNull[row];
439 Scalar currentRTimesBadGuy = oneNull[row] * badGuy[diagInd];
440 Scalar currentScore = penalties[0];
451 LO nKeep = 1, flag = 1, minId;
452 Scalar minFit, minFitRP = 0., minFitRTimesBadGuy = 0.;
453 Scalar newRP, newRTimesBadGuy;
462 for (LO i = 0; i < Nbcols; i++) {
463 if (keepOrNot[i] ==
false) {
465 newRP = currentRP + subNull[i] * subNull[i];
466 newRTimesBadGuy = currentRTimesBadGuy + subNull[i] * badGuy[i];
467 Scalar ratio = newRTimesBadGuy / newRP;
470 for (LO k = 0; k < Nbcols; k++) {
471 if (keepOrNot[k] ==
true) {
472 Scalar diff = badGuy[k] - ratio * subNull[k];
473 newFit = newFit + diff * diff;
476 if (Teuchos::ScalarTraits<SC>::magnitude(newFit) < Teuchos::ScalarTraits<SC>::magnitude(minFit)) {
480 minFitRTimesBadGuy = newRTimesBadGuy;
482 keepOrNot[i] =
false;
488 minFit = sqrt(minFit);
489 Scalar newScore = penalties[nKeep] + minFit;
490 if (Teuchos::ScalarTraits<SC>::magnitude(newScore) < Teuchos::ScalarTraits<SC>::magnitude(currentScore)) {
492 keepOrNot[minId] =
true;
493 currentScore = newScore;
494 currentRP = minFitRP;
495 currentRTimesBadGuy = minFitRTimesBadGuy;