Actual source code: pf.c

  1: /*$Id: pf.c,v 1.25 2001/08/07 03:05:06 balay Exp $*/
  2: /*
  3:     The PF mathematical functions interface routines, callable by users.
  4: */
 5:  #include src/pf/pfimpl.h

  7: /* Logging support */
  8: int PF_COOKIE;

 10: PetscFList PPetscFList         = PETSC_NULL; /* list of all registered PD functions */
 11: PetscTruth PFRegisterAllCalled = PETSC_FALSE;

 13: /*@C
 14:    PFSet - Sets the C/C++/Fortran functions to be used by the PF function

 16:    Collective on PF

 18:    Input Parameter:
 19: +  pf - the function context
 20: .  apply - function to apply to an array
 21: .  applyvec - function to apply to a Vec
 22: .  view - function that prints information about the PF
 23: .  destroy - function to free the private function context
 24: -  ctx - private function context

 26:    Level: beginner

 28: .keywords: PF, setting

 30: .seealso: PFCreate(), PFDestroy(), PFSetType(), PFApply(), PFApplyVec()
 31: @*/
 32: int PFSet(PF pf,int(*apply)(void*,int,PetscScalar*,PetscScalar*),int(*applyvec)(void*,Vec,Vec),int(*view)(void*,PetscViewer),int(*destroy)(void*),void*ctx)
 33: {
 36:   pf->data             = ctx;

 38:   pf->ops->destroy     = destroy;
 39:   pf->ops->apply       = apply;
 40:   pf->ops->applyvec    = applyvec;
 41:   pf->ops->view        = view;

 43:   return(0);
 44: }

 46: /*@C
 47:    PFDestroy - Destroys PF context that was created with PFCreate().

 49:    Collective on PF

 51:    Input Parameter:
 52: .  pf - the function context

 54:    Level: beginner

 56: .keywords: PF, destroy

 58: .seealso: PFCreate(), PFSet(), PFSetType()
 59: @*/
 60: int PFDestroy(PF pf)
 61: {
 62:   int        ierr;
 63:   PetscTruth flg;

 67:   if (--pf->refct > 0) return(0);

 69:   PetscOptionsHasName(pf->prefix,"-pf_view",&flg);
 70:   if (flg) {
 71:     PFView(pf,PETSC_VIEWER_STDOUT_(pf->comm));
 72:   }

 74:   /* if memory was published with AMS then destroy it */
 75:   PetscObjectDepublish(pf);

 77:   if (pf->ops->destroy) { (*pf->ops->destroy)(pf->data);}
 78:   PetscLogObjectDestroy(pf);
 79:   PetscHeaderDestroy(pf);
 80:   return(0);
 81: }

 83: static int PFPublish_Petsc(PetscObject obj)
 84: {
 85: #if defined(PETSC_HAVE_AMS)
 86:   PF          v = (PF) obj;
 87:   int         ierr;
 88: #endif


 92: #if defined(PETSC_HAVE_AMS)
 93:   /* if it is already published then return */
 94:   if (v->amem >=0) return(0);

 96:   PetscObjectPublishBaseBegin(obj);
 97:   PetscObjectPublishBaseEnd(obj);
 98: #endif

100:   return(0);
101: }

103: /*@C
104:    PFCreate - Creates a mathematical function context.

106:    Collective on MPI_Comm

108:    Input Parameter:
109: +  comm - MPI communicator 
110: .  dimin - dimension of the space you are mapping from
111: -  dimout - dimension of the space you are mapping to

113:    Output Parameter:
114: .  pf - the function context

116:    Level: developer

118: .keywords: PF, create, context

120: .seealso: PFSetUp(), PFApply(), PFDestroy(), PFApplyVec()
121: @*/
122: int PFCreate(MPI_Comm comm,int dimin,int dimout,PF *pf)
123: {
124:   PF  newpf;

129:   *pf = PETSC_NULL;
130: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
131:   VecInitializePackage(PETSC_NULL);
132: #endif

134:   PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_COOKIE,-1,"PF",comm,PFDestroy,PFView);
135:   PetscLogObjectCreate(newpf);
136:   newpf->bops->publish    = PFPublish_Petsc;
137:   newpf->data             = 0;

139:   newpf->ops->destroy     = 0;
140:   newpf->ops->apply       = 0;
141:   newpf->ops->applyvec    = 0;
142:   newpf->ops->view        = 0;
143:   newpf->dimin            = dimin;
144:   newpf->dimout           = dimout;

146:   *pf                     = newpf;
147:   PetscPublishAll(pf);
148:   return(0);

150: }

152: /* -------------------------------------------------------------------------------*/

