Actual source code: ainvcusp.cu

  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 <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:   Mat_SeqAIJCUSP  *gpustruct;
 55:   PetscErrorCode  ierr;

 58:   PetscTypeCompare((PetscObject)pc->pmat,MATSEQAIJCUSP,&flg);
 59:   if (!flg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Currently only handles CUSP matrices");
 60:   if (pc->setupcalled != 0){
 61:     try {
 62:       if (ainv->scaled) {
 63:         delete (cuspainvprecondscaled*)ainv->AINVCUSP;
 64:       } else{
 65:         delete (cuspainvprecond*)ainv->AINVCUSP;
 66:       }
 67:     } catch(char* ex) {
 68:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s", ex);
 69:     }
 70:   }
 71:   try {
 72:     MatCUSPCopyToGPU(pc->pmat);CHKERRCUSP(ierr);
 73:     gpustruct = (Mat_SeqAIJCUSP *)(pc->pmat->spptr);
 74:     if (ainv->scaled) {
 75:       ainv->AINVCUSP =  new cuspainvprecondscaled(*(CUSPMATRIX*)gpustruct->mat, ainv->droptolerance,ainv->nonzeros,ainv->uselin,ainv->linparam);
 76:     } else {
 77:       ainv->AINVCUSP =  new cuspainvprecond(*(CUSPMATRIX*)gpustruct->mat, ainv->droptolerance,ainv->nonzeros,ainv->uselin,ainv->linparam);
 78:     }
 79:   } catch(char* ex) {
 80:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s",ex);
 81:   }
 82:   return(0);
 83: }

 85: /* -------------------------------------------------------------------------- */
 86: /*
 87:    PCApply_AINVCUSP - Applies the CUSP AINV preconditioner to a vector.

 89:    Input Parameters:
 90: .  pc - the preconditioner context
 91: .  x - input vector

 93:    Output Parameter:
 94: .  y - output vector

 96:    Application Interface Routine: PCApply()
 97:  */
100: static PetscErrorCode PCApply_AINVCUSP(PC pc,Vec x,Vec y)
101: {
102:   PC_AINVCUSP     *ainv = (PC_AINVCUSP*)pc->data;
103:   PetscErrorCode  ierr;
104:   PetscBool       flg1,flg2;
105:   CUSPARRAY       *xarray,*yarray;

108:   PetscTypeCompare((PetscObject)x,VECSEQCUSP,&flg1);
109:   PetscTypeCompare((PetscObject)y,VECSEQCUSP,&flg2);
110:   if (!(flg1 && flg2)) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP, "Currently only handles CUSP vectors");
111:   if (!ainv->AINVCUSP) {
112:     PCSetUp_AINVCUSP(pc);
113:   }
114:   VecSet(y,0.0);
115:   VecCUSPGetArrayRead(x,&xarray);
116:   VecCUSPGetArrayWrite(y,&yarray);
117:   try {
118:     if (ainv->scaled) {
119:       cusp::multiply(*(cuspainvprecondscaled *)ainv->AINVCUSP,*xarray,*yarray);
120:     } else {
121:       cusp::multiply(*(cuspainvprecond *)ainv->AINVCUSP,*xarray,*yarray);
122:     }
123:   } catch(char* ex) {
124:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s", ex);
125:   }
126:   VecCUSPRestoreArrayRead(x,&xarray);
127:   VecCUSPRestoreArrayWrite(y,&yarray);
128:   PetscObjectStateIncrease((PetscObject)y);
129:   return(0);
130: }
131: /* -------------------------------------------------------------------------- */

135: static PetscErrorCode PCReset_AINVCUSP(PC pc)
136: {
137:   PC_AINVCUSP    *ainv  = (PC_AINVCUSP*)pc->data;

140:   if (ainv->AINVCUSP) {
141:     try {
142:       if (ainv->scaled) {
143:         delete (cuspainvprecondscaled *)ainv->AINVCUSP;
144:       } else {
145:         delete (cuspainvprecond *)ainv->AINVCUSP;
146:       }
147:     } catch(char* ex) {
148:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s", ex);
149:     }
150:     ainv->AINVCUSP = PETSC_NULL;
151:   }
152:   return(0);
153: }

