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