MueLu - Hierarchy

Multigrid setup

General preparations

Declare location of include headers


In [1]:
.I /opt/install/do-conf-ep-serial/include/


Out[1]:

Load Trilinos libraries


In [2]:
.L libepetra


Out[2]:


In [3]:
.L libxpetra


Out[3]:


In [4]:
.L libmuelu


Out[4]:


In [5]:
.L libteuchoscore


Out[5]:

Include some standard header files to create a communicator and an Xpetra::Map


In [6]:
#include "Kokkos_DefaultNode.hpp"
#include "Epetra_SerialComm.h"
#include "Epetra_Vector.h"
#include "Epetra_CrsMatrix.h"
#include "Teuchos_RCP.hpp"
#include "Teuchos_DefaultSerialComm.hpp"
#include "Xpetra_MapFactory.hpp"
#include "Xpetra_Map.hpp"
#include "Xpetra_EpetraCrsMatrix.hpp"


Out[6]:

Again, we use standard template parameters:


In [7]:
typedef double Scalar;
typedef int LocalOrdinal;
typedef int GlobalOrdinal;
typedef Kokkos::Compat::KokkosSerialWrapperNode EpetraNode;
typedef EpetraNode Node;
typedef Scalar SC;
typedef LocalOrdinal LO;
typedef GlobalOrdinal GO;
typedef Node NO;


Out[7]:


In [8]:
#include "Xpetra_CrsMatrixWrap.hpp"
#include "Xpetra_CrsMatrix.hpp"
#include "Xpetra_MultiVector.hpp"
#include "Xpetra_BlockedMultiVector.hpp"
#include "Xpetra_BlockedVector.hpp"
#include "Xpetra_MultiVectorFactory.hpp"


Out[8]:

Create a matrix object

Let's create a matrix and wrap it as an Xpetra::CrsMatrixWrap object


In [9]:
int NumMyElements = 100;


Out[9]:
(int) 100

In [10]:
Epetra_SerialComm Comm;
Epetra_Map Map(-1, NumMyElements, 0, Comm);
int NumGlobalElements = Map.NumGlobalElements();

Epetra_CrsMatrix A(Copy, Map, 3);

double negOne = -1.0;
double posTwo = 2.0;
for (int i=0; i<NumMyElements; i++) {
    int GlobalRow = A.GRID(i); int RowLess1 = GlobalRow - 1; int RowPlus1 = GlobalRow + 1;

    if (RowLess1!=-1) A.InsertGlobalValues(GlobalRow, 1, &negOne, &RowLess1);
    if (RowPlus1!=NumGlobalElements) A.InsertGlobalValues(GlobalRow, 1, &negOne, &RowPlus1);
    A.InsertGlobalValues(GlobalRow, 1, &posTwo, &GlobalRow);
};

A.FillComplete();


Out[10]:
(int) 0

In [11]:
Teuchos::RCP<Epetra_CrsMatrix> rcpA = Teuchos::rcpFromRef(A);
Xpetra::EpetraCrsMatrixT<GO,NO> xA(rcpA);
Teuchos::RCP<Xpetra::CrsMatrix<SC,LO,GO,NO> > xCrsMat = Teuchos::rcpFromRef(xA);
Xpetra::CrsMatrixWrap<SC,LO,GO,NO> xCrsWrap = Xpetra::CrsMatrixWrap<SC,LO,GO,NO>(xCrsMat);


Out[11]:
(Xpetra::CrsMatrixWrap<SC, LO, GO, NO> &) @0x7f73d7d7e208

The xCrsWrap object contains the matrix object that can be used as input for MueLu.

Create a multigrid hierarchy

First, include the necessary header files:


In [13]:
#include "MueLu_Level.hpp"
#include "MueLu_MutuallyExclusiveTime.hpp"
#include "MueLu_TimeMonitor.hpp"
#include "MueLu_Hierarchy.hpp"


Out[13]:

Then, we create a new Hierarchy object. We use the input matrix xCrsWrap as parameter. The constructor automatically generates the first (finest) level and stores the provided matrix object as variable A on the finest level.

Note: there is also an empty constructor that you can use for more special cases. You can add new levels using the ```AddLevel``` routine and fill them with data by hand.

In [14]:
MueLu::Hierarchy<SC,LO,GO,NO> H(Teuchos::rcpFromRef(xCrsWrap));


Out[14]:
(MueLu::Hierarchy<SC, LO, GO, NO> &) @0x7f73d7d7e2f8

We set the maximum size for the coarsest level to $10$ and increase the verbosity output level to get more screen output.


In [15]:
H.setDefaultVerbLevel(Teuchos::VERB_HIGH);
H.SetMaxCoarseSize(10);


Out[15]:
(void) @0x7fff2c5d7d40

You can access the finest level that has been created in the constructor using the Hierarchy::GetLevel(int) function. If you do not provide the level number it assumes the finest level. The MueLu::Level class also has a verbosity level for the output details related to the Level data.


In [16]:
Teuchos::RCP<MueLu::Level> Finest = H.GetLevel();
Finest->setDefaultVerbLevel(Teuchos::VERB_HIGH);
Finest->print(std::cout, MueLu::Extreme);


LevelID = 0
  data name             gen. factory addr.  req    keep   type             data            req'd by            
  --------------------  ------------------  -----  -----  ---------------  --------------  --------------------
  A                     NoFactory           0      User   Matrix           available                           
