Actual source code: reg.c

  1: /*$Id: reg.c,v 1.77 2001/09/07 20:08:26 bsmith Exp $*/
  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.h
 7:  #include petscsys.h

  9: #undef __FUNCT__  
 11: int PetscFListGetPathAndFunction(const char name[],char *path[],char *function[])
 12: {
 13:   char work[256],*lfunction,ierr;

 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: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)

 31: /*
 32:     This is the list used by the DLRegister routines
 33: */
 34: PetscDLLibraryList DLLibrariesLoaded = 0;

 36: #undef __FUNCT__  
 38: /*
 39:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 
 40:     search path.
 41: */
 42: int PetscInitialize_DynamicLibraries(void)
 43: {
 44:   char       *libname[32],libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
 45:   int        nmax,i,ierr;
 46:   PetscTruth found;


 50:   nmax = 32;
 51:   PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
 52:   for (i=0; i<nmax; i++) {
 53:     PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
 54:     PetscFree(libname[i]);
 55:   }

 57:   PetscStrcpy(libs,PETSC_LIB_DIR);
 58:   PetscStrcat(libs,"/libpetsc");
 59:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 60:   if (found) {
 61:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 62:   } else {
 63:     SETERRQ1(1,"Unable to locate PETSc dynamic library %s n You cannot move the dynamic libraries!n or remove USE_DYNAMIC_LIBRARIES from ${PETSC_DIR}/bmake/$PETSC_ARCH/petscconf.hn and rebuild libraries before moving",libs);
 64:   }

 66:   PetscStrcpy(libs,PETSC_LIB_DIR);
 67:   PetscStrcat(libs,"/libpetscvec");
 68:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 69:   if (found) {
 70:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 71:   }

 73:   PetscStrcpy(libs,PETSC_LIB_DIR);
 74:   PetscStrcat(libs,"/libpetscmat");
 75:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 76:   if (found) {
 77:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 78:   }

 80:   PetscStrcpy(libs,PETSC_LIB_DIR);
 81:   PetscStrcat(libs,"/libpetscdm");
 82:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 83:   if (found) {
 84:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 85:   }

 87:   PetscStrcpy(libs,PETSC_LIB_DIR);
 88:   PetscStrcat(libs,"/libpetscsles");
 89:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 90:   if (found) {
 91:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 92:   }

 94:   PetscStrcpy(libs,PETSC_LIB_DIR);
 95:   PetscStrcat(libs,"/libpetscsnes");
 96:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
 97:   if (found) {
 98:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
 99:   }

101:   PetscStrcpy(libs,PETSC_LIB_DIR);
102:   PetscStrcat(libs,"/libpetscts");
103:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
104:   if (found) {
105:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
106:   }

108:   PetscStrcpy(libs,PETSC_LIB_DIR);
109:   PetscStrcat(libs,"/libpetscdm");
110:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
111:   if (found) {
112:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
113:   }

115:   PetscStrcpy(libs,PETSC_LIB_DIR);
116:   PetscStrcat(libs,"/libpetscmesh");
117:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
118:   if (found) {
119:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
120:   }

122:   PetscStrcpy(libs,PETSC_LIB_DIR);
123:   PetscStrcat(libs,"/libpetscgrid");
124:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
125:   if (found) {
126:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
127:   }

129:   PetscStrcpy(libs,PETSC_LIB_DIR);
130:   PetscStrcat(libs,"/libpetscgsolver");
131:   PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
132:   if (found) {
133:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
134:   }

136:   nmax = 32;
137:   PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
138:   for (i=0; i<nmax; i++) {
139:     PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
140:     PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
141:     PetscFree(libname[i]);
142:   }

144:   return(0);
145: }

147: #undef __FUNCT__  
149: /*
150:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
151: */
152: int PetscFinalize_DynamicLibraries(void)
153: {
154:   int        ierr;
155:   PetscTruth flg;

158:   PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);
159:   if (flg) {
160:     PetscDLLibraryPrintPath();
161:   }
162:   PetscDLLibraryClose(DLLibrariesLoaded);
163:   return(0);
164: }

166: #else /* not using dynamic libraries */

168: EXTERN int PetscInitializePackage(char *);

170: #undef __FUNCT__  
172: int PetscInitialize_DynamicLibraries(void)
173: {

177:   /*
178:       This just initializes the draw and viewer methods, since those
179:     are ALWAYS available. The other classes are initialized the first
180:     time an XXSetType() is called.
181:   */
182:   PetscInitializePackage(PETSC_NULL);
183:   return(0);
184: }
185: #undef __FUNCT__  
187: int PetscFinalize_DynamicLibraries(void)
188: {

191:   return(0);
192: }
193: #endif

