download the original source code.
1 /*
2 Example 6
3
4 Interface: Semi-Structured interface (SStruct)
5
6 Compile with: make ex6
7
8 Sample run: mpirun -np 2 ex6
9
10 Description: This is a two processor example and is the same problem
11 as is solved with the structured interface in Example 2.
12 (The grid boxes are exactly those in the example
13 diagram in the struct interface chapter of the User's Manual.
14 Processor 0 owns two boxes and processor 1 owns one box.)
15
16 This is the simplest sstruct example, and it demonstrates how
17 the semi-structured interface can be used for structured problems.
18 There is one part and one variable. The solver is PCG with SMG
19 preconditioner. We use a structured solver for this example.
20 */
21
22 #include <stdio.h>
23
24 /* SStruct linear solvers headers */
25 #include "HYPRE_sstruct_ls.h"
26
27 int main (int argc, char *argv[])
28 {
29 int myid, num_procs;
30
31 HYPRE_SStructGrid grid;
32 HYPRE_SStructGraph graph;
33 HYPRE_SStructStencil stencil;
34 HYPRE_SStructMatrix A;
35 HYPRE_SStructVector b;
36 HYPRE_SStructVector x;
37
38 /* We are using struct solvers for this example */
39 HYPRE_StructSolver solver;
40 HYPRE_StructSolver precond;
41
42 int object_type;
43
44 /* Initialize MPI */
45 MPI_Init(&argc, &argv);
46 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
47 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
48
49 if (num_procs != 2)
50 {
51 if (myid ==0) printf("Must run with 2 processors!\n");
52 MPI_Finalize();
53
54 return(0);
55 }
56
57 /* 1. Set up the 2D grid. This gives the index space in each part.
58 Here we only use one part and one variable. (So the part id is 0
59 and the variable id is 0) */
60 {
61 int ndim = 2;
62 int nparts = 1;
63 int part = 0;
64
65 /* Create an empty 2D grid object */
66 HYPRE_SStructGridCreate(MPI_COMM_WORLD, ndim, nparts, &grid);
67
68 /* Set the extents of the grid - each processor sets its grid
69 boxes. Each part has its own relative index space numbering,
70 but in this example all boxes belong to the same part. */
71
72 /* Processor 0 owns two boxes in the grid. */
73 if (myid == 0)
74 {
75 /* Add a new box to the grid */
76 {
77 int ilower[2] = {-3, 1};
78 int iupper[2] = {-1, 2};
79
80 HYPRE_SStructGridSetExtents(grid, part, ilower, iupper);
81 }
82
83 /* Add a new box to the grid */
84 {
85 int ilower[2] = {0, 1};
86 int iupper[2] = {2, 4};
87
88 HYPRE_SStructGridSetExtents(grid, part, ilower, iupper);
89 }
90 }
91
92 /* Processor 1 owns one box in the grid. */
93 else if (myid == 1)
94 {
95 /* Add a new box to the grid */
96 {
97 int ilower[2] = {3, 1};
98 int iupper[2] = {6, 4};
99
100 HYPRE_SStructGridSetExtents(grid, part, ilower, iupper);
101 }
102 }
103
104 /* Set the variable type and number of variables on each part. */
105 {
106 int i;
107 int nvars = 1;
108 HYPRE_SStructVariable vartypes[1] = {HYPRE_SSTRUCT_VARIABLE_CELL};
109
110 for (i = 0; i< nparts; i++)
111 HYPRE_SStructGridSetVariables(grid, i, nvars, vartypes);
112 }
113
114 /* Now the grid is ready to use */
115 HYPRE_SStructGridAssemble(grid);
116 }
117
118 /* 2. Define the discretization stencil(s) */
119 {
120 /* Create an empty 2D, 5-pt stencil object */
121 HYPRE_SStructStencilCreate(2, 5, &stencil);
122
123 /* Define the geometry of the stencil. Each represents a
124 relative offset (in the index space). */
125 {
126 int entry;
127 int offsets[5][2] = {{0,0}, {-1,0}, {1,0}, {0,-1}, {0,1}};
128 int var = 0;
129
130 /* Assign numerical values to the offsets so that we can
131 easily refer to them - the last argument indicates the
132 variable for which we are assigning this stencil - we are
133 just using one variable in this example so it is the first one (0) */
134 for (entry = 0; entry < 5; entry++)
135 HYPRE_SStructStencilSetEntry(stencil, entry, offsets[entry], var);
136 }
137 }
138
139 /* 3. Set up the Graph - this determines the non-zero structure
140 of the matrix and allows non-stencil relationships between the parts */
141 {
142 int var = 0;
143 int part = 0;
144
145 /* Create the graph object */
146 HYPRE_SStructGraphCreate(MPI_COMM_WORLD, grid, &graph);
147
148 /* See MatrixSetObjectType below */
149 object_type = HYPRE_STRUCT;
150 HYPRE_SStructGraphSetObjectType(graph, object_type);
151
152 /* Now we need to tell the graph which stencil to use for each
153 variable on each part (we only have one variable and one part) */
154 HYPRE_SStructGraphSetStencil(graph, part, var, stencil);
155
156 /* Here we could establish connections between parts if we
157 had more than one part using the graph. For example, we could
158 use HYPRE_GraphAddEntries() routine or HYPRE_GridSetNeighborBox() */
159
160 /* Assemble the graph */
161 HYPRE_SStructGraphAssemble(graph);
162 }
163
164 /* 4. Set up a SStruct Matrix */
165 {
166 int i,j;
167 int part = 0;
168 int var = 0;
169
170 /* Create the empty matrix object */
171 HYPRE_SStructMatrixCreate(MPI_COMM_WORLD, graph, &A);
172
173 /* Set the object type (by default HYPRE_SSTRUCT). This determines the
174 data structure used to store the matrix. If you want to use unstructured
175 solvers, e.g. BoomerAMG, the object type should be HYPRE_PARCSR.
176 If the problem is purely structured (with one part), you may want to use
177 HYPRE_STRUCT to access the structured solvers. Here we have a purely
178 structured example. */
179 object_type = HYPRE_STRUCT;
180 HYPRE_SStructMatrixSetObjectType(A, object_type);
181
182 /* Get ready to set values */
183 HYPRE_SStructMatrixInitialize(A);
184
185 /* Each processor must set the stencil values for their boxes on each part.
186 In this example, we only set stencil entries and therefore use
187 HYPRE_SStructMatrixSetBoxValues. If we need to set non-stencil entries,
188 we have to use HYPRE_SStructMatrixSetValues (shown in a later example). */
189
190 if (myid == 0)
191 {
192 /* Set the matrix coefficients for some set of stencil entries
193 over all the gridpoints in my first box (account for boundary
194 grid points later) */
195 {
196 int ilower[2] = {-3, 1};
197 int iupper[2] = {-1, 2};
198
199 int nentries = 5;
200 int nvalues = 30; /* 6 grid points, each with 5 stencil entries */
201 double values[30];
202
203 int stencil_indices[5];
204 for (j = 0; j < nentries; j++) /* label the stencil indices -
205 these correspond to the offsets
206 defined above */
207 stencil_indices[j] = j;
208
209 for (i = 0; i < nvalues; i += nentries)
210 {
211 values[i] = 4.0;
212 for (j = 1; j < nentries; j++)
213 values[i+j] = -1.0;
214 }
215
216 HYPRE_SStructMatrixSetBoxValues(A, part, ilower, iupper,
217 var, nentries,
218 stencil_indices, values);
219 }
220
221 /* Set the matrix coefficients for some set of stencil entries
222 over the gridpoints in my second box */
223 {
224 int ilower[2] = {0, 1};
225 int iupper[2] = {2, 4};
226
227 int nentries = 5;
228 int nvalues = 60; /* 12 grid points, each with 5 stencil entries */
229 double values[60];
230
231 int stencil_indices[5];
232 for (j = 0; j < nentries; j++)
233 stencil_indices[j] = j;
234
235 for (i = 0; i < nvalues; i += nentries)
236 {
237 values[i] = 4.0;
238 for (j = 1; j < nentries; j++)
239 values[i+j] = -1.0;
240 }
241
242 HYPRE_SStructMatrixSetBoxValues(A, part, ilower, iupper,
243 var, nentries,
244 stencil_indices, values);
245 }
246 }
247 else if (myid == 1)
248 {
249 /* Set the matrix coefficients for some set of stencil entries
250 over the gridpoints in my box */
251 {
252 int ilower[2] = {3, 1};
253 int iupper[2] = {6, 4};
254
255 int nentries = 5;
256 int nvalues = 80; /* 16 grid points, each with 5 stencil entries */
257 double values[80];
258
259 int stencil_indices[5];
260 for (j = 0; j < nentries; j++)
261 stencil_indices[j] = j;
262
263 for (i = 0; i < nvalues; i += nentries)
264 {
265 values[i] = 4.0;
266 for (j = 1; j < nentries; j++)
267 values[i+j] = -1.0;
268 }
269
270 HYPRE_SStructMatrixSetBoxValues(A, part, ilower, iupper,
271 var, nentries,
272 stencil_indices, values);
273 }
274 }
275
276 /* For each box, set any coefficients that reach ouside of the
277 boundary to 0 */
278 if (myid == 0)
279 {
280 int maxnvalues = 6;
281 double values[6];
282
283 for (i = 0; i < maxnvalues; i++)
284 values[i] = 0.0;
285
286 {
287 /* Values below our first AND second box */
288 int ilower[2] = {-3, 1};
289 int iupper[2] = { 2, 1};
290
291 int stencil_indices[1] = {3};
292
293 HYPRE_SStructMatrixSetBoxValues(A, part, ilower, iupper,
294 var, 1,
295 stencil_indices, values);
296 }
297
298 {
299 /* Values to the left of our first box */
300 int ilower[2] = {-3, 1};
301 int iupper[2] = {-3, 2};
302
303 int stencil_indices[1] = {1};
304
305 HYPRE_SStructMatrixSetBoxValues(A, part, ilower, iupper,
306 var, 1,
307 stencil_indices, values);
308 }
309
310 {
311 /* Values above our first box */
312 int ilower[2] = {-3, 2};
313 int iupper[2] = {-1, 2};
314
315 int stencil_indices[1] = {4};
316
317 HYPRE_SStructMatrixSetBoxValues(A, part, ilower, iupper,
318 var, 1,
319 stencil_indices, values);
320 }
321
322 {
323 /* Values to the left of our second box (that do not border the
324 first box). */
325 int ilower[2] = { 0, 3};
326 int iupper[2] = { 0, 4};
327
328 int stencil_indices[1] = {1};
329
330 HYPRE_SStructMatrixSetBoxValues(A, part, ilower, iupper,
331 var, 1,
332 stencil_indices, values);
333 }
334
335 {
336 /* Values above our second box */
337 int ilower[2] = { 0, 4};
338 int iupper[2] = { 2, 4};
339
340 int stencil_indices[1] = {4};
341
342 HYPRE_SStructMatrixSetBoxValues(A, part, ilower, iupper,
343 var, 1,
344 stencil_indices, values);
345 }
346 }
347 else if (myid == 1)
348 {
349 int maxnvalues = 4;
350 double values[4];
351 for (i = 0; i < maxnvalues; i++)
352 values[i] = 0.0;
353
354 {
355 /* Values below our box */
356 int ilower[2] = { 3, 1};
357 int iupper[2] = { 6, 1};
358
359 int stencil_indices[1] = {3};
360
361 HYPRE_SStructMatrixSetBoxValues(A, part, ilower, iupper,
362 var, 1,
363 stencil_indices, values);
364 }
365
366 {
367 /* Values to the right of our box */
368 int ilower[2] = { 6, 1};
369 int iupper[2] = { 6, 4};
370
371 int stencil_indices[1] = {2};
372
373 HYPRE_SStructMatrixSetBoxValues(A, part, ilower, iupper,
374 var, 1,
375 stencil_indices, values);
376 }
377
378 {
379 /* Values above our box */
380 int ilower[2] = { 3, 4};
381 int iupper[2] = { 6, 4};
382
383 int stencil_indices[1] = {4};
384
385 HYPRE_SStructMatrixSetBoxValues(A, part, ilower, iupper,
386 var, 1,
387 stencil_indices, values);
388 }
389 }
390
391 /* This is a collective call finalizing the matrix assembly.
392 The matrix is now ``ready to be used'' */
393 HYPRE_SStructMatrixAssemble(A);
394 }
395
396
397 /* 5. Set up SStruct Vectors for b and x */
398 {
399 int i;
400
401 /* We have one part and one variable. */
402 int part = 0;
403 int var = 0;
404
405 /* Create an empty vector object */
406 HYPRE_SStructVectorCreate(MPI_COMM_WORLD, grid, &b);
407 HYPRE_SStructVectorCreate(MPI_COMM_WORLD, grid, &x);
408
409 /* As with the matrix, set the object type for the vectors
410 to be the struct type */
411 object_type = HYPRE_STRUCT;
412 HYPRE_SStructVectorSetObjectType(b, object_type);
413 HYPRE_SStructVectorSetObjectType(x, object_type);
414
415 /* Indicate that the vector coefficients are ready to be set */
416 HYPRE_SStructVectorInitialize(b);
417 HYPRE_SStructVectorInitialize(x);
418
419 if (myid == 0)
420 {
421 /* Set the vector coefficients over the gridpoints in my first box */
422 {
423 int ilower[2] = {-3, 1};
424 int iupper[2] = {-1, 2};
425
426 int nvalues = 6; /* 6 grid points */
427 double values[6];
428
429 for (i = 0; i < nvalues; i ++)
430 values[i] = 1.0;
431 HYPRE_SStructVectorSetBoxValues(b, part, ilower, iupper, var, values);
432
433 for (i = 0; i < nvalues; i ++)
434 values[i] = 0.0;
435 HYPRE_SStructVectorSetBoxValues(x, part, ilower, iupper, var, values);
436 }
437
438 /* Set the vector coefficients over the gridpoints in my second box */
439 {
440 int ilower[2] = { 0, 1};
441 int iupper[2] = { 2, 4};
442
443 int nvalues = 12; /* 12 grid points */
444 double values[12];
445
446 for (i = 0; i < nvalues; i ++)
447 values[i] = 1.0;
448 HYPRE_SStructVectorSetBoxValues(b, part, ilower, iupper, var, values);
449
450 for (i = 0; i < nvalues; i ++)
451 values[i] = 0.0;
452 HYPRE_SStructVectorSetBoxValues(x, part, ilower, iupper, var, values);
453 }
454 }
455 else if (myid == 1)
456 {
457 /* Set the vector coefficients over the gridpoints in my box */
458 {
459 int ilower[2] = { 3, 1};
460 int iupper[2] = { 6, 4};
461
462 int nvalues = 16; /* 16 grid points */
463 double values[16];
464
465 for (i = 0; i < nvalues; i ++)
466 values[i] = 1.0;
467 HYPRE_SStructVectorSetBoxValues(b, part, ilower, iupper, var, values);
468
469 for (i = 0; i < nvalues; i ++)
470 values[i] = 0.0;
471 HYPRE_SStructVectorSetBoxValues(x, part, ilower, iupper, var, values);
472 }
473 }
474
475 /* This is a collective call finalizing the vector assembly.
476 The vectors are now ``ready to be used'' */
477 HYPRE_SStructVectorAssemble(b);
478 HYPRE_SStructVectorAssemble(x);
479 }
480
481
482 /* 6. Set up and use a solver (See the Reference Manual for descriptions
483 of all of the options.) */
484 {
485 HYPRE_StructMatrix sA;
486 HYPRE_StructVector sb;
487 HYPRE_StructVector sx;
488
489 /* Because we are using a struct solver, we need to get the
490 object of the matrix and vectors to pass in to the struct solvers */
491 HYPRE_SStructMatrixGetObject(A, (void **) &sA);
492 HYPRE_SStructVectorGetObject(b, (void **) &sb);
493 HYPRE_SStructVectorGetObject(x, (void **) &sx);
494
495 /* Create an empty PCG Struct solver */
496 HYPRE_StructPCGCreate(MPI_COMM_WORLD, &solver);
497
498 /* Set PCG parameters */
499 HYPRE_StructPCGSetTol(solver, 1.0e-06);
500 HYPRE_StructPCGSetPrintLevel(solver, 2);
501 HYPRE_StructPCGSetMaxIter(solver, 50);
502
503 /* Create the Struct SMG solver for use as a preconditioner */
504 HYPRE_StructSMGCreate(MPI_COMM_WORLD, &precond);
505
506 /* Set SMG parameters */
507 HYPRE_StructSMGSetMaxIter(precond, 1);
508 HYPRE_StructSMGSetTol(precond, 0.0);
509 HYPRE_StructSMGSetZeroGuess(precond);
510 HYPRE_StructSMGSetNumPreRelax(precond, 1);
511 HYPRE_StructSMGSetNumPostRelax(precond, 1);
512
513 /* Set preconditioner and solve */
514 HYPRE_StructPCGSetPrecond(solver, HYPRE_StructSMGSolve,
515 HYPRE_StructSMGSetup, precond);
516 HYPRE_StructPCGSetup(solver, sA, sb, sx);
517 HYPRE_StructPCGSolve(solver, sA, sb, sx);
518 }
519
520 /* Free memory */
521 HYPRE_SStructGridDestroy(grid);
522 HYPRE_SStructStencilDestroy(stencil);
523 HYPRE_SStructGraphDestroy(graph);
524 HYPRE_SStructMatrixDestroy(A);
525 HYPRE_SStructVectorDestroy(b);
526 HYPRE_SStructVectorDestroy(x);
527
528 HYPRE_StructPCGDestroy(solver);
529 HYPRE_StructSMGDestroy(precond);
530
531 /* Finalize MPI */
532 MPI_Finalize();
533
534 return (0);
535 }
syntax highlighted by Code2HTML, v. 0.9.1