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