1245 lines
42 KiB
C
1245 lines
42 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*/
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
* Cyclic reduction algorithm (coded as if it were a 1D MG method)
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "headers.h"
|
|
|
|
#define DEBUG 0
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* Macros
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
#define hypre_CycRedSetCIndex(base_index, base_stride, level, cdir, cindex) \
|
|
{\
|
|
if (level > 0)\
|
|
hypre_SetIndex(cindex, 0, 0, 0);\
|
|
else\
|
|
hypre_CopyIndex(base_index, cindex);\
|
|
hypre_IndexD(cindex, cdir) += 0;\
|
|
}
|
|
|
|
#define hypre_CycRedSetFIndex(base_index, base_stride, level, cdir, findex) \
|
|
{\
|
|
if (level > 0)\
|
|
hypre_SetIndex(findex, 0, 0, 0);\
|
|
else\
|
|
hypre_CopyIndex(base_index, findex);\
|
|
hypre_IndexD(findex, cdir) += 1;\
|
|
}
|
|
|
|
#define hypre_CycRedSetStride(base_index, base_stride, level, cdir, stride) \
|
|
{\
|
|
if (level > 0)\
|
|
hypre_SetIndex(stride, 1, 1, 1);\
|
|
else\
|
|
hypre_CopyIndex(base_stride, stride);\
|
|
hypre_IndexD(stride, cdir) *= 2;\
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_CyclicReductionData data structure
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
typedef struct
|
|
{
|
|
MPI_Comm comm;
|
|
|
|
int num_levels;
|
|
|
|
int cdir; /* coarsening direction */
|
|
hypre_Index base_index;
|
|
hypre_Index base_stride;
|
|
|
|
hypre_StructGrid **grid_l;
|
|
|
|
hypre_BoxArray *base_points;
|
|
hypre_BoxArray **fine_points_l;
|
|
|
|
double *data;
|
|
hypre_StructMatrix **A_l;
|
|
hypre_StructVector **x_l;
|
|
|
|
hypre_ComputePkg **down_compute_pkg_l;
|
|
hypre_ComputePkg **up_compute_pkg_l;
|
|
|
|
int time_index;
|
|
int solve_flops;
|
|
|
|
} hypre_CyclicReductionData;
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_CyclicReductionCreate
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
void *
|
|
hypre_CyclicReductionCreate( MPI_Comm comm )
|
|
{
|
|
hypre_CyclicReductionData *cyc_red_data;
|
|
|
|
cyc_red_data = hypre_CTAlloc(hypre_CyclicReductionData, 1);
|
|
|
|
(cyc_red_data -> comm) = comm;
|
|
(cyc_red_data -> cdir) = 0;
|
|
(cyc_red_data -> time_index) = hypre_InitializeTiming("CyclicReduction");
|
|
|
|
/* set defaults */
|
|
hypre_SetIndex((cyc_red_data -> base_index), 0, 0, 0);
|
|
hypre_SetIndex((cyc_red_data -> base_stride), 1, 1, 1);
|
|
|
|
return (void *) cyc_red_data;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_CycRedCreateCoarseOp
|
|
*
|
|
* NOTE: This routine assumes that domain boundary ghost zones (i.e., ghost
|
|
* zones that do not intersect the grid) have the identity equation in them.
|
|
* This is currently insured by the MatrixAssemble routine.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
hypre_StructMatrix *
|
|
hypre_CycRedCreateCoarseOp( hypre_StructMatrix *A,
|
|
hypre_StructGrid *coarse_grid,
|
|
int cdir )
|
|
{
|
|
hypre_StructMatrix *Ac;
|
|
|
|
hypre_Index *Ac_stencil_shape;
|
|
hypre_StructStencil *Ac_stencil;
|
|
int Ac_stencil_size;
|
|
int Ac_stencil_dim;
|
|
int Ac_num_ghost[] = {0, 0, 0, 0, 0, 0};
|
|
|
|
int i;
|
|
int stencil_rank;
|
|
|
|
Ac_stencil_dim = 1;
|
|
|
|
/*-----------------------------------------------
|
|
* Define Ac_stencil
|
|
*-----------------------------------------------*/
|
|
|
|
stencil_rank = 0;
|
|
|
|
/*-----------------------------------------------
|
|
* non-symmetric case:
|
|
*
|
|
* 3 point fine grid stencil produces 3 point Ac
|
|
*-----------------------------------------------*/
|
|
|
|
if (!hypre_StructMatrixSymmetric(A))
|
|
{
|
|
Ac_stencil_size = 3;
|
|
Ac_stencil_shape = hypre_CTAlloc(hypre_Index, Ac_stencil_size);
|
|
for (i = -1; i < 2; i++)
|
|
{
|
|
/* Storage for 3 elements (c,w,e) */
|
|
hypre_SetIndex(Ac_stencil_shape[stencil_rank],i,0,0);
|
|
stencil_rank++;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------
|
|
* symmetric case:
|
|
*
|
|
* 3 point fine grid stencil produces 3 point Ac
|
|
*
|
|
* Only store the lower triangular part + diagonal = 2 entries,
|
|
* lower triangular means the lower triangular part on the matrix
|
|
* in the standard lexicalgraphic ordering.
|
|
*-----------------------------------------------*/
|
|
|
|
else
|
|
{
|
|
Ac_stencil_size = 2;
|
|
Ac_stencil_shape = hypre_CTAlloc(hypre_Index, Ac_stencil_size);
|
|
for (i = -1; i < 1; i++)
|
|
{
|
|
|
|
/* Storage for 2 elements in (c,w) */
|
|
hypre_SetIndex(Ac_stencil_shape[stencil_rank],i,0,0);
|
|
stencil_rank++;
|
|
}
|
|
}
|
|
|
|
Ac_stencil = hypre_StructStencilCreate(Ac_stencil_dim, Ac_stencil_size,
|
|
Ac_stencil_shape);
|
|
|
|
Ac = hypre_StructMatrixCreate(hypre_StructMatrixComm(A),
|
|
coarse_grid, Ac_stencil);
|
|
|
|
hypre_StructStencilDestroy(Ac_stencil);
|
|
|
|
/*-----------------------------------------------
|
|
* Coarse operator in symmetric iff fine operator is
|
|
*-----------------------------------------------*/
|
|
|
|
hypre_StructMatrixSymmetric(Ac) = hypre_StructMatrixSymmetric(A);
|
|
|
|
/*-----------------------------------------------
|
|
* Set number of ghost points
|
|
*-----------------------------------------------*/
|
|
|
|
Ac_num_ghost[2*cdir] = 1;
|
|
if (!hypre_StructMatrixSymmetric(A))
|
|
{
|
|
Ac_num_ghost[2*cdir + 1] = 1;
|
|
}
|
|
hypre_StructMatrixSetNumGhost(Ac, Ac_num_ghost);
|
|
|
|
hypre_StructMatrixInitializeShell(Ac);
|
|
|
|
return Ac;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_CycRedSetupCoarseOp
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
int
|
|
hypre_CycRedSetupCoarseOp( hypre_StructMatrix *A,
|
|
hypre_StructMatrix *Ac,
|
|
hypre_Index cindex,
|
|
hypre_Index cstride )
|
|
|
|
{
|
|
hypre_Index index;
|
|
|
|
hypre_StructGrid *fgrid;
|
|
int *fgrid_ids;
|
|
hypre_StructGrid *cgrid;
|
|
hypre_BoxArray *cgrid_boxes;
|
|
int *cgrid_ids;
|
|
hypre_Box *cgrid_box;
|
|
hypre_IndexRef cstart;
|
|
hypre_Index stridec;
|
|
hypre_Index fstart;
|
|
hypre_IndexRef stridef;
|
|
hypre_Index loop_size;
|
|
|
|
int fi, ci;
|
|
int loopi, loopj, loopk;
|
|
|
|
hypre_Box *A_dbox;
|
|
hypre_Box *Ac_dbox;
|
|
|
|
double *a_cc, *a_cw, *a_ce;
|
|
double *ac_cc, *ac_cw, *ac_ce;
|
|
|
|
int iA, iAm1, iAp1;
|
|
int iAc;
|
|
|
|
int xOffsetA;
|
|
|
|
int ierr = 0;
|
|
|
|
stridef = cstride;
|
|
hypre_SetIndex(stridec, 1, 1, 1);
|
|
|
|
fgrid = hypre_StructMatrixGrid(A);
|
|
fgrid_ids = hypre_StructGridIDs(fgrid);
|
|
|
|
cgrid = hypre_StructMatrixGrid(Ac);
|
|
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++;
|
|
}
|
|
|
|
cgrid_box = hypre_BoxArrayBox(cgrid_boxes, ci);
|
|
|
|
cstart = hypre_BoxIMin(cgrid_box);
|
|
hypre_StructMapCoarseToFine(cstart, cindex, cstride, fstart);
|
|
|
|
A_dbox = hypre_BoxArrayBox(hypre_StructMatrixDataSpace(A), fi);
|
|
Ac_dbox = hypre_BoxArrayBox(hypre_StructMatrixDataSpace(Ac), ci);
|
|
|
|
/*-----------------------------------------------
|
|
* Extract pointers for 3-point fine grid operator:
|
|
*
|
|
* a_cc is pointer for center coefficient
|
|
* a_cw is pointer for west coefficient
|
|
* a_ce is pointer for east coefficient
|
|
*-----------------------------------------------*/
|
|
|
|
hypre_SetIndex(index,0,0,0);
|
|
a_cc = hypre_StructMatrixExtractPointerByIndex(A, fi, index);
|
|
|
|
hypre_SetIndex(index,-1,0,0);
|
|
a_cw = hypre_StructMatrixExtractPointerByIndex(A, fi, index);
|
|
|
|
hypre_SetIndex(index,1,0,0);
|
|
a_ce = hypre_StructMatrixExtractPointerByIndex(A, fi, index);
|
|
|
|
/*-----------------------------------------------
|
|
* Extract pointers for coarse grid operator - always 3-point:
|
|
*
|
|
* If A is symmetric so is Ac. We build only the
|
|
* lower triangular part (plus diagonal).
|
|
*
|
|
* ac_cc is pointer for center coefficient (etc.)
|
|
*-----------------------------------------------*/
|
|
|
|
hypre_SetIndex(index,0,0,0);
|
|
ac_cc = hypre_StructMatrixExtractPointerByIndex(Ac, ci, index);
|
|
|
|
hypre_SetIndex(index,-1,0,0);
|
|
ac_cw = hypre_StructMatrixExtractPointerByIndex(Ac, ci, index);
|
|
|
|
if(!hypre_StructMatrixSymmetric(A))
|
|
{
|
|
hypre_SetIndex(index,1,0,0);
|
|
ac_ce = hypre_StructMatrixExtractPointerByIndex(Ac, ci, index);
|
|
}
|
|
|
|
/*-----------------------------------------------
|
|
* Define offsets for fine grid stencil and interpolation
|
|
*
|
|
* In the BoxLoop below I assume iA and iP refer
|
|
* to data associated with the point which we are
|
|
* building the stencil for. The below offsets
|
|
* are used in refering to data associated with
|
|
* other points.
|
|
*-----------------------------------------------*/
|
|
|
|
hypre_SetIndex(index,1,0,0);
|
|
xOffsetA = hypre_BoxOffsetDistance(A_dbox,index);
|
|
|
|
/*-----------------------------------------------
|
|
* non-symmetric case
|
|
*-----------------------------------------------*/
|
|
|
|
if(!hypre_StructMatrixSymmetric(A))
|
|
{
|
|
hypre_BoxGetSize(cgrid_box, loop_size);
|
|
|
|
hypre_BoxLoop2Begin(loop_size,
|
|
A_dbox, fstart, stridef, iA,
|
|
Ac_dbox, cstart, stridec, iAc);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,iA,iAc,iAm1,iAp1
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop2For(loopi, loopj, loopk, iA, iAc)
|
|
{
|
|
iAm1 = iA - xOffsetA;
|
|
iAp1 = iA + xOffsetA;
|
|
|
|
ac_cw[iAc] = - a_cw[iA] *a_cw[iAm1] / a_cc[iAm1];
|
|
|
|
ac_cc[iAc] = a_cc[iA]
|
|
- a_cw[iA] * a_ce[iAm1] / a_cc[iAm1]
|
|
- a_ce[iA] * a_cw[iAp1] / a_cc[iAp1];
|
|
|
|
ac_ce[iAc] = - a_ce[iA] *a_ce[iAp1] / a_cc[iAp1];
|
|
|
|
}
|
|
hypre_BoxLoop2End(iA, iAc);
|
|
}
|
|
|
|
/*-----------------------------------------------
|
|
* symmetric case
|
|
*-----------------------------------------------*/
|
|
|
|
else
|
|
{
|
|
hypre_BoxGetSize(cgrid_box, loop_size);
|
|
|
|
hypre_BoxLoop2Begin(loop_size,
|
|
A_dbox, fstart, stridef, iA,
|
|
Ac_dbox, cstart, stridec, iAc);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,iA,iAc,iAm1,iAp1
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop2For(loopi, loopj, loopk, iA, iAc)
|
|
{
|
|
iAm1 = iA - xOffsetA;
|
|
iAp1 = iA + xOffsetA;
|
|
|
|
ac_cw[iAc] = - a_cw[iA] *a_cw[iAm1] / a_cc[iAm1];
|
|
|
|
ac_cc[iAc] = a_cc[iA]
|
|
- a_cw[iA] * a_ce[iAm1] / a_cc[iAm1]
|
|
- a_ce[iA] * a_cw[iAp1] / a_cc[iAp1];
|
|
}
|
|
hypre_BoxLoop2End(iA, iAc);
|
|
}
|
|
|
|
} /* end ForBoxI */
|
|
|
|
hypre_StructMatrixAssemble(Ac);
|
|
|
|
/*-----------------------------------------------------------------------
|
|
* Collapse stencil in periodic direction on coarsest grid.
|
|
*-----------------------------------------------------------------------*/
|
|
|
|
if (hypre_IndexX(hypre_StructGridPeriodic(cgrid)) == 1)
|
|
{
|
|
hypre_ForBoxI(ci, cgrid_boxes)
|
|
{
|
|
cgrid_box = hypre_BoxArrayBox(cgrid_boxes, ci);
|
|
|
|
cstart = hypre_BoxIMin(cgrid_box);
|
|
|
|
Ac_dbox = hypre_BoxArrayBox(hypre_StructMatrixDataSpace(Ac), ci);
|
|
|
|
/*-----------------------------------------------
|
|
* Extract pointers for coarse grid operator - always 3-point:
|
|
*
|
|
* If A is symmetric so is Ac. We build only the
|
|
* lower triangular part (plus diagonal).
|
|
*
|
|
* ac_cc is pointer for center coefficient (etc.)
|
|
*-----------------------------------------------*/
|
|
|
|
hypre_SetIndex(index,0,0,0);
|
|
ac_cc = hypre_StructMatrixExtractPointerByIndex(Ac, ci, index);
|
|
|
|
hypre_SetIndex(index,-1,0,0);
|
|
ac_cw = hypre_StructMatrixExtractPointerByIndex(Ac, ci, index);
|
|
|
|
if(!hypre_StructMatrixSymmetric(A))
|
|
{
|
|
hypre_SetIndex(index,1,0,0);
|
|
ac_ce = hypre_StructMatrixExtractPointerByIndex(Ac, ci, index);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------
|
|
* non-symmetric case
|
|
*-----------------------------------------------*/
|
|
|
|
if(!hypre_StructMatrixSymmetric(A))
|
|
{
|
|
hypre_BoxGetSize(cgrid_box, loop_size);
|
|
|
|
hypre_BoxLoop1Begin(loop_size,
|
|
Ac_dbox, cstart, stridec, iAc);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,iAc
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop1For(loopi, loopj, loopk, iAc)
|
|
{
|
|
ac_cc[iAc] += (ac_cw[iAc] + ac_ce[iAc]);
|
|
ac_cw[iAc] = 0.0;
|
|
ac_ce[iAc] = 0.0;
|
|
}
|
|
hypre_BoxLoop1End(iAc);
|
|
}
|
|
|
|
/*-----------------------------------------------
|
|
* symmetric case
|
|
*-----------------------------------------------*/
|
|
|
|
else
|
|
{
|
|
hypre_BoxGetSize(cgrid_box, loop_size);
|
|
|
|
hypre_BoxLoop1Begin(loop_size,
|
|
Ac_dbox, cstart, stridec, iAc);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,iAc
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop1For(loopi, loopj, loopk, iAc)
|
|
{
|
|
ac_cc[iAc] += (2.0 * ac_cw[iAc]);
|
|
ac_cw[iAc] = 0.0;
|
|
}
|
|
hypre_BoxLoop1End(iAc);
|
|
}
|
|
|
|
} /* end ForBoxI */
|
|
|
|
}
|
|
|
|
hypre_StructMatrixAssemble(Ac);
|
|
|
|
return ierr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_CyclicReductionSetup
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
int
|
|
hypre_CyclicReductionSetup( void *cyc_red_vdata,
|
|
hypre_StructMatrix *A,
|
|
hypre_StructVector *b,
|
|
hypre_StructVector *x )
|
|
{
|
|
hypre_CyclicReductionData *cyc_red_data = cyc_red_vdata;
|
|
|
|
MPI_Comm comm = (cyc_red_data -> comm);
|
|
int cdir = (cyc_red_data -> cdir);
|
|
hypre_IndexRef base_index = (cyc_red_data -> base_index);
|
|
hypre_IndexRef base_stride = (cyc_red_data -> base_stride);
|
|
|
|
int num_levels;
|
|
hypre_StructGrid **grid_l;
|
|
hypre_BoxArray *base_points;
|
|
hypre_BoxArray **fine_points_l;
|
|
double *data;
|
|
int data_size = 0;
|
|
hypre_StructMatrix **A_l;
|
|
hypre_StructVector **x_l;
|
|
hypre_ComputePkg **down_compute_pkg_l;
|
|
hypre_ComputePkg **up_compute_pkg_l;
|
|
hypre_ComputeInfo *compute_info;
|
|
|
|
hypre_Index cindex;
|
|
hypre_Index findex;
|
|
hypre_Index stride;
|
|
|
|
hypre_StructGrid *grid;
|
|
|
|
hypre_Box *cbox;
|
|
|
|
int l;
|
|
int flop_divisor;
|
|
|
|
int x_num_ghost[] = {0, 0, 0, 0, 0, 0};
|
|
|
|
int ierr = 0;
|
|
|
|
/*-----------------------------------------------------
|
|
* Set up coarse grids
|
|
*-----------------------------------------------------*/
|
|
|
|
grid = hypre_StructMatrixGrid(A);
|
|
|
|
/* Compute a preliminary num_levels value based on the grid */
|
|
cbox = hypre_BoxDuplicate(hypre_StructGridBoundingBox(grid));
|
|
num_levels = hypre_Log2(hypre_BoxSizeD(cbox, cdir)) + 2;
|
|
|
|
grid_l = hypre_TAlloc(hypre_StructGrid *, num_levels);
|
|
hypre_StructGridRef(grid, &grid_l[0]);
|
|
for (l = 0; ; l++)
|
|
{
|
|
/* set cindex and stride */
|
|
hypre_CycRedSetCIndex(base_index, base_stride, l, cdir, cindex);
|
|
hypre_CycRedSetStride(base_index, base_stride, l, cdir, stride);
|
|
|
|
/* check to see if we should coarsen */
|
|
if ( hypre_BoxIMinD(cbox, cdir) == hypre_BoxIMaxD(cbox, cdir) )
|
|
{
|
|
/* stop coarsening */
|
|
break;
|
|
}
|
|
|
|
/* 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));
|
|
|
|
/* coarsen the grid */
|
|
hypre_StructCoarsen(grid_l[l], cindex, stride, 1, &grid_l[l+1]);
|
|
}
|
|
num_levels = l + 1;
|
|
|
|
/* free up some things */
|
|
hypre_BoxDestroy(cbox);
|
|
|
|
(cyc_red_data -> num_levels) = num_levels;
|
|
(cyc_red_data -> grid_l) = grid_l;
|
|
|
|
/*-----------------------------------------------------
|
|
* Set up base points
|
|
*-----------------------------------------------------*/
|
|
|
|
base_points = hypre_BoxArrayDuplicate(hypre_StructGridBoxes(grid_l[0]));
|
|
hypre_ProjectBoxArray(base_points, base_index, base_stride);
|
|
|
|
(cyc_red_data -> base_points) = base_points;
|
|
|
|
/*-----------------------------------------------------
|
|
* Set up fine points
|
|
*-----------------------------------------------------*/
|
|
|
|
fine_points_l = hypre_TAlloc(hypre_BoxArray *, num_levels);
|
|
|
|
for (l = 0; l < (num_levels - 1); l++)
|
|
{
|
|
hypre_CycRedSetCIndex(base_index, base_stride, l, cdir, cindex);
|
|
hypre_CycRedSetFIndex(base_index, base_stride, l, cdir, findex);
|
|
hypre_CycRedSetStride(base_index, base_stride, l, cdir, stride);
|
|
|
|
fine_points_l[l] =
|
|
hypre_BoxArrayDuplicate(hypre_StructGridBoxes(grid_l[l]));
|
|
hypre_ProjectBoxArray(fine_points_l[l], findex, stride);
|
|
}
|
|
|
|
fine_points_l[l] =
|
|
hypre_BoxArrayDuplicate(hypre_StructGridBoxes(grid_l[l]));
|
|
if (num_levels == 1)
|
|
{
|
|
hypre_ProjectBoxArray(fine_points_l[l], base_index, base_stride);
|
|
}
|
|
|
|
(cyc_red_data -> fine_points_l) = fine_points_l;
|
|
|
|
/*-----------------------------------------------------
|
|
* Set up matrix and vector structures
|
|
*-----------------------------------------------------*/
|
|
|
|
A_l = hypre_TAlloc(hypre_StructMatrix *, num_levels);
|
|
x_l = hypre_TAlloc(hypre_StructVector *, num_levels);
|
|
|
|
A_l[0] = hypre_StructMatrixRef(A);
|
|
x_l[0] = hypre_StructVectorRef(x);
|
|
|
|
x_num_ghost[2*cdir] = 1;
|
|
x_num_ghost[2*cdir + 1] = 1;
|
|
|
|
for (l = 0; l < (num_levels - 1); l++)
|
|
{
|
|
A_l[l+1] = hypre_CycRedCreateCoarseOp(A_l[l], grid_l[l+1], cdir);
|
|
data_size += hypre_StructMatrixDataSize(A_l[l+1]);
|
|
|
|
x_l[l+1] = hypre_StructVectorCreate(comm, grid_l[l+1]);
|
|
hypre_StructVectorSetNumGhost(x_l[l+1], x_num_ghost);
|
|
hypre_StructVectorInitializeShell(x_l[l+1]);
|
|
data_size += hypre_StructVectorDataSize(x_l[l+1]);
|
|
}
|
|
|
|
data = hypre_SharedCTAlloc(double, data_size);
|
|
|
|
(cyc_red_data -> data) = data;
|
|
|
|
for (l = 0; l < (num_levels - 1); l++)
|
|
{
|
|
hypre_StructMatrixInitializeData(A_l[l+1], data);
|
|
data += hypre_StructMatrixDataSize(A_l[l+1]);
|
|
hypre_StructVectorInitializeData(x_l[l+1], data);
|
|
hypre_StructVectorAssemble(x_l[l+1]);
|
|
data += hypre_StructVectorDataSize(x_l[l+1]);
|
|
}
|
|
|
|
(cyc_red_data -> A_l) = A_l;
|
|
(cyc_red_data -> x_l) = x_l;
|
|
|
|
/*-----------------------------------------------------
|
|
* Set up coarse grid operators
|
|
*-----------------------------------------------------*/
|
|
|
|
for (l = 0; l < (num_levels - 1); l++)
|
|
{
|
|
hypre_CycRedSetCIndex(base_index, base_stride, l, cdir, cindex);
|
|
hypre_CycRedSetStride(base_index, base_stride, l, cdir, stride);
|
|
|
|
hypre_CycRedSetupCoarseOp(A_l[l], A_l[l+1], cindex, stride);
|
|
}
|
|
|
|
/*----------------------------------------------------------
|
|
* Set up compute packages
|
|
*----------------------------------------------------------*/
|
|
|
|
down_compute_pkg_l = hypre_TAlloc(hypre_ComputePkg *, (num_levels - 1));
|
|
up_compute_pkg_l = hypre_TAlloc(hypre_ComputePkg *, (num_levels - 1));
|
|
|
|
for (l = 0; l < (num_levels - 1); l++)
|
|
{
|
|
hypre_CycRedSetCIndex(base_index, base_stride, l, cdir, cindex);
|
|
hypre_CycRedSetFIndex(base_index, base_stride, l, cdir, findex);
|
|
hypre_CycRedSetStride(base_index, base_stride, l, cdir, stride);
|
|
|
|
/* down-cycle */
|
|
hypre_CreateComputeInfo(grid_l[l], hypre_StructMatrixStencil(A_l[l]),
|
|
&compute_info);
|
|
hypre_ComputeInfoProjectSend(compute_info, findex, stride);
|
|
hypre_ComputeInfoProjectRecv(compute_info, findex, stride);
|
|
hypre_ComputeInfoProjectComp(compute_info, cindex, stride);
|
|
hypre_ComputePkgCreate(compute_info,
|
|
hypre_StructVectorDataSpace(x_l[l]), 1,
|
|
grid_l[l], &down_compute_pkg_l[l]);
|
|
|
|
/* up-cycle */
|
|
hypre_CreateComputeInfo(grid_l[l], hypre_StructMatrixStencil(A_l[l]),
|
|
&compute_info);
|
|
hypre_ComputeInfoProjectSend(compute_info, cindex, stride);
|
|
hypre_ComputeInfoProjectRecv(compute_info, cindex, stride);
|
|
hypre_ComputeInfoProjectComp(compute_info, findex, stride);
|
|
hypre_ComputePkgCreate(compute_info,
|
|
hypre_StructVectorDataSpace(x_l[l]), 1,
|
|
grid_l[l], &up_compute_pkg_l[l]);
|
|
}
|
|
|
|
(cyc_red_data -> down_compute_pkg_l) = down_compute_pkg_l;
|
|
(cyc_red_data -> up_compute_pkg_l) = up_compute_pkg_l;
|
|
|
|
/*-----------------------------------------------------
|
|
* Compute solve flops
|
|
*-----------------------------------------------------*/
|
|
|
|
flop_divisor = (hypre_IndexX(base_stride) *
|
|
hypre_IndexY(base_stride) *
|
|
hypre_IndexZ(base_stride) );
|
|
(cyc_red_data -> solve_flops) =
|
|
hypre_StructVectorGlobalSize(x_l[0])/2/flop_divisor;
|
|
(cyc_red_data -> solve_flops) +=
|
|
5*hypre_StructVectorGlobalSize(x_l[0])/2/flop_divisor;
|
|
for (l = 1; l < (num_levels - 1); l++)
|
|
{
|
|
(cyc_red_data -> solve_flops) +=
|
|
10*hypre_StructVectorGlobalSize(x_l[l])/2;
|
|
}
|
|
|
|
if (num_levels > 1)
|
|
{
|
|
(cyc_red_data -> solve_flops) +=
|
|
hypre_StructVectorGlobalSize(x_l[l])/2;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------
|
|
* Finalize some things
|
|
*-----------------------------------------------------*/
|
|
|
|
#if DEBUG
|
|
{
|
|
char filename[255];
|
|
|
|
/* debugging stuff */
|
|
for (l = 0; l < num_levels; l++)
|
|
{
|
|
sprintf(filename, "yout_A.%02d", l);
|
|
hypre_StructMatrixPrint(filename, A_l[l], 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return ierr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_CyclicReduction
|
|
*
|
|
* The solution vectors on each level are also used to store the
|
|
* right-hand-side data. We can do this because of the red-black
|
|
* nature of the algorithm and the fact that the method is exact,
|
|
* allowing one to assume initial guesses of zero on all grid levels.
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
int
|
|
hypre_CyclicReduction( void *cyc_red_vdata,
|
|
hypre_StructMatrix *A,
|
|
hypre_StructVector *b,
|
|
hypre_StructVector *x )
|
|
{
|
|
hypre_CyclicReductionData *cyc_red_data = cyc_red_vdata;
|
|
|
|
int num_levels = (cyc_red_data -> num_levels);
|
|
int cdir = (cyc_red_data -> cdir);
|
|
hypre_IndexRef base_index = (cyc_red_data -> base_index);
|
|
hypre_IndexRef base_stride = (cyc_red_data -> base_stride);
|
|
hypre_BoxArray *base_points = (cyc_red_data -> base_points);
|
|
hypre_BoxArray **fine_points_l = (cyc_red_data -> fine_points_l);
|
|
hypre_StructMatrix **A_l = (cyc_red_data -> A_l);
|
|
hypre_StructVector **x_l = (cyc_red_data -> x_l);
|
|
hypre_ComputePkg **down_compute_pkg_l =
|
|
(cyc_red_data -> down_compute_pkg_l);
|
|
hypre_ComputePkg **up_compute_pkg_l =
|
|
(cyc_red_data -> up_compute_pkg_l);
|
|
|
|
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 *A_dbox;
|
|
hypre_Box *x_dbox;
|
|
hypre_Box *b_dbox;
|
|
hypre_Box *xc_dbox;
|
|
|
|
double *Ap, *Awp, *Aep;
|
|
double *xp, *xwp, *xep;
|
|
double *bp;
|
|
double *xcp;
|
|
|
|
int Ai;
|
|
int xi;
|
|
int bi;
|
|
int xci;
|
|
|
|
hypre_Index cindex;
|
|
hypre_Index stride;
|
|
|
|
hypre_Index index;
|
|
hypre_Index loop_size;
|
|
hypre_Index start;
|
|
hypre_Index startc;
|
|
hypre_Index stridec;
|
|
|
|
int compute_i, fi, ci, j, l;
|
|
int loopi, loopj, loopk;
|
|
|
|
int ierr = 0;
|
|
|
|
hypre_BeginTiming(cyc_red_data -> time_index);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
* Initialize some things
|
|
*--------------------------------------------------*/
|
|
|
|
hypre_SetIndex(stridec, 1, 1, 1);
|
|
|
|
hypre_StructMatrixDestroy(A_l[0]);
|
|
hypre_StructVectorDestroy(x_l[0]);
|
|
A_l[0] = hypre_StructMatrixRef(A);
|
|
x_l[0] = hypre_StructVectorRef(x);
|
|
|
|
/*--------------------------------------------------
|
|
* Copy b into x
|
|
*--------------------------------------------------*/
|
|
|
|
compute_box_a = base_points;
|
|
hypre_ForBoxI(fi, compute_box_a)
|
|
{
|
|
compute_box = hypre_BoxArrayBox(compute_box_a, fi);
|
|
|
|
x_dbox = hypre_BoxArrayBox(hypre_StructVectorDataSpace(x), fi);
|
|
b_dbox = hypre_BoxArrayBox(hypre_StructVectorDataSpace(b), fi);
|
|
|
|
xp = hypre_StructVectorBoxData(x, fi);
|
|
bp = hypre_StructVectorBoxData(b, fi);
|
|
|
|
hypre_CopyIndex(hypre_BoxIMin(compute_box), start);
|
|
hypre_BoxGetStrideSize(compute_box, base_stride, loop_size);
|
|
|
|
hypre_BoxLoop2Begin(loop_size,
|
|
x_dbox, start, base_stride, xi,
|
|
b_dbox, start, base_stride, bi);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,xi,bi
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop2For(loopi, loopj, loopk, xi, bi)
|
|
{
|
|
xp[xi] = bp[bi];
|
|
}
|
|
hypre_BoxLoop2End(xi, bi);
|
|
}
|
|
|
|
/*--------------------------------------------------
|
|
* Down cycle:
|
|
*
|
|
* 1) Do an F-relaxation sweep with zero initial guess
|
|
* 2) Compute and inject residual at C-points
|
|
* - computations are at C-points
|
|
* - communications are at F-points
|
|
*
|
|
* Notes:
|
|
* - Before these two steps are executed, the
|
|
* fine-grid solution vector contains the right-hand-side.
|
|
* - After these two steps are executed, the fine-grid
|
|
* solution vector contains the right-hand side at
|
|
* C-points and the current solution approximation at
|
|
* F-points. The coarse-grid solution vector contains
|
|
* the restricted (injected) fine-grid residual.
|
|
*--------------------------------------------------*/
|
|
|
|
for (l = 0; l < num_levels - 1 ; l++)
|
|
{
|
|
/* set cindex and stride */
|
|
hypre_CycRedSetCIndex(base_index, base_stride, l, cdir, cindex);
|
|
hypre_CycRedSetStride(base_index, base_stride, l, cdir, stride);
|
|
|
|
/* Step 1 */
|
|
compute_box_a = fine_points_l[l];
|
|
hypre_ForBoxI(fi, compute_box_a)
|
|
{
|
|
compute_box = hypre_BoxArrayBox(compute_box_a, fi);
|
|
|
|
A_dbox =
|
|
hypre_BoxArrayBox(hypre_StructMatrixDataSpace(A_l[l]), fi);
|
|
x_dbox =
|
|
hypre_BoxArrayBox(hypre_StructVectorDataSpace(x_l[l]), fi);
|
|
|
|
hypre_SetIndex(index, 0, 0, 0);
|
|
Ap = hypre_StructMatrixExtractPointerByIndex(A_l[l], fi, index);
|
|
xp = hypre_StructVectorBoxData(x_l[l], fi);
|
|
|
|
hypre_CopyIndex(hypre_BoxIMin(compute_box), start);
|
|
hypre_BoxGetStrideSize(compute_box, stride, loop_size);
|
|
|
|
hypre_BoxLoop2Begin(loop_size,
|
|
A_dbox, start, stride, Ai,
|
|
x_dbox, start, stride, xi);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,Ai,xi
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop2For(loopi, loopj, loopk, Ai, xi)
|
|
{
|
|
xp[xi] /= Ap[Ai];
|
|
}
|
|
hypre_BoxLoop2End(Ai, xi);
|
|
}
|
|
|
|
/* Step 2 */
|
|
fgrid = hypre_StructVectorGrid(x_l[l]);
|
|
fgrid_ids = hypre_StructGridIDs(fgrid);
|
|
cgrid = hypre_StructVectorGrid(x_l[l+1]);
|
|
cgrid_boxes = hypre_StructGridBoxes(cgrid);
|
|
cgrid_ids = hypre_StructGridIDs(cgrid);
|
|
for (compute_i = 0; compute_i < 2; compute_i++)
|
|
{
|
|
switch(compute_i)
|
|
{
|
|
case 0:
|
|
{
|
|
xp = hypre_StructVectorData(x_l[l]);
|
|
hypre_InitializeIndtComputations(down_compute_pkg_l[l], xp,
|
|
&comm_handle);
|
|
compute_box_aa =
|
|
hypre_ComputePkgIndtBoxes(down_compute_pkg_l[l]);
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
{
|
|
hypre_FinalizeIndtComputations(comm_handle);
|
|
compute_box_aa =
|
|
hypre_ComputePkgDeptBoxes(down_compute_pkg_l[l]);
|
|
}
|
|
break;
|
|
}
|
|
|
|
fi = 0;
|
|
hypre_ForBoxI(ci, cgrid_boxes)
|
|
{
|
|
while (fgrid_ids[fi] != cgrid_ids[ci])
|
|
{
|
|
fi++;
|
|
}
|
|
|
|
compute_box_a =
|
|
hypre_BoxArrayArrayBoxArray(compute_box_aa, fi);
|
|
|
|
A_dbox =
|
|
hypre_BoxArrayBox(hypre_StructMatrixDataSpace(A_l[l]), fi);
|
|
x_dbox =
|
|
hypre_BoxArrayBox(hypre_StructVectorDataSpace(x_l[l]), fi);
|
|
xc_dbox =
|
|
hypre_BoxArrayBox(hypre_StructVectorDataSpace(x_l[l+1]), ci);
|
|
|
|
xp = hypre_StructVectorBoxData(x_l[l], fi);
|
|
xcp = hypre_StructVectorBoxData(x_l[l+1], ci);
|
|
|
|
hypre_SetIndex(index, -1, 0, 0);
|
|
Awp =
|
|
hypre_StructMatrixExtractPointerByIndex(A_l[l], fi, index);
|
|
xwp = hypre_StructVectorBoxData(x_l[l], fi) +
|
|
hypre_BoxOffsetDistance(x_dbox, index);
|
|
|
|
hypre_SetIndex(index, 1, 0, 0);
|
|
Aep =
|
|
hypre_StructMatrixExtractPointerByIndex(A_l[l], fi, index);
|
|
xep = hypre_StructVectorBoxData(x_l[l], fi) +
|
|
hypre_BoxOffsetDistance(x_dbox, index);
|
|
|
|
hypre_ForBoxI(j, compute_box_a)
|
|
{
|
|
compute_box = hypre_BoxArrayBox(compute_box_a, j);
|
|
|
|
hypre_CopyIndex(hypre_BoxIMin(compute_box), start);
|
|
hypre_StructMapFineToCoarse(start, cindex, stride,
|
|
startc);
|
|
|
|
hypre_BoxGetStrideSize(compute_box, stride, loop_size);
|
|
|
|
hypre_BoxLoop3Begin(loop_size,
|
|
A_dbox, start, stride, Ai,
|
|
x_dbox, start, stride, xi,
|
|
xc_dbox, startc, stridec, xci);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,Ai,xi,xci
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop3For(loopi, loopj, loopk, Ai, xi, xci)
|
|
{
|
|
xcp[xci] = xp[xi] -
|
|
Awp[Ai]*xwp[xi] -
|
|
Aep[Ai]*xep[xi];
|
|
}
|
|
hypre_BoxLoop3End(Ai, xi, xci);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*--------------------------------------------------
|
|
* Coarsest grid:
|
|
*
|
|
* Do an F-relaxation sweep with zero initial guess
|
|
*
|
|
* This is the same as step 1 in above, but is
|
|
* broken out as a sepecial case to add a check
|
|
* for zero diagonal that can occur for singlar
|
|
* problems like the full Neumann problem.
|
|
*--------------------------------------------------*/
|
|
|
|
/* set cindex and stride */
|
|
hypre_CycRedSetCIndex(base_index, base_stride, l, cdir, cindex);
|
|
hypre_CycRedSetStride(base_index, base_stride, l, cdir, stride);
|
|
|
|
compute_box_a = fine_points_l[l];
|
|
hypre_ForBoxI(fi, compute_box_a)
|
|
{
|
|
compute_box = hypre_BoxArrayBox(compute_box_a, fi);
|
|
|
|
A_dbox =
|
|
hypre_BoxArrayBox(hypre_StructMatrixDataSpace(A_l[l]), fi);
|
|
x_dbox =
|
|
hypre_BoxArrayBox(hypre_StructVectorDataSpace(x_l[l]), fi);
|
|
|
|
hypre_SetIndex(index, 0, 0, 0);
|
|
Ap = hypre_StructMatrixExtractPointerByIndex(A_l[l], fi, index);
|
|
xp = hypre_StructVectorBoxData(x_l[l], fi);
|
|
|
|
hypre_CopyIndex(hypre_BoxIMin(compute_box), start);
|
|
hypre_BoxGetStrideSize(compute_box, stride, loop_size);
|
|
|
|
hypre_BoxLoop2Begin(loop_size,
|
|
A_dbox, start, stride, Ai,
|
|
x_dbox, start, stride, xi);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,Ai,xi
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop2For(loopi, loopj, loopk, Ai, xi)
|
|
{
|
|
if (Ap[Ai] != 0.0)
|
|
{
|
|
xp[xi] /= Ap[Ai];
|
|
}
|
|
}
|
|
hypre_BoxLoop2End(Ai, xi);
|
|
}
|
|
|
|
/*--------------------------------------------------
|
|
* Up cycle:
|
|
*
|
|
* 1) Inject coarse error into fine-grid solution
|
|
* vector (this is the solution at the C-points)
|
|
* 2) Do an F-relaxation sweep on Ax = 0 and update
|
|
* solution at F-points
|
|
* - computations are at F-points
|
|
* - communications are at C-points
|
|
*--------------------------------------------------*/
|
|
|
|
for (l = (num_levels - 2); l >= 0; l--)
|
|
{
|
|
/* set cindex and stride */
|
|
hypre_CycRedSetCIndex(base_index, base_stride, l, cdir, cindex);
|
|
hypre_CycRedSetStride(base_index, base_stride, l, cdir, stride);
|
|
|
|
/* Step 1 */
|
|
fgrid = hypre_StructVectorGrid(x_l[l]);
|
|
fgrid_ids = hypre_StructGridIDs(fgrid);
|
|
cgrid = hypre_StructVectorGrid(x_l[l+1]);
|
|
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);
|
|
|
|
x_dbox =
|
|
hypre_BoxArrayBox(hypre_StructVectorDataSpace(x_l[l]), fi);
|
|
xc_dbox =
|
|
hypre_BoxArrayBox(hypre_StructVectorDataSpace(x_l[l+1]), ci);
|
|
|
|
xp = hypre_StructVectorBoxData(x_l[l], fi);
|
|
xcp = hypre_StructVectorBoxData(x_l[l+1], ci);
|
|
|
|
hypre_BoxGetSize(compute_box, loop_size);
|
|
|
|
hypre_BoxLoop2Begin(loop_size,
|
|
x_dbox, start, stride, xi,
|
|
xc_dbox, startc, stridec, xci);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,xi,xci
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop2For(loopi, loopj, loopk, xi, xci)
|
|
{
|
|
xp[xi] = xcp[xci];
|
|
}
|
|
hypre_BoxLoop2End(xi, xci);
|
|
}
|
|
|
|
/* Step 2 */
|
|
for (compute_i = 0; compute_i < 2; compute_i++)
|
|
{
|
|
switch(compute_i)
|
|
{
|
|
case 0:
|
|
{
|
|
xp = hypre_StructVectorData(x_l[l]);
|
|
hypre_InitializeIndtComputations(up_compute_pkg_l[l], xp,
|
|
&comm_handle);
|
|
compute_box_aa =
|
|
hypre_ComputePkgIndtBoxes(up_compute_pkg_l[l]);
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
{
|
|
hypre_FinalizeIndtComputations(comm_handle);
|
|
compute_box_aa =
|
|
hypre_ComputePkgDeptBoxes(up_compute_pkg_l[l]);
|
|
}
|
|
break;
|
|
}
|
|
|
|
hypre_ForBoxArrayI(fi, compute_box_aa)
|
|
{
|
|
compute_box_a =
|
|
hypre_BoxArrayArrayBoxArray(compute_box_aa, fi);
|
|
|
|
A_dbox =
|
|
hypre_BoxArrayBox(hypre_StructMatrixDataSpace(A_l[l]), fi);
|
|
x_dbox =
|
|
hypre_BoxArrayBox(hypre_StructVectorDataSpace(x_l[l]), fi);
|
|
|
|
hypre_SetIndex(index, 0, 0, 0);
|
|
Ap = hypre_StructMatrixExtractPointerByIndex(A_l[l], fi, index);
|
|
xp = hypre_StructVectorBoxData(x_l[l], fi);
|
|
|
|
hypre_SetIndex(index, -1, 0, 0);
|
|
Awp =
|
|
hypre_StructMatrixExtractPointerByIndex(A_l[l], fi, index);
|
|
xwp = hypre_StructVectorBoxData(x_l[l], fi) +
|
|
hypre_BoxOffsetDistance(x_dbox, index);
|
|
|
|
hypre_SetIndex(index, 1, 0, 0);
|
|
Aep =
|
|
hypre_StructMatrixExtractPointerByIndex(A_l[l], fi, index);
|
|
xep = hypre_StructVectorBoxData(x_l[l], fi) +
|
|
hypre_BoxOffsetDistance(x_dbox, index);
|
|
|
|
hypre_ForBoxI(j, compute_box_a)
|
|
{
|
|
compute_box = hypre_BoxArrayBox(compute_box_a, j);
|
|
|
|
hypre_CopyIndex(hypre_BoxIMin(compute_box), start);
|
|
hypre_BoxGetStrideSize(compute_box, stride, loop_size);
|
|
|
|
hypre_BoxLoop2Begin(loop_size,
|
|
A_dbox, start, stride, Ai,
|
|
x_dbox, start, stride, xi);
|
|
#define HYPRE_BOX_SMP_PRIVATE loopk,loopi,loopj,Ai,xi
|
|
#include "hypre_box_smp_forloop.h"
|
|
hypre_BoxLoop2For(loopi, loopj, loopk, Ai, xi)
|
|
{
|
|
xp[xi] -= (Awp[Ai]*xwp[xi] +
|
|
Aep[Ai]*xep[xi] ) / Ap[Ai];
|
|
}
|
|
hypre_BoxLoop2End(Ai, xi);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------
|
|
* Finalize some things
|
|
*-----------------------------------------------------*/
|
|
|
|
hypre_IncFLOPCount(cyc_red_data -> solve_flops);
|
|
hypre_EndTiming(cyc_red_data -> time_index);
|
|
|
|
return ierr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_CyclicReductionSetBase
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
int
|
|
hypre_CyclicReductionSetBase( void *cyc_red_vdata,
|
|
hypre_Index base_index,
|
|
hypre_Index base_stride )
|
|
{
|
|
hypre_CyclicReductionData *cyc_red_data = cyc_red_vdata;
|
|
int d;
|
|
int ierr = 0;
|
|
|
|
for (d = 0; d < 3; d++)
|
|
{
|
|
hypre_IndexD((cyc_red_data -> base_index), d) =
|
|
hypre_IndexD(base_index, d);
|
|
hypre_IndexD((cyc_red_data -> base_stride), d) =
|
|
hypre_IndexD(base_stride, d);
|
|
}
|
|
|
|
return ierr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* hypre_CyclicReductionDestroy
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
int
|
|
hypre_CyclicReductionDestroy( void *cyc_red_vdata )
|
|
{
|
|
hypre_CyclicReductionData *cyc_red_data = cyc_red_vdata;
|
|
|
|
int l;
|
|
int ierr = 0;
|
|
|
|
if (cyc_red_data)
|
|
{
|
|
hypre_BoxArrayDestroy(cyc_red_data -> base_points);
|
|
hypre_StructGridDestroy(cyc_red_data -> grid_l[0]);
|
|
hypre_StructMatrixDestroy(cyc_red_data -> A_l[0]);
|
|
hypre_StructVectorDestroy(cyc_red_data -> x_l[0]);
|
|
for (l = 0; l < ((cyc_red_data -> num_levels) - 1); l++)
|
|
{
|
|
hypre_StructGridDestroy(cyc_red_data -> grid_l[l+1]);
|
|
hypre_BoxArrayDestroy(cyc_red_data -> fine_points_l[l]);
|
|
hypre_StructMatrixDestroy(cyc_red_data -> A_l[l+1]);
|
|
hypre_StructVectorDestroy(cyc_red_data -> x_l[l+1]);
|
|
hypre_ComputePkgDestroy(cyc_red_data -> down_compute_pkg_l[l]);
|
|
hypre_ComputePkgDestroy(cyc_red_data -> up_compute_pkg_l[l]);
|
|
}
|
|
hypre_BoxArrayDestroy(cyc_red_data -> fine_points_l[l]);
|
|
hypre_SharedTFree(cyc_red_data -> data);
|
|
hypre_TFree(cyc_red_data -> grid_l);
|
|
hypre_TFree(cyc_red_data -> fine_points_l);
|
|
hypre_TFree(cyc_red_data -> A_l);
|
|
hypre_TFree(cyc_red_data -> x_l);
|
|
hypre_TFree(cyc_red_data -> down_compute_pkg_l);
|
|
hypre_TFree(cyc_red_data -> up_compute_pkg_l);
|
|
|
|
hypre_FinalizeTiming(cyc_red_data -> time_index);
|
|
hypre_TFree(cyc_red_data);
|
|
}
|
|
|
|
return ierr;
|
|
}
|
|
|