Actual source code: redundant.c

  1: #define PETSCKSP_DLL

  3: /*
  4:   This file defines a "solve the problem redundantly on each processor" preconditioner.

  6: */
 7:  #include private/pcimpl.h
 8:  #include petscksp.h

 10: typedef struct {
 11:   PC         pc;                    /* actual preconditioner used on each processor */
 12:   Vec        x,b;                   /* sequential vectors to hold parallel vectors */
 13:   Mat        *pmats;                /* matrix and optional preconditioner matrix */
 14:   VecScatter scatterin,scatterout;  /* scatter used to move all values to each processor */
 15:   PetscTruth useparallelmat;
 16: } PC_Redundant;

 20: static PetscErrorCode PCView_Redundant(PC pc,PetscViewer viewer)
 21: {
 22:   PC_Redundant   *red = (PC_Redundant*)pc->data;
 24:   PetscMPIInt    rank;
 25:   PetscTruth     iascii,isstring;
 26:   PetscViewer    sviewer;

 29:   MPI_Comm_rank(pc->comm,&rank);
 30:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
 31:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
 32:   if (iascii) {
 33:     PetscViewerASCIIPrintf(viewer,"  Redundant solver preconditioner: Actual PC follows\n");
 34:     PetscViewerGetSingleton(viewer,&sviewer);
 35:     if (!rank) {
 36:       PetscViewerASCIIPushTab(viewer);
 37:       PCView(red->pc,sviewer);
 38:       PetscViewerASCIIPopTab(viewer);
 39:     }
 40:     PetscViewerRestoreSingleton(viewer,&sviewer);
 41:   } else if (isstring) {
 42:     PetscViewerStringSPrintf(viewer," Redundant solver preconditioner");
 43:     PetscViewerGetSingleton(viewer,&sviewer);
 44:     if (!rank) {
 45:       PCView(red->pc,sviewer);
 46:     }
 47:     PetscViewerRestoreSingleton(viewer,&sviewer);
 48:   } else {
 49:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PC redundant",((PetscObject)viewer)->type_name);
 50:   }
 51:   return(0);
 52: }

 56: static PetscErrorCode PCSetUp_Redundant(PC pc)
 57: {
 58:   PC_Redundant   *red  = (PC_Redundant*)pc->data;
 60:   PetscInt       mstart,mlocal,m;
 61:   PetscMPIInt    size;
 62:   IS             isl;
 63:   MatReuse       reuse = MAT_INITIAL_MATRIX;
 64:   MatStructure   str   = DIFFERENT_NONZERO_PATTERN;
 65:   MPI_Comm       comm;
 66:   Vec            vec;
 67:   int            rank;

 70:   MatGetVecs(pc->pmat,&vec,0);
 71:   PCSetFromOptions(red->pc);
 72:   VecGetSize(vec,&m);
 73:   if (!pc->setupcalled) {
 74:     VecGetLocalSize(vec,&mlocal);
 75:     VecCreateSeq(PETSC_COMM_SELF,m,&red->x);
 76:     VecDuplicate(red->x,&red->b);
 77:     if (!red->scatterin) {

 79:       /*
 80:          Create the vectors and vector scatter to get the entire vector onto each processor
 81:       */
 82:       VecGetOwnershipRange(vec,&mstart,PETSC_NULL);
 83:       VecScatterCreate(vec,0,red->x,0,&red->scatterin);
 84:       ISCreateStride(pc->comm,mlocal,mstart,1,&isl);
 85:       VecScatterCreate(red->x,isl,vec,isl,&red->scatterout);
 86:       ISDestroy(isl);
 87:     }
 88:   }
 89:   VecDestroy(vec);

 91:   /* if pmatrix set by user is sequential then we do not need to gather the parallel matrix*/

 93:   PetscObjectGetComm((PetscObject)pc->pmat,&comm);
 94:   MPI_Comm_size(comm,&size);
 95:   if (size == 1) {
 96:     red->useparallelmat = PETSC_FALSE;
 97:   }

 99:   if (red->useparallelmat) {
100:     if (pc->setupcalled == 1 && pc->flag == DIFFERENT_NONZERO_PATTERN) {
101:       /* destroy old matrices */
102:       if (red->pmats) {
103:         MatDestroyMatrices(1,&red->pmats);
104:       }
105:     } else if (pc->setupcalled == 1) {
106:       reuse = MAT_REUSE_MATRIX;
107:       str   = SAME_NONZERO_PATTERN;
108:     }
109: 
110:     /* 
111:        grab the parallel matrix and put it on each processor
112:     */
113:     ISCreateStride(PETSC_COMM_SELF,m,0,1,&isl);
114:     MatGetSubMatrices(pc->pmat,1,&isl,&isl,reuse,&red->pmats);
115:     MPI_Comm_rank(comm,&rank);
116:     if (rank == 0) {
117:       MatView(*red->pmats,PETSC_VIEWER_BINARY_(PETSC_COMM_SELF));
118:     }
119:     ISDestroy(isl);

121:     /* tell sequential PC its operators */
122:     PCSetOperators(red->pc,red->pmats[0],red->pmats[0],str);
123:   } else {
124:     PCSetOperators(red->pc,pc->mat,pc->pmat,pc->flag);
125:   }
126:   PCSetFromOptions(red->pc);
127:   PCSetUp(red->pc);
128:   return(0);
129: }


