download the original source code.
  1 /*
  2    Example 5
  3 
  4    Interface:    Linear-Algebraic (IJ)
  5 
  6    Compile with: make ex5
  7 
  8    Sample run:   mpirun -np 4 ex5
  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 "utilities.h"
 23 #include "krylov.h"
 24 #include "HYPRE.h"
 25 #include "HYPRE_parcsr_ls.h"
 26 
 27 int main (int argc, char *argv[])
 28 {
 29    int i;
 30    int myid, num_procs;
 31    int N, n;
 32 
 33    int ilower, iupper;
 34    int local_size, extra;
 35 
 36    int solver_id;
 37    int print_solution;
 38 
 39    double h, h2;
 40 
 41    HYPRE_IJMatrix A;
 42    HYPRE_ParCSRMatrix parcsr_A;
 43    HYPRE_IJVector b;
 44    HYPRE_ParVector par_b;
 45    HYPRE_IJVector x;
 46    HYPRE_ParVector par_x;
 47 
 48    HYPRE_Solver solver, precond;
 49 
 50    /* Initialize MPI */
 51    MPI_Init(&argc, &argv);
 52    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
 53    MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
 54 
 55    /* Default problem parameters */
 56    n = 33;
 57    solver_id = 0;
 58    print_solution  = 0;
 59 
 60    /* Parse command line */
 61    {
 62       int arg_index = 0;
 63       int print_usage = 0;
 64 
 65       while (arg_index < argc)
 66       {
 67          if ( strcmp(argv[arg_index], "-n") == 0 )
 68          {
 69             arg_index++;
 70             n = atoi(argv[arg_index++]);
 71          }
 72          else if ( strcmp(argv[arg_index], "-solver") == 0 )
 73          {
 74             arg_index++;
 75             solver_id = atoi(argv[arg_index++]);
 76          }
 77          else if ( strcmp(argv[arg_index], "-print_solution") == 0 )
 78          {
 79             arg_index++;
 80             print_solution = 1;
 81          }
 82          else if ( strcmp(argv[arg_index], "-help") == 0 )
 83          {
 84             print_usage = 1;
 85             break;
 86          }
 87          else
 88          {
 89             arg_index++;
 90          }
 91       }
 92 
 93       if ((print_usage) && (myid == 0))
 94       {
 95          printf("\n");
 96          printf("Usage: %s [<options>]\n", argv[0]);
 97          printf("\n");
 98          printf("  -n <n>              : problem size in each direction (default: 33)\n");
 99          printf("  -solver <ID>        : solver ID\n");
100          printf("                        0  - AMG (default) \n");
101          printf("                        1  - AMG-PCG\n");
102          printf("                        8  - ParaSails-PCG\n");
103          printf("                        50 - PCG\n");
104          printf("  -print_solution     : print the solution vector\n");
105          printf("\n");
106       }
107 
108       if (print_usage)
109       {
110          MPI_Finalize();
111          return (0);
112       }
113    }
114 
115    /* Preliminaries: want at least one processor per row */
116    if (n*n < num_procs) n = sqrt(num_procs) + 1;
117    N = n*n; /* global number of rows */
118    h = 1.0/(n+1); /* mesh size*/
119    h2 = h*h;
120 
121    /* Each processor knows only of its own rows - the range is denoted by ilower
122       and upper.  Here we partition the rows. We account for the fact that
123       N may not divide evenly by the number of processors. */
124    local_size = N/num_procs;
125    extra = N - local_size*num_procs;
126 
127    ilower = local_size*myid;
128    ilower += hypre_min(myid, extra);
129 
130    iupper = local_size*(myid+1);
131    iupper += hypre_min(myid+1, extra);
132    iupper = iupper - 1;
133 
134    /* How many rows do I have? */
135    local_size = iupper - ilower + 1;
136 
137    /* Create the matrix.
138       Note that this is a square matrix, so we indicate the row partition
139       size twice (since number of rows = number of cols) */
140    HYPRE_IJMatrixCreate(MPI_COMM_WORLD, ilower, iupper, ilower, iupper, &A);
141 
142    /* Choose a parallel csr format storage (see the User's Manual) */
143    HYPRE_IJMatrixSetObjectType(A, HYPRE_PARCSR);
144 
145    /* Initialize before setting coefficients */
146    HYPRE_IJMatrixInitialize(A);
147 
148    /* Now go through my local rows and set the matrix entries.
149       Each row has at most 5 entries. For example, if n=3:
150 
151       A = [M -I 0; -I M -I; 0 -I M]
152       M = [4 -1 0; -1 4 -1; 0 -1 4]
153 
154       Note that here we are setting one row at a time, though
155       one could set all the rows together (see the User's Manual).
156    */
157    {
158       int nnz;
159       double values[5];
160       int cols[5];
161 
162       for (i = ilower; i <= iupper; i++)
163       {
164          nnz = 0;
165 
166          /* The left identity block:position i-n */
167          if ((i-n)>=0)
168          {
169 	    cols[nnz] = i-n;
170 	    values[nnz] = -1.0;
171 	    nnz++;
172          }
173 
174          /* The left -1: position i-1 */
175          if (i%n)
176          {
177             cols[nnz] = i-1;
178             values[nnz] = -1.0;
179             nnz++;
180          }
181 
182          /* Set the diagonal: position i */
183          cols[nnz] = i;
184          values[nnz] = 4.0;
185          nnz++;
186 
187          /* The right -1: position i+1 */
188          if ((i+1)%n)
189          {
190             cols[nnz] = i+1;
191             values[nnz] = -1.0;
192             nnz++;
193          }
194 
195          /* The right identity block:position i+n */
196          if ((i+n)< N)
197          {
198             cols[nnz] = i+n;
199             values[nnz] = -1.0;
200             nnz++;
201          }
202 
203          /* Set the values for row i */
204          HYPRE_IJMatrixSetValues(A, 1, &nnz, &i, cols, values);
205       }
206    }
207 
208    /* Assemble after setting the coefficients */
209    HYPRE_IJMatrixAssemble(A);
210    /* Get the parcsr matrix object to use */
211    HYPRE_IJMatrixGetObject(A, (void**) &parcsr_A);
212 
213    /* Create the rhs and solution */
214    HYPRE_IJVectorCreate(MPI_COMM_WORLD, ilower, iupper,&b);
215    HYPRE_IJVectorSetObjectType(b, HYPRE_PARCSR);
216    HYPRE_IJVectorInitialize(b);
217 
218    HYPRE_IJVectorCreate(MPI_COMM_WORLD, ilower, iupper,&x);
219    HYPRE_IJVectorSetObjectType(x, HYPRE_PARCSR);
220    HYPRE_IJVectorInitialize(x);
221 
222    /* Set the rhs values to h^2 and the solution to zero */
223    {
224       double *rhs_values, *x_values;
225       int    *rows;
226 
227       rhs_values = calloc(local_size, sizeof(double));
228       x_values = calloc(local_size, sizeof(double));
229       rows = calloc(local_size, sizeof(int));
230 
231       for (i=0; i<local_size; i++)
232       {
233          rhs_values[i] = h2;
234          x_values[i] = 0.0;
235          rows[i] = ilower + i;
236       }
237 
238       HYPRE_IJVectorSetValues(b, local_size, rows, rhs_values);
239       HYPRE_IJVectorSetValues(x, local_size, rows, x_values);
240 
241       free(x_values);
242       free(rhs_values);
243       free(rows);
244    }
245 
246    HYPRE_IJVectorAssemble(b);
247    HYPRE_IJVectorGetObject(b, (void **) &par_b);
248 
249    HYPRE_IJVectorAssemble(x);
250    HYPRE_IJVectorGetObject(x, (void **) &par_x);
251 
252    /* Choose a solver and solve the system */
253 
254    /* AMG */
255    if (solver_id == 0)
256    {
257       int num_iterations;
258       double final_res_norm;
259 
260       /* Create solver */
261       HYPRE_BoomerAMGCreate(&solver);
262 
263       /* Set some parameters (See Reference Manual for more parameters) */
264       HYPRE_BoomerAMGSetPrintLevel(solver, 3);  /* print solve info + parameters */
265       HYPRE_BoomerAMGSetCoarsenType(solver, 6); /* Falgout coarsening */
266       HYPRE_BoomerAMGSetRelaxType(solver, 3);   /* G-S/Jacobi hybrid relaxation */
267       HYPRE_BoomerAMGSetNumSweeps(solver, 1);   /* Sweeeps on each level */
268       HYPRE_BoomerAMGSetMaxLevels(solver, 20);  /* maximum number of levels */
269       HYPRE_BoomerAMGSetTol(solver, 1e-7);      /* conv. tolerance */
270 
271       /* Now setup and solve! */
272       HYPRE_BoomerAMGSetup(solver, parcsr_A, par_b, par_x);
273       HYPRE_BoomerAMGSolve(solver, parcsr_A, par_b, par_x);
274 
275       /* Run info - needed logging turned on */
276       HYPRE_BoomerAMGGetNumIterations(solver, &num_iterations);
277       HYPRE_BoomerAMGGetFinalRelativeResidualNorm(solver, &final_res_norm);
278       if (myid == 0)
279       {
280          printf("\n");
281          printf("Iterations = %d\n", num_iterations);
282          printf("Final Relative Residual Norm = %e\n", final_res_norm);
283          printf("\n");
284       }
285 
286       /* Destroy solver */
287       HYPRE_BoomerAMGDestroy(solver);
288    }
289    /* PCG */
290    else if (solver_id == 50)
291    {
292       int num_iterations;
293       double final_res_norm;
294 
295       /* Create solver */
296       HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
297 
298       /* Set some parameters (See Reference Manual for more parameters) */
299       HYPRE_PCGSetMaxIter(solver, 1000); /* max iterations */
300       HYPRE_PCGSetTol(solver, 1e-7); /* conv. tolerance */
301       HYPRE_PCGSetTwoNorm(solver, 1); /* use the two norm as the stopping criteria */
302       HYPRE_PCGSetPrintLevel(solver, 2); /* prints out the iteration info */
303       HYPRE_PCGSetLogging(solver, 1); /* needed to get run info later */
304 
305       /* Now setup and solve! */
306       HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
307       HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
308 
309       /* Run info - needed logging turned on */
310       HYPRE_PCGGetNumIterations(solver, &num_iterations);
311       HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
312       if (myid == 0)
313       {
314          printf("\n");
315          printf("Iterations = %d\n", num_iterations);
316          printf("Final Relative Residual Norm = %e\n", final_res_norm);
317          printf("\n");
318       }
319 
320       /* Destroy solver */
321       HYPRE_ParCSRPCGDestroy(solver);
322    }
323    /* PCG with AMG preconditioner */
324    else if (solver_id == 1)
325    {
326       int num_iterations;
327       double final_res_norm;
328 
329       /* Create solver */
330       HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
331 
332       /* Set some parameters (See Reference Manual for more parameters) */
333       HYPRE_PCGSetMaxIter(solver, 1000); /* max iterations */
334       HYPRE_PCGSetTol(solver, 1e-7); /* conv. tolerance */
335       HYPRE_PCGSetTwoNorm(solver, 1); /* use the two norm as the stopping criteria */
336       HYPRE_PCGSetPrintLevel(solver, 2); /* print solve info */
337       HYPRE_PCGSetLogging(solver, 1); /* needed to get run info later */
338 
339       /* Now set up the AMG preconditioner and specify any parameters */
340       HYPRE_BoomerAMGCreate(&precond);
341       HYPRE_BoomerAMGSetPrintLevel(precond, 1); /* print amg solution info */
342       HYPRE_BoomerAMGSetCoarsenType(precond, 6);
343       HYPRE_BoomerAMGSetRelaxType(precond, 6); /* Sym G.S./Jacobi hybrid */ 
344       HYPRE_BoomerAMGSetNumSweeps(precond, 1);
345       HYPRE_BoomerAMGSetTol(precond, 1e-3); /* conv. tolerance (if needed) */
346       HYPRE_BoomerAMGSetMaxIter(precond, 1); /* do only one iteration! */
347 
348       /* Set the PCG preconditioner */
349       HYPRE_PCGSetPrecond(solver, (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSolve,
350                           (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSetup, precond);
351 
352       /* Now setup and solve! */
353       HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
354       HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
355 
356       /* Run info - needed logging turned on */
357       HYPRE_PCGGetNumIterations(solver, &num_iterations);
358       HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
359       if (myid == 0)
360       {
361          printf("\n");
362          printf("Iterations = %d\n", num_iterations);
363          printf("Final Relative Residual Norm = %e\n", final_res_norm);
364          printf("\n");
365       }
366 
367       /* Destroy solver and preconditioner */
368       HYPRE_ParCSRPCGDestroy(solver);
369       HYPRE_BoomerAMGDestroy(precond);
370    }
371    /* PCG with Parasails Preconditioner */
372    else if (solver_id == 8)
373    {
374       int    num_iterations;
375       double final_res_norm;
376 
377       int      sai_max_levels = 1;
378       double   sai_threshold = 0.1;
379       double   sai_filter = 0.05;
380       int      sai_sym = 1;
381 
382       /* Create solver */
383       HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
384 
385       /* Set some parameters (See Reference Manual for more parameters) */
386       HYPRE_PCGSetMaxIter(solver, 1000); /* max iterations */
387       HYPRE_PCGSetTol(solver, 1e-7); /* conv. tolerance */
388       HYPRE_PCGSetTwoNorm(solver, 1); /* use the two norm as the stopping criteria */
389       HYPRE_PCGSetPrintLevel(solver, 2); /* print solve info */
390       HYPRE_PCGSetLogging(solver, 1); /* needed to get run info later */
391 
392       /* Now set up the ParaSails preconditioner and specify any parameters */
393       HYPRE_ParaSailsCreate(MPI_COMM_WORLD, &precond);
394 
395       /* Set some parameters (See Reference Manual for more parameters) */
396       HYPRE_ParaSailsSetParams(precond, sai_threshold, sai_max_levels);
397       HYPRE_ParaSailsSetFilter(precond, sai_filter);
398       HYPRE_ParaSailsSetSym(precond, sai_sym);
399       HYPRE_ParaSailsSetLogging(precond, 3);
400 
401       /* Set the PCG preconditioner */
402       HYPRE_PCGSetPrecond(solver, (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSolve,
403                           (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSetup, precond);
404 
405       /* Now setup and solve! */
406       HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
407       HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
408 
409 
410       /* Run info - needed logging turned on */
411       HYPRE_PCGGetNumIterations(solver, &num_iterations);
412       HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
413       if (myid == 0)
414       {
415          printf("\n");
416          printf("Iterations = %d\n", num_iterations);
417          printf("Final Relative Residual Norm = %e\n", final_res_norm);
418          printf("\n");
419       }
420 
421       /* Destory solver and preconditioner */
422       HYPRE_ParCSRPCGDestroy(solver);
423       HYPRE_ParaSailsDestroy(precond);
424    }
425    else
426    {
427       if (myid ==0) printf("Invalid solver id specified.\n");
428    }
429 
430    /* Print the solution */
431    if (print_solution)
432       HYPRE_IJVectorPrint(x, "ij.out.x");
433 
434    /* Clean up */
435    HYPRE_IJMatrixDestroy(A);
436    HYPRE_IJVectorDestroy(b);
437    HYPRE_IJVectorDestroy(x);
438 
439    /* Finalize MPI*/
440    MPI_Finalize();
441 
442    return(0);
443 }


syntax highlighted by Code2HTML, v. 0.9.1