Actual source code: reg.c

  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 <petscsys.h>           /*I "petscsys.h" I*/

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

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

 29: /*
 30:     This is the default list used by PETSc with the PetscDLLibrary register routines
 31: */
 32: PetscDLLibrary DLLibrariesLoaded = 0;

 34: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)

 38: static PetscErrorCode  PetscLoadDynamicLibrary(const char *name,PetscBool  *found)
 39: {
 40:   char           libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];

 44:   PetscStrcpy(libs,"${PETSC_LIB_DIR}/libpetsc");
 45:   PetscStrcat(libs,name);
 46:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
 47:   if (*found) {
 48:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,dlib);
 49:   } else {
 50:     PetscStrcpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc");
 51:     PetscStrcat(libs,name);
 52:     PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
 53:     if (*found) {
 54:       PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,dlib);
 55:     }
 56:   }
 57:   return(0);
 58: }

 60: #endif

 64: /*
 65:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 
 66:     search path.
 67: */
 68: PetscErrorCode  PetscInitialize_DynamicLibraries(void)
 69: {
 70:   char           *libname[32];
 72:   PetscInt       nmax,i;
 73: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
 74:   PetscBool      found;
 75: #endif

 78:   nmax = 32;
 79:   PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
 80:   for (i=0; i<nmax; i++) {
 81:     PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
 82:     PetscFree(libname[i]);
 83:   }

 85: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
 86:   /*
 87:       This just initializes the most basic PETSc stuff.

 89:     The classes, from PetscDraw to PetscTS, are initialized the first
 90:     time an XXCreate() is called.
 91:   */
 92:   PetscSysInitializePackage(PETSC_NULL);
 93: #else
 94: #if defined(PETSC_USE_SINGLE_LIBRARY)
 95:   PetscLoadDynamicLibrary("",&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: #else 
 98:   PetscLoadDynamicLibrary("sys",&found);
 99:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
100:   PetscLoadDynamicLibrary("vec",&found);
101:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
102:   PetscLoadDynamicLibrary("mat",&found);
103:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
104:   PetscLoadDynamicLibrary("dm",&found);
105:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
106:   PetscLoadDynamicLibrary("characteristic",&found);
107:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Characteristic dynamic library \n You cannot move the dynamic libraries!");
108:   PetscLoadDynamicLibrary("ksp",&found);
109:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
110:   PetscLoadDynamicLibrary("snes",&found);
111:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
112:   PetscLoadDynamicLibrary("ts",&found);
113:   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
114: #endif

116:   PetscLoadDynamicLibrary("mesh",&found);
117:   PetscLoadDynamicLibrary("contrib",&found);
118: #endif

120:   nmax = 32;
121:   PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
122:   for (i=0; i<nmax; i++) {
123:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
124:     PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
125:     PetscFree(libname[i]);
126:   }

128:   return(0);
129: }

133: /*
134:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
135: */
136: PetscErrorCode PetscFinalize_DynamicLibraries(void)
137: {
139:   PetscBool      flg = PETSC_FALSE;

142:   PetscOptionsGetBool(PETSC_NULL,"-dll_view",&flg,PETSC_NULL);
143:   if (flg) { PetscDLLibraryPrintPath(DLLibrariesLoaded); }
144:   PetscDLLibraryClose(DLLibrariesLoaded);
145:   DLLibrariesLoaded = 0;
146:   return(0);
147: }

149: /* ------------------------------------------------------------------------------*/
150: struct _n_PetscFList {
151:   void        (*routine)(void);   /* the routine */
152:   char        *path;              /* path of link library containing routine */
153:   char        *name;              /* string to identify routine */
154:   char        *rname;             /* routine name in dynamic library */
155:   PetscFList  next;               /* next pointer */
156:   PetscFList  next_list;          /* used to maintain list of all lists for freeing */
157: };

159: /*
160:      Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
161: */
162: static PetscFList   dlallhead = 0;

166: /*@C
167:    PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
168:    specified registry.

170:      Not Collective

172:    Input Parameters:
173: +  fl    - pointer registry
174: .  name  - string to identify routine
175: .  rname - routine name in dynamic library
176: -  fnc   - function pointer (optional if using dynamic libraries)

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

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

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

189:    Level: developer

191: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
192:           PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
193: @*/
194: PetscErrorCode  PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
195: {
196:   PetscFList     entry,ne;
198:   char           *fpath,*fname;

201:   if (!*fl) {
202:     PetscNew(struct _n_PetscFList,&entry);
203:     PetscStrallocpy(name,&entry->name);
204:     PetscFListGetPathAndFunction(rname,&fpath,&fname);
205:     entry->path    = fpath;
206:     entry->rname   = fname;
207:     entry->routine = fnc;
208:     entry->next    = 0;
209:     *fl = entry;

211:     /* add this new list to list of all lists */
212:     if (!dlallhead) {
213:       dlallhead        = *fl;
214:       (*fl)->next_list = 0;
215:     } else {
216:       ne               = dlallhead;
217:       dlallhead        = *fl;
218:       (*fl)->next_list = ne;
219:     }
220:   } else {
221:     /* search list to see if it is already there */
222:     ne = *fl;
223:     while (ne) {
224:       PetscBool  founddup;

226:       PetscStrcmp(ne->name,name,&founddup);
227:       if (founddup) { /* found duplicate */
228:         PetscFListGetPathAndFunction(rname,&fpath,&fname);
229:         PetscFree(ne->path);
230:         PetscFree(ne->rname);
231:         ne->path    = fpath;
232:         ne->rname   = fname;
233:         ne->routine = fnc;
234:         return(0);
235:       }
236:       if (ne->next) ne = ne->next; else break;
237:     }
238:     /* create new entry and add to end of list */
239:     PetscNew(struct _n_PetscFList,&entry);
240:     PetscStrallocpy(name,&entry->name);
241:     PetscFListGetPathAndFunction(rname,&fpath,&fname);
242:     entry->path    = fpath;
243:     entry->rname   = fname;
244:     entry->routine = fnc;
245:     entry->next    = 0;
246:     ne->next       = entry;
247:   }
248:   return(0);
249: }

253: /*@
254:     PetscFListDestroy - Destroys a list of registered routines.

256:     Input Parameter:
257: .   fl  - pointer to list

259:     Level: developer

261: .seealso: PetscFListAddDynamic(), PetscFList
262: @*/
263: PetscErrorCode  PetscFListDestroy(PetscFList *fl)
264: {
265:   PetscFList     next,entry,tmp = dlallhead;

269:   if (!*fl) return(0);
270:   if (!dlallhead) return(0);

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

289:   /* free this list */
290:   entry = *fl;
291:   while (entry) {
292:     next = entry->next;
293:     PetscFree(entry->path);
294:     PetscFree(entry->name);
295:     PetscFree(entry->rname);
296:     PetscFree(entry);
297:     entry = next;
298:   }
299:   *fl = 0;
300:   return(0);
301: }

303: /*
304:    Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
305: */
308: PetscErrorCode  PetscFListDestroyAll(void)
309: {
310:   PetscFList     tmp2,tmp1 = dlallhead;

314:   while (tmp1) {
315:     tmp2 = tmp1->next_list;
316:     PetscFListDestroy(&tmp1);
317:     tmp1 = tmp2;
318:   }
319:   dlallhead = 0;
320:   return(0);
321: }

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

328:     Input Parameters:
329: +   fl   - pointer to list
330: .   comm - processors looking for routine
331: .   name - name string
332: -   searchlibraries - if not found in the list then search the dynamic libraries and executable for the symbol

334:     Output Parameters:
335: .   r - the routine

337:     Level: developer

339: .seealso: PetscFListAddDynamic(), PetscFList
340: @*/
341: PetscErrorCode  PetscFListFind(PetscFList fl,MPI_Comm comm,const char name[],PetscBool searchlibraries,void (**r)(void))
342: {
343:   PetscFList     entry = fl;
345:   char           *function,*path;
346:   PetscBool      flg,f1,f2,f3;
347: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
348:   char           *newpath;
349: #endif
350: 
352:   if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");

354:   *r = 0;
355:   PetscFListGetPathAndFunction(name,&path,&function);

357:   /*
358:         If path then append it to search libraries
359:   */
360: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
361:   if (path) {
362:     PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
363:   }
364: #endif

366:   while (entry) {
367:     flg = PETSC_FALSE;
368:     if (path && entry->path) {
369:       PetscStrcmp(path,entry->path,&f1);
370:       PetscStrcmp(function,entry->rname,&f2);
371:       PetscStrcmp(function,entry->name,&f3);
372:       flg =  (PetscBool) ((f1 && f2) || (f1 && f3));
373:     } else if (!path) {
374:       PetscStrcmp(function,entry->name,&f1);
375:       PetscStrcmp(function,entry->rname,&f2);
376:       flg =  (PetscBool) (f1 || f2);
377:     } else {
378:       PetscStrcmp(function,entry->name,&flg);
379:       if (flg) {
380:         PetscFree(function);
381:         PetscStrallocpy(entry->rname,&function);
382:       } else {
383:         PetscStrcmp(function,entry->rname,&flg);
384:       }
385:     }

387:     if (flg) {
388:       if (entry->routine) {
389:         *r   = entry->routine;
390:         PetscFree(path);
391:         PetscFree(function);
392:         return(0);
393:       }
394:       if (!(entry->rname && entry->rname[0])) { /* The entry has been cleared */
395:         PetscFree(function);
396:         return(0);
397:       }
398:       if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
399:         PetscFree(function);
400:         PetscStrallocpy(entry->rname,&function);
401:       }

403:       /* it is not yet in memory so load from dynamic library */
404: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
405:       newpath = path;
406:       if (!path) newpath = entry->path;
407:       PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
408:       if (*r) {
409:         entry->routine = *r;
410:         PetscFree(path);
411:         PetscFree(function);
412:         return(0);
413:       }
414: #endif
415:     }
416:     entry = entry->next;
417:   }

419: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
420:   if (searchlibraries) {
421:     /* Function never registered; try for it anyway */
422:     PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
423:     PetscFree(path);
424:     if (*r) {
425:       PetscFListAdd(&fl,name,name,*r);
426:     }
427:   }
428: #endif
429:   PetscFree(function);
430:   return(0);
431: }

