Actual source code: pf.c

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

      7: /* Logging support */
      8: PetscCookie PF_COOKIE = 0;

     10: PetscFList PPetscFList         = PETSC_NULL; /* list of all registered PD functions */
     11: PetscTruth PFRegisterAllCalled = PETSC_FALSE;

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

     18:    Collective on PF

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

     28:    Level: beginner

     30: .keywords: PF, setting

     32: .seealso: PFCreate(), PFDestroy(), PFSetType(), PFApply(), PFApplyVec()
     33: @*/
     34: PetscErrorCode PETSCVEC_DLLEXPORT PFSet(PF pf,PetscErrorCode (*apply)(void*,PetscInt,PetscScalar*,PetscScalar*),PetscErrorCode (*applyvec)(void*,Vec,Vec),PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*destroy)(void*),void*ctx)
     35: {
     38:   pf->data             = ctx;

     40:   pf->ops->destroy     = destroy;
     41:   pf->ops->apply       = apply;
     42:   pf->ops->applyvec    = applyvec;
     43:   pf->ops->view        = view;

     45:   return(0);
     46: }

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

     53:    Collective on PF

     55:    Input Parameter:
     56: .  pf - the function context

     58:    Level: beginner

     60: .keywords: PF, destroy

     62: .seealso: PFCreate(), PFSet(), PFSetType()
     63: @*/
     64: PetscErrorCode PETSCVEC_DLLEXPORT PFDestroy(PF pf)
     65: {
     67:   PetscTruth flg;

     71:   if (--pf->refct > 0) return(0);

     73:   PetscOptionsHasName(pf->prefix,"-pf_view",&flg);
     74:   if (flg) {
     75:     PFView(pf,PETSC_VIEWER_STDOUT_(pf->comm));
     76:   }

     78:   /* if memory was published with AMS then destroy it */
     79:   PetscObjectDepublish(pf);

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

     88: static PetscErrorCode PFPublish_Petsc(PetscObject obj)
     89: {
     90: #if defined(PETSC_HAVE_AMS)
     91:   PF          v = (PF) obj;
     93: #endif

     97: #if defined(PETSC_HAVE_AMS)
     98:   /* if it is already published then return */
     99:   if (v->amem >=0) return(0);

    101:   PetscObjectPublishBaseBegin(obj);
    102:   PetscObjectPublishBaseEnd(obj);
    103: #endif

    105:   return(0);
    106: }

    110: /*@C
    111:    PFCreate - Creates a mathematical function context.

    113:    Collective on MPI_Comm

    115:    Input Parameter:
    116: +  comm - MPI communicator
    117: .  dimin - dimension of the space you are mapping from
    118: -  dimout - dimension of the space you are mapping to

    120:    Output Parameter:
    121: .  pf - the function context

    123:    Level: developer

    125: .keywords: PF, create, context

    127: .seealso: PFSetUp(), PFApply(), PFDestroy(), PFApplyVec()
    128: @*/
    129: PetscErrorCode PETSCVEC_DLLEXPORT PFCreate(MPI_Comm comm,PetscInt dimin,PetscInt dimout,PF *pf)
    130: {
    131:   PF  newpf;

    136:   *pf = PETSC_NULL;
    137: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
    138:   VecInitializePackage(PETSC_NULL);
    139: #endif

    141:   PetscHeaderCreate(newpf,_p_PF,struct _PFOps,PF_COOKIE,-1,"PF",comm,PFDestroy,PFView);
    142:   newpf->bops->publish    = PFPublish_Petsc;
    143:   newpf->data             = 0;

    145:   newpf->ops->destroy     = 0;
    146:   newpf->ops->apply       = 0;
    147:   newpf->ops->applyvec    = 0;
    148:   newpf->ops->view        = 0;
    149:   newpf->dimin            = dimin;
    150:   newpf->dimout           = dimout;

    152:   *pf                     = newpf;
    153:   PetscPublishAll(pf);
    154:   return(0);

    156: }

    158: /* -------------------------------------------------------------------------------*/

    162: /*@
    163:    PFApplyVec - Applies the mathematical function to a vector

    165:    Collective on PF

    167:    Input Parameters:
    168: +  pf - the function context
    169: -  x - input vector (or PETSC_NULL for the vector (0,1, .... N-1)

    171:    Output Parameter:
    172: .  y - output vector

    174:    Level: beginner

    176: .keywords: PF, apply

    178: .seealso: PFApply(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
    179: @*/
    180: PetscErrorCode PETSCVEC_DLLEXPORT PFApplyVec(PF pf,Vec x,Vec y)
    181: {
    183:   PetscInt       i,rstart,rend,n,p;
    184:   PetscTruth     nox = PETSC_FALSE;

    189:   if (x) {
    191:     if (x == y) SETERRQ(PETSC_ERR_ARG_IDN,"x and y must be different vectors");
    192:   } else {
    193:     PetscScalar *xx;

    195:     VecDuplicate(y,&x);
    196:     nox  = PETSC_TRUE;
    197:     VecGetOwnershipRange(x,&rstart,&rend);
    198:     VecGetArray(x,&xx);
    199:     for (i=rstart; i<rend; i++) {
    200:       xx[i-rstart] = (PetscScalar)i;
    201:     }
    202:     VecRestoreArray(x,&xx);
    203:   }

    205:   VecGetLocalSize(x,&n);
    206:   VecGetLocalSize(y,&p);
    207:   if (pf->dimin*(n/pf->dimin) != n) SETERRQ2(PETSC_ERR_ARG_IDN,"Local input vector length %D not divisible by dimin %D of function",n,pf->dimin);
    208:   if (pf->dimout*(p/pf->dimout) != p) SETERRQ2(PETSC_ERR_ARG_IDN,"Local output vector length %D not divisible by dimout %D of function",p,pf->dimout);
    209:   if (n/pf->dimin != p/pf->dimout) SETERRQ4(PETSC_ERR_ARG_IDN,"Local vector lengths %D %D are wrong for dimin and dimout %D %D of function",n,p,pf->dimin,pf->dimout);

    211:   if (pf->ops->applyvec) {
    212:     (*pf->ops->applyvec)(pf->data,x,y);
    213:   } else {
    214:     PetscScalar *xx,*yy;

    216:     VecGetLocalSize(x,&n);
    217:     n    = n/pf->dimin;
    218:     VecGetArray(x,&xx);
    219:     VecGetArray(y,&yy);
    220:     if (!pf->ops->apply) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No function has been provided for this PF");
    221:     (*pf->ops->apply)(pf->data,n,xx,yy);
    222:     VecRestoreArray(x,&xx);
    223:     VecRestoreArray(y,&yy);
    224:   }
    225:   if (nox) {
    226:     VecDestroy(x);
    227:   }
    228:   return(0);
    229: }

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

    236:    Collective on PF

    238:    Input Parameters:
    239: +  pf - the function context
    240: .  n - number of pointwise function evaluations to perform, each pointwise function evaluation
    241:        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
    242:        in the call to PFCreate()
    243: -  x - input array

    245:    Output Parameter:
    246: .  y - output array

    248:    Level: beginner

    250:    Notes:

    252: .keywords: PF, apply

    254: .seealso: PFApplyVec(), PFCreate(), PFDestroy(), PFSetType(), PFSet()
    255: @*/
    256: PetscErrorCode PETSCVEC_DLLEXPORT PFApply(PF pf,PetscInt n,PetscScalar* x,PetscScalar* y)
    257: {

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

    267:   (*pf->ops->apply)(pf->data,n,x,y);
    268:   return(0);
    269: }

    273: /*@
    274:    PFView - Prints information about a mathematical function

    276:    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF

    278:    Input Parameters:
    279: +  PF - the PF context
    280: -  viewer - optional visualization context

    282:    Note:
    283:    The available visualization contexts include
    284: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
    285: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
    286:          output where only the first processor opens
    287:          the file.  All other processors send their
    288:          data to the first processor to print.

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

    293:    Level: developer

    295: .keywords: PF, view

    297: .seealso: PetscViewerCreate(), PetscViewerASCIIOpen()
    298: @*/
    299: PetscErrorCode PETSCVEC_DLLEXPORT PFView(PF pf,PetscViewer viewer)
    300: {
    301:   PFType            cstr;
    303:   PetscTruth        iascii;
    304:   PetscViewerFormat format;

    308:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(pf->comm);

    312:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
    313:   if (iascii) {
    314:     PetscViewerGetFormat(viewer,&format);
    315:     PetscViewerASCIIPrintf(viewer,"PF Object:\n");
    316:     PFGetType(pf,&cstr);
    317:     if (cstr) {
    318:       PetscViewerASCIIPrintf(viewer,"  type: %s\n",cstr);
    319:     } else {
    320:       PetscViewerASCIIPrintf(viewer,"  type: not yet set\n");
    321:     }
    322:     if (pf->ops->view) {
    323:       PetscViewerASCIIPushTab(viewer);
    324:       (*pf->ops->view)(pf->data,viewer);
    325:       PetscViewerASCIIPopTab(viewer);
    326:     }
    327:   } else {
    328:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by PF",((PetscObject)viewer)->type_name);
    329:   }
    330:   return(0);
    331: }

    333: /*MC
    334:    PFRegisterDynamic - Adds a method to the mathematical function package.

    336:    Synopsis:
    337:    PetscErrorCode PFRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(PF))

    339:    Not collective

    341:    Input Parameters:
    342: +  name_solver - name of a new user-defined solver
    343: .  path - path (either absolute or relative) the library containing this solver
    344: .  name_create - name of routine to create method context
    345: -  routine_create - routine to create method context

    347:    Notes:
    348:    PFRegisterDynamic() may be called multiple times to add several user-defined functions

    350:    If dynamic libraries are used, then the fourth input argument (routine_create)
    351:    is ignored.

    353:    Sample usage:
    354: .vb
    355:    PFRegisterDynamic("my_function","/home/username/my_lib/lib/libO/solaris/mylib",
    356:               "MyFunctionCreate",MyFunctionSetCreate);
    357: .ve

    359:    Then, your solver can be chosen with the procedural interface via
    360: $     PFSetType(pf,"my_function")
    361:    or at runtime via the option
    362: $     -pf_type my_function

    364:    Level: advanced

    366:    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
    367:  occuring in pathname will be replaced with appropriate values.

    369: .keywords: PF, register

    371: .seealso: PFRegisterAll(), PFRegisterDestroy(), PFRegister()
    372: M*/

    376: PetscErrorCode PETSCVEC_DLLEXPORT PFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(PF,void*))
    377: {
    379:   char fullname[PETSC_MAX_PATH_LEN];

    382:   PetscFListConcat(path,name,fullname);
    383:   PetscFListAdd(&PPetscFList,sname,fullname,(void (*)(void))function);
    384:   return(0);
    385: }

    391: /*@C
    392:    PFGetType - Gets the PF method type and name (as a string) from the PF
    393:    context.

    395:    Not Collective

    397:    Input Parameter:
    398: .  pf - the function context

    400:    Output Parameter:
    401: .  name - name of function

    403:    Level: intermediate

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

    407: .seealso: PFSetType()

    409: @*/
    410: PetscErrorCode PETSCVEC_DLLEXPORT PFGetType(PF pf,PFType *meth)
    411: {
    413:   *meth = (PFType) pf->type_name;
    414:   return(0);
    415: }

    420: /*@C
    421:    PFSetType - Builds PF for a particular function

    423:    Collective on PF

    425:    Input Parameter:
    426: +  pf - the function context.
    427: .  type - a known method
    428: -  ctx - optional type dependent context

    430:    Options Database Key:
    431: .  -pf_type <type> - Sets PF type

    434:   Notes:
    435:   See "petsc/include/petscpf.h" for available methods (for instance,
    436:   PFCONSTANT)

    438:   Level: intermediate

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

    442: .seealso: PFSet(), PFRegisterDynamic(), PFCreate(), DACreatePF()

    444: @*/
    445: PetscErrorCode PETSCVEC_DLLEXPORT PFSetType(PF pf,const PFType type,void *ctx)
    446: {
    447:   PetscErrorCode ierr,(*r)(PF,void*);
    448:   PetscTruth match;

    454:   PetscTypeCompare((PetscObject)pf,type,&match);
    455:   if (match) return(0);

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

    460:   /* Get the function pointers for the method requested */
    461:   if (!PFRegisterAllCalled) {PFRegisterAll(0);}
    462:   /* Determine the PFCreateXXX routine for a particular function */
    463:    PetscFListFind(pf->comm,PPetscFList,type,(void (**)(void)) &r);
    464:   if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested PF type %s",type);
    465:   pf->ops->destroy             = 0;
    466:   pf->ops->view                = 0;
    467:   pf->ops->apply               = 0;
    468:   pf->ops->applyvec            = 0;

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

    473:   PetscObjectChangeTypeName((PetscObject)pf,type);
    474:   return(0);
    475: }

    479: /*@
    480:    PFSetFromOptions - Sets PF options from the options database.

    482:    Collective on PF

    484:    Input Parameters:
    485: .  pf - the mathematical function context

    487:    Options Database Keys:

    489:    Notes:
    490:    To see all options, run your program with the -help option
    491:    or consult the users manual.

    493:    Level: intermediate

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

    497: .seealso:
    498: @*/
    499: PetscErrorCode PETSCVEC_DLLEXPORT PFSetFromOptions(PF pf)
    500: {
    502:   char       type[256];
    503:   PetscTruth flg;

    508:   if (!PFRegisterAllCalled) {PFRegisterAll(0);}
    509:   PetscOptionsBegin(pf->comm,pf->prefix,"Mathematical functions options","Vec");
    510:     PetscOptionsList("-pf_type","Type of function","PFSetType",PPetscFList,0,type,256,&flg);
    511:     if (flg) {
    512:       PFSetType(pf,type,PETSC_NULL);
    513:     }
    514:     if (pf->ops->setfromoptions) {
    515:       (*pf->ops->setfromoptions)(pf);
    516:     }
    517:   PetscOptionsEnd();

    519:   return(0);
    520: }