Actual source code: pf.c

petsc-3.3-p7 2013-05-11
  1: /*
  2:     The PF mathematical functions interface routines, callable by users.
  3: */
  4: #include <../src/vec/pf/pfimpl.h>            /*I "petscpf.h" I*/

  6: /* Logging support */
  7: PetscClassId PF_CLASSID = 0;

  9: PetscFList PFList         = PETSC_NULL; /* list of all registered PD functions */
 10: PetscBool  PFRegisterAllCalled = PETSC_FALSE;

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

 17:    Collective on PF

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

 27:    Level: beginner

 29: .keywords: PF, setting

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

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

 44:   return(0);
 45: }

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

 52:    Collective on PF

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

 57:    Level: beginner

 59: .keywords: PF, destroy

 61: .seealso: PFCreate(), PFSet(), PFSetType()
 62: @*/
 63: PetscErrorCode  PFDestroy(PF *pf)
 64: {
 66:   PetscBool      flg = PETSC_FALSE;

 69:   if (!*pf) return(0);
 71:   if (--((PetscObject)(*pf))->refct > 0) return(0);

 73:   PetscOptionsGetBool(((PetscObject)(*pf))->prefix,"-pf_view",&flg,PETSC_NULL);
 74:   if (flg) {
 75:     PetscViewer viewer;
 76:     PetscViewerASCIIGetStdout(((PetscObject)(*pf))->comm,&viewer);
 77:     PFView((*pf),viewer);
 78:   }

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

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

 90: /*@C
 91:    PFCreate - Creates a mathematical function context.

 93:    Collective on MPI_Comm

 95:    Input Parameter:
 96: +  comm - MPI communicator 
 97: .  dimin - dimension of the space you are mapping from
 98: -  dimout - dimension of the space you are mapping to

100:    Output Parameter:
101: .  pf - the function context

103:    Level: developer

105: .keywords: PF, create, context

107: .seealso: PFSet(), PFApply(), PFDestroy(), PFApplyVec()
108: @*/
109: PetscErrorCode  PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
110: {
111:   PF             newpf;

116:   *pf = PETSC_NULL;
117: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
118:   PFInitializePackage(PETSC_NULL);
119: #endif

121:   PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_CLASSID,-1,"PF","Mathematical functions","Vec",comm,PFDestroy,PFView);
122:   newpf->data             = 0;

124:   newpf->ops->destroy     = 0;
125:   newpf->ops->apply       = 0;
126:   newpf->ops->applyvec    = 0;
127:   newpf->ops->view        = 0;
128:   newpf->dimin            = dimin;
129:   newpf->dimout           = dimout;

131:   *pf                     = newpf;
132:   return(0);

134: }

136: /* -------------------------------------------------------------------------------*/

