Actual source code: ainvcusp.cu

petsc-3.8.3 2017-12-09
Report Typos and Errors

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

  4: /*
  5:    Include files needed for the CUSP AINV preconditioner:
  6:      pcimpl.h - private include file intended for use by all preconditioners
  7: */
  8: #define PETSC_SKIP_SPINLOCK
  9:  #include <petsc/private/pcimpl.h>
 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>
 17:  #include <../src/vec/vec/impls/seq/seqcusp/cuspvecimpl.h>

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

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

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

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

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

 43:    Application Interface Routine: PCSetUp()

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

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

 78:    if (gpustruct->format==MAT_CUSP_ELL) {
 79:       CUSPMATRIXELL *mat = (CUSPMATRIXELL*)gpustruct->mat;
 80:       if (ainv->scaled) ainv->AINVCUSP = new cuspainvprecondscaled(*mat, ainv->droptolerance,ainv->nonzeros,ainv->uselin,ainv->linparam);
 81:       else ainv->AINVCUSP = new cuspainvprecond(*mat, ainv->droptolerance,ainv->nonzeros,ainv->uselin,ainv->linparam);
 82:     } else if (gpustruct->format==MAT_CUSP_DIA) {
 83:       CUSPMATRIXDIA *mat = (CUSPMATRIXDIA*)gpustruct->mat;
 84:       if (ainv->scaled) ainv->AINVCUSP = new cuspainvprecondscaled(*mat, ainv->droptolerance,ainv->nonzeros,ainv->uselin,ainv->linparam);
 85:       else ainv->AINVCUSP = new cuspainvprecond(*mat, ainv->droptolerance,ainv->nonzeros,ainv->uselin,ainv->linparam);
 86:     } else {
 87:       CUSPMATRIX *mat = (CUSPMATRIX*)gpustruct->mat;
 88:       if (ainv->scaled) ainv->AINVCUSP = new cuspainvprecondscaled(*mat, ainv->droptolerance,ainv->nonzeros,ainv->uselin,ainv->linparam);
 89:       else ainv->AINVCUSP = new cuspainvprecond(*mat, ainv->droptolerance,ainv->nonzeros,ainv->uselin,ainv->linparam);
 90:     }
 91: #endif
 92:   } catch(char *ex) {
 93:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s",ex);
 94:   }
 95:   return(0);
 96: }

 98: /* -------------------------------------------------------------------------- */
 99: /*
100:    PCApply_AINVCUSP - Applies the CUSP AINV preconditioner to a vector.

102:    Input Parameters:
103: .  pc - the preconditioner context
104: .  x - input vector

106:    Output Parameter:
107: .  y - output vector

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

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

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: */
167: static PetscErrorCode PCDestroy_AINVCUSP(PC pc)
168: {

172:   PCReset_AINVCUSP(pc);

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

181: static PetscErrorCode PCAINVCUSPSetDropTolerance_AINVCUSP(PC pc, PetscReal droptolerance)
182: {
183:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

186:   ainv->droptolerance = droptolerance;
187:   ainv->uselin        = PETSC_FALSE;
188:   ainv->linparam      = 1;
189:   ainv->nonzeros      = -1;
190:   return(0);
191: }

193: PetscErrorCode PCAINVCUSPSetDropTolerance(PC pc, PetscReal droptolerance)
194: {

199:   PetscTryMethod(pc, "PCAINVCUSPSetDropTolerance_C",(PC,PetscReal),(pc,droptolerance));
200:   return(0);
201: }

203: static PetscErrorCode PCAINVCUSPSetNonzeros_AINVCUSP(PC pc, PetscInt nonzeros)
204: {
205:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

208:   ainv->droptolerance = 0;
209:   ainv->uselin        = PETSC_FALSE;
210:   ainv->linparam      = 1;
211:   ainv->nonzeros      = nonzeros;
212:   return(0);
213: }

215: PetscErrorCode PCAINVCUSPSetNonzeros(PC pc, PetscInt nonzeros)
216: {

221:   PetscTryMethod(pc, "PCAINVCUSPSetNonzeros_C",(PC,PetscInt),(pc,nonzeros));
222:   return(0);
223: }

225: static PetscErrorCode PCAINVCUSPSetLinParameter_AINVCUSP(PC pc, PetscInt param)
226: {
227:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

230:   ainv->droptolerance = 0;
231:   ainv->uselin        = PETSC_TRUE;
232:   ainv->linparam      = param;
233:   ainv->nonzeros      = -1;
234:   return(0);
235: }

237: PetscErrorCode PCAINVCUSPSetLinParameter(PC pc, PetscInt param)
238: {

243:   PetscTryMethod(pc, "PCAINVCUSPSetLinParameter_C",(PC,PetscInt),(pc,param));
244:   return(0);
245: }

247: static PetscErrorCode PCAINVCUSPUseScaling_AINVCUSP(PC pc, PetscBool scaled)
248: {
249:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

252:   ainv->scaled = scaled;
253:   return(0);
254: }

256: PetscErrorCode PCAINVCUSPUseScaling(PC pc, PetscBool scaled)
257: {

262:   PetscTryMethod(pc, "PCAINVCUSPUseScaling_C",(PC,PetscBool),(pc,scaled));
263:   return(0);
264: }

266: static PetscErrorCode PCSetFromOptions_AINVCUSP(PetscOptionItems *PetscOptionsObject,PC pc)
267: {
268:   PC_AINVCUSP    *ainv = (PC_AINVCUSP*)pc->data;
269:   PetscBool      flag  = PETSC_FALSE;

273:   PetscOptionsHead(PetscOptionsObject,"AINVCUSP options");
274:   PetscOptionsReal("-pc_ainvcusp_droptol","drop tolerance for AINVCUSP preconditioner","PCAINVCUSPSetDropTolerance",ainv->droptolerance,&ainv->droptolerance,&flag);
275:   if (flag) {
276:     ainv->nonzeros = -1;
277:     ainv->uselin   = PETSC_FALSE;
278:     ainv->linparam = 1;
279:     flag           = PETSC_FALSE;
280:   }
281:   PetscOptionsInt("-pc_ainvcusp_nonzeros","nonzeros/row for AINVCUSP preconditioner","PCAINVCUSPSetNonzeros",ainv->nonzeros,&ainv->nonzeros,&flag);
282:   if (flag) {
283:     ainv->droptolerance = 0;
284:     ainv->uselin        = PETSC_FALSE;
285:     ainv->linparam      = 1;
286:     flag                = PETSC_FALSE;
287:   }
288:   PetscOptionsInt("-pc_ainvcusp_linparameter","Lin parameter for AINVCUSP preconditioner","PCAINVCUSPSetLinParameter",ainv->linparam,&ainv->linparam,&flag);
289:   if (flag) {
290:     ainv->droptolerance = 0;
291:     ainv->uselin        = PETSC_TRUE;
292:     ainv->droptolerance = 0;
293:     ainv->nonzeros      = -1;
294:   }
295:   PetscOptionsBool("-pc_ainvcusp_scale","Whether to use scaled AINVCUSP preconditioner or not","PCAINVCUSPUseScaling",ainv->scaled,&ainv->scaled,0);
296:   PetscOptionsTail();
297:   return(0);
298: }

300: /* -------------------------------------------------------------------------- */

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


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

308:    Level: advanced

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

312: M*/

314: PETSC_EXTERN PetscErrorCode PCCreate_AINVCUSP(PC pc)
315: {
316:   PC_AINVCUSP    *ainv;

320:   /*
321:      Creates the private data structure for this preconditioner and
322:      attach it to the PC object.
323:    */
324:   PetscNewLog(pc,&ainv);
325:   pc->data            = (void*)ainv;
326:   ainv->AINVCUSP      = 0;
327:   ainv->droptolerance = 0.1;
328:   ainv->nonzeros      = -1;
329:   ainv->scaled        = PETSC_TRUE;
330:   ainv->linparam      = 1;
331:   ainv->uselin        = PETSC_FALSE;
332:   /*
333:       Set the pointers for the functions that are provided above.
334:       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
335:       are called, they will automatically call these functions.  Note we
336:       choose not to provide a couple of these functions since they are
337:       not needed.
338:   */
339:   pc->ops->apply               = PCApply_AINVCUSP;
340:   pc->ops->applytranspose      = 0;
341:   pc->ops->setup               = PCSetUp_AINVCUSP;
342:   pc->ops->reset               = PCReset_AINVCUSP;
343:   pc->ops->destroy             = PCDestroy_AINVCUSP;
344:   pc->ops->setfromoptions      = PCSetFromOptions_AINVCUSP;
345:   pc->ops->view                = 0;
346:   pc->ops->applyrichardson     = 0;
347:   pc->ops->applysymmetricleft  = 0;
348:   pc->ops->applysymmetricright = 0;

350:   PetscObjectComposeFunction((PetscObject)pc, "PCAINVCUSPSetDropTolerance_C", PCAINVCUSPSetDropTolerance_AINVCUSP);
351:   PetscObjectComposeFunction((PetscObject)pc, "PCAINVCUSPUseScaling_C",  PCAINVCUSPUseScaling_AINVCUSP);
352:   PetscObjectComposeFunction((PetscObject)pc, "PCAINVCUSPSetLinParameter_C", PCAINVCUSPSetLinParameter_AINVCUSP);
353:   PetscObjectComposeFunction((PetscObject)pc, "PCAINVCUSPSetNonzeros_C",  PCAINVCUSPSetNonzeros_AINVCUSP);
354:   return(0);
355: }