154: /*@
155:    PFApplyVec - Applies the mathematical function to a vector

157:    Collective on PF

159:    Input Parameters:
160: +  pf - the function context
161: -  x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)

163:    Output Parameter:
164: .  y - output vector

166:    Level: beginner

168: .keywords: PF, apply

170: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
171: @*/
172: int PFApplyVec(PF pf,Vec x,Vec y)
173: {
174:   int        ierr,i,rstart,rend,n,p;
175:   PetscTruth nox = PETSC_FALSE;

180:   if (x) {
182:     if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
183:   } else {
184:     PetscScalar *xx;

186:     VecDuplicate(y,&x);
187:     nox  = PETSC_TRUE;
188:     VecGetOwnershipRange(x,&rstart,&rend);
189:     VecGetArray(x,&xx);
190:     for (i=rstart; i<rend; i++) {
191:       xx[i-rstart] = (PetscScalar)i;
192:     }
193:     VecRestoreArray(x,&xx);
194:   }

196:   VecGetLocalSize(x,&n);
197:   VecGetLocalSize(y,&p);
198:   if (pf->dimin*(n/pf->dimin) != n) SETERRQ2(PETSC_ERR_ARG_IDN,"Local input vector length %d not divisible by dimin %d of function",n,pf->dimin);
199:   if (pf->dimout*(p/pf->dimout) != p) SETERRQ2(PETSC_ERR_ARG_IDN,"Local output vector length %d not divisible by dimout %d of function",p,pf->dimout);
200:   if (n/pf->dimin != p/pf->dimout) SETERRQ4(PETSC_ERR_ARG_IDN,"Local vector lengths %d %d are wrong for dimin and dimout %d %d of function",n,p,pf->dimin,pf->dimout);

202:   if (pf->ops->applyvec) {
203:     (*pf->ops->applyvec)(pf->data,x,y);
204:   } else {
205:     PetscScalar *xx,*yy;

207:     VecGetLocalSize(x,&n);
208:     n    = n/pf->dimin;
209:     VecGetArray(x,&xx);
210:     VecGetArray(y,&yy);
211:     if (!pf->ops->apply) SETERRQ(1,"No function has been provided for this PF");
212:     (*pf->ops->apply)(pf->data,n,xx,yy);
213:     VecRestoreArray(x,&xx);
214:     VecRestoreArray(y,&yy);
215:   }
216:   if (nox) {
217:     VecDestroy(x);
218:   }
219:   return(0);
220: }

222: /*@
223:    PFApply - Applies the mathematical function to an array of values.

225:    Collective on PF

227:    Input Parameters:
228: +  pf - the function context
229: .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
230:        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
231:        in the call to PFCreate()
232: -  x - input array

234:    Output Parameter:
235: .  y - output array

237:    Level: beginner

239:    Notes: 

241: .keywords: PF, apply

243: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
244: @*/
245: int PFApply(PF pf,int n,PetscScalar* x,PetscScalar* y)
246: {
247:   int        ierr;

251:   if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different arrays");
252:   if (!pf->ops->apply) SETERRQ(1,"No function has been provided for this PF");

254:   (*pf->ops->apply)(pf->data,n,x,y);
255:   return(0);
256: }

258: /*@ 
259:    PFView - Prints information about a mathematical function

261:    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF  

263:    Input Parameters:
264: +  PF - the PF context
265: -  viewer - optional visualization context

267:    Note:
268:    The available visualization contexts include
269: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
270: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
271:          output where only the first processor opens
272:          the file.  All other processors send their 
273:          data to the first processor to print. 

275:    The user can open an alternative visualization contexts with
276:    PetscViewerASCIIOpen() (output to a specified file).

278:    Level: developer

280: .keywords: PF, view

282: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
283: @*/
284: int PFView(PF pf,PetscViewer viewer)
285: {
286:   PFType            cstr;
287:   int               ierr;
288:   PetscTruth        isascii;
289:   PetscViewerFormat format;

293:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pf->comm);

297:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
298:   if (isascii) {
299:     PetscViewerGetFormat(viewer,&format);
300:     PetscViewerASCIIPrintf(viewer,"PF Object:n");
301:     PFGetType(pf,&cstr);
302:     if (cstr) {
303:       PetscViewerASCIIPrintf(viewer,"  type: %sn",cstr);
304:     } else {
305:       PetscViewerASCIIPrintf(viewer,"  type: not yet setn");
306:     }
307:     if (pf->ops->view) {
308:       PetscViewerASCIIPushTab(viewer);
309:       (*pf->ops->view)(pf->data,viewer);
310:       PetscViewerASCIIPopTab(viewer);
311:     }
312:   } else {
313:     SETERRQ1(1,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
314:   }
315:   return(0);
316: }

