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: }