Actual source code: sacusp.cu

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

  4: /*
  5:    Include files needed for the CUSP Smoothed Aggregation 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/smoothed_aggregation.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 cuspsaprecond cusp::precond::smoothed_aggregation<PetscInt,PetscScalar,cusp::device_memory>

 20: /*
 21:    Private context (data structure) for the SACUSP preconditioner.
 22: */
 23: typedef struct {
 24:  cuspsaprecond* SACUSP;
 25:   /*int cycles; */
 26: } PC_SACUSP;

 30: static PetscErrorCode PCSACUSPSetCycles(PC pc, int n)
 31: {
 32:   PC_SACUSP      *sac = (PC_SACUSP*)pc->data;

 35:   sac->cycles = n;
 36:   return(0);

 38:   }*/

 40: /* -------------------------------------------------------------------------- */
 41: /*
 42:    PCSetUp_SACUSP - Prepares for the use of the SACUSP preconditioner
 43:                     by setting data structures and options.

 45:    Input Parameter:
 46: .  pc - the preconditioner context

 48:    Application Interface Routine: PCSetUp()

 50:    Notes:
 51:    The interface routine PCSetUp() is not usually called directly by
 52:    the user, but instead is called by PCApply() if necessary.
 53: */
 56: static PetscErrorCode PCSetUp_SACUSP(PC pc)
 57: {
 58:   PC_SACUSP      *sa = (PC_SACUSP*)pc->data;
 59:   PetscBool      flg = PETSC_FALSE;
 61:   Mat_SeqAIJCUSP *gpustruct;

 64:   PetscTypeCompare((PetscObject)pc->pmat,MATSEQAIJCUSP,&flg);
 65:   if (!flg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Currently only handles CUSP matrices");
 66:   if (pc->setupcalled != 0){
 67:     try {
 68:       delete sa->SACUSP;
 69:     } catch(char* ex) {
 70:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s", ex);
 71:     }
 72:   }
 73:   try {
 74:     MatCUSPCopyToGPU(pc->pmat);CHKERRCUSP(ierr);
 75:     gpustruct  = (Mat_SeqAIJCUSP *)(pc->pmat->spptr);
 76:     sa->SACUSP = new cuspsaprecond(*(CUSPMATRIX*)gpustruct->mat);
 77:   } catch(char* ex) {
 78:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s", ex);
 79:   }
 80:   /*PetscOptionsInt("-pc_sacusp_cycles","Number of v-cycles to perform","PCSACUSPSetCycles",sa->cycles,
 81:     &sa->cycles,PETSC_NULL);*/
 82:   return(0);
 83: }

 87: static PetscErrorCode PCApplyRichardson_SACUSP(PC pc, Vec b, Vec y, Vec w,PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt its, PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason)
 88: {
 89:   PC_SACUSP      *sac = (PC_SACUSP*)pc->data;
 91:   CUSPARRAY      *barray,*yarray;

 94:   /* how to incorporate dtol, guesszero, w?*/
 96:   VecCUSPGetArrayRead(b,&barray);
 97:   VecCUSPGetArrayReadWrite(y,&yarray);
 98:   cusp::default_monitor<PetscScalar> monitor(*barray,its,rtol,abstol);
 99:   sac->SACUSP->solve(*barray,*yarray,monitor);
100:   *outits = monitor.iteration_count();
101:   if (monitor.converged()){
102:     /* how to discern between converging from RTOL or ATOL?*/
103:     *reason = PCRICHARDSON_CONVERGED_RTOL;
104:   } else{
105:     *reason = PCRICHARDSON_CONVERGED_ITS;
106:   }
107:   PetscObjectStateIncrease((PetscObject)y);
108:   VecCUSPRestoreArrayRead(b,&barray);
109:   VecCUSPRestoreArrayReadWrite(y,&yarray);
110:   return(0);
111: }

113: /* -------------------------------------------------------------------------- */
114: /*
115:    PCApply_SACUSP - Applies the SACUSP preconditioner to a vector.

117:    Input Parameters:
118: .  pc - the preconditioner context
119: .  x - input vector

121:    Output Parameter:
122: .  y - output vector

124:    Application Interface Routine: PCApply()
125:  */
128: static PetscErrorCode PCApply_SACUSP(PC pc,Vec x,Vec y)
129: {
130:   PC_SACUSP      *sac = (PC_SACUSP*)pc->data;
132:   PetscBool      flg1,flg2;
133:   CUSPARRAY      *xarray,*yarray;

136:   /*how to apply a certain fixed number of iterations?*/
137:   PetscTypeCompare((PetscObject)x,VECSEQCUSP,&flg1);
138:   PetscTypeCompare((PetscObject)y,VECSEQCUSP,&flg2);
139:   if (!(flg1 && flg2)) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP, "Currently only handles CUSP vectors");
140:   if (!sac->SACUSP) {
141:     PCSetUp_SACUSP(pc);
142:   }
143:   VecSet(y,0.0);
144:   VecCUSPGetArrayRead(x,&xarray);
145:   VecCUSPGetArrayWrite(y,&yarray);
146:   try {
147:     cusp::multiply(*sac->SACUSP,*xarray,*yarray);
148:   } catch(char* ex) {
149:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s", ex);
150:   }
151:   VecCUSPRestoreArrayRead(x,&xarray);
152:   VecCUSPRestoreArrayWrite(y,&yarray);
153:   PetscObjectStateIncrease((PetscObject)y);
154:   return(0);
155: }
156: /* -------------------------------------------------------------------------- */
157: /*
158:    PCDestroy_SACUSP - Destroys the private context for the SACUSP preconditioner
159:    that was created with PCCreate_SACUSP().

161:    Input Parameter:
162: .  pc - the preconditioner context

164:    Application Interface Routine: PCDestroy()
165: */
168: static PetscErrorCode PCDestroy_SACUSP(PC pc)
169: {
170:   PC_SACUSP      *sac  = (PC_SACUSP*)pc->data;

174:   if (sac->SACUSP) {
175:     try {
176:       delete sac->SACUSP;
177:     } catch(char* ex) {
178:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"CUSP error: %s", ex);
179:     }
180: }