318: /*MC
319:    PFRegisterDynamic - Adds a method to the mathematical function package.

321:    Synopsis:
322:    int PFRegisterDynamic(char *name_solver,char *path,char *name_create,int (*routine_create)(PF))

324:    Not collective

326:    Input Parameters:
327: +  name_solver - name of a new user-defined solver
328: .  path - path (either absolute or relative) the library containing this solver
329: .  name_create - name of routine to create method context
330: -  routine_create - routine to create method context

332:    Notes:
333:    PFRegisterDynamic() may be called multiple times to add several user-defined functions

335:    If dynamic libraries are used, then the fourth input argument (routine_create)
336:    is ignored.

338:    Sample usage:
339: .vb
340:    PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
341:               "MyFunctionCreate",MyFunctionSetCreate);
342: .ve

344:    Then, your solver can be chosen with the procedural interface via
345: $     PFSetType(pf,"my_function")
346:    or at runtime via the option
347: $     -pf_type my_function

349:    Level: advanced

351:    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${BOPT}, or ${any environmental variable}
352:  occuring in pathname will be replaced with appropriate values.

354: .keywords: PF, register

356: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
357: M*/

359: int PFRegister(char *sname,char *path,char *name,int (*function)(PF,void*))
360: {
361:   int  ierr;
362:   char fullname[256];

365:   PetscFListConcat(path,name,fullname);
366:   PetscFListAdd(&PPetscFList,sname,fullname,(void (*)(void))function);
367:   return(0);
368: }



372: /*@C
373:    PFGetType - Gets the PF method type and name (as a string) from the PF
374:    context.

376:    Not Collective

378:    Input Parameter:
379: .  pf - the function context

381:    Output Parameter:
382: .  name - name of function 

384:    Level: intermediate

386: .keywords: PF, get, method, name, type

388: .seealso: PFSetType()

390: @*/
391: int PFGetType(PF pf,PFType *meth)
392: {
394:   *meth = (PFType) pf->type_name;
395:   return(0);
396: }


399: /*@C
400:    PFSetType - Builds PF for a particular function

402:    Collective on PF

404:    Input Parameter:
405: +  pf - the function context.
406: .  type - a known method
407: -  ctx - optional type dependent context

409:    Options Database Key:
410: .  -pf_type <type> - Sets PF type


413:   Notes:
414:   See "petsc/include/petscpf.h" for available methods (for instance,
415:   PFCONSTANT)

417:   Level: intermediate

419: .keywords: PF, set, method, type

421: .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DACreatePF()

423: @*/
424: int PFSetType(PF pf,PFType type,void *ctx)
425: {
426:   int        ierr,(*r)(PF,void*);
427:   PetscTruth match;


433:   PetscTypeCompare((PetscObject)pf,type,&match);
434:   if (match) return(0);

436:   if (pf->ops->destroy) { (*pf->ops->destroy)(pf);}
437:   pf->data        = 0;

439:   /* Get the function pointers for the method requested */
440:   if (!PFRegisterAllCalled) {PFRegisterAll(0);}

442:   /* Determine the PFCreateXXX routine for a particular function */
443:    PetscFListFind(pf->comm,PPetscFList,type,(void (**)(void)) &r);
444:   if (!r) SETERRQ1(1,"Unable to find requested PF type %s",type);

446:   pf->ops->destroy             = 0;
447:   pf->ops->view                = 0;
448:   pf->ops->apply               = 0;
449:   pf->ops->applyvec            = 0;

451:   /* Call the PFCreateXXX routine for this particular function */
452:   (*r)(pf,ctx);

454:   PetscObjectChangeTypeName((PetscObject)pf,type);
455:   return(0);
456: }

458: /*@
459:    PFSetFromOptions - Sets PF options from the options database.

461:    Collective on PF

463:    Input Parameters:
464: .  pf - the mathematical function context

466:    Options Database Keys:

468:    Notes:  
469:    To see all options, run your program with the -help option
470:    or consult the users manual.

472:    Level: intermediate

474: .keywords: PF, set, from, options, database

476: .seealso:
477: @*/
478: int PFSetFromOptions(PF pf)
479: {
480:   int        ierr;
481:   char       type[256];
482:   PetscTruth flg;


487:   if (!PFRegisterAllCalled) {PFRegisterAll(0);}
488:   PetscOptionsBegin(pf->comm,pf->prefix,"Mathematical functions options","Vec");
489:     PetscOptionsList("-pf_type","Type of function","PFSetType",PPetscFList,0,type,256,&flg);
490:     if (flg) {
491:       PFSetType(pf,type,PETSC_NULL);
492:     }
493:     if (pf->ops->setfromoptions) {
494:       (*pf->ops->setfromoptions)(pf);
495:     }
496:   PetscOptionsEnd();

498:   return(0);
499: }