hypre/sstruct_mv/sstruct_matvec.c
2012-03-06 19:15:29 +00:00

402 lines
13 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*/
/******************************************************************************
*
* SStruct matrix-vector multiply routine
*
*****************************************************************************/
#include "_hypre_sstruct_mv.h"
/*==========================================================================
* PMatvec routines
*==========================================================================*/
/*--------------------------------------------------------------------------
* hypre_SStructPMatvecData data structure
*--------------------------------------------------------------------------*/
typedef struct
{
HYPRE_Int nvars;
void ***smatvec_data;
} hypre_SStructPMatvecData;
/*--------------------------------------------------------------------------
* hypre_SStructPMatvecCreate
*--------------------------------------------------------------------------*/
HYPRE_Int
hypre_SStructPMatvecCreate( void **pmatvec_vdata_ptr )
{
hypre_SStructPMatvecData *pmatvec_data;
pmatvec_data = hypre_CTAlloc(hypre_SStructPMatvecData, 1);
*pmatvec_vdata_ptr = (void *) pmatvec_data;
return hypre_error_flag;
}
/*--------------------------------------------------------------------------
* hypre_SStructPMatvecSetup
*--------------------------------------------------------------------------*/
HYPRE_Int
hypre_SStructPMatvecSetup( void *pmatvec_vdata,
hypre_SStructPMatrix *pA,
hypre_SStructPVector *px )
{
hypre_SStructPMatvecData *pmatvec_data = pmatvec_vdata;
HYPRE_Int nvars;
void ***smatvec_data;
hypre_StructMatrix *sA;
hypre_StructVector *sx;
HYPRE_Int vi, vj;
nvars = hypre_SStructPMatrixNVars(pA);
smatvec_data = hypre_TAlloc(void **, nvars);
for (vi = 0; vi < nvars; vi++)
{
smatvec_data[vi] = hypre_TAlloc(void *, nvars);
for (vj = 0; vj < nvars; vj++)
{
sA = hypre_SStructPMatrixSMatrix(pA, vi, vj);
sx = hypre_SStructPVectorSVector(px, vj);
smatvec_data[vi][vj] = NULL;
if (sA != NULL)
{
smatvec_data[vi][vj] = hypre_StructMatvecCreate();
hypre_StructMatvecSetup(smatvec_data[vi][vj], sA, sx);
}
}
}
(pmatvec_data -> nvars) = nvars;
(pmatvec_data -> smatvec_data) = smatvec_data;
return hypre_error_flag;
}
/*--------------------------------------------------------------------------
* hypre_SStructPMatvecCompute
*--------------------------------------------------------------------------*/
HYPRE_Int
hypre_SStructPMatvecCompute( void *pmatvec_vdata,
double alpha,
hypre_SStructPMatrix *pA,
hypre_SStructPVector *px,
double beta,
hypre_SStructPVector *py )
{
hypre_SStructPMatvecData *pmatvec_data = pmatvec_vdata;
HYPRE_Int nvars = (pmatvec_data -> nvars);
void ***smatvec_data = (pmatvec_data -> smatvec_data);
void *sdata;
hypre_StructMatrix *sA;
hypre_StructVector *sx;
hypre_StructVector *sy;
HYPRE_Int vi, vj;
for (vi = 0; vi < nvars; vi++)
{
sy = hypre_SStructPVectorSVector(py, vi);
/* diagonal block computation */
if (smatvec_data[vi][vi] != NULL)
{
sdata = smatvec_data[vi][vi];
sA = hypre_SStructPMatrixSMatrix(pA, vi, vi);
sx = hypre_SStructPVectorSVector(px, vi);
hypre_StructMatvecCompute(sdata, alpha, sA, sx, beta, sy);
}
else
{
hypre_StructScale(beta, sy);
}
/* off-diagonal block computation */
for (vj = 0; vj < nvars; vj++)
{
if ((smatvec_data[vi][vj] != NULL) && (vj != vi))
{
sdata = smatvec_data[vi][vj];
sA = hypre_SStructPMatrixSMatrix(pA, vi, vj);
sx = hypre_SStructPVectorSVector(px, vj);
hypre_StructMatvecCompute(sdata, alpha, sA, sx, 1.0, sy);
}
}
}
return hypre_error_flag;
}
/*--------------------------------------------------------------------------
* hypre_SStructPMatvecDestroy
*--------------------------------------------------------------------------*/
HYPRE_Int
hypre_SStructPMatvecDestroy( void *pmatvec_vdata )
{
hypre_SStructPMatvecData *pmatvec_data = pmatvec_vdata;
HYPRE_Int nvars;
void ***smatvec_data;
HYPRE_Int vi, vj;
if (pmatvec_data)
{
nvars = (pmatvec_data -> nvars);
smatvec_data = (pmatvec_data -> smatvec_data);
for (vi = 0; vi < nvars; vi++)
{
for (vj = 0; vj < nvars; vj++)
{
if (smatvec_data[vi][vj] != NULL)
{
hypre_StructMatvecDestroy(smatvec_data[vi][vj]);
}
}
hypre_TFree(smatvec_data[vi]);
}
hypre_TFree(smatvec_data);
hypre_TFree(pmatvec_data);
}
return hypre_error_flag;
}
/*--------------------------------------------------------------------------
* hypre_SStructPMatvec
*--------------------------------------------------------------------------*/
HYPRE_Int
hypre_SStructPMatvec( double alpha,
hypre_SStructPMatrix *pA,
hypre_SStructPVector *px,
double beta,
hypre_SStructPVector *py )
{
void *pmatvec_data;
hypre_SStructPMatvecCreate(&pmatvec_data);
hypre_SStructPMatvecSetup(pmatvec_data, pA, px);
hypre_SStructPMatvecCompute(pmatvec_data, alpha, pA, px, beta, py);
hypre_SStructPMatvecDestroy(pmatvec_data);
return hypre_error_flag;
}
/*==========================================================================
* Matvec routines
*==========================================================================*/
/*--------------------------------------------------------------------------
* hypre_SStructMatvecData data structure
*--------------------------------------------------------------------------*/
typedef struct
{
HYPRE_Int nparts;
void **pmatvec_data;
} hypre_SStructMatvecData;
/*--------------------------------------------------------------------------
* hypre_SStructMatvecCreate
*--------------------------------------------------------------------------*/
HYPRE_Int
hypre_SStructMatvecCreate( void **matvec_vdata_ptr )
{
hypre_SStructMatvecData *matvec_data;
matvec_data = hypre_CTAlloc(hypre_SStructMatvecData, 1);
*matvec_vdata_ptr = (void *) matvec_data;
return hypre_error_flag;
}
/*--------------------------------------------------------------------------
* hypre_SStructMatvecSetup
*--------------------------------------------------------------------------*/
HYPRE_Int
hypre_SStructMatvecSetup( void *matvec_vdata,
hypre_SStructMatrix *A,
hypre_SStructVector *x )
{
hypre_SStructMatvecData *matvec_data = matvec_vdata;
HYPRE_Int nparts;
void **pmatvec_data;
hypre_SStructPMatrix *pA;
hypre_SStructPVector *px;
HYPRE_Int part;
nparts = hypre_SStructMatrixNParts(A);
pmatvec_data = hypre_TAlloc(void *, nparts);
for (part = 0; part < nparts; part++)
{
hypre_SStructPMatvecCreate(&pmatvec_data[part]);
pA = hypre_SStructMatrixPMatrix(A, part);
px = hypre_SStructVectorPVector(x, part);
hypre_SStructPMatvecSetup(pmatvec_data[part], pA, px);
}
(matvec_data -> nparts) = nparts;
(matvec_data -> pmatvec_data) = pmatvec_data;
return hypre_error_flag;
}
/*--------------------------------------------------------------------------
* hypre_SStructMatvecCompute
*--------------------------------------------------------------------------*/
HYPRE_Int
hypre_SStructMatvecCompute( void *matvec_vdata,
double alpha,
hypre_SStructMatrix *A,
hypre_SStructVector *x,
double beta,
hypre_SStructVector *y )
{
hypre_SStructMatvecData *matvec_data = matvec_vdata;
HYPRE_Int nparts = (matvec_data -> nparts);
void **pmatvec_data = (matvec_data -> pmatvec_data);
void *pdata;
hypre_SStructPMatrix *pA;
hypre_SStructPVector *px;
hypre_SStructPVector *py;
hypre_ParCSRMatrix *parcsrA = hypre_SStructMatrixParCSRMatrix(A);
hypre_ParVector *parx;
hypre_ParVector *pary;
HYPRE_Int part;
HYPRE_Int x_object_type= hypre_SStructVectorObjectType(x);
HYPRE_Int A_object_type= hypre_SStructMatrixObjectType(A);
if (x_object_type != A_object_type)
{
hypre_error_in_arg(2);
hypre_error_in_arg(3);
return hypre_error_flag;
}
if ( (x_object_type == HYPRE_SSTRUCT) || (x_object_type == HYPRE_STRUCT) )
{
/* do S-matrix computations */
for (part = 0; part < nparts; part++)
{
pdata = pmatvec_data[part];
pA = hypre_SStructMatrixPMatrix(A, part);
px = hypre_SStructVectorPVector(x, part);
py = hypre_SStructVectorPVector(y, part);
hypre_SStructPMatvecCompute(pdata, alpha, pA, px, beta, py);
}
if ( (x_object_type == HYPRE_SSTRUCT) )
{
/* do U-matrix computations */
/* GEC1002 the data chunk pointed by the local-parvectors
* inside the semistruct vectors x and y is now identical to the
* data chunk of the structure vectors x and y. The role of the function
* convert is to pass the addresses of the data chunk
* to the parx and pary. */
hypre_SStructVectorConvert(x, &parx);
hypre_SStructVectorConvert(y, &pary);
hypre_ParCSRMatrixMatvec(alpha, parcsrA, parx, 1.0, pary);
/* dummy functions since there is nothing to restore */
hypre_SStructVectorRestore(x, NULL);
hypre_SStructVectorRestore(y, pary);
parx = NULL;
}
}
else if (x_object_type == HYPRE_PARCSR)
{
hypre_SStructVectorConvert(x, &parx);
hypre_SStructVectorConvert(y, &pary);
hypre_ParCSRMatrixMatvec(alpha, parcsrA, parx, beta, pary);
hypre_SStructVectorRestore(x, NULL);
hypre_SStructVectorRestore(y, pary);
parx = NULL;
}
return hypre_error_flag;
}
/*--------------------------------------------------------------------------
* hypre_SStructMatvecDestroy
*--------------------------------------------------------------------------*/
HYPRE_Int
hypre_SStructMatvecDestroy( void *matvec_vdata )
{
hypre_SStructMatvecData *matvec_data = matvec_vdata;
HYPRE_Int nparts;
void **pmatvec_data;
HYPRE_Int part;
if (matvec_data)
{
nparts = (matvec_data -> nparts);
pmatvec_data = (matvec_data -> pmatvec_data);
for (part = 0; part < nparts; part++)
{
hypre_SStructPMatvecDestroy(pmatvec_data[part]);
}
hypre_TFree(pmatvec_data);
hypre_TFree(matvec_data);
}
return hypre_error_flag;
}
/*--------------------------------------------------------------------------
* hypre_SStructMatvec
*--------------------------------------------------------------------------*/
HYPRE_Int
hypre_SStructMatvec( double alpha,
hypre_SStructMatrix *A,
hypre_SStructVector *x,
double beta,
hypre_SStructVector *y )
{
void *matvec_data;
hypre_SStructMatvecCreate(&matvec_data);
hypre_SStructMatvecSetup(matvec_data, A, x);
hypre_SStructMatvecCompute(matvec_data, alpha, A, x, beta, y);
hypre_SStructMatvecDestroy(matvec_data);
return hypre_error_flag;
}