Actual source code: redundant.c

  1: /*$Id: redundant.c,v 1.29 2001/04/10 19:36:17 bsmith Exp $*/
  2: /*
  3:   This file defines a "solve the problem redundantly on each processor" preconditioner.

  5: */
 6:  #include src/sles/pc/pcimpl.h
 7:  #include petscsles.h

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

 17: static int PCView_Redundant(PC pc,PetscViewer viewer)
 18: {
 19:   PC_Redundant *red = (PC_Redundant*)pc->data;
 20:   int          ierr,rank;
 21:   PetscTruth   isascii,isstring;
 22:   PetscViewer  sviewer;

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

 50: static int PCSetUp_Redundant(PC pc)
 51: {
 52:   PC_Redundant   *red  = (PC_Redundant*)pc->data;
 53:   int            ierr,mstart,mlocal,m,size;
 54:   IS             isl;
 55:   MatReuse       reuse = MAT_INITIAL_MATRIX;
 56:   MatStructure   str   = DIFFERENT_NONZERO_PATTERN;
 57:   MPI_Comm       comm;

 60:   PCSetFromOptions(red->pc);
 61:   VecGetSize(pc->vec,&m);
 62:   if (!pc->setupcalled) {
 63:     VecGetLocalSize(pc->vec,&mlocal);
 64:     VecCreateSeq(PETSC_COMM_SELF,m,&red->x);
 65:     VecDuplicate(red->x,&red->b);
 66:     PCSetVector(red->pc,red->x);
 67:     if (!red->scatterin) {

 69:       /*
 70:          Create the vectors and vector scatter to get the entire vector onto each processor
 71:       */
 72:       VecGetOwnershipRange(pc->vec,&mstart,PETSC_NULL);
 73:       VecScatterCreate(pc->vec,0,red->x,0,&red->scatterin);
 74:       ISCreateStride(pc->comm,mlocal,mstart,1,&isl);
 75:       VecScatterCreate(red->x,isl,pc->vec,isl,&red->scatterout);
 76:       ISDestroy(isl);
 77:     }
 78:   }

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

 82:   PetscObjectGetComm((PetscObject)pc->pmat,&comm);
 83:   MPI_Comm_size(comm,&size);
 84:   if (size == 1) {
 85:     red->useparallelmat = PETSC_FALSE;
 86:   }

 88:   if (red->useparallelmat) {
 89:     if (pc->setupcalled == 1 && pc->flag == DIFFERENT_NONZERO_PATTERN) {
 90:       /* destroy old matrices */
 91:       if (red->pmats) {
 92:         MatDestroyMatrices(1,&red->pmats);
 93:       }
 94:     } else if (pc->setupcalled == 1) {
 95:       reuse = MAT_REUSE_MATRIX;
 96:       str   = SAME_NONZERO_PATTERN;
 97:     }
 98: 
 99:     /* 
100:        grab the parallel matrix and put it on each processor
101:     */
102:     ISCreateStride(PETSC_COMM_SELF,m,0,1,&isl);
103:     MatGetSubMatrices(pc->pmat,1,&isl,&isl,reuse,&red->pmats);
104:     ISDestroy(isl);

106:     /* tell sequential PC its operators */
107:     PCSetOperators(red->pc,red->pmats[0],red->pmats[0],str);
108:   } else {
109:     PCSetOperators(red->pc,pc->mat,pc->pmat,pc->flag);
110:   }
111:   PCSetFromOptions(red->pc);
112:   PCSetVector(red->pc,red->b);
113:   PCSetUp(red->pc);
114:   return(0);
115: }


118: static int PCApply_Redundant(PC pc,Vec x,Vec y)
119: {
120:   PC_Redundant      *red = (PC_Redundant*)pc->data;
121:   int               ierr;

124:   /* move all values to each processor */
125:   VecScatterBegin(x,red->b,INSERT_VALUES,SCATTER_FORWARD,red->scatterin);
126:   VecScatterEnd(x,red->b,INSERT_VALUES,SCATTER_FORWARD,red->scatterin);

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

131:   /* move local part of values into y vector */
132:   VecScatterBegin(red->x,y,INSERT_VALUES,SCATTER_FORWARD,red->scatterout);
133:   VecScatterEnd(red->x,y,INSERT_VALUES,SCATTER_FORWARD,red->scatterout);
134:   return(0);
135: }


138: static int PCDestroy_Redundant(PC pc)
139: {
140:   PC_Redundant *red = (PC_Redundant*)pc->data;
141:   int          ierr;

144:   if (red->scatterin)  {VecScatterDestroy(red->scatterin);}
145:   if (red->scatterout) {VecScatterDestroy(red->scatterout);}
146:   if (red->x)          {VecDestroy(red->x);}
147:   if (red->b)          {VecDestroy(red->b);}
148:   if (red->pmats) {
149:     MatDestroyMatrices(1,&red->pmats);
150:   }
151:   PCDestroy(red->pc);
152:   PetscFree(red);
153:   return(0);
154: }

156: static int PCSetFromOptions_Redundant(PC pc)
157: {
159:   return(0);
160: }

162: EXTERN_C_BEGIN
163: int PCRedundantSetScatter_Redundant(PC pc,VecScatter in,VecScatter out)
164: {
165:   PC_Redundant *red = (PC_Redundant*)pc->data;
166:   int          ierr;

169:   red->scatterin  = in;
170:   red->scatterout = out;
171:   PetscObjectReference((PetscObject)in);
172:   PetscObjectReference((PetscObject)out);
173:   return(0);
174: }
175: EXTERN_C_END

177: /*@
178:    PCRedundantSetScatter - Sets the scatter used to copy values into the
179:      redundant local solve and the scatter to move them back into the global
180:      vector.

182:    Collective on PC

184:    Input Parameters:
185: +  pc - the preconditioner context
186: .  in - the scatter to move the values in
187: -  out - the scatter to move them out

189:    Level: advanced

191: .keywords: PC, redundant solve
192: @*/
193: int PCRedundantSetScatter(PC pc,VecScatter in,VecScatter out)
194: {
195:   int ierr,(*f)(PC,VecScatter,VecScatter);

199:   PetscObjectQueryFunction((PetscObject)pc,"PCRedundantSetScatter_C",(void (**)(void))&f);
200:   if (f) {
201:     (*f)(pc,in,out);
202:   }
203:   return(0);
204: }

206: EXTERN_C_BEGIN
207: int PCRedundantGetPC_Redundant(PC pc,PC *innerpc)
208: {
209:   PC_Redundant *red = (PC_Redundant*)pc->data;

212:   *innerpc = red->pc;
213:   return(0);
214: }
215: EXTERN_C_END

217: /*@
218:    PCRedundantGetPC - Gets the sequential PC created by the redundant PC.

220:    Not Collective

222:    Input Parameter:
223: .  pc - the preconditioner context

225:    Output Parameter:
226: .  innerpc - the sequential PC 

228:    Level: advanced

230: .keywords: PC, redundant solve
231: @*/
232: int PCRedundantGetPC(PC pc,PC *innerpc)
233: {
234:   int ierr,(*f)(PC,PC*);

238:   PetscObjectQueryFunction((PetscObject)pc,"PCRedundantGetPC_C",(void (**)(void))&f);
239:   if (f) {
240:     (*f)(pc,innerpc);
241:   }
242:   return(0);
243: }

245: EXTERN_C_BEGIN
246: int PCRedundantGetOperators_Redundant(PC pc,Mat *mat,Mat *pmat)
247: {
248:   PC_Redundant *red = (PC_Redundant*)pc->data;

251:   if (mat)  *mat  = red->pmats[0];
252:   if (pmat) *pmat = red->pmats[0];
253:   return(0);
254: }
255: EXTERN_C_END

257: /*@
258:    PCRedundantGetOperators - gets the sequential matrix and preconditioner matrix

260:    Not Collective

262:    Input Parameter:
263: .  pc - the preconditioner context

265:    Output Parameters:
266: +  mat - the matrix
267: -  pmat - the (possibly different) preconditioner matrix

269:    Level: advanced

271: .keywords: PC, redundant solve
272: @*/
273: int PCRedundantGetOperators(PC pc,Mat *mat,Mat *pmat)
274: {
275:   int ierr,(*f)(PC,Mat*,Mat*);

279:   PetscObjectQueryFunction((PetscObject)pc,"PCRedundantGetOperators_C",(void (**)(void))&f);
280:   if (f) {
281:     (*f)(pc,mat,pmat);
282:   }
283:   return(0);
284: }

286: /* -------------------------------------------------------------------------------------*/
287: EXTERN_C_BEGIN
288: int PCCreate_Redundant(PC pc)
289: {
290:   int          ierr;
291:   PC_Redundant *red;
292:   char         *prefix;

295:   PetscNew(PC_Redundant,&red);
296:   PetscLogObjectMemory(pc,sizeof(PC_Redundant));
297:   PetscMemzero(red,sizeof(PC_Redundant));
298:   red->useparallelmat   = PETSC_TRUE;

300:   /* create the sequential PC that each processor has copy of */
301:   PCCreate(PETSC_COMM_SELF,&red->pc);
302:   PCGetOptionsPrefix(pc,&prefix);
303:   PCSetOptionsPrefix(red->pc,prefix);
304:   PCAppendOptionsPrefix(red->pc,"redundant_");

306:   pc->ops->apply             = PCApply_Redundant;
307:   pc->ops->applytranspose    = 0;
308:   pc->ops->setup             = PCSetUp_Redundant;
309:   pc->ops->destroy           = PCDestroy_Redundant;
310:   pc->ops->setfromoptions    = PCSetFromOptions_Redundant;
311:   pc->ops->setuponblocks     = 0;
312:   pc->ops->view              = PCView_Redundant;
313:   pc->ops->applyrichardson   = 0;

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

317:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantSetScatter_C","PCRedundantSetScatter_Redundant",
318:                     PCRedundantSetScatter_Redundant);
319:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantGetPC_C","PCRedundantGetPC_Redundant",
320:                     PCRedundantGetPC_Redundant);
321:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantGetOperators_C","PCRedundantGetOperators_Redundant",
322:                     PCRedundantGetOperators_Redundant);

324:   return(0);
325: }
326: EXTERN_C_END