195: /* ------------------------------------------------------------------------------*/
196: struct _PetscFList {
197:   void        (*routine)(void);   /* the routine */
198:   char        *path;              /* path of link library containing routine */
199:   char        *name;              /* string to identify routine */
200:   char        *rname;             /* routine name in dynamic library */
201:   PetscFList  next;               /* next pointer */
202:   PetscFList  next_list;          /* used to maintain list of all lists for freeing */
203: };

205: /*
206:      Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
207: */
208: static PetscFList   dlallhead = 0;

210: #undef __FUNCT__  
212: /*@C
213:    PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
214:    specified registry.

216:    Synopsis:
217:    int PetscFListAddDynamic(PetscFList *fl,char *name,char *rname,int (*fnc)(void *))

219:    Input Parameters:
220: +  fl    - pointer registry
221: .  name  - string to identify routine
222: .  rname - routine name in dynamic library
223: -  fnc   - function pointer (optional if using dynamic libraries)

225:    Notes:
226:    Users who wish to register new methods for use by a particular PETSc
227:    component (e.g., SNES) should generally call the registration routine
228:    for that particular component (e.g., SNESRegisterDynamic()) instead of
229:    calling PetscFListAddDynamic() directly.

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

234:    Level: developer

236: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
237:           PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
238: @*/
239: int PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
240: {
241:   PetscFList entry,ne;
242:   int        ierr;
243:   char       *fpath,*fname;


247:   if (!*fl) {
248:     ierr           = PetscNew(struct _PetscFList,&entry);
249:     ierr           = PetscStrallocpy(name,&entry->name);
250:     ierr           = PetscFListGetPathAndFunction(rname,&fpath,&fname);
251:     entry->path    = fpath;
252:     entry->rname   = fname;
253:     entry->routine = fnc;
254:     entry->next    = 0;
255:     *fl = entry;

257:     /* add this new list to list of all lists */
258:     if (!dlallhead) {
259:       dlallhead        = *fl;
260:       (*fl)->next_list = 0;
261:     } else {
262:       ne               = dlallhead;
263:       dlallhead        = *fl;
264:       (*fl)->next_list = ne;
265:     }
266:   } else {
267:     /* search list to see if it is already there */
268:     ne = *fl;
269:     while (ne) {
270:       PetscTruth founddup;

272:       PetscStrcmp(ne->name,name,&founddup);
273:       if (founddup) { /* found duplicate */
274:         PetscFListGetPathAndFunction(rname,&fpath,&fname);
275:         PetscStrfree(ne->path);
276:         PetscStrfree(ne->rname);
277:         ne->path    = fpath;
278:         ne->rname   = fname;
279:         ne->routine = fnc;
280:         return(0);
281:       }
282:       if (ne->next) ne = ne->next; else break;
283:     }
284:     /* create new entry and add to end of list */
285:     ierr           = PetscNew(struct _PetscFList,&entry);
286:     ierr           = PetscStrallocpy(name,&entry->name);
287:     ierr           = PetscFListGetPathAndFunction(rname,&fpath,&fname);
288:     entry->path    = fpath;
289:     entry->rname   = fname;
290:     entry->routine = fnc;
291:     entry->next    = 0;
292:     ne->next       = entry;
293:   }

295:   return(0);
296: }

298: #undef __FUNCT__  
300: /*@
301:     PetscFListDestroy - Destroys a list of registered routines.

303:     Input Parameter:
304: .   fl  - pointer to list

306:     Level: developer

308: .seealso: PetscFListAddDynamic(), PetscFList
309: @*/
310: int PetscFListDestroy(PetscFList *fl)
311: {
312:   PetscFList next,entry,tmp = dlallhead;
313:   int        ierr;

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

318:   if (!dlallhead) {
319:     return(0);
320:   }

322:   /*
323:        Remove this entry from the master DL list (if it is in it)
324:   */
325:   if (dlallhead == *fl) {
326:     if (dlallhead->next_list) {
327:       dlallhead = dlallhead->next_list;
328:     } else {
329:       dlallhead = 0;
330:     }
331:   } else {
332:     while (tmp->next_list != *fl) {
333:       tmp = tmp->next_list;
334:       if (!tmp->next_list) break;
335:     }
336:     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
337:   }

339:   /* free this list */
340:   entry = *fl;
341:   while (entry) {
342:     next = entry->next;
343:     PetscStrfree(entry->path);
344:     PetscFree(entry->name);
345:     PetscFree(entry->rname);
346:     PetscFree(entry);
347:     entry = next;
348:   }
349:   *fl = 0;
350:   return(0);
351: }

