334 lines
11 KiB
C
334 lines
11 KiB
C
/*BHEADER**********************************************************************
|
|
* (c) 2000 The Regents of the University of California
|
|
*
|
|
* See the file COPYRIGHT_and_DISCLAIMER for a complete copyright
|
|
* notice, contact person, and disclaimer.
|
|
*
|
|
* $Revision$
|
|
*********************************************************************EHEADER*/
|
|
/******************************************************************************
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "headers.h"
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_SemiInterpData data structure
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
typedef struct
|
|
{
|
|
hypre_StructMatrix *P;
|
|
int P_stored_as_transpose;
|
|
hypre_ComputePkg *compute_pkg;
|
|
hypre_Index cindex;
|
|
hypre_Index findex;
|
|
hypre_Index stride;
|
|
|
|
int time_index;
|
|
|
|
} hypre_SemiInterpData;
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_SemiInterpCreate
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void *
|
|
hypre_SemiInterpCreate( )
|
|
{
|
|
hypre_SemiInterpData *interp_data;
|
|
|
|
interp_data = hypre_CTAlloc(hypre_SemiInterpData, 1);
|
|
(interp_data -> time_index) = hypre_InitializeTiming("SemiInterp");
|
|
|
|
return (void *) interp_data;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_SemiInterpSetup
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
int
|
|
hypre_SemiInterpSetup( void *interp_vdata,
|
|
hypre_StructMatrix *P,
|
|
int P_stored_as_transpose,
|
|
hypre_StructVector *xc,
|
|
hypre_StructVector *e,
|
|
hypre_Index cindex,
|
|
hypre_Index findex,
|
|
hypre_Index stride )
|
|
{
|
|
hypre_SemiInterpData *interp_data = interp_vdata;
|
|
|
|
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_ComputePkg *compute_pkg;
|
|
|
|
int ierr = 0;
|
|
|
|
/*----------------------------------------------------------
|
|
* Set up the compute package
|
|
*----------------------------------------------------------*/
|
|
|
|
grid = hypre_StructVectorGrid(e);
|
|
stencil = hypre_StructMatrixStencil(P);
|
|
|
|
hypre_CreateComputeInfo(grid, stencil,
|
|
&send_boxes, &recv_boxes,
|
|
&send_processes, &recv_processes,
|
|
&indt_boxes, &dept_boxes);
|
|
|
|
hypre_ProjectBoxArrayArray(send_boxes, cindex, stride);
|
|
hypre_ProjectBoxArrayArray(recv_boxes, cindex, stride);
|
|
hypre_ProjectBoxArrayArray(indt_boxes, findex, stride);
|
|
hypre_ProjectBoxArrayArray(dept_boxes, findex, stride);
|
|
|
|
hypre_ComputePkgCreate(send_boxes, recv_boxes,
|
|
stride, stride,
|
|
send_processes, recv_processes,
|
|
indt_boxes, dept_boxes,
|
|
stride, grid,
|
|
hypre_StructVectorDataSpace(e), 1,
|
|
&compute_pkg);
|
|
|
|
/*----------------------------------------------------------
|
|
* Set up the interp data structure
|
|
*----------------------------------------------------------*/
|
|
|
|
(interp_data -> P) = hypre_StructMatrixRef(P);
|
|
(interp_data -> P_stored_as_transpose) = P_stored_as_transpose;
|
|
(interp_data -> compute_pkg) = compute_pkg;
|
|
hypre_CopyIndex(cindex, (interp_data -> cindex));
|
|
hypre_CopyIndex(findex, (interp_data -> findex));
|
|
hypre_CopyIndex(stride, (interp_data -> stride));
|
|
|
|
return ierr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_SemiInterp:
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
int
|
|
hypre_SemiInterp( void *interp_vdata,
|
|
hypre_StructMatrix *P,
|
|
hypre_StructVector *xc,
|
|
hypre_StructVector *e )
|
|
{
|
|
int ierr = 0;
|
|
|
|
hypre_SemiInterpData *interp_data = interp_vdata;
|
|
|
|
int P_stored_as_transpose;
|
|
hypre_ComputePkg *compute_pkg;
|
|
hypre_IndexRef cindex;
|
|
hypre_IndexRef findex;
|
|
hypre_IndexRef stride;
|
|
|
|
hypre_StructGrid *fgrid;
|
|
int *fgrid_ids;
|
|
hypre_StructGrid *cgrid;
|
|
hypre_BoxArray *cgrid_boxes;
|
|
int *cgrid_ids;
|
|
|
|
hypre_CommHandle *comm_handle;
|
|
|
|
hypre_BoxArrayArray *compute_box_aa;
|
|
hypre_BoxArray *compute_box_a;
|
|
hypre_Box *compute_box;
|
|
|
|
hypre_Box *P_dbox;
|
|
hypre_Box *xc_dbox;
|
|
hypre_Box *e_dbox;
|
|
|
|
int Pi;
|
|
int xci;
|
|
int ei;
|
|
|
|
double *Pp0, *Pp1;
|
|
double *xcp;
|
|
double *ep, *ep0, *ep1;
|
|
|
|
hypre_Index loop_size;
|
|
hypre_Index start;
|
|
hypre_Index startc;
|
|
hypre_Index stridec;
|
|
|
|
hypre_StructStencil *stencil;
|
|
hypre_Index *stencil_shape;
|
|
|
|
int compute_i, fi, ci, j;
|
|
int loopi, loopj, loopk;
|
|
|
|
/*-----------------------------------------------------------------------
|
|
* Initialize some things
|
|
*-----------------------------------------------------------------------*/
|
|
|
|
hypre_BeginTiming(interp_data -> time_index);
|
|
|
|
P_stored_as_transpose = (interp_data -> P_stored_as_transpose);
|
|
compute_pkg = (interp_data -> compute_pkg);
|
|
cindex = (interp_data -> cindex);
|
|
findex = (interp_data -> findex);
|
|
stride = (interp_data -> stride);
|
|
|
|
stencil = hypre_StructMatrixStencil(P);
|
|
stencil_shape = hypre_StructStencilShape(stencil);
|
|
|
|
hypre_SetIndex(stridec, 1, 1, 1);
|
|
|
|
/*-----------------------------------------------------------------------
|
|
* Compute e at coarse points (injection)
|
|
*-----------------------------------------------------------------------*/
|
|
|
|
fgrid = hypre_StructVectorGrid(e);
|
|
fgrid_ids = hypre_StructGridIDs(fgrid);
|
|
cgrid = hypre_StructVectorGrid(xc);
|
|
cgrid_boxes = hypre_StructGridBoxes(cgrid);
|
|
cgrid_ids = hypre_StructGridIDs(cgrid);
|
|
|
|
fi = 0;
|
|
hypre_ForBoxI(ci, cgrid_boxes)
|
|
{
|
|
while (fgrid_ids[fi] != cgrid_ids[ci])
|
|
{
|
|
fi++;
|
|
}
|
|
|
|
compute_box = hypre_BoxArrayBox(cgrid_boxes, ci);
|
|
|
|
hypre_CopyIndex(hypre_BoxIMin(compute_box), startc);
|
|
hypre_StructMapCoarseToFine(startc, cindex, stride, start);
|
|
|
|
e_dbox = hypre_BoxArrayBox(hypre_StructVectorDataSpace(e), fi);
|
|
xc_dbox = hypre_BoxArrayBox(hypre_StructVectorDataSpace(xc), ci);
|
|
|
|
ep = hypre_StructVectorBoxData(e, fi);
|
|
xcp = hypre_StructVectorBoxData(xc, ci);
|
|
|
|
hypre_BoxGetSize(compute_box, loop_size);
|
|
|
|
hypre_BoxLoop2Begin(loop_size,
|
|
e_dbox, start, stride, ei,
|
|
xc_dbox, startc, stridec, xci);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,ei,xci
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop2For(loopi, loopj, loopk, ei, xci)
|
|
{
|
|
ep[ei] = xcp[xci];
|
|
}
|
|
hypre_BoxLoop2End(ei, xci);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
* Compute e at fine points
|
|
*-----------------------------------------------------------------------*/
|
|
|
|
for (compute_i = 0; compute_i < 2; compute_i++)
|
|
{
|
|
switch(compute_i)
|
|
{
|
|
case 0:
|
|
{
|
|
ep = hypre_StructVectorData(e);
|
|
hypre_InitializeIndtComputations(compute_pkg, ep, &comm_handle);
|
|
compute_box_aa = hypre_ComputePkgIndtBoxes(compute_pkg);
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
{
|
|
hypre_FinalizeIndtComputations(comm_handle);
|
|
compute_box_aa = hypre_ComputePkgDeptBoxes(compute_pkg);
|
|
}
|
|
break;
|
|
}
|
|
|
|
hypre_ForBoxArrayI(fi, compute_box_aa)
|
|
{
|
|
compute_box_a = hypre_BoxArrayArrayBoxArray(compute_box_aa, fi);
|
|
|
|
P_dbox = hypre_BoxArrayBox(hypre_StructMatrixDataSpace(P), fi);
|
|
e_dbox = hypre_BoxArrayBox(hypre_StructVectorDataSpace(e), fi);
|
|
|
|
if (P_stored_as_transpose)
|
|
{
|
|
Pp0 = hypre_StructMatrixBoxData(P, fi, 1);
|
|
Pp1 = hypre_StructMatrixBoxData(P, fi, 0) -
|
|
hypre_BoxOffsetDistance(P_dbox, stencil_shape[0]);
|
|
}
|
|
else
|
|
{
|
|
Pp0 = hypre_StructMatrixBoxData(P, fi, 0);
|
|
Pp1 = hypre_StructMatrixBoxData(P, fi, 1);
|
|
}
|
|
ep = hypre_StructVectorBoxData(e, fi);
|
|
ep0 = ep + hypre_BoxOffsetDistance(e_dbox, stencil_shape[0]);
|
|
ep1 = ep + hypre_BoxOffsetDistance(e_dbox, stencil_shape[1]);
|
|
|
|
hypre_ForBoxI(j, compute_box_a)
|
|
{
|
|
compute_box = hypre_BoxArrayBox(compute_box_a, j);
|
|
|
|
hypre_CopyIndex(hypre_BoxIMin(compute_box), start);
|
|
hypre_StructMapFineToCoarse(start, findex, stride, startc);
|
|
|
|
hypre_BoxGetStrideSize(compute_box, stride, loop_size);
|
|
|
|
hypre_BoxLoop2Begin(loop_size,
|
|
P_dbox, startc, stridec, Pi,
|
|
e_dbox, start, stride, ei);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,Pi,ei
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop2For(loopi, loopj, loopk, Pi, ei)
|
|
{
|
|
ep[ei] = (Pp0[Pi] * ep0[ei] +
|
|
Pp1[Pi] * ep1[ei]);
|
|
}
|
|
hypre_BoxLoop2End(Pi, ei);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
* Return
|
|
*-----------------------------------------------------------------------*/
|
|
|
|
hypre_IncFLOPCount(3*hypre_StructVectorGlobalSize(xc));
|
|
hypre_EndTiming(interp_data -> time_index);
|
|
|
|
return ierr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_SemiInterpDestroy
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
int
|
|
hypre_SemiInterpDestroy( void *interp_vdata )
|
|
{
|
|
int ierr = 0;
|
|
|
|
hypre_SemiInterpData *interp_data = interp_vdata;
|
|
|
|
if (interp_data)
|
|
{
|
|
hypre_StructMatrixDestroy(interp_data -> P);
|
|
hypre_ComputePkgDestroy(interp_data -> compute_pkg);
|
|
hypre_FinalizeTiming(interp_data -> time_index);
|
|
hypre_TFree(interp_data);
|
|
}
|
|
|
|
return ierr;
|
|
}
|
|
|