Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_MLPrecOp.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Stokhos Package
4 //
5 // Copyright 2009 NTESS and the Stokhos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #include "Stokhos_MLPrecOp.hpp"
11 
12 #ifdef HAVE_STOKHOS_ML
13 
14 //==============================================================================
15 // constructor -- it's presumed that the user has constructed the ML
16 // object somewhere else. Uses AMG to invert the mean stiffness matrix.
17 Stokhos::MLPrecOp::MLPrecOp(const Epetra_CrsMatrix& mean_op,const Teuchos::Array<double>& norms, const Epetra_Comm& Comm, const Epetra_Map& DMap,const Epetra_Map& RMap)
18  : //Epetra_Operator(),
19  Comm_(Comm),
20  Label_(0),
21  DomainMap_(DMap),
22  RangeMap_(RMap),
23  norms_(norms)
24  {
25  Label_ = "Stochos::MLPrecOp";
26 
27 
28  // create a parameter list for ML options
30 
31  // Sets default parameters for classic smoothed aggregation. After this
32  // call, MLList contains the default values for the ML parameters,
33  // as required by typical smoothed aggregation for symmetric systems.
34  // Other sets of parameters are available for non-symmetric systems
35  // ("DD" and "DD-ML"), and for the Maxwell equations ("maxwell").
36  ML_Epetra::SetDefaults("SA",MLList);
37 
38  // overwrite some parameters. Please refer to the user's guide
39  // for more information
40  // some of the parameters do not differ from their default value,
41  // and they are here reported for the sake of clarity
42 
43  // output level, 0 being silent and 10 verbose
44  MLList.set("ML output", 10);
45  // maximum number of levels
46  MLList.set("max levels",5);
47  // set finest level to 0
48  MLList.set("increasing or decreasing","increasing");
49 
50  // use Uncoupled scheme to create the aggregate
51  MLList.set("aggregation: type", "Uncoupled");
52 
53  // smoother is Chebyshev. Example file
54  // `ml/examples/TwoLevelDD/ml_2level_DD.cpp' shows how to use
55  // AZTEC's preconditioners as smoothers
56 
57  MLList.set("smoother: type","Chebyshev");
58  MLList.set("smoother: sweeps",3);
59 
60  // use both pre and post smoothing
61  MLList.set("smoother: pre or post", "both");
62  //MLList.set("coarse: max size", );
63 
64 #ifdef HAVE_ML_AMESOS
65  // solve with serial direct solver KLU
66  MLList.set("coarse: type","Amesos-KLU");
67 #else
68  // this is for testing purposes only, you should have
69  // a direct solver for the coarse problem (either Amesos, or the SuperLU/
70  // SuperLU_DIST interface of ML)
71  MLList.set("coarse: type","Jacobi");
72 #endif
73 
74  // Creates the preconditioning object. We suggest to use `new' and
75  // `delete' because the destructor contains some calls to MPI (as
76  // required by ML and possibly Amesos). This is an issue only if the
77  // destructor is called **after** MPI_Finalize().
78 
79  MLPrec = new ML_Epetra::MultiLevelPreconditioner(mean_op, MLList);
80 
81  // verify unused parameters on process 0 (put -1 to print on all
82  // processes)
83  MLPrec->PrintUnused(0);
84 
85 
86 }
87 
88 //==============================================================================
89 //Applies the preconditioner implicitly to the global stiffness matrix.
90 //==============================================================================
91 
92 int Stokhos::MLPrecOp::ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const{
93 
94  if (!X.Map().SameAs(OperatorDomainMap()))
95  std::cout << "!X.Map().SameAs(OperatorDomainMap())\n";
96  if (!Y.Map().SameAs(OperatorRangeMap()))
97  std::cout<< "!Y.Map().SameAs(OperatorRangeMap())\n";
98  if (Y.NumVectors()!=X.NumVectors())
99  std::cout<< "Y.NumVectors()!=X.NumVectors()\n";
100 
101 
102 
103  for(int mm = 0; mm< X.NumVectors(); mm++){
104 
105 
106  int N_xi = norms_.size();
107  int N_x = X.MyLength()/N_xi;
108 
109  // Construct a Map with NumElements and index base of 0
110  //Epetra_Map::Epetra_Map Map(N_x, 0, Comm_);
111  Epetra_Map Map(MLPrec->OperatorDomainMap());
112 
113  // Form x and y into block vectors.
114  Epetra_MultiVector xBlock(Map,N_xi);
115  Epetra_MultiVector yBlock(MLPrec->OperatorRangeMap(),N_xi);
116 
117  // get the local size of the vector
118  int MyLength = xBlock.MyLength();
119  for( int c=0; c<N_xi ; c++){
120  for( int i=0; i<MyLength; i++){
121  xBlock[c][i] = (X)[mm][c*N_x + i];
122  yBlock[c][i] = 0;
123  }
124  }
125 
126  Epetra_MultiVector blockProducts(MLPrec->OperatorRangeMap(),N_xi);
127  MLPrec->ApplyInverse(xBlock, blockProducts);
128 
129 
130  for(int j = 0; j<N_xi; j++){
131  (*yBlock(j)).Update(1/norms_[j],*blockProducts(j), 1.0);
132  }
133 
134  for( int c=0; c<N_xi ; c++){
135  for( int i=0; i<MyLength; i++){
136  (Y)[mm][c*N_x + i] = yBlock[c][i];
137  }
138  }
139  }
140  return 1;
141 }
142 
143 #endif
144 
145 
146 
147 
bool SameAs(const Epetra_BlockMap &Map) const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
virtual const Epetra_BlockMap & Map() const =0