Actual source code: pf.c
petsc-3.10.5 2019-03-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() when using dynamic libraries, and on the first call to PFCreate()
    470:   when using 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: }