Actual source code: reg.c

      1: #define PETSC_DLL
      2: /*
      3:     Provides a general mechanism to allow one to register new routines in
      4:     dynamic libraries for many of the PETSc objects (including, e.g., KSP and PC).
      5: */
     6:  #include petsc.h
     7:  #include petscsys.h

     11: PetscErrorCode PETSC_DLLEXPORT PetscFListGetPathAndFunction(const char name[],char *path[],char *function[])
     12: {
     14:   char work[PETSC_MAX_PATH_LEN],*lfunction;

     17:   PetscStrncpy(work,name,256);
     18:   PetscStrchr(work,':',&lfunction);
     19:   if (lfunction != work && lfunction && lfunction[1] != ':') {
     20:     lfunction[0] = 0;
     21:     PetscStrallocpy(work,path);
     22:     PetscStrallocpy(lfunction+1,function);
     23:   } else {
     24:     *path = 0;
     25:     PetscStrallocpy(name,function);
     26:   }
     27:   return(0);
     28: }

     30: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)

     32: /*
     33:     This is the list used by the DLRegister routines
     34: */
     35: PetscDLLibraryList DLLibrariesLoaded = 0;

     39: /*
     40:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
     41:     search path.
     42: */
     43: PetscErrorCode PETSC_DLLEXPORT PetscInitialize_DynamicLibraries(void)
     44: {
     45:   char           *libname[32],libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
     47:   PetscInt       nmax,i;
     48:   PetscTruth     found;

     52:   nmax = 32;
     53:   PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
     54:   for (i=0; i<nmax; i++) {
     55:     PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
     56:     PetscFree(libname[i]);
     57:   }

     59:   PetscStrcpy(libs,PETSC_LIB_DIR);
     60:   PetscStrcat(libs,"/libpetsc");
     61:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
     62:   if (found) {
     63:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
     64:   } else {
     65:     SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library %s \n You cannot move the dynamic libraries!\n or remove USE_DYNAMIC_LIBRARIES from ${PETSC_DIR}/bmake/$PETSC_ARCH/petscconf.h\n and rebuild libraries before moving",libs);
     66:   }

     68:   PetscStrcpy(libs,PETSC_LIB_DIR);
     69:   PetscStrcat(libs,"/libpetscvec");
     70:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
     71:   if (found) {
     72:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
     73:   }

     75:   PetscStrcpy(libs,PETSC_LIB_DIR);
     76:   PetscStrcat(libs,"/libpetscmat");
     77:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
     78:   if (found) {
     79:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
     80:   }

     82:   PetscStrcpy(libs,PETSC_LIB_DIR);
     83:   PetscStrcat(libs,"/libpetscdm");
     84:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
     85:   if (found) {
     86:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
     87:   }

     89:   PetscStrcpy(libs,PETSC_LIB_DIR);
     90:   PetscStrcat(libs,"/libpetscksp");
     91:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
     92:   if (found) {
     93:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
     94:   }

     96:   PetscStrcpy(libs,PETSC_LIB_DIR);
     97:   PetscStrcat(libs,"/libpetscsnes");
     98:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
     99:   if (found) {
    100:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
    101:   }

    103:   PetscStrcpy(libs,PETSC_LIB_DIR);
    104:   PetscStrcat(libs,"/libpetscts");
    105:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
    106:   if (found) {
    107:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
    108:   }

    110:   PetscStrcpy(libs,PETSC_LIB_DIR);
    111:   PetscStrcat(libs,"/libpetscdm");
    112:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
    113:   if (found) {
    114:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
    115:   }

    117:   PetscStrcpy(libs,PETSC_LIB_DIR);
    118:   PetscStrcat(libs,"/libpetscmesh");
    119:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
    120:   if (found) {
    121:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
    122:   }

    124:   PetscStrcpy(libs,PETSC_LIB_DIR);
    125:   PetscStrcat(libs,"/libpetscgrid");
    126:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
    127:   if (found) {
    128:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
    129:   }

    131:   nmax = 32;
    132:   PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
    133:   for (i=0; i<nmax; i++) {
    134:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
    135:     PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
    136:     PetscFree(libname[i]);
    137:   }

    139:   return(0);
    140: }

    144: /*
    145:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
    146: */
    147: PetscErrorCode PetscFinalize_DynamicLibraries(void)
    148: {
    150:   PetscTruth     flg;

    153:   PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);
    154:   if (flg) {
    155:     PetscDLLibraryPrintPath();
    156:   }
    157:   PetscDLLibraryClose(DLLibrariesLoaded);
    158:   return(0);
    159: }

    161: #else /* not using dynamic libraries */

    165: PetscErrorCode PETSC_DLLEXPORT PetscInitialize_DynamicLibraries(void)
    166: {

    170:   /*
    171:       This just initializes the draw and viewer methods, since those
    172:     are ALWAYS available. The other classes are initialized the first
    173:     time an XXSetType() is called.
    174:   */
    175:   PetscInitializePackage(PETSC_NULL);
    176:   return(0);
    177: }
    180: PetscErrorCode PetscFinalize_DynamicLibraries(void)
    181: {

    184:   return(0);
    185: }
    186: #endif

    188: /* ------------------------------------------------------------------------------*/
    189: struct _PetscFList {
    190:   void        (*routine)(void);   /* the routine */
    191:   char        *path;              /* path of link library containing routine */
    192:   char        *name;              /* string to identify routine */
    193:   char        *rname;             /* routine name in dynamic library */
    194:   PetscFList  next;               /* next pointer */
    195:   PetscFList  next_list;          /* used to maintain list of all lists for freeing */
    196: };

    198: /*
    199:      Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
    200: */
    201: static PetscFList   dlallhead = 0;

    205: /*@C
    206:    PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
    207:    specified registry.

    209:      Not Collective

    211:    Input Parameters:
    212: +  fl    - pointer registry
    213: .  name  - string to identify routine
    214: .  rname - routine name in dynamic library
    215: -  fnc   - function pointer (optional if using dynamic libraries)

    217:    Notes:
    218:    To remove a registered routine, pass in a PETSC_NULL rname and fnc().

    220:    Users who wish to register new classes for use by a particular PETSc
    221:    component (e.g., SNES) should generally call the registration routine
    222:    for that particular component (e.g., SNESRegisterDynamic()) instead of
    223:    calling PetscFListAddDynamic() directly.

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

    228:    Level: developer

    230: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
    231:           PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
    232: @*/
    233: PetscErrorCode PETSC_DLLEXPORT PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
    234: {
    235:   PetscFList     entry,ne;
    237:   char           *fpath,*fname;

    241:   if (!*fl) {
    242:     PetscNew(struct _PetscFList,&entry);
    243:     PetscStrallocpy(name,&entry->name);
    244:     PetscFListGetPathAndFunction(rname,&fpath,&fname);
    245:     entry->path    = fpath;
    246:     entry->rname   = fname;
    247:     entry->routine = fnc;
    248:     entry->next    = 0;
    249:     *fl = entry;

    251:     /* add this new list to list of all lists */
    252:     if (!dlallhead) {
    253:       dlallhead        = *fl;
    254:       (*fl)->next_list = 0;
    255:     } else {
    256:       ne               = dlallhead;
    257:       dlallhead        = *fl;
    258:       (*fl)->next_list = ne;
    259:     }
    260:   } else {
    261:     /* search list to see if it is already there */
    262:     ne = *fl;
    263:     while (ne) {
    264:       PetscTruth founddup;

    266:       PetscStrcmp(ne->name,name,&founddup);
    267:       if (founddup) { /* found duplicate */
    268:         PetscFListGetPathAndFunction(rname,&fpath,&fname);
    269:         PetscStrfree(ne->path);
    270:         PetscStrfree(ne->rname);
    271:         ne->path    = fpath;
    272:         ne->rname   = fname;
    273:         ne->routine = fnc;
    274:         return(0);
    275:       }
    276:       if (ne->next) ne = ne->next; else break;
    277:     }
    278:     /* create new entry and add to end of list */
    279:     PetscNew(struct _PetscFList,&entry);
    280:     PetscStrallocpy(name,&entry->name);
    281:     PetscFListGetPathAndFunction(rname,&fpath,&fname);
    282:     entry->path    = fpath;
    283:     entry->rname   = fname;
    284:     entry->routine = fnc;
    285:     entry->next    = 0;
    286:     ne->next       = entry;
    287:   }

    289:   return(0);
    290: }

    294: /*@
    295:     PetscFListDestroy - Destroys a list of registered routines.

    297:     Input Parameter:
    298: .   fl  - pointer to list

    300:     Level: developer

    302: .seealso: PetscFListAddDynamic(), PetscFList
    303: @*/
    304: PetscErrorCode PETSC_DLLEXPORT PetscFListDestroy(PetscFList *fl)
    305: {
    306:   PetscFList     next,entry,tmp = dlallhead;

    310:   if (!*fl) return(0);

    312:   if (!dlallhead) {
    313:     return(0);
    314:   }

    316:   /*
    317:        Remove this entry from the master DL list (if it is in it)
    318:   */
    319:   if (dlallhead == *fl) {
    320:     if (dlallhead->next_list) {
    321:       dlallhead = dlallhead->next_list;
    322:     } else {
    323:       dlallhead = 0;
    324:     }
    325:   } else {
    326:     while (tmp->next_list != *fl) {
    327:       tmp = tmp->next_list;
    328:       if (!tmp->next_list) break;
    329:     }
    330:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
    331:   }

    333:   /* free this list */
    334:   entry = *fl;
    335:   while (entry) {
    336:     next = entry->next;
    337:     PetscStrfree(entry->path);
    338:     PetscFree(entry->name);
    339:     PetscFree(entry->rname);
    340:     PetscFree(entry);
    341:     entry = next;
    342:   }
    343:   *fl = 0;
    344:   return(0);
    345: }

    347: /*
    348:    Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
    349: */
    352: PetscErrorCode PETSC_DLLEXPORT PetscFListDestroyAll(void)
    353: {
    354:   PetscFList     tmp2,tmp1 = dlallhead;

    358:   while (tmp1) {
    359:     tmp2 = tmp1->next_list;
    360:     PetscFListDestroy(&tmp1);
    361:     tmp1 = tmp2;
    362:   }
    363:   dlallhead = 0;
    364:   return(0);
    365: }

    369: /*@C
    370:     PetscFListFind - Given a name, finds the matching routine.

    372:     Input Parameters:
    373: +   comm - processors looking for routine
    374: .   fl   - pointer to list
    375: -   name - name string

    377:     Output Parameters:
    378: .   r - the routine

    380:     Level: developer

    382: .seealso: PetscFListAddDynamic(), PetscFList
    383: @*/
    384: PetscErrorCode PETSC_DLLEXPORT PetscFListFind(MPI_Comm comm,PetscFList fl,const char name[],void (**r)(void))
    385: {
    386:   PetscFList     entry = fl;
    388:   char           *function,*path;
    389: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
    390:   char           *newpath;
    391: #endif
    392:   PetscTruth   flg,f1,f2,f3;
    393:
    395:   if (!name) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to find routine with null name");

    397:   *r = 0;
    398:   PetscFListGetPathAndFunction(name,&path,&function);

    400:   /*
    401:         If path then append it to search libraries
    402:   */
    403: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
    404:   if (path) {
    405:     PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
    406:   }
    407: #endif

    409:   while (entry) {
    410:     flg = PETSC_FALSE;
    411:     if (path && entry->path) {
    412:       PetscStrcmp(path,entry->path,&f1);
    413:       PetscStrcmp(function,entry->rname,&f2);
    414:       PetscStrcmp(function,entry->name,&f3);
    415:       flg =  (PetscTruth) ((f1 && f2) || (f1 && f3));
    416:     } else if (!path) {
    417:       PetscStrcmp(function,entry->name,&f1);
    418:       PetscStrcmp(function,entry->rname,&f2);
    419:       flg =  (PetscTruth) (f1 || f2);
    420:     } else {
    421:       PetscStrcmp(function,entry->name,&flg);
    422:       if (flg) {
    423:         PetscFree(function);
    424:         PetscStrallocpy(entry->rname,&function);
    425:       } else {
    426:         PetscStrcmp(function,entry->rname,&flg);
    427:       }
    428:     }

    430:     if (flg) {

    432:       if (entry->routine) {
    433:         *r   = entry->routine;
    434:         PetscStrfree(path);
    435:         PetscFree(function);
    436:         return(0);
    437:       }
    438:
    439:       if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
    440:         PetscFree(function);
    441:         PetscStrallocpy(entry->rname,&function);
    442:       }

    444:       /* it is not yet in memory so load from dynamic library */
    445: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
    446:       newpath = path;
    447:       if (!path) newpath = entry->path;
    448:       PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
    449:       if (*r) {
    450:         entry->routine = *r;
    451:         PetscStrfree(path);
    452:         PetscFree(function);
    453:         return(0);
    454:       } else {
    455:         PetscErrorPrintf("Unable to find function. Search path:\n");
    456:         PetscDLLibraryPrintPath();
    457:         SETERRQ1(PETSC_ERR_PLIB,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
    458:       }
    459: #endif
    460:     }
    461:     entry = entry->next;
    462:   }

    464: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
    465:   /* Function never registered; try for it anyway */
    466:   PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
    467:   PetscStrfree(path);
    468:   if (*r) {
    469:     PetscFListAdd(&fl,name,name,*r);
    470:   }
    471: #endif
    472:   PetscFree(function);
    473:   return(0);
    474: }

    478: /*@
    479:    PetscFListView - prints out contents of an PetscFList

    481:    Collective over MPI_Comm

    483:    Input Parameters:
    484: +  list - the list of functions
    485: -  viewer - currently ignored

    487:    Level: developer

    489: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
    490: @*/
    491: PetscErrorCode PETSC_DLLEXPORT PetscFListView(PetscFList list,PetscViewer viewer)
    492: {
    494:   PetscTruth     iascii;

    497:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
    500:
    501:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
    502:   if (!iascii) SETERRQ(PETSC_ERR_SUP,"Only ASCII viewer supported");

    504:   while (list) {
    505:     if (list->path) {
    506:       PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
    507:     } else {
    508:       PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
    509:     }
    510:     list = list->next;
    511:   }
    512:   PetscViewerASCIIPrintf(viewer,"\n");
    513:   return(0);
    514: }

    518: /*@
    519:    PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
    520:          by help etc.

    522:    Collective over MPI_Comm

    524:    Input Parameter:
    525: .  list   - list of types

    527:    Output Parameter:
    528: +  array - array of names
    529: -  n - length of array

    531:    Notes:
    532:        This allocates the array so that must be freed. BUT the individual entries are
    533:     not copied so should not be freed.

    535:    Level: developer

    537: .seealso: PetscFListAddDynamic(), PetscFList
    538: @*/
    539: PetscErrorCode PETSC_DLLEXPORT PetscFListGet(PetscFList list,char ***array,int *n)
    540: {
    542:   PetscInt       count = 0;
    543:   PetscFList     klist = list;

    546:   while (list) {
    547:     list = list->next;
    548:     count++;
    549:   }
    550:   PetscMalloc((count+1)*sizeof(char *),array);
    551:   count = 0;
    552:   while (klist) {
    553:     (*array)[count] = klist->name;
    554:     klist = klist->next;
    555:     count++;
    556:   }
    557:   (*array)[count] = 0;
    558:   *n = count+1;

    560:   return(0);
    561: }

    566: /*@C
    567:    PetscFListPrintTypes - Prints the methods available.

    569:    Collective over MPI_Comm

    571:    Input Parameters:
    572: +  comm   - the communicator (usually MPI_COMM_WORLD)
    573: .  fd     - file to print to, usually stdout
    574: .  prefix - prefix to prepend to name (optional)
    575: .  name   - option string (for example, "-ksp_type")
    576: .  text - short description of the object (for example, "Krylov solvers")
    577: .  man - name of manual page that discusses the object (for example, "KSPCreate")
    578: -  list   - list of types

    580:    Level: developer

    582: .seealso: PetscFListAddDynamic(), PetscFList
    583: @*/
    584: PetscErrorCode PETSC_DLLEXPORT PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFList list)
    585: {
    587:   PetscInt       count = 0;
    588:   char           p[64];

    591:   if (!fd) fd = stdout;

    593:   PetscStrcpy(p,"-");
    594:   if (prefix) {PetscStrcat(p,prefix);}
    595:   PetscFPrintf(comm,fd,"  %s%s %s:(one of)",p,name+1,text);

    597:   while (list) {
    598:     PetscFPrintf(comm,fd," %s",list->name);
    599:     list = list->next;
    600:     count++;
    601:     if (count == 8) {PetscFPrintf(comm,fd,"\n     ");}
    602:   }
    603:   PetscFPrintf(comm,fd," (%s)\n",man);
    604:   return(0);
    605: }

    609: /*@
    610:     PetscFListDuplicate - Creates a new list from a given object list.

    612:     Input Parameters:
    613: .   fl   - pointer to list

    615:     Output Parameters:
    616: .   nl - the new list (should point to 0 to start, otherwise appends)

    618:     Level: developer

    620: .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()

    622: @*/
    623: PetscErrorCode PETSC_DLLEXPORT PetscFListDuplicate(PetscFList fl,PetscFList *nl)
    624: {
    626:   char           path[PETSC_MAX_PATH_LEN];

    629:   while (fl) {
    630:     /* this is silly, rebuild the complete pathname */
    631:     if (fl->path) {
    632:       PetscStrcpy(path,fl->path);
    633:       PetscStrcat(path,":");
    634:       PetscStrcat(path,fl->name);
    635:     } else {
    636:       PetscStrcpy(path,fl->name);
    637:     }
    638:     PetscFListAdd(nl,path,fl->rname,fl->routine);
    639:     fl   = fl->next;
    640:   }
    641:   return(0);
    642: }

    647: /*
    648:     PetscFListConcat - joins name of a libary, and the path where it is located
    649:     into a single string.

    651:     Input Parameters:
    652: .   path   - path to the library name.
    653: .   name   - name of the library

    655:     Output Parameters:
    656: .   fullname - the name that is the union of the path and the library name,
    657:                delimited by a semicolon, i.e., path:name

    659:     Notes:
    660:     If the path is NULL, assumes that the name, specified also includes
    661:     the path as path:name

    663: */
    664: PetscErrorCode PETSC_DLLEXPORT PetscFListConcat(const char path[],const char name[],char fullname[])
    665: {
    668:   if (path) {
    669:     PetscStrcpy(fullname,path);
    670:     PetscStrcat(fullname,":");
    671:     PetscStrcat(fullname,name);
    672:   } else {
    673:     PetscStrcpy(fullname,name);
    674:   }
    675:   return(0);
    676: }