Ifpack Package Browser (Single Doxygen Collection) Development
Loading...
Searching...
No Matches
test/Relaxation_LL/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"
53#include "Epetra_Map.h"
54#include "Galeri_Maps.h"
55#include "Galeri_CrsMatrices.h"
56#include "Galeri_Utils.h"
57#include "Teuchos_ParameterList.hpp"
58#include "Teuchos_RefCountPtr.hpp"
62#include "Ifpack_Amesos.h"
63#include "AztecOO.h"
64
65static bool verbose = false;
66static bool SymmetricGallery = false;
67static bool Solver = AZ_gmres;
68const int NumVectors = 3;
69
70// ======================================================================
71int CompareBlockOverlap(const Teuchos::RefCountPtr<Epetra_RowMatrix>& A, int Overlap)
72{
73 Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors);
74 Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors);
75 LHS.PutScalar(0.0); RHS.Random();
76
77 Epetra_LinearProblem Problem(&*A, &LHS, &RHS);
78
79 Teuchos::ParameterList List;
80 List.set("relaxation: damping factor", 1.0);
81 List.set("relaxation: type", "Jacobi");
82 List.set("relaxation: sweeps",1);
83 List.set("partitioner: overlap", Overlap);
84 List.set("partitioner: type", "linear");
85 List.set("partitioner: local parts", 16);
86
87 RHS.PutScalar(1.0);
88 LHS.PutScalar(0.0);
89
90 Ifpack_BlockRelaxation<Ifpack_SparseContainer<Ifpack_Amesos> > Prec(&*A);
91 Prec.SetParameters(List);
92 Prec.Compute();
93
94 // set AztecOO solver object
95 AztecOO AztecOOSolver(Problem);
96 AztecOOSolver.SetAztecOption(AZ_solver,Solver);
97 if (verbose)
98 AztecOOSolver.SetAztecOption(AZ_output,32);
99 else
100 AztecOOSolver.SetAztecOption(AZ_output,AZ_none);
101 AztecOOSolver.SetPrecOperator(&Prec);
102
103 AztecOOSolver.Iterate(1550,1e-5);
104
105 return(AztecOOSolver.NumIters());
106}
107
108// ======================================================================
109int CompareBlockSizes(std::string PrecType, const Teuchos::RefCountPtr<Epetra_RowMatrix>& A, int NumParts)
110{
111 Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors);
112 Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors);
113 LHS.PutScalar(0.0); RHS.Random();
114
115 Epetra_LinearProblem Problem(&*A, &LHS, &RHS);
116
117 Teuchos::ParameterList List;
118 List.set("relaxation: damping factor", 1.0);
119 List.set("relaxation: type", PrecType);
120 List.set("relaxation: sweeps",1);
121 List.set("partitioner: type", "linear");
122 List.set("partitioner: local parts", NumParts);
123
124 RHS.PutScalar(1.0);
125 LHS.PutScalar(0.0);
126
127 Ifpack_BlockRelaxation<Ifpack_SparseContainer<Ifpack_Amesos> > Prec(&*A);
128 Prec.SetParameters(List);
129 Prec.Compute();
130
131 // set AztecOO solver object
132 AztecOO AztecOOSolver(Problem);
133 AztecOOSolver.SetAztecOption(AZ_solver,Solver);
134 if (verbose)
135 AztecOOSolver.SetAztecOption(AZ_output,32);
136 else
137 AztecOOSolver.SetAztecOption(AZ_output,AZ_none);
138 AztecOOSolver.SetPrecOperator(&Prec);
139
140 AztecOOSolver.Iterate(1550,1e-5);
141
142 return(AztecOOSolver.NumIters());
143}
144
145// ======================================================================
146bool ComparePointAndBlock(std::string PrecType, const Teuchos::RefCountPtr<Epetra_RowMatrix>& A, int sweeps)
147{
148 Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors);
149 Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors);
150 LHS.PutScalar(0.0); RHS.Random();
151
152 Epetra_LinearProblem Problem(&*A, &LHS, &RHS);
153
154 // Set up the list
155 Teuchos::ParameterList List;
156 List.set("relaxation: damping factor", 1.0);
157 List.set("relaxation: type", PrecType);
158 List.set("relaxation: sweeps",sweeps);
159 List.set("partitioner: type", "linear");
160 List.set("partitioner: local parts", A->NumMyRows());
161
162 int ItersPoint, ItersBlock;
163
164 // ================================================== //
165 // get the number of iterations with point relaxation //
166 // ================================================== //
167 {
168 RHS.PutScalar(1.0);
169 LHS.PutScalar(0.0);
170
171 Ifpack_PointRelaxation Point(&*A);
172 Point.SetParameters(List);
173 Point.Compute();
174
175 // set AztecOO solver object
176 AztecOO AztecOOSolver(Problem);
177 AztecOOSolver.SetAztecOption(AZ_solver,Solver);
178 if (verbose)
179 AztecOOSolver.SetAztecOption(AZ_output,32);
180 else
181 AztecOOSolver.SetAztecOption(AZ_output,AZ_none);
182 AztecOOSolver.SetPrecOperator(&Point);
183
184 AztecOOSolver.Iterate(1550,1e-2);
185
186 double TrueResidual = AztecOOSolver.TrueResidual();
187 ItersPoint = AztecOOSolver.NumIters();
188 // some output
189 if (verbose && Problem.GetMatrix()->Comm().MyPID() == 0) {
190 cout << "Iterations = " << ItersPoint << endl;
191 cout << "Norm of the true residual = " << TrueResidual << endl;
192 }
193 }
194
195 // ================================================== //
196 // get the number of iterations with block relaxation //
197 // ================================================== //
198 {
199
200 RHS.PutScalar(1.0);
201 LHS.PutScalar(0.0);
202
203 Ifpack_BlockRelaxation<Ifpack_SparseContainer<Ifpack_Amesos> > Block(&*A);
204 Block.SetParameters(List);
205 Block.Compute();
206
207 // set AztecOO solver object
208 AztecOO AztecOOSolver(Problem);
209 AztecOOSolver.SetAztecOption(AZ_solver,Solver);
210 if (verbose)
211 AztecOOSolver.SetAztecOption(AZ_output,32);
212 else
213 AztecOOSolver.SetAztecOption(AZ_output,AZ_none);
214 AztecOOSolver.SetPrecOperator(&Block);
215
216 AztecOOSolver.Iterate(1550,1e-2);
217
218 double TrueResidual = AztecOOSolver.TrueResidual();
219 ItersBlock = AztecOOSolver.NumIters();
220 // some output
221 if (verbose && Problem.GetMatrix()->Comm().MyPID() == 0) {
222 cout << "Iterations " << ItersBlock << endl;
223 cout << "Norm of the true residual = " << TrueResidual << endl;
224 }
225 }
226
227 int diff = ItersPoint - ItersBlock;
228 if (diff < 0) diff = -diff;
229
230 if (diff > 10)
231 {
232 if (verbose)
233 cout << "TEST FAILED!" << endl;
234 return(false);
235 }
236 else {
237 if (verbose)
238 cout << "TEST PASSED" << endl;
239 return(true);
240 }
241}
242
243// ======================================================================
244bool KrylovTest(std::string PrecType, const Teuchos::RefCountPtr<Epetra_RowMatrix>& A, bool backward)
245{
246 Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors);
247 Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors);
248 LHS.PutScalar(0.0); RHS.Random();
249
250 Epetra_LinearProblem Problem(&*A, &LHS, &RHS);
251
252 // Set up the list
253 Teuchos::ParameterList List;
254 List.set("relaxation: damping factor", 1.0);
255 List.set("relaxation: type", PrecType);
256 if(backward) List.set("relaxation: backward mode",backward);
257
258 int Iters1, Iters10;
259
260 if (verbose) {
261 cout << "Krylov test: Using " << PrecType
262 << " with AztecOO" << endl;
263 }
264
265 // ============================================== //
266 // get the number of iterations with 1 sweep only //
267 // ============================================== //
268 {
269
270 List.set("relaxation: sweeps",1);
271 Ifpack_PointRelaxation Point(&*A);
272 Point.SetParameters(List);
273 Point.Compute();
274
275 // set AztecOO solver object
276 AztecOO AztecOOSolver(Problem);
277 AztecOOSolver.SetAztecOption(AZ_solver,Solver);
278 AztecOOSolver.SetAztecOption(AZ_output,AZ_none);
279 AztecOOSolver.SetPrecOperator(&Point);
280
281 AztecOOSolver.Iterate(1550,1e-5);
282
283 double TrueResidual = AztecOOSolver.TrueResidual();
284 // some output
285 if (verbose && Problem.GetMatrix()->Comm().MyPID() == 0) {
286 cout << "Norm of the true residual = " << TrueResidual << endl;
287 }
288 Iters1 = AztecOOSolver.NumIters();
289 }
290
291 // ======================================================== //
292 // now re-run with 10 sweeps, solver should converge faster
293 // ======================================================== //
294 {
295 List.set("relaxation: sweeps",10);
296 Ifpack_PointRelaxation Point(&*A);
297 Point.SetParameters(List);
298 Point.Compute();
299 LHS.PutScalar(0.0);
300
301 // set AztecOO solver object
302 AztecOO AztecOOSolver(Problem);
303 AztecOOSolver.SetAztecOption(AZ_solver,Solver);
304 AztecOOSolver.SetAztecOption(AZ_output,AZ_none);
305 AztecOOSolver.SetPrecOperator(&Point);
306 AztecOOSolver.Iterate(1550,1e-5);
307
308 double TrueResidual = AztecOOSolver.TrueResidual();
309 // some output
310 if (verbose && Problem.GetMatrix()->Comm().MyPID() == 0) {
311 cout << "Norm of the true residual = " << TrueResidual << endl;
312 }
313 Iters10 = AztecOOSolver.NumIters();
314 }
315
316 if (verbose) {
317 cout << "Iters_1 = " << Iters1 << ", Iters_10 = " << Iters10 << endl;
318 cout << "(second number should be smaller than first one)" << endl;
319 }
320
321 if (Iters10 > Iters1) {
322 if (verbose)
323 cout << "TEST FAILED!" << endl;
324 return(false);
325 }
326 else {
327 if (verbose)
328 cout << "TEST PASSED" << endl;
329 return(true);
330 }
331}
332
333// ======================================================================
334bool BasicTest(std::string PrecType, const Teuchos::RefCountPtr<Epetra_RowMatrix>& A,bool backward)
335{
336 Epetra_MultiVector LHS(A->RowMatrixRowMap(), NumVectors);
337 Epetra_MultiVector RHS(A->RowMatrixRowMap(), NumVectors);
338 LHS.PutScalar(0.0); RHS.Random();
339
340 double starting_residual = Galeri::ComputeNorm(&*A, &LHS, &RHS);
341 Epetra_LinearProblem Problem(&*A, &LHS, &RHS);
342
343 // Set up the list
344 Teuchos::ParameterList List;
345 List.set("relaxation: damping factor", 1.0);
346 List.set("relaxation: sweeps",1550);
347 List.set("relaxation: type", PrecType);
348 if(backward) List.set("relaxation: backward mode",backward);
349
350
351 Ifpack_PointRelaxation Point(&*A);
352
353 Point.SetParameters(List);
354 Point.Compute();
355 // use the preconditioner as solver, with 1550 iterations
356 Point.ApplyInverse(RHS,LHS);
357
358 // compute the real residual
359
360 double residual = Galeri::ComputeNorm(&*A, &LHS, &RHS);
361
362 if (A->Comm().MyPID() == 0 && verbose)
363 cout << "||A * x - b||_2 (scaled) = " << residual / starting_residual << endl;
364
365 // Jacobi is very slow to converge here
366 if (residual / starting_residual < 1e-2) {
367 if (verbose)
368 cout << "Test passed" << endl;
369 return(true);
370 }
371 else {
372 if (verbose)
373 cout << "Test failed!" << endl;
374 return(false);
375 }
376}
377
378// ======================================================================
379int main(int argc, char *argv[])
380{
381#ifdef HAVE_MPI
382 MPI_Init(&argc,&argv);
383 Epetra_MpiComm Comm( MPI_COMM_WORLD );
384#else
386#endif
387
388 verbose = (Comm.MyPID() == 0);
389
390 for (int i = 1 ; i < argc ; ++i) {
391 if (strcmp(argv[i],"-s") == 0) {
392 SymmetricGallery = true;
393 Solver = AZ_cg;
394 }
395 }
396
397 // size of the global matrix.
398 Teuchos::ParameterList GaleriList;
399 int nx = 30;
400 GaleriList.set("nx", nx);
401 GaleriList.set("ny", nx * Comm.NumProc());
402 GaleriList.set("mx", 1);
403 GaleriList.set("my", Comm.NumProc());
404 Teuchos::RefCountPtr<Epetra_Map> Map = Teuchos::rcp( Galeri::CreateMap64("Cartesian2D", Comm, GaleriList) );
405 Teuchos::RefCountPtr<Epetra_CrsMatrix> A;
407 A = Teuchos::rcp( Galeri::CreateCrsMatrix("Laplace2D", &*Map, GaleriList) );
408 else
409 A = Teuchos::rcp( Galeri::CreateCrsMatrix("Recirc2D", &*Map, GaleriList) );
410
411 // test the preconditioner
412 int TestPassed = true;
413
414 // ======================================== //
415 // first verify that we can get convergence //
416 // with all point relaxation methods //
417 // ======================================== //
418
419 if(!BasicTest("Jacobi",A,false))
420 TestPassed = false;
421
422 if(!BasicTest("symmetric Gauss-Seidel",A,false))
423 TestPassed = false;
424
425 if (!SymmetricGallery) {
426 if(!BasicTest("Gauss-Seidel",A,false))
427 TestPassed = false;
428 if(!BasicTest("Gauss-Seidel",A,true))
429 TestPassed = false;
430
431 }
432
433 // ============================= //
434 // check uses as preconditioners //
435 // ============================= //
436
437 if(!KrylovTest("symmetric Gauss-Seidel",A,false))
438 TestPassed = false;
439
440 if (!SymmetricGallery) {
441 if(!KrylovTest("Gauss-Seidel",A,false))
442 TestPassed = false;
443 if(!KrylovTest("Gauss-Seidel",A,true))
444 TestPassed = false;
445
446 }
447
448 // ================================== //
449 // compare point and block relaxation //
450 // ================================== //
451
452 //TestPassed = TestPassed &&
453 // ComparePointAndBlock("Jacobi",A,1);
454
455 TestPassed = TestPassed &&
456 ComparePointAndBlock("Jacobi",A,10);
457
458 //TestPassed = TestPassed &&
459 //ComparePointAndBlock("symmetric Gauss-Seidel",A,1);
460
461 TestPassed = TestPassed &&
462 ComparePointAndBlock("symmetric Gauss-Seidel",A,10);
463
464 if (!SymmetricGallery) {
465 //TestPassed = TestPassed &&
466 //ComparePointAndBlock("Gauss-Seidel",A,1);
467
468 TestPassed = TestPassed &&
469 ComparePointAndBlock("Gauss-Seidel",A,10);
470 }
471
472 // ============================ //
473 // verify effect of # of blocks //
474 // ============================ //
475
476 {
477 int Iters4, Iters8, Iters16;
478 Iters4 = CompareBlockSizes("Jacobi",A,4);
479 Iters8 = CompareBlockSizes("Jacobi",A,8);
480 Iters16 = CompareBlockSizes("Jacobi",A,16);
481
482 if ((Iters16 > Iters8) && (Iters8 > Iters4)) {
483 if (verbose)
484 cout << "Test passed" << endl;
485 }
486 else {
487 if (verbose)
488 cout << "TEST FAILED!" << endl;
489 TestPassed = TestPassed && false;
490 }
491 }
492
493 // ================================== //
494 // verify effect of overlap in Jacobi //
495 // ================================== //
496
497 {
498 int Iters0, Iters2, Iters4;
499 Iters0 = CompareBlockOverlap(A,0);
500 Iters2 = CompareBlockOverlap(A,2);
501 Iters4 = CompareBlockOverlap(A,4);
502 if ((Iters4 < Iters2) && (Iters2 < Iters0)) {
503 if (verbose)
504 cout << "Test passed" << endl;
505 }
506 else {
507 if (verbose)
508 cout << "TEST FAILED!" << endl;
509 TestPassed = TestPassed && false;
510 }
511 }
512
513 // ============ //
514 // final output //
515 // ============ //
516
517 if (!TestPassed) {
518 cout << "Test `TestRelaxation.exe' failed!" << endl;
519 exit(EXIT_FAILURE);
520 }
521
522#ifdef HAVE_MPI
523 MPI_Finalize();
524#endif
525
526 cout << endl;
527 cout << "Test `TestRelaxation.exe' passed!" << endl;
528 cout << endl;
529 return(EXIT_SUCCESS);
530}
#define RHS(a)
Definition MatGenFD.c:60
int NumProc() const
int MyPID() const
int PutScalar(double ScalarConstant)
Ifpack_PointRelaxation: a class to define point relaxation preconditioners of for Epetra_RowMatrix's.
int main(int argc, char *argv[])
int CompareBlockOverlap(const Teuchos::RefCountPtr< Epetra_RowMatrix > &A, int Overlap)
int CompareBlockSizes(std::string PrecType, const Teuchos::RefCountPtr< Epetra_RowMatrix > &A, int NumParts)
static bool Solver
const int NumVectors
bool BasicTest(std::string PrecType, const Teuchos::RefCountPtr< Epetra_RowMatrix > &A, bool backward)
static bool verbose
bool ComparePointAndBlock(std::string PrecType, const Teuchos::RefCountPtr< Epetra_RowMatrix > &A, int sweeps)
static bool SymmetricGallery
bool KrylovTest(std::string PrecType, const Teuchos::RefCountPtr< Epetra_RowMatrix > &A, bool backward)