blob: f7bf175920e1f229e171de0759f1dc92fcff7a02 [file] [log] [blame]
/*BHEADER**********************************************************************
* (c) 1997 The Regents of the University of California
*
* See the file COPYRIGHT_and_DISCLAIMER for a complete copyright
* notice, contact person, and disclaimer.
*
* $Revision$
*********************************************************************EHEADER*/
/******************************************************************************
*
* Routine for computing residuals in the SMG code
*
*****************************************************************************/
#include "headers.h"
/*--------------------------------------------------------------------------
* hypre_SMGResidualData data structure
*--------------------------------------------------------------------------*/
typedef struct
{
hypre_Index base_index;
hypre_Index base_stride;
hypre_StructMatrix *A;
hypre_StructVector *x;
hypre_StructVector *b;
hypre_StructVector *r;
hypre_BoxArray *base_points;
hypre_ComputePkg *compute_pkg;
int time_index;
int flops;
} hypre_SMGResidualData;
/*--------------------------------------------------------------------------
* hypre_SMGResidualCreate
*--------------------------------------------------------------------------*/
void *
hypre_SMGResidualCreate( )
{
hypre_SMGResidualData *residual_data;
residual_data = hypre_CTAlloc(hypre_SMGResidualData, 1);
(residual_data -> time_index) = hypre_InitializeTiming("SMGResidual");
/* set defaults */
hypre_SetIndex((residual_data -> base_index), 0, 0, 0);
hypre_SetIndex((residual_data -> base_stride), 1, 1, 1);
return (void *) residual_data;
}
/*--------------------------------------------------------------------------
* hypre_SMGResidualSetup
*--------------------------------------------------------------------------*/
int
hypre_SMGResidualSetup( void *residual_vdata,
hypre_StructMatrix *A,
hypre_StructVector *x,
hypre_StructVector *b,
hypre_StructVector *r )
{
int ierr = 0;
hypre_SMGResidualData *residual_data = residual_vdata;
hypre_IndexRef base_index = (residual_data -> base_index);
hypre_IndexRef base_stride = (residual_data -> base_stride);
hypre_Index unit_stride;
hypre_StructGrid *grid;
hypre_StructStencil *stencil;
hypre_BoxArrayArray *send_boxes;
hypre_BoxArrayArray *recv_boxes;
int **send_processes;
int **recv_processes;
hypre_BoxArrayArray *indt_boxes;
hypre_BoxArrayArray *dept_boxes;
hypre_BoxArray *base_points;
hypre_ComputePkg *compute_pkg;
/*----------------------------------------------------------
* Set up base points and the compute package
*----------------------------------------------------------*/
grid = hypre_StructMatrixGrid(A);
stencil = hypre_StructMatrixStencil(A);
hypre_SetIndex(unit_stride, 1, 1, 1);
base_points = hypre_BoxArrayDuplicate(hypre_StructGridBoxes(grid));
hypre_ProjectBoxArray(base_points, base_index, base_stride);
hypre_CreateComputeInfo(grid, stencil,
&send_boxes, &recv_boxes,
&send_processes, &recv_processes,
&indt_boxes, &dept_boxes);
hypre_ProjectBoxArrayArray(indt_boxes, base_index, base_stride);
hypre_ProjectBoxArrayArray(dept_boxes, base_index, base_stride);
hypre_ComputePkgCreate(send_boxes, recv_boxes,
unit_stride, unit_stride,
send_processes, recv_processes,
indt_boxes, dept_boxes,
base_stride, grid,
hypre_StructVectorDataSpace(x), 1,
&compute_pkg);
/*----------------------------------------------------------
* Set up the residual data structure
*----------------------------------------------------------*/
(residual_data -> A) = hypre_StructMatrixRef(A);
(residual_data -> x) = hypre_StructVectorRef(x);
(residual_data -> b) = hypre_StructVectorRef(b);
(residual_data -> r) = hypre_StructVectorRef(r);
(residual_data -> base_points) = base_points;
(residual_data -> compute_pkg) = compute_pkg;
/*-----------------------------------------------------
* Compute flops
*-----------------------------------------------------*/
(residual_data -> flops) =
(hypre_StructMatrixGlobalSize(A) + hypre_StructVectorGlobalSize(x)) /
(hypre_IndexX(base_stride) *
hypre_IndexY(base_stride) *
hypre_IndexZ(base_stride) );
return ierr;
}
/*--------------------------------------------------------------------------
* hypre_SMGResidual
*--------------------------------------------------------------------------*/
int
hypre_SMGResidual( void *residual_vdata,
hypre_StructMatrix *A,
hypre_StructVector *x,
hypre_StructVector *b,
hypre_StructVector *r )
{
int ierr = 0;
hypre_SMGResidualData *residual_data = residual_vdata;
hypre_IndexRef base_stride = (residual_data -> base_stride);
hypre_BoxArray *base_points = (residual_data -> base_points);
hypre_ComputePkg *compute_pkg = (residual_data -> 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 *x_data_box;
hypre_Box *b_data_box;
hypre_Box *r_data_box;
int Ai;
int xi;
int bi;
int ri;
double *Ap;
double *xp;
double *bp;
double *rp;
hypre_Index loop_size;
hypre_IndexRef start;
hypre_StructStencil *stencil;
hypre_Index *stencil_shape;
int stencil_size;
int compute_i, i, j, si;
int loopi, loopj, loopk;
hypre_BeginTiming(residual_data -> time_index);
/*-----------------------------------------------------------------------
* Compute residual r = b - Ax
*-----------------------------------------------------------------------*/
stencil = hypre_StructMatrixStencil(A);
stencil_shape = hypre_StructStencilShape(stencil);
stencil_size = hypre_StructStencilSize(stencil);
for (compute_i = 0; compute_i < 2; compute_i++)
{
switch(compute_i)
{
case 0:
{
xp = hypre_StructVectorData(x);
hypre_InitializeIndtComputations(compute_pkg, xp, &comm_handle);
compute_box_aa = hypre_ComputePkgIndtBoxes(compute_pkg);
/*----------------------------------------
* Copy b into r
*----------------------------------------*/
compute_box_a = base_points;
hypre_ForBoxI(i, compute_box_a)
{
compute_box = hypre_BoxArrayBox(compute_box_a, i);
start = hypre_BoxIMin(compute_box);
b_data_box =
hypre_BoxArrayBox(hypre_StructVectorDataSpace(b), i);
r_data_box =
hypre_BoxArrayBox(hypre_StructVectorDataSpace(r), i);
bp = hypre_StructVectorBoxData(b, i);
rp = hypre_StructVectorBoxData(r, i);
hypre_BoxGetStrideSize(compute_box, base_stride, loop_size);
hypre_BoxLoop2Begin(loop_size,
b_data_box, start, base_stride, bi,
r_data_box, start, base_stride, ri);
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,bi,ri
#include "hypre_box_smp_forloop.h"
hypre_BoxLoop2For(loopi, loopj, loopk, bi, ri)
{
rp[ri] = bp[bi];
}
hypre_BoxLoop2End(bi, ri);
}
}
break;
case 1:
{
hypre_FinalizeIndtComputations(comm_handle);
compute_box_aa = hypre_ComputePkgDeptBoxes(compute_pkg);
}
break;
}
/*--------------------------------------------------------------------
* Compute r -= A*x
*--------------------------------------------------------------------*/
hypre_ForBoxArrayI(i, compute_box_aa)
{
compute_box_a = hypre_BoxArrayArrayBoxArray(compute_box_aa, i);
A_data_box = hypre_BoxArrayBox(hypre_StructMatrixDataSpace(A), i);
x_data_box = hypre_BoxArrayBox(hypre_StructVectorDataSpace(x), i);
r_data_box = hypre_BoxArrayBox(hypre_StructVectorDataSpace(r), i);
rp = hypre_StructVectorBoxData(r, i);
hypre_ForBoxI(j, compute_box_a)
{
compute_box = hypre_BoxArrayBox(compute_box_a, j);
start = hypre_BoxIMin(compute_box);
for (si = 0; si < stencil_size; si++)
{
Ap = hypre_StructMatrixBoxData(A, i, si);
xp = hypre_StructVectorBoxData(x, i) +
hypre_BoxOffsetDistance(x_data_box, stencil_shape[si]);
hypre_BoxGetStrideSize(compute_box, base_stride,
loop_size);
hypre_BoxLoop3Begin(loop_size,
A_data_box, start, base_stride, Ai,
x_data_box, start, base_stride, xi,
r_data_box, start, base_stride, ri);
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,Ai,xi,ri
#include "hypre_box_smp_forloop.h"
hypre_BoxLoop3For(loopi, loopj, loopk, Ai, xi, ri)
{
rp[ri] -= Ap[Ai] * xp[xi];
}
hypre_BoxLoop3End(Ai, xi, ri);
}
}
}
}
/*-----------------------------------------------------------------------
* Return
*-----------------------------------------------------------------------*/
hypre_IncFLOPCount(residual_data -> flops);
hypre_EndTiming(residual_data -> time_index);
return ierr;
}
/*--------------------------------------------------------------------------
* hypre_SMGResidualSetBase
*--------------------------------------------------------------------------*/
int
hypre_SMGResidualSetBase( void *residual_vdata,
hypre_Index base_index,
hypre_Index base_stride )
{
hypre_SMGResidualData *residual_data = residual_vdata;
int d;
int ierr = 0;
for (d = 0; d < 3; d++)
{
hypre_IndexD((residual_data -> base_index), d)
= hypre_IndexD(base_index, d);
hypre_IndexD((residual_data -> base_stride), d)
= hypre_IndexD(base_stride, d);
}
return ierr;
}
/*--------------------------------------------------------------------------
* hypre_SMGResidualDestroy
*--------------------------------------------------------------------------*/
int
hypre_SMGResidualDestroy( void *residual_vdata )
{
int ierr = 0;
hypre_SMGResidualData *residual_data = residual_vdata;
if (residual_data)
{
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_TFree(residual_data);
}
return ierr;
}