Actual source code: pf.c

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

  6: PetscClassId      PF_CLASSID          = 0;
  7: PetscFunctionList PFList              = NULL;   /* list of all registered PD functions */
  8: PetscBool         PFRegisterAllCalled = PETSC_FALSE;

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

 13:    Collective on PF

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

 23:    Level: beginner

 25: .seealso: PFCreate(), PFDestroy(), PFSetType(), PFApply(), PFApplyVec()
 26: @*/
 27: 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)
 28: {
 31:   pf->data          = ctx;
 32:   pf->ops->destroy  = destroy;
 33:   pf->ops->apply    = apply;
 34:   pf->ops->applyvec = applyvec;
 35:   pf->ops->view     = view;
 36:   return(0);
 37: }

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

 42:    Collective on PF

 44:    Input Parameter:
 45: .  pf - the function context

 47:    Level: beginner

 49: .seealso: PFCreate(), PFSet(), PFSetType()
 50: @*/
 51: PetscErrorCode  PFDestroy(PF *pf)
 52: {

 56:   if (!*pf) return(0);
 58:   if (--((PetscObject)(*pf))->refct > 0) return(0);

 60:   PFViewFromOptions(*pf,NULL,"-pf_view");
 61:   /* if memory was published with SAWs then destroy it */
 62:   PetscObjectSAWsViewOff((PetscObject)*pf);

 64:   if ((*pf)->ops->destroy) { (*(*pf)->ops->destroy)((*pf)->data);}
 65:   PetscHeaderDestroy(pf);
 66:   return(0);
 67: }

 69: /*@C
 70:    PFCreate - Creates a mathematical function context.

 72:    Collective

 74:    Input Parameter:
 75: +  comm - MPI communicator
 76: .  dimin - dimension of the space you are mapping from
 77: -  dimout - dimension of the space you are mapping to

 79:    Output Parameter:
 80: .  pf - the function context

 82:    Level: developer

 84: .seealso: PFSet(), PFApply(), PFDestroy(), PFApplyVec()
 85: @*/
 86: PetscErrorCode  PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
 87: {
 88:   PF             newpf;

 93:   *pf = NULL;
 94:   PFInitializePackage();

 96:   PetscHeaderCreate(newpf,PF_CLASSID,"PF","Mathematical functions","Vec",comm,PFDestroy,PFView);
 97:   newpf->data          = NULL;
 98:   newpf->ops->destroy  = NULL;
 99:   newpf->ops->apply    = NULL;
100:   newpf->ops->applyvec = NULL;
101:   newpf->ops->view     = NULL;
102:   newpf->dimin         = dimin;
103:   newpf->dimout        = dimout;

105:   *pf                  = newpf;
106:   return(0);

108: }

110: /* -------------------------------------------------------------------------------*/

112: /*@
113:    PFApplyVec - Applies the mathematical function to a vector

115:    Collective on PF

117:    Input Parameters:
118: +  pf - the function context
119: -  x - input vector (or NULL for the vector (0,1, .... N-1)

121:    Output Parameter:
122: .  y - output vector

124:    Level: beginner

126: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
127: @*/
128: PetscErrorCode  PFApplyVec(PF pf,Vec x,Vec y)
129: {
131:   PetscInt       i,rstart,rend,n,p;
132:   PetscBool      nox = PETSC_FALSE;

137:   if (x) {
139:     if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different vectors");
140:   } else {
141:     PetscScalar *xx;
142:     PetscInt    lsize;

144:     VecGetLocalSize(y,&lsize);
145:     lsize = pf->dimin*lsize/pf->dimout;
146:     VecCreateMPI(PetscObjectComm((PetscObject)y),lsize,PETSC_DETERMINE,&x);
147:     nox   = PETSC_TRUE;
148:     VecGetOwnershipRange(x,&rstart,&rend);
149:     VecGetArray(x,&xx);
150:     for (i=rstart; i<rend; i++) xx[i-rstart] = (PetscScalar)i;
151:     VecRestoreArray(x,&xx);
152:   }

154:   VecGetLocalSize(x,&n);
155:   VecGetLocalSize(y,&p);
156:   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);
157:   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);
158:   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);

