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: }