435: /*@
436:    PetscFListView - prints out contents of an PetscFList

438:    Collective over MPI_Comm

440:    Input Parameters:
441: +  list - the list of functions
442: -  viewer - currently ignored

444:    Level: developer

446: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
447: @*/
448: PetscErrorCode  PetscFListView(PetscFList list,PetscViewer viewer)
449: {
451:   PetscBool      iascii;

454:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
457: 
458:   PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
459:   if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");

461:   while (list) {
462:     if (list->path) {
463:       PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
464:     } else {
465:       PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
466:     }
467:     list = list->next;
468:   }
469:   PetscViewerASCIIPrintf(viewer,"\n");
470:   return(0);
471: }

475: /*@
476:    PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
477:          by help etc.

479:    Collective over MPI_Comm

481:    Input Parameter:
482: .  list   - list of types

484:    Output Parameter:
485: +  array - array of names
486: -  n - length of array

488:    Notes:
489:        This allocates the array so that must be freed. BUT the individual entries are
490:     not copied so should not be freed.

492:    Level: developer

494: .seealso: PetscFListAddDynamic(), PetscFList
495: @*/
496: PetscErrorCode  PetscFListGet(PetscFList list,char ***array,int *n)
497: {
499:   PetscInt       count = 0;
500:   PetscFList     klist = list;

503:   while (list) {
504:     list = list->next;
505:     count++;
506:   }
507:   PetscMalloc((count+1)*sizeof(char *),array);
508:   count = 0;
509:   while (klist) {
510:     (*array)[count] = klist->name;
511:     klist = klist->next;
512:     count++;
513:   }
514:   (*array)[count] = 0;
515:   *n = count+1;
516:   return(0);
517: }


