hypre/examples/ex1.c
2009-05-18 20:28:05 +00:00

287 lines
9.4 KiB
C

/*
Example 1
Interface: Structured interface (Struct)
Compile with: make ex1 (may need to edit HYPRE_DIR in Makefile)
Sample run: mpirun -np 2 ex1
Description: This is a two processor example. Each processor owns one
box in the grid. For reference, the two grid boxes are those
in the example diagram in the struct interface chapter
of the User's Manual. Note that in this example code, we have
used the two boxes shown in the diagram as belonging
to processor 0 (and given one box to each processor). The
solver is PCG with no preconditioner.
We recommend viewing examples 1-4 sequentially for
a nice overview/tutorial of the struct interface.
*/
#include <stdio.h>
/* Struct linear solvers header */
#include "HYPRE_struct_ls.h"
int main (int argc, char *argv[])
{
int i, j, myid, num_procs;
HYPRE_StructGrid grid;
HYPRE_StructStencil stencil;
HYPRE_StructMatrix A;
HYPRE_StructVector b;
HYPRE_StructVector x;
HYPRE_StructSolver solver;
/* Initialize MPI */
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
if (num_procs != 2)
{
if (myid ==0) printf("Must run with 2 processors!\n");
MPI_Finalize();
return(0);
}
/* 1. Set up a grid. Each processor describes the piece
of the grid that it owns. */
{
/* Create an empty 2D grid object */
HYPRE_StructGridCreate(MPI_COMM_WORLD, 2, &grid);
/* Add boxes to the grid */
if (myid == 0)
{
int ilower[2]={-3,1}, iupper[2]={-1,2};
HYPRE_StructGridSetExtents(grid, ilower, iupper);
}
else if (myid == 1)
{
int ilower[2]={0,1}, iupper[2]={2,4};
HYPRE_StructGridSetExtents(grid, ilower, iupper);
}
/* This is a collective call finalizing the grid assembly.
The grid is now ``ready to be used'' */
HYPRE_StructGridAssemble(grid);
}
/* 2. Define the discretization stencil */
{
/* Create an empty 2D, 5-pt stencil object */
HYPRE_StructStencilCreate(2, 5, &stencil);
/* Define the geometry of the stencil. Each represents a
relative offset (in the index space). */
{
int entry;
int offsets[5][2] = {{0,0}, {-1,0}, {1,0}, {0,-1}, {0,1}};
/* Assign each of the 5 stencil entries */
for (entry = 0; entry < 5; entry++)
HYPRE_StructStencilSetElement(stencil, entry, offsets[entry]);
}
}
/* 3. Set up a Struct Matrix */
{
/* Create an empty matrix object */
HYPRE_StructMatrixCreate(MPI_COMM_WORLD, grid, stencil, &A);
/* Indicate that the matrix coefficients are ready to be set */
HYPRE_StructMatrixInitialize(A);
/* Set the matrix coefficients. Each processor assigns coefficients
for the boxes in the grid that it owns. Note that the coefficients
associated with each stencil entry may vary from grid point to grid
point if desired. Here, we first set the same stencil entries for
each grid point. Then we make modifications to grid points near
the boundary. */
if (myid == 0)
{
int ilower[2]={-3,1}, iupper[2]={-1,2};
int stencil_indices[5] = {0,1,2,3,4}; /* labels for the stencil entries -
these correspond to the offsets
defined above */
int nentries = 5;
int nvalues = 30; /* 6 grid points, each with 5 stencil entries */
double values[30];
/* We have 6 grid points, each with 5 stencil entries */
for (i = 0; i < nvalues; i += nentries)
{
values[i] = 4.0;
for (j = 1; j < nentries; j++)
values[i+j] = -1.0;
}
HYPRE_StructMatrixSetBoxValues(A, ilower, iupper, nentries,
stencil_indices, values);
}
else if (myid == 1)
{
int ilower[2]={0,1}, iupper[2]={2,4};
int stencil_indices[5] = {0,1,2,3,4};
int nentries = 5;
int nvalues = 60; /* 12 grid points, each with 5 stencil entries */
double values[60];
for (i = 0; i < nvalues; i += nentries)
{
values[i] = 4.0;
for (j = 1; j < nentries; j++)
values[i+j] = -1.0;
}
HYPRE_StructMatrixSetBoxValues(A, ilower, iupper, nentries,
stencil_indices, values);
}
/* Set the coefficients reaching outside of the boundary to 0 */
if (myid == 0)
{
double values[3];
for (i = 0; i < 3; i++)
values[i] = 0.0;
{
/* values below our box */
int ilower[2]={-3,1}, iupper[2]={-1,1};
int stencil_indices[1] = {3};
HYPRE_StructMatrixSetBoxValues(A, ilower, iupper, 1,
stencil_indices, values);
}
{
/* values to the left of our box */
int ilower[2]={-3,1}, iupper[2]={-3,2};
int stencil_indices[1] = {1};
HYPRE_StructMatrixSetBoxValues(A, ilower, iupper, 1,
stencil_indices, values);
}
{
/* values above our box */
int ilower[2]={-3,2}, iupper[2]={-1,2};
int stencil_indices[1] = {4};
HYPRE_StructMatrixSetBoxValues(A, ilower, iupper, 1,
stencil_indices, values);
}
}
else if (myid == 1)
{
double values[4];
for (i = 0; i < 4; i++)
values[i] = 0.0;
{
/* values below our box */
int ilower[2]={0,1}, iupper[2]={2,1};
int stencil_indices[1] = {3};
HYPRE_StructMatrixSetBoxValues(A, ilower, iupper, 1,
stencil_indices, values);
}
{
/* values to the right of our box */
int ilower[2]={2,1}, iupper[2]={2,4};
int stencil_indices[1] = {2};
HYPRE_StructMatrixSetBoxValues(A, ilower, iupper, 1,
stencil_indices, values);
}
{
/* values above our box */
int ilower[2]={0,4}, iupper[2]={2,4};
int stencil_indices[1] = {4};
HYPRE_StructMatrixSetBoxValues(A, ilower, iupper, 1,
stencil_indices, values);
}
{
/* values to the left of our box
(that do not border the other box on proc. 0) */
int ilower[2]={0,3}, iupper[2]={0,4};
int stencil_indices[1] = {1};
HYPRE_StructMatrixSetBoxValues(A, ilower, iupper, 1,
stencil_indices, values);
}
}
/* This is a collective call finalizing the matrix assembly.
The matrix is now ``ready to be used'' */
HYPRE_StructMatrixAssemble(A);
}
/* 4. Set up Struct Vectors for b and x. Each processor sets the vectors
corresponding to its boxes. */
{
/* Create an empty vector object */
HYPRE_StructVectorCreate(MPI_COMM_WORLD, grid, &b);
HYPRE_StructVectorCreate(MPI_COMM_WORLD, grid, &x);
/* Indicate that the vector coefficients are ready to be set */
HYPRE_StructVectorInitialize(b);
HYPRE_StructVectorInitialize(x);
/* Set the vector coefficients */
if (myid == 0)
{
int ilower[2]={-3,1}, iupper[2]={-1,2};
double values[6]; /* 6 grid points */
for (i = 0; i < 6; i ++)
values[i] = 1.0;
HYPRE_StructVectorSetBoxValues(b, ilower, iupper, values);
for (i = 0; i < 6; i ++)
values[i] = 0.0;
HYPRE_StructVectorSetBoxValues(x, ilower, iupper, values);
}
else if (myid == 1)
{
int ilower[2]={0,1}, iupper[2]={2,4};
double values[12]; /* 12 grid points */
for (i = 0; i < 12; i ++)
values[i] = 1.0;
HYPRE_StructVectorSetBoxValues(b, ilower, iupper, values);
for (i = 0; i < 12; i ++)
values[i] = 0.0;
HYPRE_StructVectorSetBoxValues(x, ilower, iupper, values);
}
/* This is a collective call finalizing the vector assembly.
The vectors are now ``ready to be used'' */
HYPRE_StructVectorAssemble(b);
HYPRE_StructVectorAssemble(x);
}
/* 5. Set up and use a solver (See the Reference Manual for descriptions
of all of the options.) */
{
/* Create an empty PCG Struct solver */
HYPRE_StructPCGCreate(MPI_COMM_WORLD, &solver);
/* Set some parameters */
HYPRE_StructPCGSetTol(solver, 1.0e-06); /* convergence tolerance */
HYPRE_StructPCGSetPrintLevel(solver, 2); /* amount of info. printed */
/* Setup and solve */
HYPRE_StructPCGSetup(solver, A, b, x);
HYPRE_StructPCGSolve(solver, A, b, x);
}
/* Free memory */
HYPRE_StructGridDestroy(grid);
HYPRE_StructStencilDestroy(stencil);
HYPRE_StructMatrixDestroy(A);
HYPRE_StructVectorDestroy(b);
HYPRE_StructVectorDestroy(x);
HYPRE_StructPCGDestroy(solver);
/* Finalize MPI */
MPI_Finalize();
return (0);
}