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