353: /*
354:    Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
355: */
356: #undef __FUNCT__  
358: int PetscFListDestroyAll(void)
359: {
360:   PetscFList tmp2,tmp1 = dlallhead;
361:   int        ierr;

364:   while (tmp1) {
365:     tmp2 = tmp1->next_list;
366:     PetscFListDestroy(&tmp1);
367:     tmp1 = tmp2;
368:   }
369:   dlallhead = 0;
370:   return(0);
371: }

373: #undef __FUNCT__  
375: /*@C
376:     PetscFListFind - Given a name, finds the matching routine.

378:     Input Parameters:
379: +   comm - processors looking for routine
380: .   fl   - pointer to list
381: -   name - name string

383:     Output Parameters:
384: .   r - the routine

386:     Level: developer

388: .seealso: PetscFListAddDynamic(), PetscFList
389: @*/
390: int PetscFListFind(MPI_Comm comm,PetscFList fl,const char name[],void (**r)(void))
391: {
392:   PetscFList   entry = fl;
393:   int          ierr;
394:   char         *function,*path;
395: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
396:   char         *newpath;
397: #endif
398:   PetscTruth   flg,f1,f2,f3;
399: 
401:   if (!name) SETERRQ(1,"Trying to find routine with null name");

403:   *r = 0;
404:   PetscFListGetPathAndFunction(name,&path,&function);

406:   /*
407:         If path then append it to search libraries
408:   */
409: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
410:   if (path) {
411:     PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
412:   }
413: #endif

415:   while (entry) {
416:     flg = PETSC_FALSE;
417:     if (path && entry->path) {
418:       PetscStrcmp(path,entry->path,&f1);
419:       PetscStrcmp(function,entry->rname,&f2);
420:       PetscStrcmp(function,entry->name,&f3);
421:       flg =  (PetscTruth) ((f1 && f2) || (f1 && f3));
422:     } else if (!path) {
423:       PetscStrcmp(function,entry->name,&f1);
424:       PetscStrcmp(function,entry->rname,&f2);
425:       flg =  (PetscTruth) (f1 || f2);
426:     } else {
427:       PetscStrcmp(function,entry->name,&flg);
428:       if (flg) {
429:         PetscFree(function);
430:         PetscStrallocpy(entry->rname,&function);
431:       } else {
432:         PetscStrcmp(function,entry->rname,&flg);
433:       }
434:     }

436:     if (flg) {

438:       if (entry->routine) {
439:         *r   = entry->routine;
440:         PetscStrfree(path);
441:         PetscFree(function);
442:         return(0);
443:       }
444: 
445:       if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
446:         PetscFree(function);
447:         PetscStrallocpy(entry->rname,&function);
448:       }

450:       /* it is not yet in memory so load from dynamic library */
451: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
452:       newpath = path;
453:       if (!path) newpath = entry->path;
454:       PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
455:       if (*r) {
456:         entry->routine = *r;
457:         PetscStrfree(path);
458:         PetscFree(function);
459:         return(0);
460:       } else {
461:         PetscErrorPrintf("Unable to find function. Search path:n");
462:         PetscDLLibraryPrintPath();
463:         SETERRQ1(1,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
464:       }
465: #endif
466:     }
467:     entry = entry->next;
468:   }

470: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
471:   /* Function never registered; try for it anyway */
472:   PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
473:   PetscStrfree(path);
474:   if (*r) {
475:     PetscFListAddDynamic(&fl,name,name,r);
476:   }
477: #endif

479:   /*
480:        Do not generate error, just end
481:   PetscErrorPrintf("Function name: %sn",function);
482:   PetscDLLibraryPrintPath();
483:   SETERRQ(1,"Unable to find function: either it is mis-spelled or dynamic library is not in path");
484:   */

486:   PetscFree(function);
487:   return(0);
488: }

490: #undef __FUNCT__  
492: /*@
493:    PetscFListView - prints out contents of an PetscFList

495:    Collective over MPI_Comm

497:    Input Parameters:
498: +  list - the list of functions
499: -  viewer - currently ignored

501:    Level: developer

503: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
504: @*/
505: int PetscFListView(PetscFList list,PetscViewer viewer)
506: {
507:   int        ierr;
508:   PetscTruth isascii;

511:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
514: 
515:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
516:   if (!isascii) SETERRQ(1,"Only ASCII viewer supported");

518:   while (list) {
519:     if (list->path) {
520:       PetscViewerASCIIPrintf(viewer," %s %s %sn",list->path,list->name,list->rname);
521:     } else {
522:       PetscViewerASCIIPrintf(viewer," %s %sn",list->name,list->rname);
523:     }
524:     list = list->next;
525:   }
526:   PetscViewerASCIIPrintf(viewer,"n");
527:   return(0);
528: }

