CSE 557 - Homework assignment 3

Due: Monday, March 20, in class.
  ------------------------------------------------------------------------

GridComm library |  Include files | Source files | Example programs |
Example makefiles | Groups | What to turn in
  ------------------------------------------------------------------------

The goal of this homework is to develop a library of routines to maintain
grid-based data structures suitable for implementing iterative methods. The
idea behind using the library routines is that rather than writing a long
program that includes everything to implement an iterative method on a
parallel grid data structure, we will try to encapsulate the initialization,
partitioning, and communication routines that are common to all of these
algorithms and implement them once as library routines. When we implement an
interative method, say relaxation, we would call the appropriate library
functions to accomplish the iterative method. If we wanted to move on to
implementing multigrid, we should be able to reuse the same library without
having to rewrite everything!

  ------------------------------------------------------------------------

The GridComm library

We will call this library, GC, for "GridComm". Thus, just like for MPI, all
the routines will begin with the initials, data structures, etc., will begin
with the initials GC. It is important to keep the library in a standard
format. We keep everything in a directory entitled "GridComm" (the root
directory) and everything will be maintained in a particular unix directory
structure under this root directory.

The root directory should contain the subdirectories and files:

   * src a directory containing the library source files.
   * lib a directory containing the compiled libraries.
   * include a directory containing the library include files.
   * examples a directory containing example programs that use the library
     routines.
   * README a file that explains how to make the library and compile and
     link the example programs. This file should also explain anything that
     must be done to make the routines on different architectures.
   * makefile a main makefile that compiles and archives the libraries and
     makes the examples.

  ------------------------------------------------------------------------

The GridComm include files and data structure definitions

Well, to implement these routines, we need some data structures. These data
structures will all be defined in the include directory in a file called
GCinclude.h. Every program that uses these routines will include this file
so that the GC data structures will be defined. The include file would look
something like this (you will have to modify this!):

/*@ GCinclude.h - Include fle for the GridComm package.
    This is the include file for public use.
 @*/

#ifndef __GCincludeh
#define __GCincludeh

/* system stuff */
#include  < stdio.h >
#include  < limits.h >
#include  < math.h >

/* use FLOAT definition to switch between float and double */
#define FLOAT double

/* basic GridComm Grid data structure */
typedef struct __GCgrid {
        int     nx;       /* Number of global grid points in X-direction */
        int     ny;       /* Number of global grid points in Y-direction */
        int     lnx;      /* Number of local grid points in X-direction */
        int     lny;      /* Number of local grid points in Y-direction */
        int     ghostx;   /* Number of ghost grid points in X-direction */
        int     ghosty;   /* Number of ghost grid points in Y-direction */
        int     px;       /* Processor index in the X-direction */
        int     py;       /* Processor index in the Y-direction */
        FLOAT   **grid;   /* Actual grid values */
        ....              /* other stuff that you need */
} GCgrid;

/* GridComm function prototypes */
extern int GCinit(int *,char ***);
extern int GCfinalize();
extern int GCpartitionGrid(int *,int *,...);
...

#endif

  ------------------------------------------------------------------------

The GridComm source files

The source directory will contain the routines GridComm uses. For example,
the routine GCinit.c might look like:

#include "GCinclude.h"

int GCinit_called = 0;
int GCbegan_MPI = 0;

/*@ GCinit - Initializes GridComm and MPI.  GCinit() calls
    MPI_Init() if it has not already been called.

    Input Parameters:
.   argc - count of number of command line arguments
.   args - the command line arguments

    Notes:
    If you want to call MPI_Init() separately, call it before
    GCinit().

.keywords: initialize, startup

.seealso: GCfinalize()

 @*/

int GCinit(int *argc,char ***args)
{
        int ierr, flag;

        /* check to see if GCinit has already been called */
        if (GCinit_called) return 0;

        /* Init MPI if not already done */
        MPI_Initialized(&flag);
        if (!flag) {
                ierr = MPI_Init(argc,args); CHKERRN(ierr);
                GCbegan_MPI = 1;
        }

        GCinit_called = 1;
        return(0);
}

  ------------------------------------------------------------------------

A program that uses the GridComm library

The whole idea is to help make writing programs easy. That means the user
interface and software must be:

   * Natural: orgainized so that it makes sense to users.
   * Functional: contains all the functionality that the user needs to
     implement what they want to implement.
   * Efficient: be an efficient implementation in terms of compuational
     speed and memory use.

An example of how a user's program to do relaxation on a grid might be:

#include "GCinclude.h"

int main(int argc, char **argv)
{
        GCgrid *grid;
        double **gridPtr;
        int globalStartIndex[2], globalEndIndex[2], procIndex[2];
        int localStartIndex[2], localEndIndex[2];
        int gridSize[2], ghostSize[2];

        /* Call GCinit() to initialize GridComm and MPI */
        GCinit(&argc,&argv);

        /* set global grid size in X and Y directions */
        gridSize[0] = 1000;
        gridSize[1] = 1000;

        /* set ghost point sizes in X and Y directions */
        ghostSize[0] = 1;
        ghostSize[1] = 1;

        /* Determine the partitioning parameters */
        GCpartitionGrid(gridSize, globalStartIndex, globalEndIndex, procIndex);

        /* Set up grid data structure, malloc space etc... */
        GCinitGrid(&grid, globalStartIndex, globalEndIndex, ghostIndex,
                   localStartIndex, localEndIndex);

        /* Get pointer to grid data */
        GCgetGridDataPtr(grid, &gridPtr);

        /* Outer relaxation loop */
        while (!done)  {
           for (i=localStartIndex[0]; i < localEndIndex[0]; i++) {
             for (j=localStartIndex[1]; j < localEndIndex[1]; j++) {
                gridPtr[i][j] = 0.25*(gridPtr[i-1][j] + ... );
             }
           }
           /* Do communication */
           GCupdateGrid(grid);
        }

        /* Finalize */
        GCfreeGrid(grid);
        GCfinalize();

}

  ------------------------------------------------------------------------

Back to top
