Date: 2013-07-02T14:38:44+00:00

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

      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-private/petscimpl.h>           /*I "petscsys.h" I*/
      7: #include <petscviewer.h>

      9: /*
     10:     This is the default list used by PETSc with the PetscDLLibrary register routines
     11: */
     12: PetscDLLibrary PetscDLLibrariesLoaded = 0;

     14: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)

     18: static PetscErrorCode  PetscLoadDynamicLibrary(const char *name,PetscBool  *found)
     19: {
     20:   char           libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];

     24:   PetscStrcpy(libs,"${PETSC_LIB_DIR}/libpetsc");
     25:   PetscStrcat(libs,name);
     26:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
     27:   if (*found) {
     28:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
     29:   } else {
     30:     PetscStrcpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc");
     31:     PetscStrcat(libs,name);
     32:     PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
     33:     if (*found) {
     34:       PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
     35:     }
     36:   }
     37:   return(0);
     38: }

     40: #endif

     44: /*
     45:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
     46:     search path.
     47: */
     48: PetscErrorCode  PetscInitialize_DynamicLibraries(void)
     49: {
     50:   char           *libname[32];
     52:   PetscInt       nmax,i;
     53: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
     54:   PetscBool      found;
     55: #endif

     58:   nmax = 32;
     59:   PetscOptionsGetStringArray(NULL,"-dll_prepend",libname,&nmax,NULL);
     60:   for (i=0; i<nmax; i++) {
     61:     PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
     62:     PetscFree(libname[i]);
     63:   }

     65: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
     66:   /*
     67:       This just initializes the most basic PETSc stuff.

     69:     The classes, from PetscDraw to PetscTS, are initialized the first
     70:     time an XXCreate() is called.
     71:   */
     72:   PetscSysInitializePackage();
     73: #else
     74: #if defined(PETSC_USE_SINGLE_LIBRARY)
     75:   PetscLoadDynamicLibrary("",&found);
     76:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
     77: #else
     78:   PetscLoadDynamicLibrary("sys",&found);
     79:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
     80:   PetscLoadDynamicLibrary("vec",&found);
     81:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
     82:   PetscLoadDynamicLibrary("mat",&found);
     83:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
     84:   PetscLoadDynamicLibrary("dm",&found);
     85:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
     86:   PetscLoadDynamicLibrary("ksp",&found);
     87:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
     88:   PetscLoadDynamicLibrary("snes",&found);
     89:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
     90:   PetscLoadDynamicLibrary("ts",&found);
     91:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
     92: #endif
     93: #endif

     95:   nmax = 32;
     96:   PetscOptionsGetStringArray(NULL,"-dll_append",libname,&nmax,NULL);
     97:   for (i=0; i<nmax; i++) {
     98:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
     99:     PetscFree(libname[i]);
    100:   }
    101:   return(0);
    102: }

    106: /*
    107:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
    108: */
    109: PetscErrorCode PetscFinalize_DynamicLibraries(void)
    110: {
    112:   PetscBool      flg = PETSC_FALSE;

    115:   PetscOptionsGetBool(NULL,"-dll_view",&flg,NULL);
    116:   if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
    117:   PetscDLLibraryClose(PetscDLLibrariesLoaded);

    119:   PetscDLLibrariesLoaded = 0;
    120:   return(0);
    121: }

    125: /* ------------------------------------------------------------------------------*/
    126: struct _n_PetscFunctionList {
    127:   void              (*routine)(void);    /* the routine */
    128:   char              *name;               /* string to identify routine */
    129:   PetscFunctionList next;                /* next pointer */
    130:   PetscFunctionList next_list;           /* used to maintain list of all lists for freeing */
    131: };

    133: /*
    134:      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
    135: */
    136: static PetscFunctionList dlallhead = 0;

    138: /*MC
    139:    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
    140:    specified registry.

    142:    Synopsis:
    143:    #include "petscsys.h"
    144:    PetscErrorCode PetscFunctionListAdd(PetscFunctionList flist,const char name[],void (*fptr)(void))

    146:    Not Collective

    148:    Input Parameters:
    149: +  flist - pointer registry
    150: .  name - string to identify routine
    151: -  fptr - function pointer

    153:    Notes:
    154:    To remove a registered routine, pass in a NULL fptr.

    156:    Users who wish to register new classes for use by a particular PETSc
    157:    component (e.g., SNES) should generally call the registration routine
    158:    for that particular component (e.g., SNESRegister()) instead of
    159:    calling PetscFunctionListAdd() directly.

    161:     Level: developer

    163: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
    164:           PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
    165: M*/
    168: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
    169: {
    170:   PetscFunctionList entry,ne;
    171:   PetscErrorCode    ierr;

    174:   if (!*fl) {
    175:     PetscNew(struct _n_PetscFunctionList,&entry);
    176:     PetscStrallocpy(name,&entry->name);
    177:     entry->routine = fnc;
    178:     entry->next    = 0;
    179:     *fl            = entry;

    181:     /* add this new list to list of all lists */
    182:     if (!dlallhead) {
    183:       dlallhead        = *fl;
    184:       (*fl)->next_list = 0;
    185:     } else {
    186:       ne               = dlallhead;
    187:       dlallhead        = *fl;
    188:       (*fl)->next_list = ne;
    189:     }
    190:   } else {
    191:     /* search list to see if it is already there */
    192:     ne = *fl;
    193:     while (ne) {
    194:       PetscBool founddup;

    196:       PetscStrcmp(ne->name,name,&founddup);
    197:       if (founddup) { /* found duplicate */
    198:         ne->routine = fnc;
    199:         return(0);
    200:       }
    201:       if (ne->next) ne = ne->next;
    202:       else break;
    203:     }
    204:     /* create new entry and add to end of list */
    205:     PetscNew(struct _n_PetscFunctionList,&entry);
    206:     PetscStrallocpy(name,&entry->name);
    207:     entry->routine = fnc;
    208:     entry->next    = 0;
    209:     ne->next       = entry;
    210:   }
    211:   return(0);
    212: }

    216: /*@
    217:     PetscFunctionListDestroy - Destroys a list of registered routines.

    219:     Input Parameter:
    220: .   fl  - pointer to list

    222:     Level: developer

    224: .seealso: PetscFunctionListAdd(), PetscFunctionList
    225: @*/
    226: PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
    227: {
    228:   PetscFunctionList next,entry,tmp = dlallhead;
    229:   PetscErrorCode    ierr;

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

    234:   /*
    235:        Remove this entry from the master DL list (if it is in it)
    236:   */
    237:   if (dlallhead == *fl) {
    238:     if (dlallhead->next_list) dlallhead = dlallhead->next_list;
    239:     else dlallhead = NULL;
    240:   } else if (tmp) {
    241:     while (tmp->next_list != *fl) {
    242:       tmp = tmp->next_list;
    243:       if (!tmp->next_list) break;
    244:     }
    245:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
    246:   }

    248:   /* free this list */
    249:   entry = *fl;
    250:   while (entry) {
    251:     next  = entry->next;
    252:     PetscFree(entry->name);
    253:     PetscFree(entry);
    254:     entry = next;
    255:   }
    256:   *fl = 0;
    257:   return(0);
    258: }

    260: /*
    261:    Print any PetscFunctionLists that have not be destroyed
    262: */
    265: PetscErrorCode  PetscFunctionListPrintAll(void)
    266: {
    267:   PetscFunctionList tmp = dlallhead;
    268:   PetscErrorCode    ierr;

    271:   if (tmp) {
    272:     PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
    273:   }
    274:   while (tmp) {
    275:     PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
    276:     tmp = tmp->next_list;
    277:   }
    278:   return(0);
    279: }

    281: /*MC
    282:     PetscFunctionListFind - Find function registered under given name

    284:     Synopsis:
    285:     #include "petscsys.h"
    286:     PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))

    288:     Input Parameters:
    289: +   flist   - pointer to list
    290: -   name - name registered for the function

    292:     Output Parameters:
    293: .   fptr - the function pointer if name was found, else NULL

    295:     Level: developer

    297: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
    298: M*/
    301: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
    302: {
    303:   PetscFunctionList entry = fl;
    304:   PetscErrorCode    ierr;
    305:   PetscBool         flg;

    308:   if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");

    310:   *r = 0;
    311:   while (entry) {
    312:     PetscStrcmp(name,entry->name,&flg);
    313:     if (flg) {
    314:       *r   = entry->routine;
    315:       return(0);
    316:     }
    317:     entry = entry->next;
    318:   }
    319:   return(0);
    320: }

    324: /*@
    325:    PetscFunctionListView - prints out contents of an PetscFunctionList

    327:    Collective over MPI_Comm

    329:    Input Parameters:
    330: +  list - the list of functions
    331: -  viewer - currently ignored

    333:    Level: developer

    335: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
    336: @*/
    337: PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
    338: {
    340:   PetscBool      iascii;

    343:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;

    347:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    348:   if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");

    350:   while (list) {
    351:     PetscViewerASCIIPrintf(viewer," %s\n",list->name);
    352:     list = list->next;
    353:   }
    354:   PetscViewerASCIIPrintf(viewer,"\n");
    355:   return(0);
    356: }

    360: /*@C
    361:    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
    362:          by help etc.

    364:    Not Collective

    366:    Input Parameter:
    367: .  list   - list of types

    369:    Output Parameter:
    370: +  array - array of names
    371: -  n - length of array

    373:    Notes:
    374:        This allocates the array so that must be freed. BUT the individual entries are
    375:     not copied so should not be freed.

    377:    Level: developer

    379: .seealso: PetscFunctionListAdd(), PetscFunctionList
    380: @*/
    381: PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
    382: {
    383:   PetscErrorCode    ierr;
    384:   PetscInt          count = 0;
    385:   PetscFunctionList klist = list;

    388:   while (list) {
    389:     list = list->next;
    390:     count++;
    391:   }
    392:   PetscMalloc((count+1)*sizeof(char*),array);
    393:   count = 0;
    394:   while (klist) {
    395:     (*array)[count] = klist->name;
    396:     klist           = klist->next;
    397:     count++;
    398:   }
    399:   (*array)[count] = 0;
    400:   *n              = count+1;
    401:   return(0);
    402: }

    407: /*@C
    408:    PetscFunctionListPrintTypes - Prints the methods available.

    410:    Collective over MPI_Comm

    412:    Input Parameters:
    413: +  comm   - the communicator (usually MPI_COMM_WORLD)
    414: .  fd     - file to print to, usually stdout
    415: .  prefix - prefix to prepend to name (optional)
    416: .  name   - option string (for example, "-ksp_type")
    417: .  text - short description of the object (for example, "Krylov solvers")
    418: .  man - name of manual page that discusses the object (for example, "KSPCreate")
    419: .  list   - list of types
    420: -  def - default (current) value

    422:    Level: developer

    424: .seealso: PetscFunctionListAdd(), PetscFunctionList
    425: @*/
    426: PetscErrorCode  PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
    427: {
    429:   PetscInt       count = 0;
    430:   char           p[64];

    433:   if (!fd) fd = PETSC_STDOUT;

    435:   PetscStrcpy(p,"-");
    436:   if (prefix) {PetscStrcat(p,prefix);}
    437:   PetscFPrintf(comm,fd,"  %s%s <%s>: %s (one of)",p,name+1,def,text);

    439:   while (list) {
    440:     PetscFPrintf(comm,fd," %s",list->name);
    441:     list = list->next;
    442:     count++;
    443:     if (count == 8) {PetscFPrintf(comm,fd,"\n     ");}
    444:   }
    445:   PetscFPrintf(comm,fd," (%s)\n",man);
    446:   return(0);
    447: }

    451: /*@
    452:     PetscFunctionListDuplicate - Creates a new list from a given object list.

    454:     Input Parameters:
    455: .   fl   - pointer to list

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

    460:     Level: developer

    462: .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()

    464: @*/
    465: PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
    466: {

    470:   while (fl) {
    471:     PetscFunctionListAdd(nl,fl->name,fl->routine);
    472:     fl   = fl->next;
    473:   }
    474:   return(0);
    475: }