134: static PetscErrorCode PCApply_Redundant(PC pc,Vec x,Vec y)
135: {
136:   PC_Redundant   *red = (PC_Redundant*)pc->data;

140:   /* move all values to each processor */
141:   VecScatterBegin(x,red->b,INSERT_VALUES,SCATTER_FORWARD,red->scatterin);
142:   VecScatterEnd(x,red->b,INSERT_VALUES,SCATTER_FORWARD,red->scatterin);

144:   /* apply preconditioner on each processor */
145:   PCApply(red->pc,red->b,red->x);

147:   /* move local part of values into y vector */
148:   VecScatterBegin(red->x,y,INSERT_VALUES,SCATTER_FORWARD,red->scatterout);
149:   VecScatterEnd(red->x,y,INSERT_VALUES,SCATTER_FORWARD,red->scatterout);
150:   return(0);
151: }


156: static PetscErrorCode PCDestroy_Redundant(PC pc)
157: {
158:   PC_Redundant   *red = (PC_Redundant*)pc->data;

162:   if (red->scatterin)  {VecScatterDestroy(red->scatterin);}
163:   if (red->scatterout) {VecScatterDestroy(red->scatterout);}
164:   if (red->x)          {VecDestroy(red->x);}
165:   if (red->b)          {VecDestroy(red->b);}
166:   if (red->pmats) {
167:     MatDestroyMatrices(1,&red->pmats);
168:   }
169:   PCDestroy(red->pc);
170:   PetscFree(red);
171:   return(0);
172: }

176: static PetscErrorCode PCSetFromOptions_Redundant(PC pc)
177: {
179:   return(0);
180: }

185: PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantSetScatter_Redundant(PC pc,VecScatter in,VecScatter out)
186: {
187:   PC_Redundant   *red = (PC_Redundant*)pc->data;

191:   red->scatterin  = in;
192:   red->scatterout = out;
193:   PetscObjectReference((PetscObject)in);
194:   PetscObjectReference((PetscObject)out);
195:   return(0);
196: }

201: /*@
202:    PCRedundantSetScatter - Sets the scatter used to copy values into the
203:      redundant local solve and the scatter to move them back into the global
204:      vector.

206:    Collective on PC

208:    Input Parameters:
209: +  pc - the preconditioner context
210: .  in - the scatter to move the values in
211: -  out - the scatter to move them out

213:    Level: advanced

215: .keywords: PC, redundant solve
216: @*/
217: PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantSetScatter(PC pc,VecScatter in,VecScatter out)
218: {
219:   PetscErrorCode ierr,(*f)(PC,VecScatter,VecScatter);

225:   PetscObjectQueryFunction((PetscObject)pc,"PCRedundantSetScatter_C",(void (**)(void))&f);
226:   if (f) {
227:     (*f)(pc,in,out);
228:   }
229:   return(0);
230: }