Out[16]:
(void) @0x7fff2c5d7d40

As you can see, the finest level already contains the fine level operator A provided by the user. This is the xCrsWrap operator you provided in the constructor for the Hierarchy.

Note: Instead of providing the ```Xpetra::Matrix``` (or ```Xpetra::CrsMatrixWrap``` object) in the constructor, you can also use the *empty* standard constructor and add the fine level operator by hand using a code line like ```Finest->Set("A",xCrsWrap);```.

A whirlwind through MueLu factories

AmalgamationFactory

The AmalgamationFactory takes the matrix A as input and amalgamates it. That is, if the matrix uses more than one DOFs per node, it builds the corresponding amalgamated node map and stores information on how to unamalgamate node-based information to dof-based information in the UnamalgamationInfo container.


In [17]:
#include "MueLu_AmalgamationFactory.hpp"


Out[17]:


In [18]:
MueLu::AmalgamationFactory<SC,LO,GO,NO> amalgFact;


Out[18]:
(MueLu::AmalgamationFactory<SC, LO, GO, NO> &) @0x7f73d7d7e4a0
CoalesceDropFactory

The CoalesceDropFactory actually generates the node-based graph given a dof-based matrix A and stores it as Graph in the Level container. It also accepts a threshold parameter for dropping small entries in A. It may use information from the UnAmalgamationInfo container.


In [19]:
#include "MueLu_CoalesceDropFactory.hpp"


Out[19]:


In [20]:
MueLu::CoalesceDropFactory<SC,LO,GO,NO> coalFact;


Out[20]:
(MueLu::CoalesceDropFactory<SC, LO, GO, NO> &) @0x7f73d7d7e5f0

In [21]:
Teuchos::RCP<MueLu::CoalesceDropFactory<SC,LO,GO,NO> > rcpCoalFact = Teuchos::rcpFromRef(coalFact);


Out[21]:
(Teuchos::RCP<MueLu::CoalesceDropFactory<SC, LO, GO, NO> > &) @0x7f73d7d7e750
Note: In ```cling``` we create all factories on the stack and use ```Teuchos::rcpFromRef``` to define ```RCP``` pointers. We explicitly have to create an ```RCP``` pointer to a factory if we need it in several places.
UncoupledAggregationFactory

The UncoupledAggregationFactory builds the aggregates given a Graph and the DofsPerNode variable. DofsPerNode is provided by the CoalesceDropFactory and contains how many DOFs per node the matrix has.


In [22]:
#include "MueLu_UncoupledAggregationFactory.hpp"


Out[22]:


In [23]:
MueLu::UncoupledAggregationFactory<LO,GO,NO> aggFact;


Out[23]:
(MueLu::UncoupledAggregationFactory<LO, GO, NO> &) @0x7f73d7d7e768

There are several ways how to define data dependencies between factories. You can (and sometimes have to) directly connect factories: for example, to use Graph and DofsPerNode generated by the previously defined CoalesceDropFactory rcpCoalFact in the AggregationFactory aggFact you use:


In [24]:
aggFact.SetFactory("Graph", rcpCoalFact);
aggFact.SetFactory("DofsPerNode", rcpCoalFact);


Out[24]:
(void) @0x7fff2c5d7d40
Note: In practice, it might be too complicated to define all necessary factory dependencies by hand. For example, most factories need ```A``` as input, which is generated on the previous level (by a *RAPFactory* object). *MueLu* provides a way to globally define which factory provides which data. That is, you can declare default factories which produce certain data. This functionality is provided by the *FactoryManager* which in detail will be introduced later.
NullspaceFactory

The NullspaceFactory provides constant vectors as default near-nullspace modes for the finest level. On the coarser levels it (usually) just pipes through the Nullspaace which is produced by the TentativePFactory (see below)


In [25]:
#include "MueLu_NullspaceFactory.hpp"


Out[25]:


In [26]:
MueLu::NullspaceFactory<SC,LO,GO,NO> nspFact;


Out[26]:
(MueLu::NullspaceFactory<SC, LO, GO, NO> &) @0x7f73d7d7e8d0

In [27]:
Teuchos::RCP<MueLu::NullspaceFactory<SC,LO,GO,NO>> rcpNspFact = Teuchos::rcpFromRef(nspFact);


Out[27]:
(Teuchos::RCP<MueLu::NullspaceFactory<SC, LO, GO, NO> > &) @0x7f73d7d7ea18
TentativePFactory

The TentativePFactory build the tentative prolongation operator (with piecewise constant basis functions) using Aggregates and the fine level Nullspace. It not only calculates and stores P on the coarsest level, but also generates the coarse null space (variable Nullspace on the coarse level).


In [28]:
#include "MueLu_TentativePFactory.hpp"


Out[28]:


In [29]:
MueLu::TentativePFactory<SC,LO,GO,NO> PFact;


Out[29]:
(MueLu::TentativePFactory<SC, LO, GO, NO> &) @0x7f73d7d7ea30

For demonstration purposes we explicitly set aggFact and nspFact to be the generating factories for the Aggregates and the fine level Nullspace.


In [30]:
PFact.SetFactory("Aggregates", Teuchos::rcpFromRef(aggFact));
PFact.SetFactory("Nullspace", rcpNspFact);


