Actual source code: reg.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      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_HAVE_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

     42: #if defined(PETSC_HAVE_THREADSAFETY)
     43: extern PetscErrorCode AOInitializePackage(void);
     44: extern PetscErrorCode PetscSFInitializePackage(void);
     45: extern PetscErrorCode CharacteristicInitializePackage(void);
     46: extern PetscErrorCode ISInitializePackage(void);
     47: extern PetscErrorCode VecInitializePackage(void);
     48: extern PetscErrorCode MatInitializePackage(void);
     49: extern PetscErrorCode DMInitializePackage(void);
     50: extern PetscErrorCode PCInitializePackage(void);
     51: extern PetscErrorCode KSPInitializePackage(void);
     52: extern PetscErrorCode SNESInitializePackage(void);
     53: extern PetscErrorCode TSInitializePackage(void);
     54: static MPI_Comm PETSC_COMM_WORLD_INNER = 0,PETSC_COMM_SELF_INNER = 0;
     55: #endif

     59: /*
     60:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
     61:     search path.
     62: */
     63: PetscErrorCode  PetscInitialize_DynamicLibraries(void)
     64: {
     65:   char           *libname[32];
     67:   PetscInt       nmax,i;
     68: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
     69:   PetscBool      preload;
     70: #endif

     73:   nmax = 32;
     74:   PetscOptionsGetStringArray(NULL,NULL,"-dll_prepend",libname,&nmax,NULL);
     75:   for (i=0; i<nmax; i++) {
     76:     PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
     77:     PetscFree(libname[i]);
     78:   }

     80: #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
     81:   /*
     82:       This just initializes the most basic PETSc stuff.

     84:     The classes, from PetscDraw to PetscTS, are initialized the first
     85:     time an XXCreate() is called.
     86:   */
     87:   PetscSysInitializePackage();
     88: #else
     89:   preload = PETSC_FALSE;
     90:   PetscOptionsGetBool(NULL,NULL,"-dynamic_library_preload",&preload,NULL);
     91:   if (preload) {
     92:     PetscBool found;
     93: #if defined(PETSC_USE_SINGLE_LIBRARY)
     94:     PetscLoadDynamicLibrary("",&found);
     95:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
     96: #else
     97:     PetscLoadDynamicLibrary("sys",&found);
     98:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
     99:     PetscLoadDynamicLibrary("vec",&found);
    100:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
    101:     PetscLoadDynamicLibrary("mat",&found);
    102:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
    103:     PetscLoadDynamicLibrary("dm",&found);
    104:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
    105:     PetscLoadDynamicLibrary("ksp",&found);
    106:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
    107:     PetscLoadDynamicLibrary("snes",&found);
    108:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
    109:     PetscLoadDynamicLibrary("ts",&found);
    110:     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
    111: #endif
    112:   }
    113: #endif

    115:   nmax = 32;
    116:   PetscOptionsGetStringArray(NULL,NULL,"-dll_append",libname,&nmax,NULL);
    117:   for (i=0; i<nmax; i++) {
    118:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
    119:     PetscFree(libname[i]);
    120:   }

    122: #if defined(PETSC_HAVE_THREADSAFETY)
    123:   /* These must be done here because it is not safe for individual threads to call these initialize routines */
    124:   AOInitializePackage();
    125:   PetscSFInitializePackage();
    126:   CharacteristicInitializePackage();
    127:   ISInitializePackage();
    128:   VecInitializePackage();
    129:   MatInitializePackage();
    130:   DMInitializePackage();
    131:   PCInitializePackage();
    132:   KSPInitializePackage();
    133:   SNESInitializePackage();
    134:   TSInitializePackage();
    135:   PetscCommDuplicate(PETSC_COMM_SELF,&PETSC_COMM_SELF_INNER,NULL);
    136:   PetscCommDuplicate(PETSC_COMM_WORLD,&PETSC_COMM_WORLD_INNER,NULL);
    137: #endif
    138:   return(0);
    139: }

    143: /*
    144:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
    145: */
    146: PetscErrorCode PetscFinalize_DynamicLibraries(void)
    147: {
    149:   PetscBool      flg = PETSC_FALSE;

    152:   PetscOptionsGetBool(NULL,NULL,"-dll_view",&flg,NULL);
    153:   if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
    154:   PetscDLLibraryClose(PetscDLLibrariesLoaded);

    156: #if defined(PETSC_HAVE_THREADSAFETY)
    157:   PetscCommDestroy(&PETSC_COMM_SELF_INNER);
    158:   PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
    159: #endif

    161:   PetscDLLibrariesLoaded = 0;
    162:   return(0);
    163: }

    167: /* ------------------------------------------------------------------------------*/
    168: struct _n_PetscFunctionList {
    169:   void              (*routine)(void);    /* the routine */
    170:   char              *name;               /* string to identify routine */
    171:   PetscFunctionList next;                /* next pointer */
    172:   PetscFunctionList next_list;           /* used to maintain list of all lists for freeing */
    173: };

    175: /*
    176:      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
    177: */
    178: static PetscFunctionList dlallhead = 0;

    180: /*MC
    181:    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
    182:    specified registry.

    184:    Synopsis:
    185:    #include <petscsys.h>
    186:    PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))

    188:    Not Collective

    190:    Input Parameters:
    191: +  flist - pointer to function list object
    192: .  name - string to identify routine
    193: -  fptr - function pointer

    195:    Notes:
    196:    To remove a registered routine, pass in a NULL fptr.

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

    203:     Level: developer

    205: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
    206:           PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
    207: M*/
    210: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
    211: {
    212:   PetscFunctionList entry,ne;
    213:   PetscErrorCode    ierr;

    216:   if (!*fl) {
    217:     PetscNew(&entry);
    218:     PetscStrallocpy(name,&entry->name);
    219:     entry->routine = fnc;
    220:     entry->next    = 0;
    221:     *fl            = entry;

    223: #if defined(PETSC_USE_DEBUG)
    224:     /* add this new list to list of all lists */
    225:     if (!dlallhead) {
    226:       dlallhead        = *fl;
    227:       (*fl)->next_list = 0;
    228:     } else {
    229:       ne               = dlallhead;
    230:       dlallhead        = *fl;
    231:       (*fl)->next_list = ne;
    232:     }
    233: #endif

    235:   } else {
    236:     /* search list to see if it is already there */
    237:     ne = *fl;
    238:     while (ne) {
    239:       PetscBool founddup;

    241:       PetscStrcmp(ne->name,name,&founddup);
    242:       if (founddup) { /* found duplicate */
    243:         ne->routine = fnc;
    244:         return(0);
    245:       }
    246:       if (ne->next) ne = ne->next;
    247:       else break;
    248:     }
    249:     /* create new entry and add to end of list */
    250:     PetscNew(&entry);
    251:     PetscStrallocpy(name,&entry->name);
    252:     entry->routine = fnc;
    253:     entry->next    = 0;
    254:     ne->next       = entry;
    255:   }
    256:   return(0);
    257: }

    261: /*@
    262:     PetscFunctionListDestroy - Destroys a list of registered routines.

    264:     Input Parameter:
    265: .   fl  - pointer to list

    267:     Level: developer

    269: .seealso: PetscFunctionListAdd(), PetscFunctionList
    270: @*/
    271: PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
    272: {
    273:   PetscFunctionList next,entry,tmp = dlallhead;
    274:   PetscErrorCode    ierr;

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

    279:   /*
    280:        Remove this entry from the master DL list (if it is in it)
    281:   */
    282:   if (dlallhead == *fl) {
    283:     if (dlallhead->next_list) dlallhead = dlallhead->next_list;
    284:     else dlallhead = NULL;
    285:   } else if (tmp) {
    286:     while (tmp->next_list != *fl) {
    287:       tmp = tmp->next_list;
    288:       if (!tmp->next_list) break;
    289:     }
    290:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
    291:   }

    293:   /* free this list */
    294:   entry = *fl;
    295:   while (entry) {
    296:     next  = entry->next;
    297:     PetscFree(entry->name);
    298:     PetscFree(entry);
    299:     entry = next;
    300:   }
    301:   *fl = 0;
    302:   return(0);
    303: }

    305: /*
    306:    Print any PetscFunctionLists that have not be destroyed
    307: */
    310: PetscErrorCode  PetscFunctionListPrintAll(void)
    311: {
    312:   PetscFunctionList tmp = dlallhead;
    313:   PetscErrorCode    ierr;

    316:   if (tmp) {
    317:     PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
    318:   }
    319:   while (tmp) {
    320:     PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
    321:     tmp = tmp->next_list;
    322:   }
    323:   return(0);
    324: }

    326: /*MC
    327:     PetscFunctionListFind - Find function registered under given name

    329:     Synopsis:
    330:     #include <petscsys.h>
    331:     PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))

    333:     Input Parameters:
    334: +   flist   - pointer to list
    335: -   name - name registered for the function

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

    340:     Level: developer

    342: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
    343: M*/
    346: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
    347: {
    348:   PetscFunctionList entry = fl;
    349:   PetscErrorCode    ierr;
    350:   PetscBool         flg;

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

    355:   *r = 0;
    356:   while (entry) {
    357:     PetscStrcmp(name,entry->name,&flg);
    358:     if (flg) {
    359:       *r   = entry->routine;
    360:       return(0);
    361:     }
    362:     entry = entry->next;
    363:   }
    364:   return(0);
    365: }

    369: /*@
    370:    PetscFunctionListView - prints out contents of an PetscFunctionList

    372:    Collective over MPI_Comm

    374:    Input Parameters:
    375: +  list - the list of functions
    376: -  viewer - currently ignored

    378:    Level: developer

    380: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
    381: @*/
    382: PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
    383: {
    385:   PetscBool      iascii;

    388:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;

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

    395:   while (list) {
    396:     PetscViewerASCIIPrintf(viewer," %s\n",list->name);
    397:     list = list->next;
    398:   }
    399:   PetscViewerASCIIPrintf(viewer,"\n");
    400:   return(0);
    401: }

    405: /*@C
    406:    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
    407:          by help etc.

    409:    Not Collective

    411:    Input Parameter:
    412: .  list   - list of types

    414:    Output Parameter:
    415: +  array - array of names
    416: -  n - length of array

    418:    Notes:
    419:        This allocates the array so that must be freed. BUT the individual entries are
    420:     not copied so should not be freed.

    422:    Level: developer

    424: .seealso: PetscFunctionListAdd(), PetscFunctionList
    425: @*/
    426: PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
    427: {
    428:   PetscErrorCode    ierr;
    429:   PetscInt          count = 0;
    430:   PetscFunctionList klist = list;

    433:   while (list) {
    434:     list = list->next;
    435:     count++;
    436:   }
    437:   PetscMalloc1(count+1,array);
    438:   count = 0;
    439:   while (klist) {
    440:     (*array)[count] = klist->name;
    441:     klist           = klist->next;
    442:     count++;
    443:   }
    444:   (*array)[count] = 0;
    445:   *n              = count+1;
    446:   return(0);
    447: }

    452: /*@C
    453:    PetscFunctionListPrintTypes - Prints the methods available.

    455:    Collective over MPI_Comm

    457:    Input Parameters:
    458: +  comm   - the communicator (usually MPI_COMM_WORLD)
    459: .  fd     - file to print to, usually stdout
    460: .  prefix - prefix to prepend to name (optional)
    461: .  name   - option string (for example, "-ksp_type")
    462: .  text - short description of the object (for example, "Krylov solvers")
    463: .  man - name of manual page that discusses the object (for example, "KSPCreate")
    464: .  list   - list of types
    465: -  def - default (current) value

    467:    Level: developer

    469: .seealso: PetscFunctionListAdd(), PetscFunctionList
    470: @*/
    471:  PetscErrorCode  PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
    472: {
    474:   char           p[64];

    477:   if (!fd) fd = PETSC_STDOUT;

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

    483:   while (list) {
    484:     PetscFPrintf(comm,fd," %s",list->name);
    485:     list = list->next;
    486:   }
    487:   PetscFPrintf(comm,fd," (%s)\n",man);
    488:   return(0);
    489: }

    493: /*@
    494:     PetscFunctionListDuplicate - Creates a new list from a given object list.

    496:     Input Parameters:
    497: .   fl   - pointer to list

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

    502:     Level: developer

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

    506: @*/
    507: PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
    508: {

    512:   while (fl) {
    513:     PetscFunctionListAdd(nl,fl->name,fl->routine);
    514:     fl   = fl->next;
    515:   }
    516:   return(0);
    517: }