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: #undef __FUNCT__  
 15: /*@C
 16:    PFSet - Sets the C/C++/Fortran functions to be used by the PF function

 18:    Collective on PF

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

 28:    Level: beginner

 30: .keywords: PF, setting

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

 40:   pf->ops->destroy     = destroy;
 41:   pf->ops->apply       = apply;
 42:   pf->ops->applyvec    = applyvec;
 43:   pf->ops->view        = view;

 45:   return(0);
 46: }

 48: #undef __FUNCT__  
 50: /*@C
 51:    PFDestroy - Destroys PF context that was created with PFCreate().

 53:    Collective on PF

 55:    Input Parameter:
 56: .  pf - the function context

 58:    Level: beginner

 60: .keywords: PF, destroy

 62: .seealso: PFCreate(), PFSet(), PFSetType()
 63: @*/
 64: int PFDestroy(PF pf)
 65: {
 66:   int        ierr;
 67:   PetscTruth flg;

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

 73:   PetscOptionsHasName(pf->prefix,"-pf_view",&flg);
 74:   if (flg) {
 75:     PFView(pf,PETSC_VIEWER_STDOUT_(pf->comm));
 76:   }

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

 81:   if (pf->ops->destroy) { (*pf->ops->destroy)(pf->data);}
 82:   PetscLogObjectDestroy(pf);
 83:   PetscHeaderDestroy(pf);
 84:   return(0);
 85: }

 87: #undef __FUNCT__  
 89: static int PFPublish_Petsc(PetscObject obj)
 90: {
 91: #if defined(PETSC_HAVE_AMS)
 92:   PF          v = (PF) obj;
 93:   int         ierr;
 94: #endif


 98: #if defined(PETSC_HAVE_AMS)
 99:   /* if it is already published then return */
100:   if (v->amem >=0) return(0);

102:   PetscObjectPublishBaseBegin(obj);
103:   PetscObjectPublishBaseEnd(obj);
104: #endif

106:   return(0);
107: }

109: #undef __FUNCT__  
111: /*@C
112:    PFCreate - Creates a mathematical function context.

114:    Collective on MPI_Comm

116:    Input Parameter:
117: +  comm - MPI communicator 
118: .  dimin - dimension of the space you are mapping from
119: -  dimout - dimension of the space you are mapping to

121:    Output Parameter:
122: .  pf - the function context

124:    Level: developer

126: .keywords: PF, create, context

128: .seealso: PFSetUp(), PFApply(), PFDestroy(), PFApplyVec()
129: @*/
130: int PFCreate(MPI_Comm comm,int dimin,int dimout,PF *pf)
131: {
132:   PF  newpf;

137:   *pf = PETSC_NULL;
138: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
139:   VecInitializePackage(PETSC_NULL);
140: #endif

142:   PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_COOKIE,-1,"PF",comm,PFDestroy,PFView);
143:   PetscLogObjectCreate(newpf);
144:   newpf->bops->publish    = PFPublish_Petsc;
145:   newpf->data             = 0;

147:   newpf->ops->destroy     = 0;
148:   newpf->ops->apply       = 0;
149:   newpf->ops->applyvec    = 0;
150:   newpf->ops->view        = 0;
151:   newpf->dimin            = dimin;
152:   newpf->dimout           = dimout;

154:   *pf                     = newpf;
155:   PetscPublishAll(pf);
156:   return(0);

158: }

160: /* -------------------------------------------------------------------------------*/

162: #undef __FUNCT__  
164: /*@
165:    PFApplyVec - Applies the mathematical function to a vector

167:    Collective on PF

169:    Input Parameters:
170: +  pf - the function context
171: -  x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)

173:    Output Parameter:
174: .  y - output vector

176:    Level: beginner

178: .keywords: PF, apply

180: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
181: @*/
182: int PFApplyVec(PF pf,Vec x,Vec y)
183: {
184:   int        ierr,i,rstart,rend,n,p;
185:   PetscTruth nox = PETSC_FALSE;

190:   if (x) {
192:     if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
193:   } else {
194:     PetscScalar *xx;

196:     VecDuplicate(y,&x);
197:     nox  = PETSC_TRUE;
198:     VecGetOwnershipRange(x,&rstart,&rend);
199:     VecGetArray(x,&xx);
200:     for (i=rstart; i<rend; i++) {
201:       xx[i-rstart] = (PetscScalar)i;
202:     }
203:     VecRestoreArray(x,&xx);
204:   }

206:   VecGetLocalSize(x,&n);
207:   VecGetLocalSize(y,&p);
208:   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);
209:   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);
210:   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);

212:   if (pf->ops->applyvec) {
213:     (*pf->ops->applyvec)(pf->data,x,y);
214:   } else {
215:     PetscScalar *xx,*yy;

217:     VecGetLocalSize(x,&n);
218:     n    = n/pf->dimin;
219:     VecGetArray(x,&xx);
220:     VecGetArray(y,&yy);
221:     if (!pf->ops->apply) SETERRQ(1,"No function has been provided for this PF");
222:     (*pf->ops->apply)(pf->data,n,xx,yy);
223:     VecRestoreArray(x,&xx);
224:     VecRestoreArray(y,&yy);
225:   }
226:   if (nox) {
227:     VecDestroy(x);
228:   }
229:   return(0);
230: }

232: #undef __FUNCT__  
234: /*@
235:    PFApply - Applies the mathematical function to an array of values.

237:    Collective on PF

239:    Input Parameters:
240: +  pf - the function context
241: .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
242:        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
243:        in the call to PFCreate()
244: -  x - input array

246:    Output Parameter:
247: .  y - output array

249:    Level: beginner

251:    Notes: 

253: .keywords: PF, apply

255: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
256: @*/
257: int PFApply(PF pf,int n,PetscScalar* x,PetscScalar* y)
258: {
259:   int        ierr;

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

266:   (*pf->ops->apply)(pf->data,n,x,y);
267:   return(0);
268: }