522: /*@C
523:    PetscFListPrintTypes - Prints the methods available.

525:    Collective over MPI_Comm

527:    Input Parameters:
528: +  comm   - the communicator (usually MPI_COMM_WORLD)
529: .  fd     - file to print to, usually stdout
530: .  prefix - prefix to prepend to name (optional)
531: .  name   - option string (for example, "-ksp_type")
532: .  text - short description of the object (for example, "Krylov solvers")
533: .  man - name of manual page that discusses the object (for example, "KSPCreate")
534: .  list   - list of types
535: -  def - default (current) value

537:    Level: developer

539: .seealso: PetscFListAddDynamic(), PetscFList
540: @*/
541: PetscErrorCode  PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFList list,const char def[])
542: {
544:   PetscInt       count = 0;
545:   char           p[64];

548:   if (!fd) fd = PETSC_STDOUT;

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

554:   while (list) {
555:     PetscFPrintf(comm,fd," %s",list->name);
556:     list = list->next;
557:     count++;
558:     if (count == 8) {PetscFPrintf(comm,fd,"\n     ");}
559:   }
560:   PetscFPrintf(comm,fd," (%s)\n",man);
561:   return(0);
562: }

566: /*@
567:     PetscFListDuplicate - Creates a new list from a given object list.

569:     Input Parameters:
570: .   fl   - pointer to list

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

575:     Level: developer

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

579: @*/
580: PetscErrorCode  PetscFListDuplicate(PetscFList fl,PetscFList *nl)
581: {
583:   char           path[PETSC_MAX_PATH_LEN];

586:   while (fl) {
587:     /* this is silly, rebuild the complete pathname */
588:     if (fl->path) {
589:       PetscStrcpy(path,fl->path);
590:       PetscStrcat(path,":");
591:       PetscStrcat(path,fl->name);
592:     } else {
593:       PetscStrcpy(path,fl->name);
594:     }
595:     PetscFListAdd(nl,path,fl->rname,fl->routine);
596:     fl   = fl->next;
597:   }
598:   return(0);
599: }


604: /*
605:     PetscFListConcat - joins name of a libary, and the path where it is located
606:     into a single string.

608:     Input Parameters:
609: .   path   - path to the library name.
610: .   name   - name of the library

612:     Output Parameters:
613: .   fullname - the name that is the union of the path and the library name,
614:                delimited by a semicolon, i.e., path:name

616:     Notes:
617:     If the path is NULL, assumes that the name, specified also includes
618:     the path as path:name

620: */
621: PetscErrorCode  PetscFListConcat(const char path[],const char name[],char fullname[])
622: {
625:   if (path) {
626:     PetscStrcpy(fullname,path);
627:     PetscStrcat(fullname,":");
628:     PetscStrcat(fullname,name);
629:   } else {
630:     PetscStrcpy(fullname,name);
631:   }
632:   return(0);
633: }