hypre/struct_ls/sparse_msg_setup.c
2012-03-06 19:15:29 +00:00

838 lines
29 KiB
C

/*BHEADER**********************************************************************
* Copyright (c) 2008, Lawrence Livermore National Security, LLC.
* Produced at the Lawrence Livermore National Laboratory.
* This file is part of HYPRE. See file COPYRIGHT for details.
*
* HYPRE is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License (as published by the Free
* Software Foundation) version 2.1 dated February 1999.
*
* $Revision$
***********************************************************************EHEADER*/
/******************************************************************************
*
*
*****************************************************************************/
#include "_hypre_struct_ls.h"
#include "sparse_msg.h"
#define DEBUG 0
#define GRID 0
#define hypre_SparseMSGSetCIndex(cdir, cindex) \
{\
hypre_SetIndex(cindex, 0, 0, 0);\
hypre_IndexD(cindex, cdir) = 0;\
}
#define hypre_SparseMSGSetFIndex(cdir, findex) \
{\
hypre_SetIndex(findex, 0, 0, 0);\
hypre_IndexD(findex, cdir) = 1;\
}
#define hypre_SparseMSGSetStride(cdir, stride) \
{\
hypre_SetIndex(stride, 1, 1, 1);\
hypre_IndexD(stride, cdir) = 2;\
}
/*--------------------------------------------------------------------------
* hypre_SparseMSGSetup
*--------------------------------------------------------------------------*/
HYPRE_Int
hypre_SparseMSGSetup( void *smsg_vdata,
hypre_StructMatrix *A,
hypre_StructVector *b,
hypre_StructVector *x )
{
hypre_SparseMSGData *smsg_data = smsg_vdata;
MPI_Comm comm = (smsg_data -> comm);
HYPRE_Int max_iter;
HYPRE_Int jump = (smsg_data -> jump);
HYPRE_Int relax_type = (smsg_data -> relax_type);
HYPRE_Int usr_jacobi_weight= (smsg_data -> usr_jacobi_weight);
double jacobi_weight = (smsg_data -> jacobi_weight);
HYPRE_Int *num_grids = (smsg_data -> num_grids);
HYPRE_Int num_all_grids;
HYPRE_Int num_levels;
hypre_StructGrid **grid_a;
hypre_StructGrid **Px_grid_a;
hypre_StructGrid **Py_grid_a;
hypre_StructGrid **Pz_grid_a;
double *data;
double *tdata;
HYPRE_Int data_size = 0;
hypre_StructMatrix **A_a;
hypre_StructMatrix **Px_a;
hypre_StructMatrix **Py_a;
hypre_StructMatrix **Pz_a;
hypre_StructMatrix **RTx_a;
hypre_StructMatrix **RTy_a;
hypre_StructMatrix **RTz_a;
hypre_StructVector **b_a;
hypre_StructVector **x_a;
/* temp vectors */
hypre_StructVector **t_a;
hypre_StructVector **r_a;
hypre_StructVector **e_a;
hypre_StructVector **visitx_a;
hypre_StructVector **visity_a;
hypre_StructVector **visitz_a;
HYPRE_Int *grid_on;
void **relax_a;
void **matvec_a;
void **restrictx_a;
void **restricty_a;
void **restrictz_a;
void **interpx_a;
void **interpy_a;
void **interpz_a;
hypre_Index cindex;
hypre_Index findex;
hypre_Index stride;
hypre_Index stridePR;
hypre_StructGrid *grid;
HYPRE_Int dim;
hypre_Box *cbox;
HYPRE_Int d, l, lx, ly, lz;
HYPRE_Int fi, ci;
HYPRE_Int b_num_ghost[] = {0, 0, 0, 0, 0, 0};
HYPRE_Int x_num_ghost[] = {1, 1, 1, 1, 1, 1};
HYPRE_Int ierr = 0;
#if DEBUG
char filename[255];
#endif
/*-----------------------------------------------------
* Set up coarse grids
*-----------------------------------------------------*/
grid = hypre_StructMatrixGrid(A);
dim = hypre_StructGridDim(grid);
/* Determine num_grids[] and num_levels */
num_levels = 1;
cbox = hypre_BoxDuplicate(hypre_StructGridBoundingBox(grid));
for (d = 0; d < dim; d++)
{
while ( hypre_BoxIMaxD(cbox,d) > hypre_BoxIMinD(cbox,d) )
{
/* set cindex, findex, and stride */
hypre_SparseMSGSetCIndex(d, cindex);
hypre_SparseMSGSetFIndex(d, findex);
hypre_SparseMSGSetStride(d, stride);
/* coarsen cbox */
hypre_ProjectBox(cbox,cindex,stride);
hypre_StructMapFineToCoarse(hypre_BoxIMin(cbox),
cindex,stride,hypre_BoxIMin(cbox));
hypre_StructMapFineToCoarse(hypre_BoxIMax(cbox),
cindex,stride,hypre_BoxIMax(cbox));
/* increment level counters */
num_grids[d]++;
num_levels++;
}
}
#if 0
/* Restrict the semicoarsening to a particular direction */
num_grids[1] = 1;
num_grids[2] = 1;
num_levels = num_grids[0];
#endif
/* Compute the num_all_grids based on num_grids[] */
num_all_grids = num_grids[0] * num_grids[1] * num_grids[2];
/* Store some variables and clean up */
hypre_BoxDestroy(cbox);
(smsg_data -> num_all_grids) = num_all_grids;
(smsg_data -> num_levels) = num_levels;
grid_a = hypre_TAlloc(hypre_StructGrid *, num_all_grids);
hypre_StructGridRef(grid, &grid_a[0]);
Px_grid_a = hypre_TAlloc(hypre_StructGrid *, num_grids[0]);
Py_grid_a = hypre_TAlloc(hypre_StructGrid *, num_grids[1]);
Pz_grid_a = hypre_TAlloc(hypre_StructGrid *, num_grids[2]);
Px_grid_a[0] = NULL;
Py_grid_a[0] = NULL;
Pz_grid_a[0] = NULL;
/*-----------------------------------------
* Compute coarse grids
*-----------------------------------------*/
if (num_levels > 1)
{
/* coarsen in x direction */
hypre_SparseMSGSetCIndex(0, cindex);
hypre_SparseMSGSetStride(0, stride);
for (lx = 0; lx < num_grids[0] - 1; lx++)
{
hypre_SparseMSGMapIndex(lx, 0, 0, num_grids, fi);
hypre_SparseMSGMapIndex(lx+1, 0, 0, num_grids, ci);
hypre_StructCoarsen(grid_a[fi], cindex, stride, 1,
&grid_a[ci]);
}
/* coarsen in y direction */
hypre_SparseMSGSetCIndex(1, cindex);
hypre_SparseMSGSetStride(1, stride);
for (ly = 0; ly < num_grids[1] - 1; ly++)
{
for (lx = 0; lx < num_grids[0]; lx++)
{
hypre_SparseMSGMapIndex(lx, ly, 0, num_grids, fi);
hypre_SparseMSGMapIndex(lx, ly+1, 0, num_grids, ci);
hypre_StructCoarsen(grid_a[fi], cindex, stride, 1,
&grid_a[ci]);
}
}
/* coarsen in z direction */
hypre_SparseMSGSetCIndex(2, cindex);
hypre_SparseMSGSetStride(2, stride);
for (lz = 0; lz < num_grids[2] - 1; lz++)
{
for (ly = 0; ly < num_grids[1]; ly++)
{
for (lx = 0; lx < num_grids[0]; lx++)
{
hypre_SparseMSGMapIndex(lx, ly, lz , num_grids, fi);
hypre_SparseMSGMapIndex(lx, ly, lz+1, num_grids, ci);
hypre_StructCoarsen(grid_a[fi], cindex, stride, 1,
&grid_a[ci]);
}
}
}
}
/*-----------------------------------------
* Compute interpolation grids
*-----------------------------------------*/
if (num_levels > 1)
{
/* coarsen in x direction */
hypre_SparseMSGSetFIndex(0, findex);
hypre_SparseMSGSetStride(0, stride);
for (lx = 0; lx < num_grids[0] - 1; lx++)
{
hypre_SparseMSGMapIndex(lx, 0, 0, num_grids, fi);
hypre_StructCoarsen(grid_a[fi], findex, stride, 1,
&Px_grid_a[lx+1]);
}
/* coarsen in y direction */
hypre_SparseMSGSetFIndex(1, findex);
hypre_SparseMSGSetStride(1, stride);
for (ly = 0; ly < num_grids[1] - 1; ly++)
{
hypre_SparseMSGMapIndex(0, ly, 0, num_grids, fi);
hypre_StructCoarsen(grid_a[fi], findex, stride, 1,
&Py_grid_a[ly+1]);
}
/* coarsen in z direction */
hypre_SparseMSGSetFIndex(2, findex);
hypre_SparseMSGSetStride(2, stride);
for (lz = 0; lz < num_grids[2] - 1; lz++)
{
hypre_SparseMSGMapIndex(0, 0, lz, num_grids, fi);
hypre_StructCoarsen(grid_a[fi], findex, stride, 1,
&Pz_grid_a[lz+1]);
}
}
(smsg_data -> grid_array) = grid_a;
(smsg_data -> Px_grid_array) = Px_grid_a;
(smsg_data -> Py_grid_array) = Py_grid_a;
(smsg_data -> Pz_grid_array) = Pz_grid_a;
/*------------------------------------------------------
* Compute P, R, and A operators
* Compute visit arrays and turn grids off if possible
*
* Note: this is ordered to conserve memory
*-----------------------------------------------------*/
A_a = hypre_TAlloc(hypre_StructMatrix *, num_all_grids);
Px_a = hypre_TAlloc(hypre_StructMatrix *, num_grids[0] - 1);
Py_a = hypre_TAlloc(hypre_StructMatrix *, num_grids[1] - 1);
Pz_a = hypre_TAlloc(hypre_StructMatrix *, num_grids[2] - 1);
RTx_a = hypre_TAlloc(hypre_StructMatrix *, num_grids[0] - 1);
RTy_a = hypre_TAlloc(hypre_StructMatrix *, num_grids[1] - 1);
RTz_a = hypre_TAlloc(hypre_StructMatrix *, num_grids[2] - 1);
visitx_a = hypre_CTAlloc(hypre_StructVector *, num_all_grids);
visity_a = hypre_CTAlloc(hypre_StructVector *, num_all_grids);
visitz_a = hypre_CTAlloc(hypre_StructVector *, num_all_grids);
grid_on = hypre_CTAlloc(HYPRE_Int, num_all_grids);
A_a[0] = hypre_StructMatrixRef(A);
for (lz = 0; lz < num_grids[2]; lz++)
{
for (ly = 0; ly < num_grids[1]; ly++)
{
for (lx = 0; lx < num_grids[0]; lx++)
{
hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);
/*-------------------------------
* create visit arrays
*-------------------------------*/
/* RDF */
#if 0
l = lx + ly + lz;
if ((l >= 1) && (l <= jump))
{
visitx_a[fi] = visitx_a[0];
visity_a[fi] = visity_a[0];
visitz_a[fi] = visitz_a[0];
}
else
#endif
/* RDF */
{
visitx_a[fi] = hypre_StructVectorCreate(comm, grid_a[fi]);
visity_a[fi] = hypre_StructVectorCreate(comm, grid_a[fi]);
visitz_a[fi] = hypre_StructVectorCreate(comm, grid_a[fi]);
hypre_StructVectorSetNumGhost(visitx_a[fi], b_num_ghost);
hypre_StructVectorSetNumGhost(visity_a[fi], b_num_ghost);
hypre_StructVectorSetNumGhost(visitz_a[fi], b_num_ghost);
hypre_StructVectorInitialize(visitx_a[fi]);
hypre_StructVectorInitialize(visity_a[fi]);
hypre_StructVectorInitialize(visitz_a[fi]);
}
hypre_SparseMSGFilterSetup(A_a[fi], num_grids, lx, ly, lz, jump,
visitx_a[fi],
visity_a[fi],
visitz_a[fi]);
#if GRID
vx_dot_vx = hypre_StructInnerProd(visitx_a[fi], visitx_a[fi]);
vy_dot_vy = hypre_StructInnerProd(visity_a[fi], visity_a[fi]);
vz_dot_vz = hypre_StructInnerProd(visitz_a[fi], visitz_a[fi]);
#else
/* turn all grids on */
grid_on[fi] = 1;
#endif
/*-------------------------------
* compute Px, RTx, and A
*-------------------------------*/
if (lx < (num_grids[0] - 1))
{
hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);
hypre_SparseMSGMapIndex((lx+1), ly, lz, num_grids, ci);
hypre_SparseMSGSetCIndex(0, cindex);
hypre_SparseMSGSetFIndex(0, findex);
hypre_SparseMSGSetStride(0, stride);
/* compute x-transfer operator */
if ((lz == 0) && (ly == 0))
{
Px_a[lx] = hypre_PFMGCreateInterpOp(A_a[fi],
Px_grid_a[lx+1], 0, 0);
hypre_StructMatrixInitialize(Px_a[lx]);
hypre_PFMGSetupInterpOp(A_a[fi], 0, findex, stride,
Px_a[lx], 0);
RTx_a[lx] = Px_a[lx];
}
/* compute coarse-operator with Px */
A_a[ci] =
hypre_SparseMSGCreateRAPOp(RTx_a[lx], A_a[fi], Px_a[lx],
grid_a[ci], 0);
hypre_StructMatrixInitialize(A_a[ci]);
hypre_SetIndex(stridePR, 1, pow(2, ly), pow(2, lz));
hypre_SparseMSGSetupRAPOp(RTx_a[lx], A_a[fi], Px_a[lx],
0, cindex, stride, stridePR, A_a[ci]);
}
}
/* RDF */
#if 0
/* free up some coarse-operators to conserve memory */
for (lx = 1; lx <= hypre_min((jump-ly-lz), (num_grids[0]-1)); lx++)
{
hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);
hypre_StructMatrixDestroy(A_a[fi]);
A_a[fi] = NULL;
}
#endif
/* RDF */
/*-------------------------------
* compute Py, RTy, and A
*-------------------------------*/
if (ly < (num_grids[1] - 1))
{
hypre_SparseMSGMapIndex(0, ly, lz, num_grids, fi);
hypre_SparseMSGMapIndex(0, (ly+1), lz, num_grids, ci);
hypre_SparseMSGSetCIndex(1, cindex);
hypre_SparseMSGSetFIndex(1, findex);
hypre_SparseMSGSetStride(1, stride);
/* compute y-transfer operators */
if (lz == 0)
{
Py_a[ly] = hypre_PFMGCreateInterpOp(A_a[fi],
Py_grid_a[ly+1], 1, 0);
hypre_StructMatrixInitialize(Py_a[ly]);
hypre_PFMGSetupInterpOp(A_a[fi], 1, findex, stride,
Py_a[ly], 0);
RTy_a[ly] = Py_a[ly];
}
/* compute coarse-operator with Py */
A_a[ci] = hypre_SparseMSGCreateRAPOp(RTy_a[ly], A_a[fi], Py_a[ly],
grid_a[ci], 1);
hypre_StructMatrixInitialize(A_a[ci]);
hypre_SetIndex(stridePR, 1, 1, pow(2, lz));
hypre_SparseMSGSetupRAPOp(RTy_a[ly], A_a[fi], Py_a[ly],
1, cindex, stride, stridePR, A_a[ci]);
}
}
/* RDF */
#if 0
/* free up some coarse-operators to conserve memory */
for (ly = 1; ly <= hypre_min((jump-lz), (num_grids[1]-1)); ly++)
{
hypre_SparseMSGMapIndex(0, ly, lz, num_grids, fi);
hypre_StructMatrixDestroy(A_a[fi]);
A_a[fi] = NULL;
}
#endif
/* RDF */
/*-------------------------------
* compute Pz, RTz, and A
*-------------------------------*/
if (lz < (num_grids[2] - 1))
{
hypre_SparseMSGMapIndex(0, 0, lz, num_grids, fi);
hypre_SparseMSGMapIndex(0, 0, (lz+1), num_grids, ci);
hypre_SparseMSGSetCIndex(2, cindex);
hypre_SparseMSGSetFIndex(2, findex);
hypre_SparseMSGSetStride(2, stride);
/* compute z-transfer operators */
Pz_a[lz] = hypre_PFMGCreateInterpOp(A_a[fi], Pz_grid_a[lz+1], 2, 0);
hypre_StructMatrixInitialize(Pz_a[lz]);
hypre_PFMGSetupInterpOp(A_a[fi], 2, findex, stride, Pz_a[lz], 0);
RTz_a[lz] = Pz_a[lz];
/* compute coarse-operator with Pz */
A_a[ci] = hypre_SparseMSGCreateRAPOp(RTz_a[lz], A_a[fi], Pz_a[lz],
grid_a[ci], 2);
hypre_StructMatrixInitialize(A_a[ci]);
hypre_SetIndex(stridePR, 1, 1, 1);
hypre_SparseMSGSetupRAPOp(RTz_a[lz], A_a[fi], Pz_a[lz],
2, cindex, stride, stridePR, A_a[ci]);
}
}
/* RDF */
#if 0
/* free up some coarse-operators to conserve memory */
for (lz = 1; lz <= hypre_min((jump), (num_grids[2]-1)); lz++)
{
hypre_SparseMSGMapIndex(0, 0, lz, num_grids, fi);
hypre_StructMatrixDestroy(A_a[fi]);
A_a[fi] = NULL;
}
#endif
/* RDF */
(smsg_data -> A_array) = A_a;
(smsg_data -> Px_array) = Px_a;
(smsg_data -> Py_array) = Py_a;
(smsg_data -> Pz_array) = Pz_a;
(smsg_data -> RTx_array) = RTx_a;
(smsg_data -> RTy_array) = RTy_a;
(smsg_data -> RTz_array) = RTz_a;
(smsg_data -> visitx_array) = visitx_a;
(smsg_data -> visity_array) = visity_a;
(smsg_data -> visitz_array) = visitz_a;
(smsg_data -> grid_on) = grid_on;
/*------------------------------------------------------
* Set up vector structures
*-----------------------------------------------------*/
b_a = hypre_TAlloc(hypre_StructVector *, num_all_grids);
x_a = hypre_TAlloc(hypre_StructVector *, num_all_grids);
t_a = hypre_TAlloc(hypre_StructVector *, num_all_grids);
r_a = hypre_TAlloc(hypre_StructVector *, num_all_grids);
e_a = t_a;
data_size = 0;
b_a[0] = hypre_StructVectorRef(b);
x_a[0] = hypre_StructVectorRef(x);
t_a[0] = hypre_StructVectorCreate(comm, grid_a[0]);
hypre_StructVectorSetNumGhost(t_a[0], x_num_ghost);
hypre_StructVectorInitializeShell(t_a[0]);
data_size += hypre_StructVectorDataSize(t_a[0]);
r_a[0] = hypre_StructVectorCreate(comm, grid_a[0]);
hypre_StructVectorSetNumGhost(r_a[0], x_num_ghost);
hypre_StructVectorInitializeShell(r_a[0]);
data_size += hypre_StructVectorDataSize(r_a[0]);
for (lz = 0; lz < num_grids[2]; lz++)
{
for (ly = 0; ly < num_grids[1]; ly++)
{
for (lx = 0; lx < num_grids[0]; lx++)
{
l = lx + ly + lz;
if (l >= 1)
{
hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);
x_a[fi] = hypre_StructVectorCreate(comm, grid_a[fi]);
hypre_StructVectorSetNumGhost(x_a[fi], x_num_ghost);
hypre_StructVectorInitializeShell(x_a[fi]);
data_size += hypre_StructVectorDataSize(x_a[fi]);
t_a[fi] = hypre_StructVectorCreate(comm, grid_a[fi]);
hypre_StructVectorSetNumGhost(t_a[fi], x_num_ghost);
hypre_StructVectorInitializeShell(t_a[fi]);
/* set vector structures in jump region */
if (l <= jump)
{
b_a[fi] = x_a[fi];
r_a[fi] = x_a[fi];
}
/* set vector structures outside of jump region */
else
{
b_a[fi] = hypre_StructVectorCreate(comm, grid_a[fi]);
hypre_StructVectorSetNumGhost(b_a[fi], b_num_ghost);
hypre_StructVectorInitializeShell(b_a[fi]);
data_size += hypre_StructVectorDataSize(b_a[fi]);
r_a[fi] = hypre_StructVectorCreate(comm, grid_a[fi]);
hypre_StructVectorSetNumGhost(r_a[fi], x_num_ghost);
hypre_StructVectorInitializeShell(r_a[fi]);
}
}
}
}
}
data = hypre_SharedCTAlloc(double, data_size);
(smsg_data -> data) = data;
hypre_StructVectorInitializeData(t_a[0], data);
hypre_StructVectorAssemble(t_a[0]);
data += hypre_StructVectorDataSize(t_a[0]);
hypre_StructVectorInitializeData(r_a[0], data);
hypre_StructVectorAssemble(r_a[0]);
data += hypre_StructVectorDataSize(r_a[0]);
for (lz = 0; lz < num_grids[2]; lz++)
{
for (ly = 0; ly < num_grids[1]; ly++)
{
for (lx = 0; lx < num_grids[0]; lx++)
{
l = lx + ly + lz;
if (l >= 1)
{
hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);
hypre_StructVectorInitializeData(x_a[fi], data);
hypre_StructVectorAssemble(x_a[fi]);
data += hypre_StructVectorDataSize(x_a[fi]);
tdata = hypre_StructVectorData(t_a[0]);
hypre_StructVectorInitializeData(t_a[fi], tdata);
/* set vector structures outside of jump region */
if (l > jump)
{
hypre_StructVectorInitializeData(b_a[fi], data);
hypre_StructVectorAssemble(b_a[fi]);
data += hypre_StructVectorDataSize(b_a[fi]);
tdata = hypre_StructVectorData(r_a[0]);
hypre_StructVectorInitializeData(r_a[fi], tdata);
}
}
}
}
}
(smsg_data -> b_array) = b_a;
(smsg_data -> x_array) = x_a;
(smsg_data -> t_array) = t_a;
(smsg_data -> r_array) = r_a;
(smsg_data -> e_array) = e_a;
/*------------------------------------------------------
* Call setup routines
*-----------------------------------------------------*/
relax_a = hypre_CTAlloc(void *, num_all_grids);
matvec_a = hypre_CTAlloc(void *, num_all_grids);
restrictx_a = hypre_CTAlloc(void *, num_all_grids);
restricty_a = hypre_CTAlloc(void *, num_all_grids);
restrictz_a = hypre_CTAlloc(void *, num_all_grids);
interpx_a = hypre_CTAlloc(void *, num_all_grids);
interpy_a = hypre_CTAlloc(void *, num_all_grids);
interpz_a = hypre_CTAlloc(void *, num_all_grids);
/* set up x-transfer routines */
for (lx = 0; lx < (num_grids[0] - 1); lx++)
{
hypre_SparseMSGSetCIndex(0, cindex);
hypre_SparseMSGSetFIndex(0, findex);
hypre_SparseMSGSetStride(0, stride);
for (lz = 0; lz < num_grids[2]; lz++)
{
for (ly = 0; ly < num_grids[1]; ly++)
{
hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);
hypre_SparseMSGMapIndex(lx+1, ly, lz, num_grids, ci);
hypre_SetIndex(stridePR, 1, pow(2, ly), pow(2, lz));
interpx_a[fi] = hypre_SparseMSGInterpCreate();
hypre_SparseMSGInterpSetup(interpx_a[fi], Px_a[lx],
x_a[ci], e_a[fi],
cindex, findex, stride, stridePR);
restrictx_a[fi] = hypre_SparseMSGRestrictCreate();
hypre_SparseMSGRestrictSetup(restrictx_a[fi], RTx_a[lx],
r_a[fi], b_a[ci],
cindex, findex, stride, stridePR);
}
}
}
/* set up y-transfer routines */
for (ly = 0; ly < (num_grids[1] - 1); ly++)
{
hypre_SparseMSGSetCIndex(1, cindex);
hypre_SparseMSGSetFIndex(1, findex);
hypre_SparseMSGSetStride(1, stride);
for (lz = 0; lz < num_grids[2]; lz++)
{
for (lx = 0; lx < num_grids[0]; lx++)
{
hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);
hypre_SparseMSGMapIndex(lx, ly+1, lz, num_grids, ci);
hypre_SetIndex(stridePR, pow(2, lx), 1, pow(2, lz));
interpy_a[fi] = hypre_SparseMSGInterpCreate();
hypre_SparseMSGInterpSetup(interpy_a[fi], Py_a[ly],
x_a[ci], e_a[fi],
cindex, findex, stride, stridePR);
restricty_a[fi] = hypre_SparseMSGRestrictCreate();
hypre_SparseMSGRestrictSetup(restricty_a[fi], RTy_a[ly],
r_a[fi], b_a[ci],
cindex, findex, stride, stridePR);
}
}
}
/* set up z-transfer routines */
for (lz = 0; lz < (num_grids[2] - 1); lz++)
{
hypre_SparseMSGSetCIndex(2, cindex);
hypre_SparseMSGSetFIndex(2, findex);
hypre_SparseMSGSetStride(2, stride);
for (ly = 0; ly < num_grids[1]; ly++)
{
for (lx = 0; lx < num_grids[0]; lx++)
{
hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);
hypre_SparseMSGMapIndex(lx, ly, lz+1, num_grids, ci);
hypre_SetIndex(stridePR, pow(2, lx), pow(2, ly), 1);
interpz_a[fi] = hypre_SparseMSGInterpCreate();
hypre_SparseMSGInterpSetup(interpz_a[fi], Pz_a[lz],
x_a[ci], e_a[fi],
cindex, findex, stride, stridePR);
restrictz_a[fi] = hypre_SparseMSGRestrictCreate();
hypre_SparseMSGRestrictSetup(restrictz_a[fi], RTz_a[lz],
r_a[fi], b_a[ci],
cindex, findex, stride, stridePR);
}
}
}
/* set up fine grid relaxation */
relax_a[0] = hypre_PFMGRelaxCreate(comm);
hypre_PFMGRelaxSetTol(relax_a[0], 0.0);
hypre_PFMGRelaxSetType(relax_a[0], relax_type);
if (usr_jacobi_weight)
{
hypre_PFMGRelaxSetJacobiWeight(relax_a[0], jacobi_weight);
}
hypre_PFMGRelaxSetTempVec(relax_a[0], t_a[0]);
hypre_PFMGRelaxSetup(relax_a[0], A_a[0], b_a[0], x_a[0]);
/* set up the fine grid residual routine */
matvec_a[0] = hypre_StructMatvecCreate();
hypre_StructMatvecSetup(matvec_a[0], A_a[0], x_a[0]);
if (num_levels > 1)
{
for (lz = 0; lz < num_grids[2]; lz++)
{
for (ly = 0; ly < num_grids[1]; ly++)
{
for (lx = 0; lx < num_grids[0]; lx++)
{
l = lx + ly + lz;
if ((l > jump) && (l < (num_levels - 1)))
{
hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);
/* set up relaxation */
relax_a[fi] = hypre_PFMGRelaxCreate(comm);
hypre_PFMGRelaxSetTol(relax_a[fi], 0.0);
hypre_PFMGRelaxSetType(relax_a[fi], relax_type);
if (usr_jacobi_weight)
{
hypre_PFMGRelaxSetJacobiWeight(relax_a[fi], jacobi_weight);
}
hypre_PFMGRelaxSetTempVec(relax_a[fi], t_a[fi]);
hypre_PFMGRelaxSetup(relax_a[fi], A_a[fi], b_a[fi], x_a[fi]);
/* set up the residual routine */
matvec_a[fi] = hypre_StructMatvecCreate();
hypre_StructMatvecSetup(matvec_a[fi], A_a[fi], x_a[fi]);
}
}
}
}
/* set up coarsest grid relaxation */
fi = num_all_grids - 1;
relax_a[fi] = hypre_PFMGRelaxCreate(comm);
hypre_PFMGRelaxSetTol(relax_a[fi], 0.0);
hypre_PFMGRelaxSetMaxIter(relax_a[fi], 1);
hypre_PFMGRelaxSetType(relax_a[fi], 0);
if (usr_jacobi_weight)
{
hypre_PFMGRelaxSetJacobiWeight(relax_a[fi], jacobi_weight);
}
hypre_PFMGRelaxSetTempVec(relax_a[fi], t_a[fi]);
hypre_PFMGRelaxSetup(relax_a[fi], A_a[fi], b_a[fi], x_a[fi]);
}
(smsg_data -> relax_array) = relax_a;
(smsg_data -> matvec_array) = matvec_a;
(smsg_data -> restrictx_array) = restrictx_a;
(smsg_data -> restricty_array) = restricty_a;
(smsg_data -> restrictz_array) = restrictz_a;
(smsg_data -> interpx_array) = interpx_a;
(smsg_data -> interpy_array) = interpy_a;
(smsg_data -> interpz_array) = interpz_a;
/*-----------------------------------------------------
* Allocate space for log info
*-----------------------------------------------------*/
if ((smsg_data -> logging) > 0)
{
max_iter = (smsg_data -> max_iter);
(smsg_data -> norms) = hypre_TAlloc(double, max_iter);
(smsg_data -> rel_norms) = hypre_TAlloc(double, max_iter);
}
#if DEBUG
for (lz = 0; lz < num_grids[2]; lz++)
{
for (ly = 0; ly < num_grids[1]; ly++)
{
for (lx = 0; lx < num_grids[0]; lx++)
{
l = lx + ly + lz;
if ((l == 0) || (l > jump))
{
hypre_SparseMSGMapIndex(lx, ly, lz, num_grids, fi);
hypre_sprintf(filename, "zoutSMSG_A.%d.%d.%d", lx, ly, lz);
hypre_StructMatrixPrint(filename, A_a[fi], 0);
hypre_sprintf(filename, "zoutSMSG_visitx.%d.%d.%d", lx, ly, lz);
hypre_StructVectorPrint(filename, visitx_a[fi], 0);
hypre_sprintf(filename, "zoutSMSG_visity.%d.%d.%d", lx, ly, lz);
hypre_StructVectorPrint(filename, visity_a[fi], 0);
hypre_sprintf(filename, "zoutSMSG_visitz.%d.%d.%d", lx, ly, lz);
hypre_StructVectorPrint(filename, visitz_a[fi], 0);
}
}
}
}
for (lx = 0; lx < num_grids[0] - 1; lx++)
{
hypre_sprintf(filename, "zoutSMSG_Px.%d", lx);
hypre_StructMatrixPrint(filename, Px_a[lx], 0);
}
for (ly = 0; ly < num_grids[1] - 1; ly++)
{
hypre_sprintf(filename, "zoutSMSG_Py.%d", ly);
hypre_StructMatrixPrint(filename, Py_a[ly], 0);
}
for (lz = 0; lz < num_grids[2] - 1; lz++)
{
hypre_sprintf(filename, "zoutSMSG_Pz.%d", lz);
hypre_StructMatrixPrint(filename, Pz_a[lz], 0);
}
#endif
return ierr;
}