Actual source code: pesi.c

  1: /*$Id: jacobi.c,v 1.75 2001/08/07 03:03:32 balay Exp $*/


 4:  #include src/ksp/pc/pcimpl.h
 5:  #include esi/petsc/preconditioner.h

  7: /* 
  8:    Private context (data structure) for the ESI
  9: */
 10: typedef struct {
 11:   esi::Preconditioner<double,int>  *epc;
 12: } PC_ESI;

 16: /*@C
 17:   PCESISetPreconditioner - Takes a PETSc PC sets it to type ESI and 
 18:   provides the ESI preconditioner that it wraps to look like a PETSc PC.

 20:   Input Parameter:
 21: . xin - The Petsc PC

 23:   Output Parameter:
 24: . v   - The ESI preconditioner

 26:   Level: advanced

 28: .keywords: PC, ESI
 29: @*/
 30: int PCESISetPreconditioner(PC xin,esi::Preconditioner<double,int> *v)
 31: {
 32:   PC_ESI     *x = (PC_ESI*)xin->data;
 33:   PetscTruth tesi;
 34:   int        ierr;

 37:   PetscTypeCompare((PetscObject)xin,0,&tesi);
 38:   if (tesi) {
 39:     PCSetType(xin,PCESI);
 40:   }
 41:   PetscTypeCompare((PetscObject)xin,PCESI,&tesi);
 42:   if (tesi) {
 43:     x->epc  = v;
 44:     v->addReference();
 45:   }
 46:   return(0);
 47: }

 49:  #include esi/petsc/matrix.h

 53: static int PCSetUp_ESI(PC pc)
 54: {
 55:   PC_ESI                      *jac = (PC_ESI*)pc->data;
 56:   int                         ierr;
 57:   ::esi::Operator<double,int> *em;

 60:   MatESIWrap(pc->mat,&em);
 61:   jac->epc->setOperator(*em);
 62:   jac->epc->setup();
 63:   return(0);
 64: }

 68: static int PCApply_ESI(PC pc,Vec x,Vec y)
 69: {
 70:   PC_ESI                  *jac = (PC_ESI*)pc->data;
 71:   esi::Vector<double,int> *xx,*yy;
 72:   int                     ierr;

 75:   VecESIWrap(x,&xx);
 76:   VecESIWrap(y,&yy);
 77:   jac->epc->solve(*xx,*yy);
 78:   return(0);
 79: }

 83: static int PCApplySymmetricLeft_ESI(PC pc,Vec x,Vec y)
 84: {
 85:   int                     ierr;
 86:   PC_ESI                  *jac = (PC_ESI*)pc->data;
 87:   esi::Vector<double,int> *xx,*yy;

 90:   VecESIWrap(x,&xx);
 91:   VecESIWrap(y,&yy);
 92:   jac->epc->solveLeft(*xx,*yy);
 93:   return(0);
 94: }

 98: static int PCApplySymmetricRight_ESI(PC pc,Vec x,Vec y)
 99: {
100:   int                     ierr;
101:   PC_ESI                  *jac = (PC_ESI*)pc->data;
102:   esi::Vector<double,int> *xx,*yy;

105:   VecESIWrap(x,&xx);
106:   VecESIWrap(y,&yy);
107:   jac->epc->solveRight(*xx,*yy);
108:   return(0);
109: }

113: static int PCDestroy_ESI(PC pc)
114: {
115:   PC_ESI *jac = (PC_ESI*)pc->data;
116:   int    ierr;

119:   jac->epc->deleteReference();
120:   /*
121:       Free the private data structure that was hanging off the PC
122:   */
123:   PetscFree(jac);
124:   return(0);
125: }

129: static int PCSetFromOptions_ESI(PC pc)
130: {
131:   /* PC_ESI  *jac = (PC_ESI*)pc->data; */
132:   int     ierr;

135:   PetscOptionsHead("ESI options");
136:   PetscOptionsTail();
137:   return(0);
138: }

140: extern PetscFList CCAList;