235: PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantGetPC_Redundant(PC pc,PC *innerpc)
236: {
237:   PC_Redundant *red = (PC_Redundant*)pc->data;

240:   *innerpc = red->pc;
241:   return(0);
242: }

247: /*@
248:    PCRedundantGetPC - Gets the sequential PC created by the redundant PC.

250:    Not Collective

252:    Input Parameter:
253: .  pc - the preconditioner context

255:    Output Parameter:
256: .  innerpc - the sequential PC 

258:    Level: advanced

260: .keywords: PC, redundant solve
261: @*/
262: PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantGetPC(PC pc,PC *innerpc)
263: {
264:   PetscErrorCode ierr,(*f)(PC,PC*);

269:   PetscObjectQueryFunction((PetscObject)pc,"PCRedundantGetPC_C",(void (**)(void))&f);
270:   if (f) {
271:     (*f)(pc,innerpc);
272:   }
273:   return(0);
274: }

279: PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantGetOperators_Redundant(PC pc,Mat *mat,Mat *pmat)
280: {
281:   PC_Redundant *red = (PC_Redundant*)pc->data;

284:   if (mat)  *mat  = red->pmats[0];
285:   if (pmat) *pmat = red->pmats[0];
286:   return(0);
287: }

292: /*@
293:    PCRedundantGetOperators - gets the sequential matrix and preconditioner matrix

295:    Not Collective

297:    Input Parameter:
298: .  pc - the preconditioner context

300:    Output Parameters:
301: +  mat - the matrix
302: -  pmat - the (possibly different) preconditioner matrix

304:    Level: advanced

306: .keywords: PC, redundant solve
307: @*/
308: PetscErrorCode PETSCKSP_DLLEXPORT PCRedundantGetOperators(PC pc,Mat *mat,Mat *pmat)
309: {
310:   PetscErrorCode ierr,(*f)(PC,Mat*,Mat*);

316:   PetscObjectQueryFunction((PetscObject)pc,"PCRedundantGetOperators_C",(void (**)(void))&f);
317:   if (f) {
318:     (*f)(pc,mat,pmat);
319:   }
320:   return(0);
321: }

323: /* -------------------------------------------------------------------------------------*/
324: /*MC
325:      PCREDUNDANT - Runs a preconditioner for the entire problem on each processor


328:      Options for the redundant preconditioners can be set with -redundant_pc_xxx

330:    Level: intermediate


333: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PCRedundantSetScatter(),
334:            PCRedundantGetPC(), PCRedundantGetOperators()

336: M*/

341: PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_Redundant(PC pc)
342: {
344:   PC_Redundant   *red;
345:   const char     *prefix;

348:   PetscNew(PC_Redundant,&red);
349:   PetscLogObjectMemory(pc,sizeof(PC_Redundant));
350:   red->useparallelmat   = PETSC_TRUE;

352:   /* create the sequential PC that each processor has copy of */
353:   PCCreate(PETSC_COMM_SELF,&red->pc);
354:   PCSetType(red->pc,PCLU);
355:   PCGetOptionsPrefix(pc,&prefix);
356:   PCSetOptionsPrefix(red->pc,prefix);
357:   PCAppendOptionsPrefix(red->pc,"redundant_");

359:   pc->ops->apply             = PCApply_Redundant;
360:   pc->ops->applytranspose    = 0;
361:   pc->ops->setup             = PCSetUp_Redundant;
362:   pc->ops->destroy           = PCDestroy_Redundant;
363:   pc->ops->setfromoptions    = PCSetFromOptions_Redundant;
364:   pc->ops->setuponblocks     = 0;
365:   pc->ops->view              = PCView_Redundant;
366:   pc->ops->applyrichardson   = 0;

368:   pc->data              = (void*)red;

370:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantSetScatter_C","PCRedundantSetScatter_Redundant",
371:                     PCRedundantSetScatter_Redundant);
372:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantGetPC_C","PCRedundantGetPC_Redundant",
373:                     PCRedundantGetPC_Redundant);
374:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantGetOperators_C","PCRedundantGetOperators_Redundant",
375:                     PCRedundantGetOperators_Redundant);

377:   return(0);
378: }