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,sizeof work);
 17:   work[sizeof work - 1] = 0;
 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: /*
 31:     This is the default list used by PETSc with the PetscDLLibrary register routines
 32: */
 33: PetscDLLibrary DLLibrariesLoaded = 0;

 35: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)

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

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

 61: #endif

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

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

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

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

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

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

129:   return(0);
130: }

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

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

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

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

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

171:      Not Collective

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

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

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

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

190:    Level: developer

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

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

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

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

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

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

260:     Level: developer

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

270:   if (!*fl) return(0);
271:   if (!dlallhead) 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) {
278:       dlallhead = dlallhead->next_list;
279:     } else {
280:       dlallhead = 0;
281:     }
282:   } else {
283:     while (tmp->next_list != *fl) {
284:       tmp = tmp->next_list;
285:       if (!tmp->next_list) break;
286:     }
287:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
288:   }

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

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

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

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

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

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

338:     Level: developer

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

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

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

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

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

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

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

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

439:    Collective over MPI_Comm

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

445:    Level: developer

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

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

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

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

480:    Collective over MPI_Comm

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

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

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

493:    Level: developer

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

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


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

526:    Collective over MPI_Comm

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

538:    Level: developer

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

549:   if (!fd) fd = PETSC_STDOUT;

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

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

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

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

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

576:     Level: developer

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

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

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


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

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

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

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

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