Out[30]:
(void) @0x7fff2c5d7d40

So, it uses the Nullspace provided by the NullspaceFactory (see above), which on the finest levels creates a default set of near-nullspace vectors or uses user-provided null-space vectors. Then, the TentativePFactory creates a new coarse Nullspace on the coarse level (which is supposed to be the fine Nullspace for the next level). On the next coarser level, NullspaceFactory again is supposed to provide the fine level Nullspace (which actually has been generated by TentativePFactory). For doing so, NullspaceFactory just takes the coarse Nullspace from TentativePFactory and stores it as fine Nullspace generated by NullspaceFactory.

For doing so, we have to tell the NullspaceFactory that it is supposed to use the Nullspace from the TentativePFactory as input. The NullspaceFactory contains some code for the finest level (to generate the default nullspace) to break through the circle dependency.


In [31]:
Teuchos::RCP<MueLu::TentativePFactory<SC,LO,GO,NO>> rcpPFact = Teuchos::rcpFromRef(PFact);


Out[31]:
(Teuchos::RCP<MueLu::TentativePFactory<SC, LO, GO, NO> > &) @0x7f73d7d7eb80

In [32]:
rcpNspFact->SetFactory("Nullspace", rcpPFact);


Out[32]:
(void) @0x7fff2c5d7d40
Note: Here, for ```cling``` using the C++ interface, we can easily declare the circle dependency between *TentativePFactory* and *NullspaceFactory*. For a more general XML based input deck, we need a *FactoryManager*. Details will be discussed later.
TransPFactory

The TransPFactory takes a prolongation operator P as input and stores its transposed as R


In [33]:
#include "MueLu_TransPFactory.hpp"


Out[33]:


In [34]:
MueLu::TransPFactory<SC,LO,GO,NO> RFact;


Out[34]:
(MueLu::TransPFactory<SC, LO, GO, NO> &) @0x7f73d7d7eb98

In [35]:
RFact.SetFactory("P", Teuchos::rcpFromRef(PFact));


Out[35]:
(void) @0x7fff2c5d7d40
RAPFactory

The RAPFactory builds the triple Galerkin product to calculate the coarse level operator $A_c = RAP$. It takes the prolongation and restriction operators P and R as well as the fine level operator A as input and stores the coarse A on the coarse level.


In [36]:
#include "MueLu_RAPFactory.hpp"


Out[36]:


In [37]:
MueLu::RAPFactory<SC,LO,GO,NO> RAPFact;


Out[37]:
(MueLu::RAPFactory<SC, LO, GO, NO> &) @0x7f73d7d7ece0

One can skip the following lines, if you have only one type of P and R whose associated factories are defined in a global FactoryManager (details later). Nevertheless, directly defining the dependencies does not hurt:


In [38]:
RAPFact.SetFactory("P", Teuchos::rcpFromRef(PFact));


Out[38]:
(void) @0x7fff2c5d7d40

In [39]:
RAPFact.SetFactory("R", Teuchos::rcpFromRef(RFact));


Out[39]:
(void) @0x7fff2c5d7d40
CoarseMapFactory

The CoarseMapFactory creates the coarse map which is used as domain map for the (tentative) prolongation operator. It is usually only used within the TentativePFactory and an average MueLu developer should never get into touch with it. Nevertheless, it is listed here for the sake of completeness of factories that you need somewhere when doing aggregation-based algebraic multigrid methods. It uses the Aggregates and Nullspace as input.

Usually, you would not see the CoarseMapFactory at all, since it is usually used internally in the TentativePFactory. Nevertheless, it is there and plays an important role. In the usual case, the FactoryManager (details later) will automatically generate a default CoarseMapFactory for you that is used under the hood.

Note: The *FactoryManager* manages a list of (default) factories for all variables using ```RCP``` pointers. However, with ```cling``` it is not safe to have ```RCP``` objects within other objects, that may not live on the stack. The C++ interpreter may crash since ```RCP``` objects suddenly may have ran out of scope.

In [40]:
#include "MueLu_CoarseMapFactory.hpp"


Out[40]:


In [41]:
MueLu::CoarseMapFactory<SC,LO,GO,NO> coarseMapFact;


Out[41]:
(MueLu::CoarseMapFactory<SC, LO, GO, NO> &) @0x7f73d7d7ee48

Again, just for demonstration purposes, we directly connect the nspFact and coarseMapFact using a call to SetFactory


In [42]:
coarseMapFact.SetFactory("Nullspace", rcpNspFact);


Out[42]:
(void) nullptr
SmootherFactory

Last, but not least, the SmootherFactory handles level smoothers. More details about smoothers in MueLu can be found in a separate notebook.


In [43]:
#include "MueLu_SmootherFactory.hpp"


Out[43]:


In [44]:
MueLu::SmootherFactory<SC,LO,GO,NO> smootherFact;


Out[44]:
(MueLu::SmootherFactory<SC, LO, GO, NO> &) @0x7f739d65c000

The FactoryManager

In the previous section, we briefly introduced the minimal set of necessary factories to define an aggregation-based algebraic multigrid setup. We have seen, that one can define direct data dependencies using the Factory::SetFactory(VarName, rcpFactory) routine. Calling this routine defines VarName provided by rcpFactory to be used by the current factory.

