Actual source code: reg.c
petsc-3.10.5 2019-03-28
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>
      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) && defined(PETSC_USE_SHARED_LIBRARIES)

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

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

     38: #endif

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

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

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

     78: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) || !defined(PETSC_USE_SHARED_LIBRARIES)
     79:   /*
     80:       This just initializes the most basic PETSc stuff.

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

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

    120: #if defined(PETSC_HAVE_THREADSAFETY)
    121:   /* These must be done here because it is not safe for individual threads to call these initialize routines */
    122:   AOInitializePackage();
    123:   PetscSFInitializePackage();
    124: #if !defined(PETSC_USE_COMPLEX)
    125:   CharacteristicInitializePackage();
    126: #endif
    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: }

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

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

    154: #if defined(PETSC_HAVE_THREADSAFETY)
    155:   PetscCommDestroy(&PETSC_COMM_SELF_INNER);
    156:   PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
    157: #endif

    159:   PetscDLLibrariesLoaded = 0;
    160:   return(0);
    161: }

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

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

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

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

    186:    Not Collective

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

    193:    Notes:
    194:    To remove a registered routine, pass in a NULL fptr.

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

    201:     Level: developer

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

    212:   if (!*fl) {
    213:     PetscNew(&entry);
    214:     PetscStrallocpy(name,&entry->name);
    215:     entry->routine = fnc;
    216:     entry->next    = 0;
    217:     *fl            = entry;

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

    231:   } else {
    232:     /* search list to see if it is already there */
    233:     ne = *fl;
    234:     while (ne) {
    235:       PetscBool founddup;

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

    255: /*@
    256:     PetscFunctionListDestroy - Destroys a list of registered routines.

    258:     Input Parameter:
    259: .   fl  - pointer to list

    261:     Level: developer

    263: .seealso: PetscFunctionListAdd(), PetscFunctionList
    264: @*/
    265: PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
    266: {
    267:   PetscFunctionList next,entry,tmp = dlallhead;
    268:   PetscErrorCode    ierr;

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

    273:   /*
    274:        Remove this entry from the master DL list (if it is in it)
    275:   */
    276:   if (dlallhead == *fl) {
    277:     if (dlallhead->next_list) dlallhead = dlallhead->next_list;
    278:     else dlallhead = NULL;
    279:   } else if (tmp) {
    280:     while (tmp->next_list != *fl) {
    281:       tmp = tmp->next_list;
    282:       if (!tmp->next_list) break;
    283:     }
    284:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
    285:   }

    287:   /* free this list */
    288:   entry = *fl;
    289:   while (entry) {
    290:     next  = entry->next;
    291:     PetscFree(entry->name);
    292:     PetscFree(entry);
    293:     entry = next;
    294:   }
    295:   *fl = 0;
    296:   return(0);
    297: }

    299: /*
    300:    Print any PetscFunctionLists that have not be destroyed
    301: */
    302: PetscErrorCode  PetscFunctionListPrintAll(void)
    303: {
    304:   PetscFunctionList tmp = dlallhead;
    305:   PetscErrorCode    ierr;

    308:   if (tmp) {
    309:     PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
    310:   }
    311:   while (tmp) {
    312:     PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
    313:     tmp = tmp->next_list;
    314:   }
    315:   return(0);
    316: }

    318: /*MC
    319:     PetscFunctionListFind - Find function registered under given name

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

    325:     Input Parameters:
    326: +   flist   - pointer to list
    327: -   name - name registered for the function

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

    332:     Level: developer

    334: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
    335: M*/
    336: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
    337: {
    338:   PetscFunctionList entry = fl;
    339:   PetscErrorCode    ierr;
    340:   PetscBool         flg;

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

    345:   *r = 0;
    346:   while (entry) {
    347:     PetscStrcmp(name,entry->name,&flg);
    348:     if (flg) {
    349:       *r   = entry->routine;
    350:       return(0);
    351:     }
    352:     entry = entry->next;
    353:   }
    354:   return(0);
    355: }

    357: /*@
    358:    PetscFunctionListView - prints out contents of an PetscFunctionList

    360:    Collective over MPI_Comm

    362:    Input Parameters:
    363: +  list - the list of functions
    364: -  viewer - currently ignored

    366:    Level: developer

    368: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
    369: @*/
    370: PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
    371: {
    373:   PetscBool      iascii;

    376:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;

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

    383:   while (list) {
    384:     PetscViewerASCIIPrintf(viewer," %s\n",list->name);
    385:     list = list->next;
    386:   }
    387:   PetscViewerASCIIPrintf(viewer,"\n");
    388:   return(0);
    389: }

    391: /*@C
    392:    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
    393:          by help etc.

    395:    Not Collective

    397:    Input Parameter:
    398: .  list   - list of types

    400:    Output Parameter:
    401: +  array - array of names
    402: -  n - length of array

    404:    Notes:
    405:        This allocates the array so that must be freed. BUT the individual entries are
    406:     not copied so should not be freed.

    408:    Level: developer

    410: .seealso: PetscFunctionListAdd(), PetscFunctionList
    411: @*/
    412: PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
    413: {
    414:   PetscErrorCode    ierr;
    415:   PetscInt          count = 0;
    416:   PetscFunctionList klist = list;

    419:   while (list) {
    420:     list = list->next;
    421:     count++;
    422:   }
    423:   PetscMalloc1(count+1,(char***)array);
    424:   count = 0;
    425:   while (klist) {
    426:     (*array)[count] = klist->name;
    427:     klist           = klist->next;
    428:     count++;
    429:   }
    430:   (*array)[count] = 0;
    431:   *n              = count+1;
    432:   return(0);
    433: }

    436: /*@C
    437:    PetscFunctionListPrintTypes - Prints the methods available.

    439:    Collective over MPI_Comm

    441:    Input Parameters:
    442: +  comm   - the communicator (usually MPI_COMM_WORLD)
    443: .  fd     - file to print to, usually stdout
    444: .  prefix - prefix to prepend to name (optional)
    445: .  name   - option string (for example, "-ksp_type")
    446: .  text - short description of the object (for example, "Krylov solvers")
    447: .  man - name of manual page that discusses the object (for example, "KSPCreate")
    448: .  list   - list of types
    449: -  def - default (current) value

    451:    Level: developer

    453: .seealso: PetscFunctionListAdd(), PetscFunctionList
    454: @*/
    455:  PetscErrorCode  PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
    456: {
    458:   char           p[64];

    461:   if (!fd) fd = PETSC_STDOUT;

    463:   PetscStrncpy(p,"-",sizeof(p));
    464:   if (prefix) {PetscStrlcat(p,prefix,sizeof(p));}
    465:   PetscFPrintf(comm,fd,"  %s%s <%s>: %s (one of)",p,name+1,def,text);

    467:   while (list) {
    468:     PetscFPrintf(comm,fd," %s",list->name);
    469:     list = list->next;
    470:   }
    471:   PetscFPrintf(comm,fd," (%s)\n",man);
    472:   return(0);
    473: }

    475: /*@
    476:     PetscFunctionListDuplicate - Creates a new list from a given object list.

    478:     Input Parameters:
    479: .   fl   - pointer to list

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

    484:     Level: developer

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

    488: @*/
    489: PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
    490: {

    494:   while (fl) {
    495:     PetscFunctionListAdd(nl,fl->name,fl->routine);
    496:     fl   = fl->next;
    497:   }
    498:   return(0);
    499: }