140: /*@
141:    PFApplyVec - Applies the mathematical function to a vector

143:    Collective on PF

145:    Input Parameters:
146: +  pf - the function context
147: -  x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)

149:    Output Parameter:
150: .  y - output vector

152:    Level: beginner

154: .keywords: PF, apply

156: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
157: @*/
158: PetscErrorCode  PFApplyVec(PF pf,Vec x,Vec y)
159: {
161:   PetscInt       i,rstart,rend,n,p;
162:   PetscBool      nox = PETSC_FALSE;

167:   if (x) {
169:     if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different vectors");
170:   } else {
171:     PetscScalar *xx;
172:     PetscInt    lsize;

174:     VecGetLocalSize(y,&lsize);
175:     lsize = pf->dimin*lsize/pf->dimout;
176:     VecCreateMPI(((PetscObject)y)->comm,lsize,PETSC_DETERMINE,&x);
177:     nox  = PETSC_TRUE;
178:     VecGetOwnershipRange(x,&rstart,&rend);
179:     VecGetArray(x,&xx);
180:     for (i=rstart; i<rend; i++) {
181:       xx[i-rstart] = (PetscScalar)i;
182:     }
183:     VecRestoreArray(x,&xx);
184:   }

186:   VecGetLocalSize(x,&n);
187:   VecGetLocalSize(y,&p);
188:   if ((pf->dimin*(n/pf->dimin)) != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local input vector length %D not divisible by dimin %D of function",n,pf->dimin);
189:   if ((pf->dimout*(p/pf->dimout)) != p) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local output vector length %D not divisible by dimout %D of function",p,pf->dimout);
190:   if ((n/pf->dimin) != (p/pf->dimout)) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local vector lengths %D %D are wrong for dimin and dimout %D %D of function",n,p,pf->dimin,pf->dimout);

192:   if (pf->ops->applyvec) {
193:     (*pf->ops->applyvec)(pf->data,x,y);
194:   } else {
195:     PetscScalar *xx,*yy;

197:     VecGetLocalSize(x,&n);
198:     n    = n/pf->dimin;
199:     VecGetArray(x,&xx);
200:     VecGetArray(y,&yy);
201:     if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
202:     (*pf->ops->apply)(pf->data,n,xx,yy);
203:     VecRestoreArray(x,&xx);
204:     VecRestoreArray(y,&yy);
205:   }
206:   if (nox) {
207:     VecDestroy(&x);
208:   }
209:   return(0);
210: }

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

217:    Collective on PF

219:    Input Parameters:
220: +  pf - the function context
221: .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
222:        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
223:        in the call to PFCreate()
224: -  x - input array

226:    Output Parameter:
227: .  y - output array

229:    Level: beginner

231:    Notes: 

233: .keywords: PF, apply

235: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
236: @*/
237: PetscErrorCode  PFApply(PF pf,PetscInt n,const PetscScalar* x,PetscScalar* y)
238: {

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

248:   (*pf->ops->apply)(pf->data,n,x,y);
249:   return(0);
250: }

254: /*@ 
255:    PFView - Prints information about a mathematical function

257:    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF  

259:    Input Parameters:
260: +  PF - the PF context
261: -  viewer - optional visualization context

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

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

274:    Level: developer

276: .keywords: PF, view

278: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
279: @*/
280: PetscErrorCode  PFView(PF pf,PetscViewer viewer)
281: {
282:   PetscErrorCode    ierr;
283:   PetscBool         iascii;
284:   PetscViewerFormat format;

288:   if (!viewer) {
289:     PetscViewerASCIIGetStdout(((PetscObject)pf)->comm,&viewer);
290:   }

294:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
295:   if (iascii) {
296:     PetscViewerGetFormat(viewer,&format);
297:     PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer,"PF Object");
298:     if (pf->ops->view) {
299:       PetscViewerASCIIPushTab(viewer);
300:       (*pf->ops->view)(pf->data,viewer);
301:       PetscViewerASCIIPopTab(viewer);
302:     }
303:   } else {
304:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
305:   }
306:   return(0);
307: }

309: /*MC
310:    PFRegisterDynamic - Adds a method to the mathematical function package.

312:    Synopsis:
313:    PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))

315:    Not collective

317:    Input Parameters:
318: +  name_solver - name of a new user-defined solver
319: .  path - path (either absolute or relative) the library containing this solver
320: .  name_create - name of routine to create method context
321: -  routine_create - routine to create method context

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

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

329:    Sample usage:
330: .vb
331:    PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
332:               "MyFunctionCreate",MyFunctionSetCreate);
333: .ve

335:    Then, your solver can be chosen with the procedural interface via
336: $     PFSetType(pf,"my_function")
337:    or at runtime via the option
338: $     -pf_type my_function

340:    Level: advanced

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

345: .keywords: PF, register

347: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
348: M*/

352: PetscErrorCode  PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
353: {
355:   char           fullname[PETSC_MAX_PATH_LEN];

358:   PetscFListConcat(path,name,fullname);
359:   PetscFListAdd(&PFList,sname,fullname,(void (*)(void))function);
360:   return(0);
361: }

365: /*@C
366:    PFGetType - Gets the PF method type and name (as a string) from the PF
367:    context.

369:    Not Collective

371:    Input Parameter:
372: .  pf - the function context

374:    Output Parameter:
375: .  type - name of function 

377:    Level: intermediate

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

381: .seealso: PFSetType()

383: @*/
384: PetscErrorCode  PFGetType(PF pf,const PFType *type)
385: {
389:   *type = ((PetscObject)pf)->type_name;
390:   return(0);
391: }