It is hard to define all data dependencies this way. In addition to SetFactory we can also globally define certain factories to provide certain data. The FactoryManager manages a list of classes associated to certain data. Unless directly defined, a Factory uses then the information from the FactoryManager to find the factory supposed to provide requested data.

First, we create an empty FactoryManager object using


In [45]:
#include "MueLu_FactoryManager.hpp"


Out[45]:


In [46]:
MueLu::FactoryManager<SC,LO,GO,NO> M;


Out[46]:
(MueLu::FactoryManager<SC, LO, GO, NO> &) @0x7f739d65c178

Then, for each variable name, we declare the (default) factory, which is providing the variable.


In [47]:
M.SetFactory("Smoother", Teuchos::rcpFromRef(smootherFact));
M.SetFactory("CoarseSolver", Teuchos::rcpFromRef(smootherFact));
M.SetFactory("A", Teuchos::rcpFromRef(RAPFact));
M.SetFactory("P", rcpPFact);
M.SetFactory("R", Teuchos::rcpFromRef(RFact));
M.SetFactory("DofsPerNode", rcpCoalFact);
M.SetFactory("Graph", rcpCoalFact);
M.SetFactory("UnAmalgamationInfo", Teuchos::rcpFromRef(amalgFact));
M.SetFactory("Nullspace", rcpPFact);
M.SetFactory("Aggregates", Teuchos::rcpFromRef(aggFact));
M.SetFactory("CoarseMap", Teuchos::rcpFromRef(coarseMapFact));


Out[47]:
(void) @0x7fff2c5d7d40

For example: if not otherwise provided, the variable Nullspace is provided by the TentativePFactory PFact. Or, even more important, variable A is calculated by the RAPFactory. Here, A primarily describes the coarse matrices A, since A is provided by the user on the finest level. You may notice, that some factories (like the CoalesceDropFactory) produce several different variables (such as Graph and DofsPerNode).

For simple standard cases, one can get rid of most of the Factory::SetFactory calls. It should be sufficient to just declare all factories in the FactoryManager in one central place. Vice versa, making sure, that all direct dependencies are set using Factory::SetFactory, one can reduce the number of entries in the FactoryManager.

One can ask the FactoryManager to return the associated (default) factory for a given variable using, e.g.


In [48]:
M.GetFactory("A");


Out[48]:
(const Teuchos::RCP<const MueLu::FactoryManager<double, int, int, Kokkos::Compat::KokkosSerialWrapperNode>::FactoryBase>) @0x2fc587b0

If the variable is not associated with a factory (through a FactoryManager::SetFactory call), the FactoryManager class will try to return hard-coded default factories (for most variable names).

Note: With ```cling``` this is technically not working. That is, in this notebook we have to explicitly creating instances of all the factories we need on the stack. We cannot use auto-generated default factories from the *FactoryManager*

TopSmootherFactory and TopRAPFactory

There are two more rather special factories, which a MueLu user and a standard MueLu developer should not see. But they are there and one should be aware of their existence:

  • TopSmootherFactory
  • TopRAPFactory

It is clear, that most multigrid methods consist of smoothers and transfer operators. Therefore, the variables Smoother and CoarseSolver as well as P and R are special in the sense, that you not only create them during the Setup phase, but you also make heavily use of them during the iteration phase. That is, it makes sense, to keep these data persistent and simplify access to it. This is done by the TopRAPFactory and TopSmootherFactory. These factories make sure, that above variables can be easily accessed on all levels without providing the generating factories. I.e., on all levels you just can use level.Get<Xpetra::Matrix<SC,LO,GO,NO>>("A"); and you will just get the matrix (same for Smoother...)


In [49]:
Teuchos::RCP<MueLu::FactoryManager<SC,LO,GO,NO>> rcpM = Teuchos::rcpFromRef(M);

#include "MueLu_TopSmootherFactory.hpp"
MueLu::TopSmootherFactory<SC,LO,GO,NO> ts(rcpM,"Smoother");


Out[49]:
(MueLu::TopSmootherFactory<SC, LO, GO, NO> &) @0x7f739d65c278

In [50]:
MueLu::TopSmootherFactory<SC,LO,GO,NO> tsc(rcpM,"CoarseSolver");


Out[50]:
(MueLu::TopSmootherFactory<SC, LO, GO, NO> &) @0x7f739d65c3f0

Let's create a TopRAPFactory object:


In [52]:
#include "MueLu_TopRAPFactory.hpp"


Out[52]:


In [53]:
MueLu::TopRAPFactory<SC,LO,GO,NO> tr(rcpM);


Out[53]:
(MueLu::TopRAPFactory<SC, LO, GO, NO> &) @0x7f739d65c568

Again, you should never really need to use these factories directly (unless you are modifying the Hierarchy in special ways).

Hierarchy::Setup - let's do multigrid

With the FactoryManager set up using all the previously defined Factories, we finally can call the Setup routine to generate the multigrid hierarchy.

For example, with Hierarchy::Setup(M,0,1); we create a 1-level method using the FactoryManager M.


In [54]:
H.Setup(M,0,1);


