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