download the original source code.
1 /*
2 Example 11
3
4 Interface: Linear-Algebraic (IJ)
5
6 Compile with: make ex11
7
8 Sample run: mpirun -np 4 ex11
9
10 Description: This example solves the 2-D Laplacian eigenvalue
11 problem with zero boundary conditions on an nxn grid.
12 The number of unknowns is N=n^2. The standard 5-point
13 stencil is used, and we solve for the interior nodes
14 only.
15
16 We use the same matrix as in Examples 3 and 5.
17 The eigensolver is LOBPCG with AMG preconditioner.
18 */
19
20 #include <math.h>
21 #include "_hypre_utilities.h"
22 #include "krylov.h"
23 #include "HYPRE.h"
24 #include "HYPRE_parcsr_ls.h"
25
26 /* lobpcg stuff */
27 #include "HYPRE_lobpcg.h"
28 #include "interpreter.h"
29 #include "HYPRE_MatvecFunctions.h"
30 #include "temp_multivector.h"
31 #include "_hypre_parcsr_mv.h"
32
33 #include "vis.c"
34
35 int main (int argc, char *argv[])
36 {
37 int i;
38 int myid, num_procs;
39 int N, n;
40 int blockSize;
41
42 int ilower, iupper;
43 int local_size, extra;
44
45 int vis;
46
47 HYPRE_IJMatrix A;
48 HYPRE_ParCSRMatrix parcsr_A;
49 HYPRE_IJVector b;
50 HYPRE_ParVector par_b;
51 HYPRE_IJVector x;
52 HYPRE_ParVector par_x;
53 HYPRE_ParVector* pvx;
54
55 HYPRE_Solver precond, lobpcg_solver;
56 mv_InterfaceInterpreter* interpreter;
57 HYPRE_MatvecFunctions matvec_fn;
58
59 /* Initialize MPI */
60 MPI_Init(&argc, &argv);
61 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
62 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
63
64 /* Default problem parameters */
65 n = 33;
66 blockSize = 10;
67 vis = 0;
68
69 /* Parse command line */
70 {
71 int arg_index = 0;
72 int print_usage = 0;
73
74 while (arg_index < argc)
75 {
76 if ( strcmp(argv[arg_index], "-n") == 0 )
77 {
78 arg_index++;
79 n = atoi(argv[arg_index++]);
80 }
81 else if ( strcmp(argv[arg_index], "-blockSize") == 0 )
82 {
83 arg_index++;
84 blockSize = atoi(argv[arg_index++]);
85 }
86 else if ( strcmp(argv[arg_index], "-vis") == 0 )
87 {
88 arg_index++;
89 vis = 1;
90 }
91 else if ( strcmp(argv[arg_index], "-help") == 0 )
92 {
93 print_usage = 1;
94 break;
95 }
96 else
97 {
98 arg_index++;
99 }
100 }
101
102 if ((print_usage) && (myid == 0))
103 {
104 printf("\n");
105 printf("Usage: %s [<options>]\n", argv[0]);
106 printf("\n");
107 printf(" -n <n> : problem size in each direction (default: 33)\n");
108 printf(" -blockSize <n> : eigenproblem block size (default: 10)\n");
109 printf(" -vis : save the solution for GLVis visualization\n");
110 printf("\n");
111 }
112
113 if (print_usage)
114 {
115 MPI_Finalize();
116 return (0);
117 }
118 }
119
120 /* Preliminaries: want at least one processor per row */
121 if (n*n < num_procs) n = sqrt(num_procs) + 1;
122 N = n*n; /* global number of rows */
123
124 /* Each processor knows only of its own rows - the range is denoted by ilower
125 and iupper. Here we partition the rows. We account for the fact that
126 N may not divide evenly by the number of processors. */
127 local_size = N/num_procs;
128 extra = N - local_size*num_procs;
129
130 ilower = local_size*myid;
131 ilower += hypre_min(myid, extra);
132
133 iupper = local_size*(myid+1);
134 iupper += hypre_min(myid+1, extra);
135 iupper = iupper - 1;
136
137 /* How many rows do I have? */
138 local_size = iupper - ilower + 1;
139
140 /* Create the matrix.
141 Note that this is a square matrix, so we indicate the row partition
142 size twice (since number of rows = number of cols) */
143 HYPRE_IJMatrixCreate(MPI_COMM_WORLD, ilower, iupper, ilower, iupper, &A);
144
145 /* Choose a parallel csr format storage (see the User's Manual) */
146 HYPRE_IJMatrixSetObjectType(A, HYPRE_PARCSR);
147
148 /* Initialize before setting coefficients */
149 HYPRE_IJMatrixInitialize(A);
150
151 /* Now go through my local rows and set the matrix entries.
152 Each row has at most 5 entries. For example, if n=3:
153
154 A = [M -I 0; -I M -I; 0 -I M]
155 M = [4 -1 0; -1 4 -1; 0 -1 4]
156
157 Note that here we are setting one row at a time, though
158 one could set all the rows together (see the User's Manual).
159 */
160 {
161 int nnz;
162 double values[5];
163 int cols[5];
164
165 for (i = ilower; i <= iupper; i++)
166 {
167 nnz = 0;
168
169 /* The left identity block:position i-n */
170 if ((i-n)>=0)
171 {
172 cols[nnz] = i-n;
173 values[nnz] = -1.0;
174 nnz++;
175 }
176
177 /* The left -1: position i-1 */
178 if (i%n)
179 {
180 cols[nnz] = i-1;
181 values[nnz] = -1.0;
182 nnz++;
183 }
184
185 /* Set the diagonal: position i */
186 cols[nnz] = i;
187 values[nnz] = 4.0;
188 nnz++;
189
190 /* The right -1: position i+1 */
191 if ((i+1)%n)
192 {
193 cols[nnz] = i+1;
194 values[nnz] = -1.0;
195 nnz++;
196 }
197
198 /* The right identity block:position i+n */
199 if ((i+n)< N)
200 {
201 cols[nnz] = i+n;
202 values[nnz] = -1.0;
203 nnz++;
204 }
205
206 /* Set the values for row i */
207 HYPRE_IJMatrixSetValues(A, 1, &nnz, &i, cols, values);
208 }
209 }
210
211 /* Assemble after setting the coefficients */
212 HYPRE_IJMatrixAssemble(A);
213 /* Get the parcsr matrix object to use */
214 HYPRE_IJMatrixGetObject(A, (void**) &parcsr_A);
215
216 /* Create sample rhs and solution vectors */
217 HYPRE_IJVectorCreate(MPI_COMM_WORLD, ilower, iupper,&b);
218 HYPRE_IJVectorSetObjectType(b, HYPRE_PARCSR);
219 HYPRE_IJVectorInitialize(b);
220 HYPRE_IJVectorAssemble(b);
221 HYPRE_IJVectorGetObject(b, (void **) &par_b);
222
223 HYPRE_IJVectorCreate(MPI_COMM_WORLD, ilower, iupper,&x);
224 HYPRE_IJVectorSetObjectType(x, HYPRE_PARCSR);
225 HYPRE_IJVectorInitialize(x);
226 HYPRE_IJVectorAssemble(x);
227 HYPRE_IJVectorGetObject(x, (void **) &par_x);
228
229 /* Create a preconditioner and solve the eigenproblem */
230
231 /* AMG preconditioner */
232 {
233 HYPRE_BoomerAMGCreate(&precond);
234 HYPRE_BoomerAMGSetPrintLevel(precond, 1); /* print amg solution info */
235 HYPRE_BoomerAMGSetCoarsenType(precond, 6);
236 HYPRE_BoomerAMGSetRelaxType(precond, 6); /* Sym G.S./Jacobi hybrid */
237 HYPRE_BoomerAMGSetNumSweeps(precond, 1);
238 HYPRE_BoomerAMGSetTol(precond, 0.0); /* conv. tolerance zero */
239 HYPRE_BoomerAMGSetMaxIter(precond, 1); /* do only one iteration! */
240 }
241
242 /* LOBPCG eigensolver */
243 {
244 int time_index;
245
246 int maxIterations = 100; /* maximum number of iterations */
247 int pcgMode = 1; /* use rhs as initial guess for inner pcg iterations */
248 int verbosity = 1; /* print iterations info */
249 double tol = 1.e-8; /* absolute tolerance (all eigenvalues) */
250 int lobpcgSeed = 775; /* random seed */
251
252 mv_MultiVectorPtr eigenvectors = NULL;
253 mv_MultiVectorPtr constraints = NULL;
254 double *eigenvalues = NULL;
255
256 if (myid != 0)
257 verbosity = 0;
258
259 /* define an interpreter for the ParCSR interface */
260 interpreter = hypre_CTAlloc(mv_InterfaceInterpreter,1);
261 HYPRE_ParCSRSetupInterpreter(interpreter);
262 HYPRE_ParCSRSetupMatvec(&matvec_fn);
263
264 /* eigenvectors - create a multivector */
265 eigenvectors =
266 mv_MultiVectorCreateFromSampleVector(interpreter, blockSize, par_x);
267 mv_MultiVectorSetRandom (eigenvectors, lobpcgSeed);
268
269 /* eigenvectors - get a pointer */
270 {
271 mv_TempMultiVector* tmp = (mv_TempMultiVector*) mv_MultiVectorGetData(eigenvectors);
272 pvx = (HYPRE_ParVector*)(tmp -> vector);
273 }
274
275 /* eigenvalues - allocate space */
276 eigenvalues = (double*) calloc( blockSize, sizeof(double) );
277
278 HYPRE_LOBPCGCreate(interpreter, &matvec_fn, &lobpcg_solver);
279 HYPRE_LOBPCGSetMaxIter(lobpcg_solver, maxIterations);
280 HYPRE_LOBPCGSetPrecondUsageMode(lobpcg_solver, pcgMode);
281 HYPRE_LOBPCGSetTol(lobpcg_solver, tol);
282 HYPRE_LOBPCGSetPrintLevel(lobpcg_solver, verbosity);
283
284 /* use a preconditioner */
285 HYPRE_LOBPCGSetPrecond(lobpcg_solver,
286 (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSolve,
287 (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSetup,
288 precond);
289
290 HYPRE_LOBPCGSetup(lobpcg_solver, (HYPRE_Matrix)parcsr_A,
291 (HYPRE_Vector)par_b, (HYPRE_Vector)par_x);
292
293 time_index = hypre_InitializeTiming("LOBPCG Solve");
294 hypre_BeginTiming(time_index);
295
296 HYPRE_LOBPCGSolve(lobpcg_solver, constraints, eigenvectors, eigenvalues );
297
298 hypre_EndTiming(time_index);
299 hypre_PrintTiming("Solve phase times", MPI_COMM_WORLD);
300 hypre_FinalizeTiming(time_index);
301 hypre_ClearTiming();
302
303 /* clean-up */
304 HYPRE_BoomerAMGDestroy(precond);
305 HYPRE_LOBPCGDestroy(lobpcg_solver);
306 hypre_TFree(eigenvalues);
307 hypre_TFree(interpreter);
308 }
309
310 /* Save the solution for GLVis visualization, see vis/glvis-ex11.sh */
311 if (vis)
312 {
313 FILE *file;
314 char filename[255];
315
316 int nvalues = local_size;
317 double *values;
318
319 /* get the local solution */
320 values = hypre_VectorData(hypre_ParVectorLocalVector(
321 (hypre_ParVector*)pvx[blockSize-1]));
322
323 sprintf(filename, "%s.%06d", "vis/ex11.sol", myid);
324 if ((file = fopen(filename, "w")) == NULL)
325 {
326 printf("Error: can't open output file %s\n", filename);
327 MPI_Finalize();
328 exit(1);
329 }
330
331 /* save solution */
332 for (i = 0; i < nvalues; i++)
333 fprintf(file, "%.14e\n", values[i]);
334
335 fflush(file);
336 fclose(file);
337
338 /* save global finite element mesh */
339 if (myid == 0)
340 GLVis_PrintGlobalSquareMesh("vis/ex11.mesh", n-1);
341 }
342
343 /* Clean up */
344 HYPRE_IJMatrixDestroy(A);
345 HYPRE_IJVectorDestroy(b);
346 HYPRE_IJVectorDestroy(x);
347
348 /* Finalize MPI*/
349 MPI_Finalize();
350
351 return(0);
352 }
syntax highlighted by Code2HTML, v. 0.9.1