Actual source code: pf.c

petsc-3.11.4 2019-09-28
Report Typos and Errors
  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: .keywords: PF, setting

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

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

 44:    Collective on PF

 46:    Input Parameter:
 47: .  pf - the function context

 49:    Level: beginner

 51: .keywords: PF, destroy

 53: .seealso: PFCreate(), PFSet(), PFSetType()
 54: @*/
 55: PetscErrorCode  PFDestroy(PF *pf)
 56: {

 60:   if (!*pf) return(0);
 62:   if (--((PetscObject)(*pf))->refct > 0) return(0);

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

 68:   if ((*pf)->ops->destroy) { (*(*pf)->ops->destroy)((*pf)->data);}
 69:   PetscHeaderDestroy(pf);
 70:   return(0);
 71: }

 73: /*@C
 74:    PFCreate - Creates a mathematical function context.

 76:    Collective on MPI_Comm

 78:    Input Parameter:
 79: +  comm - MPI communicator
 80: .  dimin - dimension of the space you are mapping from
 81: -  dimout - dimension of the space you are mapping to

 83:    Output Parameter:
 84: .  pf - the function context

 86:    Level: developer

 88: .keywords: PF, create, context

 90: .seealso: PFSet(), PFApply(), PFDestroy(), PFApplyVec()
 91: @*/
 92: PetscErrorCode  PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
 93: {
 94:   PF             newpf;

 99:   *pf = NULL;
100:   PFInitializePackage();

102:   PetscHeaderCreate(newpf,PF_CLASSID,"PF","Mathematical functions","Vec",comm,PFDestroy,PFView);
103:   newpf->data          = 0;
104:   newpf->ops->destroy  = 0;
105:   newpf->ops->apply    = 0;
106:   newpf->ops->applyvec = 0;
107:   newpf->ops->view     = 0;
108:   newpf->dimin         = dimin;
109:   newpf->dimout        = dimout;

111:   *pf                  = newpf;
112:   return(0);

114: }

116: /* -------------------------------------------------------------------------------*/

118: /*@
119:    PFApplyVec - Applies the mathematical function to a vector

121:    Collective on PF

123:    Input Parameters:
124: +  pf - the function context
125: -  x - input vector (or NULL for the vector (0,1, .... N-1)

127:    Output Parameter:
128: .  y - output vector

130:    Level: beginner

132: .keywords: PF, apply

134: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
135: @*/
136: PetscErrorCode  PFApplyVec(PF pf,Vec x,Vec y)
137: {
139:   PetscInt       i,rstart,rend,n,p;
140:   PetscBool      nox = PETSC_FALSE;

145:   if (x) {
147:     if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different vectors");
148:   } else {
149:     PetscScalar *xx;
150:     PetscInt    lsize;

152:     VecGetLocalSize(y,&lsize);
153:     lsize = pf->dimin*lsize/pf->dimout;
154:     VecCreateMPI(PetscObjectComm((PetscObject)y),lsize,PETSC_DETERMINE,&x);
155:     nox   = PETSC_TRUE;
156:     VecGetOwnershipRange(x,&rstart,&rend);
157:     VecGetArray(x,&xx);
158:     for (i=rstart; i<rend; i++) xx[i-rstart] = (PetscScalar)i;
159:     VecRestoreArray(x,&xx);
160:   }

162:   VecGetLocalSize(x,&n);
163:   VecGetLocalSize(y,&p);
164:   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);
165:   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);
166:   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);

168:   if (pf->ops->applyvec) {
169:     (*pf->ops->applyvec)(pf->data,x,y);
170:   } else {
171:     PetscScalar *xx,*yy;

173:     VecGetLocalSize(x,&n);
174:     n    = n/pf->dimin;
175:     VecGetArray(x,&xx);
176:     VecGetArray(y,&yy);
177:     if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
178:     (*pf->ops->apply)(pf->data,n,xx,yy);
179:     VecRestoreArray(x,&xx);
180:     VecRestoreArray(y,&yy);
181:   }
182:   if (nox) {
183:     VecDestroy(&x);
184:   }
185:   return(0);
186: }

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

191:    Collective on PF

193:    Input Parameters:
194: +  pf - the function context
195: .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
196:        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
197:        in the call to PFCreate()
198: -  x - input array

200:    Output Parameter:
201: .  y - output array

203:    Level: beginner

205:    Notes:

207: .keywords: PF, apply

209: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
210: @*/
211: PetscErrorCode  PFApply(PF pf,PetscInt n,const PetscScalar *x,PetscScalar *y)
212: {

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

222:   (*pf->ops->apply)(pf->data,n,x,y);
223:   return(0);
224: }