Setup (MueLu::Hierarchy)
 Clearing old data (if any)
 A0 size =  100 x 100, nnz = 298
 A0 Load balancing info
 A0   # active processes: 1/1
 A0   # rows per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
 A0   #  nnz per proc   : avg = 2.98e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
 Setup loop: startLevel = 0, lastLevel = 0 (stop if numLevels = 1 or Ac.size() < 10)
 Level 0
 
 --------------------------------------------------------------------------------
 ---                            Multigrid Summary                             ---
 --------------------------------------------------------------------------------
 Number of levels    = 1
 Operator complexity = 1.00
 Smoother complexity = 0.00
 Cycle type          = V
 
 level  rows  nnz  nnz/row  c ratio  procs
   0    100  298     2.98               1
 
 Smoother (level 0) pre  : no smoother
 Smoother (level 0) post : no smoother
 
Out[54]:
(void) @0x7fff2c5d7d40

Obviously, we built a one-level method with no smoother. We can build a two-level method (starting level = 0, ending level = 1) using:


In [55]:
H.Setup(M,0,2);


Setup (MueLu::Hierarchy)
 Clearing old data (if any)
 A0 size =  100 x 100, nnz = 298
 A0 Load balancing info
 A0   # active processes: 1/1
 A0   # rows per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
 A0   #  nnz per proc   : avg = 2.98e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
 Setup loop: startLevel = 0, lastLevel = 1 (stop if numLevels = 2 or Ac.size() < 10)
 Level 0
 Level 1
  Build (MueLu::TentativePFactory)
   Build (MueLu::UncoupledAggregationFactory)
    Build (MueLu::CoalesceDropFactory)
     Build (MueLu::AmalgamationFactory)
      
      ******* WARNING *******
      AmalagamationFactory::Build(): no striding information available. Use blockdim=1 with offset=0
     lightweight wrap = 1
     algorithm = "classical": threshold = 0, blocksize = 1
     
     ******* WARNING *******
     Level::Set: unable to store "Filtering" generated by factory 0x7f73d7d7e5f0 on level 0, as it has not been requested and no keep flags were set for it
     Detected 0 Dirichlet nodes
     Number of dropped entries in unamalgamated matrix graph: 0/298 (0%)
    Algo "Phase - (Dirichlet)"
     BuildAggregates (Phase - (Dirichlet))
       aggregated : 0 (phase), 0/100 [0.00%] (total)
       remaining  : 100
       aggregates : 0 (phase), 0 (total)
    Algo "Phase 1 (main)"
     BuildAggregates (Phase 1 (main))
       aggregated : 100 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 34 (phase), 34 (total)
    Algo "Phase 2a (secondary)"
     BuildAggregates (Phase 2a (secondary))
       aggregated : 0 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 34 (total)
    Algo "Phase 2b (expansion)"
     BuildAggregates (Phase 2b (expansion))
       aggregated : 0 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 34 (total)
    Algo "Phase 3 (cleanup)"
     BuildAggregates (Phase 3 (cleanup))
       aggregated : 0 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 34 (total)
    "UC": MueLu::Aggregates{nGlobalAggregates = 34}
   Nullspace factory (MueLu::NullspaceFactory)
    Generating canonical nullspace: dimension = 1
   Build (MueLu::CoarseMapFactory)
    domainGIDOffset: 0 block size: 1 stridedBlockId: -1
   Column map is consistent with the row map, good.
   TentativePFactory : aggregates do not cross process boundaries
   
   ******* WARNING *******
   Level::Set: unable to store "Nullspace" generated by factory 0x7f73d7d7ea30 on level 1, as it has not been requested and no keep flags were set for it
   Ptent size =  100 x 34, nnz = 100
   Ptent Load balancing info
   Ptent   # active processes: 1/1
   Ptent   # rows per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   Ptent   #  nnz per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
  Transpose P (MueLu::TransPFactory)
   R size =  34 x 100, nnz = 100
   R Load balancing info
   R   # active processes: 1/1
   R   # rows per proc   : avg = 3.40e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   R   #  nnz per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
  Computing Ac (MueLu::RAPFactory)
   MxM: A x P
   MxM: R x (AP) (explicit)
   Ac size =  34 x 34, nnz = 100
   Ac Load balancing info
   Ac   # active processes: 1/1
   Ac   # rows per proc   : avg = 3.40e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   Ac   #  nnz per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   
   ******* WARNING *******
   Level::Set: unable to store "AP reuse data" generated by factory 0x7f73d7d7ece0 on level 1, as it has not been requested and no keep flags were set for it
   
   ******* WARNING *******
   Level::Set: unable to store "RAP reuse data" generated by factory 0x7f73d7d7ece0 on level 1, as it has not been requested and no keep flags were set for it
 
 --------------------------------------------------------------------------------
 ---                            Multigrid Summary                             ---
 --------------------------------------------------------------------------------
 Number of levels    = 2
 Operator complexity = 1.34
 Smoother complexity = 0.00
 Cycle type          = V
 
 level  rows  nnz  nnz/row  c ratio  procs
   0    100  298     2.98               1
   1     34  100     2.94     2.94      1
 
 Smoother (level 0) pre  : no smoother
 Smoother (level 0) post : no smoother
 
 Smoother (level 1) pre  : no smoother
 Smoother (level 1) post : no smoother
 
Out[55]:
(void) @0x7fff2c5d7d40

We got a two-level method with no smoothers. Of course, without level smoothers this would be a very inefficient multigrid method.

