Date: 2013-07-02T14:47:18+00:00

Actual source code: ainvcusp.cu
petsc-3.4.2 2013-07-02

      2: /*  -------------------------------------------------------------------- */

      4: /*
      5:    Include files needed for the CUSP AINV preconditioner:
      6:      pcimpl.h - private include file intended for use by all preconditioners
      7: */

      9: #include <petsc-private/pcimpl.h>   /*I "petscpc.h" I*/
     10: #include <../src/mat/impls/aij/seq/aij.h>
     11: #include <cusp/monitor.h>
     12: #undef VecType
     13: #include <cusp/precond/ainv.h>
     14: #define VecType char*
     15: #include <../src/vec/vec/impls/dvecimpl.h>
     16: #include <../src/mat/impls/aij/seq/seqcusp/cuspmatimpl.h>

     18: #define cuspainvprecondscaled cusp::precond::scaled_bridson_ainv<PetscScalar,cusp::device_memory>
     19: #define cuspainvprecond cusp::precond::bridson_ainv<PetscScalar,cusp::device_memory>

     21: /*
     22:    Private context (data structure) for the CUSP AINV preconditioner.  Note that this only works on CUSP SPD matrices.
     23:  */
     24: typedef struct {
     25:   void      *AINVCUSP;
     26:   PetscBool scaled; /* Whether to use the scaled version of the Bridson AINV or not */

     28:   PetscInt  nonzeros; /* can only use one of nonzeros, droptolerance, linparam at once */
     29:   PetscReal droptolerance;
     30:   PetscInt  linparam;
     31:   PetscBool uselin;
     32: } PC_AINVCUSP;

     34: /* -------------------------------------------------------------------------- */
     35: /*
     36:    PCSetUp_AINVCUSP - Prepares for the use of the CUSP AINV preconditioner
     37:                     by setting data structures and options.

     39:    Input Parameter:
     40: .  pc - the preconditioner context

     42:    Application Interface Routine: PCSetUp()

     44:    Notes:
     45:    The interface routine PCSetUp() is not usually called directly by
     46:    the user, but instead is called by PCApply() if necessary.
     47: */
     50: static PetscErrorCode PCSetUp_AINVCUSP(PC pc)
     51: {
     52:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;
     53:   PetscBool   flg   = PETSC_FALSE;
     54: #if !defined(PETSC_USE_COMPLEX)
     55:   // protect these in order to avoid compiler warnings. This preconditioner does
     56:   // not work for complex types.
     57:   Mat_SeqAIJCUSP *gpustruct;
     58:   CUSPMATRIX     * mat;
     59: #endif

     63:   PetscObjectTypeCompare((PetscObject)pc->pmat,MATSEQAIJCUSP,&flg);
     64:   if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Currently only handles CUSP matrices");
     65:   if (pc->setupcalled != 0) {
     66:     try {
     67:       if (ainv->scaled) delete (cuspainvprecondscaled*)ainv->AINVCUSP;
     68:       else delete (cuspainvprecond*)ainv->AINVCUSP;
     69:     } catch(char *ex) {
     70:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s", ex);
     71:     }
     72:   }
     73:   try {
     74:     MatCUSPCopyToGPU(pc->pmat);
     75: #if defined(PETSC_USE_COMPLEX)
     76:     ainv->AINVCUSP =  0;CHKERRQ(1); /* TODO */
     77: #else
     78:     gpustruct = (Mat_SeqAIJCUSP*)(pc->pmat->spptr);
     79: #if defined(PETSC_HAVE_TXPETSCGPU)
     80:     gpustruct->mat->getCsrMatrix(&mat);CHKERRCUSP(ierr);
     81: #else
     82:     mat = (CUSPMATRIX*)gpustruct->mat;
     83: #endif

     85:     if (ainv->scaled) ainv->AINVCUSP = new cuspainvprecondscaled(*mat, ainv->droptolerance,ainv->nonzeros,ainv->uselin,ainv->linparam);
     86:     else ainv->AINVCUSP = new cuspainvprecond(*mat, ainv->droptolerance,ainv->nonzeros,ainv->uselin,ainv->linparam);
     87: #endif
     88:   } catch(char *ex) {
     89:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s",ex);
     90:   }
     91:   return(0);
     92: }

     94: /* -------------------------------------------------------------------------- */
     95: /*
     96:    PCApply_AINVCUSP - Applies the CUSP AINV preconditioner to a vector.

     98:    Input Parameters:
     99: .  pc - the preconditioner context
    100: .  x - input vector

    102:    Output Parameter:
    103: .  y - output vector

    105:    Application Interface Routine: PCApply()
    106:  */
    109: static PetscErrorCode PCApply_AINVCUSP(PC pc,Vec x,Vec y)
    110: {
    111:   PC_AINVCUSP    *ainv = (PC_AINVCUSP*)pc->data;
    113:   PetscBool      flg1,flg2;
    114:   CUSPARRAY      *xarray=NULL,*yarray=NULL;

    117:   PetscObjectTypeCompare((PetscObject)x,VECSEQCUSP,&flg1);
    118:   PetscObjectTypeCompare((PetscObject)y,VECSEQCUSP,&flg2);
    119:   if (!(flg1 && flg2)) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP, "Currently only handles CUSP vectors");
    120:   if (!ainv->AINVCUSP) {
    121:     PCSetUp_AINVCUSP(pc);
    122:   }
    123:   VecSet(y,0.0);
    124:   VecCUSPGetArrayRead(x,&xarray);
    125:   VecCUSPGetArrayWrite(y,&yarray);
    126:   try {
    127:     if (ainv->scaled) cusp::multiply(*(cuspainvprecondscaled*)ainv->AINVCUSP,*xarray,*yarray);
    128:     else cusp::multiply(*(cuspainvprecond*)ainv->AINVCUSP,*xarray,*yarray);
    129:   } catch(char* ex) {
    130:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s", ex);
    131:   }
    132:   VecCUSPRestoreArrayRead(x,&xarray);
    133:   VecCUSPRestoreArrayWrite(y,&yarray);
    134:   PetscObjectStateIncrease((PetscObject)y);
    135:   return(0);
    136: }
    137: /* -------------------------------------------------------------------------- */

    141: static PetscErrorCode PCReset_AINVCUSP(PC pc)
    142: {
    143:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

    146:   if (ainv->AINVCUSP) {
    147:     try {
    148:       if (ainv->scaled) delete (cuspainvprecondscaled*)ainv->AINVCUSP;
    149:       else delete (cuspainvprecond*)ainv->AINVCUSP;
    150:     } catch(char* ex) {
    151:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s", ex);
    152:     }
    153:     ainv->AINVCUSP = NULL;
    154:   }
    155:   return(0);
    156: }

    158: /*
    159:    PCDestroy_AINVCUSP - Destroys the private context for the AINVCUSP preconditioner
    160:    that was created with PCCreate_AINVCUSP().

    162:    Input Parameter:
    163: .  pc - the preconditioner context

    165:    Application Interface Routine: PCDestroy()
    166: */
    169: static PetscErrorCode PCDestroy_AINVCUSP(PC pc)
    170: {

    174:   PCReset_AINVCUSP(pc);

    176:   /*
    177:       Free the private data structure that was hanging off the PC
    178:   */
    179:   PetscFree(pc->data);
    180:   return(0);
    181: }

    187: static PetscErrorCode PCAINVCUSPSetDropTolerance_AINVCUSP(PC pc, PetscReal droptolerance)
    188: {
    189:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

    192:   ainv->droptolerance = droptolerance;
    193:   ainv->uselin        = PETSC_FALSE;
    194:   ainv->linparam      = 1;
    195:   ainv->nonzeros      = -1;
    196:   return(0);
    197: }

    201: PetscErrorCode PCAINVCUSPSetDropTolerance(PC pc, PetscReal droptolerance)
    202: {

    207:   PetscTryMethod(pc, "PCAINVCUSPSetDropTolerance_C",(PC,PetscReal),(pc,droptolerance));
    208:   return(0);
    209: }
    212: static PetscErrorCode PCAINVCUSPSetNonzeros_AINVCUSP(PC pc, PetscInt nonzeros)
    213: {
    214:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

    217:   ainv->droptolerance = 0;
    218:   ainv->uselin        = PETSC_FALSE;
    219:   ainv->linparam      = 1;
    220:   ainv->nonzeros      = nonzeros;
    221:   return(0);
    222: }

    226: PetscErrorCode PCAINVCUSPSetNonzeros(PC pc, PetscInt nonzeros)
    227: {

    232:   PetscTryMethod(pc, "PCAINVCUSPSetNonzeros_C",(PC,PetscInt),(pc,nonzeros));
    233:   return(0);
    234: }
    237: static PetscErrorCode PCAINVCUSPSetLinParameter_AINVCUSP(PC pc, PetscInt param)
    238: {
    239:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

    242:   ainv->droptolerance = 0;
    243:   ainv->uselin        = PETSC_TRUE;
    244:   ainv->linparam      = param;
    245:   ainv->nonzeros      = -1;
    246:   return(0);
    247: }

    251: PetscErrorCode PCAINVCUSPSetLinParameter(PC pc, PetscInt param)
    252: {

    257:   PetscTryMethod(pc, "PCAINVCUSPSetLinParameter_C",(PC,PetscInt),(pc,param));
    258:   return(0);
    259: }
    262: static PetscErrorCode PCAINVCUSPUseScaling_AINVCUSP(PC pc, PetscBool scaled)
    263: {
    264:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

    267:   ainv->scaled = scaled;
    268:   return(0);
    269: }

    273: PetscErrorCode PCAINVCUSPUseScaling(PC pc, PetscBool scaled)
    274: {

    279:   PetscTryMethod(pc, "PCAINVCUSPUseScaling_C",(PC,PetscBool),(pc,scaled));
    280:   return(0);
    281: }

    285: static PetscErrorCode PCSetFromOptions_AINVCUSP(PC pc)
    286: {
    287:   PC_AINVCUSP    *ainv = (PC_AINVCUSP*)pc->data;
    288:   PetscBool      flag  = PETSC_FALSE;

    292:   PetscOptionsHead("AINVCUSP options");
    293:   PetscOptionsReal("-pc_ainvcusp_droptol","drop tolerance for AINVCUSP preconditioner","PCAINVCUSPSetDropTolerance",ainv->droptolerance,&ainv->droptolerance,&flag);
    294:   if (flag) {
    295:     ainv->nonzeros = -1;
    296:     ainv->uselin   = PETSC_FALSE;
    297:     ainv->linparam = 1;
    298:     flag           = PETSC_FALSE;
    299:   }
    300:   PetscOptionsInt("-pc_ainvcusp_nonzeros","nonzeros/row for AINVCUSP preconditioner","PCAINVCUSPSetNonzeros",ainv->nonzeros,&ainv->nonzeros,&flag);
    301:   if (flag) {
    302:     ainv->droptolerance = 0;
    303:     ainv->uselin        = PETSC_FALSE;
    304:     ainv->linparam      = 1;
    305:     flag                = PETSC_FALSE;
    306:   }
    307:   PetscOptionsInt("-pc_ainvcusp_linparameter","Lin parameter for AINVCUSP preconditioner","PCAINVCUSPSetLinParameter",ainv->linparam,&ainv->linparam,&flag);
    308:   if (flag) {
    309:     ainv->droptolerance = 0;
    310:     ainv->uselin        = PETSC_TRUE;
    311:     ainv->droptolerance = 0;
    312:     ainv->nonzeros      = -1;
    313:   }
    314:   PetscOptionsBool("-pc_ainvcusp_scale","Whether to use scaled AINVCUSP preconditioner or not","PCAINVCUSPUseScaling",ainv->scaled,&ainv->scaled,0);
    315:   PetscOptionsTail();
    316:   return(0);
    317: }

    319: /* -------------------------------------------------------------------------- */

    321: /*MC
    322:      PCAINVCUSP  - A sparse approximate inverse precondition that runs on the Nvidia GPU.

    325:    http://docs.cusp-library.googlecode.com/hg/classcusp_1_1precond_1_1bridson__ainv.html

    327:    Level: advanced

    329: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC

    331: M*/

    335: PETSC_EXTERN PetscErrorCode PCCreate_AINVCUSP(PC pc)
    336: {
    337:   PC_AINVCUSP    *ainv;

    341:   /*
    342:      Creates the private data structure for this preconditioner and
    343:      attach it to the PC object.
    344:    */
    345:   PetscNewLog(pc,PC_AINVCUSP,&ainv);
    346:   pc->data            = (void*)ainv;
    347:   ainv->AINVCUSP      = 0;
    348:   ainv->droptolerance = 0.1;
    349:   ainv->nonzeros      = -1;
    350:   ainv->scaled        = PETSC_TRUE;
    351:   ainv->linparam      = 1;
    352:   ainv->uselin        = PETSC_FALSE;
    353:   /*
    354:       Set the pointers for the functions that are provided above.
    355:       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
    356:       are called, they will automatically call these functions.  Note we
    357:       choose not to provide a couple of these functions since they are
    358:       not needed.
    359:   */
    360:   pc->ops->apply               = PCApply_AINVCUSP;
    361:   pc->ops->applytranspose      = 0;
    362:   pc->ops->setup               = PCSetUp_AINVCUSP;
    363:   pc->ops->reset               = PCReset_AINVCUSP;
    364:   pc->ops->destroy             = PCDestroy_AINVCUSP;
    365:   pc->ops->setfromoptions      = PCSetFromOptions_AINVCUSP;
    366:   pc->ops->view                = 0;
    367:   pc->ops->applyrichardson     = 0;
    368:   pc->ops->applysymmetricleft  = 0;
    369:   pc->ops->applysymmetricright = 0;

    371:   PetscObjectComposeFunction((PetscObject)pc, "PCAINVCUSPSetDropTolerance_C", PCAINVCUSPSetDropTolerance_AINVCUSP);
    372:   PetscObjectComposeFunction((PetscObject)pc, "PCAINVCUSPUseScaling_C",  PCAINVCUSPUseScaling_AINVCUSP);
    373:   PetscObjectComposeFunction((PetscObject)pc, "PCAINVCUSPSetLinParameter_C", PCAINVCUSPSetLinParameter_AINVCUSP);
    374:   PetscObjectComposeFunction((PetscObject)pc, "PCAINVCUSPSetNonzeros_C",  PCAINVCUSPSetNonzeros_AINVCUSP);
    375:   return(0);
    376: }