MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_SmooVecCoalesceDropFactory_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // MueLu: A package for multigrid based preconditioning
4 //
5 // Copyright 2012 NTESS and the MueLu contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #include "MueLu_SmootherBase.hpp"
11 #ifndef MUELU_SMOOVECCOALESCEDROPFACTORY_DEF_HPP
12 #define MUELU_SMOOVECCOALESCEDROPFACTORY_DEF_HPP
13 
14 #include <Xpetra_CrsGraph.hpp>
15 #include <Xpetra_ImportFactory.hpp>
16 #include <Xpetra_MapFactory.hpp>
17 #include <Xpetra_Map.hpp>
18 #include <Xpetra_Matrix.hpp>
19 #include <Xpetra_MultiVectorFactory.hpp>
20 #include <Xpetra_MultiVector.hpp>
21 #include <Xpetra_StridedMap.hpp>
22 #include <Xpetra_VectorFactory.hpp>
23 #include <Xpetra_Vector.hpp>
24 
26 
27 #include "MueLu_Exceptions.hpp"
28 #include "MueLu_LWGraph.hpp"
29 
30 #include "MueLu_Level.hpp"
31 #include "MueLu_LWGraph.hpp"
32 #include "MueLu_MasterList.hpp"
33 #include "MueLu_Monitor.hpp"
34 #include "MueLu_PreDropFunctionBaseClass.hpp"
35 
36 #include <Xpetra_IO.hpp>
37 
38 #include <algorithm>
39 #include <cstdlib>
40 #include <string>
41 
42 // If defined, read environment variables.
43 // Should be removed once we are confident that this works.
44 // #define DJS_READ_ENV_VARIABLES
45 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <math.h>
49 
50 #define poly0thOrderCoef 0
51 #define poly1stOrderCoef 1
52 #define poly2ndOrderCoef 2
53 #define poly3rdOrderCoef 3
54 #define poly4thOrderCoef 4
55 
56 namespace MueLu {
57 
58 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
60  RCP<ParameterList> validParamList = rcp(new ParameterList());
61 
62 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
63  SET_VALID_ENTRY("aggregation: drop scheme");
64  {
65  validParamList->getEntry("aggregation: drop scheme").setValidator(rcp(new Teuchos::StringValidator(Teuchos::tuple<std::string>("classical", "distance laplacian", "unsupported vector smoothing"))));
66  }
67  SET_VALID_ENTRY("aggregation: number of random vectors");
68  SET_VALID_ENTRY("aggregation: number of times to pre or post smooth");
69  SET_VALID_ENTRY("aggregation: penalty parameters");
70 #undef SET_VALID_ENTRY
71 
72  validParamList->set<RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the matrix A");
73  validParamList->set<RCP<const FactoryBase> >("PreSmoother", Teuchos::null, "Generating factory of the PreSmoother");
74  validParamList->set<RCP<const FactoryBase> >("PostSmoother", Teuchos::null, "Generating factory of the PostSmoother");
75 
76  return validParamList;
77 }
78 
79 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
81  : predrop_(Teuchos::null) {}
82 
83 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
85  Input(currentLevel, "A");
86  if (currentLevel.IsAvailable("PreSmoother")) { // rst: totally unsure that this is legal
87  Input(currentLevel, "PreSmoother"); // my guess is that this is not yet available
88  } // so this always comes out false.
89  else if (currentLevel.IsAvailable("PostSmoother")) { // perhaps we can look on the param list?
90  Input(currentLevel, "PostSmoother");
91  }
92 }
93 
94 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
96  FactoryMonitor m(*this, "Build", currentLevel);
97 
98  typedef Teuchos::ScalarTraits<SC> STS;
99 
100  if (predrop_ != Teuchos::null)
101  GetOStream(Parameters0) << predrop_->description();
102 
103  RCP<Matrix> A = Get<RCP<Matrix> >(currentLevel, "A");
104 
105  const ParameterList& pL = GetParameterList();
106 
107  LO nPDEs = A->GetFixedBlockSize();
108 
109  RCP<MultiVector> testVecs;
110  RCP<MultiVector> nearNull;
111 
112 #ifdef takeOut
113  testVecs = Xpetra::IO<SC, LO, GO, Node>::ReadMultiVector("TpetraTVecs.mm", A->getRowMap());
114 #endif
115  size_t numRandom = as<size_t>(pL.get<int>("aggregation: number of random vectors"));
116  testVecs = MultiVectorFactory::Build(A->getRowMap(), numRandom, true);
117  // use random test vectors but should be positive in order to not get
118  // crummy results ... so take abs() of randomize().
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]);
123  }
124  nearNull = MultiVectorFactory::Build(A->getRowMap(), nPDEs, true);
125 
126  // initialize null space to constants
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();
130  }
131 
132  RCP<MultiVector> zeroVec_TVecs;
133  RCP<MultiVector> zeroVec_Null;
134 
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());
139 
140  size_t nInvokeSmoother = as<size_t>(pL.get<int>("aggregation: number of times to pre or post smooth"));
141  if (currentLevel.IsAvailable("PreSmoother")) {
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);
149  } else
150  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "Must set a smoother");
151 
152  Teuchos::ArrayRCP<Scalar> penaltyPolyCoef(5);
153  Teuchos::ArrayView<const double> inputPolyCoef;
154 
155  penaltyPolyCoef[poly0thOrderCoef] = 12.;
156  penaltyPolyCoef[poly1stOrderCoef] = -.2;
157  penaltyPolyCoef[poly2ndOrderCoef] = 0.0;
158  penaltyPolyCoef[poly3rdOrderCoef] = 0.0;
159  penaltyPolyCoef[poly4thOrderCoef] = 0.0;
160 
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")();
165 
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();
168  }
169 
170  RCP<LWGraph> filteredGraph;
171  badGuysCoalesceDrop(*A, penaltyPolyCoef, nPDEs, *testVecs, *nearNull, filteredGraph);
172 
173 #ifdef takeOut
174  /* write out graph for serial debugging purposes only. */
175 
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);
183  }
184  }
185  fclose(fp);
186 #endif
187 
188  SC threshold = .01;
189  Set<bool>(currentLevel, "Filtering", (threshold != STS::zero()));
190  Set(currentLevel, "Graph", filteredGraph);
191  Set(currentLevel, "DofsPerNode", 1);
192 
193 } // Build
194 
195 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
196 void SmooVecCoalesceDropFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::badGuysCoalesceDrop(const Matrix& Amat, Teuchos::ArrayRCP<Scalar>& penaltyPolyCoef, LO nPDEs, const MultiVector& testVecs, const MultiVector& nearNull, RCP<LWGraph>& filteredGraph) const {
197  /*
198  * Compute coalesce/drop graph (in filteredGraph) for A. The basic idea is to
199  * balance trade-offs associated with
200  *
201  * (I - P inv(R P) R ) testVecs
202  *
203  * being worse for larger aggregates (less dropping) while MG cycle costs are
204  * cheaper with larger aggregates. MG costs are "penalties" in the
205  * optimization while (I - P inv(R P) R ) is the "fit" (how well a
206  * a fine grid function can be approximated on the coarse grid).
207  *
208  * For MG costs, we don't actually approximate the cost. Instead, we
209  * have just hardwired penalties below. Specifically,
210  *
211  * penalties[j] is the cost if aggregates are of size j+1, where right
212  * now a linear function of the form const*(60-j) is used.
213  *
214  * (I - P inv(P^T P) P^T ) testVecs is estimated by just looking locally at
215  * the vector portion corresponding to a possible aggregate defined by
216  * all non-dropped connections in the ith row. A tentative prolognator is
217  * used for P. This prolongator corresponds to a null space vector given
218  * by 'nearNull', which is provided to dropper(). In initial testing, nearNull is
219  * first set as a vector of all 1's and then smoothed with a relaxation
220  * method applied to a nice matrix (with the same sparsity pattern as A).
221  * Originally, nearNull was used to handle Dir bcs where relaxation of the
222  * vector of 1's has a more pronounced effect.
223  *
224  * For PDE systems, fit only considers the same dof at each node. That is,
225  * it effectively assumes that we have a tentative prolongator with no
226  * coupling between different dof types. When checking the fit for the kth
227  * dof at a paritcular node, it only considers the kth dof of this node
228  * and neighboring nodes.
229  *
230  * Note: testVecs is supplied by the user, but normally is the result of
231  * applying a relaxation scheme to Au = 0 where u is initial random.
232  */
233 
234  GO numMyNnz = Teuchos::as<GO>(Amat.getLocalNumEntries());
235  size_t nLoc = Amat.getRowMap()->getLocalNumElements();
236 
237  size_t nBlks = nLoc / nPDEs;
238  if (nBlks * nPDEs != nLoc)
239  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "Number of local dofs not divisible by BlkSize");
240 
241  typename LWGraph::row_type::non_const_type newRowPtr("newRowPtr", nBlks + 1); /* coalesce & drop matrix */
242  Teuchos::ArrayRCP<LO> newCols(numMyNnz); /* arrays */
243 
244  Teuchos::ArrayRCP<LO> bcols(nBlks); /* returned by dropfun(j,...) */
245  Teuchos::ArrayRCP<bool> keepOrNot(nBlks); /* gives cols for jth row and */
246  /* whether or not entry is */
247  /* kept or dropped. */
248 
249  LO maxNzPerRow = 200;
250  Teuchos::ArrayRCP<Scalar> penalties(maxNzPerRow); /* Penalty function */
251  /* described above. */
252 
253  Teuchos::ArrayRCP<bool> keepStatus(nBlks, true); /* accumulated keepOrNot info */
254  Teuchos::ArrayRCP<LO> bColList(nBlks); /* accumulated bcols info */
255  /* for an entire block as */
256  /* opposed to a single row */
257  /* Additionally, keepOrNot[j] */
258  /* refers to status of jth */
259  /* entry in a row while */
260  /* keepStatus[j] refers to */
261  /* whether the jth block is */
262  /* kept within the block row. */
263 
264  Teuchos::ArrayRCP<bool> alreadyOnBColList(nBlks, false); /* used to avoid recording the*/
265  /* same block column when */
266  /* processing different pt */
267  /* rows within a block. */
268 
269  typename LWGraph::boundary_nodes_type boundaryNodes("boundaryNodes", nBlks);
270  Kokkos::deep_copy(boundaryNodes, false);
271 
272  for (LO i = 0; i < maxNzPerRow; i++)
273  penalties[i] = penaltyPolyCoef[poly0thOrderCoef] +
274  penaltyPolyCoef[poly1stOrderCoef] * (as<Scalar>(i)) +
275  penaltyPolyCoef[poly2ndOrderCoef] * (as<Scalar>(i * i)) +
276  (penaltyPolyCoef[poly3rdOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i))) + // perhaps avoids overflow?
277  (penaltyPolyCoef[poly4thOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i * i)));
278 
279  LO nzTotal = 0, numBCols = 0, row = -1, Nbcols, bcol;
280  newRowPtr(0) = 0;
281 
282  /* proceed block by block */
283  for (LO i = 0; i < as<LO>(nBlks); i++) {
284  newRowPtr[i + 1] = newRowPtr[i];
285  for (LO j = 0; j < nPDEs; j++) {
286  row = row + 1;
287 
290 
291  Amat.getLocalRowView(row, indices, vals);
292 
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++)
298  penalties[k] = penaltyPolyCoef[poly0thOrderCoef] +
299  penaltyPolyCoef[poly1stOrderCoef] * (as<Scalar>(i)) +
300  penaltyPolyCoef[poly2ndOrderCoef] * (as<Scalar>(i * i)) +
301  (penaltyPolyCoef[poly3rdOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i))) +
302  (penaltyPolyCoef[poly4thOrderCoef] * (as<Scalar>(i * i)) * (as<Scalar>(i * i)));
303  }
304  badGuysDropfunc(row, indices, vals, testVecs, nPDEs, penalties, nearNull, bcols, keepOrNot, Nbcols, nLoc);
305  for (LO k = 0; k < Nbcols; k++) {
306  bcol = bcols[k];
307 
308  /* add to bColList if not already on it */
309 
310  if (alreadyOnBColList[bcol] == false) { /* for PDE systems only record */
311  bColList[numBCols++] = bcol; /* neighboring block one time */
312  alreadyOnBColList[bcol] = true;
313  }
314  /* drop if any pt row within block indicates entry should be dropped */
315 
316  if (keepOrNot[k] == false) keepStatus[bcol] = false;
317 
318  } /* for (k=0; k < Nbcols; k++) */
319  } /* for (j = 0; i < nPDEs; j++) */
320 
321  /* finished with block row. Now record block entries that we keep */
322  /* and reset keepStatus, bColList, and alreadyOnBColList. */
323 
324  if (numBCols < 2) boundaryNodes[i] = true;
325  for (LO j = 0; j < numBCols; j++) {
326  bcol = bColList[j];
327  if (keepStatus[bcol] == true) {
328  newCols[nzTotal] = bColList[j];
329  newRowPtr(i + 1)++;
330  nzTotal = nzTotal + 1;
331  }
332  keepStatus[bcol] = true;
333  alreadyOnBColList[bcol] = false;
334  bColList[j] = 0;
335  }
336  numBCols = 0;
337  } /* for (i = 0; i < nBlks; i++) */
338 
339  /* create array of the correct size and copy over newCols to it */
340 
341  typename LWGraph::entries_type::non_const_type finalCols("finalCols", nzTotal);
342  for (LO i = 0; i < nzTotal; i++) finalCols(i) = newCols[i];
343 
344  // Not using column map because we do not allow for any off-proc stuff.
345  // Not sure if this is okay. FIXME
346 
347  RCP<const Map> rowMap = Amat.getRowMap(); // , colMap = Amat.getColMap();
348 
349  LO nAmalgNodesOnProc = rowMap->getLocalNumElements() / nPDEs;
350  Teuchos::Array<GO> nodalGIDs(nAmalgNodesOnProc);
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));
356  }
357  GO nAmalgNodesGlobal = rowMap->getGlobalNumElements();
358  GO nBlkGlobal = nAmalgNodesGlobal / nPDEs;
359  if (nBlkGlobal * nPDEs != nAmalgNodesGlobal)
360  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "Number of global dofs not divisible by BlkSize");
361 
362  Teuchos::RCP<Map> AmalgRowMap = MapFactory::Build(rowMap->lib(), nBlkGlobal,
363  nodalGIDs(), 0, rowMap->getComm());
364 
365  filteredGraph = rcp(new LWGraph(newRowPtr, finalCols, AmalgRowMap, AmalgRowMap, "thresholded graph of A"));
366  filteredGraph->SetBoundaryNodeMap(boundaryNodes);
367 }
368 
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 {
371  using TST = Teuchos::ScalarTraits<Scalar>;
372 
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); /* subset of nearNull */
379  /* associated with current */
380  /* dof within node. */
381 
382  /* Only consider testVecs associated with same dof & on processor. Further */
383  /* collapse testVecs to a single badGuy vector by basically taking the worst */
384  /* (least smooth) values for each of the off diags. In particular, we look at*/
385  /* the ratio of each off-diag test value / diag test value and compare this */
386  /* with the nearNull vector ratio. The further the testVec ratio is from the */
387  /* nearNull ratio, the harder is will be to accurately interpolate is these */
388  /* two guys are aggregated. So, the biggest ratio mismatch is used to choose */
389  /* the testVec entry associated with each off-diagonal entry. */
390 
391  for (LO i = 0; i < nLeng; i++) keepOrNot[i] = false;
392 
393  LO diagInd = -1;
394  Nbcols = 0;
395  LO rowDof = row - blkRow * nPDEs;
396  Teuchos::ArrayRCP<const Scalar> oneNull = nearNull.getData(as<size_t>(rowDof));
397 
398  for (LO i = 0; i < nLeng; i++) {
399  if ((cols[i] < nLoc) && (TST::magnitude(vals[i]) != 0.0)) { /* on processor */
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) { /* same dof within node as row */
403  Bcols[Nbcols] = (cols[i] - colDof) / nPDEs;
404  subNull[Nbcols] = oneNull[cols[i]];
405 
406  if (cols[i] != row) { /* not diagonal */
407  Scalar worstRatio = -TST::one();
408  Scalar targetRatio = subNull[Nbcols] / oneNull[row];
409  Scalar actualRatio;
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);
416  }
417  }
418  } else {
419  badGuy[Nbcols] = 1.;
420  keepOrNot[Nbcols] = true;
421  diagInd = Nbcols;
422  }
423  (Nbcols)++;
424  }
425  }
426  }
427 
428  /* Make sure that diagonal entry is in block col list */
429 
430  if (diagInd == -1) {
431  Bcols[Nbcols] = (row - rowDof) / nPDEs;
432  subNull[Nbcols] = 1.;
433  badGuy[Nbcols] = 1.;
434  keepOrNot[Nbcols] = true;
435  diagInd = Nbcols;
436  (Nbcols)++;
437  }
438 
439  Scalar currentRP = oneNull[row] * oneNull[row];
440  Scalar currentRTimesBadGuy = oneNull[row] * badGuy[diagInd];
441  Scalar currentScore = penalties[0]; /* (I - P inv(R*P)*R )=0 for size */
442  /* size 1 agg, so fit is perfect */
443 
444  /* starting from a set that only includes the diagonal entry consider adding */
445  /* one off-diagonal at a time until the fitValue exceeds the penalty term. */
446  /* Here, the fit value is (I - P inv(R P) R ) and we always consider the */
447  /* lowest fitValue that is not currently in the set. R and P correspond to */
448  /* a simple tentaive grid transfer associated with an aggregate that */
449  /* includes the diagonal, all already determined neighbors, and the potential*/
450  /* new neighbor */
451 
452  LO nKeep = 1, flag = 1, minId;
453  Scalar minFit, minFitRP = 0., minFitRTimesBadGuy = 0.;
454  Scalar newRP, newRTimesBadGuy;
455 
456  while (flag == 1) {
457  /* compute a fit for each possible off-diagonal neighbor */
458  /* that has not already been added as a neighbor */
459 
460  minFit = 1000000.;
461  minId = -1;
462 
463  for (LO i = 0; i < Nbcols; i++) {
464  if (keepOrNot[i] == false) {
465  keepOrNot[i] = true; /* temporarily view i as non-dropped neighbor */
466  newRP = currentRP + subNull[i] * subNull[i];
467  newRTimesBadGuy = currentRTimesBadGuy + subNull[i] * badGuy[i];
468  Scalar ratio = newRTimesBadGuy / newRP;
469 
470  Scalar newFit = 0.0;
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;
475  }
476  }
478  minId = i;
479  minFit = newFit;
480  minFitRP = newRP;
481  minFitRTimesBadGuy = newRTimesBadGuy;
482  }
483  keepOrNot[i] = false;
484  }
485  }
486  if (minId == -1)
487  flag = 0;
488  else {
489  minFit = sqrt(minFit);
490  Scalar newScore = penalties[nKeep] + minFit;
492  nKeep = nKeep + 1;
493  keepOrNot[minId] = true;
494  currentScore = newScore;
495  currentRP = minFitRP;
496  currentRTimesBadGuy = minFitRTimesBadGuy;
497  } else
498  flag = 0;
499  }
500  }
501 }
502 
503 } // namespace MueLu
504 
505 #endif // MUELU_SMOOVECCOALESCEDROPFACTORY_DEF_HPP
void setValidator(RCP< const ParameterEntryValidator > const &validator)
GlobalOrdinal GO
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.
size_type size() const
LocalOrdinal LO
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.
size_type size() const
void resize(const size_type n, const T &val=T())
void Build(Level &currentLevel) const
Build an object with this factory.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
MueLu::DefaultScalar Scalar
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:63
#define SET_VALID_ENTRY(name)
static RCP< MultiVector > ReadMultiVector(const std::string &fileName, const RCP< const Map > &map)
void DeclareInput(Level &currentLevel) const
Input.
KOKKOS_INLINE_FUNCTION neighbor_vertices_type getNeighborVertices(LO i) const
Return the list of vertices adjacent to the vertex &#39;v&#39;.
Print class parameters.
static magnitudeType magnitude(T a)
size_type size() const
Scalar SC
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&#39;s value has been saved.