xref: /petsc/src/ksp/pc/impls/redundant/redundant.c (revision 4b9ad92859ccb93b5e851e53cb8c4c04ac10e155)
1*4b9ad928SBarry Smith /*$Id: redundant.c,v 1.29 2001/04/10 19:36:17 bsmith Exp $*/
2*4b9ad928SBarry Smith /*
3*4b9ad928SBarry Smith   This file defines a "solve the problem redundantly on each processor" preconditioner.
4*4b9ad928SBarry Smith 
5*4b9ad928SBarry Smith */
6*4b9ad928SBarry Smith #include "src/ksp/pc/pcimpl.h"     /*I "petscpc.h" I*/
7*4b9ad928SBarry Smith #include "petscksp.h"
8*4b9ad928SBarry Smith 
9*4b9ad928SBarry Smith typedef struct {
10*4b9ad928SBarry Smith   PC         pc;                    /* actual preconditioner used on each processor */
11*4b9ad928SBarry Smith   Vec        x,b;                   /* sequential vectors to hold parallel vectors */
12*4b9ad928SBarry Smith   Mat        *pmats;                /* matrix and optional preconditioner matrix */
13*4b9ad928SBarry Smith   VecScatter scatterin,scatterout;  /* scatter used to move all values to each processor */
14*4b9ad928SBarry Smith   PetscTruth useparallelmat;
15*4b9ad928SBarry Smith } PC_Redundant;
16*4b9ad928SBarry Smith 
17*4b9ad928SBarry Smith #undef __FUNCT__
18*4b9ad928SBarry Smith #define __FUNCT__ "PCView_Redundant"
19*4b9ad928SBarry Smith static int PCView_Redundant(PC pc,PetscViewer viewer)
20*4b9ad928SBarry Smith {
21*4b9ad928SBarry Smith   PC_Redundant *red = (PC_Redundant*)pc->data;
22*4b9ad928SBarry Smith   int          ierr,rank;
23*4b9ad928SBarry Smith   PetscTruth   isascii,isstring;
24*4b9ad928SBarry Smith   PetscViewer  sviewer;
25*4b9ad928SBarry Smith 
26*4b9ad928SBarry Smith   PetscFunctionBegin;
27*4b9ad928SBarry Smith   ierr = MPI_Comm_rank(pc->comm,&rank);CHKERRQ(ierr);
28*4b9ad928SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
29*4b9ad928SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);CHKERRQ(ierr);
30*4b9ad928SBarry Smith   if (isascii) {
31*4b9ad928SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Redundant solver preconditioner: Actual PC follows\n");CHKERRQ(ierr);
32*4b9ad928SBarry Smith     ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr);
33*4b9ad928SBarry Smith     if (!rank) {
34*4b9ad928SBarry Smith       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
35*4b9ad928SBarry Smith       ierr = PCView(red->pc,sviewer);CHKERRQ(ierr);
36*4b9ad928SBarry Smith       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
37*4b9ad928SBarry Smith     }
38*4b9ad928SBarry Smith     ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr);
39*4b9ad928SBarry Smith   } else if (isstring) {
40*4b9ad928SBarry Smith     ierr = PetscViewerStringSPrintf(viewer," Redundant solver preconditioner");CHKERRQ(ierr);
41*4b9ad928SBarry Smith     ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr);
42*4b9ad928SBarry Smith     if (!rank) {
43*4b9ad928SBarry Smith       ierr = PCView(red->pc,sviewer);CHKERRQ(ierr);
44*4b9ad928SBarry Smith     }
45*4b9ad928SBarry Smith     ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr);
46*4b9ad928SBarry Smith   } else {
47*4b9ad928SBarry Smith     SETERRQ1(1,"Viewer type %s not supported for PC redundant",((PetscObject)viewer)->type_name);
48*4b9ad928SBarry Smith   }
49*4b9ad928SBarry Smith   PetscFunctionReturn(0);
50*4b9ad928SBarry Smith }
51*4b9ad928SBarry Smith 
52*4b9ad928SBarry Smith #undef __FUNCT__
53*4b9ad928SBarry Smith #define __FUNCT__ "PCSetUp_Redundant"
54*4b9ad928SBarry Smith static int PCSetUp_Redundant(PC pc)
55*4b9ad928SBarry Smith {
56*4b9ad928SBarry Smith   PC_Redundant   *red  = (PC_Redundant*)pc->data;
57*4b9ad928SBarry Smith   int            ierr,mstart,mlocal,m,size;
58*4b9ad928SBarry Smith   IS             isl;
59*4b9ad928SBarry Smith   MatReuse       reuse = MAT_INITIAL_MATRIX;
60*4b9ad928SBarry Smith   MatStructure   str   = DIFFERENT_NONZERO_PATTERN;
61*4b9ad928SBarry Smith   MPI_Comm       comm;
62*4b9ad928SBarry Smith 
63*4b9ad928SBarry Smith   PetscFunctionBegin;
64*4b9ad928SBarry Smith   ierr = PCSetFromOptions(red->pc);CHKERRQ(ierr);
65*4b9ad928SBarry Smith   ierr = VecGetSize(pc->vec,&m);CHKERRQ(ierr);
66*4b9ad928SBarry Smith   if (!pc->setupcalled) {
67*4b9ad928SBarry Smith     ierr = VecGetLocalSize(pc->vec,&mlocal);CHKERRQ(ierr);
68*4b9ad928SBarry Smith     ierr = VecCreateSeq(PETSC_COMM_SELF,m,&red->x);CHKERRQ(ierr);
69*4b9ad928SBarry Smith     ierr = VecDuplicate(red->x,&red->b);CHKERRQ(ierr);
70*4b9ad928SBarry Smith     ierr = PCSetVector(red->pc,red->x);CHKERRQ(ierr);
71*4b9ad928SBarry Smith     if (!red->scatterin) {
72*4b9ad928SBarry Smith 
73*4b9ad928SBarry Smith       /*
74*4b9ad928SBarry Smith          Create the vectors and vector scatter to get the entire vector onto each processor
75*4b9ad928SBarry Smith       */
76*4b9ad928SBarry Smith       ierr = VecGetOwnershipRange(pc->vec,&mstart,PETSC_NULL);CHKERRQ(ierr);
77*4b9ad928SBarry Smith       ierr = VecScatterCreate(pc->vec,0,red->x,0,&red->scatterin);CHKERRQ(ierr);
78*4b9ad928SBarry Smith       ierr = ISCreateStride(pc->comm,mlocal,mstart,1,&isl);CHKERRQ(ierr);
79*4b9ad928SBarry Smith       ierr = VecScatterCreate(red->x,isl,pc->vec,isl,&red->scatterout);CHKERRQ(ierr);
80*4b9ad928SBarry Smith       ierr = ISDestroy(isl);CHKERRQ(ierr);
81*4b9ad928SBarry Smith     }
82*4b9ad928SBarry Smith   }
83*4b9ad928SBarry Smith 
84*4b9ad928SBarry Smith   /* if pmatrix set by user is sequential then we do not need to gather the parallel matrix*/
85*4b9ad928SBarry Smith 
86*4b9ad928SBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc->pmat,&comm);CHKERRQ(ierr);
87*4b9ad928SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);CHKERRQ(ierr);
88*4b9ad928SBarry Smith   if (size == 1) {
89*4b9ad928SBarry Smith     red->useparallelmat = PETSC_FALSE;
90*4b9ad928SBarry Smith   }
91*4b9ad928SBarry Smith 
92*4b9ad928SBarry Smith   if (red->useparallelmat) {
93*4b9ad928SBarry Smith     if (pc->setupcalled == 1 && pc->flag == DIFFERENT_NONZERO_PATTERN) {
94*4b9ad928SBarry Smith       /* destroy old matrices */
95*4b9ad928SBarry Smith       if (red->pmats) {
96*4b9ad928SBarry Smith         ierr = MatDestroyMatrices(1,&red->pmats);CHKERRQ(ierr);
97*4b9ad928SBarry Smith       }
98*4b9ad928SBarry Smith     } else if (pc->setupcalled == 1) {
99*4b9ad928SBarry Smith       reuse = MAT_REUSE_MATRIX;
100*4b9ad928SBarry Smith       str   = SAME_NONZERO_PATTERN;
101*4b9ad928SBarry Smith     }
102*4b9ad928SBarry Smith 
103*4b9ad928SBarry Smith     /*
104*4b9ad928SBarry Smith        grab the parallel matrix and put it on each processor
105*4b9ad928SBarry Smith     */
106*4b9ad928SBarry Smith     ierr = ISCreateStride(PETSC_COMM_SELF,m,0,1,&isl);CHKERRQ(ierr);
107*4b9ad928SBarry Smith     ierr = MatGetSubMatrices(pc->pmat,1,&isl,&isl,reuse,&red->pmats);CHKERRQ(ierr);
108*4b9ad928SBarry Smith     ierr = ISDestroy(isl);CHKERRQ(ierr);
109*4b9ad928SBarry Smith 
110*4b9ad928SBarry Smith     /* tell sequential PC its operators */
111*4b9ad928SBarry Smith     ierr = PCSetOperators(red->pc,red->pmats[0],red->pmats[0],str);CHKERRQ(ierr);
112*4b9ad928SBarry Smith   } else {
113*4b9ad928SBarry Smith     ierr = PCSetOperators(red->pc,pc->mat,pc->pmat,pc->flag);CHKERRQ(ierr);
114*4b9ad928SBarry Smith   }
115*4b9ad928SBarry Smith   ierr = PCSetFromOptions(red->pc);CHKERRQ(ierr);
116*4b9ad928SBarry Smith   ierr = PCSetVector(red->pc,red->b);CHKERRQ(ierr);
117*4b9ad928SBarry Smith   ierr = PCSetUp(red->pc);CHKERRQ(ierr);
118*4b9ad928SBarry Smith   PetscFunctionReturn(0);
119*4b9ad928SBarry Smith }
120*4b9ad928SBarry Smith 
121*4b9ad928SBarry Smith 
122*4b9ad928SBarry Smith #undef __FUNCT__
123*4b9ad928SBarry Smith #define __FUNCT__ "PCApply_Redundant"
124*4b9ad928SBarry Smith static int PCApply_Redundant(PC pc,Vec x,Vec y)
125*4b9ad928SBarry Smith {
126*4b9ad928SBarry Smith   PC_Redundant      *red = (PC_Redundant*)pc->data;
127*4b9ad928SBarry Smith   int               ierr;
128*4b9ad928SBarry Smith 
129*4b9ad928SBarry Smith   PetscFunctionBegin;
130*4b9ad928SBarry Smith   /* move all values to each processor */
131*4b9ad928SBarry Smith   ierr = VecScatterBegin(x,red->b,INSERT_VALUES,SCATTER_FORWARD,red->scatterin);CHKERRQ(ierr);
132*4b9ad928SBarry Smith   ierr = VecScatterEnd(x,red->b,INSERT_VALUES,SCATTER_FORWARD,red->scatterin);CHKERRQ(ierr);
133*4b9ad928SBarry Smith 
134*4b9ad928SBarry Smith   /* apply preconditioner on each processor */
135*4b9ad928SBarry Smith   ierr = PCApply(red->pc,red->b,red->x,PC_LEFT);CHKERRQ(ierr);
136*4b9ad928SBarry Smith 
137*4b9ad928SBarry Smith   /* move local part of values into y vector */
138*4b9ad928SBarry Smith   ierr = VecScatterBegin(red->x,y,INSERT_VALUES,SCATTER_FORWARD,red->scatterout);CHKERRQ(ierr);
139*4b9ad928SBarry Smith   ierr = VecScatterEnd(red->x,y,INSERT_VALUES,SCATTER_FORWARD,red->scatterout);CHKERRQ(ierr);
140*4b9ad928SBarry Smith   PetscFunctionReturn(0);
141*4b9ad928SBarry Smith }
142*4b9ad928SBarry Smith 
143*4b9ad928SBarry Smith 
144*4b9ad928SBarry Smith #undef __FUNCT__
145*4b9ad928SBarry Smith #define __FUNCT__ "PCDestroy_Redundant"
146*4b9ad928SBarry Smith static int PCDestroy_Redundant(PC pc)
147*4b9ad928SBarry Smith {
148*4b9ad928SBarry Smith   PC_Redundant *red = (PC_Redundant*)pc->data;
149*4b9ad928SBarry Smith   int          ierr;
150*4b9ad928SBarry Smith 
151*4b9ad928SBarry Smith   PetscFunctionBegin;
152*4b9ad928SBarry Smith   if (red->scatterin)  {ierr = VecScatterDestroy(red->scatterin);CHKERRQ(ierr);}
153*4b9ad928SBarry Smith   if (red->scatterout) {ierr = VecScatterDestroy(red->scatterout);CHKERRQ(ierr);}
154*4b9ad928SBarry Smith   if (red->x)          {ierr = VecDestroy(red->x);CHKERRQ(ierr);}
155*4b9ad928SBarry Smith   if (red->b)          {ierr = VecDestroy(red->b);CHKERRQ(ierr);}
156*4b9ad928SBarry Smith   if (red->pmats) {
157*4b9ad928SBarry Smith     ierr = MatDestroyMatrices(1,&red->pmats);CHKERRQ(ierr);
158*4b9ad928SBarry Smith   }
159*4b9ad928SBarry Smith   ierr = PCDestroy(red->pc);CHKERRQ(ierr);
160*4b9ad928SBarry Smith   ierr = PetscFree(red);CHKERRQ(ierr);
161*4b9ad928SBarry Smith   PetscFunctionReturn(0);
162*4b9ad928SBarry Smith }
163*4b9ad928SBarry Smith 
164*4b9ad928SBarry Smith #undef __FUNCT__
165*4b9ad928SBarry Smith #define __FUNCT__ "PCSetFromOptions_Redundant"
166*4b9ad928SBarry Smith static int PCSetFromOptions_Redundant(PC pc)
167*4b9ad928SBarry Smith {
168*4b9ad928SBarry Smith   PetscFunctionBegin;
169*4b9ad928SBarry Smith   PetscFunctionReturn(0);
170*4b9ad928SBarry Smith }
171*4b9ad928SBarry Smith 
172*4b9ad928SBarry Smith EXTERN_C_BEGIN
173*4b9ad928SBarry Smith #undef __FUNCT__
174*4b9ad928SBarry Smith #define __FUNCT__ "PCRedundantSetScatter_Redundant"
175*4b9ad928SBarry Smith int PCRedundantSetScatter_Redundant(PC pc,VecScatter in,VecScatter out)
176*4b9ad928SBarry Smith {
177*4b9ad928SBarry Smith   PC_Redundant *red = (PC_Redundant*)pc->data;
178*4b9ad928SBarry Smith   int          ierr;
179*4b9ad928SBarry Smith 
180*4b9ad928SBarry Smith   PetscFunctionBegin;
181*4b9ad928SBarry Smith   red->scatterin  = in;
182*4b9ad928SBarry Smith   red->scatterout = out;
183*4b9ad928SBarry Smith   ierr = PetscObjectReference((PetscObject)in);CHKERRQ(ierr);
184*4b9ad928SBarry Smith   ierr = PetscObjectReference((PetscObject)out);CHKERRQ(ierr);
185*4b9ad928SBarry Smith   PetscFunctionReturn(0);
186*4b9ad928SBarry Smith }
187*4b9ad928SBarry Smith EXTERN_C_END
188*4b9ad928SBarry Smith 
189*4b9ad928SBarry Smith #undef __FUNCT__
190*4b9ad928SBarry Smith #define __FUNCT__ "PCRedundantSetScatter"
191*4b9ad928SBarry Smith /*@
192*4b9ad928SBarry Smith    PCRedundantSetScatter - Sets the scatter used to copy values into the
193*4b9ad928SBarry Smith      redundant local solve and the scatter to move them back into the global
194*4b9ad928SBarry Smith      vector.
195*4b9ad928SBarry Smith 
196*4b9ad928SBarry Smith    Collective on PC
197*4b9ad928SBarry Smith 
198*4b9ad928SBarry Smith    Input Parameters:
199*4b9ad928SBarry Smith +  pc - the preconditioner context
200*4b9ad928SBarry Smith .  in - the scatter to move the values in
201*4b9ad928SBarry Smith -  out - the scatter to move them out
202*4b9ad928SBarry Smith 
203*4b9ad928SBarry Smith    Level: advanced
204*4b9ad928SBarry Smith 
205*4b9ad928SBarry Smith .keywords: PC, redundant solve
206*4b9ad928SBarry Smith @*/
207*4b9ad928SBarry Smith int PCRedundantSetScatter(PC pc,VecScatter in,VecScatter out)
208*4b9ad928SBarry Smith {
209*4b9ad928SBarry Smith   int ierr,(*f)(PC,VecScatter,VecScatter);
210*4b9ad928SBarry Smith 
211*4b9ad928SBarry Smith   PetscFunctionBegin;
212*4b9ad928SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE);
213*4b9ad928SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCRedundantSetScatter_C",(void (**)(void))&f);CHKERRQ(ierr);
214*4b9ad928SBarry Smith   if (f) {
215*4b9ad928SBarry Smith     ierr = (*f)(pc,in,out);CHKERRQ(ierr);
216*4b9ad928SBarry Smith   }
217*4b9ad928SBarry Smith   PetscFunctionReturn(0);
218*4b9ad928SBarry Smith }
219*4b9ad928SBarry Smith 
220*4b9ad928SBarry Smith EXTERN_C_BEGIN
221*4b9ad928SBarry Smith #undef __FUNCT__
222*4b9ad928SBarry Smith #define __FUNCT__ "PCRedundantGetPC_Redundant"
223*4b9ad928SBarry Smith int PCRedundantGetPC_Redundant(PC pc,PC *innerpc)
224*4b9ad928SBarry Smith {
225*4b9ad928SBarry Smith   PC_Redundant *red = (PC_Redundant*)pc->data;
226*4b9ad928SBarry Smith 
227*4b9ad928SBarry Smith   PetscFunctionBegin;
228*4b9ad928SBarry Smith   *innerpc = red->pc;
229*4b9ad928SBarry Smith   PetscFunctionReturn(0);
230*4b9ad928SBarry Smith }
231*4b9ad928SBarry Smith EXTERN_C_END
232*4b9ad928SBarry Smith 
233*4b9ad928SBarry Smith #undef __FUNCT__
234*4b9ad928SBarry Smith #define __FUNCT__ "PCRedundantGetPC"
235*4b9ad928SBarry Smith /*@
236*4b9ad928SBarry Smith    PCRedundantGetPC - Gets the sequential PC created by the redundant PC.
237*4b9ad928SBarry Smith 
238*4b9ad928SBarry Smith    Not Collective
239*4b9ad928SBarry Smith 
240*4b9ad928SBarry Smith    Input Parameter:
241*4b9ad928SBarry Smith .  pc - the preconditioner context
242*4b9ad928SBarry Smith 
243*4b9ad928SBarry Smith    Output Parameter:
244*4b9ad928SBarry Smith .  innerpc - the sequential PC
245*4b9ad928SBarry Smith 
246*4b9ad928SBarry Smith    Level: advanced
247*4b9ad928SBarry Smith 
248*4b9ad928SBarry Smith .keywords: PC, redundant solve
249*4b9ad928SBarry Smith @*/
250*4b9ad928SBarry Smith int PCRedundantGetPC(PC pc,PC *innerpc)
251*4b9ad928SBarry Smith {
252*4b9ad928SBarry Smith   int ierr,(*f)(PC,PC*);
253*4b9ad928SBarry Smith 
254*4b9ad928SBarry Smith   PetscFunctionBegin;
255*4b9ad928SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE);
256*4b9ad928SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCRedundantGetPC_C",(void (**)(void))&f);CHKERRQ(ierr);
257*4b9ad928SBarry Smith   if (f) {
258*4b9ad928SBarry Smith     ierr = (*f)(pc,innerpc);CHKERRQ(ierr);
259*4b9ad928SBarry Smith   }
260*4b9ad928SBarry Smith   PetscFunctionReturn(0);
261*4b9ad928SBarry Smith }
262*4b9ad928SBarry Smith 
263*4b9ad928SBarry Smith EXTERN_C_BEGIN
264*4b9ad928SBarry Smith #undef __FUNCT__
265*4b9ad928SBarry Smith #define __FUNCT__ "PCRedundantGetOperators_Redundant"
266*4b9ad928SBarry Smith int PCRedundantGetOperators_Redundant(PC pc,Mat *mat,Mat *pmat)
267*4b9ad928SBarry Smith {
268*4b9ad928SBarry Smith   PC_Redundant *red = (PC_Redundant*)pc->data;
269*4b9ad928SBarry Smith 
270*4b9ad928SBarry Smith   PetscFunctionBegin;
271*4b9ad928SBarry Smith   if (mat)  *mat  = red->pmats[0];
272*4b9ad928SBarry Smith   if (pmat) *pmat = red->pmats[0];
273*4b9ad928SBarry Smith   PetscFunctionReturn(0);
274*4b9ad928SBarry Smith }
275*4b9ad928SBarry Smith EXTERN_C_END
276*4b9ad928SBarry Smith 
277*4b9ad928SBarry Smith #undef __FUNCT__
278*4b9ad928SBarry Smith #define __FUNCT__ "PCRedundantGetOperators"
279*4b9ad928SBarry Smith /*@
280*4b9ad928SBarry Smith    PCRedundantGetOperators - gets the sequential matrix and preconditioner matrix
281*4b9ad928SBarry Smith 
282*4b9ad928SBarry Smith    Not Collective
283*4b9ad928SBarry Smith 
284*4b9ad928SBarry Smith    Input Parameter:
285*4b9ad928SBarry Smith .  pc - the preconditioner context
286*4b9ad928SBarry Smith 
287*4b9ad928SBarry Smith    Output Parameters:
288*4b9ad928SBarry Smith +  mat - the matrix
289*4b9ad928SBarry Smith -  pmat - the (possibly different) preconditioner matrix
290*4b9ad928SBarry Smith 
291*4b9ad928SBarry Smith    Level: advanced
292*4b9ad928SBarry Smith 
293*4b9ad928SBarry Smith .keywords: PC, redundant solve
294*4b9ad928SBarry Smith @*/
295*4b9ad928SBarry Smith int PCRedundantGetOperators(PC pc,Mat *mat,Mat *pmat)
296*4b9ad928SBarry Smith {
297*4b9ad928SBarry Smith   int ierr,(*f)(PC,Mat*,Mat*);
298*4b9ad928SBarry Smith 
299*4b9ad928SBarry Smith   PetscFunctionBegin;
300*4b9ad928SBarry Smith   PetscValidHeaderSpecific(pc,PC_COOKIE);
301*4b9ad928SBarry Smith   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCRedundantGetOperators_C",(void (**)(void))&f);CHKERRQ(ierr);
302*4b9ad928SBarry Smith   if (f) {
303*4b9ad928SBarry Smith     ierr = (*f)(pc,mat,pmat);CHKERRQ(ierr);
304*4b9ad928SBarry Smith   }
305*4b9ad928SBarry Smith   PetscFunctionReturn(0);
306*4b9ad928SBarry Smith }
307*4b9ad928SBarry Smith 
308*4b9ad928SBarry Smith /* -------------------------------------------------------------------------------------*/
309*4b9ad928SBarry Smith EXTERN_C_BEGIN
310*4b9ad928SBarry Smith #undef __FUNCT__
311*4b9ad928SBarry Smith #define __FUNCT__ "PCCreate_Redundant"
312*4b9ad928SBarry Smith int PCCreate_Redundant(PC pc)
313*4b9ad928SBarry Smith {
314*4b9ad928SBarry Smith   int          ierr;
315*4b9ad928SBarry Smith   PC_Redundant *red;
316*4b9ad928SBarry Smith   char         *prefix;
317*4b9ad928SBarry Smith 
318*4b9ad928SBarry Smith   PetscFunctionBegin;
319*4b9ad928SBarry Smith   ierr = PetscNew(PC_Redundant,&red);CHKERRQ(ierr);
320*4b9ad928SBarry Smith   PetscLogObjectMemory(pc,sizeof(PC_Redundant));
321*4b9ad928SBarry Smith   ierr = PetscMemzero(red,sizeof(PC_Redundant));CHKERRQ(ierr);
322*4b9ad928SBarry Smith   red->useparallelmat   = PETSC_TRUE;
323*4b9ad928SBarry Smith 
324*4b9ad928SBarry Smith   /* create the sequential PC that each processor has copy of */
325*4b9ad928SBarry Smith   ierr = PCCreate(PETSC_COMM_SELF,&red->pc);CHKERRQ(ierr);
326*4b9ad928SBarry Smith   ierr = PCSetType(red->pc,PCLU);CHKERRQ(ierr);
327*4b9ad928SBarry Smith   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
328*4b9ad928SBarry Smith   ierr = PCSetOptionsPrefix(red->pc,prefix);CHKERRQ(ierr);
329*4b9ad928SBarry Smith   ierr = PCAppendOptionsPrefix(red->pc,"redundant_");CHKERRQ(ierr);
330*4b9ad928SBarry Smith 
331*4b9ad928SBarry Smith   pc->ops->apply             = PCApply_Redundant;
332*4b9ad928SBarry Smith   pc->ops->applytranspose    = 0;
333*4b9ad928SBarry Smith   pc->ops->setup             = PCSetUp_Redundant;
334*4b9ad928SBarry Smith   pc->ops->destroy           = PCDestroy_Redundant;
335*4b9ad928SBarry Smith   pc->ops->setfromoptions    = PCSetFromOptions_Redundant;
336*4b9ad928SBarry Smith   pc->ops->setuponblocks     = 0;
337*4b9ad928SBarry Smith   pc->ops->view              = PCView_Redundant;
338*4b9ad928SBarry Smith   pc->ops->applyrichardson   = 0;
339*4b9ad928SBarry Smith 
340*4b9ad928SBarry Smith   pc->data              = (void*)red;
341*4b9ad928SBarry Smith 
342*4b9ad928SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantSetScatter_C","PCRedundantSetScatter_Redundant",
343*4b9ad928SBarry Smith                     PCRedundantSetScatter_Redundant);CHKERRQ(ierr);
344*4b9ad928SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantGetPC_C","PCRedundantGetPC_Redundant",
345*4b9ad928SBarry Smith                     PCRedundantGetPC_Redundant);CHKERRQ(ierr);
346*4b9ad928SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCRedundantGetOperators_C","PCRedundantGetOperators_Redundant",
347*4b9ad928SBarry Smith                     PCRedundantGetOperators_Redundant);CHKERRQ(ierr);
348*4b9ad928SBarry Smith 
349*4b9ad928SBarry Smith   PetscFunctionReturn(0);
350*4b9ad928SBarry Smith }
351*4b9ad928SBarry Smith EXTERN_C_END
352