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