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 PPetscFList         = 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;

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

 73:   PetscOptionsHasName(pf->prefix,"-pf_view",&flg);
 74:   if (flg) {
 75:     PetscViewer viewer;
 76:     PetscViewerASCIIGetStdout(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: static PetscErrorCode PFPublish_Petsc(PetscObject obj)
 91: {
 92: #if defined(PETSC_HAVE_AMS)
 93:   PF          v = (PF) obj;
 95: #endif


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

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

107:   return(0);
108: }

112: /*@C
113:    PFCreate - Creates a mathematical function context.

115:    Collective on MPI_Comm

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

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

125:    Level: developer

127: .keywords: PF, create, context

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

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

143:   PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_COOKIE,-1,"PF",comm,PFDestroy,PFView);
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: /* -------------------------------------------------------------------------------*/

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: PetscErrorCode  PFApplyVec(PF pf,Vec x,Vec y)
183: {
185:   PetscInt       i,rstart,rend,n,p;
186:   PetscTruth     nox = PETSC_FALSE;

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

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

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

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

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

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

238:    Collective on PF

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

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

250:    Level: beginner

252:    Notes: 

254: .keywords: PF, apply

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

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

269:   (*pf->ops->apply)(pf->data,n,x,y);
270:   return(0);
271: }

275: /*@ 
276:    PFView - Prints information about a mathematical function

278:    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF  

280:    Input Parameters:
281: +  PF - the PF context
282: -  viewer - optional visualization context

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

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

295:    Level: developer

297: .keywords: PF, view

299: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
300: @*/
301: PetscErrorCode  PFView(PF pf,PetscViewer viewer)
302: {
303:   PFType            cstr;
304:   PetscErrorCode    ierr;
305:   PetscTruth        iascii;
306:   PetscViewerFormat format;

310:   if (!viewer) {
311:     PetscViewerASCIIGetStdout(pf->comm,&viewer);
312:   }

316:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
317:   if (iascii) {
318:     PetscViewerGetFormat(viewer,&format);
319:     PetscViewerASCIIPrintf(viewer,"PF Object:\n");
320:     PFGetType(pf,&cstr);
321:     if (cstr) {
322:       PetscViewerASCIIPrintf(viewer,"  type: %s\n",cstr);
323:     } else {
324:       PetscViewerASCIIPrintf(viewer,"  type: not yet set\n");
325:     }
326:     if (pf->ops->view) {
327:       PetscViewerASCIIPushTab(viewer);
328:       (*pf->ops->view)(pf->data,viewer);
329:       PetscViewerASCIIPopTab(viewer);
330:     }
331:   } else {
332:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
333:   }
334:   return(0);
335: }

337: /*MC
338:    PFRegisterDynamic - Adds a method to the mathematical function package.

340:    Synopsis:
341:    PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))

343:    Not collective

345:    Input Parameters:
346: +  name_solver - name of a new user-defined solver
347: .  path - path (either absolute or relative) the library containing this solver
348: .  name_create - name of routine to create method context
349: -  routine_create - routine to create method context

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

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

357:    Sample usage:
358: .vb
359:    PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
360:               "MyFunctionCreate",MyFunctionSetCreate);
361: .ve

363:    Then, your solver can be chosen with the procedural interface via
364: $     PFSetType(pf,"my_function")
365:    or at runtime via the option
366: $     -pf_type my_function

368:    Level: advanced

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

373: .keywords: PF, register

375: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
376: M*/

380: PetscErrorCode  PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
381: {
383:   char fullname[PETSC_MAX_PATH_LEN];

386:   PetscFListConcat(path,name,fullname);
387:   PetscFListAdd(&PPetscFList,sname,fullname,(void (*)(void))function);
388:   return(0);
389: }



395: /*@C
396:    PFGetType - Gets the PF method type and name (as a string) from the PF
397:    context.

399:    Not Collective

401:    Input Parameter:
402: .  pf - the function context

404:    Output Parameter:
405: .  name - name of function 

407:    Level: intermediate

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

411: .seealso: PFSetType()

413: @*/
414: PetscErrorCode  PFGetType(PF pf,PFType *meth)
415: {
417:   *meth = (PFType) pf->type_name;
418:   return(0);
419: }


424: /*@C
425:    PFSetType - Builds PF for a particular function

427:    Collective on PF

429:    Input Parameter:
430: +  pf - the function context.
431: .  type - a known method
432: -  ctx - optional type dependent context

434:    Options Database Key:
435: .  -pf_type <type> - Sets PF type


438:   Notes:
439:   See "petsc/include/petscpf.h" for available methods (for instance,
440:   PFCONSTANT)

442:   Level: intermediate

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

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

448: @*/
449: PetscErrorCode  PFSetType(PF pf,const PFType type,void *ctx)
450: {
451:   PetscErrorCode ierr,(*r)(PF,void*);
452:   PetscTruth match;


458:   PetscTypeCompare((PetscObject)pf,type,&match);
459:   if (match) return(0);

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

464:   /* Get the function pointers for the method requested */
465:   if (!PFRegisterAllCalled) {PFRegisterAll(0);}
466:   /* Determine the PFCreateXXX routine for a particular function */
467:    PetscFListFind(pf->comm,PPetscFList,type,(void (**)(void)) &r);
468:   if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
469:   pf->ops->destroy             = 0;
470:   pf->ops->view                = 0;
471:   pf->ops->apply               = 0;
472:   pf->ops->applyvec            = 0;

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

477:   PetscObjectChangeTypeName((PetscObject)pf,type);
478:   return(0);
479: }

483: /*@
484:    PFSetFromOptions - Sets PF options from the options database.

486:    Collective on PF

488:    Input Parameters:
489: .  pf - the mathematical function context

491:    Options Database Keys:

493:    Notes:  
494:    To see all options, run your program with the -help option
495:    or consult the users manual.

497:    Level: intermediate

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

501: .seealso:
502: @*/
503: PetscErrorCode  PFSetFromOptions(PF pf)
504: {
506:   char       type[256];
507:   PetscTruth flg;


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

523:   return(0);
524: }