download the original source code.
  1 /*
  2    Example 5
  3 
  4    Interface:    Linear-Algebraic (IJ), Babel-based version
  5 
  6    Compile with: make ex5b
  7 
  8    Sample run:   mpirun -np 4 ex5b
  9 
 10    Description:  This example solves the 2-D
 11                  Laplacian problem with zero boundary conditions
 12                  on an nxn grid.  The number of unknowns is N=n^2.
 13                  The standard 5-point stencil is used, and we solve
 14                  for the interior nodes only.
 15 
 16                  This example solves the same problem as Example 3.
 17                  Available solvers are AMG, PCG, and PCG with AMG or
 18                  Parasails preconditioners.
 19 */
 20 
 21 #include <math.h>
 22 #include <assert.h>
 23 #include "_hypre_utilities.h"
 24 #include "HYPRE_krylov.h"
 25 #include "HYPRE.h"
 26 #include "HYPRE_parcsr_ls.h"
 27 
 28 #include "vis.c"
 29 
 30 /* Babel interface headers */
 31 #include "bHYPRE.h"
 32 #include "bHYPRE_Vector.h"
 33 #include "bHYPRE_IJParCSRMatrix.h"
 34 #include "bHYPRE_IJParCSRVector.h"
 35 #include "bHYPRE_ParCSRDiagScale.h"
 36 #include "bHYPRE_BoomerAMG.h"
 37 #include "sidl_Exception.h"
 38 
 39 int main (int argc, char *argv[])
 40 {
 41    int i;
 42    int myid, num_procs;
 43    int N, n;
 44 
 45    int ilower, iupper;
 46    int local_size, extra;
 47 
 48    int solver_id;
 49    int vis;
 50 
 51    double h, h2;
 52    MPI_Comm mpicommworld = MPI_COMM_WORLD;
 53 
 54    int ierr = 0;
 55    /* If this gets set to anything else, it's an error.
 56     Most functions return error flags, 0 unless there's an error.
 57     For clarity, they aren't checked much in this file. */
 58 
 59    bHYPRE_MPICommunicator mpi_comm;
 60    bHYPRE_IJParCSRMatrix parcsr_A;
 61    bHYPRE_Operator           op_A;
 62    bHYPRE_IJParCSRVector par_b;
 63    bHYPRE_IJParCSRVector par_x;
 64    bHYPRE_Vector vec_b;
 65    bHYPRE_Vector vec_x;
 66 
 67    bHYPRE_Solver precond;
 68    bHYPRE_BoomerAMG amg_solver;
 69    bHYPRE_ParaSails ps_solver;
 70    bHYPRE_PCG pcg_solver;
 71    bHYPRE_IdentitySolver identity;
 72    sidl_BaseInterface _ex = NULL;
 73 
 74    /* Initialize MPI */
 75    MPI_Init(&argc, &argv);
 76    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
 77    MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
 78    mpi_comm = bHYPRE_MPICommunicator_CreateC( &mpicommworld, &_ex );
 79 
 80    /* Default problem parameters */
 81    n = 33;
 82    solver_id = 0;
 83    vis = 0;
 84 
 85    /* Parse command line */
 86    {
 87       int arg_index = 0;
 88       int print_usage = 0;
 89 
 90       while (arg_index < argc)
 91       {
 92          if ( strcmp(argv[arg_index], "-n") == 0 )
 93          {
 94             arg_index++;
 95             n = atoi(argv[arg_index++]);
 96          }
 97          else if ( strcmp(argv[arg_index], "-solver") == 0 )
 98          {
 99             arg_index++;
100             solver_id = atoi(argv[arg_index++]);
101          }
102          else if ( strcmp(argv[arg_index], "-vis") == 0 )
103          {
104             arg_index++;
105             vis = 1;
106          }
107          else if ( strcmp(argv[arg_index], "-help") == 0 )
108          {
109             print_usage = 1;
110             break;
111          }
112          else
113          {
114             arg_index++;
115          }
116       }
117 
118       if ((print_usage) && (myid == 0))
119       {
120          printf("\n");
121          printf("Usage: %s [<options>]\n", argv[0]);
122          printf("\n");
123          printf("  -n <n>              : problem size in each direction (default: 33)\n");
124          printf("  -solver <ID>        : solver ID\n");
125          printf("                        0  - AMG (default) \n");
126          printf("                        1  - AMG-PCG\n");
127          printf("                        8  - ParaSails-PCG\n");
128          printf("                        50 - PCG\n");
129          printf("  -vis                : save the solution for GLVis visualization\n");
130          printf("\n");
131       }
132 
133       if (print_usage)
134       {
135          MPI_Finalize();
136          return (0);
137       }
138    }
139 
140    /* Preliminaries: want at least one processor per row */
141    if (n*n < num_procs) n = sqrt(num_procs) + 1;
142    N = n*n; /* global number of rows */
143    h = 1.0/(n+1); /* mesh size*/
144    h2 = h*h;
145 
146    /* Each processor knows only of its own rows - the range is denoted by ilower
147       and upper.  Here we partition the rows. We account for the fact that
148       N may not divide evenly by the number of processors. */
149    local_size = N/num_procs;
150    extra = N - local_size*num_procs;
151 
152    ilower = local_size*myid;
153    ilower += hypre_min(myid, extra);
154 
155    iupper = local_size*(myid+1);
156    iupper += hypre_min(myid+1, extra);
157    iupper = iupper - 1;
158 
159    /* How many rows do I have? */
160    local_size = iupper - ilower + 1;
161 
162    /* Create the matrix.
163       Note that this is a square matrix, so we indicate the row partition
164       size twice (since number of rows = number of cols) */
165    parcsr_A = bHYPRE_IJParCSRMatrix_Create( mpi_comm,
166                                             ilower, iupper, ilower, iupper, &_ex );
167 
168    op_A = bHYPRE_Operator__cast( parcsr_A, &_ex ); /* needed later as a function argument */
169 
170    /* Choose a parallel csr format storage (see the User's Manual) */
171    /* Note: Here the HYPRE interface requires a SetObjectType call.
172       I am using the bHYPRE interface in a way which does not because
173       the object type is already specified through the class name. */
174 
175    /* Initialize before setting coefficients */
176    bHYPRE_IJParCSRMatrix_Initialize( parcsr_A, &_ex );
177 
178    /* Now go through my local rows and set the matrix entries.
179       Each row has at most 5 entries. For example, if n=3:
180 
181       A = [M -I 0; -I M -I; 0 -I M]
182       M = [4 -1 0; -1 4 -1; 0 -1 4]
183 
184       Note that here we are setting one row at a time, though
185       one could set all the rows together (see the User's Manual).
186    */
187    {
188       int nnz;
189       double values[5];
190       int cols[5];
191 
192       for (i = ilower; i <= iupper; i++)
193       {
194          nnz = 0;
195 
196          /* The left identity block:position i-n */
197          if ((i-n)>=0)
198          {
199 	    cols[nnz] = i-n;
200 	    values[nnz] = -1.0;
201 	    nnz++;
202          }
203 
204          /* The left -1: position i-1 */
205          if (i%n)
206          {
207             cols[nnz] = i-1;
208             values[nnz] = -1.0;
209             nnz++;
210          }
211 
212          /* Set the diagonal: position i */
213          cols[nnz] = i;
214          values[nnz] = 4.0;
215          nnz++;
216 
217          /* The right -1: position i+1 */
218          if ((i+1)%n)
219          {
220             cols[nnz] = i+1;
221             values[nnz] = -1.0;
222             nnz++;
223          }
224 
225          /* The right identity block:position i+n */
226          if ((i+n)< N)
227          {
228             cols[nnz] = i+n;
229             values[nnz] = -1.0;
230             nnz++;
231          }
232 
233          /* Set the values for row i */
234          bHYPRE_IJParCSRMatrix_SetValues( parcsr_A, 1, &nnz, &i, cols, values, 5, &_ex );
235       }
236    }
237 
238    /* Assemble after setting the coefficients */
239    bHYPRE_IJParCSRMatrix_Assemble( parcsr_A, &_ex );
240 
241    /* Create the rhs and solution */
242    par_b = bHYPRE_IJParCSRVector_Create( mpi_comm, ilower, iupper, &_ex );
243 
244    vec_b = bHYPRE_Vector__cast( par_b, &_ex ); /* needed later for function arguments */
245 
246    bHYPRE_IJParCSRVector_Initialize( par_b, &_ex );
247 
248    par_x = bHYPRE_IJParCSRVector_Create( mpi_comm, ilower, iupper, &_ex );
249 
250    vec_x = bHYPRE_Vector__cast( par_x, &_ex ); /* needed later for function arguments */
251 
252    bHYPRE_IJParCSRVector_Initialize( par_x, &_ex );
253 
254    /* Set the rhs values to h^2 and the solution to zero */
255    {
256       double *rhs_values, *x_values;
257       int    *rows;
258 
259       rhs_values = calloc(local_size, sizeof(double));
260       x_values = calloc(local_size, sizeof(double));
261       rows = calloc(local_size, sizeof(int));
262 
263       for (i=0; i<local_size; i++)
264       {
265          rhs_values[i] = h2;
266          x_values[i] = 0.0;
267          rows[i] = ilower + i;
268       }
269 
270       bHYPRE_IJParCSRVector_SetValues( par_b, local_size, rows, rhs_values, &_ex );
271       bHYPRE_IJParCSRVector_SetValues( par_x, local_size, rows, x_values, &_ex );
272 
273       free(x_values);
274       free(rhs_values);
275       free(rows);
276    }
277 
278    bHYPRE_IJParCSRVector_Assemble( par_b, &_ex );
279    bHYPRE_IJParCSRVector_Assemble( par_x, &_ex );
280 
281    /* Choose a solver and solve the system */
282 
283    /* AMG */
284    if (solver_id == 0)
285    {
286       int num_iterations;
287       double final_res_norm;
288 
289       /* Create solver */
290       amg_solver = bHYPRE_BoomerAMG_Create( mpi_comm, parcsr_A, &_ex );
291 
292       /* Set some parameters (See Reference Manual for more parameters) */
293       bHYPRE_BoomerAMG_SetIntParameter( amg_solver, "PrintLevel", 3, &_ex );  /* print solve info + parameters */
294       bHYPRE_BoomerAMG_SetIntParameter( amg_solver, "CoarsenType", 6, &_ex ); /* Falgout coarsening */
295       bHYPRE_BoomerAMG_SetIntParameter( amg_solver, "RelaxType", 3, &_ex );   /* G-S/Jacobi hybrid relaxation */
296       bHYPRE_BoomerAMG_SetIntParameter( amg_solver, "NumSweeps", 1, &_ex );   /* Sweeeps on each level */
297       bHYPRE_BoomerAMG_SetIntParameter( amg_solver, "MaxLevels", 20, &_ex );  /* maximum number of levels */
298       bHYPRE_BoomerAMG_SetDoubleParameter( amg_solver, "Tolerance", 1e-7, &_ex );      /* conv. tolerance */
299 
300       /* Now setup and solve! */
301       bHYPRE_BoomerAMG_Setup( amg_solver, vec_b, vec_x, &_ex );
302       bHYPRE_BoomerAMG_Apply( amg_solver, vec_b, &vec_x, &_ex );
303 
304       /* Run info - needed logging turned on */
305       ierr += bHYPRE_BoomerAMG_GetIntValue( amg_solver, "NumIterations", &num_iterations, &_ex );
306       bHYPRE_BoomerAMG_GetDoubleValue( amg_solver, "RelResidualNorm", &final_res_norm, &_ex );
307 
308       if (myid == 0)
309       {
310          printf("\n");
311          printf("Iterations = %d\n", num_iterations);
312          printf("Final Relative Residual Norm = %e\n", final_res_norm);
313          printf("\n");
314       }
315 
316       /* Destroy solver */
317       bHYPRE_BoomerAMG_deleteRef( amg_solver, &_ex );
318    }
319 
320    /* PCG */
321    else if (solver_id == 50)
322    {
323       int num_iterations;
324       double final_res_norm;
325 
326       /* Create solver */
327       pcg_solver = bHYPRE_PCG_Create( mpi_comm, op_A, &_ex );
328 
329       /* Set some parameters (See Reference Manual for more parameters) */
330       bHYPRE_PCG_SetIntParameter( pcg_solver, "MaxIter", 1000, &_ex ); /* max iterations */
331       bHYPRE_PCG_SetDoubleParameter( pcg_solver, "Tolerance", 1e-7, &_ex ); /* conv. tolerance */
332       bHYPRE_PCG_SetIntParameter( pcg_solver, "TwoNorm", 1, &_ex ); /* use the two norm as the stopping criteria */
333       bHYPRE_PCG_SetIntParameter( pcg_solver, "PrintLevel", 2, &_ex ); /* prints out the iteration info */
334       bHYPRE_PCG_SetIntParameter( pcg_solver, "Logging", 1, &_ex ); /* needed to get run info later */
335 
336       identity = bHYPRE_IdentitySolver_Create( mpi_comm, &_ex );
337       precond = bHYPRE_Solver__cast( identity, &_ex );
338       bHYPRE_PCG_SetPreconditioner( pcg_solver, precond, &_ex );
339 
340       /* Now setup and solve! */
341       bHYPRE_PCG_Setup( pcg_solver, vec_b, vec_x, &_ex );
342       bHYPRE_PCG_Apply( pcg_solver, vec_b, &vec_x, &_ex );
343 
344       /* Run info - needed logging turned on */
345       bHYPRE_PCG_GetIntValue( pcg_solver, "NumIterations", &num_iterations, &_ex );
346       bHYPRE_PCG_GetDoubleValue( pcg_solver, "RelResidualNorm", &final_res_norm, &_ex );
347       if (myid == 0)
348       {
349          printf("\n");
350          printf("Iterations = %d\n", num_iterations);
351          printf("Final Relative Residual Norm = %e\n", final_res_norm);
352          printf("\n");
353       }
354 
355       /* Destroy solvers */
356       bHYPRE_PCG_deleteRef( pcg_solver, &_ex );
357       bHYPRE_Solver_deleteRef( precond, &_ex );
358    }
359    /* PCG with AMG preconditioner */
360    else if (solver_id == 1)
361    {
362       int num_iterations;
363       double final_res_norm;
364 
365       /* Create solver */
366       pcg_solver = bHYPRE_PCG_Create( mpi_comm, op_A, &_ex );
367 
368       /* Set some parameters (See Reference Manual for more parameters) */
369       bHYPRE_PCG_SetIntParameter( pcg_solver, "MaxIter", 1000, &_ex ); /* max iterations */
370       bHYPRE_PCG_SetDoubleParameter( pcg_solver, "Tolerance", 1e-7, &_ex ); /* conv. tolerance */
371       bHYPRE_PCG_SetIntParameter( pcg_solver, "TwoNorm", 1, &_ex ); /* use the two norm as the stopping criteria */
372       bHYPRE_PCG_SetIntParameter( pcg_solver, "PrintLevel", 2, &_ex ); /* prints out the iteration info */
373       bHYPRE_PCG_SetIntParameter( pcg_solver, "Logging", 1, &_ex ); /* needed to get run info later */
374 
375       /* Now set up the AMG preconditioner and specify any parameters */
376       amg_solver = bHYPRE_BoomerAMG_Create( mpi_comm, parcsr_A, &_ex );
377       bHYPRE_BoomerAMG_SetIntParameter( amg_solver, "PrintLevel", 1, &_ex ); /* print amg solution info*/
378       bHYPRE_BoomerAMG_SetIntParameter( amg_solver, "CoarsenType", 6, &_ex ); /* Falgout coarsening */
379       bHYPRE_BoomerAMG_SetIntParameter( amg_solver, "RelaxType", 6, &_ex );   /* Sym G-S/Jacobi hybrid relaxation */
380       bHYPRE_BoomerAMG_SetIntParameter( amg_solver, "NumSweeps", 1, &_ex );   /* Sweeeps on each level */
381       bHYPRE_BoomerAMG_SetDoubleParameter( amg_solver, "Tolerance", 0, &_ex);      /* conv. tolerance */
382       bHYPRE_BoomerAMG_SetIntParameter( amg_solver, "MaxIter", 1, &_ex ); /* do only one iteration! */
383 
384       /* Set the PCG preconditioner */
385       precond = bHYPRE_Solver__cast( amg_solver, &_ex );
386       bHYPRE_PCG_SetPreconditioner( pcg_solver, precond, &_ex );
387 
388       /* Now setup and solve! */
389       bHYPRE_PCG_Setup( pcg_solver, vec_b, vec_x, &_ex );
390       bHYPRE_PCG_Apply( pcg_solver, vec_b, &vec_x, &_ex );
391 
392       /* Run info - needed logging turned on */
393       bHYPRE_PCG_GetIntValue( pcg_solver, "NumIterations", &num_iterations, &_ex );
394       bHYPRE_PCG_GetDoubleValue( pcg_solver, "RelResidualNorm", &final_res_norm, &_ex );
395       if (myid == 0)
396       {
397          printf("\n");
398          printf("Iterations = %d\n", num_iterations);
399          printf("Final Relative Residual Norm = %e\n", final_res_norm);
400          printf("\n");
401       }
402 
403       /* Destroy solver and preconditioner */
404       bHYPRE_PCG_deleteRef( pcg_solver, &_ex );
405       bHYPRE_Solver_deleteRef( precond, &_ex );
406    }
407 
408    /* PCG with Parasails Preconditioner */
409    else if (solver_id == 8)
410    {
411       int    num_iterations;
412       double final_res_norm;
413 
414       int      sai_max_levels = 1;
415       double   sai_threshold = 0.1;
416       double   sai_filter = 0.05;
417       int      sai_sym = 1;
418 
419       /* Create solver */
420       pcg_solver = bHYPRE_PCG_Create( mpi_comm, op_A, &_ex );
421 
422       /* Set some parameters (See Reference Manual for more parameters) */
423       bHYPRE_PCG_SetIntParameter( pcg_solver, "MaxIter", 1000, &_ex ); /* max iterations */
424       bHYPRE_PCG_SetDoubleParameter( pcg_solver, "Tolerance", 1e-7, &_ex ); /* conv. tolerance */
425       bHYPRE_PCG_SetIntParameter( pcg_solver, "TwoNorm", 1, &_ex ); /* use the two norm as the stopping criteria */
426       bHYPRE_PCG_SetIntParameter( pcg_solver, "PrintLevel", 2, &_ex ); /* prints out the iteration info */
427       bHYPRE_PCG_SetIntParameter( pcg_solver, "Logging", 1, &_ex ); /* needed to get run info later */
428 
429       /* Now set up the ParaSails preconditioner and specify any parameters */
430       ps_solver = bHYPRE_ParaSails_Create( mpi_comm, parcsr_A, &_ex );
431 
432       /* Set some parameters (See Reference Manual for more parameters) */
433       bHYPRE_ParaSails_SetDoubleParameter( ps_solver, "Thresh", sai_threshold, &_ex );
434       bHYPRE_ParaSails_SetIntParameter( ps_solver, "Nlevels", sai_max_levels, &_ex );
435       bHYPRE_ParaSails_SetDoubleParameter( ps_solver, "Filter", sai_filter, &_ex );
436       bHYPRE_ParaSails_SetIntParameter( ps_solver, "Sym", sai_sym, &_ex );
437       bHYPRE_ParaSails_SetIntParameter( ps_solver, "Logging", 3, &_ex );
438 
439       /* Set the PCG preconditioner */
440       precond = bHYPRE_Solver__cast( ps_solver, &_ex );
441       bHYPRE_PCG_SetPreconditioner( pcg_solver, precond, &_ex );
442 
443       /* Now setup and solve! */
444       bHYPRE_PCG_Setup( pcg_solver, vec_b, vec_x, &_ex );
445       bHYPRE_PCG_Apply( pcg_solver, vec_b, &vec_x, &_ex );
446 
447 
448       /* Run info - needed logging turned on */
449       bHYPRE_PCG_GetIntValue( pcg_solver, "NumIterations", &num_iterations, &_ex );
450       bHYPRE_PCG_GetDoubleValue( pcg_solver, "RelResidualNorm", &final_res_norm, &_ex );
451       if (myid == 0)
452       {
453          printf("\n");
454          printf("Iterations = %d\n", num_iterations);
455          printf("Final Relative Residual Norm = %e\n", final_res_norm);
456          printf("\n");
457       }
458 
459       /* Destory solver and preconditioner */
460       bHYPRE_PCG_deleteRef( pcg_solver, &_ex );
461       bHYPRE_Solver_deleteRef( precond, &_ex );
462    }
463    else
464    {
465       if (myid ==0) printf("Invalid solver id specified.\n");
466    }
467 
468    /* Save the solution for GLVis visualization, see vis/glvis-ex5.sh */
469    if (vis)
470    {
471       FILE *file;
472       char filename[255];
473 
474       int nvalues = local_size;
475       int *rows = calloc(nvalues, sizeof(int));
476       double *values = calloc(nvalues, sizeof(double));
477 
478       for (i = 0; i < nvalues; i++)
479          rows[i] = ilower + i;
480 
481       /* get the local solution */
482       HYPRE_IJVectorGetValues(x, nvalues, rows, values);
483 
484       sprintf(filename, "%s.%06d", "vis/ex5.sol", myid);
485       if ((file = fopen(filename, "w")) == NULL)
486       {
487          printf("Error: can't open output file %s\n", filename);
488          MPI_Finalize();
489          exit(1);
490       }
491 
492       /* save solution */
493       for (i = 0; i < nvalues; i++)
494          fprintf(file, "%.14e\n", values[i]);
495 
496       fflush(file);
497       fclose(file);
498 
499       free(rows);
500       free(values);
501 
502       /* save global finite element mesh */
503       if (myid == 0)
504          GLVis_PrintGlobalSquareMesh("vis/ex5.mesh", n-1);
505    }
506 
507    /* Clean up */
508    bHYPRE_Operator_deleteRef( op_A, &_ex );
509    bHYPRE_Vector_deleteRef( vec_b, &_ex );
510    bHYPRE_Vector_deleteRef( vec_x, &_ex );
511    bHYPRE_IJParCSRMatrix_deleteRef( parcsr_A, &_ex );
512    bHYPRE_IJParCSRVector_deleteRef( par_b, &_ex );
513    bHYPRE_IJParCSRVector_deleteRef( par_x, &_ex );
514    bHYPRE_MPICommunicator_deleteRef( mpi_comm, &_ex );
515 
516    hypre_assert( ierr == 0 );
517 
518    /* Finalize MPI*/
519    MPI_Finalize();
520 
521    return(0);
522 }


syntax highlighted by Code2HTML, v. 0.9.1