160:   if (pf->ops->applyvec) {
161:     (*pf->ops->applyvec)(pf->data,x,y);
162:   } else {
163:     PetscScalar *xx,*yy;

165:     VecGetLocalSize(x,&n);
166:     n    = n/pf->dimin;
167:     VecGetArray(x,&xx);
168:     VecGetArray(y,&yy);
169:     if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
170:     (*pf->ops->apply)(pf->data,n,xx,yy);
171:     VecRestoreArray(x,&xx);
172:     VecRestoreArray(y,&yy);
173:   }
174:   if (nox) {
175:     VecDestroy(&x);
176:   }
177:   return(0);
178: }

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

183:    Collective on PF

185:    Input Parameters:
186: +  pf - the function context
187: .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
188:        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
189:        in the call to PFCreate()
190: -  x - input array

192:    Output Parameter:
193: .  y - output array

195:    Level: beginner

197:    Notes:

199: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
200: @*/
201: PetscErrorCode  PFApply(PF pf,PetscInt n,const PetscScalar *x,PetscScalar *y)
202: {

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

212:   (*pf->ops->apply)(pf->data,n,x,y);
213:   return(0);
214: }

216: /*@C
217:    PFViewFromOptions - View from Options

219:    Collective on PF

221:    Input Parameters:
222: +  A - the PF context
223: .  obj - Optional object
224: -  name - command line option

226:    Level: intermediate
227: .seealso:  PF, PFView, PetscObjectViewFromOptions(), PFCreate()
228: @*/
229: PetscErrorCode  PFViewFromOptions(PF A,PetscObject obj,const char name[])
230: {

235:   PetscObjectViewFromOptions((PetscObject)A,obj,name);
236:   return(0);
237: }

239: /*@
240:    PFView - Prints information about a mathematical function

242:    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF

244:    Input Parameters:
245: +  PF - the PF context
246: -  viewer - optional visualization context

248:    Note:
249:    The available visualization contexts include
250: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
251: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
252:          output where only the first processor opens
253:          the file.  All other processors send their
254:          data to the first processor to print.

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

259:    Level: developer

261: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
262: @*/
263: PetscErrorCode  PFView(PF pf,PetscViewer viewer)
264: {
265:   PetscErrorCode    ierr;
266:   PetscBool         iascii;
267:   PetscViewerFormat format;

271:   if (!viewer) {
272:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf),&viewer);
273:   }

277:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
278:   if (iascii) {
279:     PetscViewerGetFormat(viewer,&format);
280:     PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer);
281:     if (pf->ops->view) {
282:       PetscViewerASCIIPushTab(viewer);
283:       (*pf->ops->view)(pf->data,viewer);
284:       PetscViewerASCIIPopTab(viewer);
285:     }
286:   }
287:   return(0);
288: }


291: /*@C
292:    PFRegister - Adds a method to the mathematical function package.

294:    Not collective

296:    Input Parameters:
297: +  name_solver - name of a new user-defined solver
298: -  routine_create - routine to create method context

300:    Notes:
301:    PFRegister() may be called multiple times to add several user-defined functions

303:    Sample usage:
304: .vb
305:    PFRegister("my_function",MyFunctionSetCreate);
306: .ve

308:    Then, your solver can be chosen with the procedural interface via
309: $     PFSetType(pf,"my_function")
310:    or at runtime via the option
311: $     -pf_type my_function

313:    Level: advanced

315: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
316: @*/
317: PetscErrorCode  PFRegister(const char sname[],PetscErrorCode (*function)(PF,void*))
318: {

322:   PFInitializePackage();
323:   PetscFunctionListAdd(&PFList,sname,function);
324:   return(0);
325: }

327: /*@C
328:    PFGetType - Gets the PF method type and name (as a string) from the PF
329:    context.

331:    Not Collective

333:    Input Parameter:
334: .  pf - the function context

336:    Output Parameter:
337: .  type - name of function

339:    Level: intermediate

341: .seealso: PFSetType()

343: @*/
344: PetscErrorCode  PFGetType(PF pf,PFType *type)
345: {
349:   *type = ((PetscObject)pf)->type_name;
350:   return(0);
351: }