396: /*@C
397:    PFSetType - Builds PF for a particular function

399:    Collective on PF

401:    Input Parameter:
402: +  pf - the function context.
403: .  type - a known method
404: -  ctx - optional type dependent context

406:    Options Database Key:
407: .  -pf_type <type> - Sets PF type


410:   Notes:
411:   See "petsc/include/petscpf.h" for available methods (for instance,
412:   PFCONSTANT)

414:   Level: intermediate

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

418: .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DMDACreatePF()

420: @*/
421: PetscErrorCode  PFSetType(PF pf,const PFType type,void *ctx)
422: {
423:   PetscErrorCode ierr,(*r)(PF,void*);
424:   PetscBool      match;


430:   PetscObjectTypeCompare((PetscObject)pf,type,&match);
431:   if (match) return(0);

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

436:   /* Determine the PFCreateXXX routine for a particular function */
437:    PetscFListFind(PFList,((PetscObject)pf)->comm,type,PETSC_TRUE,(void (**)(void)) &r);
438:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
439:   pf->ops->destroy             = 0;
440:   pf->ops->view                = 0;
441:   pf->ops->apply               = 0;
442:   pf->ops->applyvec            = 0;

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

447:   PetscObjectChangeTypeName((PetscObject)pf,type);
448:   return(0);
449: }

453: /*@
454:    PFSetFromOptions - Sets PF options from the options database.

456:    Collective on PF

458:    Input Parameters:
459: .  pf - the mathematical function context

461:    Options Database Keys:

463:    Notes:  
464:    To see all options, run your program with the -help option
465:    or consult the users manual.

467:    Level: intermediate

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

471: .seealso:
472: @*/
473: PetscErrorCode  PFSetFromOptions(PF pf)
474: {
476:   char           type[256];
477:   PetscBool      flg;


482:   PetscObjectOptionsBegin((PetscObject)pf);
483:     PetscOptionsList("-pf_type","Type of function","PFSetType",PFList,0,type,256,&flg);
484:     if (flg) {
485:       PFSetType(pf,type,PETSC_NULL);
486:     }
487:     if (pf->ops->setfromoptions) {
488:       (*pf->ops->setfromoptions)(pf);
489:     }

491:     /* process any options handlers added with PetscObjectAddOptionsHandler() */
492:     PetscObjectProcessOptionsHandlers((PetscObject)pf);
493:   PetscOptionsEnd();

495:   return(0);
496: }

498: static PetscBool  PFPackageInitialized = PETSC_FALSE;
501: /*@C
502:   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
503:   called from PetscFinalize().

505:   Level: developer

507: .keywords: Petsc, destroy, package, mathematica
508: .seealso: PetscFinalize()
509: @*/
510: PetscErrorCode  PFFinalizePackage(void)
511: {
513:   PFPackageInitialized = PETSC_FALSE;
514:   PFList               = PETSC_NULL;
515:   PFRegisterAllCalled  = PETSC_FALSE;
516:   return(0);
517: }

521: /*@C
522:   PFInitializePackage - This function initializes everything in the PF package. It is called
523:   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate()
524:   when using static libraries.

526:   Input Parameter:
527: . path - The dynamic library path, or PETSC_NULL

529:   Level: developer

531: .keywords: Vec, initialize, package
532: .seealso: PetscInitialize()
533: @*/
534: PetscErrorCode  PFInitializePackage(const char path[])
535: {
536:   char              logList[256];
537:   char              *className;
538:   PetscBool         opt;
539:   PetscErrorCode    ierr;

542:   if (PFPackageInitialized) return(0);
543:   PFPackageInitialized = PETSC_TRUE;
544:   /* Register Classes */
545:   PetscClassIdRegister("PointFunction",&PF_CLASSID);
546:   /* Register Constructors */
547:   PFRegisterAll(path);
548:   /* Process info exclusions */
549:   PetscOptionsGetString(PETSC_NULL, "-info_exclude", logList, 256, &opt);
550:   if (opt) {
551:     PetscStrstr(logList, "pf", &className);
552:     if (className) {
553:       PetscInfoDeactivateClass(PF_CLASSID);
554:     }
555:   }
556:   /* Process summary exclusions */
557:   PetscOptionsGetString(PETSC_NULL, "-log_summary_exclude", logList, 256, &opt);
558:   if (opt) {
559:     PetscStrstr(logList, "pf", &className);
560:     if (className) {
561:       PetscLogEventDeactivateClass(PF_CLASSID);
562:     }
563:   }
564:   PetscRegisterFinalize(PFFinalizePackage);
565:   return(0);
566: }