int
hypre_SMGRelaxDestroy( void *relax_vdata )
{
   hypre_SMGRelaxData *relax_data = relax_vdata;
   int                 ierr = 0;

   if (relax_data)
   {
      hypre_TFree(relax_data -> space_indices);
      hypre_TFree(relax_data -> space_strides);
      hypre_TFree(relax_data -> pre_space_ranks);
      hypre_TFree(relax_data -> reg_space_ranks);
      hypre_BoxArrayDestroy(relax_data -> base_box_array);

      hypre_StructMatrixDestroy(relax_data -> A);
      hypre_StructVectorDestroy(relax_data -> b);
      hypre_StructVectorDestroy(relax_data -> x);

      hypre_SMGRelaxDestroyTempVec(relax_vdata);
      hypre_SMGRelaxDestroyARem(relax_vdata);
      hypre_SMGRelaxDestroyASol(relax_vdata);

      hypre_FinalizeTiming(relax_data -> time_index);
      hypre_TFree(relax_data);
   }

   return ierr;
}
int
hypre_PointRelaxDestroy( void *relax_vdata )
{
   hypre_PointRelaxData *relax_data = (hypre_PointRelaxData *)relax_vdata;
   int                   i;
   int                   ierr = 0;

   if (relax_data)
   {
      for (i = 0; i < (relax_data -> num_pointsets); i++)
      {
         hypre_TFree(relax_data -> pointset_indices[i]);
         hypre_ComputePkgDestroy(relax_data -> compute_pkgs[i]);
      }
      hypre_TFree(relax_data -> pointset_sizes);
      hypre_TFree(relax_data -> pointset_ranks);
      hypre_TFree(relax_data -> pointset_strides);
      hypre_TFree(relax_data -> pointset_indices);
      hypre_StructMatrixDestroy(relax_data -> A);
      hypre_StructVectorDestroy(relax_data -> b);
      hypre_StructVectorDestroy(relax_data -> x);
      hypre_TFree(relax_data -> compute_pkgs);
      hypre_StructVectorDestroy(relax_data -> t);

      hypre_FinalizeTiming(relax_data -> time_index);
      hypre_TFree(relax_data);
   }

   return ierr;
}
int
hypre_SMGRelaxDestroyASol( void *relax_vdata )
{
   hypre_SMGRelaxData  *relax_data = relax_vdata;
   int                  stencil_dim;
   int                  i;
   int                  ierr = 0;

   if (relax_data -> A_sol)
   {
      stencil_dim = (relax_data -> stencil_dim);
      for (i = 0; i < (relax_data -> num_spaces); i++)
      {
         if (stencil_dim > 2)
            hypre_SMGDestroy(relax_data -> solve_data[i]);
         else
            hypre_CyclicReductionDestroy(relax_data -> solve_data[i]);
      }
      hypre_TFree(relax_data -> solve_data);
      hypre_StructMatrixDestroy(relax_data -> A_sol);
      (relax_data -> A_sol) = NULL;
   }
   (relax_data -> setup_a_sol) = 1;

   return ierr;
}
int hypre_SMGResidualDestroy(void *residual_vdata)
{
  int ierr = 0;
  hypre_SMGResidualData *residual_data = residual_vdata;
  if (residual_data != (0)) {
    hypre_StructMatrixDestroy((residual_data -> A));
    hypre_StructVectorDestroy((residual_data -> x));
    hypre_StructVectorDestroy((residual_data -> b));
    hypre_StructVectorDestroy((residual_data -> r));
    hypre_BoxArrayDestroy((residual_data -> base_points));
    hypre_ComputePkgDestroy((residual_data -> compute_pkg));
    hypre_FinalizeTiming((residual_data -> time_index));
    (hypre_Free(((char *)residual_data)) , (residual_data = ((0))));
  }
  return ierr;
}
Esempio n. 5
0
int
hypre_SStructPMatrixDestroy( hypre_SStructPMatrix *pmatrix )
{
    hypre_SStructStencil  **stencils;
    int                     nvars;
    int                   **smaps;
    hypre_StructStencil  ***sstencils;
    hypre_StructMatrix   ***smatrices;
    int                   **symmetric;
    int                     vi, vj;

    if (pmatrix)
    {
        hypre_SStructPMatrixRefCount(pmatrix) --;
        if (hypre_SStructPMatrixRefCount(pmatrix) == 0)
        {
            stencils  = hypre_SStructPMatrixStencils(pmatrix);
            nvars     = hypre_SStructPMatrixNVars(pmatrix);
            smaps     = hypre_SStructPMatrixSMaps(pmatrix);
            sstencils = hypre_SStructPMatrixSStencils(pmatrix);
            smatrices = hypre_SStructPMatrixSMatrices(pmatrix);
            symmetric = hypre_SStructPMatrixSymmetric(pmatrix);
            for (vi = 0; vi < nvars; vi++)
            {
                HYPRE_SStructStencilDestroy(stencils[vi]);
                hypre_TFree(smaps[vi]);
                for (vj = 0; vj < nvars; vj++)
                {
                    hypre_StructStencilDestroy(sstencils[vi][vj]);
                    hypre_StructMatrixDestroy(smatrices[vi][vj]);
                }
                hypre_TFree(sstencils[vi]);
                hypre_TFree(smatrices[vi]);
                hypre_TFree(symmetric[vi]);
            }
            hypre_TFree(stencils);
            hypre_TFree(smaps);
            hypre_TFree(sstencils);
            hypre_TFree(smatrices);
            hypre_TFree(symmetric);
            hypre_TFree(hypre_SStructPMatrixSEntries(pmatrix));
            hypre_TFree(pmatrix);
        }
    }

    return hypre_error_flag;
}
int
hypre_SMGRelaxDestroyARem( void *relax_vdata )
{
   hypre_SMGRelaxData  *relax_data = relax_vdata;
   int                  i;
   int                  ierr = 0;

   if (relax_data -> A_rem)
   {
      for (i = 0; i < (relax_data -> num_spaces); i++)
      {
         hypre_SMGResidualDestroy(relax_data -> residual_data[i]);
      }
      hypre_TFree(relax_data -> residual_data);
      hypre_StructMatrixDestroy(relax_data -> A_rem);
      (relax_data -> A_rem) = NULL;
   }
   (relax_data -> setup_a_rem) = 1;

   return ierr;
}
Esempio n. 7
0
HYPRE_Int
hypre_SparseMSGDestroy( void *smsg_vdata )
{
   HYPRE_Int ierr = 0;

/* RDF */
#if 0
   hypre_SparseMSGData *smsg_data = smsg_vdata;

   HYPRE_Int fi, l;

   if (smsg_data)
   {
      if ((smsg_data -> logging) > 0)
      {
         hypre_TFree(smsg_data -> norms);
         hypre_TFree(smsg_data -> rel_norms);
      }

      if ((smsg_data -> num_levels) > 1)
      {
         for (fi = 0; fi < (smsg_data -> num_all_grids); fi++)
         {
            hypre_PFMGRelaxDestroy(smsg_data -> relax_array[fi]);
            hypre_StructMatvecDestroy(smsg_data -> matvec_array[fi]);
            hypre_SemiRestrictDestroy(smsg_data -> restrictx_array[fi]);
            hypre_SemiRestrictDestroy(smsg_data -> restricty_array[fi]);
            hypre_SemiRestrictDestroy(smsg_data -> restrictz_array[fi]);
            hypre_SemiInterpDestroy(smsg_data -> interpx_array[fi]);
            hypre_SemiInterpDestroy(smsg_data -> interpy_array[fi]);
            hypre_SemiInterpDestroy(smsg_data -> interpz_array[fi]);
            hypre_StructMatrixDestroy(smsg_data -> A_array[fi]);
            hypre_StructVectorDestroy(smsg_data -> b_array[fi]);
            hypre_StructVectorDestroy(smsg_data -> x_array[fi]);
            hypre_StructVectorDestroy(smsg_data -> t_array[fi]);
            hypre_StructVectorDestroy(smsg_data -> r_array[fi]);
            hypre_StructVectorDestroy(smsg_data -> visitx_array[fi]);
            hypre_StructVectorDestroy(smsg_data -> visity_array[fi]);
            hypre_StructVectorDestroy(smsg_data -> visitz_array[fi]);
            hypre_StructGridDestroy(smsg_data -> grid_array[fi]);
         }

         for (l = 0; l < (smsg_data -> num_grids[0]) - 1; l++)
         {
            hypre_StructMatrixDestroy(smsg_data -> Px_array[l]);
            hypre_StructGridDestroy(smsg_data -> Px_grid_array[l]); 
         }
         for (l = 0; l < (smsg_data -> num_grids[1]) - 1; l++)
         {
            hypre_StructMatrixDestroy(smsg_data -> Py_array[l]);
            hypre_StructGridDestroy(smsg_data -> Py_grid_array[l]); 
         }
         for (l = 0; l < (smsg_data -> num_grids[2]) - 1; l++)
         {
            hypre_StructMatrixDestroy(smsg_data -> Pz_array[l]);
            hypre_StructGridDestroy(smsg_data -> Pz_grid_array[l]); 
         }

         hypre_SharedTFree(smsg_data -> data);

         hypre_TFree(smsg_data -> relax_array);
         hypre_TFree(smsg_data -> matvec_array);
         hypre_TFree(smsg_data -> restrictx_array);
         hypre_TFree(smsg_data -> restricty_array);
         hypre_TFree(smsg_data -> restrictz_array);
         hypre_TFree(smsg_data -> interpx_array);
         hypre_TFree(smsg_data -> interpy_array);
         hypre_TFree(smsg_data -> interpz_array);
         hypre_TFree(smsg_data -> A_array);
         hypre_TFree(smsg_data -> Px_array);
         hypre_TFree(smsg_data -> Py_array);
         hypre_TFree(smsg_data -> Pz_array);
         hypre_TFree(smsg_data -> RTx_array);
         hypre_TFree(smsg_data -> RTy_array);
         hypre_TFree(smsg_data -> RTz_array);
         hypre_TFree(smsg_data -> b_array);
         hypre_TFree(smsg_data -> x_array);
         hypre_TFree(smsg_data -> t_array);
         hypre_TFree(smsg_data -> r_array);
         hypre_TFree(smsg_data -> grid_array);
         hypre_TFree(smsg_data -> Px_grid_array);
         hypre_TFree(smsg_data -> Py_grid_array);
         hypre_TFree(smsg_data -> Pz_grid_array);
      }
 
      hypre_FinalizeTiming(smsg_data -> time_index);
      hypre_TFree(smsg_data);
   }
#endif
/* RDF */

   return ierr;
}
int
hypre_PointRelax( void               *relax_vdata,
                  hypre_StructMatrix *A,
                  hypre_StructVector *b,
                  hypre_StructVector *x           )
{
   hypre_PointRelaxData *relax_data = (hypre_PointRelaxData *)relax_vdata;

   int                    max_iter         = (relax_data -> max_iter);
   int                    zero_guess       = (relax_data -> zero_guess);
   double                 weight           = (relax_data -> weight);
   int                    num_pointsets    = (relax_data -> num_pointsets);
   int                   *pointset_ranks   = (relax_data -> pointset_ranks);
   hypre_Index           *pointset_strides = (relax_data -> pointset_strides);
   hypre_StructVector    *t                = (relax_data -> t);
   int                    diag_rank        = (relax_data -> diag_rank);
   hypre_ComputePkg     **compute_pkgs     = (relax_data -> compute_pkgs);

   hypre_ComputePkg      *compute_pkg;
   hypre_CommHandle      *comm_handle;
                        
   hypre_BoxArrayArray   *compute_box_aa;
   hypre_BoxArray        *compute_box_a;
   hypre_Box             *compute_box;
                        
   hypre_Box             *A_data_box;
   hypre_Box             *b_data_box;
   hypre_Box             *x_data_box;
   hypre_Box             *t_data_box;
                        
   int                    Ai;
   int                    bi;
   int                    xi;
   int                    ti;
                        
   double                *Ap;
   double                *bp;
   double                *xp;
   double                *tp;
                        
   hypre_IndexRef         stride;
   hypre_IndexRef         start;
   hypre_Index            loop_size;
                        
   hypre_StructStencil   *stencil;
   hypre_Index           *stencil_shape;
   int                    stencil_size;
                        
   int                    iter, p, compute_i, i, j, si;
   int                    loopi, loopj, loopk;
   int                    pointset;

   int                    ierr = 0;

   /*----------------------------------------------------------
    * Initialize some things and deal with special cases
    *----------------------------------------------------------*/

   hypre_BeginTiming(relax_data -> time_index);

   hypre_StructMatrixDestroy(relax_data -> A);
   hypre_StructVectorDestroy(relax_data -> b);
   hypre_StructVectorDestroy(relax_data -> x);
   (relax_data -> A) = hypre_StructMatrixRef(A);
   (relax_data -> x) = hypre_StructVectorRef(x);
   (relax_data -> b) = hypre_StructVectorRef(b);

   (relax_data -> num_iterations) = 0;

   /* if max_iter is zero, return */
   if (max_iter == 0)
   {
      /* if using a zero initial guess, return zero */
      if (zero_guess)
      {
         hypre_StructVectorSetConstantValues(x, 0.0);
      }

      hypre_EndTiming(relax_data -> time_index);
      return ierr;
   }

   stencil       = hypre_StructMatrixStencil(A);
   stencil_shape = hypre_StructStencilShape(stencil);
   stencil_size  = hypre_StructStencilSize(stencil);

   /*----------------------------------------------------------
    * Do zero_guess iteration
    *----------------------------------------------------------*/

   p    = 0;
   iter = 0;

   if (zero_guess)
   {
      pointset = pointset_ranks[p];
      compute_pkg = compute_pkgs[pointset];
      stride = pointset_strides[pointset];

      for (compute_i = 0; compute_i < 2; compute_i++)
      {
         switch(compute_i)
         {
            case 0:
            {
               compute_box_aa = hypre_ComputePkgIndtBoxes(compute_pkg);
            }
            break;

            case 1:
            {
               compute_box_aa = hypre_ComputePkgDeptBoxes(compute_pkg);
            }
            break;
         }

         hypre_ForBoxArrayI(i, compute_box_aa)
            {
               compute_box_a = hypre_BoxArrayArrayBoxArray(compute_box_aa, i);

               A_data_box =
                  hypre_BoxArrayBox(hypre_StructMatrixDataSpace(A), i);
               b_data_box =
                  hypre_BoxArrayBox(hypre_StructVectorDataSpace(b), i);
               x_data_box =
                  hypre_BoxArrayBox(hypre_StructVectorDataSpace(x), i);

               Ap = hypre_StructMatrixBoxData(A, i, diag_rank);
               bp = hypre_StructVectorBoxData(b, i);
               xp = hypre_StructVectorBoxData(x, i);

               hypre_ForBoxI(j, compute_box_a)
                  {
                     compute_box = hypre_BoxArrayBox(compute_box_a, j);

                     start  = hypre_BoxIMin(compute_box);
                     hypre_BoxGetStrideSize(compute_box, stride, loop_size);

                     hypre_BoxLoop3Begin(loop_size,
                                         A_data_box, start, stride, Ai,
                                         b_data_box, start, stride, bi,
                                         x_data_box, start, stride, xi);
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,Ai,bi,xi
#include "hypre_box_smp_forloop.h"
                     hypre_BoxLoop3For(loopi, loopj, loopk, Ai, bi, xi)
                        {
                           xp[xi] = bp[bi] / Ap[Ai];
                        }
                     hypre_BoxLoop3End(Ai, bi, xi);
                  }
            }
      }
Esempio n. 9
0
hypre_SStructPMatrix *
hypre_SysPFMGCreateRAPOp( hypre_SStructPMatrix *R,
                          hypre_SStructPMatrix *A,
                          hypre_SStructPMatrix *P,
                          hypre_SStructPGrid   *coarse_grid,
                          HYPRE_Int             cdir        )
{
    hypre_SStructPMatrix    *RAP;
    HYPRE_Int                ndim;
    HYPRE_Int                nvars;
    hypre_SStructVariable    vartype;

    hypre_SStructStencil **RAP_stencils;

    hypre_StructMatrix    *RAP_s;
    hypre_StructMatrix    *R_s;
    hypre_StructMatrix    *A_s;
    hypre_StructMatrix    *P_s;

    hypre_Index          **RAP_shapes;

    hypre_StructStencil   *sstencil;
    hypre_Index           *shape;
    HYPRE_Int              s;
    HYPRE_Int             *sstencil_sizes;

    HYPRE_Int              stencil_size;

    hypre_StructGrid      *cgrid;

    HYPRE_Int              vi,vj;

    HYPRE_Int              sten_cntr;

    HYPRE_Int              P_stored_as_transpose = 0;

    ndim = hypre_StructStencilDim(hypre_SStructPMatrixSStencil(A, 0, 0));
    nvars = hypre_SStructPMatrixNVars(A);

    vartype = hypre_SStructPGridVarType(coarse_grid, 0);
    cgrid = hypre_SStructPGridVTSGrid(coarse_grid, vartype);

    RAP_stencils = hypre_CTAlloc(hypre_SStructStencil *, nvars);

    RAP_shapes = hypre_CTAlloc(hypre_Index *, nvars);
    sstencil_sizes = hypre_CTAlloc(HYPRE_Int, nvars);

    /*--------------------------------------------------------------------------
     * Symmetry within a block is exploited, but not symmetry of the form
     * A_{vi,vj} = A_{vj,vi}^T.
     *--------------------------------------------------------------------------*/

    for (vi = 0; vi < nvars; vi++)
    {
        R_s = hypre_SStructPMatrixSMatrix(R, vi, vi);
        stencil_size = 0;
        for (vj = 0; vj < nvars; vj++)
        {
            A_s = hypre_SStructPMatrixSMatrix(A, vi, vj);
            P_s = hypre_SStructPMatrixSMatrix(P, vj, vj);
            sstencil_sizes[vj] = 0;
            if (A_s != NULL)
            {
                RAP_s = hypre_SemiCreateRAPOp(R_s, A_s, P_s,
                                              cgrid, cdir,
                                              P_stored_as_transpose);
                /* Just want stencil for RAP */
                hypre_StructMatrixInitializeShell(RAP_s);
                sstencil = hypre_StructMatrixStencil(RAP_s);
                shape = hypre_StructStencilShape(sstencil);
                sstencil_sizes[vj] = hypre_StructStencilSize(sstencil);
                stencil_size += sstencil_sizes[vj];
                RAP_shapes[vj] = hypre_CTAlloc(hypre_Index,
                                               sstencil_sizes[vj]);
                for (s = 0; s < sstencil_sizes[vj]; s++)
                {
                    hypre_CopyIndex(shape[s],RAP_shapes[vj][s]);
                }
                hypre_StructMatrixDestroy(RAP_s);
            }
        }

        HYPRE_SStructStencilCreate(ndim, stencil_size, &RAP_stencils[vi]);
        sten_cntr = 0;
        for (vj = 0; vj < nvars; vj++)
        {
            if (sstencil_sizes[vj] > 0)
            {
                for (s = 0; s < sstencil_sizes[vj]; s++)
                {
                    HYPRE_SStructStencilSetEntry(RAP_stencils[vi],
                                                 sten_cntr, RAP_shapes[vj][s], vj);
                    sten_cntr++;
                }
                hypre_TFree(RAP_shapes[vj]);
            }
        }
    }

    /* create RAP Pmatrix */
    hypre_SStructPMatrixCreate(hypre_SStructPMatrixComm(A),
                               coarse_grid, RAP_stencils, &RAP);

    hypre_TFree(RAP_shapes);
    hypre_TFree(sstencil_sizes);

    return RAP;
}
Esempio n. 10
0
HYPRE_Int
hypre_SMGSolve( void               *smg_vdata,
                hypre_StructMatrix *A,
                hypre_StructVector *b,
                hypre_StructVector *x         )
{

   hypre_SMGData        *smg_data = smg_vdata;

   double                tol             = (smg_data -> tol);
   HYPRE_Int             max_iter        = (smg_data -> max_iter);
   HYPRE_Int             rel_change      = (smg_data -> rel_change);
   HYPRE_Int             zero_guess      = (smg_data -> zero_guess);
   HYPRE_Int             num_levels      = (smg_data -> num_levels);
   HYPRE_Int             num_pre_relax   = (smg_data -> num_pre_relax);
   HYPRE_Int             num_post_relax  = (smg_data -> num_post_relax);
   hypre_IndexRef        base_index      = (smg_data -> base_index);
   hypre_IndexRef        base_stride     = (smg_data -> base_stride);
   hypre_StructMatrix  **A_l             = (smg_data -> A_l);
   hypre_StructMatrix  **PT_l            = (smg_data -> PT_l);
   hypre_StructMatrix  **R_l             = (smg_data -> R_l);
   hypre_StructVector  **b_l             = (smg_data -> b_l);
   hypre_StructVector  **x_l             = (smg_data -> x_l);
   hypre_StructVector  **r_l             = (smg_data -> r_l);
   hypre_StructVector  **e_l             = (smg_data -> e_l);
   void                **relax_data_l    = (smg_data -> relax_data_l);
   void                **residual_data_l = (smg_data -> residual_data_l);
   void                **restrict_data_l = (smg_data -> restrict_data_l);
   void                **interp_data_l   = (smg_data -> interp_data_l);
   HYPRE_Int             logging         = (smg_data -> logging);
   double               *norms           = (smg_data -> norms);
   double               *rel_norms       = (smg_data -> rel_norms);

   double                b_dot_b = 0, r_dot_r, eps = 0;
   double                e_dot_e = 0, x_dot_x = 1;
                    
   HYPRE_Int             i, l;
                    
#if DEBUG
   char                  filename[255];
#endif

   /*-----------------------------------------------------
    * Initialize some things and deal with special cases
    *-----------------------------------------------------*/

   hypre_BeginTiming(smg_data -> time_index);

   hypre_StructMatrixDestroy(A_l[0]);
   hypre_StructVectorDestroy(b_l[0]);
   hypre_StructVectorDestroy(x_l[0]);
   A_l[0] = hypre_StructMatrixRef(A);
   b_l[0] = hypre_StructVectorRef(b);
   x_l[0] = hypre_StructVectorRef(x);

   (smg_data -> num_iterations) = 0;

   /* if max_iter is zero, return */
   if (max_iter == 0)
   {
      /* if using a zero initial guess, return zero */
      if (zero_guess)
      {
         hypre_StructVectorSetConstantValues(x, 0.0);
      }

      hypre_EndTiming(smg_data -> time_index);
      return hypre_error_flag;
   }

   /* part of convergence check */
   if (tol > 0.0)
   {
      /* eps = (tol^2) */
      b_dot_b = hypre_StructInnerProd(b_l[0], b_l[0]);
      eps = tol*tol;

      /* if rhs is zero, return a zero solution */
      if (b_dot_b == 0.0)
      {
         hypre_StructVectorSetConstantValues(x, 0.0);
         if (logging > 0)
         {
            norms[0]     = 0.0;
            rel_norms[0] = 0.0;
         }

         hypre_EndTiming(smg_data -> time_index);
         return hypre_error_flag;
      }
   }

   /*-----------------------------------------------------
    * Do V-cycles:
    *   For each index l, "fine" = l, "coarse" = (l+1)
    *-----------------------------------------------------*/

   for (i = 0; i < max_iter; i++)
   {
      /*--------------------------------------------------
       * Down cycle
       *--------------------------------------------------*/

      /* fine grid pre-relaxation */
      if (num_levels > 1)
      {
         hypre_SMGRelaxSetRegSpaceRank(relax_data_l[0], 0, 0);
         hypre_SMGRelaxSetRegSpaceRank(relax_data_l[0], 1, 1);
      }
      hypre_SMGRelaxSetMaxIter(relax_data_l[0], num_pre_relax);
      hypre_SMGRelaxSetZeroGuess(relax_data_l[0], zero_guess);
      hypre_SMGRelax(relax_data_l[0], A_l[0], b_l[0], x_l[0]);
      zero_guess = 0;

      /* compute fine grid residual (b - Ax) */
      hypre_SMGResidual(residual_data_l[0], A_l[0], x_l[0], b_l[0], r_l[0]);

      /* convergence check */
      if (tol > 0.0)
      {
         r_dot_r = hypre_StructInnerProd(r_l[0], r_l[0]);

         if (logging > 0)
         {
            norms[i] = sqrt(r_dot_r);
            if (b_dot_b > 0)
               rel_norms[i] = sqrt(r_dot_r/b_dot_b);
            else
               rel_norms[i] = 0.0;
         }

         /* always do at least 1 V-cycle */
         if ((r_dot_r/b_dot_b < eps) && (i > 0))
         {
            if (rel_change)
            {
               if ((e_dot_e/x_dot_x) < eps)
                  break;
            }
            else
            {
               break;
            }
         }
      }

      if (num_levels > 1)
      {
         /* restrict fine grid residual */
         hypre_SemiRestrict(restrict_data_l[0], R_l[0], r_l[0], b_l[1]);
#if DEBUG
         if(hypre_StructStencilDim(hypre_StructMatrixStencil(A)) == 3)
         {
            hypre_sprintf(filename, "zout_xdown.%02d", 0);
            hypre_StructVectorPrint(filename, x_l[0], 0);
            hypre_sprintf(filename, "zout_rdown.%02d", 0);
            hypre_StructVectorPrint(filename, r_l[0], 0);
            hypre_sprintf(filename, "zout_b.%02d", 1);
            hypre_StructVectorPrint(filename, b_l[1], 0);
         }
#endif
         for (l = 1; l <= (num_levels - 2); l++)
         {
            /* pre-relaxation */
            hypre_SMGRelaxSetRegSpaceRank(relax_data_l[l], 0, 0);
            hypre_SMGRelaxSetRegSpaceRank(relax_data_l[l], 1, 1);
            hypre_SMGRelaxSetMaxIter(relax_data_l[l], num_pre_relax);
            hypre_SMGRelaxSetZeroGuess(relax_data_l[l], 1);
            hypre_SMGRelax(relax_data_l[l], A_l[l], b_l[l], x_l[l]);

            /* compute residual (b - Ax) */
            hypre_SMGResidual(residual_data_l[l],
                              A_l[l], x_l[l], b_l[l], r_l[l]);

            /* restrict residual */
            hypre_SemiRestrict(restrict_data_l[l], R_l[l], r_l[l], b_l[l+1]);
#if DEBUG
            if(hypre_StructStencilDim(hypre_StructMatrixStencil(A)) == 3)
            {
               hypre_sprintf(filename, "zout_xdown.%02d", l);
               hypre_StructVectorPrint(filename, x_l[l], 0);
               hypre_sprintf(filename, "zout_rdown.%02d", l);
               hypre_StructVectorPrint(filename, r_l[l], 0);
               hypre_sprintf(filename, "zout_b.%02d", l+1);
               hypre_StructVectorPrint(filename, b_l[l+1], 0);
            }
#endif
         }

         /*--------------------------------------------------
          * Bottom
          *--------------------------------------------------*/

         hypre_SMGRelaxSetZeroGuess(relax_data_l[l], 1);
         hypre_SMGRelax(relax_data_l[l], A_l[l], b_l[l], x_l[l]);
#if DEBUG
         if(hypre_StructStencilDim(hypre_StructMatrixStencil(A)) == 3)
         {
            hypre_sprintf(filename, "zout_xbottom.%02d", l);
            hypre_StructVectorPrint(filename, x_l[l], 0);
         }
#endif

         /*--------------------------------------------------
          * Up cycle
          *--------------------------------------------------*/

         for (l = (num_levels - 2); l >= 1; l--)
         {
            /* interpolate error and correct (x = x + Pe_c) */
            hypre_SemiInterp(interp_data_l[l], PT_l[l], x_l[l+1], e_l[l]);
            hypre_StructAxpy(1.0, e_l[l], x_l[l]);
#if DEBUG
            if(hypre_StructStencilDim(hypre_StructMatrixStencil(A)) == 3)
            {
               hypre_sprintf(filename, "zout_eup.%02d", l);
               hypre_StructVectorPrint(filename, e_l[l], 0);
               hypre_sprintf(filename, "zout_xup.%02d", l);
               hypre_StructVectorPrint(filename, x_l[l], 0);
            }
#endif
            /* post-relaxation */
            hypre_SMGRelaxSetRegSpaceRank(relax_data_l[l], 0, 1);
            hypre_SMGRelaxSetRegSpaceRank(relax_data_l[l], 1, 0);
            hypre_SMGRelaxSetMaxIter(relax_data_l[l], num_post_relax);
            hypre_SMGRelaxSetZeroGuess(relax_data_l[l], 0);
            hypre_SMGRelax(relax_data_l[l], A_l[l], b_l[l], x_l[l]);
         }

         /* interpolate error and correct on fine grid (x = x + Pe_c) */
         hypre_SemiInterp(interp_data_l[0], PT_l[0], x_l[1], e_l[0]);
         hypre_SMGAxpy(1.0, e_l[0], x_l[0], base_index, base_stride);
#if DEBUG
         if(hypre_StructStencilDim(hypre_StructMatrixStencil(A)) == 3)
         {
            hypre_sprintf(filename, "zout_eup.%02d", 0);
            hypre_StructVectorPrint(filename, e_l[0], 0);
            hypre_sprintf(filename, "zout_xup.%02d", 0);
            hypre_StructVectorPrint(filename, x_l[0], 0);
         }
#endif
      }

      /* part of convergence check */
      if ((tol > 0.0) && (rel_change))
      {
         if (num_levels > 1)
         {
            e_dot_e = hypre_StructInnerProd(e_l[0], e_l[0]);
            x_dot_x = hypre_StructInnerProd(x_l[0], x_l[0]);
         }
         else
         {
            e_dot_e = 0.0;
            x_dot_x = 1.0;
         }
      }

      /* fine grid post-relaxation */
      if (num_levels > 1)
      {
         hypre_SMGRelaxSetRegSpaceRank(relax_data_l[0], 0, 1);
         hypre_SMGRelaxSetRegSpaceRank(relax_data_l[0], 1, 0);
      }
      hypre_SMGRelaxSetMaxIter(relax_data_l[0], num_post_relax);
      hypre_SMGRelaxSetZeroGuess(relax_data_l[0], 0);
      hypre_SMGRelax(relax_data_l[0], A_l[0], b_l[0], x_l[0]);

      (smg_data -> num_iterations) = (i + 1);
   }

   hypre_EndTiming(smg_data -> time_index);

   return hypre_error_flag;
}
Esempio n. 11
0
int 
HYPRE_StructMatrixDestroy( HYPRE_StructMatrix matrix )
{
   return( hypre_StructMatrixDestroy(matrix) );
}
int
hypre_SMGRelaxSetup( void               *relax_vdata,
                     hypre_StructMatrix *A,
                     hypre_StructVector *b,
                     hypre_StructVector *x           )
{
   hypre_SMGRelaxData  *relax_data = relax_vdata;
   int                  stencil_dim;
   int                  a_sol_test;
   int                  ierr = 0;

   stencil_dim = hypre_StructStencilDim(hypre_StructMatrixStencil(A));
   (relax_data -> stencil_dim) = stencil_dim;
   hypre_StructMatrixDestroy(relax_data -> A);
   hypre_StructVectorDestroy(relax_data -> b);
   hypre_StructVectorDestroy(relax_data -> x);
   (relax_data -> A) = hypre_StructMatrixRef(A);
   (relax_data -> b) = hypre_StructVectorRef(b);
   (relax_data -> x) = hypre_StructVectorRef(x);

   /*----------------------------------------------------------
    * Set up memory according to memory_use parameter.
    *
    * If a subset of the solver memory is not to be set up
    * until the solve is actually done, it's "setup" tag
    * should have a value greater than 1.
    *----------------------------------------------------------*/

   if ((stencil_dim - 1) <= (relax_data -> memory_use))
   {
      a_sol_test = 1;
   }
   else
   {
      a_sol_test = 0;
   }

   /*----------------------------------------------------------
    * Set up the solver
    *----------------------------------------------------------*/

   if ((relax_data -> setup_temp_vec) > 0)
   {
      ierr = hypre_SMGRelaxSetupTempVec(relax_vdata, A, b, x);
   }

   if ((relax_data -> setup_a_rem) > 0)
   {
      ierr = hypre_SMGRelaxSetupARem(relax_vdata, A, b, x);
   }

   if ((relax_data -> setup_a_sol) > a_sol_test)
   {
      ierr = hypre_SMGRelaxSetupASol(relax_vdata, A, b, x);
   }

   if ((relax_data -> base_box_array) == NULL)
   {
      ierr = hypre_SMGRelaxSetupBaseBoxArray(relax_vdata, A, b, x);
   }
   

   return ierr;
}
Esempio n. 13
0
int
hypre_SMGDestroy( void *smg_vdata )
{
   hypre_SMGData *smg_data = smg_vdata;

   int l;
   int ierr = 0;

   if (smg_data)
   {
      if ((smg_data -> logging) > 0)
      {
         hypre_TFree(smg_data -> norms);
         hypre_TFree(smg_data -> rel_norms);
      }

      if ((smg_data -> num_levels) > -1)
      {
         for (l = 0; l < ((smg_data -> num_levels) - 1); l++)
         {
            hypre_SMGRelaxDestroy(smg_data -> relax_data_l[l]);
            hypre_SMGResidualDestroy(smg_data -> residual_data_l[l]);
            hypre_SemiRestrictDestroy(smg_data -> restrict_data_l[l]);
            hypre_SemiInterpDestroy(smg_data -> interp_data_l[l]);
         }
         hypre_SMGRelaxDestroy(smg_data -> relax_data_l[l]);
         if (l == 0)
         {
            hypre_SMGResidualDestroy(smg_data -> residual_data_l[l]);
         }
         hypre_TFree(smg_data -> relax_data_l);
         hypre_TFree(smg_data -> residual_data_l);
         hypre_TFree(smg_data -> restrict_data_l);
         hypre_TFree(smg_data -> interp_data_l);
 
         hypre_StructVectorDestroy(smg_data -> tb_l[0]);
         hypre_StructVectorDestroy(smg_data -> tx_l[0]);
         hypre_StructGridDestroy(smg_data -> grid_l[0]);
         hypre_StructMatrixDestroy(smg_data -> A_l[0]);
         hypre_StructVectorDestroy(smg_data -> b_l[0]);
         hypre_StructVectorDestroy(smg_data -> x_l[0]);
         for (l = 0; l < ((smg_data -> num_levels) - 1); l++)
         {
            hypre_StructGridDestroy(smg_data -> grid_l[l+1]);
            hypre_StructGridDestroy(smg_data -> PT_grid_l[l+1]);
            hypre_StructMatrixDestroy(smg_data -> A_l[l+1]);
            if (smg_data -> PT_l[l] == smg_data -> R_l[l])
            {
               hypre_StructMatrixDestroy(smg_data -> PT_l[l]);
            }
            else
            {
               hypre_StructMatrixDestroy(smg_data -> PT_l[l]);
               hypre_StructMatrixDestroy(smg_data -> R_l[l]);
            }
            hypre_StructVectorDestroy(smg_data -> b_l[l+1]);
            hypre_StructVectorDestroy(smg_data -> x_l[l+1]);
            hypre_StructVectorDestroy(smg_data -> tb_l[l+1]);
            hypre_StructVectorDestroy(smg_data -> tx_l[l+1]);
         }
         hypre_SharedTFree(smg_data -> data);
         hypre_TFree(smg_data -> grid_l);
         hypre_TFree(smg_data -> PT_grid_l);
         hypre_TFree(smg_data -> A_l);
         hypre_TFree(smg_data -> PT_l);
         hypre_TFree(smg_data -> R_l);
         hypre_TFree(smg_data -> b_l);
         hypre_TFree(smg_data -> x_l);
         hypre_TFree(smg_data -> tb_l);
         hypre_TFree(smg_data -> tx_l);
      }
 
      hypre_FinalizeTiming(smg_data -> time_index);
      hypre_TFree(smg_data);
   }

   return(ierr);
}
Esempio n. 14
0
HYPRE_Int
hypre_SparseMSGSolve( void               *smsg_vdata,
                      hypre_StructMatrix *A,
                      hypre_StructVector *b,
                      hypre_StructVector *x          )
{
   hypre_SparseMSGData  *smsg_data = smsg_vdata;

   HYPRE_Real            tol                 = (smsg_data -> tol);
   HYPRE_Int             max_iter            = (smsg_data -> max_iter);
   HYPRE_Int             rel_change          = (smsg_data -> rel_change);
   HYPRE_Int             zero_guess          = (smsg_data -> zero_guess);
   HYPRE_Int             jump                = (smsg_data -> jump);
   HYPRE_Int             num_pre_relax       = (smsg_data -> num_pre_relax);
   HYPRE_Int             num_post_relax      = (smsg_data -> num_post_relax);
   HYPRE_Int             num_fine_relax      = (smsg_data -> num_fine_relax);
   HYPRE_Int            *num_grids           = (smsg_data -> num_grids);
   HYPRE_Int             num_all_grids       = (smsg_data -> num_all_grids);
   HYPRE_Int             num_levels          = (smsg_data -> num_levels);
   hypre_StructMatrix  **A_array             = (smsg_data -> A_array);
   hypre_StructMatrix  **Px_array            = (smsg_data -> Px_array);
   hypre_StructMatrix  **Py_array            = (smsg_data -> Py_array);
   hypre_StructMatrix  **Pz_array            = (smsg_data -> Pz_array);
   hypre_StructMatrix  **RTx_array           = (smsg_data -> RTx_array);
   hypre_StructMatrix  **RTy_array           = (smsg_data -> RTy_array);
   hypre_StructMatrix  **RTz_array           = (smsg_data -> RTz_array);
   hypre_StructVector  **b_array             = (smsg_data -> b_array);
   hypre_StructVector  **x_array             = (smsg_data -> x_array);
   hypre_StructVector  **t_array             = (smsg_data -> t_array);
   hypre_StructVector  **r_array             = (smsg_data -> r_array);
   hypre_StructVector  **e_array             = (smsg_data -> e_array);
   hypre_StructVector  **visitx_array        = (smsg_data -> visitx_array);
   hypre_StructVector  **visity_array        = (smsg_data -> visity_array);
   hypre_StructVector  **visitz_array        = (smsg_data -> visitz_array);
   HYPRE_Int            *grid_on             = (smsg_data -> grid_on);
   void                **relax_array         = (smsg_data -> relax_array);
   void                **matvec_array        = (smsg_data -> matvec_array);
   void                **restrictx_array     = (smsg_data -> restrictx_array);
   void                **restricty_array     = (smsg_data -> restricty_array);
   void                **restrictz_array     = (smsg_data -> restrictz_array);
   void                **interpx_array       = (smsg_data -> interpx_array);
   void                **interpy_array       = (smsg_data -> interpy_array);
   void                **interpz_array       = (smsg_data -> interpz_array);
   HYPRE_Int             logging             = (smsg_data -> logging);
   HYPRE_Real           *norms               = (smsg_data -> norms);
   HYPRE_Real           *rel_norms           = (smsg_data -> rel_norms);

   HYPRE_Int            *restrict_count;

   HYPRE_Real            b_dot_b, r_dot_r, eps;
   HYPRE_Real            e_dot_e, x_dot_x;
                    
   HYPRE_Int             i, l, lx, ly, lz;
   HYPRE_Int             lymin, lymax, lzmin, lzmax;
   HYPRE_Int             fi, ci;                              
   HYPRE_Int             ierr = 0;

#if DEBUG
   char                  filename[255];
#endif

   /*-----------------------------------------------------
    * Initialize some things and deal with special cases
    *-----------------------------------------------------*/

   hypre_BeginTiming(smsg_data -> time_index);

   hypre_StructMatrixDestroy(A_array[0]);
   hypre_StructVectorDestroy(b_array[0]);
   hypre_StructVectorDestroy(x_array[0]);
   A_array[0] = hypre_StructMatrixRef(A);
   b_array[0] = hypre_StructVectorRef(b);
   x_array[0] = hypre_StructVectorRef(x);

   (smsg_data -> num_iterations) = 0;

   /* if max_iter is zero, return */
   if (max_iter == 0)
   {
      /* if using a zero initial guess, return zero */
      if (zero_guess)
      {
         hypre_StructVectorSetConstantValues(x, 0.0);
      }

      hypre_EndTiming(smsg_data -> time_index);
      return ierr;
   }

   /* part of convergence check */
   if (tol > 0.0)
   {
      /* eps = (tol^2) */
      b_dot_b = hypre_StructInnerProd(b_array[0], b_array[0]);
      eps = tol*tol;

      /* if rhs is zero, return a zero solution */
      if (b_dot_b == 0.0)
      {
         hypre_StructVectorSetConstantValues(x, 0.0);
         if (logging > 0)
         {
            norms[0]     = 0.0;
            rel_norms[0] = 0.0;
         }

         hypre_EndTiming(smsg_data -> time_index);
         return ierr;
      }
   }

   restrict_count = hypre_TAlloc(HYPRE_Int, num_all_grids);

   /*-----------------------------------------------------
    * Do V-cycles:
    *   For each index l, "fine" = l, "coarse" = (l+1)
    *-----------------------------------------------------*/

   for (i = 0; i < max_iter; i++)
   {
      /*--------------------------------------------------
       * Down cycle:
       *   Note that r = b = x through the jump region
       *--------------------------------------------------*/

      /* fine grid pre-relaxation */
      hypre_PFMGRelaxSetPreRelax(relax_array[0]);
      hypre_PFMGRelaxSetMaxIter(relax_array[0], num_fine_relax);
      hypre_PFMGRelaxSetZeroGuess(relax_array[0], zero_guess);
      hypre_PFMGRelax(relax_array[0], A_array[0], b_array[0], x_array[0]);
      zero_guess = 0;

      /* compute fine grid residual (b - Ax) */
      hypre_StructCopy(b_array[0], r_array[0]);
      hypre_StructMatvecCompute(matvec_array[0],
                                -1.0, A_array[0], x_array[0], 1.0, r_array[0]);

      /* convergence check */
      if (tol > 0.0)
      {
         r_dot_r = hypre_StructInnerProd(r_array[0], r_array[0]);

         if (logging > 0)
         {
            norms[i] = sqrt(r_dot_r);
            if (b_dot_b > 0)
               rel_norms[i] = sqrt(r_dot_r/b_dot_b);
            else
               rel_norms[i] = 0.0;
         }
/* RDF */
#if 0

hypre_printf("iter = %d, rel_norm = %e\n", i, rel_norms[i]);

#endif

         /* always do at least 1 V-cycle */
         if ((r_dot_r/b_dot_b < eps) && (i > 0))
         {
            if (rel_change)
            {
               if ((e_dot_e/x_dot_x) < eps)
                  break;
            }
            else
            {
               break;
            }
         }
      }

      if (num_levels > 1)
      {
         /* initialize restrict_count */
         for (fi = 0; fi < num_all_grids; fi++)
         {
            restrict_count[fi] = 0;
         }

         for (l = 0; l <= (num_levels - 2); l++)
         {
            lzmin = hypre_max((l - num_grids[1] - num_grids[0] + 2), 0);
            lzmax = hypre_min((l), (num_grids[2] - 1));
            for (lz = lzmin; lz <= lzmax; lz++)
            {
               lymin = hypre_max((l - lz - num_grids[0] + 1), 0);
               lymax = hypre_min((l - lz), (num_grids[1] - 1));
               for (ly = lymin; ly <= lymax; ly++)
               {
                  lx = l - lz - ly;

                  hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);

                  if (!grid_on[fi])
                  {
                     break;
                  }

                  if (restrict_count[fi] > 1)
                  {
                     hypre_StructScale((1.0/restrict_count[fi]), b_array[fi]);
                  }

                  if (l > jump)
                  {
                     /* pre-relaxation */
                     hypre_PFMGRelaxSetPreRelax(relax_array[fi]);
                     hypre_PFMGRelaxSetMaxIter(relax_array[fi], num_pre_relax);
                     hypre_PFMGRelaxSetZeroGuess(relax_array[fi], 1);
                     hypre_PFMGRelax(relax_array[fi], A_array[fi], b_array[fi],
                                     x_array[fi]);

                     /* compute residual (b - Ax) */
                     hypre_StructCopy(b_array[fi], r_array[fi]);
                     hypre_StructMatvecCompute(matvec_array[fi],
                                               -1.0, A_array[fi], x_array[fi],
                                               1.0, r_array[fi]);
                  }
                        
                  if ((lx+1) < num_grids[0])
                  {
                     /* restrict to ((lx+1), ly, lz) */
                     hypre_SparseMSGMapIndex((lx+1), ly, lz, num_grids, ci);
                     if (grid_on[ci])
                     {
                        if (restrict_count[ci])
                        {
                           hypre_SparseMSGRestrict(restrictx_array[fi],
                                                   RTx_array[lx], r_array[fi],
                                                   t_array[ci]);
                           hypre_StructAxpy(1.0, t_array[ci], b_array[ci]);
                        }
                        else
                        {
                           hypre_SparseMSGRestrict(restrictx_array[fi],
                                                   RTx_array[lx], r_array[fi],
                                                   b_array[ci]);
                        }
                        restrict_count[ci]++;
                     }
                  }
                  if ((ly+1) < num_grids[1])
                  {
                     /* restrict to (lx, (ly+1), lz) */
                     hypre_SparseMSGMapIndex(lx, (ly+1), lz, num_grids, ci);
                     if (grid_on[ci])
                     {
                        if (restrict_count[ci])
                        {
                           hypre_SparseMSGRestrict(restricty_array[fi],
                                                   RTy_array[ly], r_array[fi],
                                                   t_array[ci]);
                           hypre_StructAxpy(1.0, t_array[ci], b_array[ci]);
                        }
                        else
                        {
                           hypre_SparseMSGRestrict(restricty_array[fi],
                                                   RTy_array[ly], r_array[fi],
                                                   b_array[ci]);
                        }
                        restrict_count[ci]++;
                     }
                  }
                  if ((lz+1) < num_grids[2])
                  {
                     /* restrict to (lx, ly, (lz+1)) */
                     hypre_SparseMSGMapIndex(lx, ly, (lz+1), num_grids, ci);
                     if (grid_on[ci])
                     {
                        if (restrict_count[ci])
                        {
                           hypre_SparseMSGRestrict(restrictz_array[fi],
                                                   RTz_array[lz], r_array[fi],
                                                   t_array[ci]);
                           hypre_StructAxpy(1.0, t_array[ci], b_array[ci]);
                        }
                        else
                        {
                           hypre_SparseMSGRestrict(restrictz_array[fi],
                                                   RTz_array[lz], r_array[fi],
                                                   b_array[ci]);
                        }
                        restrict_count[ci]++;
                     }
                  }
#if DEBUG
                  hypre_sprintf(filename, "zoutSMSG_bdown.%d.%d.%d", lx, ly, lz);
                  hypre_StructVectorPrint(filename, b_array[fi], 0);
                  hypre_sprintf(filename, "zoutSMSG_xdown.%d.%d.%d", lx, ly, lz);
                  hypre_StructVectorPrint(filename, x_array[fi], 0);
                  hypre_sprintf(filename, "zoutSMSG_rdown.%d.%d.%d", lx, ly, lz);
                  hypre_StructVectorPrint(filename, r_array[fi], 0);
#endif
               }
            }
         }

         /*--------------------------------------------------
          * Bottom
          *--------------------------------------------------*/
      
         fi = num_all_grids - 1;

         if (restrict_count[fi] > 1)
         {
            hypre_StructScale((1.0/restrict_count[fi]), b_array[fi]);
         }

         hypre_PFMGRelaxSetZeroGuess(relax_array[fi], 1);
         hypre_PFMGRelax(relax_array[fi], A_array[fi], b_array[fi],
                         x_array[fi]);

#if DEBUG
         hypre_sprintf(filename, "zoutSMSG_bbottom.%d.%d.%d", lx, ly, lz);
         hypre_StructVectorPrint(filename, b_array[fi], 0);
         hypre_sprintf(filename, "zoutSMSG_xbottom.%d.%d.%d", lx, ly, lz);
         hypre_StructVectorPrint(filename, x_array[fi], 0);
#endif

         /*--------------------------------------------------
          * Up cycle
          *   Note that r = b = x through the jump region
          *--------------------------------------------------*/

         for (l = (num_levels - 2); l >= 0; l--)
         {
            lzmin = hypre_max((l - num_grids[1] - num_grids[0] + 2), 0);
            lzmax = hypre_min((l), (num_grids[2] - 1));
            for (lz = lzmax; lz >= lzmin; lz--)
            {
               lymin = hypre_max((l - lz - num_grids[0] + 1), 0);
               lymax = hypre_min((l - lz), (num_grids[1] - 1));
               for (ly = lymax; ly >= lymin; ly--)
               {
                  lx = l - lz - ly;

                  hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);
                     
                  if (!grid_on[fi])
                  {
                     break;
                  }

                  if ((l >= 1) && (l <= jump))
                  {
                     hypre_StructVectorSetConstantValues(x_array[fi], 0.0);
                  }
                  if ((lx+1) < num_grids[0])
                  {
                     /* interpolate from ((lx+1), ly, lz) */
                     hypre_SparseMSGMapIndex((lx+1), ly, lz, num_grids, ci);
                     if (grid_on[ci])
                     {
                        hypre_SparseMSGInterp(interpx_array[fi],
                                              Px_array[lx], x_array[ci],
                                              e_array[fi]);
                        hypre_SparseMSGFilter(visitx_array[fi], e_array[fi],
                                              lx, ly, lz, jump);
                        hypre_StructAxpy(1.0, e_array[fi], x_array[fi]);
                     }
                  }
                  if ((ly+1) < num_grids[1])
                  {
                     /* interpolate from (lx, (ly+1), lz) */
                     hypre_SparseMSGMapIndex(lx, (ly+1), lz, num_grids, ci);
                     if (grid_on[ci])
                     {
                        hypre_SparseMSGInterp(interpy_array[fi],
                                              Py_array[ly], x_array[ci],
                                              e_array[fi]);
                        hypre_SparseMSGFilter(visity_array[fi], e_array[fi],
                                              lx, ly, lz, jump);
                        hypre_StructAxpy(1.0, e_array[fi], x_array[fi]);
                     }
                  }
                  if ((lz+1) < num_grids[2])
                  {
                     /* interpolate from (lx, ly, (lz+1)) */
                     hypre_SparseMSGMapIndex(lx, ly, (lz+1), num_grids, ci);
                     if (grid_on[ci])
                     {
                        hypre_SparseMSGInterp(interpz_array[fi],
                                              Pz_array[lz], x_array[ci],
                                              e_array[fi]);
                        hypre_SparseMSGFilter(visitz_array[fi], e_array[fi],
                                              lx, ly, lz, jump);
                        hypre_StructAxpy(1.0, e_array[fi], x_array[fi]);
                     }
                  }               
#if DEBUG
                  hypre_sprintf(filename, "zoutSMSG_xup.%d.%d.%d", lx, ly, lz);
                  hypre_StructVectorPrint(filename, x_array[fi], 0);
#endif
                  if (l > jump)
                  {
                     /* post-relaxation */
                     hypre_PFMGRelaxSetPostRelax(relax_array[fi]);
                     hypre_PFMGRelaxSetMaxIter(relax_array[fi],
                                               num_post_relax);
                     hypre_PFMGRelaxSetZeroGuess(relax_array[fi], 0);
                     hypre_PFMGRelax(relax_array[fi], A_array[fi], b_array[fi],
                                     x_array[fi]);
                  }
               }
            }
         }
      }

      /* part of convergence check */
      if ((tol > 0.0) && (rel_change))
      {
         if (num_levels > 1)
         {
            e_dot_e = hypre_StructInnerProd(e_array[0], e_array[0]);
            x_dot_x = hypre_StructInnerProd(x_array[0], x_array[0]);
         }
         else
         {
            e_dot_e = 0.0;
            x_dot_x = 1.0;
         }
      }

      /* fine grid post-relaxation */
      hypre_PFMGRelaxSetPostRelax(relax_array[0]);
      hypre_PFMGRelaxSetMaxIter(relax_array[0], num_fine_relax);
      hypre_PFMGRelaxSetZeroGuess(relax_array[0], 0);
      hypre_PFMGRelax(relax_array[0], A_array[0], b_array[0], x_array[0]);

      (smsg_data -> num_iterations) = (i + 1);
   }

   hypre_EndTiming(smsg_data -> time_index);

   return ierr;
}