11 #ifndef MUELU_SMOOVECCOALESCEDROPFACTORY_DEF_HPP
12 #define MUELU_SMOOVECCOALESCEDROPFACTORY_DEF_HPP
16 #include <Xpetra_MapFactory.hpp>
17 #include <Xpetra_Map.hpp>
19 #include <Xpetra_MultiVectorFactory.hpp>
21 #include <Xpetra_StridedMap.hpp>
28 #include "MueLu_LWGraph.hpp"
31 #include "MueLu_LWGraph.hpp"
34 #include "MueLu_PreDropFunctionBaseClass.hpp"
50 #define poly0thOrderCoef 0
51 #define poly1stOrderCoef 1
52 #define poly2ndOrderCoef 2
53 #define poly3rdOrderCoef 3
54 #define poly4thOrderCoef 4
58 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
62 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
70 #undef SET_VALID_ENTRY
76 return validParamList;
79 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
81 : predrop_(Teuchos::null) {}
83 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
85 Input(currentLevel,
"A");
87 Input(currentLevel,
"PreSmoother");
89 else if (currentLevel.
IsAvailable(
"PostSmoother")) {
90 Input(currentLevel,
"PostSmoother");
94 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
100 if (predrop_ != Teuchos::null)
101 GetOStream(
Parameters0) << predrop_->description();
103 RCP<Matrix> A = Get<RCP<Matrix> >(currentLevel,
"A");
107 LO nPDEs = A->GetFixedBlockSize();
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++) {
124 nearNull = MultiVectorFactory::Build(A->getRowMap(), nPDEs,
true);
127 for (
size_t kk = 0; kk < nearNull->getNumVectors(); kk++) {
135 zeroVec_TVecs = MultiVectorFactory::Build(A->getRowMap(), testVecs->getNumVectors(),
true);
136 zeroVec_Null = MultiVectorFactory::Build(A->getRowMap(), nPDEs,
true);
140 size_t nInvokeSmoother = as<size_t>(pL.get<
int>(
"aggregation: number of times to pre or post smooth"));
141 if (currentLevel.IsAvailable(
"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")) {
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);
161 if (pL.isParameter(
"aggregation: penalty parameters") && pL.get<
Teuchos::Array<double> >(
"aggregation: penalty parameters").size() > 0) {
166 for (
size_t i = 0; i < as<size_t>(inputPolyCoef.
size()); i++) penaltyPolyCoef[i] = as<Scalar>(inputPolyCoef[i]);
171 badGuysCoalesceDrop(*A, penaltyPolyCoef, nPDEs, *testVecs, *nearNull, filteredGraph);
176 FILE* fp = fopen(
"codeOutput",
"w");
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);
195 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
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);
249 LO maxNzPerRow = 200;
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++) {
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];
349 LO nAmalgNodesOnProc = rowMap->getLocalNumElements() / nPDEs;
352 for (
size_t i = 0; i < as<size_t>(nAmalgNodesOnProc); i++) {
353 GO gid = rowMap->getGlobalElement(i * nPDEs);
355 nodalGIDs[i] = as<GO>(floor(temp));
357 GO nAmalgNodesGlobal = rowMap->getGlobalNumElements();
358 GO nBlkGlobal = nAmalgNodesGlobal / nPDEs;
359 if (nBlkGlobal * nPDEs != nAmalgNodesGlobal)
363 nodalGIDs(), 0, rowMap->getComm());
365 filteredGraph =
rcp(
new LWGraph(newRowPtr, finalCols, AmalgRowMap, AmalgRowMap,
"thresholded graph of A"));
366 filteredGraph->SetBoundaryNodeMap(boundaryNodes);
369 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
370 void 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 {
374 typename TST::coordinateType temp;
375 temp = ((
typename TST::coordinateType)(row)) / ((
typename TST::coordinateType)(nPDEs));
376 LO blkRow = as<LO>(floor(temp));
391 for (
LO i = 0; i < nLeng; i++) keepOrNot[i] =
false;
395 LO rowDof = row - blkRow * nPDEs;
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++) {
412 actualRatio = curVec[cols[i]] / curVec[row];
413 if (TST::magnitude(actualRatio - targetRatio) > TST::magnitude(worstRatio)) {
414 badGuy[Nbcols] = actualRatio;
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;
481 minFitRTimesBadGuy = newRTimesBadGuy;
483 keepOrNot[i] =
false;
489 minFit = sqrt(minFit);
490 Scalar newScore = penalties[nKeep] + minFit;
493 keepOrNot[minId] =
true;
494 currentScore = newScore;
495 currentRP = minFitRP;
496 currentRTimesBadGuy = minFitRTimesBadGuy;
505 #endif // MUELU_SMOOVECCOALESCEDROPFACTORY_DEF_HPP
void setValidator(RCP< const ParameterEntryValidator > const &validator)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
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 resize(const size_type n, const T &val=T())
void Build(Level ¤tLevel) const
Build an object with this factory.
Kokkos::View< bool *, memory_space > boundary_nodes_type
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
MueLu::DefaultScalar Scalar
Class that holds all level-specific information.
#define SET_VALID_ENTRY(name)
static RCP< MultiVector > ReadMultiVector(const std::string &fileName, const RCP< const Map > &map)
SmooVecCoalesceDropFactory()
Constructor.
void DeclareInput(Level ¤tLevel) const
Input.
KOKKOS_INLINE_FUNCTION neighbor_vertices_type getNeighborVertices(LO i) const
Return the list of vertices adjacent to the vertex 'v'.
static magnitudeType magnitude(T a)
void badGuysDropfunc(LO row, const Teuchos::ArrayView< const LocalOrdinal > &indices, const Teuchos::ArrayView< const Scalar > &vals, const MultiVector &smoothedTVecs, LO nPDEs, Teuchos::ArrayRCP< Scalar > &penalties, const MultiVector &smoothedNull, Teuchos::ArrayRCP< LO > &Bcols, Teuchos::ArrayRCP< bool > &keepOrNot, LO &Nbcols, LO nLoc) const
Lightweight MueLu representation of a compressed row storage graph.
Exception throws to report errors in the internal logical of the program.
void badGuysCoalesceDrop(const Matrix &Amat, Teuchos::ArrayRCP< Scalar > &dropParams, LO nPDEs, const MultiVector &smoothedTVecs, const MultiVector &smoothedNull, RCP< LWGraph > &filteredGraph) const
Methods to support compatible-relaxation style dropping.
ParameterEntry & getEntry(const std::string &name)
virtual void Apply(MultiVector &x, const MultiVector &rhs, bool InitialGuessIsZero=false) const =0
Apply smoother.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.