Why does it not create level smoothers even though we extra defined a SmootherFactory in the FactoryManager?

Level smoothers in MueLu

Let's add level smoothers:


In [58]:
#include "Teuchos_ParameterList.hpp"


Out[58]:


In [59]:
Teuchos::ParameterList smooParams;


Out[59]:
(Teuchos::ParameterList &) {}

In [60]:
smooParams.set("type", Teuchos::ParameterEntry("RELAXATION"));
Teuchos::ParameterList& subSmooParams = smooParams.sublist("ParamterList");
subSmooParams.set("relaxation: type", "Symmetric Gauss-Seidel");
subSmooParams.set("relaxation: sweeps",1);
subSmooParams.set("relaxation: damping factor",1.0);


Out[60]:
(Teuchos::ParameterList &) { "relaxation: type" => @0x38e38f58, "relaxation: sweeps" => @0x38e38fa0, "relaxation: damping factor" => @0x38e38fe8 }

In [61]:
std::cout << smooParams << std::endl;


type = RELAXATION   [unused]   [unused]
ParamterList -> 
 relaxation: type = Symmetric Gauss-Seidel   [unused]
 relaxation: sweeps = 1   [unused]
 relaxation: damping factor = 1   [unused]

Out[61]:
(std::basic_ostream<char, std::char_traits<char> >::__ostream_type &) @0x7f3c65c6f700

In [62]:
#include "MueLu_TrilinosSmoother.hpp"


Out[62]:


In [63]:
MueLu::TrilinosSmoother<SC,LO,GO,NO> trSmoother("RELAXATION", subSmooParams);


Out[63]:
(MueLu::TrilinosSmoother<SC, LO, GO, NO> &) @0x7f3c2f808798

In [64]:
PFact.DisableMultipleCheckGlobally();


Out[64]:
(void) @0x7ffe046c38f0

In [65]:
smootherFact.SetSmootherPrototypes(Teuchos::rcpFromRef(trSmoother));


Out[65]:
(void) @0x7ffe046c38f0

In [66]:
H.Setup(M,0,2);


Setup (MueLu::Hierarchy)
 Clearing old data (if any)
 A0 size =  100 x 100, nnz = 298
 A0 Load balancing info
 A0   # active processes: 1/1
 A0   # rows per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
 A0   #  nnz per proc   : avg = 2.98e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
 Setup loop: startLevel = 0, lastLevel = 1 (stop if numLevels = 2 or Ac.size() < 10)
 Level 0
  Setup Smoother (MueLu::IfpackSmoother{type = point relaxation stand-alone})
   IFPACK (Local SGS, sweeps=1, damping=1)
 Level 1
  Build (MueLu::TentativePFactory)
   Build (MueLu::UncoupledAggregationFactory)
    Build (MueLu::CoalesceDropFactory)
     PreDropFunctionConstVal: threshold = 0
     Build (MueLu::AmalgamationFactory)
      
      ******* WARNING *******
      AmalagamationFactory::Build(): no striding information available. Use blockdim=1 with offset=0
     lightweight wrap = 1
     algorithm = "classical": threshold = 0.00, blocksize = 1
     
     ******* WARNING *******
     Level::Set: unable to store "Filtering" generated by factory 0x7f3c6df2a5f0 on level 0, as it has not been requested and no keep flags were set for it
     Detected 0 Dirichlet nodes
     Number of dropped entries in unamalgamated matrix graph: 0/298 (0.00%)
    Algo "Phase - (Dirichlet)"
     BuildAggregates (Phase - (Dirichlet))
       aggregated : 0 (phase), 0/100 [0.00%] (total)
       remaining  : 100
       aggregates : 0 (phase), 0 (total)
    Algo "Phase 1 (main)"
     BuildAggregates (Phase 1 (main))
       aggregated : 100 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 34 (phase), 34 (total)
    Algo "Phase 2a (secondary)"
     BuildAggregates (Phase 2a (secondary))
       aggregated : 0 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 34 (total)
    Algo "Phase 2b (expansion)"
     BuildAggregates (Phase 2b (expansion))
       aggregated : 0 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 34 (total)
    Algo "Phase 3 (cleanup)"
     BuildAggregates (Phase 3 (cleanup))
       aggregated : 0 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 34 (total)
    "UC": MueLu::Aggregates{nGlobalAggregates = 34}
   Nullspace factory (MueLu::NullspaceFactory)
    Generating canonical nullspace: dimension = 1
   Build (MueLu::CoarseMapFactory)
    domainGIDOffset: 0 block size: 1 stridedBlockId: -1
   Column map is consistent with the row map, good.
   TentativePFactory : aggregates do not cross process boundaries
   
   ******* WARNING *******
   Level::Set: unable to store "Nullspace" generated by factory 0x7f3c6df2aa30 on level 1, as it has not been requested and no keep flags were set for it
   Ptent size =  100 x 34, nnz = 100
   Ptent Load balancing info
   Ptent   # active processes: 1/1
   Ptent   # rows per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   Ptent   #  nnz per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
  Transpose P (MueLu::TransPFactory)
   R size =  34 x 100, nnz = 100
   R Load balancing info
   R   # active processes: 1/1
   R   # rows per proc   : avg = 3.40e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   R   #  nnz per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
  Computing Ac (MueLu::RAPFactory)
   MxM: A x P
   MxM: R x (AP) (explicit)
   Ac size =  34 x 34, nnz = 100
   Ac Load balancing info
   Ac   # active processes: 1/1
   Ac   # rows per proc   : avg = 3.40e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   Ac   #  nnz per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   
   ******* WARNING *******
   Level::Set: unable to store "AP reuse data" generated by factory 0x7f3c6df2ace0 on level 1, as it has not been requested and no keep flags were set for it
   
   ******* WARNING *******
   Level::Set: unable to store "RAP reuse data" generated by factory 0x7f3c6df2ace0 on level 1, as it has not been requested and no keep flags were set for it
  Setup Smoother (MueLu::IfpackSmoother{type = point relaxation stand-alone})
   IFPACK (Local SGS, sweeps=1, damping=1)
  
  ******* WARNING *******
  Level::Set: unable to store "PostSmoother" generated by factory 0x7f3c2f808000 on level 1, as it has not been requested and no keep flags were set for it
 
 --------------------------------------------------------------------------------
 ---                            Multigrid Summary                             ---
 --------------------------------------------------------------------------------
 Number of levels    = 2
 Operator complexity = 1.34
 Smoother complexity = 0.00
 Cycle type          = V
 
 level  rows  nnz  nnz/row  c ratio  procs
   0    100  298     2.98               1
   1     34  100     2.94     2.94      1
 
 Smoother (level 0) both : IFPACK (Local SGS, sweeps=1, damping=1)
 
 Smoother (level 1) pre  : IFPACK (Local SGS, sweeps=1, damping=1)
 Smoother (level 1) post : no smoother
 