354: /*@C
355:    PFSetType - Builds PF for a particular function

357:    Collective on PF

359:    Input Parameter:
360: +  pf - the function context.
361: .  type - a known method
362: -  ctx - optional type dependent context

364:    Options Database Key:
365: .  -pf_type <type> - Sets PF type


368:   Notes:
369:   See "petsc/include/petscpf.h" for available methods (for instance,
370:   PFCONSTANT)

372:   Level: intermediate

374: .seealso: PFSet(), PFRegister(), PFCreate(), DMDACreatePF()

376: @*/
377: PetscErrorCode  PFSetType(PF pf,PFType type,void *ctx)
378: {
379:   PetscErrorCode ierr,(*r)(PF,void*);
380:   PetscBool      match;


386:   PetscObjectTypeCompare((PetscObject)pf,type,&match);
387:   if (match) return(0);

389:   if (pf->ops->destroy) { (*pf->ops->destroy)(pf);}
390:   pf->data = NULL;

392:   /* Determine the PFCreateXXX routine for a particular function */
393:   PetscFunctionListFind(PFList,type,&r);
394:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
395:   pf->ops->destroy  = NULL;
396:   pf->ops->view     = NULL;
397:   pf->ops->apply    = NULL;
398:   pf->ops->applyvec = NULL;

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

403:   PetscObjectChangeTypeName((PetscObject)pf,type);
404:   return(0);
405: }

407: /*@
408:    PFSetFromOptions - Sets PF options from the options database.

410:    Collective on PF

412:    Input Parameters:
413: .  pf - the mathematical function context

415:    Options Database Keys:

417:    Notes:
418:    To see all options, run your program with the -help option
419:    or consult the users manual.

421:    Level: intermediate

423: .seealso:
424: @*/
425: PetscErrorCode  PFSetFromOptions(PF pf)
426: {
428:   char           type[256];
429:   PetscBool      flg;


434:   PetscObjectOptionsBegin((PetscObject)pf);
435:   PetscOptionsFList("-pf_type","Type of function","PFSetType",PFList,NULL,type,256,&flg);
436:   if (flg) {
437:     PFSetType(pf,type,NULL);
438:   }
439:   if (pf->ops->setfromoptions) {
440:     (*pf->ops->setfromoptions)(PetscOptionsObject,pf);
441:   }

443:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
444:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)pf);
445:   PetscOptionsEnd();
446:   return(0);
447: }

449: static PetscBool PFPackageInitialized = PETSC_FALSE;
450: /*@C
451:   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
452:   called from PetscFinalize().

454:   Level: developer

456: .seealso: PetscFinalize()
457: @*/
458: PetscErrorCode  PFFinalizePackage(void)
459: {

463:   PetscFunctionListDestroy(&PFList);
464:   PFPackageInitialized = PETSC_FALSE;
465:   PFRegisterAllCalled  = PETSC_FALSE;
466:   return(0);
467: }

469: /*@C
470:   PFInitializePackage - This function initializes everything in the PF package. It is called
471:   from PetscDLLibraryRegister_petscvec() when using dynamic libraries, and on the first call to PFCreate()
472:   when using shared or static libraries.

474:   Level: developer

476: .seealso: PetscInitialize()
477: @*/
478: PetscErrorCode  PFInitializePackage(void)
479: {
480:   char           logList[256];
481:   PetscBool      opt,pkg;

485:   if (PFPackageInitialized) return(0);
486:   PFPackageInitialized = PETSC_TRUE;
487:   /* Register Classes */
488:   PetscClassIdRegister("PointFunction",&PF_CLASSID);
489:   /* Register Constructors */
490:   PFRegisterAll();
491:   /* Process Info */
492:   {
493:     PetscClassId  classids[1];

495:     classids[0] = PF_CLASSID;
496:     PetscInfoProcessClass("pf", 1, classids);
497:   }
498:   /* Process summary exclusions */
499:   PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt);
500:   if (opt) {
501:     PetscStrInList("pf",logList,',',&pkg);
502:     if (pkg) {PetscLogEventExcludeClass(PF_CLASSID);}
503:   }
504:   /* Register package finalizer */
505:   PetscRegisterFinalize(PFFinalizePackage);
506:   return(0);
507: }