Actual source code: pf.c

  1: #define PETSCVEC_DLL
  2: /*
  3:     The PF mathematical functions interface routines, callable by users.
  4: */
 5:  #include ../src/vec/pf/pfimpl.h

  7: /* Logging support */
  8: PetscCookie PF_COOKIE = 0;

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

 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: PetscErrorCode  PFSet(PF pf,PetscErrorCode (*apply)(void*,PetscInt,PetscScalar*,PetscScalar*),PetscErrorCode (*applyvec)(void*,Vec,Vec),PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*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: }

 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: PetscErrorCode  PFDestroy(PF pf)
 65: {
 67:   PetscTruth     flg = PETSC_FALSE;

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

 73:   PetscOptionsGetTruth(((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: PFSetUp(), 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_COOKIE,-1,"PF",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:   PetscPublishAll(pf);
133:   return(0);

135: }

137: /* -------------------------------------------------------------------------------*/

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

144:    Collective on PF

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

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

153:    Level: beginner

155: .keywords: PF, apply

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

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

174:     VecDuplicate(y,&x);
175:     nox  = PETSC_TRUE;
176:     VecGetOwnershipRange(x,&rstart,&rend);
177:     VecGetArray(x,&xx);
178:     for (i=rstart; i<rend; i++) {
179:       xx[i-rstart] = (PetscScalar)i;
180:     }
181:     VecRestoreArray(x,&xx);
182:   }

184:   VecGetLocalSize(x,&n);
185:   VecGetLocalSize(y,&p);
186:   if ((pf->dimin*(n/pf->dimin)) != n) SETERRQ2(PETSC_ERR_ARG_SIZ,"Local input vector length %D not divisible by dimin %D of function",n,pf->dimin);
187:   if ((pf->dimout*(p/pf->dimout)) != p) SETERRQ2(PETSC_ERR_ARG_SIZ,"Local output vector length %D not divisible by dimout %D of function",p,pf->dimout);
188:   if ((n/pf->dimin) != (p/pf->dimout)) SETERRQ4(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);

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

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

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

215:    Collective on PF

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

224:    Output Parameter:
225: .  y - output array

227:    Level: beginner

229:    Notes: 

231: .keywords: PF, apply

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

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

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

252: /*@ 
253:    PFView - Prints information about a mathematical function

255:    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF  

257:    Input Parameters:
258: +  PF - the PF context
259: -  viewer - optional visualization context

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

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

272:    Level: developer

274: .keywords: PF, view

276: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
277: @*/
278: PetscErrorCode  PFView(PF pf,PetscViewer viewer)
279: {
280:   const PFType      cstr;
281:   PetscErrorCode    ierr;
282:   PetscTruth        iascii;
283:   PetscViewerFormat format;

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

293:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
294:   if (iascii) {
295:     PetscViewerGetFormat(viewer,&format);
296:     PetscViewerASCIIPrintf(viewer,"PF Object:\n");
297:     PFGetType(pf,&cstr);
298:     if (cstr) {
299:       PetscViewerASCIIPrintf(viewer,"  type: %s\n",cstr);
300:     } else {
301:       PetscViewerASCIIPrintf(viewer,"  type: not yet set\n");
302:     }
303:     if (pf->ops->view) {
304:       PetscViewerASCIIPushTab(viewer);
305:       (*pf->ops->view)(pf->data,viewer);
306:       PetscViewerASCIIPopTab(viewer);
307:     }
308:   } else {
309:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
310:   }
311:   return(0);
312: }

314: /*MC
315:    PFRegisterDynamic - Adds a method to the mathematical function package.

317:    Synopsis:
318:    PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))

320:    Not collective

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

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

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

334:    Sample usage:
335: .vb
336:    PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
337:               "MyFunctionCreate",MyFunctionSetCreate);
338: .ve

340:    Then, your solver can be chosen with the procedural interface via
341: $     PFSetType(pf,"my_function")
342:    or at runtime via the option
343: $     -pf_type my_function

345:    Level: advanced

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

350: .keywords: PF, register

352: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
353: M*/

357: PetscErrorCode  PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
358: {
360:   char           fullname[PETSC_MAX_PATH_LEN];

363:   PetscFListConcat(path,name,fullname);
364:   PetscFListAdd(&PFList,sname,fullname,(void (*)(void))function);
365:   return(0);
366: }

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

374:    Not Collective

376:    Input Parameter:
377: .  pf - the function context

379:    Output Parameter:
380: .  type - name of function 

382:    Level: intermediate

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

386: .seealso: PFSetType()

388: @*/
389: PetscErrorCode  PFGetType(PF pf,const PFType *type)
390: {
394:   *type = ((PetscObject)pf)->type_name;
395:   return(0);
396: }


401: /*@C
402:    PFSetType - Builds PF for a particular function

404:    Collective on PF

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

411:    Options Database Key:
412: .  -pf_type <type> - Sets PF type


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

419:   Level: intermediate

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

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

425: @*/
426: PetscErrorCode  PFSetType(PF pf,const PFType type,void *ctx)
427: {
428:   PetscErrorCode ierr,(*r)(PF,void*);
429:   PetscTruth     match;


435:   PetscTypeCompare((PetscObject)pf,type,&match);
436:   if (match) return(0);

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

441:   /* Determine the PFCreateXXX routine for a particular function */
442:    PetscFListFind(PFList,((PetscObject)pf)->comm,type,(void (**)(void)) &r);
443:   if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
444:   pf->ops->destroy             = 0;
445:   pf->ops->view                = 0;
446:   pf->ops->apply               = 0;
447:   pf->ops->applyvec            = 0;

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

452:   PetscObjectChangeTypeName((PetscObject)pf,type);
453:   return(0);
454: }

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: PetscErrorCode  PFSetFromOptions(PF pf)
479: {
481:   char           type[256];
482:   PetscTruth     flg;


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

497:   return(0);
498: }

500: static PetscTruth PFPackageInitialized = PETSC_FALSE;
503: /*@C
504:   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
505:   called from PetscFinalize().

507:   Level: developer

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

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

528:   Input Parameter:
529: . path - The dynamic library path, or PETSC_NULL

531:   Level: developer

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

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