530: #undef __FUNCT__  
532: /*@
533:    PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
534:          by help etc.

536:    Collective over MPI_Comm

538:    Input Parameter:
539: .  list   - list of types

541:    Output Parameter:
542: +  array - array of names
543: -  n - length of array

545:    Notes:
546:        This allocates the array so that must be freed. BUT the individual entries are
547:     not copied so should not be freed.

549:    Level: developer

551: .seealso: PetscFListAddDynamic(), PetscFList
552: @*/
553: int PetscFListGet(PetscFList list,char ***array,int *n)
554: {
555:   int        count = 0,ierr;
556:   PetscFList klist = list;

559:   while (list) {
560:     list = list->next;
561:     count++;
562:   }
563:   ierr  = PetscMalloc((count+1)*sizeof(char *),array);
564:   count = 0;
565:   while (klist) {
566:     (*array)[count] = klist->name;
567:     klist = klist->next;
568:     count++;
569:   }
570:   (*array)[count] = 0;
571:   *n = count+1;

573:   return(0);
574: }


577: #undef __FUNCT__  
579: /*@C
580:    PetscFListPrintTypes - Prints the methods available.

582:    Collective over MPI_Comm

584:    Input Parameters:
585: +  comm   - the communicator (usually MPI_COMM_WORLD)
586: .  fd     - file to print to, usually stdout
587: .  prefix - prefix to prepend to name (optional)
588: .  name   - option string (for example, "-ksp_type")
589: .  text - short description of the object (for example, "Krylov solvers")
590: .  man - name of manual page that discusses the object (for example, "KSPCreate")
591: -  list   - list of types

593:    Level: developer

595: .seealso: PetscFListAddDynamic(), PetscFList
596: @*/
597: int PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],char *text,char *man,PetscFList list)
598: {
599:   int      ierr,count = 0;
600:   char     p[64];

603:   if (!fd) fd = stdout;

605:   PetscStrcpy(p,"-");
606:   if (prefix) {PetscStrcat(p,prefix);}
607:   PetscFPrintf(comm,fd,"  %s%s %s:(one of)",p,name+1,text);

609:   while (list) {
610:     PetscFPrintf(comm,fd," %s",list->name);
611:     list = list->next;
612:     count++;
613:     if (count == 8) {PetscFPrintf(comm,fd,"n     ");}
614:   }
615:   PetscFPrintf(comm,fd," (%s)n",man);
616:   return(0);
617: }

619: #undef __FUNCT__  
621: /*@
622:     PetscFListDuplicate - Creates a new list from a given object list.

624:     Input Parameters:
625: .   fl   - pointer to list

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

630:     Level: developer

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

634: @*/
635: int PetscFListDuplicate(PetscFList fl,PetscFList *nl)
636: {
637:   int  ierr;
638:   char path[PETSC_MAX_PATH_LEN];

641:   while (fl) {
642:     /* this is silly, rebuild the complete pathname */
643:     if (fl->path) {
644:       PetscStrcpy(path,fl->path);
645:       PetscStrcat(path,":");
646:       PetscStrcat(path,fl->name);
647:     } else {
648:       PetscStrcpy(path,fl->name);
649:     }
650:     PetscFListAddDynamic(nl,path,fl->rname,fl->routine);
651:     fl   = fl->next;
652:   }
653:   return(0);
654: }


657: #undef __FUNCT__  
659: /*
660:     PetscFListConcat - joins name of a libary, and the path where it is located
661:     into a single string.

663:     Input Parameters:
664: .   path   - path to the library name.
665: .   name   - name of the library

667:     Output Parameters:
668: .   fullname - the name that is the union of the path and the library name,
669:                delimited by a semicolon, i.e., path:name

671:     Notes:
672:     If the path is NULL, assumes that the name, specified also includes
673:     the path as path:name

675: */
676: int PetscFListConcat(const char path[],const char name[],char fullname[])
677: {
680:   if (path) {
681:     PetscStrcpy(fullname,path);
682:     PetscStrcat(fullname,":");
683:     PetscStrcat(fullname,name);
684:   } else {
685:     PetscStrcpy(fullname,name);
686:   }
687:   return(0);
688: }