144: /*@C
145:     PCESISetType - Given a PETSc matrix of type ESI loads the ESI constructor
146:           by name and wraps the ESI operator to look like a PETSc matrix.

148:    Collective on PC

150:    Input Parameters:
151: +   V - preconditioner object
152: -   name - name of the ESI constructor

154:    Level: intermediate

156: @*/
157: int PCESISetType(PC V,const char *name)
158: {
159:   int                                        ierr;
160:   ::esi::Preconditioner<double,int>          *ve;
161:   ::esi::Preconditioner<double,int>::Factory *f,*(*r)(void);

164:   PetscFListFind(V->comm,CCAList,name,(void(**)(void))&r);
165:   if (!r) SETERRQ1(1,"Unable to load esi::PreconditionerFactory constructor %s",name);
166:   f    = (*r)();

168:   f->create((char *) "MPI",(void*)&V->comm,ve);
169:   delete f;
170:   PCESISetPreconditioner(V,ve);
171:   ve->deleteReference();
172:   return(0);
173: }

177: int PCESISetFromOptions(PC V)
178: {
179:   char       string[PETSC_MAX_PATH_LEN];
180:   PetscTruth flg;
181:   int        ierr;
182: 
184:   PetscTypeCompare((PetscObject)V,PCESI,&flg);
185:   if (flg) {
186:     PetscOptionsGetString(V->prefix,"-pc_esi_type",string,1024,&flg);
187:     if (flg) {
188:       PCESISetType(V,string);
189:     }
190:   }
191:   return(0);
192: }

194: /*MC
195:      PCESI - Makes an ESI operator be able to used in PETSc as a preconditioner

197:    Options Database Keys:
198: .  -pc_esi_type - the string name of an ESI operator type that will be dynamically loaded

200:   Level: intermediate

202: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types),
203:            PCESISetPreconditioner(), 

205: M*/

207: EXTERN_C_BEGIN
210: int PCCreate_ESI(PC pc)
211: {
212:   PC_ESI *jac;
213:   int    ierr;


217:   /*
218:      Creates the private data structure for this preconditioner and
219:      attach it to the PC object.
220:   */
221:   PetscNew(PC_ESI,&jac);
222:   pc->data  = (void*)jac;

224:   /*
225:      Logs the memory usage; this is not needed but allows PETSc to 
226:      monitor how much memory is being used for various purposes.
227:   */
228:   PetscLogObjectMemory(pc,sizeof(PC_ESI));

230:   /*
231:       Set the pointers for the functions that are provided above.
232:       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
233:       are called, they will automatically call these functions.  Note we
234:       choose not to provide a couple of these functions since they are
235:       not needed.
236:   */
237:   pc->ops->apply               = PCApply_ESI;
238:   pc->ops->applytranspose      = 0;
239:   pc->ops->setup               = PCSetUp_ESI;
240:   pc->ops->destroy             = PCDestroy_ESI;
241:   pc->ops->setfromoptions      = PCSetFromOptions_ESI;
242:   pc->ops->view                = 0;
243:   pc->ops->applyrichardson     = 0;
244:   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_ESI;
245:   pc->ops->applysymmetricright = PCApplySymmetricRight_ESI;
246:   return(0);
247: }
248: EXTERN_C_END

250: EXTERN_C_BEGIN
253: int PCCreate_PetscESI(PC V)
254: {
255:   int                                    ierr;
256:   PC                                     v;
257:   esi::petsc::Preconditioner<double,int> *ve;

260:   V->ops->destroy = 0;  /* since this is called from PCSetType() we have to make sure it doesn't get destroyed twice */
261:   PCSetType(V,PCESI);
262:   PCCreate(V->comm,&v);
263:   PetscObjectSetOptionsPrefix((PetscObject)v,"esi_");
264:   PCSetFromOptions(v);
265:   ve   = new esi::petsc::Preconditioner<double,int>(v);
266:   PCESISetPreconditioner(V,ve);
267:   ve->deleteReference();
268:   PetscObjectDereference((PetscObject)v);
269:   return(0);
270: }
271: EXTERN_C_END