Out[66]:
(void) @0x7ffe046c38f0

In [67]:
H.Setup(M,0,3);


Setup (MueLu::Hierarchy)
 Clearing old data (if any)
 A0 size =  100 x 100, nnz = 298
 A0 Load balancing info
 A0   # active processes: 1/1
 A0   # rows per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
 A0   #  nnz per proc   : avg = 2.98e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
 Setup loop: startLevel = 0, lastLevel = 2 (stop if numLevels = 3 or Ac.size() < 10)
 Level 0
  Setup Smoother (MueLu::IfpackSmoother{type = point relaxation stand-alone})
   IFPACK (Local SGS, sweeps=1, damping=1)
 Level 1
  Build (MueLu::TentativePFactory)
   Build (MueLu::UncoupledAggregationFactory)
    Build (MueLu::CoalesceDropFactory)
     PreDropFunctionConstVal: threshold = 0
     Build (MueLu::AmalgamationFactory)
      
      ******* WARNING *******
      AmalagamationFactory::Build(): no striding information available. Use blockdim=1 with offset=0
     lightweight wrap = 1
     algorithm = "classical": threshold = 0.00, blocksize = 1
     
     ******* WARNING *******
     Level::Set: unable to store "Filtering" generated by factory 0x7f3c6df2a5f0 on level 0, as it has not been requested and no keep flags were set for it
     Detected 0 Dirichlet nodes
     Number of dropped entries in unamalgamated matrix graph: 0/298 (0.00%)
    Algo "Phase - (Dirichlet)"
     BuildAggregates (Phase - (Dirichlet))
       aggregated : 0 (phase), 0/100 [0.00%] (total)
       remaining  : 100
       aggregates : 0 (phase), 0 (total)
    Algo "Phase 1 (main)"
     BuildAggregates (Phase 1 (main))
       aggregated : 100 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 34 (phase), 34 (total)
    Algo "Phase 2a (secondary)"
     BuildAggregates (Phase 2a (secondary))
       aggregated : 0 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 34 (total)
    Algo "Phase 2b (expansion)"
     BuildAggregates (Phase 2b (expansion))
       aggregated : 0 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 34 (total)
    Algo "Phase 3 (cleanup)"
     BuildAggregates (Phase 3 (cleanup))
       aggregated : 0 (phase), 100/100 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 34 (total)
    "UC": MueLu::Aggregates{nGlobalAggregates = 34}
   Nullspace factory (MueLu::NullspaceFactory)
    Generating canonical nullspace: dimension = 1
   Build (MueLu::CoarseMapFactory)
    domainGIDOffset: 0 block size: 1 stridedBlockId: -1
   Column map is consistent with the row map, good.
   TentativePFactory : aggregates do not cross process boundaries
   Ptent size =  100 x 34, nnz = 100
   Ptent Load balancing info
   Ptent   # active processes: 1/1
   Ptent   # rows per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   Ptent   #  nnz per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
  Transpose P (MueLu::TransPFactory)
   R size =  34 x 100, nnz = 100
   R Load balancing info
   R   # active processes: 1/1
   R   # rows per proc   : avg = 3.40e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   R   #  nnz per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
  Computing Ac (MueLu::RAPFactory)
   MxM: A x P
   MxM: R x (AP) (explicit)
   Ac size =  34 x 34, nnz = 100
   Ac Load balancing info
   Ac   # active processes: 1/1
   Ac   # rows per proc   : avg = 3.40e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   Ac   #  nnz per proc   : avg = 1.00e+02,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   
   ******* WARNING *******
   Level::Set: unable to store "AP reuse data" generated by factory 0x7f3c6df2ace0 on level 1, as it has not been requested and no keep flags were set for it
   
   ******* WARNING *******
   Level::Set: unable to store "RAP reuse data" generated by factory 0x7f3c6df2ace0 on level 1, as it has not been requested and no keep flags were set for it
  Setup Smoother (MueLu::IfpackSmoother{type = point relaxation stand-alone})
   IFPACK (Local SGS, sweeps=1, damping=1)
 Level 2
  Build (MueLu::TentativePFactory)
   Build (MueLu::UncoupledAggregationFactory)
    Build (MueLu::CoalesceDropFactory)
     PreDropFunctionConstVal: threshold = 0
     Build (MueLu::AmalgamationFactory)
      AmalagamationFactory::Build(): found fullblocksize=1 and stridedblocksize=1 from strided maps. offset=0
     lightweight wrap = 1
     algorithm = "classical": threshold = 0.00, blocksize = 1
     
     ******* WARNING *******
     Level::Set: unable to store "Filtering" generated by factory 0x7f3c6df2a5f0 on level 1, as it has not been requested and no keep flags were set for it
     Detected 0 Dirichlet nodes
     Number of dropped entries in unamalgamated matrix graph: 0/100 (0.00%)
    Algo "Phase - (Dirichlet)"
     BuildAggregates (Phase - (Dirichlet))
       aggregated : 0 (phase), 0/34 [0.00%] (total)
       remaining  : 34
       aggregates : 0 (phase), 0 (total)
    Algo "Phase 1 (main)"
     BuildAggregates (Phase 1 (main))
       aggregated : 34 (phase), 34/34 [100.00%] (total)
       remaining  : 0
       aggregates : 12 (phase), 12 (total)
    Algo "Phase 2a (secondary)"
     BuildAggregates (Phase 2a (secondary))
       aggregated : 0 (phase), 34/34 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 12 (total)
    Algo "Phase 2b (expansion)"
     BuildAggregates (Phase 2b (expansion))
       aggregated : 0 (phase), 34/34 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 12 (total)
    Algo "Phase 3 (cleanup)"
     BuildAggregates (Phase 3 (cleanup))
       aggregated : 0 (phase), 34/34 [100.00%] (total)
       remaining  : 0
       aggregates : 0 (phase), 12 (total)
    "UC": MueLu::Aggregates{nGlobalAggregates = 12}
   Nullspace factory (MueLu::NullspaceFactory)
   Build (MueLu::CoarseMapFactory)
    domainGIDOffset: 0 block size: 1 stridedBlockId: -1
   Column map is consistent with the row map, good.
   TentativePFactory : aggregates do not cross process boundaries
   
   ******* WARNING *******
   Level::Set: unable to store "Nullspace" generated by factory 0x7f3c6df2aa30 on level 2, as it has not been requested and no keep flags were set for it
   Ptent size =  34 x 12, nnz = 34
   Ptent Load balancing info
   Ptent   # active processes: 1/1
   Ptent   # rows per proc   : avg = 3.40e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   Ptent   #  nnz per proc   : avg = 3.40e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
  Transpose P (MueLu::TransPFactory)
   R size =  12 x 34, nnz = 34
   R Load balancing info
   R   # active processes: 1/1
   R   # rows per proc   : avg = 1.20e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   R   #  nnz per proc   : avg = 3.40e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
  Computing Ac (MueLu::RAPFactory)
   MxM: A x P
   MxM: R x (AP) (explicit)
   Ac size =  12 x 12, nnz = 34
   Ac Load balancing info
   Ac   # active processes: 1/1
   Ac   # rows per proc   : avg = 1.20e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   Ac   #  nnz per proc   : avg = 3.40e+01,  dev =   0.0%,  min =   +0.0%,  max =   +0.0%
   
   ******* WARNING *******
   Level::Set: unable to store "AP reuse data" generated by factory 0x7f3c6df2ace0 on level 2, as it has not been requested and no keep flags were set for it
   
   ******* WARNING *******
   Level::Set: unable to store "RAP reuse data" generated by factory 0x7f3c6df2ace0 on level 2, as it has not been requested and no keep flags were set for it
  Setup Smoother (MueLu::IfpackSmoother{type = point relaxation stand-alone})
   IFPACK (Local SGS, sweeps=1, damping=1)
  
  ******* WARNING *******
  Level::Set: unable to store "PostSmoother" generated by factory 0x7f3c2f808000 on level 2, as it has not been requested and no keep flags were set for it
 
 --------------------------------------------------------------------------------
 ---                            Multigrid Summary                             ---
 --------------------------------------------------------------------------------
 Number of levels    = 3
 Operator complexity = 1.45
 Smoother complexity = 0.00
 Cycle type          = V
 
 level  rows  nnz  nnz/row  c ratio  procs
   0    100  298     2.98               1
   1     34  100     2.94     2.94      1
   2     12   34     2.83     2.83      1
 
 Smoother (level 0) both : IFPACK (Local SGS, sweeps=1, damping=1)
 
 Smoother (level 1) both : IFPACK (Local SGS, sweeps=1, damping=1)
 
 Smoother (level 2) pre  : IFPACK (Local SGS, sweeps=1, damping=1)
 Smoother (level 2) post : no smoother
 
Out[67]:
(void) @0x7ffe046c38f0

In [ ]: