Date: 2013-07-02T14:40:50+00:00

Actual source code: pf.c
petsc-3.4.2 2013-07-02

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

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

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

     15:    Collective on PF

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

     25:    Level: beginner

     27: .keywords: PF, setting

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

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

     48:    Collective on PF

     50:    Input Parameter:
     51: .  pf - the function context

     53:    Level: beginner

     55: .keywords: PF, destroy

     57: .seealso: PFCreate(), PFSet(), PFSetType()
     58: @*/
     59: PetscErrorCode  PFDestroy(PF *pf)
     60: {
     62:   PetscBool      flg = PETSC_FALSE;

     65:   if (!*pf) return(0);
     67:   if (--((PetscObject)(*pf))->refct > 0) return(0);

     69:   PetscOptionsGetBool(((PetscObject)(*pf))->prefix,"-pf_view",&flg,NULL);
     70:   if (flg) {
     71:     PetscViewer viewer;
     72:     PetscViewerASCIIGetStdout(((PetscObject)(*pf))->comm,&viewer);
     73:     PFView((*pf),viewer);
     74:   }

     76:   /* if memory was published with AMS then destroy it */
     77:   PetscObjectAMSViewOff((PetscObject)*pf);

     79:   if ((*pf)->ops->destroy) { (*(*pf)->ops->destroy)((*pf)->data);}
     80:   PetscHeaderDestroy(pf);
     81:   return(0);
     82: }

     86: /*@C
     87:    PFCreate - Creates a mathematical function context.

     89:    Collective on MPI_Comm

     91:    Input Parameter:
     92: +  comm - MPI communicator
     93: .  dimin - dimension of the space you are mapping from
     94: -  dimout - dimension of the space you are mapping to

     96:    Output Parameter:
     97: .  pf - the function context

     99:    Level: developer

    101: .keywords: PF, create, context

    103: .seealso: PFSet(), PFApply(), PFDestroy(), PFApplyVec()
    104: @*/
    105: PetscErrorCode  PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
    106: {
    107:   PF             newpf;

    112:   *pf = NULL;
    113: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
    114:   PFInitializePackage();
    115: #endif

    117:   PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_CLASSID,"PF","Mathematical functions","Vec",comm,PFDestroy,PFView);
    118:   newpf->data          = 0;
    119:   newpf->ops->destroy  = 0;
    120:   newpf->ops->apply    = 0;
    121:   newpf->ops->applyvec = 0;
    122:   newpf->ops->view     = 0;
    123:   newpf->dimin         = dimin;
    124:   newpf->dimout        = dimout;

    126:   *pf                  = newpf;
    127:   return(0);

    129: }

    131: /* -------------------------------------------------------------------------------*/

    135: /*@
    136:    PFApplyVec - Applies the mathematical function to a vector

    138:    Collective on PF

    140:    Input Parameters:
    141: +  pf - the function context
    142: -  x - input vector (or NULL for the vector (0,1, .... N-1)

    144:    Output Parameter:
    145: .  y - output vector

    147:    Level: beginner

    149: .keywords: PF, apply

    151: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
    152: @*/
    153: PetscErrorCode  PFApplyVec(PF pf,Vec x,Vec y)
    154: {
    156:   PetscInt       i,rstart,rend,n,p;
    157:   PetscBool      nox = PETSC_FALSE;

    162:   if (x) {
    164:     if (x == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"x and y must be different vectors");
    165:   } else {
    166:     PetscScalar *xx;
    167:     PetscInt    lsize;

    169:     VecGetLocalSize(y,&lsize);
    170:     lsize = pf->dimin*lsize/pf->dimout;
    171:     VecCreateMPI(PetscObjectComm((PetscObject)y),lsize,PETSC_DETERMINE,&x);
    172:     nox   = PETSC_TRUE;
    173:     VecGetOwnershipRange(x,&rstart,&rend);
    174:     VecGetArray(x,&xx);
    175:     for (i=rstart; i<rend; i++) xx[i-rstart] = (PetscScalar)i;
    176:     VecRestoreArray(x,&xx);
    177:   }

    179:   VecGetLocalSize(x,&n);
    180:   VecGetLocalSize(y,&p);
    181:   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);
    182:   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);
    183:   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);

    185:   if (pf->ops->applyvec) {
    186:     (*pf->ops->applyvec)(pf->data,x,y);
    187:   } else {
    188:     PetscScalar *xx,*yy;

    190:     VecGetLocalSize(x,&n);
    191:     n    = n/pf->dimin;
    192:     VecGetArray(x,&xx);
    193:     VecGetArray(y,&yy);
    194:     if (!pf->ops->apply) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
    195:     (*pf->ops->apply)(pf->data,n,xx,yy);
    196:     VecRestoreArray(x,&xx);
    197:     VecRestoreArray(y,&yy);
    198:   }
    199:   if (nox) {
    200:     VecDestroy(&x);
    201:   }
    202:   return(0);
    203: }

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

    210:    Collective on PF

    212:    Input Parameters:
    213: +  pf - the function context
    214: .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
    215:        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
    216:        in the call to PFCreate()
    217: -  x - input array

    219:    Output Parameter:
    220: .  y - output array

    222:    Level: beginner

    224:    Notes:

    226: .keywords: PF, apply

    228: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
    229: @*/
    230: PetscErrorCode  PFApply(PF pf,PetscInt n,const PetscScalar *x,PetscScalar *y)
    231: {

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

    241:   (*pf->ops->apply)(pf->data,n,x,y);
    242:   return(0);
    243: }

    247: /*@
    248:    PFView - Prints information about a mathematical function

    250:    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF

    252:    Input Parameters:
    253: +  PF - the PF context
    254: -  viewer - optional visualization context

    256:    Note:
    257:    The available visualization contexts include
    258: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
    259: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
    260:          output where only the first processor opens
    261:          the file.  All other processors send their
    262:          data to the first processor to print.

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

    267:    Level: developer

    269: .keywords: PF, view

    271: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
    272: @*/
    273: PetscErrorCode  PFView(PF pf,PetscViewer viewer)
    274: {
    275:   PetscErrorCode    ierr;
    276:   PetscBool         iascii;
    277:   PetscViewerFormat format;

    281:   if (!viewer) {
    282:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf),&viewer);
    283:   }

    287:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    288:   if (iascii) {
    289:     PetscViewerGetFormat(viewer,&format);
    290:     PetscObjectPrintClassNamePrefixType((PetscObject)pf,viewer,"PF Object");
    291:     if (pf->ops->view) {
    292:       PetscViewerASCIIPushTab(viewer);
    293:       (*pf->ops->view)(pf->data,viewer);
    294:       PetscViewerASCIIPopTab(viewer);
    295:     }
    296:   }
    297:   return(0);
    298: }

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

    306:    Not collective

    308:    Input Parameters:
    309: +  name_solver - name of a new user-defined solver
    310: -  routine_create - routine to create method context

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

    315:    Sample usage:
    316: .vb
    317:    PFRegister("my_function",MyFunctionSetCreate);
    318: .ve

    320:    Then, your solver can be chosen with the procedural interface via
    321: $     PFSetType(pf,"my_function")
    322:    or at runtime via the option
    323: $     -pf_type my_function

    325:    Level: advanced

    327: .keywords: PF, register

    329: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
    330: @*/
    331: PetscErrorCode  PFRegister(const char sname[],PetscErrorCode (*function)(PF,void*))
    332: {

    336:   PetscFunctionListAdd(&PFList,sname,function);
    337:   return(0);
    338: }

    342: /*@C
    343:    PFGetType - Gets the PF method type and name (as a string) from the PF
    344:    context.

    346:    Not Collective

    348:    Input Parameter:
    349: .  pf - the function context

    351:    Output Parameter:
    352: .  type - name of function

    354:    Level: intermediate

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

    358: .seealso: PFSetType()

    360: @*/
    361: PetscErrorCode  PFGetType(PF pf,PFType *type)
    362: {
    366:   *type = ((PetscObject)pf)->type_name;
    367:   return(0);
    368: }

    373: /*@C
    374:    PFSetType - Builds PF for a particular function

    376:    Collective on PF

    378:    Input Parameter:
    379: +  pf - the function context.
    380: .  type - a known method
    381: -  ctx - optional type dependent context

    383:    Options Database Key:
    384: .  -pf_type <type> - Sets PF type

    387:   Notes:
    388:   See "petsc/include/petscpf.h" for available methods (for instance,
    389:   PFCONSTANT)

    391:   Level: intermediate

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

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

    397: @*/
    398: PetscErrorCode  PFSetType(PF pf,PFType type,void *ctx)
    399: {
    400:   PetscErrorCode ierr,(*r)(PF,void*);
    401:   PetscBool      match;

    407:   PetscObjectTypeCompare((PetscObject)pf,type,&match);
    408:   if (match) return(0);

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

    413:   /* Determine the PFCreateXXX routine for a particular function */
    414:   PetscFunctionListFind(PFList,type,&r);
    415:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
    416:   pf->ops->destroy  = 0;
    417:   pf->ops->view     = 0;
    418:   pf->ops->apply    = 0;
    419:   pf->ops->applyvec = 0;

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

    424:   PetscObjectChangeTypeName((PetscObject)pf,type);
    425:   return(0);
    426: }

    430: /*@
    431:    PFSetFromOptions - Sets PF options from the options database.

    433:    Collective on PF

    435:    Input Parameters:
    436: .  pf - the mathematical function context

    438:    Options Database Keys:

    440:    Notes:
    441:    To see all options, run your program with the -help option
    442:    or consult the users manual.

    444:    Level: intermediate

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

    448: .seealso:
    449: @*/
    450: PetscErrorCode  PFSetFromOptions(PF pf)
    451: {
    453:   char           type[256];
    454:   PetscBool      flg;

    459:   PetscObjectOptionsBegin((PetscObject)pf);
    460:   PetscOptionsList("-pf_type","Type of function","PFSetType",PFList,0,type,256,&flg);
    461:   if (flg) {
    462:     PFSetType(pf,type,NULL);
    463:   }
    464:   if (pf->ops->setfromoptions) {
    465:     (*pf->ops->setfromoptions)(pf);
    466:   }

    468:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
    469:   PetscObjectProcessOptionsHandlers((PetscObject)pf);
    470:   PetscOptionsEnd();
    471:   return(0);
    472: }

    474: static PetscBool PFPackageInitialized = PETSC_FALSE;
    477: /*@C
    478:   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
    479:   called from PetscFinalize().

    481:   Level: developer

    483: .keywords: Petsc, destroy, package, mathematica
    484: .seealso: PetscFinalize()
    485: @*/
    486: PetscErrorCode  PFFinalizePackage(void)
    487: {

    491:   PetscFunctionListDestroy(&PFList);
    492:   PFPackageInitialized = PETSC_FALSE;
    493:   PFRegisterAllCalled  = PETSC_FALSE;
    494:   return(0);
    495: }

    499: /*@C
    500:   PFInitializePackage - This function initializes everything in the PF package. It is called
    501:   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PFCreate()
    502:   when using static libraries.

    504:   Level: developer

    506: .keywords: Vec, initialize, package
    507: .seealso: PetscInitialize()
    508: @*/
    509: PetscErrorCode  PFInitializePackage(void)
    510: {
    511:   char           logList[256];
    512:   char           *className;
    513:   PetscBool      opt;

    517:   if (PFPackageInitialized) return(0);
    518:   PFPackageInitialized = PETSC_TRUE;
    519:   /* Register Classes */
    520:   PetscClassIdRegister("PointFunction",&PF_CLASSID);
    521:   /* Register Constructors */
    522:   PFRegisterAll();
    523:   /* Process info exclusions */
    524:   PetscOptionsGetString(NULL, "-info_exclude", logList, 256, &opt);
    525:   if (opt) {
    526:     PetscStrstr(logList, "pf", &className);
    527:     if (className) {
    528:       PetscInfoDeactivateClass(PF_CLASSID);
    529:     }
    530:   }
    531:   /* Process summary exclusions */
    532:   PetscOptionsGetString(NULL, "-log_summary_exclude", logList, 256, &opt);
    533:   if (opt) {
    534:     PetscStrstr(logList, "pf", &className);
    535:     if (className) {
    536:       PetscLogEventDeactivateClass(PF_CLASSID);
    537:     }
    538:   }
    539:   PetscRegisterFinalize(PFFinalizePackage);
    540:   return(0);
    541: }