226: /*@
227:    PFView - Prints information about a mathematical function

229:    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF

231:    Input Parameters:
232: +  PF - the PF context
233: -  viewer - optional visualization context

235:    Note:
236:    The available visualization contexts include
237: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
238: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
239:          output where only the first processor opens
240:          the file.  All other processors send their
241:          data to the first processor to print.

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

246:    Level: developer

248: .keywords: PF, view

250: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
251: @*/
252: PetscErrorCode  PFView(PF pf,PetscViewer viewer)
253: {
254:   PetscErrorCode    ierr;
255:   PetscBool         iascii;
256:   PetscViewerFormat format;

260:   if (!viewer) {
261:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf),&viewer);
262:   }

266:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
267:   if (iascii) {
268:     PetscViewerGetFormat(viewer,&format);
269:     PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer);
270:     if (pf->ops->view) {
271:       PetscViewerASCIIPushTab(viewer);
272:       (*pf->ops->view)(pf->data,viewer);
273:       PetscViewerASCIIPopTab(viewer);
274:     }
275:   }
276:   return(0);
277: }


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

283:    Not collective

285:    Input Parameters:
286: +  name_solver - name of a new user-defined solver
287: -  routine_create - routine to create method context

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

292:    Sample usage:
293: .vb
294:    PFRegister("my_function",MyFunctionSetCreate);
295: .ve

297:    Then, your solver can be chosen with the procedural interface via
298: $     PFSetType(pf,"my_function")
299:    or at runtime via the option
300: $     -pf_type my_function

302:    Level: advanced

304: .keywords: PF, register

306: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
307: @*/
308: PetscErrorCode  PFRegister(const char sname[],PetscErrorCode (*function)(PF,void*))
309: {

313:   PFInitializePackage();
314:   PetscFunctionListAdd(&PFList,sname,function);
315:   return(0);
316: }

318: /*@C
319:    PFGetType - Gets the PF method type and name (as a string) from the PF
320:    context.

322:    Not Collective

324:    Input Parameter:
325: .  pf - the function context

327:    Output Parameter:
328: .  type - name of function

330:    Level: intermediate

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

334: .seealso: PFSetType()

336: @*/
337: PetscErrorCode  PFGetType(PF pf,PFType *type)
338: {
342:   *type = ((PetscObject)pf)->type_name;
343:   return(0);
344: }


347: /*@C
348:    PFSetType - Builds PF for a particular function

350:    Collective on PF

352:    Input Parameter:
353: +  pf - the function context.
354: .  type - a known method
355: -  ctx - optional type dependent context

357:    Options Database Key:
358: .  -pf_type <type> - Sets PF type


361:   Notes:
362:   See "petsc/include/petscpf.h" for available methods (for instance,
363:   PFCONSTANT)

365:   Level: intermediate

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

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

371: @*/
372: PetscErrorCode  PFSetType(PF pf,PFType type,void *ctx)
373: {
374:   PetscErrorCode ierr,(*r)(PF,void*);
375:   PetscBool      match;


381:   PetscObjectTypeCompare((PetscObject)pf,type,&match);
382:   if (match) return(0);

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

387:   /* Determine the PFCreateXXX routine for a particular function */
388:   PetscFunctionListFind(PFList,type,&r);
389:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
390:   pf->ops->destroy  = 0;
391:   pf->ops->view     = 0;
392:   pf->ops->apply    = 0;
393:   pf->ops->applyvec = 0;

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

398:   PetscObjectChangeTypeName((PetscObject)pf,type);
399:   return(0);
400: }

402: /*@
403:    PFSetFromOptions - Sets PF options from the options database.

405:    Collective on PF

407:    Input Parameters:
408: .  pf - the mathematical function context

410:    Options Database Keys:

412:    Notes:
413:    To see all options, run your program with the -help option
414:    or consult the users manual.

416:    Level: intermediate

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

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


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

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

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

451:   Level: developer

453: .keywords: Petsc, destroy, package, mathematica
454: .seealso: PetscFinalize()
455: @*/
456: PetscErrorCode  PFFinalizePackage(void)
457: {

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

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

472:   Level: developer

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

484:   if (PFPackageInitialized) return(0);
485:   PFPackageInitialized = PETSC_TRUE;
486:   /* Register Classes */
487:   PetscClassIdRegister("PointFunction",&PF_CLASSID);
488:   /* Register Constructors */
489:   PFRegisterAll();
490:   /* Process info exclusions */
491:   PetscOptionsGetString(NULL,NULL,"-info_exclude",logList,sizeof(logList),&opt);
492:   if (opt) {
493:     PetscStrInList("pf",logList,',',&pkg);
494:     if (pkg) {PetscInfoDeactivateClass(PF_CLASSID);}
495:   }
496:   /* Process summary exclusions */
497:   PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt);
498:   if (opt) {
499:     PetscStrInList("pf",logList,',',&pkg);
500:     if (pkg) {PetscLogEventExcludeClass(PF_CLASSID);}
501:   }
502:   /* Register package finalizer */
503:   PetscRegisterFinalize(PFFinalizePackage);
504:   return(0);
505: }