155: /*
156:    PCDestroy_AINVCUSP - Destroys the private context for the AINVCUSP preconditioner
157:    that was created with PCCreate_AINVCUSP().

159:    Input Parameter:
160: .  pc - the preconditioner context

162:    Application Interface Routine: PCDestroy()
163: */
166: static PetscErrorCode PCDestroy_AINVCUSP(PC pc)
167: {
168:   PetscErrorCode  ierr;

171:   PCReset_AINVCUSP(pc);

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



184: static PetscErrorCode PCAINVCUSPSetDropTolerance_AINVCUSP(PC pc, PetscReal droptolerance)
185: {
186:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

189:   ainv->droptolerance = droptolerance;
190:   ainv->uselin        = PETSC_FALSE;
191:   ainv->linparam      = 1;
192:   ainv->nonzeros      = -1;
193:   return(0);
194: }

198: PetscErrorCode PCAINVCUSPSetDropTolerance(PC pc, PetscReal droptolerance)
199: {

204:   PetscTryMethod(pc, "PCAINVCUSPSetDropTolerance_C",(PC,PetscReal),(pc,droptolerance));
205:   return(0);
206: }
209: static PetscErrorCode PCAINVCUSPSetNonzeros_AINVCUSP(PC pc, PetscInt nonzeros)
210: {
211:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

214:   ainv->droptolerance = 0;
215:   ainv->uselin        = PETSC_FALSE;
216:   ainv->linparam      = 1;
217:   ainv->nonzeros      = nonzeros;
218:   return(0);
219: }

223: PetscErrorCode PCAINVCUSPSetNonzeros(PC pc, PetscInt nonzeros)
224: {

229:   PetscTryMethod(pc, "PCAINVCUSPSetNonzeros_C",(PC,PetscInt),(pc,nonzeros));
230:   return(0);
231: }
234: static PetscErrorCode PCAINVCUSPSetLinParameter_AINVCUSP(PC pc, PetscInt param)
235: {
236:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

239:   ainv->droptolerance = 0;
240:   ainv->uselin        = PETSC_TRUE;
241:   ainv->linparam      = param;
242:   ainv->nonzeros      = -1;
243:   return(0);
244: }

248: PetscErrorCode PCAINVCUSPSetLinParameter(PC pc, PetscInt param)
249: {

254:   PetscTryMethod(pc, "PCAINVCUSPSetLinParameter_C",(PC,PetscInt),(pc,param));
255:   return(0);
256: }
259: static PetscErrorCode PCAINVCUSPUseScaling_AINVCUSP(PC pc, PetscBool scaled)
260: {
261:   PC_AINVCUSP *ainv = (PC_AINVCUSP*)pc->data;

264:   ainv->scaled = scaled;
265:   return(0);
266: }

270: PetscErrorCode PCAINVCUSPUseScaling(PC pc, PetscBool scaled)
271: {

276:   PetscTryMethod(pc, "PCAINVCUSPUseScaling_C",(PC,PetscBool),(pc,scaled));
277:   return(0);
278: }

282: static PetscErrorCode PCSetFromOptions_AINVCUSP(PC pc)
283: {
284:   PC_AINVCUSP     *ainv = (PC_AINVCUSP*)pc->data;
285:   PetscBool       flag  = PETSC_FALSE;
286:   PetscErrorCode  ierr;

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

316: /* -------------------------------------------------------------------------- */


322: PetscErrorCode  PCCreate_AINVCUSP(PC pc)
323: {
324:   PC_AINVCUSP     *ainv;
325:   PetscErrorCode  ierr;

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

358:  PetscObjectComposeFunctionDynamic((PetscObject)pc, "PCAINVCUSPSetDropTolerance_C", "PCAINVCUSPSetDropTolerance_AINVCUSP", PCAINVCUSPSetDropTolerance_AINVCUSP);
359:  PetscObjectComposeFunctionDynamic((PetscObject)pc, "PCAINVCUSPUseScaling_C", "PCAINVCUSPUseScaling_AINVCUSP", PCAINVCUSPUseScaling_AINVCUSP);
360:  PetscObjectComposeFunctionDynamic((PetscObject)pc, "PCAINVCUSPSetLinParameter_C", "PCAINVCUSPSetLinParameter_AINVCUSP", PCAINVCUSPSetLinParameter_AINVCUSP);
361:  PetscObjectComposeFunctionDynamic((PetscObject)pc, "PCAINVCUSPSetNonzeros_C", "PCAINVCUSPSetNonzeros_AINVCUSP", PCAINVCUSPSetNonzeros_AINVCUSP);
362:   return(0);
363: }