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