270: #undef __FUNCT__  
272: /*@ 
273:    PFView - Prints information about a mathematical function

275:    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF  

277:    Input Parameters:
278: +  PF - the PF context
279: -  viewer - optional visualization context

281:    Note:
282:    The available visualization contexts include
283: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
284: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
285:          output where only the first processor opens
286:          the file.  All other processors send their 
287:          data to the first processor to print. 

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

292:    Level: developer

294: .keywords: PF, view

296: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
297: @*/
298: int PFView(PF pf,PetscViewer viewer)
299: {
300:   PFType            cstr;
301:   int               ierr;
302:   PetscTruth        isascii;
303:   PetscViewerFormat format;

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

311:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
312:   if (isascii) {
313:     PetscViewerGetFormat(viewer,&format);
314:     PetscViewerASCIIPrintf(viewer,"PF Object:n");
315:     PFGetType(pf,&cstr);
316:     if (cstr) {
317:       PetscViewerASCIIPrintf(viewer,"  type: %sn",cstr);
318:     } else {
319:       PetscViewerASCIIPrintf(viewer,"  type: not yet setn");
320:     }
321:     if (pf->ops->view) {
322:       PetscViewerASCIIPushTab(viewer);
323:       (*pf->ops->view)(pf->data,viewer);
324:       PetscViewerASCIIPopTab(viewer);
325:     }
326:   } else {
327:     SETERRQ1(1,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
328:   }
329:   return(0);
330: }

332: /*MC
333:    PFRegisterDynamic - Adds a method to the mathematical function package.

335:    Synopsis:
336:    int PFRegisterDynamic(char *name_solver,char *path,char *name_create,int (*routine_create)(PF))

338:    Not collective

340:    Input Parameters:
341: +  name_solver - name of a new user-defined solver
342: .  path - path (either absolute or relative) the library containing this solver
343: .  name_create - name of routine to create method context
344: -  routine_create - routine to create method context

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

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

352:    Sample usage:
353: .vb
354:    PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
355:               "MyFunctionCreate",MyFunctionSetCreate);
356: .ve

358:    Then, your solver can be chosen with the procedural interface via
359: $     PFSetType(pf,"my_function")
360:    or at runtime via the option
361: $     -pf_type my_function

363:    Level: advanced

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

368: .keywords: PF, register

370: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
371: M*/

373: #undef __FUNCT__  
375: int PFRegister(char *sname,char *path,char *name,int (*function)(PF,void*))
376: {
377:   int  ierr;
378:   char fullname[256];

381:   PetscFListConcat(path,name,fullname);
382:   PetscFListAdd(&PPetscFList,sname,fullname,(void (*)(void))function);
383:   return(0);
384: }



388: #undef __FUNCT__  
390: /*@C
391:    PFGetType - Gets the PF method type and name (as a string) from the PF
392:    context.

394:    Not Collective

396:    Input Parameter:
397: .  pf - the function context

399:    Output Parameter:
400: .  name - name of function 

402:    Level: intermediate

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

406: .seealso: PFSetType()

408: @*/
409: int PFGetType(PF pf,PFType *meth)
410: {
412:   *meth = (PFType) pf->type_name;
413:   return(0);
414: }


417: #undef __FUNCT__  
419: /*@C
420:    PFSetType - Builds PF for a particular function

422:    Collective on PF

424:    Input Parameter:
425: +  pf - the function context.
426: .  type - a known method
427: -  ctx - optional type dependent context

429:    Options Database Key:
430: .  -pf_type <type> - Sets PF type


433:   Notes:
434:   See "petsc/include/petscpf.h" for available methods (for instance,
435:   PFCONSTANT)

437:   Level: intermediate

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

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

443: @*/
444: int PFSetType(PF pf,PFType type,void *ctx)
445: {
446:   int        ierr,(*r)(PF,void*);
447:   PetscTruth match;


453:   PetscTypeCompare((PetscObject)pf,type,&match);
454:   if (match) return(0);

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

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

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

466:   pf->ops->destroy             = 0;
467:   pf->ops->view                = 0;
468:   pf->ops->apply               = 0;
469:   pf->ops->applyvec            = 0;

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

474:   PetscObjectChangeTypeName((PetscObject)pf,type);
475:   return(0);
476: }

478: #undef __FUNCT__  
480: /*@
481:    PFSetFromOptions - Sets PF options from the options database.

483:    Collective on PF

485:    Input Parameters:
486: .  pf - the mathematical function context

488:    Options Database Keys:

490:    Notes:  
491:    To see all options, run your program with the -help option
492:    or consult the users manual.

494:    Level: intermediate

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

498: .seealso:
499: @*/
500: int PFSetFromOptions(PF pf)
501: {
502:   int        ierr;
503:   char       type[256];
504:   PetscTruth flg;


509:   if (!PFRegisterAllCalled) {PFRegisterAll(0);}
510:   PetscOptionsBegin(pf->comm,pf->prefix,"Mathematical functions options","Vec");
511:     PetscOptionsList("-pf_type","Type of function","PFSetType",PPetscFList,0,type,256,&flg);
512:     if (flg) {
513:       PFSetType(pf,type,PETSC_NULL);
514:     }
515:     if (pf->ops->setfromoptions) {
516:       (*pf->ops->setfromoptions)(pf);
517:     }
518:   PetscOptionsEnd();

520:   return(0);
521: }