**********************************************************
** Description of the AMG-PETSc interface using the AMG **
** code developed by K. Stueben in the '90s (referred   **
** to by SAMG)                                          **
**********************************************************

* General description of the interface 
  There exist so-called the LEVEL 1 and the LEVEL 2 SAMG-PETSc interfaces. 
  In the LEVEL 1 interface SAMG is used as a user defined preconditioner. 
  SAMG is responsible for both the setup and solve phase, while PETSc can
  be used e.g. for the Krylov acceleration. In the LEVEL 2 interface SAMG is 
  only responsible for the setup phase. The solve phase is caried out by 
  PETSc's multigrid components. 

* Description of the LEVEL 1 interface 
  the Level 1 SAMG-PETSc interface has the following call tree: 

   int SamgShellPCCreate(SamgShellPC **shell)
   int SamgShellPCSetUp(SamgShellPC *shell, Mat pmat)
       int SamgGetParam(SAMG_PARAM *samg_param)
   int SamgShellPCApply(void *ctx, Vec r, Vec z)
   int SamgShellPCDestroy(SamgShellPC *shell)

  These routines are defined in samgpetsc.c. The contexts required by these 
  functions, i.e., SAMGPARAM and SamgShellPC are defined in samgfunc.h 
  anbd petscfunc.h respectively. 

* Description of the LEVEL 2 interface 
  the Level 2 SAMG-PETSc interface has the following call tree: 

  int SamgShellPCCreate(SamgShellPC **shell)
  int SamgShellPCSetUp(SamgShellPC *shell, Mat pmat)
      int SamgGetParam(SAMG_PARAM *samg_param)
  int SamgGetGrid(int levels, int numnodes, int numnonzero, 
			 GridCtx* grid, void* ctx); 
  [...PETSc multigrid routines...]
  int SamgShellPCDestroy(SamgShellPC *shell)

  The routine SamgGetGrid is defined in samgpetsctools.c. The context GridCtx 
  required by this routine is defined in petscfunc.h. The routine 
  SamgGetGrid passes the SAMG hierarchy to the PETSc data structure of type 
  GridCtx. It can broken up into following steps: 

  int SamgGetGrid(int levels, int numnodes, int numnonzero, 
			 GridCtx* grid, void* ctx); 
     int SamgGetCoarseMat(int level, int ia_shift, int ja_shift,
			  Mat* coarsemat, void* ctx);
	samggetdimmat_(...)
	samggetmat_(...)     
     int SamgGetInterpolation(int level, int iw_shift, int jw_shift,
			      Mat* interpolation, void* ctx) ;
	samggetdimint_(...)
	samggetdimmat_(...)
	samggetint_(...)

  Remarks: 
  ** The SamgGetCoarseMat and SamgGetInterpolation fetch the coarser grid 
  matrices and the interpolation operators from the SAMG common blocks. This 
  fetching is performed in two steps. 
  1) In the first steps the dimension of the coarse grid matrix and 
     interpolation operator are looked up in the common block (calls to 
     samggetdimmat and samggetdimint). The reason for calling a getdim routine 
     twice for the interpolation is that the interpolation is a rectangular 
     matrix, and the number of rows and collumns are looked up seperately. 
  2) Given the dimension of the matrices, PETSc allocates memory from them. 
     Having allocated the necessary memory, the matrix valued are fetched. 

  ** CAUTION: THERE IS A VERY TRICKY ROUTINE, CALLED appy_shift HIDDEN 
  IN SamgGetCoarseMat AND SamgGetInterpolation. The reason for it being 
  there is the following. The coarse grid matrices and the interpolation 
  operators on the consecutive levels in SAMG are stored continguously in 
  a long work array (like in the good old Fortran77 days). (SAMG inheritted 
  this structure from RAMG). The values of the ia and ja pointers in SAMG 
  are thus pointers in this large work array. In PETSc we would the ia and 
  ja pointers to be pointers in seperate data structures for each level. Only 
  then we can convert the tupple (a,ia,ja) into a PETSc matrix. The shifting 
  of pointers to global work array to pointers in local data structures is 
  done in the appy_shift routine. 

  ** The routine SamgCheckGalerkin was written for debugging purposes only. It 
  checks whether the SAMG hierarchy is parsed OK to the PETSc data structures 
  by checking whether A^H = I_h^H A^h I_H^h. The functions used in this 
  routine are defined in samgpetsctools.C. 

