HYPRE_Int
HYPRE_StructSMGSetMemoryUse( HYPRE_StructSolver solver,
                             HYPRE_Int          memory_use )
{
   return( hypre_SMGSetMemoryUse( (void *) solver, memory_use ) );
}
int
hypre_SMGRelaxSetupASol( void               *relax_vdata,
                         hypre_StructMatrix *A,
                         hypre_StructVector *b,
                         hypre_StructVector *x           )
{
   hypre_SMGRelaxData   *relax_data = relax_vdata;

   int                   num_spaces    = (relax_data -> num_spaces);
   int                  *space_indices = (relax_data -> space_indices);
   int                  *space_strides = (relax_data -> space_strides);
   hypre_StructVector   *temp_vec      = (relax_data -> temp_vec);

   int                   num_pre_relax   = (relax_data -> num_pre_relax);
   int                   num_post_relax  = (relax_data -> num_post_relax);

   hypre_StructStencil  *stencil       = hypre_StructMatrixStencil(A);     
   hypre_Index          *stencil_shape = hypre_StructStencilShape(stencil);
   int                   stencil_size  = hypre_StructStencilSize(stencil); 
   int                   stencil_dim   = hypre_StructStencilDim(stencil);
                       
   hypre_StructMatrix   *A_sol;
   void                **solve_data;

   hypre_Index           base_index;
   hypre_Index           base_stride;

   int                   num_stencil_indices;
   int                  *stencil_indices;
                       
   int                   i;

   int                   ierr = 0;

   /*----------------------------------------------------------
    * Free up old data before putting new data into structure
    *----------------------------------------------------------*/

   hypre_SMGRelaxDestroyASol(relax_vdata);

   /*----------------------------------------------------------
    * Set up data
    *----------------------------------------------------------*/

   hypre_CopyIndex((relax_data -> base_index),  base_index);
   hypre_CopyIndex((relax_data -> base_stride), base_stride);

   stencil_indices = hypre_TAlloc(int, stencil_size);
   num_stencil_indices = 0;
   for (i = 0; i < stencil_size; i++)
   {
      if (hypre_IndexD(stencil_shape[i], (stencil_dim - 1)) == 0)
      {
         stencil_indices[num_stencil_indices] = i;
         num_stencil_indices++;
      }
   }
   A_sol = hypre_StructMatrixCreateMask(A, num_stencil_indices, stencil_indices);
   hypre_StructStencilDim(hypre_StructMatrixStencil(A_sol)) = stencil_dim - 1;
   hypre_TFree(stencil_indices);

   /* Set up solve_data */
   solve_data    = hypre_TAlloc(void *, num_spaces);

   for (i = 0; i < num_spaces; i++)
   {
      hypre_IndexD(base_index,  (stencil_dim - 1)) = space_indices[i];
      hypre_IndexD(base_stride, (stencil_dim - 1)) = space_strides[i];

      if (stencil_dim > 2)
      {
         solve_data[i] = hypre_SMGCreate(relax_data -> comm);
         hypre_SMGSetNumPreRelax( solve_data[i], num_pre_relax);
         hypre_SMGSetNumPostRelax( solve_data[i], num_post_relax);
         hypre_SMGSetBase(solve_data[i], base_index, base_stride);
         hypre_SMGSetMemoryUse(solve_data[i], (relax_data -> memory_use));
         hypre_SMGSetTol(solve_data[i], 0.0);
         hypre_SMGSetMaxIter(solve_data[i], 1);
         hypre_SMGSetup(solve_data[i], A_sol, temp_vec, x);
      }
      else
      {
         solve_data[i] = hypre_CyclicReductionCreate(relax_data -> comm);
         hypre_CyclicReductionSetBase(solve_data[i], base_index, base_stride);
         hypre_CyclicReductionSetup(solve_data[i], A_sol, temp_vec, x);
      }
   }

   (relax_data -> A_sol)      = A_sol;
   (relax_data -> solve_data) = solve_data;

   (relax_data -> setup_a_sol) = 0;

   return ierr;
}