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