Ifpack Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
test/TestAll/cxx_main.cpp
Go to the documentation of this file.
1 /*@HEADER
2 // ***********************************************************************
3 //
4 // Ifpack: Object-Oriented Algebraic Preconditioner Package
5 // Copyright (2002) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 //@HEADER
41 */
42 
43 #include "Ifpack_ConfigDefs.h"
44 
45 #ifdef HAVE_MPI
46 #include "Epetra_MpiComm.h"
47 #else
48 #include "Epetra_SerialComm.h"
49 #endif
50 #include "Epetra_CrsMatrix.h"
51 #include "Epetra_Vector.h"
52 #include "Epetra_LinearProblem.h"
53 #include "Galeri_Maps.h"
54 #include "Galeri_CrsMatrices.h"
55 #include "Teuchos_ParameterList.hpp"
56 #include "Teuchos_RefCountPtr.hpp"
57 #include "Ifpack_AdditiveSchwarz.h"
58 #include "AztecOO.h"
59 #include "Ifpack_PointRelaxation.h"
60 #include "Ifpack_BlockRelaxation.h"
61 #include "Ifpack_DenseContainer.h"
62 #include "Ifpack_SparseContainer.h"
63 #include "Ifpack_Amesos.h"
64 #include "Ifpack_Utils.h"
65 #include "Ifpack_Chebyshev.h"
66 #include "Ifpack_Polynomial.h"
67 #include "Ifpack_Krylov.h"
68 
69 template <class CommType>
70 Teuchos::RefCountPtr<Epetra_RowMatrix>
71 createTriDiagMat(int NumGlobalElements, CommType Comm, bool str_singular, bool num_singular) {
72  // Construct a Map that puts approximatively the same number of
73  // equations on each processor. `0' is the index base (that is,
74  // numbering starts from 0.
75  Epetra_Map Map(NumGlobalElements, 0, Comm);
76 
77  // Create an empty EpetraCrsMatrix
78  Teuchos::RefCountPtr<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix(Copy, Map, 0));
79 
80  // Create the structure of the matrix (tridiagonal)
81  int NumMyElements = Map.NumMyElements();
82 
83  // Add rows one-at-a-time
84  // Need some vectors to help
85 
86  double Values[3];
87  // Right now, we put zeros only in the matrix.
88  int Indices[3];
89  int NumEntries;
91  int* MyGlobalElements = Map.MyGlobalElements();
92 
93  // At this point we simply set the nonzero structure of A.
94  // Actual values will be inserted later (now all zeros)
95  for (int i = 0; i < NumMyElements; i++)
96  {
97  if (MyGlobalElements[i] == 0)
98  {
99  if (str_singular) {
100  NumEntries = 0;
101  } else {
102  Indices[0] = 0;
103  Indices[1] = 1;
104  if (num_singular) {
105  Values[0] = 0.0;
106  Values[1] = 0.0;
107  } else {
108  Values[0] = 2.0;
109  Values[1] = 1.0;
110  }
111  NumEntries = 2;
112  }
113  }
114  else if (MyGlobalElements[i] == NumGlobalElements-1)
115  {
116  Indices[0] = NumGlobalElements-1;
117  Indices[1] = NumGlobalElements-2;
118  Values[0] = 2.0;
119  Values[1] = 1.0;
120  NumEntries = 2;
121  }
122  else
123  {
124  Indices[0] = MyGlobalElements[i]-1;
125  Indices[1] = MyGlobalElements[i];
126  Indices[2] = MyGlobalElements[i]+1;
127  Values[0] = 1.0;
128  Values[1] = 2.0;
129  Values[2] = 1.0;
130  NumEntries = 3;
131  }
132 
133  if (NumEntries > 0)
134  A->InsertGlobalValues(MyGlobalElements[i],
135  NumEntries, Values, Indices);
136  }
137 
138  // Finish up.
139  A->FillComplete();
140  //A->Print(std::cout);
141 
142  return A;
143 }
144 
145 template <class T>
146 bool Test(const Teuchos::RefCountPtr<Epetra_RowMatrix>& Matrix, Teuchos::ParameterList& List)
147 {
148 
149  int NumVectors = 1;
150  bool UseTranspose = false;
151 
152  Epetra_MultiVector LHS(Matrix->OperatorDomainMap(),NumVectors);
153  Epetra_MultiVector RHS(Matrix->OperatorRangeMap(),NumVectors);
154  Epetra_MultiVector LHSexact(Matrix->OperatorDomainMap(),NumVectors);
155 
156  LHS.PutScalar(0.0);
157  LHSexact.Random();
158  Matrix->Multiply(UseTranspose,LHSexact,RHS);
159 
160  Epetra_LinearProblem Problem(&*Matrix,&LHS,&RHS);
161 
162  Teuchos::RefCountPtr<T> Prec;
163 
164  Prec = Teuchos::rcp( new T(&*Matrix) );
165  assert(Prec != Teuchos::null);
166 
167  IFPACK_CHK_ERRB(Prec->SetParameters(List));
168  IFPACK_CHK_ERRB(Prec->Initialize());
169  IFPACK_CHK_ERRB(Prec->Compute());
170 
171  // create the AztecOO solver
172  AztecOO AztecOOSolver(Problem);
173 
174  // specify solver
175  AztecOOSolver.SetAztecOption(AZ_solver,AZ_gmres);
176  AztecOOSolver.SetAztecOption(AZ_output,32);
177 
178  AztecOOSolver.SetPrecOperator(&*Prec);
179 
180  // solver. The solver should converge in one iteration,
181  // or maximum two (numerical errors)
182  AztecOOSolver.Iterate(1550,1e-8);
183 
184  cout << *Prec;
185 
186  std::vector<double> Norm(NumVectors);
187  LHS.Update(1.0,LHSexact,-1.0);
188  LHS.Norm2(&Norm[0]);
189  for (int i = 0 ; i < NumVectors ; ++i) {
190  cout << "Norm[" << i << "] = " << Norm[i] << endl;
191  if (Norm[i] > 1e-3)
192  return(false);
193  }
194  return(true);
195 
196 }
197 
198 int main(int argc, char *argv[])
199 {
200 
201 #ifdef HAVE_MPI
202  MPI_Init(&argc,&argv);
203  Epetra_MpiComm Comm(MPI_COMM_WORLD);
204 #else
205  Epetra_SerialComm Comm;
206 #endif
207 
208  bool verbose = (Comm.MyPID() == 0);
209 
210  Teuchos::ParameterList GaleriList;
211  const int nx = 30;
212  GaleriList.set("n", nx * nx);
213  GaleriList.set("nx", nx);
214  GaleriList.set("ny", nx);
215  Teuchos::RefCountPtr<Epetra_Map> Map = Teuchos::rcp( Galeri::CreateMap("Linear", Comm, GaleriList) );
216  Teuchos::RefCountPtr<Epetra_RowMatrix> Matrix = Teuchos::rcp( Galeri::CreateCrsMatrix("Laplace2D", &*Map, GaleriList) );
217 
218  Teuchos::ParameterList List, DefaultList;
219 
220  // test the preconditioner
221  int TestPassed = true;
222 
223  if (!Test<Ifpack_Chebyshev>(Matrix,List))
224  {
225  TestPassed = false;
226  }
227 
228  List.set("polynomial: degree",3);
229  if (!Test<Ifpack_Polynomial>(Matrix,List))
230  {
231  TestPassed = false;
232  }
233 
234  List = DefaultList;
235  List.set("krylov: tolerance", 1e-14);
236  List.set("krylov: iterations", 100);
237  List.set("krylov: preconditioner", 2);
238  List.set("krylov: block size", 9);
239  List.set("krylov: number of sweeps", 2);
240  if (!Test<Ifpack_Krylov>(Matrix,List))
241  {
242  TestPassed = false;
243  }
244 
245  if (!Test< Ifpack_AdditiveSchwarz<Ifpack_Krylov> >(Matrix,List)) {
246  TestPassed = false;
247  }
248 
249  if (!Test<Ifpack_Amesos>(Matrix,List))
250  {
251  TestPassed = false;
252  }
253 
254  // FIXME
255 #if 0
257  TestPassed = false;
258  }
259 #endif
260 
261  // this is ok as long as just one sweep is applied
262  List = DefaultList;
263  List.set("relaxation: type", "Gauss-Seidel");
264  if (!Test<Ifpack_PointRelaxation>(Matrix,List)) {
265  TestPassed = false;
266  }
267 
268  // this is ok as long as just one sweep is applied
269  List = DefaultList;
270  List.set("relaxation: type", "symmetric Gauss-Seidel");
271  List.set("relaxation: sweeps", 5);
272  List.set("partitioner: local parts", 128);
273  List.set("partitioner: type", "linear");
275  TestPassed = false;
276  }
277 
278  // this is ok as long as just one sweep is applied
279  List = DefaultList;
280  List.set("relaxation: type", "symmetric Gauss-Seidel");
281  List.set("partitioner: local parts", 128);
282  List.set("partitioner: type", "linear");
284  TestPassed = false;
285  }
286 
287  // this is ok as long as just one sweep is applied
288  List = DefaultList;
289  List.set("relaxation: type", "symmetric Gauss-Seidel");
290  List.set("partitioner: local parts", 128);
291  List.set("partitioner: type", "linear");
293  TestPassed = false;
294  }
295 
296 #ifdef HAVE_IFPACK_AMESOS
297  // Additive Schwarz with local Amesos
298  // Amesos should fail on MPI-0.
299  // So, these tests should fail,
300  // but are designed to check that error is propagated to all MPI processes
301  // instead of just failing on MPI-0, causing deadlock
302  bool check_for_global_error = false;
303  if (check_for_global_error) {
304  // structurally singular case
305  List = DefaultList;
306  bool num_singular = false;
307  bool str_singular = true;
308  Matrix = createTriDiagMat(10, Comm, str_singular, num_singular);
309  if (Test<Ifpack_AdditiveSchwarz<Ifpack_Amesos>>(Matrix,List)) {
310  TestPassed = false;
311  }
312  // numerically singular case
313  num_singular = true;
314  str_singular = false;
315  Matrix = createTriDiagMat(10, Comm, str_singular, num_singular);
316  if (Test<Ifpack_AdditiveSchwarz<Ifpack_Amesos>>(Matrix,List)) {
317  TestPassed = false;
318  }
319  }
320 #endif
321 
322  if (!TestPassed) {
323  cerr << "Test `TestAll.exe' FAILED!" << endl;
324  exit(EXIT_FAILURE);
325  }
326 
327 #ifdef HAVE_MPI
328  MPI_Finalize();
329 #endif
330  if (verbose)
331  cout << "Test `TestAll.exe' passed!" << endl;
332 
333  return(EXIT_SUCCESS);
334 }
bool Test(const Teuchos::RefCountPtr< Epetra_RowMatrix > &Matrix, Teuchos::ParameterList &List)
Ifpack_BlockRelaxation: a class to define block relaxation preconditioners of Epetra_RowMatrix&#39;s.
int MyGlobalElements(int *MyGlobalElementList) const
const int NumVectors
Definition: performance.cpp:71
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
int MyPID() const
int NumMyElements() const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Ifpack_AdditiveSchwarz: a class to define Additive Schwarz preconditioners of Epetra_RowMatrix&#39;s.
Ifpack_SparseContainer: a class for storing and solving linear systems using sparse matrices...
int main(int argc, char *argv[])
#define IFPACK_CHK_ERRB(ifpack_err)
Teuchos::RefCountPtr< Epetra_RowMatrix > createTriDiagMat(int NumGlobalElements, CommType Comm, bool str_singular, bool num_singular)
#define RHS(a)
Definition: MatGenFD.c:60