182:   /*
183:       Free the private data structure that was hanging off the PC
184:   */
185:   PetscFree(pc->data);
186:   return(0);
187: }

191: static PetscErrorCode PCSetFromOptions_SACUSP(PC pc)
192: {

196:   PetscOptionsHead("SACUSP options");
197:   PetscOptionsTail();
198:   return(0);
199: }

201: /* -------------------------------------------------------------------------- */



208: PetscErrorCode  PCCreate_SACUSP(PC pc)
209: {
210:   PC_SACUSP      *sac;

214:   /*
215:      Creates the private data structure for this preconditioner and
216:      attach it to the PC object.
217:   */
218:   PetscNewLog(pc,PC_SACUSP,&sac);
219:   pc->data  = (void*)sac;

221:   /*
222:      Initialize the pointer to zero
223:      Initialize number of v-cycles to default (1)
224:   */
225:   sac->SACUSP          = 0;
226:   /*sac->cycles=1;*/


229:   /*
230:       Set the pointers for the functions that are provided above.
231:       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
232:       are called, they will automatically call these functions.  Note we
233:       choose not to provide a couple of these functions since they are
234:       not needed.
235:   */
236:   pc->ops->apply               = PCApply_SACUSP;
237:   pc->ops->applytranspose      = 0;
238:   pc->ops->setup               = PCSetUp_SACUSP;
239:   pc->ops->destroy             = PCDestroy_SACUSP;
240:   pc->ops->setfromoptions      = PCSetFromOptions_SACUSP;
241:   pc->ops->view                = 0;
242:   pc->ops->applyrichardson     = PCApplyRichardson_SACUSP;
243:   pc->ops->applysymmetricleft  = 0;
244:   pc->ops->applysymmetricright = 0;
245:   return(0);
246: }