Actual source code: ainvcusp.cu
petsc-3.8.4 2018-03-24
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: }